Downloads containing arcaneweapons.mut

Downloads
Name Author Game Mode Rating
JJ2+ Only: Arcane WeaponsFeatured Download PurpleJazz Mutator 10 Download file

File preview

#pragma name "Arcane Weapons"
#pragma require "Meteor.j2a"
#pragma require "expmine.wav"
#pragma require "CosmicDust.j2a"
#pragma require "lowind.wav"
#pragma require "Mortar.j2a"
#pragma require "f_gren4.wav"
#pragma require "Nail.j2a"
#pragma require "f_ar3.wav"
#pragma require "TornadoGun.j2a"
#pragma require "Lightningrod.j2a"
#pragma require "ZAPFIZZ1.wav"
#pragma require "ZAPFIZZ2.wav"
#pragma require "Syringe.j2a"
#pragma require "FusionCannon.j2a"
#pragma require "f_fus1.wav"
#pragma require "f_fus3.wav"

bool gameIsActive() {
	return jjGameState == GAME::STARTED || jjGameState == GAME::OVERTIME;
}

void onLevelLoad() {
	jjAnimSets[ANIM::CUSTOM[22]].load(0, "Meteor.j2a");
	jjAnimations[jjAnimSets[ANIM::AMMO] + 24] = jjAnimations[jjAnimSets[ANIM::CUSTOM[22]] + 1];
	jjAnimations[jjAnimSets[ANIM::AMMO] + 25] = jjAnimations[jjAnimSets[ANIM::CUSTOM[22]] + 2];
	
	jjObjectPresets[OBJECT::BOUNCERBULLET].behavior = jjObjectPresets[OBJECT::BOUNCERBULLETPU].behavior = Meteor();
	jjObjectPresets[OBJECT::BOUNCERBULLET].special = jjObjectPresets[OBJECT::BOUNCERBULLET].determineCurAnim(ANIM::CUSTOM[22], 1);
	jjObjectPresets[OBJECT::BOUNCERBULLETPU].special = jjObjectPresets[OBJECT::BOUNCERBULLETPU].determineCurAnim(ANIM::CUSTOM[22], 0);
	jjObjectPresets[OBJECT::BOUNCERBULLET].ySpeed = jjObjectPresets[OBJECT::BOUNCERBULLETPU].ySpeed = jjObjectPresets[OBJECT::BLASTERBULLET].ySpeed;
	jjObjectPresets[OBJECT::BOUNCERBULLETPU].killAnim = jjObjectPresets[OBJECT::SEEKERBULLET].killAnim;
	jjObjectPresets[OBJECT::BOUNCERBULLET].lightType = LIGHT::POINT;
	jjObjectPresets[OBJECT::BOUNCERBULLETPU].lightType = LIGHT::BRIGHT;
	jjObjectPresets[OBJECT::BOUNCERBULLET].light = jjObjectPresets[OBJECT::BOUNCERBULLETPU].light = 10;
	
	jjObjectPresets[OBJECT::BOUNCERAMMO15].determineCurAnim(ANIM::CUSTOM[22], 3);
	jjObjectPresets[OBJECT::BOUNCERAMMO15].determineCurFrame();
	
	jjObjectPresets[OBJECT::BOUNCERPOWERUP].determineCurAnim(ANIM::CUSTOM[22], 4);
	jjObjectPresets[OBJECT::BOUNCERPOWERUP].determineCurFrame();
	
	jjWeapons[WEAPON::BOUNCER].defaultSample = false;
	jjWeapons[WEAPON::BOUNCER].style = WEAPON::MISSILE;
	
	jjSampleLoad(SOUND::ORANGE_BOEMR, "expmine.wav");
	
	jjAnimSets[ANIM::CUSTOM[23]].load(0, "CosmicDust.j2a");
	jjAnimations[jjAnimSets[ANIM::AMMO] + 28] = jjAnimations[jjAnimSets[ANIM::CUSTOM[23]] + 1];
	jjAnimations[jjAnimSets[ANIM::AMMO] + 29] = jjAnimations[jjAnimSets[ANIM::CUSTOM[23]] + 2];
	
	jjObjectPresets[OBJECT::ICEBULLET].behavior = jjObjectPresets[OBJECT::ICEBULLETPU].behavior = CosmicDust();
	jjObjectPresets[OBJECT::ICEBULLET].counterEnd = jjObjectPresets[OBJECT::ICEBULLETPU].counterEnd = 180;
	jjObjectPresets[OBJECT::ICEBULLET].special = jjObjectPresets[OBJECT::ICEBULLET].determineCurAnim(ANIM::CUSTOM[23], 1);
	jjObjectPresets[OBJECT::ICEBULLETPU].special = jjObjectPresets[OBJECT::ICEBULLETPU].determineCurAnim(ANIM::CUSTOM[23], 0);
	jjObjectPresets[OBJECT::ICEBULLET].lightType = jjObjectPresets[OBJECT::ICEBULLETPU].lightType = LIGHT::BRIGHT;
	jjObjectPresets[OBJECT::ICEBULLET].light = 8;
	jjObjectPresets[OBJECT::ICEBULLETPU].light = 12;

	jjObjectPresets[OBJECT::ICEAMMO15].determineCurAnim(ANIM::CUSTOM[23], 3);
	jjObjectPresets[OBJECT::ICEAMMO15].determineCurFrame();
	
	jjObjectPresets[OBJECT::ICEPOWERUP].determineCurAnim(ANIM::CUSTOM[23], 4);
	jjObjectPresets[OBJECT::ICEPOWERUP].determineCurFrame();
	
	jjObjectPresets[OBJECT::DESTRUCTSCENERY].triggersTNT = false;
	
	jjWeapons[WEAPON::ICE].multiplier = 16;
	jjWeapons[WEAPON::ICE].style = WEAPON::POPCORN;
	jjWeapons[WEAPON::ICE].spread = SPREAD::NORMAL;
	jjWeapons[WEAPON::ICE].defaultSample = false;
	
	jjSampleLoad(SOUND::COMMON_FLAMER, "lowind.wav");
	
	jjAnimSets[ANIM::CUSTOM[24]].load(0, "Mortar.j2a");
	jjAnimations[jjAnimSets[ANIM::AMMO] + 34] = jjAnimations[jjAnimSets[ANIM::CUSTOM[24]] + 1];
	jjAnimations[jjAnimSets[ANIM::AMMO] + 33] = jjAnimations[jjAnimSets[ANIM::CUSTOM[24]] + 3];
	
	jjObjectPresets[OBJECT::SEEKERBULLET].behavior = jjObjectPresets[OBJECT::SEEKERBULLETPU].behavior = Mortar();
	jjObjectPresets[OBJECT::SEEKERBULLET].xSpeed = 7;
	jjObjectPresets[OBJECT::SEEKERBULLET].ySpeed = -9;
	jjObjectPresets[OBJECT::SEEKERBULLETPU].xSpeed = 7;
	jjObjectPresets[OBJECT::SEEKERBULLETPU].ySpeed = -10;
	jjObjectPresets[OBJECT::SEEKERBULLET].counterEnd = 90;
	jjObjectPresets[OBJECT::SEEKERBULLETPU].counterEnd = 105;
	
	jjObjectPresets[OBJECT::SEEKERAMMO15].determineCurAnim(ANIM::CUSTOM[24], 4);
	jjObjectPresets[OBJECT::SEEKERAMMO15].determineCurFrame();
	
	jjObjectPresets[OBJECT::SEEKERPOWERUP].determineCurAnim(ANIM::CUSTOM[24], 5);
	jjObjectPresets[OBJECT::SEEKERPOWERUP].determineCurFrame();
	
	jjWeapons[WEAPON::SEEKER].defaultSample = false;
	
	jjSampleLoad(SOUND::P2_TONG, "f_gren4.wav");
	
	jjAnimSets[ANIM::CUSTOM[25]].load(0, "Nail.j2a");
	
	jjAnimations[jjAnimSets[ANIM::AMMO] + 49] = jjAnimations[jjAnimSets[ANIM::CUSTOM[25]] + 4];
	jjAnimations[jjAnimSets[ANIM::AMMO] + 48] = jjAnimations[jjAnimSets[ANIM::CUSTOM[25]] + 5];
	
	jjSampleLoad(SOUND::P2_CRUNCH, "f_ar3.wav");
	
	jjObjectPresets[OBJECT::RFBULLET].behavior = jjObjectPresets[OBJECT::RFBULLETPU].behavior = Nailgun();
	jjObjectPresets[OBJECT::RFBULLET].var[6] = 16;
	jjObjectPresets[OBJECT::RFBULLET].counterEnd = 60;
	jjObjectPresets[OBJECT::RFBULLET].killAnim = jjObjectPresets[OBJECT::BLASTERBULLET].killAnim;
	jjObjectPresets[OBJECT::RFBULLET].special = jjObjectPresets[OBJECT::RFBULLET].determineCurAnim(ANIM::CUSTOM[25], 0);
	jjObjectPresets[OBJECT::RFBULLETPU].var[6] = 8 + 16;
	jjObjectPresets[OBJECT::RFBULLETPU].counterEnd = 55;
	jjObjectPresets[OBJECT::RFBULLETPU].killAnim = jjObjectPresets[OBJECT::BLASTERBULLET].killAnim;
	jjObjectPresets[OBJECT::RFBULLETPU].special = jjObjectPresets[OBJECT::RFBULLETPU].determineCurAnim(ANIM::CUSTOM[25], 1);
	jjObjectPresets[OBJECT::RFBULLET].lightType = jjObjectPresets[OBJECT::RFBULLETPU].lightType = LIGHT::POINT;
	
	jjObjectPresets[OBJECT::RFAMMO3].lightType = LIGHT::POINT;
	
	jjObjectPresets[OBJECT::RFAMMO15].determineCurAnim(ANIM::CUSTOM[25], 2);
	jjObjectPresets[OBJECT::RFAMMO15].determineCurFrame();
	
	jjObjectPresets[OBJECT::RFPOWERUP].determineCurAnim(ANIM::CUSTOM[25], 3);
	jjObjectPresets[OBJECT::RFPOWERUP].determineCurFrame();
	
	jjWeapons[WEAPON::RF].spread = SPREAD::NORMAL;
	jjWeapons[WEAPON::RF].style = WEAPON::NORMAL;
	jjWeapons[WEAPON::RF].defaultSample = false;
	
	jjANIMATION@ anim = jjAnimations[jjAnimSets[ANIM::AMMO] + 71];
	for (uint i = 0; i < anim.frameCount; ++i) {
		jjANIMFRAME@ frame = jjAnimFrames[anim + i];
		jjPIXELMAP sprite(frame);
		for (uint x = 0; x < sprite.width; ++x)
			for (uint y = 0; y < sprite.height; ++y)
			if (sprite[x,y] != 0) sprite[x,y] = 0;
		sprite.save(frame);
	}
	
	jjAnimSets[ANIM::CUSTOM[26]].load(0, "TornadoGun.j2a");
	jjAnimations[jjAnimSets[ANIM::AMMO] + 57] = jjAnimations[jjAnimSets[ANIM::CUSTOM[26]] + 3];
	jjAnimations[jjAnimSets[ANIM::AMMO] + 56] = jjAnimations[jjAnimSets[ANIM::CUSTOM[26]] + 2];
	
	jjObjectPresets[OBJECT::TOASTERBULLET].behavior = TornadoGun();
	jjObjectPresets[OBJECT::TOASTERBULLET].special = jjObjectPresets[OBJECT::TOASTERBULLET].determineCurAnim(ANIM::CUSTOM[26], 0);
	jjObjectPresets[OBJECT::TOASTERBULLET].xSpeed = 4;
	jjObjectPresets[OBJECT::TOASTERBULLET].counterEnd = 110;
	jjObjectPresets[OBJECT::TOASTERBULLET].var[6] = 0;
	jjObjectPresets[OBJECT::TOASTERBULLET].freeze = 0;
	jjObjectPresets[OBJECT::TOASTERBULLET].eventID = OBJECT::FIREBALLBULLET;
	jjObjectPresets[OBJECT::TOASTERBULLET].lightType = jjObjectPresets[OBJECT::FIREBALLBULLET].lightType;
	jjObjectPresets[OBJECT::TOASTERBULLET].killAnim = jjObjectPresets[OBJECT::ICEBULLET].killAnim;
	jjObjectPresets[OBJECT::TOASTERBULLET].lightType = LIGHT::POINT;
	
	jjObjectPresets[OBJECT::TOASTERBULLETPU].behavior = TornadoGunPU();
	jjObjectPresets[OBJECT::TOASTERBULLETPU].special = jjObjectPresets[OBJECT::TOASTERBULLETPU].determineCurAnim(ANIM::CUSTOM[26], 1);
	jjObjectPresets[OBJECT::TOASTERBULLETPU].xSpeed = 6;
	jjObjectPresets[OBJECT::TOASTERBULLETPU].counterEnd = 120;
	jjObjectPresets[OBJECT::TOASTERBULLETPU].var[6] = 8;
	jjObjectPresets[OBJECT::TOASTERBULLETPU].freeze = 0;
	jjObjectPresets[OBJECT::TOASTERBULLETPU].eventID = OBJECT::FIREBALLBULLET;
	jjObjectPresets[OBJECT::TOASTERBULLETPU].killAnim = jjObjectPresets[OBJECT::ICEBULLET].killAnim;
	jjObjectPresets[OBJECT::TOASTERBULLETPU].lightType = LIGHT::POINT2;
	
	jjObjectPresets[OBJECT::TOASTERPOWERUP].determineCurAnim(ANIM::CUSTOM[26], 4);
	jjObjectPresets[OBJECT::TOASTERPOWERUP].determineCurFrame();
	
	jjObjectPresets[OBJECT::TOASTERAMMO15].determineCurAnim(ANIM::CUSTOM[26], 5);
	jjObjectPresets[OBJECT::TOASTERAMMO15].determineCurFrame();

	jjWeapons[WEAPON::TOASTER].defaultSample = false;
	jjWeapons[WEAPON::TOASTER].replacedByBubbles = false;
	jjWeapons[WEAPON::TOASTER].spread = SPREAD::NORMAL;
	jjWeapons[WEAPON::TOASTER].style = WEAPON::NORMAL;
	jjWeapons[WEAPON::TOASTER].multiplier = 1;
	
	jjAnimSets[ANIM::CUSTOM[27]].load(0, "Lightningrod.j2a");
	jjAnimations[jjAnimSets[ANIM::AMMO] + 59] = jjAnimations[jjAnimSets[ANIM::CUSTOM[27]] + 0];
	
	jjObjectPresets[OBJECT::TNT].behavior = Lightningrod();
	jjObjectPresets[OBJECT::TNT].determineCurAnim(ANIM::CUSTOM[27], 0);
	jjObjectPresets[OBJECT::TNT].playerHandling = HANDLING::PARTICLE;
	jjObjectPresets[OBJECT::TNT].bulletHandling = HANDLING::IGNOREBULLET;
	jjObjectPresets[OBJECT::TNT].counterEnd = 255;
	
	jjObjectPresets[OBJECT::TNTAMMO3].behavior = LightningrodPickup();
	jjObjectPresets[OBJECT::TNTAMMO3].scriptedCollisions = true;
	jjObjectPresets[OBJECT::TNTAMMO3].determineCurAnim(ANIM::CUSTOM[27], 0);
	jjWeapons[WEAPON::TNT].maximum = 10;
	
	jjSampleLoad(SOUND::COMMON_ELECTRICHIT, "ZAPFIZZ1.wav");
	jjSampleLoad(SOUND::COMMON_ELECTRIC2, "ZAPFIZZ2.wav");
	
	jjAnimSets[ANIM::HATTER].load();
	jjAnimSets[ANIM::MONKEY].load();
	jjAnimSets[ANIM::CUSTOM[28]].load(0, "Syringe.j2a");
	
	jjAnimations[jjAnimSets[ANIM::AMMO] + 62] = jjAnimations[jjAnimSets[ANIM::CUSTOM[28]] + 0];
	jjAnimations[jjAnimSets[ANIM::AMMO] + 61] = jjAnimations[jjAnimSets[ANIM::CUSTOM[28]] + 1];
	jjAnimations[jjAnimSets[ANIM::PLUS_COMMON] + 0] = jjAnimations[jjAnimSets[ANIM::CUSTOM[28]] + 3]; //gun 8 crate

	jjObjectPresets[OBJECT::FIREBALLBULLET].behavior = jjObjectPresets[OBJECT::FIREBALLBULLETPU].behavior = BloodSpear();
	jjObjectPresets[OBJECT::FIREBALLBULLET].ySpeed = -1.5;
	jjObjectPresets[OBJECT::FIREBALLBULLET].xSpeed = 8;
	jjObjectPresets[OBJECT::FIREBALLBULLET].counterEnd = 85;
	jjObjectPresets[OBJECT::FIREBALLBULLET].var[6] = 0;
	jjObjectPresets[OBJECT::FIREBALLBULLETPU].ySpeed = -2;
	jjObjectPresets[OBJECT::FIREBALLBULLETPU].xSpeed = 8.5;
	jjObjectPresets[OBJECT::FIREBALLBULLETPU].counterEnd = 95;
	jjObjectPresets[OBJECT::FIREBALLBULLETPU].var[6] = 8;
	
	jjObjectPresets[OBJECT::GUN8POWERUP].determineCurAnim(ANIM::CUSTOM[28], 2, true);
	jjObjectPresets[OBJECT::GUN8POWERUP].determineCurFrame();

	jjWeapons[WEAPON::GUN8].gradualAim = false;
	jjWeapons[WEAPON::GUN8].defaultSample = false;
	jjWeapons[WEAPON::GUN8].replacedByBubbles = true;
	
	jjAnimSets[ANIM::CUSTOM[29]].load(0, "FusionCannon.j2a");
	jjAnimations[jjAnimSets[ANIM::AMMO] + 68] = jjAnimations[jjAnimSets[ANIM::CUSTOM[29]] + 0];
	jjAnimations[jjAnimSets[ANIM::AMMO] + 67] = jjAnimations[jjAnimSets[ANIM::CUSTOM[29]] + 1];
	jjAnimations[jjAnimSets[ANIM::PLUS_COMMON] + 1] = jjAnimations[jjAnimSets[ANIM::CUSTOM[29]] + 3]; //gun 9 crate

	jjObjectPresets[OBJECT::ELECTROBULLET].behavior = jjObjectPresets[OBJECT::ELECTROBULLETPU].behavior = FusionCannon();
	jjObjectPresets[OBJECT::ELECTROBULLET].counterEnd = jjObjectPresets[OBJECT::ELECTROBULLETPU].counterEnd = 255;
	jjObjectPresets[OBJECT::ELECTROBULLET].eventID = jjObjectPresets[OBJECT::BLASTERBULLET].eventID;
	jjObjectPresets[OBJECT::ELECTROBULLET].eventID = jjObjectPresets[OBJECT::BLASTERBULLETPU].eventID;
	jjObjectPresets[OBJECT::ELECTROBULLET].killAnim = jjObjectPresets[OBJECT::ELECTROBULLETPU].killAnim = jjObjectPresets[OBJECT::ICEBULLET].killAnim;
	jjObjectPresets[OBJECT::ELECTROBULLET].var[6] = 2 + 16;
	jjObjectPresets[OBJECT::ELECTROBULLETPU].var[6] = 2 + 8 + 16;

	jjObjectPresets[OBJECT::GUN9AMMO3].behavior = FusionPickup();
	jjObjectPresets[OBJECT::GUN9AMMO3].determineCurFrame();
	jjObjectPresets[OBJECT::GUN9AMMO3].scriptedCollisions = true;
	
	jjObjectPresets[OBJECT::GUN9POWERUP].determineCurAnim(ANIM::CUSTOM[29], 2);
	jjObjectPresets[OBJECT::GUN9POWERUP].determineCurFrame();
	
	jjWeapons[WEAPON::GUN9].style = WEAPON::CAPPED;
	jjWeapons[WEAPON::GUN9].maximum = 25;
	
	jjSampleLoad(SOUND::AMMO_LASER2, "f_fus1.wav");
	jjSampleLoad(SOUND::AMMO_LASER3, "f_fus3.wav");
}

class Meteor : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::BULLET, obj.state == STATE::EXPLODE? true:false);
		jjPLAYER@ creator = jjPlayers[obj.creatorID];
		
		if (obj.state != STATE::EXPLODE) {
			if (obj.counter == 1 && creator.isLocal) {
				jjSample(creator.xPos, creator.yPos, SOUND::ORANGE_BOEMR, 42, obj.eventID == OBJECT::BOUNCERBULLET? 22000 : 20000);
				obj.var[2] = 0;
			}
			obj.age += obj.direction == 0? 10 : 10 * obj.direction;
			
			jjDrawRotatedSprite(obj.xPos, obj.yPos, ANIM::CUSTOM[22], obj.eventID == OBJECT::BOUNCERBULLET? 1:0, 0, -obj.age, 1, 1, obj.eventID == OBJECT::BOUNCERBULLET || obj.var[4] == 1? SPRITE::SINGLEHUE : SPRITE::NORMAL, 72);
			
			jjPARTICLE@ smoke = jjAddParticle(PARTICLE::SMOKE);
			if (smoke !is null) {
				smoke.xPos = smoke.xPos;
				smoke.yPos = smoke.yPos;
			}
			
			if (obj.eventID == OBJECT::BOUNCERBULLETPU && obj.var[4] == 0) {
				jjDrawRotatedSprite(obj.xPos, obj.yPos, ANIM::CUSTOM[22], 0, 0, -obj.age, 1, 1, SPRITE::TRANSLUCENTSINGLEHUE, 40);
				jjPARTICLE@ cinders = jjAddParticle(PARTICLE::FIRE);
				if (cinders !is null) {
					cinders.xPos = int(obj.xPos - 8) + jjRandom()%17;
					cinders.yPos = int(obj.yPos - 8) + jjRandom()%17;
				}
			}
			
			if (obj.yPos > jjWaterLevel) {
				obj.var[4] = 1;
				obj.xSpeed = obj.xSpeed * 0.875;
				obj.ySpeed = obj.ySpeed * 0.875;
			}
		
			switch (obj.direction) {
				case 1: obj.xSpeed -= obj.eventID == OBJECT::BOUNCERBULLET? 0.1:0.15; obj.ySpeed += obj.eventID == OBJECT::BOUNCERBULLET? 0.15:0.2; break;
				case -1: obj.xSpeed += obj.eventID == OBJECT::BOUNCERBULLET? 0.1:0.15; obj.ySpeed += obj.eventID == OBJECT::BOUNCERBULLET? 0.15:0.2; break;
			}
			
			if (obj.xSpeed == 0) obj.ySpeed += 0.4;
			if (obj.ySpeed > 8) obj.ySpeed = 8;
			

			
		} else {
			obj.age = 0;
			if (obj.var[2] == 0) {
				jjSample(obj.xPos, obj.yPos, SOUND::COMMON_BENZIN1, 0, 0);
				obj.var[2] = 1;
				
				if (obj.eventID == OBJECT::BOUNCERBULLETPU) {
					for (int i = -1; i <= 1; i+= 2) {
					Rock temp;
						jjOBJ@ rock = jjObjects[jjAddObject(OBJECT::SHARD, int(obj.xPos + (i * 12)), int(obj.yPos - 8), obj.creatorID, CREATOR::PLAYER, jjVOIDFUNCOBJ(temp.onBehave))];
						rock.determineCurAnim(ANIM::CUSTOM[22], 1);
						rock.playerHandling = HANDLING::PLAYERBULLET;
						rock.var[3] = 2;
						rock.var[4] = obj.var[4];
						rock.var[6] = 8;
						rock.animSpeed = 2;
						rock.direction = i;
						rock.xSpeed = 6 * i;
						rock.ySpeed = -3;
						rock.state = STATE::FLY;
						rock.lightType = LIGHT::POINT;
						rock.light = 10;
						rock.counterEnd = jjObjectPresets[OBJECT::BOUNCERBULLET].counterEnd;
						rock.killAnim = jjObjectPresets[OBJECT::BOUNCERBULLET].killAnim;
					}
				}
			}
		}
	}
}

class Rock : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::BULLET, obj.state == STATE::EXPLODE? true:false);
		
		if (obj.state == STATE::FLY) {
			obj.age += obj.direction == 0? 10 : 10 * obj.direction;
			jjDrawRotatedSprite(obj.xPos, obj.yPos, ANIM::CUSTOM[22], 1, 0, -obj.age, 1, 1, obj.var[4] == 1? SPRITE::SINGLEHUE : SPRITE::NORMAL, 72);
			
			switch (obj.direction) {
				case 1: obj.xSpeed -= 0.05; obj.ySpeed += 0.1; break;
				case -1: obj.xSpeed += 0.05; obj.ySpeed += 0.1; break;
			}
			
			if (obj.yPos > jjWaterLevel) {
				obj.var[4] = 1;
				obj.xSpeed = obj.xSpeed * 0.875;
				obj.ySpeed = obj.ySpeed * 0.875;
			}
			
			jjPARTICLE@ smoke = jjAddParticle(PARTICLE::SMOKE);
			if (smoke !is null) {
				smoke.xPos = obj.xPos;
				smoke.yPos = obj.yPos;
			}
			
		}
		
	}
}

class CosmicDust : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(obj.state == STATE::EXPLODE? BEHAVIOR::BULLET : BEHAVIOR::TNT, false);
		jjPLAYER@ creator = jjPlayers[obj.creatorID];
		obj.var[0] = obj.var[0] + (5 * obj.direction);
		
		if (obj.state != STATE::EXPLODE) {
			if (obj.counter > 1) {
				jjDrawRotatedSprite(obj.xPos, obj.yPos, ANIM::CUSTOM[23], obj.eventID == OBJECT::ICEBULLETPU? 0:1, 0, -obj.var[0], 1, 1, SPRITE::ALPHAMAP, obj.eventID == OBJECT::ICEBULLETPU? 34:72);
				jjDrawRotatedSprite(obj.xPos, obj.yPos, ANIM::CUSTOM[23], obj.eventID == OBJECT::ICEBULLETPU? 0:1, 0, -obj.var[0], 1, 1, SPRITE::ALPHAMAP, obj.eventID == OBJECT::ICEBULLETPU? 34:72);
			}
			obj.xPos = creator.xPos + (obj.eventID == OBJECT::ICEBULLETPU? 160:120)*jjSin((obj.counter + 1)*12) * (obj.direction != 0? obj.direction : 1);
			obj.yPos = creator.yPos - (obj.eventID == OBJECT::ICEBULLETPU? 80:60)*jjCos((obj.counter + 1)*12);
		} else {
			obj.delete();
		}
	}
}

class Mortar : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(obj.state == STATE::EXPLODE? BEHAVIOR::RFBULLET : BEHAVIOR::BULLET, false);
		jjPLAYER@ creator = jjPlayers[obj.creatorID];
		obj.var[0] = int(atan2(-obj.ySpeed, obj.xSpeed) * (512.f * 0.318309886142228f));
		obj.var[5] = obj.eventID == OBJECT::SEEKERBULLETPU? 2:1;
		
		switch (obj.state) {
			case STATE::START:
				obj.state = STATE::FLY;
				obj.lightType = LIGHT::POINT;
				obj.var[2] = 0;
			break;
			
			case STATE::FLY:
				if (obj.counter == 1 && creator.isLocal) {
					jjSample(creator.xPos, creator.yPos, SOUND::P2_TONG, 0, 0);
				}
				
				jjDrawRotatedSprite(obj.xPos, obj.yPos, ANIM::CUSTOM[24], obj.eventID == OBJECT::SEEKERBULLETPU? 2:0, jjGameTicks >> 2, obj.var[0], 0.75, 0.75, SPRITE::NORMAL);
				
				if (obj.counter % 5 == 0 && !jjLowDetail) {
					jjOBJ@ trail = jjObjects[jjAddObject(OBJECT::EXPLOSION, int(obj.xPos - jjCos(obj.var[0])), int(obj.yPos - jjSin(obj.var[0])))];
					trail.determineCurAnim(ANIM::AMMO, 3);
					trail.lightType = LIGHT::NONE;
					trail.playerHandling = HANDLING::PARTICLE;
					trail.bulletHandling = HANDLING::IGNOREBULLET;
					trail.isBlastable = false;
				}
				
				switch (obj.direction) {
					case 1: obj.xSpeed -= 0.275; obj.ySpeed += 0.225; break;
					case -1: obj.xSpeed += 0.275; obj.ySpeed += 0.225; break;
				}
				if (obj.xSpeed == 0) obj.ySpeed += 0.3;
				if (obj.ySpeed > 12) obj.ySpeed = 12;
			break;
			
			case STATE::EXPLODE:
				jjDrawResizedSprite(obj.xPos, obj.yPos, ANIM::AMMO, 5, obj.curFrame + 5, 2, 2, SPRITE::NORMAL);
			
				if (obj.var[2] == 0) {
					MortarShockwave temp;
					jjOBJ@ blast = jjObjects[jjAddObject(OBJECT::BULLET, obj.xPos, obj.yPos, obj.creatorID, CREATOR::PLAYER, jjVOIDFUNCOBJ(temp.onBehave))];
					obj.var[2] = 1;
					blast.var[2] = 1;
					blast.var[5] = obj.var[5];
				}
			break;
		}
	}
}

class MortarShockwave : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		jjPLAYER@ creator = jjPlayers[obj.creatorID];
		
		obj.playerHandling = HANDLING::PARTICLE;
		obj.bulletHandling = HANDLING::IGNOREBULLET;
		obj.animSpeed = 1;
		
		if (obj.var[2] == 1) {
			obj.lightType = obj.var[2] == 1? LIGHT::RING2 : LIGHT::NONE;
			obj.var[1] = obj.var[1] + 1;
			obj.light += 2;
			obj.var[4] = obj.light * 4;
			
			for (int i = 1; i < jjObjectCount; i++) {
				jjOBJ@ target = jjObjects[i];
				float dx = target.xPos - obj.xPos, dy = target.yPos - obj.yPos;
				if ((target.eventID == OBJECT::TNT || target.behavior == BEHAVIOR::MONITOR || target.behavior == BEHAVIOR::AMMO15 || target.eventID == OBJECT::GUNCRATE || target.eventID == OBJECT::GEMCRATE || target.eventID == OBJECT::CARROTCRATE || target.playerHandling == HANDLING::ENEMY || target.eventID == OBJECT::DESTRUCTSCENERY) && target.var[4] == 0) {
					if (dx * dx + dy * dy < obj.var[4] * obj.var[4]) {
						if (target.eventID != OBJECT::TNT) {
							obj.objectHit(target, target.playerHandling == HANDLING::ENEMY? HANDLING::ENEMY : HANDLING::SPECIAL);
							if (target.playerHandling != HANDLING::ENEMY) target.state = STATE::KILL;
						}
						else target.state = STATE::EXPLODE;
						if (target.playerHandling != HANDLING::ENEMY) target.var[4] = 1;
					}
					else target.var[4] = 0;
				}
				else if ((target.behavior == BEHAVIOR::PICKUP || target.eventID == OBJECT::TNTAMMO3 || target.eventID == OBJECT::GUN9AMMO3) && target.state == STATE::FLOAT) {
					if (dx * dx + dy * dy < obj.var[4] * obj.var[4])
						target.state = STATE::FLOATFALL;
				}
			}
			
			float pdx = jjLocalPlayers[0].xPos - obj.xPos, pdy = jjLocalPlayers[0].yPos - obj.yPos;
			if ((pdx * pdx + pdy * pdy < 64 * 64) && obj.curFrame < 2105) {
				jjLocalPlayers[0].xSpeed = jjLocalPlayers[0].xPos > obj.xPos? 8:-8;
				jjLocalPlayers[0].ySpeed = jjLocalPlayers[0].yPos > obj.yPos? 8:-8;
			}
			
			if (jjIsServer && gameIsActive()) {
				for (int i = 0; i < 32; i++) {
					jjPLAYER@ player = jjPlayers[i];
					if (
						player.isActive && player.isInGame && player.health > 0 && player !is creator && creator.blink == 0 && 
							(jjGameMode != GAME::CTF || jjFriendlyFire || player.team != creator.team)
					) {
						float dx = player.xPos - obj.xPos, dy = player.yPos - obj.yPos;
						if (dx * dx + dy * dy < obj.var[4] * obj.var[4]) {
							if (obj.var[8] & 1 << i == 0) {
								player.hurt(obj.var[5], false, creator);
								obj.var[8] = obj.var[8] | 1 << i;
							}
						}
					}
				}
			}
		}
		
		if (obj.var[1] == 14) {
			obj.var[1] = 0;
			obj.var[2] = 0;
			obj.var[4] = 0;
			obj.delete();
		}
	}
}

class Nailgun : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(obj.state == STATE::EXPLODE? BEHAVIOR::BULLET : BEHAVIOR::RFBULLET, obj.state == STATE::EXPLODE? true:false);
		jjPLAYER@ creator = jjPlayers[obj.creatorID];
		
		obj.var[0] = int(atan2(-obj.ySpeed, obj.xSpeed) * (512.f * 0.318309886142228f));
		
		obj.xAcc = (obj.eventID == OBJECT::RFBULLETPU? 0.4:0.35) * obj.direction;
		if (obj.ySpeed < 0 && obj.direction == 0 && obj.xSpeed == 0) obj.yAcc = -0.5;
		
		
		if (obj.state != STATE::EXPLODE) {
			if (obj.counter == 1 && creator.isLocal) {
				jjSample(creator.xPos, creator.yPos, SOUND::P2_CRUNCH, 48, obj.eventID == OBJECT::RFBULLETPU? 19000:17500);
				obj.var[2] = 0;
				obj.playerHandling = HANDLING::PLAYERBULLET;
			}
			
			jjDrawRotatedSprite(obj.xPos, obj.yPos, ANIM::CUSTOM[25], obj.eventID == OBJECT::RFBULLETPU? 1:0, 0, obj.var[0], 1, 1, SPRITE::NORMAL);
			
			float dx = jjLocalPlayers[0].xPos - obj.xPos, dy = jjLocalPlayers[0].yPos - obj.yPos;
			if ((dx * dx + dy * dy < 64 * 24) && !creator.isLocal && jjLocalPlayers[0].blink == 0 && (jjLocalPlayers[0].team != creator.team || jjFriendlyFire || jjGameMode != GAME::CTF) && gameIsActive()) {
				jjLocalPlayers[0].xPos = obj.xPos - (24 * obj.direction);
				jjLocalPlayers[0].ySpeed = obj.ySpeed;
			}
			
			if (jjMaskedPixel(int(obj.xPos + obj.xSpeed + obj.var[7] / 65536.f), int(obj.yPos))) {
				obj.xSpeed = 0;
				obj.var[7] = 0;
				obj.playerHandling = HANDLING::PARTICLE;
				obj.bePlatform(obj.xPos, obj.yPos, 32, 8);
				if (obj.var[2] == 0) {
					jjSample(obj.xPos, obj.yPos, SOUND::COMMON_METALHIT, 0, 0);
					obj.counter = 1;
					if (obj.eventID == OBJECT::RFBULLETPU) obj.counterEnd = 90;
					obj.var[2] = 1;
				}
			}
			else if (jjMaskedPixel(int(obj.xPos), int(obj.yPos + obj.ySpeed))) {
				obj.ySpeed = 0;
				obj.playerHandling = HANDLING::PARTICLE;
				if (obj.var[2] == 0) {
					jjSample(obj.xPos, obj.yPos, SOUND::COMMON_METALHIT, 0, 0);
					obj.counter = 1;
					if (obj.eventID == OBJECT::RFBULLETPU) obj.counterEnd = 90;
					obj.var[2] = 1;
				}
			}
		} else {
			obj.clearPlatform();
			obj.var[2] = 0;
			obj.counterEnd = obj.eventID == OBJECT::RFBULLETPU? 55:60;
		}
	}
}

class TornadoGun : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::BULLET);
		jjPLAYER@ creator = jjPlayers[obj.creatorID];
		if (obj.state == STATE::FLY) {
			if (obj.counter == 1 && creator.isLocal) {
				jjSample(creator.xPos, creator.yPos, SOUND::INTRO_BLOW, 48, 25000);
				jjSample(creator.xPos, creator.yPos, SOUND::COMMON_BIRDFLY, 48, 25000);
			}
			
			switch (obj.direction) {
				case 1: obj.xSpeed = obj.xSpeed - 0.05; obj.ySpeed = obj.ySpeed - 0.1; break;
				case -1: obj.xSpeed = obj.xSpeed + 0.05; obj.ySpeed = obj.ySpeed - 0.1; break;
			}
			
			float pdx = jjLocalPlayers[0].xPos - obj.xPos, pdy = jjLocalPlayers[0].yPos - obj.yPos;
			if ((pdx * pdx + pdy * pdy < 64 * 64) && !creator.isLocal && jjLocalPlayers[0].blink == 0 && (jjLocalPlayers[0].team != creator.team || jjFriendlyFire || jjGameMode != GAME::CTF) && gameIsActive()) {
				jjLocalPlayers[0].ySpeed -= 2.5;
				jjLocalPlayers[0].xSpeed += 2.5 * obj.direction;
			}
		}
		if (obj.state == STATE::EXPLODE) {
			if (obj.var[0] == 0) {
				jjSample(obj.xPos, obj.yPos, SOUND::COMMON_SWISH4, 36, 15000);
				obj.var[0] = 1;
			}
		}
	}
}

class TornadoGunPU : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::BULLET);
		jjPLAYER@ creator = jjPlayers[obj.creatorID];
		if (obj.state == STATE::FLY) {
			if (obj.counter == 1 && creator.isLocal) {
				jjSample(creator.xPos, creator.yPos, SOUND::INTRO_BLOW, 48, 30000);
				jjSample(creator.xPos, creator.yPos, SOUND::COMMON_BIRDFLY, 48, 30000);
			}

			switch (obj.direction) {
				case 1: obj.xSpeed = obj.xSpeed - 0.05; obj.ySpeed = obj.ySpeed - 0.1; break;
				case -1: obj.xSpeed = obj.xSpeed + 0.05; obj.ySpeed = obj.ySpeed - 0.1; break;
			}
			
			float pdx = jjLocalPlayers[0].xPos - obj.xPos, pdy = jjLocalPlayers[0].yPos - obj.yPos;
			if ((pdx * pdx + pdy * pdy < 96 * 96) && !creator.isLocal && jjLocalPlayers[0].blink == 0 && (jjLocalPlayers[0].team != creator.team || jjFriendlyFire || jjGameMode != GAME::CTF) && gameIsActive()) {
				jjLocalPlayers[0].ySpeed -= 5;
				jjLocalPlayers[0].xSpeed += 5 * obj.direction;
			}
		}
		if (obj.state == STATE::EXPLODE) {
			if (obj.var[0] == 0) {
				jjSample(obj.xPos, obj.yPos, SOUND::COMMON_SWISH4, 36, 15000);
				obj.var[0] = 1;
			}
		}
	}
}

class Lightningrod : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::BULLET, false);
		jjPLAYER@ creator = jjPlayers[obj.creatorID];
		
		if (jjGameMode == GAME::CTF) {
			switch (creator.team) {
				case TEAM::BLUE: obj.var[4] = 1; break;
				case TEAM::RED: obj.var[4] = 2; break;
				case TEAM::YELLOW: obj.var[4] = 3; break;
				case TEAM::GREEN: obj.var[4] = 4; break;
			}
		} else {
			obj.var[4] = 1;
		}
		
		jjDrawSprite(obj.xPos, obj.yPos, ANIM::CUSTOM[27], obj.var[0] == 1? obj.var[4] : 0, obj.var[0] == 1? jjGameTicks / 10 % 6 : 0, obj.direction, SPRITE::NORMAL);
		
		if (obj.counter == 2 && jjPlayers[obj.creatorID].isLocal) {
			jjSample(creator.xPos, creator.yPos, SOUND::COMMON_MONITOR, 0, 12500);
			obj.age = 0;
			obj.var[1] = 0;
		}
		
		if (obj.counter == 127) obj.counter = 2; 
		
		if (!jjMaskedHLine(int(obj.xPos - 16), 24, int(obj.yPos + 8))) {
			obj.yPos += 6;
			obj.var[0] = 0;
			obj.lightType = LIGHT::POINT;
		} else {
			obj.var[0] = 1;
		}
		
		if (obj.var[0] == 1) {
			obj.age++;
			if (obj.var[1] == 0) {
				jjSample(obj.xPos, obj.yPos, SOUND::COMMON_LANDCAN1, 0, 30000);
				obj.var[1] = 1;
			}
			obj.lightType = LIGHT::BRIGHT;
			obj.light = 10;
			if (obj.age % 20 == 0) {
				for (int i = -4; i <= 4; i += 4) {
					Electricity temp;
					int id = jjAddObject(OBJECT::LIGHTNINGSHIELDBULLET, obj.xPos, obj.yPos - 12, obj.creatorID, CREATOR::PLAYER, jjVOIDFUNCOBJ(temp.onBehave));
					if (id != 0) {
						jjOBJ@ zap = jjObjects[id];
						zap.lightType = LIGHT::NONE;
						zap.counterEnd = 6;
						zap.animSpeed = 2;
						zap.direction = obj.direction;
						zap.lightType = LIGHT::NONE;
						zap.playerHandling = HANDLING::PLAYERBULLET;
						zap.var[3] = 1;
						zap.var[6] = 8;
						zap.xSpeed = i;
						zap.xAcc = 0;
						if (i == 0) zap.ySpeed = -4;
					}
				}
			}
		}
		
		if (obj.age == 420) {
			obj.var[0] = obj.var[1] = 0;
			obj.particlePixelExplosion(0);
			obj.delete();
		}
	}
}

class Electricity : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::BULLET, false);
	}
}

class LightningrodPickup : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::PICKUP);
	}
	bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
		if (play.ammo[WEAPON::TNT] < jjWeapons[WEAPON::TNT].maximum) {
			if (play.isLocal) {
				play.ammo[WEAPON::TNT] = play.ammo[WEAPON::TNT] + 1;
				if (jjAutoWeaponChange && play.ammo[WEAPON::TNT] < 1) play.currWeapon = WEAPON::TNT;
				jjSample(obj.xPos, obj.yPos, SOUND::COMMON_PICKUPW1, 0, 0);
			}
			obj.behavior = BEHAVIOR::EXPLOSION2;
			obj.scriptedCollisions = false;
			obj.frameID = 0;
		}
		return true;
	}
}

class BloodSpear : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::BULLET, false);
		obj.var[0] = int(atan2(-obj.ySpeed, obj.xSpeed) * (512.f * 0.318309886142228f));
		
		if (obj.counter == 1 && obj.state == STATE::FLY && jjPlayers[obj.creatorID].isLocal) {
			jjSample(jjPlayers[obj.creatorID].xPos, jjPlayers[obj.creatorID].yPos, SOUND::HATTER_PTOEI, 0, obj.eventID == OBJECT::FIREBALLBULLETPU? 19000:20000);
		}
		
		if (obj.state == STATE::FLY) {
			jjDrawRotatedSprite(obj.xPos, obj.yPos, ANIM::HATTER, 3, jjGameTicks >> 2, obj.var[0], 2, 1, SPRITE::SINGLEHUE, obj.eventID == OBJECT::FIREBALLBULLETPU? 15:24);
			switch (obj.direction) {
				case 1: obj.xSpeed -= 0.1; obj.ySpeed += 0.1; break;
				case -1: obj.xSpeed += 0.1; obj.ySpeed += 0.1; break;
			}
			if (obj.xSpeed == 0) obj.ySpeed += 0.15;
			
			jjPARTICLE@ blood = jjAddParticle(PARTICLE::ICETRAIL);
			blood.xPos = obj.xPos;
			blood.yPos = obj.yPos;
			blood.icetrail.color = obj.eventID == OBJECT::FIREBALLBULLETPU? 16:24;
			blood.icetrail.colorStop = obj.eventID == OBJECT::FIREBALLBULLETPU? 24:32;
		}
		
		if (obj.state == STATE::EXPLODE) {
			jjDrawSprite(obj.xPos, obj.yPos, ANIM::MONKEY, 1, obj.curFrame, obj.direction, SPRITE::SINGLEHUE, obj.eventID == OBJECT::FIREBALLBULLETPU? 15:24);
			if (obj.var[1] < 27) {
				if (obj.var[1] == 1) jjSample(obj.xPos, obj.yPos, SOUND::HATTER_SPLOUT, 0, 20000);
				obj.var[1] = obj.var[1] + 1;
			}
			if (obj.var[1] == 27) {
				obj.var[1] = 0;
				obj.delete();
			}
		}
	}
}

class FusionCannon : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::BULLET, obj.state == STATE::EXPLODE? true:false);
		jjPLAYER@ creator = jjPlayers[obj.creatorID];
		
		obj.var[5] = obj.eventID == OBJECT::ELECTROBULLETPU? 2:1;
		
		switch (obj.state) {
			case STATE::START:
				obj.state = STATE::FLY;
			break;
			
			case STATE::FLY:
				obj.var[11] = obj.xSpeed > 0? 5 : obj.xSpeed < 0? -5 : 0;
				obj.xSpeed = obj.var[11];
				obj.ySpeed = obj.var[11] == 0? -4:0;
				
				jjDrawSprite(obj.xPos, obj.yPos, ANIM::AMMO, 77, 6, 0, SPRITE::ALPHAMAP, obj.eventID == OBJECT::ELECTROBULLETPU? 35:40);
				jjDrawSprite(obj.xPos, obj.yPos, ANIM::AMMO, 77, 6, 0, SPRITE::ALPHAMAP, obj.eventID == OBJECT::ELECTROBULLETPU? 35:40);
				
				if (obj.counter % 5 == 0 && !jjLowDetail) {
					ColoredTrail temp;
					jjOBJ@ trail = jjObjects[jjAddObject(OBJECT::EXPLOSION, int(obj.xPos - jjCos(obj.var[0])), int(obj.yPos - jjSin(obj.var[0])), obj.creatorID, CREATOR::PLAYER, jjVOIDFUNCOBJ(temp.onBehave))];
					trail.determineCurAnim(ANIM::AMMO, 12);
					trail.lightType = LIGHT::POINT;
					trail.playerHandling = HANDLING::PARTICLE;
					trail.bulletHandling = HANDLING::IGNOREBULLET;
					trail.isBlastable = false;
					trail.var[0] = obj.eventID == OBJECT::ELECTROBULLETPU? 32:59;
				}
				
			break;
			
			case STATE::EXPLODE:
				if (obj.var[2] == 0) {
					FusionShockwave temp;
					jjOBJ@ blast = jjObjects[jjAddObject(OBJECT::BULLET, obj.xPos, obj.yPos, obj.creatorID, CREATOR::PLAYER, jjVOIDFUNCOBJ(temp.onBehave))];
					obj.var[2] = 1;
					blast.var[2] = 1;
					blast.var[5] = obj.var[5];
				}
			break;
		}
	}
}

class FusionShockwave : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		jjPLAYER@ creator = jjPlayers[obj.creatorID];
		
		obj.playerHandling = HANDLING::PARTICLE;
		obj.bulletHandling = HANDLING::IGNOREBULLET;
		obj.animSpeed = 1;
		
		if (obj.var[2] == 1) {
			obj.lightType = obj.var[2] == 1? LIGHT::RING2 : LIGHT::NONE;
			obj.var[0] = obj.var[0] + 1;
			obj.light += 3;
			obj.var[4] = obj.light * 4;
			
			for (int i = 1; i < jjObjectCount; i++) {
				jjOBJ@ target = jjObjects[i];
				float dx = target.xPos - obj.xPos, dy = target.yPos - obj.yPos;
				if ((target.eventID == OBJECT::TNT || target.behavior == BEHAVIOR::MONITOR || target.behavior == BEHAVIOR::AMMO15 || target.eventID == OBJECT::GUNCRATE || target.eventID == OBJECT::GEMCRATE || target.eventID == OBJECT::CARROTCRATE || target.playerHandling == HANDLING::ENEMY || target.eventID == OBJECT::DESTRUCTSCENERY) && target.var[4] == 0) {
					if (dx * dx + dy * dy < obj.var[4] * obj.var[4]) {
						if (target.eventID != OBJECT::TNT) {
							obj.objectHit(target, target.bulletHandling == HANDLING::HURTBYBULLET? HANDLING::ENEMY : HANDLING::SPECIAL);
							if (target.playerHandling != HANDLING::ENEMY) target.state = STATE::KILL;
						}
						else target.state = STATE::EXPLODE;
						if (target.playerHandling != HANDLING::ENEMY) target.var[4] = 1;
					}
					else target.var[4] = 0;
				}
				else if ((target.behavior == BEHAVIOR::PICKUP || target.eventID == OBJECT::TNTAMMO3 || target.eventID == OBJECT::GUN9AMMO3) && target.state == STATE::FLOAT) {
					if (dx * dx + dy * dy < obj.var[4] * obj.var[4])
						target.state = STATE::FLOATFALL;
				}
				else if (target.playerHandling == HANDLING::ENEMY && target.state != STATE::KILL) {
					if (dx * dx + dy * dy < obj.var[4] * obj.var[4]) {
						if (obj.var[8] & 1 << i == 0) {
							obj.energy -= 1;
							obj.var[8] = obj.var[8] | 1 << i;
						}
					}
				}
			}
			
			if (jjIsServer && gameIsActive()) {
				for (int i = 0; i < 32; i++) {
					jjPLAYER@ player = jjPlayers[i];
					if (
						player.isActive && player.isInGame && player.health > 0 && player !is creator && creator.blink == 0 &&
							(jjGameMode != GAME::CTF || jjFriendlyFire || player.team != creator.team)
					) {
						float dx = player.xPos - obj.xPos, dy = player.yPos - obj.yPos;
						if (dx * dx + dy * dy < obj.var[4] * obj.var[4]) {
							if (obj.var[8] & 1 << i == 0) {
								player.hurt(obj.var[5], false, creator);
								obj.var[8] = obj.var[8] | 1 << i;
							}
						}
					}
				}
			}
		}
		
		if (obj.var[0] == 20) {
			obj.var[0] = 0;
			obj.var[2] = 0;
			obj.var[4] = 0;
			obj.delete();
		}
	}
}

class ColoredTrail : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::EXPLOSION, false);
		if (obj.isActive) jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::TRANSLUCENTSINGLEHUE, obj.var[0]);
	}
}

class FusionPickup : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::PICKUP);
	}
	bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
		if (play.ammo[WEAPON::GUN9] < jjWeapons[WEAPON::GUN9].maximum) {
			if (play.isLocal) {
				play.ammo[WEAPON::GUN9] = play.ammo[WEAPON::GUN9] + 2;
				if (jjAutoWeaponChange && play.ammo[WEAPON::GUN9] < 1) play.currWeapon = WEAPON::GUN9;
				jjSample(obj.xPos, obj.yPos, SOUND::COMMON_PICKUPW1, 0, 0);
			}
			obj.behavior = BEHAVIOR::EXPLOSION2;
			obj.scriptedCollisions = false;
			obj.frameID = 0;
		}
		return true;
	}
}

void onMain() {
	for (int i = 0; i < 1024; i++) {
		jjPARTICLE@ particle = jjParticles[i];
		if (particle.type == PARTICLE::FIRE) {
			particle.fire.size = particle.fire.color == 40? 3:2;
		}
	}
}

void onPlayer(jjPLAYER@ play) {
	float MaxHealth = jjMaxHealth + 1;
	float Health = play.health + 1;
	float healthratio = MaxHealth / Health;

	if (healthratio < 1.3) jjWeapons[WEAPON::GUN8].spread = SPREAD::NORMAL;
	if (healthratio >= 1.3 && healthratio < 2) jjWeapons[WEAPON::GUN8].spread = SPREAD::RFNORMAL;
	if (healthratio >= 2) jjWeapons[WEAPON::GUN8].spread = SPREAD::RFPU;
	
	jjEnforceLighting = LIGHT::BASIC;
	if (play.ammo[WEAPON::TNT] > 10) play.ammo[WEAPON::TNT] = 10;
	if (play.ammo[WEAPON::GUN9] > 25) play.ammo[WEAPON::GUN9] = 25;
}