Downloads containing SEenergyblast.asc

Downloads
Name Author Game Mode Rating
TSF with JJ2+ Only: Goliath WoodsFeatured Download PurpleJazz Capture the flag 8.9 Download file
TSF with JJ2+ Only: Hollow of the HauntedFeatured Download cooba Capture the flag 9.2 Download file
TSF with JJ2+ Only: Giant's StepsFeatured Download PurpleJazz Capture the flag 9.2 Download file
TSF with JJ2+ Only: Anniversary Bash 22 levels Jazz2Online Multiple N/A Download file
TSF with JJ2+ Only: Party Crash LandingFeatured Download cooba Battle 9.5 Download file
TSF with JJ2+ Only: Anniversary Bash 21 Levels Jazz2Online Multiple N/A Download file
TSF with JJ2+ Only: The Fingers of IcarusFeatured Download cooba Battle 8.8 Download file
JJ2+ Only: CleanseFeatured Download Seren Capture the flag 8.7 Download file
TSF with JJ2+ Only: Anniversary Bash 20 Levels Jazz2Online Multiple N/A Download file
TSF with JJ2+ Only: Press GardenFeatured Download SmokeNC Battle 9.2 Download file
Standard Weapon InterfaceFeatured Download Seren Other 10 Download file

File preview

  1. #pragma require "SEweapon.asc"
  2. #pragma require "SEenergyblast.j2a"
  3. #pragma offer "SEenergyblast.wav"
  4. #include "SEweapon.asc"
  5. namespace se {
  6. shared class EnergyBlastWeapon : WeaponInterface {
  7.         private ::jjANIMSET@ m_animSet;
  8.         private SOUND::Sample m_sample = SOUND::COMMON_BURNIN;
  9.         private ::array<int> m_lastUsed(32, -15), m_lastObserved(32, -1), m_sampleHandle(32, 0);
  10.         private int m_soundFrequency = 25000;
  11.         protected ::jjANIMSET@ getAnimSet() const {
  12.                 return @m_animSet;
  13.         }
  14.         protected SOUND::Sample getSample() const {
  15.                 return m_sample;
  16.         }
  17.         protected bool loadAnimSet(::jjANIMSET@ animSet, const ::string &in filename, uint setID) {
  18.                 if (animSet !is null && !::jjSTREAM(filename).isEmpty()) {
  19.                         @m_animSet = @animSet.load(setID, filename);
  20.                         return true;
  21.                 }
  22.                 return false;
  23.         }
  24.         protected bool loadSample(SOUND::Sample sample, const ::string &in filename) {
  25.                 if (::jjSampleLoad(sample, filename)) {
  26.                         m_sample = sample;
  27.                         m_soundFrequency = 150000;
  28.                         return true;
  29.                 }
  30.                 return false;
  31.         }
  32.         protected bool lowestFreePlayerSpace(float x, float y, float height = 0.f, float &out result = void) {
  33.                 int left = int(x) - 12;
  34.                 int top = int(y) - 12;
  35.                 int row = int(y + height) - 12;
  36.                 int bottom = row + 24;
  37.                 while (row >= top) {
  38.                         int start = row;
  39.                         while (!::jjMaskedHLine(left, 24, row)) {
  40.                                 row++;
  41.                                 if (row == bottom) {
  42.                                         result = start + 12;
  43.                                         return true;
  44.                                 }
  45.                         }
  46.                         bottom = start;
  47.                         row -= 24;
  48.                 }
  49.                 return false;
  50.         }
  51.         protected void behave(::jjOBJ@ obj) {
  52.                 switch (obj.state) {
  53.                         case STATE::START:
  54.                                 if (obj.creatorType != CREATOR::PLAYER || m_lastObserved[obj.creatorID] < ::jjGameTicks) {
  55.                                         if (obj.creatorType == CREATOR::PLAYER)
  56.                                                 m_lastObserved[obj.creatorID] = ::jjGameTicks;
  57.                                         int angle = int(atan2(-obj.ySpeed, obj.xSpeed) * 162.974662f + 768.5f);
  58.                                         obj.state = STATE::FLY;
  59.                                         if (obj.ySpeed > 10.f)
  60.                                                 obj.ySpeed = 10.f;
  61.                                         else if (obj.ySpeed < -10.f)
  62.                                                 obj.ySpeed = -10.f;
  63.                                         {
  64.                                                 float xNew = obj.xPos + obj.xSpeed;
  65.                                                 float yNew = obj.yPos + obj.ySpeed;
  66.                                                 if (lowestFreePlayerSpace(xNew, yNew)) {
  67.                                                         obj.xPos = xNew;
  68.                                                         obj.yPos = yNew;
  69.                                                         if (!lowestFreePlayerSpace(xNew + obj.xSpeed, yNew + obj.ySpeed))
  70.                                                                 obj.xSpeed = obj.ySpeed = 0.f;
  71.                                                 } else {
  72.                                                         bool ok = obj.ySpeed >= 0.f;
  73.                                                         float yFree;
  74.                                                         if (ok) {
  75.                                                                 float y = obj.yPos - ::abs(obj.xSpeed);
  76.                                                                 ok = lowestFreePlayerSpace(xNew, y, yNew - y, yFree);
  77.                                                         }
  78.                                                         if (ok) {
  79.                                                                 obj.xPos = xNew;
  80.                                                                 obj.yPos = yFree;
  81.                                                                 obj.ySpeed = yFree - obj.yPos;
  82.                                                         } else if (lowestFreePlayerSpace(obj.xPos, yNew)) {
  83.                                                                 obj.yPos = yNew;
  84.                                                                 obj.xSpeed = 0.f;      
  85.                                                         } else {
  86.                                                                 obj.xSpeed = obj.ySpeed = 0.f;
  87.                                                         }
  88.                                                 }
  89.                                         }
  90.                                         obj.yPos -= 8.f;
  91.                                         array<int> colors = {obj.var[6] & 8 != 0 ? 84 : 60, obj.var[6] & 8 != 0 ? 80 : 40};
  92.                                         for (int i = 0; i < 2; i++) {
  93.                                                 const ::jjANIMATION@ anim = ::jjAnimations[obj.curAnim + 3];
  94.                                                 int frame = anim + ::jjGameTicks % anim.frameCount;
  95.                                                 ::jjDrawRotatedSpriteFromCurFrame(obj.xPos, obj.yPos, frame, angle, i * 2 - 1.f, 1.f, SPRITE::ALPHAMAP, colors[i], 4);
  96.                                         }
  97.                                         for (int i = 0; i < 2; i++) {
  98.                                                 const ::jjANIMATION@ anim = ::jjAnimations[obj.curAnim + i + 1];
  99.                                                 int frame = anim + ::jjGameTicks % anim.frameCount;
  100.                                                 ::jjDrawRotatedSpriteFromCurFrame(obj.xPos, obj.yPos, frame, angle, 1.f, 1.f, SPRITE::ALPHAMAP, colors[1], i + 3);
  101.                                         }
  102.                                 }
  103.                                 break;
  104.                         case STATE::FLY:
  105.                                 obj.state = STATE::EXPLODE;
  106.                                 break;
  107.                         case STATE::EXPLODE:
  108.                         case STATE::KILL:
  109.                         case STATE::DEACTIVATE:
  110.                                 obj.delete();
  111.                                 break;
  112.                 }
  113.         }
  114.         protected void behaveTNT(::jjOBJ@ obj) {
  115.                 if (obj.creatorType == CREATOR::PLAYER && ::jjPlayers[obj.creatorID].powerup[WEAPON::TNT]) {
  116.                         obj.animSpeed = 2;
  117.                         obj.var[6] = 24;
  118.                         obj.xSpeed = 16.f;
  119.                 } else {
  120.                         obj.animSpeed = 1;
  121.                         obj.var[6] = 16;
  122.                         obj.xSpeed = 14.f;
  123.                 }
  124.                 obj.behavior = @::jjVOIDFUNCOBJ(behave);
  125.                 obj.behave();
  126.         }
  127.         protected void disableControl(::jjPLAYER@ player) const {
  128.                 float xPos = player.xPos;
  129.                 float yPos = player.yPos;
  130.                 ::jjOBJ@ obj = ::jjObjects[0];
  131.                 int state = obj.state;
  132.                 int var = obj.var[0];
  133.                 int counter = obj.counter;
  134.                 obj.state = STATE::ACTION;
  135.                 obj.var[0] = player.playerID;
  136.                 obj.behave(BEHAVIOR::EVA, false);
  137.                 obj.state = state;
  138.                 obj.var[0] = var;
  139.                 obj.counter = counter;
  140.                 player.idle = 0;
  141.                 player.xPos = xPos;
  142.                 player.yPos = yPos;
  143.         }
  144.         protected void reactToPlayerInput(::jjPLAYER@ player, int number) {
  145.                 const array<int> forbiddenChars = {CHAR::FROG, CHAR::BIRD};
  146.                 const array<int> forbiddenEvents = {AREA::HPOLE, AREA::VPOLE, AREA::WARP, AREA::SUCKERTUBE};
  147.                 if (forbiddenChars.find(player.charCurr) >= 0)
  148.                         return;
  149.                 bool forbidden = player.health <= 0 || player.noFire || player.fly > 1 || player.warpID != 0 && player.xSpeed == 0.f && player.ySpeed == 0.f || player.charCurr == CHAR::BIRD2 || forbiddenEvents.find(::jjEventGet(int(player.xPos) >> 5, int(player.yPos) >> 5)) >= 0;
  150.                 if (forbidden) {
  151.                         m_lastUsed[player.playerID] = -15;
  152.                         if (int(player.currWeapon) == number)
  153.                                 player.keyFire = false;
  154.                         return;
  155.                 }
  156.                 bool using = int(player.currWeapon) == number && player.keyFire && player.frozen == 0;
  157.                 if (using)
  158.                         m_lastUsed[player.playerID] = ::jjGameTicks;
  159.                 if (using || ::jjGameTicks - m_lastUsed[player.playerID] < 15) {
  160.                         const float tau = 6.28318531f, pi = 3.14159265f, pi4 = 0.785398163f;
  161.                         const float dirUp = 0.f, dirRight = 1.57079633f, dirDown = pi, dirLeft = 4.71238898f;
  162.                         const float angularVelocity = 0.2f, gravity = 0.125f;
  163.                         bool ignoreCurrent = ::closeTo(player.xSpeed, 0.f) && player.ySpeed <= gravity && player.ySpeed >= 0.f;
  164.                         float current, direction;
  165.                         if (ignoreCurrent) {
  166.                                 if (player.buttstomp < 81) {
  167.                                         current = dirDown;
  168.                                         ignoreCurrent = false;
  169.                                 }
  170.                         } else {
  171.                                 current = ::atan2(player.xSpeed, -(player.ySpeed - gravity));
  172.                         }
  173.                         if (::jjAllowsMouseAim && ::jjMouseAim) {
  174.                                 float x, y;
  175.                                 x = ::jjMouseX + player.cameraX - player.xPos;
  176.                                 y = ::jjMouseY + player.cameraY - player.yPos;
  177.                                 direction = ::atan2(x, -y);
  178.                         } else {
  179.                                 int x = 0, y = 0;
  180.                                 if (player.keyLeft)
  181.                                         x--;
  182.                                 if (player.keyRight)
  183.                                         x++;
  184.                                 if (player.keyUp)
  185.                                         y--;
  186.                                 if (player.keyDown)
  187.                                         y++;
  188.                                 if (x == 0 && y == 0) {
  189.                                         if (ignoreCurrent) {
  190.                                                 direction = player.direction < 0 ? dirLeft : dirRight;
  191.                                         } else {
  192.                                                 direction = current / pi4;
  193.                                                 float frac = ::fraction(direction);
  194.                                                 if (frac >= 0.5f || frac < 0.f && frac >= -0.5f)
  195.                                                         direction = ::ceil(direction);
  196.                                                 else
  197.                                                         direction = ::floor(direction);
  198.                                                 direction *= pi4;
  199.                                         }
  200.                                 } else {
  201.                                         direction = ::atan2(x, -y);
  202.                                 }
  203.                         }
  204.                         if (!ignoreCurrent) {
  205.                                 float difference = direction - current;
  206.                                 difference = (difference + tau) % tau;
  207.                                 if (::closeTo(difference, pi)) {
  208.                                         direction = player.direction < 0 ? dirLeft : dirRight;
  209.                                         difference = direction - current;
  210.                                         difference = (difference + tau) % tau;
  211.                                         if (::closeTo(difference, 0.f) || ::closeTo(difference, pi)) {
  212.                                                 direction = dirUp;
  213.                                                 difference = direction - current;
  214.                                                 difference = (difference + tau) % tau;
  215.                                         }
  216.                                 }
  217.                                 if (difference < pi) {
  218.                                         if (difference > angularVelocity)
  219.                                                 difference = angularVelocity;
  220.                                 } else {
  221.                                         difference -= tau;
  222.                                         if (difference < -angularVelocity)
  223.                                                 difference = -angularVelocity;
  224.                                 }
  225.                                 direction = current + difference;
  226.                         }
  227.                         float xSpeed = player.xSpeed;
  228.                         float ySpeed = player.ySpeed;
  229.                         player.xSpeed = 0.f;
  230.                         player.ySpeed = 0.f;
  231.                         int id = player.fireBullet(number, true, true, direction + tau);
  232.                         if (id > 0) {
  233.                                 const ::jjOBJ@ obj = @::jjObjects[id];
  234.                                 disableControl(@player);
  235.                                 player.ballTime = 10;
  236.                                 player.currWeapon = number;
  237.                                 player.xAcc = 0.f;
  238.                                 player.yAcc = 0.f;
  239.                                 player.xSpeed = obj.xSpeed;
  240.                                 player.ySpeed = player.antiGrav ? -obj.ySpeed : obj.ySpeed;
  241.                                 player.keyLeft = false;
  242.                                 player.keyRight = false;
  243.                                 player.keyUp = false;
  244.                                 player.keyDown = player.yPos < ::jjWaterLevel;
  245.                                 player.keyJump = false;
  246.                                 player.keyRun = false;
  247.                                 player.buttstomp = player.keyDown ? 81 : 121;
  248.                                 player.fly = FLIGHT::NONE;
  249.                                 player.helicopter = 0;
  250.                                 player.specialMove = 0;
  251.                                 if (player.invincibility > -2 && player.invincibility < 2)
  252.                                         player.invincibility = -2;
  253.                                 int volume = player.ammo[number] << 3 | 4;
  254.                                 int vol2 = 63 - ((::jjGameTicks - m_lastUsed[player.playerID]) << 2);
  255.                                 if (volume > vol2)
  256.                                         volume = vol2;
  257.                                 m_sampleHandle[player.playerID] = ::jjSampleLooped(obj.xPos, obj.yPos, m_sample, m_sampleHandle[player.playerID], volume, m_soundFrequency);
  258.                         } else {
  259.                                 m_lastUsed[player.playerID] = -15;
  260.                                 player.xSpeed = xSpeed;
  261.                                 player.ySpeed = ySpeed;
  262.                                 do {
  263.                                         if (player.currWeapon == WEAPON::BLASTER)
  264.                                                 player.currWeapon = WEAPON::GUN9;
  265.                                         else
  266.                                                 player.currWeapon = player.currWeapon - 1;
  267.                                 } while (player.ammo[player.currWeapon] <= 0 && int(player.currWeapon) != number);
  268.                                 if (int(player.currWeapon) == number)
  269.                                         player.currWeapon = WEAPON::BLASTER;
  270.                         }
  271.                 }
  272.         }
  273.         protected void prepareWeaponProfile(::jjWEAPON@ weapon) const {
  274.                 weapon.comesFromBirds = false;
  275.                 weapon.comesFromBirdsPowerup = false;
  276.                 weapon.defaultSample = false;
  277.                 weapon.gradualAim = false;
  278.                 weapon.multiplier = 3;
  279.                 weapon.replacedByBubbles = false;
  280.                 weapon.spread = SPREAD::NORMAL;
  281.                 weapon.style = WEAPON::POPCORN;
  282.         }
  283.         protected void prepareBulletPresets(::jjOBJ@ basic, ::jjOBJ@ powerup, uint number) const {
  284.                 if (basic is powerup)
  285.                         basic.behavior = @::jjVOIDFUNCOBJ(behaveTNT);
  286.                 else
  287.                         basic.behavior = powerup.behavior = @::jjVOIDFUNCOBJ(behave);
  288.                 basic.animSpeed = 1;
  289.                 powerup.animSpeed = 2;
  290.                 basic.counterEnd = powerup.counterEnd = 1;
  291.                 basic.curAnim = powerup.curAnim = basic.special = powerup.special = m_animSet + 4;
  292.                 basic.curFrame = powerup.curFrame = ::jjAnimations[basic.curAnim];
  293.                 basic.direction = powerup.direction = 0;
  294.                 basic.energy = powerup.energy = basic.freeze = powerup.freeze = 0;
  295.                 basic.frameID = powerup.frameID = 0;
  296.                 basic.killAnim = powerup.killAnim = 0;
  297.                 basic.lightType = powerup.lightType = LIGHT::NONE;
  298.                 basic.playerHandling = powerup.playerHandling = HANDLING::PLAYERBULLET;
  299.                 basic.var[3] = powerup.var[3] = number;
  300.                 basic.var[6] = 16;
  301.                 powerup.var[6] = 24;
  302.                 basic.xAcc = powerup.xAcc = 0.f;
  303.                 basic.yAcc = powerup.yAcc = 0.f;
  304.                 basic.xSpeed = 14.f;
  305.                 powerup.xSpeed = 16.f;
  306.                 basic.ySpeed = powerup.ySpeed = 0.f;
  307.         }
  308.         protected void preparePickupPresets(::jjOBJ@ ammo3, ::jjOBJ@ ammo15, ::jjOBJ@ powerup) const {
  309.                 if (ammo3 !is null) {
  310.                         ammo3.behavior = @AmmoPickup(::jjAnimations[m_animSet], ::jjAnimations[m_animSet + 1], 5);
  311.                         ammo3.curAnim = m_animSet;
  312.                         ammo3.frameID = 0;
  313.                         ammo3.determineCurFrame();
  314.                 }
  315.                 if (ammo15 !is null) {
  316.                         ammo15.curAnim = m_animSet + 2;
  317.                         ammo15.frameID = 0;
  318.                         ammo15.determineCurFrame();
  319.                 }
  320.                 if (powerup !is null) {
  321.                         powerup.curAnim = m_animSet + 3;
  322.                         powerup.frameID = 0;
  323.                         powerup.determineCurFrame();
  324.                 }
  325.         }
  326.         ::jjANIMSET@ loadAnims(::jjANIMSET@ animSet) override {
  327.                 loadAnimSet(animSet, "SEenergyblast.j2a", 0);
  328.                 return @animSet;
  329.         }
  330.         ::array<bool>@ loadSamples(const ::array<SOUND::Sample>& samples) override {
  331.                 return @::array<bool>(1, samples.length() == 1 && loadSample(samples[0], "SEenergyblast.wav"));
  332.         }
  333.         uint getSampleCount() const override {
  334.                 return 1;
  335.         }
  336.         uint getTraits(bool) const override {
  337.                 return weapon_default_traits | weapon_increases_mobility;
  338.         }
  339.         uint getMaxDamage(bool powerup) const override {
  340.                 return powerup ? 2 : 1;
  341.         }
  342.         bool setAsWeapon(uint number, WeaponHook@ weaponHook) override {
  343.                 if (m_animSet !is null && isValidWeapon(number) && weaponHook !is null) {
  344.                         uint basic = getBasicBulletOfWeapon(number);
  345.                         uint powered = getPoweredBulletOfWeapon(number);
  346.                         uint ammo3 = getAmmoPickupOfWeapon(number);
  347.                         uint ammo15 = getAmmoCrateOfWeapon(number);
  348.                         uint powerup = getPowerupMonitorOfWeapon(number);
  349.                         weaponHook.resetCallbacks(number);
  350.                         weaponHook.setWeaponSprite(number, false, ::jjAnimations[m_animSet]);
  351.                         weaponHook.setWeaponSprite(number, true, ::jjAnimations[m_animSet + 1]);
  352.                         weaponHook.setPlayerInputCallback(number, @PlayerCallback(reactToPlayerInput));
  353.                         prepareWeaponProfile(@::jjWeapons[number]);
  354.                         prepareBulletPresets(@::jjObjectPresets[basic], @::jjObjectPresets[powered], number);
  355.                         preparePickupPresets(ammo3 != 0 ? @::jjObjectPresets[ammo3] : null, ammo15 != 0 ? @::jjObjectPresets[ammo15] : null, @::jjObjectPresets[powerup]);
  356.                         return true;
  357.                 }
  358.                 return false;
  359.         }
  360. }
  361. EnergyBlastWeapon energyBlast;
  362. }
  363.