Downloads containing weaponVMega4.asc

Downloads
Name Author Game Mode Rating
JJ2+ Only: violetclm DOM Episodes I...Featured Download Violet CLM Custom / Concept 9 Download file
Custom Weapons...Featured Download Violet CLM Other 10 Download file

File preview

#pragma require "weaponVMega4.asc"
#include "MLLE-Weapons.asc"
#pragma require "weaponVMega.j2a"

namespace WeaponVMega {
	namespace Pathfinder {
		class Weapon : MLLEWeapons::WeaponInterface {
			uint node1 = 1, node2 = 4, node3 = 2, node4 = 6;
			Weapon() {
				super(
					regularObjectTemplate: MLLEWeapons::ObjectTemplate(
						xSpeed: 2,
						xAcc: 0.125,
						killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 80,
						counterEnd: 46,
						lightType: LIGHT::POINT2,
						isBlastable: false,
						playerHandling: HANDLING::PARTICLE
					),
					powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
						xSpeed: 1.5,
						xAcc: 0.1875,
						killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 80,
						counterEnd: 32,
						lightType: LIGHT::POINT2,
						curAnim: 1,
						isBlastable: false,
						playerHandling: HANDLING::PARTICLE
					),
					animSetFilename: "weaponVMega.j2a",
					animSetID: 3,
					pickupAnimation: 4,
					poweredUpPickupAnimation: 5,
					style: WEAPON::MISSILE,
					replacedByBubbles: true,
					traits: se::weapon_default_traits | se::weapon_melts_ice | se::weapon_fails_underwater,
					behavior: MLLEWeapons::behaviorFunction(DetermineBehavior),
					apply: MLLEWeapons::applyFunction(DetermineNodeCount)
				);
			}
			void DetermineBehavior(jjOBJ@ obj, bool powerup) const {
				obj.behavior = Behavior(
					obj,
					!powerup ?
						array<uint>={node1,node2} :
						array<uint>={node3,node4}
				);
			}
			bool DetermineNodeCount(uint, se::WeaponHook@, jjSTREAM@ parameter) {
				if (parameter !is null && parameter.getSize() >= 16) {
					int p;
					parameter.pop(p); node1 = p;
					parameter.pop(p); node2 = p;
					parameter.pop(p); node3 = p;
					parameter.pop(p); node4 = p;
				}
				return true;
			}
		}
	
		class Behavior : jjBEHAVIORINTERFACE {
			jjOBJ@ obj;
			array<jjOBJ@> nodes;
			bool waiting = false;
			bool foundAtLeastOneTarget = false;
			uint counter = 0;
			bool powerup;
			array<uint> nodeLimits;
			Behavior(jjOBJ@ objectOfAttachment, array<uint> nl) {
				@obj = @objectOfAttachment;
				obj.state = STATE::FLY;
				powerup = MLLEWeapons::HelpfulBulletFunctions::IsPowerup(obj);
				jjSample(obj.xPos, obj.yPos, powerup ? SOUND::AMMO_LASER3 : SOUND::AMMO_LASER2);
				nodeLimits = nl;
			}
			void destroy() {
				jjSample(obj.xPos, obj.yPos, SOUND::COMMON_ELECTRIC2);
				for (uint i = 0; i < nodes.length; ++i)
					nodes[i].delete();
				obj.delete();
			}
			void onBehave(jjOBJ@) {
				if (obj.state == STATE::EXPLODE) {
					destroy();
					return;
				}
				obj.frameID = (obj.objectID + jjGameTicks / 3) % 3;
				if (++counter >= obj.counterEnd) {
					if (waiting = !waiting) { //stop moving
						addNode();
						counter = obj.counterEnd / 2;
					} else { //start moving
						if (nodes.length > (nodeLimits[foundAtLeastOneTarget ? 1 : 0]) || obj.state == STATE::DONE) {
							destroy();
							return;
						}
						const array<float>@ target = MLLEWeapons::HelpfulBulletFunctions::GetNearestEnemyPosition(obj, 200);
						if (target !is null) {
							obj.var[7] = 0;
							const float standardSpeed = (powerup ? 3.f : 2.5f);
							const float dx = target[0] - obj.xPos, dy = target[1] - obj.yPos;
							foundAtLeastOneTarget = true;
							if (abs(dx) > abs(dy)) {
								obj.xSpeed = (dx > 0) ? standardSpeed : -standardSpeed;
								obj.ySpeed = 0;
							} else {
								obj.xSpeed = 0;
								obj.ySpeed = (dy > 0) ? standardSpeed : -standardSpeed;
							}
						}
						counter = 0;
					}
				}
				if (!waiting) {
					obj.xPos += obj.xSpeed + obj.var[7] / 65536.f;
					obj.yPos += obj.ySpeed;
					if (obj.var[7] > 0x100000)
						obj.var[7] = obj.var[7] - 0x80000;
					else if (obj.var[7] < -0x100000)
						obj.var[7] = obj.var[7] + 0x80000;
					if (MLLEWeapons::HelpfulBulletFunctions::MaskedPixel(obj) && jjEventAtLastMaskedPixel != AREA::ONEWAY && jjEventAtLastMaskedPixel != AREA::HOOK && jjEventAtLastMaskedPixel != AREA::VINE) {
						counter = obj.counterEnd / 2;
						waiting = true;
						addNode();
						obj.state = STATE::DONE;
					}
				}
			}
			void addNode() {
				jjOBJ@ node = jjObjects[jjAddObject(OBJECT::BEES, obj.xPos, obj.yPos, obj.creatorID, obj.creatorType, BEHAVIOR::BEES)];
				node.playerHandling = HANDLING::PLAYERBULLET;
				node.var[6] = 2 | (powerup ? 8 : 0) | 16; //fireball
				node.animSpeed = powerup ? 2 : 1;
				node.curFrame = jjAnimations[obj.curAnim + 2];
				node.state = STATE::FLY;
				node.lightType = LIGHT::BRIGHT;
				node.light = powerup ? 10 : 8;
				node.isTarget = false;
				nodes.insertLast(node);
				jjSample(obj.xPos, obj.yPos, SOUND::COMMON_ELECTRIC1);
			}
			void onDraw(jjOBJ@) {
				jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame + obj.frameID);
				for (uint i = 0; i < nodes.length; ++i) {
					const jjOBJ@ node = nodes[i];
					const jjOBJ@ node2 = (i < nodes.length - 1) ? nodes[i + 1] : obj;
					if (node.xPos == node2.xPos || node.yPos == node2.yPos) //non-diagonal
						jjDrawRectangle(node.xPos, node.yPos, int(node2.xPos - node.xPos) + 1, int(node2.yPos - node.yPos) + 1, 15);
					jjDrawSpriteFromCurFrame(node.xPos, node.yPos, node.curFrame + obj.frameID);
				}
			}
		}
	}
}