//-----------------------------------------------------------------------------
//
//  $Logfile:: /Quake 2 Engine/Sin/code/game/g_utils.h                        $
// $Revision:: 17                                                             $
//   $Author:: Markd                                                          $
//     $Date:: 5/19/99 4:57p                                                  $
//
// Copyright (C) 1998 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
// $Log:: /Quake 2 Engine/Sin/code/game/g_utils.h                             $
//
// 17    5/19/99 4:57p Markd
// fixed some errors
//
// 16    3/02/99 9:16p Aldie
// Added CTF game code
//
// 2     2/16/99 4:08p Aldie
//
// 1     2/11/99 1:38p Aldie
//
// 15    10/26/98 3:50a Markd
// put in prediction
//
// 14    10/18/98 3:23a Jimdose
// Added G_Milliseconds and G_DebugPrintf
//
// 13    10/16/98 7:18p Markd
// Changed ExecuteThread a little bit
//
// 12    10/10/98 1:34a Jimdose
// added edict archiving functions
//
// 11    10/09/98 4:54p Markd
// Added ExecuteThread
//
// 10    10/07/98 11:48p Jimdose
// Added G_FixSlashes
//
// 9     10/03/98 1:10p Aldie
// added findclientsinradius
//
// 8     9/14/98 5:41p Jimdose
// Added G_CalcBoundsOfMove
//
// 7     8/29/98 9:50p Jimdose
// Moved prototypes from g_local.h
// Moved all debugline functions from g_main.cpp
// Added trace info to G_Trace
//
// 6     8/27/98 9:05p Jimdose
// Moved several short functions to g_utils.h as inline
//
// 5     8/24/98 4:55p Markd
// Added G_CalculateImpulse
//
// 4     2/18/98 8:08p Jimdose
// Prototyped IsNumeric
//
// 3     2/06/98 5:51p Jimdose
// Added KillBox
// Changed G_TouchTriggers and M_CheckBottom to be .cpp compatible
//
// 2     2/03/98 10:49a Jimdose
// Created file.
//
// DESCRIPTION:
//

#ifndef __G_UTILS_H__
#define __G_UTILS_H__

class Archiver;

void       G_ArchiveEdict( Archiver& arc, edict_t* edict );
void       G_UnarchiveEdict( Archiver& arc, edict_t* edict );

#include "entity.h"

void            G_InitEdict( edict_t* e );
edict_t*        G_Spawn( void );
void            G_FreeEdict( edict_t* e );

void            G_TouchTriggers( Entity* ent );
void            G_TouchSolids( Entity* ent );

char*           G_CopyString( const char* in );

int G_FindClass( int entnum, const char* classname );
Entity*     G_NextEntity( Entity* ent );

void       G_CalcBoundsOfMove( Vector& start, Vector& end, Vector& mins, Vector& maxs, Vector* minbounds, Vector* maxbounds );

void            G_ShowTrace( trace_t* trace, edict_t* passent, const char* reason );
trace_t     G_Trace( const Vector& start, const Vector& mins, const Vector& maxs, const Vector& end, Entity* passent, int contentmask, const char* reason );
trace_t     G_Trace( vec3_t start, const vec3_t mins, const vec3_t maxs, vec3_t end, edict_t* passent, int contentmask, const char* reason );
trace_t     G_FullTrace( Vector& start, Vector& mins, Vector& maxs, Vector& end, float radius, Entity* passent, int contentmask,    const char* reason );
trace_t     G_FullTrace( vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, float radius, edict_t* passent, int contentmask,   const char* reason );

//###
//void			SelectSpawnPoint( Vector &origin, Vector &angles, int *gravaxis = NULL );
void            SelectSpawnPoint( Vector& origin, Vector& angles, edict_t* edict, int* gravaxis = NULL, int* startonbike = NULL );

int         G_FindTarget( int entnum, const char* name );
Entity*     G_NextEntity( Entity* ent );

qboolean    M_CheckBottom( Entity* ent );
qboolean    M_CeilingCheckBottom( Entity* ent ); //###

Vector      G_GetMovedir( void );
qboolean    KillBox( Entity* ent );
qboolean    IsNumeric( const char* str );

Entity*     findradius( Entity* startent, Vector org, float rad );
Entity*     findclientsinradius( Entity* startent, Vector org, float rad );
const char* G_GetNameForSurface( csurface_t* s );

Vector      G_CalculateImpulse( Vector start, Vector end, float speed, float gravity );
Vector     G_PredictPosition( Vector start, Vector target, Vector targetvelocity, float speed );

void G_InitDebugLines( void );
void G_DebugLine( Vector start, Vector end, float r, float g, float b, float alpha );
void G_Color3f( float r, float g, float b );
void G_Color3v( Vector color );
void G_Color4f( float r, float g,   float b,    float alpha );
void G_Color3vf( Vector color, float alpha );
void G_BeginLine( void );
void G_Vertex( Vector v );
void G_EndLine( void );
void G_DebugBBox( Vector origin, Vector mins, Vector maxs, float r, float g, float b, float alpha );
void G_DrawDebugNumber( Vector org, float number, float scale, float r, float g, float b, int precision = 0 );

void G_LoadAndExecScript( const char* filename, const char* label = NULL );
ScriptThread* ExecuteThread( str thread_name, qboolean start = true );

int  G_Milliseconds( void );
void G_DebugPrintf( const char* fmt, ... ) __attribute__((__format__(__printf__,1,2)));
extern str G_FixSlashes( const char* filename );
extern Entity* SelectRandomDeathmatchSpawnPoint( void );
extern float PlayersRangeFromSpot( Entity* spot );
extern Entity* SelectFarthestDeathmatchSpawnPoint( void );
extern void G_AllocDebugLines( void );

//==================================================================
//
// Inline functions
//
//==================================================================

inline float angmod( float v )
{
	int b;

	b = ( int )v;

	b = b - ( b % 360 );
	if( b < 0 )
	{
		b -= 360;
	}

	return v - ( float )b;
}

/*
=================
G_GetEntity

Takes an index to an entity and returns pointer to it.
=================
*/

inline Entity* G_GetEntity( int entnum )
{
	if( ( entnum < 0 ) || ( entnum >= globals.max_edicts ) )
	{
		gi.error( "G_GetEntity: %d out of valid range.", entnum );
	}

	return ( Entity* )g_edicts[ entnum ].entity;
}

/*
=================
G_Random

Returns a number from 0<= num < 1

random()
=================
*/

inline float G_Random( void )
{
	return ( ( float )( rand() & 0x7fff ) ) / ( ( float )0x8000 );
}

/*
=================
G_Random

Returns a number from 0 <= num < n

random()
=================
*/

inline float G_Random( float n )
{
	return G_Random() * n;
}

/*
=================
G_CRandom

Returns a number from -1 <= num < 1

crandom()
=================
*/

inline float G_CRandom( void )
{
	return G_Random( 2 ) - 1;
}

/*
=================
G_CRandom

Returns a number from -n <= num < n

crandom()
=================
*/

inline float G_CRandom( float n )
{
	return G_CRandom() * n;
}


#endif /* g_utils.h */
