/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.

This file is part of Quake III Arena source code.

Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.

Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
===========================================================================
*/

// q_shared.h -- included first by ALL program modules.
// A user mod should never modify this file

#pragma once

#if defined(__cplusplus)
extern "C" {
#endif

#define PRODUCT_NAME					"OpenMoHAA"
#define PRODUCT_DATE					__DATE__

#define BASEGAME				"main"
// We're always legacy
#define LEGACY_PROTOCOL

#define GAME_EXTENSION_MOH				"main"
#define PRODUCT_EXTENSION_MOH			"Allied Assault"
#define TARGET_GAME_VERSION_MOH			"1.12"
#define TARGET_GAME_PROTOCOL_DEMO_MOH	6
#define TARGET_GAME_PROTOCOL_MOH		8
#define TARGET_GAME_NAME_MOH			"mohaa"

#define HOMEPATH_NAME_UNIX_MOH		".moh"
#define HOMEPATH_NAME_WIN_MOH		"moh"
#define HOMEPATH_NAME_MACOSX_MOH	HOMEPATH_NAME_WIN_MOH

#define GAME_EXTENSION_MOHTA			"mainta"
#define PRODUCT_EXTENSION_MOHTA			"Spearhead"
#define TARGET_GAME_VERSION_MOHTA		"2.16"
#define TARGET_GAME_PROTOCOL_MIN_MOHTA	16
#define TARGET_GAME_PROTOCOL_MOHTA		17
#define TARGET_GAME_NAME_MOHTA			"mohaas"

#define HOMEPATH_NAME_UNIX_MOHTA	".mohta"
#define HOMEPATH_NAME_WIN_MOHTA		"mohta"
#define HOMEPATH_NAME_MACOSX_MOHTA	HOMEPATH_NAME_WIN_MOHTA

#define GAME_EXTENSION_BASE_MOHTT		"maintt"
#define PRODUCT_EXTENSION_MOHTT			"Breakthrough"
// The version string must be equal or above 2.0 to be able to connect to breakthrough servers
#define	TARGET_GAME_VERSION_MOHTT		"2.41"
#define	TARGET_GAME_VERSION_MOHTT_DEMO	"0.31"
#define TARGET_GAME_PROTOCOL_MIN_MOHTT	16
#define TARGET_GAME_PROTOCOL_MOHTT		17
#define TARGET_GAME_NAME_MOHTT			"mohaab"

#define HOMEPATH_NAME_UNIX_MOHTT	".mohtt"
#define HOMEPATH_NAME_WIN_MOHTT		"mohtt"
#define HOMEPATH_NAME_MACOSX_MOHTT	HOMEPATH_NAME_WIN_MOHTT

//
// The target type specifies which content pack the engine targets.
// 
// Note: An universal client is not currently possible without refactoring the network and the file system.
//       Pak files must be reloaded on-the-fly depending on the server the client is connecting to.
//
#define HOMEPATH_NAME_UNIX		".openmohaa"
#define HOMEPATH_NAME_WIN		"openmohaa"
#define HOMEPATH_NAME_MACOSX	HOMEPATH_NAME_WIN

#define CLIENT_WINDOW_TITLE		PRODUCT_NAME
#define CLIENT_WINDOW_MIN_TITLE PRODUCT_NAME
    
#define MAX_MASTER_SERVERS      5	// number of supported master servers

#define DEMOEXT	"dm_"			// standard demo extension

#ifdef _MSC_VER

#pragma warning(disable : 4018)     // signed/unsigned mismatch
#pragma warning(disable : 4032)
#pragma warning(disable : 4051)
#pragma warning(disable : 4057)		// slightly different base types
#pragma warning(disable : 4100)		// unreferenced formal parameter
#pragma warning(disable : 4115)
#pragma warning(disable : 4125)		// decimal digit terminates octal escape sequence
#pragma warning(disable : 4127)		// conditional expression is constant
#pragma warning(disable : 4136)
#pragma warning(disable : 4152)		// nonstandard extension, function/data pointer conversion in expression
//#pragma warning(disable : 4201)
//#pragma warning(disable : 4214)
#pragma warning(disable : 4244)
#pragma warning(disable : 4142)		// benign redefinition
//#pragma warning(disable : 4305)		// truncation from const double to float
//#pragma warning(disable : 4310)		// cast truncates constant value
//#pragma warning(disable:  4505) 	// unreferenced local function has been removed
#pragma warning(disable : 4514)
#pragma warning(disable : 4702)		// unreachable code
#pragma warning(disable : 4711)		// selected for automatic inline expansion
#pragma warning(disable : 4220)		// varargs matches remaining parameters
//#pragma intrinsic( memset, memcpy )
#endif

//Ignore __attribute__ on non-gcc platforms
#ifndef __GNUC__
#ifndef __attribute__
#define __attribute__(x)
#endif
#endif

#ifdef __GNUC__
#define UNUSED_VAR __attribute__((unused))
#else
#define UNUSED_VAR
#endif

#if (defined _MSC_VER)
#define Q_EXPORT __declspec(dllexport)
#elif (defined __SUNPRO_C)
#define Q_EXPORT __global
#elif ((__GNUC__ >= 3) && (!__EMX__) && (!sun))
#define Q_EXPORT __attribute__((visibility("default")))
#else
#define Q_EXPORT
#endif

/**********************************************************************
  VM Considerations

  The VM can not use the standard system headers because we aren't really
  using the compiler they were meant for.  We use bg_lib.h which contains
  prototypes for the functions we define for our own use in bg_lib.c.

  When writing mods, please add needed headers HERE, do not start including
  stuff like <stdio.h> in the various .c files that make up each of the VMs
  since you will be including system headers files can will have issues.

  Remember, if you use a C library function that is not defined in bg_lib.c,
  you will have to add your own version for support in the VM.

 **********************************************************************/

#ifndef Q3_VM

#ifdef _DEBUG_MEM
#  ifdef WIN32
#    define _CRTDBG_MAP_ALLOC
#    include <stdlib.h>
#    include <crtdbg.h>
#  endif
#endif

#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <limits.h>

#ifdef _MSC_VER
#include <io.h>
#include <stdint.h>

#else
#include <unistd.h>
#include <stdint.h>
#endif

#ifdef _WIN32
 // vsnprintf is ISO/IEC 9899:1999
 // abstracting this to make it portable
size_t Q_vsnprintf(char* str, size_t size, const char* format, va_list ap);
#else
#define Q_vsnprintf vsnprintf
#endif

#endif

#include "q_platform.h"

//=============================================================

typedef unsigned char 		byte;
typedef unsigned char		uchar;

enum { qfalse, qtrue };

typedef union {
	float f;
	int i;
	unsigned int ui;
} floatint_t;

typedef int	qboolean;

typedef int		qhandle_t;
typedef int		sfxHandle_t;
typedef int		fileHandle_t;
typedef int		clipHandle_t;

#ifdef __GNUC__
#define ALIGN(x) __attribute__((aligned(x)))
#else
#define ALIGN(x)
#endif

#define PAD(base, alignment)	(((base)+(alignment)-1) & ~((alignment)-1))
#define PADLEN(base, alignment)	(PAD((base), (alignment)) - (base))

#define PADP(base, alignment)	((void *) PAD((intptr_t) (base), (alignment)))

#ifdef __GNUC__
#define QALIGN(x) __attribute__((aligned(x)))
#else
#define QALIGN(x)
#endif

#ifndef NULL
#define NULL ((void *)0)
#endif

#ifndef BIT
#define BIT(x)				(1 << x)
#endif

#define STRING(s)			#s
// expand constants before stringifying them
#define XSTRING(s)			STRING(s)

#define	MAX_QINT			0x7fffffff
#define	MIN_QINT			(-MAX_QINT-1)

#define ARRAY_LEN(x)			(sizeof(x) / sizeof(*(x)))
#define STRARRAY_LEN(x)			(ARRAY_LEN(x) - 1)

// angle indexes
#define	PITCH				0		// up / down
#define	YAW					1		// left / right
#define	ROLL				2		// fall over

#ifndef WIN32
#define stricmp strcasecmp
#define strnicmp strncasecmp
#endif

typedef enum {
    TG_MOH,
    TG_MOHTA,
    TG_MOHTT,
    TG_INVALID
} target_game_e;

typedef enum {
    PROTOCOL_MOH_MIN = 6,
    PROTOCOL_MOH_DEMO = 6,
    PROTOCOL_MOH = 8,
    PROTOCOL_MOHTA_MIN = 15,
    PROTOCOL_MOHTA_DEMO = 16,
    PROTOCOL_MOHTA = 17,
} protocol_e;

// plane sides
typedef enum
{
	SIDE_FRONT = 0,
	SIDE_BACK = 1,
	SIDE_ON = 2,
	SIDE_CROSS = 3
} planeSide_t;

typedef enum
{
	SOLID_NOT,			// no interaction with other objects
	SOLID_TRIGGER,		// only touch when inside, after moving
	SOLID_BBOX,			// touch on edge
	SOLID_BSP			// bsp clip, touch on edge
} solid_t;

// the game guarantees that no string from the network will ever
// exceed MAX_STRING_CHARS
#define	MAX_STRING_CHARS	2048	// max length of a string passed to Cmd_TokenizeString
#define	MAX_STRING_TOKENS	1024	// max tokens resulting from Cmd_TokenizeString
#define	MAX_TOKEN_CHARS		1024	// max length of an individual token

#define	MAX_INFO_STRING		1350
#define	MAX_INFO_KEY		  1024
#define	MAX_INFO_VALUE		1024

#define	BIG_INFO_STRING		8192  // used for system info key only
#define	BIG_INFO_KEY		8192
#define	BIG_INFO_VALUE		8192

#define MAX_RES_NAME        64

#define	MAX_QPATH			256		// max length of a quake game pathname
#ifdef PATH_MAX
#define MAX_OSPATH			PATH_MAX
#else
#define	MAX_OSPATH			256		// max length of a filesystem pathname
#endif

#define	MAX_NAME_LENGTH		32		// max length of a client name

#define	MAX_SAY_TEXT	150

// paramters for command buffer stuffing
typedef enum {
	EXEC_NOW,			// don't return until completed, a VM should NEVER use this,
						// because some commands might cause the VM to be unloaded...
	EXEC_INSERT,		// insert at current position, but don't run yet
	EXEC_APPEND			// add to end of the command buffer (normal case)
} cbufExec_t;


//
// these aren't needed by any of the VMs.  put in another header?
//
#define	MAX_MAP_AREA_BYTES		32		// bit vector of area visibility


// print levels from renderer (FIXME: set up for game / cgame?)
typedef enum {
	PRINT_ALL,
	PRINT_DEVELOPER,		// only print when "developer 1"
	PRINT_DEVELOPER_2,		// print when "developer 2"
	PRINT_WARNING,
	PRINT_ERROR
} printParm_t;


#ifdef ERR_FATAL
#undef ERR_FATAL			// this is be defined in malloc.h
#endif

// parameters to the main Error routine
typedef enum {
	ERR_FATAL,					// exit the entire game with a popup window
	ERR_DROP,					// print to console and disconnect from game
	ERR_SERVERDISCONNECT,		// don't kill server
	ERR_DISCONNECT,				// client disconnected from the server
	ERR_NEED_CD					// pop up the need-cd dialog
} errorParm_t;


// font rendering values used by ui and cgame

#define PROP_GAP_WIDTH			5
#define PROP_SPACE_WIDTH		8
#define PROP_HEIGHT				30
#define PROP_SMALL_SIZE_SCALE	0.75

#define BLINK_DIVISOR			200
#define PULSE_DIVISOR			250.0f

#define UI_LEFT			0x00000000	// default
#define UI_CENTER		0x00000001
#define UI_RIGHT		0x00000002
#define UI_FORMATMASK	0x00000007
#define UI_SMALLFONT	0x00000010
#define UI_BIGFONT		0x00000020	// default
#define UI_GIANTFONT	0x00000040
#define UI_DROPSHADOW	0x00000800
#define UI_BLINK		0x00001000
#define UI_INVERSE		0x00002000
#define UI_PULSE		0x00004000

typedef enum {
	h_high,
	h_low,
	h_dontcare
} ha_pref;

#ifdef HUNK_DEBUG
#define Hunk_Alloc( size, preference )				Hunk_AllocDebug(size, preference, #size, __FILE__, __LINE__)
void *Hunk_AllocDebug( int size, ha_pref preference, const char *label, const char *file, int line );
#else
void *Hunk_Alloc( int size, ha_pref preference );
#endif

#define Com_Memset memset
#define Com_Memcpy memcpy

#define Com_Allocate malloc
#define Com_Dealloc free

#define CIN_system	1
#define CIN_loop	2
#define	CIN_hold	4
#define CIN_silent	8
#define CIN_shader	16

/*
==============================================================

MATHLIB

==============================================================
*/


typedef float vec_t;
typedef vec_t vec2_t[2];
typedef vec_t vec3_t[3];
typedef vec_t vec4_t[4];
typedef vec_t quat_t[4]; // | x y z w |
typedef vec_t vec5_t[5];
typedef vec_t matrix3x3_t[9];
typedef vec_t matrix_t[16];
typedef vec3_t axis_t[3];

typedef	int	fixed4_t;
typedef	int	fixed8_t;
typedef	int	fixed16_t;

#ifndef M_PI
#define M_PI		3.14159265358979323846	// matches value in gcc v2 math.h
#endif

#ifndef M_SQRT2
#define M_SQRT2		1.414213562f
#endif

#ifndef M_SQRT1_2
#define M_SQRT1_2	7.0710678118654752440E-1
#endif

#define NUMVERTEXNORMALS	162
extern	vec3_t	bytedirs[NUMVERTEXNORMALS];

// all drawing is done to a 640*480 virtual screen size
// and will be automatically scaled to the real resolution
#define	SCREEN_WIDTH		640
#define	SCREEN_HEIGHT		480

#define TINYCHAR_WIDTH		(SMALLCHAR_WIDTH)
#define TINYCHAR_HEIGHT		(SMALLCHAR_HEIGHT/2)

#define SMALLCHAR_WIDTH		8
#define SMALLCHAR_HEIGHT	16

#define BIGCHAR_WIDTH		16
#define BIGCHAR_HEIGHT		16

#define	GIANTCHAR_WIDTH		32
#define	GIANTCHAR_HEIGHT	48

extern	vec4_t		colorBlack;
extern	vec4_t		colorRed;
extern	vec4_t		colorGreen;
extern	vec4_t		colorBlue;
extern	vec4_t		colorYellow;
extern	vec4_t		colorMagenta;
extern	vec4_t		colorCyan;
extern	vec4_t		colorWhite;
extern	vec4_t		colorLtGrey;
extern	vec4_t		colorMdGrey;
extern	vec4_t		colorDkGrey;

enum {
	MESSAGE_YELLOW = 1,
	MESSAGE_CHAT_WHITE,
	MESSAGE_WHITE,
	MESSAGE_CHAT_RED,
	MESSAGE_CHAT_GREEN,
	MESSAGE_MAX
};

#define Q_COLOR_ESCAPE	'^'
#define Q_IsColorString(p)	( p && *(p) == Q_COLOR_ESCAPE && *((p)+1) && isalnum(*((p)+1)) ) // ^[0-9a-zA-Z]

#define COLOR_BLACK		'0'
#define COLOR_RED		'1'
#define COLOR_GREEN		'2'
#define COLOR_YELLOW	'3'
#define COLOR_BLUE		'4'
#define COLOR_CYAN		'5'
#define COLOR_MAGENTA	'6'
#define COLOR_WHITE		'7'
#define ColorIndex(c)	( ( (c) - '0' ) & 7 )

#if 0
#define S_COLOR_BLACK	"^0"
#define S_COLOR_RED		"^1"
#define S_COLOR_GREEN	"^2"
#define S_COLOR_YELLOW	"^3"
#define S_COLOR_BLUE	"^4"
#define S_COLOR_CYAN	"^5"
#define S_COLOR_MAGENTA	"^6"
#define S_COLOR_WHITE	"^7"
#else
#define S_COLOR_BLACK	""
#define S_COLOR_RED		""
#define S_COLOR_GREEN	""
#define S_COLOR_YELLOW	""
#define S_COLOR_BLUE	""
#define S_COLOR_CYAN	""
#define S_COLOR_MAGENTA	""
#define S_COLOR_WHITE	""
#endif

#define HUD_MESSAGE_YELLOW			"\x01"
#define HUD_MESSAGE_WHITE			"\x03"
#define HUD_MESSAGE_CHAT_WHITE		"\x02"
#define HUD_MESSAGE_CHAT_RED		"\x04"

extern vec4_t	g_color_table[8];

#define	MAKERGB( v, r, g, b ) v[0]=r;v[1]=g;v[2]=b
#define	MAKERGBA( v, r, g, b, a ) v[0]=r;v[1]=g;v[2]=b;v[3]=a

#define DEG2RAD( a ) ( ( (a) * M_PI ) / 180.0F )
#define RAD2DEG( a ) ( ( (a) * 180.0f ) / M_PI )

#define Q_max(a, b)      ((a) > (b) ? (a) : (b))
#define Q_min(a, b)      ((a) < (b) ? (a) : (b))
#define Q_bound(a, b, c) (Q_max(a, Q_min(b, c)))
#define Q_clamp(a, b, c) ((b) >= (c) ? (a)=(b) : (a) < (b) ? (a)=(b) : (a) > (c) ? (a)=(c) : (a))
#define Q_lerp(from, to, frac) (from + ((to - from) * frac))

#define LERP( a, b, w ) ( ( a ) * ( 1.0f - ( w ) ) + ( b ) * ( w ) )
#define LUMA( red, green, blue ) ( 0.2126f * ( red ) + 0.7152f * ( green ) + 0.0722f * ( blue ) )

#ifndef Q_min
#define Q_min(a,b)  (((a) < (b)) ? (a) : (b))
#endif
#ifndef Q_max
#define Q_max(a,b)  (((a) > (b)) ? (a) : (b))
#endif

int Q_clamp_int(int value, int min, int max);
float Q_clamp_float(float value, float min, float max);

#define bound(a,minval,maxval)  ( ((a) > (minval)) ? ( ((a) < (maxval)) ? (a) : (maxval) ) : (minval) )

struct cplane_s;

extern	vec3_t	vec3_origin;
extern	vec3_t	axisDefault[3];
extern matrix_t matrixIdentity;

#define	nanmask (255<<23)

#define	IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)

static ID_INLINE long Q_ftol(float f)
{
#if id386_sse && defined(_MSC_VER)
	static int      tmp;
	__asm fld f
	__asm fistp tmp
	__asm mov eax, tmp
#else
	return (long)f;
#endif
}

#if idppc

static ID_INLINE float Q_rsqrt( float number ) {
		float x = 0.5f * number;
                float y;
#ifdef __GNUC__
                asm("frsqrte %0,%1" : "=f" (y) : "f" (number));
#else
		y = __frsqrte( number );
#endif
		return y * (1.5f - (x * y * y));
	}

#ifdef __GNUC__
static ID_INLINE float Q_fabs(float x) {
    float abs_x;

    asm("fabs %0,%1" : "=f" (abs_x) : "f" (x));
    return abs_x;
}
#else
#define Q_fabs __fabsf
#endif

#else
float Q_fabs( float f );
float Q_rsqrt( float f );		// reciprocal square root
#endif

#define SQRTFAST( x ) ( (x) * Q_rsqrt( x ) )

byte ClampByte(int i);
signed char ClampChar( int i );
signed short ClampShort( int i );

double		dEpsilon( void );
double 		dIdentity( void );
double		dSign( const double number );
double		dClamp( const double value, const double min, const double max );
double		dDistance( const double value1, const double value2 );
qboolean	dCloseEnough( const double value1, const double value2, const double epsilon );
qboolean	dSmallEnough( const double value, const double epsilon );

float		fEpsilon( void );
float 		fIdentity( void );
float		fSign( const float number );
float		fClamp( const float value, const float min, const float max );
float		fDistance( const float value1, const float value2 );
qboolean	fCloseEnough( const float value1, const float value2, const float epsilon );
qboolean	fSmallEnough( const float value, const float epsilon );

int			iSign( const int number );
int			iClamp( const int value, const int min, const int max );

// this isn't a real cheap function to call!
int DirToByte( vec3_t dir );
void ByteToDir( int b, vec3_t dir );

#if	1

#define DotProduct(x,y)			((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2])
#define DotProduct2D(x,y)		((x)[0]*(y)[0]+(x)[1]*(y)[1])
#define CrossProduct2D(a,b)		((a)[0]*(b)[1]-(b)[0]*(a)[1])
#define VectorSubtract(a,b,c)	((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
#define VectorAdd(a,b,c)		((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
#define VectorAdd2D(a,b,c)		((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1])
#define VectorSub2D(a,b,c)		((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1])
#define VectorCopy(a,b)			((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
#define VectorCopy2D(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1])
#define	VectorScale(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s))
#define	VectorScale2D(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s))
#define	VectorMA(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s))
#define	VectorMA2D(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s))

#else

#define DotProduct(x,y)			_DotProduct(x,y)
#define VectorSubtract(a,b,c)	_VectorSubtract(a,b,c)
#define VectorAdd(a,b,c)		_VectorAdd(a,b,c)
#define VectorCopy(a,b)			_VectorCopy(a,b)
#define	VectorScale(v, s, o)	_VectorScale(v,s,o)
#define	VectorMA(v, s, b, o)	_VectorMA(v,s,b,o)

#endif

#ifdef Q3_VM
#ifdef VectorCopy
#undef VectorCopy
// this is a little hack to get more efficient copies in our interpreter
typedef struct {
	float	v[3];
} vec3struct_t;
#define VectorCopy(a,b)	(*(vec3struct_t *)b=*(vec3struct_t *)a)
#endif
#endif

#define VectorClear2D(a)			((a)[0]=(a)[1]=0)
#define VectorLength2DSquared(a)	((a)[0]*(a)[0]+(a)[1]*(a)[1])
#define VectorLength2D(a)			(sqrt(VectorLength2DSquared(a)))
#define VectorSet2D(v, x, y)		((v)[0]=(x), (v)[1]=(y))

#define VectorClear(a)			((a)[0]=(a)[1]=(a)[2]=0)
#define VectorNegate(a,b)		((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2])
#define VectorSet(v, x, y, z)	((v)[0]=(x), (v)[1]=(y), (v)[2]=(z))
#define Vector4Copy(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])

#define	SnapVector(v) {v[0]=((int)(v[0]));v[1]=((int)(v[1]));v[2]=((int)(v[2]));}

#define DotProduct4(x,y)		((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3])
#define VectorSubtract4(a,b,c)	((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2],(c)[3]=(a)[3]-(b)[3])
#define VectorAdd4(a,b,c)		((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3])
#define VectorCopy4(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
#define	VectorScale4(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s),(o)[3]=(v)[3]*(s))
#define	VectorMA4(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s),(o)[3]=(v)[3]+(b)[3]*(s))
#define VectorClear4(a)			((a)[0]=(a)[1]=(a)[2]=(a)[3]=0)
#define VectorNegate4(a,b)		((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2],(b)[3]=-(a)[3])
#define VectorSet4(v,x,y,z,w)	((v)[0]=(x),(v)[1]=(y),(v)[2]=(z),(v)[3]=(w))

#define VectorCopy5(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3],(b)[4]=(a)[4])

// just in case you do't want to use the macros
vec_t _DotProduct( const vec3_t v1, const vec3_t v2 );
void _VectorSubtract( const vec3_t veca, const vec3_t vecb, vec3_t out );
void _VectorAdd( const vec3_t veca, const vec3_t vecb, vec3_t out );
void _VectorCopy( const vec3_t in, vec3_t out );
void _VectorScale( const vec3_t in, float scale, vec3_t out );
void _VectorMA( const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc );
vec_t Q_rint( vec_t in );

unsigned ColorBytes3 (float r, float g, float b);
unsigned ColorBytes4 (float r, float g, float b, float a);

float NormalizeColor( const vec3_t in, vec3_t out );
void RotatePointAroundAxis(vec3_t dst, int axis, const vec3_t point, float degrees);
void ClampColor(vec4_t color);

float RadiusFromBounds( const vec3_t mins, const vec3_t maxs );
void ClearBounds( vec3_t mins, vec3_t maxs );
void ZeroBounds(vec3_t mins, vec3_t maxs);
void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs );
void BoundsAdd(vec3_t mins, vec3_t maxs, const vec3_t mins2, const vec3_t maxs2);

float PointToSegmentDistanceSquared(const vec3_t origin, const vec3_t a, const vec3_t b);

#if !defined( Q3_VM ) || ( defined( Q3_VM ) && defined( __Q3_VM_MATH ) )
static ID_INLINE int VectorCompare( const vec3_t v1, const vec3_t v2 ) {
	if (v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2]) {
		return 0;
	}
	return 1;
}

static ID_INLINE int VectorCompare2D( const vec2_t v1, const vec2_t v2 ) {
	if( v1[ 0 ] != v2[ 0 ] || v1[ 1 ] != v2[ 1 ] ) {
		return 0;
	}
	return 1;
}

static ID_INLINE int VectorCompareEpsilon( const vec3_t v1, const vec3_t v2, float fEpsilon )
{
	int i;

	for( i = 0; i < 3; i++ )
	{
		if( fabs( v1[ i ] - v2[ i ] ) > fEpsilon ) {
			return 0;
		}
	}
	return 1;
}

static ID_INLINE vec_t VectorLength( const vec3_t v ) {
	return (vec_t)sqrt (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
}

static ID_INLINE vec_t VectorLengthSquared( const vec3_t v ) {
	return (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
}

static ID_INLINE vec_t Distance( const vec3_t p1, const vec3_t p2 ) {
	vec3_t	v;

	VectorSubtract (p2, p1, v);
	return VectorLength( v );
}

static ID_INLINE vec_t DistanceSquared( const vec3_t p1, const vec3_t p2 ) {
	vec3_t	v;

	VectorSubtract (p2, p1, v);
	return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
}

// fast vector normalize routine that does not check to make sure
// that length != 0, nor does it return length, uses rsqrt approximation
static ID_INLINE void VectorNormalizeFast( vec3_t v )
{
	float ilength;

	ilength = Q_rsqrt( DotProduct( v, v ) );

	v[0] *= ilength;
	v[1] *= ilength;
	v[2] *= ilength;
}

static ID_INLINE void VectorInverse( vec3_t v ){
	v[0] = -v[0];
	v[1] = -v[1];
	v[2] = -v[2];
}

static ID_INLINE void CrossProduct( const vec3_t v1, const vec3_t v2, vec3_t cross ) {
	cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
	cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
	cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
}

#else
int VectorCompare( const vec3_t v1, const vec3_t v2 );

vec_t VectorLength( const vec3_t v );

vec_t VectorLengthSquared( const vec3_t v );

vec_t Distance( const vec3_t p1, const vec3_t p2 );

vec_t DistanceSquared( const vec3_t p1, const vec3_t p2 );

void VectorNormalizeFast( vec3_t v );

void VectorInverse( vec3_t v );

void CrossProduct( const vec3_t v1, const vec3_t v2, vec3_t cross );

#endif

vec_t VectorNormalize (vec3_t v);		// returns vector length
vec_t VectorNormalize2( const vec3_t v, vec3_t out );
vec_t VectorNormalize2D( vec2_t v );
vec_t VectorNormalize2D2( const vec2_t v, vec2_t out );
void VectorPackTo01( vec3_t v );
void Vector4Scale( const vec4_t in, vec_t scale, vec4_t out );
void VectorRotate( vec3_t in, vec3_t matrix[3], vec3_t out );

int NearestPowerOfTwo(int val);
int Q_log2(int val);

float Q_acos(float c);

int		Q_rand( int *seed );
float	Q_random( int *seed );
float	Q_crandom( int *seed );

#define random()	((rand () & 0x7fff) / ((float)0x7fff))
#define random2()	((rand () & 0x7fff) * (1.0 / ((float)0x7fff)))
#define crandom()	(2.0 * (random() - 0.5))

float grandom( void );
float erandom( float mean );

#define AnglesToMat AnglesToAxis

void vectoangles( const vec3_t value1, vec3_t angles );
void VectorToAngles( const vec3_t vec, vec3_t angles );
void AnglesToAxis(const vec3_t angles, vec3_t axis[3]);
void YawToAxis(float yaw, float axis[2]);

float noise(float vec[], int len);
float noise1(float arg);
float noise2(vec3_t arg);
float noise3(vec3_t arg);

void	R_ConcatRotations( float in1[ 3 ][ 3 ], float in2[ 3 ][ 3 ], float out[ 3 ][ 3 ] );
void	R_ConcatTransforms( float in1[ 3 ][ 4 ], float in2[ 3 ][ 4 ], float out[ 3 ][ 4 ] );

void	MatrixToEulerAngles( const float mat[ 3 ][ 3 ], vec3_t ang );
void	QuatToMat( const float q[ 4 ], float m[ 3 ][ 3 ] );
void SlerpQuaternion(float from[4], float to[4], float t, float res[4]);
void	EulerToQuat( float ang[ 3 ], float q[ 4 ] );
void	MatToQuat( float srcMatrix[ 3 ][ 3 ], float destQuat[ 4 ] );

float ProjectPointOnLine( const vec3_t i_vStart, const vec3_t i_vEnd, const vec3_t i_vPoint, vec3_t o_vProj );
float ProjectLineOnPlane(const vec3_t vPlaneNorm, float fPlaneDist, const vec3_t vStart, const vec3_t vEnd, vec3_t vProj );

float anglemod( float a );
float angledist( float ang );

void AxisClear( vec3_t axis[3] );
void AxisCopy( const vec3_t in[3], vec3_t out[3] );

void SetPlaneSignbits( struct cplane_s *out );
int BoxOnPlaneSide (const vec3_t emins, const vec3_t emaxs, struct cplane_s *plane);

void  CalculateRotatedBounds( vec3_t angles, vec3_t mins, vec3_t maxs );
void  CalculateRotatedBounds2( float trans[ 3 ][ 3 ], vec3_t mins, vec3_t maxs );
int   BoundingBoxToInteger( vec3_t mins, vec3_t maxs );
void  IntegerToBoundingBox( int num, vec3_t mins, vec3_t maxs );
qboolean BoundsIntersect(const vec3_t mins, const vec3_t maxs,
		const vec3_t mins2, const vec3_t maxs2);
qboolean BoundsIntersectSphere(const vec3_t mins, const vec3_t maxs,
		const vec3_t origin, vec_t radius);
qboolean BoundsIntersectPoint(const vec3_t mins, const vec3_t maxs,
		const vec3_t origin);

float	AngleMod(float a);
float	LerpAngle (float from, float to, float frac);
float	LerpAngleFromCurrent( float from, float to, float current, float frac );
float	AngleSubtract( float a1, float a2 );
void	AnglesSubtract( vec3_t v1, vec3_t v2, vec3_t v3 );

float AngleNormalize360 ( float angle );
float AngleNormalize180 ( float angle );
float AngleDelta ( float angle1, float angle2 );

qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c );
qboolean PlanesGetIntersectionPoint(const vec4_t plane1, const vec4_t plane2, const vec4_t plane3, vec3_t out);
void PlaneIntersectRay(const vec3_t rayPos, const vec3_t rayDir, const vec4_t plane, vec3_t res);
void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal );
void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees );
void RotateAroundDirection( vec3_t axis[3], float yaw );
void MakeNormalVectors( const vec3_t forward, vec3_t right, vec3_t up );
// perpendicular vector could be replaced by this

//int	PlaneTypeForNormal (vec3_t normal);

void  MatrixTransformVector( const vec3_t in, const float mat[ 3 ][ 3 ], vec3_t out );
void  MatrixTransformVectorRight( const float mat[ 3 ][ 3 ], const vec3_t in, vec3_t out );
void Matrix3x3Multiply( const float in1[ 3 ][ 3 ], const float in2[ 3 ][ 3 ], float out[ 3 ][ 3 ] );
void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up );
void AngleVectorsLeft( const vec3_t angles, vec3_t forward, vec3_t left, vec3_t up );
void PerpendicularVector( vec3_t dst, const vec3_t src );

void            GetPerpendicularViewVector(const vec3_t point, const vec3_t p1, const vec3_t p2, vec3_t up);
void            ProjectPointOntoVector(vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj);

float           pointToLineDistance(const vec3_t point, const vec3_t p1, const vec3_t p2);
float           VectorMinComponent(vec3_t v);
float           VectorMaxComponent(vec3_t v);

#ifndef MAX
#define MAX(x,y) ((x)>(y)?(x):(y))
#endif

#ifndef MIN
#define MIN(x,y) ((x)<(y)?(x):(y))
#endif

vec_t           DistanceBetweenLineSegmentsSquared(const vec3_t sP0, const vec3_t sP1,
												   const vec3_t tP0, const vec3_t tP1, float *s, float *t);
vec_t           DistanceBetweenLineSegments(const vec3_t sP0, const vec3_t sP1,
											const vec3_t tP0, const vec3_t tP1, float *s, float *t);

void			VectorMatrixInverse( void* DstMatrix, const void* SrcMatrix );

void            MatrixIdentity(matrix_t m);
void            MatrixClear(matrix_t m);
void            MatrixCopy(const matrix_t in, matrix_t out);
qboolean        MatrixCompare(const matrix_t a, const matrix_t b);
void            MatrixTransposeIntoXMM(const matrix_t m);
void            MatrixTranspose(const matrix_t in, matrix_t out);

// invert any m4x4 using Kramer's rule.. return qtrue if matrix is singular, else return qfalse
qboolean        MatrixInverse(matrix_t m);
void            MatrixSetupXRotation(matrix_t m, vec_t degrees);
void            MatrixSetupYRotation(matrix_t m, vec_t degrees);
void            MatrixSetupZRotation(matrix_t m, vec_t degrees);
void            MatrixSetupTranslation(matrix_t m, vec_t x, vec_t y, vec_t z);
void            MatrixSetupScale(matrix_t m, vec_t x, vec_t y, vec_t z);
void            MatrixSetupShear(matrix_t m, vec_t x, vec_t y);
void            Matrix4x4Multiply(const matrix_t a, const matrix_t b, matrix_t out);
void			MatrixMultiply( const float in1[ 3 ][ 3 ], const float in2[ 3 ][ 3 ], float out[ 3 ][ 3 ] );
void            MatrixMultiply2( matrix_t m, const matrix_t m2 );
void            MatrixMultiplyRotation(matrix_t m, vec_t pitch, vec_t yaw, vec_t roll);
void            MatrixMultiplyZRotation(matrix_t m, vec_t degrees);
void            MatrixMultiplyTranslation(matrix_t m, vec_t x, vec_t y, vec_t z);
void            MatrixMultiplyScale(matrix_t m, vec_t x, vec_t y, vec_t z);
void            MatrixMultiplyShear(matrix_t m, vec_t x, vec_t y);
void            MatrixToAngles(const matrix_t m, vec3_t angles);
void            MatrixFromAngles(matrix_t m, vec_t pitch, vec_t yaw, vec_t roll);
void            MatrixFromVectorsFLU(matrix_t m, const vec3_t forward, const vec3_t left, const vec3_t up);
void            MatrixFromVectorsFRU(matrix_t m, const vec3_t forward, const vec3_t right, const vec3_t up);
void            MatrixFromQuat(matrix_t m, const quat_t q);
void            MatrixFromPlanes(matrix_t m, const vec4_t left, const vec4_t right, const vec4_t bottom, const vec4_t top,
								 const vec4_t near, const vec4_t far);
void            MatrixToVectorsFLU(const matrix_t m, vec3_t forward, vec3_t left, vec3_t up);
void            MatrixToVectorsFRU(const matrix_t m, vec3_t forward, vec3_t right, vec3_t up);
void            MatrixSetupTransformFromVectorsFLU(matrix_t m, const vec3_t forward, const vec3_t left, const vec3_t up, const vec3_t origin);
void            MatrixSetupTransformFromVectorsFRU(matrix_t m, const vec3_t forward, const vec3_t right, const vec3_t up, const vec3_t origin);
void            MatrixSetupTransformFromRotation(matrix_t m, const matrix_t rot, const vec3_t origin);
void            MatrixSetupTransformFromQuat(matrix_t m, const quat_t quat, const vec3_t origin);
void            MatrixAffineInverse(const matrix_t in, matrix_t out);
void            MatrixTransformNormal(const matrix_t m, const vec3_t in, vec3_t out);
void            MatrixTransformNormal2(const matrix_t m, vec3_t inout);
void            MatrixTransformPoint(const matrix_t m, const vec3_t in, vec3_t out);
void            MatrixTransformPoint2(const matrix_t m, vec3_t inout);
void            MatrixTransform4(const matrix_t m, const vec4_t in, vec4_t out);
void            MatrixTransformPlane(const matrix_t m, const vec4_t in, vec4_t out);
void            MatrixTransformPlane2(const matrix_t m, vec3_t inout);
void            MatrixPerspectiveProjection(matrix_t m, vec_t left, vec_t right, vec_t bottom, vec_t top, vec_t near, vec_t far);
void            MatrixPerspectiveProjectionLH(matrix_t m, vec_t left, vec_t right, vec_t bottom, vec_t top, vec_t near, vec_t far);
void            MatrixPerspectiveProjectionRH(matrix_t m, vec_t left, vec_t right, vec_t bottom, vec_t top, vec_t near, vec_t far);
void            MatrixPerspectiveProjectionFovYAspectLH(matrix_t m, vec_t fov, vec_t aspect, vec_t near, vec_t far);
void            MatrixPerspectiveProjectionFovXYLH(matrix_t m, vec_t fovX, vec_t fovY, vec_t near, vec_t far);
void            MatrixPerspectiveProjectionFovXYRH(matrix_t m, vec_t fovX, vec_t fovY, vec_t near, vec_t far);
void            MatrixPerspectiveProjectionFovXYInfiniteRH(matrix_t m, vec_t fovX, vec_t fovY, vec_t near);
void            MatrixOrthogonalProjection(matrix_t m, vec_t left, vec_t right, vec_t bottom, vec_t top, vec_t near, vec_t far);

void			MatrixOrthogonalProjectionLH(matrix_t m, vec_t left, vec_t right, vec_t bottom, vec_t top, vec_t near, vec_t far);
void			MatrixOrthogonalProjectionRH(matrix_t m, vec_t left, vec_t right, vec_t bottom, vec_t top, vec_t near, vec_t far);

void			MatrixPlaneReflection(matrix_t m, const vec4_t plane);

void            MatrixLookAtLH(matrix_t output, const vec3_t pos, const vec3_t dir, const vec3_t up);
void            MatrixLookAtRH(matrix_t m, const vec3_t eye, const vec3_t dir, const vec3_t up);
void            MatrixScaleTranslateToUnitCube(matrix_t m, const vec3_t mins, const vec3_t maxs);
void            MatrixCrop(matrix_t m, const vec3_t mins, const vec3_t maxs);

void			TransposeMatrix( float in[ 3 ][ 3 ], float out[ 3 ][ 3 ] );

static ID_INLINE void AnglesToMatrix(const vec3_t angles, matrix_t m)
{
	MatrixFromAngles(m, angles[PITCH], angles[YAW], angles[ROLL]);
}


#define QuatSet(q,x,y,z,w)	((q)[0]=(x),(q)[1]=(y),(q)[2]=(z),(q)[3]=(w))
#define QuatCopy(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])

#define QuatCompare(a,b)	((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3])

static ID_INLINE void QuatClear(quat_t q)
{
	q[0] = 0;
	q[1] = 0;
	q[2] = 0;
	q[3] = 1;
}

/*
static ID_INLINE int QuatCompare(const quat_t a, const quat_t b)
{
	if(a[0] != b[0] || a[1] != b[1] || a[2] != b[2] || a[3] != b[3])
	{
		return 0;
	}
	return 1;
}
*/

static ID_INLINE void QuatCalcW(quat_t q)
{
#if 1
	vec_t           term = 1.0f - (q[0] * q[0] + q[1] * q[1] + q[2] * q[2]);

	if(term < 0.0)
		q[3] = 0.0;
	else
		q[3] = -sqrt(term);
#else
	q[3] = sqrt(fabs(1.0f - (q[0] * q[0] + q[1] * q[1] + q[2] * q[2])));
#endif
}

static ID_INLINE void QuatInverse(quat_t q)
{
	q[0] = -q[0];
	q[1] = -q[1];
	q[2] = -q[2];
}

static ID_INLINE void QuatAntipodal(quat_t q)
{
	q[0] = -q[0];
	q[1] = -q[1];
	q[2] = -q[2];
	q[3] = -q[3];
}

static ID_INLINE vec_t QuatLength(const quat_t q)
{
	return (vec_t) sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
}

vec_t           QuatNormalize(quat_t q);

void            QuatFromAngles(quat_t q, vec_t pitch, vec_t yaw, vec_t roll);

static ID_INLINE void AnglesToQuat(const vec3_t angles, quat_t q)
{
	QuatFromAngles(q, angles[PITCH], angles[YAW], angles[ROLL]);
}

void            QuatFromMatrix(quat_t q, const matrix_t m);
void            QuatToVectorsFLU(const quat_t quat, vec3_t forward, vec3_t left, vec3_t up);
void            QuatToVectorsFRU(const quat_t quat, vec3_t forward, vec3_t right, vec3_t up);
void            QuatToAxis(const quat_t q, vec3_t axis[3]);
void            QuatToAngles(const quat_t q, vec3_t angles);

// wombat: pretty straightforward
void			QuatToRotAngle( const quat_t q, vec_t *angle );
void			QuatToRotAngleAxis( const quat_t q, vec_t *angle, vec3_t axis );

void			QuatFromRotAngleAxis( quat_t q, vec_t angle, const vec3_t axis );

// Quaternion multiplication, analogous to the matrix multiplication routines.

// qa = rotate by qa, then qb
void            QuatMultiply0(quat_t qa, const quat_t qb);

// qc = rotate by qa, then qb
void            QuatMultiply1(const quat_t qa, const quat_t qb, quat_t qc);

// qc = rotate by qa, then by inverse of qb
void            QuatMultiply2(const quat_t qa, const quat_t qb, quat_t qc);

// qc = rotate by inverse of qa, then by qb
void            QuatMultiply3(const quat_t qa, const quat_t qb, quat_t qc);

// qc = rotate by inverse of qa, then by inverse of qb
void            QuatMultiply4(const quat_t qa, const quat_t qb, quat_t qc);

void QuaternionMultiply( quat_t output, quat_t first, quat_t second );

void            QuatSlerp(const quat_t from, const quat_t to, float frac, quat_t out);
void            QuatTransformVector(const quat_t q, const vec3_t in, vec3_t out);
int Q_isnan( float x );

//=============================================


typedef struct
{
	qboolean        frameMemory;
	int             currentElements;
	int             maxElements;	// will reallocate and move when exceeded
	void          **elements;
} growList_t;

// you don't need to init the growlist if you don't mind it growing and moving
// the list as it expands
void            Com_InitGrowList(growList_t * list, int maxElements);
void            Com_DestroyGrowList(growList_t * list);
int             Com_AddToGrowList(growList_t * list, void *data);
void           *Com_GrowListElement(const growList_t * list, int index);
int             Com_IndexForGrowListElement(const growList_t * list, const void *element);


//=============================================

float Com_Clamp( float min, float max, float value );

const char	*COM_SkipPath( const char *pathname );
const char	*COM_GetExtension( const char *name );
void	COM_StripExtension(const char *in, char *out, int destsize);
qboolean COM_CompareExtension(const char* in, const char* ext);
void	COM_DefaultExtension( char *path, int maxSize, const char *extension );

void	COM_BeginParseSession( const char *name );
int		COM_GetCurrentParseLine( void );
const char	*COM_Parse( char **data_p );
char	*COM_ParseExt( char **data_p, qboolean allowLineBreak );
char	*COM_ParseExtIgnoreQuotes( char **data_p, qboolean allowLineBreak );
const char *COM_GetToken( char **data_p, qboolean crossline );
void	Com_SkipRestOfLine(char **data);
void	Com_SkipBracedSection(char **program);
void	Com_Parse1DMatrix(char **buf_p, int x, float *m, qboolean checkBrackets);
int		COM_Compress( char *data_p );
void	COM_ParseError( char *format, ... ) __attribute__ ((format (printf, 1, 2)));
void	COM_ParseWarning( char *format, ... ) __attribute__ ((format (printf, 1, 2)));
//int		COM_ParseInfos( char *buf, int max, char infos[][MAX_INFO_STRING] );

#define MAX_TOKENLENGTH		1024

#ifndef TT_STRING
//token types
#define TT_STRING					1			// string
#define TT_LITERAL					2			// literal
#define TT_NUMBER					3			// number
#define TT_NAME						4			// name
#define TT_PUNCTUATION				5			// punctuation
#endif

typedef struct pc_token_s
{
	int type;
	int subtype;
	int intvalue;
	float floatvalue;
	char string[MAX_TOKENLENGTH];
} pc_token_t;

// data is an in/out parm, returns a parsed out token

void	COM_MatchToken( char**buf_p, char *match );

qboolean SkipBracedSection (char **program, int depth);
void SkipRestOfLine ( char **data );

void Parse1DMatrix (char **buf_p, int x, float *m);
void Parse2DMatrix (char **buf_p, int y, int x, float *m);
void Parse3DMatrix (char **buf_p, int z, int y, int x, float *m);

int Com_HexStrToInt( const char *str );

size_t	QDECL Com_sprintf (char *dest, size_t size, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));

char *Com_SkipTokens( char *s, int numTokens, const char *sep );
char *Com_SkipCharset( char *s, const char *sep );

void Com_RandomBytes(byte* string, int len);
void Com_BackslashToSlash( char *str );

// mode parm for FS_FOpenFile
typedef enum {
	FS_READ,
	FS_WRITE,
	FS_APPEND,
	FS_APPEND_SYNC
} fsMode_t;

typedef enum {
	FS_SEEK_CUR,
	FS_SEEK_END,
	FS_SEEK_SET
} fsOrigin_t;

//=============================================

// get the control character for the given key (moved from sdl_input.c)
#define CTRL(a) ((a)-'a'+1)

int Q_isprint( int c );
int Q_islower( int c );
int Q_isupper( int c );
int Q_isalpha( int c );
qboolean Q_isanumber( const char *s );
qboolean Q_isintegral( float f );

// portable case insensitive compare
int		Q_stricmp (const char *s1, const char *s2);
int		Q_strncmp( const char *s1, const char *s2, size_t n );
int		Q_stricmpn (const char *s1, const char *s2, size_t n);
char	*Q_strlwr( char *s1 );
char	*Q_strupr( char *s1 );
char	*Q_strrchr( const char* string, int c );
const char	*Q_stristr( const char *s, const char *find);
qboolean Q_strreplace(char *dest, int destsize, const char *find, const char *replace);

// buffer size safe library replacements
void	Q_strncpyz( char *dest, const char *src, size_t destsize );
void	Q_strcat( char *dest, int size, const char *src );

// strlen that discounts Quake color sequences
int Q_PrintStrlen( const char *string );
// removes color sequences from string
char *Q_CleanStr( char *string );
// Count the number of char tocount encountered in string
int Q_CountChar(const char *string, char tocount);

//=============================================

void	Swap_Init(void);

// 64-bit integers for global rankings interface
// implemented as a struct for qvm compatibility
typedef struct
{
	byte	b0;
	byte	b1;
	byte	b2;
	byte	b3;
	byte	b4;
	byte	b5;
	byte	b6;
	byte	b7;
} qint64;

const char *va( const char *format, ... ) __attribute__ ((format (printf, 1, 2)));

#define TRUNCATE_LENGTH	64
void Com_TruncateLongString( char *buffer, const char *s );

//=============================================

float vectoyaw(const vec3_t vec);
int MusicMood_NameToNum( const char * name );
const char * MusicMood_NumToName( int num );
int EAXMode_NameToNum( const char * name );
const char * EAXMode_NumToName( int num );

//
// key / value info strings
//
char *Info_ValueForKey( const char *s, const char *key );
void Info_RemoveKey( char *s, const char *key );
void Info_RemoveKey_big( char *s, const char *key );
void Info_SetValueForKey( char *s, const char *key, const char *value );
void Info_SetValueForKey_Big( char *s, const char *key, const char *value );
qboolean Info_Validate( const char *s );
void Info_NextPair( const char **s, char *key, char *value );

// this is only here so the functions in q_shared.c and bg_*.c can link
void	QDECL Com_Error( int level, const char *error, ... ) __attribute__ ((format (printf, 2, 3)));
void	QDECL Com_Printf( const char *msg, ... ) __attribute__ ((format (printf, 1, 2)));
void	QDECL Com_DPrintf( const char *msg, ... ) __attribute__ ((format (printf, 1, 2)));
void	QDECL Com_DPrintf2( const char *msg, ... ) __attribute__ ((format (printf, 1, 2)));
void	QDECL Com_DebugPrintf( const char *msg, ... ) __attribute__ ((format (printf, 1, 2)));


/*
==========================================================

CVARS (console variables)

Many variables can be used for cheating purposes, so when
cheats is zero, force all unspecified variables to their
default values.
==========================================================
*/

#define	CVAR_ARCHIVE		0x0001	// set to cause it to be saved to vars.rc
					// used for system variables, not for player
					// specific configurations
#define	CVAR_USERINFO		0x0002	// sent to server on connect or change
#define	CVAR_SERVERINFO		0x0004	// sent in response to front end requests
#define	CVAR_SYSTEMINFO		0x0008	// these cvars will be duplicated on all clients
#define	CVAR_INIT		0x0010	// don't allow change from console at all,
					// but can be set from the command line
#define	CVAR_LATCH		0x0020	// will only change when C code next does
					// a Cvar_Get(), so it can't be changed
					// without proper initialization.  modified
					// will be set, even though the value hasn't
					// changed yet
#define	CVAR_ROM		0x0040	// display only, cannot be set by user at all
#define	CVAR_USER_CREATED	0x0080	// created by a set command
#define	CVAR_TEMP		0x0100	// can be set even when cheats are disabled, but is not archived
#define CVAR_CHEAT		0x0200	// can not be changed if cheats are disabled
#define CVAR_NORESTART		0x0400	// do not clear when a cvar_restart is issued

#define CVAR_SERVER_CREATED	0x0800	// cvar was created by a server the client connected to.

#define	CVAR_SOUND_LATCH	0x1000		// specifically for sound will only change 
											// when C code next does a Cvar_Get(), so it 
											// can't be changed without proper initialization.
											// modified will be set, even though the value hasn't
											// changed yet

#define	CVAR_TERRAIN_LATCH	0x2000		// specifically for terrain will only change

#define	CVAR_SAVEGAME		0x4000		// cvar will be saved when saving to file

#define CVAR_VM_CREATED		0x8000	// cvar was created exclusively in one of the VMs.
#define CVAR_PROTECTED		0x10000	// prevent modifying this var from VMs or the server
#define CVAR_RESETSTRING	0x20000	// force the cvar's reset string to be set
// These flags are only returned by the Cvar_Flags() function
#define CVAR_MODIFIED		0x40000000	// Cvar was modified
#define CVAR_NONEXISTENT	0x80000000	// Cvar doesn't exist.

// nothing outside the Cvar_*() functions should modify these fields!
typedef struct cvar_s cvar_t;

struct cvar_s {
	char			*name;
	char			*string;
	char			*resetString;		// cvar_restart will reset to this value
	char			*latchedString;		// for CVAR_LATCH vars
	int				flags;
	qboolean	modified;			// set each time the cvar is changed
	int				modificationCount;	// incremented each time the cvar is changed
	float			value;				// atof( string )
	int				integer;			// atoi( string )
	qboolean	validate;
	qboolean	integral;
	float			min;
	float			max;
	char			*description;

	cvar_t *next;
	cvar_t *prev;
	cvar_t *hashNext;
	cvar_t *hashPrev;
	int			hashIndex;
};

#define	MAX_CVAR_VALUE_STRING	256

typedef int	cvarHandle_t;

// the modules that run in the virtual machine can't access the cvar_t directly,
// so they must ask for structured updates
typedef struct {
	cvarHandle_t	handle;
	int			modificationCount;
	float		value;
	int			integer;
	char		string[MAX_CVAR_VALUE_STRING];
	char		latchedString[MAX_CVAR_VALUE_STRING];
} vmCvar_t;

/*
==============================================================

COLLISION DETECTION

==============================================================
*/

#include "surfaceflags.h"			// shared with the q3map utility

// plane types are used to speed some tests
// 0-2 are axial planes
#define	PLANE_X			0
#define	PLANE_Y			1
#define	PLANE_Z			2
#define	PLANE_NON_AXIAL	3
#define PLANE_NON_PLANAR 4


/*
=================
PlaneTypeForNormal
=================
*/

//#define PlaneTypeForNormal(x) (x[0] == 1.0 ? PLANE_X : (x[1] == 1.0 ? PLANE_Y : (x[2] == 1.0 ? PLANE_Z : PLANE_NON_AXIAL) ) )
static ID_INLINE int PlaneTypeForNormal(vec3_t normal)
{
	if(normal[0] == 1.0)
		return PLANE_X;

	if(normal[1] == 1.0)
		return PLANE_Y;

	if(normal[2] == 1.0)
		return PLANE_Z;

	if(normal[0] == 0.0 && normal[1] == 0.0 && normal[2] == 0.0)
		return PLANE_NON_PLANAR;

	return PLANE_NON_AXIAL;
}

// plane_t structure
// !!! if this is changed, it must be changed in asm code too !!!
typedef struct cplane_s {
	vec3_t	normal;
	float	dist;
	byte	type;			// for fast side tests: 0,1,2 = axial, 3 = nonaxial
	byte	signbits;		// signx + (signy<<1) + (signz<<2), used as lookup during collision
	byte	pad[2];
} cplane_t;

// body hit location
typedef enum hitloc_e {
	HITLOC_MISS = -2,
	HITLOC_GENERAL = -1,
	HITLOC_HEAD = 0,
	HITLOC_HELMET,
	HITLOC_NECK,
	HITLOC_TORSO_UPPER,
	HITLOC_TORSO_MID,
	HITLOC_TORSO_LOWER,
	HITLOC_PELVIS,
	HITLOC_R_ARM_UPPER,
	HITLOC_L_ARM_UPPER,
	HITLOC_R_LEG_UPPER,
	HITLOC_L_LEG_UPPER,
	HITLOC_R_ARM_LOWER,
	HITLOC_L_ARM_LOWER,
	HITLOC_R_LEG_LOWER,
	HITLOC_L_LEG_LOWER,
	HITLOC_R_HAND,
	HITLOC_L_HAND,
	HITLOC_R_FOOT,
	HITLOC_L_FOOT,
	NUMBODYLOCATIONS
} hitloc_t;

// a trace is returned when a box is swept through the world
typedef struct {
	qboolean	allsolid;	// if true, plane is not valid
	qboolean	startsolid;	// if true, the initial point was in a solid area
	float		fraction;	// time completed, 1.0 = didn't hit anything
	vec3_t		endpos;		// final position
	cplane_t	plane;		// surface normal at impact, transformed to world space
	int			surfaceFlags;	// surface hit
	int			shaderNum;
	int			contents;	// contents on other side of surface hit
	int			entityNum;	// entity the contacted surface is a part of

	int			location;
	struct gentity_s *ent;
} trace_t;

// trace->entityNum can also be 0 to (MAX_GENTITIES-1)
// or ENTITYNUM_NONE, ENTITYNUM_WORLD

#define SAVEGAME_STRUCT_VERSION 4

typedef struct savegamestruct_s {
	//int version
	// Modified in OPM
	//===
	short version;
	// The type matches com_target_game
	byte type;
	// Currently unused
	byte flags;
	//===
	int time;
	int mapTime;
	char comment[ 64 ];
	char mapName[ 64 ];
	char saveName[ 64 ];
	char tm_filename[ 64 ];
	int tm_loopcount;
	int tm_offset;
} savegamestruct_t;

// markfragments are returned by CM_MarkFragments()
typedef struct {
	int		firstPoint;
	int		numPoints;
	int		iIndex;
} markFragment_t;

typedef struct treadMark_s {
	int			iReferenceNumber;
	int			iLastTime;
	qhandle_t	hTreadShader;
	int			iState;
	float		fWidth;
	vec3_t		vStartDir;
	vec3_t		vStartVerts[ 2 ];
	float		fStartTexCoord;
	float		fStartAlpha;
	vec3_t		vMidPos;
	vec3_t		vMidVerts[ 2 ];
	float		fMidTexCoord;
	float		fMidAlpha;
	vec3_t		vEndPos;
	vec3_t		vEndVerts[ 2 ];
	float		fEndTexCoord;
	float		fEndAlpha;
} treadMark_t;

typedef struct {
	vec3_t p;
	quat_t q;
} bone_t;

typedef struct {
	vec3_t		origin;
	vec3_t		axis[ 3 ];
} orientation_t;

//=====================================================================


// in order from highest priority to lowest
// if none of the catchers are active, bound key strings will be executed
#define KEYCATCH_CONSOLE		0x0001
#define	KEYCATCH_UI				0x0002
#define	KEYCATCH_MESSAGE		0x0004
#define	KEYCATCH_CGAME			0x0008


// sound channels
// channel 0 never willingly overrides
// other channels will allways override a playing sound on that channel
/*typedef enum {
	CHAN_AUTO,
	CHAN_LOCAL,		// menu sounds, etc
	CHAN_WEAPON,
	CHAN_VOICE,
	CHAN_ITEM,
	CHAN_BODY,
	CHAN_LOCAL_SOUND,	// chat messages, etc
	CHAN_ANNOUNCER		// announcer voices, etc
} soundChannel_t;*/
typedef enum {
	CHAN_AUTO,
	CHAN_BODY,
	CHAN_ITEM,
	CHAN_WEAPONIDLE,
	CHAN_VOICE,
	CHAN_LOCAL,
	CHAN_WEAPON,
	CHAN_DIALOG_SECONDARY,
	CHAN_DIALOG,
	CHAN_MENU,
	CHAN_LOCAL_SOUND,	// chat messages, etc
	CHAN_ANNOUNCER,		// announcer voices, etc
	CHAN_MAX
} soundChannel_t;

#define S_FLAG_DO_CALLBACK 0x400

#define DEFAULT_MIN_DIST  -1.0
#define DEFAULT_VOL  -1.0

#define LEVEL_WIDE_MIN_DIST  10000	// full volume the entire level
#define LEVEL_WIDE_STRING "levelwide"

#define  SOUND_SYNCH             0x1
#define  SOUND_SYNCH_FADE        0x2
#define  SOUND_RANDOM_PITCH_20   0x4
#define  SOUND_RANDOM_PITCH_40   0x8
#define  SOUND_LOCAL_DIALOG      0x10

typedef enum
{
	mood_none,
	mood_normal,
	mood_action,
	mood_suspense,
	mood_mystery,
	mood_success,
	mood_failure,
	mood_surprise,
	mood_special,
	mood_aux1,
	mood_aux2,
	mood_aux3,
	mood_aux4,
	mood_aux5,
	mood_aux6,
	mood_aux7,
	mood_totalnumber
} music_mood_t;

typedef enum
{
	eax_generic,
	eax_paddedcell,
	eax_room,
	eax_bathroom,
	eax_livingroom,
	eax_stoneroom,
	eax_auditorium,
	eax_concerthall,
	eax_cave,
	eax_arena,
	eax_hangar,
	eax_carpetedhallway,
	eax_hallway,
	eax_stonecorridor,
	eax_alley,
	eax_forest,
	eax_city,
	eax_mountains,
	eax_quarry,
	eax_plain,
	eax_parkinglot,
	eax_sewerpipe,
	eax_underwater,
	eax_drugged,
	eax_dizzy,
	eax_psychotic,
	eax_totalnumber
} eax_mode_t;

/*
========================================================================

  ELEMENTS COMMUNICATED ACROSS THE NET

========================================================================
*/

#define	ANGLE2SHORT(x)	((int)((x)*65536/360) & 65535)
#define	BYTE2ANGLE(x)	((x)*(360.0/255))
#define	SHORT2ANGLE(x)	((x)*(360.0/65536))

#define	SNAPFLAG_RATE_DELAYED	1
#define	SNAPFLAG_NOT_ACTIVE		2	// snapshot used during connection and for zombies
#define SNAPFLAG_SERVERCOUNT	4	// toggled every map_restart so transitions can be detected

//
// per-level limits
//
#define	MAX_CLIENTS			64		// absolute limit
#define MAX_LOCATIONS		64

#define MAX_MAP_BOUNDS          8192
#define MIN_MAP_BOUNDS          ( -MAX_MAP_BOUNDS )
#define MAP_SIZE                ( MAX_MAP_BOUNDS - MIN_MAP_BOUNDS )

#define	GENTITYNUM_BITS		10		// don't need to send any more
#define	MAX_GENTITIES		(1<<GENTITYNUM_BITS)

// entitynums are communicated with GENTITY_BITS, so any reserved
// values that are going to be communcated over the net need to
// also be in this range
#define	ENTITYNUM_NONE		(MAX_GENTITIES-1)
#define	ENTITYNUM_WORLD		(MAX_GENTITIES-2)
#define	ENTITYNUM_MAX_NORMAL	(MAX_GENTITIES-2)

#define MAX_SERVER_SOUNDS			64
#define MAX_SERVER_SOUNDS_BITS		(MAX_SERVER_SOUNDS-1)

#define	MAX_MODELS			1024		// these are sent over the net as 8 bits
#define	MAX_SOUNDS			512		// so they cannot be blindly increased
#define MAX_OBJECTIVES		20
#define MAX_LIGHTSTYLES		32
#define MAX_WEAPONS			64

#define	MAX_CONFIGSTRINGS	2736
#define MAX_HUDDRAW_ELEMENTS 256

#define MAX_SUBTITLES 4

// these are the only configstrings that the system reserves, all the
// other ones are strictly for servergame to clientgame communication
#define	CS_SERVERINFO		0		// an info string with all the serverinfo cvars
#define	CS_SYSTEMINFO		1		// an info string for server system to client system configuration (timescale, etc)

#define	RESERVED_CONFIGSTRINGS	2	// game can't modify below this, only the system can

#define	MAX_GAMESTATE_CHARS	41952
typedef struct {
	int			stringOffsets[MAX_CONFIGSTRINGS];
	char		stringData[MAX_GAMESTATE_CHARS];
	int			dataCount;
} gameState_t;

//=========================================================

// maybe this is better put somewhere else...
typedef struct server_sound_s {
	vec3_t origin;
	int entity_number;
	int channel;
	short int sound_index;
	float volume;
	float min_dist;
	float maxDist;
	float pitch;
	qboolean stop_flag;
	qboolean streamed;
} server_sound_t;

typedef struct usereyes_s {
	signed char ofs[ 3 ];
	float angles[ 2 ];
} usereyes_t;

// bit field limits
#define	MAX_STATS				32
#define	MAX_ACTIVE_ITEMS		8
#define	MAX_AMMO				16
#define	MAX_AMMOCOUNT			16

#define	MAX_PERSISTANT			16
#define	MAX_POWERUPS			16

#define	MAX_PS_EVENTS			2

#define PS_PMOVEFRAMECOUNTBITS	6

// playerState_t is the information needed by both the client and server
// to predict player motion and actions
// nothing outside of pmove should modify these, or some degree of prediction error
// will occur

// you can't add anything to this without modifying the code in msg.c

// playerState_t is a full superset of entityState_t as it is used by players,
// so if a playerState_t is transmitted, the entityState_t can be fully derived
// from it.

typedef struct playerState_s {
	int			commandTime;	// cmd->serverTime of last executed command
	int			pm_type;
	int			bobCycle;		// for view bobbing and footstep generation
	int			net_pm_flags;	// ducked, jump_held, etc
	int			pm_flags;		// ducked, jump_held, etc
	int			pm_time;

	vec3_t		origin;
	vec3_t		velocity;

	int			gravity;
	int			speed;
	int			delta_angles[3];	// add to command angles to get view direction
									// changed by spawns, rotating objects, and teleporters

	int			groundEntityNum;	// ENTITYNUM_NONE = in air

	qboolean	walking;
	qboolean	groundPlane;
	int			feetfalling;
	float		falldir[3];
	trace_t		groundTrace;

	int			clientNum;		// ranges from 0 to MAX_CLIENTS-1

	vec3_t		viewangles;		// for fixed views
	int			viewheight;

	float		fLeanAngle;
	int			iNetViewModelAnim;
	int			iViewModelAnim;
	int			iViewModelAnimChanged;

	int			stats[MAX_STATS];
	int			activeItems[MAX_ACTIVE_ITEMS];
	int			ammo_name_index[MAX_AMMO];
	int			ammo_amount[MAX_AMMOCOUNT];
	int			max_ammo_amount[MAX_AMMOCOUNT];

	int			current_music_mood;
	int			fallback_music_mood;
	float		music_volume;
	float		music_volume_fade_time;

	int			reverb_type;
	float		reverb_level;

	float		blend[4];			// rgba full screen effect
	float		fov;				// fov of the player

    vec3_t		camera_origin;	// origin for camera view
    vec3_t		camera_angles;	// angles for camera view
	float		camera_time;

	vec3_t		camera_offset;	// angular offset for camera
	vec3_t		camera_posofs;
	int			camera_flags;	// third-person camera flags
	vec3_t		damage_angles;	// these angles are added directly to the view, without lerping
	// --
	// Team Assault
	int			radarInfo;
	qboolean	voted;
	// --

	// not communicated over the net at all
	int			ping;			// server to game info for scoreboard
	float		vEyePos[3];
} playerState_t;


//====================================================================

//
// usercmd_t->button bits, many of which are generated by the client system,
// so they aren't game-only definitions
//
#define BUTTON_ATTACKLEFT_BITINDEX  	0
#define BUTTON_ATTACKRIGHT_BITINDEX 	1
#define BUTTON_RUN_BITINDEX				2
#define BUTTON_USE_BITINDEX				3
#define BUTTON_LEAN_LEFT_BITINDEX		4
#define BUTTON_LEAN_RIGHT_BITINDEX		5
#define BUTTON_TALK_BITINDEX			6			// displays talk balloon and disables actions
#define BUTTON_ANY_BITINDEX				14			// any key whatsoever
#define BUTTON_MOUSE_BITINDEX			15			// mouse move

#define	BUTTON_ATTACKLEFT  	   (1 << BUTTON_ATTACKLEFT_BITINDEX)
#define	BUTTON_ATTACKRIGHT 	   (1 << BUTTON_ATTACKRIGHT_BITINDEX)
#define BUTTON_RUN             (1 << BUTTON_RUN_BITINDEX)
#define BUTTON_USE             (1 << BUTTON_USE_BITINDEX)
#define BUTTON_LEAN_LEFT       (1 << BUTTON_LEAN_LEFT_BITINDEX)
#define BUTTON_LEAN_RIGHT      (1 << BUTTON_LEAN_RIGHT_BITINDEX)
#define	BUTTON_TALK			   (1 << BUTTON_TALK_BITINDEX)			// displays talk balloon and disables actions
#define	BUTTON_ANY			   (1 << BUTTON_ANY_BITINDEX)		   // any key whatsoever
#define BUTTON_MOUSE           (1 << BUTTON_MOUSE_BITINDEX)

typedef enum {
    WEAPON_COMMAND_NONE,
	WEAPON_COMMAND_USE_PISTOL,
	WEAPON_COMMAND_USE_RIFLE,
	WEAPON_COMMAND_USE_SMG,
	WEAPON_COMMAND_USE_MG,
	WEAPON_COMMAND_USE_GRENADE,
	WEAPON_COMMAND_USE_HEAVY,
	WEAPON_COMMAND_USE_ITEM1,
	WEAPON_COMMAND_USE_ITEM2,
	WEAPON_COMMAND_USE_ITEM3,
	WEAPON_COMMAND_USE_ITEM4,
    WEAPON_COMMAND_USE_PREV_WEAPON,
    WEAPON_COMMAND_USE_NEXT_WEAPON,
    WEAPON_COMMAND_USE_LAST_WEAPON,
	WEAPON_COMMAND_HOLSTER,
    WEAPON_COMMAND_DROP,
} weaponcommand_t;

#define WEAPON_COMMAND_MAX_VER6		15
#define WEAPON_COMMAND_MAX_VER17	31

static unsigned int GetWeaponCommandMask(unsigned int maxCmds) {
	return maxCmds << 7;
}

static unsigned int GetWeaponCommand(unsigned int buttons, unsigned int maxCmds) {
    return (buttons & (maxCmds << 7)) >> 7;
}

#define	MOVE_RUN			120			// if forwardmove or rightmove are >= MOVE_RUN,
										// then BUTTON_WALKING should be set

// usercmd_t is sent to the server each client frame
typedef struct usercmd_s {
	int					serverTime;
	byte				msec;
	short unsigned int	buttons;
	short int			angles[3];
	//int	weapon; // su44: there is no 'weapon' field
	// in MoHAA's usercmd_s - weapon commands are encoded 
	// into buttons bits. See CL_CmdButtons from cl_input.c.
	signed char	forwardmove, rightmove, upmove;
} usercmd_t;

//===================================================================

//
// Animation flags
//
#define  MDL_ANIM_DELTA_DRIVEN   ( 1 << 0 )
#define  MDL_ANIM_DEFAULT_ANGLES ( 1 << 3 )
#define  MDL_ANIM_NO_TIMECHECK   ( 1 << 4 )

// if entityState->solid == SOLID_BMODEL, modelindex is an inline model number
#define	SOLID_BMODEL	0xffffff

// renderfx flags (entityState_t::renderfx)
// su44: moved it here, in MoHAA (and FAKK)
// render flags are set by "renderEffects" event
// and sent to cgame trough entityState_t
// TODO: find out rest of them
#define	RF_THIRD_PERSON			(1<<0)   	// don't draw through eyes, only mirrors (player bodies, chat sprites)
#define	RF_FIRST_PERSON			(1<<1)		// only draw through eyes (view weapon, damage blood blob)
#define	RF_DEPTHHACK			(1<<2)		// hack the z-depth so that view weapons do not clip into walls
#define	RF_VIEWLENSFLARE		(1<<3)		// View dependent lensflare
#define	RF_FRAMELERP			(1<<4)		// interpolate between current and next state
#define	RF_BEAM					(1<<5)		// draw a beam between origin and origin2
#define RF_DONTDRAW				(1<<7)		// don't draw this entity but send it over
#define RF_LENSFLARE			(1<<8)		// add a lens flare to this
#define RF_EXTRALIGHT			(1<<9)		// use good lighting on this entity
#define RF_DETAIL				(1<<10)		// Culls a model based on the distance away from you
#define RF_SHADOW				(1<<11)		// whether or not to draw a shadow
#define	RF_PORTALSURFACE		(1<<12)   	// don't draw, but use to set portal views
#define	RF_SKYORIGIN   			(1<<13)   	// don't draw, but use to set sky portal origin and coordinate system
#define	RF_SKYENTITY   			(1<<14)   	// this entity is only visible through a skyportal
#define	RF_LIGHTOFFSET   		(1<<15)   	// this entity has a light offset
#define	RF_CUSTOMSHADERPASS		(1<<16)		// draw the custom shader on top of the base geometry
#define	RF_MINLIGHT				(1<<17)		// allways have some light (viewmodel, some items)
#define	RF_FULLBRIGHT			(1<<18)		// allways have full lighting
#define RF_LIGHTING_ORIGIN		(1<<19)		// use refEntity->lightingOrigin instead of refEntity->origin
// for lighting.  This allows entities to sink into the floor
// with their origin going solid, and allows all parts of a
// player to get the same lighting
#define	RF_SHADOW_PLANE			(1<<20)		// use refEntity->shadowPlane
#define	RF_WRAP_FRAMES			(1<<21)		// mod the model frames by the maxframes to allow continuous
// animation without needing to know the frame count
//#define RF_PORTALENTITY			(1<<22)		// this entity should only be drawn from a portal
//#define RF_DUALENTITY			(1<<23)		// this entity is drawn both in the portal and outside it.
#define RF_ADDITIVE_DLIGHT		(1<<22)		// this entity has an additive dynamic light
#define RF_LIGHTSTYLE_DLIGHT	(1<<23)		// this entity has a dynamic light that uses a light style
#define RF_SHADOW_PRECISE		(1<<24)		// this entity can have a precise shadow applied to it
#define RF_INVISIBLE			(1<<25)		// This entity is invisible, and only negative lights will light it up
#define RF_VIEWMODEL			(1<<26)		// This entity is invisible, and only negative lights will light it up
#define RF_PRECISESHADOW		(1<<28)		// This entity is invisible, and only negative lights will light it up
#define RF_ALWAYSDRAW			(1<<30)
//
// use this mask when propagating renderfx from one entity to another
//
#define  RF_FLAGS_NOT_INHERITED ( RF_LENSFLARE | RF_VIEWLENSFLARE | RF_BEAM | RF_EXTRALIGHT | RF_SKYORIGIN | RF_SHADOW | RF_SHADOW_PRECISE | RF_SHADOW_PLANE )


//#define RF_ADDICTIVEDYNAMICLIGHT ?????

#define RF_FORCENOLOD		1024

#define BEAM_LIGHTNING_EFFECT   (1<<0)
#define BEAM_USEMODEL           (1<<1)
#define BEAM_PERSIST_EFFECT     (1<<2)
#define BEAM_SPHERE_EFFECT      (1<<3)
#define BEAM_RANDOM_DELAY       (1<<4)
#define BEAM_TOGGLE             (1<<5)
#define BEAM_RANDOM_TOGGLEDELAY (1<<6)
#define BEAM_WAVE_EFFECT        (1<<7)
#define BEAM_USE_NOISE          (1<<8)
#define BEAM_PARENT             (1<<9)
#define BEAM_TILESHADER         (1<<10)
#define BEAM_OFFSET_ENDPOINTS   (1<<11)
#define BEAM_FADE               (1<<12)
#define BEAM_INVERTED           (1<<13)
#define BEAM_INVERTED_FAST      (1<<14)

typedef struct frameInfo_s {
    int index;
    float time;
    float weight;
} frameInfo_t;

typedef enum {
	TR_STATIONARY,
	TR_INTERPOLATE,				// non-parametric, but interpolate between snapshots
	TR_LINEAR,
	TR_LINEAR_STOP,
	TR_SINE,					// value = base + sin( time / duration ) * delta
	TR_GRAVITY,
	TR_LERP
} trType_t;

typedef struct {
	int trTime;
	vec3_t trDelta;
} trajectory_t;

#define NUM_BONE_CONTROLLERS 5

#define NUM_MORPH_CONTROLLERS 10

#define MAX_MODEL_SURFACES   32 // this needs to be the same in qfiles.h for TIKI_MAX_SURFACES

#define  MDL_SURFACE_SKINOFFSET_BIT0  ( 1 << 0 )
#define  MDL_SURFACE_SKINOFFSET_BIT1  ( 1 << 1 )
#define  MDL_SURFACE_NODRAW           ( 1 << 2 )
#define  MDL_SURFACE_SURFACETYPE_BIT0 ( 1 << 3 )
#define  MDL_SURFACE_SURFACETYPE_BIT1 ( 1 << 4 )
#define  MDL_SURFACE_SURFACETYPE_BIT2 ( 1 << 5 )
#define  MDL_SURFACE_CROSSFADE_SKINS  ( 1 << 6 )
#define  MDL_SURFACE_SKIN_NO_DAMAGE   ( 1 << 7 )

#define CROUCH_HEIGHT		36
#define CROUCH_EYE_HEIGHT	48
#define STAND_HEIGHT			72
#define STAND_EYE_HEIGHT	82

#define MAX_FRAMEINFOS			16
#define FRAMEINFO_BLEND			( MAX_FRAMEINFOS >> 1 )

// entityState_t is the information conveyed from the server
// in an update message about entities that the client will
// need to render in some way
// Different eTypes may use the information in different ways
// The messages are delta compressed, so it doesn't really matter if
// the structure size is fairly large

typedef struct entityState_s {
	int		number;			// entity index
	int		eType;			// entityType_t
	int		eFlags;

	trajectory_t pos;

	vec3_t	netorigin;
	vec3_t	origin;
	vec3_t	origin2;

	vec3_t	netangles;
	vec3_t	angles;

	int		constantLight;	// r + (g<<8) + (b<<16) + (intensity<<24)
	int		loopSound;		// constantly loop this sound
	float	loopSoundVolume;
	float	loopSoundMinDist;
	float	loopSoundMaxDist;
	float	loopSoundPitch;
	int		loopSoundFlags;

	int		parent;
	int		tag_num;

	qboolean	attach_use_angles;
	vec3_t		attach_offset;

	int		beam_entnum;

	int		modelindex;
	int		usageIndex;
	int		skinNum;
	int		wasframe;
	frameInfo_t frameInfo[ MAX_FRAMEINFOS ];
	float	actionWeight;

	int		bone_tag[ NUM_BONE_CONTROLLERS ];
	vec3_t	bone_angles[ NUM_BONE_CONTROLLERS ];
	quat_t	bone_quat[ NUM_BONE_CONTROLLERS ]; // not sent over
	byte	surfaces[ 32 ];

	int		clientNum;			// 0 to (MAX_CLIENTS - 1), for players and corpses
	int		groundEntityNum;	// -1 = in air

	int		solid;				// for client side prediction, trap_linkentity sets this properly

	float	scale;
	float	alpha;
	int		renderfx;
	float	shader_data[ 2 ];
	float	shader_time;
	quat_t	quat;
	vec3_t	eyeVector;
} entityState_t;

typedef enum {
	CA_UNINITIALIZED,
	CA_DISCONNECTED, 	// not talking to a server
	CA_AUTHORIZING,		// not used any more, was checking cd key
	CA_CONNECTING,		// sending request packets to the server
	CA_CHALLENGING,		// sending challenge packets to the server
	CA_CONNECTED,		// netchan_t established, getting gamestate
	CA_LOADING,			// only during cgame initialization, never during main loop
	CA_PRIMED,			// got gamestate, waiting for first frame
	CA_ACTIVE,			// game views should be displayed
	CA_CINEMATIC		// playing a cinematic or a static pic, not connected to a server
} connstate_t;

typedef struct qtime_s {
	int		tm_sec;
	int		tm_min;
	int		tm_hour;
	int		tm_mday;
	int		tm_mon;
	int		tm_year;
	int		tm_wday;
	int		tm_yday;
	int		tm_isdst;
} qtime_t;

typedef struct {
	float			start[ 3 ];
	float			end[ 3 ];
	float			color[ 3 ];
	float			alpha;
	float			width;
	unsigned short	factor;
	unsigned short	pattern;
} debugline_t;

typedef struct {
	char	szText[ 64 ];
	float	pos[ 3 ];
	float	scale;
	float	color[ 4 ];
} debugstring_t;

enum hdalign_e
{
    HUD_ALIGN_X_LEFT = 0,
    HUD_ALIGN_X_CENTER = 1,
    HUD_ALIGN_X_RIGHT = 2,
    HUD_ALIGN_Y_TOP = 0,
    HUD_ALIGN_Y_CENTER = 1,
    HUD_ALIGN_Y_BOTTOM = 2,
};

typedef struct hdelement_s {
	qhandle_t		hShader;
	char			shaderName[ MAX_RES_NAME ];

	int				iX;
	int				iY;
	int				iWidth;
	int				iHeight;

	float			vColor[ 4 ];

	int				iHorizontalAlign;
	int				iVerticalAlign;
	qboolean		bVirtualScreen;

	char			string[ MAX_STRING_CHARS ];
	char			fontName[ MAX_RES_NAME ];

	struct fontheader_s *pFont;
} hdelement_t;

typedef struct {
	frameInfo_t	g_VMFrameInfo[MAX_FRAMEINFOS];

	int			g_iLastVMAnim;
	int			g_iLastVMAnimChanged;
	int			g_iCurrentVMAnimSlot;
	int			g_iCurrentVMDuration;

	qboolean	g_bCrossblending;

	int			g_iLastEquippedWeaponStat;
	char		g_szLastActiveItem[ 80 ];
	int			g_iLastAnimPrefixIndex;

	float		g_vCurrentVMPosOffset[ 3 ];
} clientAnim_t;

#define GLYPH_START 0
#define GLYPH_END 255
#define GLYPH_CHARSTART 32
#define GLYPH_CHAREND 127
#define GLYPHS_PER_FONT GLYPH_END - GLYPH_START + 1
typedef struct {
  int height;       // number of scan lines
  int top;          // top of glyph in buffer
  int bottom;       // bottom of glyph in buffer
  int pitch;        // width for copying
  int xSkip;        // x adjustment
  int imageWidth;   // width of actual image
  int imageHeight;  // height of actual image
  float s;          // x offset in image where glyph starts
  float t;          // y offset in image where glyph starts
  float s2;
  float t2;
  qhandle_t glyph;  // handle to the shader with the glyph
  char shaderName[32];
} glyphInfo_t;

typedef struct {
  glyphInfo_t glyphs [GLYPHS_PER_FONT];
  float glyphScale;
  char name[MAX_QPATH];
} fontInfo_t;

#define Square(x) ((x)*(x))

// real time
//=============================================

// server browser sources
// TTimo: AS_MPLAYER is no longer used
#define AS_LOCAL			0
#define AS_MPLAYER			99
#define AS_GLOBAL			2
#define AS_FAVORITES		3
#define AS_GAMESPY			1	// wombat: right now we use AS_GLOBAL for GS, too


// cinematic states
typedef enum {
	FMV_IDLE,
	FMV_PLAY,		// play
	FMV_EOF,		// all other conditions, i.e. stop/EOF/abort
	FMV_ID_BLT,
	FMV_ID_IDLE,
	FMV_LOOPED,
	FMV_ID_WAIT
} e_status;

typedef enum _flag_status {
	FLAG_ATBASE = 0,
	FLAG_TAKEN,			// CTF
	FLAG_TAKEN_RED,		// One Flag CTF
	FLAG_TAKEN_BLUE,	// One Flag CTF
	FLAG_DROPPED
} flagStatus_t;

//
// Radar system
//
typedef struct {
	int time;
	int lastSpeakTime;
	int teamShader;
	float origin[2];
	float axis[2];
} radarClient_t;

typedef struct {
	int clientNum;
	float x;
	float y;
	float yaw;
} radarUnpacked_t;

#define	MAX_GLOBAL_SERVERS				2048
#define	MAX_OTHER_SERVERS					128
#define MAX_PINGREQUESTS					32
#define MAX_SERVERSTATUSREQUESTS	16

#define SAY_ALL		0
#define SAY_TEAM	1
#define SAY_TELL	2

#define CDKEY_LEN 16
#define CDCHKSUM_LEN 2

#define FLOAT_TO_INT( x, fracbits ) ( ( x ) * ( 1 << ( fracbits ) ) )

#define FLOAT_TO_PKT( x, dest, wholebits, fracbits )                            \
   {                                                                            \
   if ( ( x ) >= ( 1 << ( wholebits ) ) )                                       \
         {                                                                         \
      ( dest ) = FLOAT_TO_INT( ( 1 << ( wholebits ) ), ( fracbits ) ) - 1; \
         }                                                                         \
      else if ( ( x ) < 0 )                                                        \
      {                                                                         \
      ( dest ) = 0;                                                             \
      }                                                                         \
      else                                                                         \
      {                                                                         \
      ( dest ) = FLOAT_TO_INT( ( x ), ( fracbits ) );               \
      }                                                                         \
   }

#define SIGNED_FLOAT_TO_PKT( x, dest, wholebits, fracbits )                   \
   {                                                                          \
   float temp_x;                                                              \
   temp_x = ( x ) + ( 1 << ( wholebits ) );                                   \
   if ( temp_x >= ( 1 << ( ( wholebits ) + 1 ) ) )                            \
      ( dest ) = FLOAT_TO_INT( ( 1 << ( ( wholebits ) + 1 ) ), ( fracbits ) ) - 1;    \
      else if ( temp_x < 0 )                                                     \
      (dest) = 0;                                                             \
      else                                                                       \
      ( dest ) = FLOAT_TO_INT( temp_x, ( fracbits ) );                        \
   }

#define INT_TO_FLOAT( x, wholebits, fracbits ) ( ( float )( ( ( float )( x ) ) / ( float )( 1 << ( fracbits ) ) - ( float )( 1 << ( wholebits ) ) ) )
#define UINT_TO_FLOAT( x, fracbits ) ( ( float )( ( ( float )( x ) ) / ( float )( 1 << ( fracbits ) ) ) )

#define TRANSLATION_TO_PKT( x, dest ) FLOAT_TO_PKT( ( x ), ( dest ), 4, 11 )
#define PKT_TO_TRANSLATION( x ) UINT_TO_FLOAT( ( x ), 11 )

#define OFFSET_TO_PKT( x, dest ) FLOAT_TO_PKT( ( x ), ( dest ), 1, 14 )
#define PKT_TO_OFFSET( x ) UINT_TO_FLOAT( ( x ), 14 )

#define ROTATE_TO_PKT( x, dest ) FLOAT_TO_PKT( ( x ), ( dest ), 9, 6 )
#define PKT_TO_ROTATE( x ) UINT_TO_FLOAT( ( x ), 6 )

#define BASE_TO_PKT( x, dest ) SIGNED_FLOAT_TO_PKT( ( x ), ( dest ), 3, 4 )
#define PKT_TO_BASE( x ) INT_TO_FLOAT( ( x ), 3, 4 )

#define AMPLITUDE_TO_PKT( x, dest ) FLOAT_TO_PKT( ( x ), ( dest ), 4, 4 )
#define PKT_TO_AMPLITUDE( x ) UINT_TO_FLOAT( ( x ), 4 )

#define PHASE_TO_PKT( x, dest ) SIGNED_FLOAT_TO_PKT( ( x ), ( dest ), 3, 4 )
#define PKT_TO_PHASE( x ) INT_TO_FLOAT( ( x ), 3, 4 )

#define FREQUENCY_TO_PKT( x, dest ) FLOAT_TO_PKT( ( x ), ( dest ), 4, 4 )
#define PKT_TO_FREQUENCY( x ) UINT_TO_FLOAT( ( x ), 4 )

#define BEAM_PARM_TO_PKT( x, dest ) FLOAT_TO_PKT( ( x ), ( dest ), 4, 4 )
#define PKT_TO_BEAM_PARM( x ) UINT_TO_FLOAT( ( x ), 4 )

#define STUB() printf( "STUB: function %s in %s line %d.\n", __FUNCTION__, __FILE__, __LINE__ )
#define STUB_DESC( description ) printf( "STUB: %s in %s line %d.\n", description, __FILE__, __LINE__ )
#define UNIMPLEMENTED() Com_Printf( "FIXME: (%s) is unimplemented (file %s:%d)\n", __FUNCTION__, __FILE__, __LINE__ )

#if defined(__cplusplus)
}
#endif

#ifdef __cplusplus
#include <chrono>

using qcclock_t = std::chrono::steady_clock;
using qctime_t = qcclock_t::time_point;
using qctimedelta_t = qcclock_t::duration;
#endif
