Downloads containing mo4a_4-1.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, WeaponVMega::IceCloud::Weapon(), WeaponVMega::Voranj::Weapon(), 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_4-1-MLLE-Data-1.j2l" ///@MLLE-Generated
  4. #pragma require "mo4a_4-1.j2l" ///@MLLE-Generated
  5. #include "ArcaneWeapon4.asc" ///@MLLE-Generated
  6. #pragma require "ArcaneWeapon4.asc" ///@MLLE-Generated
  7. #include "ArcaneWeapon9.asc" ///@MLLE-Generated
  8. #pragma require "ArcaneWeapon9.asc" ///@MLLE-Generated
  9. #include "WeaponVMega5.asc" ///@MLLE-Generated
  10. #pragma require "WeaponVMega5.asc" ///@MLLE-Generated
  11. #include "WeaponVMega8.asc" ///@MLLE-Generated
  12. #pragma require "WeaponVMega8.asc" ///@MLLE-Generated
  13. #include "WeaponVMega3.asc" ///@MLLE-Generated
  14. #pragma require "WeaponVMega3.asc" ///@MLLE-Generated
  15. int SpeedUpUntil = 0;
  16. #include "Jazz1Enemies v05.asc"
  17. #include "Resize v11.asc"
  18. #include "TrueColor v13.asc"
  19. #include "HH18savegems.asc"
  20. bool Lever4 = false, Lever15 = false, Lever16 = false;
  21. int exit = 0;
  22.  
  23. void onLevelLoad() {
  24.         gem::restorePlayerGems();
  25.         jjLevelName = ("@@@@@@@@@Central Area");
  26.  
  27.         jjObjectPresets[OBJECT::SEEKERAMMO15].behavior = Gwell();
  28.         jjObjectPresets[OBJECT::SEEKERAMMO15].scriptedCollisions = true;
  29.         jjObjectPresets[OBJECT::SEEKERAMMO15].playerHandling = HANDLING::SPECIAL;
  30.  
  31.         jjObjectPresets[OBJECT::SEEKERAMMO3].deactivates = false;
  32.  
  33.         Jazz1::MakeEnemy(OBJECT::SUCKER, Jazz1::Enemies::Holidaius_HandVertical).SetDirection(Jazz1::Directions::Right);
  34.         Jazz1::MakeEnemy(OBJECT::RAVEN, Jazz1::Enemies::Holidaius_Devil).SetUsesJJ2StyleDeathAnimation(true).SetDeathSound(SOUND::BILSBOSS_THUNDER);
  35.         Jazz1::MakeEnemy(OBJECT::FLOATSUCKER, Jazz1::Enemies::Holidaius_HandVertical).SetDirection(Jazz1::Directions::Left);
  36.         Jazz1::MakeEnemy(OBJECT::HATTER, Jazz1::Enemies::Megairbase_Doofusguard).SetUsesJJ2StyleDeathAnimation(true).SetBulletFireSound(SOUND::INTRO_SHOTGRN).SetBulletExplosionSound(SOUND::COMMON_GUNSM1);
  37.  
  38.         jjObjectPresets[OBJECT::SAVEPOST].behavior = CheckpointWrapper;
  39.         jjObjectPresets[OBJECT::SAVEPOST].deactivates = false;
  40.         jjObjectPresets[OBJECT::GRASSPLATFORM].scriptedCollisions = true;
  41.         jjObjectPresets[OBJECT::GRASSPLATFORM].behavior = PlatformH;
  42.  
  43.         jjObjectPresets[OBJECT::FRUITPLATFORM].scriptedCollisions = true;
  44.         jjObjectPresets[OBJECT::FRUITPLATFORM].behavior = Air();
  45.         jjObjectPresets[OBJECT::FRUITPLATFORM].deactivates = false;    
  46.         jjObjectPresets[OBJECT::FRUITPLATFORM].state = STATE::FLOAT;   
  47.  
  48.         jjObjectPresets[OBJECT::PINKPLATFORM].scriptedCollisions = true;
  49.         jjObjectPresets[OBJECT::PINKPLATFORM].behavior = Gong();
  50.  
  51.         jjObjectPresets[OBJECT::SONICPLATFORM].scriptedCollisions = true;
  52.         jjObjectPresets[OBJECT::SONICPLATFORM].behavior = FlyingSpring();      
  53.         jjObjectPresets[OBJECT::SONICPLATFORM].determineCurAnim(ANIM::SPRING,6);
  54.  
  55.         jjObjectPresets[OBJECT::FASTFEET].behavior = SuperCopter();
  56.         jjObjectPresets[OBJECT::FASTFEET].scriptedCollisions = true;
  57.  
  58.         jjObjectPresets[OBJECT::FRIES].behavior = Key();
  59.         jjObjectPresets[OBJECT::FRIES].scriptedCollisions = true;
  60.  
  61.         jjObjectPresets[OBJECT::AIRBOARD].behavior = Chakra();
  62.         jjObjectPresets[OBJECT::AIRBOARD].scriptedCollisions = true;
  63.  
  64.         jjObjectPresets[OBJECT::CHIPS].behavior = Chakra2();
  65.         jjObjectPresets[OBJECT::CHIPS].scriptedCollisions = true;
  66.  
  67.         jjObjectPresets[OBJECT::PRETZEL].behavior = Chakra3();
  68.         jjObjectPresets[OBJECT::PRETZEL].scriptedCollisions = true;
  69.  
  70.         jjObjectPresets[OBJECT::CHICKENLEG].behavior = Chakra4();
  71.         jjObjectPresets[OBJECT::CHICKENLEG].scriptedCollisions = true;
  72.  
  73.         jjObjectPresets[OBJECT::WEENIE].behavior = Chakra5();
  74.         jjObjectPresets[OBJECT::WEENIE].scriptedCollisions = true;
  75.  
  76.         jjObjectPresets[OBJECT::FREEZEENEMIES].behavior = Chakra6();
  77.         jjObjectPresets[OBJECT::FREEZEENEMIES].scriptedCollisions = true;
  78.  
  79.         jjObjectPresets[OBJECT::HAM].behavior = Chakra7();
  80.         jjObjectPresets[OBJECT::HAM].scriptedCollisions = true;
  81.  
  82.         jjObjectPresets[OBJECT::STOPWATCH].behavior = Fastrun();
  83.         jjObjectPresets[OBJECT::STOPWATCH].scriptedCollisions = true;
  84.  
  85.         jjObjectPresets[OBJECT::SILVERCOIN].behavior = PlatinCoin();
  86.         jjObjectPresets[OBJECT::SILVERCOIN].scriptedCollisions = true;
  87.  
  88.         jjObjectPresets[OBJECT::EVA].behavior = TimeMachine;
  89.         jjObjectPresets[OBJECT::EVA].determineCurAnim(ANIM::FLAG, 1);
  90.         jjObjectPresets[OBJECT::EVA].putOnGround(false);
  91.         jjObjectPresets[OBJECT::EVA].scriptedCollisions = true;
  92.         jjANIMATION@ tmAnim = jjAnimations[jjObjectPresets[OBJECT::EVA].curAnim];
  93.         for (uint i = 0; i < tmAnim.frameCount; ++i)
  94.                 jjAnimFrames[tmAnim.firstFrame + i].coldSpotY = -44;
  95.         for (uint i = 0; i < tmAnim.frameCount; ++i)
  96.                 jjAnimFrames[tmAnim.firstFrame + i].hotSpotY = -64;
  97.         for (uint i = 0; i < tmAnim.frameCount; ++i)
  98.                 jjAnimFrames[tmAnim.firstFrame + i].hotSpotX = -54;
  99.  
  100.         jjObjectPresets[OBJECT::FLYCARROT].determineCurAnim(ANIM::PLUS_WARP, 0);
  101.         jjObjectPresets[OBJECT::FLYCARROT].behavior = Bonus;
  102.         jjObjectPresets[OBJECT::FLYCARROT].scriptedCollisions = true;
  103.         jjANIMATION@ BAnim = jjAnimations[jjObjectPresets[OBJECT::FLYCARROT].curAnim];
  104.         for (uint i = 0; i < BAnim.frameCount; ++i)
  105.                 jjAnimFrames[BAnim.firstFrame + i].hotSpotX = 20;
  106.  
  107.         jjObjectPresets[OBJECT::INVINCIBILITY].determineCurAnim(ANIM::PLUS_WARP, 1);
  108.         jjObjectPresets[OBJECT::INVINCIBILITY].behavior = Bonuseye;
  109.         jjObjectPresets[OBJECT::INVINCIBILITY].scriptedCollisions = true;
  110.         jjObjectPresets[OBJECT::INVINCIBILITY].bulletHandling = HANDLING::IGNOREBULLET;
  111.         jjObjectPresets[OBJECT::INVINCIBILITY].playerHandling = HANDLING::PLAYERBULLET;
  112.         jjANIMATION@ BeAnim = jjAnimations[jjObjectPresets[OBJECT::INVINCIBILITY].curAnim];
  113.  
  114.         for (uint i = 0; i < BeAnim.frameCount; ++i)
  115.                 jjAnimFrames[BeAnim.firstFrame + i].hotSpotY = 27;
  116.         for (uint i = 0; i < BeAnim.frameCount; ++i)
  117.                 jjAnimFrames[BeAnim.firstFrame + i].hotSpotX = 26;
  118.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::ORANGE].curAnim];
  119.         anim.frameCount = 1;
  120.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  121.         jjPIXELMAP fruit(0, 19*32, 1*32, 1*32, 5);
  122.         fruit.save(frame);
  123. }
  124.  
  125. void Bonuseye(jjOBJ@ obj){
  126.         obj.direction = -1;
  127.         obj.behave(BEHAVIOR::PICKUP, false);
  128.         obj.draw();
  129. }
  130. void Bonus(jjOBJ@ obj){
  131.         obj.putOnGround();
  132.         obj.direction = -1;
  133.         obj.behave(BEHAVIOR::PICKUP, false);
  134.         obj.draw();
  135. }
  136.  
  137. bool copterfloat = false;
  138.  
  139. class Air : jjBEHAVIORINTERFACE {
  140.  
  141.         void onBehave(jjOBJ@ obj) {
  142.                 obj.behave(BEHAVIOR::BURNING, false);
  143.                 obj.determineCurAnim(ANIM::AMMO,3);
  144.                 obj.deactivates = false;
  145.                 obj.determineCurFrame();
  146.                 ++obj.counter;
  147.                 obj.yPos = jjSin(obj.counter*3 + 5)*2 + obj.yOrg;
  148.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::TRANSLUCENTSINGLEHUE, 64);
  149.         }
  150.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  151.                 if(bullet is null)
  152.                         {copterfloat = true;}
  153.                 return true;
  154.         }
  155. }
  156.  
  157. class Gwell : jjBEHAVIORINTERFACE {
  158.  
  159.         void onBehave(jjOBJ@ obj) {
  160.                 if(p.ammo[WEAPON::SEEKER] > 1)
  161.                 {obj.delete();}
  162.                 obj.behave(BEHAVIOR::MONITOR); 
  163.         }
  164.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
  165.                 if(bullet !is null && play !is null)
  166.                         {obj.behave(BEHAVIOR::EXPLOSION2);
  167.                         jjAddObject(OBJECT::SEEKERAMMO3, 81*32, 38*32);
  168.                         jjAddObject(OBJECT::SEEKERAMMO3, 82*32, 38*32);
  169.                         jjAddObject(OBJECT::SEEKERAMMO3, 83*32, 38*32);
  170.                         jjAddObject(OBJECT::SEEKERAMMO3, 81*32, 39*32);                
  171.                         jjAddObject(OBJECT::SEEKERAMMO3, 82*32, 39*32);
  172.                         jjAddObject(OBJECT::SEEKERAMMO3, 83*32, 39*32);
  173.                         jjSample(p.xPos, p.yPos, SOUND::COMMON_HARP1, 1000);}
  174.                 return true;
  175.         }
  176.        
  177. }
  178.  
  179. void TimeMachine(jjOBJ@ obj){
  180.         obj.behave(BEHAVIOR::EVA, false);
  181.                         jjDrawResizedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, 1, 1, SPRITE::PALSHIFT, 8);
  182.  
  183. }
  184.  
  185. bool gonghit = false;
  186.  
  187. class Gong : jjBEHAVIORINTERFACE {
  188.         void onBehave(jjOBJ@ obj){
  189.  
  190.         obj.playerHandling = HANDLING::SPECIAL;
  191.                 obj.energy = 2;
  192.                 if(obj.energy == 0)
  193.                 {obj.energy += 1;}
  194.                 jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::PINKPLATFORM].curAnim];
  195.                 anim.frameCount = 1;
  196.                 jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  197.                 jjPIXELMAP lamp(0, 25*32, 4*32, 4*32, 5);
  198.                 lamp.save(frame);
  199.                 frame.hotSpotX = -42;
  200.                 obj.behave(BEHAVIOR::BUMP, false);
  201.         if(obj.justHit == 0)
  202.         {jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::BRIGHTNESS, 180);}
  203.         else    obj.draw();
  204.         }
  205.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
  206.                 if(play !is null && bullet !is null){
  207.                         if(bullet.xPos > obj.xPos)
  208.                                 {bullet.delete();}
  209.                 obj.bulletHandling = HANDLING::HURTBYBULLET;
  210.                 if(gonghit == false) {
  211.                 jjSample(p.xPos, p.yPos, SOUND::PINBALL_BELL);
  212.                 p.showText("@@Once all tokens are collected@this gong will unlock the gate.");}
  213.                 gonghit = true;}
  214.  
  215.                 return true;
  216.         }
  217. }
  218.  
  219. class PlatinCoin : jjBEHAVIORINTERFACE {
  220.  
  221.         void onBehave(jjOBJ@ obj) {
  222.                 if(p.coins >= 1)
  223.                 {obj.delete();}
  224.                 obj.behave(BEHAVIOR::PICKUP, false);
  225.                 ++obj.counter;
  226.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  227.                 if(jjTriggers[1] && jjTriggers[8]==true && jjTriggers[9]==true && jjTriggers[10]==true &&jjTriggers[11]==true && jjTriggers[12]==true)
  228.                 {jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, -8);}
  229.                 else jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::TRANSLUCENTPALSHIFT, -8);
  230. }
  231.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  232.                 if(jjTriggers[1] && jjTriggers[8]==true && jjTriggers[9]==true && jjTriggers[10]==true &&jjTriggers[11]==true && jjTriggers[12]==true)
  233.                 {p.coins += 1;
  234.                 obj.behavior = BEHAVIOR::EXPLOSION2;           
  235.                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_COIN, 1000);}
  236.                 else
  237.                 {p.showText("@@Collect all 6 artifacts first.");}
  238.  
  239.                 return true;
  240.         }
  241. }
  242.  
  243. int SuperCopterOn = 0;
  244. class SuperCopter : jjBEHAVIORINTERFACE {
  245.         void onBehave(jjOBJ@ obj) {
  246.  
  247. obj.behave(BEHAVIOR::PICKUP, false);
  248. obj.determineCurAnim(ANIM::PICKUPS, 33);
  249. ++obj.counter;
  250.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  251.  
  252.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, -8);
  253.  
  254. }
  255.  
  256.         bool onObjectHit(jjOBJ@ obj, jjOBJ@, jjPLAYER@ play, int force) {
  257.                 play.timerStart(240);
  258.                 p.morphTo(CHAR::JAZZ);
  259.                 SuperCopterOn= jjGameTicks + 4 * 61;
  260.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  261.                 obj.frameID = 0;
  262.                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_PICKUP1, 6000);
  263.  
  264.                 return true;
  265.         }
  266.  
  267. }
  268.  
  269. class FlyingSpring : jjBEHAVIORINTERFACE {
  270.  
  271.         void onBehave(jjOBJ@ obj) {
  272.                 float YSpeed = 22;
  273.                 obj.behave(BEHAVIOR::BUTTERFLY,false);
  274.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::SINGLEHUE, 72);
  275.  
  276.                 jjPARTICLE@ particle = jjAddParticle(PARTICLE::STAR);
  277.                 particle.snow.frame = jjRandom() & 987;
  278.                 particle.xPos = obj.xPos;
  279.                 particle.yPos = obj.yPos+14;
  280.         }
  281.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int) {
  282.                 if(bullet !is null) {
  283.                 obj.causesRicochet = true;
  284.                 }
  285.                 else
  286.                 player.direction = player.ySpeed = -42;
  287.                 obj.scriptedCollisions = true;
  288.                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_SPRING1);
  289.                 return true;
  290.                 }
  291. }
  292.  
  293.  
  294. class Fastrun : jjBEHAVIORINTERFACE {
  295.         void onBehave(jjOBJ@ obj) {
  296.                 obj.behave(BEHAVIOR::PICKUP, false);
  297.                 obj.determineCurAnim(ANIM::PICKUPS, 33);
  298.                 ++obj.counter;
  299.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  300.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, -32);
  301.         }
  302.  
  303.         bool onObjectHit(jjOBJ@ obj, jjOBJ@, jjPLAYER@ play, int force) {
  304.         play.timerStart(1800);
  305.                 SpeedUpUntil = jjGameTicks + 30 * 61;
  306.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  307.                 obj.frameID = 0;
  308.                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_PICKUP1, 6000);
  309.                 jjTriggers[14] = true;
  310.  
  311.                 return true;
  312.         }
  313.  
  314. }
  315.  
  316. class Key : jjBEHAVIORINTERFACE {
  317.  
  318.         void onBehave(jjOBJ@ obj) {
  319.                 obj.behave(BEHAVIOR::PICKUP, false);
  320.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::FRIES].curAnim];
  321.         anim.frameCount = 1;
  322.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  323.         jjPIXELMAP pump(0, 18*32, 1*32, 1*32, 5);
  324.         pump.save(frame);
  325.                 ++obj.counter;
  326.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  327.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  328. }
  329.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  330.                 jjTriggers[2] = true;
  331.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  332.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  333.  
  334.                 return true;
  335.         }
  336. }
  337.  
  338.  
  339. class Chakra : jjBEHAVIORINTERFACE {
  340.  
  341.         void onBehave(jjOBJ@ obj) {
  342.                 if(jjTriggers[11] == true)
  343.                         {obj.delete();}
  344.                 obj.behave(BEHAVIOR::PICKUP, false);
  345.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::AIRBOARD].curAnim];
  346.         anim.frameCount = 1;
  347.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  348.         jjPIXELMAP pump(0, 11*32, 1*32, 1*32, 5);
  349.         pump.save(frame);
  350.                 ++obj.counter;
  351.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  352.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  353. }
  354.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  355.                 jjTriggers[11] = true;
  356.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  357.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  358.  
  359.                 return true;
  360.         }
  361. }
  362.  
  363. class Chakra2 : jjBEHAVIORINTERFACE {
  364.  
  365.         void onBehave(jjOBJ@ obj) {
  366.                 if(jjTriggers[1] == true)
  367.                         {obj.delete();}
  368.                 obj.behave(BEHAVIOR::PICKUP, false);
  369.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::CHIPS].curAnim];
  370.         anim.frameCount = 1;
  371.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  372.         jjPIXELMAP pump(0, 12*32, 1*32, 1*32, 5);
  373.         pump.save(frame);
  374.                 ++obj.counter;
  375.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  376.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  377. }
  378.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  379.                 jjTriggers[1] = true;
  380.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  381.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  382.  
  383.                 return true;
  384.         }
  385. }
  386.  
  387. class Chakra3 : jjBEHAVIORINTERFACE {
  388.  
  389.         void onBehave(jjOBJ@ obj) {
  390.                 if(jjTriggers[10] == true)
  391.                         {obj.delete();}
  392.                 obj.behave(BEHAVIOR::PICKUP, false);
  393.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::PRETZEL].curAnim];
  394.         anim.frameCount = 1;
  395.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  396.         jjPIXELMAP pump(0, 17*32, 1*32, 1*32, 5);
  397.         pump.save(frame);
  398.                 ++obj.counter;
  399.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  400.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  401. }
  402.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  403.                 jjTriggers[10] = true;
  404.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  405.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  406.  
  407.                 return true;
  408.         }
  409. }
  410.  
  411. class Chakra4 : jjBEHAVIORINTERFACE {
  412.  
  413.         void onBehave(jjOBJ@ obj) {
  414.                 if(jjTriggers[8] == true)
  415.                         {obj.delete();}
  416.                 obj.behave(BEHAVIOR::PICKUP, false);
  417.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::CHICKENLEG].curAnim];
  418.         anim.frameCount = 1;
  419.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  420.         jjPIXELMAP pump(0, 14*32, 1*32, 1*32, 5);
  421.         pump.save(frame);
  422.                 ++obj.counter;
  423.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  424.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  425. }
  426.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  427.                 jjTriggers[8] = true;
  428.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  429.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  430.  
  431.                 return true;
  432.         }
  433. }
  434.  
  435. class Chakra5 : jjBEHAVIORINTERFACE {
  436.  
  437.         void onBehave(jjOBJ@ obj) {
  438.                 if(jjTriggers[9] == true)
  439.                         {obj.delete();}
  440.                 obj.behave(BEHAVIOR::PICKUP, false);
  441.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::WEENIE].curAnim];
  442.         anim.frameCount = 1;
  443.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  444.         jjPIXELMAP pump(0, 15*32, 1*32, 1*32, 5);
  445.         pump.save(frame);
  446.                 ++obj.counter;
  447.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  448.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  449. }
  450.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  451.                 jjTriggers[9] = true;
  452.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  453.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  454.  
  455.                 return true;
  456.         }
  457. }
  458.  
  459. class Chakra6 : jjBEHAVIORINTERFACE {
  460.  
  461.         void onBehave(jjOBJ@ obj) {
  462.                 if(jjTriggers[12] == true)
  463.                         {obj.delete();}
  464.                 obj.behave(BEHAVIOR::PICKUP, false);
  465.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::FREEZEENEMIES].curAnim];
  466.         anim.frameCount = 1;
  467.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  468.         jjPIXELMAP pump(0, 16*32, 1*32, 1*32, 5);
  469.         pump.save(frame);
  470.                 ++obj.counter;
  471.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  472.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  473. }
  474.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  475.                 jjTriggers[12] = true;
  476.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  477.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  478.  
  479.                 return true;
  480.         }
  481. }
  482.  
  483. class Chakra7 : jjBEHAVIORINTERFACE {
  484.  
  485.         void onBehave(jjOBJ@ obj) {
  486.                 if(jjTriggers[12] == true)
  487.                         {obj.delete();}
  488.                 obj.behave(BEHAVIOR::PICKUP, false);
  489.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::HAM].curAnim];
  490.         anim.frameCount = 1;
  491.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  492.         jjPIXELMAP pump(0, 13*32, 1*32, 1*32, 5);
  493.         pump.save(frame);
  494.                 ++obj.counter;
  495.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  496.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  497. }
  498.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  499.                 jjTriggers[12] = true;
  500.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  501.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  502.                 p.showText("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Temple Gate unlocked.");
  503.                 return true;
  504.         }
  505. }
  506.  
  507. void PlatformH (jjOBJ@ obj) {
  508.  
  509.         switch (obj.state) {
  510.                 case STATE::START:
  511.                         obj.direction = obj.xSpeed = -2;
  512.                         obj.determineCurAnim(ANIM::GRASSPLAT, 0);  
  513.                         obj.determineCurFrame();
  514.                         obj.playerHandling = HANDLING::SPECIAL;
  515.                         obj.state = STATE::FLY;
  516.                         obj.beSolid();
  517.                 case STATE::FLY:
  518.                         obj.xPos = obj.xPos + obj.xSpeed;
  519.                         obj.beSolid();
  520.                         obj.deactivates = false;
  521.                         if (jjMaskedVLine(obj.xSpeed > 0 ? obj.xPos + 16 : obj.xPos - 16, obj.yPos, 1)) {
  522.                                 obj.direction = obj.xSpeed = -obj.xSpeed;
  523.                         }
  524.                         obj.draw();
  525.  
  526.                         break;
  527.  
  528.         }
  529. }
  530.  
  531.  
  532. void onLevelReload() {
  533.         gem::restorePlayerGems();
  534.         jjLocalPlayers[0].lives++;
  535.         buyammo = false;
  536.         for (uint i = 0; i < 32; ++i)
  537.                 jjTriggers[i] = SavedTriggers[i];
  538. }
  539.  
  540.  
  541. void onMain() {
  542. gem::deleteCollectedGems();
  543. if(jjKey[9] && jjKey[0x51]) {
  544. p.morphTo(CHAR::JAZZ, false);
  545. }
  546. if(jjKey[9] && jjKey[0x57]) {
  547. p.morphTo(CHAR::SPAZ, false);
  548. }
  549. if(jjKey[9] && jjKey[0x45]) {
  550. p.morphTo(CHAR::LORI, false);
  551. }
  552.  
  553. }
  554.  
  555. int slope = 0;
  556.  
  557. void onFunction0(jjPLAYER@ p) {
  558.         p.showText("@@@@@@@@@@@@@@@@@@@@@@@@@TEMPLE OF BUDDHA", STRING::MEDIUM);
  559.         jjEnabledASFunctions[0] = false;}
  560.  
  561. void onFunction1(jjPLAYER@ p) {
  562.         p.showText("@@@@@@@@@@@@@@@@@@@@@@@@@MT. EVEREST", STRING::MEDIUM);
  563.         jjEnabledASFunctions[0] = false;}
  564.  
  565. void onFunction2(jjPLAYER@ p) {
  566.         SpeedUpUntil = 0;
  567.         p.timerStop();}
  568.  
  569. void onFunction3(jjPLAYER@ p)
  570. {copterfloat = false;}
  571. void onFunction4(jjPLAYER@ p)
  572. {copterfloat = true;}
  573.  
  574. void onFunction5(jjPLAYER@ p) {
  575. slope = jjGameTicks + 2*61;
  576. }
  577. void onFunction6(jjPLAYER@ p) {
  578. slope = 0;
  579. }
  580.  
  581. void onFunction11(jjPLAYER@ p) {
  582. SuperCopterOn = 0;
  583. jjTriggers[31] = true;
  584. }
  585.  
  586. void onFunction10(jjPLAYER@ p) {
  587. p.cameraUnfreeze();
  588. }
  589.  
  590. bool doorunblocked = false;
  591. bool buyammo = false;
  592. bool startrush = false;
  593. bool readytorush = false;
  594.  
  595. void onPlayer(jjPLAYER@ p) {
  596.  
  597.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::EXTRALIFE].curAnim];
  598.         anim.frameCount = 1;
  599.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  600.         jjPIXELMAP pump(0, 13*32, 1*32, 1*32, 5);
  601.         pump.save(frame);
  602.  
  603.         exit = 0;
  604.         if(jjTriggers[1] == true)
  605.                 {exit += 1;}
  606.         if(jjTriggers[8] == true)
  607.                 {exit += 1;}
  608.         if(jjTriggers[9] == true)
  609.                 {exit += 1;}
  610.         if(jjTriggers[10] == true)
  611.                 {exit += 1;}
  612.         if(jjTriggers[11] == true)
  613.                 {exit += 1;}
  614.         if(jjTriggers[12] == true)
  615.                 {exit += 1;}
  616.  
  617.         if(p.xPos > 114*32)
  618.         {SpeedUpUntil = 0;}
  619.  
  620.         if(p.xPos < 114*32)
  621.         {SuperCopterOn = 0;}
  622.  
  623.         if(p.xPos > 113*32 && p.xPos < 115*32)
  624.         {p.timerStop();}
  625.  
  626.         gem::trackPlayerGems(p);
  627.         gem::upgradeHealth(p);
  628.         p.lightType = LIGHT::NONE;
  629.  
  630.         if(p.food == 100 && jjKey[0x52] == false && startrush == false)
  631.                 {p.showText("@@@@@@@@@@@@@@@@Press 'R' when you need to use Sugar Rush!", STRING::MEDIUM);
  632.                 p.startSugarRush(0);
  633.                 startrush = true;
  634.                 readytorush = true;}
  635.  
  636.         if(readytorush == true)
  637.                 {p.food = 100;}
  638.  
  639.         if(p.food == 100 && jjKey[0x52])
  640.                 {p.startSugarRush(1400);
  641.                 p.food = 0;
  642.                 readytorush = false;
  643.                 startrush = false;
  644.         }
  645.  
  646.         if(p.ammo[WEAPON::SEEKER] < 1 && p.xPos>66*32 && p.xPos<70*32 && p.yPos<44*32 && p.yPos>40*32 && jjKey[0x50] && p.gems[GEM::RED]<50 && buyammo == false)
  647.                 {p.testForGems(50, GEM::RED);}
  648.         if(p.ammo[WEAPON::SEEKER] < 1 && p.xPos>66*32 && p.xPos<70*32 && p.yPos<44*32 && p.yPos>40*32 && jjKey[0x50] && p.gems[GEM::RED]>=50 && buyammo == false)
  649.         {p.testForGems(50, GEM::RED);
  650.         jjTriggers[3]=true;
  651.         buyammo = true;}
  652.         if(p.ammo[WEAPON::SEEKER] >= 1 && p.xPos>66*32 && p.xPos<70*32 && p.yPos<44*32 && p.yPos>40*32 && jjKey[0x50] && buyammo == false)
  653.                 {p.showText("@@You already have the weapon.");}
  654.  
  655.                 if (doorunblocked == false && jjTriggers[1]==true && jjTriggers[8]==true && jjTriggers[9]==true && jjTriggers[10]==true&& jjTriggers[11]==true && jjTriggers[12]==true) {
  656.                 p.showText("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Token unlocked.");
  657.                 doorunblocked = true;}
  658. if(copterfloat == true)
  659. {jjCharacters[CHAR::JAZZ].helicopterYSpeed= -2;
  660. jjCharacters[CHAR::LORI].helicopterYSpeed= -2;}
  661. if(copterfloat == false)
  662. {jjCharacters[CHAR::JAZZ].helicopterYSpeed= 1;
  663. jjCharacters[CHAR::LORI].helicopterYSpeed= 1;}
  664.  
  665. if(p.keyUp && slope > jjGameTicks){
  666.         p.yPos = p.yPos - 4;
  667.         p.invisibility = true;
  668.         jjDrawSprite(p.xPos, p.yPos, p.setID, RABBIT::HPOLE, p.curFrame, p.direction, SPRITE::PLAYER);
  669.         }
  670. if(p.keyUp == false && slope > jjGameTicks){
  671.         p.invisibility = false;
  672. }
  673. if(slope < jjGameTicks){
  674.         p.invisibility = false;
  675. }
  676.  
  677.         for (int i = 1; i < jjObjectCount; i++) {
  678.         jjOBJ@ o = jjObjects[i];
  679.                 if (o.isActive && o.eventID == OBJECT::SILVERCOIN && p.coins >= 1) {
  680.                 o.state = STATE::KILL;
  681.                 }
  682.  
  683.         }
  684.  
  685.         if(p.keyUp && Lever15 == false && p.xPos > 25*32 && p.xPos < 28*32 && p.yPos < 30*32 && p.yPos > 27*32)
  686.         {jjTriggers[15] = false;
  687.         Lever15 = true;}
  688.  
  689.         if(p.keyUp && Lever16 == false && p.xPos > 14*32 && p.xPos < 17*32 && p.yPos < 30*32 && p.yPos > 27*32)
  690.         {jjTriggers[16] = false;
  691.         Lever16 = true;}
  692.  
  693.         if(jjTriggers[16] == true)
  694.         {Lever16 = false;}
  695.  
  696.         if(jjTriggers[15] == true)
  697.         {Lever15 = false;}
  698.  
  699.         if(p.keyUp && Lever4 == false && p.xPos > 221*32 && p.xPos < 224*32 && p.yPos < 38*32 && p.yPos > 35*32)
  700.         {jjTriggers[4] = true;
  701.         Lever4 = true;}
  702.  
  703.         if(p.coins<1 && p.xPos < 111*32 && p.xPos > 108*32 && p.yPos < 3*32)
  704.         {p.testForCoins(1);}
  705.         if(p.coins>=1 && p.xPos < 111*32 && p.xPos > 108*32 && p.yPos < 3*32)
  706.         {jjNxt("mo4a_4-2_save", false, true);
  707.         gem::saveGemData();}
  708.  
  709.         if(p.coins<3 && p.xPos < 116*32 && p.xPos > 113*32 && p.yPos < 52*32 && p.yPos > 47*32)
  710.         {p.testForCoins(3);}
  711.         if(p.coins>=3 && p.xPos < 116*32 && p.xPos > 113*32 && p.yPos < 52*32 && p.yPos > 47*32)
  712.         {jjNxt("mo4a_4-4_save", false, true);
  713.         gem::saveGemData();}
  714.  
  715.         if(SuperCopterOn > jjGameTicks)
  716.         {jjCharacters[CHAR::JAZZ].helicopterYSpeed= 0;}
  717.         if(SuperCopterOn < jjGameTicks && copterfloat == false)
  718.         {jjCharacters[CHAR::JAZZ].helicopterYSpeed= 1;}
  719.  
  720. if (SpeedUpUntil > jjGameTicks) {
  721. p.keyRun = true;
  722. if(p.keyRight)
  723. p.xSpeed = 30;
  724. if(p.keyLeft)
  725. p.xSpeed = -30;
  726.   }
  727.  
  728. if (SpeedUpUntil < jjGameTicks)
  729.                 {jjTriggers[14] = false;}
  730.  
  731.         for (int i = 1; i < jjObjectCount; i++) {
  732.                 jjOBJ@ o = jjObjects[i];
  733.                 if (o.isActive && o.eventID == OBJECT::RFAMMO3 && p.ammo[WEAPON::RF] < 1) {
  734.                         o.state = STATE::KILL;}
  735.         }
  736.         for (int i = 1; i < jjObjectCount; i++) {
  737.                 jjOBJ@ o = jjObjects[i];
  738.                 if (o.isActive && o.eventID == OBJECT::TNTAMMO3 && p.ammo[WEAPON::TNT] < 1) {
  739.                         o.state = STATE::KILL;}
  740.         }
  741.         for (int i = 1; i < jjObjectCount; i++) {
  742.                 jjOBJ@ o = jjObjects[i];
  743.                 if (o.isActive && o.eventID == OBJECT::GUN9AMMO3 && p.ammo[WEAPON::GUN9] < 1) {
  744.                         o.state = STATE::KILL;}
  745.         }
  746.         for (int i = 1; i < jjObjectCount; i++) {
  747.                 jjOBJ@ o = jjObjects[i];
  748.                 if (o.isActive && o.eventID == OBJECT::SEEKERPOWERUP && p.ammo[WEAPON::SEEKER] < 1) {
  749.                         o.state = STATE::KILL;}
  750.         }
  751.         for (int i = 1; i < jjObjectCount; i++) {
  752.                 jjOBJ@ o = jjObjects[i];
  753.                 if (o.isActive && o.eventID == OBJECT::RFPOWERUP && p.ammo[WEAPON::RF] < 1) {
  754.                         o.state = STATE::KILL;}
  755.         }
  756.         for (int i = 1; i < jjObjectCount; i++) {
  757.                 jjOBJ@ o = jjObjects[i];
  758.                 if (o.isActive && o.eventID == OBJECT::TNTPOWERUP && p.ammo[WEAPON::TNT] < 1) {
  759.                         o.state = STATE::KILL;}
  760.         }
  761.         for (int i = 1; i < jjObjectCount; i++) {
  762.                 jjOBJ@ o = jjObjects[i];
  763.                 if (o.isActive && o.eventID == OBJECT::GUN9POWERUP && p.ammo[WEAPON::GUN9] < 1) {
  764.                         o.state = STATE::KILL;}
  765.         }
  766. }
  767.  
  768.  
  769. void onFunction12(jjPLAYER@ p) {
  770. p.cameraFreeze(115*32, 43*32, true, false);
  771. }
  772.  
  773.  
  774. bool onDrawHealth(jjPLAYER@ player, jjCANVAS@ canvas) {
  775.     canvas.drawSprite(100, 580, ANIM::PICKUPS, 0, jjGameTicks>>2, -1, SPRITE::NORMAL);
  776.     canvas.drawString(110, 585, formatInt(exit%7, "1") + "/6", STRING::SMALL, STRING::NORMAL);
  777.     canvas.drawSprite(20, 585, ANIM::PICKUPS, 84, jjGameTicks>>2, -1, SPRITE::PALSHIFT, -8);
  778.     canvas.drawString(30, 585, formatInt(player.coins%4, "1") + "/3", STRING::SMALL, STRING::NORMAL);
  779.     return false;
  780. }
  781.  
  782. bool onDrawLives(jjPLAYER@ player, jjCANVAS@ canvas) {return true;}
  783.  
  784. array<bool> SavedTriggers(32, false);
  785. //Extendable Checkpoints by VioletCLM
  786. void CheckpointWrapper(jjOBJ@ obj) {
  787.   if (obj.state == STATE::STOP) { //don't do anything anymore
  788.     jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 8);
  789.   } else if (obj.state == STATE::DEACTIVATE) { //due to death
  790.     obj.deactivate();
  791.   } else {
  792.     obj.behave(BEHAVIOR::CHECKPOINT);
  793.         jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 8);
  794.     if (obj.state == STATE::DONE) { //triggered by the player hitting it
  795.       obj.state = STATE::STOP;
  796.       //save the current state of some properties
  797.       for (uint i = 0; i < 32; ++i)
  798.         SavedTriggers[i] = jjTriggers[i];
  799.  
  800.       //OPTIONAL: this loop makes checkpoints reusable, so only the most recent checkpoint you touched is ever active
  801.       for (int i = jjObjectCount; --i > 0;) {
  802.         jjOBJ@ obj2 = jjObjects[i];
  803.         if (obj2.eventID == OBJECT::CHECKPOINT && i != obj.objectID && obj2.isActive) {
  804.           obj2.state = STATE::SLEEP;
  805.           obj2.var[0] = 0;
  806.         }
  807.       }
  808.     }
  809.   }
  810. }
  811.  
  812.  
  813. jjTEXTAPPEARANCE SignTextAppearance = STRING::NORMAL;
  814. class Sign {
  815.         private int xPos, yPos; //These pixel-based positions will be generated from tile-based positions in the constructor by multiplying by 32
  816.         private string text;
  817.         private uint widthOfText;
  818.         Sign(){} //AngelScript requires any class that appears in any array to have an explicit default constructor, even if it's never called
  819.         Sign(int xTile, int yTile, const string &in t) {
  820.                 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
  821.                 yPos = yTile * 32; //
  822.                 text = t;
  823.                 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.
  824.                 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.
  825.                 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.
  826.         }
  827.         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.
  828.                 layer.drawRectangle(xPos, yPos - 16, widthOfText + 8, 55, 0, SPRITE::TRANSLUCENT);
  829.                 layer.drawString(xPos, yPos, text, STRING::SMALL, SignTextAppearance, 0, SPRITE::BLEND_HARDLIGHT, textIntensity);
  830.         }
  831. }
  832. const array<Sign> Signs = {
  833.         Sign(5, 64, "You're almost there for the\nlast Time Freezer. Good luck!"),
  834.         Sign(58, 63, "Demons are in our Sacred Temple.\nThey are on to something."),
  835.         Sign(53, 41, "Weird plants started growing in\nthese lands. I bet it's Demons' work."),
  836.         Sign(168, 7, "There will always be obstacles\nin your path..."),
  837.         Sign(77, 32, "Always climb up\nto proceed."),
  838.         Sign(49, 61, "Demons are builing a fortress above the\nmountains, working on special experiments."),
  839.         Sign(30, 50, "Collect the chakra symbols\nfrom the Chakra Temples."),
  840.         Sign(117, 50, "Demon lies beneath this temple. Collect\n6 CHAKRA symbols to get one of the tokens."),
  841.         Sign(68, 40, "Press P if you'd like to\nbuy Voranj for 50 Gems."),
  842. };
  843.  
  844. void onDrawLayer3(jjPLAYER@, jjCANVAS@ layer) {
  845.         if(jjKey[0x54]){
  846.         const uint8 textIntensity = 200 + int(jjSin(jjGameTicks * 16) * 50);
  847.         for (uint signID = 0; signID < Signs.length; ++signID)
  848.                 Signs[signID].draw(layer, textIntensity);
  849. }
  850. }
  851. bool onDrawAmmo(jjPLAYER@ player, jjCANVAS@ canvas) {
  852.         return MLLE::WeaponHook.drawAmmo(player, canvas);
  853. }
  854.