
init(delay)
{
	self endon("killed_player");
	self endon("disconnect");

	if(self.wwx_air_strike) return;

	self notify("end_airstrike");
	wait(0.1);
	self endon("end_airstrike");
	
	// wait the first
	self.wwx_air_strike = true;

	if(!isDefined(delay)) delay = level.wwx_rank_airstrike_first;

	wait delay;

	// check for napalm
	self.wwx_napalm = false;

	switch(level.wwx_rank_wmdtype)
	{
		case 1: // random rank
		if(self.pers["rank"] >= level.wwx_rank_napalm && randomInt(100) < 50) self.wwx_napalm = true;
		break;

		case 2: // allowed random
		if(level.wwx_rank_allow_napalm)
		{
			if(!level.wwx_rank_allow_airstrike) self.wwx_napalm = true;
			else if(randomInt(100) < 50) self.wwx_napalm = true;
		}
		break;

		default: // fixed rank
		if(self.pers["rank"] >= level.wwx_rank_napalm) self.wwx_napalm = true;
		break;
	}

	// ok, lets go
	while(self.wwx_air_strike)
	{
		// let them know the airstrike strike is available
		if(!self.wwx_napalm) self iprintlnbold(&"AIRSTRIKE_READY");
		else self iprintlnbold(&"AIRSTRIKE_READY_NAPALM");
		self teamsound("airstk_ready",1);
			
		//set up the on screen icon
		self hudnotify();
            self.calling = false;
		level.cmg = false;
		level.cmgf = false;
		level.cmgb = false;
		//monitor for binocular fire
		self thread waitforuse();
		
		// wait until they use airstrike
		self waittill("airstrike_over");

		if(level.wwx_planes_flak && level.wwx_flakison)
		{
			level notify("stop_flak");
			level.wwx_flakison = false;
		}

		if(level.wwx_rank_wmdtype >= 1) break;
            self iprintlnbold(&"AIRSTRIKE_WAIT");
		self teamsound("airstk_reload",3);
		// now wait for one interval
		wait(level.wwx_rank_airstrike_int + randomint(10));
	}

	// stop airstrikes
	self.wwx_air_strike = false;

	self notify("airstrike_over");
	self notify("end_airstrike");
}	

friendlyInstrikezone(targetpos)
{
	// dont need to check friendly disabled
	if(level.wwx_frndly == 0) return false;

	// dont need to check friendly if non teambased
      if(level.wwx_currentgt == "dm" || level.wwx_currentgt == "lms" || level.wwx_currentgt == "ihtf") return false;
	
	if(!isDefined(targetpos)) return (undefined);
    
	if(distance(targetpos, self.origin) <= 1000) return (undefined);
		
	// check if players  in the same team are in targetzone
	players = getentarray("player", "classname");
	for(i = 0; i < players.size; i++)
	{
		if(isPlayer(self) && isPlayer(players[i]))
		{
			if(players[i].sessionstate == "playing" && players[i].pers["team"] == self.pers["team"])
			{
				if(distance(targetpos, players[i].origin) <= 1000)
				return true;
			}
		}
	}

	return false;
}


hudnotify()
{
	self endon("killed_player");
	
	self hudnotifyremove();

	self.airstrike_available_icon = newClientHudElem(self);		
	self.airstrike_available_icon.alignX = "center";
	self.airstrike_available_icon.alignY = "middle";
	self.airstrike_available_icon.x = 172;
	self.airstrike_available_icon.y = 455;
	self.airstrike_available_icon.alpha = 1;
	self.airstrike_available_icon setShader(game["airstrike"], 32, 32);	

	if(!isDefined(self.wwx_binocular_hint))
	{
		self.wwx_binocular_hint = newClientHudElem( self );
		self.wwx_binocular_hint.alignX = "center";
		self.wwx_binocular_hint.alignY = "top";
		self.wwx_binocular_hint.fontScale = 1;
		self.wwx_binocular_hint.x = 320;
		self.wwx_binocular_hint.y = 464;
		
		self.wwx_binocular_hint.sort = 5;
		self.wwx_binocular_hint setText(&"WMD_ACTIVATE_HINT");

		// do not show hint if planting a tripwire
		if(level.wwx_tweapon)
		{
			if(	!self.wwx_plantwire && !self.wwx_defusewire && !isDefined(self.wwx_actimer) ||
				self [[level.wwx_getstance]](false) != 2 && !isDefined(self.wwx_actimer)) self.wwx_binocular_hint.alpha = 1;
			else self.wwx_binocular_hint.alpha = 0;
		}
		else self.wwx_binocular_hint.alpha = 1;
	}
}

hudnotifyremove()
{
	if(isDefined(self.airstrike_available_icon)) self.airstrike_available_icon destroy();
}

binochinthud()
{
	self endon("binocular_exit");
	
	if(!isDefined(self.wwx_binocular_hint))
	{
		self.wwx_binocular_hint = newClientHudElem( self );
		self.wwx_binocular_hint.alignX = "center";
		self.wwx_binocular_hint.alignY = "top";
		self.wwx_binocular_hint.fontScale = 1;
		self.wwx_binocular_hint.x = 320;
		self.wwx_binocular_hint.y = 464;
		self.wwx_binocular_hint.alpha = 1;
		self.wwx_binocular_hint.sort = 5;
	}

	if(!self.wwx_napalm) self.wwx_binocular_hint setText(&"WMD_AIRSTRIKE_HINT");
	else self.wwx_binocular_hint setText(&"WMD_NAPALM_HINT");

	self thread airstrike_binocularhint_hud_destroy2();
}

airstrike_binocularhint_hud_destroy()
{	
	if(isDefined(self.wwx_binocular_hint)) self.wwx_binocular_hint destroy();
}

airstrike_binocularhint_hud_destroy2()
{
	self endon("binocular_enter");
	self endon("killed_player");
	self waittill("binocular_exit");
	
	if(isDefined(self.wwx_binocular_hint)) self.wwx_binocular_hint destroy();
}

gettargetposition()
{
	startOrigin = self getEye() + (0,0,20);
	forward = anglesToForward( self getplayerangles() );
	forward = [[level.wwx_vectorscale]]( forward, 100000 );
	endOrigin = startOrigin + forward;
	
	trace = bulletTrace( startOrigin, endOrigin, false, self );

	if(trace["fraction"] == 1.0 || trace["surfacetype"] == "default") return (undefined);
	else return (trace["position"]);
}

waitforuse()
{
	self endon("end_waitforuse");
	self endon("killed_player");

	for (;;)
	{
		self waittill("binocular_enter");
		self thread waitforbinocuse();
		self thread binochinthud();
		wait .2;
	}

}

waitforbinocuse()
{
	//kill dupes
	self notify("binocular_exit");
	wait(0.1);
	self endon("binocular_exit");
	self endon("airstrike_fired");
	self endon("killed_player");

	//wait for use button to be pressed
	for(;;)
	{
		if(isPlayer(self) && self useButtonPressed() && !self.calling)
		  {
		  self.calling = true;
		  self thread callradio();
		  self waittill ("radiodone");
		  }
		wait .01;						
	}
}
callradio()
{
        self endon("killed_player");    
			
		targetpos = gettargetposition();
		self iprintlnbold(&"AIRSTRIKE_RADIO_IN");	
		self teamsound("airstk_firemission",3.6);
		for(i=1;i<4;i++) self teamsound("airstk_" + randomInt(8),0.6);
	         
		self teamsound("airstk_pointfuse",3);
			
		friendly =  friendlyInstrikezone(targetpos);	
			
			
			
			if(isDefined(targetpos) && isDefined(friendly) && friendly == false)
			{
				self iprintlnbold(&"AIRSTRIKE_ONWAY");	
				self teamsound("airstk_ontheway",4);

				//notify threads
				self notify("radiodone");
				self notify("end_waitforuse");
				self notify ("airstrike_fired");
				
				// player has used weapon
				self.usedweapons = true;
				
				airstrike = spawn("script_origin",targetpos);
				
	            if(level.wwx_air_raid) airstrike thread ww2x\_wwx_utils::playSoundLoc("air_raid",targetpos);
				
				airstrike thread firebarrage(self);

				//clear hud icon
				self hudnotifyremove();

				//clear hint icon
				if(isDefined(self.wwx_binocular_hint)) self.wwx_binocular_hint destroy();

			}
		    else if(!isDefined(targetpos) && !isDefined(friendly)) 
		       {
		       friendly = undefined; 
			   self iprintlnbold(&"AIRSTRIKE_NOT_VALID");
			   self teamsound("airstk_novalid",3);
		       //wait(3);
			   self notify("radiodone");
			   }
		    else if(isDefined(friendly) && friendly == true) 
			   {
			   friendly = undefined; 
			   self iprintlnbold(&"AIRSTRIKE_FRIENDLY_WARNING");
			   self teamsound("airstk_frndly",3);
		       //wait(3);
			   self notify("radiodone");
			   }
	        else if(isDefined(targetpos) && !isDefined(friendly)) 
		       {
		       friendly = undefined; 
			   self iprintlnbold(&"AIRSTRIKE_TO_CLOSE_WARNING");
			   self teamsound("airstk_tooclose",3);
		       //wait(3);
			   self notify("radiodone");
			   }
	self.calling = false;
}

firebarrage(owner)
{
	//drop flare
	if(level.wwx_rank_wmd_flare) playfx(level.wwx_effect["flare_indicator"], self.origin);

	//do warning
	//warnings(self.origin, owner);

	if(level.wwx_planes_flak && !level.wwx_flakison)
	{
		for(flak=0;flak<level.wwx_flakfx;flak++)
		thread ww2x\_wwx_skyeffects::flakfx();
	}

	wait 10;

	//create planes
	airstrikesize = randomInt(3) + 2;
	bombpositions = [];
	
	for(i = 0; i < airstrikesize; i++ )
		bombpositions[i] = calcshellpos(self.origin);
	
	//reset delay
	self.airstrikeGlobalDelay = 0;
	
	apflangle = randomInt(360);

	//fire shells
	for(i = 0; i < airstrikesize; i++)
	{
		if(isDefined(self)) self thread createplanes(bombpositions[i] , apflangle, owner);
		wait (randomFloatRange( 1.5, 3));
	}

	wait 10;

	if(level.wwx_planes_flak && level.wwx_flakison)
	{
		level notify("stop_flak");
		level.wwx_flakison = false;
	}

	//end
	owner notify ("airstrike_over");

	self delete();
}

calcshellpos(targetPos)
{	
	bombPos = undefined;
	iterations = 0;
	
	while(!isDefined (bombPos) && iterations < 5)
	{
		bombPos = targetPos;
		angle = randomfloat( 360 );
		radius = randomfloat(level.wwx_rank_airstrike_radius);
		randomOffset = (cos(angle) * radius, sin(angle) * radius, 0);
		bombPos += randomOffset;
		startOrigin = bombPos + (0, 0, 800);
		endOrigin = bombPos + (0, 0, -2048);

		trace = bulletTrace( startOrigin, endOrigin, false, undefined );
		if(trace["fraction"] < 1.0) bombPos = trace["position"];
		else bombPos = undefined;

		iterations++;
	}
      if(!isDefined(bombPos)) bombPos = targetPos;
	return (bombPos);
}

createplanes(targetpos , apflangle, owner)
{
	thread ww2x\_wwx_logfile::Log("Planes");

	level endon("wwx_stop_ambient_fx");

	// pick a plane team
	if(isPlayer(owner))
	{
		if(owner.pers["team"] == "axis") apteam = 0;
		else apteam = 1;
	}
	else return;

	// set team definition
	if(apteam == 0) level.apteam = "axis";
	else level.apteam = "allies";

	// set planes in sky values
	if(apteam == 0) level.wwx_pallieapinsky++;
	else level.wwx_paxisapinsky++;
				
	apstpoint = [];
	apenpoint = [];
	apposinmap = [];

	x = targetpos[0] + randomInt(250);
	y = targetpos[1] + randomInt(250);

	if(	level.wwx_currentmap == "mp_carentan" || level.wwx_currentmap == "mp_decoy" ||
		level.wwx_currentmap == "mp_railyard" || level.wwx_currentmap == "mp_toujane") z = level.wwx_mapArea_PlaneZ - randomInt(50);
      else if(level.wwx_planes_altitude) z = level.wwx_planes_altitude - randomInt(50);
		else z = level.wwx_mapArea_Max[2] - randomInt(50);

	stenpos = getapsten((x,y,z),apflangle);
	stenpos2 = getapsten((stenpos[1]),apflangle);
		
	if(stenpos2[10] == 1) stenpos[1] = stenpos2[1];

	apstpoint = stenpos[0];
	apenpoint = stenpos[1];
	apposinmap = (x,y,z);

	apmodel = [];
	apsoundchoice = [];

	if(apteam == 0)
	{
		// plane models
		apmodel[0] = "xmodel/vehicle_stuka_flying";
		apmodel[1] = "xmodel/vehicle_condor";

		// plane names
		apname[0] = &"VEHICLES_STUKA";
		apname[1] = &"VEHICLES_CONDOR";

		// plane sounds
		apsoundchoice[0] = "stuka_flyby_1";
		apsoundchoice[1] = "stuka_flyby_2";
	}
	else
	{
		// plane models
		apmodel[0] = "xmodel/vehicle_spitfire_flying";
		apmodel[1] = "xmodel/vehicle_p51_mustang";

		// plane names
		apname[0] = &"VEHICLES_SPITFIRE";
		apname[1] = &"VEHICLES_P51MUSTANG";

		// plane sounds
		apsoundchoice[0] = "spitfire_flyby_1";
	}

	aprand = randomInt(apmodel.size);
	apsound = apsoundchoice[randomInt(apsoundchoice.size)];

	planetype = 0; // fighter
	if(apteam == 0 && aprand == 1) planetype = 1; // bomber

	plane = spawn("script_model", (0,0,0));
	plane setModel(apmodel[aprand]);
	plane hide();

	if(apteam == 0 && planetype == 0) plane.angles = plane.angles + (10,apflangle,0);
	else plane.angles = plane.angles + (0,apflangle,0);

	plane.origin = apstpoint;
	plane show();
	plane.identity = "plane";
	plane.name = apname[aprand];
	plane.isbombing = false;
	planecrash = false;
	randomcrash = false;

	if(randomInt(100) < 10) // 10% chance plane will crash
	randomcrash = true;

	plane.smoke = false;
	plane.playapdivesound = false;
	plane.health = 200 + randomInt(100);	// plane starting health	
	plane.smhealth = plane.health - 100;		// when planes health drops below this, turn on smoke!

	// set speed
	apspeed = randomInt(250) + 300; // fighters
	if(apteam == 0 && planetype == 1) apspeed = randomInt(250) + 200; // bombers

	plane.apdivesound = spawn("script_model", (0,0,0));
	plane.apdivesound.origin = apstpoint - (0,50,0);
	plane.apdivesound linkto(plane);

	plane.apsound = spawn("script_model", (0,0,0));
	plane.apsound.origin = apstpoint - (0,50,0);
	plane.apsound linkto(plane);
	plane.apsound playloopsound(apsound);

	// flighttime
	flighttime = int(timespeedcalc(apspeed, apstpoint, apenpoint));
	plane moveto(apenpoint, flighttime);

	rollpos = undefined;
	rollneg = undefined;

	if(flighttime >= 4)
	{
		switch(randomInt(3))
		{
			case 0:	{ plane rotateroll(45,flighttime,3,1); rollpos = 1; break; }
			case 1: { plane rotateroll(-45,flighttime,3,1); rollneg = 1; break; }
		}
	}

	if(level.cmg == false ) 
	{
	level.cmg = true; 
	owner teamsound("pilot_cmg_target",4);
	}
	wait 3;
	if(level.wwx_planes_flak && level.wwx_flakison && level.cmgf == false) 
	{
	level.cmgf = true;
	owner teamsound("flack_hang_on",3);
	}
	for(i=0;i<((flighttime/3)*2);i+=0.1)
	{
		if(distance(targetPos, plane.origin) < 1000 + apspeed && !plane.isbombing)
			plane thread bombsetup(flighttime, apteam, planetype, owner, targetpos);

		if(flighttime > (flighttime/2))
		{
			if(isDefined(rollpos)) plane rotateroll(-90,(flighttime/2),1,1);
			if(isDefined(rollneg)) plane rotateroll(90,(flighttime/2),1,1);
		}

		if(distance(level.wwx_playArea_Centre, plane.origin) < 3000 && randomcrash)
		{
			
			
			playfx(level.wwx_effect["flak_flash"], plane.origin - (0, 200, 0));
			plane playsound("plane_explosion_2");
			if(planetype == 1) owner teamsound("airstk_vbc",1);
			if(planetype == 0) owner teamsound("airstk_vfc",2);
			wait 0.2;
			playfx(level.wwx_effect["flak_smoke"], plane.origin - (0, 200, 0));
			wait 0.2;
			playfx(level.wwx_effect["flak_dust"], plane.origin - (0, 200, 0));
			wait 0.5;			
			plane.apdivesound playloopsound("plane_dive");
			playfx(level.wwx_effect["plane_explosion"], plane.origin);
			plane playsound("plane_explosion_2");
			wait 0.5;
			playfx(level.wwx_effect["plane_explosion"], plane.origin);
			speed = randomInt(200) + 200;
			plane airplanecrash(undefined, speed, apteam,planetype, undefined, true);
			return;
		}
		
		if(plane.smoke) playfx(level.wwx_effect["plane_smoke"], plane.origin);
		wait 0.05;
		if(plane.smoke) playfx(level.wwx_effect["plane_smoke"], plane.origin);
		wait 0.05;
	}

	rolltime = flighttime / 3;

	// has survived?, victory roll for fighters and bank for bombers but not every time!
	if(!rolltime <= 0)
	{
		if(planetype != 1)
		{
			switch(randomInt(5))
			{
				case 0:	{ plane rotateroll(360,rolltime,rolltime/2,rolltime/2); break; }
				case 1: { plane rotateroll(-360,rolltime,rolltime/2,rolltime/2); break; }
				default: break;
			}
		}
		else
		{
			switch(randomInt(5))
			{
				case 0:	{ plane rotateroll(45,rolltime,rolltime/2,rolltime/2); break; }
				case 1: { plane rotateroll(-45,rolltime,rolltime/2,rolltime/2); break; }
				default: break;
			}
		}
	}

	wait rolltime;

	if(isDefined(plane.apsound))
	{
		plane.apsound stopLoopSound();
		plane.apsound delete();
	}

	if(isDefined(plane.apdivesound))
	{
		plane.apdivesound stopLoopSound();
		plane.apdivesound delete();
	}

	if(apteam == 0) level.wwx_paxisapinsky--;
	else level.wwx_pallieapinsky--;

	if(isDefined(plane)) plane delete();
}

getapsten(startpos, angle)
{
	thread ww2x\_wwx_logfile::Log("getapsten");

	forwardvector = anglestoforward( (0,angle,0) );
	backpos = startpos + ([[level.wwx_vectormulti]](forwardvector,-30000));
	frontpos = startpos + ([[level.wwx_vectormulti]](forwardvector,30000));
	fronthit = 0;

	trace = bulletTrace(startpos,backpos,false,undefined);
	if(trace["fraction"] != 1) start = trace["position"];
	else start = backpos;

	trace = bulletTrace(startpos,frontpos,false,undefined);
	if(trace["fraction"] != 1)
	{
		endpoint = trace["position"];
		font_hit = 1;
	}
	else endpoint = frontpos;

	startpos = start + ([[level.wwx_vectormulti]](forwardvector,-3000));
	endpoint = endpoint + ([[level.wwx_vectormulti]](forwardvector,3000));
	stenpos[0] = startpos;
	stenpos[1] = endpoint;
	stenpos[10] = fronthit;
	return stenpos;
}

airplanecrash(attacker, speed, apteam,planetype, crashpos, forced)
{
	thread ww2x\_wwx_logfile::Log("airplanecrash");

	self.fire = 1;

	if(!isDefined(attacker)) self.fire = 0;
	else if(randomInt(100) > 50) self.fire = 1;

	angle = self.angles;
	
	if(forced)
		pitch = randomInt(25) + 25;
	else
		pitch = randomInt(4) + 4;

	yaw = randomInt(50)  - 25;
	roll = 200 - randomInt(400);
	angle_start = angle + (pitch,yaw,0);
	forwardvector = anglestoforward(angle_start);              

	if(isDefined(crashpos))
	{
		if(randomInt(100) < 50)
			endpoint = crashpos;
		else
		{
			x = int((crashpos[0]) / 8);
			y = int((crashpos[1]) / 8);
			
			endpoint = crashpos - (x, y, 100);
		}
	}
	else
	{
		endpoint = self.origin + ([[level.wwx_vectormulti]](forwardvector,30000));
	
		trace=bulletTrace(self.origin,endpoint, true, undefined);
		if(trace["fraction"] < 1 && trace["position"][2] > level.wwx_mapArea_Min[2] - 500) endpoint = trace["position"];
		else endpoint = self.origin + ([[level.wwx_vectormulti]](forwardvector,100));
	}

	falltime = timespeedcalc(speed, self.origin, endpoint);
	rotdone = "notdone";

	if(falltime > 1)
	{
		start_turn = 0;

		self moveto(endpoint,falltime);

		np = (pitch/(0.5/0.05));
		ny = (yaw/(0.5/0.05));
		nr = (roll/(falltime/0.05));

		for(i=0;i<falltime;i+=0.05)
		{
			if(i <= 0.5)
			{
				self.angles += (np,0,0);
				self.angles += (0,ny,0);
				self.angles += (0,0,nr);
			}
			else if(start_turn == 0)
			{
				start_turn   = 1;
				self.angles += (0,0,nr);
			}

			playfx(level.wwx_effect["plane_smoke"], self.origin);

			if(self.fire == 1) playfx(level.wwx_effect["plane_smoke"], self.origin);

			wait 0.05;
		}
	}       

	wait 0.05;

	self stoploopsound();

	if(isDefined(self.apsound))
	{
		self.apsound stopLoopSound();
		self.apsound delete();
	}

	if(isDefined(self.apdivesound))
	{
		self.apdivesound stopLoopSound();
		self.apdivesound delete();
	}

	// explosions
	hm = randomInt(2) + 1; // how many explosions, at least 1

	for(i = 0; i < 2;i++)
	{
		for(exp=0; exp < hm; exp++)
		{
			// play the incoming sound falling sound
			planecrashsfx[0] = "plane_explosion_1";
			planecrashsfx[1] = "plane_explosion_2";
			planecrashsfx[2] = "plane_explosion_3";
			pc = randomInt(planecrashsfx.size);
			self playsound(planecrashsfx[pc]);
	
			// * do the damage *
			self thread ww2x\_wwx_utils::scriptedfxradiusdamage(self, undefined, "MOD_EXPLOSIVE", "plane_mp", level.wwx_planecrash_radius, 500, 300, "plane_explosion", undefined, true, true, true);
	
			playfx(level.wwx_effect["plane_smoke"], self.origin);
	
			if(exp != 2)
			{
				wait 0.3;
				wait randomFloat(1);
			}
			else
			{
				wait 0.3;
				wait randomFloat(2);
			}
		}
	}

	if(apteam == 0) level.wwx_paxisapinsky--;
	else level.wwx_pallieapinsky--;

	level.wwx_planescrashed++;
	if(level.wwx_planescrashed > 4)
	{
		self hide();
		self delete();
		return;
	}

	self planeCrashSmokeFX();
	level.wwx_planescrashed--;
	self delete();
}

planeCrashSmokeFX()
{
	self thread ww2x\_wwx_utils::hotSpot(self.origin, 120, "MOD_EXPLOSIVE", "plane_mp");

	for(i = 0; i < 25; i++)
	{
		playfx(level.wwx_effect["planecrash_fire"], self.origin);
		wait 0.5;
		playfx(level.wwx_effect["planecrash_ball"], self.origin);
		wait 0.5;
	}

	self notify("endhotspot");
	self hide();
	thread planeCrashDelayedSmokeFX(self.origin);
}

planeCrashDelayedSmokeFX(position)
{
	for(i = 0; i < 25; i++)
	{
		playfx(level.wwx_effect["planecrash_smoke"], position);
		wait 0.5;
		if(i < 15) playfx(level.wwx_effect["planecrash_ball"], position);
		wait 0.5;
	}
}

// bomb routines
bombsetup(time, apteam, planetype, owner, targetpos)
{
	self.isbombing = true;
	bombcount = 0;
	bombno = randomInt(3) + 2;

	// add 2 more bombs for bomber
	if(apteam == 0 && planetype == 1) bombno+= 2;

	while(bombcount < bombno)
	{
		self thread dropthebombs(time, apteam, planetype, owner, targetpos);
		bombcount++;
		wait 0.3;
	}
}

dropthebombs(time, apteam, planetype, owner, targetpos)
{
	if(!isDefined(self)) return;

	startpoint = self.origin;
	forwardvector = anglestoforward(self.angles);                
	endorigin = startpoint + ([[level.wwx_vectormulti]](forwardvector,360));

	// get the impact point
	trace = bulletTrace(startpoint,(endorigin[0],endorigin[1],endorigin[2] - 2048), true, self);                   
	if(trace["fraction"] < 1) endorigin = trace["position"];
	else 	endorigin = targetpos;

	// bomb falltime
	falltime = timespeedcalc(350, startpoint, endorigin);
	if(falltime <= 0.1) return; // abort

	// bomb model
	modeltype = "xmodel/prop_stuka_bomb";

	// spawn the bomb and drop it
	if(level.cmgb == false )
	{
	level.cmgb = true;
	owner teamsound("fire_away",1);
	}
	bomb = spawn("script_model", startpoint);
	bomb.angles = self.angles + (-180 + randomint(50),0,0);
	bomb setModel(modeltype);
	bomb moveto(endorigin + (0,0, - 100), falltime);

	// play the incoming sound falling sound
	bombsfx[0] = "mortar_incoming1";
	bombsfx[1] = "mortar_incoming2";
	bombsfx[2] = "mortar_incoming3";
	bombsfx[3] = "mortar_incoming4";
	bombsfx[4] = "mortar_incoming5";
	bs = randomInt(bombsfx.size);
	bomb playsound(bombsfx[bs]);

	// wait for it to hit
	wait falltime;

	// do the damage
	if(isPlayer(owner) && isDefined(owner.wwx_napalm))
	{
		if(owner.wwx_napalm) bomb thread ww2x\_wwx_utils::scriptedfxradiusdamage(owner, undefined, "MOD_GRENADE", "planebomb_mp", level.wwx_planebomb_radius, 500, 400, "plane_bomb", undefined, true, true, true, "napalm");
		else bomb thread ww2x\_wwx_utils::scriptedfxradiusdamage(owner, undefined, "MOD_GRENADE", "planebomb_mp", level.wwx_planebomb_radius, 500, 400, "plane_bomb", undefined, true, true, true);
	}
	else bomb thread ww2x\_wwx_utils::scriptedfxradiusdamage(self, undefined, "MOD_GRENADE", "planebomb_mp", level.wwx_planebomb_radius, 500, 400, "plane_bomb", undefined, true, true, true);

	// play the explosion sound
	bombsfx[0] = "mortar_explosion1";
	bombsfx[1] = "mortar_explosion2";
	bombsfx[2] = "mortar_explosion3";
	bombsfx[3] = "mortar_explosion4";
	bombsfx[4] = "mortar_explosion5";
	bs = randomInt(bombsfx.size);
	bomb playsound(bombsfx[bs]);

	bomb hide();
	wait 1;
	bomb delete();
}

timespeedcalc(speed,startpoint,endpoint)
{
	// do not allow negative values
	if(speed < 1) return 0.1;

	abstand = distance(startpoint,endpoint);
	falltime = (abstand/speed) /4;

	// do not allow negative values
	if(falltime < 0) falltime = 0.1;

	return falltime;
}
teamsound(nat,wt)
{
    if (self.pers["team"] == "allies")
		{
		switch(game["allies"])
			{
			case "american":self playLocalSound("us_"+nat);wait(wt);break;
							
			case "british":self playLocalSound("uk_"+nat);wait(wt);break;
					
			default:self playLocalSound("ru_"+nat);wait(wt);break;
			}
		}
	else if (self.pers["team"] == "axis")
		{
		switch(game["axis"])
			{
			case "german":self playLocalSound("ge_"+nat);wait(wt);break;
			}
		}
}