Downloads containing mlvoid.j2as

Downloads
Name Author Game Mode Rating
TSF with JJ2+ Only: Without Form and Void cooba Battle N/A Download file

File preview

const bool MLLESetupSuccessful = MLLE::Setup(array<MLLEWeaponApply@> = {null, null, NapsWeapons::AntiGravityBouncer(), null, null, null, null, null, null}); ///@MLLE-Generated
#include "MLLE-Include-1.8w.asc" ///@MLLE-Generated
#pragma require "mlvoid-MLLE-Data-1.j2l" ///@MLLE-Generated
#pragma require "mlvoid.j2l" ///@MLLE-Generated
#include "AntiGravBouncers.asc" ///@MLLE-Generated
#pragma require "AntiGravBouncers.asc" ///@MLLE-Generated
///@SaveAndRunArgs -server -battle ///@MLLE-Generated

/*******************************
A 2026 Mystic Legends Release!
http://www.mysticlegends.org
/******************************/

jjANIMSET@ animSet = jjAnimSets[ANIM::CUSTOM[0]];
jjLAYER effectLayer(jjLayers[5]);
float effectRadius = 208.f; //cooba: originally 128

void onMain() {
	jjLayerXOffset[6] = jjSin(jjGameTicks*2)*120;
	jjLayers[8].hasTiles = jjLowDetail;
}

const int THIRTYSECONDS = 7*70;
CHAR::Char OldCharacter;

class Invertibility : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::PICKUP, false);
		if (obj.state == STATE::FLOATFALL) obj.state = STATE::FLOAT;
	}
	void onDraw(jjOBJ@ obj) {
		int frame = obj.objectID * 8 + jjGameTicks;
		frame = (frame + int(obj.xPos) + int(obj.yPos) * 256)*16;
		
		jjDrawRotatedSpriteFromCurFrame(obj.xPos, (obj.yPos + jjSin(frame)*4) - 2, obj.curFrame, 512);
	}
	bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
		if (player.timerTime > 0) {
			player.timerTime += THIRTYSECONDS;
			jjSample(player.xPos, player.yPos, SOUND::COMMON_PICKUP1, 63, 17500);
		}
		else {
			player.timerStart(THIRTYSECONDS);
			jjSamplePriority(SOUND::COMMON_HOLYFLUT);
			jjSamplePriority(SOUND::COMMON_BUBBLGN1);
			
			player.morph();
			player.morphTo(OldCharacter, false);
		}
	
		player.antiGrav = true;
		jjTileSet(4, 79, 44, 0);
		jjTileSet(4, 80, 44, 0);
		jjTileSet(4, 81, 44, 0);
		
		obj.frameID = 0;
		obj.behavior = BEHAVIOR::EXPLOSION2;
		return true;
	}
}

void CustomGemRing(jjOBJ@ obj) {
	if (obj.state == STATE::START) {
		
		obj.animSpeed = 5;
		
		obj.counterEnd = uint8(jjParameterGet(int(obj.xOrg/32), int(obj.yOrg/32) + 1, 0, 8));
		obj.points = uint8(jjParameterGet(int(obj.xOrg/32), int(obj.yOrg/32) + 1, 8, 8));
		if (obj.points == 0) obj.points = 7;
		
		obj.curAnim = jjObjectPresets[obj.counterEnd].curAnim;
		
		obj.state = STATE::SLEEP;
	}
	obj.behave(BEHAVIOR::GEMRING);
}

void recolorAnimation(const array<uint8>& recolor, jjANIMATION@ anim) {
    for (uint i = 0; i < anim.frameCount; ++i) {
        jjANIMFRAME@ frame = jjAnimFrames[anim + i];
        jjPIXELMAP(frame).recolor(recolor).save(frame);
    }
}

void onPlayer(jjPLAYER@ play) {
	if (play.noclipMode) play.fly = FLIGHT::NONE;						//tubes disable fly c
	
	if (play.fly == FLIGHT::FLYCARROT && play.timerTime > 0) play.timerTime = 1;
	
	OldCharacter = play.charCurr;	
	if (play.timerState == TIMER::STARTED && play.timerTime <= 3*70 && play.timerTime > 0 && play.timerTime % 70 == 0) {
		jjSamplePriority(SOUND::COMMON_NOCOIN);
	}
	
	if (play.yPos >= 0) {
		int skill = jjParameterGet(uint16(play.xPos/32), uint16(play.yPos/32), -4, 2);	
		if (skill == 3 && !play.antiGrav) {
			play.ySpeed -= 8; 			//8*abs(play.ySpeed);
			play.yAcc = -32768;
			play.idle = 0;				//?????
			if (play.ySpeed < -12) {
				play.ySpeed = -12;	
			}
			if (play.ySpeed > 4) {
				play.ySpeed = 4;	
			}
		}
	}
	
	jjWeapons[WEAPON::GUN8].gradualAim = play.powerup[WEAPON::GUN8];
}

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 - 104,		//xpos
			jjSubscreenHeight - 276,	//ypos	
			ANIM::PICKUPS,				//setID
			72, 						//animation
			jjGameTicks / 4 % 8,		//frame
			int8(180)					//angle (wtf?)
		);
	return true;
}

void onPlayerTimerEnd(jjPLAYER@ play) {
	jjSample(play.xPos, play.yPos, SOUND::COMMON_SWISH3, 32);
	play.antiGrav = false;
}

void onLevelLoad() {
	jjObjectPresets[OBJECT::ICEPOWERUP].direction = SPRITE::FLIPHV;
	
	jjObjectPresets[OBJECT::FASTFEET].behavior = Invertibility();
	jjObjectPresets[OBJECT::FASTFEET].scriptedCollisions = true;
	jjObjectPresets[OBJECT::FASTFEET].determineCurAnim(ANIM::PICKUPS, 72);
	jjObjectPresets[OBJECT::FASTFEET].determineCurFrame();
	
	jjObjectPresets[OBJECT::GEMRING].behavior = CustomGemRing;
	jjObjectPresets[OBJECT::GEMRING].triggersTNT = false;
	
	jjWeapons[WEAPON::GUN8].spread = SPREAD::NORMAL;
	jjObjectPresets[OBJECT::FIREBALLBULLETPU].var[6] = 8 + 16;
	jjObjectPresets[OBJECT::FIREBALLBULLETPU].lightType = LIGHT::POINT2;
	
	//thanks Violet
    array<uint8> recolor(256);
    for (uint i = 15; i < 88; ++i) //don't change most sprite colors
        recolor[i] = i;
    for (uint i = 88; i < 96; ++i) //purple to green
        recolor[i] = i - 8;
    for (uint i = 32; i < 40; ++i) //blue to green
        recolor[i] = i + 48;
    for (uint i = 24; i < 30; ++i) //red to orange
        recolor[i] = i + 16;
    for (uint i = 40; i < 48; ++i) //orange to "pink"
        recolor[i] = i + 48;
    recolorAnimation(recolor, jjAnimations[jjAnimSets[ANIM::AMMO] + 63]); //bullet
    recolorAnimation(recolor, jjAnimations[jjAnimSets[ANIM::AMMO] + 61]); //pickup
    recolorAnimation(recolor, jjAnimations[jjAnimSets[ANIM::PICKUPS] + 66]); //monitor
	
	//Seren
	const int tileCount = jjTileCount;
	animSet.allocate(array<uint>((tileCount + 127) >>> 7, 128));
	for (int i = 0; i < tileCount; i++) {
		auto@ frame = jjAnimFrames[jjAnimations[animSet + (i >>> 7)] + (i & 127)];
		jjPIXELMAP(i).save(frame);
		frame.hotSpotX = -16;
		frame.hotSpotY = -16;
	}
	auto@ order = jjLayerOrderGet();
	jjLayers[5].spriteMode = SPRITE::INVISIBLE;
	effectLayer.generateSettableTileArea();
	order.insertAt(5, effectLayer);
	jjLayerOrderSet(order);
}

void onDrawLayer5(jjPLAYER@ player, jjCANVAS@ canvas) {
	const auto@ spriteLayer = jjLayers[5];
	int width = spriteLayer.width;
	int height = spriteLayer.height;
	array<array<int>> newLayer(height, array<int>(width));
	float leftPix = player.cameraX;
	float topPix = player.cameraY;
	float rightPix = player.cameraX + jjSubscreenWidth;
	float bottomPix = player.cameraY + jjSubscreenHeight;
	int leftScr = int(leftPix) >>> 5;
	int topScr = int(topPix) >>> 5;
	int rightScr = int(rightPix) >>> 5;
	int bottomScr = int(bottomPix) >>> 5;
	for (int i = topScr; i <= bottomScr; i++) {
		int y = i << 5;
		float topDist = y + 32 - topPix;
		float bottomDist = bottomPix - y;
		float vertDist = topDist < bottomDist ? topDist : bottomDist;
		for (int j = leftScr; j <= rightScr; j++) {
			int x = j << 5;
			float leftDist = x + 32 - leftPix;
			float rightDist = rightPix - x;
			float horDist = leftDist < rightDist ? leftDist : rightDist;
			float dist = vertDist < horDist ? vertDist : horDist;
			int srcTile = jjGetStaticTile(spriteLayer.tileGet(j, i));
			int xFlip = srcTile & TILE::HFLIPPED != 0 ? -1 : 1;
			int yFlip = srcTile & TILE::VFLIPPED != 0 ? -1 : 1;
			int tile = srcTile & TILE::RAWRANGE;
			SPRITE::Mode mode = jjTileType[tile] == 1 ? SPRITE::TRANSLUCENTTILE : SPRITE::NORMAL;
			if (dist >= effectRadius) {
				newLayer[i][j] = srcTile;
				if (dist < effectRadius + 32.f && int(effectLayer.tileGet(j, i)) != srcTile)
					canvas.drawSprite(x | 16, y | 16, ANIM::CUSTOM[0], tile >>> 7, tile & 127, xFlip ^ (yFlip < 0 ? 64 : 0), mode);
			} else {
				float scale = dist / effectRadius;
				//cooba: minimum cap on arted tile
				if (scale <= 0.2f) scale = 0.f;
				
				int angle = int(jjSin(x ^ y) * (1.f - scale) * 1024.f);				
				canvas.drawRotatedSprite(x | 16, y | 16, ANIM::CUSTOM[0], tile >>> 7, tile & 127, angle, scale * xFlip, scale * yFlip, mode);
			}
		}
	}
	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++) {
			effectLayer.tileSet(j, i, newLayer[i][j]);
		}
	}
}
void onLevelReload() {
	MLLE::SpawnOffgridsLocal();
	MLLE::ReapplyPalette();
}

bool onDrawAmmo(jjPLAYER@ player, jjCANVAS@ canvas) {
	return MLLE::WeaponHook.drawAmmo(player, canvas);
}

void onLevelBegin() {
	MLLE::SpawnOffgrids();
}