Downloads containing autoTurret.asc

Downloads
Name Author Game Mode Rating
Custom Weapons...Featured Download Violet CLM Other 10 Download file

File preview

#pragma require "autoTurret.j2a"
#pragma require "autoTurret.asc"
#include "MLLE-Weapons.asc"

/**Auto-Turret**/
/**Author: szmol96**/

namespace SzmolWeaponPack {
	namespace AutoTurret {
		enum packet_type {packet_getTurretData, packet_createTurret, packet_turretDeath};
		const int turretBulletPointIdentifier = 21 + jjScriptModuleID;
		
		class Weapon : MLLEWeapons::WeaponInterface {
			Weapon() {
				super(
					regularObjectTemplate: MLLEWeapons::ObjectTemplate(
						state: STATE::FLY,
						xSpeed: 6,
						points: turretBulletPointIdentifier,
						curAnim: 1,
						killAnim: jjAnimSets[ANIM::AMMO] + 4,
						animSpeed: 2,
						lightType: LIGHT::POINT,
						counterEnd: 30
					),
					style: WEAPON::MISSILE,
					animSetFilename: "autoTurret.j2a",
					pickupAnimation: 0,
					poweredUpPickupAnimation: 0,
					generateSupplementalAnimations: false,
					roundsPerPickup: 1,
					traits: (se::weapon_default_traits | se::weapon_cannot_be_fired_by_key_press) & ~(se::weapon_has_powerup_monitors | se::weapon_has_distinct_powerup | se::weapon_has_ammo_crates),
					onMain: se::MainCallback(RequestServerData),
					onPlayerInput: se::PlayerCallback(PreventFiringAdditionalTurrets),
					onReceive: se::PacketCallback(ProcessPacket),
					onDrawAmmo: se::DrawingCallback(DrawAmmoIcon),
					weaponHookRequired: true,
					behavior: function(obj, powerup) { obj.behavior = BEHAVIOR::BULLET; obj.var[6] = 8; }
				);
			}
			
			TurretBehavior@ MyTurretBehavior = TurretBehavior(this);
			int AddTurret(float x, float y, uint16 crID, CREATOR::Type crType) {
				if (crType == CREATOR::PLAYER) {
					crID &= 31;
					if (turrets[crID] !is null)
						return 0;
				}
				const int objectID = jjAddObject(OBJECT::BULLET, x,y, crID, crType, BEHAVIOR::INACTIVE);
				jjOBJ@ obj = jjObjects[objectID];
				if (crType == CREATOR::PLAYER)
					@turrets[crID] = @obj;
				obj.behavior = MyTurretBehavior;
				obj.playerHandling = HANDLING::SPECIAL;
				obj.bulletHandling = HANDLING::DETECTBULLET;
				obj.scriptedCollisions = true;
				obj.energy = 50;
				obj.freeze = 0;
				obj.isTarget = false;
				obj.state = STATE::WAIT;
				obj.curFrame = jjAnimations[AnimSet];
				obj.killAnim = jjAnimSets[ANIM::AMMO] + 5;
				return objectID;
			}
			
			uint getMaxDamage(bool powerup) const override { return 2; }
			
			array<jjOBJ@> turrets(32, null);

			void sendTurretPacket(int32 playNum, uint8 playID = 0) const {
				jjSTREAM packet = ConstructPacket();
				packet.push(uint8(packet_createTurret));
				packet.push(uint8(playNum));
				const jjOBJ@ turret = turrets[playNum];
				if (turret !is null) {
					packet.push(int16(turret.xPos));
					packet.push(int16(turret.yPos));
					packet.push(turret.energy);
				} else {
					const jjPLAYER@ play = jjPlayers[playNum];
					packet.push(int16(play.xPos));
					packet.push(int16(play.yPos));
					packet.push(int8(50));
				}
				jjSendPacket(packet, playID);
			}

			void sendDeathPacket(uint8 playNum) const {
				jjSTREAM packet = ConstructPacket();
				packet.push(uint8(packet_turretDeath));
				packet.push(playNum);
				jjSendPacket(packet);
			}

			array<bool> keyHeld(jjLocalPlayerCount);
			void PreventFiringAdditionalTurrets(jjPLAYER@ p, int number) {
				if (p.currWeapon == uint(number)) {
					if (turrets[p.playerID] !is null)
						p.keyFire = false;
					else if (p.keyFire) {
						if (jjIsServer || jjGameConnection == GAME::LOCAL)
							AddTurret(p.xPos, p.yPos, p.playerID, CREATOR::PLAYER);
						sendTurretPacket(p.playerID);
						p.ammo[number] = 0;
						keyHeld[p.localPlayerID] = true;
					}
					if (p.ammo[number] == 0) p.keySelect = true;
				}
				if (keyHeld[p.localPlayerID]) {
					if (p.keyFire) p.keyFire = false;
					else keyHeld[p.localPlayerID] = false;
				}
				
			}
			
			bool RequestedServerData = false;
			void RequestServerData(int) {
				if (!RequestedServerData) {
					jjAnimations[AnimSet].frameCount = 1; //makes pickup/ammoicon animation less ridiculous
					RequestedServerData = true;
					if (!jjIsServer && jjGameConnection != GAME::LOCAL) {
						jjSTREAM packet = ConstructPacket();
						packet.push(uint8(packet_getTurretData));
						jjSendPacket(packet);
					}
				}
			}

			void ProcessPacket(jjSTREAM& packet, int clientID) {
				uint8 type;
				packet.pop(type);
				if (type == packet_createTurret) {
					uint8 playNum;
					packet.pop(playNum);
					if (jjIsServer && jjPlayers[playNum].clientID != clientID)
						return;
					int16 posX;
					int16 posY;
					packet.pop(posX);
					packet.pop(posY);
					
					AddTurret(posX, posY, playNum, CREATOR::PLAYER);
					packet.pop(turrets[playNum].energy);
					if (jjIsServer)
						sendTurretPacket(playNum);
				}
				else if (jjIsServer) {
					if (type == packet_getTurretData) {
						for (uint8 i = 0; i < 32; ++i) {
							jjOBJ@ turret = turrets[i];
							if (turret !is null)
								sendTurretPacket(i, clientID);
						}
					}
				} else {
					if (type == packet_turretDeath) {
						uint8 playNum;
						packet.pop(playNum);
						
						if (turrets[playNum] !is null) //just to be safe
							turrets[playNum].state = STATE::EXPLODE;
					}
				}
			}
			
			bool DrawAmmoIcon(jjPLAYER@ player, jjCANVAS@ canvas, const jjANIMATION@ anim) const {
				if (player !is null && !player.noFire && player.charCurr != CHAR::FROG && player.charCurr != CHAR::BIRD) {
					int x, y;
					if (::jjSubscreenWidth > 400) {
						x = ::jjSubscreenWidth - 88;
						y = ::jjSubscreenHeight - 14;
					} else {
						x = ::jjSubscreenWidth - 48;
						y = ::jjSubscreenHeight - 9;
					}
					canvas.drawSpriteFromCurFrame(x, y, anim + (::jjGameTicks >> 2) % anim.frameCount, 1, turrets[player.playerID] is null ? SPRITE::NORMAL : SPRITE::TRANSLUCENT);
				}
				return true;
			}
		}
		class TurretBehavior : jjBEHAVIORINTERFACE {
			Weapon@ weapon;
			TurretBehavior(Weapon@ w) { @weapon = @w; }
			void onBehave(jjOBJ@ obj) {
				const array<float>@ target = MLLEWeapons::HelpfulBulletFunctions::GetNearestEnemyPosition(obj, 222, true);
				if (target !is null) {
					if (obj.freeze == 0) {
						obj.special = int(atan2(obj.xPos - target[0], obj.yPos - target[1]) * 162.974662); //turret angle
						if (obj.age % 15 == 0)
							jjObjects[weapon.FireBullet(
								obj.xPos - (jjSin(obj.special) * 20),
								obj.yPos - (jjCos(obj.special) * 20),
								768 - obj.special,
								true,
								obj.creatorID, obj.creatorType,
								number: obj.var[3]
							)[0]].var[7] = 0;
					} //else remember previous angle
				} else {
					obj.special = int(jjSin(obj.age * 2) * 256);
				}
				
				if (!jjMaskedHLine(int(obj.xPos) - 10, 20, int(obj.yPos) + 16) && obj.ySpeed < 7.5) obj.ySpeed += 0.1;
				else obj.ySpeed = 0;
				
				if (obj.energy <= 0 || obj.state == STATE::EXPLODE || obj.state == STATE::DEACTIVATE) {
					if (jjIsServer && obj.creatorType == CREATOR::PLAYER)
						weapon.sendDeathPacket(obj.creatorID);
					obj.particlePixelExplosion(0);
					obj.behavior = BEHAVIOR::EXPLOSION2;
					obj.frameID = 0;
					if (obj.creatorType == CREATOR::PLAYER)
						@weapon.turrets[obj.creatorID] = null;
				}
				
				obj.yPos += obj.ySpeed;
				if (obj.freeze > 0) --obj.freeze;
				else ++obj.age;
				
				jjDrawRotatedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame + 1, obj.special);
				if (obj.creatorType == CREATOR::PLAYER)
					jjDrawString(obj.xPos - 8, obj.yPos + 24, "" + obj.creatorID);
				obj.draw();
			}
			bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ p, int force) {
				if (bullet !is null && bullet.points != turretBulletPointIdentifier) {
					if (jjIsServer || jjGameConnection == GAME::LOCAL)
						obj.energy -= bullet.animSpeed;
					obj.justHit = 5;
					bullet.state = STATE::EXPLODE;
				}
				return true;
			}
		}
	}
}