// File created by Sixten Hilborn

#include serverapi.jss
#include effects.jss

Func defaulteffect_upd(id) // The ID of this projectile
{
	// Get the time at which it should be removed
	Var EntityID = GetProjEntity(id);
	Var Data = GetEntData(EntityID);

	// Get the difference between now and then
	if(GetTime() - Data[0] >= 0)
	{
		return -1;
	}
	return 0;
}


Func BulletShot( Who, Dest, Bullets, Volume, Damage, Bounces ) // Dest is the direction, where Dest[0] = cos(v) and Dest[1] = sin(v)
{
	Var i;

	Var Bounds[2];
	Bounds[0] = 8;
	Bounds[1] = 8;

	Var PlayerId = GetPlayerEntity(Who);

	Var Data[3];
	Data[0] = PlayerId; // Who
	Data[1] = Bounces + 1; // Bounces - 1
	Data[2] = Damage;


	Var Pos = GetPos(PlayerId);

	// Remove acceleration
	Pos[4] = Pos[5] = 0.0;


	Pos[7] = 1; // Always face right
	Pos[8] = "bullet";
	Pos[9] = Pos[10] = 0; // Set animation length to zero to use client settings

	for(i = 0; i < Bullets; i += 1)
	{
		// Set velocity
		Var Angle = GetAngle(Dest[0], Dest[1]);
		if(Bullets > 1)
			Angle += float(Random() % 11 - 5) / 15.0;
		Pos[2] = cos(Angle) * 1000.0;
		Pos[3] = sin(Angle) * 1000.0;
		
		Var ProjId = AddProj(Pos);	
		Var Id = GetProjEntity(ProjId);

		
		SetProjInfo(ProjId, "", "bullet:bulletimpact", Bounds);

		SetEntData(Id, Data);
	}

	Var SndPos[3];
	SndPos[0] = Pos[6];
	SndPos[1] = Pos[0];
	SndPos[2] = Pos[1];
	PlaySound("pistol_shot.wav", -1, SndPos, Volume);
	
	return 0;
}


Func Pistol( Who, Dest )
{
	return BulletShot(Who, Dest, 1, 32, 15.0, 0);
}


Func Shotgun( Who, Dest ) // Dest is the direction, where Dest[0] = cos(v) and Dest[1] = sin(v)
{
	return BulletShot(Who, Dest, 9, 64, 15.0, 0);
}

Func Minigun( Who, Dest ) // Dest is the direction, where Dest[0] = cos(v) and Dest[1] = sin(v)
{
	return BulletShot(Who, Dest, 1, 32, 15.0, 1);
}



Func Rocketlauncher( Who, Dest ) // Dest is the direction, where Dest[0] = cos(v) and Dest[1] = sin(v)
{
	Var i;

	Var Bounds[2];
	Bounds[0] = 16;
	Bounds[1] = 16;

	Var PlayerId = GetPlayerEntity(Who);

	Var Data[2];
	Data[0] = PlayerId; // Who
	Data[1] = GetTime() + 750; // Svoch time


	Var Pos = GetPos(PlayerId);


	Pos[7] = 1; // Always face right
	Pos[8] = "rocket";
	Pos[9] = Pos[10] = 0; // Set animation length to zero to use client settings


	// Set velocity
	Pos[11] = GetAngle(Dest[0], Dest[1]);

	Var cosv = cos(Pos[11]),
		sinv = sin(Pos[11]);
	Pos[2] = cosv * 300.0;
	Pos[3] = sinv * 300.0;
	Pos[4] = cosv * 1200.0;
	Pos[5] = sinv * 1200.0;

	Var ProjId = AddProj(Pos);
	Var Id = GetProjEntity(ProjId);

	SetProjInfo(ProjId, "bullet:rocketupdate", "bullet:rocketimpact", Bounds);

	SetEntData(Id, Data);


	Var SndPos[3];
	SndPos[0] = Pos[6];
	SndPos[1] = Pos[0];
	SndPos[2] = Pos[1];
	PlaySound("firerocket.wav", -1, SndPos, 64);

	return 0;
}

Func GrenadeCore( Who, Dest, EntityID, Velocity)
{
	Var Data[2];
	Data[0] = GetPlayerEntity(Who); // EntityID; // Who
	Data[1] = GetTime() + 1500;


	Var Bounds[2];
	Bounds[0] = 20;
	Bounds[1] = 20;

	Var Pos = GetPos(EntityID);


	// Pos[7] = 1; // Always face right
	Pos[8] = "grenade";
	Pos[9] = Pos[10] = 0; // Set animation length to zero to use client settings

	// Set rotation & rotation velocity
	Pos[11] = GetAngle(Dest[0], Dest[1]);
	Pos[12] = float(Random() % 11 - 6) * 2.0 + 1.0;

	Var Gravity = GetConf("sv_gravity");

	// Set velocity
	Var cosv = cos(Pos[11]),
		sinv = sin(Pos[11]);
	Pos[2] += cosv * Velocity;
	Pos[3] += sinv * Velocity;
	Pos[4] = 0; // No X-acceleration
	Pos[5] = Gravity; // Gravity !!11 C:
	

	Var ProjId = AddProj(Pos);
	Var Id = GetProjEntity(ProjId);

	SetProjInfo(ProjId, "bullet:grenadeupdate", "bullet:grenadeimpact", Bounds);

	SetEntData(Id, Data);
	
	return Id;
}

Func CreateCluster(AttackerId, Clusters, X, Y, Level, #Bounces = 0)
{
	Var i;

	Var Bounds[2];
	Bounds[0] = 12;
	Bounds[1] = 12;

	Var Data[2];
	Data[0] = AttackerId;
	Data[1] = Bounces + 1;

	Var Pos[13];

	Var Gravity = GetConf("sv_gravity");

	Pos[0] = X;
	Pos[1] = Y;
	// 2 & 3 are configured within the for-loop
	Pos[4] = 0; // No X-acceleration
	Pos[5] = Gravity; // Gravity !!11 C:
	Pos[6] = Level;
	Pos[7] = 1; // Always pheyz right
	Pos[8] = "cluster";
	Pos[9] = Pos[10] = 0; // Set animation length to zero to use client settings
	// Set rotation & rotation velocity to zero
	Pos[11] = Pos[12] = 0;


	for(i = 0; i < Clusters; i += 1)
	{
		Var Angle = float(Random() % 360) / 360.0;
		
		if(Angle > 0 && Angle < 180)
			Angle = float(Random() % 360) / 360.0;

		Angle *= 6.28318;
		
		// Set velocity
		Var cosv = cos(Angle);
		Var sinv = sin(Angle);

		Var Velocity = float(Random() % 1500 + 500);

		Pos[2] = cosv * Velocity;
		Pos[3] = sinv * Velocity;
	
		Var NewProjId = AddProj(Pos);
		Var EId = GetProjEntity(NewProjId);

		
		SetProjInfo(NewProjId, "", "bullet:ClusterImpact", Bounds);

		SetEntData(EId, Data);
	}
}

Func Grenade( Who, Dest ) // Dest is the direction, where Dest[0] = cos(v) and Dest[1] = sin(v)
{
	Var PlayerId = GetPlayerEntity(Who);

	GrenadeCore( Who, Dest, PlayerId, 400.0 );
	
	Var Pos = GetPos(PlayerId);
	Var SndPos[3];
	SndPos[0] = Pos[6];
	SndPos[1] = Pos[0];
	SndPos[2] = Pos[1];
	PlaySound("throw.wav", -1, SndPos, 128);
	
	return 0;
}


Func SuperGrenade( Who, Dest ) // Dest is the direction, where Dest[0] = cos(v) and Dest[1] = sin(v)
{
	Var i;

	Var Bounds[2];
	Bounds[0] = 20;
	Bounds[1] = 20;

	Var PlayerId = GetPlayerEntity(Who);

	Var Data[2];
	Data[0] = PlayerId; // Who
	Data[1] = GetTime() + 1500;


	Var Pos = GetPos(PlayerId);


	// Pos[7] = 1; // Always face right
	Pos[8] = "supergrenade";
	Pos[9] = Pos[10] = 0; // Set animation length to zero to use client settings

	// Set rotation & rotation velocity
	Pos[11] = GetAngle(Dest[0], Dest[1]);
	Pos[12] = float(Random() % 11 - 6) * 2.0 + 1.0;

	Var Gravity = GetConf("sv_gravity");

	// Set velocity
	Var cosv = cos(Pos[11]),
		sinv = sin(Pos[11]);
	Pos[2] += cosv * 400.0;
	Pos[3] += sinv * 400.0;
	Pos[4] = 0; // No X-acceleration
	Pos[5] = Gravity; // Gravity !!11 C:
	

	Var ProjId = AddProj(Pos);
	Var Id = GetProjEntity(ProjId);

	SetProjInfo(ProjId, "bullet:supergrenadeupdate", "bullet:grenadeimpact", Bounds);

	SetEntData(Id, Data);
	
	Var SndPos[3];
	SndPos[0] = Pos[6];
	SndPos[1] = Pos[0];
	SndPos[2] = Pos[1];
	PlaySound("throw.wav", -1, SndPos);
	
	return 0;
}

Func NukeGrenade( Who, Dest ) // Dest is the direction, where Dest[0] = cos(v) and Dest[1] = sin(v)
{
	Var i;

	Var Bounds[2];
	Bounds[0] = 20;
	Bounds[1] = 20;

	Var PlayerId = GetPlayerEntity(Who);

	Var Data[2];
	Data[0] = PlayerId; // Who
	Data[1] = GetTime() + 1500;


	Var Pos = GetPos(PlayerId);


	// Pos[7] = 1; // Always face right
	Pos[8] = "nukegrenade";
	Pos[9] = Pos[10] = 0; // Set animation length to zero to use client settings

	// Set rotation & rotation velocity
	Pos[11] = GetAngle(Dest[0], Dest[1]);
	Pos[12] = float(Random() % 11 - 6) * 2.0 + 1.0;

	Var Gravity = GetConf("sv_gravity");

	// Set velocity
	Var cosv = cos(Pos[11]),
		sinv = sin(Pos[11]);
	Pos[2] += cosv * 400.0;
	Pos[3] += sinv * 400.0;
	Pos[4] = 0; // No X-acceleration
	Pos[5] = Gravity; // Gravity !!11 C:
	

	Var ProjId = AddProj(Pos);
	Var Id = GetProjEntity(ProjId);

	SetProjInfo(ProjId, "bullet:nukegrenadeupdate", "bullet:grenadeimpact", Bounds);

	SetEntData(Id, Data);
	
	Var SndPos[3];
	SndPos[0] = Pos[6];
	SndPos[1] = Pos[0];
	SndPos[2] = Pos[1];
	PlaySound("throw.wav", -1, SndPos);
	
	return 0;
}



Func BulletImpact( ProjId, Who )
{
	Var ID = GetProjEntity(ProjId);
	Var Pos = GetPos(ID);

	Var Data = GetEntData(Id);

	if(Who >= 0)
	{
		// Don't damage ourselves!
		if(Who == Data[0])
			return 0;

		DealDmg(Data[0], Who, Data[2], 0);

		// RemoveProj(ProjId); (return negative values instead of use removeproj() to win performance)
		return -1;
	}


	Who = -Who;

	if(Who & 2 || Who & 8)
	{
		Pos[2] = -Pos[2];
		Data[1] -= 1;
		SetEntData(Id, Data);
	}

	if(Who & 1 || Who & 4)
	{
		Pos[3] = -Pos[3];
		Data[1] -= 1;
		SetEntData(Id, Data);
	}

	if(Data[1] <= 0)
	{
		// RemoveProj(ProjId); (return negative values instead of use removeproj() for performance)
		return -1;
	}

	SetPos(ID, Pos);

	return 0;
}

Func RocketUpdate( ProjId )
{
	Var ID = GetProjEntity(ProjId);
	Var Data = GetEntData(ID);
	

	if(GetTime() > Data[1])
	{
		Var Pos = GetPos(ID);
		Var Velocity = float(Pos[2] * Pos[2] + Pos[3] * Pos[3]) ^ 0.5;
		Var Delay = Velocity / 1000;
		if(Delay > 300)
			Delay = 300;
		Data[1] = GetTime() + 400 - Delay;
		
		Var Volume = int(Velocity / 1000.0) * 128;
		if(Volume > 128)
			Volume = 128;
		
		
		Var SndPos[3];
		SndPos[0] = Pos[6];
		SndPos[1] = Pos[0];
		SndPos[2] = Pos[1];
		PlaySound("svoch.wav", -1, SndPos, Volume);
		
		SetEntData(ID, Data);
	}
}

Func RocketImpact( ProjId, Who )
{
	Var ID = GetProjEntity(ProjId);
	Var Pos = GetPos(ID);

	Var Data = GetEntData(Id);

	// Don't collide with ourselves!
	if(Who == Data[0])
		return 0;

	if(Who >= 0)
	{
		DealDmg(Data[0], Who, 15.0, 0);
	}

	XPlode(Data[0], Pos, 105.0, 25.0, 200.0, 1.5, ProjId);
	return 0; // XPlode uses the rocket projectile for EXPLOSION

	// RemoveProj(ProjId); (return negative values instead of use removeproj() to win performance)
	return -1;
}


Func GrenadeUpdate(id) // The ID of this projectile
{
	// Get the time at which it should be removed
	Var EntityID = GetProjEntity(id);
	Var Time = GetEntData(EntityID);

	// Get the difference between now and then
	if(GetTime() - Time[1] >= 0)
	{
		Var Pos = GetPos(EntityID);
		XPlode(Time[0], Pos, 90.0, 25.0, 200.0, 1.5, id);

		CreateCluster(Time[0], 6, Pos[0], Pos[1], Pos[6], 1);
		// return zero since XPlode reuses the old projectile
		return 0; // -1;
	}
	return 0;
}


Func GrenadeImpact( ProjId, Who )
{
	Var ID = GetProjEntity(ProjId);
	Var Pos = GetPos(ID);

	// Don't bounce on players plox
	if(Who >= 0)
	{
		return 0;
	}


	Who = -Who;

	if(Who & 2 || Who & 8)
	{
		if(Pos[2] > 0)
			Pos[0] -= 1;
		else
			Pos[0] += 1;
		Pos[2] *= -0.80;
	}
	if(Who & 1 || Who & 4)
	{
		if(Pos[3] > 0)
			Pos[1] -= 1;
		else
			Pos[1] += 1;
		Pos[3] *= -0.60;
	}
	SetPos(ID, Pos);

	return 0;
}


Func ClusterImpact( ProjId, Who )
{
	Var ID = GetProjEntity(ProjId);
	Var Pos = GetPos(ID);

	Var Data = GetEntData(Id);

	XPlode(Data[0], Pos, 50.0, 10.0, 100.0, 0.8);
	
	
	if(Who >= 0)
		return -1;
		
	Who = -Who;

	if(Who & 2 || Who & 8)
	{
		Pos[2] = -Pos[2];
		if(Who & 2)
			Pos[2] -= Random() % 700;
		else
			Pos[2] += Random() % 700;
		Data[1] -= 1;
	}

	if(Who & 1 || Who & 4)
	{
		Pos[3] = -Pos[3];
		if(Who & 1)
			Pos[3] -= Random() % 700;
		else
			Pos[3] += Random() % 700;
		Data[1] -= 1;
	}

	if(Data[1] <= 0)
		return -1;

	SetEntData(Id, Data);
	SetPos(ID, Pos);

	return 0;
}



Func SuperGrenadeUpdate(id) // The ID of this projectile
{
	// Get the time at which it should be removed
	Var EntityID = GetProjEntity(id);
	Var Time = GetEntData(EntityID);

	// Get the difference between now and then
	if(GetTime() - Time[1] >= 0)
	{
		XPlode(Time[0], GetPos(EntityID), 90.0, 25.0, 200.0, 2.0, id);

		Var Dest[2];

		for(Var i = 0; i < 6; i += 1)
		{

			Var Angle = float(Random() % 360) / 360.0;

			if(Angle > 0 && Angle < 180)
				Angle = float(Random() % 360) / 360.0;

			Angle *= 6.28318;

			Dest[0] = cos(Angle);
			Dest[1] = sin(Angle);

			Var Who = GetPlayerIndex(Time[0]);
			
			Var Velocity = float(Random() % 2000) + 50;

			GrenadeCore(Who, Dest, EntityID, Velocity );
		}



		return 0;
	}
	return 0;
}

Func NukeGrenadeUpdate(id) // The ID of this projectile
{
	// Get the time at which it should be removed
	Var EntityID = GetProjEntity(id);
	Var Time = GetEntData(EntityID);

	// Get the difference between now and then
	if(GetTime() - Time[1] >= 0)
	{
		XPlode(Time[0], GetPos(EntityID), 150.0, 40.0, 400.0, 5.0, id);

		return 0;
	}
	return 0;
}

Func Crawler( Who, Dest ) // Dest is the direction, where Dest[0] = cos(v) and Dest[1] = sin(v)
{
	Var i;

	Var Bounds[2];
	Bounds[0] = 20;
	Bounds[1] = 20;

	Var PlayerId = GetPlayerEntity(Who);

	Var Data[3];
	Data[0] = PlayerId;
	Data[1] = GetTime() + 3000;
	
	Var Pos = GetPos(PlayerId);
	
	
	Pos[8] = "proj_crawler";
	Pos[9] = Pos[10] = 0; // Set animation length to zero to use client settings
	
	// Set rotation & rotation velocity
	Pos[11] = Pos[12] = 0;
	
	Var Gravity = GetConf("sv_gravity");
	
	Pos[2] += Dest[0] * 600.0;
	Pos[3] += Dest[1] * 600.0;
	Pos[4] = 0; // No X-acceleration
	Pos[5] = Gravity; // Gravity !!11 C:
	

	Var ProjId = AddProj(Pos);
	Var Id = GetProjEntity(ProjId);
	
	SetProjInfo(ProjId, "bullet:crawlerupdate", "bullet:crawlerimpact", Bounds);
	
	SetEntData(Id, Data);
	
	Var SndPos[3];
	SndPos[0] = Pos[6];
	SndPos[1] = Pos[0];
	SndPos[2] = Pos[1];
	PlaySound("throw.wav", -1, SndPos);
	
	return 0;
}



Func CrawlerUpdate(id) // The ID of this projectile
{
	// Get the time at which it should be removed
	Var EntityID = GetProjEntity(id);
	Var Data = GetEntData(EntityID);
	Var Pos = GetPos(EntityID);
	
	if(!Pos[5])
	{
		Var EntityList = GetLivingEntities(Pos[6], Pos[0], Pos[1], 100.0);
		Var Size = ArraySize(EntityList);
		if(Size > 0)
		{
			for(Var i = 0; i < Size; i += 1)
			{
				if(Size > 1 || EntityList[i] != Data[0])
				{
					Var MyTeam = GetEntityTeam(Data[0]);
					if(MyTeam >= 0 && GetEntityTeam(EntityList[i]) == MyTeam)
						continue;
					Data[1] = GetTime();
					break;
				}
			}
		}
	}

	// Get the difference between now and then
	if(GetTime() - Data[1] >= 0)
	{
		XPlode(Data[0], Pos, 30.0, 25.0, 200.0, 0.5, id);
		CreateCluster(Data[0], 12, Pos[0], Pos[1], Pos[6]);
		return 0;
	}
		
	if(Pos[5])
	{
		Data[1] = GetTime() + 3000;
	}
	else // ANNARS
	{
		
		Var X = int(Pos[0] / 32),
			Y = int(Pos[1] / 32);
			
		Var Vel = 500.0;
		
		if(Data[2] & 2)
		{
			if(!GetTileSolid(Pos[6], X + 1, Y))
			{
				if(Pos[3] > 0)
					Data[2] = 4;
				else
					Data[2] = 1;
				Pos[3] = 0;
				Pos[2] = Vel;
			}
		}
		else if(Data[2] & 8)
		{
			if(!GetTileSolid(Pos[6], X - 1, Y))
			{
				if(Pos[3] > 0)
					Data[2] = 4;
				else
					Data[2] = 1;
				Pos[3] = 0;
				Pos[2] = -Vel;
			}
		}
		else if(Data[2] & 1)
		{
			if(!GetTileSolid(Pos[6], X, Y + 1))
			{
				if(Pos[2] > 0)
					Data[2] = 8;
				else
					Data[2] = 2;
				Pos[2] = 0;
				Pos[3] = Vel;
			}
		}
		else // if(Data[2] & 4)
		{
			if(!GetTileSolid(Pos[6], X, Y - 1))
			{
				if(Pos[2] > 0)
					Data[2] = 8;
				else
					Data[2] = 2;
				Pos[2] = 0;
				Pos[3] = -Vel;
			}
		}
		
		SetEntData(EntityID, Data);
		SetPos(EntityID, Pos);
	}
	
	
	return 0;
}

Func CrawlerImpact( ProjId, Who )
{
	Var ID = GetProjEntity(ProjId);
	Var Pos = GetPos(ID);
	
	// Don't bounce on players plox
	if(Who >= 0)
	{
		return 0;
	}
	
	Var Data = GetEntData(ID);
	
	Var Vel = 500.0;
	
	Who = -Who;
	
	Var X = int(Pos[0] / 32),
		Y = int(Pos[1] / 32);
	

	if(Who & 2 || Who & 8)
	{
		// DON'T GET STUCK IN THE WALL
		if(Who & 2)
			Pos[0] -= 1;
		if(Who & 8)
			Pos[0] += 1;

		Pos[2] = 0;
		if(Pos[5])
		{
			if(Pos[3] > 0)
				Pos[3] = Vel;
			else
				Pos[3] = -Vel;
		}
		else
		{
			if(Data[2] & 1)
				Pos[3] = -Vel;
			else
				Pos[3] = Vel;
		}
	}
	if(Who & 1 || Who & 4)
	{
		// DON'T GET STUCK IN THE WALL
		if(Who & 1)
			Pos[1] -= 1;
		if(Who & 4)
			Pos[1] += 1;

		Pos[3] = 0;
		if(Pos[5])
		{
			if(Pos[2] > 0)
				Pos[2] = Vel;
			else
				Pos[2] = -Vel;
		}
		else
		{
			if(Data[2] & 2)
				Pos[2] = -Vel;
			else
				Pos[2] = Vel;
		}
	}
	
	Pos[5] = 0;
	
	Data[2] = Who;
	SetEntData(ID, Data);
	SetPos(ID, Pos);
	
	return 0;
}


Func Bfg9000( Who, Dest ) // Dest is the direction, where Dest[0] = cos(v) and Dest[1] = sin(v)
{
	Var i;


	Var PlayerId = GetPlayerEntity(Who);

	Var Data[5];
	Data[0] = PlayerId; // Who
	Data[1] = GetTime() + 1000; // Load time of 1 sec
	Data[2] = Dest[0];
	Data[3] = Dest[1];
	Data[4] = -1;


	Var ProjId = AddProj();
	Var Id = GetProjEntity(ProjId);
	
	
	SetProjInfo(ProjId, "bullet:bfg9000update", "", 0);

	SetEntData(Id, Data);

	/*
	Var SndPos[3];
	SndPos[0] = Pos[6];
	SndPos[1] = Pos[0];
	SndPos[2] = Pos[1];
	PlaySound("pistol_shot.wav", -1, SndPos, Volume);
	*/
	
	return 0;
}


Func bfg9000update(id) // The ID of this projectile
{
	// Get the time at which it should be removed
	Var EntityID = GetProjEntity(id);
	Var Data = GetEntData(EntityID);
	Var Pos;

	if(Data[4] < 0)
	{
		// Get the difference between now and then
		if(GetTime() - Data[1] >= 0)
		{
			Pos = GetPos(Data[0]);
			
			// Set velocity
			Var Angle = GetAngle(Data[2], Data[3]);
			Pos[2] = -cos(Angle) * 500.0;
			Pos[3] = -sin(Angle) * 500.0;
			
			SetPos(Data[0], Pos);
			
			Pos[2] *= -1.0;
			Pos[3] *= -1.0;

			// Remove acceleration
			Pos[4] = Pos[5] = 0.0;


			Pos[7] = 1; // Always face right
			Pos[8] = "plasmaball";
			Pos[9] = Pos[10] = 0; // Set animation length to zero to use client settings
			
			SetPos(EntityID, Pos);
			
			Data[4] = 0;
			SetEntData(EntityId, Data);
			
			Var Bounds[2];
			Bounds[0] = 30;
			Bounds[1] = 30;
			
			SetProjInfo(id, "bullet:bfg9000update", "bullet:bfg9000impact", Bounds);
		}
	}
	else
	{
		if(GetTime() - Data[4] >= 0)
		{
			Pos = GetPos(EntityID);
			Var MaxRadius = 200.0;
			Var EntityList = GetLivingEntities(Pos[6], Pos[0], Pos[1], MaxRadius);
			Var ListSize = ArraySize(EntityList);
			MaxRadius *= MaxRadius;

			for(Var i = 0; i < ListSize; i += 1)
			{
				Var Entity = EntityList[i];
				
				if(Entity < 0 || Entity == Data[0])
					continue;

				Var CurrPos = GetPos(Entity);

				
				Var diffX = Pos[0] - CurrPos[0],
					diffY = Pos[1] - CurrPos[1];
				Var Radius = MaxRadius - (diffX * diffX + diffY * diffY);
				
				if(Radius > 0)
				{
					Var Damage = 75.0 * Radius / MaxRadius + 15.0;
					DealDmg(Data[0], Entity, Damage, 0);
				}
			}
			
			Data[4] = GetTime() + 250;
			SetEntData(EntityId, Data);
		}
	}
}


Func bfg9000Impact( ProjId, Who )
{
	Var ID = GetProjEntity(ProjId);
	Var Pos = GetPos(ID);
	Var Data = GetEntData(ID);
	
	// Don't bounce on players plox
	if(Who >= 0 || Data[4] < 0)
	{
		return 0;
	}
	
	
	XPlode(Data[0], Pos, 105.0, 105.0, 500.0, 6.0, ProjId);
	
	/*
	Var EntityList = GetLivingEntities(Pos[6], Pos[0], Pos[1], 750.0);
	Var ListSize = ArraySize(EntityList);
	for(Var i = 0; i < ListSize; i += 1)
	{
		Var Entity = EntityList[i];
		DealDmg(Data[0], Entity, 100.0, 0);
	}
	*/
	
	return 0;
}




Func Landmine( Who, Dest ) // Dest is the direction, where Dest[0] = cos(v) and Dest[1] = sin(v)
{
	Var i;

	Var Bounds[2];
	Bounds[0] = 10;
	Bounds[1] = 10;

	Var PlayerId = GetPlayerEntity(Who);
	
	// Get player data and allocate space if there isn't any
	Var PlyData = GetEntData(PlayerId);
	if(ArraySize(PlyData) < 1)
	{
		resize PlyData, 1;
		PlyData[0] = 0;
	}
	
	// Max number of mines
	if(PlyData[0] >= 4)
		return -2;
	
	// Increment mine count
	PlyData[0] += 1;
	SetEntData(PlayerId, PlyData);

	// Set entity data
	Var Data[1];
	Data[0] = PlayerId;
	
	Var Pos = GetPos(PlayerId);
	
	
	Pos[8] = "landmine"; // Animation name
	Pos[9] = Pos[10] = 0; // Set animation length to zero to use client settings
	
	// Set rotation & rotation velocity
	Pos[11] = GetAngle(Dest[0], Dest[1]);
	Pos[12] = float(Random() % 11 - 6) * 2.0 + 2.0;
	
	Var Gravity = GetConf("sv_gravity");
	
	Pos[2] += Dest[0] * 600.0;
	Pos[3] += Dest[1] * 600.0;
	Pos[4] = 0; // No X-acceleration
	Pos[5] = Gravity; // Gravity !!11 C:
	

	Var ProjId = AddProj(Pos);
	Var Id = GetProjEntity(ProjId);
	
	SetProjInfo(ProjId, "", "bullet:mineimpact", Bounds);
	
	SetEntData(Id, Data);
	
	Var SndPos[3];
	SndPos[0] = Pos[6];
	SndPos[1] = Pos[0];
	SndPos[2] = Pos[1];
	PlaySound("throw.wav", -1, SndPos);
	
	return 0;
}

Func MineUpdate(ProjId)
{
	Var ID = GetProjEntity(ProjId);
	Var Data = GetEntData(ID);
	
	if(GetPlayerIndex(Data[0]) < 0)
	{
		Var Pos = GetPos(ID);
		XPlode(Data[0], Pos, 0.0, 0.0, 0.0, 1.0, ProjId);
		return 0;
	}
}

Func MineImpact( ProjId, Who )
{
	Var ID = GetProjEntity(ProjId);
	Var Pos = GetPos(ID);
	
	// If it's a living entity, KILL IT
	if(Who >= 0)
	{
		Var Data = GetEntData(ID);
		// Don't explode in the air on ourself or on a teamm8
		Var MyTeam = GetEntityTeam(Data[0]);
		if((Who == Data[0] || (MyTeam == GetEntityTeam(Who) && MyTeam >= 0)) && Pos[5])
		{
			return 0;
		}
	
		// FUCK SOMEONE IN THE ASS
		XPlode(Data[0], Pos, 150.0, 20.0, 200.0, 2.0, ProjId);
		
		// Decrease number of mines
		Var PlyData = GetEntData(Data[0]);
		PlyData[0] -= 1;
		SetEntData(Data[0], PlyData);
		
		return 0;
	}
	
	// Don't impact with walls if the mine isn't in the air
	if(!Pos[5])
		return 0;
		
	// Increase the bounds!
	Var Bounds[2];
	Bounds[0] = 150;
	Bounds[1] = 150;
	SetProjInfo(ProjId, "bullet:mineupdate", "bullet:mineimpact", Bounds);


	Who = -Who;
	
	Pos[12] = Pos[2] = Pos[3] = Pos[5] = 0;
	if(Who & 2)
	{
		Pos[11] = 4.71238898;
	}
	else if(Who & 8)
	{
		Pos[11] = 1.57079633;
	}
	else if(Who & 1)
	{
		Pos[11] = 0;
	}
	else if(Who & 4)
	{
		Pos[11] = 3.14159265;
	}
	SetPos(ID, Pos);
	
	return 0;
}


Func Railgun( Who, Dest ) // Dest is the direction, where Dest[0] = cos(v) and Dest[1] = sin(v)
{
	Var PlayerId = GetPlayerEntity(Who);
	Var Pos = GetPos(PlayerId);
	
	Var Anim[3];
	Anim[0] = "lazer";
	Anim[1] = 22;
	Anim[2] = 500;
	
	Lazer(Pos, Dest, PlayerId, 75.0, Anim);
	
	Var SndPos[3];
	SndPos[0] = Pos[6];
	SndPos[1] = Pos[0];
	SndPos[2] = Pos[1];
	PlaySound("lazor.wav", -1, SndPos);
}

