Downloads containing ab22btl12.j2as

Downloads
Name Author Game Mode Rating
TSF with JJ2+ Only: Anniversary Bash 22 levels Jazz2Online Multiple N/A Download file

File preview

  1. const bool MLLESetupSuccessful = MLLE::Setup(); ///@MLLE-Generated
  2. #include "MLLE-Include-1.5.asc" ///@MLLE-Generated
  3. #pragma require "ab22btl12-MLLE-Data-2.j2l" ///@MLLE-Generated
  4. #pragma require "ab22btl12-MLLE-Data-1.j2l" ///@MLLE-Generated
  5. #pragma require "ab22btl12.j2l" ///@MLLE-Generated
  6. #pragma require "SEenergyblast.asc"
  7. #include "SEenergyblast.asc"
  8. #include "weaponMega.asc"
  9. #pragma require "weaponMega.asc"
  10. #pragma require "SEfirework.asc"
  11. #include "SEfirework.asc"
  12. #pragma require "TornadoGun.j2a"
  13. #pragma require "weaponMega.j2a"
  14.  
  15. void onLevelLoad() {
  16. resetSpread();
  17. ReplaceEggmanAnimation() ;
  18.         EnergyBlastEdit energyBlast;
  19.         energyBlast.loadAnims(jjAnimSets[ANIM::CUSTOM[0]]);
  20.         energyBlast.loadSamples(array<SOUND::Sample> = {SOUND::INTRO_BLOW});
  21.         energyBlast.setAsWeapon(4, weaponHook);
  22.         se::firework.loadAnims(jjAnimSets[ANIM::CUSTOM[1]]);
  23.         se::firework.loadSamples(array<SOUND::Sample> = {SOUND::INTRO_BOEM1, SOUND::INTRO_BOEM2});
  24.         se::firework.setAsWeapon(5, weaponHook);
  25.     jjObjectPresets[OBJECT::BRIDGE].behavior = Bridge;
  26.         jjObjectPresets[OBJECT::CHIPS].scriptedCollisions = true;
  27.         jjObjectPresets[OBJECT::CHIPS].behavior = SpreadShot();
  28.                 jjWeapons[WEAPON::GUN8].spread = SPREAD::NORMAL;
  29.                 jjObjectPresets[OBJECT::APPLE].behavior = Eggman();
  30.                 for (int i = 1; i < 255; i++) {
  31.                 if (jjObjectPresets[i].behavior == BEHAVIOR::PICKUP) {
  32.                         jjObjectPresets[i].behavior = CannotBeShotDown;
  33.                 }
  34.         }
  35.         jjObjectPresets[OBJECT::RFAMMO3].behavior = CannotBeShotDown;
  36.         jjObjectPresets[OBJECT::SEEKERAMMO3].behavior = CannotBeShotDown;
  37.         jjAnimSets[ANIM::CUSTOM[6]].load(0, "TornadoGun.j2a");
  38.         jjAnimations[jjAnimSets[ANIM::AMMO] + 57] = jjAnimations[jjAnimSets[ANIM::CUSTOM[6]] + 3];
  39.         jjAnimations[jjAnimSets[ANIM::AMMO] + 56] = jjAnimations[jjAnimSets[ANIM::CUSTOM[6]] + 2];
  40.        
  41.         jjObjectPresets[OBJECT::TOASTERBULLET].behavior = TornadoGun();
  42.         jjObjectPresets[OBJECT::TOASTERBULLET].special = jjObjectPresets[OBJECT::TOASTERBULLET].determineCurAnim(ANIM::CUSTOM[6], 0);
  43.         jjObjectPresets[OBJECT::TOASTERBULLET].xSpeed = 4;
  44.         jjObjectPresets[OBJECT::TOASTERBULLET].counterEnd = 110;
  45.         jjObjectPresets[OBJECT::TOASTERBULLET].var[6] = 0;
  46.         jjObjectPresets[OBJECT::TOASTERBULLET].freeze = 0;
  47.         jjObjectPresets[OBJECT::TOASTERBULLET].eventID = OBJECT::FIREBALLBULLET;
  48.         jjObjectPresets[OBJECT::TOASTERBULLET].lightType = jjObjectPresets[OBJECT::FIREBALLBULLET].lightType;
  49.         jjObjectPresets[OBJECT::TOASTERBULLET].killAnim = jjObjectPresets[OBJECT::ICEBULLET].killAnim;
  50.         jjObjectPresets[OBJECT::TOASTERBULLET].lightType = LIGHT::POINT;
  51.        
  52.         jjObjectPresets[OBJECT::TOASTERBULLETPU].behavior = TornadoGunPU();
  53.         jjObjectPresets[OBJECT::TOASTERBULLETPU].special = jjObjectPresets[OBJECT::TOASTERBULLETPU].determineCurAnim(ANIM::CUSTOM[6], 1);
  54.         jjObjectPresets[OBJECT::TOASTERBULLETPU].xSpeed = 6;
  55.         jjObjectPresets[OBJECT::TOASTERBULLETPU].counterEnd = 120;
  56.         jjObjectPresets[OBJECT::TOASTERBULLETPU].var[6] = 8;
  57.         jjObjectPresets[OBJECT::TOASTERBULLETPU].freeze = 0;
  58.         jjObjectPresets[OBJECT::TOASTERBULLETPU].eventID = OBJECT::FIREBALLBULLET;
  59.         jjObjectPresets[OBJECT::TOASTERBULLETPU].killAnim = jjObjectPresets[OBJECT::ICEBULLET].killAnim;
  60.         jjObjectPresets[OBJECT::TOASTERBULLETPU].lightType = LIGHT::POINT2;
  61.        
  62.         jjObjectPresets[OBJECT::TOASTERPOWERUP].determineCurAnim(ANIM::CUSTOM[6], 4);
  63.         jjObjectPresets[OBJECT::TOASTERPOWERUP].determineCurFrame();
  64.        
  65.         jjObjectPresets[OBJECT::TOASTERAMMO15].determineCurAnim(ANIM::CUSTOM[6], 5);
  66.         jjObjectPresets[OBJECT::TOASTERAMMO15].determineCurFrame();
  67.  
  68.         jjWeapons[WEAPON::TOASTER].defaultSample = false;
  69.         jjWeapons[WEAPON::TOASTER].replacedByBubbles = false;
  70.         //jjWeapons[WEAPON::TOASTER].spread = SPREAD::NORMAL;
  71.         jjWeapons[WEAPON::TOASTER].style = WEAPON::NORMAL;
  72.         jjWeapons[WEAPON::TOASTER].multiplier = 1;
  73.        
  74. }
  75.  
  76. se::DefaultWeaponHook weaponHook;
  77. bool gameIsActive() {
  78.         return jjGameState == GAME::STARTED || jjGameState == GAME::OVERTIME;
  79. }
  80. class EnergyBlastEdit : se::EnergyBlastWeapon {
  81.         protected void prepareWeaponProfile(::jjWEAPON@ weapon) const override {
  82.                 weapon.comesFromBirds = false;
  83.                 weapon.comesFromBirdsPowerup = false;
  84.                 weapon.defaultSample = false;
  85.                 weapon.gradualAim = false;
  86.                 weapon.multiplier = 6; //was originally 3
  87.                 weapon.replacedByBubbles = false;
  88.                 weapon.spread = SPREAD::NORMAL;
  89.                 weapon.style = WEAPON::POPCORN;
  90.         }
  91. }
  92. void CannotBeShotDown(jjOBJ@ obj) {
  93.         obj.behave(BEHAVIOR::PICKUP);
  94.         if (obj.state == STATE::FLOATFALL) obj.state = STATE::FLOAT;
  95. }
  96.  
  97. bool onDrawAmmo(jjPLAYER@ player, jjCANVAS@ canvas) {
  98.         return weaponHook.drawAmmo(player, canvas);
  99. }
  100. uint nextBullet = 200;
  101. int timer = 0;
  102.  
  103. void onLevelBegin() {
  104.     if (!jjIsServer) jjSendPacket(jjSTREAM());
  105. }
  106.  
  107. void onReceive(jjSTREAM &in packet, int clientID) {
  108. weaponHook.processPacket(packet, clientID);
  109.     if (jjIsServer) {
  110.         updateTime(clientID);
  111.     } else {
  112.         int currTime;
  113.         packet.pop(currTime);
  114.         timer = currTime;
  115.     }
  116. }
  117.  
  118. void updateTime(int clientID) {
  119.     jjSTREAM packet;
  120.     packet.push(timer);
  121.     jjSendPacket(packet, clientID);
  122. }
  123.  
  124.  
  125. void onMain() {
  126.         weaponHook.processMain();
  127.        
  128. }
  129. class SpreadShot : jjBEHAVIORINTERFACE {
  130.         void onBehave(jjOBJ@ obj) {
  131.                 obj.behave(BEHAVIOR::PICKUP, false);
  132.                 obj.light = 12;
  133.                 obj.lightType = LIGHT::BRIGHT;
  134.                         obj.xPos=obj.xOrg+0*jjSin(-jjGameTicks*5+int(obj.xOrg)*32/3);
  135.                         obj.yPos=obj.yOrg+0*jjCos(-jjGameTicks*5+int(obj.xOrg)*32/3);   }
  136.         void onDraw(jjOBJ@ obj) {
  137.                 jjDrawRotatedSprite(obj.xPos, obj.yPos + 10, ANIM::AMMO, 37, jjGameTicks >> 2, angle, 1, 1, SPRITE::NORMAL, 0, 1);
  138.                 jjDrawRotatedSprite(obj.xPos, obj.yPos, ANIM::AMMO, 37, jjGameTicks >> 2, angle, 1, 1, SPRITE::NORMAL, 0, 1);
  139.                 jjDrawRotatedSprite(obj.xPos, obj.yPos - 10, ANIM::AMMO, 37, jjGameTicks >> 2, angle, 1, 1, SPRITE::NORMAL, 0, 1);
  140.         }
  141.         bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ p, int force) {
  142.                 obj.bulletHandling = HANDLING::IGNOREBULLET;
  143.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  144.                 obj.scriptedCollisions = false;
  145.                 obj.frameID = 0;
  146.                 if (p.isLocal) spreadShotCountdown = 15;
  147.                 jjSamplePriority(SOUND::COMMON_PICKUP1);
  148.                 return true;
  149.         }
  150. }
  151. uint spreadShotCountdown = 0;
  152. uint16 angle = 0;
  153. void resetSpread() {
  154.         jjWeapons[WEAPON::BLASTER].spread = SPREAD::NORMAL;
  155.         jjWeapons[WEAPON::BOUNCER].spread = SPREAD::NORMAL;
  156.         jjWeapons[WEAPON::ICE].spread = SPREAD::ICE;
  157.         jjWeapons[WEAPON::SEEKER].spread = SPREAD::NORMAL;
  158.         jjWeapons[WEAPON::RF].spread = SPREAD::NORMAL;
  159.         jjWeapons[WEAPON::TNT].spread = SPREAD::NORMAL;
  160.         jjWeapons[WEAPON::TOASTER].spread = SPREAD::NORMAL;
  161.         jjWeapons[WEAPON::GUN8].spread = SPREAD::NORMAL;
  162.         jjWeapons[WEAPON::GUN9].spread = SPREAD::NORMAL;
  163. }
  164. void onPlayer(jjPLAYER@ p) {
  165.         weaponHook.processPlayer(p);
  166.         if (spreadShotCountdown > 0 && jjGameTicks % 70 == 0) {
  167.                 spreadShotCountdown--;
  168.                 if (spreadShotCountdown == 0) {
  169.                         resetSpread();
  170.                 }
  171.         }
  172.         else if (spreadShotCountdown == 15) {
  173.         /*      for (uint i = 1; i <= 4; i++) {
  174.        
  175.                         jjWeapons[i].spread = SPREAD::RFPU;
  176.                 }  
  177.                 for (uint i = 7; i <= 9; i++) {
  178.        
  179.                         jjWeapons[i].spread = SPREAD::RFPU;
  180.                 }  
  181.                 jjWeapons[6].spread = SPREAD::RFPU;
  182.                 */
  183.                 jjWeapons[1].spread = SPREAD::RFPU;
  184.                 jjWeapons[2].spread = SPREAD::RFPU;
  185.                 jjWeapons[3].spread = SPREAD::RFPU;
  186.                 jjWeapons[6].spread = SPREAD::RFPU;
  187.                 jjWeapons[8].spread = SPREAD::RFPU;
  188.                 jjWeapons[9].spread = SPREAD::RFPU;
  189.         }
  190.         if (spreadShotCountdown > 0) {
  191.                 jjTEXTAPPEARANCE normal(STRING::NORMAL);
  192.                
  193.                 int x = int(p.cameraX);
  194.                 int y = int(p.cameraY);
  195.                
  196.                 jjDrawSprite(x + jjResolutionWidth - 72, y + jjResolutionHeight - 270, ANIM::PICKUPS, 87, jjGameTicks >> 2, 0, SPRITE::NORMAL, 0, 1);
  197.                 jjDrawString(x + jjResolutionWidth - 55, y + jjResolutionHeight - 274, "" + spreadShotCountdown, STRING::MEDIUM, normal, 0, SPRITE::PALSHIFT, 0, 1);
  198.         }
  199.         if (p.health == 0) {
  200.                 spreadShotCountdown == 0;
  201.                 resetSpread();
  202.         }
  203.         angle += 12;
  204. }
  205. void onPlayerInput(jjPLAYER@ player) {
  206.         weaponHook.processPlayerInput(player);
  207. }
  208. /*void onReceive(jjSTREAM &in packet, int clientID) {
  209.         weaponHook.processPacket(packet, clientID);
  210. }*/
  211.  
  212.  
  213. void Bridge(jjOBJ@ obj) {
  214.     obj.behave(BEHAVIOR::BRIDGE);
  215.     obj.yPos = obj.yOrg - 12;
  216. }
  217.  
  218.  
  219.  
  220. bool LoadWeaponMega3() {
  221.         if (!SafeToReplaceWeapon(WEAPON::ICE))
  222.                 return false;
  223.        
  224.         jjWeapons[WEAPON::ICE].style = WEAPON::POPCORN;
  225.         jjWeapons[WEAPON::ICE].spread = SPREAD::TOASTER;
  226.         jjWeapons[WEAPON::ICE].multiplier = 12;
  227.         jjWeapons[WEAPON::ICE].gradualAim = true;
  228.        
  229.         Preset1.behavior = ApplyIceCloud;
  230.         Preset2.behavior = ApplyIceCloud;
  231.         Preset1.special = Preset1.determineCurAnim(AnimSet, 0);
  232.         Preset2.special = Preset2.determineCurAnim(AnimSet, 0);
  233.         Preset1.determineCurFrame(); Preset2.determineCurFrame();
  234.         Preset1.isBlastable = true; Preset2.isBlastable = true;
  235.         //Preset1.var[6] = Preset1.var[6] | 16; //"fireball"
  236.         //Preset2.var[6] = Preset2.var[6] | 16;
  237.         Preset1.counterEnd = 100; //lifetime
  238.         Preset2.counterEnd = 100;
  239.        
  240.         return true;
  241. }
  242. const bool WeaponMega3Loaded = LoadWeaponMega3();
  243.  
  244. void ApplyIceCloud(jjOBJ@ obj) { obj.behavior = IceCloud(obj); obj.behave(); }
  245. class IceCloud : WeaponMega {
  246.         IceCloud(jjOBJ@ objectOfAttachment) {
  247.                 @obj = @objectOfAttachment;
  248.                 obj.xSpeed += obj.var[7] / 65536.f;
  249.                 if (obj.creatorType == CREATOR::PLAYER)
  250.                         obj.ySpeed += int(jjPlayers[obj.creatorID].ySpeed) / 2;
  251.                 obj.state = STATE::FLY;
  252.         }
  253.         void onBehave(jjOBJ@) override {
  254.                 obj.xPos += obj.xSpeed *= 0.96;
  255.                 obj.yPos += obj.ySpeed *= 0.96;
  256.                 if (obj.frameID < 3 && ++obj.age & 15 == 15) {
  257.                         ++obj.frameID; ++obj.curFrame;
  258.                 }
  259.                 if (--obj.counterEnd == 0 || obj.state == STATE::EXPLODE) {
  260.                         int playerID;
  261.                         if (  (playerID = getNearestEnemy(400)) >= 0) {
  262.                                 obj.frameID = 0;
  263.                                 obj.killAnim = (obj.curAnim += 1) + 1;
  264.                                 obj.counterEnd = 100;
  265.                                 obj.freeze = 0;
  266.                                 const jjPLAYER@ target = jjPlayers[playerID];
  267.                                 obj.xSpeed = (target.xPos - obj.xPos) / 25;
  268.                                 obj.ySpeed = (target.yPos - obj.yPos) / 25;
  269.                                 obj.xAcc = obj.yAcc = obj.var[7] = 0;
  270.                                 obj.behavior = BEHAVIOR::BULLET;
  271.                         } else {
  272.                                 obj.counter = 0;
  273.                                 obj.frameID = 0;
  274.                                 obj.curAnim += 2;
  275.                                 obj.behavior = BEHAVIOR::EXPLOSION;
  276.                         }
  277.                         jjSample(obj.xPos, obj.yPos, SOUND::COMMON_ICECRUSH);
  278.                 } else if (jjGameTicks & 1 == 0) {
  279.                         jjPARTICLE@ part = jjAddParticle(PARTICLE::ICETRAIL);
  280.                         if (part !is null) {
  281.                                 part.yPos = obj.yPos;
  282.                                 part.xPos = obj.xPos + (jjRandom() & 31) - 15;
  283.                         }
  284.                 }
  285.         }
  286.         void onDraw(jjOBJ@) override {
  287.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, 1, SPRITE::TRANSLUCENT);
  288.                 if (obj.frameID == 3)
  289.                         jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, jjAnimations[obj.curAnim + 1], 0, SPRITE::TRANSLUCENTCOLOR, 15);
  290.         }
  291. }
  292.  
  293.  
  294.  
  295.        
  296.        
  297.         bool LoadWeaponMega4() {
  298.         if (!SafeToReplaceWeapon(WEAPON::SEEKER))
  299.                 return false;
  300.                
  301.         jjWeapons[WEAPON::GUN9].defaultSample = false;
  302.         jjWeapons[WEAPON::GUN9].replacedByBubbles = true;
  303.        
  304. jjObjectPresets[OBJECT::ELECTROBULLET].behavior = ApplyPathfinder;
  305.         jjObjectPresets[OBJECT::ELECTROBULLETPU].behavior = ApplyPathfinder;
  306.         jjObjectPresets[OBJECT::ELECTROBULLET].special = jjObjectPresets[OBJECT::ELECTROBULLET].determineCurAnim(AnimSet, 0);
  307.         jjObjectPresets[OBJECT::ELECTROBULLETPU].special = jjObjectPresets[OBJECT::ELECTROBULLETPU].determineCurAnim(AnimSet, 1);
  308.         jjObjectPresets[OBJECT::ELECTROBULLET].determineCurFrame(); jjObjectPresets[OBJECT::ELECTROBULLETPU].determineCurFrame();
  309.         jjObjectPresets[OBJECT::ELECTROBULLET].isBlastable = false; jjObjectPresets[OBJECT::ELECTROBULLETPU].isBlastable = false;
  310.         jjObjectPresets[OBJECT::ELECTROBULLET].playerHandling = jjObjectPresets[OBJECT::ELECTROBULLETPU].playerHandling = HANDLING::PLAYERBULLET;
  311.         jjObjectPresets[OBJECT::ELECTROBULLET].counterEnd = 46; jjObjectPresets[OBJECT::ELECTROBULLETPU].counterEnd = 32;
  312.         jjObjectPresets[OBJECT::ELECTROBULLET].var[6] = 16;
  313.        
  314.         return true;
  315. }
  316. const bool WeaponMega4Loaded = LoadWeaponMega4();
  317.  
  318. void ApplyPathfinder(jjOBJ@ obj) { obj.behavior = Pathfinder(obj); obj.behave(); }
  319. class Pathfinder : WeaponMega {
  320.         array<jjOBJ@> nodes;
  321.         bool waiting = false;
  322.         bool foundAtLeastOneTarget = false;
  323.         uint counter = 0;
  324.         bool powerup;
  325.         Pathfinder(jjOBJ@ objectOfAttachment) {
  326.                 @obj = @objectOfAttachment;
  327.                 obj.state = STATE::FLY;
  328.                 powerup = isPowerup();
  329.                 jjSample(obj.xPos, obj.yPos, powerup ? SOUND::AMMO_LASER3 : SOUND::AMMO_LASER2);
  330.         }
  331.         void destroy() {
  332.                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_ELECTRIC2);
  333.                 for (uint i = 0; i < nodes.length; ++i)
  334.                         nodes[i].delete();
  335.                 obj.delete();
  336.         }
  337.         void onBehave(jjOBJ@) override {
  338.                 if (obj.state == STATE::EXPLODE) {
  339.                         destroy();
  340.                         return;
  341.                 }
  342.                 obj.frameID = (obj.objectID + jjGameTicks / 3) % 3;
  343.                 if (++counter >= obj.counterEnd) {
  344.                         if (waiting = !waiting) { //stop moving
  345.                                 addNode();
  346.                                 counter = obj.counterEnd / 2;
  347.                         } else { //start moving
  348.                                 if (nodes.length > (uint(powerup ? 6 : 4) / uint(foundAtLeastOneTarget ? 1 : 3)) || obj.state == STATE::DONE) {
  349.                                         destroy();
  350.                                         return;
  351.                                 }
  352.                                 const int nearestEnemyID = getNearestEnemy(200);
  353.                                 if (nearestEnemyID >= 0) {
  354.                                         const jjPLAYER@ target = jjPlayers[nearestEnemyID];
  355.                                         obj.var[7] = 0;
  356.                                         const float standardSpeed = (powerup ? 3.f : 2.5f);
  357.                                         const float dx = target.xPos - obj.xPos, dy = target.yPos - obj.yPos;
  358.                                         foundAtLeastOneTarget = true;
  359.                                         if (abs(dx) > abs(dy)) {
  360.                                                 obj.xSpeed = (dx > 0) ? standardSpeed : -standardSpeed;
  361.                                                 obj.ySpeed = 0;
  362.                                         } else {
  363.                                                 obj.xSpeed = 0;
  364.                                                 obj.ySpeed = (dy > 0) ? standardSpeed : -standardSpeed;
  365.                                         }
  366.                                 }
  367.                                 counter = 0;
  368.                         }
  369.                 }
  370.                 if (!waiting) {
  371.                         obj.xPos += obj.xSpeed + obj.var[7] / 65536.f;
  372.                         obj.yPos += obj.ySpeed;
  373.                         if (obj.var[7] > 0x100000)
  374.                                 obj.var[7] = obj.var[7] - 0x80000;
  375.                         else if (obj.var[7] < -0x100000)
  376.                                 obj.var[7] = obj.var[7] + 0x80000;
  377.                         if (colliding()) {
  378.                                 counter = obj.counterEnd / 2;
  379.                                 waiting = true;
  380.                                 addNode();
  381.                                 obj.state = STATE::DONE;
  382.                         }
  383.                 }
  384.         }
  385.         bool colliding() const {
  386.                 return maskedPixelAtBullet() && jjEventAtLastMaskedPixel != AREA::ONEWAY && jjEventAtLastMaskedPixel != AREA::HOOK && jjEventAtLastMaskedPixel != AREA::VINE;
  387.         }
  388.         void addNode() {
  389.                 jjOBJ@ node = jjObjects[jjAddObject(OBJECT::BEES, obj.xPos, obj.yPos, obj.creatorID, obj.creatorType)];
  390.                 node.playerHandling = HANDLING::PLAYERBULLET;
  391.                 node.var[6] = 2 | (powerup ? 8 : 0) | 16; //fireball
  392.                 node.animSpeed = powerup ? 2 : 1;
  393.                 node.curFrame = jjAnimations[obj.curAnim + 2];
  394.                 node.state = STATE::FLY;
  395.                 node.lightType = LIGHT::BRIGHT;
  396.                 node.light = powerup ? 10 : 8;
  397.                 nodes.insertLast(node);
  398.                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_ELECTRIC1);
  399.         }
  400.         void onDraw(jjOBJ@) override {
  401.                 jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame + obj.frameID);
  402.                 for (uint i = 0; i < nodes.length; ++i) {
  403.                         const jjOBJ@ node = nodes[i];
  404.                         const jjOBJ@ node2 = (i < nodes.length - 1) ? nodes[i + 1] : obj;
  405.                         //jjDrawRectangle(node.xPos, node.yPos, int(node2.xPos - node.xPos) + 1, int(node2.yPos - node.yPos) + 1, 15);
  406.                         jjDrawSpriteFromCurFrame(node.xPos, node.yPos, node.curFrame + obj.frameID);
  407.                 }
  408.         }
  409. }
  410.  
  411.  
  412.  
  413. class TornadoGun : jjBEHAVIORINTERFACE {
  414.         void onBehave(jjOBJ@ obj) {
  415.                 obj.behave(BEHAVIOR::BULLET);
  416.                 jjPLAYER@ creator = jjPlayers[obj.creatorID];
  417.                 if (obj.state == STATE::FLY) {
  418.                         if (obj.counter == 1 && creator.isLocal) {
  419.                                 //jjSample(creator.xPos, creator.yPos, SOUND::INTRO_BLOW, 48, 25000);
  420.                                 jjSample(creator.xPos, creator.yPos, SOUND::COMMON_BIRDFLY, 48, 25000);
  421.                         }
  422.                        
  423.                         switch (obj.direction) {
  424.                                 case 1: obj.xSpeed = obj.xSpeed - 0.05; obj.ySpeed = obj.ySpeed - 0.1; break;
  425.                                 case -1: obj.xSpeed = obj.xSpeed + 0.05; obj.ySpeed = obj.ySpeed - 0.1; break;
  426.                         }
  427.                        
  428.                         float pdx = jjLocalPlayers[0].xPos - obj.xPos, pdy = jjLocalPlayers[0].yPos - obj.yPos;
  429.                         if ((pdx * pdx + pdy * pdy < 64 * 64) && !creator.isLocal && (jjLocalPlayers[0].team != creator.team || jjFriendlyFire) && gameIsActive()) {
  430.                                 jjLocalPlayers[0].ySpeed -= 2;
  431.                                 jjLocalPlayers[0].xSpeed += 2 * obj.direction;
  432.                         }
  433.                 }
  434.                 if (obj.state == STATE::EXPLODE) {
  435.                         if (obj.var[0] == 0) {
  436.                                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_SWISH4, 36, 15000);
  437.                                 obj.var[0] = 1;
  438.                         }
  439.                 }
  440.         }
  441. }
  442.  
  443. class TornadoGunPU : jjBEHAVIORINTERFACE {
  444.         void onBehave(jjOBJ@ obj) {
  445.                 obj.behave(BEHAVIOR::BULLET);
  446.                 jjPLAYER@ creator = jjPlayers[obj.creatorID];
  447.                 if (obj.state == STATE::FLY) {
  448.                         if (obj.counter == 1 && creator.isLocal) {
  449.                         //      jjSample(creator.xPos, creator.yPos, SOUND::INTRO_BLOW, 48, 30000);
  450.                                 jjSample(creator.xPos, creator.yPos, SOUND::COMMON_BIRDFLY, 48, 30000);
  451.                         }
  452.  
  453.                         switch (obj.direction) {
  454.                                 case 1: obj.xSpeed = obj.xSpeed - 0.05; obj.ySpeed = obj.ySpeed - 0.1; break;
  455.                                 case -1: obj.xSpeed = obj.xSpeed + 0.05; obj.ySpeed = obj.ySpeed - 0.1; break;
  456.                         }
  457.                        
  458.                         float pdx = jjLocalPlayers[0].xPos - obj.xPos, pdy = jjLocalPlayers[0].yPos - obj.yPos;
  459.                         if ((pdx * pdx + pdy * pdy < 96 * 96) && !creator.isLocal && (jjLocalPlayers[0].team != creator.team || jjFriendlyFire) && gameIsActive()) {
  460.                                 jjLocalPlayers[0].ySpeed -= 4;
  461.                                 jjLocalPlayers[0].xSpeed += 4 * obj.direction;
  462.                         }
  463.                 }
  464.                 if (obj.state == STATE::EXPLODE) {
  465.                         if (obj.var[0] == 0) {
  466.                                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_SWISH4, 36, 15000);
  467.                                 obj.var[0] = 1;
  468.                         }
  469.                 }
  470.         }
  471. }
  472.  
  473. bool LoadWeaponMega7() {
  474.         if (!SafeToReplaceWeapon(WEAPON::TNT))
  475.                 return false;
  476.                
  477.         jjWeapons[WEAPON::TNT].defaultSample = false;
  478.         jjWeapons[WEAPON::TNT].style = WEAPON::CAPPED;
  479.         jjWeapons[WEAPON::TNT].maximum = 18;
  480.         Preset1.behavior = function(obj){obj.behavior = GravityWell(obj); obj.behave();};
  481.         Preset1.special = Preset1.determineCurAnim(AnimSet, 0);
  482.         Preset1.determineCurFrame();
  483.         Preset1.state = STATE::IDLE; //why bother with START, really
  484.         Preset1.var[6] = 16; //fireball-ish
  485.         Preset1.var[6] = 8;
  486.         Preset1.animSpeed = 1; //do damage to objects (as opposed to players)
  487.         Preset1.counter = 0;
  488.         Preset1.xSpeed = 1; //needed to get a direction
  489.         Preset1.playerHandling = HANDLING::PLAYERBULLET;
  490.         Preset1.eventID = OBJECT::BULLET; //to prevent using /tntdamage
  491.        
  492.        
  493.         return true;
  494. }
  495. const bool WeaponMega7Loaded = LoadWeaponMega7();
  496.  
  497. class GravityWell : WeaponMega {
  498.         GravityWell(jjOBJ@ objectOfAttachment) {
  499.                 @obj = @objectOfAttachment;
  500.         }
  501.         void onBehave(jjOBJ@) override {
  502.                 obj.frameID = ++obj.counter / 7;
  503.                 obj.age = jjSampleLooped(obj.xPos, obj.yPos, SOUND::COMMON_MONITOR, obj.age, 63, 5000);
  504.                
  505.                 if (obj.counter > 175) {
  506.                         jjSample(obj.xPos, obj.yPos, SOUND::COMMON_SHLDOF3);
  507.                         obj.particlePixelExplosion(88);
  508.                         obj.delete();
  509.                 } else {
  510.                         for (uint i = jjObjectCount - 1; i > 0; --i) {
  511.                                 jjOBJ@ other = jjObjects[i];
  512.                                 if (other.isActive && other.eventID <= OBJECT::BULLET && other.isBlastable && other.state != STATE::EXPLODE && (other.creatorType != CREATOR::PLAYER || playerIsEnemy(jjPlayers[other.creator]))) {
  513.                                         float d, dx, dy;
  514.                                         if (withinRange(other.xPos, other.yPos, d, dx, dy)) {
  515.                                                 const float angle = atan2(dy, dx);
  516.                                                 other.xSpeed += 64 / d * cos(angle);
  517.                                                 other.ySpeed += 64 / d * sin(angle);
  518.                                         }
  519.                                 }
  520.                         }
  521.                         for (uint i = 0; i < 32; ++i) {
  522.                                 jjPLAYER@ other = jjPlayers[i];
  523.                                 if (other.isInGame && other.blink == 0 && playerIsEnemy(other)) {
  524.                                         float d, dx, dy;
  525.                                         if (withinRange(other.xPos, other.yPos, d, dx, dy)) {
  526.                                                 const float angle = atan2(dy, dx);
  527.                                                 other.xSpeed += 24 / d * cos(angle);
  528.                                                 other.ySpeed += 10 / d * sin(angle);
  529.                                         }
  530.                                 }
  531.                         }
  532.                 }
  533.         }
  534.         void onDraw(jjOBJ@) override {
  535.                 if (obj.frameID <= 6) {
  536.                         obj.curFrame = jjAnimations[obj.curAnim] + obj.frameID;
  537.                         jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame);
  538.                 } else {
  539.                         while (obj.frameID > 6) obj.frameID -= 3;
  540.                         obj.curFrame = jjAnimations[obj.curAnim] + obj.frameID;
  541.                         jjDrawRotatedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, (obj.counter - 7*7) * (obj.xSpeed >= 0 ? -32 : 32));
  542.                         obj.lightType = LIGHT::RING2;
  543.                         obj.light = 15 - (obj.counter & 7) * 2;
  544.                 }
  545.         }
  546.         bool withinRange(float x, float y, float &out d, float &out dx, float &out dy) const {
  547.                 dx = obj.xPos - x;
  548.                 dy = obj.yPos - y;
  549.                 return (d = sqrt(dx * dx + dy * dy)) < (290);
  550.         }
  551. }
  552. class Eggman : jjBEHAVIORINTERFACE {
  553.         void onBehave(jjOBJ@ obj) {    
  554.         float t = (jjGameTicks);
  555.         obj.playerHandling = HANDLING::HURT;
  556.         obj.xPos = obj.xOrg + 12*32*cos(0.25*t/7+40);
  557.         obj.yPos = obj.yOrg + 32*sin(t/7)+32*sin(0.6*t/7+70)+32*sin(0.3*t/7-20);
  558.        
  559.         jjDrawSprite(obj.xPos  , obj.yPos , ANIM::PICKUPS, 1, 1, -3*sin(0.25*t/7+40));
  560.        
  561.         }
  562.         }
  563.         void ReplaceEggmanAnimation() {
  564.         jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::APPLE].curAnim];
  565.         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.
  566.         jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
  567.         jjPIXELMAP gargoyle(0, 158*32, 2*32, 2*32, 4); //Arguments in order: Leftmost pixel of image in layer; topmost pixel; area width; area height; layer ID (1-indexed). You can check the level for yourself in JCS to see how this matches up with the gargoyle's position in layer 3, although note that JCS uses 1-indexed tile positions, not 0-indexed like AngelScript does.
  568.         gargoyle.save(frame);
  569.         frame.hotSpotX = -frame.width / 2;      //Most hotspot values are negative, and the most common position for a hotspot is in the (negative) center of the frame. That's what this code does.
  570.         frame.hotSpotY = -frame.height / 2;     //Of course, you're welcome to experiment with other hotspot positions for your own specialized needs, but this is fine for a simple Bee enemy.
  571. }