Downloads containing lockOnMissile.asc

Downloads
Name Author Game Mode Rating
JJ2+ Only: Threed RealmsFeatured Download Violet CLM Single player 9.7 Download file
JJ2+ Only: Anniversary Bash 25 CTF Jazz2Online Capture the flag N/A Download file
TSF with JJ2+ Only: Anniversary Bash 22 levels Jazz2Online Multiple N/A Download file
JJ2+ Only: Tech Tree Violet CLM Capture the flag 7.8 Download file
Custom Weapons...Featured Download Violet CLM Other 10 Download file

File preview

#pragma require "lockOnMissile.asc"
#pragma require "lockOnMissile.j2a"
#pragma offer "lock-on.wav"
#include "MLLE-Weapons.asc"

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

namespace SzmolWeaponPack {
	namespace LockOnMissile {
		class PlayerX {
			int prevClosest = 0;
			int missileCounter = 0;
			uint mCounterDelay = 0;
		}
		array<PlayerX> PlayersX(jjLocalPlayerCount);
		array<int> closestPlayers(32, -1); //needed even for non-local players
		
		class Weapon : MLLEWeapons::WeaponInterface {
			Weapon() {
				super(
					regularObjectTemplate: MLLEWeapons::ObjectTemplate(
						xSpeed: 7,
						animSpeed: 2,
						curAnim: 0
					),
					powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
						xSpeed: 7.5,
						animSpeed: 3,
						curAnim: 1,
						doesHurt: 8
					),
					sampleFilenames: array<string> = {"lock-on.wav"},
					animSetFilename: "lockOnMissile.j2a",
					pickupAnimation: 3,
					poweredUpPickupAnimation: 4,
					powerupAnimation: 5,
					style: WEAPON::MISSILE,
					traits: se::weapon_default_traits,
					onDrawAmmo: se::DrawingCallback(DrawMissiles),
					onMain: TrackNearestPlayers,
					onPlayer: se::PlayerCallback(DoLockOnTarget),
					weaponHookRequired: false, //it can get by
					behavior: function(obj, powerup) { obj.behavior = Behavior; }
				);
			}
		
			bool DrawMissiles(jjPLAYER@ p, jjCANVAS@ canvas, const jjANIMATION@) const {
				for (int i = 0; i != PlayersX[p.localPlayerID].missileCounter; ++i)
					canvas.drawSprite(jjSubscreenWidth - 64, jjSubscreenHeight - 32 - i * 8, SetID,2,1, (i % 2 == 0) ? 1 : -1);
				return false;
			}
			void DoLockOnTarget(jjPLAYER@ p, int number) {
				const int closestID = closestPlayers[p.playerID];
				PlayerX@ px = PlayersX[p.localPlayerID];
				
				if (int(p.currWeapon) == number) {
					if (closestID >= 0) {
						const jjPLAYER@ target = jjPlayers[closestID];
						jjDrawSprite(target.xPos, target.yPos, SetID,2,0, 0, SPRITE::NORMAL,0, 1,4, p.playerID);
						if (SamplesLoaded[0] && closestID != px.prevClosest)
							jjSample(p.xPos, p.yPos, Samples[0]);
					}
						
					if (p.keyFire) {
						if (px.mCounterDelay++ > 70 && px.mCounterDelay % 17 == 0 && px.missileCounter < 8 && px.missileCounter < p.ammo[WEAPON::CURRENT])
							px.missileCounter += 1;
					} else {
						if (px.missileCounter > 0) {
							for (int i = 0; i < px.missileCounter; ++i)
								p.fireBullet(number, true, true, i * 6.2831853 / px.missileCounter);
							px.missileCounter = 0;
							p.keySelect = p.ammo[WEAPON::CURRENT] == 0;
						}
						px.mCounterDelay = 0;
					}
				}
				
				px.prevClosest = closestID;
			}
		}
		
		void TrackNearestPlayers(int) {
			if (jjGameMode <= GAME::COOP)
				return;
			jjOBJ@ bogus = jjObjects[0];
			bogus.creator = CREATOR::PLAYER;
			for (uint playerID = 0; playerID < 32; ++playerID, ++bogus.creator) {
				const jjPLAYER@ p = jjPlayers[playerID];
				if (p.isInGame) {
					bogus.xPos = p.xPos;
					bogus.yPos = p.yPos;
					closestPlayers[playerID] = MLLEWeapons::HelpfulBulletFunctions::GetNearestEnemyPlayer(bogus, 450);
				}
			}
		}

		void Behavior(jjOBJ@ obj) {
			if (obj.state == STATE::START) {
				obj.points = int(atan2(obj.xSpeed, obj.ySpeed) * 162.974636 /*+ (jjCos(jjRandom() % 512) * 10)*/); //angle
				obj.state = STATE::FLY;
				obj.xSpeed += obj.var[7] / 65536.f;
			} else if (obj.age > 17) { //redirect
				array<float>@ target = null;
				if (obj.creatorType == CREATOR::PLAYER && jjGameMode > GAME::COOP) {
					const int targetPlayerID = closestPlayers[obj.creatorID]; //closest to player who fired this
					if (targetPlayerID >= 0)
						@target = array<float> = { jjPlayers[targetPlayerID].xPos, jjPlayers[targetPlayerID].yPos };
				}
				if (target is null)
					@target = MLLEWeapons::HelpfulBulletFunctions::GetNearestEnemyPosition(obj, 450); //closest to bullet itself... this part is new to the .asc reimplementation
				
				if (target !is null) {
					int difference = ((int(atan2(obj.xPos - target[0], obj.yPos - target[1]) * 162.974636) + 512 - obj.points) & 1023);
					if (difference >= 512) difference -= 1024;
					obj.points += difference / 8;
					const float speed = MLLEWeapons::HelpfulBulletFunctions::IsPowerup(obj) ? 7.5f : 7;
					obj.xSpeed = speed * jjSin(obj.points);
					obj.ySpeed = speed * jjCos(obj.points);
				}
			}
			
			obj.xPos += obj.xSpeed;
			obj.yPos += obj.ySpeed;
			++obj.age;
			
			if (obj.age > 105 || obj.state == STATE::EXPLODE || MLLEWeapons::HelpfulBulletFunctions::MaskedPixel(obj)) {
				for (uint8 i = 0; i < 10; ++i) {
					jjPARTICLE@ spark1 = jjAddParticle(PARTICLE::SPARK);
					if (spark1 !is null) {
						spark1.spark.color = 32 + obj.doesHurt;
						spark1.spark.colorDelta = 1;
						spark1.spark.colorStop = 38 + obj.doesHurt;
						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();
			} else {
				jjAddObject(OBJECT::EXPLOSION, obj.xPos, obj.yPos, obj.objectID, CREATOR::OBJECT, missileTrail);
				obj.draw();
			}
		}
		void missileTrail(jjOBJ@ trail) {
			if (trail.state == STATE::START) {
				trail.age = 0;
				trail.curAnim = jjObjects[trail.creatorID].curAnim;
				trail.direction = jjObjects[trail.creatorID].direction;
				trail.lightType = LIGHT::NONE;
				trail.playerHandling = HANDLING::EXPLOSION;
				trail.state = STATE::FLY;
			}
			
			if (trail.age > 15)
				trail.delete();
			else
				jjDrawSpriteFromCurFrame(trail.xPos, trail.yPos, jjAnimations[trail.curAnim] + (trail.age++ / 3), trail.direction, SPRITE::TRANSLUCENT);
		}
	}
}