Downloads containing SEast.j2as

Downloads
Name Author Game Mode Rating
TSF with JJ2+ Only: Astolfo Seren Battle 7.5 Download file

File preview

  1. #pragma require "SEroller.asc"
  2. #include "SEroller.asc"
  3. funcdef float EasingFunction(float);
  4. class Point {
  5.         int x, y;
  6.         Point() {}
  7.         Point(int X, int Y) {
  8.                 x = X;
  9.                 y = Y;
  10.         }
  11. }
  12. class Timer {
  13.         private EasingFunction@ easing;
  14.         private const jjANIMATION@ anim;
  15.         private int animFrameDelay;
  16.         private int frameCounter;
  17.         private int curFrame;
  18.         private bool visible;
  19.         private int visibility;
  20.         private int maxVisibility;
  21.         private float posAlpha;
  22.         private float posBeta;
  23.         private int time;
  24.         private string oldText;
  25.         private string newText;
  26.         private STRING::Size size;
  27.         private int transition;
  28.         private int maxTransition;
  29.         private int textAlpha;
  30.         private int textBeta;
  31.         private float offsetAlpha;
  32.         private float offsetBeta;
  33.         private float maxOffset;
  34.         jjTEXTAPPEARANCE style;
  35.         Timer() {
  36.                 @easing = function(t) {
  37.                         const float c = 1.70158f;
  38.                         const float a3 = c + 1.f;
  39.                         const float a2 = -2.f * c - 3.f;
  40.                         const float a1 = c + 3.f;
  41.                         return t * (t * (t * a3 + a2) + a1);
  42.                 };
  43.                 @anim = jjAnimations[jjAnimSets[ANIM::PICKUPS] + 40];
  44.                 animFrameDelay = 4;
  45.                 maxVisibility = 35;
  46.                 size = STRING::MEDIUM;
  47.                 maxTransition = 15;
  48.                 maxOffset = 16.f;
  49.         }
  50.         void setVisible(bool value) {
  51.                 visible = value;
  52.         }
  53.         void setTime(int value, bool playSample) {
  54.                 if (time != value) {
  55.                         time = value;
  56.                         oldText = newText;
  57.                         newText = formatInt(value);
  58.                         transition = visibility == 0 ? maxTransition : 0;
  59.                         if (playSample)
  60.                                 jjSamplePriority(value == 0 ? SOUND::COMMON_BELL_FIRE : SOUND::COMMON_BELL_FIRE2);
  61.                 }
  62.         }
  63.         void process() {
  64.                 frameCounter++;
  65.                 curFrame = anim + frameCounter / animFrameDelay % anim.frameCount;
  66.                 if (visible) {
  67.                         if (visibility < maxVisibility)
  68.                                 visibility++;
  69.                 } else {
  70.                         if (visibility > 0)
  71.                                 visibility--;
  72.                 }
  73.                 float t = float(visibility) / maxVisibility;
  74.                 posBeta = easing(t);
  75.                 posAlpha = 1.f - posBeta;
  76.                 if (transition < maxTransition) {
  77.                         transition++;
  78.                         float a = float(transition) / maxTransition;
  79.                         textBeta = int(a * 255.f);
  80.                         textAlpha = 255 - textBeta;
  81.                         offsetAlpha = -a * maxOffset;
  82.                         offsetBeta = maxOffset + offsetAlpha;
  83.                 }
  84.         }
  85.         void draw(jjCANVAS@ canvas, float x0, float y0, float x1, float y1) const {
  86.                 int x = int(x0 * posAlpha + x1 * posBeta);
  87.                 float y = y0 * posAlpha + y1 * posBeta;
  88.                 if (curFrame != 0)
  89.                         canvas.drawSpriteFromCurFrame(x, int(y), curFrame);
  90.                 x += jjAnimFrames[anim].width + jjAnimFrames[anim].hotSpotX;
  91.                 canvas.drawString(x, int(y + offsetAlpha), oldText, size, style, 0, SPRITE::BLEND_NORMAL, textAlpha);
  92.                 canvas.drawString(x, int(y + offsetBeta), newText, size, style, 0, SPRITE::BLEND_NORMAL, textBeta);
  93.         }
  94. }
  95. const array<int> powerupEventIDs = {
  96.         OBJECT::BLASTERPOWERUP,
  97.         OBJECT::BOUNCERPOWERUP,
  98.         OBJECT::ICEPOWERUP,
  99.         OBJECT::SEEKERPOWERUP,
  100.         OBJECT::RFPOWERUP,
  101.         OBJECT::TOASTERPOWERUP,
  102.         OBJECT::TNTPOWERUP,
  103.         OBJECT::GUN8POWERUP,
  104.         OBJECT::GUN9POWERUP,
  105. };
  106. bool powerupsEnabled = false;
  107. int powerupSpawnTimesAtPrevTick = -3;
  108. se::DefaultWeaponHook weaponHook;
  109. array<Point> oneWays;
  110. array<bool> specialMove(jjLocalPlayerCount);
  111. array<int> fastSpringSpeeds(jjLocalPlayerCount);
  112. array<int> flyCarrotTime(jjLocalPlayerCount);
  113. array<Timer> flyCarrotTimers(jjLocalPlayerCount);
  114. void prepareOneWays() {
  115.         for (int i = 0; i < jjLayerHeight[4]; i++) {
  116.                 for (int j = 0; j < jjLayerWidth[4]; j++) {
  117.                         if (jjEventGet(j, i) == AREA::ONEWAY)
  118.                                 oneWays.insertLast(Point(j, i));
  119.                 }
  120.         }
  121. }
  122. void enforceOneWays(jjPLAYER@ player) {
  123.         bool previousSpecialMove = specialMove[player.localPlayerID];
  124.         bool currentSpecialMove = player.specialMove != 0 && jjCharacters[player.charCurr].groundJump != GROUND::JAZZ;
  125.         if (currentSpecialMove ^^ previousSpecialMove) {
  126.                 for (uint i = 0; i < oneWays.length(); i++) {
  127.                         const Point@ tile = oneWays[i];
  128.                         jjEventSet(tile.x, tile.y, currentSpecialMove ? 0 : AREA::ONEWAY);
  129.                 }
  130.                 specialMove[player.localPlayerID] = currentSpecialMove;
  131.         }
  132. }
  133. void handleFastSpringSpeeds(jjPLAYER@ player) {
  134.         if (player.ySpeed < -32.f) {
  135.                 fastSpringSpeeds[player.localPlayerID] = int(ceil((player.ySpeed + 32.f) / -0.125f));
  136.         } else if (fastSpringSpeeds[player.localPlayerID] != 0) {
  137.                 if (player.ySpeed < -31.f) {
  138.                         fastSpringSpeeds[player.localPlayerID]--;
  139.                         player.ySpeed = -32.f;
  140.                 } else {
  141.                         fastSpringSpeeds[player.localPlayerID] = 0;
  142.                 }
  143.         }
  144. }
  145. void handleFlight(jjPLAYER@ player) {
  146.         Timer@ timer = flyCarrotTimers[player.localPlayerID];
  147.         if (flyCarrotTime[player.localPlayerID] > 0) {
  148.                 if (player.fly == FLIGHT::FLYCARROT) {
  149.                         flyCarrotTime[player.localPlayerID]--;
  150.                         if (flyCarrotTime[player.localPlayerID] == 0)
  151.                                 player.fly = FLIGHT::NONE;
  152.                         timer.setTime((flyCarrotTime[player.localPlayerID] + 69) / 70, flyCarrotTime[player.localPlayerID] < 250);
  153.                 } else {
  154.                         flyCarrotTime[player.localPlayerID] = 0;
  155.                 }
  156.         }
  157.         timer.setVisible(flyCarrotTime[player.localPlayerID] > 0);
  158.         timer.process();
  159. }
  160. void moveGenerators() {
  161.         array<Point> positions;
  162.         for (int i = 1; i < jjObjectCount; i++) {
  163.                 jjOBJ@ obj = jjObjects[i];
  164.                 if (obj.isActive) {
  165.                         Point position(int(obj.xPos) >>> 5, int(obj.yPos) >>> 5);
  166.                         int tile = jjTileGet(2, position.x, position.y);
  167.                         if (tile != 0) {
  168.                                 obj.xPos += ((tile + 2) % 9 - 1 << 5) / 3.f;
  169.                                 obj.yPos += ((tile + 2) / 9 - 3 << 5) / 3.f;
  170.                                 positions.insertLast(position);
  171.                         }
  172.                 }
  173.         }
  174.         for (int i = positions.length(); i-- != 0;) {
  175.                 const Point@ position = positions[i];
  176.                 jjTileSet(2, position.x, position.y, 0);
  177.         }
  178.         jjLayerHasTiles[2] = false;
  179. }
  180. void detectPowerupsEnabled() {
  181.         if (jjIsServer) {
  182.                 int powerupSpawnTimes = -1;
  183.                 for (int i = 1; i < jjObjectCount; i++) {
  184.                         const jjOBJ@ obj = jjObjects[i];
  185.                         if (obj.eventID == OBJECT::GENERATOR && powerupEventIDs.find(obj.var[3]) >= 0) {
  186.                                 if (obj.var[0] > 0 && jjObjects[obj.var[0]].isActive && jjObjects[obj.var[0]].creatorID == uint(i)) {
  187.                                         powerupSpawnTimes = -2;
  188.                                         break;
  189.                                 } else if (powerupSpawnTimes == -1) {
  190.                                         powerupSpawnTimes = obj.var[1];
  191.                                 } else if (obj.var[1] != powerupSpawnTimes) {
  192.                                         powerupSpawnTimes = -2;
  193.                                         break;
  194.                                 }
  195.                         }
  196.                 }
  197.                 bool newPowerupsEnabled = powerupSpawnTimesAtPrevTick == -3 ? powerupsEnabled : powerupSpawnTimes == -2 || powerupSpawnTimes != powerupSpawnTimesAtPrevTick;
  198.                 powerupSpawnTimesAtPrevTick = powerupSpawnTimes;
  199.                 if (newPowerupsEnabled != powerupsEnabled) {
  200.                         powerupsEnabled = newPowerupsEnabled;
  201.                         jjSTREAM packet;
  202.                         packet.push(powerupsEnabled);
  203.                         jjSendPacket(packet);
  204.                 }
  205.         }
  206. }
  207. void grantPoints(jjPLAYER@ player, jjOBJ@ obj) {
  208.         if (obj.points > 0 && (jjGameMode == GAME::SP || jjGameMode == GAME::COOP)) {
  209.                 player.score += obj.points;
  210.                 jjPARTICLE@ part = jjAddParticle(PARTICLE::STRING);
  211.                 if (part !is null) {
  212.                         part.xPos = obj.xPos;
  213.                         part.yPos = obj.yPos;
  214.                         part.xSpeed = -(0x8000 + (jjRandom() & 0x3FFF)) / float(0x10000);
  215.                         part.ySpeed = -(0x10000 + (jjRandom() & 0x7FFF)) / float(0x10000);
  216.                         part.string.text = formatInt(obj.points);
  217.                 }
  218.                 obj.points = 0;
  219.         }
  220. }
  221. float getPickupY(const jjOBJ@ obj) {
  222.         bool floating = obj.state == STATE::FLOAT || obj.behavior != BEHAVIOR::PICKUP;
  223.         int arg = (((obj.objectID << 3) + jjGameTicks) << (floating && obj.yPos > jjWaterLevel ? 1 : 4)) + (floating ? int(obj.xPos) << 4 : 0);
  224.         return obj.yPos + jjSin(arg) * 4.f;
  225. }
  226. void turnPickupIntoFlyCarrot(jjOBJ@ obj, int time) {
  227.         const jjOBJ@ flyCarrot = jjObjectPresets[OBJECT::FLYCARROT];
  228.         obj.eventID = OBJECT::FLYCARROT;
  229.         obj.counter = time;
  230.         obj.curAnim = flyCarrot.curAnim;
  231.         obj.curFrame = flyCarrot.curFrame;
  232.         obj.points = flyCarrot.points;
  233.         obj.scriptedCollisions = true;
  234. }
  235. void drawFlyCarrotPickupTimer(const jjOBJ@ obj, int alpha = 255, int layer = 4) {
  236.         jjTEXTAPPEARANCE style;
  237.         style.align = STRING::CENTER;
  238.         jjDrawString(obj.xPos - 3.f, obj.yPos + 22.f, formatInt(obj.counter / 70), STRING::SMALL, style, 0, SPRITE::BLEND_LUMINANCE, alpha, layer);
  239. }
  240. bool onDrawAmmo(jjPLAYER@ player, jjCANVAS@ canvas) {
  241.         flyCarrotTimers[player.localPlayerID].draw(canvas, jjSubscreenWidth + 32, jjSubscreenHeight / 2, jjSubscreenWidth - 64, jjSubscreenHeight / 2);
  242.         return weaponHook.drawAmmo(player, canvas);
  243. }
  244. void onLevelBegin() {
  245.         jjWeapons[WEAPON::GUN8].allowedPowerup = true;
  246.         moveGenerators();
  247. }
  248. void onLevelLoad() {
  249.         if (!jjIsServer)
  250.                 jjSendPacket(jjSTREAM());
  251.         jjUseLayer8Speeds = true;
  252.         prepareOneWays();
  253.         jjObjectPresets[OBJECT::BLUESPRING].ySpeed = -35.f;
  254.         turnPickupIntoFlyCarrot(jjObjectPresets[OBJECT::EXTRATIME], 490);
  255.         turnPickupIntoFlyCarrot(jjObjectPresets[OBJECT::EXTRALIFE], 700);
  256.         se::roller.loadAnims(jjAnimSets[ANIM::CUSTOM[0]]);
  257.         se::roller.loadSamples(array<SOUND::Sample> = {SOUND::INTRO_BLOW});
  258.         se::roller.setAsWeapon(4, weaponHook);
  259. }
  260. void onMain() {
  261.         for (int i = 6; i <= 7; i++) {
  262.                 jjLayerXOffset[i] = (jjLayerXOffset[i] + (i == 6 ? -1.f : 1.f)) % (jjLayerWidth[i] * 32);
  263.         }
  264.         for (int i = 1; i < jjObjectCount; i++) {
  265.                 const jjOBJ@ obj = jjObjects[i];
  266.                 if (obj.playerHandling == HANDLING::PICKUP) {
  267.                         int x = int(obj.xPos);
  268.                         int y = int(obj.yPos);
  269.                         int tile = jjTileGet(3, x >>> 5, y >>> 5);
  270.                         bool isFlyCarrot = obj.eventID == OBJECT::FLYCARROT;
  271.                         if (isFlyCarrot)
  272.                                 drawFlyCarrotPickupTimer(obj);
  273.                         if (tile != 0) {
  274.                                 jjPIXELMAP image(tile);
  275.                                 if (image[x & 31, y & 31] != 0) {
  276.                                         int alpha = jjAnimFrames[obj.curFrame].transparent ? 32 : 64;
  277.                                         jjDrawSpriteFromCurFrame(obj.xPos, getPickupY(obj), obj.curFrame, obj.direction, SPRITE::BLEND_NORMAL, alpha, 3);
  278.                                         if (isFlyCarrot)
  279.                                                 drawFlyCarrotPickupTimer(obj, alpha, 3);
  280.                                 }
  281.                         }
  282.                 }
  283.         }
  284.         detectPowerupsEnabled();
  285.         weaponHook.processMain();
  286. }
  287. void onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int) {
  288.         if (bullet is null && obj.eventID == OBJECT::FLYCARROT) {
  289.                 player.fly = FLIGHT::FLYCARROT;
  290.                 player.doubleJumpCount = 0;
  291.                 if (player.isLocal && flyCarrotTime[player.localPlayerID] < obj.counter)
  292.                         flyCarrotTime[player.localPlayerID] = obj.counter;
  293.                 grantPoints(player, obj);
  294.                 obj.frameID = 0;
  295.                 obj.behavior = BEHAVIOR::EXPLOSION2;
  296.                 jjSample(obj.xPos, obj.yPos, SOUND::COMMON_PICKUP1);
  297.         }
  298. }
  299. void onPlayer(jjPLAYER@ player) {
  300.         if (jjColorDepth == 8) {
  301.                 jjEnforceLighting = LIGHT::COMPLETE;
  302.                 player.lighting = 110;
  303.         } else {
  304.                 jjEnforceLighting = LIGHT::OPTIONAL;
  305.                 player.lighting = 100;
  306.         }
  307.         if (player.ammo[WEAPON::GUN8] == 0 || !player.powerup[WEAPON::GUN8])
  308.                 player.powerup[WEAPON::GUN8] = powerupsEnabled;
  309.         enforceOneWays(player);
  310.         handleFastSpringSpeeds(player);
  311.         handleFlight(player);
  312.         weaponHook.processPlayer(player);
  313. }
  314. void onPlayerInput(jjPLAYER@ player) {
  315.         weaponHook.processPlayerInput(player);
  316. }
  317. void onReceive(jjSTREAM &in packet, int clientID) {
  318.         if (jjIsServer) {
  319.                 jjSTREAM response;
  320.                 response.push(powerupsEnabled);
  321.                 jjSendPacket(response, clientID);
  322.         } else {
  323.                 packet.pop(powerupsEnabled);
  324.         }
  325. }
  326.