Downloads containing mo4a_1-2.j2as

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

File preview

  1. const bool MLLESetupSuccessful = MLLE::Setup(array<MLLEWeaponApply@> = {null, null, DefaultWeapons::Blaster(), DefaultWeapons::Blaster(), WeaponVMega::Backfire::Weapon(), null, null, null, DefaultWeapons::Blaster()}); ///@MLLE-Generated
  2. #include "MLLE-Include-1.5w.asc" ///@MLLE-Generated
  3. #pragma require "mo4a_1-2-MLLE-Data-1.j2l" ///@MLLE-Generated
  4. #pragma require "mo4a_1-2.j2l" ///@MLLE-Generated
  5. #include "WeaponVMega5.asc" ///@MLLE-Generated
  6. #pragma require "WeaponVMega5.asc" ///@MLLE-Generated
  7. #include "MLLE-DefaultWeapons.asc" ///@MLLE-Generated
  8. #pragma require "MLLE-DefaultWeapons.asc" ///@MLLE-Generated
  9. #include "Jazz1Enemies v05.asc"
  10. #include "Resize v11.asc"
  11. #include "TrueColor v13.asc"
  12. #include "HH18savegems.asc"
  13. #pragma require "kangaroo.j2a"
  14.  
  15. const OBJECT::Object JillEventID = OBJECT::FENCER;
  16. int LaserFrog = 0, exit = 0, frogexit = 0;
  17. bool crate2 =false, crate3 = false, crate5 = false, crate6 = false, control = true;
  18.  
  19. bool froggy = false, doorunblocked = false, startrush = false, readytorush = false, womensaved = false;
  20.  
  21. void onPlayer(jjPLAYER@ play) {
  22.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::ORANGE].curAnim];
  23.         anim.frameCount = 1;
  24.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  25.         jjPIXELMAP fruit(0, 31*32, 1*32, 1*32, 5);
  26.         fruit.save(frame);
  27. for (int i = 0; i < 1024; i++) { //loop through the global array jjParticles[1024]
  28.     jjPARTICLE@ particle = jjParticles[i];
  29.     if (particle.type == PARTICLE::RAIN) {
  30.       particle.xSpeed = 0; //make rain fall straight down
  31.       particle.ySpeed = play.ySpeed < 0? 10 : int(10 + play.ySpeed); //the rain speed accounts for differences in the player speed, and so won't appear to fall more slowly when the player is falling
  32.     }
  33.   }
  34.         if(jjTriggers[15] == false)
  35.                 {jjEnabledASFunctions[2] = true;}
  36.         if(jjTriggers[14] == false)
  37.                 {jjEnabledASFunctions[8] = true;}
  38.         if(jjTriggers[13] == false)
  39.                 {jjEnabledASFunctions[7] = true;}
  40.         if(jjTriggers[12] == false)
  41.                 {jjEnabledASFunctions[6] = true;}
  42.         if(jjTriggers[1] == false)
  43.                 {jjEnabledASFunctions[5] = true;}
  44.         if(jjTriggers[10] == false)
  45.                 {jjEnabledASFunctions[4] = true;}
  46.  
  47.         frogexit = 0;
  48.         if(jjTriggers[2] == true)
  49.                 {frogexit += 1;
  50.                 crate2 = true;}
  51.         if(jjTriggers[3] == true)
  52.                 {frogexit += 1;
  53.                 crate3 = true;}
  54.         if(jjTriggers[5] == true)
  55.                 {frogexit += 1;
  56.                 crate5 = true;}
  57.         if(jjTriggers[6] == true)
  58.                 {frogexit += 1;
  59.                 crate6 = true;}
  60.  
  61.         exit = 0;
  62.         if(jjTriggers[15] == true)
  63.                 {exit += 1;}
  64.         if(jjTriggers[14] == true)
  65.                 {exit += 1;}
  66.         if(jjTriggers[13] == true)
  67.                 {exit += 1;}
  68.         if(jjTriggers[12] == true)
  69.                 {exit += 1;}
  70.         if(jjTriggers[1] == true)
  71.                 {exit += 1;}
  72.         if(jjTriggers[10] == true)
  73.                 {exit += 1;}
  74.         gem::trackPlayerGems(p);
  75.         gem::upgradeHealth(p);
  76.  
  77.         if(womensaved == false && jjTriggers[10] == true && jjTriggers[1] == true && jjTriggers[12] == true && jjTriggers[13] == true && jjTriggers[14] == true && jjTriggers[15] == true)
  78.                 {p.showText("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Coin unlocked.");
  79.                 womensaved = true;}
  80.  
  81.         if(p.food == 100 && jjKey[0x52] == false && startrush == false)
  82.                 {p.showText("@@@@@@@@@@@@@@@@||||||||Press 'R' when you need to use Sugar Rush!", STRING::MEDIUM);
  83.                 p.startSugarRush(0);
  84.                 startrush = true;
  85.                 readytorush = true;}
  86.  
  87.         if(readytorush == true)
  88.                 {p.food = 100;}
  89.  
  90.         if(p.food == 100 && jjKey[0x52])
  91.                 {p.startSugarRush(1400);
  92.                 p.food = 0;
  93.                 readytorush = false;
  94.                 startrush = false;
  95.         }
  96.  
  97.         for (int i = 1; i < jjObjectCount; i++) {
  98.         jjOBJ@ o = jjObjects[i];
  99.                 if (o.isActive && o.eventID == OBJECT::SILVERCOIN && p.coins >= 2) {
  100.                 o.state = STATE::KILL;
  101.                 }
  102.  
  103.         }
  104.  
  105.         for (int i = 1; i < jjObjectCount; i++) {
  106.                 jjOBJ@ o = jjObjects[i];
  107.                 if (o.isActive && o.eventID == OBJECT::SEEKERAMMO3 && p.ammo[WEAPON::SEEKER] < 1) {
  108.                         o.state = STATE::KILL;}
  109.         }
  110.         for (int i = 1; i < jjObjectCount; i++) {
  111.                 jjOBJ@ o = jjObjects[i];
  112.                 if (o.isActive && o.eventID == OBJECT::RFAMMO3 && p.ammo[WEAPON::RF] < 1) {
  113.                         o.state = STATE::KILL;}
  114.         }
  115.         for (int i = 1; i < jjObjectCount; i++) {
  116.                 jjOBJ@ o = jjObjects[i];
  117.                 if (o.isActive && o.eventID == OBJECT::TNTAMMO3 && p.ammo[WEAPON::TNT] < 1) {
  118.                         o.state = STATE::KILL;}
  119.         }
  120.         for (int i = 1; i < jjObjectCount; i++) {
  121.                 jjOBJ@ o = jjObjects[i];
  122.                 if (o.isActive && o.eventID == OBJECT::GUN9AMMO3 && p.ammo[WEAPON::GUN9] < 1) {
  123.                         o.state = STATE::KILL;}
  124.         }
  125.         for (int i = 1; i < jjObjectCount; i++) {
  126.                 jjOBJ@ o = jjObjects[i];
  127.                 if (o.isActive && o.eventID == OBJECT::SEEKERPOWERUP && p.ammo[WEAPON::SEEKER] < 1) {
  128.                         o.state = STATE::KILL;}
  129.         }
  130.         for (int i = 1; i < jjObjectCount; i++) {
  131.                 jjOBJ@ o = jjObjects[i];
  132.                 if (o.isActive && o.eventID == OBJECT::RFPOWERUP && p.ammo[WEAPON::RF] < 1) {
  133.                         o.state = STATE::KILL;}
  134.         }
  135.         for (int i = 1; i < jjObjectCount; i++) {
  136.                 jjOBJ@ o = jjObjects[i];
  137.                 if (o.isActive && o.eventID == OBJECT::TNTPOWERUP && p.ammo[WEAPON::TNT] < 1) {
  138.                         o.state = STATE::KILL;}
  139.         }
  140.         for (int i = 1; i < jjObjectCount; i++) {
  141.                 jjOBJ@ o = jjObjects[i];
  142.                 if (o.isActive && o.eventID == OBJECT::GUN9POWERUP && p.ammo[WEAPON::GUN9] < 1) {
  143.                         o.state = STATE::KILL;}
  144.         }
  145.                 if (doorunblocked == false && jjTriggers[2]==true && jjTriggers[3]==true && jjTriggers[5]==true && jjTriggers[6]==true) {
  146.                 p.showText("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Cage door's key activated.");
  147.                 doorunblocked = true;}
  148.  
  149.         if(p.yPos<4*32 && p.xPos>95*32 && p.xPos<99*32 && p.coins < 2)
  150.                 {p.testForCoins(2);}
  151.         if(p.yPos<4*32 && p.xPos>95*32 && p.xPos<99*32 && p.coins == 2)
  152.                 {jjNxt("mo4a_1-3_save", false, true);
  153.                 gem::saveGemData();}
  154.  
  155.         if(p.charCurr == CHAR::FROG) {
  156.                 p.furSet(64, 64, 64, 64);
  157.         }
  158.         if(p.charCurr != CHAR::FROG) {
  159.                 p.furSet(0, 0, 0, 0);
  160.         }
  161.  
  162.         if(froggy == true) {
  163.         jjTriggers[20] = true;
  164.         }
  165.                
  166.         if(p.coins==0)
  167.         {p.coins +=1;}
  168.  
  169.                 if(control==false)
  170.                 {p.keyLeft = false;
  171.                 p.keyRight = false;
  172.                 p.keyDown = false;}
  173.  
  174.                 if(p.idle > 100)
  175.                 {p.cameraUnfreeze(true);
  176.                 control=true;}
  177.                 else if (p.idle > 30 && (p.keyLeft || p.keyRight || p.keyJump || p.keyFire || p.keyFire))
  178.                 {p.cameraUnfreeze(true);
  179.                 control=true;}
  180.  
  181.  
  182.         if(play.keyUp == true && p.xPos>225*32 && p.xPos<228*32 && p.yPos<51*32 && p.yPos>49*32 && jjTriggers[2]==false){
  183.         jjTriggers[2] = true;
  184.         p.cameraFreeze(208*32, 48*32, true, false);
  185.         control = false;
  186.         jjSample(p.xPos, p.yPos, SOUND::INTRO_MONSTER2);}
  187.  
  188.         if(play.keyUp == true && p.xPos<3*32 && p.yPos<4*32 && jjTriggers[7]==false){
  189.         jjTriggers[7] = true;
  190.         p.cameraFreeze(49*32, 12*32, true, false);
  191.         control = false;
  192.         jjSample(p.xPos, p.yPos, SOUND::INTRO_MONSTER2);}      
  193.  
  194.         if(play.keyUp == true && p.xPos>5*32 && p.xPos<8*32 && p.yPos>56*32 && p.yPos<59*32 && jjTriggers[8]==false){
  195.         jjTriggers[8] = true;
  196.         p.cameraFreeze(8*32, 38*32, true, false);
  197.         control = false;
  198.         jjSample(p.xPos, p.yPos, SOUND::INTRO_MONSTER2);}
  199.  
  200.         if(play.keyUp == true && p.xPos>248*32 && p.xPos<251*32 && p.yPos<57*32 && p.yPos>54*32 && jjTriggers[9]==false){
  201.         jjTriggers[9] = true;
  202.         jjSample(p.xPos, p.yPos, SOUND::INTRO_MONSTER2);}
  203.  
  204.         if(play.keyUp == true && p.xPos>248*32 && p.xPos<251*32 && p.yPos<25*32 && p.yPos>22*32 && jjTriggers[11]==false){
  205.         jjTriggers[11] = true;
  206.         jjSample(p.xPos, p.yPos, SOUND::INTRO_MONSTER2);}
  207.  
  208.         if(play.yPos > jjWaterLevel && play.charCurr == CHAR::FROG && p.keyJump == true)
  209.         {play.jumpStrength = -10;}
  210.         if(play.yPos > jjWaterLevel && play.charCurr != CHAR::FROG)
  211.         {play.health = 0;}
  212.         play.lightType = LIGHT::NONE;
  213.        
  214.         if(LaserFrog < jjGameTicks)            
  215.                 {p.invisibility = false;}
  216.         if (LaserFrog > jjGameTicks) {
  217.                         p.invisibility = false;
  218.  
  219.         if(play.keyFire) {
  220.                         p.invisibility = true;
  221.                         p.lightType = LIGHT::LASER;
  222.                         jjDrawSprite(p.xPos, p.yPos, p.setID, RABBIT::EARBRACHIATE, p.curFrame, p.direction, SPRITE::PLAYER);
  223.         if(jjRandom() & 9 == 0){
  224.                         jjOBJ@ obj = jjObjects[OBJECT::LASER];
  225.                         jjAddObject(OBJECT::LASER, -p.xPos, p.yPos);
  226.                                         obj.behave(BEHAVIOR::BULLET);
  227.                                         obj.determineCurAnim(ANIM::AMMO, 60);
  228.                                         obj.playerHandling = HANDLING::PLAYERBULLET;
  229.                                         obj.bulletHandling = HANDLING::IGNOREBULLET;
  230.                                         }
  231.  
  232. }
  233.   }
  234.  
  235.  
  236. }
  237.  
  238.  
  239. void onLevelLoad() {
  240. jjPIXELMAP rain(32,32);
  241.   for (uint x = 0; x < rain.width; ++x) {
  242.     for (uint y = 0; y < rain.height; ++y) {
  243.       if (x == 16) { //draw in the middle of the tile, xPixel 16
  244.         if (y <= 24) rain[x,y] = 75; //if at yPixel 24 or less, use color 75
  245.         else rain[x,y] = 74; //use color 74 for yPixels 25-32
  246.       } else {
  247.         rain[x,y] = 0;
  248.       }
  249.     }
  250.   }
  251.  
  252.   jjANIMATION@ anim = jjAnimations[jjAnimSets[ANIM::COMMON].firstAnim + 2];
  253.   for (uint frameID = 0; frameID < anim.frameCount; ++frameID) {
  254.     jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame + frameID];
  255.     rain.save(frame);
  256.     frame.hotSpotX = -frame.width/2;
  257.     frame.hotSpotY = -frame.height;
  258.   }
  259.  
  260.         jjWaterLighting = WATERLIGHT::GLOBAL;
  261.         gem::restorePlayerGems();
  262.         jjLevelName = ("@@@@@@@@@Sacred Woods");
  263.         jjObjectPresets[OBJECT::SAVEPOST].behavior = CheckpointWrapper;
  264.         jjObjectPresets[OBJECT::SAVEPOST].deactivates = false;
  265.  
  266.         jjObjectPresets[OBJECT::FISH].determineCurAnim(ANIM::FROG, 2);
  267.         jjObjectPresets[OBJECT::FISH].scriptedCollisions = true;
  268.         jjObjectPresets[OBJECT::FISH].direction = 1;
  269.         jjObjectPresets[OBJECT::FISH].playerHandling = HANDLING::SPECIAL;
  270.         jjObjectPresets[OBJECT::FISH].bulletHandling = HANDLING::IGNOREBULLET;
  271.         jjObjectPresets[OBJECT::FISH].putOnGround();
  272.         jjObjectPresets[OBJECT::FISH].behavior = FrogWait;
  273.  
  274.         Jazz1::MakeEnemy(OBJECT::HATTER, Jazz1::Enemies::Marbelara_Schwarzenguard, true).SetUsesJJ2StyleDeathAnimation(true).SetBulletFireSound(SOUND::INTRO_SHOT1).SetBulletExplosionSound(SOUND::COMMON_GUNSM1);
  275.  
  276.         jjObjectPresets[OBJECT::AIRBOARD].behavior = Key();
  277.         jjObjectPresets[OBJECT::AIRBOARD].scriptedCollisions = true;
  278.  
  279.         jjObjectPresets[OBJECT::SEEKERPOWERUP].behavior = Switch1();
  280.         jjObjectPresets[OBJECT::SEEKERPOWERUP].scriptedCollisions = true;
  281.  
  282.         jjObjectPresets[OBJECT::TOASTERPOWERUP].behavior = Switch2();
  283.         jjObjectPresets[OBJECT::TOASTERPOWERUP].scriptedCollisions = true;
  284.  
  285.         jjObjectPresets[OBJECT::BOUNCERPOWERUP].behavior = Switch3();
  286.         jjObjectPresets[OBJECT::BOUNCERPOWERUP].scriptedCollisions = true;
  287.  
  288.         jjObjectPresets[OBJECT::BLASTERPOWERUP].behavior = Switch4();
  289.         jjObjectPresets[OBJECT::BLASTERPOWERUP].scriptedCollisions = true;
  290.  
  291.         jjObjectPresets[OBJECT::EXTRATIME].behavior = Laser();
  292.         jjObjectPresets[OBJECT::EXTRATIME].scriptedCollisions = true;
  293.  
  294.         jjObjectPresets[OBJECT::SILVERCOIN].behavior = PlatinCoin();
  295.         jjObjectPresets[OBJECT::SILVERCOIN].scriptedCollisions = true;
  296.  
  297.         jjObjectPresets[OBJECT::TRIGGERCRATE].deactivates = false;
  298.  
  299.         jjObjectPresets[OBJECT::FLYCARROT].determineCurAnim(ANIM::PLUS_WARP, 0);
  300.         jjObjectPresets[OBJECT::FLYCARROT].behavior = Bonus;
  301.         jjObjectPresets[OBJECT::FLYCARROT].scriptedCollisions = true;
  302.         jjANIMATION@ BAnim = jjAnimations[jjObjectPresets[OBJECT::FLYCARROT].curAnim];
  303.         for (uint i = 0; i < BAnim.frameCount; ++i)
  304.                 jjAnimFrames[BAnim.firstFrame + i].hotSpotY = -85;
  305.         for (uint i = 0; i < BAnim.frameCount; ++i)
  306.                 jjAnimFrames[BAnim.firstFrame + i].hotSpotX = 20;
  307.  
  308.         jjObjectPresets[OBJECT::INVINCIBILITY].determineCurAnim(ANIM::PLUS_WARP, 1);
  309.         jjObjectPresets[OBJECT::INVINCIBILITY].behavior = Bonuseye;
  310.         jjObjectPresets[OBJECT::INVINCIBILITY].scriptedCollisions = true;
  311.         jjANIMATION@ BeAnim = jjAnimations[jjObjectPresets[OBJECT::INVINCIBILITY].curAnim];
  312.  
  313.         for (uint i = 0; i < BeAnim.frameCount; ++i)
  314.                 jjAnimFrames[BeAnim.firstFrame + i].hotSpotY = 32;
  315.         for (uint i = 0; i < BeAnim.frameCount; ++i)
  316.                 jjAnimFrames[BeAnim.firstFrame + i].hotSpotX = 26;
  317.  
  318.  
  319.  
  320. jjEventSet(197, 11, JillEventID);
  321.        
  322.         //call a couple Kangaroo functions
  323.         Kangaroo::MakeEventJoey(OBJECT::MONKEY); //default parameters
  324.         Kangaroo::MakeEventJoey(OBJECT::STANDMONKEY, 0, 5, 5, 12, 5, 256); //custom parameters
  325.         Kangaroo::MakeEventJill(
  326.                 JillEventID
  327.         ).deactivates = false; //note that both MakeEventJoey and MakeEventJill return the jjObjectPresets entry of the eventID passed to them
  328.  
  329. }
  330.  
  331. void Bonuseye(jjOBJ@ obj){
  332.         obj.direction = -1;
  333.         obj.behave(BEHAVIOR::PICKUP, false);
  334.         obj.draw();
  335. }
  336. void Bonus(jjOBJ@ obj){
  337.         obj.putOnGround();
  338.         obj.direction = -1;
  339.         obj.behave(BEHAVIOR::PICKUP, false);
  340.         obj.draw();
  341. }
  342.  
  343. void FrogWait(jjOBJ@ obj) {
  344.  
  345.                 obj.behave(BEHAVIOR::FISH, false);
  346.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::SINGLEHUE, 64);
  347. }
  348.  
  349. bool cointext = true;
  350.  
  351. class PlatinCoin : jjBEHAVIORINTERFACE {
  352.  
  353.         void onBehave(jjOBJ@ obj) {
  354.                 if(p.coins >= 2)
  355.                 {obj.delete();}
  356.                 obj.behave(BEHAVIOR::PICKUP, false);
  357.                 ++obj.counter;
  358.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  359.                 if(jjTriggers[10] == true && jjTriggers[1] == true && jjTriggers[12] == true && jjTriggers[13] == true && jjTriggers[14] == true && jjTriggers[15] == true)
  360.                         {jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, -8);}
  361.                 else jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::TRANSLUCENTPALSHIFT, -8);
  362. }
  363.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  364.                 if(jjTriggers[10] == true && jjTriggers[1] == true && jjTriggers[12] == true && jjTriggers[13] == true && jjTriggers[14] == true && jjTriggers[15] == true)
  365.                 {p.coins += 1;
  366.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  367.                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_COIN, 1000);}
  368.                 else if(cointext == true)
  369.                 {p.showText("@@Save the women to@unlock the token.");
  370.                 cointext=false;}
  371.  
  372.                 return true;
  373.         }
  374. }
  375.  
  376. bool keytext = true;
  377.  
  378. class Key : jjBEHAVIORINTERFACE {
  379.  
  380.         void onBehave(jjOBJ@ obj) {
  381.                 if(jjTriggers[0]==true)
  382.                         {obj.delete();}
  383.                 obj.behave(BEHAVIOR::PICKUP, false);
  384.                 jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::AIRBOARD].curAnim];
  385.                 anim.frameCount = 1;
  386.                 jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  387.                 jjPIXELMAP pump(0, 59*32, 1*32, 1*32, 5);
  388.                 pump.save(frame);
  389.                 ++obj.counter;
  390.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  391.         if(jjTriggers[2] == true && jjTriggers[3] == true && jjTriggers[5] == true && jjTriggers[6] == true)
  392.                 {jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL);}
  393.         else {jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::TRANSLUCENT);}
  394.  
  395.         }
  396.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
  397.         if(jjTriggers[2] == true && jjTriggers[3] == true && jjTriggers[5] == true && jjTriggers[6] == true)
  398.         {
  399.                 jjTriggers[0]=true;
  400.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  401.                 jjSample(obj.xPos, obj.yPos, SOUND::MENUSOUNDS_TYPEENTER, 1000);
  402.         }
  403.         if(keytext==true) {
  404.                 p.showText("@@@Find 4 metal crates@to activate this key.");
  405.                 keytext = false;}
  406.                 return true;
  407.         }
  408. }
  409.  
  410. void onFunction0(jjPLAYER@ play) {
  411. if(p.charCurr == CHAR::FROG) {
  412. play.boss=jjAddObject(OBJECT::FISH, 103*32, 51*32);
  413. froggy = true;
  414. p.xPos = 104*32;
  415. p.yPos = 60*32;
  416. p.cameraFreeze(99*32, 57*32, true, false);
  417. //control = false;
  418. }
  419. }
  420.  
  421. void onFunction1(jjPLAYER@ play) {
  422. jjTriggers[20] = true;
  423. p.revertMorph(false);
  424. p.cameraUnfreeze();
  425. froggy = true;
  426. }
  427.  
  428. void onFunction2(jjPLAYER@ play) {
  429.         if(p.charCurr != CHAR::FROG && jjTriggers[15] == false) {
  430.                 play.activateBoss();
  431.                 jjMusicLoad("mo4a_Doc's Cave.ogg");
  432.                 jjEnabledASFunctions[2] = false;
  433.         }
  434. }
  435.  
  436. void onFunction3(jjPLAYER@ play) {
  437. if(froggy == false)
  438. p.morphTo(CHAR::FROG, false);
  439. }
  440.  
  441. void onFunction4(jjPLAYER@ p) {
  442.         p.showText("@@You are free to go now.");
  443.         jjTriggers[10] = true;
  444.         exit += 1;
  445.         jjSample(p.xPos, p.yPos, SOUND::LORISOUNDS_LORIFALL);
  446. }
  447. void onFunction5(jjPLAYER@ p) {
  448.         p.showText("@@You are free to go now.");
  449.         jjSample(p.xPos, p.yPos, SOUND::LORISOUNDS_LORIFALL);
  450.         exit += 1;
  451.         jjTriggers[1] = true;
  452. }
  453. void onFunction6(jjPLAYER@ p) {
  454.         p.showText("@@You are free to go now.");
  455.         jjSample(p.xPos, p.yPos, SOUND::LORISOUNDS_LORIFALL);
  456.         exit += 1;
  457.         jjTriggers[12] = true;
  458. }
  459. void onFunction7(jjPLAYER@ p) {
  460.         p.showText("@@You are free to go now.");
  461.         jjSample(p.xPos, p.yPos, SOUND::LORISOUNDS_LORIFALL);
  462.         exit += 1;
  463.         jjTriggers[13] = true;
  464. }
  465. void onFunction8(jjPLAYER@ p) {
  466.         p.showText("@@You are free to go now.");
  467.         jjSample(p.xPos, p.yPos, SOUND::LORISOUNDS_LORIFALL);
  468.         exit += 1;
  469.         jjTriggers[14] = true;
  470. }
  471.  
  472. class Laser : jjBEHAVIORINTERFACE {
  473.         void onBehave(jjOBJ@ obj) {
  474.  
  475. obj.behave(BEHAVIOR::PICKUP, false);
  476. obj.determineCurAnim(ANIM::AMMO, 58);
  477. ++obj.counter;
  478.                 obj.yPos = jjSin(obj.counter*15 + 5)*4 + obj.yOrg;
  479.  
  480.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 56);
  481.  
  482. }
  483.  
  484.         bool onObjectHit(jjOBJ@ obj, jjOBJ@, jjPLAYER@ play, int force) {
  485.  
  486.                 LaserFrog= jjGameTicks + 5 * 61;
  487.                 p.timerStart(300);
  488.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  489.                 obj.frameID = 0;
  490.                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_PICKUP1, 6000);
  491.  
  492.                 return true;
  493.         }
  494.  
  495. }
  496.  
  497.  
  498.  
  499.  
  500. class Switch1: jjBEHAVIORINTERFACE {
  501.         void onBehave(jjOBJ@ obj) {
  502.                 obj.behave(BEHAVIOR::PICKUP, false);
  503.                 obj.draw();
  504.  
  505.  
  506.  
  507. jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::SEEKERPOWERUP].curAnim];
  508.         anim.frameCount = 1;
  509.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  510.         jjPIXELMAP sw(0, 30*32, 1*32, 1*32, 5);
  511.         sw.save(frame);
  512.         frame.hotSpotY = 17;
  513.         frame.hotSpotX = -17;
  514. }
  515.  
  516. bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
  517.  
  518. obj.playerHandling = HANDLING::ENEMY;
  519. obj.scriptedCollisions = false;
  520.                 jjSwitchTrigger(8);
  521. jjSample(p.xPos, p.yPos, SOUND::COMMON_EXPSM1, 3000);
  522.                 obj.frameID = 0;
  523.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  524.  
  525.                 return true;  
  526.         }
  527. }
  528.  
  529. class Switch2: jjBEHAVIORINTERFACE {
  530.         void onBehave(jjOBJ@ obj) {
  531.                 obj.behave(BEHAVIOR::PICKUP, false);
  532.                 obj.draw();
  533.  
  534.  
  535.  
  536. jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::TOASTERPOWERUP].curAnim];
  537.         anim.frameCount = 1; //The Bee enemy's animation has several frames, but the tileset only has material for one. Editing jjANIMATION::frameCount to 1 will ensure that the animation never extends beyond the one frame we're providing.
  538.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  539.         jjPIXELMAP pump(0, 30*32, 1*32, 1*32, 5);
  540.         pump.save(frame);
  541.         frame.hotSpotY = 17;
  542.         frame.hotSpotX = -17;
  543. }
  544.  
  545. bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
  546.  
  547. obj.playerHandling = HANDLING::ENEMY;
  548. obj.scriptedCollisions = false;
  549.                 jjSwitchTrigger(7);
  550. jjSample(p.xPos, p.yPos, SOUND::COMMON_EXPSM1, 3000);
  551.                 obj.frameID = 0;
  552.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  553.  
  554.                 return true;  
  555.         }
  556. }
  557.  
  558. class Switch3: jjBEHAVIORINTERFACE {
  559.         void onBehave(jjOBJ@ obj) {
  560.                 obj.behave(BEHAVIOR::PICKUP, false);
  561.                 obj.draw();
  562.  
  563.  
  564.  
  565. jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::BOUNCERPOWERUP].curAnim];
  566.         anim.frameCount = 1; //The Bee enemy's animation has several frames, but the tileset only has material for one. Editing jjANIMATION::frameCount to 1 will ensure that the animation never extends beyond the one frame we're providing.
  567.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  568.         jjPIXELMAP pump(0, 30*32, 1*32, 1*32, 5);
  569.         pump.save(frame);
  570.         frame.hotSpotY = 17;
  571.         frame.hotSpotX = -15;
  572. }
  573.  
  574. bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
  575.  
  576. obj.playerHandling = HANDLING::ENEMY;
  577. obj.scriptedCollisions = false;
  578.                 jjSwitchTrigger(9);
  579. jjSample(p.xPos, p.yPos, SOUND::COMMON_EXPSM1, 3000);
  580.                 obj.frameID = 0;
  581.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  582.  
  583.                 return true;  
  584.         }
  585. }
  586.  
  587. class Switch4: jjBEHAVIORINTERFACE {
  588.         void onBehave(jjOBJ@ obj) {
  589.                 obj.behave(BEHAVIOR::PICKUP, false);
  590.                 obj.draw();
  591.  
  592.  
  593.  
  594. jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::BLASTERPOWERUP].curAnim];
  595.         anim.frameCount = 1; //The Bee enemy's animation has several frames, but the tileset only has material for one. Editing jjANIMATION::frameCount to 1 will ensure that the animation never extends beyond the one frame we're providing.
  596.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  597.         jjPIXELMAP pump(0, 30*32, 1*32, 1*32, 5);
  598.         pump.save(frame);
  599.         frame.hotSpotY = 17;
  600.         frame.hotSpotX = -17;
  601. }
  602.  
  603. bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
  604.  
  605. obj.playerHandling = HANDLING::ENEMY;
  606. obj.scriptedCollisions = false;
  607.                 jjSwitchTrigger(11);
  608. jjSample(p.xPos, p.yPos, SOUND::COMMON_EXPSM1, 3000);
  609.                 obj.frameID = 0;
  610.                 obj.behavior = BEHAVIOR::EXPLOSION;
  611.  
  612.                 return true;  
  613.         }
  614. }
  615.  
  616.  
  617.  
  618. void onMain() {
  619.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::BURGER].curAnim];
  620.         anim.frameCount = 1;
  621.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  622.         jjPIXELMAP woman(0, 32*32, 1*32, 1*32, 5);
  623.         woman.save(frame);
  624.         frame.hotSpotY = -27;
  625.  
  626.  
  627. gem::deleteCollectedGems();
  628. if(jjTriggers[20]==true){
  629. if(jjKey[9] && jjKey[0x51]) {
  630. p.morphTo(CHAR::JAZZ, false);
  631. }
  632. if(jjKey[9] && jjKey[0x57]) {
  633. p.morphTo(CHAR::SPAZ, false);
  634. }
  635. if(jjKey[9] && jjKey[0x45]) {
  636. p.morphTo(CHAR::LORI, false);
  637. }
  638. }
  639. }
  640.  
  641.  
  642. /*
  643. // *Kangaroo by VioletCLM.* I wanted to use a jjAddObject instead of jjNxt after the defeat of Jill. So I had to carry the contents of the ASC folder here and make a small arrangement. Sorry about that Violet.
  644. API (all expected to be called in onLevelLoad):
  645.         jjOBJ@ Kangaroo::MakeEventJoey(uint8 eventID, int minX = 0, int maxX = 4, int minY = 6, int maxY = 12, int jumpDelay = 35, int minDistance = 224)
  646.                 Assign a specific event slot to the Joey enemy, e.g. replacing another enemy type or a food object or something. If you assign multiple event slots, you can get Joey enemies with different parameters.
  647.         jjOBJ@ Kangaroo::MakeEventJill(uint8 eventID, uint8 spawn = 0, bool secondStage = false, int textID = -1)
  648.                 Assign a specific event slot to the Jill boss.
  649.                         "spawn", if non-zero, is an eventID that the boss will occasionally create from her pouch. This is assumed to be a Joey enemy but may be other objects as well.
  650.                         The "secondStage" bool causes Jill to turn red and jump faster after she has lost three-quarters of her health.
  651.                         If "textID" is 0-16, defeating Jill will display that text ID.
  652.         void Kangaroo::OnJillDefeat(JILLCALLBACKFUNC@ callback = null)
  653.                 Three seconds after defeating Jill, this function will be called. The JILLCALLBACKFUNC pattern is the same as the behavior pattern: a void-returning function taking a jjOBJ@ as its only argument. If "callback" is left null, or if OnJillDefeat is never called, defeating a Jill will simply end the level.
  654.         void Kangaroo::Joey(jjOBJ@ obj)
  655.                 The behavior function for the Joey enemy
  656.         void Kangaroo::Jill(jjOBJ@ obj)
  657.                 The behavior function for the Jill boss
  658. */
  659.  
  660.  
  661.  
  662.  
  663. namespace Kangaroo {
  664.         namespace Private {
  665.                 void jillDefeatedDefaultAction(jjOBJ@ o) {
  666.                         p.showText("@@You are free to go now.");
  667.                         jjTriggers[15] = true;
  668.                         jjAddObject(OBJECT::SAVEPOST, 204*32, 13*32);
  669.                         exit += 1;
  670.                         jjSample(p.xPos, p.yPos, SOUND::LORISOUNDS_LORIFALL);
  671.                         jjMusicLoad("mo4a_The Golden City.ogg");
  672.                         p.bossActivated = false;
  673.                 }
  674.                 JILLCALLBACKFUNC@ jillCallback = jillDefeatedDefaultAction;
  675.                
  676.                 bool animsLoaded = false;
  677.                 uint customAnimID = 0;
  678.                 void loadAnims() {
  679.                         if (!animsLoaded) {
  680.                                 animsLoaded = true;
  681.                                 while (jjAnimSets[ANIM::CUSTOM[customAnimID]] != 0)
  682.                                         ++customAnimID;
  683.                                 customAnimID = ANIM::CUSTOM[customAnimID];
  684.                                 jjAnimSets[customAnimID].load(0, "kangaroo.j2a");
  685.                                 if (!jjSampleIsLoaded(SOUND::BUBBA_BUBBABOUNCE1))
  686.                                         jjAnimSets[ANIM::BUBBA].load();
  687.                         }
  688.                 }
  689.                
  690.                 void applyGenericEnemySettingsToPreset(jjOBJ@ preset) {
  691.                         preset.playerHandling = HANDLING::ENEMY;
  692.                         preset.bulletHandling = HANDLING::HURTBYBULLET;
  693.                         preset.causesRicochet = false;
  694.                         preset.isBlastable = false;
  695.                         preset.triggersTNT = true;
  696.                         preset.isFreezable = true;
  697.                         preset.isTarget = true;
  698.                         preset.scriptedCollisions = false;
  699.                         preset.direction = 1;
  700.                         preset.freeze = 0;
  701.                 }
  702.                
  703.                 void putKangarooOnGround(jjOBJ@ obj, int width, int height) {
  704.                         while (!jjMaskedHLine(int(obj.xPos) - width/2, width, int(obj.yPos) + height/2))
  705.                                 obj.yPos += 1;
  706.                 }
  707.                
  708.                 uint firstGloveAnimationFrame;
  709.                 const jjANIMFRAME@ roundExplosionFrame = jjAnimFrames[jjAnimations[jjAnimSets[ANIM::AMMO] + 5] + 2];;
  710.                
  711.                 void doGloveAt(int x, int y) {
  712.                         for (int i = 0; i < jjLocalPlayerCount; ++i) {
  713.                                 jjPLAYER@ localPlayer = jjLocalPlayers[i];
  714.                                 if (localPlayer.blink == 0 && roundExplosionFrame.doesCollide(x, y, 0, jjAnimFrames[localPlayer.curFrame], int(localPlayer.xPos), int(localPlayer.yPos), localPlayer.direction))
  715.                                         localPlayer.hurt();
  716.                         }
  717.                         for (int i = jjObjectCount - 1; i > 0; --i) {
  718.                                 jjOBJ@ obj = jjObjects[i];
  719.                                 if (obj.playerHandling == HANDLING::PLAYERBULLET && obj.state != STATE::EXPLODE && roundExplosionFrame.doesCollide(x, y, 0, jjAnimFrames[obj.curFrame], int(obj.xPos), int(obj.yPos), obj.direction)) {
  720.                                         obj.ricochet();
  721.                                         //obj.playerHandling = HANDLING::ENEMYBULLET;
  722.                                 }
  723.                         }
  724.                 }
  725.         }
  726.         enum KangarooVariables {
  727.                 kvWIDTH = 0, kvHEIGHT, kvMINX, kvMAXX, kvMINY, kvMAXY, kvJUMPDELAY, kvMINDISTANCE, kvGLOVE1FRAME, kvGLOVE2FRAME, kvSECONDSTAGE
  728.         }
  729.         jjOBJ@ MakeEventJoey(uint8 eventID, int minX = 0, int maxX = 4, int minY = 6, int maxY = 12, int jumpDelay = 35, int minDistance = 224) {
  730.                 Kangaroo::Private::loadAnims();
  731.                
  732.                 jjOBJ@ preset = jjObjectPresets[eventID];
  733.                 preset.behavior = Joey;
  734.                 preset.determineCurAnim(Kangaroo::Private::customAnimID, 0);
  735.                 preset.frameID = 0; preset.determineCurFrame();
  736.                
  737.                 Kangaroo::Private::applyGenericEnemySettingsToPreset(preset);
  738.                
  739.                 preset.deactivates = true;
  740.                 preset.energy = 1;
  741.                 preset.points = 200;
  742.                 preset.yAcc = 0.33f;
  743.                 preset.counter = 0;
  744.                 preset.var[kvWIDTH] = 12;
  745.                 preset.var[kvHEIGHT] = 28;
  746.                 preset.var[kvMINX] = minX;
  747.                 preset.var[kvMAXX] = maxX;
  748.                 preset.var[kvMINY] = minY;
  749.                 preset.var[kvMAXY] = maxY;
  750.                 preset.var[kvJUMPDELAY] = jumpDelay;
  751.                 preset.var[kvMINDISTANCE] = minDistance;
  752.                
  753.                 return preset;
  754.         }
  755.        
  756.         funcdef void JILLCALLBACKFUNC(jjOBJ@);
  757.         jjOBJ@ MakeEventJill(uint8 eventID, uint8 spawn = 0, bool secondStage = false, int textID = -1) {
  758.                 Kangaroo::Private::loadAnims();
  759.                 if (jjAnimSets[ANIM::GLOVE] == 0)
  760.                         jjAnimSets[ANIM::GLOVE].load();
  761.                 Kangaroo::Private::firstGloveAnimationFrame = jjAnimations[jjAnimSets[ANIM::GLOVE] + 3];
  762.                
  763.                 jjOBJ@ preset = jjObjectPresets[eventID];
  764.                 preset.behavior = Jill;
  765.                 preset.determineCurAnim(Kangaroo::Private::customAnimID, 1);
  766.                 preset.frameID = 0; preset.determineCurFrame();
  767.                
  768.                 Kangaroo::Private::applyGenericEnemySettingsToPreset(preset);
  769.                
  770.                 preset.doesHurt = spawn;
  771.                 preset.yAcc = 0.16f;
  772.                 preset.energy = 100;
  773.                 preset.points = 5000;
  774.                 preset.counterEnd = 210; //death wait
  775.                 preset.special = textID;
  776.                 preset.playerHandling = HANDLING::DYING; //no initial collision damage
  777.                 preset.var[kvWIDTH] = 32;
  778.                 preset.var[kvHEIGHT] = 98;
  779.                 preset.var[kvMINX] = 2;
  780.                 preset.var[kvMAXX] = 4;
  781.                 preset.var[kvMINY] = 5;
  782.                 preset.var[kvMAXY] = 10;
  783.                 preset.var[kvJUMPDELAY] = 140;
  784.                 preset.var[kvMINDISTANCE] = 400;
  785.                 preset.var[kvGLOVE1FRAME] = 0;
  786.                 preset.var[kvGLOVE2FRAME] = 0;
  787.                 preset.var[kvSECONDSTAGE] = secondStage ? 1 : 0;
  788.                
  789.                 return preset;
  790.         }
  791.         void OnJillDefeat(JILLCALLBACKFUNC@ callback = null) {
  792.                 if (callback !is null)
  793.                         @Kangaroo::Private::jillCallback = callback;
  794.         }
  795.        
  796.        
  797.         void Joey(jjOBJ@ obj) {
  798.                 const int width = obj.var[kvWIDTH];
  799.                 const int height = obj.var[kvHEIGHT];
  800.                 switch (obj.state) {
  801.                         case STATE::START:
  802.                                 obj.state = STATE::IDLE;
  803.                                 Kangaroo::Private::putKangarooOnGround(obj, width, height);
  804.                         case STATE::IDLE:
  805.                                 if (obj.counter == 0 || --obj.counter == 0) {
  806.                                         const int nearestPlayerID = obj.findNearestPlayer(int(pow(obj.var[kvMINDISTANCE], 2)));
  807.                                         if (nearestPlayerID >= 0) {
  808.                                                 jjPLAYER@ nearestPlayer = jjPlayers[nearestPlayerID];
  809.                                                 obj.xSpeed = (nearestPlayer.xPos - obj.xPos) / 20.0f;
  810.                                                 obj.direction = (obj.xSpeed >= 0) ? 1 : -1;
  811.                                                
  812.                                                 float xSpeed = abs(obj.xSpeed);
  813.                                                 if (xSpeed > obj.var[kvMAXX]) xSpeed = obj.var[kvMAXX];
  814.                                                 else if (xSpeed < obj.var[kvMINX]) xSpeed = obj.var[kvMINX];
  815.                                                 obj.xSpeed = xSpeed * obj.direction;
  816.                                                
  817.                                                 float ySpeed = abs((nearestPlayer.yPos - obj.yPos) / 20.0f);
  818.                                                 if (ySpeed > obj.var[kvMAXY]) ySpeed = obj.var[kvMAXY];
  819.                                                 else if (ySpeed < obj.var[kvMINY]) ySpeed = obj.var[kvMINY];
  820.                                                 obj.ySpeed = -ySpeed;
  821.                                                
  822.                                                 obj.state = STATE::JUMP;
  823.                                                 obj.counter = obj.var[kvJUMPDELAY];
  824.                                                 jjSample(obj.xPos, obj.yPos, ((jjRandom() & 1) == 0) ? SOUND::BUBBA_BUBBABOUNCE1 : SOUND::BUBBA_BUBBABOUNCE2);
  825.                                         } else
  826.                                                 obj.direction = (obj.xPos > jjLocalPlayers[0].xPos) ? -1 : 1;
  827.                                 }
  828.                                 break;
  829.                         case STATE::FREEZE:
  830.                                 if (obj.freeze > 0)
  831.                                         --obj.freeze;
  832.                                 if (obj.freeze <= 0) {
  833.                                         obj.state = obj.oldState;
  834.                                         obj.unfreeze(0);
  835.                                 }
  836.                                 break;
  837.                         case STATE::JUMP:{
  838.                                 obj.yPos += (obj.ySpeed += obj.yAcc);
  839.                                 const int newXPos = int(obj.xPos + obj.xSpeed) + (width * obj.direction)/2;
  840.                                 if ((newXPos < 0) || (newXPos > jjLayerWidth[4]*32) || jjMaskedVLine(newXPos, int(obj.yPos - height/2), height)) {
  841.                                         obj.xSpeed = -obj.xSpeed;
  842.                                         obj.direction = -obj.direction;
  843.                                 }
  844.                                 obj.xPos += obj.xSpeed;
  845.                                 int newYPos = int(obj.yPos + obj.ySpeed);
  846.                                 if (obj.ySpeed < 0) {
  847.                                         if ((newYPos < 0) || jjMaskedHLine(int(obj.xPos) - width/2, width, newYPos - height/2)) {
  848.                                                 obj.ySpeed = obj.yAcc;
  849.                                                 obj.frameID = 2;
  850.                                         } else obj.frameID = 1;
  851.                                 }
  852.                                 if (obj.ySpeed > 0) {
  853.                                         if ((newYPos > jjLayerHeight[4]*32) || jjMaskedHLine(int(obj.xPos) - width/2, width, newYPos + height/2)) {
  854.                                                 obj.state = STATE::IDLE;
  855.                                                 obj.ySpeed = 0;
  856.                                                 obj.frameID = 0;
  857.                                                 Kangaroo::Private::putKangarooOnGround(obj, width, height);
  858.                                         } else obj.frameID = 2;
  859.                                 }
  860.                                 obj.determineCurFrame();
  861.                                 break;
  862.                         } case STATE::DEACTIVATE:
  863.                                 obj.deactivate();
  864.                                 return;
  865.                         case STATE::KILL:
  866.                                 obj.delete();
  867.                                 return;
  868.                 }
  869.                 obj.draw();
  870.         }
  871.         void Jill(jjOBJ@ obj) {
  872.                 switch (obj.state) {
  873.                         case STATE::START:
  874.                                 obj.state = STATE::DELAYEDSTART;
  875.                         case STATE::DELAYEDSTART:
  876.                                 for (int i = 0; i < jjLocalPlayerCount; ++i) {
  877.                                         jjPLAYER@ localPlayer = jjLocalPlayers[i];
  878.                                         if (localPlayer.bossActivated) {
  879.                                                 localPlayer.boss = obj.objectID;
  880.                                                 obj.state = STATE::START;
  881.                                         }
  882.                                 }
  883.                                 if (obj.state == STATE::START) {
  884.                                         obj.playerHandling = HANDLING::ENEMY;
  885.                                         break;
  886.                                 }
  887.                                 return;
  888.                         case STATE::KILL:
  889.                                 if (obj.special >= 0) //textID
  890.                                         jjLocalPlayers[0].showText(obj.special, 0);
  891.                                 obj.playerHandling = HANDLING::DYING;
  892.                                 obj.state = STATE::DONE;
  893.                         case STATE::DONE:
  894.                                 if (--obj.counterEnd == 0) {
  895.                                         obj.delete();
  896.                                         Kangaroo::Private::jillCallback(obj);
  897.                                 }
  898.                                 return;
  899.                         default:
  900.                                 break;
  901.                 }
  902.                
  903.                 int oldState = obj.state;
  904.                 obj.behave(Joey, false);
  905.                 obj.frameID = 0;
  906.                 obj.determineCurFrame();
  907.                
  908.                 const int direction = obj.direction;
  909.                 const bool secondStage = (obj.var[kvSECONDSTAGE] != 0 && obj.energy < 25);
  910.                 if (secondStage) {
  911.                         if (obj.var[kvSECONDSTAGE] == 1) {
  912.                                 obj.var[kvSECONDSTAGE] = 2;
  913.                                 obj.var[kvMINX] = 3;
  914.                                 obj.var[kvMAXX] = 5;
  915.                                 obj.var[kvJUMPDELAY] = 50;
  916.                                 obj.var[kvMINDISTANCE] = 600;
  917.                         }
  918.                 }
  919.                 if (obj.doesHurt != 0 && (jjRandom() & 255) == 0) {
  920.                         jjOBJ@ spawn = jjObjects[jjAddObject(obj.doesHurt, obj.xPos, obj.yPos + 11, obj.objectID, CREATOR::OBJECT, BEHAVIOR::INACTIVE)];
  921.                         jjBEHAVIOR originalBehavior = jjObjectPresets[obj.doesHurt].behavior;
  922.                         if (originalBehavior == Joey) {
  923.                                 spawn.direction = obj.direction;
  924.                                 spawn.xSpeed = spawn.direction * (1 + (jjRandom() & 3));
  925.                                 spawn.ySpeed = -6;
  926.                                 spawn.state = STATE::JUMP;
  927.                         }
  928.                         spawn.behavior = originalBehavior;
  929.                 }
  930.                
  931.                 SPRITE::Mode mode = SPRITE::NORMAL;
  932.                 uint8 param = 15;
  933.                 SPRITE::Mode modeDark = SPRITE::BRIGHTNESS;
  934.                 uint8 paramDark = 96;
  935.                 if (obj.justHit != 0) {
  936.                         mode = modeDark = SPRITE::SINGLECOLOR;
  937.                         paramDark = param;
  938.                         const int nearestPlayerID = obj.findNearestPlayer(64);
  939.                         for (int i = 0; i < jjLocalPlayerCount; ++i) {
  940.                                 jjPLAYER@ localPlayer = jjLocalPlayers[i];
  941.                                 if (localPlayer.specialMove != 0) {
  942.                                         localPlayer.specialMove = 0;
  943.                                         localPlayer.ySpeed -= 1;
  944.                                         localPlayer.extendInvincibility(-35);
  945.                                 }
  946.                         }
  947.                        
  948.                 } else if (obj.state == STATE::FREEZE) {
  949.                         mode = modeDark = SPRITE::FROZEN;
  950.                 } else if (secondStage) {
  951.                         mode = modeDark = SPRITE::TINTED;
  952.                         param = 25;
  953.                         paramDark = 29;
  954.                 }
  955.                
  956.                 int armAngle = obj.age;
  957.                 if (obj.state != STATE::FREEZE) {
  958.                         const int nearestPlayerID = obj.findNearestPlayer(1000000);
  959.                         if (nearestPlayerID >= 0) {
  960.                                 jjPLAYER@ nearestPlayer = jjPlayers[nearestPlayerID];
  961.                                 const float deltaX = nearestPlayer.xPos - obj.xPos;
  962.                                 const float deltaY = nearestPlayer.yPos - obj.yPos;
  963.                                 armAngle = int(atan2(
  964.                                     (direction == 1) ? deltaY : -deltaY,
  965.                                     abs(deltaX)
  966.                                 ) * -512.0 * 0.318309886142228);
  967.                         }
  968.                         obj.age = armAngle;
  969.                 }
  970.                 const float armSin = jjSin(armAngle);
  971.                 const float armCos = jjCos(armAngle);
  972.                 int tailAngle = int(obj.ySpeed*-16)*direction;
  973.                 const int tailX = int(obj.xPos) - 32 * direction;
  974.                 const int tailY = int(obj.yPos) + 23;
  975.                 const int gloveLength = (12 + 29 + 29) * obj.direction;
  976.                 const int legAngle = int(obj.ySpeed*8)*direction;
  977.                 const int arm1X = int(obj.xPos) - 2 * direction;
  978.                 const int arm1Y = int(obj.yPos) - 7;
  979.                 const int arm2X = int(obj.xPos) + 4 * direction;
  980.                 const int arm2Y = int(obj.yPos - 11);
  981.                 //if (tailAngle > 0) tailAngle = 0;
  982.                
  983.                 if (obj.ySpeed < 0) {
  984.                         obj.animSpeed = jjSampleLooped(obj.xPos, obj.yPos, SOUND::COMMON_FLAMER, obj.animSpeed);
  985.                         if (obj.state != STATE::FREEZE && (jjRandom() & 1) == 0) {
  986.                                 jjPARTICLE@ part = jjAddParticle(PARTICLE::FIRE);
  987.                                 if (part !is null) {
  988.                                         part.xSpeed = jjSin(tailAngle) * 2;
  989.                                         part.ySpeed = jjCos(tailAngle) * 2;
  990.                                         part.xPos = tailX + part.xSpeed * 8;
  991.                                         part.yPos = tailY + part.ySpeed * 8;
  992.                                         part.xSpeed += abs(obj.xSpeed) * -obj.direction;
  993.                                 }
  994.                         }
  995.                         if (oldState == STATE::IDLE) {
  996.                                 obj.var[kvGLOVE1FRAME] = 1;
  997.                                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_PISTOL1);
  998.                                 obj.var[kvGLOVE2FRAME] = 0;
  999.                         }
  1000.                 }
  1001.                 {
  1002.                         int oldGloveFrame = obj.var[kvGLOVE1FRAME];
  1003.                         if (oldGloveFrame > 0 && oldGloveFrame < 12 && (jjGameTicks & 3) == 1)
  1004.                                 obj.var[kvGLOVE1FRAME] = oldGloveFrame + 1;
  1005.                        
  1006.                         oldGloveFrame = obj.var[kvGLOVE2FRAME];
  1007.                         if (obj.state == STATE::IDLE && oldGloveFrame == 0) {
  1008.                                 obj.var[kvGLOVE2FRAME] = 1;
  1009.                                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_PISTOL1);
  1010.                         }
  1011.                         if (oldGloveFrame > 0 && oldGloveFrame < 12 && (jjGameTicks & 3) == 1)
  1012.                                 obj.var[kvGLOVE2FRAME] = oldGloveFrame + 1;
  1013.                 }
  1014.                
  1015.                 const int glove2FrameID = Kangaroo::Private::firstGloveAnimationFrame + (obj.var[kvGLOVE2FRAME] + 3) % 12;
  1016.                 jjDrawRotatedSpriteFromCurFrame(
  1017.                         arm2X + 12*armSin + gloveLength*armCos,
  1018.                         arm2Y + 12*armCos - gloveLength*armSin,
  1019.                          glove2FrameID,
  1020.                         armAngle - 256 * obj.direction,
  1021.                         direction, 2, modeDark, paramDark
  1022.                 ); //glove
  1023.                 if (obj.state != STATE::FREEZE) {
  1024.                         const int glove2Length = gloveLength + (jjAnimFrames[glove2FrameID].height - 30) * 2 * obj.direction;
  1025.                         Kangaroo::Private::doGloveAt(
  1026.                                 int(arm2X + 12*armSin + glove2Length*armCos),
  1027.                                 int(arm2Y + 12*armCos - glove2Length*armSin)
  1028.                         );
  1029.                 }
  1030.                 jjDrawRotatedSpriteFromCurFrame(arm2X, arm2Y, obj.curFrame + 1, armAngle, direction, 1, modeDark, paramDark); //back arm
  1031.                
  1032.                 jjDrawRotatedSpriteFromCurFrame(obj.xPos - 24 * direction, obj.yPos + 24, obj.curFrame + 2, legAngle, direction, 1, modeDark, paramDark); //back leg
  1033.                 jjDrawRotatedSpriteFromCurFrame(tailX, tailY, obj.curFrame + 3, tailAngle, direction, 1, mode, param); //tail
  1034.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, direction, mode, param); //body
  1035.                 jjDrawRotatedSpriteFromCurFrame(obj.xPos - 30 * direction, obj.yPos + 28, obj.curFrame + 2, legAngle, direction, 1, mode, param); //leg
  1036.                
  1037.                 jjDrawRotatedSpriteFromCurFrame(arm1X, arm1Y, obj.curFrame + 1, armAngle, direction, 1, mode, param); //arm
  1038.                 const int glove1FrameID = Kangaroo::Private::firstGloveAnimationFrame + (obj.var[kvGLOVE1FRAME] + 3) % 12;
  1039.                 jjDrawRotatedSpriteFromCurFrame(
  1040.                         arm1X + 12*armSin + gloveLength*armCos,
  1041.                         arm1Y + 12*armCos - gloveLength*armSin,
  1042.                          glove1FrameID,
  1043.                         armAngle - 256 * obj.direction,
  1044.                         direction, 2, mode, param
  1045.                 ); //glove
  1046.                 if (obj.state != STATE::FREEZE) {
  1047.                         const int glove1Length = gloveLength + (jjAnimFrames[glove1FrameID].height - 30) * 2 * obj.direction;
  1048.                         Kangaroo::Private::doGloveAt(
  1049.                                 int(arm2X + 12*armSin + glove1Length*armCos),
  1050.                                 int(arm2Y + 12*armCos - glove1Length*armSin)
  1051.                         );
  1052.                 }
  1053.         }
  1054. }
  1055.  
  1056. bool onDrawHealth(jjPLAYER@ player, jjCANVAS@ canvas) {
  1057.     canvas.drawString(30, 585, formatInt(exit%7, "1") + "/6", STRING::SMALL, STRING::NORMAL);
  1058.     canvas.drawSprite(20, 585, ANIM::PICKUPS, 11, jjGameTicks>>2, -1, SPRITE::NORMAL);
  1059.     canvas.drawString(100, 585, formatInt(frogexit%5, "1") + "/4", STRING::SMALL, STRING::NORMAL);
  1060.     canvas.drawResizedSprite(90, 585, ANIM::PICKUPS, 52, 4,0.7, 0.7, SPRITE::NORMAL);
  1061.     return false;
  1062. }
  1063.  
  1064. bool onDrawLives(jjPLAYER@ player, jjCANVAS@ canvas) {     return true;}
  1065.  
  1066.  
  1067. void onLevelReload() {
  1068.  
  1069.         if(crate2 == true)
  1070.                 {jjAddObject(OBJECT::TNT, 1*32, 35*32);}
  1071.         if(crate3 == true)
  1072.                 {jjAddObject(OBJECT::TNT, 49*32, 12*32);}
  1073.         if(crate5 == true)
  1074.                 {jjAddObject(OBJECT::TNT, 208*32, 48*32);}
  1075.         if(crate6 == true)
  1076.                 {jjAddObject(OBJECT::TNT, 250*32, 14*32);}
  1077.  
  1078.  
  1079.  
  1080.         jjEnabledASFunctions[3] = true;
  1081.         jjEnabledASFunctions[2] = true;
  1082.         jjMusicLoad("mo4a_The Golden City.ogg");
  1083.         gem::restorePlayerGems();
  1084.         jjLocalPlayers[0].lives++;
  1085.         jjWaterLighting = WATERLIGHT::GLOBAL;
  1086.         for (uint i = 0; i < 32; ++i)
  1087.                 jjTriggers[i] = SavedTriggers[i];
  1088. }
  1089.  
  1090. array<bool> SavedTriggers(32, false);
  1091. //Extendable Checkpoints by VioletCLM
  1092. void CheckpointWrapper(jjOBJ@ obj) {
  1093.   if (obj.state == STATE::STOP) { //don't do anything anymore
  1094.     jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 8);
  1095.   } else if (obj.state == STATE::DEACTIVATE) { //due to death
  1096.     obj.deactivate();
  1097.   } else {
  1098.     obj.behave(BEHAVIOR::CHECKPOINT);
  1099.         jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 8);
  1100.     if (obj.state == STATE::DONE) { //triggered by the player hitting it
  1101.       obj.state = STATE::STOP;
  1102.       //save the current state of some properties
  1103.       for (uint i = 0; i < 32; ++i)
  1104.         SavedTriggers[i] = jjTriggers[i];
  1105.  
  1106.       //OPTIONAL: this loop makes checkpoints reusable, so only the most recent checkpoint you touched is ever active
  1107.       for (int i = jjObjectCount; --i > 0;) {
  1108.         jjOBJ@ obj2 = jjObjects[i];
  1109.         if (obj2.eventID == OBJECT::CHECKPOINT && i != obj.objectID && obj2.isActive) {
  1110.           obj2.state = STATE::SLEEP;
  1111.           obj2.var[0] = 0;
  1112.         }
  1113.       }
  1114.     }
  1115.   }
  1116. }
  1117.  
  1118. jjTEXTAPPEARANCE SignTextAppearance = STRING::NORMAL;
  1119. class Sign {
  1120.         private int xPos, yPos; //These pixel-based positions will be generated from tile-based positions in the constructor by multiplying by 32
  1121.         private string text;
  1122.         private uint widthOfText;
  1123.         Sign(){} //AngelScript requires any class that appears in any array to have an explicit default constructor, even if it's never called
  1124.         Sign(int xTile, int yTile, const string &in t) {
  1125.                 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
  1126.                 yPos = yTile * 32; //
  1127.                 text = t;
  1128.                 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.
  1129.                 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.
  1130.                 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.
  1131.         }
  1132.         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.
  1133.                 layer.drawRectangle(xPos, yPos - 16, widthOfText + 8, 55, 0, SPRITE::TRANSLUCENT);
  1134.                 layer.drawString(xPos, yPos, text, STRING::SMALL, SignTextAppearance, 0, SPRITE::BLEND_HARDLIGHT, textIntensity);
  1135.         }
  1136. }
  1137. const array<Sign> Signs = {
  1138.         Sign(54, 38, "Rabbits cannot swim.\nHow about frogs?"),
  1139.         Sign(100, 56, "HEY! GET ME OUTTA HERE\nWITH THAT KEY OVER THERE!"),
  1140. };
  1141.  
  1142. void onDrawLayer3(jjPLAYER@, jjCANVAS@ layer) {
  1143.         if((jjKey[0x54] && p.charCurr == CHAR::FROG)||(p.charCurr == CHAR::FROG && p.xPos >90*32 && p.xPos<113*32 && p.yPos>34*32)){
  1144.         const uint8 textIntensity = 200 + int(jjSin(jjGameTicks * 16) * 50);
  1145.         for (uint signID = 0; signID < Signs.length; ++signID)
  1146.                 Signs[signID].draw(layer, textIntensity);
  1147. }
  1148. }
  1149. bool onDrawAmmo(jjPLAYER@ player, jjCANVAS@ canvas) {
  1150.         return MLLE::WeaponHook.drawAmmo(player, canvas);
  1151. }
  1152.