// Template file v4.23a (02/09/01)   @020901a
////////////////////////////////////////////////////////////////////////
// File: weapons.wdl
//		WDL prefabs for weapon entities & effects
////////////////////////////////////////////////////////////////////////
//
// Mod Date: 8/31/00 DCP
//		Scaled entities that us _flashup and _blowup by actor_scale
//		Scaled bullet_shot and rocket_launch entities by actor_scale
//		Scaled bullet_shot and rocket_launch movement by movement_scale
//
// Mod Date: 10/3/00 DCP
//		Added 'wait' to ammo_pickup action if message is displayed,
//	  allows show_message to finish displaying
//
// Mod Date: 10/17/00 DCP
//		Replaced commands with "javascript" style commands
//		Add bullet holes
// Mod Date: 10/31/00 DCP
//				Changed to 4.30 format
//
//	Mod Date: 11/2/00 DCP
//		Added 'bullet_hole': creates a bullet_hole effect in map walls if
//	HIT_HOLE is set in weapon's _FIREMODE
//
// Mod Date: 11/17/00 DCP
//		Added DEFINE 'kMaxWeapons' to be equal to the maximum number of weapons
//	the player can have.
//		Added functions: 'gun_select_cycle_up' & 'gun_select_cycle_up' used
// to select the next or prev weapon in the player's list
// These new functions are called on 'E' and 'Q'
//
// Mod Date: 11/17/00 DCP
//		Added inverted bullet map (white)
//		Added 'laser_fire'  & 'FIRE_LASER' flag
//		Added 'GUNFX_BRASS' flag
//
// Mod Date: 12/11/00 DCP
//		Added weaponTmpSyn and code to gun_shot to store/restore YOU value
// when using a laser (so bullethole and other effects will continue to work).
//		To test new effects try the following FIREMODE with your weapon:
//			MY._FIREMODE = DAMAGE_SHOOT + HIT_FLASH + HIT_HOLE
//								+ HIT_SMOKE + HIT_SPARKS
//								+ FIRE_LASER + GUNFX_BRASS + 0.50;
//
// Mod Date: 01/24/01 JCL
//		Bullhole bitmaps fixed
//
// Mod Date: 02/06/01 DCP
//		In '_fireball_event':
//			Added wait before shoot command to remove 'Dangerous instruction error'
////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////

// change these sounds and graphics for your weapon
IFNDEF WEAPON_DEFS;
 SOUND gun_click,<empty.wav>;
 SOUND gun_wham,<wham.wav>;
 SOUND explo_wham,<explo.wav>;
 DEFINE hit_wham,explo_wham;
 SOUND gun_fetch,<beamer.wav>;
 DEFINE ammo_fetch,gun_fetch;
 DEFINE health_fetch,gun_fetch;

 DEFINE muzzle_flash,<particle.pcx>;
 DEFINE small_flash,<particle.pcx>;
 DEFINE fireball,<blitz.pcx>;
 DEFINE BULLET_EXPLO,<explo+7.pcx>;
 DEFINE EXPLO_FRAMES,7;
 DEFINE WEAPON_AMPL,0.2;	// swaying
ENDIF;

IFNDEF WEAPON_DEFS2;
 DEFINE bullethole_map,<bulhole.pcx>;    // bullet hole bitmap ***
 DEFINE ibullethole_map,<ibulhole.pcx>;    // inverted bullet hole bitmap (white) ***
ENDIF;

//////////////////////////////////////////////////////////////////////
// adapt those skills and strings to your game
// ammo starting and maximum values
var ammo1[3] = 0, 0, 200;
var ammo2[3] = 0, 0, 100;
var ammo3[3] = 0, 0,  40;
var ammo4[3] = 0, 0,  10;

// dynamic light values
var light_explo[3]  =  50,  50, 255;// { RED 50; GREEN 50; BLUE 255; }
var light_flash[3]  = 200, 150,  50;// { RED 200; GREEN 150; BLUE 50; }
var light_muzzle[3] = 200,  20,  20;// { RED 200; GREEN 20; BLUE 20; }
var light_bullet[3] = 200,  50,  20;// { RED 200; GREEN 50; BLUE 20; }



// you'll probably want to redefine those strings. No problem.
STRING got_ammo1_str,"Got an ammo pack!";
STRING got_ammo2_str,"Got a big ammo pack!";
STRING got_ammo3_str,"Got a grenade pack!";
STRING got_ammo4_str,"Got a rocket pack!";
STRING got_medi_str,"Got a first aid kit!";
STRING got_gun1_str,"Got a small gun!";
STRING got_gun2_str,"Got a medium gun!";
STRING got_gun3_str,"Got a large gun!";
STRING got_gun4_str,"Got a gun no. 4!";
STRING got_gun5_str,"Got a gun no. 5!";
STRING got_gun6_str,"Got a gun no. 6!";
STRING got_gun7_str,"Got a gun no. 7!";

//////////////////////////////////////////////////////////////////////
/* Gun Action

FLAG1
	If this flag is set, the gun model rotates before being picked up.

FLAG2
	If this flag is set, the message on picking up the item will be
	suppressed.

FLAG5
   If this flag is marked, the gun sways a little if the camera is
	moving. The sway period is the same as used for head bobbing in the
	movement.wdl. If the flag is not marked, the gun stands still.

FLAG7
   If this flag is marked, it's a machine gun. Otherwise, a single
	action gun.

SKILL1..SKILL3
	X Y Z position of the gun relative to the camera.

SKILL4
	Ammo type (1..4). If 0, the gun doesn't consume ammunition. The part
	after the decimal, times 100, gives the amount of ammo to be added
	on picking up the gun. E.g. 2.30 = Ammo type 2, 30 rounds are
	already in the gun.

SKILL5 (_BULLETSPEED)
	Speed of the bullet, default = 200 quants / tick. The part after the
	decimal, times 10, gives the strength of the recoil. If 0, then
	there is no recoil. If SKILL5 is above 0, the recoil is done by
	moving backwards. If SKILL5 is below 0, then the recoil is done by
	swinging upwards.

SKILL6
	Weapon number that determines the key (1..7) to be pressed to select
	that gun.

SKILL7
   The time (in ticks) the gun needs to reload. Includes the time for
   the gun animation, if any.

SKILL8
   Fire mode, can be composed by adding the following numbers:

	1 - Damage is applied by a SHOOT instruction, without bullet (DAMAGE_SHOOT).
	2 - Damage is applied by IMPACT of the bullet (DAMAGE_IMPACT).
	3 - Damage is applied by a SCAN explosion of the bullet (DAMAGE_EXPLODE).

	4 - the gun fires red particles (FIRE_PARTICLE).
	8 - the gun fires dark bullets (FIRE_DPARTICLE).
	12 - the gun fires orange fireballs, which radiate light (FIRE_BALL).
	16 - the gun fires a rocket model w/smoke trail (FIRE_ROCKET)
	20 - (NEW 11/17/00) the gun fires a laser (FIRE_LASER)
	24 - Reserved
	28 - Reserved

	32 - the bullets leave smoke trails(BULLET_SMOKETRAIL).

	64 - reserved

	128 - at hit point there will be a light flash (HIT_FLASH).
	256 - at hit point there will be an explosion (HIT_EXPLO).
	384 - at hit point there will be a big explosion (HIT_GIB).

	512 - at hit point a cloud of smoke will ascend (HIT_SMOKE).

	1024 - there will be multiple hit points, as by a shotgun (HIT_SCATTER).

	2048 - the gun spits out cartridge cases (GUNFX_BRASS).

	4096 - the bullets follow gravity.

	8192 - at hit point a shower of sparks (HIT_SPARKS).

	16384 - bullet hole at hit point (HIT_HOLE)

	The part after the decimal, times 100, gives the amount of damage
	the bullet produces (default = 10).  ***

*/
///////////////////////////////////////////////////////////////////////
DEFINE _OFFS_X,MY.SKILL1;
DEFINE _OFFS_Y,MY.SKILL2;
DEFINE _OFFS_Z,MY.SKILL3;
DEFINE _AMMOTYPE,SKILL4;
DEFINE _BULLETSPEED,SKILL5;
DEFINE _WEAPONNUMBER,SKILL6;
DEFINE _FIRETIME,SKILL7;

DEFINE _OFFS_FLASH,SKILL14;
DEFINE _RECOIL,SKILL15;
DEFINE _DAMAGE,SKILL16;
DEFINE _DISPLACEMENT,SKILL17;
DEFINE _FIRE,SKILL18;

DEFINE __REPEAT,FLAG7;

DEFINE MODE_DAMAGE,3;
DEFINE DAMAGE_SHOOT,1;
DEFINE DAMAGE_IMPACT,2;
DEFINE DAMAGE_EXPLODE,3;

DEFINE MODE_FIRE,28;        // DCP
DEFINE FIRE_PARTICLE,4;
DEFINE FIRE_DPARTICLE,8;
DEFINE FIRE_BALL,12;
DEFINE FIRE_ROCKET,16;
DEFINE FIRE_LASER,20;		// 11/17/00

DEFINE BULLET_SMOKETRAIL,32;

DEFINE MODE_HIT,384;
DEFINE HIT_FLASH,128;
DEFINE HIT_EXPLO,256;
DEFINE HIT_GIB,384;

DEFINE HIT_SMOKE, 512;

DEFINE HIT_SCATTER,1024;
DEFINE GUNFX_BRASS,2048;

DEFINE HIT_SPARKS,8192;

DEFINE HIT_HOLE 16384;        //***
///////////////////////////////////////////////////////////////////////
SYNONYM weapon { TYPE ENTITY; }
// The weapon must be a model pointing into X-direction,
// its center must be inside the barrel.

DEFINE	kMaxWeapons = 7;

SYNONYM weapon1 { TYPE ENTITY; }
SYNONYM weapon2 { TYPE ENTITY; }
SYNONYM weapon3 { TYPE ENTITY; }
SYNONYM weapon4 { TYPE ENTITY; }
SYNONYM weapon5 { TYPE ENTITY; }
SYNONYM weapon6 { TYPE ENTITY; }
SYNONYM weapon7 { TYPE ENTITY; }

SYNONYM weaponTmpSyn {TYPE ENTITY;}     // tmp ENTITY synonym


var weapon_1 = 0; 	// set to 1 if the player owns that weapon
var weapon_2 = 0;
var weapon_3 = 0;
var weapon_4 = 0;
var weapon_5 = 0;
var weapon_6 = 0;
var weapon_7 = 0;

var gun_muzzle;
var gun_target;
var gun_loaded = 1;
var fireball_speed = 0;

var weapon_number = 0;
var ammo_number = 0;

var damage = 0;
var range = 0;
var fire_mode = 0;
var weapon_firing = 0;

//////////////////////////////////////////////////////////////////////
ACTION testgun
{
IFNDEF TEST;
	remove(ME);
	return;
ENDIF;
	MY.__ROTATE = ON;
	MY.__REPEAT = ON;
	MY.__BOB = ON;
	MY.SKILL1 = 50;
	MY.SKILL2 = 20;
	MY.SKILL3 = 20;
	MY._AMMOTYPE = 1.50;
	MY._WEAPONNUMBER = 1;
	MY._BULLETSPEED = -500.05;
	MY._FIRETIME = 2;
	MY._FIREMODE = DAMAGE_SHOOT+FIRE_PARTICLE+HIT_FLASH+0.30;
	gun();
}

// Desc: "Logan's Run" type gun, used for testing
ACTION logangun
{
	MY.__ROTATE = ON;	// gun rotates before being picked up
	MY.__REPEAT = ON; // repeats (Auto-fire)
	MY.__BOB = ON;  	// 'bobs' when the player moves
	MY.SKILL1 = 42;   // x,y,z pos of the gun
	MY.SKILL2 = 20;
	MY.SKILL3 = 7;
	MY._AMMOTYPE = 10.0; 		// type of ammo '.' rounds in gun
									//(0 means no ammo needed)

	MY._WEAPONNUMBER = 3;   	// weapon number (press 3 to equip)
	MY._BULLETSPEED = 1000.25;	// bulletspeed '.' recoil
	MY._FIRETIME = 1;          // time to cycle (reload)

	// SHOOT damage (immediate)
	// + flash at hit point
	// + smoke at hit point
	// + sparks at hit point
	// 50 points of damage per shot
	MY._FIREMODE = DAMAGE_SHOOT + HIT_FLASH + HIT_SMOKE + HIT_SPARKS + FIRE_PARTICLE + 0.50;
	gun();
}

// Desc: Laser beam type gun
//
// 11/17/00
ACTION lasergun
{
	MY.__ROTATE = ON;	// gun rotates before being picked up
	MY.__REPEAT = OFF;// repeats (Auto-fire)
	MY.__BOB = ON;  	// 'bobs' when the player moves
	MY.SKILL1 = 42;   // x,y,z pos of the gun
	MY.SKILL2 = 20;
	MY.SKILL3 = 7;
	MY._AMMOTYPE = 0.0; 		// type of ammo '.' rounds in gun
									//(0 means no ammo needed)

	MY._WEAPONNUMBER = 4;   	// weapon number (press 3 to equip)
	MY._BULLETSPEED = 1000.25;	// bulletspeed '.' recoil
	MY._FIRETIME = 5;          // time to cycle (reload)

	// SHOOT damage (immediate)
	// + use laser beam
	// + flash at hit point
	// + smoke at hit point
	// + sparks at hit point
	// 50 points of damage per shot
	MY._FIREMODE = DAMAGE_SHOOT + FIRE_LASER + HIT_FLASH + HIT_SMOKE + HIT_SPARKS + 0.50;
	gun();
}


ACTION sparkgun
{
	MY.__ROTATE = ON;
	MY.__REPEAT = ON;
	MY.__BOB = ON;
	MY.SKILL1 = 50;
	MY.SKILL2 = 20;
	MY.SKILL3 = 20;
	MY._AMMOTYPE = 1.50;
	MY._WEAPONNUMBER = 1;
	MY._BULLETSPEED = -500.05;
	MY._FIRETIME = 2;
	MY._FIREMODE = DAMAGE_SHOOT+FIRE_PARTICLE+HIT_FLASH+0.30;
	gun();
}

ACTION flashgun {
	MY.__ROTATE = ON;
	MY.__REPEAT = ON;
	MY.__BOB = ON;
	MY.SKILL1 = 42;
	MY.SKILL2 = 20;
	MY.SKILL3 = 7;
	MY._AMMOTYPE = 2.15;
	MY._WEAPONNUMBER = 2;
	MY._BULLETSPEED = 150.05;
	MY._FIRETIME = 5;
	MY._FIREMODE = DAMAGE_EXPLODE+FIRE_BALL+HIT_EXPLO+BULLET_SMOKETRAIL+0.50;
	gun();
}

////////////////////////////////////////////////////////////////////////

// Desc: Called from player_move action; player must exist here
ACTION weapon_carry
{
  	if(weapon == NULL || player == NULL) { return; }
	if(person_3rd != 0)
	{
		weapon.INVISIBLE = ON;

		player._FIREMODE = weapon._FIRE;  //show the attack animation for the player
	/*	// if firing in 3rd person mode, calculate the player's attack frame
		if(weapon._FIRE > 0)
		{
			temp = (weapon._FIRETIME - weapon._FIRE) / weapon._FIRETIME;
			if(temp < 0) { temp = 0; }
			if(temp > 0.9) { temp = 0.9; }
			player.FRAME = 1 + player._WALKFRAMES + player._RUNFRAMES + 1 + player._ATTACKFRAMES * temp;
		}
	*/
	}
	else
	{
		weapon.INVISIBLE = OFF;
		MY_POS.X = weapon.SKILL1;
		MY_POS.Y = -weapon.SKILL2;
		MY_POS.Z = -weapon.SKILL3;
		if(weapon._RECOIL > 0)
		{
			MY_POS.X -= weapon._DISPLACEMENT;
		}
		if(player.__BOB == ON)
		{
			MY_POS.Y += headwave * WEAPON_AMPL;
			MY_POS.X += headwave * WEAPON_AMPL;
			MY_POS.Z -= headwave * WEAPON_AMPL;
		}

		_set_pos_ahead_xyz();
		weapon.X = MY_POS.X ;
		weapon.Y = MY_POS.Y;
		weapon.Z = MY_POS.Z;
		weapon.PAN = CAMERA.PAN;
		weapon.TILT = CAMERA.TILT;
		if(weapon._RECOIL < 0)
		{
			weapon.TILT -= weapon._DISPLACEMENT;
		}
	}
}


////////////////////////////////////////////////////////////////////////
// Gun select functions
ACTION _gun_select1 { weapon_number = 1; gun_select(); }
ACTION _gun_select2 { weapon_number = 2; gun_select(); }
ACTION _gun_select3 { weapon_number = 3; gun_select(); }
ACTION _gun_select4 { weapon_number = 4; gun_select(); }
ACTION _gun_select5 { weapon_number = 5; gun_select(); }
ACTION _gun_select6 { weapon_number = 6; gun_select(); }
ACTION _gun_select7 { weapon_number = 7; gun_select(); }

// Desc: select the 'next' weapon
function	gun_select_cycle_up()
{
	temp = weapon_number; // save the current weapon_number
	weapon_number += 1;
	while(temp != weapon_number)
	{
		if(weapon_number > kMaxWeapons)
		{
			weapon_number = 0;
		}
		if(gun_select() != -1)
		{
			return(weapon_number);
		}
		weapon_number += 1;   // try next weapon
	}
}

// Desc: select the 'prev' weapon
function	gun_select_cycle_down()
{
	temp = weapon_number; // save the current weapon_number
	weapon_number -= 1;
	while(temp != weapon_number)
	{
		if(weapon_number < 0)
		{
			weapon_number = kMaxWeapons;
		}
		if(gun_select() != -1)
		{
			return(weapon_number);
		}
		weapon_number -= 1;   // try next weapon
	}
}

ON_E gun_select_cycle_up;
ON_Q gun_select_cycle_down;


// Desc: select/switch weapon
//
// Mod 11/17/00 DCP
// Function returns -1 if no weapon is found (ME == NULL)
//	Function returns new weapon_number is a weapon is selected
ACTION gun_select
{
	if(weapon != NULL)
	{	// remove old weapon
		weapon.INVISIBLE = ON;
		weapon.PASSABLE = ON;
	}

	if(weapon_number == 1) {  ME = weapon1; }
	if(weapon_number == 2) {  ME = weapon2; }
	if(weapon_number == 3) {  ME = weapon3; }
	if(weapon_number == 4) {  ME = weapon4; }
	if(weapon_number == 5) {  ME = weapon5; }
	if(weapon_number == 6) {  ME = weapon6; }
	if(ME == NULL) { return(-1); }

	ammo_number = MY._AMMOTYPE;
	MY.INVISIBLE =  OFF;
	MY.PASSABLE = ON;	// prevent collision with obstacles
	MY.NEAR = ON;	// prevent clipping
	weapon = ME;		// I'm the current weapon now
	carry = weapon_carry;

	EXCLUSIVE_GLOBAL;

	// handle firing
	while(weapon == ME)
	{
		if(weapon_firing && (gun_loaded > 0) && (MY._FIRE <= 0) )
		{
			gun_fire();
		}

		if((weapon_firing == 0) && (gun_loaded == 0) && (MY.__REPEAT == OFF))
		{
			gun_loaded = 1;
		}
		wait(1);
	}
	return(weapon_number);
}

//////////////////////////////////////////////////////////////////////
// Pickup functions



// Desc:
function _ammo_limit()
{	// clip ammo at maximum values
	if(ammo1 > ammo1.Z) { ammo1 = ammo1.Z; }
	if(ammo2 > ammo2.Z) { ammo2 = ammo2.Z; }
	if(ammo3 > ammo3.Z) { ammo3 = ammo3.Z; }
	if(ammo4 > ammo4.Z) { ammo4 = ammo4.Z; }
}

ACTION gun_pickup
{
	if(EVENT_TYPE == EVENT_SCAN && indicator != _HANDLE) { return; }
	if(EVENT_TYPE == EVENT_PUSH && YOU != player) { return; }

	MY.ENABLE_SCAN = OFF;
	MY.ENABLE_CLICK = OFF;
	MY.ENABLE_PUSH = OFF;

	if(INT(MY._AMMOTYPE) == 1) { ammo1 += INT(FRC(MY._AMMOTYPE) * 100 + 0.5); }
	if(INT(MY._AMMOTYPE) == 2) { ammo2 += INT(FRC(MY._AMMOTYPE) * 100 + 0.5); }
	if(INT(MY._AMMOTYPE) == 3) { ammo3 += INT(FRC(MY._AMMOTYPE) * 100 + 0.5);	}
	if(INT(MY._AMMOTYPE) == 4) { ammo4 += INT(FRC(MY._AMMOTYPE) * 100 + 0.5);	}
	MY._AMMOTYPE = INT(MY._AMMOTYPE);	// ammo type
	_ammo_limit();

	weapon_number = MY._WEAPONNUMBER;
	if(weapon_number == 1) {  weapon1 = ME; weapon_1 = 1;  ON_1 = _gun_select1;  msg.STRING = got_gun1_str; }
	if(weapon_number == 2) {  weapon2 = ME; weapon_2 = 1;  ON_2 = _gun_select2;  msg.STRING = got_gun2_str; }
	if(weapon_number == 3) {  weapon3 = ME; weapon_3 = 1;  ON_3 = _gun_select3;  msg.STRING = got_gun3_str; }
	if(weapon_number == 4) {  weapon4 = ME; weapon_4 = 1;  ON_4 = _gun_select4;  msg.STRING = got_gun4_str; }
	if(weapon_number == 5) {  weapon5 = ME; weapon_5 = 1;  ON_5 = _gun_select5;  msg.STRING = got_gun5_str; }
	if(weapon_number == 6) {  weapon6 = ME; weapon_6 = 1;  ON_6 = _gun_select6;  msg.STRING = got_gun6_str; }
	if(weapon_number == 7) {  weapon7 = ME; weapon_7 = 1;  ON_7 = _gun_select7;  msg.STRING = got_gun7_str; }

	if(MY.__SILENT != ON) { show_message(); }
	gun_select();
}


// Mod: 10/3/00 Added 'wait' if message is displayed, allows show_message
// 				to finish displaying
function ammo_pickup()
{
	if(EVENT_TYPE == EVENT_SCAN && indicator != _HANDLE) { return; }
	if(EVENT_TYPE == EVENT_PUSH && YOU != player) { return; }

	if(MY._AMMOTYPE == 1) { ammo1 += MY.SKILL5;  msg.STRING = got_ammo1_str; }
	if(MY._AMMOTYPE == 2) { ammo2 += MY.SKILL5;  msg.STRING = got_ammo2_str; }
	if(MY._AMMOTYPE == 3) { ammo3 += MY.SKILL5;  msg.STRING = got_ammo3_str; }
	if(MY._AMMOTYPE == 4) { ammo4 += MY.SKILL5;  msg.STRING = got_ammo4_str; }
	if(MY.__SILENT != ON) { show_message(); }
	_ammo_limit();
	PLAY_SOUND ammo_fetch,50;


	if(MY.__SILENT != ON)
	{
		// hide item..
		MY.EVENT = NULL;
		MY.PASSABLE = ON;
		MY.INVISIBLE = ON;

		waitt(MSG_TICKS);	// wait for message to vanish
	}

	remove(ME);
}


// Desc: ammo pack entity
ACTION ammopac
{
	// default ammo type is 1
	if(MY._AMMOTYPE == 0) { MY._AMMOTYPE = 1; }

	// default ammo amount is a quarter of ammo maximum
	if(MY.SKILL5 == 0)
	{
		if(MY._AMMOTYPE == 1) { MY.SKILL5 = ammo1.Z * 0.25; }
		if(MY._AMMOTYPE == 2) { MY.SKILL5 = ammo2.Z * 0.25; }
		if(MY._AMMOTYPE == 3) { MY.SKILL5 = ammo3.Z * 0.25; }
		if(MY._AMMOTYPE == 4) { MY.SKILL5 = ammo4.Z * 0.25; }
	}

	MY.EVENT = ammo_pickup;
	item_pickup();
}

// Desc: medipac event function
function medi_pickup()
{
	if(EVENT_TYPE == EVENT_SCAN && indicator != _HANDLE) { return; }
	if(EVENT_TYPE == EVENT_PUSH && YOU != player) { return; }

	if(YOU == NULL) {  YOU = player; }
	if(YOU == NULL) { return; }

	YOUR._HEALTH += MY.SKILL5;
	if(YOUR._HEALTH > 100) { YOUR._HEALTH = 100; }  // health max at 100%

	PLAY_SOUND health_fetch,50;
	msg.STRING = got_medi_str;

	if(MY.__SILENT != ON) { show_message(); }
	remove(ME);
}

// Desc: medipac entity
ACTION medipac
{
	if(MY.SKILL5 == 0) { MY.SKILL5 = 25; }
	MY.EVENT = medi_pickup;
	item_pickup();
}



// Desc: set up a gun
//
ACTION gun
{
	// set the weapon camera offset (if one is not already defined)
	if(MY.SKILL1 == 0)
	{
		MY.SKILL1 = 50;
		MY.SKILL2 = 20;
		MY.SKILL3 = 20;
	}

	// make sure we have a valid _WEAPONNUMBER
	if(MY._WEAPONNUMBER <= 0 || MY._WEAPONNUMBER > 7)
	{ MY._WEAPONNUMBER = 1; }

	// set damage
	MY._DAMAGE = FRC(MY._FIREMODE) * 100;
 	if(MY._DAMAGE == 0)
	{ MY._DAMAGE = 20; } // default to 20 damage

	// set firemode
	MY._FIREMODE = INT(MY._FIREMODE);
	if(MY._FIREMODE == 0)
	{ MY._FIREMODE = DAMAGE_SHOOT+FIRE_PARTICLE+HIT_FLASH; }   // default to

	// set recoil (up or back)
	MY._RECOIL = FRC(MY._BULLETSPEED) * 100;

	// set bullet speed
	MY._BULLETSPEED = ABS(MY._BULLETSPEED);
	if(MY._BULLETSPEED < 1)
	{ MY._BULLETSPEED = 200; }   // default to 200

	MY._OFFS_FLASH = MY.MAX_X + 1; 	// Muzzle flash offset

	MY.EVENT = gun_pickup;
	item_pickup();

	// check whether this gun was picked up before in another level,
	// and has to be re-created for this level
	if(MY._WEAPONNUMBER == 1 && weapon_1 == 1 && weapon1 == NULL)
	{ weapon1 = ME; GOTO restore; }
	if(MY._WEAPONNUMBER == 2 && weapon_2 == 1 && weapon2 == NULL)
	{ weapon2 = ME; GOTO restore; }
	if(MY._WEAPONNUMBER == 3 && weapon_3 == 1 && weapon3 == NULL)
	{ weapon3 = ME; GOTO restore; }
	if(MY._WEAPONNUMBER == 4 && weapon_4 == 1 && weapon4 == NULL)
	{ weapon4 = ME; GOTO restore; }
	if(MY._WEAPONNUMBER == 5 && weapon_5 == 1 && weapon5 == NULL)
	{ weapon5 = ME; GOTO restore; }
	if(MY._WEAPONNUMBER == 6 && weapon_6 == 1 && weapon6 == NULL)
	{ weapon6 = ME; GOTO restore; }
	if(MY._WEAPONNUMBER == 7 && weapon_7 == 1 && weapon7 == NULL)
	{ weapon7 = ME; GOTO restore; }

	return;

restore:
	// weapon was already picked up by the player
	MY._AMMOTYPE = INT(MY._AMMOTYPE);	// happens on pickup

	MY.INVISIBLE = ON;
	MY.PASSABLE = ON;
	MY.ENABLE_SCAN = OFF;
	MY.ENABLE_CLICK = OFF;
	MY.ENABLE_PUSH = OFF;
	MY.EVENT = NULL;
	// Was it the last weapon the player carried?
	if(weapon_number == MY._WEAPONNUMBER) { gun_select(); }
}



//////////////////////////////////////////////////////////////////////

// Desc: fire weapon
function weapon_fire()
{
	weapon_firing = 1;
 	while(KEY_CTRL || MOUSE_LEFT) { wait(1); }
	weapon_firing = 0;
}

// Desc: deselect weapon
function weapon_remove()
{
	if(weapon != NULL)
	{
		weapon.INVISIBLE = ON;
		weapon = NULL;
		weapon_number = 0;
	}
}

// put weapons and ammo to inital state
function weapon_init()
{
	weapon_remove();
	ammo1 = 0;
	ammo2 = 0;
	ammo3 = 0;
	ammo4 = 0;
	weapon_1 = 0;
	weapon_2 = 0;
	weapon_3 = 0;
	weapon_4 = 0;
	weapon_5 = 0;
	weapon_6 = 0;
	weapon_7 = 0;
	weapon_number = 0;
}

//////////////////////////////////////////////////////////////////////

// Desc:
//
// Mod: 6/14/00 Doug Poston
//			Added a WAIT 1 so bullet does not collide with muzzle_flash
function gun_fire()
{
// anymore ammo?
	if(MY._AMMOTYPE == 1)
	{
		if(ammo1 > 0) { ammo1 -= 1; }
		else{ goto no_ammo; }
	}
	if(MY._AMMOTYPE == 2)
	{
		if(ammo2 > 0) { ammo2 -= 1; }
		else{ goto no_ammo; }
	}
	if(MY._AMMOTYPE == 3)
	{
		if(ammo3 > 0) { ammo3 -= 1; }
		else{ goto no_ammo; }
	}
	if(MY._AMMOTYPE == 4)
	{
		if(ammo4 > 0) { ammo4 -= 1; }
		else{ goto no_ammo; }
	}

   gun_loaded = 0;
// place muzzle flash
	if((person_3rd != 0) && (player != NULL))
	{
		MY_POS.X = player.MAX_X - player.MIN_X;
		MY_POS.Y = 0;
		MY_POS.Z = 0;
	}
	else
	{
		MY_POS.X = MY.SKILL1 + MY._OFFS_FLASH;
		MY_POS.Y = -MY.SKILL2;
		MY_POS.Z = -MY.SKILL3;
	}
	_set_pos_ahead_xyz();
	gun_muzzle.X = MY_POS.X;
	gun_muzzle.Y = MY_POS.Y;
	gun_muzzle.Z = MY_POS.Z;
	create(muzzle_flash,gun_muzzle,_flashup);

	MY_POS.X = MY._BULLETSPEED;
	if((person_3rd != 0) && (player != NULL))
	{
		MY_POS.Y = 0;
		MY_POS.Z = 0;
	}
	else
	{
		MY_POS.Y = -MY.SKILL2;
		MY_POS.Z = -MY.SKILL3;
	}
	_set_pos_ahead_xyz();
	gun_target.X = MY_POS.X;
	gun_target.Y = MY_POS.Y;
	gun_target.Z = MY_POS.Z;

   // emit a bullet or particle
	shot_speed.X = (gun_target.X - gun_muzzle.X);
	shot_speed.Y = (gun_target.Y - gun_muzzle.Y);
	shot_speed.Z = (gun_target.Z - gun_muzzle.Z);

	damage = MY._DAMAGE;
	fire_mode = MY._FIREMODE;
	wait(1); // allow muzzle_flash to become passable (so bullet does not hit it!)
	gun_shot();

	MY._FIRE = MY._FIRETIME;
	MY._DISPLACEMENT = MY._RECOIL;
	while(MY._FIRE > 0)
	{
		wait(1);
 		// rock back into place from recoil
		MY._DISPLACEMENT *= 0.6;
		MY._FIRE -= TIME;
	}
	MY._DISPLACEMENT = 0 ;
	MY._FIRE = 0 ;

	if(MY.__REPEAT == ON) { gun_loaded = 1;}
	return;

no_ammo:
	PLAY_ENTSOUND ME,gun_click,50;
}

// Desc: select and handle shot type using 'fire_mode'
//
// needs gun_muzzle,shot_speed,damage,fire_mode
//
// Mod:	6/14/00 Doug Poston
//			uses _hit_point_effect() for SHOOT bullets
// Mod:	6/14/00 Doug Poston
//			added placeholder for darkshot particles
//			when functions can take parameters, use a color para for particle_shot()
// Mod:	8/15/00 JCL
//			modified FIRE_PARTICLE to produce a particle_line effect
// Mod:  10/18/00 DCP
//			replace SHOOT with trace
// Mod:  12/11/00 DCP
//			add weaponTmpSyn to store/restore YOU value when using a laser
//		 (so bullethole and other effects will continue to work).
ACTION gun_shot
{
	// select and handle shot type using 'fire_mode'

	// particle trail shot (line of particles)
	if((fire_mode & MODE_FIRE) == FIRE_PARTICLE)
	{
		vec_set(p,gun_muzzle);
		vec_set(p2,gun_target);
		particle_line();
	}

	// single particle
	if((fire_mode & MODE_FIRE) == FIRE_DPARTICLE)
	{ emit(1,gun_muzzle,particle_shot); }

	// fireball
	if((fire_mode & MODE_FIRE) == FIRE_BALL)
	{ create(fireball,gun_muzzle,bullet_shot); }

	// rocket model
	if((fire_mode & MODE_FIRE) == FIRE_ROCKET)
	{ create(<rocket.mdl>,gun_muzzle,rocket_launch); }

	// eject brass?
	if((fire_mode & GUNFX_BRASS) != 0)
	{
	 	emit(1,gun_muzzle,particle_gunBrass); // emit smoke
	}


	// bullet damage is done with a trace
	if((fire_mode & MODE_DAMAGE) == DAMAGE_SHOOT)
	{
		gun_target.X = 2*shot_speed.X + gun_muzzle.X;
		gun_target.Y = 2*shot_speed.Y + gun_muzzle.Y;
		gun_target.Z = 2*shot_speed.Z + gun_muzzle.Z;

		indicator = _GUNFIRE;	// indicator for the entity that was hit
		//---SHOOT gun_muzzle,gun_target;    replaced by 'trace' call below
		trace_mode = IGNORE_ME + IGNORE_PASSABLE + ACTIVATE_SHOOT;
		RESULT = trace(gun_muzzle,gun_target);
		if((fire_mode & MODE_FIRE) == FIRE_LASER)
		{
			weaponTmpSyn = YOU;  // save YOU value (used for bullet holes)
			create(<lbeam.mdl>,gun_muzzle,laser_fire);  // uses TARGET & RESULT
			YOU = weaponTmpSyn;	// restore YOU value
		}

   	if(RESULT > 0)
		{ // hit something?
			_hit_point_effect();	// send fire_mode and TARGET
		}

	}
}

///////////////////////////////////////////////////////////////////////
// Desc: hit flash
//
// Mod Date: 8/31/00 DCP
//		Scaled by actor_scale
function _blowup()
{
	MY.SCALE_X = 2;
	MY.SCALE_Y = 2;
	vec_scale(MY.SCALE_X,actor_scale);

	MY.PASSABLE = ON;
	MY.FACING = ON;
	MY.NEAR = ON;
	MY.FLARE = ON;
	MY.AMBIENT = 100;
	MY.LIGHTRED = light_flash.RED;
	MY.LIGHTGREEN = light_flash.GREEN;
	MY.LIGHTBLUE = light_flash.BLUE;
	MY.LIGHTRANGE = 64;
	wait(1);
	PLAY_ENTSOUND ME,hit_wham,300;
	remove(ME);
}

// Desc: muzzle flash
//
// Mod Date: 8/31/00 DCP
//		Scaled by actor_scale
function _flashup()
{
	MY.SCALE_X = 2;
	MY.SCALE_Y = 2;
	vec_scale(MY.SCALE_X,actor_scale);

	MY.PASSABLE = ON;
// Set flare only in D3D mode
	if(VIDEO_MODE > 8) { MY.FLARE = ON; }
	else{ MY.TRANSPARENT = ON; }

	MY.FACING = ON;
	MY.AMBIENT = 100;
	MY.LIGHTRED = light_muzzle.RED;
	MY.LIGHTGREEN = light_muzzle.GREEN;
	MY.LIGHTBLUE = light_muzzle.BLUE;
	MY.LIGHTRANGE = 100;
	wait(1);
	PLAY_SOUND gun_wham,50;
	remove(ME);
}


// Mod Date: 02/06/01 DCP
//			Added wait before shoot command to remove 'Dangerous instruction error'
function _fireball_event()
{
	// check for all collision events
	if(EVENT_TYPE == EVENT_BLOCK
		|| EVENT_TYPE == EVENT_ENTITY
		|| EVENT_TYPE == EVENT_STUCK
		|| EVENT_TYPE == EVENT_IMPACT
		|| EVENT_TYPE == EVENT_PUSH)
	{
		wait(1);// added to avoid Dangerous instruction
		EXCLUSIVE_ENTITY;	// terminate other actions, to stop moving
		MY.EVENT = NULL;

 		range = MY._DAMAGE * 3;
		damage = MY._DAMAGE;
 		temp.PAN = 360;
		temp.TILT = 180;
		temp.Z = range;
		indicator = _EXPLODE;	// must always be set before scanning
		scan(MY.POS,MY_ANGLE,temp);

		morph BULLET_EXPLO,ME;
		MY._DIEFRAMES = EXPLO_FRAMES;
		actor_explode();
	}
}


// Desc: event attached to rocket
//			Explode the rocket.
//
// Mod Date: 6/13/00 Doug Poston
//				Created
function _rocket_event()
{
	EXCLUSIVE_ENTITY;	// terminate other actions, to stop moving
	MY.EVENT = NULL;
	MY.SKILL9 = -1;   // stop movement

  	// Explode
	morph <explo+7.pcx>, ME;
	MY.AMBIENT = 100;
	MY.FACING = ON;
	MY.NEAR = ON;
  	MY.FLARE = ON;

	MY.PASSABLE =  ON;
	MY.AMBIENT = 100;
	MY.LIGHTRED = light_flash.RED;
	MY.LIGHTGREEN = light_flash.GREEN;
	MY.LIGHTBLUE = light_flash.BLUE;
	MY.LIGHTRANGE = 64;
	wait(1);

	play_entsound ME,hit_wham,300;
	while(MY.CYCLE <= 7)
	{
		MY.CYCLE += TIME;
		waitt(1);
	}

	// Apply damage
	range = MY._DAMAGE * 6;
	damage = MY._DAMAGE;
 	temp.PAN = 360;
	temp.TILT = 360;
	temp.Z = range;
	indicator = _EXPLODE;	// must always be set before scanning
	scan(MY.POS,MY_ANGLE,temp);

	remove(ME);
}




// runs a bullet; requires shot_speed, damage, fire_mode to be set
//
// Mod Date: 8/31/00 DCP
//				Scale fireball_speed by movement_scale
//				Scaled entity by actor_scale
ACTION bullet_shot
{
	vec_scale(MY.SCALE_X,actor_scale);	// use actor_scale

	MY.ENABLE_BLOCK = ON;
	MY.ENABLE_ENTITY = ON;
	MY.ENABLE_STUCK = ON;
	MY.ENABLE_IMPACT = ON;
	MY.ENABLE_PUSH = ON;
	MY.EVENT = _fireball_event;

	MY.FACING = ON;	// in case of fireball

	MY.LIGHTRED = light_bullet.RED;
	MY.LIGHTGREEN = light_bullet.GREEN;
	MY.LIGHTBLUE = light_bullet.BLUE;
	MY.LIGHTRANGE = 100;
	MY.AMBIENT = 100;

	MY.SKILL2 = shot_speed.x;
	MY.SKILL3 = shot_speed.y;
	MY.SKILL4 = shot_speed.z;
	MY._DAMAGE = damage;
	MY._FIREMODE = fire_mode;

  	// my.near is set by the explosion
	while(MY.NEAR != ON)
	{
		wait(1); // wait at the loop beginning, to let it appear at the start position

		temp = TIME;
		if(temp > 1.5) { temp = 1.5; }	// make bullet slower on slow PCs
// MOVE moves by a distance, so multiply the speed by time.
		fireball_speed.x = MY.SKILL2 * temp;
		fireball_speed.y = MY.SKILL3 * temp;
		fireball_speed.z = MY.SKILL4 * temp;

		if((MY._FIREMODE & BULLET_SMOKETRAIL) == BULLET_SMOKETRAIL)
		{
			temp = 3 * TIME;
			if(temp > 6) { temp = 6; }	// generate max 6 particels
			emit(temp,MY.POS,particle_fade); 	// smoke trail
		}

		vec_scale(fireball_speed,movement_scale);	// scale fireball_speed by movement_scale
 		move(ME,nullskill,fireball_speed);
	}
}




// Desc: launch a rocket (models)
//
// Mod Date: 6/13/00 Doug Poston
//				Created
// Mod Date: 8/31/00 DCP
//				Scale rocket movement by movement_scale
//				Scale rocket size by actor_scale
function rocket_launch()
{
	vec_scale(MY.SCALE_X,actor_scale);	// use actor_scale

 	MY.ENABLE_BLOCK =  ON;      // collision with map surface
	MY.ENABLE_ENTITY =  ON;     // collision with entity
 	MY.ENABLE_STUCK = ON;
	MY.ENABLE_IMPACT = ON;
	MY.ENABLE_PUSH = ON;
 	MY.EVENT = _rocket_event;

	MY.AMBIENT = 100;  // bright
	MY.LIGHTRANGE = 150;
	MY.LIGHTRED = 250;
	MY.LIGHTGREEN = 50;
	MY.LIGHTBLUE = 50;

 	MY.PAN = YOUR.PAN; // the rocket start in the same direction than this 'emitter'
 	MY.TILT = YOUR.TILT;
 	MY.ROLL = YOUR.ROLL;

	MY.SKILL2 = shot_speed.x;
	MY.SKILL3 = shot_speed.y;
	MY.SKILL4 = shot_speed.z;
	MY._DAMAGE = damage;
	MY._FIREMODE = fire_mode;

	MY.SKILL9 = 250; // 'burn time'  (fuel)
	while(MY.SKILL9 > 0)
	{
		temp.X = MY.SKILL2 * TIME;
		temp.Y = MY.SKILL3 * TIME;
		temp.Z = MY.SKILL4 * TIME;
  		vec_scale(temp,movement_scale);	// scale distance by movement_scale
		move(ME,NULLSKILL,temp);

		emit(3,MY.POS,particle_smoke);	// emit( smoke
		MY.SKILL9 -= TIME;  // burn fuel
		waitt(1);     // update position once per tick
	}
	_rocket_event();   // explode when out of fuel
}



// Desc: actor "explode" :
//				face camera
//				play explosion sound
//				animate frames
//		  		remove
ACTION actor_explode
{
	MY.FACING = ON;	// face the camera
	MY.NEAR = ON;
	MY.FLARE = ON;
	MY.PASSABLE = ON;	// don't push the player through walls
	MY.FRAME = 1;
	wait(1);

	PLAY_ENTSOUND ME,explo_wham,1000;
	MY.LIGHTRED = light_explo.RED;
	MY.LIGHTGREEN = light_explo.GREEN;
	MY.LIGHTBLUE = light_explo.BLUE;
	MY.AMBIENT = 100;
	MY.LIGHTRANGE += 50;

// use the new sprite animation
	while(MY.FRAME < MY._DIEFRAMES)
	{
		wait(1);
		MY.LIGHTRANGE += 15;
		MY.LIGHTRED += 20 * TIME;	// fade to red
		MY.LIGHTBLUE -= 20 * TIME;
		MY.FRAME += TIME;
	}
	wait(1);
	remove(ME);
}


// Desc: create a hit point 'effect' depending on (fire_mode & MODE_HIT) value
//
// Input:fire_mode
//			TARGET
//
// 		6/14/00 Doug Poston
//
function _hit_point_effect()
{
	// flash at hit point?
	if((fire_mode & MODE_HIT) == HIT_FLASH)
	{
		weaponTmpSyn = YOU;  // save YOU value
		create(small_flash,TARGET,_blowup);
		YOU = weaponTmpSyn;
	}

	// smoke at hit point?
	if(fire_mode & HIT_SMOKE)
	{
	 	emit(20,TARGET,particle_smoke); // emit smoke
	}

	if(fire_mode & HIT_SPARKS)
	{
		emit(20,TARGET,particle_scatter); // emit sparks
	}

	// bullet hole ***
	if(fire_mode & HIT_HOLE)
	{
		if(YOU == NULL)	// hit wall (not entity)
		{
			create(bullethole_map,TARGET,bullet_hole);  // create bullet hole
		}
	}
}


var	bullet_hole_counter = 0;
DEFINE	kMaxBulletHole	50;

// Desc: bullet hole
function bullet_hole()
{
	// check for maximum bullet holes at any time
	if(bullet_hole_counter < kMaxBulletHole)
	{

		bullet_hole_counter += 1;  // inc bullet hole counter

		MY.TRANSPARENT = ON;
		MY.FLARE = ON;
		MY.PASSABLE = ON;

		MY.ORIENTED = ON;

	   vec_to_angle(MY.PAN,NORMAL);	// rotate to target normal

		waitt(160);          // time bullet stays before vanishing

		// alpha fade
		while(MY.ALPHA > 0)
		{
			MY.ALPHA -= TIME;
			waitt(1);
		}

		bullet_hole_counter -= 1;	// dec bullet hole counter
		remove(ME);
	}
	else   // no room for this bullet
	{
		remove(ME);
	}
}



// Desc: scale and remove the laser beam
//
// Uses: TARGET,
//
// ToDo: make work in 3D player mode
function	laser_fire()
{
	MY.PASSABLE = ON;
   MY.LIGHT = ON;       // illuminate myself
	MY.LIGHTRED = 255;
//?	MY.TRANSPARENT = ON;      // todo: add alpha effects in A5
//?	MY.ALPHA = 15;

	if(RESULT == 0)
	{
		// set the lightrange
		MY.LIGHTRANGE =  vec_length(shot_speed)/2;
		// scale the beam
		MY.SCALE_X = MY.LIGHTRANGE/50;
		// move the beam (center halfway to target)
		vec_add(MY.X,shot_speed.X);

	}
	else
	{
		// set the lightrange
		MY.LIGHTRANGE = RESULT/2;//200;

		MY.SCALE_X = RESULT/200.0; // 200 = beam length
		// move the beam (center halfway to target)
		vec_set(temp,TARGET);	// temp = TARGET
		vec_sub(temp,ME.X);     // temp = TARGET - ME.X
		vec_scale(temp,0.5);    // temp = (TARGET - ME.X)/2
		vec_add(MY.X,temp);
	}
	vec_set(MY.PAN,YOUR.PAN);	// rotate the beam



	WAITT(4);
	REMOVE(ME);

}

/////////////////////////////////////////////////////////////
ON_CTRL weapon_fire;
ON_MOUSE_LEFT weapon_fire;