Downloads containing mo4a_3-4.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-4.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.  
  16. bool boss = false;
  17. int Lever19 = 0, Lever21 = 0, Lever22 = 0, killThea = 0;
  18. int CountlessDoubleJumps = 0;
  19. bool poisoned= false, ElevatorUp = false;
  20. uint limitedOxygen = 0;
  21. int slope = 0, exit = 0;
  22. bool Leveractivated22 = false,  Leveractivated21 = false, Leveractivated19 = false, control = true;
  23.  
  24. bool onDrawLives(jjPLAYER@ play, jjCANVAS@ canvas) {return true;}
  25.  
  26.  
  27. bool onDrawAmmo(jjPLAYER@ p, jjCANVAS@ canvas)   {
  28.         return MLLE::WeaponHook.drawAmmo(p, canvas);
  29. if(p.xPos < 223*32){
  30. return false;}
  31. else return true;
  32. }
  33.  
  34. bool onDrawHealth(jjPLAYER@ play, jjCANVAS@ canvas) {
  35. if(p.xPos < 223*32){
  36.     canvas.drawSprite(20, 585, ANIM::PICKUPS, 11, jjGameTicks>>2, -1, SPRITE::NORMAL);
  37.     canvas.drawString(30, 585, formatInt(exit%4, "1") + "/3", STRING::SMALL, STRING::NORMAL);
  38.  
  39.   if (limitedOxygen > 0 && limitedOxygen < 420) {
  40.   canvas.drawSprite(jjSubscreenWidth-12, jjSubscreenHeight-574, ANIM::COMMON, 1, 3, 0, SPRITE::NORMAL, 0); canvas.drawSprite(jjSubscreenWidth-28, jjSubscreenHeight-574, ANIM::COMMON, 1, 3, 0, SPRITE::NORMAL, 0); canvas.drawSprite(jjSubscreenWidth-44, jjSubscreenHeight-574, ANIM::COMMON, 1, 3, 0, SPRITE::NORMAL, 0); canvas.drawSprite(jjSubscreenWidth-60, jjSubscreenHeight-574, ANIM::COMMON, 1, 3, 0, SPRITE::NORMAL, 0);
  41.   canvas.drawSprite(jjSubscreenWidth-76, jjSubscreenHeight-574, ANIM::COMMON, 1, 3, 0, SPRITE::NORMAL, 0);
  42.   }
  43.  
  44.   if (limitedOxygen > 420 && limitedOxygen < 840) {
  45.   canvas.drawSprite(jjSubscreenWidth-12, jjSubscreenHeight-574, ANIM::COMMON, 1, 3, 0, SPRITE::NORMAL, 0); canvas.drawSprite(jjSubscreenWidth-28, jjSubscreenHeight-574, ANIM::COMMON, 1, 3, 0, SPRITE::NORMAL, 0); canvas.drawSprite(jjSubscreenWidth-44, jjSubscreenHeight-574, ANIM::COMMON, 1, 3, 0, SPRITE::NORMAL, 0); canvas.drawSprite(jjSubscreenWidth-60, jjSubscreenHeight-574, ANIM::COMMON, 1, 3, 0, SPRITE::NORMAL, 0);
  46.   }
  47.  
  48.   if (limitedOxygen > 840 && limitedOxygen < 1260) {
  49.   canvas.drawSprite(jjSubscreenWidth-12, jjSubscreenHeight-574, ANIM::COMMON, 1, 3, 0, SPRITE::NORMAL, 0); canvas.drawSprite(jjSubscreenWidth-28, jjSubscreenHeight-574, ANIM::COMMON, 1, 3, 0, SPRITE::NORMAL, 0); canvas.drawSprite(jjSubscreenWidth-44, jjSubscreenHeight-574, ANIM::COMMON, 1, 3, 0, SPRITE::NORMAL, 0);
  50.   }
  51.  
  52.   if (limitedOxygen > 1260 && limitedOxygen < 1680) {
  53.   canvas.drawSprite(jjSubscreenWidth-12, jjSubscreenHeight-574, ANIM::COMMON, 1, 3, 0, SPRITE::NORMAL, 0); canvas.drawSprite(jjSubscreenWidth-28, jjSubscreenHeight-574, ANIM::COMMON, 1, 3, 0, SPRITE::NORMAL, 0);
  54.   }
  55.  
  56.   if (limitedOxygen > 1680 && limitedOxygen < 2100) {
  57.   canvas.drawSprite(jjSubscreenWidth-12, jjSubscreenHeight-574, ANIM::COMMON, 1, 3, 0, SPRITE::NORMAL, 0);
  58.   }
  59.  
  60.   return false;
  61. }
  62. else return true;
  63. }
  64.        
  65. bool doorunblocked = false;
  66.  
  67. void onPlayer(jjPLAYER@ p) {
  68.  
  69.                 if(control==false)
  70.                 {p.keyLeft = false;
  71.                 p.keyRight = false;
  72.                 p.keyDown = false;}
  73.  
  74.                 if(p.idle > 100 && p.xPos < 223*32)
  75.                 {p.cameraUnfreeze(true);
  76.                 control=true;}
  77.                 else if (p.idle > 5 && (p.keyLeft || p.keyRight || p.keyJump || p.keyFire))
  78.                 {p.cameraUnfreeze(true);
  79.                 control=true;}
  80.  
  81.         exit = 0;
  82.         if(jjTriggers[4] == true)
  83.                 {exit += 1;}
  84.         if(jjTriggers[7] == true)
  85.                 {exit += 1;}
  86.         if(jjTriggers[15] == true)
  87.                 {exit += 1;}
  88.  
  89.         gem::trackPlayerGems(p);
  90.         gem::upgradeHealth(p);
  91.  
  92.                 if (doorunblocked == false && jjTriggers[4]==true && jjTriggers[7]==true && jjTriggers[15]==true) {
  93.                 p.showText("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Keys collected.");
  94.                 doorunblocked = true;}
  95.         if(p.xPos > 223*32 && p.xPos <244*32)
  96.                 {p.cameraFreeze(240*32, 56*32,true, true);
  97.                 p.lighting = 0;
  98.                 p.idle = 100;
  99.                 p.invisibility = true;}
  100.        
  101.         if(p.xPos < 223*32 && p.yPos < 6*32)
  102.                 p.cameraUnfreeze();
  103.  
  104.         for (int i = 1; i < jjObjectCount; i++) {
  105.                 jjOBJ@ o = jjObjects[i];
  106.                 if (o.isActive && o.eventID == OBJECT::SEEKERAMMO3 && p.ammo[WEAPON::SEEKER] < 1) {
  107.                         o.state = STATE::KILL;}
  108.         }
  109.         for (int i = 1; i < jjObjectCount; i++) {
  110.                 jjOBJ@ o = jjObjects[i];
  111.                 if (o.isActive && o.eventID == OBJECT::RFAMMO3 && p.ammo[WEAPON::RF] < 1) {
  112.                         o.state = STATE::KILL;}
  113.         }
  114.         for (int i = 1; i < jjObjectCount; i++) {
  115.                 jjOBJ@ o = jjObjects[i];
  116.                 if (o.isActive && o.eventID == OBJECT::TNTAMMO3 && p.ammo[WEAPON::TNT] < 1) {
  117.                         o.state = STATE::KILL;}
  118.         }
  119.         for (int i = 1; i < jjObjectCount; i++) {
  120.                 jjOBJ@ o = jjObjects[i];
  121.                 if (o.isActive && o.eventID == OBJECT::GUN9AMMO3 && p.ammo[WEAPON::GUN9] < 1) {
  122.                         o.state = STATE::KILL;}
  123.         }
  124.         for (int i = 1; i < jjObjectCount; i++) {
  125.                 jjOBJ@ o = jjObjects[i];
  126.                 if (o.isActive && o.eventID == OBJECT::SEEKERPOWERUP && p.ammo[WEAPON::SEEKER] < 1) {
  127.                         o.state = STATE::KILL;}
  128.         }
  129.         for (int i = 1; i < jjObjectCount; i++) {
  130.                 jjOBJ@ o = jjObjects[i];
  131.                 if (o.isActive && o.eventID == OBJECT::RFPOWERUP && p.ammo[WEAPON::RF] < 1) {
  132.                         o.state = STATE::KILL;}
  133.         }
  134.         for (int i = 1; i < jjObjectCount; i++) {
  135.                 jjOBJ@ o = jjObjects[i];
  136.                 if (o.isActive && o.eventID == OBJECT::TNTPOWERUP && p.ammo[WEAPON::TNT] < 1) {
  137.                         o.state = STATE::KILL;}
  138.         }
  139.         for (int i = 1; i < jjObjectCount; i++) {
  140.                 jjOBJ@ o = jjObjects[i];
  141.                 if (o.isActive && o.eventID == OBJECT::GUN9POWERUP && p.ammo[WEAPON::GUN9] < 1) {
  142.                         o.state = STATE::KILL;}
  143.         }
  144.  
  145. if(p.keyUp && slope > jjGameTicks){
  146.         p.yPos = p.yPos - 4;
  147.         p.invisibility = true;
  148.         jjDrawSprite(p.xPos, p.yPos, p.setID, RABBIT::HPOLE, p.curFrame, p.direction, SPRITE::PLAYER);
  149.         }
  150. if(p.keyUp == false && slope > jjGameTicks){
  151.         p.invisibility = false;
  152. }
  153. if(slope < jjGameTicks){
  154.         p.invisibility = false;
  155. }
  156.  
  157. if((p.xPos > 223*32 && (p.keyJump || p.keyFire)) || p.xPos>244*32)
  158. {p.xPos =87*32;
  159. p.yPos = 3*32;
  160. p.resetLight();
  161. p.showText("@@Extreme depth here.@I won't be holding my breath that long.");
  162. jjSetWaterLevel(-32, true);}   
  163.  
  164. if(p.coins == 0){
  165. p.coins += 3;
  166. }
  167. if (CountlessDoubleJumps > jjGameTicks && p.keyJump) {
  168.         p.doubleJumpCount = 0;}
  169.  
  170. if (p.health == 0){
  171.         CountlessDoubleJumps  = 0;
  172. }
  173.   if (p.yPos < jjWaterLevel) {
  174.         jjMusicLoad("mo4a_Umber's Sacrifice.ogg");}
  175.   if (p.yPos > jjWaterLevel && p.bossActivated == false) {
  176.         jjMusicLoad("mo4a_Carnaval2m07.ogg");}
  177.                
  178.   if (p.yPos > jjWaterLevel) {
  179.     switch(p.shieldType) {
  180.       case 0: limitedOxygen++; p.shieldTime = 0; p.shieldType = 0; break;
  181.       case 1: limitedOxygen++; p.shieldTime = 0; p.shieldType = 0; break;
  182.       case 2: limitedOxygen = 0; break;
  183.       case 3: limitedOxygen++; p.shieldTime = 0; p.shieldType = 0; break;
  184.       case 4: limitedOxygen++; p.shieldTime = 0; p.shieldType = 0; break;
  185.     }
  186.   }
  187.   else { limitedOxygen = 0;
  188.   }
  189.  
  190.   if (limitedOxygen == 2100) {
  191.     p.kill();
  192.   }
  193.  
  194.   if (p.health == 0) limitedOxygen = 0;
  195.  
  196.         p.lightType = LIGHT::NONE;
  197.  
  198.         if(p.keyUp && p.xPos >45*32 && p.xPos <48*32 && p.yPos <47*32 && p.yPos >44*32)
  199.                 {if(jjTriggers[3]==false)
  200.                 {jjSample(p.xPos, p.yPos, SOUND::INTRO_MONSTER2, 1000);}
  201.                 jjTriggers[3] = true;
  202.                 p.cameraFreeze(40*32, 61*32, true, false);}
  203.         if(p.keyUp && p.xPos >189*32 && p.xPos <192*32 && p.yPos <23*32 && p.yPos >20*32)
  204.                 {if(jjTriggers[8]==false)
  205.                 {jjSample(p.xPos, p.yPos, SOUND::INTRO_MONSTER2, 1000);}
  206.                 jjTriggers[8] = true;
  207.                 p.cameraFreeze(161*32, 34*32, true, false);}
  208.  
  209.         if(p.keyUp && p.xPos >4*32 && p.xPos <7*32 && p.yPos <68*32 && p.yPos >65*32)
  210.         {jjTriggers[1] = true;
  211.         jjTriggers[5] = false;
  212.         jjTriggers[14] = false;
  213.         }
  214.         if(p.keyUp && p.xPos >66*32 && p.xPos <69*32 && p.yPos <7*32 && p.yPos >5*32)
  215.         {jjTriggers[5] = true;
  216.         jjTriggers[1] = false;
  217.         jjTriggers[14] = false;
  218.         }
  219.         if(p.keyUp && p.xPos >10*32 && p.xPos <12*32 && p.yPos <26*32 && p.yPos >23*32)
  220.         {jjTriggers[14] = true;
  221.         jjTriggers[5] = false;
  222.         jjTriggers[1] = false;
  223.         }
  224.  
  225.         if(Lever19 < jjGameTicks && Lever21 < jjGameTicks && Lever22 < jjGameTicks)
  226.         {Leveractivated19 = false; Leveractivated21 = false; Leveractivated22 = false;}
  227.  
  228.         if(p.keyUp && Lever19 > jjGameTicks && Leveractivated19 == false)
  229.         {jjTriggers[19] = true;
  230.         Leveractivated19 = true;
  231.                 if(jjTriggers[22] == false && jjTriggers[21] == false)
  232.                 {p.timerStart(1200);}
  233.         }
  234.         if(p.keyUp && Lever21 > jjGameTicks && Leveractivated21 == false)
  235.         {jjTriggers[21] = true;
  236.         Leveractivated21 = true;
  237.                 if(jjTriggers[22] == false && jjTriggers[19] == false)
  238.                 {p.timerStart(1200);}
  239.         }
  240.         if(p.keyUp && Lever22 > jjGameTicks && Leveractivated22 == false)
  241.         {jjTriggers[22] = true;
  242.         Leveractivated22 = true;
  243.                 if(jjTriggers[19] == false && jjTriggers[21] == false)
  244.                 {p.timerStart(1200);}
  245.         }
  246.         if(jjTriggers[19] == true && jjTriggers[21] == true && jjTriggers[22] == true)
  247.                 {jjTriggers[18] = true;}
  248.         if (jjTriggers[11] == true && jjTriggers[12] == true && jjTriggers[13] == true)
  249.         {jjTriggers[10]= true;}
  250.  
  251.         if(poisoned == true && p.xPos > 120*32 && p.yPos > 37*32) {
  252.                 p.shieldType = SHIELD::LASER;
  253.                         p.invisibility = false;
  254.                         p.resetLight();
  255.                         p.lightType = LIGHT::NONE;
  256.                 if(p.keyFire == true) {
  257.                         p.shieldType = SHIELD::LASER;
  258.                         p.shieldTime = 10;
  259.                         p.lightType = LIGHT::FLICKER;
  260.                         p.invisibility = true;
  261.                         p.lighting = 140;
  262.                         jjDrawSprite(p.xPos, p.yPos, p.setID, RABBIT::HURT, p.curFrame, p.direction, SPRITE::PLAYER);
  263.                         jjOBJ@ obj = jjObjects[p.fireBullet(OBJECT::BULLET)];
  264.                                 obj.behavior = BEHAVIOR::BULLET;
  265.                                 obj.determineCurAnim(ANIM::AMMO, 70);
  266.                                 obj.playerHandling = HANDLING::PLAYERBULLET;
  267.                                 obj.bulletHandling = HANDLING::IGNOREBULLET;
  268.                                 obj.lightType = LIGHT::POINT;
  269.                                 obj.xSpeed = 1.2*p.direction;
  270.                                 int xs = (jjRandom() & 39);
  271.                                 obj.xSpeed = xs - 1*p.direction;
  272.                                 obj.ySpeed = 0;
  273.                 }
  274.                
  275.         }
  276. }
  277.  
  278. void onFunction19(jjPLAYER@ p) {
  279. Lever19 = jjGameTicks + 5*61;
  280. }
  281.  
  282. void onFunction8(jjPLAYER@ p) {
  283. slope = jjGameTicks + 2*61;
  284. }
  285.  
  286. void onFunction10(jjPLAYER@ p) {
  287. slope = 0;
  288. }
  289.  
  290. void onFunction4(jjPLAYER@ p) {
  291. jjWaterLighting = WATERLIGHT::GLOBAL;
  292. poisoned = false;
  293. jjSetWaterLevel(-32, true);
  294. }
  295.  
  296. void onFunction21(jjPLAYER@ p) {
  297. Lever21 = jjGameTicks + 5*61;
  298. }
  299.  
  300. void onFunction22(jjPLAYER@ p) {
  301. Lever22 = jjGameTicks + 5*61;
  302. }
  303.  
  304.  
  305.  
  306. void onPlayerTimerEnd(jjPLAYER@ p) {
  307.                 jjTriggers[18] = false;
  308.                 jjTriggers[19] = false;
  309.                 jjTriggers[21] = false;
  310.                 jjTriggers[22] = false;}
  311.  
  312. void onMain() {
  313.         gem::deleteCollectedGems();
  314.         if(p.ammo[WEAPON::TOASTER] > 0)
  315.         {jjEnabledASFunctions[7] = true; }
  316.  
  317.         if(jjKey[9] && jjKey[0x51]) {
  318.         p.morphTo(CHAR::JAZZ, false);
  319.         }
  320.         if(jjKey[9] && jjKey[0x57]) {
  321.         p.morphTo(CHAR::SPAZ, false);
  322.         }
  323.         if(jjKey[9] && jjKey[0x45]) {
  324.         p.morphTo(CHAR::LORI, false);
  325.         }
  326.  
  327. }
  328.  
  329. void onLevelLoad() {
  330.         jjWaterLighting = WATERLIGHT::GLOBAL;
  331.         gem::restorePlayerGems();
  332.         jjLevelName = ("");
  333.         jjObjectPresets[OBJECT::SAVEPOST].behavior = CheckpointWrapper;
  334.         jjObjectPresets[OBJECT::SAVEPOST].deactivates = false;
  335.  
  336.         Jazz1::MakeEnemy(OBJECT::SKELETON, Jazz1::Enemies::Scraparap_LaunchCart, true).SetUsesJJ2StyleDeathAnimation(true).SetBulletFireSound(SOUND::DEVILDEVAN_WINGSOUT).SetBulletExplosionSound(SOUND::COMMON_GUNSM1);
  337.         Jazz1::MakeEnemy(OBJECT::SPARK, Jazz1::Enemies::Scraparap_GunnerDrone).SetUsesJJ2StyleDeathAnimation(true).SetBulletFireSound(SOUND::ROBOT_SHOOT).SetBulletExplosionSound(SOUND::COMMON_GUNSM1);
  338.         Jazz1::MakeEnemy(OBJECT::NORMTURTLE, Jazz1::Enemies::Dreempipes_TerrapinSwimmer).SetUsesJJ2StyleDeathAnimation(true);
  339.         Jazz1::MakeEnemy(OBJECT::SUCKER, Jazz1::Enemies::Battleships_Generator).SetBulletFireSound(SOUND::COMMON_ITEMTRE).SetBulletExplosionSound(SOUND::COMMON_GUNSM1);
  340.  
  341.         jjObjectPresets[OBJECT::AIRBOARD].behavior = KeyRed();
  342.         jjObjectPresets[OBJECT::AIRBOARD].scriptedCollisions = true;
  343.  
  344.         jjObjectPresets[OBJECT::SONICPLATFORM].scriptedCollisions = true;
  345.         jjObjectPresets[OBJECT::SONICPLATFORM].behavior = Elevator;
  346.         jjObjectPresets[OBJECT::SONICPLATFORM].deactivates = false;
  347.  
  348.         jjObjectPresets[OBJECT::BANANA].behavior = KeyBlue();
  349.         jjObjectPresets[OBJECT::BANANA].scriptedCollisions = true;
  350.  
  351.         jjObjectPresets[OBJECT::CHICKENLEG].behavior = Potion();
  352.         jjObjectPresets[OBJECT::CHICKENLEG].scriptedCollisions = true;
  353.  
  354.         jjObjectPresets[OBJECT::FREEZEENEMIES].behavior = TimeFreezer();
  355.         jjObjectPresets[OBJECT::FREEZEENEMIES].scriptedCollisions = true;
  356.  
  357.         jjObjectPresets[OBJECT::CHIPS].behavior = Air();
  358.         jjObjectPresets[OBJECT::CHIPS].scriptedCollisions = true;
  359.  
  360.         jjObjectPresets[OBJECT::FASTFEET].behavior = CountlessJumps();
  361.         jjObjectPresets[OBJECT::FASTFEET].scriptedCollisions = true;
  362.  
  363.         jjObjectPresets[OBJECT::BURGER].behavior = KeyYellow();
  364.         jjObjectPresets[OBJECT::BURGER].scriptedCollisions = true;
  365.  
  366.         jjObjectPresets[OBJECT::TURTLESHELL].xSpeed = 5;
  367.         jjObjectPresets[OBJECT::TURTLESHELL].scriptedCollisions = true;
  368.         jjObjectPresets[OBJECT::TURTLESHELL].behavior = MovingSpring();
  369.         jjObjectPresets[OBJECT::TURTLESHELL].determineCurAnim(ANIM::SPRING,7);
  370.         jjObjectPresets[OBJECT::TURTLESHELL].deactivates = false;
  371.  
  372.         jjObjectPresets[OBJECT::WEENIE].energy = 2;
  373.         jjObjectPresets[OBJECT::WEENIE].behavior = SeaHorseGuard;
  374.         jjObjectPresets[OBJECT::WEENIE].playerHandling = HANDLING::ENEMY;
  375.         jjObjectPresets[OBJECT::WEENIE].bulletHandling = HANDLING::HURTBYBULLET;
  376.         jjObjectPresets[OBJECT::WEENIE].isBlastable = true;
  377.         jjObjectPresets[OBJECT::WEENIE].determineCurFrame();   
  378.         jjObjectPresets[OBJECT::WEENIE].deactivates = false;
  379.         jjObjectPresets[OBJECT::PIZZA].energy = 100;
  380.         jjObjectPresets[OBJECT::PIZZA].behavior = Thea;
  381.         jjObjectPresets[OBJECT::PIZZA].playerHandling = HANDLING::ENEMY;
  382.         jjObjectPresets[OBJECT::PIZZA].bulletHandling = HANDLING::HURTBYBULLET;
  383.         jjObjectPresets[OBJECT::PIZZA].deactivates = false;
  384.         jjObjectPresets[OBJECT::PIZZA].scriptedCollisions = true;
  385.  
  386.  
  387.  
  388. jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::PRETZEL].curAnim];
  389.         anim.frameCount = 1;
  390.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  391.         jjPIXELMAP pump(0, 57*32, 2*32, 2*32, 5);
  392.         pump.save(frame);
  393.         frame.hotSpotX = -32;
  394.  
  395.  
  396.         jjObjectPresets[OBJECT::TACO].behavior = Powder1();
  397.         jjObjectPresets[OBJECT::TACO].scriptedCollisions = true;
  398.         jjObjectPresets[OBJECT::SANDWICH].behavior = Powder2();
  399.         jjObjectPresets[OBJECT::SANDWICH].scriptedCollisions = true;
  400.         jjObjectPresets[OBJECT::FRIES].behavior = Powder3();
  401.         jjObjectPresets[OBJECT::FRIES].scriptedCollisions = true;
  402. }
  403.  
  404.  
  405. class Powder1 : jjBEHAVIORINTERFACE {
  406.         void onBehave(jjOBJ@ obj) {
  407.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::TACO].curAnim];
  408.         anim.frameCount = 1;
  409.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  410.         jjPIXELMAP pump(0, 1*32, 1*32, 1*32, 5);
  411.         pump.save(frame);
  412.         frame.hotSpotX = -14;
  413.         frame.hotSpotY = -14;
  414.         obj.draw();
  415.         obj.playerHandling = HANDLING::SPECIAL;
  416.  
  417.                 jjPARTICLE@ particle = jjAddParticle(PARTICLE::FIRE);
  418.  
  419.                 particle.xPos = obj.xPos;
  420.                 particle.yPos = obj.yPos+14;
  421.         }
  422.  
  423.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
  424.                 if(play !is null && bullet !is null && bullet.var[3] == WEAPON::TOASTER)
  425.                 {jjTriggers[11]=true;
  426.                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_BURN, 6000);
  427.                 obj.behave(BEHAVIOR::BURNING, false);
  428.                 jjAddObject(OBJECT::SPIKEBOLL, obj.xPos, obj.yPos);}
  429.                 return true;
  430.         }
  431.  
  432. }
  433.  
  434. class Powder2 : jjBEHAVIORINTERFACE {
  435.         void onBehave(jjOBJ@ obj) {
  436.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::SANDWICH].curAnim];
  437.         anim.frameCount = 1;
  438.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  439.         jjPIXELMAP pump(0, 1*32, 1*32, 1*32, 5);
  440.         pump.save(frame);
  441.         obj.draw();
  442.         obj.playerHandling = HANDLING::SPECIAL;
  443.  
  444.                 jjPARTICLE@ particle = jjAddParticle(PARTICLE::FIRE);
  445.  
  446.                 particle.xPos = obj.xPos;
  447.                 particle.yPos = obj.yPos+14;
  448.  
  449.  
  450.         }
  451.  
  452.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
  453.                 if(play !is null && bullet !is null && bullet.var[3] == WEAPON::TOASTER)
  454.                 {jjTriggers[12]=true;
  455.                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_BURN, 6000);
  456.                 obj.behave(BEHAVIOR::BURNING, false);
  457.                 jjAddObject(OBJECT::SPIKEBOLL, obj.xPos, obj.yPos);}
  458.                 return true;
  459.         }
  460.  
  461. }
  462.  
  463. class Powder3 : jjBEHAVIORINTERFACE {
  464.         void onBehave(jjOBJ@ obj) {
  465.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::FRIES].curAnim];
  466.         anim.frameCount = 1;
  467.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  468.         jjPIXELMAP pump(0, 1*32, 1*32, 1*32, 5);
  469.         pump.save(frame);
  470.         obj.draw();
  471.         obj.playerHandling = HANDLING::SPECIAL;
  472.  
  473.                 jjPARTICLE@ particle = jjAddParticle(PARTICLE::FIRE);
  474.  
  475.                 particle.xPos = obj.xPos;
  476.                 particle.yPos = obj.yPos+14;
  477.  
  478.  
  479.         }
  480.  
  481.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
  482.                 if(play !is null && bullet !is null && bullet.var[3] == WEAPON::TOASTER)
  483.                 {jjTriggers[13]=true;
  484.                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_BURN, 6000);
  485.                 obj.behave(BEHAVIOR::BURNING, false);
  486.                 jjAddObject(OBJECT::SPIKEBOLL, obj.xPos, obj.yPos);}
  487.                 return true;   
  488.         }
  489.  
  490. }
  491.  
  492.  
  493. class CountlessJumps : jjBEHAVIORINTERFACE {
  494.         void onBehave(jjOBJ@ obj) {
  495.  
  496. obj.behave(BEHAVIOR::PICKUP, false);
  497. obj.determineCurAnim(ANIM::PICKUPS, 33);
  498. ++obj.counter;
  499.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  500.  
  501.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 16);
  502.  
  503. }
  504.  
  505.         bool onObjectHit(jjOBJ@ obj, jjOBJ@, jjPLAYER@ play, int force) {
  506.                 play.timerStart(600);
  507.                 p.morphTo(CHAR::SPAZ);
  508.                 CountlessDoubleJumps = jjGameTicks + 10 * 61;
  509.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  510.                 obj.frameID = 0;
  511.                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_PICKUP1, 6000);
  512.  
  513.                 return true;
  514.         }
  515.  
  516. }
  517. void onFunction7(jjPLAYER@ p){
  518.                 if(p.ammo[WEAPON::TOASTER] == 0)
  519.                 {jjAddObject(OBJECT::TOASTERAMMO15, 122*32, 41*32);}
  520. }
  521.  
  522.  
  523. void onFunction17(jjPLAYER@ p){
  524.         ElevatorUp = true;
  525.         if(jjTriggers[9]==false) {
  526.         jjTriggers[9] = true;
  527.         jjSample(p.xPos, p.yPos, SOUND::COMMON_ICECRUSH, 1000);}
  528. }
  529.  
  530. void Elevator (jjOBJ@ obj) {
  531.  
  532.         switch (obj.state) {
  533.                 case STATE::START:
  534.  
  535.                         obj.determineCurAnim(ANIM::SONICPLAT, 0);  
  536.                         obj.determineCurFrame();
  537.                         obj.playerHandling = HANDLING::SPECIAL;
  538.                         obj.state = STATE::FLY;
  539.                         obj.beSolid();
  540.                 case STATE::FLY:
  541.                         obj.beSolid();
  542.  
  543.                         if(obj.yPos < 2 && p.keyUp) {
  544.                                 obj.ySpeed = 0;}
  545.  
  546.                         if(obj.yPos < 2 && p.keyDown) {
  547.                         obj.direction = obj.ySpeed = 2; }
  548.                         if(p.keyUp && ElevatorUp == true && p.xPos>obj.xPos-32 && p.xPos<obj.xPos+32) {
  549.                         obj.yPos = obj.yPos + obj.ySpeed;
  550.                         obj.direction = obj.ySpeed = -2;
  551.                          }
  552.                         if(p.keyDown && ElevatorUp == true && p.xPos>obj.xPos-32 && p.xPos<obj.xPos+32) {
  553.                         jjTriggers[16] = true;
  554.                         obj.yPos = obj.yPos + obj.ySpeed;
  555.                         p.ySpeed=3;
  556.                         obj.direction = obj.ySpeed = 2;
  557.                         if (jjMaskedVLine(obj.xSpeed > 0 ? obj.xPos + 16 : obj.xPos - 16, obj.yPos, -1)) {
  558.                                 obj.ySpeed = 0;
  559.                         }
  560.                         }
  561.  
  562.                         obj.draw();
  563.                         break;
  564.  
  565.         }
  566. }
  567.  
  568. void Thea (jjOBJ@ boss) {
  569.  
  570.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::PIZZA].curAnim];
  571.         anim.frameCount = 1;
  572.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  573.         jjPIXELMAP thea(0, 59*32, 1*32, 2*32, 5);
  574.         thea.save(frame);
  575.         frame.hotSpotX = -8;
  576.         frame.hotSpotY = 24;
  577.         if (boss.state == STATE::KILL || boss.state == STATE::DEACTIVATE) {
  578.                 boss.counter<=0;
  579.                 boss.counter += 1;
  580.                 jjSample(boss.xPos, boss.yPos, SOUND::COMMON_EXPL_TNT, 6000);
  581.                 if (boss.energy==0&&++boss.counter>210) {
  582.                         for (int i = 0;  i < jjObjectCount; i++)
  583.                         jjObjects[i].state=STATE::KILL;
  584.                         boss.delete();
  585.                         boss.lightType = LIGHT::NONE;
  586.                         p.showText("@@Thrasymakhos: NOOO!!!!");
  587.                         ++boss.counter;
  588.                         jjAddObject(OBJECT::FREEZEENEMIES, 94*32,62*32, boss.yPos);}
  589.         }
  590.         else  switch (boss.state) {
  591.                 case STATE::START:
  592.                 boss.frameID = boss.counter/8;
  593.                 boss.determineCurFrame();
  594.                 if (p.xPos < boss.xPos) boss.direction = 1;
  595.                 else boss.direction = -1;              
  596.                 ++boss.counter;
  597.                 boss.yPos = jjSin(boss.counter*52 + 156)*7 + boss.yOrg;
  598.         }
  599.         if (boss.justHit == 0)
  600.  
  601.                 jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);
  602.         else
  603.                 boss.draw();
  604.  
  605. }
  606.  
  607. void SeaHorseGuard (jjOBJ@ enemy) {
  608.  
  609. jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::WEENIE].curAnim];
  610.         anim.frameCount = 1;
  611.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  612.         jjPIXELMAP pump(0, 57*32, 2*32, 2*32, 5);
  613.         pump.save(frame);
  614.         frame.hotSpotX = -32;
  615.         if (enemy.state == STATE::KILL || enemy.state == STATE::DEACTIVATE) {
  616.                 enemy.delete();
  617.         } else         
  618.         switch (enemy.state) {
  619.                 case STATE::START:
  620.                 enemy.frameID = enemy.counter/8;
  621.                 enemy.determineCurFrame();
  622.                 if (p.xPos < enemy.xPos) enemy.direction = 1;
  623.                 else enemy.direction = -1;             
  624.                 ++enemy.counter;
  625.                 enemy.xPos = jjSin(enemy.counter*5)*70 + enemy.xOrg;
  626.                 enemy.yPos = jjSin(enemy.counter*15 + 256)*11 + enemy.yOrg;
  627.  
  628.                 if (jjRandom() & 63 == 0) {
  629.                         jjOBJ@ obj = jjObjects[enemy.fireBullet(OBJECT::BULLET)];
  630.                         obj.behavior = BEHAVIOR::BULLET;
  631.                         obj.determineCurAnim(ANIM::COMMON, 1);
  632.                         jjSample(enemy.xPos, enemy.yPos, SOUND::COMMON_PLOP2);
  633.                         obj.bulletHandling = HANDLING::IGNOREBULLET;
  634.                         obj.points = 5;
  635.                         obj.xSpeed = -10;
  636.                                 if (p.xPos < obj.xPos) obj.direction = -1;
  637.                                 else obj.direction = 1;
  638.                                 if (p.yPos < obj.yPos) obj.ySpeed = -1;
  639.                                 else obj.ySpeed = 6;
  640.                         obj.counterEnd = 100;
  641.  
  642.                 }
  643.         }
  644.         if (enemy.justHit == 0)
  645.  
  646.                 jjDrawSpriteFromCurFrame(enemy.xPos, enemy.yPos, enemy.curFrame, enemy.direction, SPRITE::NORMAL);
  647.         else
  648.                 enemy.draw();
  649.  
  650. }      
  651.  
  652.  
  653.  
  654. class MovingSpring : jjBEHAVIORINTERFACE {
  655.  
  656.         void onBehave(jjOBJ@ obj) {
  657.                 obj.behave(BEHAVIOR::WALKINGENEMY, false);
  658.                 obj.putOnGround();
  659.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 16);
  660.         }
  661.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int) {
  662.                 if(bullet is null) {
  663.                 player.direction = player.ySpeed = -62;
  664.                 obj.scriptedCollisions = true;
  665.                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_SPRING1);}
  666.                 if(player !is null && bullet !is null)
  667.                 {obj.bulletHandling = HANDLING::DETECTBULLET;
  668.                 obj.causesRicochet = true;}
  669.                 return true;
  670.                 }
  671. }
  672.  
  673.  
  674. void onFunction0(jjPLAYER@ p) {
  675.                 p.cameraUnfreeze();
  676. }
  677.  
  678. void onFunction11(jjPLAYER@ p) {
  679.         p.showText("@@@@@@@@@@@@@@@@@@@@@@@@@Underwater City", STRING::MEDIUM);
  680.         jjEnabledASFunctions[11] = false;}
  681.  
  682.  
  683. void onFunction3(jjPLAYER@ p) {
  684.                 jjTriggers[13] = true;
  685.                 p.light = 1000;
  686.                 p.health = 1;
  687. }
  688.  
  689. void onFunction6(jjPLAYER@ p) {
  690.                 if(jjTriggers[4] == true && jjTriggers[7] == true && jjTriggers[15] == true)
  691.                 {jjTriggers[20] = true;}
  692.                 if(jjTriggers[4] == false || jjTriggers[7] == false || jjTriggers[15] == false)
  693.                 {p.showText("@@Collect all three keys@to open the gates towards Poseidon!");}
  694.                 jjSample(p.xPos, p.yPos, SOUND::INTRO_MONSTER2);
  695. }
  696. void onFunction5(jjPLAYER@ p) {
  697.                 jjSetWaterLevel(-32, true);
  698.                 boss=true;
  699.                 jjMusicLoad("mo4a_Doc's Cave.ogg");
  700.                 p.activateBoss(true);
  701.                 {p.boss=jjAddObject(OBJECT::PIZZA, 95*32, 65*32);}
  702.                 jjOBJ@ boss = jjObjects[p.boss];
  703.                 p.showText("@@Thrasymakhos: Guards! Cover me!");
  704. }
  705.  
  706.  
  707. class KeyRed : jjBEHAVIORINTERFACE {
  708.  
  709.         void onBehave(jjOBJ@ obj) {
  710.                 if(jjTriggers[7] == true)
  711.                         {obj.delete();}
  712.                 obj.behave(BEHAVIOR::PICKUP, false);
  713.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::AIRBOARD].curAnim];
  714.         anim.frameCount = 1;
  715.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  716.         jjPIXELMAP pump(0, 16*32, 1*32, 1*32, 5);
  717.         pump.save(frame);
  718.                 ++obj.counter;
  719.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  720.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  721. }
  722.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  723.                 jjTriggers[7] = true;
  724.                 jjTriggerRock(0);
  725.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  726.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  727.  
  728.                 return true;
  729.         }
  730. }
  731.  
  732. class Air : jjBEHAVIORINTERFACE {
  733.  
  734.         void onBehave(jjOBJ@ obj) {
  735.                 obj.behave(BEHAVIOR::PICKUP, false);
  736.                 obj.determineCurAnim(ANIM::COMMON, 1);
  737.                 ++obj.counter;
  738.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  739.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  740. }
  741.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  742.                 limitedOxygen = 0;
  743.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  744.                 jjSample(obj.xPos, obj.yPos, SOUND::AMMO_BLUB2, 1000);
  745.  
  746.                 return true;
  747.         }
  748. }
  749.  
  750. class Potion: jjBEHAVIORINTERFACE {
  751.  
  752.         void onBehave(jjOBJ@ obj) {
  753.                 obj.behave(BEHAVIOR::PICKUP, false);
  754.                         obj.determineCurAnim(ANIM::PICKUPS, 78);
  755.                 ++obj.counter;
  756.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  757.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  758. }
  759.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  760.                 p.currWeapon = WEAPON::BLASTER;
  761.                 p.light = 100;
  762.                 poisoned = true;
  763.                 jjSample(p.xPos, p.yPos, SOUND::DEVILDEVAN_VANISH1, 6000);
  764.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  765.                 jjSample(obj.xPos, obj.yPos, SOUND::AMMO_BLUB2, 1000);
  766.  
  767.                 return true;
  768.         }
  769. }
  770.  
  771. class KeyBlue : jjBEHAVIORINTERFACE {
  772.  
  773.         void onBehave(jjOBJ@ obj) {
  774.                 if(jjTriggers[4] == true)
  775.                         {obj.delete();}
  776.                 obj.behave(BEHAVIOR::PICKUP, false);
  777. jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::BANANA].curAnim];
  778.         anim.frameCount = 1;
  779.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  780.         jjPIXELMAP pump(0, 17*32, 1*32, 1*32, 5);
  781.         pump.save(frame);
  782.                 ++obj.counter;
  783.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  784.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  785. }
  786.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  787.                 jjTriggers[4] = true;
  788.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  789.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  790.  
  791.                 return true;
  792.         }
  793. }
  794. class TimeFreezer : jjBEHAVIORINTERFACE {
  795.  
  796.         void onBehave(jjOBJ@ obj) {
  797.                 obj.behave(BEHAVIOR::PICKUP);
  798.                 obj.lightType = LIGHT::LASER;
  799.                 obj.light = 100;
  800.         }
  801.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  802.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  803.                 limitedOxygen = 0;
  804.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  805.                 jjNxt();
  806.                 gem::saveGemData();
  807.                 return true;
  808.         }
  809. }
  810.  
  811. class KeyYellow : jjBEHAVIORINTERFACE {
  812.  
  813.         void onBehave(jjOBJ@ obj) {
  814.                 if(jjTriggers[15] == true)
  815.                         {obj.delete();}
  816.                 obj.behave(BEHAVIOR::PICKUP, false);
  817.                 jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::BURGER].curAnim];
  818.                 anim.frameCount = 1;
  819.                 jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  820.                 jjPIXELMAP pump(0, 18*32, 1*32, 1*32, 5);
  821.                 pump.save(frame);
  822.                 ++obj.counter;
  823.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  824.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);
  825. }
  826.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  827.                 jjTriggers[15] = true;
  828.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  829.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  830.                 return true;
  831.         }
  832. }
  833.  
  834. array<bool> SavedTriggers(32, false); //you will need some way to keep track of whatever information you want saved... a global variable is the simplest choice
  835.  
  836.  
  837. void CheckpointWrapper(jjOBJ@ obj) {
  838.   if (obj.state == STATE::STOP) { //don't do anything anymore
  839.     jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 8);
  840.   } else if (obj.state == STATE::DEACTIVATE) { //due to death
  841.     obj.deactivate();
  842.   } else {
  843.     obj.behave(BEHAVIOR::CHECKPOINT);
  844.         jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 8);
  845.     if (obj.state == STATE::DONE) { //triggered by the player hitting it
  846.       obj.state = STATE::STOP;
  847.       //save the current state of some properties
  848.       for (uint i = 0; i < 32; ++i)
  849.         SavedTriggers[i] = jjTriggers[i];
  850.  
  851.       //OPTIONAL: this loop makes checkpoints reusable, so only the most recent checkpoint you touched is ever active
  852.       for (int i = jjObjectCount; --i > 0;) {
  853.         jjOBJ@ obj2 = jjObjects[i];
  854.         if (obj2.eventID == OBJECT::CHECKPOINT && i != obj.objectID && obj2.isActive) {
  855.           obj2.state = STATE::SLEEP;
  856.           obj2.var[0] = 0;
  857.         }
  858.       }
  859.     }
  860.   }
  861. }
  862.  
  863. void onLevelReload() { //restore the state of the saved properties to how they were last time you visited a checkpoint
  864.   for (uint i = 0; i < 32; ++i)
  865.     jjTriggers[i] = SavedTriggers[i]; //although this example uses jjTriggers, other things should work as well
  866.         jjWaterLighting = WATERLIGHT::GLOBAL;
  867.         gem::restorePlayerGems();
  868.         jjLocalPlayers[0].lives++;
  869. }
  870.  
  871.  
  872. jjTEXTAPPEARANCE SignTextAppearance = STRING::NORMAL;
  873. class Sign {
  874.         private int xPos, yPos; //These pixel-based positions will be generated from tile-based positions in the constructor by multiplying by 32
  875.         private string text;
  876.         private uint widthOfText;
  877.         Sign(){} //AngelScript requires any class that appears in any array to have an explicit default constructor, even if it's never called
  878.         Sign(int xTile, int yTile, const string &in t) {
  879.                 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
  880.                 yPos = yTile * 32; //
  881.                 text = t;
  882.                 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.
  883.                 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.
  884.                 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.
  885.         }
  886.         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.
  887.                 layer.drawRectangle(xPos, yPos - 16, widthOfText + 8, 55, 0, SPRITE::TRANSLUCENT);
  888.                 layer.drawString(xPos, yPos, text, STRING::SMALL, SignTextAppearance, 0, SPRITE::BLEND_HARDLIGHT, textIntensity);
  889.         }
  890. }
  891. const array<Sign> Signs = {
  892.         Sign(232, 61, "GUARDIAN: There's an intruder, sir.\nTHRASYMAKHOS: Make sure he does not cause any trouble!\nWe are so close to awaken the beast.\nSoon that filthy city will be destroyed!\n\nHit |||||FIRE |or |||||JUMP |to skip."),
  893. };
  894.  
  895. void onDrawLayer3(jjPLAYER@, jjCANVAS@ layer) {
  896.         if(jjKey[0x54] || p.xPos >222*32){
  897.         const uint8 textIntensity = 200 + int(jjSin(jjGameTicks * 16) * 50);
  898.         for (uint signID = 0; signID < Signs.length; ++signID)
  899.                 Signs[signID].draw(layer, textIntensity);
  900. }
  901. }
  902.  
  903.  
  904.  
  905.  
  906.  
  907.  
  908.  
  909.  
  910.  
  911.  
  912.  
  913. //HH18.savegems.asc
  914. // Had to copy the contents in here so that I could return DrawScore true during the cutscene.
  915.  
  916. namespace gem {
  917.         int gemsCollected, nextHealth, currAmount;
  918.        
  919.         int maxHealth() {
  920.                 return ((jjMaxHealth+1) - (jjDifficulty < 3? 5:3));
  921.         }
  922.        
  923.         array<int> gemTotals(4);
  924.         bool restoreGems;
  925.         bool draw = true;
  926.  
  927.         void upgradeHealth(jjPLAYER@ play) { //onPlayer
  928.                 switch (maxHealth()) {
  929.                         case 1: currAmount = 100; break;
  930.                         case 2: currAmount = 275; break;
  931.                         case 3: currAmount = 450; break;
  932.                         case 4: currAmount = 625; break;
  933.                         case 5: currAmount = 800; break;
  934.                 }
  935.        
  936.                 if (gemsCollected >= currAmount && nextHealth != maxHealth() && maxHealth() < 6) {
  937.                         jjChat("/smhealth " + (jjMaxHealth + 1));
  938.                         for (int i = 0; i < 8; ++i) {
  939.                                 jjAlert("");
  940.                         }
  941.                         nextHealth = jjMaxHealth;
  942.                         if (jjGameTicks > 7) {
  943.                                 jjSample(play.xPos, play.yPos, SOUND::COMMON_HARP1, 0, 0);
  944.                                 jjAlert("||||By the power of gems, your maximum health is increased!", false, STRING::MEDIUM);
  945.                                 if (maxHealth() == 6) jjAlert("|||Congratulations, your health is maximised!", false, STRING::MEDIUM);
  946.                         }
  947.                 }
  948.         }
  949.        
  950.         void trackPlayerGems(jjPLAYER@ play) { //onPlayer
  951.                 if (!restoreGems) {
  952.                         gemTotals[0] = play.gems[GEM::RED];
  953.                         gemTotals[1] = play.gems[GEM::GREEN] * 5;
  954.                         gemTotals[2] = play.gems[GEM::BLUE] * 10;
  955.                         gemTotals[3] = play.gems[GEM::PURPLE] * 20;
  956.                         gemsCollected = gemTotals[0] + gemTotals[1] + gemTotals[2] + gemTotals[3];
  957.                 } else {
  958.                         play.gems[GEM::RED] = jjGameTicks > 1? gemTotals[0] : play.lives;
  959.                         play.gems[GEM::GREEN] = gemTotals[1] / 5;
  960.                         play.gems[GEM::BLUE] = gemTotals[2] / 10;
  961.                         play.gems[GEM::PURPLE] = gemTotals[3] / 20;
  962.                         restoreGems = false;
  963.                 }
  964.         }
  965.        
  966.         void restorePlayerGems() { //onLevelLoad and onLevelReload
  967.                 restoreGems = true;
  968.         }
  969.        
  970.         void saveGemData() { //this needs to go in an AS function that also acts as the level exit
  971.                 jjLocalPlayers[0].lives = gemsCollected;
  972.         }
  973.        
  974.         void deleteCollectedGems() {
  975.                 for (int i = 1; i < jjObjectCount; i++) {
  976.                         jjOBJ@ obj = jjObjects[i];
  977.                         int playerID = obj.findNearestPlayer(200000);
  978.                         jjPLAYER@ play = jjPlayers[playerID];
  979.                        
  980.                         if (playerID > -1 &&
  981.                         (obj.eventID == OBJECT::REDGEM ||
  982.                         obj.eventID == OBJECT::GREENGEM ||
  983.                         obj.eventID == OBJECT::BLUEGEM ||
  984.                         obj.eventID == OBJECT::PURPLEGEM ||
  985.                         obj.eventID == OBJECT::RECTREDGEM ||
  986.                         obj.eventID == OBJECT::RECTGREENGEM ||
  987.                         obj.eventID == OBJECT::RECTBLUEGEM)) {
  988.                                 if (obj.creatorType == CREATOR::LEVEL) {
  989.                                         if (play.doesCollide(obj, true)) {
  990.                                                 jjEventSet(uint(obj.xOrg) >> 5, uint(obj.yOrg) >> 5, 0);
  991.                                         }
  992.                                 } else {
  993.                                         if (obj.creatorID == 0 && obj.state != STATE::FLOATFALL) {
  994.                                                 obj.playerHandling = HANDLING::PARTICLE;
  995.                                                 obj.delete();
  996.                                         }
  997.                                        
  998.                                 }
  999.                         }
  1000.                        
  1001.                         if (obj.eventID == OBJECT::GEMBARREL || obj.eventID == OBJECT::GEMCRATE) {
  1002.                                 if (obj.state == STATE::EXPLODE) jjEventSet(uint(obj.xOrg) >> 5, uint(obj.yOrg) >> 5, 0);
  1003.                         }
  1004.                        
  1005.                         if (obj.eventID == OBJECT::GEMRING) {
  1006.                                 if (obj.state == STATE::HIT) jjEventSet(uint(obj.xOrg) >> 5, uint(obj.yOrg) >> 5, 0);
  1007.                         }
  1008.                        
  1009.                         if (obj.eventID == OBJECT::SUPERGEM) {
  1010.                                 if (obj.state == STATE::ACTION) jjEventSet(uint(obj.xOrg) >> 5, uint(obj.yOrg) >> 5, 0);
  1011.                         }
  1012.                        
  1013.                         if (obj.eventID == OBJECT::BOMBCRATE || obj.eventID == OBJECT::ONEUPCRATE) {
  1014.                                 if (obj.state == STATE::FALL && (obj.var[0] == OBJECT::REDGEM ||
  1015.                                 obj.var[0] == OBJECT::GREENGEM ||
  1016.                                 obj.var[0] == OBJECT::BLUEGEM ||
  1017.                                 obj.var[0] == OBJECT::PURPLEGEM ||
  1018.                                 obj.var[0] == OBJECT::RECTREDGEM ||
  1019.                                 obj.var[0] == OBJECT::RECTGREENGEM ||
  1020.                                 obj.var[0] == OBJECT::RECTBLUEGEM)) {
  1021.                                         jjEventSet(uint(obj.xOrg) >> 5, uint(obj.yOrg) >> 5, 0);
  1022.                                 }
  1023.                         }
  1024.                 }
  1025.         }
  1026. }
  1027.  
  1028. bool onCheat(string &in cheat) {
  1029.         if (cheat == "jjnxt" || cheat == "jjnext") {
  1030.                 gem::saveGemData();
  1031.                 jjNxt(true, true);
  1032.         } else if (cheat == "jjgems") {
  1033.                 jjLocalPlayers[0].gems[GEM::RED] = jjLocalPlayers[0].gems[GEM::RED] + 100;
  1034.         } else
  1035.                 return false;
  1036.         jjAlert(cheat, false, STRING::MEDIUM);
  1037.         return true;
  1038. }
  1039.  
  1040.  
  1041.  
  1042. bool onDrawScore(jjPLAYER@ play, jjCANVAS@ canvas) {
  1043.  
  1044.         if (gem::draw && p.xPos < 223*32) {
  1045.                 canvas.drawSprite(20, 42, ANIM::PICKUPS, 22, jjGameTicks>>2, 0, SPRITE::GEM, 0);
  1046.                 canvas.drawString(36, 42, "x " + gem::gemsCollected, STRING::MEDIUM, STRING::NORMAL);
  1047.                 if (gem::maxHealth() < 6) {
  1048.                         canvas.drawString(8, 70, "|" + gem::currAmount + " |||||for upgrade", STRING::SMALL, STRING::NORMAL);
  1049.                 } else {
  1050.                         canvas.drawString(8, 70, "||||Max!", STRING::SMALL, STRING::NORMAL);
  1051.                 }
  1052.        
  1053.         return false;}
  1054.         else return true;
  1055. }