/*	Damage entities within a specific radius.
*/
void Entity_RadiusDamage(edict_t *eInflictor,float fRadius,int iDamage,int iDamageType)
{
	int		i;
	float	fDistance;
	vec3_t	vOrigin;
	edict_t *eTarget = Engine.Server_FindRadius(eInflictor->v.origin,fRadius);

	Engine.WriteByte(MSG_BROADCAST,SVC_TEMPENTITY);
	Engine.WriteByte(MSG_BROADCAST,CTE_EXPLOSION);

	for(i = 0; i < 3; i++)
		Engine.WriteCoord(MSG_BROADCAST,eInflictor->v.origin[i]);

	do
	{
		if(eTarget->v.bTakeDamage)
		{
			int i;

			for(i = 0; i < 3; i++)
				vOrigin[i] = eTarget->v.origin[i]+(eTarget->v.mins[i]+eTarget->v.maxs[i])*0.5f;

			Math_VectorSubtract(eInflictor->v.origin,vOrigin,vOrigin);

			fDistance = 0.5f*(float)Math_VectorLength(vOrigin);
			if(fDistance > 0)
			{
				Math_VectorInverse(vOrigin);
				Math_VectorAdd(eTarget->v.velocity,vOrigin,eTarget->v.velocity);

				// [15/7/2013] Reduce the damage by distance ~hogsy
				fDistance = (float)iDamage-(100.0f/fDistance);

				// [15/8/2013] Less damage for the inflictor ~hogsy
				if(eTarget == eInflictor)
					fDistance = fDistance/2.0f;

				if(fDistance > 0)
					if(Entity_CanDamage(eInflictor,eTarget, iDamageType))
						MONSTER_Damage(eTarget,eInflictor,(int)fDistance,iDamageType);
			}
		}

		eTarget = eTarget->v.chain;
	}
	while(eTarget);
}
/*	Returns the range from an entity to a target.
*/
float MONSTER_GetRange(edict_t *ent,vec3_t target)
{
	// [12/4/2012] Revised ~hogsy
	vec3_t spot,spot1,spot2;

	spot1[0] = ent->v.origin[0]+ent->v.view_ofs[0];
	spot1[1] = ent->v.origin[1]+ent->v.view_ofs[1];
	spot1[2] = ent->v.origin[2]+ent->v.view_ofs[2];
	spot2[0] = target[0]; //+ target->v.view_ofs[0];
	spot2[1] = target[1]; //+ target->v.view_ofs[1];
	spot2[2] = target[2]; //+ target->v.view_ofs[2];

	Math_VectorSubtract(spot1,spot2,spot);

	// [4/2/2013] Shouldn't this be a float rather than a double? Oh well, whatever you say, Carmack ~hogsy
	return (float)Math_VectorLength(spot);
}
/*	Damage entities within a specific radius.
*/
void Entity_RadiusDamage(ServerEntity_t *eInflictor, float fRadius, int iDamage, int iDamageType)
{
	int		i;
	float	fDistance;
	MathVector3f_t	vOrigin;
	ServerEntity_t *eTarget = Engine.Server_FindRadius(eInflictor->v.origin, fRadius);

	do
	{
		if(eTarget->v.bTakeDamage)
		{
			for(i = 0; i < 3; i++)
				vOrigin[i] = eTarget->v.origin[i]+(eTarget->v.mins[i]+eTarget->v.maxs[i])*0.5f;

			Math_VectorSubtract(eInflictor->v.origin,vOrigin,vOrigin);

			fDistance = 0.5f*(float)Math_VectorLength(vOrigin);
			if(fDistance > 0)
			{
				Math_VectorInverse(vOrigin);
				Math_VectorAdd(eTarget->v.velocity,vOrigin,eTarget->v.velocity);

				// Reduce the damage by distance.
				fDistance = (float)iDamage-(100.0f/fDistance);

				// Less damage for the inflictor.
				if(eTarget == eInflictor)
					fDistance = fDistance/2.0f;

				if(fDistance > 0)
					Entity_Damage(eTarget,eInflictor,(int)fDistance,iDamageType);
			}
		}

		eTarget = eTarget->v.chain;
	}
	while(eTarget);
}
void Waypoint_Spawn(MathVector3f_t vOrigin,WaypointType_t type)
{
#ifdef	DEBUG_WAYPOINT
	char		*cModelName = WAYPOINT_MODEL_BASE;
#endif
	int			iPointContents;
	Waypoint_t	*wPoint;

	/*	TODO
		If we're between two other waypoints
		and they can be seen then slot ourselves
		in so that we act as the last waypoint
		instead.
	*/

	iPointContents = Engine.Server_PointContents(vOrigin);
	// [17/6/2012] Check that this area is safe ~hogsy
	if(iPointContents == BSP_CONTENTS_SOLID)
	{
		Engine.Con_Warning("Failed to place waypoint, position is within a solid!\n");
		return;
	}

	{
		Waypoint_t *wVisibleWaypoint = Waypoint_GetByVisibility(vOrigin);
		// [30/1/2013] Oops! Check we actually have a visible waypoint!! ~hogsy
		if(wVisibleWaypoint)
		{
			MathVector3f_t vDistance;

			Math_VectorSubtract(wVisibleWaypoint->position,vOrigin,vDistance);
			if(Math_VectorLength(vDistance) < MONSTER_RANGE_MEDIUM)
			{
				Engine.Con_Printf("Invalid waypoint position!\n");
				return;
			}
		}
	}

	wPoint = Waypoint_Allocate();
	if(!wPoint)
	{
		Engine.Con_Warning("Failed to allocate waypoint!\n");
		return;
	}

	Math_VectorCopy(vOrigin,wPoint->position);

	wPoint->number	= waypoint_count;
	wPoint->bOpen	= false;
	wPoint->next	= Waypoint_GetByNumber(wPoint->number+1);
	wPoint->last	= Waypoint_GetByNumber(wPoint->number-1);
	wPoint->wType	= type;

	switch(type)
	{
	case WAYPOINT_ITEM:
		wPoint->cName = "item";
#ifdef DEBUG_WAYPOINT
		cModelName	= WAYPOINT_MODEL_ITEM;
#endif
		break;
	case WAYPOINT_CLIMB:
		wPoint->cName = "climb";
		// TODO: Check that there's a ladder nearby.
#ifdef DEBUG_WAYPOINT
		cModelName	= WAYPOINT_MODEL_CLIMB;
#endif
		break;
	case WAYPOINT_COVER:
		wPoint->cName = "cover";
		// [27/12/2012] TODO: Check that this is actually cover ~hogsy
		break;
	case WAYPOINT_TYPE_JUMP:
		wPoint->cName = "jump";
		// [27/12/2012] TODO: Check if this is actually a jump by tracing out ahead ~hogsy
#ifdef DEBUG_WAYPOINT
		cModelName	= WAYPOINT_MODEL_JUMP;
#endif
		break;
	case WAYPOINT_TYPE_SWIM:
		if(iPointContents != BSP_CONTENTS_WATER)
		{
			Engine.Con_Warning("Waypoint with type swim not within water contents (%i %i %i)!",
				(int)vOrigin[0],
				(int)vOrigin[1],
				(int)vOrigin[2]);

			Waypoint_Delete(wPoint);
			return;
		}

		wPoint->cName = "swim";
#ifdef DEBUG_WAYPOINT
		cModelName	= WAYPOINT_MODEL_SWIM;
#endif
		break;
	case WAYPOINT_TYPE_DEFAULT:
		wPoint->cName = "default";
		break;
	case WAYPOINT_SPAWN:
		wPoint->cName = "spawn";
		break;
	default:
		Engine.Con_Warning("Unknown waypoint type (%i)!\n",type);

		Waypoint_Delete(wPoint);
		return;
	}

	// [30/1/2013] Pathetic reordering... Ugh ~hogsy
	if(!wPoint->last)
	{
		wPoint->last = Waypoint_GetByVisibility(vOrigin);
		if(!wPoint->last)
		{
			Engine.Con_Warning("Failed to get another visible waypoint! (%i)\n",wPoint->number);
			return;
		}
	}
	else if(wPoint->last != wPoint && wPoint->last->next)
		wPoint->last->next = wPoint;

#ifdef DEBUG_WAYPOINT
	wPoint->eDebug = Entity_Spawn();
	if(wPoint->eDebug)
	{
		wPoint->eDebug->v.effects = EF_MOTION_ROTATE;

		Entity_SetModel(wPoint->eDebug,cModelName);
		Entity_SetSizeVector(wPoint->eDebug,g_mvOrigin3f,g_mvOrigin3f);
		Entity_SetOrigin(wPoint->eDebug,wPoint->position);
	}

	Engine.Con_DPrintf("Waypoint placed (%i %i %i)\n",
		(int)wPoint->position[0],
		(int)wPoint->position[1],
		(int)wPoint->position[2]);
	Engine.Con_DPrintf(" number: %i\n",wPoint->number);
	Engine.Con_DPrintf(" type:   %i\n",wPoint->wType);
#endif
}