Downloads containing MLLE-DefaultWeapons.asc

Downloads
Name Author Game Mode Rating
TSF with JJ2+ Only: Mystery of the Four... chandie Single player 6.6 Download file
Multi-Layer Level Editor...Featured Download Violet CLM Utility 9.6 Download file

File preview

#include "MLLE-Weapons.asc"
namespace DefaultWeapons {
	class Blaster : MLLEWeapons::WeaponInterface {
		Blaster() {
			super(
				regularObjectTemplate: MLLEWeapons::ObjectTemplate(
					xSpeed: 6,
					xAcc: 0.125,
					killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 80,
					curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 17,
					lightType: LIGHT::POINT2,
					counterEnd: 35
				),
				powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
					xSpeed: 7,
					xAcc: 0.1875,
					animSpeed: 2,
					killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 80,
					curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 20,
					lightType: LIGHT::POINT,
					counterEnd: 30
				),
				pickupAnimation: jjAnimSets[ANIM::PICKUPS] + 29,
				poweredUpPickupAnimation: jjAnimSets[ANIM::AMMO] + 18,
				powerupAnimation: jjAnimSets[ANIM::PICKUPS] + 60,
				behavior: function(obj, powerup) {
					obj.behavior = BEHAVIOR::BULLET; 
					if (obj.eventID == OBJECT::ICEBULLET) obj.eventID = OBJECT::BLASTERBULLET;
					DefaultSample(obj, WEAPON::BLASTER);
				},
				onDrawAmmo: function(player, canvas, ignore) { //character-specific animations:
					if (player !is null && !player.noFire && player.charCurr != CHAR::FROG && player.charCurr != CHAR::BIRD) {
						const uint number = player.currWeapon;
						const bool powerup = player.powerup[WEAPON::CURRENT];
						const CHAR::Char charCurr = player.charCurr != CHAR::BIRD2 ? player.charCurr : player.charOrig;
						const ::jjANIMATION@ anim = jjAnimations[
							charCurr == CHAR::SPAZ ? (powerup ? (::jjAnimSets[ANIM::AMMO] + 19) : (::jjAnimSets[ANIM::PICKUPS] + 30)) :
							(::jjIsTSF && charCurr == CHAR::LORI) ? (powerup ? (::jjAnimSets[ANIM::PLUS_AMMO] + 6) : (::jjAnimSets[ANIM::PLUS_AMMO] + 5)) :
							(powerup ? (::jjAnimSets[ANIM::AMMO] + 18) : (::jjAnimSets[ANIM::PICKUPS] + 29))
						];
						int x, y;
						STRING::Size font;
						::string text;
						if (::jjSubscreenWidth > 400) {
							x = ::jjSubscreenWidth - 88;
							y = ::jjSubscreenHeight - 14;
							font = STRING::MEDIUM;
						} else {
							x = ::jjSubscreenWidth - 48;
							y = ::jjSubscreenHeight - 9;
							font = STRING::SMALL;
						}
						canvas.drawSpriteFromCurFrame(x, y, anim + (::jjGameTicks >> 2) % anim.frameCount);
						const ::jjWEAPON@ weapon = ::jjWeapons[number];
						if (weapon.infinite || weapon.replacedByShield && player.shieldTime > 0) {
							text = "x^";
						} else {
							const int ammo = player.ammo[number];
							text = "x" + (ammo > 0 ? ammo : 0);
						}
						canvas.drawString(x + 8, y, text, font);
					}
					return true;
				}
			);
		}
	}
	class Bouncer : MLLEWeapons::WeaponInterface {
		bool ReverseBehaviors = false;
		bool BounceThroughWalls = true;
		Bouncer() {
			super(
				regularObjectTemplate: MLLEWeapons::ObjectTemplate(
					xSpeed: 5,
					ySpeed: 1,
					xAcc: 0.25,
					yAcc: 0.0915527344f,
					killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 4,
					curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 23,
					lightType: LIGHT::POINT2,
					counterEnd: (70*3)/2
				),
				powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
					xSpeed: 5,
					ySpeed: 1,
					xAcc: 0.25,
					yAcc: 0.0915527344f,
					animSpeed: 2,
					killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 4,
					curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 26,
					lightType: LIGHT::POINT2,
					counterEnd: (70*3)/2
				),
				pickupAnimation: jjAnimSets[ANIM::AMMO] + 25,
				poweredUpPickupAnimation: jjAnimSets[ANIM::AMMO] + 24,
				powerupAnimation: jjAnimSets[ANIM::PICKUPS] + 61,
				ammoCrateAnimation: jjAnimSets[ANIM::PICKUPS] + 54,
				traits: se::weapon_default_traits | se::weapon_goes_through_thin_walls,
				behavior: MLLEWeapons::behaviorFunction(DetermineBehavior),
				apply: MLLEWeapons::applyFunction(DetermineReversedness)
			);
		}
		void DetermineBehavior(jjOBJ@ obj, bool powerup) const {
			DefaultSample(obj, WEAPON::BOUNCER);
			if (BounceThroughWalls)
				obj.behavior = (powerup != ReverseBehaviors) ? BEHAVIOR::BOUNCERBULLETPU : BEHAVIOR::BOUNCERBULLET;
			else
				obj.behavior = (powerup != ReverseBehaviors) ? BouncerPUNoWallWrapper : BouncerNoWallWrapper;
		}
		bool DetermineReversedness(uint, se::WeaponHook@, jjSTREAM@ parameter) {
			if (parameter !is null && parameter.getSize() >= 2) {
				parameter.pop(ReverseBehaviors);
				parameter.pop(BounceThroughWalls);
			}
			return true;
		}
	}
	void BouncerNoWallWrapper(jjOBJ@ obj) {
		const bool right = obj.xSpeed >= 0;
		obj.behave(BEHAVIOR::BOUNCERBULLET);
		if (right != (obj.xSpeed >= 0))
			obj.var[7] = -obj.var[7];
	}
	void BouncerPUNoWallWrapper(jjOBJ@ obj) {
		const bool right = obj.xSpeed >= 0;
		obj.behave(BEHAVIOR::BOUNCERBULLETPU);
		if (right != (obj.xSpeed >= 0))
			obj.var[7] = -obj.var[7];
	}
	class Ice : MLLEWeapons::WeaponInterface {
		bool FiringUnfreezesFaster = true;
		Ice() {
			super(
				regularObjectTemplate: MLLEWeapons::ObjectTemplate(
					xSpeed: 6,
					xAcc: 0.125,
					animSpeed: 2,
					killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 82,
					curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 27,
					lightType: LIGHT::POINT2,
					counterEnd: 35,
					freeze: 200
				),
				powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
					xSpeed: 7,
					xAcc: 0.1875,
					animSpeed: 2,
					killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 82,
					curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 30,
					special: jjAnimSets[ANIM::AMMO].firstAnim + 32,
					lightType: LIGHT::POINT2,
					counterEnd: 30,
					freeze: 254
				),
				spread: SPREAD::ICE,
				traits: se::weapon_is_effective_against_all_targets | se::weapon_supports_mouse_aim | se::weapon_works_in_all_modes | se::weapon_has_all_pickups | se::weapon_inflicts_status_condition | se::weapon_freezes_objects | se::weapon_melts_ice,
				pickupAnimation: jjAnimSets[ANIM::AMMO] + 29,
				poweredUpPickupAnimation: jjAnimSets[ANIM::AMMO] + 28,
				powerupAnimation: jjAnimSets[ANIM::PICKUPS] + 62,
				ammoCrateAnimation: jjAnimSets[ANIM::PICKUPS] + 55,
				onPlayerInput: se::PlayerCallback(playerInput),
				apply: MLLEWeapons::applyFunction(DetermineUnfreezing),
				behavior: function(obj, powerup) {
					DefaultSample(obj, WEAPON::ICE);
					if (powerup) {
						if (obj.xSpeed == 0 || obj.ySpeed == 0) {
							obj.behavior = BEHAVIOR::ICEBULLETPU;
							obj.eventID = OBJECT::ICEBULLETPU;
						} else {
							obj.behavior = BEHAVIOR::BULLET;
							if (powerup) obj.curAnim = jjAnimSets[ANIM::AMMO].firstAnim + 30;
						}
						if (obj.xSpeed != 0) obj.counterEnd = 30;
						obj.var[0] = AlternatingPoweredUpIce ^= 512;
					} else {
						obj.behavior = BEHAVIOR::BULLET;
						obj.eventID = OBJECT::ICEBULLET;
					}
				}
			);
		}
		uint getMaxDamage(bool powerup) const override { return 0; }
		bool DetermineUnfreezing(uint, se::WeaponHook@, jjSTREAM@ parameter) {
			if (parameter !is null && !parameter.isEmpty())
				parameter.pop(FiringUnfreezesFaster);
			return true;
		}
		void playerInput(jjPLAYER@ play, int) {
			if (!FiringUnfreezesFaster && play.frozen != 0)
				play.keyFire = false;
		}
	}
	int AlternatingPoweredUpIce = 0;
	class Seeker : MLLEWeapons::WeaponInterface {
		Seeker() {
			super(
				regularObjectTemplate: MLLEWeapons::ObjectTemplate(
					xSpeed: 2,
					xAcc: 0.25,
					yAcc: 0.00390625f,
					animSpeed: 2,
					killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 5,
					curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 37,
					lightType: LIGHT::POINT2,
					counterEnd: 140
				),
				powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
					xSpeed: 1.5,
					xAcc: 0.25,
					yAcc: 0.00390625f,
					animSpeed: 3,
					killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 5,
					curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 42,
					lightType: LIGHT::POINT2,
					counterEnd: 140
				),
				style: WEAPON::MISSILE,
				pickupAnimation: jjAnimSets[ANIM::AMMO] + 34,
				poweredUpPickupAnimation: jjAnimSets[ANIM::AMMO] + 33,
				powerupAnimation: jjAnimSets[ANIM::PICKUPS] + 63,
				ammoCrateAnimation: jjAnimSets[ANIM::PICKUPS] + 56,
				behavior: function(obj, powerup) { obj.behavior = BEHAVIOR::SEEKERBULLET; DefaultSample(obj, WEAPON::SEEKER); }
			);
		}
	}
	class RFs : MLLEWeapons::WeaponInterface {
		RFs() {
			super(
				regularObjectTemplate: MLLEWeapons::ObjectTemplate(
					xSpeed: 1,
					xAcc: 0.1875,
					animSpeed: 2,
					killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 3,
					curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 45,
					lightType: LIGHT::POINT2,
					counterEnd: 40
				),
				powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
					xSpeed: 1.5,
					xAcc: 0.1875,
					animSpeed: 2,
					killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 3,
					curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 50,
					lightType: LIGHT::POINT2,
					counterEnd: 35
				),
				isRFMissile: true,
				spread: SPREAD::RF,
				style: WEAPON::MISSILE,
				pickupAnimation: jjAnimSets[ANIM::AMMO] + 49,
				poweredUpPickupAnimation: jjAnimSets[ANIM::AMMO] + 48,
				powerupAnimation: jjAnimSets[ANIM::PICKUPS] + 64,
				ammoCrateAnimation: jjAnimSets[ANIM::PICKUPS] + 57,
				traits: se::weapon_default_traits | se::weapon_causes_splash_damage | se::weapon_increases_mobility,
				behavior: function(obj, powerup) { obj.behavior = BEHAVIOR::RFBULLET; DefaultSample(obj, WEAPON::RF); }
			);
		}
	}
	class Toaster : MLLEWeapons::WeaponInterface {
		Toaster() {
			super(
				regularObjectTemplate: MLLEWeapons::ObjectTemplate(
					xSpeed: 1,
					xAcc: 0.125,
					curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 55,
					var: array<int> = {0,0,0,0,0,0,2},
					counterEnd: 35
				),
				powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
					xSpeed: 1,
					xAcc: 0.125,
					animSpeed: 2,
					curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 58,
					var: array<int> = {0,0,0,0,0,0,2},
					counterEnd: 35
				),
				spread: SPREAD::TOASTER,
				style: WEAPON::POPCORN,
				pickupAnimation: jjAnimSets[ANIM::AMMO] + 57,
				poweredUpPickupAnimation: jjAnimSets[ANIM::AMMO] + 56,
				powerupAnimation: jjAnimSets[ANIM::PICKUPS] + 65,
				ammoCrateAnimation: jjAnimSets[ANIM::PICKUPS] + 58,
				replacedByBubbles: true,
				multiplier: 32,
				traits: se::weapon_default_traits | se::weapon_melts_ice | se::weapon_fails_underwater,
				behavior: function(obj, powerup) { obj.behavior = BEHAVIOR::TOASTERBULLET; if (powerup) obj.eventID = OBJECT::TOASTERBULLETPU; DefaultSample(obj, WEAPON::TOASTER); }
			);
		}
	}
	class TNT : MLLEWeapons::WeaponInterface {
		bool IncludePowerup = true;
		TNT() {
			super(
				regularObjectTemplate: MLLEWeapons::ObjectTemplate(
					energy: 1,
					playerHandling: HANDLING::SPECIAL,
					curAnim: jjAnimSets[ANIM::AMMO] + 59,
					killAnim: jjAnimSets[ANIM::AMMO] + 77,
					lightType: LIGHT::POINT,
					counterEnd: 255
				),
				style: WEAPON::MISSILE,
				pickupAnimation: jjAnimSets[ANIM::AMMO] + 59,
				ammoCrateAnimation: jjAnimSets[ANIM::PICKUPS] + 59,
				traits: se::weapon_default_traits | se::weapon_causes_splash_damage | se::weapon_increases_mobility,
				behavior: MLLEWeapons::behaviorFunction(DetermineBehavior),
				apply: MLLEWeapons::applyFunction(DeterminePowerup)
			);
		}
		void DetermineBehavior(jjOBJ@ obj, bool powerup) const {
			obj.eventID = OBJECT::TNT; //use TNTdamage
			if (!IncludePowerup || !powerup || PoweredUpPickupAnimation <= 0)
				obj.behavior = BEHAVIOR::TNT;
			else {
				obj.behavior = TNTPowerupBehavior;
				obj.counter = -256; //double lifetime
				obj.curAnim = PoweredUpPickupAnimation;
			}
		}
		bool DeterminePowerup(uint, se::WeaponHook@, jjSTREAM@ parameter) {
			if (parameter !is null && !parameter.isEmpty())
				parameter.pop(IncludePowerup);
			return true;
		}
		uint getMaxDamage(bool powerup) const override { return 1; }
	}
	void TNTPowerupBehavior(jjOBJ@ obj) {
		if (obj.state == STATE::EXPLODE && obj.counter == 0) //beginning of explosion sequence
			obj.blast(96*96, true); //hurt nearby players NOW, not just 20 ticks from now after they've already run far away
		obj.behave(BEHAVIOR::TNT);
		if (obj.light == 17) //just created an explosion object
			for (uint objectID = jjObjectCount; --objectID != 0;) {
				jjOBJ@ obj2 = jjObjects[objectID];
				if (obj2.eventID == OBJECT::EXPLOSION && obj2.curAnim == obj.killAnim && obj2.xPos == obj.xPos && obj2.yPos == obj.yPos) {
					obj2.frameID = 4; //skip part where TNT is still visible (using the non-powerup colors)
					break;
				}
			}
	}
	class Gun8 : MLLEWeapons::WeaponInterface {
		Gun8() {
			super(
				regularObjectTemplate: MLLEWeapons::ObjectTemplate(
					xSpeed: 11,
					xAcc: 0.125,
					animSpeed: 2,
					killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 80,
					curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 60,
					var: array<int> = {0,0,0,0,0,0,16},
					lightType: LIGHT::POINT2,
					counterEnd: 45
				),
				powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
					xSpeed: 11,
					xAcc: 0.25,
					animSpeed: 3,
					killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 80,
					curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 63,
					var: array<int> = {0,0,0,0,0,0,16},
					lightType: LIGHT::POINT,
					counterEnd: 70
				),
				spread: SPREAD::NORMAL,
				gradualAim: false,
				pickupAnimation: jjAnimSets[ANIM::AMMO] + 62,
				poweredUpPickupAnimation: jjAnimSets[ANIM::AMMO] + 61,
				powerupAnimation: jjAnimSets[ANIM::PICKUPS] + 66,
				ammoCrateAnimation: jjAnimSets[ANIM::PLUS_COMMON] + 0,
				behavior: function(obj, powerup) {
					obj.behavior = BEHAVIOR::BULLET;
					if (obj.eventID == OBJECT::ICEBULLET)
						obj.eventID = OBJECT::FIREBALLBULLET;
					DefaultSample(obj, WEAPON::GUN8);
				},
				apply: MLLEWeapons::applyFunction(DetermineSpread)
			);
		}
		bool DetermineSpread(uint, se::WeaponHook@, jjSTREAM@ parameter) {
			if (parameter !is null && !parameter.isEmpty()) {
				GradualAim = true;
				uint8 pbyte;
				parameter.pop(pbyte);
                if (pbyte == 0)
                    Spread = SPREAD::GUN8;
				else if (pbyte == 1)
					Spread = SPREAD::PEPPERSPRAY;
				else if (pbyte >= 2) {
					Spread = SPREAD::NORMAL;
					if (pbyte == 2)
						GradualAim = false;
				}
			}
			return true;
		}
	}
	class ElectroBlaster : MLLEWeapons::WeaponInterface {
		ElectroBlaster() {
			super(
				regularObjectTemplate: MLLEWeapons::ObjectTemplate(
					xSpeed: 4,
					curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 75,
					frameID: 4,
					var: array<int> = {0,40,0,0,0,0,2},
					lightType: LIGHT::POINT2,
					counterEnd: 35
				),
				powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
					xSpeed: 4,
					animSpeed: 3,
					curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 75,
					frameID: 4,
					var: array<int> = {0,32,0,0,0,0,2},
					lightType: LIGHT::POINT2,
					counterEnd: 35
				),
				pickupAnimation: jjAnimSets[ANIM::AMMO] + 68,
				poweredUpPickupAnimation: jjAnimSets[ANIM::AMMO] + 67,
				powerupAnimation: jjAnimSets[ANIM::PICKUPS] + 67,
				ammoCrateAnimation: jjAnimSets[ANIM::PLUS_COMMON] + 1,
				traits: se::weapon_default_traits | se::weapon_goes_through_walls | se::weapon_melts_ice,
				behavior: function(obj, powerup) { obj.behavior = BEHAVIOR::ELECTROBULLET; if (powerup) obj.eventID = OBJECT::ELECTROBULLETPU; DefaultSample(obj, WEAPON::GUN9); }
			);
		}
	}
}