Downloads containing lockOnMissile.mut

Downloads
Name Author Game Mode Rating
JJ2+ Only: Szmol Weapon Pack vol. 1 szmol96 Mutator N/A Download file

File preview

#pragma name "Lock-on Missile"
#pragma require "lockOnMissile.j2a"
#pragma require "lock-on.wav"

/**Lock-on Missile**/
/**Author: szmol96**/

const float pi = 3.14159265;
const float degTo1024 = 2.844444;

array<uint8> closestPlayers(32, 0);
uint8 prevClosest = 0;

uint customAnimID = 0;
uint8 missileCounter = 0;
uint8 mCounterDelay = 0;

void findCustomAnimID() { //This function is copied from Bunny Must Die! guns
	while (jjAnimSets[ANIM::CUSTOM[customAnimID]].firstAnim != 0) ++customAnimID;
	
	jjAnimSets[ANIM::CUSTOM[customAnimID]].load(0, "lockOnMissile.j2a");
}

uint8 closestPlayer(int toPlayerNum) {
	jjPLAYER@ p = jjPlayers[toPlayerNum];
	
	float minDist = 450;
	uint8 cp = 0;
	
	for (uint8 i = 0; i < 32; ++i) {
		if (!jjPlayers[i].isInGame || !jjPlayers[toPlayerNum].isEnemy(jjPlayers[i])) continue;
		float distX = p.xPos - jjPlayers[i].xPos;
		float distY = p.yPos - jjPlayers[i].yPos;
		float curDist = sqrt(distX * distX + distY * distY);
		if (curDist < minDist) {
			minDist = curDist;
			cp = i;
		}
	}
	if (minDist < 450) {
		return cp;
	}
	return 255;
}

void lMissile(jjOBJ@ obj) {
	jjPLAYER@ p = jjPlayers[obj.creatorID];
	
	float dx = obj.xPos - jjPlayers[closestPlayers[p.playerID]].xPos;
	float dy = obj.yPos - jjPlayers[closestPlayers[p.playerID]].yPos;
	float angle;
	
	if (obj.state == STATE::START) {
		obj.age = 0;
		obj.direction = p.direction;
		obj.points = (atan2(obj.xSpeed, obj.ySpeed) * 180 / pi) * degTo1024 + (jjCos(jjRandom() % 512) * 10);
		
		obj.state = STATE::FLY;
	}
	
	angle = (atan2(dx, dy) * 180 / pi) * degTo1024 + 512;
	
	if (obj.age > 105 || jjMaskedPixel(obj.xPos + obj.xSpeed, obj.yPos + obj.ySpeed)) {
		for (uint8 i = 0; i < 10; ++i) {
			jjPARTICLE@ spark1 = jjAddParticle(PARTICLE::SPARK);
			if (spark1 !is null) {
				spark1.spark.color = 32;
				spark1.spark.colorDelta = 1;
				spark1.spark.colorStop = 38;
				spark1.xPos = obj.xPos;
				spark1.yPos = obj.yPos;
				spark1.xSpeed = obj.xSpeed / 3 + (jjCos(jjRandom() % 512));
				spark1.ySpeed = obj.ySpeed / 3 + (jjCos(jjRandom() % 512));
			}
		}
		obj.delete();
	}
	
	if (obj.age > 17 && jjPlayers[closestPlayers[p.playerID]].playerID != p.playerID && closestPlayers[p.playerID] != 255) {
		int difference = ((angle - obj.points) & 1023);
		if (difference >= 512) difference -= 1024;
		obj.points += difference / 8;
	}
	obj.xSpeed = 7 * jjSin(obj.points);
	obj.ySpeed = 7 * jjCos(obj.points);
	obj.xPos += obj.xSpeed;
	obj.yPos += obj.ySpeed;
	
	addTrail(obj.xPos - obj.xSpeed, obj.yPos - obj.ySpeed, obj.creatorID, obj.direction, false);
	
	obj.age++;
	obj.determineCurFrame(true);
	obj.draw();
}

void lMissilePu(jjOBJ@ obj) {
	jjPLAYER@ p = jjPlayers[obj.creatorID];
	
	float dx = obj.xPos - jjPlayers[closestPlayers[p.playerID]].xPos;
	float dy = obj.yPos - jjPlayers[closestPlayers[p.playerID]].yPos;
	float angle;
	
	if (obj.state == STATE::START) {
		obj.age = 0;
		obj.direction = p.direction;
		obj.points = (atan2(obj.xSpeed, obj.ySpeed) * 180 / pi) * degTo1024 + (jjCos(jjRandom() % 512) * 10);
		
		obj.state = STATE::FLY;
	}
	
	angle = (atan2(dx, dy) * 180 / pi) * degTo1024 + 512;
	
	if (obj.age > 105 || jjMaskedPixel(obj.xPos + obj.xSpeed, obj.yPos + obj.ySpeed)) {
		for (uint8 i = 0; i < 10; ++i) {
			jjPARTICLE@ spark1 = jjAddParticle(PARTICLE::SPARK);
			if (spark1 !is null) {
				spark1.spark.color = 40;
				spark1.spark.colorDelta = 1;
				spark1.spark.colorStop = 46;
				spark1.xPos = obj.xPos;
				spark1.yPos = obj.yPos;
				spark1.xSpeed = obj.xSpeed / 3 + (jjCos(jjRandom() % 512));
				spark1.ySpeed = obj.ySpeed / 3 + (jjCos(jjRandom() % 512));
			}
		}
		obj.delete();
	}
	
	if (obj.age > 17 && jjPlayers[closestPlayers[p.playerID]].playerID != p.playerID && closestPlayers[p.playerID] != 255) {
		int difference = ((angle - obj.points) & 1023);
		if (difference >= 512) difference -= 1024;
		obj.points += difference / 8;
	}
	obj.xSpeed = 7.5 * jjSin(obj.points);
	obj.ySpeed = 7.5 * jjCos(obj.points);
	obj.xPos += obj.xSpeed;
	obj.yPos += obj.ySpeed;
	
	addTrail(obj.xPos - obj.xSpeed, obj.yPos - obj.ySpeed, obj.creatorID, obj.direction, true);
	
	obj.age++;
	obj.determineCurFrame(true);
	obj.draw();
}

void missileTrail(jjOBJ@ trail) {
	jjPLAYER@ p = jjPlayers[trail.creatorID];

	if (trail.state == STATE::START) {
		trail.age = 0;
		trail.state = STATE::FLY;
	}
	
	if (trail.age > 15) trail.delete();
	
	trail.frameID = trail.age / 3;
	trail.age++;
	trail.determineCurFrame(true);
	jjDrawSpriteFromCurFrame(trail.xPos, trail.yPos, trail.curFrame, trail.direction, SPRITE::TRANSLUCENT, 0, 4, 4, -1);
}

void addTrail(float x, float y, uint16 crID, uint16 dir, bool isPU) {
	jjOBJ@ trail;
	
	@trail = jjObjects[jjAddObject(OBJECT::EXPLOSION, x, y, crID, CREATOR::PLAYER)];
	trail.xSpeed = 0;
	trail.ySpeed = 0;
	if (isPU) {
		trail.determineCurAnim(ANIM::CUSTOM[customAnimID], 1, true);
	} else {
		trail.determineCurAnim(ANIM::CUSTOM[customAnimID], 0, true);
	}
	trail.lightType = LIGHT::NONE;
	trail.behavior = missileTrail;
}

void onLevelLoad() {
	findCustomAnimID();
	jjSampleLoad(SOUND::ORANGE_GLAS1R, "lock-on.wav");
	
	jjAnimations[jjAnimSets[ANIM::AMMO] + 33] = jjAnimations[jjAnimSets[ANIM::CUSTOM[customAnimID]] + 4];
	jjAnimations[jjAnimSets[ANIM::AMMO] + 34] = jjAnimations[jjAnimSets[ANIM::CUSTOM[customAnimID]] + 3];
	jjAnimations[jjAnimSets[ANIM::PICKUPS] + 63] = jjAnimations[jjAnimSets[ANIM::CUSTOM[customAnimID]] + 5];
	
	jjObjectPresets[OBJECT::SEEKERBULLET].determineCurAnim(ANIM::CUSTOM[customAnimID], 0, true);
	jjObjectPresets[OBJECT::SEEKERBULLET].playerHandling = HANDLING::PLAYERBULLET;
	jjObjectPresets[OBJECT::SEEKERBULLET].special = 0;
	jjObjectPresets[OBJECT::SEEKERBULLET].behavior = lMissile;
	
	jjObjectPresets[OBJECT::SEEKERBULLETPU].determineCurAnim(ANIM::CUSTOM[customAnimID], 1, true);
	jjObjectPresets[OBJECT::SEEKERBULLETPU].playerHandling = HANDLING::PLAYERBULLET;
	jjObjectPresets[OBJECT::SEEKERBULLETPU].special = 0;
	jjObjectPresets[OBJECT::SEEKERBULLETPU].behavior = lMissilePu;
}

void onLevelBegin() {
	jjWeapons[4].allowed = true;
	jjWeapons[4].allowedPowerup = true;
	jjWeapons[4].spread = SPREAD::NORMAL;
	jjWeapons[4].style = WEAPON::MISSILE;
	jjWeapons[4].defaultSample = false;
}

void onPlayer(jjPLAYER@ p) {
	for (uint8 i = 0; i < 32; ++i) {
		closestPlayers[i] = closestPlayer(i);
	}
	if (p.currWeapon == 4) {
		jjDrawSprite(jjPlayers[closestPlayers[p.playerID]].xPos, jjPlayers[closestPlayers[p.playerID]].yPos, ANIM::CUSTOM[customAnimID], 2, 0, 0, SPRITE::NORMAL, 0, 1, 4, -1);
		if (closestPlayers[p.playerID] != prevClosest && closestPlayers[p.playerID] != 255) jjSample(p.xPos, p.yPos, SOUND::ORANGE_GLAS1R, 63, 0);
	}
	
	prevClosest = closestPlayers[p.playerID];
}

void onPlayerInput(jjPLAYER@ p) {
	if (p.currWeapon == 4) {
		if (p.keyFire) {
			if (mCounterDelay > 70 && mCounterDelay % 17 == 0 && missileCounter < 8 && missileCounter < p.ammo[4]) missileCounter++;
			mCounterDelay++;
		} else {
			if (missileCounter > 0) {
				for (float i = 0; i < missileCounter; ++i) {
					p.fireBullet(WEAPON::SEEKER, true, true, 2 * pi / missileCounter * i);
				}
				missileCounter = 0;
			}
			mCounterDelay = 0;
		}
	}
}

bool onDrawAmmo(jjPLAYER@ p, jjCANVAS@ canvas) {
	if (p.currWeapon == 4) {
		for (uint8 i = 0; i < missileCounter; ++i) {
			if (i % 2 == 0) {
				canvas.drawSprite(jjResolutionWidth - 64, jjResolutionHeight - 32 - i * 8, ANIM::CUSTOM[customAnimID], 2, 1, 1, SPRITE::NORMAL, 0);
			} else {
				canvas.drawSprite(jjResolutionWidth - 64, jjResolutionHeight - 32 - i * 8, ANIM::CUSTOM[customAnimID], 2, 1, -1, SPRITE::NORMAL, 0);
			}
		}
	}
	return false;
}