void Crossbow_Projectile(ServerEntity_t *ent)
{
	// [11/2/2012] Revised and fixed ~hogsy
	MathVector3f_t mvDirection;
	ServerEntity_t *eArrow;

	eArrow = Entity_Spawn();
	if(eArrow)
	{
		eArrow->local.eOwner = ent;

		eArrow->v.movetype	= MOVETYPE_FLY;

		eArrow->Physics.iSolid	= SOLID_BBOX;

		Math_MVToVector(Weapon_Aim(ent), mvDirection);
		Math_VectorScale(mvDirection, 2000.0f, eArrow->v.velocity);

		Entity_SetModel(eArrow,"models/arrow.md2");
		Entity_SetSizeVector(eArrow,g_mvOrigin3f,g_mvOrigin3f);

		// [25/6/2012] Simplified ~hogsy
		Math_VectorCopy(ent->v.origin,eArrow->v.origin);
		eArrow->v.origin[2] += 15.0f;

		Math_MVToVector(Math_VectorToAngles(ent->v.velocity),ent->v.angles);

		eArrow->v.TouchFunction = arrow_touch;
	}
}
// [4/7/2012] Renamed to Discus_SpawnProjectile ~hogsy
void Discus_SpawnProjectile(ServerEntity_t *ent,vec3_t org)
{
	ServerEntity_t *eDiscus;
	MathVector3f_t mvDirection;

	eDiscus = Entity_Spawn();

	eDiscus->v.cClassname = "discus";
	eDiscus->v.movetype = MOVETYPE_FLYBOUNCE;
	eDiscus->Physics.iSolid = SOLID_BBOX;
	eDiscus->v.effects = EF_MOTION_ROTATE;
	eDiscus->v.enemy = ent;

	// [4/8/2012] Updated to use owner instead ~hogsy
	eDiscus->local.eOwner = ent;

	eDiscus->local.hit = 0;

	Math_MVToVector(Weapon_Aim(ent), mvDirection);
	Math_VectorScale(mvDirection, 700.0f, eDiscus->v.velocity);

	Math_MVToVector(Math_VectorToAngles(eDiscus->v.velocity), eDiscus->v.angles);

	eDiscus->v.TouchFunction = Discus_ProjectileTouch;

	Entity_SetModel(eDiscus, "models/w_daedalus.md2");
	Entity_SetSizeVector(eDiscus, g_mvOrigin3f, g_mvOrigin3f);
	Entity_SetOrigin(eDiscus, org);

	Sound(ent,CHAN_WEAPON,"weapons/discus/discusthrow.wav",255,ATTN_NORM);
}
void C4Vizatergo_PrimaryAttack(ServerEntity_t *eOwner)
{
	MathVector3f_t vOrigin;
	MathVector3f_t mvDirection;
	ServerEntity_t *c4ball = Entity_Spawn();

	Sound(eOwner,CHAN_AUTO,"weapons/c4/c4fire.wav",255,ATTN_NORM);
	Sound(eOwner,CHAN_AUTO,"weapons/c4/c4cock.wav",255,ATTN_NORM);

	Weapon_Animate(eOwner,C4Animation_Fire1);
	Weapon_ViewPunch(eOwner, 7, true);

	eOwner->v.iPrimaryAmmo = eOwner->local.iC4Ammo -= 1;

	c4ball->v.cClassname	= "c4ball";
	c4ball->v.movetype		= MOVETYPE_BOUNCE;

	c4ball->local.style = AMMO_C4BOMBS;		// Cleaner way to tell if this can explode or not :V ~hogsy
	c4ball->local.iC4Ammo = 1;				// [11/8/2013] Since style is used for other shit too LAWL ~hogsy
	c4ball->local.eOwner = eOwner;

	// Set the physical properties.
	c4ball->Physics.iSolid = SOLID_BBOX;
	c4ball->Physics.fMass = 0.9f;
	c4ball->Physics.eIgnore = eOwner;
	c4ball->Physics.fGravity = SERVER_GRAVITY;

	Math_MVToVector(Weapon_Aim(eOwner), mvDirection);
	Math_VectorScale(mvDirection, C4VIZATERGO_MAX_RANGE, c4ball->v.velocity);

	c4ball->v.velocity[pY] += 20.0f;

	Math_MVToVector(Math_VectorToAngles(c4ball->v.velocity),c4ball->v.angles);
	Math_VectorCopy(eOwner->v.origin,vOrigin);

	c4ball->v.TouchFunction = C4Vizatergo_C4BallTouch;
	c4ball->v.think = C4Vizatergo_Think;
	c4ball->v.dNextThink = Server.dTime + 2.5;

	Entity_SetModel(c4ball,"models/c4ammo.md2");
	Entity_SetSizeVector(c4ball,g_mvOrigin3f,g_mvOrigin3f);
	Entity_SetOrigin(c4ball,vOrigin);

	if(eOwner->local.attackb_finished > Server.dTime)	// No attack boost...
		eOwner->local.dAttackFinished = Server.dTime+0.6;
	else
		eOwner->local.dAttackFinished = Server.dTime+1.2;
}
void GreekFire_Throw(edict_t *ent)
{
	float	*dir;
	edict_t *greekfire = Entity_Spawn();

	greekfire->v.cClassname	= "greekfire";
	greekfire->v.movetype	= MOVETYPE_BOUNCE;
	greekfire->v.effects	= EF_DIMLIGHT;

	greekfire->Physics.iSolid = SOLID_BBOX;

	greekfire->local.eOwner = ent;

	dir = Engine.Aim(ent);
	greekfire->v.velocity[0] = dir[0]*800;
	greekfire->v.velocity[1] = dir[1]*800;
	greekfire->v.velocity[2] = dir[2]*800;

	Engine.MakeVectors(greekfire->v.v_angle);

	Entity_SetModel(greekfire,"models/w_greekfire.md2");
	Math_MVToVector(Math_VectorToAngles(greekfire->v.velocity),greekfire->v.angles);

	// [4/7/2012] Simplified ~hogsy
	Math_VectorCopy(ent->v.origin,greekfire->v.origin);

	Entity_SetSizeVector(greekfire,mv3Origin,mv3Origin);

	Engine.LinkEntity(greekfire,false);

	greekfire->v.TouchFunction = GreekfireTouch;
}
void Shockwave_SpawnProjectile(ServerEntity_t *ent)
{
	ServerEntity_t *eLaser;

	Sound(ent,CHAN_WEAPON,"weapons/shockwave/fire.wav",255,ATTN_NORM);

	ent->v.punchangle[0] -= 10.0f;
	
	eLaser = Entity_Spawn();
	if(eLaser)
	{
		Weapon_Projectile(ent, eLaser, 2000.0f);

		Math_VectorCopy(ent->v.origin,eLaser->v.origin);
		Math_MVToVector(plVectorToAngles(eLaser->v.velocity),eLaser->v.angles);

		eLaser->local.owner = ent;

		eLaser->v.movetype		= MOVETYPE_FLY;
		eLaser->v.TouchFunction = ShockLaser_Touch;
		eLaser->v.origin[2]		+= 25.0f;

		eLaser->Physics.solid	= SOLID_BBOX;

		Entity_SetModel(eLaser,"models/slaser.md2");
		Entity_SetSizeVector(eLaser, pl_origin3f, pl_origin3f);
	}

	ent->local.shockwave_ammo--;
	ent->v.primary_ammo = ent->local.shockwave_ammo;
}
/*	TODO:
		- Firstly save each iteration of our water, so we can keep track of colour etc.
		- Recalc colour for different dynamic moving lights.
*/
void Warp_DrawWaterPoly(glpoly_t *p)
{
	VideoObject_t	*voWaterPoly;
	vec3_t			vWave,vLightColour;
	float			*v;
	int				i;

	voWaterPoly = malloc(p->numverts*sizeof(VideoObject_t));
	if(!voWaterPoly)
	{
		Sys_Error("Failed to allocate water poly!\n");
		return;
	}

	v = p->verts[0];

	for(i = 0; i < p->numverts; i++,v += VERTEXSIZE)
	{
		voWaterPoly[i].vTextureCoord[0][0]	= WARPCALC(v[3],v[4]);
		voWaterPoly[i].vTextureCoord[0][1]	= WARPCALC(v[4],v[3]);
		voWaterPoly[i].vColour[3] = Math_Clamp(0, r_wateralpha.value, 1.0f);

		Math_VectorCopy(v,vWave);

		// Shitty lit water, use dynamic light points in the future...
		{
			MathVector_t	mvLightColour;

			// Use vWave position BEFORE we move it, otherwise the water will flicker.
			mvLightColour = Light_GetSample(vWave);

			Math_MVToVector(mvLightColour,vLightColour);
			Math_VectorScale(vLightColour,1.0f/200.0f,vLightColour);
			Math_VectorDivide(vLightColour,0.2f,vLightColour);
		}

		Math_VectorCopy(vLightColour,voWaterPoly[i].vColour);

		// [20/1/2013] Added in subtle water bobbing, based on this code http://www.quake-1.com/docs/quakesrc.org/26.html ~hogsy
		vWave[2] =	v[2]+
					2.0f*(float)sin(v[0]*0.025f+cl.time)*(float)sin(v[2]*0.05f+cl.time)+
					2.0f*(float)sin(v[1]*0.025f+cl.time*2.0f)*(float)sin(v[2]*0.05f+cl.time);

		Math_VectorCopy(vWave,voWaterPoly[i].vVertex);
	}

	Video_DrawObject(voWaterPoly,VIDEO_PRIMITIVE_TRIANGLE_FAN,p->numverts);

	free(voWaterPoly);
}
void Discus_Follow(ServerEntity_t *ent)
{
	vec3_t	vtemp;

	// [23/5/2012] Quick fix for possible issue ~hogsy
	if(!ent || !ent->v.enemy)
		return;

	vtemp[0] = ent->v.enemy->v.origin[0]-ent->v.origin[0];
	vtemp[1] = ent->v.enemy->v.origin[1]-ent->v.origin[1];
	vtemp[2] = ent->v.enemy->v.origin[2]+22.0f-ent->v.origin[2];

	Math_VectorNormalize(vtemp);
	ent->v.velocity[0] = vtemp[0]*3000.0f;
	ent->v.velocity[1] = vtemp[1]*3000.0f;
	ent->v.velocity[2] = vtemp[2]*3000.0f;

	// [25/6/2012] Simplified ~hogsy
	Math_MVToVector(Math_VectorToAngles(ent->v.velocity),ent->v.angles);

	ent->v.think		= Discus_Follow;
	ent->v.dNextThink	= Server.dTime+0.01;
}
void GreekFire_Throw(ServerEntity_t *ent)
{
	ServerEntity_t *greekfire = Entity_Spawn();

	greekfire->v.cClassname	= "greekfire";
	greekfire->v.movetype	= MOVETYPE_BOUNCE;
	greekfire->v.effects	= EF_DIMLIGHT;

	greekfire->Physics.iSolid = SOLID_BBOX;

	greekfire->local.eOwner = ent;

	Weapon_Projectile(ent,greekfire,800.0f);

	Entity_SetModel(greekfire,"models/w_greekfire.md2");
	Math_MVToVector(Math_VectorToAngles(greekfire->v.velocity),greekfire->v.angles);

	// Use SetOrigin since it automatically links.
	Entity_SetOrigin(greekfire, ent->v.origin);

	Entity_SetSizeVector(greekfire,g_mvOrigin3f,g_mvOrigin3f);

	greekfire->v.TouchFunction = GreekfireTouch;
}