#include "MLLE-Include-1.4.asc"
const bool MLLESetupSuccessful = MLLE::Setup();
#pragma require "ab21btl21.j2l"
#pragma require "Aztec2.j2t"
#pragma require "Heaven.j2t"
/*******************************
A 2019 Mystic Legends Release!
http://www.mysticlegends.org
/******************************/
#pragma require "SEenergyblast.asc"
#include "SEenergyblast.asc"
#pragma require "Nail.j2a"
#pragma require "ROCKET1I.wav"
#pragma require "SPIKE2.wav"
se::DefaultWeaponHook weaponHook;
funcdef jjPALCOLOR ColorFunction(jjPALCOLOR);
const array<int> FoodAnims = {26, 89, 1, 71, 11, 74, 73, 12, 2, 48, 16, 21, 50, 13};
array<jjLAYER@> ClonedRainLayers;
void onLevelLoad() {
se::energyBlast.loadAnims(jjAnimSets[ANIM::CUSTOM[0]]);
se::energyBlast.loadSamples(array<SOUND::Sample> = {SOUND::INTRO_BLOW});
se::energyBlast.setAsWeapon(8, weaponHook);
NailgunPrepStuff(); //goto 308
jjWeapons[WEAPON::RF].comesFromGunCrates = false;
jjObjectPresets[OBJECT::BOUNCERPOWERUP].direction = SPRITE::FLIPH;
jjObjectPresets[OBJECT::RFPOWERUP].direction = SPRITE::FLIPNONE;
jjObjectPresets[OBJECT::SWINGINGVINE].lightType = LIGHT::BRIGHT;
jjObjectPresets[OBJECT::SWINGINGVINE].light = 8;
jjObjectPresets[OBJECT::BRIDGE].behavior = MyBridge;
jjLayers[4].generateSettableTileArea();
for (uint i = 0; i < FoodAnims.length; i++) {
jjANIMFRAME@ frame = jjAnimFrames[jjAnimations[jjAnimSets[ANIM::PICKUPS].firstAnim + FoodAnims[i]].firstFrame];
jjPIXELMAP(32+i*32, 0, 32, 32, 4).save(frame);
frame.hotSpotX = -frame.width/2;
frame.hotSpotY = -frame.height + 14;
jjTileSet(4, 1+i, 0, 0);
}
jjANIMFRAME@ grapeFrame = jjAnimFrames[jjAnimations[jjAnimSets[ANIM::PICKUPS].firstAnim + 38].firstFrame];
jjPIXELMAP(32, 32, 32, 64, 4).save(grapeFrame);
grapeFrame.hotSpotX = -grapeFrame.width/2;
grapeFrame.hotSpotY = -grapeFrame.height;
jjTileSet(4, 1, 1, 0);
jjTileSet(4, 1, 2, 0);
//sorry, I tried to do this in a loop but it didn't work
jjObjectPresets[OBJECT::CARROT].lightType =
jjObjectPresets[OBJECT::FASTFIRE].lightType =
jjObjectPresets[OBJECT::BOUNCERAMMO3].lightType =
jjObjectPresets[OBJECT::ICEAMMO3].lightType =
jjObjectPresets[OBJECT::SEEKERAMMO3].lightType =
jjObjectPresets[OBJECT::TOASTERAMMO3].lightType =
jjObjectPresets[OBJECT::GUN8AMMO3].lightType =
jjObjectPresets[OBJECT::GUN9AMMO3].lightType =
jjObjectPresets[OBJECT::SILVERCOIN].lightType =
jjObjectPresets[OBJECT::SHARD].lightType = LIGHT::POINT;
//jjObjectPresets[OBJECT::SOFTDRINK].determineCurAnim(ANIM::PLUS_COMMON, 7);
for (int i = 1; i < 255; i++) {
if (jjObjectPresets[i].playerHandling == HANDLING::PICKUP) {
jjObjectPresets[i].behavior = CannotBeShotDown(jjObjectPresets[i].behavior);
}
}
jjANIMFRAME@ bridgeFrame = jjAnimFrames[jjAnimations[jjAnimSets[ANIM::BRIDGE].firstAnim + 5].firstFrame];
jjPIXELMAP(33, 96, 16, 16, 4).save(bridgeFrame);
bridgeFrame.hotSpotX = -bridgeFrame.width/2;
bridgeFrame.hotSpotY = -bridgeFrame.height + 8;
jjTileSet(4, 1, 3, 0);
jjANIMFRAME@ woodBridgeFrame = jjAnimFrames[jjAnimations[jjAnimSets[ANIM::BRIDGE].firstAnim + 6].firstFrame];
jjPIXELMAP(42, 148, 14, 21, 4).save(woodBridgeFrame);
woodBridgeFrame.hotSpotX = -woodBridgeFrame.width/2;
woodBridgeFrame.hotSpotY = -woodBridgeFrame.height + 16;
jjTileSet(4, 1, 4, 0);
jjTileSet(4, 1, 5, 0);
/*jjPIXELMAP rain(1,1);
jjANIMATION@ anim = jjAnimations[jjAnimSets[ANIM::COMMON].firstAnim + 2];
for (uint frameID = 0; frameID < anim.frameCount; ++frameID) {
jjANIMFRAME@ blank = jjAnimFrames[anim.firstFrame + frameID];
rain.save(blank);
blank.hotSpotX = -blank.width/2;
blank.hotSpotY = -blank.height;
}*/
ClonedRainLayers = jjLayersFromLevel("mlfingers.j2l", array<uint> = {1, 1, 1, 1, 1, 1});
for (uint i = 0; i < ClonedRainLayers.length; i++) {
ClonedRainLayers[i].spriteMode = SPRITE::BLEND_NORMAL;
ClonedRainLayers[i].spriteParam = 24;
ClonedRainLayers[i].xOffset = ClonedRainLayers[i].yOffset = jjRandom()%112;
}
array<jjLAYER@> ClonedBigClouds = jjLayersFromLevel("mlfingers.j2l", array<uint> = {6, 6});
array<jjLAYER@> ClonedMountains = jjLayersFromLevel("mlfingers.j2l", array<uint> = {7});
ClonedBigClouds[0].xOffset = 112;
ClonedBigClouds[0].yOffset = 96;
ClonedBigClouds[0].xSpeed = ClonedBigClouds[0].ySpeed = 0.325f;
//ClonedBigClouds[0].spriteMode = SPRITE::TRANSLUCENTTILE;
ClonedBigClouds[1].xOffset = 32;
ClonedBigClouds[1].yOffset = -4000;
ClonedBigClouds[1].xSpeed = ClonedBigClouds[1].ySpeed = 1.25f;
//ClonedBigClouds[1].spriteMode = SPRITE::TRANSLUCENTTILE;
ClonedMountains[0].xSpeed = ClonedMountains[0].ySpeed = 0.15f;
ClonedMountains[0].xOffset = 1500;
ClonedMountains[0].yOffset = 16;
jjLayerOrderSet(array<jjLAYER@> = {
ClonedBigClouds[1],
jjLayers[1],
ClonedRainLayers[0],
ClonedRainLayers[1],
ClonedRainLayers[2],
ClonedRainLayers[3],
ClonedRainLayers[4],
ClonedRainLayers[5],
jjLayers[3],
jjLayers[4],
jjLayers[5],
jjLayers[2],
jjLayers[6],
ClonedBigClouds[0],
jjLayers[7],
ClonedMountains[0],
jjLayers[8]
}
);
jjUseLayer8Speeds = true;
jjCharacters[CHAR::BIRD].canRun = true;
//jjSnowingType = SNOWING::RAIN;
}
const float TOPS00 = 3*32;
const float TOPS01 = 9*32;
const float TOPS02 = 15*32;
const float FLOOR0 = 20*32;
const float FLOOR1 = 36*32;
const float FLOOR2 = 53*32;
const float FLOOR3 = 70*32;
const float FLOOR4 = 81*32;
const float FLOOR5 = 97*32;
const int LEVELHEIGHT = 3840;
const array<int> ColumnsToLock = {7, 33, 42, 69, 76, 102};
const int SIXTYSECONDS = 45*70;
const int GODHEAD = 777*70;
void onPlayer(jjPLAYER@ play) {
weaponHook.processPlayer(play);
for (uint i = 0; i < ClonedRainLayers.length; i++) {
if (play.yPos < 40*32) {
jjLayers[1].hasTiles = ClonedRainLayers[i].hasTiles = false;
}
else {
jjLayers[1].hasTiles = ClonedRainLayers[i].hasTiles = true;
jjLayers[1].spriteParam = ClonedRainLayers[i].spriteParam = int(30 * (play.yPos / LEVELHEIGHT));
}
}
if (play.shieldType == SHIELD::LASER) {
for (int x = 0; x < 6; x++) {
for (int y = 30; y < 118; y++) {
jjTileSet(4, ColumnsToLock[x], y, 1981);
}
}
play.shieldTime = GODHEAD;
play.currWeapon = WEAPON::BLASTER;
}
else {
for (int x = 0; x < 6; x++) {
for (int y = 30; y < 118; y++) {
jjTileSet(4, ColumnsToLock[x], y, 0);
}
}
play.shieldTime = 0;
}
if (!play.isSpectating) {
if (play.yPos > FLOOR5) play.lighting = 72;
else if (play.yPos > FLOOR4 && play.yPos < FLOOR5) play.lighting = 75;
else if (play.yPos > FLOOR3 && play.yPos < FLOOR4) play.lighting = 79;
else if (play.yPos > FLOOR2 && play.yPos < FLOOR3) play.lighting = 82;
else if (play.yPos > FLOOR1 && play.yPos < FLOOR2) play.lighting = 89;
else if (play.yPos > FLOOR0 && play.yPos < FLOOR1) play.lighting = 100;
else if (play.yPos > TOPS02 && play.yPos < FLOOR0) play.lighting = 110;
else if (play.yPos > TOPS01 && play.yPos < TOPS02) play.lighting = 118;
else if (play.yPos > TOPS00 && play.yPos < TOPS01) play.lighting = 124;
else if (play.yPos < TOPS00) play.lighting = 140;
}
if (play.charCurr == CHAR::LORI) {
jjAlert("Sorry, not this time!");
play.morphTo(CHAR::JAZZ);
}
/*if (play.charCurr == CHAR::BIRD2) {
if (play.xSpeed > 0) {
play.xPos += 0.5f;
}
else if (play.xSpeed < 0) {
play.xPos -= 0.5f;
}
if (play.ySpeed > 0) {
play.yPos += 0.75f;
}
else if (play.ySpeed < 0) {
play.yPos -= 0.75f;
}
}*/
if (play.timerState == TIMER::STARTED && play.timerTime <= 3*70 && play.timerTime > 0 && play.timerTime % 70 == 0) {
jjSamplePriority(SOUND::COMMON_NOCOIN);
}
play.noFire = play.invisibility;
}
bool onDrawPlayerTimer(jjPLAYER@ play, jjCANVAS@ canvas) {
canvas.drawString(
jjSubscreenWidth - 75,
jjSubscreenHeight - 284,
"" + (play.timerTime > 0? (play.timerTime + 70) / 70 : 0),
STRING::LARGE,
STRING::PALSHIFT,
play.timerTime > 3*70?
0 :
jjGameTicks % 28 > 14?
216 :
232
);
canvas.drawSprite(
jjSubscreenWidth - 92,
jjSubscreenHeight - 280,
ANIM::BIRD,
6,
jjGameTicks / 6 % 8,
0,
SPRITE::PLAYER
);
return true;
}
void onPlayerTimerEnd(jjPLAYER@ play) {
play.morphTo(play.charOrig);
}
void onFunction0(jjPLAYER@ play) {
play.showText("@@§0#You found Pandora's Box!");
}
void onFunction1(jjPLAYER@ play) {
play.showText("@@§0Pandora's Box is only accessed from below...");
}
void onFunction10(jjPLAYER@ play) {
if (play.noclipMode && play.charCurr != CHAR::BIRD2) {
play.noclipMode = false;
play.morphTo(CHAR::BIRD2);
jjSample(play.xPos, play.yPos, SOUND::COMMON_BUBBLGN1);
play.timerStart(SIXTYSECONDS);
play.showText("@@§0#Dare to fly where eagles soar!");
}
}
void onFunction100(jjPLAYER@ play) {
if (play.charCurr == CHAR::BIRD2) {
play.timerTime = 0;
play.morphTo(play.charOrig);
}
jjSample(play.xPos, play.yPos, SOUND::INTRO_BOEM2);
jjSample(play.xPos, play.yPos, SOUND::INTRO_IFEEL);
//jjSamplePriority(SOUND::DEVILDEVAN_WHISTLEDESCENDING2);
play.ballTime = 70;
play.xSpeed = 0;
play.ySpeed = 10;
play.blink = 99999;
play.shieldType = SHIELD::LASER;
play.shieldTime = GODHEAD;
}
class CannotBeShotDown : jjBEHAVIORINTERFACE {
jjBEHAVIOR originalBehavior;
CannotBeShotDown(jjBEHAVIOR behavior) {
originalBehavior = behavior;
}
void onBehave(jjOBJ@ obj) override {
obj.behave(originalBehavior);
if (obj.state == STATE::FLOATFALL)
obj.state = STATE::FLOAT;
if (obj.eventID == OBJECT::FULLENERGY)
obj.xPos = obj.xOrg - 16;
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
obj.behavior = originalBehavior;
if (bullet is null)
player.objectHit(obj, force, obj.playerHandling);
else
bullet.objectHit(obj, obj.playerHandling);
obj.behavior = CannotBeShotDown(obj.behavior);
return true;
}
}
void onMain() {
weaponHook.processMain();
}
void onReceive(jjSTREAM &in packet, int clientID) {
weaponHook.processPacket(packet, clientID);
}
bool onDrawAmmo(jjPLAYER@ play, jjCANVAS@ canvas) {
return weaponHook.drawAmmo(play, canvas);
}
void onPlayerInput(jjPLAYER@ play) {
weaponHook.processPlayerInput(play);
if (play.shieldType == SHIELD::LASER) {
play.keyDown = play.keyJump = false;
if (play.ballTime > 0) {
play.keyLeft = play.keyRight = false;
}
}
}
//nailgun stuff begins here
bool gameIsActive() {
return jjGameState == GAME::STARTED || jjGameState == GAME::OVERTIME;
}
void NailgunPrepStuff() {
jjAnimSets[ANIM::CUSTOM[25]].load(0, "Nail.j2a");
jjAnimations[jjAnimSets[ANIM::AMMO] + 49] = jjAnimations[jjAnimSets[ANIM::CUSTOM[25]] + 4];
jjAnimations[jjAnimSets[ANIM::AMMO] + 48] = jjAnimations[jjAnimSets[ANIM::CUSTOM[25]] + 5];
//jjSampleLoad(SOUND::P2_CRUNCH, "f_ar3.wav");
jjSampleLoad(SOUND::P2_CRUNCH, "ROCKET1I.wav");
jjSampleLoad(SOUND::P2_FART, "SPIKE2.wav");
jjObjectPresets[OBJECT::RFBULLET].behavior = jjObjectPresets[OBJECT::RFBULLETPU].behavior = Nailgun();
jjObjectPresets[OBJECT::RFBULLET].var[6] = 16;
jjObjectPresets[OBJECT::RFBULLET].counterEnd = 60;
jjObjectPresets[OBJECT::RFBULLET].killAnim = jjObjectPresets[OBJECT::BLASTERBULLET].killAnim;
jjObjectPresets[OBJECT::RFBULLET].special = jjObjectPresets[OBJECT::RFBULLET].determineCurAnim(ANIM::CUSTOM[25], 0);
jjObjectPresets[OBJECT::RFBULLETPU].var[6] = 8 + 16;
jjObjectPresets[OBJECT::RFBULLETPU].counterEnd = 55;
jjObjectPresets[OBJECT::RFBULLETPU].killAnim = jjObjectPresets[OBJECT::BLASTERBULLET].killAnim;
jjObjectPresets[OBJECT::RFBULLETPU].special = jjObjectPresets[OBJECT::RFBULLETPU].determineCurAnim(ANIM::CUSTOM[25], 1);
jjObjectPresets[OBJECT::RFBULLET].lightType = jjObjectPresets[OBJECT::RFBULLETPU].lightType = LIGHT::POINT;
jjObjectPresets[OBJECT::RFAMMO3].lightType = LIGHT::POINT;
jjObjectPresets[OBJECT::RFAMMO15].determineCurAnim(ANIM::CUSTOM[25], 2);
jjObjectPresets[OBJECT::RFAMMO15].determineCurFrame();
jjObjectPresets[OBJECT::RFPOWERUP].determineCurAnim(ANIM::CUSTOM[25], 3);
jjObjectPresets[OBJECT::RFPOWERUP].determineCurFrame();
jjWeapons[WEAPON::RF].spread = SPREAD::NORMAL;
jjWeapons[WEAPON::RF].style = WEAPON::NORMAL;
jjWeapons[WEAPON::RF].defaultSample = false;
jjANIMATION@ anim = jjAnimations[jjAnimSets[ANIM::AMMO] + 71];
for (uint i = 0; i < anim.frameCount; ++i) {
jjANIMFRAME@ frame = jjAnimFrames[anim + i];
jjPIXELMAP sprite(frame);
for (uint x = 0; x < sprite.width; ++x)
for (uint y = 0; y < sprite.height; ++y)
if (sprite[x,y] != 0) sprite[x,y] = 0;
sprite.save(frame);
}
}
class Nailgun : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.behave(obj.state == STATE::EXPLODE? BEHAVIOR::BULLET : BEHAVIOR::RFBULLET, obj.state == STATE::EXPLODE? true:false);
jjPLAYER@ creator = jjPlayers[obj.creatorID];
obj.var[0] = int(atan2(-obj.ySpeed, obj.xSpeed) * (512.f * 0.318309886142228f));
obj.xAcc = (obj.eventID == OBJECT::RFBULLETPU? 0.4:0.35) * obj.direction;
if (obj.ySpeed < 0 && obj.direction == 0 && obj.xSpeed == 0) obj.yAcc = -0.5;
if (obj.state != STATE::EXPLODE) {
if (obj.counter == 1 && creator.isLocal) {
//jjSample(creator.xPos, creator.yPos, SOUND::P2_CRUNCH, 48, obj.eventID == OBJECT::RFBULLETPU? 19000:17500);
jjSample(creator.xPos, creator.yPos, obj.eventID == OBJECT::RFBULLETPU? SOUND::P2_FART : SOUND::P2_CRUNCH, 48);
obj.var[2] = 0;
obj.playerHandling = HANDLING::PLAYERBULLET;
}
jjDrawRotatedSprite(obj.xPos, obj.yPos, ANIM::CUSTOM[25], obj.eventID == OBJECT::RFBULLETPU? 1:0, 0, obj.var[0], 1, 1, SPRITE::NORMAL);
float dx = jjLocalPlayers[0].xPos - obj.xPos, dy = jjLocalPlayers[0].yPos - obj.yPos;
if ((dx * dx + dy * dy < 64 * 24) && !creator.isLocal && jjLocalPlayers[0].blink == 0 && (jjLocalPlayers[0].team != creator.team || jjFriendlyFire || jjGameMode != GAME::CTF) && gameIsActive()) {
jjLocalPlayers[0].xPos = obj.xPos - (24 * obj.direction);
jjLocalPlayers[0].ySpeed = obj.ySpeed;
}
if (jjMaskedPixel(int(obj.xPos + obj.xSpeed + obj.var[7] / 65536.f), int(obj.yPos))) {
obj.xSpeed = 0;
obj.var[7] = 0;
obj.playerHandling = HANDLING::PARTICLE;
obj.bePlatform(obj.xPos, obj.yPos, 32, 8);
if (obj.var[2] == 0) {
jjSample(obj.xPos, obj.yPos, SOUND::COMMON_METALHIT, 0, 0);
obj.counter = 1;
if (obj.eventID == OBJECT::RFBULLETPU) obj.counterEnd = 90;
obj.var[2] = 1;
}
}
else if (jjMaskedPixel(int(obj.xPos), int(obj.yPos + obj.ySpeed))) {
obj.ySpeed = 0;
obj.playerHandling = HANDLING::PARTICLE;
if (obj.var[2] == 0) {
jjSample(obj.xPos, obj.yPos, SOUND::COMMON_METALHIT, 0, 0);
obj.counter = 1;
if (obj.eventID == OBJECT::RFBULLETPU) obj.counterEnd = 90;
obj.var[2] = 1;
}
}
} else {
obj.clearPlatform();
obj.var[2] = 0;
obj.counterEnd = obj.eventID == OBJECT::RFBULLETPU? 55:60;
}
}
}
//violet's witchcraft bridges
enum BridgeVariables { PhysicalWidth, MaximumSagDistance, VisualWidth, FirstObjectIDOfPlatformForSplitscreenPlayers, Angle = FirstObjectIDOfPlatformForSplitscreenPlayers + 3 };
void MyBridge(jjOBJ@ obj) {
//first, check collision with bridge
if (obj.state==STATE::START) {
obj.state=STATE::STILL;
const uint xTile = uint(obj.xOrg) >> 5, yTile = uint(obj.yOrg) >> 5;
obj.var[BridgeVariables::PhysicalWidth] = 32 * jjParameterGet(xTile,yTile, 0,4);
obj.curAnim = jjAnimSets[ANIM::BRIDGE].firstAnim + (jjParameterGet(xTile,yTile, 4,3) % 7); //"Type" parameter... % 7 because there are only seven bridge types for some reason.
int toughness = jjParameterGet(xTile,yTile, 7,4);
if (toughness == 0) toughness = 4; //default toughness of 4, to avoid dividing by zero
obj.var[BridgeVariables::MaximumSagDistance] = obj.var[BridgeVariables::PhysicalWidth] / toughness;
//int heightInTiles = jjParameterGet(xTile,yTile, 11,-5);
int heightInTiles = jjParameterGet(xTile, yTile-1, 0, -8);
obj.var[BridgeVariables::Angle] = int(atan2(heightInTiles, obj.var[BridgeVariables::PhysicalWidth] / 32) * 162.974662f);
obj.xAcc = jjCos(obj.var[BridgeVariables::Angle]);
obj.yAcc = jjSin(obj.var[BridgeVariables::Angle]);
{ //determine how wide the bridge is, in drawn pixels (will always be >= how wide it is in mask pixels)
int frameID = 0;
int bridge_len = 0;
const int numberOfFramesUsedByAnimation = jjAnimations[obj.curAnim].frameCount;
const uint firstBridgeFrameID = jjAnimations[obj.curAnim].firstFrame;
while (true) {
if ((bridge_len += jjAnimFrames[firstBridgeFrameID + frameID].width) >= obj.var[BridgeVariables::PhysicalWidth])
break;
if (++frameID >= numberOfFramesUsedByAnimation)
frameID = 0;
}
obj.var[BridgeVariables::VisualWidth] = bridge_len;
}
obj.xOrg -= 16; //start at left edge of tile, not center
obj.yOrg -= 6; //worth noting that bridges are never deactivated, so we don't need to worry about where this gets moved to at all
for (int i = 1; i < jjLocalPlayerCount; ++i) { //this portion has no native JJ2 counterpart, because the API for platforms is still pretty limited
const int platformObjectID = jjAddObject(OBJECT::BRIDGE, 0,0, obj.objectID,CREATOR::OBJECT, BEHAVIOR::BEES);
jjOBJ@ platform = jjObjects[platformObjectID];
platform.deactivates = false;
platform.curFrame = jjAnimations[obj.curAnim].firstFrame;
obj.var[BridgeVariables::FirstObjectIDOfPlatformForSplitscreenPlayers - 1 + i] = platformObjectID;
}
}
obj.clearPlatform();
for (int i = 1; i < jjLocalPlayerCount; ++i)
jjObjects[obj.var[BridgeVariables::FirstObjectIDOfPlatformForSplitscreenPlayers - 1 + i]].clearPlatform();
array<int> pressXPosition;
array<jjPLAYER@> pressPlayer;
for (int playerID = 0; playerID < 32; ++playerID) {
jjPLAYER@ play = jjPlayers[playerID];
if (play.isActive && play.shieldType != SHIELD::LASER && jjObjects[play.platform].eventID != OBJECT::BURGER) { //all active players are valid, even if isLocal is false
const int tx = int(play.xPos-obj.xOrg);
const int ty = int(play.yPos-obj.yOrg - obj.yAcc / obj.xAcc * tx);
if ((tx >= 0) && (tx <= obj.var[BridgeVariables::PhysicalWidth]) && //player is within bridge area (horizontal)
(ty > -32) && (ty < obj.var[BridgeVariables::MaximumSagDistance]) && //(and vertical) //-32 was -24
(play.ySpeed > -1.f)) //not jumping, using a spring, etc.
{
pressXPosition.insertLast(tx);
pressPlayer.insertLast(play);
}
}
}
float max, amp, leftamp, rightamp;
int leftmostPressedX, rightmostPressedX;
if (pressPlayer.length != 0) {
if (pressPlayer.length > 1) {
leftmostPressedX=12312312;
rightmostPressedX=0;
uint t = 0;
do {
const int pressedX = pressXPosition[t];
if (pressedX < leftmostPressedX)
leftmostPressedX = pressedX;
if (pressedX > rightmostPressedX)
rightmostPressedX = pressedX;
} while (++t < pressPlayer.length);
leftamp = obj.var[BridgeVariables::MaximumSagDistance]*jjSin((512* leftmostPressedX)/obj.var[BridgeVariables::PhysicalWidth]);
rightamp = obj.var[BridgeVariables::MaximumSagDistance]*jjSin((512*rightmostPressedX)/obj.var[BridgeVariables::PhysicalWidth]);
}
uint t = 0;
uint numberOfLocalPlayersNeedingPlatforms = 0;
do {
const auto pressedPosition = pressXPosition[t];
if (pressPlayer.length == 1)
max = obj.var[BridgeVariables::MaximumSagDistance] * jjSin((512 * pressedPosition) / obj.var[BridgeVariables::PhysicalWidth]); //same formula as side amps above, but for single player bridges
else if ((pressedPosition>leftmostPressedX) && (pressedPosition<rightmostPressedX))
max = leftamp+(rightamp-leftamp)*(pressedPosition-leftmostPressedX)/(rightmostPressedX-leftmostPressedX);
else
max = obj.var[BridgeVariables::MaximumSagDistance]*jjSin((512 * pressedPosition)/obj.var[BridgeVariables::PhysicalWidth]);
jjPLAYER@ play = pressPlayer[t];
play.yPos = obj.yOrg + obj.yAcc / obj.xAcc * pressedPosition + max - 24;
if (play.isLocal) {
jjOBJ@ platform = (numberOfLocalPlayersNeedingPlatforms == 0) ? obj : jjObjects[obj.var[BridgeVariables::FirstObjectIDOfPlatformForSplitscreenPlayers - 1 + numberOfLocalPlayersNeedingPlatforms]];
platform.bePlatform(
platform.xPos = play.xPos,
platform.yPos = play.yPos + 24
);
//platform.draw();
if (play.buttstomp < 120)
play.buttstomp = 120;
numberOfLocalPlayersNeedingPlatforms += 1;
}
} while (++t < pressPlayer.length);
}
//draw
float bridge_len_x = 0, bridge_len_y = 0;
int frameID = 0;
const int numberOfFramesUsedByAnimation = jjAnimations[obj.curAnim].frameCount;
while (true) { //cooba - change specifically for mlfingers.j2l conditions
obj.curFrame = jjAnimations[obj.curAnim].firstFrame + frameID;
const jjANIMFRAME@ frame = jjAnimFrames[obj.curFrame];
float plankOffset = 0; //"straight bridge, or terugveren"
if (pressPlayer.length == 1) {
const auto pressedPosition = pressXPosition[0];
plankOffset = ((bridge_len_x<pressedPosition) ?
(max*jjSin(int(256*bridge_len_x)/pressedPosition)) : //left
(max*jjCos(int(256*(bridge_len_x-pressedPosition))/(obj.var[BridgeVariables::VisualWidth]-pressedPosition) ))
);
} else if (pressPlayer.length > 1) {
if (bridge_len_x < leftmostPressedX)
plankOffset = (leftamp*jjSin(int(256*bridge_len_x)/leftmostPressedX));
else if (bridge_len_x > rightmostPressedX)
plankOffset = (rightamp*jjCos(int(256*(bridge_len_x-rightmostPressedX))/(obj.var[BridgeVariables::VisualWidth]-rightmostPressedX) ));
else
plankOffset = leftamp+(rightamp-leftamp)*(bridge_len_x-leftmostPressedX)/(rightmostPressedX-leftmostPressedX);
}
jjDrawRotatedSpriteFromCurFrame(
obj.xOrg + bridge_len_x - frame.hotSpotX,
obj.yOrg + bridge_len_y + plankOffset,
obj.curFrame,
-obj.var[BridgeVariables::Angle],
1,
1,
jjLocalPlayers[0].shieldType == SHIELD::LASER? SPRITE::TRANSLUCENTPALSHIFT : SPRITE::NORMAL,
96
);
if (int(bridge_len_x += obj.xAcc * frame.width) >= obj.var[BridgeVariables::PhysicalWidth])
break;
bridge_len_y += obj.yAcc * frame.width;
if (++frameID >= numberOfFramesUsedByAnimation)
frameID = 0;
}
}