Jedi Outcast v054
This commit is contained in:
commit
0c7c4bdee2
972 changed files with 686197 additions and 0 deletions
BIN
CODEmp/Debug/botlib.lib
Normal file
BIN
CODEmp/Debug/botlib.lib
Normal file
Binary file not shown.
BIN
CODEmp/Debug/cgamex86.lib
Normal file
BIN
CODEmp/Debug/cgamex86.lib
Normal file
Binary file not shown.
BIN
CODEmp/Debug/jk2mpgamex86.lib
Normal file
BIN
CODEmp/Debug/jk2mpgamex86.lib
Normal file
Binary file not shown.
BIN
CODEmp/Debug/uix86.lib
Normal file
BIN
CODEmp/Debug/uix86.lib
Normal file
Binary file not shown.
BIN
CODEmp/Final/botlib.lib
Normal file
BIN
CODEmp/Final/botlib.lib
Normal file
Binary file not shown.
BIN
CODEmp/Final/cgamex86.lib
Normal file
BIN
CODEmp/Final/cgamex86.lib
Normal file
Binary file not shown.
BIN
CODEmp/Final/jk2mpgamex86.lib
Normal file
BIN
CODEmp/Final/jk2mpgamex86.lib
Normal file
Binary file not shown.
BIN
CODEmp/Final/uix86.lib
Normal file
BIN
CODEmp/Final/uix86.lib
Normal file
Binary file not shown.
BIN
CODEmp/Release/botlib.lib
Normal file
BIN
CODEmp/Release/botlib.lib
Normal file
Binary file not shown.
BIN
CODEmp/Release/cgamex86.lib
Normal file
BIN
CODEmp/Release/cgamex86.lib
Normal file
Binary file not shown.
BIN
CODEmp/Release/jk2mpgamex86.lib
Normal file
BIN
CODEmp/Release/jk2mpgamex86.lib
Normal file
Binary file not shown.
BIN
CODEmp/Release/uix86.lib
Normal file
BIN
CODEmp/Release/uix86.lib
Normal file
Binary file not shown.
156
CODEmp/Splines/Splines.dsp
Normal file
156
CODEmp/Splines/Splines.dsp
Normal file
|
@ -0,0 +1,156 @@
|
|||
# Microsoft Developer Studio Project File - Name="Splines" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=Splines - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "Splines.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "Splines.mak" CFG="Splines - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Splines - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "Splines - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""$/General/code/Splines", GAAAAAAA"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "Splines - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "Splines - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GR /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "Splines - Win32 Release"
|
||||
# Name "Splines - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\math_angles.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\math_matrix.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\math_quaternion.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\math_vector.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\q_parse.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\q_shared.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\splines.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\util_str.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\math_angles.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\math_matrix.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\math_quaternion.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\math_vector.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\q_shared.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\splines.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\util_list.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\util_str.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
129
CODEmp/Splines/math_angles.cpp
Normal file
129
CODEmp/Splines/math_angles.cpp
Normal file
|
@ -0,0 +1,129 @@
|
|||
#include "q_shared.h"
|
||||
#include <float.h>
|
||||
|
||||
angles_t ang_zero( 0.0f, 0.0f, 0.0f );
|
||||
|
||||
void toAngles( mat3_t &src, angles_t &dst ) {
|
||||
double theta;
|
||||
double cp;
|
||||
double sp;
|
||||
|
||||
sp = src[ 0 ][ 2 ];
|
||||
|
||||
// cap off our sin value so that we don't get any NANs
|
||||
if ( sp > 1.0 ) {
|
||||
sp = 1.0;
|
||||
} else if ( sp < -1.0 ) {
|
||||
sp = -1.0;
|
||||
}
|
||||
|
||||
theta = -asin( sp );
|
||||
cp = cos( theta );
|
||||
|
||||
if ( cp > 8192 * FLT_EPSILON ) {
|
||||
dst.pitch = theta * 180 / M_PI;
|
||||
dst.yaw = atan2( src[ 0 ][ 1 ], src[ 0 ][ 0 ] ) * 180 / M_PI;
|
||||
dst.roll = atan2( src[ 1 ][ 2 ], src[ 2 ][ 2 ] ) * 180 / M_PI;
|
||||
} else {
|
||||
dst.pitch = theta * 180 / M_PI;
|
||||
dst.yaw = -atan2( src[ 1 ][ 0 ], src[ 1 ][ 1 ] ) * 180 / M_PI;
|
||||
dst.roll = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void toAngles( quat_t &src, angles_t &dst ) {
|
||||
mat3_t temp;
|
||||
|
||||
toMatrix( src, temp );
|
||||
toAngles( temp, dst );
|
||||
}
|
||||
|
||||
void toAngles( idVec3_t &src, angles_t &dst ) {
|
||||
dst.pitch = src[ 0 ];
|
||||
dst.yaw = src[ 1 ];
|
||||
dst.roll = src[ 2 ];
|
||||
}
|
||||
|
||||
void angles_t::toVectors( idVec3_t *forward, idVec3_t *right, idVec3_t *up ) {
|
||||
float angle;
|
||||
static float sr, sp, sy, cr, cp, cy; // static to help MS compiler fp bugs
|
||||
|
||||
angle = yaw * ( M_PI * 2 / 360 );
|
||||
sy = sin( angle );
|
||||
cy = cos( angle );
|
||||
|
||||
angle = pitch * ( M_PI * 2 / 360 );
|
||||
sp = sin( angle );
|
||||
cp = cos( angle );
|
||||
|
||||
angle = roll * ( M_PI * 2 / 360 );
|
||||
sr = sin( angle );
|
||||
cr = cos( angle );
|
||||
|
||||
if ( forward ) {
|
||||
forward->set( cp * cy, cp * sy, -sp );
|
||||
}
|
||||
|
||||
if ( right ) {
|
||||
right->set( -sr * sp * cy + cr * sy, -sr * sp * sy + -cr * cy, -sr * cp );
|
||||
}
|
||||
|
||||
if ( up ) {
|
||||
up->set( cr * sp * cy + -sr * -sy, cr * sp * sy + -sr * cy, cr * cp );
|
||||
}
|
||||
}
|
||||
|
||||
idVec3_t angles_t::toForward( void ) {
|
||||
float angle;
|
||||
static float sp, sy, cp, cy; // static to help MS compiler fp bugs
|
||||
|
||||
angle = yaw * ( M_PI * 2 / 360 );
|
||||
sy = sin( angle );
|
||||
cy = cos( angle );
|
||||
|
||||
angle = pitch * ( M_PI * 2 / 360 );
|
||||
sp = sin( angle );
|
||||
cp = cos( angle );
|
||||
|
||||
return idVec3_t( cp * cy, cp * sy, -sp );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Normalize360
|
||||
|
||||
returns angles normalized to the range [0 <= angle < 360]
|
||||
=================
|
||||
*/
|
||||
angles_t& angles_t::Normalize360( void ) {
|
||||
pitch = (360.0 / 65536) * ( ( int )( pitch * ( 65536 / 360.0 ) ) & 65535 );
|
||||
yaw = (360.0 / 65536) * ( ( int )( yaw * ( 65536 / 360.0 ) ) & 65535 );
|
||||
roll = (360.0 / 65536) * ( ( int )( roll * ( 65536 / 360.0 ) ) & 65535 );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
Normalize180
|
||||
|
||||
returns angles normalized to the range [-180 < angle <= 180]
|
||||
=================
|
||||
*/
|
||||
angles_t& angles_t::Normalize180( void ) {
|
||||
Normalize360();
|
||||
|
||||
if ( pitch > 180.0 ) {
|
||||
pitch -= 360.0;
|
||||
}
|
||||
|
||||
if ( yaw > 180.0 ) {
|
||||
yaw -= 360.0;
|
||||
}
|
||||
|
||||
if ( roll > 180.0 ) {
|
||||
roll -= 360.0;
|
||||
}
|
||||
return *this;
|
||||
}
|
174
CODEmp/Splines/math_angles.h
Normal file
174
CODEmp/Splines/math_angles.h
Normal file
|
@ -0,0 +1,174 @@
|
|||
#ifndef __MATH_ANGLES_H__
|
||||
#define __MATH_ANGLES_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "math_vector.h"
|
||||
|
||||
class mat3_t;
|
||||
class quat_t;
|
||||
class idVec3_t;
|
||||
typedef idVec3_t &vec3_p;
|
||||
|
||||
class angles_t {
|
||||
public:
|
||||
float pitch;
|
||||
float yaw;
|
||||
float roll;
|
||||
|
||||
angles_t();
|
||||
angles_t( float pitch, float yaw, float roll );
|
||||
angles_t( const idVec3_t &vec );
|
||||
|
||||
friend void toAngles( idVec3_t &src, angles_t &dst );
|
||||
friend void toAngles( quat_t &src, angles_t &dst );
|
||||
friend void toAngles( mat3_t &src, angles_t &dst );
|
||||
|
||||
operator vec3_p();
|
||||
|
||||
float operator[]( int index ) const;
|
||||
float& operator[]( int index );
|
||||
|
||||
void set( float pitch, float yaw, float roll );
|
||||
|
||||
void operator=( angles_t const &a );
|
||||
void operator=( idVec3_t const &a );
|
||||
|
||||
friend angles_t operator+( const angles_t &a, const angles_t &b );
|
||||
angles_t &operator+=( angles_t const &a );
|
||||
angles_t &operator+=( idVec3_t const &a );
|
||||
|
||||
friend angles_t operator-( angles_t &a, angles_t &b );
|
||||
angles_t &operator-=( angles_t &a );
|
||||
|
||||
friend angles_t operator*( const angles_t &a, float b );
|
||||
friend angles_t operator*( float a, const angles_t &b );
|
||||
angles_t &operator*=( float a );
|
||||
|
||||
friend int operator==( angles_t &a, angles_t &b );
|
||||
|
||||
friend int operator!=( angles_t &a, angles_t &b );
|
||||
|
||||
void toVectors( idVec3_t *forward, idVec3_t *right = NULL, idVec3_t *up = NULL );
|
||||
idVec3_t toForward( void );
|
||||
|
||||
angles_t &Zero( void );
|
||||
|
||||
angles_t &Normalize360( void );
|
||||
angles_t &Normalize180( void );
|
||||
};
|
||||
|
||||
extern angles_t ang_zero;
|
||||
|
||||
inline angles_t::angles_t() {}
|
||||
|
||||
inline angles_t::angles_t( float pitch, float yaw, float roll ) {
|
||||
this->pitch = pitch;
|
||||
this->yaw = yaw;
|
||||
this->roll = roll;
|
||||
}
|
||||
|
||||
inline angles_t::angles_t( const idVec3_t &vec ) {
|
||||
this->pitch = vec.x;
|
||||
this->yaw = vec.y;
|
||||
this->roll = vec.z;
|
||||
}
|
||||
|
||||
inline float angles_t::operator[]( int index ) const {
|
||||
assert( ( index >= 0 ) && ( index < 3 ) );
|
||||
return ( &pitch )[ index ];
|
||||
}
|
||||
|
||||
inline float& angles_t::operator[]( int index ) {
|
||||
assert( ( index >= 0 ) && ( index < 3 ) );
|
||||
return ( &pitch )[ index ];
|
||||
}
|
||||
|
||||
inline angles_t::operator vec3_p( void ) {
|
||||
return *( idVec3_t * )&pitch;
|
||||
}
|
||||
|
||||
inline void angles_t::set( float pitch, float yaw, float roll ) {
|
||||
this->pitch = pitch;
|
||||
this->yaw = yaw;
|
||||
this->roll = roll;
|
||||
}
|
||||
|
||||
inline void angles_t::operator=( angles_t const &a ) {
|
||||
pitch = a.pitch;
|
||||
yaw = a.yaw;
|
||||
roll = a.roll;
|
||||
}
|
||||
|
||||
inline void angles_t::operator=( idVec3_t const &a ) {
|
||||
pitch = a[ 0 ];
|
||||
yaw = a[ 1 ];
|
||||
roll = a[ 2 ];
|
||||
}
|
||||
|
||||
inline angles_t operator+( const angles_t &a, const angles_t &b ) {
|
||||
return angles_t( a.pitch + b.pitch, a.yaw + b.yaw, a.roll + b.roll );
|
||||
}
|
||||
|
||||
inline angles_t& angles_t::operator+=( angles_t const &a ) {
|
||||
pitch += a.pitch;
|
||||
yaw += a.yaw;
|
||||
roll += a.roll;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline angles_t& angles_t::operator+=( idVec3_t const &a ) {
|
||||
pitch += a.x;
|
||||
yaw += a.y;
|
||||
roll += a.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline angles_t operator-( angles_t &a, angles_t &b ) {
|
||||
return angles_t( a.pitch - b.pitch, a.yaw - b.yaw, a.roll - b.roll );
|
||||
}
|
||||
|
||||
inline angles_t& angles_t::operator-=( angles_t &a ) {
|
||||
pitch -= a.pitch;
|
||||
yaw -= a.yaw;
|
||||
roll -= a.roll;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline angles_t operator*( const angles_t &a, float b ) {
|
||||
return angles_t( a.pitch * b, a.yaw * b, a.roll * b );
|
||||
}
|
||||
|
||||
inline angles_t operator*( float a, const angles_t &b ) {
|
||||
return angles_t( a * b.pitch, a * b.yaw, a * b.roll );
|
||||
}
|
||||
|
||||
inline angles_t& angles_t::operator*=( float a ) {
|
||||
pitch *= a;
|
||||
yaw *= a;
|
||||
roll *= a;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline int operator==( angles_t &a, angles_t &b ) {
|
||||
return ( ( a.pitch == b.pitch ) && ( a.yaw == b.yaw ) && ( a.roll == b.roll ) );
|
||||
}
|
||||
|
||||
inline int operator!=( angles_t &a, angles_t &b ) {
|
||||
return ( ( a.pitch != b.pitch ) || ( a.yaw != b.yaw ) || ( a.roll != b.roll ) );
|
||||
}
|
||||
|
||||
inline angles_t& angles_t::Zero( void ) {
|
||||
pitch = 0.0f;
|
||||
yaw = 0.0f;
|
||||
roll = 0.0f;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif /* !__MATH_ANGLES_H__ */
|
113
CODEmp/Splines/math_matrix.cpp
Normal file
113
CODEmp/Splines/math_matrix.cpp
Normal file
|
@ -0,0 +1,113 @@
|
|||
#include "q_shared.h"
|
||||
|
||||
mat3_t mat3_default( idVec3_t( 1, 0, 0 ), idVec3_t( 0, 1, 0 ), idVec3_t( 0, 0, 1 ) );
|
||||
|
||||
void toMatrix( quat_t const &src, mat3_t &dst ) {
|
||||
float wx, wy, wz;
|
||||
float xx, yy, yz;
|
||||
float xy, xz, zz;
|
||||
float x2, y2, z2;
|
||||
|
||||
x2 = src.x + src.x;
|
||||
y2 = src.y + src.y;
|
||||
z2 = src.z + src.z;
|
||||
|
||||
xx = src.x * x2;
|
||||
xy = src.x * y2;
|
||||
xz = src.x * z2;
|
||||
|
||||
yy = src.y * y2;
|
||||
yz = src.y * z2;
|
||||
zz = src.z * z2;
|
||||
|
||||
wx = src.w * x2;
|
||||
wy = src.w * y2;
|
||||
wz = src.w * z2;
|
||||
|
||||
dst[ 0 ][ 0 ] = 1.0f - ( yy + zz );
|
||||
dst[ 0 ][ 1 ] = xy - wz;
|
||||
dst[ 0 ][ 2 ] = xz + wy;
|
||||
|
||||
dst[ 1 ][ 0 ] = xy + wz;
|
||||
dst[ 1 ][ 1 ] = 1.0f - ( xx + zz );
|
||||
dst[ 1 ][ 2 ] = yz - wx;
|
||||
|
||||
dst[ 2 ][ 0 ] = xz - wy;
|
||||
dst[ 2 ][ 1 ] = yz + wx;
|
||||
dst[ 2 ][ 2 ] = 1.0f - ( xx + yy );
|
||||
}
|
||||
|
||||
void toMatrix( angles_t const &src, mat3_t &dst ) {
|
||||
float angle;
|
||||
static float sr, sp, sy, cr, cp, cy; // static to help MS compiler fp bugs
|
||||
|
||||
angle = src.yaw * ( M_PI * 2.0f / 360.0f );
|
||||
sy = sin( angle );
|
||||
cy = cos( angle );
|
||||
|
||||
angle = src.pitch * ( M_PI * 2.0f / 360.0f );
|
||||
sp = sin( angle );
|
||||
cp = cos( angle );
|
||||
|
||||
angle = src.roll * ( M_PI * 2.0f / 360.0f );
|
||||
sr = sin( angle );
|
||||
cr = cos( angle );
|
||||
|
||||
dst[ 0 ].set( cp * cy, cp * sy, -sp );
|
||||
dst[ 1 ].set( sr * sp * cy + cr * -sy, sr * sp * sy + cr * cy, sr * cp );
|
||||
dst[ 2 ].set( cr * sp * cy + -sr * -sy, cr * sp * sy + -sr * cy, cr * cp );
|
||||
}
|
||||
|
||||
void toMatrix( idVec3_t const &src, mat3_t &dst ) {
|
||||
angles_t sup = src;
|
||||
toMatrix(sup, dst);
|
||||
}
|
||||
|
||||
void mat3_t::ProjectVector( const idVec3_t &src, idVec3_t &dst ) const {
|
||||
dst.x = src * mat[ 0 ];
|
||||
dst.y = src * mat[ 1 ];
|
||||
dst.z = src * mat[ 2 ];
|
||||
}
|
||||
|
||||
void mat3_t::UnprojectVector( const idVec3_t &src, idVec3_t &dst ) const {
|
||||
dst = mat[ 0 ] * src.x + mat[ 1 ] * src.y + mat[ 2 ] * src.z;
|
||||
}
|
||||
|
||||
void mat3_t::Transpose( mat3_t &matrix ) {
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for( i = 0; i < 3; i++ ) {
|
||||
for( j = 0; j < 3; j++ ) {
|
||||
matrix[ i ][ j ] = mat[ j ][ i ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mat3_t::Transpose( void ) {
|
||||
float temp;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for( i = 0; i < 3; i++ ) {
|
||||
for( j = i + 1; j < 3; j++ ) {
|
||||
temp = mat[ i ][ j ];
|
||||
mat[ i ][ j ] = mat[ j ][ i ];
|
||||
mat[ j ][ i ] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mat3_t mat3_t::Inverse( void ) const {
|
||||
mat3_t inv( *this );
|
||||
|
||||
inv.Transpose();
|
||||
|
||||
return inv;
|
||||
}
|
||||
|
||||
void mat3_t::Clear( void ) {
|
||||
mat[0].set( 1, 0, 0 );
|
||||
mat[1].set( 0, 1, 0 );
|
||||
mat[2].set( 0, 0, 1 );
|
||||
}
|
202
CODEmp/Splines/math_matrix.h
Normal file
202
CODEmp/Splines/math_matrix.h
Normal file
|
@ -0,0 +1,202 @@
|
|||
#ifndef __MATH_MATRIX_H__
|
||||
#define __MATH_MATRIX_H__
|
||||
|
||||
#include <string.h>
|
||||
#include "math_vector.h"
|
||||
|
||||
#ifndef ID_INLINE
|
||||
#ifdef _WIN32
|
||||
#define ID_INLINE __inline
|
||||
#else
|
||||
#define ID_INLINE inline
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class quat_t;
|
||||
class angles_t;
|
||||
|
||||
class mat3_t {
|
||||
public:
|
||||
idVec3_t mat[ 3 ];
|
||||
|
||||
mat3_t();
|
||||
mat3_t( float src[ 3 ][ 3 ] );
|
||||
mat3_t( idVec3_t const &x, idVec3_t const &y, idVec3_t const &z );
|
||||
mat3_t( const float xx, const float xy, const float xz, const float yx, const float yy, const float yz, const float zx, const float zy, const float zz );
|
||||
|
||||
friend void toMatrix( quat_t const &src, mat3_t &dst );
|
||||
friend void toMatrix( angles_t const &src, mat3_t &dst );
|
||||
friend void toMatrix( idVec3_t const &src, mat3_t &dst );
|
||||
|
||||
idVec3_t operator[]( int index ) const;
|
||||
idVec3_t &operator[]( int index );
|
||||
|
||||
idVec3_t operator*( const idVec3_t &vec ) const;
|
||||
mat3_t operator*( const mat3_t &a ) const;
|
||||
mat3_t operator*( float a ) const;
|
||||
mat3_t operator+( mat3_t const &a ) const;
|
||||
mat3_t operator-( mat3_t const &a ) const;
|
||||
|
||||
friend idVec3_t operator*( const idVec3_t &vec, const mat3_t &mat );
|
||||
friend mat3_t operator*( float a, mat3_t const &b );
|
||||
|
||||
mat3_t &operator*=( float a );
|
||||
mat3_t &operator+=( mat3_t const &a );
|
||||
mat3_t &operator-=( mat3_t const &a );
|
||||
|
||||
void Clear( void );
|
||||
|
||||
void ProjectVector( const idVec3_t &src, idVec3_t &dst ) const;
|
||||
void UnprojectVector( const idVec3_t &src, idVec3_t &dst ) const;
|
||||
|
||||
void OrthoNormalize( void );
|
||||
void Transpose( mat3_t &matrix );
|
||||
void Transpose( void );
|
||||
mat3_t Inverse( void ) const;
|
||||
void Identity( void );
|
||||
|
||||
friend void InverseMultiply( const mat3_t &inv, const mat3_t &b, mat3_t &dst );
|
||||
friend mat3_t SkewSymmetric( idVec3_t const &src );
|
||||
};
|
||||
|
||||
ID_INLINE mat3_t::mat3_t() {
|
||||
}
|
||||
|
||||
ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) {
|
||||
memcpy( mat, src, sizeof( src ) );
|
||||
}
|
||||
|
||||
ID_INLINE mat3_t::mat3_t( idVec3_t const &x, idVec3_t const &y, idVec3_t const &z ) {
|
||||
mat[ 0 ].x = x.x; mat[ 0 ].y = x.y; mat[ 0 ].z = x.z;
|
||||
mat[ 1 ].x = y.x; mat[ 1 ].y = y.y; mat[ 1 ].z = y.z;
|
||||
mat[ 2 ].x = z.x; mat[ 2 ].y = z.y; mat[ 2 ].z = z.z;
|
||||
}
|
||||
|
||||
ID_INLINE mat3_t::mat3_t( const float xx, const float xy, const float xz, const float yx, const float yy, const float yz, const float zx, const float zy, const float zz ) {
|
||||
mat[ 0 ].x = xx; mat[ 0 ].y = xy; mat[ 0 ].z = xz;
|
||||
mat[ 1 ].x = yx; mat[ 1 ].y = yy; mat[ 1 ].z = yz;
|
||||
mat[ 2 ].x = zx; mat[ 2 ].y = zy; mat[ 2 ].z = zz;
|
||||
}
|
||||
|
||||
ID_INLINE idVec3_t mat3_t::operator[]( int index ) const {
|
||||
assert( ( index >= 0 ) && ( index < 3 ) );
|
||||
return mat[ index ];
|
||||
}
|
||||
|
||||
ID_INLINE idVec3_t& mat3_t::operator[]( int index ) {
|
||||
assert( ( index >= 0 ) && ( index < 3 ) );
|
||||
return mat[ index ];
|
||||
}
|
||||
|
||||
ID_INLINE idVec3_t mat3_t::operator*( const idVec3_t &vec ) const {
|
||||
return idVec3_t(
|
||||
mat[ 0 ].x * vec.x + mat[ 1 ].x * vec.y + mat[ 2 ].x * vec.z,
|
||||
mat[ 0 ].y * vec.x + mat[ 1 ].y * vec.y + mat[ 2 ].y * vec.z,
|
||||
mat[ 0 ].z * vec.x + mat[ 1 ].z * vec.y + mat[ 2 ].z * vec.z );
|
||||
}
|
||||
|
||||
ID_INLINE mat3_t mat3_t::operator*( const mat3_t &a ) const {
|
||||
return mat3_t(
|
||||
mat[0].x * a[0].x + mat[0].y * a[1].x + mat[0].z * a[2].x,
|
||||
mat[0].x * a[0].y + mat[0].y * a[1].y + mat[0].z * a[2].y,
|
||||
mat[0].x * a[0].z + mat[0].y * a[1].z + mat[0].z * a[2].z,
|
||||
mat[1].x * a[0].x + mat[1].y * a[1].x + mat[1].z * a[2].x,
|
||||
mat[1].x * a[0].y + mat[1].y * a[1].y + mat[1].z * a[2].y,
|
||||
mat[1].x * a[0].z + mat[1].y * a[1].z + mat[1].z * a[2].z,
|
||||
mat[2].x * a[0].x + mat[2].y * a[1].x + mat[2].z * a[2].x,
|
||||
mat[2].x * a[0].y + mat[2].y * a[1].y + mat[2].z * a[2].y,
|
||||
mat[2].x * a[0].z + mat[2].y * a[1].z + mat[2].z * a[2].z );
|
||||
}
|
||||
|
||||
ID_INLINE mat3_t mat3_t::operator*( float a ) const {
|
||||
return mat3_t(
|
||||
mat[0].x * a, mat[0].y * a, mat[0].z * a,
|
||||
mat[1].x * a, mat[1].y * a, mat[1].z * a,
|
||||
mat[2].x * a, mat[2].y * a, mat[2].z * a );
|
||||
}
|
||||
|
||||
ID_INLINE mat3_t mat3_t::operator+( mat3_t const &a ) const {
|
||||
return mat3_t(
|
||||
mat[0].x + a[0].x, mat[0].y + a[0].y, mat[0].z + a[0].z,
|
||||
mat[1].x + a[1].x, mat[1].y + a[1].y, mat[1].z + a[1].z,
|
||||
mat[2].x + a[2].x, mat[2].y + a[2].y, mat[2].z + a[2].z );
|
||||
}
|
||||
|
||||
ID_INLINE mat3_t mat3_t::operator-( mat3_t const &a ) const {
|
||||
return mat3_t(
|
||||
mat[0].x - a[0].x, mat[0].y - a[0].y, mat[0].z - a[0].z,
|
||||
mat[1].x - a[1].x, mat[1].y - a[1].y, mat[1].z - a[1].z,
|
||||
mat[2].x - a[2].x, mat[2].y - a[2].y, mat[2].z - a[2].z );
|
||||
}
|
||||
|
||||
ID_INLINE idVec3_t operator*( const idVec3_t &vec, const mat3_t &mat ) {
|
||||
return idVec3_t(
|
||||
mat[ 0 ].x * vec.x + mat[ 1 ].x * vec.y + mat[ 2 ].x * vec.z,
|
||||
mat[ 0 ].y * vec.x + mat[ 1 ].y * vec.y + mat[ 2 ].y * vec.z,
|
||||
mat[ 0 ].z * vec.x + mat[ 1 ].z * vec.y + mat[ 2 ].z * vec.z );
|
||||
}
|
||||
|
||||
ID_INLINE mat3_t operator*( float a, mat3_t const &b ) {
|
||||
return mat3_t(
|
||||
b[0].x * a, b[0].y * a, b[0].z * a,
|
||||
b[1].x * a, b[1].y * a, b[1].z * a,
|
||||
b[2].x * a, b[2].y * a, b[2].z * a );
|
||||
}
|
||||
|
||||
ID_INLINE mat3_t &mat3_t::operator*=( float a ) {
|
||||
mat[0].x *= a; mat[0].y *= a; mat[0].z *= a;
|
||||
mat[1].x *= a; mat[1].y *= a; mat[1].z *= a;
|
||||
mat[2].x *= a; mat[2].y *= a; mat[2].z *= a;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE mat3_t &mat3_t::operator+=( mat3_t const &a ) {
|
||||
mat[0].x += a[0].x; mat[0].y += a[0].y; mat[0].z += a[0].z;
|
||||
mat[1].x += a[1].x; mat[1].y += a[1].y; mat[1].z += a[1].z;
|
||||
mat[2].x += a[2].x; mat[2].y += a[2].y; mat[2].z += a[2].z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE mat3_t &mat3_t::operator-=( mat3_t const &a ) {
|
||||
mat[0].x -= a[0].x; mat[0].y -= a[0].y; mat[0].z -= a[0].z;
|
||||
mat[1].x -= a[1].x; mat[1].y -= a[1].y; mat[1].z -= a[1].z;
|
||||
mat[2].x -= a[2].x; mat[2].y -= a[2].y; mat[2].z -= a[2].z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE void mat3_t::OrthoNormalize( void ) {
|
||||
mat[ 0 ].Normalize();
|
||||
mat[ 2 ].Cross( mat[ 0 ], mat[ 1 ] );
|
||||
mat[ 2 ].Normalize();
|
||||
mat[ 1 ].Cross( mat[ 2 ], mat[ 0 ] );
|
||||
mat[ 1 ].Normalize();
|
||||
}
|
||||
|
||||
ID_INLINE void mat3_t::Identity( void ) {
|
||||
mat[ 0 ].x = 1.f; mat[ 0 ].y = 0.f; mat[ 0 ].z = 0.f;
|
||||
mat[ 1 ].x = 0.f; mat[ 1 ].y = 1.f; mat[ 1 ].z = 0.f;
|
||||
mat[ 2 ].x = 0.f; mat[ 2 ].y = 0.f; mat[ 2 ].z = 1.f;
|
||||
}
|
||||
|
||||
ID_INLINE void InverseMultiply( const mat3_t &inv, const mat3_t &b, mat3_t &dst ) {
|
||||
dst[0].x = inv[0].x * b[0].x + inv[1].x * b[1].x + inv[2].x * b[2].x;
|
||||
dst[0].y = inv[0].x * b[0].y + inv[1].x * b[1].y + inv[2].x * b[2].y;
|
||||
dst[0].z = inv[0].x * b[0].z + inv[1].x * b[1].z + inv[2].x * b[2].z;
|
||||
dst[1].x = inv[0].y * b[0].x + inv[1].y * b[1].x + inv[2].y * b[2].x;
|
||||
dst[1].y = inv[0].y * b[0].y + inv[1].y * b[1].y + inv[2].y * b[2].y;
|
||||
dst[1].z = inv[0].y * b[0].z + inv[1].y * b[1].z + inv[2].y * b[2].z;
|
||||
dst[2].x = inv[0].z * b[0].x + inv[1].z * b[1].x + inv[2].z * b[2].x;
|
||||
dst[2].y = inv[0].z * b[0].y + inv[1].z * b[1].y + inv[2].z * b[2].y;
|
||||
dst[2].z = inv[0].z * b[0].z + inv[1].z * b[1].z + inv[2].z * b[2].z;
|
||||
}
|
||||
|
||||
ID_INLINE mat3_t SkewSymmetric( idVec3_t const &src ) {
|
||||
return mat3_t( 0.0f, -src.z, src.y, src.z, 0.0f, -src.x, -src.y, src.x, 0.0f );
|
||||
}
|
||||
|
||||
extern mat3_t mat3_default;
|
||||
|
||||
#endif /* !__MATH_MATRIX_H__ */
|
57
CODEmp/Splines/math_quaternion.cpp
Normal file
57
CODEmp/Splines/math_quaternion.cpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
#include "math_quaternion.h"
|
||||
#include "math_matrix.h"
|
||||
|
||||
void toQuat( idVec3_t &src, quat_t &dst ) {
|
||||
dst.x = src.x;
|
||||
dst.y = src.y;
|
||||
dst.z = src.z;
|
||||
dst.w = 0.0f;
|
||||
}
|
||||
|
||||
void toQuat( angles_t &src, quat_t &dst ) {
|
||||
mat3_t temp;
|
||||
|
||||
toMatrix( src, temp );
|
||||
toQuat( temp, dst );
|
||||
}
|
||||
|
||||
void toQuat( mat3_t &src, quat_t &dst ) {
|
||||
float trace;
|
||||
float s;
|
||||
int i;
|
||||
int j;
|
||||
int k;
|
||||
|
||||
static int next[ 3 ] = { 1, 2, 0 };
|
||||
|
||||
trace = src[ 0 ][ 0 ] + src[ 1 ][ 1 ] + src[ 2 ][ 2 ];
|
||||
if ( trace > 0.0f ) {
|
||||
s = ( float )sqrt( trace + 1.0f );
|
||||
dst.w = s * 0.5f;
|
||||
s = 0.5f / s;
|
||||
|
||||
dst.x = ( src[ 2 ][ 1 ] - src[ 1 ][ 2 ] ) * s;
|
||||
dst.y = ( src[ 0 ][ 2 ] - src[ 2 ][ 0 ] ) * s;
|
||||
dst.z = ( src[ 1 ][ 0 ] - src[ 0 ][ 1 ] ) * s;
|
||||
} else {
|
||||
i = 0;
|
||||
if ( src[ 1 ][ 1 ] > src[ 0 ][ 0 ] ) {
|
||||
i = 1;
|
||||
}
|
||||
if ( src[ 2 ][ 2 ] > src[ i ][ i ] ) {
|
||||
i = 2;
|
||||
}
|
||||
|
||||
j = next[ i ];
|
||||
k = next[ j ];
|
||||
|
||||
s = ( float )sqrt( ( src[ i ][ i ] - ( src[ j ][ j ] + src[ k ][ k ] ) ) + 1.0f );
|
||||
dst[ i ] = s * 0.5f;
|
||||
|
||||
s = 0.5f / s;
|
||||
|
||||
dst.w = ( src[ k ][ j ] - src[ j ][ k ] ) * s;
|
||||
dst[ j ] = ( src[ j ][ i ] + src[ i ][ j ] ) * s;
|
||||
dst[ k ] = ( src[ k ][ i ] + src[ i ][ k ] ) * s;
|
||||
}
|
||||
}
|
169
CODEmp/Splines/math_quaternion.h
Normal file
169
CODEmp/Splines/math_quaternion.h
Normal file
|
@ -0,0 +1,169 @@
|
|||
#ifndef __MATH_QUATERNION_H__
|
||||
#define __MATH_QUATERNION_H__
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
class idVec3_t;
|
||||
class angles_t;
|
||||
class mat3_t;
|
||||
|
||||
class quat_t {
|
||||
public:
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
|
||||
quat_t();
|
||||
quat_t( float x, float y, float z, float w );
|
||||
|
||||
friend void toQuat( idVec3_t &src, quat_t &dst );
|
||||
friend void toQuat( angles_t &src, quat_t &dst );
|
||||
friend void toQuat( mat3_t &src, quat_t &dst );
|
||||
|
||||
float *vec4( void );
|
||||
|
||||
float operator[]( int index ) const;
|
||||
float &operator[]( int index );
|
||||
|
||||
void set( float x, float y, float z, float w );
|
||||
|
||||
void operator=( quat_t a );
|
||||
|
||||
friend quat_t operator+( quat_t a, quat_t b );
|
||||
quat_t &operator+=( quat_t a );
|
||||
|
||||
friend quat_t operator-( quat_t a, quat_t b );
|
||||
quat_t &operator-=( quat_t a );
|
||||
|
||||
friend quat_t operator*( quat_t a, float b );
|
||||
friend quat_t operator*( float a, quat_t b );
|
||||
quat_t &operator*=( float a );
|
||||
|
||||
friend int operator==( quat_t a, quat_t b );
|
||||
friend int operator!=( quat_t a, quat_t b );
|
||||
|
||||
float Length( void );
|
||||
quat_t &Normalize( void );
|
||||
|
||||
quat_t operator-();
|
||||
};
|
||||
|
||||
inline quat_t::quat_t() {
|
||||
}
|
||||
|
||||
inline quat_t::quat_t( float x, float y, float z, float w ) {
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
this->w = w;
|
||||
}
|
||||
|
||||
inline float *quat_t::vec4( void ) {
|
||||
return &x;
|
||||
}
|
||||
|
||||
inline float quat_t::operator[]( int index ) const {
|
||||
assert( ( index >= 0 ) && ( index < 4 ) );
|
||||
return ( &x )[ index ];
|
||||
}
|
||||
|
||||
inline float& quat_t::operator[]( int index ) {
|
||||
assert( ( index >= 0 ) && ( index < 4 ) );
|
||||
return ( &x )[ index ];
|
||||
}
|
||||
|
||||
inline void quat_t::set( float x, float y, float z, float w ) {
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
this->w = w;
|
||||
}
|
||||
|
||||
inline void quat_t::operator=( quat_t a ) {
|
||||
x = a.x;
|
||||
y = a.y;
|
||||
z = a.z;
|
||||
w = a.w;
|
||||
}
|
||||
|
||||
inline quat_t operator+( quat_t a, quat_t b ) {
|
||||
return quat_t( a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w );
|
||||
}
|
||||
|
||||
inline quat_t& quat_t::operator+=( quat_t a ) {
|
||||
x += a.x;
|
||||
y += a.y;
|
||||
z += a.z;
|
||||
w += a.w;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline quat_t operator-( quat_t a, quat_t b ) {
|
||||
return quat_t( a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w );
|
||||
}
|
||||
|
||||
inline quat_t& quat_t::operator-=( quat_t a ) {
|
||||
x -= a.x;
|
||||
y -= a.y;
|
||||
z -= a.z;
|
||||
w -= a.w;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline quat_t operator*( quat_t a, float b ) {
|
||||
return quat_t( a.x * b, a.y * b, a.z * b, a.w * b );
|
||||
}
|
||||
|
||||
inline quat_t operator*( float a, quat_t b ) {
|
||||
return b * a;
|
||||
}
|
||||
|
||||
inline quat_t& quat_t::operator*=( float a ) {
|
||||
x *= a;
|
||||
y *= a;
|
||||
z *= a;
|
||||
w *= a;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline int operator==( quat_t a, quat_t b ) {
|
||||
return ( ( a.x == b.x ) && ( a.y == b.y ) && ( a.z == b.z ) && ( a.w == b.w ) );
|
||||
}
|
||||
|
||||
inline int operator!=( quat_t a, quat_t b ) {
|
||||
return ( ( a.x != b.x ) || ( a.y != b.y ) || ( a.z != b.z ) && ( a.w != b.w ) );
|
||||
}
|
||||
|
||||
inline float quat_t::Length( void ) {
|
||||
float length;
|
||||
|
||||
length = x * x + y * y + z * z + w * w;
|
||||
return ( float )sqrt( length );
|
||||
}
|
||||
|
||||
inline quat_t& quat_t::Normalize( void ) {
|
||||
float length;
|
||||
float ilength;
|
||||
|
||||
length = this->Length();
|
||||
if ( length ) {
|
||||
ilength = 1 / length;
|
||||
x *= ilength;
|
||||
y *= ilength;
|
||||
z *= ilength;
|
||||
w *= ilength;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline quat_t quat_t::operator-() {
|
||||
return quat_t( -x, -y, -z, -w );
|
||||
}
|
||||
|
||||
#endif /* !__MATH_QUATERNION_H__ */
|
123
CODEmp/Splines/math_vector.cpp
Normal file
123
CODEmp/Splines/math_vector.cpp
Normal file
|
@ -0,0 +1,123 @@
|
|||
//#include "../game/q_shared.h"
|
||||
#include "math_vector.h"
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
|
||||
|
||||
#define LERP_DELTA 1e-6
|
||||
|
||||
idVec3_t vec_zero( 0.0f, 0.0f, 0.0f );
|
||||
|
||||
Bounds boundsZero;
|
||||
|
||||
float idVec3_t::toYaw( void ) {
|
||||
float yaw;
|
||||
|
||||
if ( ( y == 0 ) && ( x == 0 ) ) {
|
||||
yaw = 0;
|
||||
} else {
|
||||
yaw = atan2( y, x ) * 180 / M_PI;
|
||||
if ( yaw < 0 ) {
|
||||
yaw += 360;
|
||||
}
|
||||
}
|
||||
|
||||
return yaw;
|
||||
}
|
||||
|
||||
float idVec3_t::toPitch( void ) {
|
||||
float forward;
|
||||
float pitch;
|
||||
|
||||
if ( ( x == 0 ) && ( y == 0 ) ) {
|
||||
if ( z > 0 ) {
|
||||
pitch = 90;
|
||||
} else {
|
||||
pitch = 270;
|
||||
}
|
||||
} else {
|
||||
forward = ( float )idSqrt( x * x + y * y );
|
||||
pitch = atan2( z, forward ) * 180 / M_PI;
|
||||
if ( pitch < 0 ) {
|
||||
pitch += 360;
|
||||
}
|
||||
}
|
||||
|
||||
return pitch;
|
||||
}
|
||||
|
||||
/*
|
||||
angles_t idVec3_t::toAngles( void ) {
|
||||
float forward;
|
||||
float yaw;
|
||||
float pitch;
|
||||
|
||||
if ( ( x == 0 ) && ( y == 0 ) ) {
|
||||
yaw = 0;
|
||||
if ( z > 0 ) {
|
||||
pitch = 90;
|
||||
} else {
|
||||
pitch = 270;
|
||||
}
|
||||
} else {
|
||||
yaw = atan2( y, x ) * 180 / M_PI;
|
||||
if ( yaw < 0 ) {
|
||||
yaw += 360;
|
||||
}
|
||||
|
||||
forward = ( float )idSqrt( x * x + y * y );
|
||||
pitch = atan2( z, forward ) * 180 / M_PI;
|
||||
if ( pitch < 0 ) {
|
||||
pitch += 360;
|
||||
}
|
||||
}
|
||||
|
||||
return angles_t( -pitch, yaw, 0 );
|
||||
}
|
||||
*/
|
||||
|
||||
idVec3_t LerpVector( idVec3_t &w1, idVec3_t &w2, const float t ) {
|
||||
float omega, cosom, sinom, scale0, scale1;
|
||||
|
||||
cosom = w1 * w2;
|
||||
if ( ( 1.0 - cosom ) > LERP_DELTA ) {
|
||||
omega = acos( cosom );
|
||||
sinom = sin( omega );
|
||||
scale0 = sin( ( 1.0 - t ) * omega ) / sinom;
|
||||
scale1 = sin( t * omega ) / sinom;
|
||||
} else {
|
||||
scale0 = 1.0 - t;
|
||||
scale1 = t;
|
||||
}
|
||||
|
||||
return ( w1 * scale0 + w2 * scale1 );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
idVec3_t::string
|
||||
|
||||
This is just a convenience function
|
||||
for printing vectors
|
||||
=============
|
||||
*/
|
||||
char *idVec3_t::string( void ) {
|
||||
static int index = 0;
|
||||
static char str[ 8 ][ 36 ];
|
||||
char *s;
|
||||
|
||||
// use an array so that multiple toString's won't collide
|
||||
s = str[ index ];
|
||||
index = (index + 1)&7;
|
||||
|
||||
sprintf( s, "%.2f %.2f %.2f", x, y, z );
|
||||
|
||||
return s;
|
||||
}
|
553
CODEmp/Splines/math_vector.h
Normal file
553
CODEmp/Splines/math_vector.h
Normal file
|
@ -0,0 +1,553 @@
|
|||
#ifndef __MATH_VECTOR_H__
|
||||
#define __MATH_VECTOR_H__
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma warning(disable : 4244)
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
//#define DotProduct(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
|
||||
//#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 VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
|
||||
//#define VectorCopy(a,b) ((b).x=(a).x,(b).y=(a).y,(b).z=(a).z])
|
||||
|
||||
//#define VectorScale(v, s, o) ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(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 CrossProduct(a,b,c) ((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
|
||||
|
||||
#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 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];}
|
||||
|
||||
|
||||
//#include "util_heap.h"
|
||||
|
||||
#ifndef EQUAL_EPSILON
|
||||
#define EQUAL_EPSILON 0.001
|
||||
#endif
|
||||
|
||||
float Q_fabs( float f );
|
||||
|
||||
#ifndef ID_INLINE
|
||||
#ifdef _WIN32
|
||||
#define ID_INLINE __inline
|
||||
#else
|
||||
#define ID_INLINE inline
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// if this is defined, vec3 will take four elements, which may allow
|
||||
// easier SIMD optimizations
|
||||
//#define FAT_VEC3
|
||||
//#ifdef __ppc__
|
||||
//#pragma align(16)
|
||||
//#endif
|
||||
|
||||
class angles_t;
|
||||
#ifdef __ppc__
|
||||
// Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction,
|
||||
// runs *much* faster than calling sqrt(). We'll use two Newton-Raphson
|
||||
// refinement steps to get bunch more precision in the 1/sqrt() value for very little cost.
|
||||
// We'll then multiply 1/sqrt times the original value to get the sqrt.
|
||||
// This is about 12.4 times faster than sqrt() and according to my testing (not exhaustive)
|
||||
// it returns fairly accurate results (error below 1.0e-5 up to 100000.0 in 0.1 increments).
|
||||
|
||||
static inline float idSqrt(float x) {
|
||||
const float half = 0.5;
|
||||
const float one = 1.0;
|
||||
float B, y0, y1;
|
||||
|
||||
// This'll NaN if it hits frsqrte. Handle both +0.0 and -0.0
|
||||
if (fabs(x) == 0.0)
|
||||
return x;
|
||||
B = x;
|
||||
|
||||
#ifdef __GNUC__
|
||||
asm("frsqrte %0,%1" : "=f" (y0) : "f" (B));
|
||||
#else
|
||||
y0 = __frsqrte(B);
|
||||
#endif
|
||||
/* First refinement step */
|
||||
|
||||
y1 = y0 + half*y0*(one - B*y0*y0);
|
||||
|
||||
/* Second refinement step -- copy the output of the last step to the input of this step */
|
||||
|
||||
y0 = y1;
|
||||
y1 = y0 + half*y0*(one - B*y0*y0);
|
||||
|
||||
/* Get sqrt(x) from x * 1/sqrt(x) */
|
||||
return x * y1;
|
||||
}
|
||||
#else
|
||||
static inline double idSqrt(double x) {
|
||||
return sqrt(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//class idVec3_t : public idHeap<idVec3_t> {
|
||||
class idVec3_t {
|
||||
public:
|
||||
#ifndef FAT_VEC3
|
||||
float x,y,z;
|
||||
#else
|
||||
float x,y,z,dist;
|
||||
#endif
|
||||
|
||||
#ifndef FAT_VEC3
|
||||
idVec3_t() {};
|
||||
#else
|
||||
idVec3_t() {dist = 0.0f;};
|
||||
#endif
|
||||
idVec3_t( const float x, const float y, const float z );
|
||||
|
||||
operator float *();
|
||||
|
||||
float operator[]( const int index ) const;
|
||||
float &operator[]( const int index );
|
||||
|
||||
void set( const float x, const float y, const float z );
|
||||
|
||||
idVec3_t operator-() const;
|
||||
|
||||
idVec3_t &operator=( const idVec3_t &a );
|
||||
|
||||
float operator*( const idVec3_t &a ) const;
|
||||
idVec3_t operator*( const float a ) const;
|
||||
friend idVec3_t operator*( float a, idVec3_t b );
|
||||
|
||||
idVec3_t operator+( const idVec3_t &a ) const;
|
||||
idVec3_t operator-( const idVec3_t &a ) const;
|
||||
|
||||
idVec3_t &operator+=( const idVec3_t &a );
|
||||
idVec3_t &operator-=( const idVec3_t &a );
|
||||
idVec3_t &operator*=( const float a );
|
||||
|
||||
int operator==( const idVec3_t &a ) const;
|
||||
int operator!=( const idVec3_t &a ) const;
|
||||
|
||||
idVec3_t Cross( const idVec3_t &a ) const;
|
||||
idVec3_t &Cross( const idVec3_t &a, const idVec3_t &b );
|
||||
|
||||
float Length( void ) const;
|
||||
float Normalize( void );
|
||||
|
||||
void Zero( void );
|
||||
void Snap( void );
|
||||
void SnapTowards( const idVec3_t &to );
|
||||
|
||||
float toYaw( void );
|
||||
float toPitch( void );
|
||||
angles_t toAngles( void );
|
||||
friend idVec3_t LerpVector( const idVec3_t &w1, const idVec3_t &w2, const float t );
|
||||
|
||||
char *string( void );
|
||||
};
|
||||
|
||||
extern idVec3_t vec_zero;
|
||||
|
||||
ID_INLINE idVec3_t::idVec3_t( const float x, const float y, const float z ) {
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
#ifdef FAT_VEC3
|
||||
this->dist = 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
ID_INLINE float idVec3_t::operator[]( const int index ) const {
|
||||
return ( &x )[ index ];
|
||||
}
|
||||
|
||||
ID_INLINE float &idVec3_t::operator[]( const int index ) {
|
||||
return ( &x )[ index ];
|
||||
}
|
||||
|
||||
ID_INLINE idVec3_t::operator float *( void ) {
|
||||
return &x;
|
||||
}
|
||||
|
||||
ID_INLINE idVec3_t idVec3_t::operator-() const {
|
||||
return idVec3_t( -x, -y, -z );
|
||||
}
|
||||
|
||||
ID_INLINE idVec3_t &idVec3_t::operator=( const idVec3_t &a ) {
|
||||
x = a.x;
|
||||
y = a.y;
|
||||
z = a.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE void idVec3_t::set( const float x, const float y, const float z ) {
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
ID_INLINE idVec3_t idVec3_t::operator-( const idVec3_t &a ) const {
|
||||
return idVec3_t( x - a.x, y - a.y, z - a.z );
|
||||
}
|
||||
|
||||
ID_INLINE float idVec3_t::operator*( const idVec3_t &a ) const {
|
||||
return x * a.x + y * a.y + z * a.z;
|
||||
}
|
||||
|
||||
ID_INLINE idVec3_t idVec3_t::operator*( const float a ) const {
|
||||
return idVec3_t( x * a, y * a, z * a );
|
||||
}
|
||||
|
||||
ID_INLINE idVec3_t operator*( const float a, const idVec3_t b ) {
|
||||
return idVec3_t( b.x * a, b.y * a, b.z * a );
|
||||
}
|
||||
|
||||
ID_INLINE idVec3_t idVec3_t::operator+( const idVec3_t &a ) const {
|
||||
return idVec3_t( x + a.x, y + a.y, z + a.z );
|
||||
}
|
||||
|
||||
ID_INLINE idVec3_t &idVec3_t::operator+=( const idVec3_t &a ) {
|
||||
x += a.x;
|
||||
y += a.y;
|
||||
z += a.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idVec3_t &idVec3_t::operator-=( const idVec3_t &a ) {
|
||||
x -= a.x;
|
||||
y -= a.y;
|
||||
z -= a.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idVec3_t &idVec3_t::operator*=( const float a ) {
|
||||
x *= a;
|
||||
y *= a;
|
||||
z *= a;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE int idVec3_t::operator==( const idVec3_t &a ) const {
|
||||
if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ID_INLINE int idVec3_t::operator!=( const idVec3_t &a ) const {
|
||||
if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ID_INLINE idVec3_t idVec3_t::Cross( const idVec3_t &a ) const {
|
||||
return idVec3_t( y * a.z - z * a.y, z * a.x - x * a.z, x * a.y - y * a.x );
|
||||
}
|
||||
|
||||
ID_INLINE idVec3_t &idVec3_t::Cross( const idVec3_t &a, const idVec3_t &b ) {
|
||||
x = a.y * b.z - a.z * b.y;
|
||||
y = a.z * b.x - a.x * b.z;
|
||||
z = a.x * b.y - a.y * b.x;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE float idVec3_t::Length( void ) const {
|
||||
float length;
|
||||
|
||||
length = x * x + y * y + z * z;
|
||||
return ( float )idSqrt( length );
|
||||
}
|
||||
|
||||
ID_INLINE float idVec3_t::Normalize( void ) {
|
||||
float length;
|
||||
float ilength;
|
||||
|
||||
length = this->Length();
|
||||
if ( length ) {
|
||||
ilength = 1.0f / length;
|
||||
x *= ilength;
|
||||
y *= ilength;
|
||||
z *= ilength;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
ID_INLINE void idVec3_t::Zero( void ) {
|
||||
x = 0.0f;
|
||||
y = 0.0f;
|
||||
z = 0.0f;
|
||||
}
|
||||
|
||||
ID_INLINE void idVec3_t::Snap( void ) {
|
||||
x = float( int( x ) );
|
||||
y = float( int( y ) );
|
||||
z = float( int( z ) );
|
||||
}
|
||||
|
||||
/*
|
||||
======================
|
||||
SnapTowards
|
||||
|
||||
Round a vector to integers for more efficient network
|
||||
transmission, but make sure that it rounds towards a given point
|
||||
rather than blindly truncating. This prevents it from truncating
|
||||
into a wall.
|
||||
======================
|
||||
*/
|
||||
ID_INLINE void idVec3_t::SnapTowards( const idVec3_t &to ) {
|
||||
if ( to.x <= x ) {
|
||||
x = float( int( x ) );
|
||||
} else {
|
||||
x = float( int( x ) + 1 );
|
||||
}
|
||||
|
||||
if ( to.y <= y ) {
|
||||
y = float( int( y ) );
|
||||
} else {
|
||||
y = float( int( y ) + 1 );
|
||||
}
|
||||
|
||||
if ( to.z <= z ) {
|
||||
z = float( int( z ) );
|
||||
} else {
|
||||
z = float( int( z ) + 1 );
|
||||
}
|
||||
}
|
||||
|
||||
//===============================================================
|
||||
|
||||
class Bounds {
|
||||
public:
|
||||
idVec3_t b[2];
|
||||
|
||||
Bounds();
|
||||
Bounds( const idVec3_t &mins, const idVec3_t &maxs );
|
||||
|
||||
void Clear();
|
||||
void Zero();
|
||||
float Radius(); // radius from origin, not from center
|
||||
idVec3_t Center();
|
||||
void AddPoint( const idVec3_t &v );
|
||||
void AddBounds( const Bounds &bb );
|
||||
bool IsCleared();
|
||||
bool ContainsPoint( const idVec3_t &p );
|
||||
bool IntersectsBounds( const Bounds &b2 ); // touching is NOT intersecting
|
||||
};
|
||||
|
||||
extern Bounds boundsZero;
|
||||
|
||||
ID_INLINE Bounds::Bounds(){
|
||||
}
|
||||
|
||||
ID_INLINE bool Bounds::IsCleared() {
|
||||
return b[0][0] > b[1][0];
|
||||
}
|
||||
|
||||
ID_INLINE bool Bounds::ContainsPoint( const idVec3_t &p ) {
|
||||
if ( p[0] < b[0][0] || p[1] < b[0][1] || p[2] < b[0][2]
|
||||
|| p[0] > b[1][0] || p[1] > b[1][1] || p[2] > b[1][2] ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ID_INLINE bool Bounds::IntersectsBounds( const Bounds &b2 ) {
|
||||
if ( b2.b[1][0] < b[0][0] || b2.b[1][1] < b[0][1] || b2.b[1][2] < b[0][2]
|
||||
|| b2.b[0][0] > b[1][0] || b2.b[0][1] > b[1][1] || b2.b[0][2] > b[1][2] ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ID_INLINE Bounds::Bounds( const idVec3_t &mins, const idVec3_t &maxs ) {
|
||||
b[0] = mins;
|
||||
b[1] = maxs;
|
||||
}
|
||||
|
||||
ID_INLINE idVec3_t Bounds::Center() {
|
||||
return idVec3_t( ( b[1][0] + b[0][0] ) * 0.5f, ( b[1][1] + b[0][1] ) * 0.5f, ( b[1][2] + b[0][2] ) * 0.5f );
|
||||
}
|
||||
|
||||
ID_INLINE void Bounds::Clear() {
|
||||
b[0][0] = b[0][1] = b[0][2] = 99999;
|
||||
b[1][0] = b[1][1] = b[1][2] = -99999;
|
||||
}
|
||||
|
||||
ID_INLINE void Bounds::Zero() {
|
||||
b[0][0] = b[0][1] = b[0][2] =
|
||||
b[1][0] = b[1][1] = b[1][2] = 0;
|
||||
}
|
||||
|
||||
ID_INLINE void Bounds::AddPoint( const idVec3_t &v ) {
|
||||
if ( v[0] < b[0][0]) {
|
||||
b[0][0] = v[0];
|
||||
}
|
||||
if ( v[0] > b[1][0]) {
|
||||
b[1][0] = v[0];
|
||||
}
|
||||
if ( v[1] < b[0][1] ) {
|
||||
b[0][1] = v[1];
|
||||
}
|
||||
if ( v[1] > b[1][1]) {
|
||||
b[1][1] = v[1];
|
||||
}
|
||||
if ( v[2] < b[0][2] ) {
|
||||
b[0][2] = v[2];
|
||||
}
|
||||
if ( v[2] > b[1][2]) {
|
||||
b[1][2] = v[2];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ID_INLINE void Bounds::AddBounds( const Bounds &bb ) {
|
||||
if ( bb.b[0][0] < b[0][0]) {
|
||||
b[0][0] = bb.b[0][0];
|
||||
}
|
||||
if ( bb.b[0][1] < b[0][1]) {
|
||||
b[0][1] = bb.b[0][1];
|
||||
}
|
||||
if ( bb.b[0][2] < b[0][2]) {
|
||||
b[0][2] = bb.b[0][2];
|
||||
}
|
||||
|
||||
if ( bb.b[1][0] > b[1][0]) {
|
||||
b[1][0] = bb.b[1][0];
|
||||
}
|
||||
if ( bb.b[1][1] > b[1][1]) {
|
||||
b[1][1] = bb.b[1][1];
|
||||
}
|
||||
if ( bb.b[1][2] > b[1][2]) {
|
||||
b[1][2] = bb.b[1][2];
|
||||
}
|
||||
}
|
||||
|
||||
ID_INLINE float Bounds::Radius( ) {
|
||||
int i;
|
||||
float total;
|
||||
float a, aa;
|
||||
|
||||
total = 0;
|
||||
for (i=0 ; i<3 ; i++) {
|
||||
a = (float)fabs( b[0][i] );
|
||||
aa = (float)fabs( b[1][i] );
|
||||
if ( aa > a ) {
|
||||
a = aa;
|
||||
}
|
||||
total += a * a;
|
||||
}
|
||||
|
||||
return (float)idSqrt( total );
|
||||
}
|
||||
|
||||
//===============================================================
|
||||
|
||||
|
||||
class idVec2_t {
|
||||
public:
|
||||
float x;
|
||||
float y;
|
||||
|
||||
operator float *();
|
||||
float operator[]( int index ) const;
|
||||
float &operator[]( int index );
|
||||
};
|
||||
|
||||
ID_INLINE float idVec2_t::operator[]( int index ) const {
|
||||
return ( &x )[ index ];
|
||||
}
|
||||
|
||||
ID_INLINE float& idVec2_t::operator[]( int index ) {
|
||||
return ( &x )[ index ];
|
||||
}
|
||||
|
||||
ID_INLINE idVec2_t::operator float *( void ) {
|
||||
return &x;
|
||||
}
|
||||
|
||||
class vec4_t : public idVec3_t {
|
||||
public:
|
||||
#ifndef FAT_VEC3
|
||||
float dist;
|
||||
#endif
|
||||
vec4_t();
|
||||
~vec4_t() {};
|
||||
|
||||
vec4_t( float x, float y, float z, float dist );
|
||||
float operator[]( int index ) const;
|
||||
float &operator[]( int index );
|
||||
};
|
||||
|
||||
ID_INLINE vec4_t::vec4_t() {}
|
||||
ID_INLINE vec4_t::vec4_t( float x, float y, float z, float dist ) {
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
this->dist = dist;
|
||||
}
|
||||
|
||||
ID_INLINE float vec4_t::operator[]( int index ) const {
|
||||
return ( &x )[ index ];
|
||||
}
|
||||
|
||||
ID_INLINE float& vec4_t::operator[]( int index ) {
|
||||
return ( &x )[ index ];
|
||||
}
|
||||
|
||||
|
||||
class idVec5_t : public idVec3_t {
|
||||
public:
|
||||
float s;
|
||||
float t;
|
||||
float operator[]( int index ) const;
|
||||
float &operator[]( int index );
|
||||
};
|
||||
|
||||
|
||||
ID_INLINE float idVec5_t::operator[]( int index ) const {
|
||||
return ( &x )[ index ];
|
||||
}
|
||||
|
||||
ID_INLINE float& idVec5_t::operator[]( int index ) {
|
||||
return ( &x )[ index ];
|
||||
}
|
||||
|
||||
#endif /* !__MATH_VECTOR_H__ */
|
514
CODEmp/Splines/q_parse.cpp
Normal file
514
CODEmp/Splines/q_parse.cpp
Normal file
|
@ -0,0 +1,514 @@
|
|||
// q_parse.c -- support for parsing text files
|
||||
|
||||
#include "q_shared.h"
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
|
||||
PARSING
|
||||
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
// multiple character punctuation tokens
|
||||
static const char *punctuation[] = {
|
||||
"+=", "-=", "*=", "/=", "&=", "|=", "++", "--",
|
||||
"&&", "||", "<=", ">=", "==", "!=",
|
||||
NULL
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
char token[MAX_TOKEN_CHARS];
|
||||
int lines;
|
||||
qboolean ungetToken;
|
||||
char parseFile[MAX_QPATH];
|
||||
} parseInfo_t;
|
||||
|
||||
#define MAX_PARSE_INFO 16
|
||||
static parseInfo_t parseInfo[MAX_PARSE_INFO];
|
||||
static int parseInfoNum;
|
||||
static parseInfo_t *pi = &parseInfo[0];
|
||||
|
||||
/*
|
||||
===================
|
||||
Com_BeginParseSession
|
||||
===================
|
||||
*/
|
||||
void Com_BeginParseSession( const char *filename ) {
|
||||
if ( parseInfoNum == MAX_PARSE_INFO - 1 ) {
|
||||
Com_Error( ERR_FATAL, "Com_BeginParseSession: session overflow" );
|
||||
}
|
||||
parseInfoNum++;
|
||||
pi = &parseInfo[parseInfoNum];
|
||||
|
||||
pi->lines = 1;
|
||||
Q_strncpyz( pi->parseFile, filename, sizeof( pi->parseFile ) );
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
Com_EndParseSession
|
||||
===================
|
||||
*/
|
||||
void Com_EndParseSession( void ) {
|
||||
if ( parseInfoNum == 0 ) {
|
||||
Com_Error( ERR_FATAL, "Com_EndParseSession: session underflow" );
|
||||
}
|
||||
parseInfoNum--;
|
||||
pi = &parseInfo[parseInfoNum];
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
Com_GetCurrentParseLine
|
||||
===================
|
||||
*/
|
||||
int Com_GetCurrentParseLine( void ) {
|
||||
return pi->lines;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
Com_ScriptError
|
||||
|
||||
Prints the script name and line number in the message
|
||||
===================
|
||||
*/
|
||||
void Com_ScriptError( const char *msg, ... ) {
|
||||
va_list argptr;
|
||||
char string[32000];
|
||||
|
||||
va_start( argptr, msg );
|
||||
vsprintf( string, msg,argptr );
|
||||
va_end( argptr );
|
||||
|
||||
Com_Error( ERR_DROP, "File %s, line %i: %s", pi->parseFile, pi->lines, string );
|
||||
}
|
||||
|
||||
void Com_ScriptWarning( const char *msg, ... ) {
|
||||
va_list argptr;
|
||||
char string[32000];
|
||||
|
||||
va_start( argptr, msg );
|
||||
vsprintf( string, msg,argptr );
|
||||
va_end( argptr );
|
||||
|
||||
Com_Printf( "File %s, line %i: %s", pi->parseFile, pi->lines, string );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
Com_UngetToken
|
||||
|
||||
Calling this will make the next Com_Parse return
|
||||
the current token instead of advancing the pointer
|
||||
===================
|
||||
*/
|
||||
void Com_UngetToken( void ) {
|
||||
if ( pi->ungetToken ) {
|
||||
Com_ScriptError( "UngetToken called twice" );
|
||||
}
|
||||
pi->ungetToken = qtrue;
|
||||
}
|
||||
|
||||
|
||||
static const char *SkipWhitespace( const char (*data), qboolean *hasNewLines ) {
|
||||
int c;
|
||||
|
||||
while( (c = *data) <= ' ') {
|
||||
if( !c ) {
|
||||
return NULL;
|
||||
}
|
||||
if( c == '\n' ) {
|
||||
pi->lines++;
|
||||
*hasNewLines = qtrue;
|
||||
}
|
||||
data++;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Com_ParseExt
|
||||
|
||||
Parse a token out of a string
|
||||
Will never return NULL, just empty strings.
|
||||
An empty string will only be returned at end of file.
|
||||
|
||||
If "allowLineBreaks" is qtrue then an empty
|
||||
string will be returned if the next token is
|
||||
a newline.
|
||||
==============
|
||||
*/
|
||||
static char *Com_ParseExt( const char *(*data_p), qboolean allowLineBreaks ) {
|
||||
int c = 0, len;
|
||||
qboolean hasNewLines = qfalse;
|
||||
const char *data;
|
||||
const char **punc;
|
||||
|
||||
if ( !data_p ) {
|
||||
Com_Error( ERR_FATAL, "Com_ParseExt: NULL data_p" );
|
||||
}
|
||||
|
||||
data = *data_p;
|
||||
len = 0;
|
||||
pi->token[0] = 0;
|
||||
|
||||
// make sure incoming data is valid
|
||||
if ( !data ) {
|
||||
*data_p = NULL;
|
||||
return pi->token;
|
||||
}
|
||||
|
||||
// skip any leading whitespace
|
||||
while ( 1 ) {
|
||||
// skip whitespace
|
||||
data = SkipWhitespace( data, &hasNewLines );
|
||||
if ( !data ) {
|
||||
*data_p = NULL;
|
||||
return pi->token;
|
||||
}
|
||||
if ( hasNewLines && !allowLineBreaks ) {
|
||||
*data_p = data;
|
||||
return pi->token;
|
||||
}
|
||||
|
||||
c = *data;
|
||||
|
||||
// skip double slash comments
|
||||
if ( c == '/' && data[1] == '/' ) {
|
||||
while (*data && *data != '\n') {
|
||||
data++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip /* */ comments
|
||||
if ( c=='/' && data[1] == '*' ) {
|
||||
while ( *data && ( *data != '*' || data[1] != '/' ) ) {
|
||||
if( *data == '\n' ) {
|
||||
pi->lines++;
|
||||
}
|
||||
data++;
|
||||
}
|
||||
if ( *data ) {
|
||||
data += 2;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// a real token to parse
|
||||
break;
|
||||
}
|
||||
|
||||
// handle quoted strings
|
||||
if ( c == '\"' ) {
|
||||
data++;
|
||||
while( 1 ) {
|
||||
c = *data++;
|
||||
if ( ( c=='\\' ) && ( *data == '\"' ) ) {
|
||||
// allow quoted strings to use \" to indicate the " character
|
||||
data++;
|
||||
} else if ( c=='\"' || !c ) {
|
||||
pi->token[len] = 0;
|
||||
*data_p = ( char * ) data;
|
||||
return pi->token;
|
||||
} else if( *data == '\n' ) {
|
||||
pi->lines++;
|
||||
}
|
||||
if ( len < MAX_TOKEN_CHARS - 1 ) {
|
||||
pi->token[len] = c;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for a number
|
||||
// is this parsing of negative numbers going to cause expression problems
|
||||
if ( ( c >= '0' && c <= '9' ) || ( c == '-' && data[ 1 ] >= '0' && data[ 1 ] <= '9' ) ||
|
||||
( c == '.' && data[ 1 ] >= '0' && data[ 1 ] <= '9' ) ) {
|
||||
do {
|
||||
|
||||
if (len < MAX_TOKEN_CHARS - 1) {
|
||||
pi->token[len] = c;
|
||||
len++;
|
||||
}
|
||||
data++;
|
||||
|
||||
c = *data;
|
||||
} while ( ( c >= '0' && c <= '9' ) || c == '.' );
|
||||
|
||||
// parse the exponent
|
||||
if ( c == 'e' || c == 'E' ) {
|
||||
if (len < MAX_TOKEN_CHARS - 1) {
|
||||
pi->token[len] = c;
|
||||
len++;
|
||||
}
|
||||
data++;
|
||||
c = *data;
|
||||
|
||||
if ( c == '-' || c == '+' ) {
|
||||
if (len < MAX_TOKEN_CHARS - 1) {
|
||||
pi->token[len] = c;
|
||||
len++;
|
||||
}
|
||||
data++;
|
||||
c = *data;
|
||||
}
|
||||
|
||||
do {
|
||||
if (len < MAX_TOKEN_CHARS - 1) {
|
||||
pi->token[len] = c;
|
||||
len++;
|
||||
}
|
||||
data++;
|
||||
|
||||
c = *data;
|
||||
} while ( c >= '0' && c <= '9' );
|
||||
}
|
||||
|
||||
if (len == MAX_TOKEN_CHARS) {
|
||||
len = 0;
|
||||
}
|
||||
pi->token[len] = 0;
|
||||
|
||||
*data_p = ( char * ) data;
|
||||
return pi->token;
|
||||
}
|
||||
|
||||
// check for a regular word
|
||||
// we still allow forward and back slashes in name tokens for pathnames
|
||||
// and also colons for drive letters
|
||||
if ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || c == '_' || c == '/' || c == '\\' ) {
|
||||
do {
|
||||
if (len < MAX_TOKEN_CHARS - 1) {
|
||||
pi->token[len] = c;
|
||||
len++;
|
||||
}
|
||||
data++;
|
||||
|
||||
c = *data;
|
||||
} while ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || c == '_'
|
||||
|| ( c >= '0' && c <= '9' ) || c == '/' || c == '\\' || c == ':' || c == '.' );
|
||||
|
||||
if (len == MAX_TOKEN_CHARS) {
|
||||
len = 0;
|
||||
}
|
||||
pi->token[len] = 0;
|
||||
|
||||
*data_p = ( char * ) data;
|
||||
return pi->token;
|
||||
}
|
||||
|
||||
// check for multi-character punctuation token
|
||||
for ( punc = punctuation ; *punc ; punc++ ) {
|
||||
int l;
|
||||
int j;
|
||||
|
||||
l = strlen( *punc );
|
||||
for ( j = 0 ; j < l ; j++ ) {
|
||||
if ( data[j] != (*punc)[j] ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( j == l ) {
|
||||
// a valid multi-character punctuation
|
||||
memcpy( pi->token, *punc, l );
|
||||
pi->token[l] = 0;
|
||||
data += l;
|
||||
*data_p = (char *)data;
|
||||
return pi->token;
|
||||
}
|
||||
}
|
||||
|
||||
// single character punctuation
|
||||
pi->token[0] = *data;
|
||||
pi->token[1] = 0;
|
||||
data++;
|
||||
*data_p = (char *)data;
|
||||
|
||||
return pi->token;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
Com_Parse
|
||||
===================
|
||||
*/
|
||||
const char *Com_Parse( const char *(*data_p) ) {
|
||||
if ( pi->ungetToken ) {
|
||||
pi->ungetToken = qfalse;
|
||||
return pi->token;
|
||||
}
|
||||
return Com_ParseExt( data_p, qtrue );
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
Com_ParseOnLine
|
||||
===================
|
||||
*/
|
||||
const char *Com_ParseOnLine( const char *(*data_p) ) {
|
||||
if ( pi->ungetToken ) {
|
||||
pi->ungetToken = qfalse;
|
||||
return pi->token;
|
||||
}
|
||||
return Com_ParseExt( data_p, qfalse );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
Com_MatchToken
|
||||
==================
|
||||
*/
|
||||
void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning ) {
|
||||
const char *token;
|
||||
|
||||
token = Com_Parse( buf_p );
|
||||
if ( strcmp( token, match ) ) {
|
||||
if (warning) {
|
||||
Com_ScriptWarning( "MatchToken: %s != %s", token, match );
|
||||
} else {
|
||||
Com_ScriptError( "MatchToken: %s != %s", token, match );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
Com_SkipBracedSection
|
||||
|
||||
The next token should be an open brace.
|
||||
Skips until a matching close brace is found.
|
||||
Internal brace depths are properly skipped.
|
||||
=================
|
||||
*/
|
||||
void Com_SkipBracedSection( const char *(*program) ) {
|
||||
const char *token;
|
||||
int depth;
|
||||
|
||||
depth = 0;
|
||||
do {
|
||||
token = Com_Parse( program );
|
||||
if( token[1] == 0 ) {
|
||||
if( token[0] == '{' ) {
|
||||
depth++;
|
||||
}
|
||||
else if( token[0] == '}' ) {
|
||||
depth--;
|
||||
}
|
||||
}
|
||||
} while( depth && *program );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Com_SkipRestOfLine
|
||||
=================
|
||||
*/
|
||||
void Com_SkipRestOfLine ( const char *(*data) ) {
|
||||
const char *p;
|
||||
int c;
|
||||
|
||||
p = *data;
|
||||
while ( (c = *p++) != 0 ) {
|
||||
if ( c == '\n' ) {
|
||||
pi->lines++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*data = p;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
Com_ParseRestOfLine
|
||||
====================
|
||||
*/
|
||||
const char *Com_ParseRestOfLine( const char *(*data_p) ) {
|
||||
static char line[MAX_TOKEN_CHARS];
|
||||
const char *token;
|
||||
|
||||
line[0] = 0;
|
||||
while( 1 ) {
|
||||
token = Com_ParseOnLine( data_p );
|
||||
if ( !token[0] ) {
|
||||
break;
|
||||
}
|
||||
if ( line[0] ) {
|
||||
Q_strcat( line, sizeof(line), " " );
|
||||
}
|
||||
Q_strcat( line, sizeof(line), token );
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
|
||||
float Com_ParseFloat( const char *(*buf_p) ) {
|
||||
const char *token;
|
||||
|
||||
token = Com_Parse( buf_p );
|
||||
if ( !token[0] ) {
|
||||
return 0;
|
||||
}
|
||||
return atof( token );
|
||||
}
|
||||
|
||||
int Com_ParseInt( const char *(*buf_p) ) {
|
||||
const char *token;
|
||||
|
||||
token = Com_Parse( buf_p );
|
||||
if ( !token[0] ) {
|
||||
return 0;
|
||||
}
|
||||
return atoi( token );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Com_Parse1DMatrix( const char *(*buf_p), int x, float *m ) {
|
||||
const char *token;
|
||||
int i;
|
||||
|
||||
Com_MatchToken( buf_p, "(" );
|
||||
|
||||
for (i = 0 ; i < x ; i++) {
|
||||
token = Com_Parse(buf_p);
|
||||
m[i] = atof(token);
|
||||
}
|
||||
|
||||
Com_MatchToken( buf_p, ")" );
|
||||
}
|
||||
|
||||
void Com_Parse2DMatrix( const char *(*buf_p), int y, int x, float *m ) {
|
||||
int i;
|
||||
|
||||
Com_MatchToken( buf_p, "(" );
|
||||
|
||||
for (i = 0 ; i < y ; i++) {
|
||||
Com_Parse1DMatrix (buf_p, x, m + i * x);
|
||||
}
|
||||
|
||||
Com_MatchToken( buf_p, ")" );
|
||||
}
|
||||
|
||||
void Com_Parse3DMatrix( const char *(*buf_p), int z, int y, int x, float *m ) {
|
||||
int i;
|
||||
|
||||
Com_MatchToken( buf_p, "(" );
|
||||
|
||||
for (i = 0 ; i < z ; i++) {
|
||||
Com_Parse2DMatrix (buf_p, y, x, m + i * x*y);
|
||||
}
|
||||
|
||||
Com_MatchToken( buf_p, ")" );
|
||||
}
|
||||
|
955
CODEmp/Splines/q_shared.cpp
Normal file
955
CODEmp/Splines/q_shared.cpp
Normal file
|
@ -0,0 +1,955 @@
|
|||
// q_shared.c -- stateless support routines that are included in each code dll
|
||||
#include "q_shared.h"
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
|
||||
GROWLISTS
|
||||
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
// malloc / free all in one place for debugging
|
||||
extern "C" void *Com_Allocate( int bytes );
|
||||
extern "C" void Com_Dealloc( void *ptr );
|
||||
|
||||
void Com_InitGrowList( growList_t *list, int maxElements ) {
|
||||
list->maxElements = maxElements;
|
||||
list->currentElements = 0;
|
||||
list->elements = (void **)Com_Allocate( list->maxElements * sizeof( void * ) );
|
||||
}
|
||||
|
||||
int Com_AddToGrowList( growList_t *list, void *data ) {
|
||||
void **old;
|
||||
|
||||
if ( list->currentElements != list->maxElements ) {
|
||||
list->elements[list->currentElements] = data;
|
||||
return list->currentElements++;
|
||||
}
|
||||
|
||||
// grow, reallocate and move
|
||||
old = list->elements;
|
||||
|
||||
if ( list->maxElements < 0 ) {
|
||||
Com_Error( ERR_FATAL, "Com_AddToGrowList: maxElements = %i", list->maxElements );
|
||||
}
|
||||
|
||||
if ( list->maxElements == 0 ) {
|
||||
// initialize the list to hold 100 elements
|
||||
Com_InitGrowList( list, 100 );
|
||||
return Com_AddToGrowList( list, data );
|
||||
}
|
||||
|
||||
list->maxElements *= 2;
|
||||
|
||||
Com_DPrintf( "Resizing growlist to %i maxElements\n", list->maxElements );
|
||||
|
||||
list->elements = (void **)Com_Allocate( list->maxElements * sizeof( void * ) );
|
||||
|
||||
if ( !list->elements ) {
|
||||
Com_Error( ERR_DROP, "Growlist alloc failed" );
|
||||
}
|
||||
|
||||
memcpy( list->elements, old, list->currentElements * sizeof( void * ) );
|
||||
|
||||
Com_Dealloc( old );
|
||||
|
||||
return Com_AddToGrowList( list, data );
|
||||
}
|
||||
|
||||
void *Com_GrowListElement( const growList_t *list, int index ) {
|
||||
if ( index < 0 || index >= list->currentElements ) {
|
||||
Com_Error( ERR_DROP, "Com_GrowListElement: %i out of range of %i",
|
||||
index, list->currentElements );
|
||||
}
|
||||
return list->elements[index];
|
||||
}
|
||||
|
||||
int Com_IndexForGrowListElement( const growList_t *list, const void *element ) {
|
||||
int i;
|
||||
|
||||
for ( i = 0 ; i < list->currentElements ; i++ ) {
|
||||
if ( list->elements[i] == element ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
||||
float Com_Clamp( float min, float max, float value ) {
|
||||
if ( value < min ) {
|
||||
return min;
|
||||
}
|
||||
if ( value > max ) {
|
||||
return max;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Com_StringContains
|
||||
============
|
||||
*/
|
||||
const char *Com_StringContains( const char *str1, const char *str2, int casesensitive) {
|
||||
int len, i, j;
|
||||
|
||||
len = strlen(str1) - strlen(str2);
|
||||
for (i = 0; i <= len; i++, str1++) {
|
||||
for (j = 0; str2[j]; j++) {
|
||||
if (casesensitive) {
|
||||
if (str1[j] != str2[j]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (toupper(str1[j]) != toupper(str2[j])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!str2[j]) {
|
||||
return str1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Com_Filter
|
||||
============
|
||||
*/
|
||||
int Com_Filter( const char *filter, const char *name, int casesensitive)
|
||||
{
|
||||
char buf[MAX_TOKEN_CHARS];
|
||||
const char *ptr;
|
||||
int i, found;
|
||||
|
||||
while(*filter) {
|
||||
if (*filter == '*') {
|
||||
filter++;
|
||||
for (i = 0; *filter; i++) {
|
||||
if (*filter == '*' || *filter == '?') break;
|
||||
buf[i] = *filter;
|
||||
filter++;
|
||||
}
|
||||
buf[i] = '\0';
|
||||
if (strlen(buf)) {
|
||||
ptr = Com_StringContains(name, buf, casesensitive);
|
||||
if (!ptr) return qfalse;
|
||||
name = ptr + strlen(buf);
|
||||
}
|
||||
}
|
||||
else if (*filter == '?') {
|
||||
filter++;
|
||||
name++;
|
||||
}
|
||||
else if (*filter == '[' && *(filter+1) == '[') {
|
||||
filter++;
|
||||
}
|
||||
else if (*filter == '[') {
|
||||
filter++;
|
||||
found = qfalse;
|
||||
while(*filter && !found) {
|
||||
if (*filter == ']' && *(filter+1) != ']') break;
|
||||
if (*(filter+1) == '-' && *(filter+2) && (*(filter+2) != ']' || *(filter+3) == ']')) {
|
||||
if (casesensitive) {
|
||||
if (*name >= *filter && *name <= *(filter+2)) found = qtrue;
|
||||
}
|
||||
else {
|
||||
if (toupper(*name) >= toupper(*filter) &&
|
||||
toupper(*name) <= toupper(*(filter+2))) found = qtrue;
|
||||
}
|
||||
filter += 3;
|
||||
}
|
||||
else {
|
||||
if (casesensitive) {
|
||||
if (*filter == *name) found = qtrue;
|
||||
}
|
||||
else {
|
||||
if (toupper(*filter) == toupper(*name)) found = qtrue;
|
||||
}
|
||||
filter++;
|
||||
}
|
||||
}
|
||||
if (!found) return qfalse;
|
||||
while(*filter) {
|
||||
if (*filter == ']' && *(filter+1) != ']') break;
|
||||
filter++;
|
||||
}
|
||||
filter++;
|
||||
name++;
|
||||
}
|
||||
else {
|
||||
if (casesensitive) {
|
||||
if (*filter != *name) return qfalse;
|
||||
}
|
||||
else {
|
||||
if (toupper(*filter) != toupper(*name)) return qfalse;
|
||||
}
|
||||
filter++;
|
||||
name++;
|
||||
}
|
||||
}
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Com_HashString
|
||||
|
||||
================
|
||||
*/
|
||||
int Com_HashString( const char *fname ) {
|
||||
int i;
|
||||
long hash;
|
||||
char letter;
|
||||
|
||||
hash = 0;
|
||||
i = 0;
|
||||
while (fname[i] != '\0') {
|
||||
letter = tolower(fname[i]);
|
||||
if (letter =='.') break; // don't include extension
|
||||
if (letter =='\\') letter = '/'; // damn path names
|
||||
hash+=(long)(letter)*(i+119);
|
||||
i++;
|
||||
}
|
||||
hash &= (FILE_HASH_SIZE-1);
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
Com_SkipPath
|
||||
============
|
||||
*/
|
||||
char *Com_SkipPath (char *pathname)
|
||||
{
|
||||
char *last;
|
||||
|
||||
last = pathname;
|
||||
while (*pathname)
|
||||
{
|
||||
if (*pathname=='/')
|
||||
last = pathname+1;
|
||||
pathname++;
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Com_StripExtension
|
||||
============
|
||||
*/
|
||||
void Com_StripExtension( const char *in, char *out ) {
|
||||
while ( *in && *in != '.' ) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
*out = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
Com_DefaultExtension
|
||||
==================
|
||||
*/
|
||||
void Com_DefaultExtension (char *path, int maxSize, const char *extension ) {
|
||||
char oldPath[MAX_QPATH];
|
||||
char *src;
|
||||
|
||||
//
|
||||
// if path doesn't have a .EXT, append extension
|
||||
// (extension should include the .)
|
||||
//
|
||||
src = path + strlen(path) - 1;
|
||||
|
||||
while (*src != '/' && src != path) {
|
||||
if ( *src == '.' ) {
|
||||
return; // it has an extension
|
||||
}
|
||||
src--;
|
||||
}
|
||||
|
||||
Q_strncpyz( oldPath, path, sizeof( oldPath ) );
|
||||
Com_sprintf( path, maxSize, "%s%s", oldPath, extension );
|
||||
}
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
|
||||
BYTE ORDER FUNCTIONS
|
||||
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
// can't just use function pointers, or dll linkage can
|
||||
// mess up when qcommon is included in multiple places
|
||||
static short (*_BigShort) (short l);
|
||||
static short (*_LittleShort) (short l);
|
||||
static int (*_BigLong) (int l);
|
||||
static int (*_LittleLong) (int l);
|
||||
static float (*_BigFloat) (float l);
|
||||
static float (*_LittleFloat) (float l);
|
||||
|
||||
short BigShort(short l){return _BigShort(l);}
|
||||
short LittleShort(short l) {return _LittleShort(l);}
|
||||
int BigLong (int l) {return _BigLong(l);}
|
||||
int LittleLong (int l) {return _LittleLong(l);}
|
||||
float BigFloat (float l) {return _BigFloat(l);}
|
||||
float LittleFloat (float l) {return _LittleFloat(l);}
|
||||
|
||||
short ShortSwap (short l)
|
||||
{
|
||||
byte b1,b2;
|
||||
|
||||
b1 = l&255;
|
||||
b2 = (l>>8)&255;
|
||||
|
||||
return (b1<<8) + b2;
|
||||
}
|
||||
|
||||
short ShortNoSwap (short l)
|
||||
{
|
||||
return l;
|
||||
}
|
||||
|
||||
int LongSwap (int l)
|
||||
{
|
||||
byte b1,b2,b3,b4;
|
||||
|
||||
b1 = l&255;
|
||||
b2 = (l>>8)&255;
|
||||
b3 = (l>>16)&255;
|
||||
b4 = (l>>24)&255;
|
||||
|
||||
return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
|
||||
}
|
||||
|
||||
int LongNoSwap (int l)
|
||||
{
|
||||
return l;
|
||||
}
|
||||
|
||||
float FloatSwap (float f)
|
||||
{
|
||||
union
|
||||
{
|
||||
float f;
|
||||
byte b[4];
|
||||
} dat1, dat2;
|
||||
|
||||
|
||||
dat1.f = f;
|
||||
dat2.b[0] = dat1.b[3];
|
||||
dat2.b[1] = dat1.b[2];
|
||||
dat2.b[2] = dat1.b[1];
|
||||
dat2.b[3] = dat1.b[0];
|
||||
return dat2.f;
|
||||
}
|
||||
|
||||
float FloatNoSwap (float f)
|
||||
{
|
||||
return f;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Swap_Init
|
||||
================
|
||||
*/
|
||||
void Swap_Init (void)
|
||||
{
|
||||
byte swaptest[2] = {1,0};
|
||||
|
||||
// set the byte swapping variables in a portable manner
|
||||
if ( *(short *)swaptest == 1)
|
||||
{
|
||||
_BigShort = ShortSwap;
|
||||
_LittleShort = ShortNoSwap;
|
||||
_BigLong = LongSwap;
|
||||
_LittleLong = LongNoSwap;
|
||||
_BigFloat = FloatSwap;
|
||||
_LittleFloat = FloatNoSwap;
|
||||
}
|
||||
else
|
||||
{
|
||||
_BigShort = ShortNoSwap;
|
||||
_LittleShort = ShortSwap;
|
||||
_BigLong = LongNoSwap;
|
||||
_LittleLong = LongSwap;
|
||||
_BigFloat = FloatNoSwap;
|
||||
_LittleFloat = FloatSwap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Com_ParseInfos
|
||||
===============
|
||||
*/
|
||||
int Com_ParseInfos( const char *buf, int max, char infos[][MAX_INFO_STRING] ) {
|
||||
const char *token;
|
||||
int count;
|
||||
char key[MAX_TOKEN_CHARS];
|
||||
|
||||
count = 0;
|
||||
|
||||
while ( 1 ) {
|
||||
token = Com_Parse( &buf );
|
||||
if ( !token[0] ) {
|
||||
break;
|
||||
}
|
||||
if ( strcmp( token, "{" ) ) {
|
||||
Com_Printf( "Missing { in info file\n" );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( count == max ) {
|
||||
Com_Printf( "Max infos exceeded\n" );
|
||||
break;
|
||||
}
|
||||
|
||||
infos[count][0] = 0;
|
||||
while ( 1 ) {
|
||||
token = Com_Parse( &buf );
|
||||
if ( !token[0] ) {
|
||||
Com_Printf( "Unexpected end of info file\n" );
|
||||
break;
|
||||
}
|
||||
if ( !strcmp( token, "}" ) ) {
|
||||
break;
|
||||
}
|
||||
Q_strncpyz( key, token, sizeof( key ) );
|
||||
|
||||
token = Com_ParseOnLine( &buf );
|
||||
if ( !token[0] ) {
|
||||
token = "<NULL>";
|
||||
}
|
||||
Info_SetValueForKey( infos[count], key, token );
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
|
||||
LIBRARY REPLACEMENT FUNCTIONS
|
||||
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
int Q_isprint( int c )
|
||||
{
|
||||
if ( c >= 0x20 && c <= 0x7E )
|
||||
return ( 1 );
|
||||
return ( 0 );
|
||||
}
|
||||
|
||||
int Q_islower( int c )
|
||||
{
|
||||
if (c >= 'a' && c <= 'z')
|
||||
return ( 1 );
|
||||
return ( 0 );
|
||||
}
|
||||
|
||||
int Q_isupper( int c )
|
||||
{
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return ( 1 );
|
||||
return ( 0 );
|
||||
}
|
||||
|
||||
int Q_isalpha( int c )
|
||||
{
|
||||
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
|
||||
return ( 1 );
|
||||
return ( 0 );
|
||||
}
|
||||
|
||||
char* Q_strrchr( const char* string, int c )
|
||||
{
|
||||
char cc = c;
|
||||
char *s;
|
||||
char *sp=(char *)0;
|
||||
|
||||
s = (char*)string;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
if (*s == cc)
|
||||
sp = s;
|
||||
s++;
|
||||
}
|
||||
if (cc == 0)
|
||||
sp = s;
|
||||
|
||||
return sp;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Q_strncpyz
|
||||
|
||||
Safe strncpy that ensures a trailing zero
|
||||
=============
|
||||
*/
|
||||
void Q_strncpyz( char *dest, const char *src, int destsize ) {
|
||||
if ( !src ) {
|
||||
Com_Error( ERR_FATAL, "Q_strncpyz: NULL src" );
|
||||
}
|
||||
if ( destsize < 1 ) {
|
||||
Com_Error(ERR_FATAL,"Q_strncpyz: destsize < 1" );
|
||||
}
|
||||
|
||||
strncpy( dest, src, destsize-1 );
|
||||
dest[destsize-1] = 0;
|
||||
}
|
||||
|
||||
int Q_stricmpn (const char *s1, const char *s2, int n) {
|
||||
int c1, c2;
|
||||
|
||||
do {
|
||||
c1 = *s1++;
|
||||
c2 = *s2++;
|
||||
|
||||
if (!n--) {
|
||||
return 0; // strings are equal until end point
|
||||
}
|
||||
|
||||
if (c1 != c2) {
|
||||
if (c1 >= 'a' && c1 <= 'z') {
|
||||
c1 -= ('a' - 'A');
|
||||
}
|
||||
if (c2 >= 'a' && c2 <= 'z') {
|
||||
c2 -= ('a' - 'A');
|
||||
}
|
||||
if (c1 != c2) {
|
||||
return c1 < c2 ? -1 : 1;
|
||||
}
|
||||
}
|
||||
} while (c1);
|
||||
|
||||
return 0; // strings are equal
|
||||
}
|
||||
|
||||
int Q_strncmp (const char *s1, const char *s2, int n) {
|
||||
int c1, c2;
|
||||
|
||||
do {
|
||||
c1 = *s1++;
|
||||
c2 = *s2++;
|
||||
|
||||
if (!n--) {
|
||||
return 0; // strings are equal until end point
|
||||
}
|
||||
|
||||
if (c1 != c2) {
|
||||
return c1 < c2 ? -1 : 1;
|
||||
}
|
||||
} while (c1);
|
||||
|
||||
return 0; // strings are equal
|
||||
}
|
||||
|
||||
int Q_stricmp (const char *s1, const char *s2) {
|
||||
return Q_stricmpn (s1, s2, 99999);
|
||||
}
|
||||
|
||||
|
||||
char *Q_strlwr( char *s1 ) {
|
||||
char *s;
|
||||
|
||||
s = s1;
|
||||
while ( *s ) {
|
||||
*s = tolower(*s);
|
||||
s++;
|
||||
}
|
||||
return s1;
|
||||
}
|
||||
|
||||
char *Q_strupr( char *s1 ) {
|
||||
char *s;
|
||||
|
||||
s = s1;
|
||||
while ( *s ) {
|
||||
*s = toupper(*s);
|
||||
s++;
|
||||
}
|
||||
return s1;
|
||||
}
|
||||
|
||||
|
||||
// never goes past bounds or leaves without a terminating 0
|
||||
void Q_strcat( char *dest, int size, const char *src ) {
|
||||
int l1;
|
||||
|
||||
l1 = strlen( dest );
|
||||
if ( l1 >= size ) {
|
||||
Com_Error( ERR_FATAL, "Q_strcat: already overflowed" );
|
||||
}
|
||||
Q_strncpyz( dest + l1, src, size - l1 );
|
||||
}
|
||||
|
||||
|
||||
int Q_PrintStrlen( const char *string ) {
|
||||
int len;
|
||||
const char *p;
|
||||
|
||||
if( !string ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = 0;
|
||||
p = string;
|
||||
while( *p ) {
|
||||
if( Q_IsColorString( p ) ) {
|
||||
p += 2;
|
||||
continue;
|
||||
}
|
||||
p++;
|
||||
len++;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
char *Q_CleanStr( char *string ) {
|
||||
char* d;
|
||||
char* s;
|
||||
int c;
|
||||
|
||||
s = string;
|
||||
d = string;
|
||||
while ((c = *s) != 0 ) {
|
||||
if ( Q_IsColorString( s ) ) {
|
||||
s++;
|
||||
}
|
||||
else if ( c >= 0x20 && c <= 0x7E ) {
|
||||
*d++ = c;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
*d = '\0';
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
void QDECL Com_sprintf( char *dest, int size, const char *fmt, ...) {
|
||||
int len;
|
||||
va_list argptr;
|
||||
char bigbuffer[32000]; // big, but small enough to fit in PPC stack
|
||||
|
||||
va_start (argptr,fmt);
|
||||
len = vsprintf (bigbuffer,fmt,argptr);
|
||||
va_end (argptr);
|
||||
if ( len >= sizeof( bigbuffer ) ) {
|
||||
Com_Error( ERR_FATAL, "Com_sprintf: overflowed bigbuffer" );
|
||||
}
|
||||
if (len >= size) {
|
||||
Com_Printf ("Com_sprintf: overflow of %i in %i\n", len, size);
|
||||
}
|
||||
Q_strncpyz (dest, bigbuffer, size );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
va
|
||||
|
||||
does a varargs printf into a temp buffer, so I don't need to have
|
||||
varargs versions of all text functions.
|
||||
FIXME: make this buffer size safe someday
|
||||
============
|
||||
*/
|
||||
char * QDECL va( char *format, ... ) {
|
||||
va_list argptr;
|
||||
static char string[2][32000]; // in case va is called by nested functions
|
||||
static int index = 0;
|
||||
char *buf;
|
||||
|
||||
buf = string[index & 1];
|
||||
index++;
|
||||
|
||||
va_start (argptr, format);
|
||||
vsprintf (buf, format,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=====================================================================
|
||||
|
||||
INFO STRINGS
|
||||
|
||||
=====================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
===============
|
||||
Info_ValueForKey
|
||||
|
||||
Searches the string for the given
|
||||
key and returns the associated value, or an empty string.
|
||||
FIXME: overflow check?
|
||||
===============
|
||||
*/
|
||||
char *Info_ValueForKey( const char *s, const char *key ) {
|
||||
char pkey[MAX_INFO_KEY];
|
||||
static char value[2][MAX_INFO_VALUE]; // use two buffers so compares
|
||||
// work without stomping on each other
|
||||
static int valueindex = 0;
|
||||
char *o;
|
||||
|
||||
if ( !s || !key ) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if ( strlen( s ) >= MAX_INFO_STRING ) {
|
||||
Com_Error( ERR_DROP, "Info_ValueForKey: oversize infostring" );
|
||||
}
|
||||
|
||||
valueindex ^= 1;
|
||||
if (*s == '\\')
|
||||
s++;
|
||||
while (1)
|
||||
{
|
||||
o = pkey;
|
||||
while (*s != '\\')
|
||||
{
|
||||
if (!*s)
|
||||
return "";
|
||||
*o++ = *s++;
|
||||
}
|
||||
*o = 0;
|
||||
s++;
|
||||
|
||||
o = value[valueindex];
|
||||
|
||||
while (*s != '\\' && *s)
|
||||
{
|
||||
*o++ = *s++;
|
||||
}
|
||||
*o = 0;
|
||||
|
||||
if (!Q_stricmp (key, pkey) )
|
||||
return value[valueindex];
|
||||
|
||||
if (!*s)
|
||||
break;
|
||||
s++;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
Info_NextPair
|
||||
|
||||
Used to itterate through all the key/value pairs in an info string
|
||||
===================
|
||||
*/
|
||||
void Info_NextPair( const char *(*head), char key[MAX_INFO_KEY], char value[MAX_INFO_VALUE] ) {
|
||||
char *o;
|
||||
const char *s;
|
||||
|
||||
s = *head;
|
||||
|
||||
if ( *s == '\\' ) {
|
||||
s++;
|
||||
}
|
||||
key[0] = 0;
|
||||
value[0] = 0;
|
||||
|
||||
o = key;
|
||||
while ( *s != '\\' ) {
|
||||
if ( !*s ) {
|
||||
*o = 0;
|
||||
*head = s;
|
||||
return;
|
||||
}
|
||||
*o++ = *s++;
|
||||
}
|
||||
*o = 0;
|
||||
s++;
|
||||
|
||||
o = value;
|
||||
while ( *s != '\\' && *s ) {
|
||||
*o++ = *s++;
|
||||
}
|
||||
*o = 0;
|
||||
|
||||
*head = s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
Info_RemoveKey
|
||||
===================
|
||||
*/
|
||||
void Info_RemoveKey( char *s, const char *key ) {
|
||||
char *start;
|
||||
char pkey[MAX_INFO_KEY];
|
||||
char value[MAX_INFO_VALUE];
|
||||
char *o;
|
||||
|
||||
if ( strlen( s ) >= MAX_INFO_STRING ) {
|
||||
Com_Error( ERR_DROP, "Info_RemoveKey: oversize infostring" );
|
||||
}
|
||||
|
||||
if (strchr (key, '\\')) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
start = s;
|
||||
if (*s == '\\')
|
||||
s++;
|
||||
o = pkey;
|
||||
while (*s != '\\')
|
||||
{
|
||||
if (!*s)
|
||||
return;
|
||||
*o++ = *s++;
|
||||
}
|
||||
*o = 0;
|
||||
s++;
|
||||
|
||||
o = value;
|
||||
while (*s != '\\' && *s)
|
||||
{
|
||||
if (!*s)
|
||||
return;
|
||||
*o++ = *s++;
|
||||
}
|
||||
*o = 0;
|
||||
|
||||
if (!strcmp (key, pkey) )
|
||||
{
|
||||
strcpy (start, s); // remove this part
|
||||
return;
|
||||
}
|
||||
|
||||
if (!*s)
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
Info_Validate
|
||||
|
||||
Some characters are illegal in info strings because they
|
||||
can mess up the server's parsing
|
||||
==================
|
||||
*/
|
||||
qboolean Info_Validate( const char *s ) {
|
||||
if ( strchr( s, '\"' ) ) {
|
||||
return qfalse;
|
||||
}
|
||||
if ( strchr( s, ';' ) ) {
|
||||
return qfalse;
|
||||
}
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Info_SetValueForKey
|
||||
|
||||
Changes or adds a key/value pair
|
||||
==================
|
||||
*/
|
||||
void Info_SetValueForKey( char *s, const char *key, const char *value ) {
|
||||
char newi[MAX_INFO_STRING];
|
||||
|
||||
if ( strlen( s ) >= MAX_INFO_STRING ) {
|
||||
Com_Error( ERR_DROP, "Info_SetValueForKey: oversize infostring" );
|
||||
}
|
||||
|
||||
if (strchr (key, '\\') || strchr (value, '\\'))
|
||||
{
|
||||
Com_Printf ("Can't use keys or values with a \\\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strchr (key, ';') || strchr (value, ';'))
|
||||
{
|
||||
Com_Printf ("Can't use keys or values with a semicolon\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strchr (key, '\"') || strchr (value, '\"'))
|
||||
{
|
||||
Com_Printf ("Can't use keys or values with a \"\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Info_RemoveKey (s, key);
|
||||
if (!value || !strlen(value))
|
||||
return;
|
||||
|
||||
Com_sprintf (newi, sizeof(newi), "\\%s\\%s", key, value);
|
||||
|
||||
if (strlen(newi) + strlen(s) > MAX_INFO_STRING)
|
||||
{
|
||||
Com_Printf ("Info string length exceeded\n");
|
||||
return;
|
||||
}
|
||||
|
||||
strcat (s, newi);
|
||||
}
|
||||
|
||||
//====================================================================
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
ParseHex
|
||||
===============
|
||||
*/
|
||||
int ParseHex( const char *text ) {
|
||||
int value;
|
||||
int c;
|
||||
|
||||
value = 0;
|
||||
while ( ( c = *text++ ) != 0 ) {
|
||||
if ( c >= '0' && c <= '9' ) {
|
||||
value = value * 16 + c - '0';
|
||||
continue;
|
||||
}
|
||||
if ( c >= 'a' && c <= 'f' ) {
|
||||
value = value * 16 + 10 + c - 'a';
|
||||
continue;
|
||||
}
|
||||
if ( c >= 'A' && c <= 'F' ) {
|
||||
value = value * 16 + 10 + c - 'A';
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
789
CODEmp/Splines/q_shared.h
Normal file
789
CODEmp/Splines/q_shared.h
Normal file
|
@ -0,0 +1,789 @@
|
|||
#ifndef __Q_SHARED_H
|
||||
#define __Q_SHARED_H
|
||||
|
||||
// q_shared.h -- included first by ALL program modules.
|
||||
// these are the definitions that have no dependance on
|
||||
// central system services, and can be used by any part
|
||||
// of the program without any state issues.
|
||||
|
||||
// A user mod should never modify this file
|
||||
|
||||
// incursion of DOOM code into the Q3A codebase
|
||||
//#define Q3_VERSION "DOOM 0.01"
|
||||
|
||||
// alignment macros for SIMD
|
||||
#define ALIGN_ON
|
||||
#define ALIGN_OFF
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#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 : 4201)
|
||||
#pragma warning(disable : 4214)
|
||||
#pragma warning(disable : 4244)
|
||||
#pragma warning(disable : 4305) // truncation from const double to float
|
||||
#pragma warning(disable : 4310) // cast truncates constant value
|
||||
#pragma warning(disable : 4514)
|
||||
#pragma warning(disable : 4711) // selected for automatic inline expansion
|
||||
#pragma warning(disable : 4220) // varargs matches remaining parameters
|
||||
|
||||
#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>
|
||||
#ifdef WIN32 // mac doesn't have malloc.h
|
||||
#include <malloc.h> // for _alloca()
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
|
||||
//#pragma intrinsic( memset, memcpy )
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// this is the define for determining if we have an asm version of a C function
|
||||
#if (defined _M_IX86 || defined __i386__) && !defined __sun__ && !defined __LCC__
|
||||
#define id386 1
|
||||
#else
|
||||
#define id386 0
|
||||
#endif
|
||||
|
||||
// for windows fastcall option
|
||||
|
||||
#define QDECL
|
||||
|
||||
//======================= WIN32 DEFINES =================================
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#define MAC_STATIC
|
||||
|
||||
#undef QDECL
|
||||
#define QDECL __cdecl
|
||||
|
||||
// buildstring will be incorporated into the version string
|
||||
#ifdef NDEBUG
|
||||
#ifdef _M_IX86
|
||||
#define CPUSTRING "win-x86"
|
||||
#elif defined _M_ALPHA
|
||||
#define CPUSTRING "win-AXP"
|
||||
#endif
|
||||
#else
|
||||
#ifdef _M_IX86
|
||||
#define CPUSTRING "win-x86-debug"
|
||||
#elif defined _M_ALPHA
|
||||
#define CPUSTRING "win-AXP-debug"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#define PATH_SEP '\\'
|
||||
|
||||
#endif
|
||||
|
||||
//======================= MAC OS X SERVER DEFINES =====================
|
||||
|
||||
#if defined(__MACH__) && defined(__APPLE__)
|
||||
|
||||
#define MAC_STATIC
|
||||
|
||||
#ifdef __ppc__
|
||||
#define CPUSTRING "MacOSXS-ppc"
|
||||
#elif defined __i386__
|
||||
#define CPUSTRING "MacOSXS-i386"
|
||||
#else
|
||||
#define CPUSTRING "MacOSXS-other"
|
||||
#endif
|
||||
|
||||
#define PATH_SEP '/'
|
||||
|
||||
#define GAME_HARD_LINKED
|
||||
#define CGAME_HARD_LINKED
|
||||
#define UI_HARD_LINKED
|
||||
#define _alloca alloca
|
||||
|
||||
#undef ALIGN_ON
|
||||
#undef ALIGN_OFF
|
||||
#define ALIGN_ON #pragma align(16)
|
||||
#define ALIGN_OFF #pragma align()
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *osxAllocateMemory(long size);
|
||||
void osxFreeMemory(void *pointer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//======================= MAC DEFINES =================================
|
||||
|
||||
#ifdef __MACOS__
|
||||
|
||||
#define MAC_STATIC static
|
||||
|
||||
#define CPUSTRING "MacOS-PPC"
|
||||
|
||||
#define PATH_SEP ':'
|
||||
|
||||
void Sys_PumpEvents( void );
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __MRC__
|
||||
|
||||
#define MAC_STATIC
|
||||
|
||||
#define CPUSTRING "MacOS-PPC"
|
||||
|
||||
#define PATH_SEP ':'
|
||||
|
||||
void Sys_PumpEvents( void );
|
||||
|
||||
#undef QDECL
|
||||
#define QDECL __cdecl
|
||||
|
||||
#define _alloca alloca
|
||||
#endif
|
||||
|
||||
//======================= LINUX DEFINES =================================
|
||||
|
||||
// the mac compiler can't handle >32k of locals, so we
|
||||
// just waste space and make big arrays static...
|
||||
#ifdef __linux__
|
||||
|
||||
// bk001205 - from Makefile
|
||||
#define stricmp strcasecmp
|
||||
|
||||
#define MAC_STATIC // bk: FIXME
|
||||
|
||||
#ifdef __i386__
|
||||
#define CPUSTRING "linux-i386"
|
||||
#elif defined __axp__
|
||||
#define CPUSTRING "linux-alpha"
|
||||
#else
|
||||
#define CPUSTRING "linux-other"
|
||||
#endif
|
||||
|
||||
#define PATH_SEP '/'
|
||||
|
||||
// bk001205 - try
|
||||
#ifdef Q3_STATIC
|
||||
#define GAME_HARD_LINKED
|
||||
#define CGAME_HARD_LINKED
|
||||
#define UI_HARD_LINKED
|
||||
#define BOTLIB_HARD_LINKED
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//=============================================================
|
||||
|
||||
|
||||
|
||||
typedef enum {qfalse, qtrue} qboolean;
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
#define EQUAL_EPSILON 0.001
|
||||
|
||||
typedef int qhandle_t;
|
||||
typedef int sfxHandle_t;
|
||||
typedef int fileHandle_t;
|
||||
typedef int clipHandle_t;
|
||||
|
||||
typedef enum {
|
||||
INVALID_JOINT = -1
|
||||
} jointHandle_t;
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
#define MAX_QINT 0x7fffffff
|
||||
#define MIN_QINT (-MAX_QINT-1)
|
||||
|
||||
#ifndef max
|
||||
#define max( x, y ) ( ( ( x ) > ( y ) ) ? ( x ) : ( y ) )
|
||||
#define min( x, y ) ( ( ( x ) < ( y ) ) ? ( x ) : ( y ) )
|
||||
#endif
|
||||
|
||||
#ifndef sign
|
||||
#define sign( f ) ( ( f > 0 ) ? 1 : ( ( f < 0 ) ? -1 : 0 ) )
|
||||
#endif
|
||||
|
||||
// angle indexes
|
||||
#define PITCH 0 // up / down
|
||||
#define YAW 1 // left / right
|
||||
#define ROLL 2 // fall over
|
||||
|
||||
// the game guarantees that no string from the network will ever
|
||||
// exceed MAX_STRING_CHARS
|
||||
#define MAX_STRING_CHARS 1024 // max length of a string passed to Cmd_TokenizeString
|
||||
#define MAX_STRING_TOKENS 256 // max tokens resulting from Cmd_TokenizeString
|
||||
#define MAX_TOKEN_CHARS 1024 // max length of an individual token
|
||||
|
||||
#define MAX_INFO_STRING 1024
|
||||
#define MAX_INFO_KEY 1024
|
||||
#define MAX_INFO_VALUE 1024
|
||||
|
||||
|
||||
#define MAX_QPATH 64 // max length of a quake game pathname
|
||||
#define MAX_OSPATH 128 // max length of a filesystem pathname
|
||||
|
||||
#define MAX_NAME_LENGTH 32 // max length of a client name
|
||||
|
||||
// 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
|
||||
|
||||
#undef ERR_FATAL // malloc.h on unix
|
||||
|
||||
// parameters to the main Error routine
|
||||
typedef enum {
|
||||
ERR_NONE,
|
||||
ERR_FATAL, // exit the entire game with a popup window
|
||||
ERR_DROP, // print to console and disconnect from game
|
||||
ERR_DISCONNECT, // don't kill server
|
||||
ERR_NEED_CD // pop up the need-cd dialog
|
||||
} errorParm_t;
|
||||
|
||||
|
||||
// font rendering values used by ui and cgame
|
||||
|
||||
#define PROP_GAP_WIDTH 3
|
||||
#define PROP_SPACE_WIDTH 8
|
||||
#define PROP_HEIGHT 27
|
||||
#define PROP_SMALL_SIZE_SCALE 0.75
|
||||
|
||||
#define BLINK_DIVISOR 200
|
||||
#define PULSE_DIVISOR 75
|
||||
|
||||
#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
|
||||
|
||||
|
||||
/*
|
||||
==============================================================
|
||||
|
||||
MATHLIB
|
||||
|
||||
==============================================================
|
||||
*/
|
||||
#ifdef __cplusplus // so we can include this in C code
|
||||
#define SIDE_FRONT 0
|
||||
#define SIDE_BACK 1
|
||||
#define SIDE_ON 2
|
||||
#define SIDE_CROSS 3
|
||||
|
||||
#define Q_PI 3.14159265358979323846
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
|
||||
#endif
|
||||
|
||||
#include "math_vector.h"
|
||||
#include "math_angles.h"
|
||||
#include "math_matrix.h"
|
||||
#include "math_quaternion.h"
|
||||
|
||||
class idVec3_t; // for defining vectors
|
||||
typedef idVec3_t &vec3_p; // for passing vectors as function arguments
|
||||
typedef const idVec3_t &vec3_c; // for passing vectors as const function arguments
|
||||
|
||||
class angles_t; // for defining angle vectors
|
||||
typedef angles_t &angles_p; // for passing angles as function arguments
|
||||
typedef const angles_t &angles_c; // for passing angles as const function arguments
|
||||
|
||||
class mat3_t; // for defining matrices
|
||||
typedef mat3_t &mat3_p; // for passing matrices as function arguments
|
||||
typedef const mat3_t &mat3_c; // for passing matrices as const function arguments
|
||||
|
||||
|
||||
|
||||
#define NUMVERTEXNORMALS 162
|
||||
extern idVec3_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;
|
||||
|
||||
#define Q_COLOR_ESCAPE '^'
|
||||
#define Q_IsColorString(p) ( p && *(p) == Q_COLOR_ESCAPE && *((p)+1) && *((p)+1) != Q_COLOR_ESCAPE )
|
||||
|
||||
#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 )
|
||||
|
||||
#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"
|
||||
|
||||
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 )
|
||||
|
||||
struct cplane_s;
|
||||
|
||||
extern idVec3_t vec3_origin;
|
||||
extern vec4_t vec4_origin;
|
||||
extern mat3_t axisDefault;
|
||||
|
||||
#define nanmask (255<<23)
|
||||
|
||||
#define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
|
||||
|
||||
float Q_fabs( float f );
|
||||
float Q_rsqrt( float f ); // reciprocal square root
|
||||
|
||||
#define SQRTFAST( x ) ( 1.0f / Q_rsqrt( x ) )
|
||||
|
||||
signed char ClampChar( int i );
|
||||
signed short ClampShort( int i );
|
||||
|
||||
// this isn't a real cheap function to call!
|
||||
int DirToByte( const idVec3_t &dir );
|
||||
void ByteToDir( int b, vec3_p dir );
|
||||
|
||||
#define DotProduct(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
|
||||
#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 VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
|
||||
//#define VectorCopy(a,b) ((b).x=(a).x,(b).y=(a).y,(b).z=(a).z])
|
||||
|
||||
#define VectorScale(v, s, o) ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(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 CrossProduct(a,b,c) ((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
|
||||
|
||||
#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 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];}
|
||||
|
||||
float NormalizeColor( vec3_c in, vec3_p out );
|
||||
|
||||
int VectorCompare( vec3_c v1, vec3_c v2 );
|
||||
float VectorLength( vec3_c v );
|
||||
float Distance( vec3_c p1, vec3_c p2 );
|
||||
float DistanceSquared( vec3_c p1, vec3_c p2 );
|
||||
float VectorNormalize (vec3_p v); // returns vector length
|
||||
void VectorNormalizeFast(vec3_p v); // does NOT return vector length, uses rsqrt approximation
|
||||
float VectorNormalize2( vec3_c v, vec3_p out );
|
||||
void VectorInverse (vec3_p v);
|
||||
void VectorRotate( vec3_c in, mat3_c matrix, vec3_p out );
|
||||
void VectorPolar(vec3_p v, float radius, float theta, float phi);
|
||||
void VectorSnap(vec3_p v);
|
||||
void Vector53Copy( const idVec5_t &in, vec3_p out);
|
||||
void Vector5Scale( const idVec5_t &v, float scale, idVec5_t &out);
|
||||
void Vector5Add( const idVec5_t &va, const idVec5_t &vb, idVec5_t &out);
|
||||
void VectorRotate3( vec3_c vIn, vec3_c vRotation, vec3_p out);
|
||||
void VectorRotate3Origin(vec3_c vIn, vec3_c vRotation, vec3_c vOrigin, vec3_p out);
|
||||
|
||||
|
||||
int Q_log2(int val);
|
||||
|
||||
int Q_rand( int *seed );
|
||||
float Q_random( int *seed );
|
||||
float Q_crandom( int *seed );
|
||||
|
||||
#define random() ((rand () & 0x7fff) / ((float)0x7fff))
|
||||
#define crandom() (2.0 * (random() - 0.5))
|
||||
|
||||
float Q_rint( float in );
|
||||
|
||||
void vectoangles( vec3_c value1, angles_p angles);
|
||||
void AnglesToAxis( angles_c angles, mat3_p axis );
|
||||
|
||||
void AxisCopy( mat3_c in, mat3_p out );
|
||||
qboolean AxisRotated( mat3_c in ); // assumes a non-degenerate axis
|
||||
|
||||
int SignbitsForNormal( vec3_c normal );
|
||||
int BoxOnPlaneSide( const Bounds &b, struct cplane_s *p );
|
||||
|
||||
float AngleMod(float a);
|
||||
float LerpAngle (float from, float to, float frac);
|
||||
float AngleSubtract( float a1, float a2 );
|
||||
void AnglesSubtract( angles_c v1, angles_c v2, angles_p v3 );
|
||||
|
||||
float AngleNormalize360 ( float angle );
|
||||
float AngleNormalize180 ( float angle );
|
||||
float AngleDelta ( float angle1, float angle2 );
|
||||
|
||||
qboolean PlaneFromPoints( vec4_t &plane, vec3_c a, vec3_c b, vec3_c c );
|
||||
void ProjectPointOnPlane( vec3_p dst, vec3_c p, vec3_c normal );
|
||||
void RotatePointAroundVector( vec3_p dst, vec3_c dir, vec3_c point, float degrees );
|
||||
void RotateAroundDirection( mat3_p axis, float yaw );
|
||||
void MakeNormalVectors( vec3_c forward, vec3_p right, vec3_p up );
|
||||
// perpendicular vector could be replaced by this
|
||||
|
||||
int PlaneTypeForNormal( vec3_c normal );
|
||||
|
||||
void MatrixMultiply( mat3_c in1, mat3_c in2, mat3_p out );
|
||||
void MatrixInverseMultiply( mat3_c in1, mat3_c in2, mat3_p out ); // in2 is transposed during multiply
|
||||
void MatrixTransformVector( vec3_c in, mat3_c matrix, vec3_p out );
|
||||
void MatrixProjectVector( vec3_c in, mat3_c matrix, vec3_p out ); // Places the vector into a new coordinate system.
|
||||
void AngleVectors( angles_c angles, vec3_p forward, vec3_p right, vec3_p up);
|
||||
void PerpendicularVector( vec3_p dst, vec3_c src );
|
||||
|
||||
float TriangleArea( vec3_c a, vec3_c b, vec3_c c );
|
||||
#endif // __cplusplus
|
||||
|
||||
//=============================================
|
||||
|
||||
float Com_Clamp( float min, float max, float value );
|
||||
|
||||
#define FILE_HASH_SIZE 1024
|
||||
int Com_HashString( const char *fname );
|
||||
|
||||
char *Com_SkipPath( char *pathname );
|
||||
|
||||
// it is ok for out == in
|
||||
void Com_StripExtension( const char *in, char *out );
|
||||
|
||||
// "extension" should include the dot: ".map"
|
||||
void Com_DefaultExtension( char *path, int maxSize, const char *extension );
|
||||
|
||||
int Com_ParseInfos( const char *buf, int max, char infos[][MAX_INFO_STRING] );
|
||||
|
||||
/*
|
||||
=====================================================================================
|
||||
|
||||
SCRIPT PARSING
|
||||
|
||||
=====================================================================================
|
||||
*/
|
||||
|
||||
// this just controls the comment printing, it doesn't actually load a file
|
||||
void Com_BeginParseSession( const char *filename );
|
||||
void Com_EndParseSession( void );
|
||||
|
||||
int Com_GetCurrentParseLine( void );
|
||||
|
||||
// Will never return NULL, just empty strings.
|
||||
// An empty string will only be returned at end of file.
|
||||
// ParseOnLine will return empty if there isn't another token on this line
|
||||
|
||||
// this funny typedef just means a moving pointer into a const char * buffer
|
||||
const char *Com_Parse( const char *(*data_p) );
|
||||
const char *Com_ParseOnLine( const char *(*data_p) );
|
||||
const char *Com_ParseRestOfLine( const char *(*data_p) );
|
||||
|
||||
void Com_UngetToken( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning = qfalse );
|
||||
#else
|
||||
void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning );
|
||||
#endif
|
||||
|
||||
void Com_ScriptError( const char *msg, ... );
|
||||
void Com_ScriptWarning( const char *msg, ... );
|
||||
|
||||
void Com_SkipBracedSection( const char *(*program) );
|
||||
void Com_SkipRestOfLine( const char *(*data) );
|
||||
|
||||
float Com_ParseFloat( const char *(*buf_p) );
|
||||
int Com_ParseInt( const char *(*buf_p) );
|
||||
|
||||
void Com_Parse1DMatrix( const char *(*buf_p), int x, float *m );
|
||||
void Com_Parse2DMatrix( const char *(*buf_p), int y, int x, float *m );
|
||||
void Com_Parse3DMatrix( const char *(*buf_p), int z, int y, int x, float *m );
|
||||
|
||||
//=====================================================================================
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void QDECL Com_sprintf (char *dest, int size, const char *fmt, ...);
|
||||
|
||||
|
||||
// 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;
|
||||
|
||||
//=============================================
|
||||
|
||||
int Q_isprint( int c );
|
||||
int Q_islower( int c );
|
||||
int Q_isupper( int c );
|
||||
int Q_isalpha( int c );
|
||||
|
||||
// portable case insensitive compare
|
||||
int Q_stricmp (const char *s1, const char *s2);
|
||||
int Q_strncmp (const char *s1, const char *s2, int n);
|
||||
int Q_stricmpn (const char *s1, const char *s2, int n);
|
||||
char *Q_strlwr( char *s1 );
|
||||
char *Q_strupr( char *s1 );
|
||||
char *Q_strrchr( const char* string, int c );
|
||||
|
||||
// buffer size safe library replacements
|
||||
void Q_strncpyz( char *dest, const char *src, int 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 );
|
||||
|
||||
int Com_Filter( const char *filter, const char *name, int casesensitive );
|
||||
const char *Com_StringContains( const char *str1, const char *str2, int casesensitive );
|
||||
|
||||
|
||||
//=============================================
|
||||
|
||||
short BigShort(short l);
|
||||
short LittleShort(short l);
|
||||
int BigLong (int l);
|
||||
int LittleLong (int l);
|
||||
float BigFloat (float l);
|
||||
float LittleFloat (float l);
|
||||
|
||||
void Swap_Init (void);
|
||||
char * QDECL va(char *format, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//=============================================
|
||||
#ifdef __cplusplus
|
||||
//
|
||||
// mapfile parsing
|
||||
//
|
||||
typedef struct ePair_s {
|
||||
char *key;
|
||||
char *value;
|
||||
} ePair_t;
|
||||
|
||||
typedef struct mapSide_s {
|
||||
char material[MAX_QPATH];
|
||||
vec4_t plane;
|
||||
vec4_t textureVectors[2];
|
||||
} mapSide_t;
|
||||
|
||||
typedef struct {
|
||||
int numSides;
|
||||
mapSide_t **sides;
|
||||
} mapBrush_t;
|
||||
|
||||
typedef struct {
|
||||
idVec3_t xyz;
|
||||
float st[2];
|
||||
} patchVertex_t;
|
||||
|
||||
typedef struct {
|
||||
char material[MAX_QPATH];
|
||||
int width, height;
|
||||
patchVertex_t *patchVerts;
|
||||
} mapPatch_t;
|
||||
|
||||
typedef struct {
|
||||
char modelName[MAX_QPATH];
|
||||
float matrix[16];
|
||||
} mapModel_t;
|
||||
|
||||
typedef struct mapPrimitive_s {
|
||||
int numEpairs;
|
||||
ePair_t **ePairs;
|
||||
|
||||
// only one of these will be non-NULL
|
||||
mapBrush_t *brush;
|
||||
mapPatch_t *patch;
|
||||
mapModel_t *model;
|
||||
} mapPrimitive_t;
|
||||
|
||||
typedef struct mapEntity_s {
|
||||
int numPrimitives;
|
||||
mapPrimitive_t **primitives;
|
||||
|
||||
int numEpairs;
|
||||
ePair_t **ePairs;
|
||||
} mapEntity_t;
|
||||
|
||||
typedef struct {
|
||||
int numEntities;
|
||||
mapEntity_t **entities;
|
||||
} mapFile_t;
|
||||
|
||||
|
||||
// the order of entities, brushes, and sides will be maintained, the
|
||||
// lists won't be swapped on each load or save
|
||||
mapFile_t *ParseMapFile( const char *text );
|
||||
void FreeMapFile( mapFile_t *mapFile );
|
||||
void WriteMapFile( const mapFile_t *mapFile, FILE *f );
|
||||
|
||||
// key names are case-insensitive
|
||||
const char *ValueForMapEntityKey( const mapEntity_t *ent, const char *key );
|
||||
float FloatForMapEntityKey( const mapEntity_t *ent, const char *key );
|
||||
qboolean GetVectorForMapEntityKey( const mapEntity_t *ent, const char *key, idVec3_t &vec );
|
||||
|
||||
typedef struct {
|
||||
idVec3_t xyz;
|
||||
idVec2_t st;
|
||||
idVec3_t normal;
|
||||
idVec3_t tangents[2];
|
||||
byte smoothing[4]; // colors for silhouette smoothing
|
||||
} drawVert_t;
|
||||
|
||||
typedef struct {
|
||||
int width, height;
|
||||
drawVert_t *verts;
|
||||
} drawVertMesh_t;
|
||||
|
||||
// Tesselate a map patch into smoothed, drawable vertexes
|
||||
// MaxError of around 4 is reasonable
|
||||
drawVertMesh_t *SubdivideMapPatch( const mapPatch_t *patch, float maxError );
|
||||
#endif // __cplusplus
|
||||
|
||||
//=========================================
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void QDECL Com_Error( int level, const char *error, ... );
|
||||
void QDECL Com_Printf( const char *msg, ... );
|
||||
void QDECL Com_DPrintf( const char *msg, ... );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
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 );
|
||||
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 );
|
||||
|
||||
|
||||
//
|
||||
// key / value info strings
|
||||
//
|
||||
char *Info_ValueForKey( const char *s, const char *key );
|
||||
void Info_RemoveKey( char *s, const char *key );
|
||||
void Info_SetValueForKey( char *s, const char *key, const char *value );
|
||||
qboolean Info_Validate( const char *s );
|
||||
void Info_NextPair( const char *(*s), char key[MAX_INFO_KEY], char value[MAX_INFO_VALUE] );
|
||||
|
||||
// get cvar defs, collision defs, etc
|
||||
//#include "../shared/interface.h"
|
||||
|
||||
// get key code numbers for events
|
||||
//#include "../shared/keycodes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
// get the polygon winding functions
|
||||
//#include "../shared/windings.h"
|
||||
|
||||
// get the flags class
|
||||
//#include "../shared/idflags.h"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __Q_SHARED_H
|
||||
|
1226
CODEmp/Splines/splines.cpp
Normal file
1226
CODEmp/Splines/splines.cpp
Normal file
File diff suppressed because it is too large
Load diff
1061
CODEmp/Splines/splines.h
Normal file
1061
CODEmp/Splines/splines.h
Normal file
File diff suppressed because it is too large
Load diff
325
CODEmp/Splines/util_list.h
Normal file
325
CODEmp/Splines/util_list.h
Normal file
|
@ -0,0 +1,325 @@
|
|||
#ifndef __UTIL_LIST_H__
|
||||
#define __UTIL_LIST_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
template< class type >
|
||||
class idList {
|
||||
private:
|
||||
int m_num;
|
||||
int m_size;
|
||||
int m_granularity;
|
||||
type *m_list;
|
||||
|
||||
public:
|
||||
idList( int granularity = 16 );
|
||||
~idList<type>();
|
||||
void Clear( void );
|
||||
int Num( void );
|
||||
void SetNum( int num );
|
||||
void SetGranularity( int granularity );
|
||||
void Condense( void );
|
||||
int Size( void );
|
||||
void Resize( int size );
|
||||
type operator[]( int index ) const;
|
||||
type &operator[]( int index );
|
||||
int Append( type const & obj );
|
||||
int AddUnique( type const & obj );
|
||||
type *Find( type const & obj, int *index = NULL );
|
||||
bool RemoveIndex( int index );
|
||||
bool Remove( type const & obj );
|
||||
typedef int cmp_t(const void *, const void *);
|
||||
void Sort( cmp_t *compare );
|
||||
};
|
||||
|
||||
/*
|
||||
================
|
||||
idList<type>::idList( int )
|
||||
================
|
||||
*/
|
||||
template< class type >
|
||||
inline idList<type>::idList( int granularity ) {
|
||||
assert( granularity > 0 );
|
||||
|
||||
m_list = NULL;
|
||||
m_granularity = granularity;
|
||||
Clear();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idList<type>::~idList<type>
|
||||
================
|
||||
*/
|
||||
template< class type >
|
||||
inline idList<type>::~idList() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idList<type>::Clear
|
||||
================
|
||||
*/
|
||||
template< class type >
|
||||
inline void idList<type>::Clear( void ) {
|
||||
if ( m_list ) {
|
||||
delete[] m_list;
|
||||
}
|
||||
|
||||
m_list = NULL;
|
||||
m_num = 0;
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idList<type>::Num
|
||||
================
|
||||
*/
|
||||
template< class type >
|
||||
inline int idList<type>::Num( void ) {
|
||||
return m_num;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idList<type>::SetNum
|
||||
================
|
||||
*/
|
||||
template< class type >
|
||||
inline void idList<type>::SetNum( int num ) {
|
||||
assert( num >= 0 );
|
||||
if ( num > m_size ) {
|
||||
// resize it up to the closest level of granularity
|
||||
Resize( ( ( num + m_granularity - 1 ) / m_granularity ) * m_granularity );
|
||||
}
|
||||
m_num = num;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idList<type>::SetGranularity
|
||||
================
|
||||
*/
|
||||
template< class type >
|
||||
inline void idList<type>::SetGranularity( int granularity ) {
|
||||
int newsize;
|
||||
|
||||
assert( granularity > 0 );
|
||||
m_granularity = granularity;
|
||||
|
||||
if ( m_list ) {
|
||||
// resize it to the closest level of granularity
|
||||
newsize = ( ( m_num + m_granularity - 1 ) / m_granularity ) * m_granularity;
|
||||
if ( newsize != m_size ) {
|
||||
Resize( newsize );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idList<type>::Condense
|
||||
|
||||
Resizes the array to exactly the number of elements it contains
|
||||
================
|
||||
*/
|
||||
template< class type >
|
||||
inline void idList<type>::Condense( void ) {
|
||||
if ( m_list ) {
|
||||
if ( m_num ) {
|
||||
Resize( m_num );
|
||||
} else {
|
||||
Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idList<type>::Size
|
||||
================
|
||||
*/
|
||||
template< class type >
|
||||
inline int idList<type>::Size( void ) {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idList<type>::Resize
|
||||
================
|
||||
*/
|
||||
template< class type >
|
||||
inline void idList<type>::Resize( int size ) {
|
||||
type *temp;
|
||||
int i;
|
||||
|
||||
assert( size > 0 );
|
||||
|
||||
if ( size <= 0 ) {
|
||||
Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
temp = m_list;
|
||||
m_size = size;
|
||||
if ( m_size < m_num ) {
|
||||
m_num = m_size;
|
||||
}
|
||||
|
||||
m_list = new type[ m_size ];
|
||||
for( i = 0; i < m_num; i++ ) {
|
||||
m_list[ i ] = temp[ i ];
|
||||
}
|
||||
|
||||
if ( temp ) {
|
||||
delete[] temp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idList<type>::operator[] const
|
||||
================
|
||||
*/
|
||||
template< class type >
|
||||
inline type idList<type>::operator[]( int index ) const {
|
||||
assert( index >= 0 );
|
||||
assert( index < m_num );
|
||||
|
||||
return m_list[ index ];
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idList<type>::operator[]
|
||||
================
|
||||
*/
|
||||
template< class type >
|
||||
inline type &idList<type>::operator[]( int index ) {
|
||||
assert( index >= 0 );
|
||||
assert( index < m_num );
|
||||
|
||||
return m_list[ index ];
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idList<type>::Append
|
||||
================
|
||||
*/
|
||||
template< class type >
|
||||
inline int idList<type>::Append( type const & obj ) {
|
||||
if ( !m_list ) {
|
||||
Resize( m_granularity );
|
||||
}
|
||||
|
||||
if ( m_num == m_size ) {
|
||||
Resize( m_size + m_granularity );
|
||||
}
|
||||
|
||||
m_list[ m_num ] = obj;
|
||||
m_num++;
|
||||
|
||||
return m_num - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idList<type>::AddUnique
|
||||
================
|
||||
*/
|
||||
template< class type >
|
||||
inline int idList<type>::AddUnique( type const & obj ) {
|
||||
int index;
|
||||
|
||||
if ( !Find( obj, &index ) ) {
|
||||
index = Append( obj );
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idList<type>::Find
|
||||
================
|
||||
*/
|
||||
template< class type >
|
||||
inline type *idList<type>::Find( type const & obj, int *index ) {
|
||||
int i;
|
||||
|
||||
for( i = 0; i < m_num; i++ ) {
|
||||
if ( m_list[ i ] == obj ) {
|
||||
if ( index ) {
|
||||
*index = i;
|
||||
}
|
||||
return &m_list[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idList<type>::RemoveIndex
|
||||
================
|
||||
*/
|
||||
template< class type >
|
||||
inline bool idList<type>::RemoveIndex( int index ) {
|
||||
int i;
|
||||
|
||||
if ( !m_list || !m_num ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
assert( index >= 0 );
|
||||
assert( index < m_num );
|
||||
|
||||
if ( ( index < 0 ) || ( index >= m_num ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_num--;
|
||||
for( i = index; i < m_num; i++ ) {
|
||||
m_list[ i ] = m_list[ i + 1 ];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idList<type>::Remove
|
||||
================
|
||||
*/
|
||||
template< class type >
|
||||
inline bool idList<type>::Remove( type const & obj ) {
|
||||
int index;
|
||||
|
||||
if ( Find( obj, &index ) ) {
|
||||
return RemoveIndex( index );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idList<type>::Sort
|
||||
================
|
||||
*/
|
||||
template< class type >
|
||||
inline void idList<type>::Sort( cmp_t *compare ) {
|
||||
if ( !m_list ) {
|
||||
return;
|
||||
}
|
||||
|
||||
qsort( ( void * )m_list, ( size_t )m_num, sizeof( type ), compare );
|
||||
}
|
||||
|
||||
#endif /* !__UTIL_LIST_H__ */
|
598
CODEmp/Splines/util_str.cpp
Normal file
598
CODEmp/Splines/util_str.cpp
Normal file
|
@ -0,0 +1,598 @@
|
|||
//need to rewrite this
|
||||
|
||||
#include "util_str.h"
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(disable : 4244) // 'conversion' conversion from 'type1' to 'type2', possible loss of data
|
||||
#pragma warning(disable : 4710) // function 'blah' not inlined
|
||||
#endif
|
||||
|
||||
static const int STR_ALLOC_GRAN = 20;
|
||||
|
||||
char *idStr::tolower
|
||||
(
|
||||
char *s1
|
||||
)
|
||||
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = s1;
|
||||
while( *s )
|
||||
{
|
||||
*s = ::tolower( *s );
|
||||
s++;
|
||||
}
|
||||
|
||||
return s1;
|
||||
}
|
||||
|
||||
char *idStr::toupper
|
||||
(
|
||||
char *s1
|
||||
)
|
||||
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = s1;
|
||||
while( *s )
|
||||
{
|
||||
*s = ::toupper( *s );
|
||||
s++;
|
||||
}
|
||||
|
||||
return s1;
|
||||
}
|
||||
|
||||
int idStr::icmpn
|
||||
(
|
||||
const char *s1,
|
||||
const char *s2,
|
||||
int n
|
||||
)
|
||||
|
||||
{
|
||||
int c1;
|
||||
int c2;
|
||||
|
||||
do
|
||||
{
|
||||
c1 = *s1++;
|
||||
c2 = *s2++;
|
||||
|
||||
if ( !n-- )
|
||||
{
|
||||
// idStrings are equal until end point
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( c1 != c2 )
|
||||
{
|
||||
if ( c1 >= 'a' && c1 <= 'z' )
|
||||
{
|
||||
c1 -= ( 'a' - 'A' );
|
||||
}
|
||||
|
||||
if ( c2 >= 'a' && c2 <= 'z' )
|
||||
{
|
||||
c2 -= ( 'a' - 'A' );
|
||||
}
|
||||
|
||||
if ( c1 < c2 )
|
||||
{
|
||||
// strings less than
|
||||
return -1;
|
||||
}
|
||||
else if ( c1 > c2 )
|
||||
{
|
||||
// strings greater than
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
while( c1 );
|
||||
|
||||
// strings are equal
|
||||
return 0;
|
||||
}
|
||||
|
||||
int idStr::icmp
|
||||
(
|
||||
const char *s1,
|
||||
const char *s2
|
||||
)
|
||||
|
||||
{
|
||||
int c1;
|
||||
int c2;
|
||||
|
||||
do
|
||||
{
|
||||
c1 = *s1++;
|
||||
c2 = *s2++;
|
||||
|
||||
if ( c1 != c2 )
|
||||
{
|
||||
if ( c1 >= 'a' && c1 <= 'z' )
|
||||
{
|
||||
c1 -= ( 'a' - 'A' );
|
||||
}
|
||||
|
||||
if ( c2 >= 'a' && c2 <= 'z' )
|
||||
{
|
||||
c2 -= ( 'a' - 'A' );
|
||||
}
|
||||
|
||||
if ( c1 < c2 )
|
||||
{
|
||||
// strings less than
|
||||
return -1;
|
||||
}
|
||||
else if ( c1 > c2 )
|
||||
{
|
||||
// strings greater than
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
while( c1 );
|
||||
|
||||
// strings are equal
|
||||
return 0;
|
||||
}
|
||||
|
||||
int idStr::cmpn
|
||||
(
|
||||
const char *s1,
|
||||
const char *s2,
|
||||
int n
|
||||
)
|
||||
|
||||
{
|
||||
int c1;
|
||||
int c2;
|
||||
|
||||
do
|
||||
{
|
||||
c1 = *s1++;
|
||||
c2 = *s2++;
|
||||
|
||||
if ( !n-- )
|
||||
{
|
||||
// strings are equal until end point
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( c1 < c2 )
|
||||
{
|
||||
// strings less than
|
||||
return -1;
|
||||
}
|
||||
else if ( c1 > c2 )
|
||||
{
|
||||
// strings greater than
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
while( c1 );
|
||||
|
||||
// strings are equal
|
||||
return 0;
|
||||
}
|
||||
|
||||
int idStr::cmp
|
||||
(
|
||||
const char *s1,
|
||||
const char *s2
|
||||
)
|
||||
|
||||
{
|
||||
int c1;
|
||||
int c2;
|
||||
|
||||
do
|
||||
{
|
||||
c1 = *s1++;
|
||||
c2 = *s2++;
|
||||
|
||||
if ( c1 < c2 )
|
||||
{
|
||||
// strings less than
|
||||
return -1;
|
||||
}
|
||||
else if ( c1 > c2 )
|
||||
{
|
||||
// strings greater than
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
while( c1 );
|
||||
|
||||
// strings are equal
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
IsNumeric
|
||||
|
||||
Checks a string to see if it contains only numerical values.
|
||||
============
|
||||
*/
|
||||
bool idStr::isNumeric
|
||||
(
|
||||
const char *str
|
||||
)
|
||||
|
||||
{
|
||||
int len;
|
||||
int i;
|
||||
bool dot;
|
||||
|
||||
if ( *str == '-' )
|
||||
{
|
||||
str++;
|
||||
}
|
||||
|
||||
dot = false;
|
||||
len = strlen( str );
|
||||
for( i = 0; i < len; i++ )
|
||||
{
|
||||
if ( !isdigit( str[ i ] ) )
|
||||
{
|
||||
if ( ( str[ i ] == '.' ) && !dot )
|
||||
{
|
||||
dot = true;
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
idStr operator+
|
||||
(
|
||||
const idStr& a,
|
||||
const float b
|
||||
)
|
||||
|
||||
{
|
||||
char text[ 20 ];
|
||||
|
||||
idStr result( a );
|
||||
|
||||
sprintf( text, "%f", b );
|
||||
result.append( text );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
idStr operator+
|
||||
(
|
||||
const idStr& a,
|
||||
const int b
|
||||
)
|
||||
|
||||
{
|
||||
char text[ 20 ];
|
||||
|
||||
idStr result( a );
|
||||
|
||||
sprintf( text, "%d", b );
|
||||
result.append( text );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
idStr operator+
|
||||
(
|
||||
const idStr& a,
|
||||
const unsigned b
|
||||
)
|
||||
|
||||
{
|
||||
char text[ 20 ];
|
||||
|
||||
idStr result( a );
|
||||
|
||||
sprintf( text, "%u", b );
|
||||
result.append( text );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
idStr& idStr::operator+=
|
||||
(
|
||||
const float a
|
||||
)
|
||||
|
||||
{
|
||||
char text[ 20 ];
|
||||
|
||||
sprintf( text, "%f", a );
|
||||
append( text );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
idStr& idStr::operator+=
|
||||
(
|
||||
const int a
|
||||
)
|
||||
|
||||
{
|
||||
char text[ 20 ];
|
||||
|
||||
sprintf( text, "%d", a );
|
||||
append( text );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
idStr& idStr::operator+=
|
||||
(
|
||||
const unsigned a
|
||||
)
|
||||
|
||||
{
|
||||
char text[ 20 ];
|
||||
|
||||
sprintf( text, "%u", a );
|
||||
append( text );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void idStr::CapLength
|
||||
(
|
||||
int newlen
|
||||
)
|
||||
|
||||
{
|
||||
assert ( m_data );
|
||||
|
||||
if ( length() <= newlen )
|
||||
return;
|
||||
|
||||
EnsureDataWritable ();
|
||||
|
||||
m_data->data[newlen] = 0;
|
||||
m_data->len = newlen;
|
||||
}
|
||||
|
||||
void idStr::EnsureDataWritable
|
||||
(
|
||||
void
|
||||
)
|
||||
|
||||
{
|
||||
assert ( m_data );
|
||||
strdata *olddata;
|
||||
int len;
|
||||
|
||||
if ( !m_data->refcount )
|
||||
return;
|
||||
|
||||
olddata = m_data;
|
||||
len = length();
|
||||
|
||||
m_data = new strdata;
|
||||
|
||||
EnsureAlloced ( len + 1, false );
|
||||
strncpy ( m_data->data, olddata->data, len+1 );
|
||||
m_data->len = len;
|
||||
|
||||
olddata->DelRef ();
|
||||
}
|
||||
|
||||
void idStr::EnsureAlloced (int amount, bool keepold) {
|
||||
|
||||
if ( !m_data ) {
|
||||
m_data = new strdata();
|
||||
}
|
||||
|
||||
// Now, let's make sure it's writable
|
||||
EnsureDataWritable ();
|
||||
|
||||
char *newbuffer;
|
||||
bool wasalloced = ( m_data->alloced != 0 );
|
||||
|
||||
if ( amount < m_data->alloced ) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert ( amount );
|
||||
if ( amount == 1 ) {
|
||||
m_data->alloced = 1;
|
||||
} else {
|
||||
int newsize, mod;
|
||||
mod = amount % STR_ALLOC_GRAN;
|
||||
if ( !mod ) {
|
||||
newsize = amount;
|
||||
} else {
|
||||
newsize = amount + STR_ALLOC_GRAN - mod;
|
||||
}
|
||||
m_data->alloced = newsize;
|
||||
}
|
||||
|
||||
newbuffer = new char[m_data->alloced];
|
||||
if ( wasalloced && keepold ) {
|
||||
strcpy ( newbuffer, m_data->data );
|
||||
}
|
||||
|
||||
if ( m_data->data ) {
|
||||
delete [] m_data->data;
|
||||
}
|
||||
m_data->data = newbuffer;
|
||||
}
|
||||
|
||||
void idStr::BackSlashesToSlashes
|
||||
(
|
||||
void
|
||||
)
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
EnsureDataWritable ();
|
||||
|
||||
for ( i=0; i < m_data->len; i++ )
|
||||
{
|
||||
if ( m_data->data[i] == '\\' )
|
||||
m_data->data[i] = '/';
|
||||
}
|
||||
}
|
||||
|
||||
void idStr::snprintf
|
||||
(
|
||||
char *dst,
|
||||
int size,
|
||||
const char *fmt,
|
||||
...
|
||||
)
|
||||
|
||||
{
|
||||
char buffer[0x10000];
|
||||
int len;
|
||||
va_list argptr;
|
||||
|
||||
va_start (argptr,fmt);
|
||||
len = vsprintf (buffer,fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
assert ( len < size );
|
||||
|
||||
strncpy (dst, buffer, size-1);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(disable : 4189) // local variable is initialized but not referenced
|
||||
#endif
|
||||
|
||||
/*
|
||||
=================
|
||||
TestStringClass
|
||||
|
||||
This is a fairly rigorous test of the idStr class's functionality.
|
||||
Because of the fairly global and subtle ramifications of a bug occuring
|
||||
in this class, it should be run after any changes to the class.
|
||||
Add more tests as functionality is changed. Tests should include
|
||||
any possible bounds violation and NULL data tests.
|
||||
=================
|
||||
*/
|
||||
void TestStringClass
|
||||
(
|
||||
void
|
||||
)
|
||||
|
||||
{
|
||||
char ch; // ch == ?
|
||||
idStr *t; // t == ?
|
||||
idStr a; // a.len == 0, a.data == "\0"
|
||||
idStr b; // b.len == 0, b.data == "\0"
|
||||
idStr c( "test" ); // c.len == 4, c.data == "test\0"
|
||||
idStr d( c ); // d.len == 4, d.data == "test\0"
|
||||
idStr e( reinterpret_cast<const char *>(NULL) );
|
||||
// e.len == 0, e.data == "\0" ASSERT!
|
||||
int i; // i == ?
|
||||
|
||||
i = a.length(); // i == 0
|
||||
i = c.length(); // i == 4
|
||||
|
||||
// TTimo: not used
|
||||
// const char *s1 = a.c_str(); // s1 == "\0"
|
||||
// const char *s2 = c.c_str(); // s2 == "test\0"
|
||||
|
||||
t = new idStr(); // t->len == 0, t->data == "\0"
|
||||
delete t; // t == ?
|
||||
|
||||
b = "test"; // b.len == 4, b.data == "test\0"
|
||||
t = new idStr( "test" ); // t->len == 4, t->data == "test\0"
|
||||
delete t; // t == ?
|
||||
|
||||
a = c; // a.len == 4, a.data == "test\0"
|
||||
// a = "";
|
||||
a = NULL; // a.len == 0, a.data == "\0" ASSERT!
|
||||
a = c + d; // a.len == 8, a.data == "testtest\0"
|
||||
a = c + "wow"; // a.len == 7, a.data == "testwow\0"
|
||||
a = c + reinterpret_cast<const char *>(NULL);
|
||||
// a.len == 4, a.data == "test\0" ASSERT!
|
||||
a = "this" + d; // a.len == 8, a.data == "thistest\0"
|
||||
a = reinterpret_cast<const char *>(NULL) + d;
|
||||
// a.len == 4, a.data == "test\0" ASSERT!
|
||||
a += c; // a.len == 8, a.data == "testtest\0"
|
||||
a += "wow"; // a.len == 11, a.data == "testtestwow\0"
|
||||
a += reinterpret_cast<const char *>(NULL);
|
||||
// a.len == 11, a.data == "testtestwow\0" ASSERT!
|
||||
|
||||
a = "test"; // a.len == 4, a.data == "test\0"
|
||||
ch = a[ 0 ]; // ch == 't'
|
||||
ch = a[ -1 ]; // ch == 0 ASSERT!
|
||||
ch = a[ 1000 ]; // ch == 0 ASSERT!
|
||||
ch = a[ 0 ]; // ch == 't'
|
||||
ch = a[ 1 ]; // ch == 'e'
|
||||
ch = a[ 2 ]; // ch == 's'
|
||||
ch = a[ 3 ]; // ch == 't'
|
||||
ch = a[ 4 ]; // ch == '\0' ASSERT!
|
||||
ch = a[ 5 ]; // ch == '\0' ASSERT!
|
||||
|
||||
a[ 1 ] = 'b'; // a.len == 4, a.data == "tbst\0"
|
||||
a[ -1 ] = 'b'; // a.len == 4, a.data == "tbst\0" ASSERT!
|
||||
a[ 0 ] = '0'; // a.len == 4, a.data == "0bst\0"
|
||||
a[ 1 ] = '1'; // a.len == 4, a.data == "01st\0"
|
||||
a[ 2 ] = '2'; // a.len == 4, a.data == "012t\0"
|
||||
a[ 3 ] = '3'; // a.len == 4, a.data == "0123\0"
|
||||
a[ 4 ] = '4'; // a.len == 4, a.data == "0123\0" ASSERT!
|
||||
a[ 5 ] = '5'; // a.len == 4, a.data == "0123\0" ASSERT!
|
||||
a[ 7 ] = '7'; // a.len == 4, a.data == "0123\0" ASSERT!
|
||||
|
||||
a = "test"; // a.len == 4, a.data == "test\0"
|
||||
b = "no"; // b.len == 2, b.data == "no\0"
|
||||
|
||||
i = ( a == b ); // i == 0
|
||||
i = ( a == c ); // i == 1
|
||||
|
||||
i = ( a == "blow" ); // i == 0
|
||||
i = ( a == "test" ); // i == 1
|
||||
i = ( a == NULL ); // i == 0 ASSERT!
|
||||
|
||||
i = ( "test" == b ); // i == 0
|
||||
i = ( "test" == a ); // i == 1
|
||||
i = ( NULL == a ); // i == 0 ASSERT!
|
||||
|
||||
i = ( a != b ); // i == 1
|
||||
i = ( a != c ); // i == 0
|
||||
|
||||
i = ( a != "blow" ); // i == 1
|
||||
i = ( a != "test" ); // i == 0
|
||||
i = ( a != NULL ); // i == 1 ASSERT!
|
||||
|
||||
i = ( "test" != b ); // i == 1
|
||||
i = ( "test" != a ); // i == 0
|
||||
i = ( NULL != a ); // i == 1 ASSERT!
|
||||
|
||||
a = "test"; // a.data == "test"
|
||||
b = a; // b.data == "test"
|
||||
|
||||
a = "not"; // a.data == "not", b.data == "test"
|
||||
|
||||
a = b; // a.data == b.data == "test"
|
||||
|
||||
a += b; // a.data == "testtest", b.data = "test"
|
||||
|
||||
a = b;
|
||||
|
||||
a[1] = '1'; // a.data = "t1st", b.data = "test"
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(default : 4189) // local variable is initialized but not referenced
|
||||
#pragma warning(disable : 4514) // unreferenced inline function has been removed
|
||||
#endif
|
796
CODEmp/Splines/util_str.h
Normal file
796
CODEmp/Splines/util_str.h
Normal file
|
@ -0,0 +1,796 @@
|
|||
//need to rewrite this
|
||||
|
||||
#ifndef __UTIL_STR_H__
|
||||
#define __UTIL_STR_H__
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(disable : 4710) // function 'blah' not inlined
|
||||
#endif
|
||||
|
||||
void TestStringClass ();
|
||||
|
||||
class strdata
|
||||
{
|
||||
public:
|
||||
strdata () : len( 0 ), refcount ( 0 ), data ( NULL ), alloced ( 0 ) {}
|
||||
~strdata ()
|
||||
{
|
||||
if ( data )
|
||||
delete [] data;
|
||||
}
|
||||
|
||||
void AddRef () { refcount++; }
|
||||
bool DelRef () // True if killed
|
||||
{
|
||||
refcount--;
|
||||
if ( refcount < 0 )
|
||||
{
|
||||
delete this;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int len;
|
||||
int refcount;
|
||||
char *data;
|
||||
int alloced;
|
||||
};
|
||||
|
||||
class idStr {
|
||||
protected:
|
||||
strdata *m_data;
|
||||
void EnsureAlloced ( int, bool keepold = true );
|
||||
void EnsureDataWritable ();
|
||||
|
||||
public:
|
||||
~idStr();
|
||||
idStr();
|
||||
idStr( const char *text );
|
||||
idStr( const idStr& string );
|
||||
idStr( const idStr string, int start, int end );
|
||||
idStr( const char ch );
|
||||
idStr( const int num );
|
||||
idStr( const float num );
|
||||
idStr( const unsigned num );
|
||||
int length( void ) const;
|
||||
int allocated( void ) const;
|
||||
const char * c_str( void ) const;
|
||||
|
||||
void append( const char *text );
|
||||
void append( const idStr& text );
|
||||
char operator[]( int index ) const;
|
||||
char& operator[]( int index );
|
||||
|
||||
void operator=( const idStr& text );
|
||||
void operator=( const char *text );
|
||||
|
||||
friend idStr operator+( const idStr& a, const idStr& b );
|
||||
friend idStr operator+( const idStr& a, const char *b );
|
||||
friend idStr operator+( const char *a, const idStr& b );
|
||||
|
||||
friend idStr operator+( const idStr& a, const float b );
|
||||
friend idStr operator+( const idStr& a, const int b );
|
||||
friend idStr operator+( const idStr& a, const unsigned b );
|
||||
friend idStr operator+( const idStr& a, const bool b );
|
||||
friend idStr operator+( const idStr& a, const char b );
|
||||
|
||||
idStr& operator+=( const idStr& a );
|
||||
idStr& operator+=( const char *a );
|
||||
idStr& operator+=( const float a );
|
||||
idStr& operator+=( const char a );
|
||||
idStr& operator+=( const int a );
|
||||
idStr& operator+=( const unsigned a );
|
||||
idStr& operator+=( const bool a );
|
||||
|
||||
friend bool operator==( const idStr& a, const idStr& b );
|
||||
friend bool operator==( const idStr& a, const char *b );
|
||||
friend bool operator==( const char *a, const idStr& b );
|
||||
|
||||
friend bool operator!=( const idStr& a, const idStr& b );
|
||||
friend bool operator!=( const idStr& a, const char *b );
|
||||
friend bool operator!=( const char *a, const idStr& b );
|
||||
|
||||
operator const char * () const;
|
||||
operator const char * ();
|
||||
|
||||
int icmpn( const char *text, int n ) const;
|
||||
int icmpn( const idStr& text, int n ) const;
|
||||
int icmp( const char *text ) const;
|
||||
int icmp( const idStr& text ) const;
|
||||
int cmpn( const char *text, int n ) const;
|
||||
int cmpn( const idStr& text, int n ) const;
|
||||
int cmp( const char *text ) const;
|
||||
int cmp( const idStr& text ) const;
|
||||
|
||||
void tolower( void );
|
||||
void toupper( void );
|
||||
|
||||
static char *tolower( char *s1 );
|
||||
static char *toupper( char *s1 );
|
||||
|
||||
static int icmpn( const char *s1, const char *s2, int n );
|
||||
static int icmp( const char *s1, const char *s2 );
|
||||
static int cmpn( const char *s1, const char *s2, int n );
|
||||
static int cmp( const char *s1, const char *s2 );
|
||||
|
||||
static void snprintf ( char *dst, int size, const char *fmt, ... );
|
||||
|
||||
static bool isNumeric( const char *str );
|
||||
bool isNumeric( void ) const;
|
||||
|
||||
void CapLength ( int );
|
||||
|
||||
void BackSlashesToSlashes ();
|
||||
|
||||
};
|
||||
|
||||
inline idStr::~idStr()
|
||||
{
|
||||
if ( m_data )
|
||||
{
|
||||
m_data->DelRef ();
|
||||
m_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
inline idStr::idStr() : m_data ( NULL )
|
||||
{
|
||||
EnsureAlloced ( 1 );
|
||||
m_data->data[ 0 ] = 0;
|
||||
}
|
||||
|
||||
inline idStr::idStr
|
||||
(
|
||||
const char *text
|
||||
) : m_data ( NULL )
|
||||
|
||||
{
|
||||
int len;
|
||||
|
||||
assert( text );
|
||||
|
||||
if ( text )
|
||||
{
|
||||
len = strlen( text );
|
||||
EnsureAlloced ( len + 1 );
|
||||
strcpy( m_data->data, text );
|
||||
m_data->len = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
EnsureAlloced ( 1 );
|
||||
m_data->data[ 0 ] = 0;
|
||||
m_data->len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline idStr::idStr
|
||||
(
|
||||
const idStr& text
|
||||
) : m_data ( NULL )
|
||||
|
||||
{
|
||||
m_data = text.m_data;
|
||||
m_data->AddRef ();
|
||||
}
|
||||
|
||||
inline idStr::idStr
|
||||
(
|
||||
const idStr text,
|
||||
int start,
|
||||
int end
|
||||
) : m_data ( NULL )
|
||||
|
||||
{
|
||||
int i;
|
||||
int len;
|
||||
|
||||
if ( end > text.length() )
|
||||
{
|
||||
end = text.length();
|
||||
}
|
||||
|
||||
if ( start > text.length() )
|
||||
{
|
||||
start = text.length();
|
||||
}
|
||||
|
||||
len = end - start;
|
||||
if ( len < 0 )
|
||||
{
|
||||
len = 0;
|
||||
}
|
||||
|
||||
EnsureAlloced ( len + 1 );
|
||||
|
||||
for( i = 0; i < len; i++ )
|
||||
{
|
||||
m_data->data[ i ] = text[ start + i ];
|
||||
}
|
||||
|
||||
m_data->data[ len ] = 0;
|
||||
m_data->len = len;
|
||||
}
|
||||
|
||||
inline idStr::idStr
|
||||
(
|
||||
const char ch
|
||||
) : m_data ( NULL )
|
||||
|
||||
{
|
||||
EnsureAlloced ( 2 );
|
||||
|
||||
m_data->data[ 0 ] = ch;
|
||||
m_data->data[ 1 ] = 0;
|
||||
m_data->len = 1;
|
||||
}
|
||||
|
||||
inline idStr::idStr
|
||||
(
|
||||
const float num
|
||||
) : m_data ( NULL )
|
||||
|
||||
{
|
||||
char text[ 32 ];
|
||||
int len;
|
||||
|
||||
sprintf( text, "%.3f", num );
|
||||
len = strlen( text );
|
||||
EnsureAlloced( len + 1 );
|
||||
strcpy( m_data->data, text );
|
||||
m_data->len = len;
|
||||
}
|
||||
|
||||
inline idStr::idStr
|
||||
(
|
||||
const int num
|
||||
) : m_data ( NULL )
|
||||
|
||||
{
|
||||
char text[ 32 ];
|
||||
int len;
|
||||
|
||||
sprintf( text, "%d", num );
|
||||
len = strlen( text );
|
||||
EnsureAlloced( len + 1 );
|
||||
strcpy( m_data->data, text );
|
||||
m_data->len = len;
|
||||
}
|
||||
|
||||
inline idStr::idStr
|
||||
(
|
||||
const unsigned num
|
||||
) : m_data ( NULL )
|
||||
|
||||
{
|
||||
char text[ 32 ];
|
||||
int len;
|
||||
|
||||
sprintf( text, "%u", num );
|
||||
len = strlen( text );
|
||||
EnsureAlloced( len + 1 );
|
||||
strcpy( m_data->data, text );
|
||||
m_data->len = len;
|
||||
}
|
||||
|
||||
inline int idStr::length( void ) const
|
||||
{
|
||||
return ( m_data != NULL ) ? m_data->len : 0;
|
||||
}
|
||||
|
||||
inline int idStr::allocated( void ) const
|
||||
{
|
||||
return ( m_data != NULL ) ? m_data->alloced + sizeof( *m_data ) : 0;
|
||||
}
|
||||
|
||||
inline const char *idStr::c_str( void ) const
|
||||
{
|
||||
assert( m_data );
|
||||
|
||||
return m_data->data;
|
||||
}
|
||||
|
||||
inline void idStr::append
|
||||
(
|
||||
const char *text
|
||||
)
|
||||
|
||||
{
|
||||
int len;
|
||||
|
||||
assert( text );
|
||||
|
||||
if ( text )
|
||||
{
|
||||
len = length() + strlen( text );
|
||||
EnsureAlloced( len + 1 );
|
||||
|
||||
strcat( m_data->data, text );
|
||||
m_data->len = len;
|
||||
}
|
||||
}
|
||||
|
||||
inline void idStr::append
|
||||
(
|
||||
const idStr& text
|
||||
)
|
||||
|
||||
{
|
||||
int len;
|
||||
|
||||
len = length() + text.length();
|
||||
EnsureAlloced ( len + 1 );
|
||||
|
||||
strcat ( m_data->data, text.c_str () );
|
||||
m_data->len = len;
|
||||
}
|
||||
|
||||
inline char idStr::operator[]( int index ) const
|
||||
{
|
||||
assert ( m_data );
|
||||
|
||||
if ( !m_data )
|
||||
return 0;
|
||||
|
||||
// don't include the '/0' in the test, because technically, it's out of bounds
|
||||
assert( ( index >= 0 ) && ( index < m_data->len ) );
|
||||
|
||||
// In release mode, give them a null character
|
||||
// don't include the '/0' in the test, because technically, it's out of bounds
|
||||
if ( ( index < 0 ) || ( index >= m_data->len ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_data->data[ index ];
|
||||
}
|
||||
|
||||
inline char& idStr::operator[]
|
||||
(
|
||||
int index
|
||||
)
|
||||
|
||||
{
|
||||
// Used for result for invalid indices
|
||||
static char dummy = 0;
|
||||
assert ( m_data );
|
||||
|
||||
// We don't know if they'll write to it or not
|
||||
// if it's not a const object
|
||||
EnsureDataWritable ();
|
||||
|
||||
if ( !m_data )
|
||||
return dummy;
|
||||
|
||||
// don't include the '/0' in the test, because technically, it's out of bounds
|
||||
assert( ( index >= 0 ) && ( index < m_data->len ) );
|
||||
|
||||
// In release mode, let them change a safe variable
|
||||
// don't include the '/0' in the test, because technically, it's out of bounds
|
||||
if ( ( index < 0 ) || ( index >= m_data->len ) )
|
||||
{
|
||||
return dummy;
|
||||
}
|
||||
|
||||
return m_data->data[ index ];
|
||||
}
|
||||
|
||||
inline void idStr::operator=
|
||||
(
|
||||
const idStr& text
|
||||
)
|
||||
|
||||
{
|
||||
// adding the reference before deleting our current reference prevents
|
||||
// us from deleting our string if we are copying from ourself
|
||||
text.m_data->AddRef();
|
||||
m_data->DelRef();
|
||||
m_data = text.m_data;
|
||||
}
|
||||
|
||||
inline void idStr::operator=
|
||||
(
|
||||
const char *text
|
||||
)
|
||||
|
||||
{
|
||||
int len;
|
||||
|
||||
assert( text );
|
||||
|
||||
if ( !text )
|
||||
{
|
||||
// safe behaviour if NULL
|
||||
EnsureAlloced ( 1, false );
|
||||
m_data->data[0] = 0;
|
||||
m_data->len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !m_data )
|
||||
{
|
||||
len = strlen ( text );
|
||||
EnsureAlloced( len + 1, false );
|
||||
strcpy ( m_data->data, text );
|
||||
m_data->len = len;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( text == m_data->data )
|
||||
return; // Copying same thing. Punt.
|
||||
|
||||
// If we alias and I don't do this, I could corrupt other strings... This
|
||||
// will get called with EnsureAlloced anyway
|
||||
EnsureDataWritable ();
|
||||
|
||||
// Now we need to check if we're aliasing..
|
||||
if ( text >= m_data->data && text <= m_data->data + m_data->len )
|
||||
{
|
||||
// Great, we're aliasing. We're copying from inside ourselves.
|
||||
// This means that I don't have to ensure that anything is alloced,
|
||||
// though I'll assert just in case.
|
||||
int diff = text - m_data->data;
|
||||
int i;
|
||||
|
||||
assert ( strlen ( text ) < (unsigned) m_data->len );
|
||||
|
||||
for ( i = 0; text[i]; i++ )
|
||||
{
|
||||
m_data->data[i] = text[i];
|
||||
}
|
||||
|
||||
m_data->data[i] = 0;
|
||||
|
||||
m_data->len -= diff;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
len = strlen( text );
|
||||
EnsureAlloced ( len + 1, false );
|
||||
strcpy( m_data->data, text );
|
||||
m_data->len = len;
|
||||
}
|
||||
|
||||
inline idStr operator+
|
||||
(
|
||||
const idStr& a,
|
||||
const idStr& b
|
||||
)
|
||||
|
||||
{
|
||||
idStr result( a );
|
||||
|
||||
result.append( b );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline idStr operator+
|
||||
(
|
||||
const idStr& a,
|
||||
const char *b
|
||||
)
|
||||
|
||||
{
|
||||
idStr result( a );
|
||||
|
||||
result.append( b );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline idStr operator+
|
||||
(
|
||||
const char *a,
|
||||
const idStr& b
|
||||
)
|
||||
|
||||
{
|
||||
idStr result( a );
|
||||
|
||||
result.append( b );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline idStr operator+
|
||||
(
|
||||
const idStr& a,
|
||||
const bool b
|
||||
)
|
||||
|
||||
{
|
||||
idStr result( a );
|
||||
|
||||
result.append( b ? "true" : "false" );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline idStr operator+
|
||||
(
|
||||
const idStr& a,
|
||||
const char b
|
||||
)
|
||||
|
||||
{
|
||||
char text[ 2 ];
|
||||
|
||||
text[ 0 ] = b;
|
||||
text[ 1 ] = 0;
|
||||
|
||||
return a + text;
|
||||
}
|
||||
|
||||
inline idStr& idStr::operator+=
|
||||
(
|
||||
const idStr& a
|
||||
)
|
||||
|
||||
{
|
||||
append( a );
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline idStr& idStr::operator+=
|
||||
(
|
||||
const char *a
|
||||
)
|
||||
|
||||
{
|
||||
append( a );
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline idStr& idStr::operator+=
|
||||
(
|
||||
const char a
|
||||
)
|
||||
|
||||
{
|
||||
char text[ 2 ];
|
||||
|
||||
text[ 0 ] = a;
|
||||
text[ 1 ] = 0;
|
||||
append( text );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline idStr& idStr::operator+=
|
||||
(
|
||||
const bool a
|
||||
)
|
||||
|
||||
{
|
||||
append( a ? "true" : "false" );
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool operator==
|
||||
(
|
||||
const idStr& a,
|
||||
const idStr& b
|
||||
)
|
||||
|
||||
{
|
||||
return ( !strcmp( a.c_str(), b.c_str() ) );
|
||||
}
|
||||
|
||||
inline bool operator==
|
||||
(
|
||||
const idStr& a,
|
||||
const char *b
|
||||
)
|
||||
|
||||
{
|
||||
assert( b );
|
||||
if ( !b )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return ( !strcmp( a.c_str(), b ) );
|
||||
}
|
||||
|
||||
inline bool operator==
|
||||
(
|
||||
const char *a,
|
||||
const idStr& b
|
||||
)
|
||||
|
||||
{
|
||||
assert( a );
|
||||
if ( !a )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return ( !strcmp( a, b.c_str() ) );
|
||||
}
|
||||
|
||||
inline bool operator!=
|
||||
(
|
||||
const idStr& a,
|
||||
const idStr& b
|
||||
)
|
||||
|
||||
{
|
||||
return !( a == b );
|
||||
}
|
||||
|
||||
inline bool operator!=
|
||||
(
|
||||
const idStr& a,
|
||||
const char *b
|
||||
)
|
||||
|
||||
{
|
||||
return !( a == b );
|
||||
}
|
||||
|
||||
inline bool operator!=
|
||||
(
|
||||
const char *a,
|
||||
const idStr& b
|
||||
)
|
||||
|
||||
{
|
||||
return !( a == b );
|
||||
}
|
||||
|
||||
inline int idStr::icmpn
|
||||
(
|
||||
const char *text,
|
||||
int n
|
||||
) const
|
||||
|
||||
{
|
||||
assert( m_data );
|
||||
assert( text );
|
||||
|
||||
return idStr::icmpn( m_data->data, text, n );
|
||||
}
|
||||
|
||||
inline int idStr::icmpn
|
||||
(
|
||||
const idStr& text,
|
||||
int n
|
||||
) const
|
||||
|
||||
{
|
||||
assert( m_data );
|
||||
assert( text.m_data );
|
||||
|
||||
return idStr::icmpn( m_data->data, text.m_data->data, n );
|
||||
}
|
||||
|
||||
inline int idStr::icmp
|
||||
(
|
||||
const char *text
|
||||
) const
|
||||
|
||||
{
|
||||
assert( m_data );
|
||||
assert( text );
|
||||
|
||||
return idStr::icmp( m_data->data, text );
|
||||
}
|
||||
|
||||
inline int idStr::icmp
|
||||
(
|
||||
const idStr& text
|
||||
) const
|
||||
|
||||
{
|
||||
assert( c_str () );
|
||||
assert( text.c_str () );
|
||||
|
||||
return idStr::icmp( c_str () , text.c_str () );
|
||||
}
|
||||
|
||||
inline int idStr::cmp
|
||||
(
|
||||
const char *text
|
||||
) const
|
||||
|
||||
{
|
||||
assert( m_data );
|
||||
assert( text );
|
||||
|
||||
return idStr::cmp( m_data->data, text );
|
||||
}
|
||||
|
||||
inline int idStr::cmp
|
||||
(
|
||||
const idStr& text
|
||||
) const
|
||||
|
||||
{
|
||||
assert( c_str () );
|
||||
assert( text.c_str () );
|
||||
|
||||
return idStr::cmp( c_str () , text.c_str () );
|
||||
}
|
||||
|
||||
inline int idStr::cmpn
|
||||
(
|
||||
const char *text,
|
||||
int n
|
||||
) const
|
||||
|
||||
{
|
||||
assert( c_str () );
|
||||
assert( text );
|
||||
|
||||
return idStr::cmpn( c_str () , text, n );
|
||||
}
|
||||
|
||||
inline int idStr::cmpn
|
||||
(
|
||||
const idStr& text,
|
||||
int n
|
||||
) const
|
||||
|
||||
{
|
||||
assert( c_str () );
|
||||
assert( text.c_str () );
|
||||
|
||||
return idStr::cmpn( c_str () , text.c_str () , n );
|
||||
}
|
||||
|
||||
inline void idStr::tolower
|
||||
(
|
||||
void
|
||||
)
|
||||
|
||||
{
|
||||
assert( m_data );
|
||||
|
||||
EnsureDataWritable ();
|
||||
|
||||
idStr::tolower( m_data->data );
|
||||
}
|
||||
|
||||
inline void idStr::toupper
|
||||
(
|
||||
void
|
||||
)
|
||||
|
||||
{
|
||||
assert( m_data );
|
||||
|
||||
EnsureDataWritable ();
|
||||
|
||||
idStr::toupper( m_data->data );
|
||||
}
|
||||
|
||||
inline bool idStr::isNumeric
|
||||
(
|
||||
void
|
||||
) const
|
||||
|
||||
{
|
||||
assert( m_data );
|
||||
return idStr::isNumeric( m_data->data );
|
||||
}
|
||||
|
||||
inline idStr::operator const char *() {
|
||||
return c_str();
|
||||
}
|
||||
|
||||
inline idStr::operator const char *
|
||||
(
|
||||
void
|
||||
) const
|
||||
|
||||
{
|
||||
return c_str ();
|
||||
}
|
||||
|
||||
#endif
|
246
CODEmp/botlib/aasfile.h
Normal file
246
CODEmp/botlib/aasfile.h
Normal file
|
@ -0,0 +1,246 @@
|
|||
|
||||
|
||||
//NOTE: int = default signed
|
||||
// default long
|
||||
|
||||
#define AASID (('S'<<24)+('A'<<16)+('A'<<8)+'E')
|
||||
#define AASVERSION_OLD 4
|
||||
#define AASVERSION 5
|
||||
|
||||
//presence types
|
||||
#define PRESENCE_NONE 1
|
||||
#define PRESENCE_NORMAL 2
|
||||
#define PRESENCE_CROUCH 4
|
||||
|
||||
//travel types
|
||||
#define MAX_TRAVELTYPES 32
|
||||
#define TRAVEL_INVALID 1 //temporary not possible
|
||||
#define TRAVEL_WALK 2 //walking
|
||||
#define TRAVEL_CROUCH 3 //crouching
|
||||
#define TRAVEL_BARRIERJUMP 4 //jumping onto a barrier
|
||||
#define TRAVEL_JUMP 5 //jumping
|
||||
#define TRAVEL_LADDER 6 //climbing a ladder
|
||||
#define TRAVEL_WALKOFFLEDGE 7 //walking of a ledge
|
||||
#define TRAVEL_SWIM 8 //swimming
|
||||
#define TRAVEL_WATERJUMP 9 //jump out of the water
|
||||
#define TRAVEL_TELEPORT 10 //teleportation
|
||||
#define TRAVEL_ELEVATOR 11 //travel by elevator
|
||||
#define TRAVEL_ROCKETJUMP 12 //rocket jumping required for travel
|
||||
#define TRAVEL_BFGJUMP 13 //bfg jumping required for travel
|
||||
#define TRAVEL_GRAPPLEHOOK 14 //grappling hook required for travel
|
||||
#define TRAVEL_DOUBLEJUMP 15 //double jump
|
||||
#define TRAVEL_RAMPJUMP 16 //ramp jump
|
||||
#define TRAVEL_STRAFEJUMP 17 //strafe jump
|
||||
#define TRAVEL_JUMPPAD 18 //jump pad
|
||||
#define TRAVEL_FUNCBOB 19 //func bob
|
||||
|
||||
//additional travel flags
|
||||
#define TRAVELTYPE_MASK 0xFFFFFF
|
||||
#define TRAVELFLAG_NOTTEAM1 (1 << 24)
|
||||
#define TRAVELFLAG_NOTTEAM2 (2 << 24)
|
||||
|
||||
//face flags
|
||||
#define FACE_SOLID 1 //just solid at the other side
|
||||
#define FACE_LADDER 2 //ladder
|
||||
#define FACE_GROUND 4 //standing on ground when in this face
|
||||
#define FACE_GAP 8 //gap in the ground
|
||||
#define FACE_LIQUID 16 //face seperating two areas with liquid
|
||||
#define FACE_LIQUIDSURFACE 32 //face seperating liquid and air
|
||||
#define FACE_BRIDGE 64 //can walk over this face if bridge is closed
|
||||
|
||||
//area contents
|
||||
#define AREACONTENTS_WATER 1
|
||||
#define AREACONTENTS_LAVA 2
|
||||
#define AREACONTENTS_SLIME 4
|
||||
#define AREACONTENTS_CLUSTERPORTAL 8
|
||||
#define AREACONTENTS_TELEPORTAL 16
|
||||
#define AREACONTENTS_ROUTEPORTAL 32
|
||||
#define AREACONTENTS_TELEPORTER 64
|
||||
#define AREACONTENTS_JUMPPAD 128
|
||||
#define AREACONTENTS_DONOTENTER 256
|
||||
#define AREACONTENTS_VIEWPORTAL 512
|
||||
#define AREACONTENTS_MOVER 1024
|
||||
#define AREACONTENTS_NOTTEAM1 2048
|
||||
#define AREACONTENTS_NOTTEAM2 4096
|
||||
//number of model of the mover inside this area
|
||||
#define AREACONTENTS_MODELNUMSHIFT 24
|
||||
#define AREACONTENTS_MAXMODELNUM 0xFF
|
||||
#define AREACONTENTS_MODELNUM (AREACONTENTS_MAXMODELNUM << AREACONTENTS_MODELNUMSHIFT)
|
||||
|
||||
//area flags
|
||||
#define AREA_GROUNDED 1 //bot can stand on the ground
|
||||
#define AREA_LADDER 2 //area contains one or more ladder faces
|
||||
#define AREA_LIQUID 4 //area contains a liquid
|
||||
#define AREA_DISABLED 8 //area is disabled for routing when set
|
||||
#define AREA_BRIDGE 16 //area ontop of a bridge
|
||||
|
||||
//aas file header lumps
|
||||
#define AAS_LUMPS 14
|
||||
#define AASLUMP_BBOXES 0
|
||||
#define AASLUMP_VERTEXES 1
|
||||
#define AASLUMP_PLANES 2
|
||||
#define AASLUMP_EDGES 3
|
||||
#define AASLUMP_EDGEINDEX 4
|
||||
#define AASLUMP_FACES 5
|
||||
#define AASLUMP_FACEINDEX 6
|
||||
#define AASLUMP_AREAS 7
|
||||
#define AASLUMP_AREASETTINGS 8
|
||||
#define AASLUMP_REACHABILITY 9
|
||||
#define AASLUMP_NODES 10
|
||||
#define AASLUMP_PORTALS 11
|
||||
#define AASLUMP_PORTALINDEX 12
|
||||
#define AASLUMP_CLUSTERS 13
|
||||
|
||||
//========== bounding box =========
|
||||
|
||||
//bounding box
|
||||
typedef struct aas_bbox_s
|
||||
{
|
||||
int presencetype;
|
||||
int flags;
|
||||
vec3_t mins, maxs;
|
||||
} aas_bbox_t;
|
||||
|
||||
//============ settings ===========
|
||||
|
||||
//reachability to another area
|
||||
typedef struct aas_reachability_s
|
||||
{
|
||||
int areanum; //number of the reachable area
|
||||
int facenum; //number of the face towards the other area
|
||||
int edgenum; //number of the edge towards the other area
|
||||
vec3_t start; //start point of inter area movement
|
||||
vec3_t end; //end point of inter area movement
|
||||
int traveltype; //type of travel required to get to the area
|
||||
unsigned short int traveltime;//travel time of the inter area movement
|
||||
} aas_reachability_t;
|
||||
|
||||
//area settings
|
||||
typedef struct aas_areasettings_s
|
||||
{
|
||||
//could also add all kind of statistic fields
|
||||
int contents; //contents of the area
|
||||
int areaflags; //several area flags
|
||||
int presencetype; //how a bot can be present in this area
|
||||
int cluster; //cluster the area belongs to, if negative it's a portal
|
||||
int clusterareanum; //number of the area in the cluster
|
||||
int numreachableareas; //number of reachable areas from this one
|
||||
int firstreachablearea; //first reachable area in the reachable area index
|
||||
} aas_areasettings_t;
|
||||
|
||||
//cluster portal
|
||||
typedef struct aas_portal_s
|
||||
{
|
||||
int areanum; //area that is the actual portal
|
||||
int frontcluster; //cluster at front of portal
|
||||
int backcluster; //cluster at back of portal
|
||||
int clusterareanum[2]; //number of the area in the front and back cluster
|
||||
} aas_portal_t;
|
||||
|
||||
//cluster portal index
|
||||
typedef int aas_portalindex_t;
|
||||
|
||||
//cluster
|
||||
typedef struct aas_cluster_s
|
||||
{
|
||||
int numareas; //number of areas in the cluster
|
||||
int numreachabilityareas; //number of areas with reachabilities
|
||||
int numportals; //number of cluster portals
|
||||
int firstportal; //first cluster portal in the index
|
||||
} aas_cluster_t;
|
||||
|
||||
//============ 3d definition ============
|
||||
|
||||
typedef vec3_t aas_vertex_t;
|
||||
|
||||
//just a plane in the third dimension
|
||||
typedef struct aas_plane_s
|
||||
{
|
||||
vec3_t normal; //normal vector of the plane
|
||||
float dist; //distance of the plane (normal vector * distance = point in plane)
|
||||
int type;
|
||||
} aas_plane_t;
|
||||
|
||||
//edge
|
||||
typedef struct aas_edge_s
|
||||
{
|
||||
int v[2]; //numbers of the vertexes of this edge
|
||||
} aas_edge_t;
|
||||
|
||||
//edge index, negative if vertexes are reversed
|
||||
typedef int aas_edgeindex_t;
|
||||
|
||||
//a face bounds an area, often it will also seperate two areas
|
||||
typedef struct aas_face_s
|
||||
{
|
||||
int planenum; //number of the plane this face is in
|
||||
int faceflags; //face flags (no use to create face settings for just this field)
|
||||
int numedges; //number of edges in the boundary of the face
|
||||
int firstedge; //first edge in the edge index
|
||||
int frontarea; //area at the front of this face
|
||||
int backarea; //area at the back of this face
|
||||
} aas_face_t;
|
||||
|
||||
//face index, stores a negative index if backside of face
|
||||
typedef int aas_faceindex_t;
|
||||
|
||||
//area with a boundary of faces
|
||||
typedef struct aas_area_s
|
||||
{
|
||||
int areanum; //number of this area
|
||||
//3d definition
|
||||
int numfaces; //number of faces used for the boundary of the area
|
||||
int firstface; //first face in the face index used for the boundary of the area
|
||||
vec3_t mins; //mins of the area
|
||||
vec3_t maxs; //maxs of the area
|
||||
vec3_t center; //'center' of the area
|
||||
} aas_area_t;
|
||||
|
||||
//nodes of the bsp tree
|
||||
typedef struct aas_node_s
|
||||
{
|
||||
int planenum;
|
||||
int children[2]; //child nodes of this node, or areas as leaves when negative
|
||||
//when a child is zero it's a solid leaf
|
||||
} aas_node_t;
|
||||
|
||||
//=========== aas file ===============
|
||||
|
||||
//header lump
|
||||
typedef struct
|
||||
{
|
||||
int fileofs;
|
||||
int filelen;
|
||||
} aas_lump_t;
|
||||
|
||||
//aas file header
|
||||
typedef struct aas_header_s
|
||||
{
|
||||
int ident;
|
||||
int version;
|
||||
int bspchecksum;
|
||||
//data entries
|
||||
aas_lump_t lumps[AAS_LUMPS];
|
||||
} aas_header_t;
|
||||
|
||||
|
||||
//====== additional information ======
|
||||
/*
|
||||
|
||||
- when a node child is a solid leaf the node child number is zero
|
||||
- two adjacent areas (sharing a plane at opposite sides) share a face
|
||||
this face is a portal between the areas
|
||||
- when an area uses a face from the faceindex with a positive index
|
||||
then the face plane normal points into the area
|
||||
- the face edges are stored counter clockwise using the edgeindex
|
||||
- two adjacent convex areas (sharing a face) only share One face
|
||||
this is a simple result of the areas being convex
|
||||
- the areas can't have a mixture of ground and gap faces
|
||||
other mixtures of faces in one area are allowed
|
||||
- areas with the AREACONTENTS_CLUSTERPORTAL in the settings have
|
||||
the cluster number set to the negative portal number
|
||||
- edge zero is a dummy
|
||||
- face zero is a dummy
|
||||
- area zero is a dummy
|
||||
- node zero is a dummy
|
||||
*/
|
72
CODEmp/botlib/be_aas_bsp.h
Normal file
72
CODEmp/botlib/be_aas_bsp.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_bsp.h
|
||||
*
|
||||
* desc: AAS
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_aas_bsp.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef AASINTERN
|
||||
//loads the given BSP file
|
||||
int AAS_LoadBSPFile(void);
|
||||
//dump the loaded BSP data
|
||||
void AAS_DumpBSPData(void);
|
||||
//unlink the given entity from the bsp tree leaves
|
||||
void AAS_UnlinkFromBSPLeaves(bsp_link_t *leaves);
|
||||
//link the given entity to the bsp tree leaves of the given model
|
||||
bsp_link_t *AAS_BSPLinkEntity(vec3_t absmins,
|
||||
vec3_t absmaxs,
|
||||
int entnum,
|
||||
int modelnum);
|
||||
|
||||
//calculates collision with given entity
|
||||
qboolean AAS_EntityCollision(int entnum,
|
||||
vec3_t start,
|
||||
vec3_t boxmins,
|
||||
vec3_t boxmaxs,
|
||||
vec3_t end,
|
||||
int contentmask,
|
||||
bsp_trace_t *trace);
|
||||
//for debugging
|
||||
void AAS_PrintFreeBSPLinks(char *str);
|
||||
//
|
||||
#endif //AASINTERN
|
||||
|
||||
#define MAX_EPAIRKEY 128
|
||||
|
||||
//trace through the world
|
||||
bsp_trace_t AAS_Trace( vec3_t start,
|
||||
vec3_t mins,
|
||||
vec3_t maxs,
|
||||
vec3_t end,
|
||||
int passent,
|
||||
int contentmask);
|
||||
//returns the contents at the given point
|
||||
int AAS_PointContents(vec3_t point);
|
||||
//returns true when p2 is in the PVS of p1
|
||||
qboolean AAS_inPVS(vec3_t p1, vec3_t p2);
|
||||
//returns true when p2 is in the PHS of p1
|
||||
qboolean AAS_inPHS(vec3_t p1, vec3_t p2);
|
||||
//returns true if the given areas are connected
|
||||
qboolean AAS_AreasConnected(int area1, int area2);
|
||||
//creates a list with entities totally or partly within the given box
|
||||
int AAS_BoxEntities(vec3_t absmins, vec3_t absmaxs, int *list, int maxcount);
|
||||
//gets the mins, maxs and origin of a BSP model
|
||||
void AAS_BSPModelMinsMaxsOrigin(int modelnum, vec3_t angles, vec3_t mins, vec3_t maxs, vec3_t origin);
|
||||
//handle to the next bsp entity
|
||||
int AAS_NextBSPEntity(int ent);
|
||||
//return the value of the BSP epair key
|
||||
int AAS_ValueForBSPEpairKey(int ent, char *key, char *value, int size);
|
||||
//get a vector for the BSP epair key
|
||||
int AAS_VectorForBSPEpairKey(int ent, char *key, vec3_t v);
|
||||
//get a float for the BSP epair key
|
||||
int AAS_FloatForBSPEpairKey(int ent, char *key, float *value);
|
||||
//get an integer for the BSP epair key
|
||||
int AAS_IntForBSPEpairKey(int ent, char *key, int *value);
|
||||
|
470
CODEmp/botlib/be_aas_bspq3.cpp
Normal file
470
CODEmp/botlib/be_aas_bspq3.cpp
Normal file
|
@ -0,0 +1,470 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_bspq3.c
|
||||
*
|
||||
* desc: BSP, Environment Sampling
|
||||
*
|
||||
* $Archive: /MissionPack/code/botlib/be_aas_bspq3.c $
|
||||
* $Author: Ttimo $
|
||||
* $Revision: 5 $
|
||||
* $Modtime: 4/22/01 8:52a $
|
||||
* $Date: 4/22/01 8:52a $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "l_memory.h"
|
||||
#include "l_script.h"
|
||||
#include "l_precomp.h"
|
||||
#include "l_struct.h"
|
||||
#include "aasfile.h"
|
||||
#include "../game/botlib.h"
|
||||
#include "../game/be_aas.h"
|
||||
#include "be_aas_funcs.h"
|
||||
#include "be_aas_def.h"
|
||||
|
||||
extern botlib_import_t botimport;
|
||||
|
||||
//#define TRACE_DEBUG
|
||||
|
||||
#define ON_EPSILON 0.005
|
||||
//#define DEG2RAD( a ) (( a * M_PI ) / 180.0F)
|
||||
|
||||
#define MAX_BSPENTITIES 2048
|
||||
|
||||
typedef struct rgb_s
|
||||
{
|
||||
int red;
|
||||
int green;
|
||||
int blue;
|
||||
} rgb_t;
|
||||
|
||||
//bsp entity epair
|
||||
typedef struct bsp_epair_s
|
||||
{
|
||||
char *key;
|
||||
char *value;
|
||||
struct bsp_epair_s *next;
|
||||
} bsp_epair_t;
|
||||
|
||||
//bsp data entity
|
||||
typedef struct bsp_entity_s
|
||||
{
|
||||
bsp_epair_t *epairs;
|
||||
} bsp_entity_t;
|
||||
|
||||
//id Sofware BSP data
|
||||
typedef struct bsp_s
|
||||
{
|
||||
//true when bsp file is loaded
|
||||
int loaded;
|
||||
//entity data
|
||||
int entdatasize;
|
||||
char *dentdata;
|
||||
//bsp entities
|
||||
int numentities;
|
||||
bsp_entity_t entities[MAX_BSPENTITIES];
|
||||
} bsp_t;
|
||||
|
||||
//global bsp
|
||||
bsp_t bspworld;
|
||||
|
||||
|
||||
#ifdef BSP_DEBUG
|
||||
typedef struct cname_s
|
||||
{
|
||||
int value;
|
||||
char *name;
|
||||
} cname_t;
|
||||
|
||||
cname_t contentnames[] =
|
||||
{
|
||||
{CONTENTS_SOLID,"CONTENTS_SOLID"},
|
||||
{CONTENTS_WINDOW,"CONTENTS_WINDOW"},
|
||||
{CONTENTS_AUX,"CONTENTS_AUX"},
|
||||
{CONTENTS_LAVA,"CONTENTS_LAVA"},
|
||||
{CONTENTS_SLIME,"CONTENTS_SLIME"},
|
||||
{CONTENTS_WATER,"CONTENTS_WATER"},
|
||||
{CONTENTS_MIST,"CONTENTS_MIST"},
|
||||
{LAST_VISIBLE_CONTENTS,"LAST_VISIBLE_CONTENTS"},
|
||||
|
||||
{CONTENTS_AREAPORTAL,"CONTENTS_AREAPORTAL"},
|
||||
{CONTENTS_PLAYERCLIP,"CONTENTS_PLAYERCLIP"},
|
||||
{CONTENTS_MONSTERCLIP,"CONTENTS_MONSTERCLIP"},
|
||||
{CONTENTS_CURRENT_0,"CONTENTS_CURRENT_0"},
|
||||
{CONTENTS_CURRENT_90,"CONTENTS_CURRENT_90"},
|
||||
{CONTENTS_CURRENT_180,"CONTENTS_CURRENT_180"},
|
||||
{CONTENTS_CURRENT_270,"CONTENTS_CURRENT_270"},
|
||||
{CONTENTS_CURRENT_UP,"CONTENTS_CURRENT_UP"},
|
||||
{CONTENTS_CURRENT_DOWN,"CONTENTS_CURRENT_DOWN"},
|
||||
{CONTENTS_ORIGIN,"CONTENTS_ORIGIN"},
|
||||
{CONTENTS_MONSTER,"CONTENTS_MONSTER"},
|
||||
{CONTENTS_DEADMONSTER,"CONTENTS_DEADMONSTER"},
|
||||
{CONTENTS_DETAIL,"CONTENTS_DETAIL"},
|
||||
{CONTENTS_TRANSLUCENT,"CONTENTS_TRANSLUCENT"},
|
||||
{CONTENTS_LADDER,"CONTENTS_LADDER"},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
void PrintContents(int contents)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; contentnames[i].value; i++)
|
||||
{
|
||||
if (contents & contentnames[i].value)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "%s\n", contentnames[i].name);
|
||||
} //end if
|
||||
} //end for
|
||||
} //end of the function PrintContents
|
||||
|
||||
#endif // BSP_DEBUG
|
||||
//===========================================================================
|
||||
// traces axial boxes of any size through the world
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
bsp_trace_t AAS_Trace(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int passent, int contentmask)
|
||||
{
|
||||
bsp_trace_t bsptrace;
|
||||
botimport.Trace(&bsptrace, start, mins, maxs, end, passent, contentmask);
|
||||
return bsptrace;
|
||||
} //end of the function AAS_Trace
|
||||
//===========================================================================
|
||||
// returns the contents at the given point
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_PointContents(vec3_t point)
|
||||
{
|
||||
return botimport.PointContents(point);
|
||||
} //end of the function AAS_PointContents
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
qboolean AAS_EntityCollision(int entnum,
|
||||
vec3_t start, vec3_t boxmins, vec3_t boxmaxs, vec3_t end,
|
||||
int contentmask, bsp_trace_t *trace)
|
||||
{
|
||||
bsp_trace_t enttrace;
|
||||
|
||||
botimport.EntityTrace(&enttrace, start, boxmins, boxmaxs, end, entnum, contentmask);
|
||||
if (enttrace.fraction < trace->fraction)
|
||||
{
|
||||
Com_Memcpy(trace, &enttrace, sizeof(bsp_trace_t));
|
||||
return qtrue;
|
||||
} //end if
|
||||
return qfalse;
|
||||
} //end of the function AAS_EntityCollision
|
||||
//===========================================================================
|
||||
// returns true if in Potentially Hearable Set
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
qboolean AAS_inPVS(vec3_t p1, vec3_t p2)
|
||||
{
|
||||
return (qboolean)botimport.inPVS(p1, p2);
|
||||
} //end of the function AAS_InPVS
|
||||
//===========================================================================
|
||||
// returns true if in Potentially Visible Set
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
qboolean AAS_inPHS(vec3_t p1, vec3_t p2)
|
||||
{
|
||||
return qtrue;
|
||||
} //end of the function AAS_inPHS
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_BSPModelMinsMaxsOrigin(int modelnum, vec3_t angles, vec3_t mins, vec3_t maxs, vec3_t origin)
|
||||
{
|
||||
botimport.BSPModelMinsMaxsOrigin(modelnum, angles, mins, maxs, origin);
|
||||
} //end of the function AAS_BSPModelMinsMaxs
|
||||
//===========================================================================
|
||||
// unlinks the entity from all leaves
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_UnlinkFromBSPLeaves(bsp_link_t *leaves)
|
||||
{
|
||||
} //end of the function AAS_UnlinkFromBSPLeaves
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
bsp_link_t *AAS_BSPLinkEntity(vec3_t absmins, vec3_t absmaxs, int entnum, int modelnum)
|
||||
{
|
||||
return NULL;
|
||||
} //end of the function AAS_BSPLinkEntity
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_BoxEntities(vec3_t absmins, vec3_t absmaxs, int *list, int maxcount)
|
||||
{
|
||||
return 0;
|
||||
} //end of the function AAS_BoxEntities
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_NextBSPEntity(int ent)
|
||||
{
|
||||
ent++;
|
||||
if (ent >= 1 && ent < bspworld.numentities) return ent;
|
||||
return 0;
|
||||
} //end of the function AAS_NextBSPEntity
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_BSPEntityInRange(int ent)
|
||||
{
|
||||
if (ent <= 0 || ent >= bspworld.numentities)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "bsp entity out of range\n");
|
||||
return qfalse;
|
||||
} //end if
|
||||
return qtrue;
|
||||
} //end of the function AAS_BSPEntityInRange
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_ValueForBSPEpairKey(int ent, char *key, char *value, int size)
|
||||
{
|
||||
bsp_epair_t *epair;
|
||||
|
||||
value[0] = '\0';
|
||||
if (!AAS_BSPEntityInRange(ent)) return qfalse;
|
||||
for (epair = bspworld.entities[ent].epairs; epair; epair = epair->next)
|
||||
{
|
||||
if (!strcmp(epair->key, key))
|
||||
{
|
||||
strncpy(value, epair->value, size-1);
|
||||
value[size-1] = '\0';
|
||||
return qtrue;
|
||||
} //end if
|
||||
} //end for
|
||||
return qfalse;
|
||||
} //end of the function AAS_FindBSPEpair
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_VectorForBSPEpairKey(int ent, char *key, vec3_t v)
|
||||
{
|
||||
char buf[MAX_EPAIRKEY];
|
||||
double v1, v2, v3;
|
||||
|
||||
VectorClear(v);
|
||||
if (!AAS_ValueForBSPEpairKey(ent, key, buf, MAX_EPAIRKEY)) return qfalse;
|
||||
//scanf into doubles, then assign, so it is vec_t size independent
|
||||
v1 = v2 = v3 = 0;
|
||||
sscanf(buf, "%lf %lf %lf", &v1, &v2, &v3);
|
||||
v[0] = v1;
|
||||
v[1] = v2;
|
||||
v[2] = v3;
|
||||
return qtrue;
|
||||
} //end of the function AAS_VectorForBSPEpairKey
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_FloatForBSPEpairKey(int ent, char *key, float *value)
|
||||
{
|
||||
char buf[MAX_EPAIRKEY];
|
||||
|
||||
*value = 0;
|
||||
if (!AAS_ValueForBSPEpairKey(ent, key, buf, MAX_EPAIRKEY)) return qfalse;
|
||||
*value = atof(buf);
|
||||
return qtrue;
|
||||
} //end of the function AAS_FloatForBSPEpairKey
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_IntForBSPEpairKey(int ent, char *key, int *value)
|
||||
{
|
||||
char buf[MAX_EPAIRKEY];
|
||||
|
||||
*value = 0;
|
||||
if (!AAS_ValueForBSPEpairKey(ent, key, buf, MAX_EPAIRKEY)) return qfalse;
|
||||
*value = atoi(buf);
|
||||
return qtrue;
|
||||
} //end of the function AAS_IntForBSPEpairKey
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_FreeBSPEntities(void)
|
||||
{
|
||||
int i;
|
||||
bsp_entity_t *ent;
|
||||
bsp_epair_t *epair, *nextepair;
|
||||
|
||||
for (i = 1; i < bspworld.numentities; i++)
|
||||
{
|
||||
ent = &bspworld.entities[i];
|
||||
for (epair = ent->epairs; epair; epair = nextepair)
|
||||
{
|
||||
nextepair = epair->next;
|
||||
//
|
||||
if (epair->key) FreeMemory(epair->key);
|
||||
if (epair->value) FreeMemory(epair->value);
|
||||
FreeMemory(epair);
|
||||
} //end for
|
||||
} //end for
|
||||
bspworld.numentities = 0;
|
||||
} //end of the function AAS_FreeBSPEntities
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_ParseBSPEntities(void)
|
||||
{
|
||||
script_t *script;
|
||||
token_t token;
|
||||
bsp_entity_t *ent;
|
||||
bsp_epair_t *epair;
|
||||
|
||||
script = LoadScriptMemory(bspworld.dentdata, bspworld.entdatasize, "entdata");
|
||||
SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES|SCFL_NOSTRINGESCAPECHARS);//SCFL_PRIMITIVE);
|
||||
|
||||
bspworld.numentities = 1;
|
||||
|
||||
while(PS_ReadToken(script, &token))
|
||||
{
|
||||
if (strcmp(token.string, "{"))
|
||||
{
|
||||
ScriptError(script, "invalid %s\n", token.string);
|
||||
AAS_FreeBSPEntities();
|
||||
FreeScript(script);
|
||||
return;
|
||||
} //end if
|
||||
if (bspworld.numentities >= MAX_BSPENTITIES)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "too many entities in BSP file\n");
|
||||
break;
|
||||
} //end if
|
||||
ent = &bspworld.entities[bspworld.numentities];
|
||||
bspworld.numentities++;
|
||||
ent->epairs = NULL;
|
||||
while(PS_ReadToken(script, &token))
|
||||
{
|
||||
if (!strcmp(token.string, "}")) break;
|
||||
epair = (bsp_epair_t *) GetClearedHunkMemory(sizeof(bsp_epair_t));
|
||||
epair->next = ent->epairs;
|
||||
ent->epairs = epair;
|
||||
if (token.type != TT_STRING)
|
||||
{
|
||||
ScriptError(script, "invalid %s\n", token.string);
|
||||
AAS_FreeBSPEntities();
|
||||
FreeScript(script);
|
||||
return;
|
||||
} //end if
|
||||
StripDoubleQuotes(token.string);
|
||||
epair->key = (char *) GetHunkMemory(strlen(token.string) + 1);
|
||||
strcpy(epair->key, token.string);
|
||||
if (!PS_ExpectTokenType(script, TT_STRING, 0, &token))
|
||||
{
|
||||
AAS_FreeBSPEntities();
|
||||
FreeScript(script);
|
||||
return;
|
||||
} //end if
|
||||
StripDoubleQuotes(token.string);
|
||||
epair->value = (char *) GetHunkMemory(strlen(token.string) + 1);
|
||||
strcpy(epair->value, token.string);
|
||||
} //end while
|
||||
if (strcmp(token.string, "}"))
|
||||
{
|
||||
ScriptError(script, "missing }\n");
|
||||
AAS_FreeBSPEntities();
|
||||
FreeScript(script);
|
||||
return;
|
||||
} //end if
|
||||
} //end while
|
||||
FreeScript(script);
|
||||
} //end of the function AAS_ParseBSPEntities
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_BSPTraceLight(vec3_t start, vec3_t end, vec3_t endpos, int *red, int *green, int *blue)
|
||||
{
|
||||
return 0;
|
||||
} //end of the function AAS_BSPTraceLight
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_DumpBSPData(void)
|
||||
{
|
||||
AAS_FreeBSPEntities();
|
||||
|
||||
if (bspworld.dentdata) FreeMemory(bspworld.dentdata);
|
||||
bspworld.dentdata = NULL;
|
||||
bspworld.entdatasize = 0;
|
||||
//
|
||||
bspworld.loaded = qfalse;
|
||||
Com_Memset( &bspworld, 0, sizeof(bspworld) );
|
||||
} //end of the function AAS_DumpBSPData
|
||||
//===========================================================================
|
||||
// load an bsp file
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_LoadBSPFile(void)
|
||||
{
|
||||
AAS_DumpBSPData();
|
||||
bspworld.entdatasize = strlen(botimport.BSPEntityData()) + 1;
|
||||
bspworld.dentdata = (char *) GetClearedHunkMemory(bspworld.entdatasize);
|
||||
Com_Memcpy(bspworld.dentdata, botimport.BSPEntityData(), bspworld.entdatasize);
|
||||
AAS_ParseBSPEntities();
|
||||
bspworld.loaded = qtrue;
|
||||
return BLERR_NOERROR;
|
||||
} //end of the function AAS_LoadBSPFile
|
1528
CODEmp/botlib/be_aas_cluster.cpp
Normal file
1528
CODEmp/botlib/be_aas_cluster.cpp
Normal file
File diff suppressed because it is too large
Load diff
21
CODEmp/botlib/be_aas_cluster.h
Normal file
21
CODEmp/botlib/be_aas_cluster.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_cluster.h
|
||||
*
|
||||
* desc: AAS
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_aas_cluster.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef AASINTERN
|
||||
//initialize the AAS clustering
|
||||
void AAS_InitClustering(void);
|
||||
//
|
||||
void AAS_SetViewPortalsAsClusterPortals(void);
|
||||
#endif //AASINTERN
|
||||
|
760
CODEmp/botlib/be_aas_debug.cpp
Normal file
760
CODEmp/botlib/be_aas_debug.cpp
Normal file
|
@ -0,0 +1,760 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_debug.c
|
||||
*
|
||||
* desc: AAS debug code
|
||||
*
|
||||
* $Archive: /MissionPack/code/botlib/be_aas_debug.c $
|
||||
* $Author: Ttimo $
|
||||
* $Revision: 8 $
|
||||
* $Modtime: 4/22/01 8:52a $
|
||||
* $Date: 4/22/01 8:52a $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "l_memory.h"
|
||||
#include "l_script.h"
|
||||
#include "l_precomp.h"
|
||||
#include "l_struct.h"
|
||||
#include "l_libvar.h"
|
||||
#include "aasfile.h"
|
||||
#include "../game/botlib.h"
|
||||
#include "../game/be_aas.h"
|
||||
#include "be_interface.h"
|
||||
#include "be_aas_funcs.h"
|
||||
#include "be_aas_def.h"
|
||||
|
||||
#define MAX_DEBUGLINES 1024
|
||||
#define MAX_DEBUGPOLYGONS 8192
|
||||
|
||||
int debuglines[MAX_DEBUGLINES];
|
||||
int debuglinevisible[MAX_DEBUGLINES];
|
||||
int numdebuglines;
|
||||
|
||||
static int debugpolygons[MAX_DEBUGPOLYGONS];
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_ClearShownPolygons(void)
|
||||
{
|
||||
int i;
|
||||
//*
|
||||
for (i = 0; i < MAX_DEBUGPOLYGONS; i++)
|
||||
{
|
||||
if (debugpolygons[i]) botimport.DebugPolygonDelete(debugpolygons[i]);
|
||||
debugpolygons[i] = 0;
|
||||
} //end for
|
||||
//*/
|
||||
/*
|
||||
for (i = 0; i < MAX_DEBUGPOLYGONS; i++)
|
||||
{
|
||||
botimport.DebugPolygonDelete(i);
|
||||
debugpolygons[i] = 0;
|
||||
} //end for
|
||||
*/
|
||||
} //end of the function AAS_ClearShownPolygons
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_ShowPolygon(int color, int numpoints, vec3_t *points)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_DEBUGPOLYGONS; i++)
|
||||
{
|
||||
if (!debugpolygons[i])
|
||||
{
|
||||
debugpolygons[i] = botimport.DebugPolygonCreate(color, numpoints, points);
|
||||
break;
|
||||
} //end if
|
||||
} //end for
|
||||
} //end of the function AAS_ShowPolygon
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_ClearShownDebugLines(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
//make all lines invisible
|
||||
for (i = 0; i < MAX_DEBUGLINES; i++)
|
||||
{
|
||||
if (debuglines[i])
|
||||
{
|
||||
//botimport.DebugLineShow(debuglines[i], NULL, NULL, LINECOLOR_NONE);
|
||||
botimport.DebugLineDelete(debuglines[i]);
|
||||
debuglines[i] = 0;
|
||||
debuglinevisible[i] = qfalse;
|
||||
} //end if
|
||||
} //end for
|
||||
} //end of the function AAS_ClearShownDebugLines
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_DebugLine(vec3_t start, vec3_t end, int color)
|
||||
{
|
||||
int line;
|
||||
|
||||
for (line = 0; line < MAX_DEBUGLINES; line++)
|
||||
{
|
||||
if (!debuglines[line])
|
||||
{
|
||||
debuglines[line] = botimport.DebugLineCreate();
|
||||
debuglinevisible[line] = qfalse;
|
||||
numdebuglines++;
|
||||
} //end if
|
||||
if (!debuglinevisible[line])
|
||||
{
|
||||
botimport.DebugLineShow(debuglines[line], start, end, color);
|
||||
debuglinevisible[line] = qtrue;
|
||||
return;
|
||||
} //end else
|
||||
} //end for
|
||||
} //end of the function AAS_DebugLine
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_PermanentLine(vec3_t start, vec3_t end, int color)
|
||||
{
|
||||
int line;
|
||||
|
||||
line = botimport.DebugLineCreate();
|
||||
botimport.DebugLineShow(line, start, end, color);
|
||||
} //end of the function AAS_PermenentLine
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_DrawPermanentCross(vec3_t origin, float size, int color)
|
||||
{
|
||||
int i, debugline;
|
||||
vec3_t start, end;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
VectorCopy(origin, start);
|
||||
start[i] += size;
|
||||
VectorCopy(origin, end);
|
||||
end[i] -= size;
|
||||
AAS_DebugLine(start, end, color);
|
||||
debugline = botimport.DebugLineCreate();
|
||||
botimport.DebugLineShow(debugline, start, end, color);
|
||||
} //end for
|
||||
} //end of the function AAS_DrawPermanentCross
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_DrawPlaneCross(vec3_t point, vec3_t normal, float dist, int type, int color)
|
||||
{
|
||||
int n0, n1, n2, j, line, lines[2];
|
||||
vec3_t start1, end1, start2, end2;
|
||||
|
||||
//make a cross in the hit plane at the hit point
|
||||
VectorCopy(point, start1);
|
||||
VectorCopy(point, end1);
|
||||
VectorCopy(point, start2);
|
||||
VectorCopy(point, end2);
|
||||
|
||||
n0 = type % 3;
|
||||
n1 = (type + 1) % 3;
|
||||
n2 = (type + 2) % 3;
|
||||
start1[n1] -= 6;
|
||||
start1[n2] -= 6;
|
||||
end1[n1] += 6;
|
||||
end1[n2] += 6;
|
||||
start2[n1] += 6;
|
||||
start2[n2] -= 6;
|
||||
end2[n1] -= 6;
|
||||
end2[n2] += 6;
|
||||
|
||||
start1[n0] = (dist - (start1[n1] * normal[n1] +
|
||||
start1[n2] * normal[n2])) / normal[n0];
|
||||
end1[n0] = (dist - (end1[n1] * normal[n1] +
|
||||
end1[n2] * normal[n2])) / normal[n0];
|
||||
start2[n0] = (dist - (start2[n1] * normal[n1] +
|
||||
start2[n2] * normal[n2])) / normal[n0];
|
||||
end2[n0] = (dist - (end2[n1] * normal[n1] +
|
||||
end2[n2] * normal[n2])) / normal[n0];
|
||||
|
||||
for (j = 0, line = 0; j < 2 && line < MAX_DEBUGLINES; line++)
|
||||
{
|
||||
if (!debuglines[line])
|
||||
{
|
||||
debuglines[line] = botimport.DebugLineCreate();
|
||||
lines[j++] = debuglines[line];
|
||||
debuglinevisible[line] = qtrue;
|
||||
numdebuglines++;
|
||||
} //end if
|
||||
else if (!debuglinevisible[line])
|
||||
{
|
||||
lines[j++] = debuglines[line];
|
||||
debuglinevisible[line] = qtrue;
|
||||
} //end else
|
||||
} //end for
|
||||
botimport.DebugLineShow(lines[0], start1, end1, color);
|
||||
botimport.DebugLineShow(lines[1], start2, end2, color);
|
||||
} //end of the function AAS_DrawPlaneCross
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_ShowBoundingBox(vec3_t origin, vec3_t mins, vec3_t maxs)
|
||||
{
|
||||
vec3_t bboxcorners[8];
|
||||
int lines[3];
|
||||
int i, j, line;
|
||||
|
||||
//upper corners
|
||||
bboxcorners[0][0] = origin[0] + maxs[0];
|
||||
bboxcorners[0][1] = origin[1] + maxs[1];
|
||||
bboxcorners[0][2] = origin[2] + maxs[2];
|
||||
//
|
||||
bboxcorners[1][0] = origin[0] + mins[0];
|
||||
bboxcorners[1][1] = origin[1] + maxs[1];
|
||||
bboxcorners[1][2] = origin[2] + maxs[2];
|
||||
//
|
||||
bboxcorners[2][0] = origin[0] + mins[0];
|
||||
bboxcorners[2][1] = origin[1] + mins[1];
|
||||
bboxcorners[2][2] = origin[2] + maxs[2];
|
||||
//
|
||||
bboxcorners[3][0] = origin[0] + maxs[0];
|
||||
bboxcorners[3][1] = origin[1] + mins[1];
|
||||
bboxcorners[3][2] = origin[2] + maxs[2];
|
||||
//lower corners
|
||||
Com_Memcpy(bboxcorners[4], bboxcorners[0], sizeof(vec3_t) * 4);
|
||||
for (i = 0; i < 4; i++) bboxcorners[4 + i][2] = origin[2] + mins[2];
|
||||
//draw bounding box
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
for (j = 0, line = 0; j < 3 && line < MAX_DEBUGLINES; line++)
|
||||
{
|
||||
if (!debuglines[line])
|
||||
{
|
||||
debuglines[line] = botimport.DebugLineCreate();
|
||||
lines[j++] = debuglines[line];
|
||||
debuglinevisible[line] = qtrue;
|
||||
numdebuglines++;
|
||||
} //end if
|
||||
else if (!debuglinevisible[line])
|
||||
{
|
||||
lines[j++] = debuglines[line];
|
||||
debuglinevisible[line] = qtrue;
|
||||
} //end else
|
||||
} //end for
|
||||
//top plane
|
||||
botimport.DebugLineShow(lines[0], bboxcorners[i],
|
||||
bboxcorners[(i+1)&3], LINECOLOR_RED);
|
||||
//bottom plane
|
||||
botimport.DebugLineShow(lines[1], bboxcorners[4+i],
|
||||
bboxcorners[4+((i+1)&3)], LINECOLOR_RED);
|
||||
//vertical lines
|
||||
botimport.DebugLineShow(lines[2], bboxcorners[i],
|
||||
bboxcorners[4+i], LINECOLOR_RED);
|
||||
} //end for
|
||||
} //end of the function AAS_ShowBoundingBox
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_ShowFace(int facenum)
|
||||
{
|
||||
int i, color, edgenum;
|
||||
aas_edge_t *edge;
|
||||
aas_face_t *face;
|
||||
aas_plane_t *plane;
|
||||
vec3_t start, end;
|
||||
|
||||
color = LINECOLOR_YELLOW;
|
||||
//check if face number is in range
|
||||
if (facenum >= aasworld.numfaces)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "facenum %d out of range\n", facenum);
|
||||
} //end if
|
||||
face = &aasworld.faces[facenum];
|
||||
//walk through the edges of the face
|
||||
for (i = 0; i < face->numedges; i++)
|
||||
{
|
||||
//edge number
|
||||
edgenum = abs(aasworld.edgeindex[face->firstedge + i]);
|
||||
//check if edge number is in range
|
||||
if (edgenum >= aasworld.numedges)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "edgenum %d out of range\n", edgenum);
|
||||
} //end if
|
||||
edge = &aasworld.edges[edgenum];
|
||||
if (color == LINECOLOR_RED) color = LINECOLOR_GREEN;
|
||||
else if (color == LINECOLOR_GREEN) color = LINECOLOR_BLUE;
|
||||
else if (color == LINECOLOR_BLUE) color = LINECOLOR_YELLOW;
|
||||
else color = LINECOLOR_RED;
|
||||
AAS_DebugLine(aasworld.vertexes[edge->v[0]],
|
||||
aasworld.vertexes[edge->v[1]],
|
||||
color);
|
||||
} //end for
|
||||
plane = &aasworld.planes[face->planenum];
|
||||
edgenum = abs(aasworld.edgeindex[face->firstedge]);
|
||||
edge = &aasworld.edges[edgenum];
|
||||
VectorCopy(aasworld.vertexes[edge->v[0]], start);
|
||||
VectorMA(start, 20, plane->normal, end);
|
||||
AAS_DebugLine(start, end, LINECOLOR_RED);
|
||||
} //end of the function AAS_ShowFace
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_ShowFacePolygon(int facenum, int color, int flip)
|
||||
{
|
||||
int i, edgenum, numpoints;
|
||||
vec3_t points[128];
|
||||
aas_edge_t *edge;
|
||||
aas_face_t *face;
|
||||
|
||||
//check if face number is in range
|
||||
if (facenum >= aasworld.numfaces)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "facenum %d out of range\n", facenum);
|
||||
} //end if
|
||||
face = &aasworld.faces[facenum];
|
||||
//walk through the edges of the face
|
||||
numpoints = 0;
|
||||
if (flip)
|
||||
{
|
||||
for (i = face->numedges-1; i >= 0; i--)
|
||||
{
|
||||
//edge number
|
||||
edgenum = aasworld.edgeindex[face->firstedge + i];
|
||||
edge = &aasworld.edges[abs(edgenum)];
|
||||
VectorCopy(aasworld.vertexes[edge->v[edgenum < 0]], points[numpoints]);
|
||||
numpoints++;
|
||||
} //end for
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
for (i = 0; i < face->numedges; i++)
|
||||
{
|
||||
//edge number
|
||||
edgenum = aasworld.edgeindex[face->firstedge + i];
|
||||
edge = &aasworld.edges[abs(edgenum)];
|
||||
VectorCopy(aasworld.vertexes[edge->v[edgenum < 0]], points[numpoints]);
|
||||
numpoints++;
|
||||
} //end for
|
||||
} //end else
|
||||
AAS_ShowPolygon(color, numpoints, points);
|
||||
} //end of the function AAS_ShowFacePolygon
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_ShowArea(int areanum, int groundfacesonly)
|
||||
{
|
||||
int areaedges[MAX_DEBUGLINES];
|
||||
int numareaedges, i, j, n, color = 0, line;
|
||||
int facenum, edgenum;
|
||||
aas_area_t *area;
|
||||
aas_face_t *face;
|
||||
aas_edge_t *edge;
|
||||
|
||||
//
|
||||
numareaedges = 0;
|
||||
//
|
||||
if (areanum < 0 || areanum >= aasworld.numareas)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "area %d out of range [0, %d]\n",
|
||||
areanum, aasworld.numareas);
|
||||
return;
|
||||
} //end if
|
||||
//pointer to the convex area
|
||||
area = &aasworld.areas[areanum];
|
||||
//walk through the faces of the area
|
||||
for (i = 0; i < area->numfaces; i++)
|
||||
{
|
||||
facenum = abs(aasworld.faceindex[area->firstface + i]);
|
||||
//check if face number is in range
|
||||
if (facenum >= aasworld.numfaces)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "facenum %d out of range\n", facenum);
|
||||
} //end if
|
||||
face = &aasworld.faces[facenum];
|
||||
//ground faces only
|
||||
if (groundfacesonly)
|
||||
{
|
||||
if (!(face->faceflags & (FACE_GROUND | FACE_LADDER))) continue;
|
||||
} //end if
|
||||
//walk through the edges of the face
|
||||
for (j = 0; j < face->numedges; j++)
|
||||
{
|
||||
//edge number
|
||||
edgenum = abs(aasworld.edgeindex[face->firstedge + j]);
|
||||
//check if edge number is in range
|
||||
if (edgenum >= aasworld.numedges)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "edgenum %d out of range\n", edgenum);
|
||||
} //end if
|
||||
//check if the edge is stored already
|
||||
for (n = 0; n < numareaedges; n++)
|
||||
{
|
||||
if (areaedges[n] == edgenum) break;
|
||||
} //end for
|
||||
if (n == numareaedges && numareaedges < MAX_DEBUGLINES)
|
||||
{
|
||||
areaedges[numareaedges++] = edgenum;
|
||||
} //end if
|
||||
} //end for
|
||||
//AAS_ShowFace(facenum);
|
||||
} //end for
|
||||
//draw all the edges
|
||||
for (n = 0; n < numareaedges; n++)
|
||||
{
|
||||
for (line = 0; line < MAX_DEBUGLINES; line++)
|
||||
{
|
||||
if (!debuglines[line])
|
||||
{
|
||||
debuglines[line] = botimport.DebugLineCreate();
|
||||
debuglinevisible[line] = qfalse;
|
||||
numdebuglines++;
|
||||
} //end if
|
||||
if (!debuglinevisible[line])
|
||||
{
|
||||
break;
|
||||
} //end else
|
||||
} //end for
|
||||
if (line >= MAX_DEBUGLINES) return;
|
||||
edge = &aasworld.edges[areaedges[n]];
|
||||
if (color == LINECOLOR_RED) color = LINECOLOR_BLUE;
|
||||
else if (color == LINECOLOR_BLUE) color = LINECOLOR_GREEN;
|
||||
else if (color == LINECOLOR_GREEN) color = LINECOLOR_YELLOW;
|
||||
else color = LINECOLOR_RED;
|
||||
botimport.DebugLineShow(debuglines[line],
|
||||
aasworld.vertexes[edge->v[0]],
|
||||
aasworld.vertexes[edge->v[1]],
|
||||
color);
|
||||
debuglinevisible[line] = qtrue;
|
||||
} //end for*/
|
||||
} //end of the function AAS_ShowArea
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_ShowAreaPolygons(int areanum, int color, int groundfacesonly)
|
||||
{
|
||||
int i, facenum;
|
||||
aas_area_t *area;
|
||||
aas_face_t *face;
|
||||
|
||||
//
|
||||
if (areanum < 0 || areanum >= aasworld.numareas)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "area %d out of range [0, %d]\n",
|
||||
areanum, aasworld.numareas);
|
||||
return;
|
||||
} //end if
|
||||
//pointer to the convex area
|
||||
area = &aasworld.areas[areanum];
|
||||
//walk through the faces of the area
|
||||
for (i = 0; i < area->numfaces; i++)
|
||||
{
|
||||
facenum = abs(aasworld.faceindex[area->firstface + i]);
|
||||
//check if face number is in range
|
||||
if (facenum >= aasworld.numfaces)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "facenum %d out of range\n", facenum);
|
||||
} //end if
|
||||
face = &aasworld.faces[facenum];
|
||||
//ground faces only
|
||||
if (groundfacesonly)
|
||||
{
|
||||
if (!(face->faceflags & (FACE_GROUND | FACE_LADDER))) continue;
|
||||
} //end if
|
||||
AAS_ShowFacePolygon(facenum, color, face->frontarea != areanum);
|
||||
} //end for
|
||||
} //end of the function AAS_ShowAreaPolygons
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_DrawCross(vec3_t origin, float size, int color)
|
||||
{
|
||||
int i;
|
||||
vec3_t start, end;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
VectorCopy(origin, start);
|
||||
start[i] += size;
|
||||
VectorCopy(origin, end);
|
||||
end[i] -= size;
|
||||
AAS_DebugLine(start, end, color);
|
||||
} //end for
|
||||
} //end of the function AAS_DrawCross
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_PrintTravelType(int traveltype)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
char *str;
|
||||
//
|
||||
switch(traveltype & TRAVELTYPE_MASK)
|
||||
{
|
||||
case TRAVEL_INVALID: str = "TRAVEL_INVALID"; break;
|
||||
case TRAVEL_WALK: str = "TRAVEL_WALK"; break;
|
||||
case TRAVEL_CROUCH: str = "TRAVEL_CROUCH"; break;
|
||||
case TRAVEL_BARRIERJUMP: str = "TRAVEL_BARRIERJUMP"; break;
|
||||
case TRAVEL_JUMP: str = "TRAVEL_JUMP"; break;
|
||||
case TRAVEL_LADDER: str = "TRAVEL_LADDER"; break;
|
||||
case TRAVEL_WALKOFFLEDGE: str = "TRAVEL_WALKOFFLEDGE"; break;
|
||||
case TRAVEL_SWIM: str = "TRAVEL_SWIM"; break;
|
||||
case TRAVEL_WATERJUMP: str = "TRAVEL_WATERJUMP"; break;
|
||||
case TRAVEL_TELEPORT: str = "TRAVEL_TELEPORT"; break;
|
||||
case TRAVEL_ELEVATOR: str = "TRAVEL_ELEVATOR"; break;
|
||||
case TRAVEL_ROCKETJUMP: str = "TRAVEL_ROCKETJUMP"; break;
|
||||
case TRAVEL_BFGJUMP: str = "TRAVEL_BFGJUMP"; break;
|
||||
case TRAVEL_GRAPPLEHOOK: str = "TRAVEL_GRAPPLEHOOK"; break;
|
||||
case TRAVEL_JUMPPAD: str = "TRAVEL_JUMPPAD"; break;
|
||||
case TRAVEL_FUNCBOB: str = "TRAVEL_FUNCBOB"; break;
|
||||
default: str = "UNKNOWN TRAVEL TYPE"; break;
|
||||
} //end switch
|
||||
botimport.Print(PRT_MESSAGE, "%s", str);
|
||||
#endif
|
||||
} //end of the function AAS_PrintTravelType
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_DrawArrow(vec3_t start, vec3_t end, int linecolor, int arrowcolor)
|
||||
{
|
||||
vec3_t dir, cross, p1, p2, up = {0, 0, 1};
|
||||
float dot;
|
||||
|
||||
VectorSubtract(end, start, dir);
|
||||
VectorNormalize(dir);
|
||||
dot = DotProduct(dir, up);
|
||||
if (dot > 0.99 || dot < -0.99) VectorSet(cross, 1, 0, 0);
|
||||
else CrossProduct(dir, up, cross);
|
||||
|
||||
VectorMA(end, -6, dir, p1);
|
||||
VectorCopy(p1, p2);
|
||||
VectorMA(p1, 6, cross, p1);
|
||||
VectorMA(p2, -6, cross, p2);
|
||||
|
||||
AAS_DebugLine(start, end, linecolor);
|
||||
AAS_DebugLine(p1, end, arrowcolor);
|
||||
AAS_DebugLine(p2, end, arrowcolor);
|
||||
} //end of the function AAS_DrawArrow
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_ShowReachability(aas_reachability_t *reach)
|
||||
{
|
||||
vec3_t dir, cmdmove, velocity;
|
||||
float speed, zvel;
|
||||
aas_clientmove_t move;
|
||||
|
||||
AAS_ShowAreaPolygons(reach->areanum, 5, qtrue);
|
||||
//AAS_ShowArea(reach->areanum, qtrue);
|
||||
AAS_DrawArrow(reach->start, reach->end, LINECOLOR_BLUE, LINECOLOR_YELLOW);
|
||||
//
|
||||
if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMP ||
|
||||
(reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_WALKOFFLEDGE)
|
||||
{
|
||||
AAS_HorizontalVelocityForJump(aassettings.phys_jumpvel, reach->start, reach->end, &speed);
|
||||
//
|
||||
VectorSubtract(reach->end, reach->start, dir);
|
||||
dir[2] = 0;
|
||||
VectorNormalize(dir);
|
||||
//set the velocity
|
||||
VectorScale(dir, speed, velocity);
|
||||
//set the command movement
|
||||
VectorClear(cmdmove);
|
||||
cmdmove[2] = aassettings.phys_jumpvel;
|
||||
//
|
||||
AAS_PredictClientMovement(&move, -1, reach->start, PRESENCE_NORMAL, qtrue,
|
||||
velocity, cmdmove, 3, 30, 0.1f,
|
||||
SE_HITGROUND|SE_ENTERWATER|SE_ENTERSLIME|
|
||||
SE_ENTERLAVA|SE_HITGROUNDDAMAGE, 0, qtrue);
|
||||
//
|
||||
if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMP)
|
||||
{
|
||||
AAS_JumpReachRunStart(reach, dir);
|
||||
AAS_DrawCross(dir, 4, LINECOLOR_BLUE);
|
||||
} //end if
|
||||
} //end if
|
||||
else if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_ROCKETJUMP)
|
||||
{
|
||||
zvel = AAS_RocketJumpZVelocity(reach->start);
|
||||
AAS_HorizontalVelocityForJump(zvel, reach->start, reach->end, &speed);
|
||||
//
|
||||
VectorSubtract(reach->end, reach->start, dir);
|
||||
dir[2] = 0;
|
||||
VectorNormalize(dir);
|
||||
//get command movement
|
||||
VectorScale(dir, speed, cmdmove);
|
||||
VectorSet(velocity, 0, 0, zvel);
|
||||
//
|
||||
AAS_PredictClientMovement(&move, -1, reach->start, PRESENCE_NORMAL, qtrue,
|
||||
velocity, cmdmove, 30, 30, 0.1f,
|
||||
SE_ENTERWATER|SE_ENTERSLIME|
|
||||
SE_ENTERLAVA|SE_HITGROUNDDAMAGE|
|
||||
SE_TOUCHJUMPPAD|SE_HITGROUNDAREA, reach->areanum, qtrue);
|
||||
} //end else if
|
||||
else if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMPPAD)
|
||||
{
|
||||
VectorSet(cmdmove, 0, 0, 0);
|
||||
//
|
||||
VectorSubtract(reach->end, reach->start, dir);
|
||||
dir[2] = 0;
|
||||
VectorNormalize(dir);
|
||||
//set the velocity
|
||||
//NOTE: the edgenum is the horizontal velocity
|
||||
VectorScale(dir, reach->edgenum, velocity);
|
||||
//NOTE: the facenum is the Z velocity
|
||||
velocity[2] = reach->facenum;
|
||||
//
|
||||
AAS_PredictClientMovement(&move, -1, reach->start, PRESENCE_NORMAL, qtrue,
|
||||
velocity, cmdmove, 30, 30, 0.1f,
|
||||
SE_ENTERWATER|SE_ENTERSLIME|
|
||||
SE_ENTERLAVA|SE_HITGROUNDDAMAGE|
|
||||
SE_TOUCHJUMPPAD|SE_HITGROUNDAREA, reach->areanum, qtrue);
|
||||
} //end else if
|
||||
} //end of the function AAS_ShowReachability
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_ShowReachableAreas(int areanum)
|
||||
{
|
||||
aas_areasettings_t *settings;
|
||||
static aas_reachability_t reach;
|
||||
static int index, lastareanum;
|
||||
static float lasttime;
|
||||
|
||||
if (areanum != lastareanum)
|
||||
{
|
||||
index = 0;
|
||||
lastareanum = areanum;
|
||||
} //end if
|
||||
settings = &aasworld.areasettings[areanum];
|
||||
//
|
||||
if (!settings->numreachableareas) return;
|
||||
//
|
||||
if (index >= settings->numreachableareas) index = 0;
|
||||
//
|
||||
if (AAS_Time() - lasttime > 1.5)
|
||||
{
|
||||
Com_Memcpy(&reach, &aasworld.reachability[settings->firstreachablearea + index], sizeof(aas_reachability_t));
|
||||
index++;
|
||||
lasttime = AAS_Time();
|
||||
AAS_PrintTravelType(reach.traveltype & TRAVELTYPE_MASK);
|
||||
botimport.Print(PRT_MESSAGE, "\n");
|
||||
} //end if
|
||||
AAS_ShowReachability(&reach);
|
||||
} //end of the function ShowReachableAreas
|
||||
|
||||
void AAS_FloodAreas_r(int areanum, int cluster, int *done)
|
||||
{
|
||||
int nextareanum, i, facenum;
|
||||
aas_area_t *area;
|
||||
aas_face_t *face;
|
||||
aas_areasettings_t *settings;
|
||||
aas_reachability_t *reach;
|
||||
|
||||
AAS_ShowAreaPolygons(areanum, 1, qtrue);
|
||||
//pointer to the convex area
|
||||
area = &aasworld.areas[areanum];
|
||||
settings = &aasworld.areasettings[areanum];
|
||||
//walk through the faces of the area
|
||||
for (i = 0; i < area->numfaces; i++)
|
||||
{
|
||||
facenum = abs(aasworld.faceindex[area->firstface + i]);
|
||||
face = &aasworld.faces[facenum];
|
||||
if (face->frontarea == areanum)
|
||||
nextareanum = face->backarea;
|
||||
else
|
||||
nextareanum = face->frontarea;
|
||||
if (!nextareanum)
|
||||
continue;
|
||||
if (done[nextareanum])
|
||||
continue;
|
||||
done[nextareanum] = qtrue;
|
||||
if (aasworld.areasettings[nextareanum].contents & AREACONTENTS_VIEWPORTAL)
|
||||
continue;
|
||||
if (AAS_AreaCluster(nextareanum) != cluster)
|
||||
continue;
|
||||
AAS_FloodAreas_r(nextareanum, cluster, done);
|
||||
} //end for
|
||||
//
|
||||
for (i = 0; i < settings->numreachableareas; i++)
|
||||
{
|
||||
reach = &aasworld.reachability[settings->firstreachablearea + i];
|
||||
nextareanum = reach->areanum;
|
||||
if (!nextareanum)
|
||||
continue;
|
||||
if (done[nextareanum])
|
||||
continue;
|
||||
done[nextareanum] = qtrue;
|
||||
if (aasworld.areasettings[nextareanum].contents & AREACONTENTS_VIEWPORTAL)
|
||||
continue;
|
||||
if (AAS_AreaCluster(nextareanum) != cluster)
|
||||
continue;
|
||||
/*
|
||||
if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_WALKOFFLEDGE)
|
||||
{
|
||||
AAS_DebugLine(reach->start, reach->end, 1);
|
||||
}
|
||||
*/
|
||||
AAS_FloodAreas_r(nextareanum, cluster, done);
|
||||
}
|
||||
}
|
||||
|
||||
void AAS_FloodAreas(vec3_t origin)
|
||||
{
|
||||
int areanum, cluster, *done;
|
||||
|
||||
done = (int *) GetClearedMemory(aasworld.numareas * sizeof(int));
|
||||
areanum = AAS_PointAreaNum(origin);
|
||||
cluster = AAS_AreaCluster(areanum);
|
||||
AAS_FloodAreas_r(areanum, cluster, done);
|
||||
}
|
45
CODEmp/botlib/be_aas_debug.h
Normal file
45
CODEmp/botlib/be_aas_debug.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_debug.h
|
||||
*
|
||||
* desc: AAS
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_aas_debug.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//clear the shown debug lines
|
||||
void AAS_ClearShownDebugLines(void);
|
||||
//
|
||||
void AAS_ClearShownPolygons(void);
|
||||
//show a debug line
|
||||
void AAS_DebugLine(vec3_t start, vec3_t end, int color);
|
||||
//show a permenent line
|
||||
void AAS_PermanentLine(vec3_t start, vec3_t end, int color);
|
||||
//show a permanent cross
|
||||
void AAS_DrawPermanentCross(vec3_t origin, float size, int color);
|
||||
//draw a cross in the plane
|
||||
void AAS_DrawPlaneCross(vec3_t point, vec3_t normal, float dist, int type, int color);
|
||||
//show a bounding box
|
||||
void AAS_ShowBoundingBox(vec3_t origin, vec3_t mins, vec3_t maxs);
|
||||
//show a face
|
||||
void AAS_ShowFace(int facenum);
|
||||
//show an area
|
||||
void AAS_ShowArea(int areanum, int groundfacesonly);
|
||||
//
|
||||
void AAS_ShowAreaPolygons(int areanum, int color, int groundfacesonly);
|
||||
//draw a cros
|
||||
void AAS_DrawCross(vec3_t origin, float size, int color);
|
||||
//print the travel type
|
||||
void AAS_PrintTravelType(int traveltype);
|
||||
//draw an arrow
|
||||
void AAS_DrawArrow(vec3_t start, vec3_t end, int linecolor, int arrowcolor);
|
||||
//visualize the given reachability
|
||||
void AAS_ShowReachability(struct aas_reachability_s *reach);
|
||||
//show the reachable areas from the given area
|
||||
void AAS_ShowReachableAreas(int areanum);
|
||||
|
290
CODEmp/botlib/be_aas_def.h
Normal file
290
CODEmp/botlib/be_aas_def.h
Normal file
|
@ -0,0 +1,290 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_def.h
|
||||
*
|
||||
* desc: AAS
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_aas_def.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//debugging on
|
||||
#define AAS_DEBUG
|
||||
|
||||
// these are also in q_shared.h - argh (rjr)
|
||||
#define MAX_CLIENTS 64
|
||||
#define MAX_MODELS 256 // these are sent over the net as 8 bits
|
||||
#define MAX_SOUNDS 256 // so they cannot be blindly increased
|
||||
|
||||
// these are also in bg_public.h - argh (rjr)
|
||||
#define CS_SCORES 32
|
||||
#define CS_MODELS (CS_SCORES+MAX_CLIENTS)
|
||||
#define CS_SOUNDS (CS_MODELS+MAX_MODELS)
|
||||
|
||||
#define DF_AASENTNUMBER(x) (x - aasworld.entities)
|
||||
#define DF_NUMBERAASENT(x) (&aasworld.entities[x])
|
||||
#define DF_AASENTCLIENT(x) (x - aasworld.entities - 1)
|
||||
#define DF_CLIENTAASENT(x) (&aasworld.entities[x + 1])
|
||||
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH MAX_QPATH
|
||||
#endif
|
||||
|
||||
//string index (for model, sound and image index)
|
||||
typedef struct aas_stringindex_s
|
||||
{
|
||||
int numindexes;
|
||||
char **index;
|
||||
} aas_stringindex_t;
|
||||
|
||||
//structure to link entities to areas and areas to entities
|
||||
typedef struct aas_link_s
|
||||
{
|
||||
int entnum;
|
||||
int areanum;
|
||||
struct aas_link_s *next_ent, *prev_ent;
|
||||
struct aas_link_s *next_area, *prev_area;
|
||||
} aas_link_t;
|
||||
|
||||
//structure to link entities to leaves and leaves to entities
|
||||
typedef struct bsp_link_s
|
||||
{
|
||||
int entnum;
|
||||
int leafnum;
|
||||
struct bsp_link_s *next_ent, *prev_ent;
|
||||
struct bsp_link_s *next_leaf, *prev_leaf;
|
||||
} bsp_link_t;
|
||||
|
||||
typedef struct bsp_entdata_s
|
||||
{
|
||||
vec3_t origin;
|
||||
vec3_t angles;
|
||||
vec3_t absmins;
|
||||
vec3_t absmaxs;
|
||||
int solid;
|
||||
int modelnum;
|
||||
} bsp_entdata_t;
|
||||
|
||||
//entity
|
||||
typedef struct aas_entity_s
|
||||
{
|
||||
//entity info
|
||||
aas_entityinfo_t i;
|
||||
//links into the AAS areas
|
||||
aas_link_t *areas;
|
||||
//links into the BSP leaves
|
||||
bsp_link_t *leaves;
|
||||
} aas_entity_t;
|
||||
|
||||
typedef struct aas_settings_s
|
||||
{
|
||||
vec3_t phys_gravitydirection;
|
||||
float phys_friction;
|
||||
float phys_stopspeed;
|
||||
float phys_gravity;
|
||||
float phys_waterfriction;
|
||||
float phys_watergravity;
|
||||
float phys_maxvelocity;
|
||||
float phys_maxwalkvelocity;
|
||||
float phys_maxcrouchvelocity;
|
||||
float phys_maxswimvelocity;
|
||||
float phys_walkaccelerate;
|
||||
float phys_airaccelerate;
|
||||
float phys_swimaccelerate;
|
||||
float phys_maxstep;
|
||||
float phys_maxsteepness;
|
||||
float phys_maxwaterjump;
|
||||
float phys_maxbarrier;
|
||||
float phys_jumpvel;
|
||||
float phys_falldelta5;
|
||||
float phys_falldelta10;
|
||||
float rs_waterjump;
|
||||
float rs_teleport;
|
||||
float rs_barrierjump;
|
||||
float rs_startcrouch;
|
||||
float rs_startgrapple;
|
||||
float rs_startwalkoffledge;
|
||||
float rs_startjump;
|
||||
float rs_rocketjump;
|
||||
float rs_bfgjump;
|
||||
float rs_jumppad;
|
||||
float rs_aircontrolledjumppad;
|
||||
float rs_funcbob;
|
||||
float rs_startelevator;
|
||||
float rs_falldamage5;
|
||||
float rs_falldamage10;
|
||||
float rs_maxfallheight;
|
||||
float rs_maxjumpfallheight;
|
||||
} aas_settings_t;
|
||||
|
||||
#define CACHETYPE_PORTAL 0
|
||||
#define CACHETYPE_AREA 1
|
||||
|
||||
//routing cache
|
||||
typedef struct aas_routingcache_s
|
||||
{
|
||||
byte type; //portal or area cache
|
||||
float time; //last time accessed or updated
|
||||
int size; //size of the routing cache
|
||||
int cluster; //cluster the cache is for
|
||||
int areanum; //area the cache is created for
|
||||
vec3_t origin; //origin within the area
|
||||
float starttraveltime; //travel time to start with
|
||||
int travelflags; //combinations of the travel flags
|
||||
struct aas_routingcache_s *prev, *next;
|
||||
struct aas_routingcache_s *time_prev, *time_next;
|
||||
unsigned char *reachabilities; //reachabilities used for routing
|
||||
unsigned short int traveltimes[1]; //travel time for every area (variable sized)
|
||||
} aas_routingcache_t;
|
||||
|
||||
//fields for the routing algorithm
|
||||
typedef struct aas_routingupdate_s
|
||||
{
|
||||
int cluster;
|
||||
int areanum; //area number of the update
|
||||
vec3_t start; //start point the area was entered
|
||||
unsigned short int tmptraveltime; //temporary travel time
|
||||
unsigned short int *areatraveltimes; //travel times within the area
|
||||
qboolean inlist; //true if the update is in the list
|
||||
struct aas_routingupdate_s *next;
|
||||
struct aas_routingupdate_s *prev;
|
||||
} aas_routingupdate_t;
|
||||
|
||||
//reversed reachability link
|
||||
typedef struct aas_reversedlink_s
|
||||
{
|
||||
int linknum; //the aas_areareachability_t
|
||||
int areanum; //reachable from this area
|
||||
struct aas_reversedlink_s *next; //next link
|
||||
} aas_reversedlink_t;
|
||||
|
||||
//reversed area reachability
|
||||
typedef struct aas_reversedreachability_s
|
||||
{
|
||||
int numlinks;
|
||||
aas_reversedlink_t *first;
|
||||
} aas_reversedreachability_t;
|
||||
|
||||
//areas a reachability goes through
|
||||
typedef struct aas_reachabilityareas_s
|
||||
{
|
||||
int firstarea, numareas;
|
||||
} aas_reachabilityareas_t;
|
||||
|
||||
typedef struct aas_s
|
||||
{
|
||||
int loaded; //true when an AAS file is loaded
|
||||
int initialized; //true when AAS has been initialized
|
||||
int savefile; //set true when file should be saved
|
||||
int bspchecksum;
|
||||
//current time
|
||||
float time;
|
||||
int numframes;
|
||||
//name of the aas file
|
||||
char filename[MAX_PATH];
|
||||
char mapname[MAX_PATH];
|
||||
//bounding boxes
|
||||
int numbboxes;
|
||||
aas_bbox_t *bboxes;
|
||||
//vertexes
|
||||
int numvertexes;
|
||||
aas_vertex_t *vertexes;
|
||||
//planes
|
||||
int numplanes;
|
||||
aas_plane_t *planes;
|
||||
//edges
|
||||
int numedges;
|
||||
aas_edge_t *edges;
|
||||
//edge index
|
||||
int edgeindexsize;
|
||||
aas_edgeindex_t *edgeindex;
|
||||
//faces
|
||||
int numfaces;
|
||||
aas_face_t *faces;
|
||||
//face index
|
||||
int faceindexsize;
|
||||
aas_faceindex_t *faceindex;
|
||||
//convex areas
|
||||
int numareas;
|
||||
aas_area_t *areas;
|
||||
//convex area settings
|
||||
int numareasettings;
|
||||
aas_areasettings_t *areasettings;
|
||||
//reachablity list
|
||||
int reachabilitysize;
|
||||
aas_reachability_t *reachability;
|
||||
//nodes of the bsp tree
|
||||
int numnodes;
|
||||
aas_node_t *nodes;
|
||||
//cluster portals
|
||||
int numportals;
|
||||
aas_portal_t *portals;
|
||||
//cluster portal index
|
||||
int portalindexsize;
|
||||
aas_portalindex_t *portalindex;
|
||||
//clusters
|
||||
int numclusters;
|
||||
aas_cluster_t *clusters;
|
||||
//
|
||||
int numreachabilityareas;
|
||||
float reachabilitytime;
|
||||
//enities linked in the areas
|
||||
aas_link_t *linkheap; //heap with link structures
|
||||
int linkheapsize; //size of the link heap
|
||||
aas_link_t *freelinks; //first free link
|
||||
aas_link_t **arealinkedentities; //entities linked into areas
|
||||
//entities
|
||||
int maxentities;
|
||||
int maxclients;
|
||||
aas_entity_t *entities;
|
||||
//string indexes
|
||||
char *configstrings[MAX_CONFIGSTRINGS];
|
||||
int indexessetup;
|
||||
//index to retrieve travel flag for a travel type
|
||||
int travelflagfortype[MAX_TRAVELTYPES];
|
||||
//travel flags for each area based on contents
|
||||
int *areacontentstravelflags;
|
||||
//routing update
|
||||
aas_routingupdate_t *areaupdate;
|
||||
aas_routingupdate_t *portalupdate;
|
||||
//number of routing updates during a frame (reset every frame)
|
||||
int frameroutingupdates;
|
||||
//reversed reachability links
|
||||
aas_reversedreachability_t *reversedreachability;
|
||||
//travel times within the areas
|
||||
unsigned short ***areatraveltimes;
|
||||
//array of size numclusters with cluster cache
|
||||
aas_routingcache_t ***clusterareacache;
|
||||
aas_routingcache_t **portalcache;
|
||||
//cache list sorted on time
|
||||
aas_routingcache_t *oldestcache; // start of cache list sorted on time
|
||||
aas_routingcache_t *newestcache; // end of cache list sorted on time
|
||||
//maximum travel time through portal areas
|
||||
int *portalmaxtraveltimes;
|
||||
//areas the reachabilities go through
|
||||
int *reachabilityareaindex;
|
||||
aas_reachabilityareas_t *reachabilityareas;
|
||||
} aas_t;
|
||||
|
||||
#define AASINTERN
|
||||
|
||||
#ifndef BSPCINCLUDE
|
||||
|
||||
#include "be_aas_main.h"
|
||||
#include "be_aas_entity.h"
|
||||
#include "be_aas_sample.h"
|
||||
#include "be_aas_cluster.h"
|
||||
#include "be_aas_reach.h"
|
||||
#include "be_aas_route.h"
|
||||
#include "be_aas_routealt.h"
|
||||
#include "be_aas_debug.h"
|
||||
#include "be_aas_file.h"
|
||||
#include "be_aas_optimize.h"
|
||||
#include "be_aas_bsp.h"
|
||||
#include "be_aas_move.h"
|
||||
|
||||
#endif //BSPCINCLUDE
|
420
CODEmp/botlib/be_aas_entity.cpp
Normal file
420
CODEmp/botlib/be_aas_entity.cpp
Normal file
|
@ -0,0 +1,420 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_entity.c
|
||||
*
|
||||
* desc: AAS entities
|
||||
*
|
||||
* $Archive: /MissionPack/code/botlib/be_aas_entity.c $
|
||||
* $Author: Zaphod $
|
||||
* $Revision: 11 $
|
||||
* $Modtime: 11/22/00 8:50a $
|
||||
* $Date: 11/22/00 8:55a $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "l_memory.h"
|
||||
#include "l_script.h"
|
||||
#include "l_precomp.h"
|
||||
#include "l_struct.h"
|
||||
#include "l_utils.h"
|
||||
#include "l_log.h"
|
||||
#include "aasfile.h"
|
||||
#include "../game/botlib.h"
|
||||
#include "../game/be_aas.h"
|
||||
#include "be_aas_funcs.h"
|
||||
#include "be_interface.h"
|
||||
#include "be_aas_def.h"
|
||||
|
||||
#define MASK_SOLID CONTENTS_PLAYERCLIP
|
||||
|
||||
//FIXME: these might change
|
||||
enum {
|
||||
ET_GENERAL,
|
||||
ET_PLAYER,
|
||||
ET_ITEM,
|
||||
ET_MISSILE,
|
||||
ET_MOVER
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_UpdateEntity(int entnum, bot_entitystate_t *state)
|
||||
{
|
||||
int relink;
|
||||
aas_entity_t *ent;
|
||||
vec3_t absmins, absmaxs;
|
||||
|
||||
if (!aasworld.loaded)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "AAS_UpdateEntity: not loaded\n");
|
||||
return BLERR_NOAASFILE;
|
||||
} //end if
|
||||
|
||||
ent = &aasworld.entities[entnum];
|
||||
|
||||
if (!state) {
|
||||
//unlink the entity
|
||||
AAS_UnlinkFromAreas(ent->areas);
|
||||
//unlink the entity from the BSP leaves
|
||||
AAS_UnlinkFromBSPLeaves(ent->leaves);
|
||||
//
|
||||
ent->areas = NULL;
|
||||
//
|
||||
ent->leaves = NULL;
|
||||
return BLERR_NOERROR;
|
||||
}
|
||||
|
||||
ent->i.update_time = AAS_Time() - ent->i.ltime;
|
||||
ent->i.type = state->type;
|
||||
ent->i.flags = state->flags;
|
||||
ent->i.ltime = AAS_Time();
|
||||
VectorCopy(ent->i.origin, ent->i.lastvisorigin);
|
||||
VectorCopy(state->old_origin, ent->i.old_origin);
|
||||
ent->i.solid = state->solid;
|
||||
ent->i.groundent = state->groundent;
|
||||
ent->i.modelindex = state->modelindex;
|
||||
ent->i.modelindex2 = state->modelindex2;
|
||||
ent->i.frame = state->frame;
|
||||
ent->i.event = state->event;
|
||||
ent->i.eventParm = state->eventParm;
|
||||
ent->i.powerups = state->powerups;
|
||||
ent->i.weapon = state->weapon;
|
||||
ent->i.legsAnim = state->legsAnim;
|
||||
ent->i.torsoAnim = state->torsoAnim;
|
||||
//number of the entity
|
||||
ent->i.number = entnum;
|
||||
//updated so set valid flag
|
||||
ent->i.valid = qtrue;
|
||||
//link everything the first frame
|
||||
if (aasworld.numframes == 1) relink = qtrue;
|
||||
else relink = qfalse;
|
||||
//
|
||||
if (ent->i.solid == SOLID_BSP)
|
||||
{
|
||||
//if the angles of the model changed
|
||||
if (!VectorCompare(state->angles, ent->i.angles))
|
||||
{
|
||||
VectorCopy(state->angles, ent->i.angles);
|
||||
relink = qtrue;
|
||||
} //end if
|
||||
//get the mins and maxs of the model
|
||||
//FIXME: rotate mins and maxs
|
||||
AAS_BSPModelMinsMaxsOrigin(ent->i.modelindex, ent->i.angles, ent->i.mins, ent->i.maxs, NULL);
|
||||
} //end if
|
||||
else if (ent->i.solid == SOLID_BBOX)
|
||||
{
|
||||
//if the bounding box size changed
|
||||
if (!VectorCompare(state->mins, ent->i.mins) ||
|
||||
!VectorCompare(state->maxs, ent->i.maxs))
|
||||
{
|
||||
VectorCopy(state->mins, ent->i.mins);
|
||||
VectorCopy(state->maxs, ent->i.maxs);
|
||||
relink = qtrue;
|
||||
} //end if
|
||||
VectorCopy(state->angles, ent->i.angles);
|
||||
} //end if
|
||||
//if the origin changed
|
||||
if (!VectorCompare(state->origin, ent->i.origin))
|
||||
{
|
||||
VectorCopy(state->origin, ent->i.origin);
|
||||
relink = qtrue;
|
||||
} //end if
|
||||
//if the entity should be relinked
|
||||
if (relink)
|
||||
{
|
||||
//don't link the world model
|
||||
if (entnum != ENTITYNUM_WORLD)
|
||||
{
|
||||
//absolute mins and maxs
|
||||
VectorAdd(ent->i.mins, ent->i.origin, absmins);
|
||||
VectorAdd(ent->i.maxs, ent->i.origin, absmaxs);
|
||||
//unlink the entity
|
||||
AAS_UnlinkFromAreas(ent->areas);
|
||||
//relink the entity to the AAS areas (use the larges bbox)
|
||||
ent->areas = AAS_LinkEntityClientBBox(absmins, absmaxs, entnum, PRESENCE_NORMAL);
|
||||
//unlink the entity from the BSP leaves
|
||||
AAS_UnlinkFromBSPLeaves(ent->leaves);
|
||||
//link the entity to the world BSP tree
|
||||
ent->leaves = AAS_BSPLinkEntity(absmins, absmaxs, entnum, 0);
|
||||
} //end if
|
||||
} //end if
|
||||
return BLERR_NOERROR;
|
||||
} //end of the function AAS_UpdateEntity
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_EntityInfo(int entnum, aas_entityinfo_t *info)
|
||||
{
|
||||
if (!aasworld.initialized)
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "AAS_EntityInfo: aasworld not initialized\n");
|
||||
Com_Memset(info, 0, sizeof(aas_entityinfo_t));
|
||||
return;
|
||||
} //end if
|
||||
|
||||
if (entnum < 0 || entnum >= aasworld.maxentities)
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "AAS_EntityInfo: entnum %d out of range\n", entnum);
|
||||
Com_Memset(info, 0, sizeof(aas_entityinfo_t));
|
||||
return;
|
||||
} //end if
|
||||
|
||||
Com_Memcpy(info, &aasworld.entities[entnum].i, sizeof(aas_entityinfo_t));
|
||||
} //end of the function AAS_EntityInfo
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_EntityOrigin(int entnum, vec3_t origin)
|
||||
{
|
||||
if (entnum < 0 || entnum >= aasworld.maxentities)
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "AAS_EntityOrigin: entnum %d out of range\n", entnum);
|
||||
VectorClear(origin);
|
||||
return;
|
||||
} //end if
|
||||
|
||||
VectorCopy(aasworld.entities[entnum].i.origin, origin);
|
||||
} //end of the function AAS_EntityOrigin
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_EntityModelindex(int entnum)
|
||||
{
|
||||
if (entnum < 0 || entnum >= aasworld.maxentities)
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "AAS_EntityModelindex: entnum %d out of range\n", entnum);
|
||||
return 0;
|
||||
} //end if
|
||||
return aasworld.entities[entnum].i.modelindex;
|
||||
} //end of the function AAS_EntityModelindex
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_EntityType(int entnum)
|
||||
{
|
||||
if (!aasworld.initialized) return 0;
|
||||
|
||||
if (entnum < 0 || entnum >= aasworld.maxentities)
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "AAS_EntityType: entnum %d out of range\n", entnum);
|
||||
return 0;
|
||||
} //end if
|
||||
return aasworld.entities[entnum].i.type;
|
||||
} //end of the AAS_EntityType
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_EntityModelNum(int entnum)
|
||||
{
|
||||
if (!aasworld.initialized) return 0;
|
||||
|
||||
if (entnum < 0 || entnum >= aasworld.maxentities)
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "AAS_EntityModelNum: entnum %d out of range\n", entnum);
|
||||
return 0;
|
||||
} //end if
|
||||
return aasworld.entities[entnum].i.modelindex;
|
||||
} //end of the function AAS_EntityModelNum
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_OriginOfMoverWithModelNum(int modelnum, vec3_t origin)
|
||||
{
|
||||
int i;
|
||||
aas_entity_t *ent;
|
||||
|
||||
for (i = 0; i < aasworld.maxentities; i++)
|
||||
{
|
||||
ent = &aasworld.entities[i];
|
||||
if (ent->i.type == ET_MOVER)
|
||||
{
|
||||
if (ent->i.modelindex == modelnum)
|
||||
{
|
||||
VectorCopy(ent->i.origin, origin);
|
||||
return qtrue;
|
||||
} //end if
|
||||
} //end if
|
||||
} //end for
|
||||
return qfalse;
|
||||
} //end of the function AAS_OriginOfMoverWithModelNum
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_EntitySize(int entnum, vec3_t mins, vec3_t maxs)
|
||||
{
|
||||
aas_entity_t *ent;
|
||||
|
||||
if (!aasworld.initialized) return;
|
||||
|
||||
if (entnum < 0 || entnum >= aasworld.maxentities)
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "AAS_EntitySize: entnum %d out of range\n", entnum);
|
||||
return;
|
||||
} //end if
|
||||
|
||||
ent = &aasworld.entities[entnum];
|
||||
VectorCopy(ent->i.mins, mins);
|
||||
VectorCopy(ent->i.maxs, maxs);
|
||||
} //end of the function AAS_EntitySize
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_EntityBSPData(int entnum, bsp_entdata_t *entdata)
|
||||
{
|
||||
aas_entity_t *ent;
|
||||
|
||||
ent = &aasworld.entities[entnum];
|
||||
VectorCopy(ent->i.origin, entdata->origin);
|
||||
VectorCopy(ent->i.angles, entdata->angles);
|
||||
VectorAdd(ent->i.origin, ent->i.mins, entdata->absmins);
|
||||
VectorAdd(ent->i.origin, ent->i.maxs, entdata->absmaxs);
|
||||
entdata->solid = ent->i.solid;
|
||||
entdata->modelnum = ent->i.modelindex - 1;
|
||||
} //end of the function AAS_EntityBSPData
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_ResetEntityLinks(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < aasworld.maxentities; i++)
|
||||
{
|
||||
aasworld.entities[i].areas = NULL;
|
||||
aasworld.entities[i].leaves = NULL;
|
||||
} //end for
|
||||
} //end of the function AAS_ResetEntityLinks
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_InvalidateEntities(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < aasworld.maxentities; i++)
|
||||
{
|
||||
aasworld.entities[i].i.valid = qfalse;
|
||||
aasworld.entities[i].i.number = i;
|
||||
} //end for
|
||||
} //end of the function AAS_InvalidateEntities
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_UnlinkInvalidEntities(void)
|
||||
{
|
||||
int i;
|
||||
aas_entity_t *ent;
|
||||
|
||||
for (i = 0; i < aasworld.maxentities; i++)
|
||||
{
|
||||
ent = &aasworld.entities[i];
|
||||
if (!ent->i.valid)
|
||||
{
|
||||
AAS_UnlinkFromAreas( ent->areas );
|
||||
ent->areas = NULL;
|
||||
AAS_UnlinkFromBSPLeaves( ent->leaves );
|
||||
ent->leaves = NULL;
|
||||
} //end for
|
||||
} //end for
|
||||
} //end of the function AAS_UnlinkInvalidEntities
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_NearestEntity(vec3_t origin, int modelindex)
|
||||
{
|
||||
int i, bestentnum;
|
||||
float dist, bestdist;
|
||||
aas_entity_t *ent;
|
||||
vec3_t dir;
|
||||
|
||||
bestentnum = 0;
|
||||
bestdist = 99999;
|
||||
for (i = 0; i < aasworld.maxentities; i++)
|
||||
{
|
||||
ent = &aasworld.entities[i];
|
||||
if (ent->i.modelindex != modelindex) continue;
|
||||
VectorSubtract(ent->i.origin, origin, dir);
|
||||
if (abs(dir[0]) < 40)
|
||||
{
|
||||
if (abs(dir[1]) < 40)
|
||||
{
|
||||
dist = VectorLength(dir);
|
||||
if (dist < bestdist)
|
||||
{
|
||||
bestdist = dist;
|
||||
bestentnum = i;
|
||||
} //end if
|
||||
} //end if
|
||||
} //end if
|
||||
} //end for
|
||||
return bestentnum;
|
||||
} //end of the function AAS_NearestEntity
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_BestReachableEntityArea(int entnum)
|
||||
{
|
||||
aas_entity_t *ent;
|
||||
|
||||
ent = &aasworld.entities[entnum];
|
||||
return AAS_BestReachableLinkArea(ent->areas);
|
||||
} //end of the function AAS_BestReachableEntityArea
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_NextEntity(int entnum)
|
||||
{
|
||||
if (!aasworld.loaded) return 0;
|
||||
|
||||
if (entnum < 0) entnum = -1;
|
||||
while(++entnum < aasworld.maxentities)
|
||||
{
|
||||
if (aasworld.entities[entnum].i.valid) return entnum;
|
||||
} //end while
|
||||
return 0;
|
||||
} //end of the function AAS_NextEntity
|
46
CODEmp/botlib/be_aas_entity.h
Normal file
46
CODEmp/botlib/be_aas_entity.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_entity.h
|
||||
*
|
||||
* desc: AAS
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_aas_entity.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef AASINTERN
|
||||
//invalidates all entity infos
|
||||
void AAS_InvalidateEntities(void);
|
||||
//unlink not updated entities
|
||||
void AAS_UnlinkInvalidEntities(void);
|
||||
//resets the entity AAS and BSP links (sets areas and leaves pointers to NULL)
|
||||
void AAS_ResetEntityLinks(void);
|
||||
//updates an entity
|
||||
int AAS_UpdateEntity(int ent, bot_entitystate_t *state);
|
||||
//gives the entity data used for collision detection
|
||||
void AAS_EntityBSPData(int entnum, bsp_entdata_t *entdata);
|
||||
#endif //AASINTERN
|
||||
|
||||
//returns the size of the entity bounding box in mins and maxs
|
||||
void AAS_EntitySize(int entnum, vec3_t mins, vec3_t maxs);
|
||||
//returns the BSP model number of the entity
|
||||
int AAS_EntityModelNum(int entnum);
|
||||
//returns the origin of an entity with the given model number
|
||||
int AAS_OriginOfMoverWithModelNum(int modelnum, vec3_t origin);
|
||||
//returns the best reachable area the entity is situated in
|
||||
int AAS_BestReachableEntityArea(int entnum);
|
||||
//returns the info of the given entity
|
||||
void AAS_EntityInfo(int entnum, aas_entityinfo_t *info);
|
||||
//returns the next entity
|
||||
int AAS_NextEntity(int entnum);
|
||||
//returns the origin of the entity
|
||||
void AAS_EntityOrigin(int entnum, vec3_t origin);
|
||||
//returns the entity type
|
||||
int AAS_EntityType(int entnum);
|
||||
//returns the model index of the entity
|
||||
int AAS_EntityModelindex(int entnum);
|
||||
|
565
CODEmp/botlib/be_aas_file.cpp
Normal file
565
CODEmp/botlib/be_aas_file.cpp
Normal file
|
@ -0,0 +1,565 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_file.c
|
||||
*
|
||||
* desc: AAS file loading/writing
|
||||
*
|
||||
* $Archive: /MissionPack/code/botlib/be_aas_file.c $
|
||||
* $Author: Zaphod $
|
||||
* $Revision: 5 $
|
||||
* $Modtime: 5/16/01 2:36p $
|
||||
* $Date: 5/16/01 2:41p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "l_memory.h"
|
||||
#include "l_script.h"
|
||||
#include "l_precomp.h"
|
||||
#include "l_struct.h"
|
||||
#include "l_libvar.h"
|
||||
#include "l_utils.h"
|
||||
#include "aasfile.h"
|
||||
#include "../game/botlib.h"
|
||||
#include "../game/be_aas.h"
|
||||
#include "be_aas_funcs.h"
|
||||
#include "be_interface.h"
|
||||
#include "be_aas_def.h"
|
||||
|
||||
//#define AASFILEDEBUG
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_SwapAASData(void)
|
||||
{
|
||||
int i, j;
|
||||
//bounding boxes
|
||||
for (i = 0; i < aasworld.numbboxes; i++)
|
||||
{
|
||||
aasworld.bboxes[i].presencetype = LittleLong(aasworld.bboxes[i].presencetype);
|
||||
aasworld.bboxes[i].flags = LittleLong(aasworld.bboxes[i].flags);
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
aasworld.bboxes[i].mins[j] = LittleLong(aasworld.bboxes[i].mins[j]);
|
||||
aasworld.bboxes[i].maxs[j] = LittleLong(aasworld.bboxes[i].maxs[j]);
|
||||
} //end for
|
||||
} //end for
|
||||
//vertexes
|
||||
for (i = 0; i < aasworld.numvertexes; i++)
|
||||
{
|
||||
for (j = 0; j < 3; j++)
|
||||
aasworld.vertexes[i][j] = LittleFloat(aasworld.vertexes[i][j]);
|
||||
} //end for
|
||||
//planes
|
||||
for (i = 0; i < aasworld.numplanes; i++)
|
||||
{
|
||||
for (j = 0; j < 3; j++)
|
||||
aasworld.planes[i].normal[j] = LittleFloat(aasworld.planes[i].normal[j]);
|
||||
aasworld.planes[i].dist = LittleFloat(aasworld.planes[i].dist);
|
||||
aasworld.planes[i].type = LittleLong(aasworld.planes[i].type);
|
||||
} //end for
|
||||
//edges
|
||||
for (i = 0; i < aasworld.numedges; i++)
|
||||
{
|
||||
aasworld.edges[i].v[0] = LittleLong(aasworld.edges[i].v[0]);
|
||||
aasworld.edges[i].v[1] = LittleLong(aasworld.edges[i].v[1]);
|
||||
} //end for
|
||||
//edgeindex
|
||||
for (i = 0; i < aasworld.edgeindexsize; i++)
|
||||
{
|
||||
aasworld.edgeindex[i] = LittleLong(aasworld.edgeindex[i]);
|
||||
} //end for
|
||||
//faces
|
||||
for (i = 0; i < aasworld.numfaces; i++)
|
||||
{
|
||||
aasworld.faces[i].planenum = LittleLong(aasworld.faces[i].planenum);
|
||||
aasworld.faces[i].faceflags = LittleLong(aasworld.faces[i].faceflags);
|
||||
aasworld.faces[i].numedges = LittleLong(aasworld.faces[i].numedges);
|
||||
aasworld.faces[i].firstedge = LittleLong(aasworld.faces[i].firstedge);
|
||||
aasworld.faces[i].frontarea = LittleLong(aasworld.faces[i].frontarea);
|
||||
aasworld.faces[i].backarea = LittleLong(aasworld.faces[i].backarea);
|
||||
} //end for
|
||||
//face index
|
||||
for (i = 0; i < aasworld.faceindexsize; i++)
|
||||
{
|
||||
aasworld.faceindex[i] = LittleLong(aasworld.faceindex[i]);
|
||||
} //end for
|
||||
//convex areas
|
||||
for (i = 0; i < aasworld.numareas; i++)
|
||||
{
|
||||
aasworld.areas[i].areanum = LittleLong(aasworld.areas[i].areanum);
|
||||
aasworld.areas[i].numfaces = LittleLong(aasworld.areas[i].numfaces);
|
||||
aasworld.areas[i].firstface = LittleLong(aasworld.areas[i].firstface);
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
aasworld.areas[i].mins[j] = LittleFloat(aasworld.areas[i].mins[j]);
|
||||
aasworld.areas[i].maxs[j] = LittleFloat(aasworld.areas[i].maxs[j]);
|
||||
aasworld.areas[i].center[j] = LittleFloat(aasworld.areas[i].center[j]);
|
||||
} //end for
|
||||
} //end for
|
||||
//area settings
|
||||
for (i = 0; i < aasworld.numareasettings; i++)
|
||||
{
|
||||
aasworld.areasettings[i].contents = LittleLong(aasworld.areasettings[i].contents);
|
||||
aasworld.areasettings[i].areaflags = LittleLong(aasworld.areasettings[i].areaflags);
|
||||
aasworld.areasettings[i].presencetype = LittleLong(aasworld.areasettings[i].presencetype);
|
||||
aasworld.areasettings[i].cluster = LittleLong(aasworld.areasettings[i].cluster);
|
||||
aasworld.areasettings[i].clusterareanum = LittleLong(aasworld.areasettings[i].clusterareanum);
|
||||
aasworld.areasettings[i].numreachableareas = LittleLong(aasworld.areasettings[i].numreachableareas);
|
||||
aasworld.areasettings[i].firstreachablearea = LittleLong(aasworld.areasettings[i].firstreachablearea);
|
||||
} //end for
|
||||
//area reachability
|
||||
for (i = 0; i < aasworld.reachabilitysize; i++)
|
||||
{
|
||||
aasworld.reachability[i].areanum = LittleLong(aasworld.reachability[i].areanum);
|
||||
aasworld.reachability[i].facenum = LittleLong(aasworld.reachability[i].facenum);
|
||||
aasworld.reachability[i].edgenum = LittleLong(aasworld.reachability[i].edgenum);
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
aasworld.reachability[i].start[j] = LittleFloat(aasworld.reachability[i].start[j]);
|
||||
aasworld.reachability[i].end[j] = LittleFloat(aasworld.reachability[i].end[j]);
|
||||
} //end for
|
||||
aasworld.reachability[i].traveltype = LittleLong(aasworld.reachability[i].traveltype);
|
||||
aasworld.reachability[i].traveltime = LittleShort(aasworld.reachability[i].traveltime);
|
||||
} //end for
|
||||
//nodes
|
||||
for (i = 0; i < aasworld.numnodes; i++)
|
||||
{
|
||||
aasworld.nodes[i].planenum = LittleLong(aasworld.nodes[i].planenum);
|
||||
aasworld.nodes[i].children[0] = LittleLong(aasworld.nodes[i].children[0]);
|
||||
aasworld.nodes[i].children[1] = LittleLong(aasworld.nodes[i].children[1]);
|
||||
} //end for
|
||||
//cluster portals
|
||||
for (i = 0; i < aasworld.numportals; i++)
|
||||
{
|
||||
aasworld.portals[i].areanum = LittleLong(aasworld.portals[i].areanum);
|
||||
aasworld.portals[i].frontcluster = LittleLong(aasworld.portals[i].frontcluster);
|
||||
aasworld.portals[i].backcluster = LittleLong(aasworld.portals[i].backcluster);
|
||||
aasworld.portals[i].clusterareanum[0] = LittleLong(aasworld.portals[i].clusterareanum[0]);
|
||||
aasworld.portals[i].clusterareanum[1] = LittleLong(aasworld.portals[i].clusterareanum[1]);
|
||||
} //end for
|
||||
//cluster portal index
|
||||
for (i = 0; i < aasworld.portalindexsize; i++)
|
||||
{
|
||||
aasworld.portalindex[i] = LittleLong(aasworld.portalindex[i]);
|
||||
} //end for
|
||||
//cluster
|
||||
for (i = 0; i < aasworld.numclusters; i++)
|
||||
{
|
||||
aasworld.clusters[i].numareas = LittleLong(aasworld.clusters[i].numareas);
|
||||
aasworld.clusters[i].numreachabilityareas = LittleLong(aasworld.clusters[i].numreachabilityareas);
|
||||
aasworld.clusters[i].numportals = LittleLong(aasworld.clusters[i].numportals);
|
||||
aasworld.clusters[i].firstportal = LittleLong(aasworld.clusters[i].firstportal);
|
||||
} //end for
|
||||
} //end of the function AAS_SwapAASData
|
||||
//===========================================================================
|
||||
// dump the current loaded aas file
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_DumpAASData(void)
|
||||
{
|
||||
aasworld.numbboxes = 0;
|
||||
if (aasworld.bboxes) FreeMemory(aasworld.bboxes);
|
||||
aasworld.bboxes = NULL;
|
||||
aasworld.numvertexes = 0;
|
||||
if (aasworld.vertexes) FreeMemory(aasworld.vertexes);
|
||||
aasworld.vertexes = NULL;
|
||||
aasworld.numplanes = 0;
|
||||
if (aasworld.planes) FreeMemory(aasworld.planes);
|
||||
aasworld.planes = NULL;
|
||||
aasworld.numedges = 0;
|
||||
if (aasworld.edges) FreeMemory(aasworld.edges);
|
||||
aasworld.edges = NULL;
|
||||
aasworld.edgeindexsize = 0;
|
||||
if (aasworld.edgeindex) FreeMemory(aasworld.edgeindex);
|
||||
aasworld.edgeindex = NULL;
|
||||
aasworld.numfaces = 0;
|
||||
if (aasworld.faces) FreeMemory(aasworld.faces);
|
||||
aasworld.faces = NULL;
|
||||
aasworld.faceindexsize = 0;
|
||||
if (aasworld.faceindex) FreeMemory(aasworld.faceindex);
|
||||
aasworld.faceindex = NULL;
|
||||
aasworld.numareas = 0;
|
||||
if (aasworld.areas) FreeMemory(aasworld.areas);
|
||||
aasworld.areas = NULL;
|
||||
aasworld.numareasettings = 0;
|
||||
if (aasworld.areasettings) FreeMemory(aasworld.areasettings);
|
||||
aasworld.areasettings = NULL;
|
||||
aasworld.reachabilitysize = 0;
|
||||
if (aasworld.reachability) FreeMemory(aasworld.reachability);
|
||||
aasworld.reachability = NULL;
|
||||
aasworld.numnodes = 0;
|
||||
if (aasworld.nodes) FreeMemory(aasworld.nodes);
|
||||
aasworld.nodes = NULL;
|
||||
aasworld.numportals = 0;
|
||||
if (aasworld.portals) FreeMemory(aasworld.portals);
|
||||
aasworld.portals = NULL;
|
||||
aasworld.numportals = 0;
|
||||
if (aasworld.portalindex) FreeMemory(aasworld.portalindex);
|
||||
aasworld.portalindex = NULL;
|
||||
aasworld.portalindexsize = 0;
|
||||
if (aasworld.clusters) FreeMemory(aasworld.clusters);
|
||||
aasworld.clusters = NULL;
|
||||
aasworld.numclusters = 0;
|
||||
//
|
||||
aasworld.loaded = qfalse;
|
||||
aasworld.initialized = qfalse;
|
||||
aasworld.savefile = qfalse;
|
||||
} //end of the function AAS_DumpAASData
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
#ifdef AASFILEDEBUG
|
||||
void AAS_FileInfo(void)
|
||||
{
|
||||
int i, n, optimized;
|
||||
|
||||
botimport.Print(PRT_MESSAGE, "version = %d\n", AASVERSION);
|
||||
botimport.Print(PRT_MESSAGE, "numvertexes = %d\n", aasworld.numvertexes);
|
||||
botimport.Print(PRT_MESSAGE, "numplanes = %d\n", aasworld.numplanes);
|
||||
botimport.Print(PRT_MESSAGE, "numedges = %d\n", aasworld.numedges);
|
||||
botimport.Print(PRT_MESSAGE, "edgeindexsize = %d\n", aasworld.edgeindexsize);
|
||||
botimport.Print(PRT_MESSAGE, "numfaces = %d\n", aasworld.numfaces);
|
||||
botimport.Print(PRT_MESSAGE, "faceindexsize = %d\n", aasworld.faceindexsize);
|
||||
botimport.Print(PRT_MESSAGE, "numareas = %d\n", aasworld.numareas);
|
||||
botimport.Print(PRT_MESSAGE, "numareasettings = %d\n", aasworld.numareasettings);
|
||||
botimport.Print(PRT_MESSAGE, "reachabilitysize = %d\n", aasworld.reachabilitysize);
|
||||
botimport.Print(PRT_MESSAGE, "numnodes = %d\n", aasworld.numnodes);
|
||||
botimport.Print(PRT_MESSAGE, "numportals = %d\n", aasworld.numportals);
|
||||
botimport.Print(PRT_MESSAGE, "portalindexsize = %d\n", aasworld.portalindexsize);
|
||||
botimport.Print(PRT_MESSAGE, "numclusters = %d\n", aasworld.numclusters);
|
||||
//
|
||||
for (n = 0, i = 0; i < aasworld.numareasettings; i++)
|
||||
{
|
||||
if (aasworld.areasettings[i].areaflags & AREA_GROUNDED) n++;
|
||||
} //end for
|
||||
botimport.Print(PRT_MESSAGE, "num grounded areas = %d\n", n);
|
||||
//
|
||||
botimport.Print(PRT_MESSAGE, "planes size %d bytes\n", aasworld.numplanes * sizeof(aas_plane_t));
|
||||
botimport.Print(PRT_MESSAGE, "areas size %d bytes\n", aasworld.numareas * sizeof(aas_area_t));
|
||||
botimport.Print(PRT_MESSAGE, "areasettings size %d bytes\n", aasworld.numareasettings * sizeof(aas_areasettings_t));
|
||||
botimport.Print(PRT_MESSAGE, "nodes size %d bytes\n", aasworld.numnodes * sizeof(aas_node_t));
|
||||
botimport.Print(PRT_MESSAGE, "reachability size %d bytes\n", aasworld.reachabilitysize * sizeof(aas_reachability_t));
|
||||
botimport.Print(PRT_MESSAGE, "portals size %d bytes\n", aasworld.numportals * sizeof(aas_portal_t));
|
||||
botimport.Print(PRT_MESSAGE, "clusters size %d bytes\n", aasworld.numclusters * sizeof(aas_cluster_t));
|
||||
|
||||
optimized = aasworld.numplanes * sizeof(aas_plane_t) +
|
||||
aasworld.numareas * sizeof(aas_area_t) +
|
||||
aasworld.numareasettings * sizeof(aas_areasettings_t) +
|
||||
aasworld.numnodes * sizeof(aas_node_t) +
|
||||
aasworld.reachabilitysize * sizeof(aas_reachability_t) +
|
||||
aasworld.numportals * sizeof(aas_portal_t) +
|
||||
aasworld.numclusters * sizeof(aas_cluster_t);
|
||||
botimport.Print(PRT_MESSAGE, "optimzed size %d KB\n", optimized >> 10);
|
||||
} //end of the function AAS_FileInfo
|
||||
#endif //AASFILEDEBUG
|
||||
//===========================================================================
|
||||
// allocate memory and read a lump of a AAS file
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
char *AAS_LoadAASLump(fileHandle_t fp, int offset, int length, int *lastoffset, int size)
|
||||
{
|
||||
char *buf;
|
||||
//
|
||||
if (!length)
|
||||
{
|
||||
//just alloc a dummy
|
||||
return (char *) GetClearedHunkMemory(size+1);
|
||||
} //end if
|
||||
//seek to the data
|
||||
if (offset != *lastoffset)
|
||||
{
|
||||
botimport.Print(PRT_WARNING, "AAS file not sequentially read\n");
|
||||
if (botimport.FS_Seek(fp, offset, FS_SEEK_SET))
|
||||
{
|
||||
AAS_Error("can't seek to aas lump\n");
|
||||
AAS_DumpAASData();
|
||||
botimport.FS_FCloseFile(fp);
|
||||
return 0;
|
||||
} //end if
|
||||
} //end if
|
||||
//allocate memory
|
||||
buf = (char *) GetClearedHunkMemory(length+1);
|
||||
//read the data
|
||||
if (length)
|
||||
{
|
||||
botimport.FS_Read(buf, length, fp );
|
||||
*lastoffset += length;
|
||||
} //end if
|
||||
return buf;
|
||||
} //end of the function AAS_LoadAASLump
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_DData(unsigned char *data, int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
data[i] ^= (unsigned char) i * 119;
|
||||
} //end for
|
||||
} //end of the function AAS_DData
|
||||
//===========================================================================
|
||||
// load an aas file
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_LoadAASFile(char *filename)
|
||||
{
|
||||
fileHandle_t fp;
|
||||
aas_header_t header;
|
||||
int offset, length, lastoffset;
|
||||
|
||||
botimport.Print(PRT_MESSAGE, "trying to load %s\n", filename);
|
||||
//dump current loaded aas file
|
||||
AAS_DumpAASData();
|
||||
//open the file
|
||||
botimport.FS_FOpenFile( filename, &fp, FS_READ );
|
||||
if (!fp)
|
||||
{
|
||||
AAS_Error("can't open %s\n", filename);
|
||||
return BLERR_CANNOTOPENAASFILE;
|
||||
} //end if
|
||||
//read the header
|
||||
botimport.FS_Read(&header, sizeof(aas_header_t), fp );
|
||||
lastoffset = sizeof(aas_header_t);
|
||||
//check header identification
|
||||
header.ident = LittleLong(header.ident);
|
||||
if (header.ident != AASID)
|
||||
{
|
||||
AAS_Error("%s is not an AAS file\n", filename);
|
||||
botimport.FS_FCloseFile(fp);
|
||||
return BLERR_WRONGAASFILEID;
|
||||
} //end if
|
||||
//check the version
|
||||
header.version = LittleLong(header.version);
|
||||
//
|
||||
if (header.version != AASVERSION_OLD && header.version != AASVERSION)
|
||||
{
|
||||
AAS_Error("aas file %s is version %i, not %i\n", filename, header.version, AASVERSION);
|
||||
botimport.FS_FCloseFile(fp);
|
||||
return BLERR_WRONGAASFILEVERSION;
|
||||
} //end if
|
||||
//
|
||||
if (header.version == AASVERSION)
|
||||
{
|
||||
AAS_DData((unsigned char *) &header + 8, sizeof(aas_header_t) - 8);
|
||||
} //end if
|
||||
//
|
||||
aasworld.bspchecksum = atoi(LibVarGetString( "sv_mapChecksum"));
|
||||
if (LittleLong(header.bspchecksum) != aasworld.bspchecksum)
|
||||
{
|
||||
AAS_Error("aas file %s is out of date\n", filename);
|
||||
botimport.FS_FCloseFile(fp);
|
||||
return BLERR_WRONGAASFILEVERSION;
|
||||
} //end if
|
||||
//load the lumps:
|
||||
//bounding boxes
|
||||
offset = LittleLong(header.lumps[AASLUMP_BBOXES].fileofs);
|
||||
length = LittleLong(header.lumps[AASLUMP_BBOXES].filelen);
|
||||
aasworld.bboxes = (aas_bbox_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_bbox_t));
|
||||
aasworld.numbboxes = length / sizeof(aas_bbox_t);
|
||||
if (aasworld.numbboxes && !aasworld.bboxes) return BLERR_CANNOTREADAASLUMP;
|
||||
//vertexes
|
||||
offset = LittleLong(header.lumps[AASLUMP_VERTEXES].fileofs);
|
||||
length = LittleLong(header.lumps[AASLUMP_VERTEXES].filelen);
|
||||
aasworld.vertexes = (aas_vertex_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_vertex_t));
|
||||
aasworld.numvertexes = length / sizeof(aas_vertex_t);
|
||||
if (aasworld.numvertexes && !aasworld.vertexes) return BLERR_CANNOTREADAASLUMP;
|
||||
//planes
|
||||
offset = LittleLong(header.lumps[AASLUMP_PLANES].fileofs);
|
||||
length = LittleLong(header.lumps[AASLUMP_PLANES].filelen);
|
||||
aasworld.planes = (aas_plane_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_plane_t));
|
||||
aasworld.numplanes = length / sizeof(aas_plane_t);
|
||||
if (aasworld.numplanes && !aasworld.planes) return BLERR_CANNOTREADAASLUMP;
|
||||
//edges
|
||||
offset = LittleLong(header.lumps[AASLUMP_EDGES].fileofs);
|
||||
length = LittleLong(header.lumps[AASLUMP_EDGES].filelen);
|
||||
aasworld.edges = (aas_edge_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_edge_t));
|
||||
aasworld.numedges = length / sizeof(aas_edge_t);
|
||||
if (aasworld.numedges && !aasworld.edges) return BLERR_CANNOTREADAASLUMP;
|
||||
//edgeindex
|
||||
offset = LittleLong(header.lumps[AASLUMP_EDGEINDEX].fileofs);
|
||||
length = LittleLong(header.lumps[AASLUMP_EDGEINDEX].filelen);
|
||||
aasworld.edgeindex = (aas_edgeindex_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_edgeindex_t));
|
||||
aasworld.edgeindexsize = length / sizeof(aas_edgeindex_t);
|
||||
if (aasworld.edgeindexsize && !aasworld.edgeindex) return BLERR_CANNOTREADAASLUMP;
|
||||
//faces
|
||||
offset = LittleLong(header.lumps[AASLUMP_FACES].fileofs);
|
||||
length = LittleLong(header.lumps[AASLUMP_FACES].filelen);
|
||||
aasworld.faces = (aas_face_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_face_t));
|
||||
aasworld.numfaces = length / sizeof(aas_face_t);
|
||||
if (aasworld.numfaces && !aasworld.faces) return BLERR_CANNOTREADAASLUMP;
|
||||
//faceindex
|
||||
offset = LittleLong(header.lumps[AASLUMP_FACEINDEX].fileofs);
|
||||
length = LittleLong(header.lumps[AASLUMP_FACEINDEX].filelen);
|
||||
aasworld.faceindex = (aas_faceindex_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_faceindex_t));
|
||||
aasworld.faceindexsize = length / sizeof(aas_faceindex_t);
|
||||
if (aasworld.faceindexsize && !aasworld.faceindex) return BLERR_CANNOTREADAASLUMP;
|
||||
//convex areas
|
||||
offset = LittleLong(header.lumps[AASLUMP_AREAS].fileofs);
|
||||
length = LittleLong(header.lumps[AASLUMP_AREAS].filelen);
|
||||
aasworld.areas = (aas_area_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_area_t));
|
||||
aasworld.numareas = length / sizeof(aas_area_t);
|
||||
if (aasworld.numareas && !aasworld.areas) return BLERR_CANNOTREADAASLUMP;
|
||||
//area settings
|
||||
offset = LittleLong(header.lumps[AASLUMP_AREASETTINGS].fileofs);
|
||||
length = LittleLong(header.lumps[AASLUMP_AREASETTINGS].filelen);
|
||||
aasworld.areasettings = (aas_areasettings_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_areasettings_t));
|
||||
aasworld.numareasettings = length / sizeof(aas_areasettings_t);
|
||||
if (aasworld.numareasettings && !aasworld.areasettings) return BLERR_CANNOTREADAASLUMP;
|
||||
//reachability list
|
||||
offset = LittleLong(header.lumps[AASLUMP_REACHABILITY].fileofs);
|
||||
length = LittleLong(header.lumps[AASLUMP_REACHABILITY].filelen);
|
||||
aasworld.reachability = (aas_reachability_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_reachability_t));
|
||||
aasworld.reachabilitysize = length / sizeof(aas_reachability_t);
|
||||
if (aasworld.reachabilitysize && !aasworld.reachability) return BLERR_CANNOTREADAASLUMP;
|
||||
//nodes
|
||||
offset = LittleLong(header.lumps[AASLUMP_NODES].fileofs);
|
||||
length = LittleLong(header.lumps[AASLUMP_NODES].filelen);
|
||||
aasworld.nodes = (aas_node_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_node_t));
|
||||
aasworld.numnodes = length / sizeof(aas_node_t);
|
||||
if (aasworld.numnodes && !aasworld.nodes) return BLERR_CANNOTREADAASLUMP;
|
||||
//cluster portals
|
||||
offset = LittleLong(header.lumps[AASLUMP_PORTALS].fileofs);
|
||||
length = LittleLong(header.lumps[AASLUMP_PORTALS].filelen);
|
||||
aasworld.portals = (aas_portal_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_portal_t));
|
||||
aasworld.numportals = length / sizeof(aas_portal_t);
|
||||
if (aasworld.numportals && !aasworld.portals) return BLERR_CANNOTREADAASLUMP;
|
||||
//cluster portal index
|
||||
offset = LittleLong(header.lumps[AASLUMP_PORTALINDEX].fileofs);
|
||||
length = LittleLong(header.lumps[AASLUMP_PORTALINDEX].filelen);
|
||||
aasworld.portalindex = (aas_portalindex_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_portalindex_t));
|
||||
aasworld.portalindexsize = length / sizeof(aas_portalindex_t);
|
||||
if (aasworld.portalindexsize && !aasworld.portalindex) return BLERR_CANNOTREADAASLUMP;
|
||||
//clusters
|
||||
offset = LittleLong(header.lumps[AASLUMP_CLUSTERS].fileofs);
|
||||
length = LittleLong(header.lumps[AASLUMP_CLUSTERS].filelen);
|
||||
aasworld.clusters = (aas_cluster_t *) AAS_LoadAASLump(fp, offset, length, &lastoffset, sizeof(aas_cluster_t));
|
||||
aasworld.numclusters = length / sizeof(aas_cluster_t);
|
||||
if (aasworld.numclusters && !aasworld.clusters) return BLERR_CANNOTREADAASLUMP;
|
||||
//swap everything
|
||||
AAS_SwapAASData();
|
||||
//aas file is loaded
|
||||
aasworld.loaded = qtrue;
|
||||
//close the file
|
||||
botimport.FS_FCloseFile(fp);
|
||||
//
|
||||
#ifdef AASFILEDEBUG
|
||||
AAS_FileInfo();
|
||||
#endif //AASFILEDEBUG
|
||||
//
|
||||
return BLERR_NOERROR;
|
||||
} //end of the function AAS_LoadAASFile
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
static int AAS_WriteAASLump_offset;
|
||||
|
||||
int AAS_WriteAASLump(fileHandle_t fp, aas_header_t *h, int lumpnum, void *data, int length)
|
||||
{
|
||||
aas_lump_t *lump;
|
||||
|
||||
lump = &h->lumps[lumpnum];
|
||||
|
||||
lump->fileofs = LittleLong(AAS_WriteAASLump_offset); //LittleLong(ftell(fp));
|
||||
lump->filelen = LittleLong(length);
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
botimport.FS_Write(data, length, fp );
|
||||
} //end if
|
||||
|
||||
AAS_WriteAASLump_offset += length;
|
||||
|
||||
return qtrue;
|
||||
} //end of the function AAS_WriteAASLump
|
||||
//===========================================================================
|
||||
// aas data is useless after writing to file because it is byte swapped
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
qboolean AAS_WriteAASFile(char *filename)
|
||||
{
|
||||
aas_header_t header;
|
||||
fileHandle_t fp;
|
||||
|
||||
botimport.Print(PRT_MESSAGE, "writing %s\n", filename);
|
||||
//swap the aas data
|
||||
AAS_SwapAASData();
|
||||
//initialize the file header
|
||||
Com_Memset(&header, 0, sizeof(aas_header_t));
|
||||
header.ident = LittleLong(AASID);
|
||||
header.version = LittleLong(AASVERSION);
|
||||
header.bspchecksum = LittleLong(aasworld.bspchecksum);
|
||||
//open a new file
|
||||
botimport.FS_FOpenFile( filename, &fp, FS_WRITE );
|
||||
if (!fp)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "error opening %s\n", filename);
|
||||
return qfalse;
|
||||
} //end if
|
||||
//write the header
|
||||
botimport.FS_Write(&header, sizeof(aas_header_t), fp);
|
||||
AAS_WriteAASLump_offset = sizeof(aas_header_t);
|
||||
//add the data lumps to the file
|
||||
if (!AAS_WriteAASLump(fp, &header, AASLUMP_BBOXES, aasworld.bboxes,
|
||||
aasworld.numbboxes * sizeof(aas_bbox_t))) return qfalse;
|
||||
if (!AAS_WriteAASLump(fp, &header, AASLUMP_VERTEXES, aasworld.vertexes,
|
||||
aasworld.numvertexes * sizeof(aas_vertex_t))) return qfalse;
|
||||
if (!AAS_WriteAASLump(fp, &header, AASLUMP_PLANES, aasworld.planes,
|
||||
aasworld.numplanes * sizeof(aas_plane_t))) return qfalse;
|
||||
if (!AAS_WriteAASLump(fp, &header, AASLUMP_EDGES, aasworld.edges,
|
||||
aasworld.numedges * sizeof(aas_edge_t))) return qfalse;
|
||||
if (!AAS_WriteAASLump(fp, &header, AASLUMP_EDGEINDEX, aasworld.edgeindex,
|
||||
aasworld.edgeindexsize * sizeof(aas_edgeindex_t))) return qfalse;
|
||||
if (!AAS_WriteAASLump(fp, &header, AASLUMP_FACES, aasworld.faces,
|
||||
aasworld.numfaces * sizeof(aas_face_t))) return qfalse;
|
||||
if (!AAS_WriteAASLump(fp, &header, AASLUMP_FACEINDEX, aasworld.faceindex,
|
||||
aasworld.faceindexsize * sizeof(aas_faceindex_t))) return qfalse;
|
||||
if (!AAS_WriteAASLump(fp, &header, AASLUMP_AREAS, aasworld.areas,
|
||||
aasworld.numareas * sizeof(aas_area_t))) return qfalse;
|
||||
if (!AAS_WriteAASLump(fp, &header, AASLUMP_AREASETTINGS, aasworld.areasettings,
|
||||
aasworld.numareasettings * sizeof(aas_areasettings_t))) return qfalse;
|
||||
if (!AAS_WriteAASLump(fp, &header, AASLUMP_REACHABILITY, aasworld.reachability,
|
||||
aasworld.reachabilitysize * sizeof(aas_reachability_t))) return qfalse;
|
||||
if (!AAS_WriteAASLump(fp, &header, AASLUMP_NODES, aasworld.nodes,
|
||||
aasworld.numnodes * sizeof(aas_node_t))) return qfalse;
|
||||
if (!AAS_WriteAASLump(fp, &header, AASLUMP_PORTALS, aasworld.portals,
|
||||
aasworld.numportals * sizeof(aas_portal_t))) return qfalse;
|
||||
if (!AAS_WriteAASLump(fp, &header, AASLUMP_PORTALINDEX, aasworld.portalindex,
|
||||
aasworld.portalindexsize * sizeof(aas_portalindex_t))) return qfalse;
|
||||
if (!AAS_WriteAASLump(fp, &header, AASLUMP_CLUSTERS, aasworld.clusters,
|
||||
aasworld.numclusters * sizeof(aas_cluster_t))) return qfalse;
|
||||
//rewrite the header with the added lumps
|
||||
botimport.FS_Seek(fp, 0, FS_SEEK_SET);
|
||||
AAS_DData((unsigned char *) &header + 8, sizeof(aas_header_t) - 8);
|
||||
botimport.FS_Write(&header, sizeof(aas_header_t), fp);
|
||||
//close the file
|
||||
botimport.FS_FCloseFile(fp);
|
||||
return qtrue;
|
||||
} //end of the function AAS_WriteAASFile
|
25
CODEmp/botlib/be_aas_file.h
Normal file
25
CODEmp/botlib/be_aas_file.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_file.h
|
||||
*
|
||||
* desc: AAS
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_aas_file.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef AASINTERN
|
||||
//loads the AAS file with the given name
|
||||
int AAS_LoadAASFile(char *filename);
|
||||
//writes an AAS file with the given name
|
||||
qboolean AAS_WriteAASFile(char *filename);
|
||||
//dumps the loaded AAS data
|
||||
void AAS_DumpAASData(void);
|
||||
//print AAS file information
|
||||
void AAS_FileInfo(void);
|
||||
#endif //AASINTERN
|
||||
|
30
CODEmp/botlib/be_aas_funcs.h
Normal file
30
CODEmp/botlib/be_aas_funcs.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_funcs.h
|
||||
*
|
||||
* desc: AAS
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_aas_funcs.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef BSPCINCLUDE
|
||||
|
||||
#include "be_aas_main.h"
|
||||
#include "be_aas_entity.h"
|
||||
#include "be_aas_sample.h"
|
||||
#include "be_aas_cluster.h"
|
||||
#include "be_aas_reach.h"
|
||||
#include "be_aas_route.h"
|
||||
#include "be_aas_routealt.h"
|
||||
#include "be_aas_debug.h"
|
||||
#include "be_aas_file.h"
|
||||
#include "be_aas_optimize.h"
|
||||
#include "be_aas_bsp.h"
|
||||
#include "be_aas_move.h"
|
||||
|
||||
#endif //BSPCINCLUDE
|
412
CODEmp/botlib/be_aas_main.cpp
Normal file
412
CODEmp/botlib/be_aas_main.cpp
Normal file
|
@ -0,0 +1,412 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_main.c
|
||||
*
|
||||
* desc: AAS
|
||||
*
|
||||
* $Archive: /MissionPack/code/botlib/be_aas_main.c $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 8 $
|
||||
* $Modtime: 11/28/00 7:52a $
|
||||
* $Date: 11/28/00 7:52a $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "l_memory.h"
|
||||
#include "l_libvar.h"
|
||||
#include "l_utils.h"
|
||||
#include "l_script.h"
|
||||
#include "l_precomp.h"
|
||||
#include "l_struct.h"
|
||||
#include "l_log.h"
|
||||
#include "aasfile.h"
|
||||
#include "../game/botlib.h"
|
||||
#include "../game/be_aas.h"
|
||||
#include "be_aas_funcs.h"
|
||||
#include "be_interface.h"
|
||||
#include "be_aas_def.h"
|
||||
|
||||
aas_t aasworld;
|
||||
|
||||
libvar_t *saveroutingcache;
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void QDECL AAS_Error(char *fmt, ...)
|
||||
{
|
||||
char str[1024];
|
||||
va_list arglist;
|
||||
|
||||
va_start(arglist, fmt);
|
||||
vsprintf(str, fmt, arglist);
|
||||
va_end(arglist);
|
||||
botimport.Print(PRT_FATAL, str);
|
||||
} //end of the function AAS_Error
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
char *AAS_StringFromIndex(char *indexname, char *stringindex[], int numindexes, int index)
|
||||
{
|
||||
if (!aasworld.indexessetup)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "%s: index %d not setup\n", indexname, index);
|
||||
return "";
|
||||
} //end if
|
||||
if (index < 0 || index >= numindexes)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "%s: index %d out of range\n", indexname, index);
|
||||
return "";
|
||||
} //end if
|
||||
if (!stringindex[index])
|
||||
{
|
||||
if (index)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "%s: reference to unused index %d\n", indexname, index);
|
||||
} //end if
|
||||
return "";
|
||||
} //end if
|
||||
return stringindex[index];
|
||||
} //end of the function AAS_StringFromIndex
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_IndexFromString(char *indexname, char *stringindex[], int numindexes, char *string)
|
||||
{
|
||||
int i;
|
||||
if (!aasworld.indexessetup)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "%s: index not setup \"%s\"\n", indexname, string);
|
||||
return 0;
|
||||
} //end if
|
||||
for (i = 0; i < numindexes; i++)
|
||||
{
|
||||
if (!stringindex[i]) continue;
|
||||
if (!Q_stricmp(stringindex[i], string)) return i;
|
||||
} //end for
|
||||
return 0;
|
||||
} //end of the function AAS_IndexFromString
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
char *AAS_ModelFromIndex(int index)
|
||||
{
|
||||
return AAS_StringFromIndex("ModelFromIndex", &aasworld.configstrings[CS_MODELS], MAX_MODELS, index);
|
||||
} //end of the function AAS_ModelFromIndex
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_IndexFromModel(char *modelname)
|
||||
{
|
||||
return AAS_IndexFromString("IndexFromModel", &aasworld.configstrings[CS_MODELS], MAX_MODELS, modelname);
|
||||
} //end of the function AAS_IndexFromModel
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_UpdateStringIndexes(int numconfigstrings, char *configstrings[])
|
||||
{
|
||||
int i;
|
||||
//set string pointers and copy the strings
|
||||
for (i = 0; i < numconfigstrings; i++)
|
||||
{
|
||||
if (configstrings[i])
|
||||
{
|
||||
//if (aasworld.configstrings[i]) FreeMemory(aasworld.configstrings[i]);
|
||||
aasworld.configstrings[i] = (char *) GetMemory(strlen(configstrings[i]) + 1);
|
||||
strcpy(aasworld.configstrings[i], configstrings[i]);
|
||||
} //end if
|
||||
} //end for
|
||||
aasworld.indexessetup = qtrue;
|
||||
} //end of the function AAS_UpdateStringIndexes
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_Loaded(void)
|
||||
{
|
||||
return aasworld.loaded;
|
||||
} //end of the function AAS_Loaded
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_Initialized(void)
|
||||
{
|
||||
return aasworld.initialized;
|
||||
} //end of the function AAS_Initialized
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_SetInitialized(void)
|
||||
{
|
||||
aasworld.initialized = qtrue;
|
||||
botimport.Print(PRT_MESSAGE, "AAS initialized.\n");
|
||||
#ifdef DEBUG
|
||||
//create all the routing cache
|
||||
//AAS_CreateAllRoutingCache();
|
||||
//
|
||||
//AAS_RoutingInfo();
|
||||
#endif
|
||||
} //end of the function AAS_SetInitialized
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_ContinueInit(float time)
|
||||
{
|
||||
//if no AAS file loaded
|
||||
if (!aasworld.loaded) return;
|
||||
//if AAS is already initialized
|
||||
if (aasworld.initialized) return;
|
||||
//calculate reachability, if not finished return
|
||||
if (AAS_ContinueInitReachability(time)) return;
|
||||
//initialize clustering for the new map
|
||||
AAS_InitClustering();
|
||||
//if reachability has been calculated and an AAS file should be written
|
||||
//or there is a forced data optimization
|
||||
if (aasworld.savefile || ((int)LibVarGetValue("forcewrite")))
|
||||
{
|
||||
//optimize the AAS data
|
||||
if ((int)LibVarValue("aasoptimize", "0")) AAS_Optimize();
|
||||
//save the AAS file
|
||||
if (AAS_WriteAASFile(aasworld.filename))
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "%s written succesfully\n", aasworld.filename);
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "couldn't write %s\n", aasworld.filename);
|
||||
} //end else
|
||||
} //end if
|
||||
//initialize the routing
|
||||
AAS_InitRouting();
|
||||
//at this point AAS is initialized
|
||||
AAS_SetInitialized();
|
||||
} //end of the function AAS_ContinueInit
|
||||
//===========================================================================
|
||||
// called at the start of every frame
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_StartFrame(float time)
|
||||
{
|
||||
aasworld.time = time;
|
||||
//unlink all entities that were not updated last frame
|
||||
AAS_UnlinkInvalidEntities();
|
||||
//invalidate the entities
|
||||
AAS_InvalidateEntities();
|
||||
//initialize AAS
|
||||
AAS_ContinueInit(time);
|
||||
//
|
||||
aasworld.frameroutingupdates = 0;
|
||||
//
|
||||
if (bot_developer)
|
||||
{
|
||||
if (LibVarGetValue("showcacheupdates"))
|
||||
{
|
||||
AAS_RoutingInfo();
|
||||
LibVarSet("showcacheupdates", "0");
|
||||
} //end if
|
||||
if (LibVarGetValue("showmemoryusage"))
|
||||
{
|
||||
PrintUsedMemorySize();
|
||||
LibVarSet("showmemoryusage", "0");
|
||||
} //end if
|
||||
if (LibVarGetValue("memorydump"))
|
||||
{
|
||||
PrintMemoryLabels();
|
||||
LibVarSet("memorydump", "0");
|
||||
} //end if
|
||||
} //end if
|
||||
//
|
||||
if (saveroutingcache->value)
|
||||
{
|
||||
AAS_WriteRouteCache();
|
||||
LibVarSet("saveroutingcache", "0");
|
||||
} //end if
|
||||
//
|
||||
aasworld.numframes++;
|
||||
return BLERR_NOERROR;
|
||||
} //end of the function AAS_StartFrame
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
float AAS_Time(void)
|
||||
{
|
||||
return aasworld.time;
|
||||
} //end of the function AAS_Time
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_ProjectPointOntoVector( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj )
|
||||
{
|
||||
vec3_t pVec, vec;
|
||||
|
||||
VectorSubtract( point, vStart, pVec );
|
||||
VectorSubtract( vEnd, vStart, vec );
|
||||
VectorNormalize( vec );
|
||||
// project onto the directional vector for this segment
|
||||
VectorMA( vStart, DotProduct( pVec, vec ), vec, vProj );
|
||||
} //end of the function AAS_ProjectPointOntoVector
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_LoadFiles(const char *mapname)
|
||||
{
|
||||
int errnum;
|
||||
char aasfile[MAX_PATH];
|
||||
// char bspfile[MAX_PATH];
|
||||
|
||||
strcpy(aasworld.mapname, mapname);
|
||||
//NOTE: first reset the entity links into the AAS areas and BSP leaves
|
||||
// the AAS link heap and BSP link heap are reset after respectively the
|
||||
// AAS file and BSP file are loaded
|
||||
AAS_ResetEntityLinks();
|
||||
// load bsp info
|
||||
AAS_LoadBSPFile();
|
||||
|
||||
//load the aas file
|
||||
Com_sprintf(aasfile, MAX_PATH, "maps/%s.aas", mapname);
|
||||
errnum = AAS_LoadAASFile(aasfile);
|
||||
if (errnum != BLERR_NOERROR)
|
||||
return errnum;
|
||||
|
||||
botimport.Print(PRT_MESSAGE, "loaded %s\n", aasfile);
|
||||
strncpy(aasworld.filename, aasfile, MAX_PATH);
|
||||
return BLERR_NOERROR;
|
||||
} //end of the function AAS_LoadFiles
|
||||
//===========================================================================
|
||||
// called everytime a map changes
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_LoadMap(const char *mapname)
|
||||
{
|
||||
int errnum;
|
||||
|
||||
//if no mapname is provided then the string indexes are updated
|
||||
if (!mapname)
|
||||
{
|
||||
return 0;
|
||||
} //end if
|
||||
//
|
||||
aasworld.initialized = qfalse;
|
||||
//NOTE: free the routing caches before loading a new map because
|
||||
// to free the caches the old number of areas, number of clusters
|
||||
// and number of areas in a clusters must be available
|
||||
AAS_FreeRoutingCaches();
|
||||
//load the map
|
||||
errnum = AAS_LoadFiles(mapname);
|
||||
if (errnum != BLERR_NOERROR)
|
||||
{
|
||||
aasworld.loaded = qfalse;
|
||||
return errnum;
|
||||
} //end if
|
||||
//
|
||||
AAS_InitSettings();
|
||||
//initialize the AAS link heap for the new map
|
||||
AAS_InitAASLinkHeap();
|
||||
//initialize the AAS linked entities for the new map
|
||||
AAS_InitAASLinkedEntities();
|
||||
//initialize reachability for the new map
|
||||
AAS_InitReachability();
|
||||
//initialize the alternative routing
|
||||
AAS_InitAlternativeRouting();
|
||||
//everything went ok
|
||||
return 0;
|
||||
} //end of the function AAS_LoadMap
|
||||
//===========================================================================
|
||||
// called when the library is first loaded
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_Setup(void)
|
||||
{
|
||||
aasworld.maxclients = (int) LibVarValue("maxclients", "128");
|
||||
aasworld.maxentities = (int) LibVarValue("maxentities", "1024");
|
||||
// as soon as it's set to 1 the routing cache will be saved
|
||||
saveroutingcache = LibVar("saveroutingcache", "0");
|
||||
//allocate memory for the entities
|
||||
if (aasworld.entities) FreeMemory(aasworld.entities);
|
||||
aasworld.entities = (aas_entity_t *) GetClearedHunkMemory(aasworld.maxentities * sizeof(aas_entity_t));
|
||||
//invalidate all the entities
|
||||
AAS_InvalidateEntities();
|
||||
//force some recalculations
|
||||
//LibVarSet("forceclustering", "1"); //force clustering calculation
|
||||
//LibVarSet("forcereachability", "1"); //force reachability calculation
|
||||
aasworld.numframes = 0;
|
||||
return BLERR_NOERROR;
|
||||
} //end of the function AAS_Setup
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_Shutdown(void)
|
||||
{
|
||||
AAS_ShutdownAlternativeRouting();
|
||||
//
|
||||
AAS_DumpBSPData();
|
||||
//free routing caches
|
||||
AAS_FreeRoutingCaches();
|
||||
//free aas link heap
|
||||
AAS_FreeAASLinkHeap();
|
||||
//free aas linked entities
|
||||
AAS_FreeAASLinkedEntities();
|
||||
//free the aas data
|
||||
AAS_DumpAASData();
|
||||
//free the entities
|
||||
if (aasworld.entities) FreeMemory(aasworld.entities);
|
||||
//clear the aasworld structure
|
||||
Com_Memset(&aasworld, 0, sizeof(aas_t));
|
||||
//aas has not been initialized
|
||||
aasworld.initialized = qfalse;
|
||||
//NOTE: as soon as a new .bsp file is loaded the .bsp file memory is
|
||||
// freed an reallocated, so there's no need to free that memory here
|
||||
//print shutdown
|
||||
botimport.Print(PRT_MESSAGE, "AAS shutdown.\n");
|
||||
} //end of the function AAS_Shutdown
|
44
CODEmp/botlib/be_aas_main.h
Normal file
44
CODEmp/botlib/be_aas_main.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_main.h
|
||||
*
|
||||
* desc: AAS
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_aas_main.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef AASINTERN
|
||||
|
||||
extern aas_t aasworld;
|
||||
|
||||
//AAS error message
|
||||
void QDECL AAS_Error(char *fmt, ...);
|
||||
//set AAS initialized
|
||||
void AAS_SetInitialized(void);
|
||||
//setup AAS with the given number of entities and clients
|
||||
int AAS_Setup(void);
|
||||
//shutdown AAS
|
||||
void AAS_Shutdown(void);
|
||||
//start a new map
|
||||
int AAS_LoadMap(const char *mapname);
|
||||
//start a new time frame
|
||||
int AAS_StartFrame(float time);
|
||||
#endif //AASINTERN
|
||||
|
||||
//returns true if AAS is initialized
|
||||
int AAS_Initialized(void);
|
||||
//returns true if the AAS file is loaded
|
||||
int AAS_Loaded(void);
|
||||
//returns the model name from the given index
|
||||
char *AAS_ModelFromIndex(int index);
|
||||
//returns the index from the given model name
|
||||
int AAS_IndexFromModel(char *modelname);
|
||||
//returns the current time
|
||||
float AAS_Time(void);
|
||||
//
|
||||
void AAS_ProjectPointOntoVector( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj );
|
1084
CODEmp/botlib/be_aas_move.cpp
Normal file
1084
CODEmp/botlib/be_aas_move.cpp
Normal file
File diff suppressed because it is too large
Load diff
54
CODEmp/botlib/be_aas_move.h
Normal file
54
CODEmp/botlib/be_aas_move.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_move.h
|
||||
*
|
||||
* desc: AAS
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_aas_move.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef AASINTERN
|
||||
extern aas_settings_t aassettings;
|
||||
#endif //AASINTERN
|
||||
|
||||
//movement prediction
|
||||
int AAS_PredictClientMovement(struct aas_clientmove_s *move,
|
||||
int entnum, vec3_t origin,
|
||||
int presencetype, int onground,
|
||||
vec3_t velocity, vec3_t cmdmove,
|
||||
int cmdframes,
|
||||
int maxframes, float frametime,
|
||||
int stopevent, int stopareanum, int visualize);
|
||||
//predict movement until bounding box is hit
|
||||
int AAS_ClientMovementHitBBox(struct aas_clientmove_s *move,
|
||||
int entnum, vec3_t origin,
|
||||
int presencetype, int onground,
|
||||
vec3_t velocity, vec3_t cmdmove,
|
||||
int cmdframes,
|
||||
int maxframes, float frametime,
|
||||
vec3_t mins, vec3_t maxs, int visualize);
|
||||
//returns true if on the ground at the given origin
|
||||
int AAS_OnGround(vec3_t origin, int presencetype, int passent);
|
||||
//returns true if swimming at the given origin
|
||||
int AAS_Swimming(vec3_t origin);
|
||||
//returns the jump reachability run start point
|
||||
void AAS_JumpReachRunStart(struct aas_reachability_s *reach, vec3_t runstart);
|
||||
//returns true if against a ladder at the given origin
|
||||
int AAS_AgainstLadder(vec3_t origin);
|
||||
//rocket jump Z velocity when rocket-jumping at origin
|
||||
float AAS_RocketJumpZVelocity(vec3_t origin);
|
||||
//bfg jump Z velocity when bfg-jumping at origin
|
||||
float AAS_BFGJumpZVelocity(vec3_t origin);
|
||||
//calculates the horizontal velocity needed for a jump and returns true this velocity could be calculated
|
||||
int AAS_HorizontalVelocityForJump(float zvel, vec3_t start, vec3_t end, float *velocity);
|
||||
//
|
||||
void AAS_SetMovedir(vec3_t angles, vec3_t movedir);
|
||||
//
|
||||
int AAS_DropToFloor(vec3_t origin, vec3_t mins, vec3_t maxs);
|
||||
//
|
||||
void AAS_InitSettings(void);
|
295
CODEmp/botlib/be_aas_optimize.cpp
Normal file
295
CODEmp/botlib/be_aas_optimize.cpp
Normal file
|
@ -0,0 +1,295 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_optimize.c
|
||||
*
|
||||
* desc: decreases the .aas file size after the reachabilities have
|
||||
* been calculated, just dumps all the faces, edges and vertexes
|
||||
*
|
||||
* $Archive: /MissionPack/code/botlib/be_aas_optimize.c $
|
||||
* $Author: Zaphod $
|
||||
* $Revision: 5 $
|
||||
* $Modtime: 11/22/00 8:50a $
|
||||
* $Date: 11/22/00 8:55a $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "l_libvar.h"
|
||||
#include "l_memory.h"
|
||||
#include "l_script.h"
|
||||
#include "l_precomp.h"
|
||||
#include "l_struct.h"
|
||||
#include "aasfile.h"
|
||||
#include "../game/botlib.h"
|
||||
#include "../game/be_aas.h"
|
||||
#include "be_aas_funcs.h"
|
||||
#include "be_interface.h"
|
||||
#include "be_aas_def.h"
|
||||
|
||||
typedef struct optimized_s
|
||||
{
|
||||
//vertexes
|
||||
int numvertexes;
|
||||
aas_vertex_t *vertexes;
|
||||
//edges
|
||||
int numedges;
|
||||
aas_edge_t *edges;
|
||||
//edge index
|
||||
int edgeindexsize;
|
||||
aas_edgeindex_t *edgeindex;
|
||||
//faces
|
||||
int numfaces;
|
||||
aas_face_t *faces;
|
||||
//face index
|
||||
int faceindexsize;
|
||||
aas_faceindex_t *faceindex;
|
||||
//convex areas
|
||||
int numareas;
|
||||
aas_area_t *areas;
|
||||
//
|
||||
int *vertexoptimizeindex;
|
||||
int *edgeoptimizeindex;
|
||||
int *faceoptimizeindex;
|
||||
} optimized_t;
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_KeepEdge(aas_edge_t *edge)
|
||||
{
|
||||
return 1;
|
||||
} //end of the function AAS_KeepFace
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_OptimizeEdge(optimized_t *optimized, int edgenum)
|
||||
{
|
||||
int i, optedgenum;
|
||||
aas_edge_t *edge, *optedge;
|
||||
|
||||
edge = &aasworld.edges[abs(edgenum)];
|
||||
if (!AAS_KeepEdge(edge)) return 0;
|
||||
|
||||
optedgenum = optimized->edgeoptimizeindex[abs(edgenum)];
|
||||
if (optedgenum)
|
||||
{
|
||||
//keep the edge reversed sign
|
||||
if (edgenum > 0) return optedgenum;
|
||||
else return -optedgenum;
|
||||
} //end if
|
||||
|
||||
optedge = &optimized->edges[optimized->numedges];
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (optimized->vertexoptimizeindex[edge->v[i]])
|
||||
{
|
||||
optedge->v[i] = optimized->vertexoptimizeindex[edge->v[i]];
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
VectorCopy(aasworld.vertexes[edge->v[i]], optimized->vertexes[optimized->numvertexes]);
|
||||
optedge->v[i] = optimized->numvertexes;
|
||||
optimized->vertexoptimizeindex[edge->v[i]] = optimized->numvertexes;
|
||||
optimized->numvertexes++;
|
||||
} //end else
|
||||
} //end for
|
||||
optimized->edgeoptimizeindex[abs(edgenum)] = optimized->numedges;
|
||||
optedgenum = optimized->numedges;
|
||||
optimized->numedges++;
|
||||
//keep the edge reversed sign
|
||||
if (edgenum > 0) return optedgenum;
|
||||
else return -optedgenum;
|
||||
} //end of the function AAS_OptimizeEdge
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_KeepFace(aas_face_t *face)
|
||||
{
|
||||
if (!(face->faceflags & FACE_LADDER)) return 0;
|
||||
else return 1;
|
||||
} //end of the function AAS_KeepFace
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_OptimizeFace(optimized_t *optimized, int facenum)
|
||||
{
|
||||
int i, edgenum, optedgenum, optfacenum;
|
||||
aas_face_t *face, *optface;
|
||||
|
||||
face = &aasworld.faces[abs(facenum)];
|
||||
if (!AAS_KeepFace(face)) return 0;
|
||||
|
||||
optfacenum = optimized->faceoptimizeindex[abs(facenum)];
|
||||
if (optfacenum)
|
||||
{
|
||||
//keep the face side sign
|
||||
if (facenum > 0) return optfacenum;
|
||||
else return -optfacenum;
|
||||
} //end if
|
||||
|
||||
optface = &optimized->faces[optimized->numfaces];
|
||||
Com_Memcpy(optface, face, sizeof(aas_face_t));
|
||||
|
||||
optface->numedges = 0;
|
||||
optface->firstedge = optimized->edgeindexsize;
|
||||
for (i = 0; i < face->numedges; i++)
|
||||
{
|
||||
edgenum = aasworld.edgeindex[face->firstedge + i];
|
||||
optedgenum = AAS_OptimizeEdge(optimized, edgenum);
|
||||
if (optedgenum)
|
||||
{
|
||||
optimized->edgeindex[optface->firstedge + optface->numedges] = optedgenum;
|
||||
optface->numedges++;
|
||||
optimized->edgeindexsize++;
|
||||
} //end if
|
||||
} //end for
|
||||
optimized->faceoptimizeindex[abs(facenum)] = optimized->numfaces;
|
||||
optfacenum = optimized->numfaces;
|
||||
optimized->numfaces++;
|
||||
//keep the face side sign
|
||||
if (facenum > 0) return optfacenum;
|
||||
else return -optfacenum;
|
||||
} //end of the function AAS_OptimizeFace
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_OptimizeArea(optimized_t *optimized, int areanum)
|
||||
{
|
||||
int i, facenum, optfacenum;
|
||||
aas_area_t *area, *optarea;
|
||||
|
||||
area = &aasworld.areas[areanum];
|
||||
optarea = &optimized->areas[areanum];
|
||||
Com_Memcpy(optarea, area, sizeof(aas_area_t));
|
||||
|
||||
optarea->numfaces = 0;
|
||||
optarea->firstface = optimized->faceindexsize;
|
||||
for (i = 0; i < area->numfaces; i++)
|
||||
{
|
||||
facenum = aasworld.faceindex[area->firstface + i];
|
||||
optfacenum = AAS_OptimizeFace(optimized, facenum);
|
||||
if (optfacenum)
|
||||
{
|
||||
optimized->faceindex[optarea->firstface + optarea->numfaces] = optfacenum;
|
||||
optarea->numfaces++;
|
||||
optimized->faceindexsize++;
|
||||
} //end if
|
||||
} //end for
|
||||
} //end of the function AAS_OptimizeArea
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_OptimizeAlloc(optimized_t *optimized)
|
||||
{
|
||||
optimized->vertexes = (aas_vertex_t *) GetClearedMemory(aasworld.numvertexes * sizeof(aas_vertex_t));
|
||||
optimized->numvertexes = 0;
|
||||
optimized->edges = (aas_edge_t *) GetClearedMemory(aasworld.numedges * sizeof(aas_edge_t));
|
||||
optimized->numedges = 1; //edge zero is a dummy
|
||||
optimized->edgeindex = (aas_edgeindex_t *) GetClearedMemory(aasworld.edgeindexsize * sizeof(aas_edgeindex_t));
|
||||
optimized->edgeindexsize = 0;
|
||||
optimized->faces = (aas_face_t *) GetClearedMemory(aasworld.numfaces * sizeof(aas_face_t));
|
||||
optimized->numfaces = 1; //face zero is a dummy
|
||||
optimized->faceindex = (aas_faceindex_t *) GetClearedMemory(aasworld.faceindexsize * sizeof(aas_faceindex_t));
|
||||
optimized->faceindexsize = 0;
|
||||
optimized->areas = (aas_area_t *) GetClearedMemory(aasworld.numareas * sizeof(aas_area_t));
|
||||
optimized->numareas = aasworld.numareas;
|
||||
//
|
||||
optimized->vertexoptimizeindex = (int *) GetClearedMemory(aasworld.numvertexes * sizeof(int));
|
||||
optimized->edgeoptimizeindex = (int *) GetClearedMemory(aasworld.numedges * sizeof(int));
|
||||
optimized->faceoptimizeindex = (int *) GetClearedMemory(aasworld.numfaces * sizeof(int));
|
||||
} //end of the function AAS_OptimizeAlloc
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_OptimizeStore(optimized_t *optimized)
|
||||
{
|
||||
//store the optimized vertexes
|
||||
if (aasworld.vertexes) FreeMemory(aasworld.vertexes);
|
||||
aasworld.vertexes = optimized->vertexes;
|
||||
aasworld.numvertexes = optimized->numvertexes;
|
||||
//store the optimized edges
|
||||
if (aasworld.edges) FreeMemory(aasworld.edges);
|
||||
aasworld.edges = optimized->edges;
|
||||
aasworld.numedges = optimized->numedges;
|
||||
//store the optimized edge index
|
||||
if (aasworld.edgeindex) FreeMemory(aasworld.edgeindex);
|
||||
aasworld.edgeindex = optimized->edgeindex;
|
||||
aasworld.edgeindexsize = optimized->edgeindexsize;
|
||||
//store the optimized faces
|
||||
if (aasworld.faces) FreeMemory(aasworld.faces);
|
||||
aasworld.faces = optimized->faces;
|
||||
aasworld.numfaces = optimized->numfaces;
|
||||
//store the optimized face index
|
||||
if (aasworld.faceindex) FreeMemory(aasworld.faceindex);
|
||||
aasworld.faceindex = optimized->faceindex;
|
||||
aasworld.faceindexsize = optimized->faceindexsize;
|
||||
//store the optimized areas
|
||||
if (aasworld.areas) FreeMemory(aasworld.areas);
|
||||
aasworld.areas = optimized->areas;
|
||||
aasworld.numareas = optimized->numareas;
|
||||
//free optimize indexes
|
||||
FreeMemory(optimized->vertexoptimizeindex);
|
||||
FreeMemory(optimized->edgeoptimizeindex);
|
||||
FreeMemory(optimized->faceoptimizeindex);
|
||||
} //end of the function AAS_OptimizeStore
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_Optimize(void)
|
||||
{
|
||||
int i, sign;
|
||||
optimized_t optimized;
|
||||
|
||||
AAS_OptimizeAlloc(&optimized);
|
||||
for (i = 1; i < aasworld.numareas; i++)
|
||||
{
|
||||
AAS_OptimizeArea(&optimized, i);
|
||||
} //end for
|
||||
//reset the reachability face pointers
|
||||
for (i = 0; i < aasworld.reachabilitysize; i++)
|
||||
{
|
||||
//NOTE: for TRAVEL_ELEVATOR the facenum is the model number of
|
||||
// the elevator
|
||||
if ((aasworld.reachability[i].traveltype & TRAVELTYPE_MASK) == TRAVEL_ELEVATOR) continue;
|
||||
//NOTE: for TRAVEL_JUMPPAD the facenum is the Z velocity and the edgenum is the hor velocity
|
||||
if ((aasworld.reachability[i].traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMPPAD) continue;
|
||||
//NOTE: for TRAVEL_FUNCBOB the facenum and edgenum contain other coded information
|
||||
if ((aasworld.reachability[i].traveltype & TRAVELTYPE_MASK) == TRAVEL_FUNCBOB) continue;
|
||||
//
|
||||
sign = aasworld.reachability[i].facenum;
|
||||
aasworld.reachability[i].facenum = optimized.faceoptimizeindex[abs(aasworld.reachability[i].facenum)];
|
||||
if (sign < 0) aasworld.reachability[i].facenum = -aasworld.reachability[i].facenum;
|
||||
sign = aasworld.reachability[i].edgenum;
|
||||
aasworld.reachability[i].edgenum = optimized.edgeoptimizeindex[abs(aasworld.reachability[i].edgenum)];
|
||||
if (sign < 0) aasworld.reachability[i].edgenum = -aasworld.reachability[i].edgenum;
|
||||
} //end for
|
||||
//store the optimized AAS data into aasworld
|
||||
AAS_OptimizeStore(&optimized);
|
||||
//print some nice stuff :)
|
||||
botimport.Print(PRT_MESSAGE, "AAS data optimized.\n");
|
||||
} //end of the function AAS_Optimize
|
16
CODEmp/botlib/be_aas_optimize.h
Normal file
16
CODEmp/botlib/be_aas_optimize.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_optimize.h
|
||||
*
|
||||
* desc: AAS
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_aas_optimize.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void AAS_Optimize(void);
|
||||
|
4525
CODEmp/botlib/be_aas_reach.cpp
Normal file
4525
CODEmp/botlib/be_aas_reach.cpp
Normal file
File diff suppressed because it is too large
Load diff
51
CODEmp/botlib/be_aas_reach.h
Normal file
51
CODEmp/botlib/be_aas_reach.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_reach.h
|
||||
*
|
||||
* desc: AAS
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_aas_reach.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef AASINTERN
|
||||
//initialize calculating the reachabilities
|
||||
void AAS_InitReachability(void);
|
||||
//continue calculating the reachabilities
|
||||
int AAS_ContinueInitReachability(float time);
|
||||
//
|
||||
int AAS_BestReachableLinkArea(aas_link_t *areas);
|
||||
#endif //AASINTERN
|
||||
|
||||
//returns true if the are has reachabilities to other areas
|
||||
int AAS_AreaReachability(int areanum);
|
||||
//returns the best reachable area and goal origin for a bounding box at the given origin
|
||||
int AAS_BestReachableArea(vec3_t origin, vec3_t mins, vec3_t maxs, vec3_t goalorigin);
|
||||
//returns the best jumppad area from which the bbox at origin is reachable
|
||||
int AAS_BestReachableFromJumpPadArea(vec3_t origin, vec3_t mins, vec3_t maxs);
|
||||
//returns the next reachability using the given model
|
||||
int AAS_NextModelReachability(int num, int modelnum);
|
||||
//returns the total area of the ground faces of the given area
|
||||
float AAS_AreaGroundFaceArea(int areanum);
|
||||
//returns true if the area is crouch only
|
||||
int AAS_AreaCrouch(int areanum);
|
||||
//returns true if a player can swim in this area
|
||||
int AAS_AreaSwim(int areanum);
|
||||
//returns true if the area is filled with a liquid
|
||||
int AAS_AreaLiquid(int areanum);
|
||||
//returns true if the area contains lava
|
||||
int AAS_AreaLava(int areanum);
|
||||
//returns true if the area contains slime
|
||||
int AAS_AreaSlime(int areanum);
|
||||
//returns true if the area has one or more ground faces
|
||||
int AAS_AreaGrounded(int areanum);
|
||||
//returns true if the area has one or more ladder faces
|
||||
int AAS_AreaLadder(int areanum);
|
||||
//returns true if the area is a jump pad
|
||||
int AAS_AreaJumpPad(int areanum);
|
||||
//returns true if the area is donotenter
|
||||
int AAS_AreaDoNotEnter(int areanum);
|
2192
CODEmp/botlib/be_aas_route.cpp
Normal file
2192
CODEmp/botlib/be_aas_route.cpp
Normal file
File diff suppressed because it is too large
Load diff
50
CODEmp/botlib/be_aas_route.h
Normal file
50
CODEmp/botlib/be_aas_route.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_route.h
|
||||
*
|
||||
* desc: AAS
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_aas_route.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef AASINTERN
|
||||
//initialize the AAS routing
|
||||
void AAS_InitRouting(void);
|
||||
//free the AAS routing caches
|
||||
void AAS_FreeRoutingCaches(void);
|
||||
//returns the travel time from start to end in the given area
|
||||
unsigned short int AAS_AreaTravelTime(int areanum, vec3_t start, vec3_t end);
|
||||
//
|
||||
void AAS_CreateAllRoutingCache(void);
|
||||
void AAS_WriteRouteCache(void);
|
||||
//
|
||||
void AAS_RoutingInfo(void);
|
||||
#endif //AASINTERN
|
||||
|
||||
//returns the travel flag for the given travel type
|
||||
int AAS_TravelFlagForType(int traveltype);
|
||||
//return the travel flag(s) for traveling through this area
|
||||
int AAS_AreaContentsTravelFlags(int areanum);
|
||||
//returns the index of the next reachability for the given area
|
||||
int AAS_NextAreaReachability(int areanum, int reachnum);
|
||||
//returns the reachability with the given index
|
||||
void AAS_ReachabilityFromNum(int num, struct aas_reachability_s *reach);
|
||||
//returns a random goal area and goal origin
|
||||
int AAS_RandomGoalArea(int areanum, int travelflags, int *goalareanum, vec3_t goalorigin);
|
||||
//enable or disable an area for routing
|
||||
int AAS_EnableRoutingArea(int areanum, int enable);
|
||||
//returns the travel time within the given area from start to end
|
||||
unsigned short int AAS_AreaTravelTime(int areanum, vec3_t start, vec3_t end);
|
||||
//returns the travel time from the area to the goal area using the given travel flags
|
||||
int AAS_AreaTravelTimeToGoalArea(int areanum, vec3_t origin, int goalareanum, int travelflags);
|
||||
//predict a route up to a stop event
|
||||
int AAS_PredictRoute(struct aas_predictroute_s *route, int areanum, vec3_t origin,
|
||||
int goalareanum, int travelflags, int maxareas, int maxtime,
|
||||
int stopevent, int stopcontents, int stoptfl, int stopareanum);
|
||||
|
||||
|
223
CODEmp/botlib/be_aas_routealt.cpp
Normal file
223
CODEmp/botlib/be_aas_routealt.cpp
Normal file
|
@ -0,0 +1,223 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_routealt.c
|
||||
*
|
||||
* desc: AAS
|
||||
*
|
||||
* $Archive: /MissionPack/code/botlib/be_aas_routealt.c $
|
||||
* $Author: Zaphod $
|
||||
* $Revision: 5 $
|
||||
* $Modtime: 11/22/00 8:47a $
|
||||
* $Date: 11/22/00 8:55a $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "l_utils.h"
|
||||
#include "l_memory.h"
|
||||
#include "l_log.h"
|
||||
#include "l_script.h"
|
||||
#include "l_precomp.h"
|
||||
#include "l_struct.h"
|
||||
#include "aasfile.h"
|
||||
#include "../game/botlib.h"
|
||||
#include "../game/be_aas.h"
|
||||
#include "be_aas_funcs.h"
|
||||
#include "be_interface.h"
|
||||
#include "be_aas_def.h"
|
||||
|
||||
#define ENABLE_ALTROUTING
|
||||
//#define ALTROUTE_DEBUG
|
||||
|
||||
typedef struct midrangearea_s
|
||||
{
|
||||
int valid;
|
||||
unsigned short starttime;
|
||||
unsigned short goaltime;
|
||||
} midrangearea_t;
|
||||
|
||||
midrangearea_t *midrangeareas;
|
||||
int *clusterareas;
|
||||
int numclusterareas;
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_AltRoutingFloodCluster_r(int areanum)
|
||||
{
|
||||
int i, otherareanum;
|
||||
aas_area_t *area;
|
||||
aas_face_t *face;
|
||||
|
||||
//add the current area to the areas of the current cluster
|
||||
clusterareas[numclusterareas] = areanum;
|
||||
numclusterareas++;
|
||||
//remove the area from the mid range areas
|
||||
midrangeareas[areanum].valid = qfalse;
|
||||
//flood to other areas through the faces of this area
|
||||
area = &aasworld.areas[areanum];
|
||||
for (i = 0; i < area->numfaces; i++)
|
||||
{
|
||||
face = &aasworld.faces[abs(aasworld.faceindex[area->firstface + i])];
|
||||
//get the area at the other side of the face
|
||||
if (face->frontarea == areanum) otherareanum = face->backarea;
|
||||
else otherareanum = face->frontarea;
|
||||
//if there is an area at the other side of this face
|
||||
if (!otherareanum) continue;
|
||||
//if the other area is not a midrange area
|
||||
if (!midrangeareas[otherareanum].valid) continue;
|
||||
//
|
||||
AAS_AltRoutingFloodCluster_r(otherareanum);
|
||||
} //end for
|
||||
} //end of the function AAS_AltRoutingFloodCluster_r
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AAS_AlternativeRouteGoals(vec3_t start, int startareanum, vec3_t goal, int goalareanum, int travelflags,
|
||||
aas_altroutegoal_t *altroutegoals, int maxaltroutegoals,
|
||||
int type)
|
||||
{
|
||||
#ifndef ENABLE_ALTROUTING
|
||||
return 0;
|
||||
#else
|
||||
int i, j, bestareanum;
|
||||
int numaltroutegoals, nummidrangeareas;
|
||||
int starttime, goaltime, goaltraveltime;
|
||||
float dist, bestdist;
|
||||
vec3_t mid, dir;
|
||||
#ifdef ALTROUTE_DEBUG
|
||||
int startmillisecs;
|
||||
|
||||
startmillisecs = Sys_MilliSeconds();
|
||||
#endif
|
||||
|
||||
if (!startareanum || !goalareanum)
|
||||
return 0;
|
||||
//travel time towards the goal area
|
||||
goaltraveltime = AAS_AreaTravelTimeToGoalArea(startareanum, start, goalareanum, travelflags);
|
||||
//clear the midrange areas
|
||||
Com_Memset(midrangeareas, 0, aasworld.numareas * sizeof(midrangearea_t));
|
||||
numaltroutegoals = 0;
|
||||
//
|
||||
nummidrangeareas = 0;
|
||||
//
|
||||
for (i = 1; i < aasworld.numareas; i++)
|
||||
{
|
||||
//
|
||||
if (!(type & ALTROUTEGOAL_ALL))
|
||||
{
|
||||
if (!(type & ALTROUTEGOAL_CLUSTERPORTALS && (aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL)))
|
||||
{
|
||||
if (!(type & ALTROUTEGOAL_VIEWPORTALS && (aasworld.areasettings[i].contents & AREACONTENTS_VIEWPORTAL)))
|
||||
{
|
||||
continue;
|
||||
} //end if
|
||||
} //end if
|
||||
} //end if
|
||||
//if the area has no reachabilities
|
||||
if (!AAS_AreaReachability(i)) continue;
|
||||
//tavel time from the area to the start area
|
||||
starttime = AAS_AreaTravelTimeToGoalArea(startareanum, start, i, travelflags);
|
||||
if (!starttime) continue;
|
||||
//if the travel time from the start to the area is greater than the shortest goal travel time
|
||||
if (starttime > (float) 1.1 * goaltraveltime) continue;
|
||||
//travel time from the area to the goal area
|
||||
goaltime = AAS_AreaTravelTimeToGoalArea(i, NULL, goalareanum, travelflags);
|
||||
if (!goaltime) continue;
|
||||
//if the travel time from the area to the goal is greater than the shortest goal travel time
|
||||
if (goaltime > (float) 0.8 * goaltraveltime) continue;
|
||||
//this is a mid range area
|
||||
midrangeareas[i].valid = qtrue;
|
||||
midrangeareas[i].starttime = starttime;
|
||||
midrangeareas[i].goaltime = goaltime;
|
||||
Log_Write("%d midrange area %d", nummidrangeareas, i);
|
||||
nummidrangeareas++;
|
||||
} //end for
|
||||
//
|
||||
for (i = 1; i < aasworld.numareas; i++)
|
||||
{
|
||||
if (!midrangeareas[i].valid) continue;
|
||||
//get the areas in one cluster
|
||||
numclusterareas = 0;
|
||||
AAS_AltRoutingFloodCluster_r(i);
|
||||
//now we've got a cluster with areas through which an alternative route could go
|
||||
//get the 'center' of the cluster
|
||||
VectorClear(mid);
|
||||
for (j = 0; j < numclusterareas; j++)
|
||||
{
|
||||
VectorAdd(mid, aasworld.areas[clusterareas[j]].center, mid);
|
||||
} //end for
|
||||
VectorScale(mid, 1.0 / numclusterareas, mid);
|
||||
//get the area closest to the center of the cluster
|
||||
bestdist = 999999;
|
||||
bestareanum = 0;
|
||||
for (j = 0; j < numclusterareas; j++)
|
||||
{
|
||||
VectorSubtract(mid, aasworld.areas[clusterareas[j]].center, dir);
|
||||
dist = VectorLength(dir);
|
||||
if (dist < bestdist)
|
||||
{
|
||||
bestdist = dist;
|
||||
bestareanum = clusterareas[j];
|
||||
} //end if
|
||||
} //end for
|
||||
//now we've got an area for an alternative route
|
||||
//FIXME: add alternative goal origin
|
||||
VectorCopy(aasworld.areas[bestareanum].center, altroutegoals[numaltroutegoals].origin);
|
||||
altroutegoals[numaltroutegoals].areanum = bestareanum;
|
||||
altroutegoals[numaltroutegoals].starttraveltime = midrangeareas[bestareanum].starttime;
|
||||
altroutegoals[numaltroutegoals].goaltraveltime = midrangeareas[bestareanum].goaltime;
|
||||
altroutegoals[numaltroutegoals].extratraveltime =
|
||||
(midrangeareas[bestareanum].starttime + midrangeareas[bestareanum].goaltime) -
|
||||
goaltraveltime;
|
||||
numaltroutegoals++;
|
||||
//
|
||||
#ifdef ALTROUTE_DEBUG
|
||||
AAS_ShowAreaPolygons(bestareanum, 1, qtrue);
|
||||
#endif
|
||||
//don't return more than the maximum alternative route goals
|
||||
if (numaltroutegoals >= maxaltroutegoals) break;
|
||||
} //end for
|
||||
#ifdef ALTROUTE_DEBUG
|
||||
botimport.Print(PRT_MESSAGE, "alternative route goals in %d msec\n", Sys_MilliSeconds() - startmillisecs);
|
||||
#endif
|
||||
return numaltroutegoals;
|
||||
#endif
|
||||
} //end of the function AAS_AlternativeRouteGoals
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_InitAlternativeRouting(void)
|
||||
{
|
||||
#ifdef ENABLE_ALTROUTING
|
||||
if (midrangeareas) FreeMemory(midrangeareas);
|
||||
midrangeareas = (midrangearea_t *) GetMemory(aasworld.numareas * sizeof(midrangearea_t));
|
||||
if (clusterareas) FreeMemory(clusterareas);
|
||||
clusterareas = (int *) GetMemory(aasworld.numareas * sizeof(int));
|
||||
#endif
|
||||
} //end of the function AAS_InitAlternativeRouting
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_ShutdownAlternativeRouting(void)
|
||||
{
|
||||
#ifdef ENABLE_ALTROUTING
|
||||
if (midrangeareas) FreeMemory(midrangeareas);
|
||||
midrangeareas = NULL;
|
||||
if (clusterareas) FreeMemory(clusterareas);
|
||||
clusterareas = NULL;
|
||||
numclusterareas = 0;
|
||||
#endif
|
||||
} //end of the function AAS_ShutdownAlternativeRouting
|
23
CODEmp/botlib/be_aas_routealt.h
Normal file
23
CODEmp/botlib/be_aas_routealt.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_routealt.h
|
||||
*
|
||||
* desc: AAS
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_aas_routealt.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef AASINTERN
|
||||
void AAS_InitAlternativeRouting(void);
|
||||
void AAS_ShutdownAlternativeRouting(void);
|
||||
#endif //AASINTERN
|
||||
|
||||
|
||||
int AAS_AlternativeRouteGoals(vec3_t start, int startareanum, vec3_t goal, int goalareanum, int travelflags,
|
||||
aas_altroutegoal_t *altroutegoals, int maxaltroutegoals,
|
||||
int type);
|
1377
CODEmp/botlib/be_aas_sample.cpp
Normal file
1377
CODEmp/botlib/be_aas_sample.cpp
Normal file
File diff suppressed because it is too large
Load diff
52
CODEmp/botlib/be_aas_sample.h
Normal file
52
CODEmp/botlib/be_aas_sample.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_aas_sample.h
|
||||
*
|
||||
* desc: AAS
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_aas_sample.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef AASINTERN
|
||||
void AAS_InitAASLinkHeap(void);
|
||||
void AAS_InitAASLinkedEntities(void);
|
||||
void AAS_FreeAASLinkHeap(void);
|
||||
void AAS_FreeAASLinkedEntities(void);
|
||||
aas_face_t *AAS_AreaGroundFace(int areanum, vec3_t point);
|
||||
aas_face_t *AAS_TraceEndFace(aas_trace_t *trace);
|
||||
aas_plane_t *AAS_PlaneFromNum(int planenum);
|
||||
aas_link_t *AAS_AASLinkEntity(vec3_t absmins, vec3_t absmaxs, int entnum);
|
||||
aas_link_t *AAS_LinkEntityClientBBox(vec3_t absmins, vec3_t absmaxs, int entnum, int presencetype);
|
||||
qboolean AAS_PointInsideFace(int facenum, vec3_t point, float epsilon);
|
||||
qboolean AAS_InsideFace(aas_face_t *face, vec3_t pnormal, vec3_t point, float epsilon);
|
||||
void AAS_UnlinkFromAreas(aas_link_t *areas);
|
||||
#endif //AASINTERN
|
||||
|
||||
//returns the mins and maxs of the bounding box for the given presence type
|
||||
void AAS_PresenceTypeBoundingBox(int presencetype, vec3_t mins, vec3_t maxs);
|
||||
//returns the cluster the area is in (negative portal number if the area is a portal)
|
||||
int AAS_AreaCluster(int areanum);
|
||||
//returns the presence type(s) of the area
|
||||
int AAS_AreaPresenceType(int areanum);
|
||||
//returns the presence type(s) at the given point
|
||||
int AAS_PointPresenceType(vec3_t point);
|
||||
//returns the result of the trace of a client bbox
|
||||
aas_trace_t AAS_TraceClientBBox(vec3_t start, vec3_t end, int presencetype, int passent);
|
||||
//stores the areas the trace went through and returns the number of passed areas
|
||||
int AAS_TraceAreas(vec3_t start, vec3_t end, int *areas, vec3_t *points, int maxareas);
|
||||
//returns the areas the bounding box is in
|
||||
int AAS_BBoxAreas(vec3_t absmins, vec3_t absmaxs, int *areas, int maxareas);
|
||||
//return area information
|
||||
int AAS_AreaInfo( int areanum, aas_areainfo_t *info );
|
||||
//returns the area the point is in
|
||||
int AAS_PointAreaNum(vec3_t point);
|
||||
//
|
||||
int AAS_PointReachabilityAreaIndex( vec3_t point );
|
||||
//returns the plane the given face is in
|
||||
void AAS_FacePlane(int facenum, vec3_t normal, float *dist);
|
||||
|
773
CODEmp/botlib/be_ai_char.cpp
Normal file
773
CODEmp/botlib/be_ai_char.cpp
Normal file
|
@ -0,0 +1,773 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_ai_char.c
|
||||
*
|
||||
* desc: bot characters
|
||||
*
|
||||
* $Archive: /MissionPack/code/botlib/be_ai_char.c $
|
||||
* $Author: Ttimo $
|
||||
* $Revision: 6 $
|
||||
* $Modtime: 4/22/01 8:52a $
|
||||
* $Date: 4/22/01 8:52a $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "l_log.h"
|
||||
#include "l_memory.h"
|
||||
#include "l_utils.h"
|
||||
#include "l_script.h"
|
||||
#include "l_precomp.h"
|
||||
#include "l_struct.h"
|
||||
#include "l_libvar.h"
|
||||
#include "aasfile.h"
|
||||
#include "../game/botlib.h"
|
||||
#include "../game/be_aas.h"
|
||||
#include "be_aas_funcs.h"
|
||||
#include "be_interface.h"
|
||||
#include "../game/be_ai_char.h"
|
||||
|
||||
#define MAX_CHARACTERISTICS 80
|
||||
|
||||
#define CT_INTEGER 1
|
||||
#define CT_FLOAT 2
|
||||
#define CT_STRING 3
|
||||
|
||||
#define DEFAULT_CHARACTER "bots/default_c.c"
|
||||
|
||||
//characteristic value
|
||||
union cvalue
|
||||
{
|
||||
int integer;
|
||||
float _float;
|
||||
char *string;
|
||||
};
|
||||
//a characteristic
|
||||
typedef struct bot_characteristic_s
|
||||
{
|
||||
char type; //characteristic type
|
||||
union cvalue value; //characteristic value
|
||||
} bot_characteristic_t;
|
||||
|
||||
//a bot character
|
||||
typedef struct bot_character_s
|
||||
{
|
||||
char filename[MAX_QPATH];
|
||||
float skill;
|
||||
bot_characteristic_t c[1]; //variable sized
|
||||
} bot_character_t;
|
||||
|
||||
bot_character_t *botcharacters[MAX_CLIENTS + 1];
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//========================================================================
|
||||
bot_character_t *BotCharacterFromHandle(int handle)
|
||||
{
|
||||
if (handle <= 0 || handle > MAX_CLIENTS)
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "character handle %d out of range\n", handle);
|
||||
return NULL;
|
||||
} //end if
|
||||
if (!botcharacters[handle])
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "invalid character %d\n", handle);
|
||||
return NULL;
|
||||
} //end if
|
||||
return botcharacters[handle];
|
||||
} //end of the function BotCharacterFromHandle
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void BotDumpCharacter(bot_character_t *ch)
|
||||
{
|
||||
int i;
|
||||
|
||||
Log_Write("%s", ch->filename);
|
||||
Log_Write("skill %d\n", ch->skill);
|
||||
Log_Write("{\n");
|
||||
for (i = 0; i < MAX_CHARACTERISTICS; i++)
|
||||
{
|
||||
switch(ch->c[i].type)
|
||||
{
|
||||
case CT_INTEGER: Log_Write(" %4d %d\n", i, ch->c[i].value.integer); break;
|
||||
case CT_FLOAT: Log_Write(" %4d %f\n", i, ch->c[i].value._float); break;
|
||||
case CT_STRING: Log_Write(" %4d %s\n", i, ch->c[i].value.string); break;
|
||||
} //end case
|
||||
} //end for
|
||||
Log_Write("}\n");
|
||||
} //end of the function BotDumpCharacter
|
||||
//========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//========================================================================
|
||||
void BotFreeCharacterStrings(bot_character_t *ch)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CHARACTERISTICS; i++)
|
||||
{
|
||||
if (ch->c[i].type == CT_STRING)
|
||||
{
|
||||
FreeMemory(ch->c[i].value.string);
|
||||
} //end if
|
||||
} //end for
|
||||
} //end of the function BotFreeCharacterStrings
|
||||
//========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//========================================================================
|
||||
void BotFreeCharacter2(int handle)
|
||||
{
|
||||
if (handle <= 0 || handle > MAX_CLIENTS)
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "character handle %d out of range\n", handle);
|
||||
return;
|
||||
} //end if
|
||||
if (!botcharacters[handle])
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "invalid character %d\n", handle);
|
||||
return;
|
||||
} //end if
|
||||
BotFreeCharacterStrings(botcharacters[handle]);
|
||||
FreeMemory(botcharacters[handle]);
|
||||
botcharacters[handle] = NULL;
|
||||
} //end of the function BotFreeCharacter2
|
||||
//========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//========================================================================
|
||||
void BotFreeCharacter(int handle)
|
||||
{
|
||||
if (!LibVarGetValue("bot_reloadcharacters")) return;
|
||||
BotFreeCharacter2(handle);
|
||||
} //end of the function BotFreeCharacter
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void BotDefaultCharacteristics(bot_character_t *ch, bot_character_t *defaultch)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CHARACTERISTICS; i++)
|
||||
{
|
||||
if (ch->c[i].type) continue;
|
||||
//
|
||||
if (defaultch->c[i].type == CT_FLOAT)
|
||||
{
|
||||
ch->c[i].type = CT_FLOAT;
|
||||
ch->c[i].value._float = defaultch->c[i].value._float;
|
||||
} //end if
|
||||
else if (defaultch->c[i].type == CT_INTEGER)
|
||||
{
|
||||
ch->c[i].type = CT_INTEGER;
|
||||
ch->c[i].value.integer = defaultch->c[i].value.integer;
|
||||
} //end else if
|
||||
else if (defaultch->c[i].type == CT_STRING)
|
||||
{
|
||||
ch->c[i].type = CT_STRING;
|
||||
ch->c[i].value.string = (char *) GetMemory(strlen(defaultch->c[i].value.string)+1);
|
||||
strcpy(ch->c[i].value.string, defaultch->c[i].value.string);
|
||||
} //end else if
|
||||
} //end for
|
||||
} //end of the function BotDefaultCharacteristics
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
bot_character_t *BotLoadCharacterFromFile(char *charfile, int skill)
|
||||
{
|
||||
int indent, index, foundcharacter;
|
||||
bot_character_t *ch;
|
||||
source_t *source;
|
||||
token_t token;
|
||||
|
||||
foundcharacter = qfalse;
|
||||
//a bot character is parsed in two phases
|
||||
PC_SetBaseFolder(BOTFILESBASEFOLDER);
|
||||
source = LoadSourceFile(charfile);
|
||||
if (!source)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "counldn't load %s\n", charfile);
|
||||
return NULL;
|
||||
} //end if
|
||||
ch = (bot_character_t *) GetClearedMemory(sizeof(bot_character_t) +
|
||||
MAX_CHARACTERISTICS * sizeof(bot_characteristic_t));
|
||||
strcpy(ch->filename, charfile);
|
||||
while(PC_ReadToken(source, &token))
|
||||
{
|
||||
if (!strcmp(token.string, "skill"))
|
||||
{
|
||||
if (!PC_ExpectTokenType(source, TT_NUMBER, 0, &token))
|
||||
{
|
||||
FreeSource(source);
|
||||
BotFreeCharacterStrings(ch);
|
||||
FreeMemory(ch);
|
||||
return NULL;
|
||||
} //end if
|
||||
if (!PC_ExpectTokenString(source, "{"))
|
||||
{
|
||||
FreeSource(source);
|
||||
BotFreeCharacterStrings(ch);
|
||||
FreeMemory(ch);
|
||||
return NULL;
|
||||
} //end if
|
||||
//if it's the correct skill
|
||||
if (skill < 0 || token.intvalue == skill)
|
||||
{
|
||||
foundcharacter = qtrue;
|
||||
ch->skill = token.intvalue;
|
||||
while(PC_ExpectAnyToken(source, &token))
|
||||
{
|
||||
if (!strcmp(token.string, "}")) break;
|
||||
if (token.type != TT_NUMBER || !(token.subtype & TT_INTEGER))
|
||||
{
|
||||
SourceError(source, "expected integer index, found %s\n", token.string);
|
||||
FreeSource(source);
|
||||
BotFreeCharacterStrings(ch);
|
||||
FreeMemory(ch);
|
||||
return NULL;
|
||||
} //end if
|
||||
index = token.intvalue;
|
||||
if (index < 0 || index > MAX_CHARACTERISTICS)
|
||||
{
|
||||
SourceError(source, "characteristic index out of range [0, %d]\n", MAX_CHARACTERISTICS);
|
||||
FreeSource(source);
|
||||
BotFreeCharacterStrings(ch);
|
||||
FreeMemory(ch);
|
||||
return NULL;
|
||||
} //end if
|
||||
if (ch->c[index].type)
|
||||
{
|
||||
SourceError(source, "characteristic %d already initialized\n", index);
|
||||
FreeSource(source);
|
||||
BotFreeCharacterStrings(ch);
|
||||
FreeMemory(ch);
|
||||
return NULL;
|
||||
} //end if
|
||||
if (!PC_ExpectAnyToken(source, &token))
|
||||
{
|
||||
FreeSource(source);
|
||||
BotFreeCharacterStrings(ch);
|
||||
FreeMemory(ch);
|
||||
return NULL;
|
||||
} //end if
|
||||
if (token.type == TT_NUMBER)
|
||||
{
|
||||
if (token.subtype & TT_FLOAT)
|
||||
{
|
||||
ch->c[index].value._float = token.floatvalue;
|
||||
ch->c[index].type = CT_FLOAT;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
ch->c[index].value.integer = token.intvalue;
|
||||
ch->c[index].type = CT_INTEGER;
|
||||
} //end else
|
||||
} //end if
|
||||
else if (token.type == TT_STRING)
|
||||
{
|
||||
StripDoubleQuotes(token.string);
|
||||
ch->c[index].value.string = (char *)GetMemory(strlen(token.string)+1);
|
||||
strcpy(ch->c[index].value.string, token.string);
|
||||
ch->c[index].type = CT_STRING;
|
||||
} //end else if
|
||||
else
|
||||
{
|
||||
SourceError(source, "expected integer, float or string, found %s\n", token.string);
|
||||
FreeSource(source);
|
||||
BotFreeCharacterStrings(ch);
|
||||
FreeMemory(ch);
|
||||
return NULL;
|
||||
} //end else
|
||||
} //end if
|
||||
break;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
indent = 1;
|
||||
while(indent)
|
||||
{
|
||||
if (!PC_ExpectAnyToken(source, &token))
|
||||
{
|
||||
FreeSource(source);
|
||||
BotFreeCharacterStrings(ch);
|
||||
FreeMemory(ch);
|
||||
return NULL;
|
||||
} //end if
|
||||
if (!strcmp(token.string, "{")) indent++;
|
||||
else if (!strcmp(token.string, "}")) indent--;
|
||||
} //end while
|
||||
} //end else
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
SourceError(source, "unknown definition %s\n", token.string);
|
||||
FreeSource(source);
|
||||
BotFreeCharacterStrings(ch);
|
||||
FreeMemory(ch);
|
||||
return NULL;
|
||||
} //end else
|
||||
} //end while
|
||||
FreeSource(source);
|
||||
//
|
||||
if (!foundcharacter)
|
||||
{
|
||||
BotFreeCharacterStrings(ch);
|
||||
FreeMemory(ch);
|
||||
return NULL;
|
||||
} //end if
|
||||
return ch;
|
||||
} //end of the function BotLoadCharacterFromFile
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int BotFindCachedCharacter(char *charfile, float skill)
|
||||
{
|
||||
int handle;
|
||||
|
||||
for (handle = 1; handle <= MAX_CLIENTS; handle++)
|
||||
{
|
||||
if ( !botcharacters[handle] ) continue;
|
||||
if ( strcmp( botcharacters[handle]->filename, charfile ) == 0 &&
|
||||
(skill < 0 || fabs(botcharacters[handle]->skill - skill) < 0.01) )
|
||||
{
|
||||
return handle;
|
||||
} //end if
|
||||
} //end for
|
||||
return 0;
|
||||
} //end of the function BotFindCachedCharacter
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int BotLoadCachedCharacter(char *charfile, float skill, int reload)
|
||||
{
|
||||
int handle, cachedhandle, intskill;
|
||||
bot_character_t *ch = NULL;
|
||||
#ifdef DEBUG
|
||||
int starttime;
|
||||
|
||||
starttime = Sys_MilliSeconds();
|
||||
#endif //DEBUG
|
||||
|
||||
//find a free spot for a character
|
||||
for (handle = 1; handle <= MAX_CLIENTS; handle++)
|
||||
{
|
||||
if (!botcharacters[handle]) break;
|
||||
} //end for
|
||||
if (handle > MAX_CLIENTS) return 0;
|
||||
//try to load a cached character with the given skill
|
||||
if (!reload)
|
||||
{
|
||||
cachedhandle = BotFindCachedCharacter(charfile, skill);
|
||||
if (cachedhandle)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "loaded cached skill %f from %s\n", skill, charfile);
|
||||
return cachedhandle;
|
||||
} //end if
|
||||
} //end else
|
||||
//
|
||||
intskill = (int) (skill + 0.5);
|
||||
//try to load the character with the given skill
|
||||
ch = BotLoadCharacterFromFile(charfile, intskill);
|
||||
if (ch)
|
||||
{
|
||||
botcharacters[handle] = ch;
|
||||
//
|
||||
botimport.Print(PRT_MESSAGE, "loaded skill %d from %s\n", intskill, charfile);
|
||||
#ifdef DEBUG
|
||||
if (bot_developer)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "skill %d loaded in %d msec from %s\n", intskill, Sys_MilliSeconds() - starttime, charfile);
|
||||
} //end if
|
||||
#endif //DEBUG
|
||||
return handle;
|
||||
} //end if
|
||||
//
|
||||
botimport.Print(PRT_WARNING, "couldn't find skill %d in %s\n", intskill, charfile);
|
||||
//
|
||||
if (!reload)
|
||||
{
|
||||
//try to load a cached default character with the given skill
|
||||
cachedhandle = BotFindCachedCharacter(DEFAULT_CHARACTER, skill);
|
||||
if (cachedhandle)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "loaded cached default skill %d from %s\n", intskill, charfile);
|
||||
return cachedhandle;
|
||||
} //end if
|
||||
} //end if
|
||||
//try to load the default character with the given skill
|
||||
ch = BotLoadCharacterFromFile(DEFAULT_CHARACTER, intskill);
|
||||
if (ch)
|
||||
{
|
||||
botcharacters[handle] = ch;
|
||||
botimport.Print(PRT_MESSAGE, "loaded default skill %d from %s\n", intskill, charfile);
|
||||
return handle;
|
||||
} //end if
|
||||
//
|
||||
if (!reload)
|
||||
{
|
||||
//try to load a cached character with any skill
|
||||
cachedhandle = BotFindCachedCharacter(charfile, -1);
|
||||
if (cachedhandle)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "loaded cached skill %f from %s\n", botcharacters[cachedhandle]->skill, charfile);
|
||||
return cachedhandle;
|
||||
} //end if
|
||||
} //end if
|
||||
//try to load a character with any skill
|
||||
ch = BotLoadCharacterFromFile(charfile, -1);
|
||||
if (ch)
|
||||
{
|
||||
botcharacters[handle] = ch;
|
||||
botimport.Print(PRT_MESSAGE, "loaded skill %f from %s\n", ch->skill, charfile);
|
||||
return handle;
|
||||
} //end if
|
||||
//
|
||||
if (!reload)
|
||||
{
|
||||
//try to load a cached character with any skill
|
||||
cachedhandle = BotFindCachedCharacter(DEFAULT_CHARACTER, -1);
|
||||
if (cachedhandle)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "loaded cached default skill %f from %s\n", botcharacters[cachedhandle]->skill, charfile);
|
||||
return cachedhandle;
|
||||
} //end if
|
||||
} //end if
|
||||
//try to load a character with any skill
|
||||
ch = BotLoadCharacterFromFile(DEFAULT_CHARACTER, -1);
|
||||
if (ch)
|
||||
{
|
||||
botcharacters[handle] = ch;
|
||||
botimport.Print(PRT_MESSAGE, "loaded default skill %f from %s\n", ch->skill, charfile);
|
||||
return handle;
|
||||
} //end if
|
||||
//
|
||||
botimport.Print(PRT_WARNING, "couldn't load any skill from %s\n", charfile);
|
||||
//couldn't load any character
|
||||
return 0;
|
||||
} //end of the function BotLoadCachedCharacter
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int BotLoadCharacterSkill(char *charfile, float skill)
|
||||
{
|
||||
int ch, defaultch;
|
||||
|
||||
defaultch = BotLoadCachedCharacter(DEFAULT_CHARACTER, skill, qfalse);
|
||||
ch = BotLoadCachedCharacter(charfile, skill, LibVarGetValue("bot_reloadcharacters"));
|
||||
|
||||
if (defaultch && ch)
|
||||
{
|
||||
BotDefaultCharacteristics(botcharacters[ch], botcharacters[defaultch]);
|
||||
} //end if
|
||||
|
||||
return ch;
|
||||
} //end of the function BotLoadCharacterSkill
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int BotInterpolateCharacters(int handle1, int handle2, float desiredskill)
|
||||
{
|
||||
bot_character_t *ch1, *ch2, *out;
|
||||
int i, handle;
|
||||
float scale;
|
||||
|
||||
ch1 = BotCharacterFromHandle(handle1);
|
||||
ch2 = BotCharacterFromHandle(handle2);
|
||||
if (!ch1 || !ch2)
|
||||
return 0;
|
||||
//find a free spot for a character
|
||||
for (handle = 1; handle <= MAX_CLIENTS; handle++)
|
||||
{
|
||||
if (!botcharacters[handle]) break;
|
||||
} //end for
|
||||
if (handle > MAX_CLIENTS) return 0;
|
||||
out = (bot_character_t *) GetClearedMemory(sizeof(bot_character_t) +
|
||||
MAX_CHARACTERISTICS * sizeof(bot_characteristic_t));
|
||||
out->skill = desiredskill;
|
||||
strcpy(out->filename, ch1->filename);
|
||||
botcharacters[handle] = out;
|
||||
|
||||
scale = (float) (desiredskill - ch1->skill) / (ch2->skill - ch1->skill);
|
||||
for (i = 0; i < MAX_CHARACTERISTICS; i++)
|
||||
{
|
||||
//
|
||||
if (ch1->c[i].type == CT_FLOAT && ch2->c[i].type == CT_FLOAT)
|
||||
{
|
||||
out->c[i].type = CT_FLOAT;
|
||||
out->c[i].value._float = ch1->c[i].value._float +
|
||||
(ch2->c[i].value._float - ch1->c[i].value._float) * scale;
|
||||
} //end if
|
||||
else if (ch1->c[i].type == CT_INTEGER)
|
||||
{
|
||||
out->c[i].type = CT_INTEGER;
|
||||
out->c[i].value.integer = ch1->c[i].value.integer;
|
||||
} //end else if
|
||||
else if (ch1->c[i].type == CT_STRING)
|
||||
{
|
||||
out->c[i].type = CT_STRING;
|
||||
out->c[i].value.string = (char *) GetMemory(strlen(ch1->c[i].value.string)+1);
|
||||
strcpy(out->c[i].value.string, ch1->c[i].value.string);
|
||||
} //end else if
|
||||
} //end for
|
||||
return handle;
|
||||
} //end of the function BotInterpolateCharacters
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int BotLoadCharacter(char *charfile, float skill)
|
||||
{
|
||||
int firstskill, secondskill, handle;
|
||||
|
||||
//make sure the skill is in the valid range
|
||||
if (skill < 1.0) skill = 1.0;
|
||||
else if (skill > 5.0) skill = 5.0;
|
||||
//skill 1, 4 and 5 should be available in the character files
|
||||
if (skill == 1.0 || skill == 4.0 || skill == 5.0)
|
||||
{
|
||||
return BotLoadCharacterSkill(charfile, skill);
|
||||
} //end if
|
||||
//check if there's a cached skill
|
||||
handle = BotFindCachedCharacter(charfile, skill);
|
||||
if (handle)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "loaded cached skill %f from %s\n", skill, charfile);
|
||||
return handle;
|
||||
} //end if
|
||||
if (skill < 4.0)
|
||||
{
|
||||
//load skill 1 and 4
|
||||
firstskill = BotLoadCharacterSkill(charfile, 1);
|
||||
if (!firstskill) return 0;
|
||||
secondskill = BotLoadCharacterSkill(charfile, 4);
|
||||
if (!secondskill) return firstskill;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
//load skill 4 and 5
|
||||
firstskill = BotLoadCharacterSkill(charfile, 4);
|
||||
if (!firstskill) return 0;
|
||||
secondskill = BotLoadCharacterSkill(charfile, 5);
|
||||
if (!secondskill) return firstskill;
|
||||
} //end else
|
||||
//interpolate between the two skills
|
||||
handle = BotInterpolateCharacters(firstskill, secondskill, skill);
|
||||
if (!handle) return 0;
|
||||
//write the character to the log file
|
||||
BotDumpCharacter(botcharacters[handle]);
|
||||
//
|
||||
return handle;
|
||||
} //end of the function BotLoadCharacter
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int CheckCharacteristicIndex(int character, int index)
|
||||
{
|
||||
bot_character_t *ch;
|
||||
|
||||
ch = BotCharacterFromHandle(character);
|
||||
if (!ch) return qfalse;
|
||||
if (index < 0 || index >= MAX_CHARACTERISTICS)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "characteristic %d does not exist\n", index);
|
||||
return qfalse;
|
||||
} //end if
|
||||
if (!ch->c[index].type)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "characteristic %d is not initialized\n", index);
|
||||
return qfalse;
|
||||
} //end if
|
||||
return qtrue;
|
||||
} //end of the function CheckCharacteristicIndex
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
float Characteristic_Float(int character, int index)
|
||||
{
|
||||
bot_character_t *ch;
|
||||
|
||||
ch = BotCharacterFromHandle(character);
|
||||
if (!ch) return 0;
|
||||
//check if the index is in range
|
||||
if (!CheckCharacteristicIndex(character, index)) return 0;
|
||||
//an integer will be converted to a float
|
||||
if (ch->c[index].type == CT_INTEGER)
|
||||
{
|
||||
return (float) ch->c[index].value.integer;
|
||||
} //end if
|
||||
//floats are just returned
|
||||
else if (ch->c[index].type == CT_FLOAT)
|
||||
{
|
||||
return ch->c[index].value._float;
|
||||
} //end else if
|
||||
//cannot convert a string pointer to a float
|
||||
else
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "characteristic %d is not a float\n", index);
|
||||
return 0;
|
||||
} //end else if
|
||||
// return 0;
|
||||
} //end of the function Characteristic_Float
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
float Characteristic_BFloat(int character, int index, float min, float max)
|
||||
{
|
||||
float value;
|
||||
bot_character_t *ch;
|
||||
|
||||
ch = BotCharacterFromHandle(character);
|
||||
if (!ch) return 0;
|
||||
if (min > max)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "cannot bound characteristic %d between %f and %f\n", index, min, max);
|
||||
return 0;
|
||||
} //end if
|
||||
value = Characteristic_Float(character, index);
|
||||
if (value < min) return min;
|
||||
if (value > max) return max;
|
||||
return value;
|
||||
} //end of the function Characteristic_BFloat
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int Characteristic_Integer(int character, int index)
|
||||
{
|
||||
bot_character_t *ch;
|
||||
|
||||
ch = BotCharacterFromHandle(character);
|
||||
if (!ch) return 0;
|
||||
//check if the index is in range
|
||||
if (!CheckCharacteristicIndex(character, index)) return 0;
|
||||
//an integer will just be returned
|
||||
if (ch->c[index].type == CT_INTEGER)
|
||||
{
|
||||
return ch->c[index].value.integer;
|
||||
} //end if
|
||||
//floats are casted to integers
|
||||
else if (ch->c[index].type == CT_FLOAT)
|
||||
{
|
||||
return (int) ch->c[index].value._float;
|
||||
} //end else if
|
||||
else
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "characteristic %d is not a integer\n", index);
|
||||
return 0;
|
||||
} //end else if
|
||||
// return 0;
|
||||
} //end of the function Characteristic_Integer
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int Characteristic_BInteger(int character, int index, int min, int max)
|
||||
{
|
||||
int value;
|
||||
bot_character_t *ch;
|
||||
|
||||
ch = BotCharacterFromHandle(character);
|
||||
if (!ch) return 0;
|
||||
if (min > max)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "cannot bound characteristic %d between %d and %d\n", index, min, max);
|
||||
return 0;
|
||||
} //end if
|
||||
value = Characteristic_Integer(character, index);
|
||||
if (value < min) return min;
|
||||
if (value > max) return max;
|
||||
return value;
|
||||
} //end of the function Characteristic_BInteger
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void Characteristic_String(int character, int index, char *buf, int size)
|
||||
{
|
||||
bot_character_t *ch;
|
||||
|
||||
ch = BotCharacterFromHandle(character);
|
||||
if (!ch) return;
|
||||
//check if the index is in range
|
||||
if (!CheckCharacteristicIndex(character, index)) return;
|
||||
//an integer will be converted to a float
|
||||
if (ch->c[index].type == CT_STRING)
|
||||
{
|
||||
strncpy(buf, ch->c[index].value.string, size-1);
|
||||
buf[size-1] = '\0';
|
||||
return;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "characteristic %d is not a string\n", index);
|
||||
return;
|
||||
} //end else if
|
||||
return;
|
||||
} //end of the function Characteristic_String
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void BotShutdownCharacters(void)
|
||||
{
|
||||
int handle;
|
||||
|
||||
for (handle = 1; handle <= MAX_CLIENTS; handle++)
|
||||
{
|
||||
if (botcharacters[handle])
|
||||
{
|
||||
BotFreeCharacter2(handle);
|
||||
} //end if
|
||||
} //end for
|
||||
} //end of the function BotShutdownCharacters
|
||||
|
3000
CODEmp/botlib/be_ai_chat.cpp
Normal file
3000
CODEmp/botlib/be_ai_chat.cpp
Normal file
File diff suppressed because it is too large
Load diff
117
CODEmp/botlib/be_ai_gen.cpp
Normal file
117
CODEmp/botlib/be_ai_gen.cpp
Normal file
|
@ -0,0 +1,117 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_ai_gen.c
|
||||
*
|
||||
* desc: genetic selection
|
||||
*
|
||||
* $Archive: /MissionPack/code/botlib/be_ai_gen.c $
|
||||
* $Author: Zaphod $
|
||||
* $Revision: 3 $
|
||||
* $Modtime: 11/22/00 8:50a $
|
||||
* $Date: 11/22/00 8:55a $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "l_memory.h"
|
||||
#include "l_log.h"
|
||||
#include "l_utils.h"
|
||||
#include "l_script.h"
|
||||
#include "l_precomp.h"
|
||||
#include "l_struct.h"
|
||||
#include "aasfile.h"
|
||||
#include "../game/botlib.h"
|
||||
#include "../game/be_aas.h"
|
||||
#include "be_aas_funcs.h"
|
||||
#include "be_interface.h"
|
||||
#include "../game/be_ai_gen.h"
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int GeneticSelection(int numranks, float *rankings)
|
||||
{
|
||||
float sum, select;
|
||||
int i, index;
|
||||
|
||||
sum = 0;
|
||||
for (i = 0; i < numranks; i++)
|
||||
{
|
||||
if (rankings[i] < 0) continue;
|
||||
sum += rankings[i];
|
||||
} //end for
|
||||
if (sum > 0)
|
||||
{
|
||||
//select a bot where the ones with the higest rankings have
|
||||
//the highest chance of being selected
|
||||
select = random() * sum;
|
||||
for (i = 0; i < numranks; i++)
|
||||
{
|
||||
if (rankings[i] < 0) continue;
|
||||
sum -= rankings[i];
|
||||
if (sum <= 0) return i;
|
||||
} //end for
|
||||
} //end if
|
||||
//select a bot randomly
|
||||
index = random() * numranks;
|
||||
for (i = 0; i < numranks; i++)
|
||||
{
|
||||
if (rankings[index] >= 0) return index;
|
||||
index = (index + 1) % numranks;
|
||||
} //end for
|
||||
return 0;
|
||||
} //end of the function GeneticSelection
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int GeneticParentsAndChildSelection(int numranks, float *ranks, int *parent1, int *parent2, int *child)
|
||||
{
|
||||
float rankings[256], max;
|
||||
int i;
|
||||
|
||||
if (numranks > 256)
|
||||
{
|
||||
botimport.Print(PRT_WARNING, "GeneticParentsAndChildSelection: too many bots\n");
|
||||
*parent1 = *parent2 = *child = 0;
|
||||
return qfalse;
|
||||
} //end if
|
||||
for (max = 0, i = 0; i < numranks; i++)
|
||||
{
|
||||
if (ranks[i] < 0) continue;
|
||||
max++;
|
||||
} //end for
|
||||
if (max < 3)
|
||||
{
|
||||
botimport.Print(PRT_WARNING, "GeneticParentsAndChildSelection: too few valid bots\n");
|
||||
*parent1 = *parent2 = *child = 0;
|
||||
return qfalse;
|
||||
} //end if
|
||||
Com_Memcpy(rankings, ranks, sizeof(float) * numranks);
|
||||
//select first parent
|
||||
*parent1 = GeneticSelection(numranks, rankings);
|
||||
rankings[*parent1] = -1;
|
||||
//select second parent
|
||||
*parent2 = GeneticSelection(numranks, rankings);
|
||||
rankings[*parent2] = -1;
|
||||
//reverse the rankings
|
||||
max = 0;
|
||||
for (i = 0; i < numranks; i++)
|
||||
{
|
||||
if (rankings[i] < 0) continue;
|
||||
if (rankings[i] > max) max = rankings[i];
|
||||
} //end for
|
||||
for (i = 0; i < numranks; i++)
|
||||
{
|
||||
if (rankings[i] < 0) continue;
|
||||
rankings[i] = max - rankings[i];
|
||||
} //end for
|
||||
//select child
|
||||
*child = GeneticSelection(numranks, rankings);
|
||||
return qtrue;
|
||||
} //end of the function GeneticParentsAndChildSelection
|
1803
CODEmp/botlib/be_ai_goal.cpp
Normal file
1803
CODEmp/botlib/be_ai_goal.cpp
Normal file
File diff suppressed because it is too large
Load diff
3593
CODEmp/botlib/be_ai_move.cpp
Normal file
3593
CODEmp/botlib/be_ai_move.cpp
Normal file
File diff suppressed because it is too large
Load diff
526
CODEmp/botlib/be_ai_weap.cpp
Normal file
526
CODEmp/botlib/be_ai_weap.cpp
Normal file
|
@ -0,0 +1,526 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_ai_weap.c
|
||||
*
|
||||
* desc: weapon AI
|
||||
*
|
||||
* $Archive: /MissionPack/code/botlib/be_ai_weap.c $
|
||||
* $Author: Ttimo $
|
||||
* $Revision: 6 $
|
||||
* $Modtime: 4/13/01 4:45p $
|
||||
* $Date: 4/13/01 4:45p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "l_libvar.h"
|
||||
#include "l_log.h"
|
||||
#include "l_memory.h"
|
||||
#include "l_utils.h"
|
||||
#include "l_script.h"
|
||||
#include "l_precomp.h"
|
||||
#include "l_struct.h"
|
||||
#include "aasfile.h"
|
||||
#include "../game/botlib.h"
|
||||
#include "../game/be_aas.h"
|
||||
#include "be_aas_funcs.h"
|
||||
#include "be_interface.h"
|
||||
#include "be_ai_weight.h" //fuzzy weights
|
||||
#include "../game/be_ai_weap.h"
|
||||
|
||||
//#define DEBUG_AI_WEAP
|
||||
|
||||
//structure field offsets
|
||||
#define WEAPON_OFS(x) (int)&(((weaponinfo_t *)0)->x)
|
||||
#define PROJECTILE_OFS(x) (int)&(((projectileinfo_t *)0)->x)
|
||||
|
||||
//weapon definition // bk001212 - static
|
||||
static fielddef_t weaponinfo_fields[] =
|
||||
{
|
||||
{"number", WEAPON_OFS(number), FT_INT}, //weapon number
|
||||
{"name", WEAPON_OFS(name), FT_STRING}, //name of the weapon
|
||||
{"level", WEAPON_OFS(level), FT_INT},
|
||||
{"model", WEAPON_OFS(model), FT_STRING}, //model of the weapon
|
||||
{"weaponindex", WEAPON_OFS(weaponindex), FT_INT}, //index of weapon in inventory
|
||||
{"flags", WEAPON_OFS(flags), FT_INT}, //special flags
|
||||
{"projectile", WEAPON_OFS(projectile), FT_STRING}, //projectile used by the weapon
|
||||
{"numprojectiles", WEAPON_OFS(numprojectiles), FT_INT}, //number of projectiles
|
||||
{"hspread", WEAPON_OFS(hspread), FT_FLOAT}, //horizontal spread of projectiles (degrees from middle)
|
||||
{"vspread", WEAPON_OFS(vspread), FT_FLOAT}, //vertical spread of projectiles (degrees from middle)
|
||||
{"speed", WEAPON_OFS(speed), FT_FLOAT}, //speed of the projectile (0 = instant hit)
|
||||
{"acceleration", WEAPON_OFS(acceleration), FT_FLOAT}, //"acceleration" * time (in seconds) + "speed" = projectile speed
|
||||
{"recoil", WEAPON_OFS(recoil), FT_FLOAT|FT_ARRAY, 3}, //amount of recoil the player gets from the weapon
|
||||
{"offset", WEAPON_OFS(offset), FT_FLOAT|FT_ARRAY, 3}, //projectile start offset relative to eye and view angles
|
||||
{"angleoffset", WEAPON_OFS(angleoffset), FT_FLOAT|FT_ARRAY, 3},//offset of the shoot angles relative to the view angles
|
||||
{"extrazvelocity", WEAPON_OFS(extrazvelocity), FT_FLOAT},//extra z velocity the projectile gets
|
||||
{"ammoamount", WEAPON_OFS(ammoamount), FT_INT}, //ammo amount used per shot
|
||||
{"ammoindex", WEAPON_OFS(ammoindex), FT_INT}, //index of ammo in inventory
|
||||
{"activate", WEAPON_OFS(activate), FT_FLOAT}, //time it takes to select the weapon
|
||||
{"reload", WEAPON_OFS(reload), FT_FLOAT}, //time it takes to reload the weapon
|
||||
{"spinup", WEAPON_OFS(spinup), FT_FLOAT}, //time it takes before first shot
|
||||
{"spindown", WEAPON_OFS(spindown), FT_FLOAT}, //time it takes before weapon stops firing
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
//projectile definition
|
||||
static fielddef_t projectileinfo_fields[] =
|
||||
{
|
||||
{"name", PROJECTILE_OFS(name), FT_STRING}, //name of the projectile
|
||||
{"model", WEAPON_OFS(model), FT_STRING}, //model of the projectile
|
||||
{"flags", PROJECTILE_OFS(flags), FT_INT}, //special flags
|
||||
{"gravity", PROJECTILE_OFS(gravity), FT_FLOAT}, //amount of gravity applied to the projectile [0,1]
|
||||
{"damage", PROJECTILE_OFS(damage), FT_INT}, //damage of the projectile
|
||||
{"radius", PROJECTILE_OFS(radius), FT_FLOAT}, //radius of damage
|
||||
{"visdamage", PROJECTILE_OFS(visdamage), FT_INT}, //damage of the projectile to visible entities
|
||||
{"damagetype", PROJECTILE_OFS(damagetype), FT_INT}, //type of damage (combination of the DAMAGETYPE_? flags)
|
||||
{"healthinc", PROJECTILE_OFS(healthinc), FT_INT}, //health increase the owner gets
|
||||
{"push", PROJECTILE_OFS(push), FT_FLOAT}, //amount a player is pushed away from the projectile impact
|
||||
{"detonation", PROJECTILE_OFS(detonation), FT_FLOAT}, //time before projectile explodes after fire pressed
|
||||
{"bounce", PROJECTILE_OFS(bounce), FT_FLOAT}, //amount the projectile bounces
|
||||
{"bouncefric", PROJECTILE_OFS(bouncefric), FT_FLOAT}, //amount the bounce decreases per bounce
|
||||
{"bouncestop", PROJECTILE_OFS(bouncestop), FT_FLOAT}, //minimum bounce value before bouncing stops
|
||||
//recurive projectile definition??
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
static structdef_t weaponinfo_struct =
|
||||
{
|
||||
sizeof(weaponinfo_t), weaponinfo_fields
|
||||
};
|
||||
static structdef_t projectileinfo_struct =
|
||||
{
|
||||
sizeof(projectileinfo_t), projectileinfo_fields
|
||||
};
|
||||
|
||||
//weapon configuration: set of weapons with projectiles
|
||||
typedef struct weaponconfig_s
|
||||
{
|
||||
int numweapons;
|
||||
int numprojectiles;
|
||||
projectileinfo_t *projectileinfo;
|
||||
weaponinfo_t *weaponinfo;
|
||||
} weaponconfig_t;
|
||||
|
||||
//the bot weapon state
|
||||
typedef struct bot_weaponstate_s
|
||||
{
|
||||
struct weightconfig_s *weaponweightconfig; //weapon weight configuration
|
||||
int *weaponweightindex; //weapon weight index
|
||||
} bot_weaponstate_t;
|
||||
|
||||
static bot_weaponstate_t *botweaponstates[MAX_CLIENTS+1];
|
||||
static weaponconfig_t *weaponconfig;
|
||||
|
||||
//========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//========================================================================
|
||||
int BotValidWeaponNumber(int weaponnum)
|
||||
{
|
||||
if (weaponnum <= 0 || weaponnum > weaponconfig->numweapons)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "weapon number out of range\n");
|
||||
return qfalse;
|
||||
} //end if
|
||||
return qtrue;
|
||||
} //end of the function BotValidWeaponNumber
|
||||
//========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//========================================================================
|
||||
bot_weaponstate_t *BotWeaponStateFromHandle(int handle)
|
||||
{
|
||||
if (handle <= 0 || handle > MAX_CLIENTS)
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "move state handle %d out of range\n", handle);
|
||||
return NULL;
|
||||
} //end if
|
||||
if (!botweaponstates[handle])
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "invalid move state %d\n", handle);
|
||||
return NULL;
|
||||
} //end if
|
||||
return botweaponstates[handle];
|
||||
} //end of the function BotWeaponStateFromHandle
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
#ifdef DEBUG_AI_WEAP
|
||||
void DumpWeaponConfig(weaponconfig_t *wc)
|
||||
{
|
||||
FILE *fp;
|
||||
int i;
|
||||
|
||||
fp = Log_FileStruct();
|
||||
if (!fp) return;
|
||||
for (i = 0; i < wc->numprojectiles; i++)
|
||||
{
|
||||
WriteStructure(fp, &projectileinfo_struct, (char *) &wc->projectileinfo[i]);
|
||||
Log_Flush();
|
||||
} //end for
|
||||
for (i = 0; i < wc->numweapons; i++)
|
||||
{
|
||||
WriteStructure(fp, &weaponinfo_struct, (char *) &wc->weaponinfo[i]);
|
||||
Log_Flush();
|
||||
} //end for
|
||||
} //end of the function DumpWeaponConfig
|
||||
#endif //DEBUG_AI_WEAP
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
weaponconfig_t *LoadWeaponConfig(char *filename)
|
||||
{
|
||||
int max_weaponinfo, max_projectileinfo;
|
||||
token_t token;
|
||||
char path[MAX_PATH];
|
||||
int i, j;
|
||||
source_t *source;
|
||||
weaponconfig_t *wc;
|
||||
weaponinfo_t weaponinfo;
|
||||
|
||||
max_weaponinfo = (int) LibVarValue("max_weaponinfo", "32");
|
||||
if (max_weaponinfo < 0)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "max_weaponinfo = %d\n", max_weaponinfo);
|
||||
max_weaponinfo = 32;
|
||||
LibVarSet("max_weaponinfo", "32");
|
||||
} //end if
|
||||
max_projectileinfo = (int) LibVarValue("max_projectileinfo", "32");
|
||||
if (max_projectileinfo < 0)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "max_projectileinfo = %d\n", max_projectileinfo);
|
||||
max_projectileinfo = 32;
|
||||
LibVarSet("max_projectileinfo", "32");
|
||||
} //end if
|
||||
strncpy(path, filename, MAX_PATH);
|
||||
PC_SetBaseFolder(BOTFILESBASEFOLDER);
|
||||
source = LoadSourceFile(path);
|
||||
if (!source)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "counldn't load %s\n", path);
|
||||
return NULL;
|
||||
} //end if
|
||||
//initialize weapon config
|
||||
wc = (weaponconfig_t *) GetClearedHunkMemory(sizeof(weaponconfig_t) +
|
||||
max_weaponinfo * sizeof(weaponinfo_t) +
|
||||
max_projectileinfo * sizeof(projectileinfo_t));
|
||||
wc->weaponinfo = (weaponinfo_t *) ((char *) wc + sizeof(weaponconfig_t));
|
||||
wc->projectileinfo = (projectileinfo_t *) ((char *) wc->weaponinfo +
|
||||
max_weaponinfo * sizeof(weaponinfo_t));
|
||||
wc->numweapons = max_weaponinfo;
|
||||
wc->numprojectiles = 0;
|
||||
//parse the source file
|
||||
while(PC_ReadToken(source, &token))
|
||||
{
|
||||
if (!strcmp(token.string, "weaponinfo"))
|
||||
{
|
||||
Com_Memset(&weaponinfo, 0, sizeof(weaponinfo_t));
|
||||
if (!ReadStructure(source, &weaponinfo_struct, (char *) &weaponinfo))
|
||||
{
|
||||
FreeMemory(wc);
|
||||
FreeSource(source);
|
||||
return NULL;
|
||||
} //end if
|
||||
if (weaponinfo.number < 0 || weaponinfo.number >= max_weaponinfo)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "weapon info number %d out of range in %s\n", weaponinfo.number, path);
|
||||
FreeMemory(wc);
|
||||
FreeSource(source);
|
||||
return NULL;
|
||||
} //end if
|
||||
Com_Memcpy(&wc->weaponinfo[weaponinfo.number], &weaponinfo, sizeof(weaponinfo_t));
|
||||
wc->weaponinfo[weaponinfo.number].valid = qtrue;
|
||||
} //end if
|
||||
else if (!strcmp(token.string, "projectileinfo"))
|
||||
{
|
||||
if (wc->numprojectiles >= max_projectileinfo)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "more than %d projectiles defined in %s\n", max_projectileinfo, path);
|
||||
FreeMemory(wc);
|
||||
FreeSource(source);
|
||||
return NULL;
|
||||
} //end if
|
||||
Com_Memset(&wc->projectileinfo[wc->numprojectiles], 0, sizeof(projectileinfo_t));
|
||||
if (!ReadStructure(source, &projectileinfo_struct, (char *) &wc->projectileinfo[wc->numprojectiles]))
|
||||
{
|
||||
FreeMemory(wc);
|
||||
FreeSource(source);
|
||||
return NULL;
|
||||
} //end if
|
||||
wc->numprojectiles++;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "unknown definition %s in %s\n", token.string, path);
|
||||
FreeMemory(wc);
|
||||
FreeSource(source);
|
||||
return NULL;
|
||||
} //end else
|
||||
} //end while
|
||||
FreeSource(source);
|
||||
//fix up weapons
|
||||
for (i = 0; i < wc->numweapons; i++)
|
||||
{
|
||||
if (!wc->weaponinfo[i].valid) continue;
|
||||
if (!wc->weaponinfo[i].name[0])
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "weapon %d has no name in %s\n", i, path);
|
||||
FreeMemory(wc);
|
||||
return NULL;
|
||||
} //end if
|
||||
if (!wc->weaponinfo[i].projectile[0])
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "weapon %s has no projectile in %s\n", wc->weaponinfo[i].name, path);
|
||||
FreeMemory(wc);
|
||||
return NULL;
|
||||
} //end if
|
||||
//find the projectile info and copy it to the weapon info
|
||||
for (j = 0; j < wc->numprojectiles; j++)
|
||||
{
|
||||
if (!strcmp(wc->projectileinfo[j].name, wc->weaponinfo[i].projectile))
|
||||
{
|
||||
Com_Memcpy(&wc->weaponinfo[i].proj, &wc->projectileinfo[j], sizeof(projectileinfo_t));
|
||||
break;
|
||||
} //end if
|
||||
} //end for
|
||||
if (j == wc->numprojectiles)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "weapon %s uses undefined projectile in %s\n", wc->weaponinfo[i].name, path);
|
||||
FreeMemory(wc);
|
||||
return NULL;
|
||||
} //end if
|
||||
} //end for
|
||||
if (!wc->numweapons) botimport.Print(PRT_WARNING, "no weapon info loaded\n");
|
||||
botimport.Print(PRT_MESSAGE, "loaded %s\n", path);
|
||||
return wc;
|
||||
} //end of the function LoadWeaponConfig
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int *WeaponWeightIndex(weightconfig_t *wwc, weaponconfig_t *wc)
|
||||
{
|
||||
int *index, i;
|
||||
|
||||
//initialize item weight index
|
||||
index = (int *) GetClearedMemory(sizeof(int) * wc->numweapons);
|
||||
|
||||
for (i = 0; i < wc->numweapons; i++)
|
||||
{
|
||||
index[i] = FindFuzzyWeight(wwc, wc->weaponinfo[i].name);
|
||||
} //end for
|
||||
return index;
|
||||
} //end of the function WeaponWeightIndex
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void BotFreeWeaponWeights(int weaponstate)
|
||||
{
|
||||
bot_weaponstate_t *ws;
|
||||
|
||||
ws = BotWeaponStateFromHandle(weaponstate);
|
||||
if (!ws) return;
|
||||
if (ws->weaponweightconfig) FreeWeightConfig(ws->weaponweightconfig);
|
||||
if (ws->weaponweightindex) FreeMemory(ws->weaponweightindex);
|
||||
} //end of the function BotFreeWeaponWeights
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int BotLoadWeaponWeights(int weaponstate, char *filename)
|
||||
{
|
||||
bot_weaponstate_t *ws;
|
||||
|
||||
ws = BotWeaponStateFromHandle(weaponstate);
|
||||
if (!ws) return BLERR_CANNOTLOADWEAPONWEIGHTS;
|
||||
BotFreeWeaponWeights(weaponstate);
|
||||
//
|
||||
ws->weaponweightconfig = ReadWeightConfig(filename);
|
||||
if (!ws->weaponweightconfig)
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "couldn't load weapon config %s\n", filename);
|
||||
return BLERR_CANNOTLOADWEAPONWEIGHTS;
|
||||
} //end if
|
||||
if (!weaponconfig) return BLERR_CANNOTLOADWEAPONCONFIG;
|
||||
ws->weaponweightindex = WeaponWeightIndex(ws->weaponweightconfig, weaponconfig);
|
||||
return BLERR_NOERROR;
|
||||
} //end of the function BotLoadWeaponWeights
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void BotGetWeaponInfo(int weaponstate, int weapon, weaponinfo_t *weaponinfo)
|
||||
{
|
||||
bot_weaponstate_t *ws;
|
||||
|
||||
if (!BotValidWeaponNumber(weapon)) return;
|
||||
ws = BotWeaponStateFromHandle(weaponstate);
|
||||
if (!ws) return;
|
||||
if (!weaponconfig) return;
|
||||
Com_Memcpy(weaponinfo, &weaponconfig->weaponinfo[weapon], sizeof(weaponinfo_t));
|
||||
} //end of the function BotGetWeaponInfo
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int BotChooseBestFightWeapon(int weaponstate, int *inventory)
|
||||
{
|
||||
int i, index, bestweapon;
|
||||
float weight, bestweight;
|
||||
weaponconfig_t *wc;
|
||||
bot_weaponstate_t *ws;
|
||||
|
||||
ws = BotWeaponStateFromHandle(weaponstate);
|
||||
if (!ws) return 0;
|
||||
wc = weaponconfig;
|
||||
if (!weaponconfig) return 0;
|
||||
|
||||
//if the bot has no weapon weight configuration
|
||||
if (!ws->weaponweightconfig) return 0;
|
||||
|
||||
bestweight = 0;
|
||||
bestweapon = 0;
|
||||
for (i = 0; i < wc->numweapons; i++)
|
||||
{
|
||||
if (!wc->weaponinfo[i].valid) continue;
|
||||
index = ws->weaponweightindex[i];
|
||||
if (index < 0) continue;
|
||||
weight = FuzzyWeight(inventory, ws->weaponweightconfig, index);
|
||||
if (weight > bestweight)
|
||||
{
|
||||
bestweight = weight;
|
||||
bestweapon = i;
|
||||
} //end if
|
||||
} //end for
|
||||
return bestweapon;
|
||||
} //end of the function BotChooseBestFightWeapon
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void BotResetWeaponState(int weaponstate)
|
||||
{
|
||||
struct weightconfig_s *weaponweightconfig;
|
||||
int *weaponweightindex;
|
||||
bot_weaponstate_t *ws;
|
||||
|
||||
ws = BotWeaponStateFromHandle(weaponstate);
|
||||
if (!ws) return;
|
||||
weaponweightconfig = ws->weaponweightconfig;
|
||||
weaponweightindex = ws->weaponweightindex;
|
||||
|
||||
//Com_Memset(ws, 0, sizeof(bot_weaponstate_t));
|
||||
ws->weaponweightconfig = weaponweightconfig;
|
||||
ws->weaponweightindex = weaponweightindex;
|
||||
} //end of the function BotResetWeaponState
|
||||
//========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//========================================================================
|
||||
int BotAllocWeaponState(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= MAX_CLIENTS; i++)
|
||||
{
|
||||
if (!botweaponstates[i])
|
||||
{
|
||||
botweaponstates[i] = (struct bot_weaponstate_s *)GetClearedMemory(sizeof(bot_weaponstate_t));
|
||||
return i;
|
||||
} //end if
|
||||
} //end for
|
||||
return 0;
|
||||
} //end of the function BotAllocWeaponState
|
||||
//========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//========================================================================
|
||||
void BotFreeWeaponState(int handle)
|
||||
{
|
||||
if (handle <= 0 || handle > MAX_CLIENTS)
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "move state handle %d out of range\n", handle);
|
||||
return;
|
||||
} //end if
|
||||
if (!botweaponstates[handle])
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "invalid move state %d\n", handle);
|
||||
return;
|
||||
} //end if
|
||||
BotFreeWeaponWeights(handle);
|
||||
FreeMemory(botweaponstates[handle]);
|
||||
botweaponstates[handle] = NULL;
|
||||
} //end of the function BotFreeWeaponState
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int BotSetupWeaponAI(void)
|
||||
{
|
||||
char *file;
|
||||
|
||||
file = LibVarString("weaponconfig", "weapons.c");
|
||||
weaponconfig = LoadWeaponConfig(file);
|
||||
if (!weaponconfig)
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "couldn't load the weapon config\n");
|
||||
return BLERR_CANNOTLOADWEAPONCONFIG;
|
||||
} //end if
|
||||
|
||||
#ifdef DEBUG_AI_WEAP
|
||||
DumpWeaponConfig(weaponconfig);
|
||||
#endif //DEBUG_AI_WEAP
|
||||
//
|
||||
return BLERR_NOERROR;
|
||||
} //end of the function BotSetupWeaponAI
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void BotShutdownWeaponAI(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (weaponconfig) FreeMemory(weaponconfig);
|
||||
weaponconfig = NULL;
|
||||
|
||||
for (i = 1; i <= MAX_CLIENTS; i++)
|
||||
{
|
||||
if (botweaponstates[i])
|
||||
{
|
||||
BotFreeWeaponState(i);
|
||||
} //end if
|
||||
} //end for
|
||||
} //end of the function BotShutdownWeaponAI
|
||||
|
895
CODEmp/botlib/be_ai_weight.cpp
Normal file
895
CODEmp/botlib/be_ai_weight.cpp
Normal file
|
@ -0,0 +1,895 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_ai_weight.c
|
||||
*
|
||||
* desc: fuzzy logic
|
||||
*
|
||||
* $Archive: /MissionPack/code/botlib/be_ai_weight.c $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 3 $
|
||||
* $Modtime: 8/06/00 5:25p $
|
||||
* $Date: 8/06/00 11:07p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "l_memory.h"
|
||||
#include "l_log.h"
|
||||
#include "l_utils.h"
|
||||
#include "l_script.h"
|
||||
#include "l_precomp.h"
|
||||
#include "l_struct.h"
|
||||
#include "l_libvar.h"
|
||||
#include "aasfile.h"
|
||||
#include "../game/botlib.h"
|
||||
#include "../game/be_aas.h"
|
||||
#include "be_aas_funcs.h"
|
||||
#include "be_interface.h"
|
||||
#include "be_ai_weight.h"
|
||||
|
||||
#define MAX_INVENTORYVALUE 999999
|
||||
#define EVALUATERECURSIVELY
|
||||
|
||||
#define MAX_WEIGHT_FILES 128
|
||||
weightconfig_t *weightFileList[MAX_WEIGHT_FILES];
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int ReadValue(source_t *source, float *value)
|
||||
{
|
||||
token_t token;
|
||||
|
||||
if (!PC_ExpectAnyToken(source, &token)) return qfalse;
|
||||
if (!strcmp(token.string, "-"))
|
||||
{
|
||||
SourceWarning(source, "negative value set to zero\n");
|
||||
if (!PC_ExpectTokenType(source, TT_NUMBER, 0, &token)) return qfalse;
|
||||
} //end if
|
||||
if (token.type != TT_NUMBER)
|
||||
{
|
||||
SourceError(source, "invalid return value %s\n", token.string);
|
||||
return qfalse;
|
||||
} //end if
|
||||
*value = token.floatvalue;
|
||||
return qtrue;
|
||||
} //end of the function ReadValue
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int ReadFuzzyWeight(source_t *source, fuzzyseperator_t *fs)
|
||||
{
|
||||
if (PC_CheckTokenString(source, "balance"))
|
||||
{
|
||||
fs->type = WT_BALANCE;
|
||||
if (!PC_ExpectTokenString(source, "(")) return qfalse;
|
||||
if (!ReadValue(source, &fs->weight)) return qfalse;
|
||||
if (!PC_ExpectTokenString(source, ",")) return qfalse;
|
||||
if (!ReadValue(source, &fs->minweight)) return qfalse;
|
||||
if (!PC_ExpectTokenString(source, ",")) return qfalse;
|
||||
if (!ReadValue(source, &fs->maxweight)) return qfalse;
|
||||
if (!PC_ExpectTokenString(source, ")")) return qfalse;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
fs->type = 0;
|
||||
if (!ReadValue(source, &fs->weight)) return qfalse;
|
||||
fs->minweight = fs->weight;
|
||||
fs->maxweight = fs->weight;
|
||||
} //end if
|
||||
if (!PC_ExpectTokenString(source, ";")) return qfalse;
|
||||
return qtrue;
|
||||
} //end of the function ReadFuzzyWeight
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void FreeFuzzySeperators_r(fuzzyseperator_t *fs)
|
||||
{
|
||||
if (!fs) return;
|
||||
if (fs->child) FreeFuzzySeperators_r(fs->child);
|
||||
if (fs->next) FreeFuzzySeperators_r(fs->next);
|
||||
FreeMemory(fs);
|
||||
} //end of the function FreeFuzzySeperators
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void FreeWeightConfig2(weightconfig_t *config)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < config->numweights; i++)
|
||||
{
|
||||
FreeFuzzySeperators_r(config->weights[i].firstseperator);
|
||||
if (config->weights[i].name) FreeMemory(config->weights[i].name);
|
||||
} //end for
|
||||
FreeMemory(config);
|
||||
} //end of the function FreeWeightConfig2
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void FreeWeightConfig(weightconfig_t *config)
|
||||
{
|
||||
if (!LibVarGetValue("bot_reloadcharacters")) return;
|
||||
FreeWeightConfig2(config);
|
||||
} //end of the function FreeWeightConfig
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
fuzzyseperator_t *ReadFuzzySeperators_r(source_t *source)
|
||||
{
|
||||
int newindent, index, def, founddefault;
|
||||
token_t token;
|
||||
fuzzyseperator_t *fs, *lastfs, *firstfs;
|
||||
|
||||
founddefault = qfalse;
|
||||
firstfs = NULL;
|
||||
lastfs = NULL;
|
||||
if (!PC_ExpectTokenString(source, "(")) return NULL;
|
||||
if (!PC_ExpectTokenType(source, TT_NUMBER, TT_INTEGER, &token)) return NULL;
|
||||
index = token.intvalue;
|
||||
if (!PC_ExpectTokenString(source, ")")) return NULL;
|
||||
if (!PC_ExpectTokenString(source, "{")) return NULL;
|
||||
if (!PC_ExpectAnyToken(source, &token)) return NULL;
|
||||
do
|
||||
{
|
||||
def = !strcmp(token.string, "default");
|
||||
if (def || !strcmp(token.string, "case"))
|
||||
{
|
||||
fs = (fuzzyseperator_t *) GetClearedMemory(sizeof(fuzzyseperator_t));
|
||||
fs->index = index;
|
||||
if (lastfs) lastfs->next = fs;
|
||||
else firstfs = fs;
|
||||
lastfs = fs;
|
||||
if (def)
|
||||
{
|
||||
if (founddefault)
|
||||
{
|
||||
SourceError(source, "switch already has a default\n");
|
||||
FreeFuzzySeperators_r(firstfs);
|
||||
return NULL;
|
||||
} //end if
|
||||
fs->value = MAX_INVENTORYVALUE;
|
||||
founddefault = qtrue;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
if (!PC_ExpectTokenType(source, TT_NUMBER, TT_INTEGER, &token))
|
||||
{
|
||||
FreeFuzzySeperators_r(firstfs);
|
||||
return NULL;
|
||||
} //end if
|
||||
fs->value = token.intvalue;
|
||||
} //end else
|
||||
if (!PC_ExpectTokenString(source, ":") || !PC_ExpectAnyToken(source, &token))
|
||||
{
|
||||
FreeFuzzySeperators_r(firstfs);
|
||||
return NULL;
|
||||
} //end if
|
||||
newindent = qfalse;
|
||||
if (!strcmp(token.string, "{"))
|
||||
{
|
||||
newindent = qtrue;
|
||||
if (!PC_ExpectAnyToken(source, &token))
|
||||
{
|
||||
FreeFuzzySeperators_r(firstfs);
|
||||
return NULL;
|
||||
} //end if
|
||||
} //end if
|
||||
if (!strcmp(token.string, "return"))
|
||||
{
|
||||
if (!ReadFuzzyWeight(source, fs))
|
||||
{
|
||||
FreeFuzzySeperators_r(firstfs);
|
||||
return NULL;
|
||||
} //end if
|
||||
} //end if
|
||||
else if (!strcmp(token.string, "switch"))
|
||||
{
|
||||
fs->child = ReadFuzzySeperators_r(source);
|
||||
if (!fs->child)
|
||||
{
|
||||
FreeFuzzySeperators_r(firstfs);
|
||||
return NULL;
|
||||
} //end if
|
||||
} //end else if
|
||||
else
|
||||
{
|
||||
SourceError(source, "invalid name %s\n", token.string);
|
||||
return NULL;
|
||||
} //end else
|
||||
if (newindent)
|
||||
{
|
||||
if (!PC_ExpectTokenString(source, "}"))
|
||||
{
|
||||
FreeFuzzySeperators_r(firstfs);
|
||||
return NULL;
|
||||
} //end if
|
||||
} //end if
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
FreeFuzzySeperators_r(firstfs);
|
||||
SourceError(source, "invalid name %s\n", token.string);
|
||||
return NULL;
|
||||
} //end else
|
||||
if (!PC_ExpectAnyToken(source, &token))
|
||||
{
|
||||
FreeFuzzySeperators_r(firstfs);
|
||||
return NULL;
|
||||
} //end if
|
||||
} while(strcmp(token.string, "}"));
|
||||
//
|
||||
if (!founddefault)
|
||||
{
|
||||
SourceWarning(source, "switch without default\n");
|
||||
fs = (fuzzyseperator_t *) GetClearedMemory(sizeof(fuzzyseperator_t));
|
||||
fs->index = index;
|
||||
fs->value = MAX_INVENTORYVALUE;
|
||||
fs->weight = 0;
|
||||
fs->next = NULL;
|
||||
fs->child = NULL;
|
||||
if (lastfs) lastfs->next = fs;
|
||||
else firstfs = fs;
|
||||
lastfs = fs;
|
||||
} //end if
|
||||
//
|
||||
return firstfs;
|
||||
} //end of the function ReadFuzzySeperators_r
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
weightconfig_t *ReadWeightConfig(char *filename)
|
||||
{
|
||||
int newindent, avail = 0, n;
|
||||
token_t token;
|
||||
source_t *source;
|
||||
fuzzyseperator_t *fs;
|
||||
weightconfig_t *config = NULL;
|
||||
#ifdef DEBUG
|
||||
int starttime;
|
||||
|
||||
starttime = Sys_MilliSeconds();
|
||||
#endif //DEBUG
|
||||
|
||||
if (!LibVarGetValue("bot_reloadcharacters"))
|
||||
{
|
||||
avail = -1;
|
||||
for( n = 0; n < MAX_WEIGHT_FILES; n++ )
|
||||
{
|
||||
config = weightFileList[n];
|
||||
if( !config )
|
||||
{
|
||||
if( avail == -1 )
|
||||
{
|
||||
avail = n;
|
||||
} //end if
|
||||
continue;
|
||||
} //end if
|
||||
if( strcmp( filename, config->filename ) == 0 )
|
||||
{
|
||||
//botimport.Print( PRT_MESSAGE, "retained %s\n", filename );
|
||||
return config;
|
||||
} //end if
|
||||
} //end for
|
||||
|
||||
if( avail == -1 )
|
||||
{
|
||||
botimport.Print( PRT_ERROR, "weightFileList was full trying to load %s\n", filename );
|
||||
return NULL;
|
||||
} //end if
|
||||
} //end if
|
||||
|
||||
PC_SetBaseFolder(BOTFILESBASEFOLDER);
|
||||
source = LoadSourceFile(filename);
|
||||
if (!source)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "counldn't load %s\n", filename);
|
||||
return NULL;
|
||||
} //end if
|
||||
//
|
||||
config = (weightconfig_t *) GetClearedMemory(sizeof(weightconfig_t));
|
||||
config->numweights = 0;
|
||||
Q_strncpyz( config->filename, filename, sizeof(config->filename) );
|
||||
//parse the item config file
|
||||
while(PC_ReadToken(source, &token))
|
||||
{
|
||||
if (!strcmp(token.string, "weight"))
|
||||
{
|
||||
if (config->numweights >= MAX_WEIGHTS)
|
||||
{
|
||||
SourceWarning(source, "too many fuzzy weights\n");
|
||||
break;
|
||||
} //end if
|
||||
if (!PC_ExpectTokenType(source, TT_STRING, 0, &token))
|
||||
{
|
||||
FreeWeightConfig(config);
|
||||
FreeSource(source);
|
||||
return NULL;
|
||||
} //end if
|
||||
StripDoubleQuotes(token.string);
|
||||
config->weights[config->numweights].name = (char *) GetClearedMemory(strlen(token.string) + 1);
|
||||
strcpy(config->weights[config->numweights].name, token.string);
|
||||
if (!PC_ExpectAnyToken(source, &token))
|
||||
{
|
||||
FreeWeightConfig(config);
|
||||
FreeSource(source);
|
||||
return NULL;
|
||||
} //end if
|
||||
newindent = qfalse;
|
||||
if (!strcmp(token.string, "{"))
|
||||
{
|
||||
newindent = qtrue;
|
||||
if (!PC_ExpectAnyToken(source, &token))
|
||||
{
|
||||
FreeWeightConfig(config);
|
||||
FreeSource(source);
|
||||
return NULL;
|
||||
} //end if
|
||||
} //end if
|
||||
if (!strcmp(token.string, "switch"))
|
||||
{
|
||||
fs = ReadFuzzySeperators_r(source);
|
||||
if (!fs)
|
||||
{
|
||||
FreeWeightConfig(config);
|
||||
FreeSource(source);
|
||||
return NULL;
|
||||
} //end if
|
||||
config->weights[config->numweights].firstseperator = fs;
|
||||
} //end if
|
||||
else if (!strcmp(token.string, "return"))
|
||||
{
|
||||
fs = (fuzzyseperator_t *) GetClearedMemory(sizeof(fuzzyseperator_t));
|
||||
fs->index = 0;
|
||||
fs->value = MAX_INVENTORYVALUE;
|
||||
fs->next = NULL;
|
||||
fs->child = NULL;
|
||||
if (!ReadFuzzyWeight(source, fs))
|
||||
{
|
||||
FreeMemory(fs);
|
||||
FreeWeightConfig(config);
|
||||
FreeSource(source);
|
||||
return NULL;
|
||||
} //end if
|
||||
config->weights[config->numweights].firstseperator = fs;
|
||||
} //end else if
|
||||
else
|
||||
{
|
||||
SourceError(source, "invalid name %s\n", token.string);
|
||||
FreeWeightConfig(config);
|
||||
FreeSource(source);
|
||||
return NULL;
|
||||
} //end else
|
||||
if (newindent)
|
||||
{
|
||||
if (!PC_ExpectTokenString(source, "}"))
|
||||
{
|
||||
FreeWeightConfig(config);
|
||||
FreeSource(source);
|
||||
return NULL;
|
||||
} //end if
|
||||
} //end if
|
||||
config->numweights++;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
SourceError(source, "invalid name %s\n", token.string);
|
||||
FreeWeightConfig(config);
|
||||
FreeSource(source);
|
||||
return NULL;
|
||||
} //end else
|
||||
} //end while
|
||||
//free the source at the end of a pass
|
||||
FreeSource(source);
|
||||
//if the file was located in a pak file
|
||||
botimport.Print(PRT_MESSAGE, "loaded %s\n", filename);
|
||||
#ifdef DEBUG
|
||||
if (bot_developer)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "weights loaded in %d msec\n", Sys_MilliSeconds() - starttime);
|
||||
} //end if
|
||||
#endif //DEBUG
|
||||
//
|
||||
if (!LibVarGetValue("bot_reloadcharacters"))
|
||||
{
|
||||
weightFileList[avail] = config;
|
||||
} //end if
|
||||
//
|
||||
return config;
|
||||
} //end of the function ReadWeightConfig
|
||||
#if 0
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
qboolean WriteFuzzyWeight(FILE *fp, fuzzyseperator_t *fs)
|
||||
{
|
||||
if (fs->type == WT_BALANCE)
|
||||
{
|
||||
if (fprintf(fp, " return balance(") < 0) return qfalse;
|
||||
if (!WriteFloat(fp, fs->weight)) return qfalse;
|
||||
if (fprintf(fp, ",") < 0) return qfalse;
|
||||
if (!WriteFloat(fp, fs->minweight)) return qfalse;
|
||||
if (fprintf(fp, ",") < 0) return qfalse;
|
||||
if (!WriteFloat(fp, fs->maxweight)) return qfalse;
|
||||
if (fprintf(fp, ");\n") < 0) return qfalse;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
if (fprintf(fp, " return ") < 0) return qfalse;
|
||||
if (!WriteFloat(fp, fs->weight)) return qfalse;
|
||||
if (fprintf(fp, ";\n") < 0) return qfalse;
|
||||
} //end else
|
||||
return qtrue;
|
||||
} //end of the function WriteFuzzyWeight
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
qboolean WriteFuzzySeperators_r(FILE *fp, fuzzyseperator_t *fs, int indent)
|
||||
{
|
||||
if (!WriteIndent(fp, indent)) return qfalse;
|
||||
if (fprintf(fp, "switch(%d)\n", fs->index) < 0) return qfalse;
|
||||
if (!WriteIndent(fp, indent)) return qfalse;
|
||||
if (fprintf(fp, "{\n") < 0) return qfalse;
|
||||
indent++;
|
||||
do
|
||||
{
|
||||
if (!WriteIndent(fp, indent)) return qfalse;
|
||||
if (fs->next)
|
||||
{
|
||||
if (fprintf(fp, "case %d:", fs->value) < 0) return qfalse;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
if (fprintf(fp, "default:") < 0) return qfalse;
|
||||
} //end else
|
||||
if (fs->child)
|
||||
{
|
||||
if (fprintf(fp, "\n") < 0) return qfalse;
|
||||
if (!WriteIndent(fp, indent)) return qfalse;
|
||||
if (fprintf(fp, "{\n") < 0) return qfalse;
|
||||
if (!WriteFuzzySeperators_r(fp, fs->child, indent + 1)) return qfalse;
|
||||
if (!WriteIndent(fp, indent)) return qfalse;
|
||||
if (fs->next)
|
||||
{
|
||||
if (fprintf(fp, "} //end case\n") < 0) return qfalse;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
if (fprintf(fp, "} //end default\n") < 0) return qfalse;
|
||||
} //end else
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
if (!WriteFuzzyWeight(fp, fs)) return qfalse;
|
||||
} //end else
|
||||
fs = fs->next;
|
||||
} while(fs);
|
||||
indent--;
|
||||
if (!WriteIndent(fp, indent)) return qfalse;
|
||||
if (fprintf(fp, "} //end switch\n") < 0) return qfalse;
|
||||
return qtrue;
|
||||
} //end of the function WriteItemFuzzyWeights_r
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
qboolean WriteWeightConfig(char *filename, weightconfig_t *config)
|
||||
{
|
||||
int i;
|
||||
FILE *fp;
|
||||
weight_t *ifw;
|
||||
|
||||
fp = fopen(filename, "wb");
|
||||
if (!fp) return qfalse;
|
||||
|
||||
for (i = 0; i < config->numweights; i++)
|
||||
{
|
||||
ifw = &config->weights[i];
|
||||
if (fprintf(fp, "\nweight \"%s\"\n", ifw->name) < 0) return qfalse;
|
||||
if (fprintf(fp, "{\n") < 0) return qfalse;
|
||||
if (ifw->firstseperator->index > 0)
|
||||
{
|
||||
if (!WriteFuzzySeperators_r(fp, ifw->firstseperator, 1)) return qfalse;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
if (!WriteIndent(fp, 1)) return qfalse;
|
||||
if (!WriteFuzzyWeight(fp, ifw->firstseperator)) return qfalse;
|
||||
} //end else
|
||||
if (fprintf(fp, "} //end weight\n") < 0) return qfalse;
|
||||
} //end for
|
||||
fclose(fp);
|
||||
return qtrue;
|
||||
} //end of the function WriteWeightConfig
|
||||
#endif
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int FindFuzzyWeight(weightconfig_t *wc, char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < wc->numweights; i++)
|
||||
{
|
||||
if (!strcmp(wc->weights[i].name, name))
|
||||
{
|
||||
return i;
|
||||
} //end if
|
||||
} //end if
|
||||
return -1;
|
||||
} //end of the function FindFuzzyWeight
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
float FuzzyWeight_r(int *inventory, fuzzyseperator_t *fs)
|
||||
{
|
||||
float scale, w1, w2;
|
||||
|
||||
if (inventory[fs->index] < fs->value)
|
||||
{
|
||||
if (fs->child) return FuzzyWeight_r(inventory, fs->child);
|
||||
else return fs->weight;
|
||||
} //end if
|
||||
else if (fs->next)
|
||||
{
|
||||
if (inventory[fs->index] < fs->next->value)
|
||||
{
|
||||
//first weight
|
||||
if (fs->child) w1 = FuzzyWeight_r(inventory, fs->child);
|
||||
else w1 = fs->weight;
|
||||
//second weight
|
||||
if (fs->next->child) w2 = FuzzyWeight_r(inventory, fs->next->child);
|
||||
else w2 = fs->next->weight;
|
||||
//the scale factor
|
||||
scale = (inventory[fs->index] - fs->value) / (fs->next->value - fs->value);
|
||||
//scale between the two weights
|
||||
return scale * w1 + (1 - scale) * w2;
|
||||
} //end if
|
||||
return FuzzyWeight_r(inventory, fs->next);
|
||||
} //end else if
|
||||
return fs->weight;
|
||||
} //end of the function FuzzyWeight_r
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
float FuzzyWeightUndecided_r(int *inventory, fuzzyseperator_t *fs)
|
||||
{
|
||||
float scale, w1, w2;
|
||||
|
||||
if (inventory[fs->index] < fs->value)
|
||||
{
|
||||
if (fs->child) return FuzzyWeightUndecided_r(inventory, fs->child);
|
||||
else return fs->minweight + random() * (fs->maxweight - fs->minweight);
|
||||
} //end if
|
||||
else if (fs->next)
|
||||
{
|
||||
if (inventory[fs->index] < fs->next->value)
|
||||
{
|
||||
//first weight
|
||||
if (fs->child) w1 = FuzzyWeightUndecided_r(inventory, fs->child);
|
||||
else w1 = fs->minweight + random() * (fs->maxweight - fs->minweight);
|
||||
//second weight
|
||||
if (fs->next->child) w2 = FuzzyWeight_r(inventory, fs->next->child);
|
||||
else w2 = fs->next->minweight + random() * (fs->next->maxweight - fs->next->minweight);
|
||||
//the scale factor
|
||||
scale = (inventory[fs->index] - fs->value) / (fs->next->value - fs->value);
|
||||
//scale between the two weights
|
||||
return scale * w1 + (1 - scale) * w2;
|
||||
} //end if
|
||||
return FuzzyWeightUndecided_r(inventory, fs->next);
|
||||
} //end else if
|
||||
return fs->weight;
|
||||
} //end of the function FuzzyWeightUndecided_r
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
float FuzzyWeight(int *inventory, weightconfig_t *wc, int weightnum)
|
||||
{
|
||||
#ifdef EVALUATERECURSIVELY
|
||||
return FuzzyWeight_r(inventory, wc->weights[weightnum].firstseperator);
|
||||
#else
|
||||
fuzzyseperator_t *s;
|
||||
|
||||
s = wc->weights[weightnum].firstseperator;
|
||||
if (!s) return 0;
|
||||
while(1)
|
||||
{
|
||||
if (inventory[s->index] < s->value)
|
||||
{
|
||||
if (s->child) s = s->child;
|
||||
else return s->weight;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
if (s->next) s = s->next;
|
||||
else return s->weight;
|
||||
} //end else
|
||||
} //end if
|
||||
return 0;
|
||||
#endif
|
||||
} //end of the function FuzzyWeight
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
float FuzzyWeightUndecided(int *inventory, weightconfig_t *wc, int weightnum)
|
||||
{
|
||||
#ifdef EVALUATERECURSIVELY
|
||||
return FuzzyWeightUndecided_r(inventory, wc->weights[weightnum].firstseperator);
|
||||
#else
|
||||
fuzzyseperator_t *s;
|
||||
|
||||
s = wc->weights[weightnum].firstseperator;
|
||||
if (!s) return 0;
|
||||
while(1)
|
||||
{
|
||||
if (inventory[s->index] < s->value)
|
||||
{
|
||||
if (s->child) s = s->child;
|
||||
else return s->minweight + random() * (s->maxweight - s->minweight);
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
if (s->next) s = s->next;
|
||||
else return s->minweight + random() * (s->maxweight - s->minweight);
|
||||
} //end else
|
||||
} //end if
|
||||
return 0;
|
||||
#endif
|
||||
} //end of the function FuzzyWeightUndecided
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EvolveFuzzySeperator_r(fuzzyseperator_t *fs)
|
||||
{
|
||||
if (fs->child)
|
||||
{
|
||||
EvolveFuzzySeperator_r(fs->child);
|
||||
} //end if
|
||||
else if (fs->type == WT_BALANCE)
|
||||
{
|
||||
//every once in a while an evolution leap occurs, mutation
|
||||
if (random() < 0.01) fs->weight += crandom() * (fs->maxweight - fs->minweight);
|
||||
else fs->weight += crandom() * (fs->maxweight - fs->minweight) * 0.5;
|
||||
//modify bounds if necesary because of mutation
|
||||
if (fs->weight < fs->minweight) fs->minweight = fs->weight;
|
||||
else if (fs->weight > fs->maxweight) fs->maxweight = fs->weight;
|
||||
} //end else if
|
||||
if (fs->next) EvolveFuzzySeperator_r(fs->next);
|
||||
} //end of the function EvolveFuzzySeperator_r
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EvolveWeightConfig(weightconfig_t *config)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < config->numweights; i++)
|
||||
{
|
||||
EvolveFuzzySeperator_r(config->weights[i].firstseperator);
|
||||
} //end for
|
||||
} //end of the function EvolveWeightConfig
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void ScaleFuzzySeperator_r(fuzzyseperator_t *fs, float scale)
|
||||
{
|
||||
if (fs->child)
|
||||
{
|
||||
ScaleFuzzySeperator_r(fs->child, scale);
|
||||
} //end if
|
||||
else if (fs->type == WT_BALANCE)
|
||||
{
|
||||
//
|
||||
fs->weight = (fs->maxweight + fs->minweight) * scale;
|
||||
//get the weight between bounds
|
||||
if (fs->weight < fs->minweight) fs->weight = fs->minweight;
|
||||
else if (fs->weight > fs->maxweight) fs->weight = fs->maxweight;
|
||||
} //end else if
|
||||
if (fs->next) ScaleFuzzySeperator_r(fs->next, scale);
|
||||
} //end of the function ScaleFuzzySeperator_r
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void ScaleWeight(weightconfig_t *config, char *name, float scale)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (scale < 0) scale = 0;
|
||||
else if (scale > 1) scale = 1;
|
||||
for (i = 0; i < config->numweights; i++)
|
||||
{
|
||||
if (!strcmp(name, config->weights[i].name))
|
||||
{
|
||||
ScaleFuzzySeperator_r(config->weights[i].firstseperator, scale);
|
||||
break;
|
||||
} //end if
|
||||
} //end for
|
||||
} //end of the function ScaleWeight
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void ScaleFuzzySeperatorBalanceRange_r(fuzzyseperator_t *fs, float scale)
|
||||
{
|
||||
if (fs->child)
|
||||
{
|
||||
ScaleFuzzySeperatorBalanceRange_r(fs->child, scale);
|
||||
} //end if
|
||||
else if (fs->type == WT_BALANCE)
|
||||
{
|
||||
float mid = (fs->minweight + fs->maxweight) * 0.5;
|
||||
//get the weight between bounds
|
||||
fs->maxweight = mid + (fs->maxweight - mid) * scale;
|
||||
fs->minweight = mid + (fs->minweight - mid) * scale;
|
||||
if (fs->maxweight < fs->minweight)
|
||||
{
|
||||
fs->maxweight = fs->minweight;
|
||||
} //end if
|
||||
} //end else if
|
||||
if (fs->next) ScaleFuzzySeperatorBalanceRange_r(fs->next, scale);
|
||||
} //end of the function ScaleFuzzySeperatorBalanceRange_r
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void ScaleFuzzyBalanceRange(weightconfig_t *config, float scale)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (scale < 0) scale = 0;
|
||||
else if (scale > 100) scale = 100;
|
||||
for (i = 0; i < config->numweights; i++)
|
||||
{
|
||||
ScaleFuzzySeperatorBalanceRange_r(config->weights[i].firstseperator, scale);
|
||||
} //end for
|
||||
} //end of the function ScaleFuzzyBalanceRange
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int InterbreedFuzzySeperator_r(fuzzyseperator_t *fs1, fuzzyseperator_t *fs2,
|
||||
fuzzyseperator_t *fsout)
|
||||
{
|
||||
if (fs1->child)
|
||||
{
|
||||
if (!fs2->child || !fsout->child)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "cannot interbreed weight configs, unequal child\n");
|
||||
return qfalse;
|
||||
} //end if
|
||||
if (!InterbreedFuzzySeperator_r(fs2->child, fs2->child, fsout->child))
|
||||
{
|
||||
return qfalse;
|
||||
} //end if
|
||||
} //end if
|
||||
else if (fs1->type == WT_BALANCE)
|
||||
{
|
||||
if (fs2->type != WT_BALANCE || fsout->type != WT_BALANCE)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "cannot interbreed weight configs, unequal balance\n");
|
||||
return qfalse;
|
||||
} //end if
|
||||
fsout->weight = (fs1->weight + fs2->weight) / 2;
|
||||
if (fsout->weight > fsout->maxweight) fsout->maxweight = fsout->weight;
|
||||
if (fsout->weight > fsout->minweight) fsout->minweight = fsout->weight;
|
||||
} //end else if
|
||||
if (fs1->next)
|
||||
{
|
||||
if (!fs2->next || !fsout->next)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "cannot interbreed weight configs, unequal next\n");
|
||||
return qfalse;
|
||||
} //end if
|
||||
if (!InterbreedFuzzySeperator_r(fs1->next, fs2->next, fsout->next))
|
||||
{
|
||||
return qfalse;
|
||||
} //end if
|
||||
} //end if
|
||||
return qtrue;
|
||||
} //end of the function InterbreedFuzzySeperator_r
|
||||
//===========================================================================
|
||||
// config1 and config2 are interbreeded and stored in configout
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void InterbreedWeightConfigs(weightconfig_t *config1, weightconfig_t *config2,
|
||||
weightconfig_t *configout)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (config1->numweights != config2->numweights ||
|
||||
config1->numweights != configout->numweights)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "cannot interbreed weight configs, unequal numweights\n");
|
||||
return;
|
||||
} //end if
|
||||
for (i = 0; i < config1->numweights; i++)
|
||||
{
|
||||
InterbreedFuzzySeperator_r(config1->weights[i].firstseperator,
|
||||
config2->weights[i].firstseperator,
|
||||
configout->weights[i].firstseperator);
|
||||
} //end for
|
||||
} //end of the function InterbreedWeightConfigs
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void BotShutdownWeights(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < MAX_WEIGHT_FILES; i++ )
|
||||
{
|
||||
if (weightFileList[i])
|
||||
{
|
||||
FreeWeightConfig2(weightFileList[i]);
|
||||
weightFileList[i] = NULL;
|
||||
} //end if
|
||||
} //end for
|
||||
} //end of the function BotShutdownWeights
|
66
CODEmp/botlib/be_ai_weight.h
Normal file
66
CODEmp/botlib/be_ai_weight.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_ai_weight.h
|
||||
*
|
||||
* desc: fuzzy weights
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_ai_weight.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define WT_BALANCE 1
|
||||
#define MAX_WEIGHTS 128
|
||||
|
||||
//fuzzy seperator
|
||||
typedef struct fuzzyseperator_s
|
||||
{
|
||||
int index;
|
||||
int value;
|
||||
int type;
|
||||
float weight;
|
||||
float minweight;
|
||||
float maxweight;
|
||||
struct fuzzyseperator_s *child;
|
||||
struct fuzzyseperator_s *next;
|
||||
} fuzzyseperator_t;
|
||||
|
||||
//fuzzy weight
|
||||
typedef struct weight_s
|
||||
{
|
||||
char *name;
|
||||
struct fuzzyseperator_s *firstseperator;
|
||||
} weight_t;
|
||||
|
||||
//weight configuration
|
||||
typedef struct weightconfig_s
|
||||
{
|
||||
int numweights;
|
||||
weight_t weights[MAX_WEIGHTS];
|
||||
char filename[MAX_QPATH];
|
||||
} weightconfig_t;
|
||||
|
||||
//reads a weight configuration
|
||||
weightconfig_t *ReadWeightConfig(char *filename);
|
||||
//free a weight configuration
|
||||
void FreeWeightConfig(weightconfig_t *config);
|
||||
//writes a weight configuration, returns true if successfull
|
||||
qboolean WriteWeightConfig(char *filename, weightconfig_t *config);
|
||||
//find the fuzzy weight with the given name
|
||||
int FindFuzzyWeight(weightconfig_t *wc, char *name);
|
||||
//returns the fuzzy weight for the given inventory and weight
|
||||
float FuzzyWeight(int *inventory, weightconfig_t *wc, int weightnum);
|
||||
float FuzzyWeightUndecided(int *inventory, weightconfig_t *wc, int weightnum);
|
||||
//scales the weight with the given name
|
||||
void ScaleWeight(weightconfig_t *config, char *name, float scale);
|
||||
//scale the balance range
|
||||
void ScaleBalanceRange(weightconfig_t *config, float scale);
|
||||
//evolves the weight configuration
|
||||
void EvolveWeightConfig(weightconfig_t *config);
|
||||
//interbreed the weight configurations and stores the interbreeded one in configout
|
||||
void InterbreedWeightConfigs(weightconfig_t *config1, weightconfig_t *config2, weightconfig_t *configout);
|
||||
//frees cached weight configurations
|
||||
void BotShutdownWeights(void);
|
519
CODEmp/botlib/be_ea.cpp
Normal file
519
CODEmp/botlib/be_ea.cpp
Normal file
|
@ -0,0 +1,519 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_ea.c
|
||||
*
|
||||
* desc: elementary actions
|
||||
*
|
||||
* $Archive: /MissionPack/code/botlib/be_ea.c $
|
||||
* $Author: Zaphod $
|
||||
* $Revision: 5 $
|
||||
* $Modtime: 11/22/00 8:50a $
|
||||
* $Date: 11/22/00 8:55a $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "l_memory.h"
|
||||
#include "l_script.h"
|
||||
#include "l_precomp.h"
|
||||
#include "l_struct.h"
|
||||
#include "../game/botlib.h"
|
||||
#include "be_interface.h"
|
||||
|
||||
#define MAX_USERMOVE 400
|
||||
#define MAX_COMMANDARGUMENTS 10
|
||||
#define ACTION_JUMPEDLASTFRAME 0x0800000//128
|
||||
|
||||
bot_input_t *botinputs;
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_Say(int client, char *str)
|
||||
{
|
||||
botimport.BotClientCommand(client, va("say %s", str) );
|
||||
} //end of the function EA_Say
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_SayTeam(int client, char *str)
|
||||
{
|
||||
botimport.BotClientCommand(client, va("say_team %s", str));
|
||||
} //end of the function EA_SayTeam
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_Tell(int client, int clientto, char *str)
|
||||
{
|
||||
botimport.BotClientCommand(client, va("tell %d, %s", clientto, str));
|
||||
} //end of the function EA_SayTeam
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_UseItem(int client, char *it)
|
||||
{
|
||||
botimport.BotClientCommand(client, va("use %s", it));
|
||||
} //end of the function EA_UseItem
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_DropItem(int client, char *it)
|
||||
{
|
||||
botimport.BotClientCommand(client, va("drop %s", it));
|
||||
} //end of the function EA_DropItem
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_UseInv(int client, char *inv)
|
||||
{
|
||||
botimport.BotClientCommand(client, va("invuse %s", inv));
|
||||
} //end of the function EA_UseInv
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_DropInv(int client, char *inv)
|
||||
{
|
||||
botimport.BotClientCommand(client, va("invdrop %s", inv));
|
||||
} //end of the function EA_DropInv
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_Gesture(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->actionflags |= ACTION_GESTURE;
|
||||
} //end of the function EA_Gesture
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_Command(int client, char *command)
|
||||
{
|
||||
botimport.BotClientCommand(client, command);
|
||||
} //end of the function EA_Command
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_SelectWeapon(int client, int weapon)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->weapon = weapon;
|
||||
} //end of the function EA_SelectWeapon
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_Attack(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->actionflags |= ACTION_ATTACK;
|
||||
} //end of the function EA_Attack
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_Alt_Attack(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->actionflags |= ACTION_ALT_ATTACK;
|
||||
} //end of the function EA_Alt_Attack
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_ForcePower(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->actionflags |= ACTION_FORCEPOWER;
|
||||
} //end of the function EA_ForcePower
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_Talk(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->actionflags |= ACTION_TALK;
|
||||
} //end of the function EA_Talk
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_Use(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->actionflags |= ACTION_USE;
|
||||
} //end of the function EA_Use
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_Respawn(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->actionflags |= ACTION_RESPAWN;
|
||||
} //end of the function EA_Respawn
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_Jump(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
if (bi->actionflags & ACTION_JUMPEDLASTFRAME)
|
||||
{
|
||||
bi->actionflags &= ~ACTION_JUMP;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
bi->actionflags |= ACTION_JUMP;
|
||||
} //end if
|
||||
} //end of the function EA_Jump
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_DelayedJump(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
if (bi->actionflags & ACTION_JUMPEDLASTFRAME)
|
||||
{
|
||||
bi->actionflags &= ~ACTION_DELAYEDJUMP;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
bi->actionflags |= ACTION_DELAYEDJUMP;
|
||||
} //end if
|
||||
} //end of the function EA_DelayedJump
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_Crouch(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->actionflags |= ACTION_CROUCH;
|
||||
} //end of the function EA_Crouch
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_Walk(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->actionflags |= ACTION_WALK;
|
||||
} //end of the function EA_Walk
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_Action(int client, int action)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->actionflags |= action;
|
||||
} //end of function EA_Action
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_MoveUp(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->actionflags |= ACTION_MOVEUP;
|
||||
} //end of the function EA_MoveUp
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_MoveDown(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->actionflags |= ACTION_MOVEDOWN;
|
||||
} //end of the function EA_MoveDown
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_MoveForward(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->actionflags |= ACTION_MOVEFORWARD;
|
||||
} //end of the function EA_MoveForward
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_MoveBack(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->actionflags |= ACTION_MOVEBACK;
|
||||
} //end of the function EA_MoveBack
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_MoveLeft(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->actionflags |= ACTION_MOVELEFT;
|
||||
} //end of the function EA_MoveLeft
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_MoveRight(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->actionflags |= ACTION_MOVERIGHT;
|
||||
} //end of the function EA_MoveRight
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_Move(int client, vec3_t dir, float speed)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
VectorCopy(dir, bi->dir);
|
||||
//cap speed
|
||||
if (speed > MAX_USERMOVE) speed = MAX_USERMOVE;
|
||||
else if (speed < -MAX_USERMOVE) speed = -MAX_USERMOVE;
|
||||
bi->speed = speed;
|
||||
} //end of the function EA_Move
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_View(int client, vec3_t viewangles)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
VectorCopy(viewangles, bi->viewangles);
|
||||
} //end of the function EA_View
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_EndRegular(int client, float thinktime)
|
||||
{
|
||||
/*
|
||||
bot_input_t *bi;
|
||||
int jumped = qfalse;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
bi->actionflags &= ~ACTION_JUMPEDLASTFRAME;
|
||||
|
||||
bi->thinktime = thinktime;
|
||||
botimport.BotInput(client, bi);
|
||||
|
||||
bi->thinktime = 0;
|
||||
VectorClear(bi->dir);
|
||||
bi->speed = 0;
|
||||
jumped = bi->actionflags & ACTION_JUMP;
|
||||
bi->actionflags = 0;
|
||||
if (jumped) bi->actionflags |= ACTION_JUMPEDLASTFRAME;
|
||||
*/
|
||||
} //end of the function EA_EndRegular
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_GetInput(int client, float thinktime, bot_input_t *input)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
// int jumped = qfalse;
|
||||
|
||||
bi = &botinputs[client];
|
||||
|
||||
// bi->actionflags &= ~ACTION_JUMPEDLASTFRAME;
|
||||
|
||||
bi->thinktime = thinktime;
|
||||
Com_Memcpy(input, bi, sizeof(bot_input_t));
|
||||
|
||||
/*
|
||||
bi->thinktime = 0;
|
||||
VectorClear(bi->dir);
|
||||
bi->speed = 0;
|
||||
jumped = bi->actionflags & ACTION_JUMP;
|
||||
bi->actionflags = 0;
|
||||
if (jumped) bi->actionflags |= ACTION_JUMPEDLASTFRAME;
|
||||
*/
|
||||
} //end of the function EA_GetInput
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_ResetInput(int client)
|
||||
{
|
||||
bot_input_t *bi;
|
||||
int jumped = qfalse;
|
||||
|
||||
bi = &botinputs[client];
|
||||
bi->actionflags &= ~ACTION_JUMPEDLASTFRAME;
|
||||
|
||||
bi->thinktime = 0;
|
||||
VectorClear(bi->dir);
|
||||
bi->speed = 0;
|
||||
jumped = bi->actionflags & ACTION_JUMP;
|
||||
bi->actionflags = 0;
|
||||
if (jumped) bi->actionflags |= ACTION_JUMPEDLASTFRAME;
|
||||
} //end of the function EA_ResetInput
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int EA_Setup(void)
|
||||
{
|
||||
//initialize the bot inputs
|
||||
botinputs = (bot_input_t *) GetClearedHunkMemory(
|
||||
botlibglobals.maxclients * sizeof(bot_input_t));
|
||||
return BLERR_NOERROR;
|
||||
} //end of the function EA_Setup
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void EA_Shutdown(void)
|
||||
{
|
||||
FreeMemory(botinputs);
|
||||
botinputs = NULL;
|
||||
} //end of the function EA_Shutdown
|
867
CODEmp/botlib/be_interface.cpp
Normal file
867
CODEmp/botlib/be_interface.cpp
Normal file
|
@ -0,0 +1,867 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_interface.c // bk010221 - FIXME - DEAD code elimination
|
||||
*
|
||||
* desc: bot library interface
|
||||
*
|
||||
* $Archive: /MissionPack/code/botlib/be_interface.c $
|
||||
* $Author: Zaphod $
|
||||
* $Revision: 16 $
|
||||
* $Modtime: 5/16/01 2:36p $
|
||||
* $Date: 5/16/01 2:41p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "l_memory.h"
|
||||
#include "l_log.h"
|
||||
#include "l_libvar.h"
|
||||
#include "l_script.h"
|
||||
#include "l_precomp.h"
|
||||
#include "l_struct.h"
|
||||
#include "aasfile.h"
|
||||
#include "../game/botlib.h"
|
||||
#include "../game/be_aas.h"
|
||||
#include "be_aas_funcs.h"
|
||||
#include "be_aas_def.h"
|
||||
#include "be_interface.h"
|
||||
|
||||
#include "../game/be_ea.h"
|
||||
#include "be_ai_weight.h"
|
||||
#include "../game/be_ai_goal.h"
|
||||
#include "../game/be_ai_move.h"
|
||||
#include "../game/be_ai_weap.h"
|
||||
#include "../game/be_ai_chat.h"
|
||||
#include "../game/be_ai_char.h"
|
||||
#include "../game/be_ai_gen.h"
|
||||
|
||||
//library globals in a structure
|
||||
botlib_globals_t botlibglobals;
|
||||
|
||||
botlib_export_t be_botlib_export;
|
||||
botlib_import_t botimport;
|
||||
//
|
||||
int bot_developer;
|
||||
//qtrue if the library is setup
|
||||
int botlibsetup = qfalse;
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// several functions used by the exported functions
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int Sys_MilliSeconds(void)
|
||||
{
|
||||
return clock() * 1000 / CLOCKS_PER_SEC;
|
||||
} //end of the function Sys_MilliSeconds
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
qboolean ValidClientNumber(int num, char *str)
|
||||
{
|
||||
if (num < 0 || num > botlibglobals.maxclients)
|
||||
{
|
||||
//weird: the disabled stuff results in a crash
|
||||
botimport.Print(PRT_ERROR, "%s: invalid client number %d, [0, %d]\n",
|
||||
str, num, botlibglobals.maxclients);
|
||||
return qfalse;
|
||||
} //end if
|
||||
return qtrue;
|
||||
} //end of the function BotValidateClientNumber
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
qboolean ValidEntityNumber(int num, char *str)
|
||||
{
|
||||
if (num < 0 || num > botlibglobals.maxentities)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "%s: invalid entity number %d, [0, %d]\n",
|
||||
str, num, botlibglobals.maxentities);
|
||||
return qfalse;
|
||||
} //end if
|
||||
return qtrue;
|
||||
} //end of the function BotValidateClientNumber
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
qboolean BotLibSetup(char *str)
|
||||
{
|
||||
if (!botlibglobals.botlibsetup)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "%s: bot library used before being setup\n", str);
|
||||
return qfalse;
|
||||
} //end if
|
||||
return qtrue;
|
||||
} //end of the function BotLibSetup
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int Export_BotLibSetup(void)
|
||||
{
|
||||
int errnum;
|
||||
|
||||
bot_developer = LibVarGetValue("bot_developer");
|
||||
memset( &botlibglobals, 0, sizeof(botlibglobals) ); // bk001207 - init
|
||||
//initialize byte swapping (litte endian etc.)
|
||||
// Swap_Init();
|
||||
Log_Open("botlib.log");
|
||||
//
|
||||
botimport.Print(PRT_MESSAGE, "------- BotLib Initialization -------\n");
|
||||
//
|
||||
botlibglobals.maxclients = (int) LibVarValue("maxclients", "128");
|
||||
botlibglobals.maxentities = (int) LibVarValue("maxentities", "1024");
|
||||
|
||||
errnum = AAS_Setup(); //be_aas_main.c
|
||||
if (errnum != BLERR_NOERROR) return errnum;
|
||||
errnum = EA_Setup(); //be_ea.c
|
||||
if (errnum != BLERR_NOERROR) return errnum;
|
||||
/*
|
||||
errnum = BotSetupWeaponAI(); //be_ai_weap.c
|
||||
if (errnum != BLERR_NOERROR)return errnum;
|
||||
errnum = BotSetupGoalAI(); //be_ai_goal.c
|
||||
if (errnum != BLERR_NOERROR) return errnum;
|
||||
errnum = BotSetupChatAI(); //be_ai_chat.c
|
||||
if (errnum != BLERR_NOERROR) return errnum;
|
||||
errnum = BotSetupMoveAI(); //be_ai_move.c
|
||||
if (errnum != BLERR_NOERROR) return errnum;
|
||||
*/
|
||||
botlibsetup = qtrue;
|
||||
botlibglobals.botlibsetup = qtrue;
|
||||
|
||||
return BLERR_NOERROR;
|
||||
} //end of the function Export_BotLibSetup
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int Export_BotLibShutdown(void)
|
||||
{
|
||||
if (!BotLibSetup("BotLibShutdown")) return BLERR_LIBRARYNOTSETUP;
|
||||
#ifndef DEMO
|
||||
//DumpFileCRCs();
|
||||
#endif //DEMO
|
||||
//
|
||||
BotShutdownChatAI(); //be_ai_chat.c
|
||||
BotShutdownMoveAI(); //be_ai_move.c
|
||||
BotShutdownGoalAI(); //be_ai_goal.c
|
||||
BotShutdownWeaponAI(); //be_ai_weap.c
|
||||
BotShutdownWeights(); //be_ai_weight.c
|
||||
BotShutdownCharacters(); //be_ai_char.c
|
||||
//shud down aas
|
||||
AAS_Shutdown();
|
||||
//shut down bot elemantary actions
|
||||
EA_Shutdown();
|
||||
//free all libvars
|
||||
LibVarDeAllocAll();
|
||||
//remove all global defines from the pre compiler
|
||||
PC_RemoveAllGlobalDefines();
|
||||
|
||||
//dump all allocated memory
|
||||
// DumpMemory();
|
||||
#ifdef DEBUG
|
||||
PrintMemoryLabels();
|
||||
#endif
|
||||
//shut down library log file
|
||||
Log_Shutdown();
|
||||
//
|
||||
botlibsetup = qfalse;
|
||||
botlibglobals.botlibsetup = qfalse;
|
||||
// print any files still open
|
||||
PC_CheckOpenSourceHandles();
|
||||
//
|
||||
return BLERR_NOERROR;
|
||||
} //end of the function Export_BotLibShutdown
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int Export_BotLibVarSet(char *var_name, char *value)
|
||||
{
|
||||
LibVarSet(var_name, value);
|
||||
return BLERR_NOERROR;
|
||||
} //end of the function Export_BotLibVarSet
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int Export_BotLibVarGet(char *var_name, char *value, int size)
|
||||
{
|
||||
char *varvalue;
|
||||
|
||||
varvalue = LibVarGetString(var_name);
|
||||
strncpy(value, varvalue, size-1);
|
||||
value[size-1] = '\0';
|
||||
return BLERR_NOERROR;
|
||||
} //end of the function Export_BotLibVarGet
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int Export_BotLibStartFrame(float time)
|
||||
{
|
||||
if (!BotLibSetup("BotStartFrame")) return BLERR_LIBRARYNOTSETUP;
|
||||
return AAS_StartFrame(time);
|
||||
} //end of the function Export_BotLibStartFrame
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int Export_BotLibLoadMap(const char *mapname)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
int starttime = Sys_MilliSeconds();
|
||||
#endif
|
||||
int errnum;
|
||||
|
||||
if (!BotLibSetup("BotLoadMap")) return BLERR_LIBRARYNOTSETUP;
|
||||
//
|
||||
botimport.Print(PRT_MESSAGE, "------------ Map Loading ------------\n");
|
||||
//startup AAS for the current map, model and sound index
|
||||
errnum = AAS_LoadMap(mapname);
|
||||
if (errnum != BLERR_NOERROR) return errnum;
|
||||
//initialize the items in the level
|
||||
BotInitLevelItems(); //be_ai_goal.h
|
||||
BotSetBrushModelTypes(); //be_ai_move.h
|
||||
//
|
||||
botimport.Print(PRT_MESSAGE, "-------------------------------------\n");
|
||||
#ifdef DEBUG
|
||||
botimport.Print(PRT_MESSAGE, "map loaded in %d msec\n", Sys_MilliSeconds() - starttime);
|
||||
#endif
|
||||
//
|
||||
return BLERR_NOERROR;
|
||||
} //end of the function Export_BotLibLoadMap
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int Export_BotLibUpdateEntity(int ent, bot_entitystate_t *state)
|
||||
{
|
||||
if (!BotLibSetup("BotUpdateEntity")) return BLERR_LIBRARYNOTSETUP;
|
||||
if (!ValidEntityNumber(ent, "BotUpdateEntity")) return BLERR_INVALIDENTITYNUMBER;
|
||||
|
||||
return AAS_UpdateEntity(ent, state);
|
||||
} //end of the function Export_BotLibUpdateEntity
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void AAS_TestMovementPrediction(int entnum, vec3_t origin, vec3_t dir);
|
||||
void ElevatorBottomCenter(aas_reachability_t *reach, vec3_t bottomcenter);
|
||||
int BotGetReachabilityToGoal(vec3_t origin, int areanum,
|
||||
int lastgoalareanum, int lastareanum,
|
||||
int *avoidreach, float *avoidreachtimes, int *avoidreachtries,
|
||||
bot_goal_t *goal, int travelflags, int movetravelflags,
|
||||
struct bot_avoidspot_s *avoidspots, int numavoidspots, int *flags);
|
||||
|
||||
int AAS_PointLight(vec3_t origin, int *red, int *green, int *blue);
|
||||
|
||||
int AAS_TraceAreas(vec3_t start, vec3_t end, int *areas, vec3_t *points, int maxareas);
|
||||
|
||||
int AAS_Reachability_WeaponJump(int area1num, int area2num);
|
||||
|
||||
int BotFuzzyPointReachabilityArea(vec3_t origin);
|
||||
|
||||
float BotGapDistance(vec3_t origin, vec3_t hordir, int entnum);
|
||||
|
||||
void AAS_FloodAreas(vec3_t origin);
|
||||
|
||||
int BotExportTest(int parm0, char *parm1, vec3_t parm2, vec3_t parm3)
|
||||
{
|
||||
|
||||
// return AAS_PointLight(parm2, NULL, NULL, NULL);
|
||||
|
||||
#ifdef DEBUG
|
||||
static int area = -1;
|
||||
static int line[2];
|
||||
int newarea, i, highlightarea, flood;
|
||||
// int reachnum;
|
||||
vec3_t eye, forward, right, end, origin;
|
||||
// vec3_t bottomcenter;
|
||||
// aas_trace_t trace;
|
||||
// aas_face_t *face;
|
||||
// aas_entity_t *ent;
|
||||
// bsp_trace_t bsptrace;
|
||||
// aas_reachability_t reach;
|
||||
// bot_goal_t goal;
|
||||
|
||||
// clock_t start_time, end_time;
|
||||
vec3_t mins = {-16, -16, -24};
|
||||
vec3_t maxs = {16, 16, 32};
|
||||
|
||||
// int areas[10], numareas;
|
||||
|
||||
|
||||
//return 0;
|
||||
|
||||
if (!aasworld.loaded) return 0;
|
||||
|
||||
/*
|
||||
if (parm0 & 1)
|
||||
{
|
||||
AAS_ClearShownPolygons();
|
||||
AAS_FloodAreas(parm2);
|
||||
} //end if
|
||||
return 0;
|
||||
*/
|
||||
for (i = 0; i < 2; i++) if (!line[i]) line[i] = botimport.DebugLineCreate();
|
||||
|
||||
// AAS_ClearShownDebugLines();
|
||||
|
||||
//if (AAS_AgainstLadder(parm2)) botimport.Print(PRT_MESSAGE, "against ladder\n");
|
||||
//BotOnGround(parm2, PRESENCE_NORMAL, 1, &newarea, &newarea);
|
||||
//botimport.Print(PRT_MESSAGE, "%f %f %f\n", parm2[0], parm2[1], parm2[2]);
|
||||
//*
|
||||
highlightarea = LibVarGetValue("bot_highlightarea");
|
||||
if (highlightarea > 0)
|
||||
{
|
||||
newarea = highlightarea;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
VectorCopy(parm2, origin);
|
||||
origin[2] += 0.5;
|
||||
//newarea = AAS_PointAreaNum(origin);
|
||||
newarea = BotFuzzyPointReachabilityArea(origin);
|
||||
} //end else
|
||||
|
||||
botimport.Print(PRT_MESSAGE, "\rtravel time to goal (%d) = %d ", botlibglobals.goalareanum,
|
||||
AAS_AreaTravelTimeToGoalArea(newarea, origin, botlibglobals.goalareanum, TFL_DEFAULT));
|
||||
//newarea = BotReachabilityArea(origin, qtrue);
|
||||
if (newarea != area)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "origin = %f, %f, %f\n", origin[0], origin[1], origin[2]);
|
||||
area = newarea;
|
||||
botimport.Print(PRT_MESSAGE, "new area %d, cluster %d, presence type %d\n",
|
||||
area, AAS_AreaCluster(area), AAS_PointPresenceType(origin));
|
||||
botimport.Print(PRT_MESSAGE, "area contents: ");
|
||||
if (aasworld.areasettings[area].contents & AREACONTENTS_WATER)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "water &");
|
||||
} //end if
|
||||
if (aasworld.areasettings[area].contents & AREACONTENTS_LAVA)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "lava &");
|
||||
} //end if
|
||||
if (aasworld.areasettings[area].contents & AREACONTENTS_SLIME)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "slime &");
|
||||
} //end if
|
||||
if (aasworld.areasettings[area].contents & AREACONTENTS_JUMPPAD)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "jump pad &");
|
||||
} //end if
|
||||
if (aasworld.areasettings[area].contents & AREACONTENTS_CLUSTERPORTAL)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "cluster portal &");
|
||||
} //end if
|
||||
if (aasworld.areasettings[area].contents & AREACONTENTS_VIEWPORTAL)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "view portal &");
|
||||
} //end if
|
||||
if (aasworld.areasettings[area].contents & AREACONTENTS_DONOTENTER)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "do not enter &");
|
||||
} //end if
|
||||
if (aasworld.areasettings[area].contents & AREACONTENTS_MOVER)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "mover &");
|
||||
} //end if
|
||||
if (!aasworld.areasettings[area].contents)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "empty");
|
||||
} //end if
|
||||
botimport.Print(PRT_MESSAGE, "\n");
|
||||
botimport.Print(PRT_MESSAGE, "travel time to goal (%d) = %d\n", botlibglobals.goalareanum,
|
||||
AAS_AreaTravelTimeToGoalArea(newarea, origin, botlibglobals.goalareanum, TFL_DEFAULT|TFL_ROCKETJUMP));
|
||||
/*
|
||||
VectorCopy(origin, end);
|
||||
end[2] += 5;
|
||||
numareas = AAS_TraceAreas(origin, end, areas, NULL, 10);
|
||||
AAS_TraceClientBBox(origin, end, PRESENCE_CROUCH, -1);
|
||||
botimport.Print(PRT_MESSAGE, "num areas = %d, area = %d\n", numareas, areas[0]);
|
||||
*/
|
||||
/*
|
||||
botlibglobals.goalareanum = newarea;
|
||||
VectorCopy(parm2, botlibglobals.goalorigin);
|
||||
botimport.Print(PRT_MESSAGE, "new goal %2.1f %2.1f %2.1f area %d\n",
|
||||
origin[0], origin[1], origin[2], newarea);
|
||||
*/
|
||||
} //end if
|
||||
//*
|
||||
flood = LibVarGetValue("bot_flood");
|
||||
if (parm0 & 1)
|
||||
{
|
||||
if (flood)
|
||||
{
|
||||
AAS_ClearShownPolygons();
|
||||
AAS_ClearShownDebugLines();
|
||||
AAS_FloodAreas(parm2);
|
||||
}
|
||||
else
|
||||
{
|
||||
botlibglobals.goalareanum = newarea;
|
||||
VectorCopy(parm2, botlibglobals.goalorigin);
|
||||
botimport.Print(PRT_MESSAGE, "new goal %2.1f %2.1f %2.1f area %d\n",
|
||||
origin[0], origin[1], origin[2], newarea);
|
||||
}
|
||||
} //end if*/
|
||||
if (flood)
|
||||
return 0;
|
||||
// if (parm0 & BUTTON_USE)
|
||||
// {
|
||||
// botlibglobals.runai = !botlibglobals.runai;
|
||||
// if (botlibglobals.runai) botimport.Print(PRT_MESSAGE, "started AI\n");
|
||||
// else botimport.Print(PRT_MESSAGE, "stopped AI\n");
|
||||
//* /
|
||||
/*
|
||||
goal.areanum = botlibglobals.goalareanum;
|
||||
reachnum = BotGetReachabilityToGoal(parm2, newarea, 1,
|
||||
ms.avoidreach, ms.avoidreachtimes,
|
||||
&goal, TFL_DEFAULT);
|
||||
if (!reachnum)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "goal not reachable\n");
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
AAS_ReachabilityFromNum(reachnum, &reach);
|
||||
AAS_ClearShownDebugLines();
|
||||
AAS_ShowArea(area, qtrue);
|
||||
AAS_ShowArea(reach.areanum, qtrue);
|
||||
AAS_DrawCross(reach.start, 6, LINECOLOR_BLUE);
|
||||
AAS_DrawCross(reach.end, 6, LINECOLOR_RED);
|
||||
//
|
||||
if ((reach.traveltype & TRAVELTYPE_MASK) == TRAVEL_ELEVATOR)
|
||||
{
|
||||
ElevatorBottomCenter(&reach, bottomcenter);
|
||||
AAS_DrawCross(bottomcenter, 10, LINECOLOR_GREEN);
|
||||
} //end if
|
||||
} //end else*/
|
||||
// botimport.Print(PRT_MESSAGE, "travel time to goal = %d\n",
|
||||
// AAS_AreaTravelTimeToGoalArea(area, origin, botlibglobals.goalareanum, TFL_DEFAULT));
|
||||
// botimport.Print(PRT_MESSAGE, "test rj from 703 to 716\n");
|
||||
// AAS_Reachability_WeaponJump(703, 716);
|
||||
// } //end if*/
|
||||
|
||||
/* face = AAS_AreaGroundFace(newarea, parm2);
|
||||
if (face)
|
||||
{
|
||||
AAS_ShowFace(face - aasworld.faces);
|
||||
} //end if*/
|
||||
/*
|
||||
AAS_ClearShownDebugLines();
|
||||
AAS_ShowArea(newarea, parm0 & BUTTON_USE);
|
||||
AAS_ShowReachableAreas(area);
|
||||
*/
|
||||
AAS_ClearShownPolygons();
|
||||
AAS_ClearShownDebugLines();
|
||||
AAS_ShowAreaPolygons(newarea, 1, parm0 & 4);
|
||||
if (parm0 & 2) AAS_ShowReachableAreas(area);
|
||||
else
|
||||
{
|
||||
static int lastgoalareanum, lastareanum;
|
||||
static int avoidreach[MAX_AVOIDREACH];
|
||||
static float avoidreachtimes[MAX_AVOIDREACH];
|
||||
static int avoidreachtries[MAX_AVOIDREACH];
|
||||
int reachnum, resultFlags;
|
||||
bot_goal_t goal;
|
||||
aas_reachability_t reach;
|
||||
|
||||
/*
|
||||
goal.areanum = botlibglobals.goalareanum;
|
||||
VectorCopy(botlibglobals.goalorigin, goal.origin);
|
||||
reachnum = BotGetReachabilityToGoal(origin, newarea,
|
||||
lastgoalareanum, lastareanum,
|
||||
avoidreach, avoidreachtimes, avoidreachtries,
|
||||
&goal, TFL_DEFAULT|TFL_FUNCBOB|TFL_ROCKETJUMP, TFL_DEFAULT|TFL_FUNCBOB|TFL_ROCKETJUMP,
|
||||
NULL, 0, &resultFlags);
|
||||
AAS_ReachabilityFromNum(reachnum, &reach);
|
||||
AAS_ShowReachability(&reach);
|
||||
*/
|
||||
int curarea;
|
||||
vec3_t curorigin;
|
||||
|
||||
goal.areanum = botlibglobals.goalareanum;
|
||||
VectorCopy(botlibglobals.goalorigin, goal.origin);
|
||||
VectorCopy(origin, curorigin);
|
||||
curarea = newarea;
|
||||
for ( i = 0; i < 100; i++ ) {
|
||||
if ( curarea == goal.areanum ) {
|
||||
break;
|
||||
}
|
||||
reachnum = BotGetReachabilityToGoal(curorigin, curarea,
|
||||
lastgoalareanum, lastareanum,
|
||||
avoidreach, avoidreachtimes, avoidreachtries,
|
||||
&goal, TFL_DEFAULT|TFL_FUNCBOB|TFL_ROCKETJUMP, TFL_DEFAULT|TFL_FUNCBOB|TFL_ROCKETJUMP,
|
||||
NULL, 0, &resultFlags);
|
||||
AAS_ReachabilityFromNum(reachnum, &reach);
|
||||
AAS_ShowReachability(&reach);
|
||||
VectorCopy(reach.end, origin);
|
||||
lastareanum = curarea;
|
||||
curarea = reach.areanum;
|
||||
}
|
||||
} //end else
|
||||
VectorClear(forward);
|
||||
//BotGapDistance(origin, forward, 0);
|
||||
/*
|
||||
if (parm0 & BUTTON_USE)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "test rj from 703 to 716\n");
|
||||
AAS_Reachability_WeaponJump(703, 716);
|
||||
} //end if*/
|
||||
|
||||
AngleVectors(parm3, forward, right, NULL);
|
||||
//get the eye 16 units to the right of the origin
|
||||
VectorMA(parm2, 8, right, eye);
|
||||
//get the eye 24 units up
|
||||
eye[2] += 24;
|
||||
//get the end point for the line to be traced
|
||||
VectorMA(eye, 800, forward, end);
|
||||
|
||||
// AAS_TestMovementPrediction(1, parm2, forward);
|
||||
/*
|
||||
//trace the line to find the hit point
|
||||
trace = AAS_TraceClientBBox(eye, end, PRESENCE_NORMAL, 1);
|
||||
if (!line[0]) line[0] = botimport.DebugLineCreate();
|
||||
botimport.DebugLineShow(line[0], eye, trace.endpos, LINECOLOR_BLUE);
|
||||
//
|
||||
AAS_ClearShownDebugLines();
|
||||
if (trace.ent)
|
||||
{
|
||||
ent = &aasworld.entities[trace.ent];
|
||||
AAS_ShowBoundingBox(ent->origin, ent->mins, ent->maxs);
|
||||
} //end if
|
||||
*/
|
||||
|
||||
/*
|
||||
start_time = clock();
|
||||
for (i = 0; i < 2000; i++)
|
||||
{
|
||||
AAS_Trace2(eye, mins, maxs, end, 1, MASK_PLAYERSOLID);
|
||||
// AAS_TraceClientBBox(eye, end, PRESENCE_NORMAL, 1);
|
||||
} //end for
|
||||
end_time = clock();
|
||||
botimport.Print(PRT_MESSAGE, "me %lu clocks, %lu CLOCKS_PER_SEC\n", end_time - start_time, CLOCKS_PER_SEC);
|
||||
start_time = clock();
|
||||
for (i = 0; i < 2000; i++)
|
||||
{
|
||||
AAS_Trace(eye, mins, maxs, end, 1, MASK_PLAYERSOLID);
|
||||
} //end for
|
||||
end_time = clock();
|
||||
botimport.Print(PRT_MESSAGE, "id %lu clocks, %lu CLOCKS_PER_SEC\n", end_time - start_time, CLOCKS_PER_SEC);
|
||||
*/
|
||||
|
||||
// TTimo: nested comments are BAD for gcc -Werror, use #if 0 instead..
|
||||
#if 0
|
||||
AAS_ClearShownDebugLines();
|
||||
//bsptrace = AAS_Trace(eye, NULL, NULL, end, 1, MASK_PLAYERSOLID);
|
||||
bsptrace = AAS_Trace(eye, mins, maxs, end, 1, MASK_PLAYERSOLID);
|
||||
if (!line[0]) line[0] = botimport.DebugLineCreate();
|
||||
botimport.DebugLineShow(line[0], eye, bsptrace.endpos, LINECOLOR_YELLOW);
|
||||
if (bsptrace.fraction < 1.0)
|
||||
{
|
||||
face = AAS_TraceEndFace(&trace);
|
||||
if (face)
|
||||
{
|
||||
AAS_ShowFace(face - aasworld.faces);
|
||||
} //end if
|
||||
|
||||
AAS_DrawPlaneCross(bsptrace.endpos,
|
||||
bsptrace.plane.normal,
|
||||
bsptrace.plane.dist + bsptrace.exp_dist,
|
||||
bsptrace.plane.type, LINECOLOR_GREEN);
|
||||
if (trace.ent)
|
||||
{
|
||||
ent = &aasworld.entities[trace.ent];
|
||||
AAS_ShowBoundingBox(ent->origin, ent->mins, ent->maxs);
|
||||
} //end if
|
||||
} //end if
|
||||
//bsptrace = AAS_Trace2(eye, NULL, NULL, end, 1, MASK_PLAYERSOLID);
|
||||
bsptrace = AAS_Trace2(eye, mins, maxs, end, 1, MASK_PLAYERSOLID);
|
||||
botimport.DebugLineShow(line[1], eye, bsptrace.endpos, LINECOLOR_BLUE);
|
||||
if (bsptrace.fraction < 1.0)
|
||||
{
|
||||
AAS_DrawPlaneCross(bsptrace.endpos,
|
||||
bsptrace.plane.normal,
|
||||
bsptrace.plane.dist,// + bsptrace.exp_dist,
|
||||
bsptrace.plane.type, LINECOLOR_RED);
|
||||
if (bsptrace.ent)
|
||||
{
|
||||
ent = &aasworld.entities[bsptrace.ent];
|
||||
AAS_ShowBoundingBox(ent->origin, ent->mins, ent->maxs);
|
||||
} //end if
|
||||
} //end if
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
} //end of the function BotExportTest
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
Init_AAS_Export
|
||||
============
|
||||
*/
|
||||
static void Init_AAS_Export( aas_export_t *aas ) {
|
||||
//--------------------------------------------
|
||||
// be_aas_entity.c
|
||||
//--------------------------------------------
|
||||
aas->AAS_EntityInfo = AAS_EntityInfo;
|
||||
//--------------------------------------------
|
||||
// be_aas_main.c
|
||||
//--------------------------------------------
|
||||
aas->AAS_Initialized = AAS_Initialized;
|
||||
aas->AAS_PresenceTypeBoundingBox = AAS_PresenceTypeBoundingBox;
|
||||
aas->AAS_Time = AAS_Time;
|
||||
//--------------------------------------------
|
||||
// be_aas_sample.c
|
||||
//--------------------------------------------
|
||||
aas->AAS_PointAreaNum = AAS_PointAreaNum;
|
||||
aas->AAS_PointReachabilityAreaIndex = AAS_PointReachabilityAreaIndex;
|
||||
aas->AAS_TraceAreas = AAS_TraceAreas;
|
||||
aas->AAS_BBoxAreas = AAS_BBoxAreas;
|
||||
aas->AAS_AreaInfo = AAS_AreaInfo;
|
||||
//--------------------------------------------
|
||||
// be_aas_bspq3.c
|
||||
//--------------------------------------------
|
||||
aas->AAS_PointContents = AAS_PointContents;
|
||||
aas->AAS_NextBSPEntity = AAS_NextBSPEntity;
|
||||
aas->AAS_ValueForBSPEpairKey = AAS_ValueForBSPEpairKey;
|
||||
aas->AAS_VectorForBSPEpairKey = AAS_VectorForBSPEpairKey;
|
||||
aas->AAS_FloatForBSPEpairKey = AAS_FloatForBSPEpairKey;
|
||||
aas->AAS_IntForBSPEpairKey = AAS_IntForBSPEpairKey;
|
||||
//--------------------------------------------
|
||||
// be_aas_reach.c
|
||||
//--------------------------------------------
|
||||
aas->AAS_AreaReachability = AAS_AreaReachability;
|
||||
//--------------------------------------------
|
||||
// be_aas_route.c
|
||||
//--------------------------------------------
|
||||
aas->AAS_AreaTravelTimeToGoalArea = AAS_AreaTravelTimeToGoalArea;
|
||||
aas->AAS_EnableRoutingArea = AAS_EnableRoutingArea;
|
||||
aas->AAS_PredictRoute = AAS_PredictRoute;
|
||||
//--------------------------------------------
|
||||
// be_aas_altroute.c
|
||||
//--------------------------------------------
|
||||
aas->AAS_AlternativeRouteGoals = AAS_AlternativeRouteGoals;
|
||||
//--------------------------------------------
|
||||
// be_aas_move.c
|
||||
//--------------------------------------------
|
||||
aas->AAS_Swimming = AAS_Swimming;
|
||||
aas->AAS_PredictClientMovement = AAS_PredictClientMovement;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
Init_EA_Export
|
||||
============
|
||||
*/
|
||||
static void Init_EA_Export( ea_export_t *ea ) {
|
||||
//ClientCommand elementary actions
|
||||
ea->EA_Command = EA_Command;
|
||||
ea->EA_Say = EA_Say;
|
||||
ea->EA_SayTeam = EA_SayTeam;
|
||||
|
||||
ea->EA_Action = EA_Action;
|
||||
ea->EA_Gesture = EA_Gesture;
|
||||
ea->EA_Talk = EA_Talk;
|
||||
ea->EA_Attack = EA_Attack;
|
||||
ea->EA_Alt_Attack = EA_Alt_Attack;
|
||||
ea->EA_ForcePower = EA_ForcePower;
|
||||
ea->EA_Use = EA_Use;
|
||||
ea->EA_Respawn = EA_Respawn;
|
||||
ea->EA_Crouch = EA_Crouch;
|
||||
ea->EA_MoveUp = EA_MoveUp;
|
||||
ea->EA_MoveDown = EA_MoveDown;
|
||||
ea->EA_MoveForward = EA_MoveForward;
|
||||
ea->EA_MoveBack = EA_MoveBack;
|
||||
ea->EA_MoveLeft = EA_MoveLeft;
|
||||
ea->EA_MoveRight = EA_MoveRight;
|
||||
|
||||
ea->EA_SelectWeapon = EA_SelectWeapon;
|
||||
ea->EA_Jump = EA_Jump;
|
||||
ea->EA_DelayedJump = EA_DelayedJump;
|
||||
ea->EA_Move = EA_Move;
|
||||
ea->EA_View = EA_View;
|
||||
ea->EA_GetInput = EA_GetInput;
|
||||
ea->EA_EndRegular = EA_EndRegular;
|
||||
ea->EA_ResetInput = EA_ResetInput;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
Init_AI_Export
|
||||
============
|
||||
*/
|
||||
static void Init_AI_Export( ai_export_t *ai ) {
|
||||
//-----------------------------------
|
||||
// be_ai_char.h
|
||||
//-----------------------------------
|
||||
ai->BotLoadCharacter = BotLoadCharacter;
|
||||
ai->BotFreeCharacter = BotFreeCharacter;
|
||||
ai->Characteristic_Float = Characteristic_Float;
|
||||
ai->Characteristic_BFloat = Characteristic_BFloat;
|
||||
ai->Characteristic_Integer = Characteristic_Integer;
|
||||
ai->Characteristic_BInteger = Characteristic_BInteger;
|
||||
ai->Characteristic_String = Characteristic_String;
|
||||
//-----------------------------------
|
||||
// be_ai_chat.h
|
||||
//-----------------------------------
|
||||
ai->BotAllocChatState = BotAllocChatState;
|
||||
ai->BotFreeChatState = BotFreeChatState;
|
||||
ai->BotQueueConsoleMessage = BotQueueConsoleMessage;
|
||||
ai->BotRemoveConsoleMessage = BotRemoveConsoleMessage;
|
||||
ai->BotNextConsoleMessage = BotNextConsoleMessage;
|
||||
ai->BotNumConsoleMessages = BotNumConsoleMessages;
|
||||
ai->BotInitialChat = BotInitialChat;
|
||||
ai->BotNumInitialChats = BotNumInitialChats;
|
||||
ai->BotReplyChat = BotReplyChat;
|
||||
ai->BotChatLength = BotChatLength;
|
||||
ai->BotEnterChat = BotEnterChat;
|
||||
ai->BotGetChatMessage = BotGetChatMessage;
|
||||
ai->StringContains = StringContains;
|
||||
ai->BotFindMatch = BotFindMatch;
|
||||
ai->BotMatchVariable = BotMatchVariable;
|
||||
ai->UnifyWhiteSpaces = UnifyWhiteSpaces;
|
||||
ai->BotReplaceSynonyms = BotReplaceSynonyms;
|
||||
ai->BotLoadChatFile = BotLoadChatFile;
|
||||
ai->BotSetChatGender = BotSetChatGender;
|
||||
ai->BotSetChatName = BotSetChatName;
|
||||
//-----------------------------------
|
||||
// be_ai_goal.h
|
||||
//-----------------------------------
|
||||
ai->BotResetGoalState = BotResetGoalState;
|
||||
ai->BotResetAvoidGoals = BotResetAvoidGoals;
|
||||
ai->BotRemoveFromAvoidGoals = BotRemoveFromAvoidGoals;
|
||||
ai->BotPushGoal = BotPushGoal;
|
||||
ai->BotPopGoal = BotPopGoal;
|
||||
ai->BotEmptyGoalStack = BotEmptyGoalStack;
|
||||
ai->BotDumpAvoidGoals = BotDumpAvoidGoals;
|
||||
ai->BotDumpGoalStack = BotDumpGoalStack;
|
||||
ai->BotGoalName = BotGoalName;
|
||||
ai->BotGetTopGoal = BotGetTopGoal;
|
||||
ai->BotGetSecondGoal = BotGetSecondGoal;
|
||||
ai->BotChooseLTGItem = BotChooseLTGItem;
|
||||
ai->BotChooseNBGItem = BotChooseNBGItem;
|
||||
ai->BotTouchingGoal = BotTouchingGoal;
|
||||
ai->BotItemGoalInVisButNotVisible = BotItemGoalInVisButNotVisible;
|
||||
ai->BotGetLevelItemGoal = BotGetLevelItemGoal;
|
||||
ai->BotGetNextCampSpotGoal = BotGetNextCampSpotGoal;
|
||||
ai->BotGetMapLocationGoal = BotGetMapLocationGoal;
|
||||
ai->BotAvoidGoalTime = BotAvoidGoalTime;
|
||||
ai->BotSetAvoidGoalTime = BotSetAvoidGoalTime;
|
||||
ai->BotInitLevelItems = BotInitLevelItems;
|
||||
ai->BotUpdateEntityItems = BotUpdateEntityItems;
|
||||
ai->BotLoadItemWeights = BotLoadItemWeights;
|
||||
ai->BotFreeItemWeights = BotFreeItemWeights;
|
||||
ai->BotInterbreedGoalFuzzyLogic = BotInterbreedGoalFuzzyLogic;
|
||||
ai->BotSaveGoalFuzzyLogic = BotSaveGoalFuzzyLogic;
|
||||
ai->BotMutateGoalFuzzyLogic = BotMutateGoalFuzzyLogic;
|
||||
ai->BotAllocGoalState = BotAllocGoalState;
|
||||
ai->BotFreeGoalState = BotFreeGoalState;
|
||||
//-----------------------------------
|
||||
// be_ai_move.h
|
||||
//-----------------------------------
|
||||
ai->BotResetMoveState = BotResetMoveState;
|
||||
ai->BotMoveToGoal = BotMoveToGoal;
|
||||
ai->BotMoveInDirection = BotMoveInDirection;
|
||||
ai->BotResetAvoidReach = BotResetAvoidReach;
|
||||
ai->BotResetLastAvoidReach = BotResetLastAvoidReach;
|
||||
ai->BotReachabilityArea = BotReachabilityArea;
|
||||
ai->BotMovementViewTarget = BotMovementViewTarget;
|
||||
ai->BotPredictVisiblePosition = BotPredictVisiblePosition;
|
||||
ai->BotAllocMoveState = BotAllocMoveState;
|
||||
ai->BotFreeMoveState = BotFreeMoveState;
|
||||
ai->BotInitMoveState = BotInitMoveState;
|
||||
ai->BotAddAvoidSpot = BotAddAvoidSpot;
|
||||
//-----------------------------------
|
||||
// be_ai_weap.h
|
||||
//-----------------------------------
|
||||
ai->BotChooseBestFightWeapon = BotChooseBestFightWeapon;
|
||||
ai->BotGetWeaponInfo = BotGetWeaponInfo;
|
||||
ai->BotLoadWeaponWeights = BotLoadWeaponWeights;
|
||||
ai->BotAllocWeaponState = BotAllocWeaponState;
|
||||
ai->BotFreeWeaponState = BotFreeWeaponState;
|
||||
ai->BotResetWeaponState = BotResetWeaponState;
|
||||
//-----------------------------------
|
||||
// be_ai_gen.h
|
||||
//-----------------------------------
|
||||
ai->GeneticParentsAndChildSelection = GeneticParentsAndChildSelection;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
GetBotLibAPI
|
||||
============
|
||||
*/
|
||||
botlib_export_t *GetBotLibAPI(int apiVersion, botlib_import_t *import) {
|
||||
assert(import); // bk001129 - this wasn't set for base/
|
||||
botimport = *import;
|
||||
assert(botimport.Print); // bk001129 - pars pro toto
|
||||
|
||||
Com_Memset( &be_botlib_export, 0, sizeof( be_botlib_export ) );
|
||||
|
||||
if ( apiVersion != BOTLIB_API_VERSION ) {
|
||||
botimport.Print( PRT_ERROR, "Mismatched BOTLIB_API_VERSION: expected %i, got %i\n", BOTLIB_API_VERSION, apiVersion );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Init_AAS_Export(&be_botlib_export.aas);
|
||||
Init_EA_Export(&be_botlib_export.ea);
|
||||
Init_AI_Export(&be_botlib_export.ai);
|
||||
|
||||
be_botlib_export.BotLibSetup = Export_BotLibSetup;
|
||||
be_botlib_export.BotLibShutdown = Export_BotLibShutdown;
|
||||
be_botlib_export.BotLibVarSet = Export_BotLibVarSet;
|
||||
be_botlib_export.BotLibVarGet = Export_BotLibVarGet;
|
||||
|
||||
be_botlib_export.PC_AddGlobalDefine = PC_AddGlobalDefine;
|
||||
be_botlib_export.PC_LoadSourceHandle = PC_LoadSourceHandle;
|
||||
be_botlib_export.PC_FreeSourceHandle = PC_FreeSourceHandle;
|
||||
be_botlib_export.PC_ReadTokenHandle = PC_ReadTokenHandle;
|
||||
be_botlib_export.PC_SourceFileAndLine = PC_SourceFileAndLine;
|
||||
|
||||
be_botlib_export.BotLibStartFrame = Export_BotLibStartFrame;
|
||||
be_botlib_export.BotLibLoadMap = Export_BotLibLoadMap;
|
||||
be_botlib_export.BotLibUpdateEntity = Export_BotLibUpdateEntity;
|
||||
be_botlib_export.Test = BotExportTest;
|
||||
|
||||
return &be_botlib_export;
|
||||
}
|
40
CODEmp/botlib/be_interface.h
Normal file
40
CODEmp/botlib/be_interface.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: be_interface.h
|
||||
*
|
||||
* desc: botlib interface
|
||||
*
|
||||
* $Archive: /source/code/botlib/be_interface.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//#define DEBUG //debug code
|
||||
#define RANDOMIZE //randomize bot behaviour
|
||||
|
||||
//FIXME: get rid of this global structure
|
||||
typedef struct botlib_globals_s
|
||||
{
|
||||
int botlibsetup; //true when the bot library has been setup
|
||||
int maxentities; //maximum number of entities
|
||||
int maxclients; //maximum number of clients
|
||||
float time; //the global time
|
||||
#ifdef DEBUG
|
||||
qboolean debug; //true if debug is on
|
||||
int goalareanum;
|
||||
vec3_t goalorigin;
|
||||
int runai;
|
||||
#endif
|
||||
} botlib_globals_t;
|
||||
|
||||
|
||||
extern botlib_globals_t botlibglobals;
|
||||
extern botlib_import_t botimport;
|
||||
extern int bot_developer; //true if developer is on
|
||||
|
||||
//
|
||||
int Sys_MilliSeconds(void);
|
||||
|
400
CODEmp/botlib/botlib.dsp
Normal file
400
CODEmp/botlib/botlib.dsp
Normal file
|
@ -0,0 +1,400 @@
|
|||
# Microsoft Developer Studio Project File - Name="botlib" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=botlib - Win32 Release JK2
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "botlib.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "botlib.mak" CFG="botlib - Win32 Release JK2"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "botlib - Win32 Release JK2" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "botlib - Win32 Debug JK2" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "botlib - Win32 Final JK2" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""$/General/code/botlib", ACAAAAAA"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "botlib - Win32 Release JK2"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "botlib___Win32_Release_TA"
|
||||
# PROP BASE Intermediate_Dir "botlib___Win32_Release_TA"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "../Release"
|
||||
# PROP Intermediate_Dir "../Release/botlib"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /G6 /W4 /GX /O2 /D "WIN32" /D "NDebug" /D "_MBCS" /D "_LIB" /D "BOTLIB" /YX /FD /c
|
||||
# ADD CPP /nologo /G6 /W4 /GX /Zi /O2 /I "../game" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "BOTLIB" /D "_JK2" /YX /FD /c
|
||||
# SUBTRACT CPP /Fr
|
||||
# ADD BASE RSC /l 0x409 /d "NDebug"
|
||||
# ADD RSC /l 0x409 /d "NDebug"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "botlib - Win32 Debug JK2"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "botlib___Win32_Debug_TA"
|
||||
# PROP BASE Intermediate_Dir "botlib___Win32_Debug_TA"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "../Debug"
|
||||
# PROP Intermediate_Dir "../Debug/botlib"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /G5 /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_Debug" /D "_MBCS" /D "_LIB" /D "BOTLIB" /D "Debug" /FR /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /G6 /W3 /Gm /GX /ZI /Od /I "../game" /D "_DEBUG" /D "DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "BOTLIB" /D "_JK2" /FR /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_Debug"
|
||||
# ADD RSC /l 0x409 /d "_Debug"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "botlib - Win32 Final JK2"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "botlib___Win32_Final_JK2"
|
||||
# PROP BASE Intermediate_Dir "botlib___Win32_Final_JK2"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "../Final"
|
||||
# PROP Intermediate_Dir "../Final/botlib"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /G6 /W4 /GX /Zi /O2 /I "../jk2/game" /D "NDebug" /D "WIN32" /D "_MBCS" /D "_LIB" /D "BOTLIB" /D "_JK2" /YX /FD /c
|
||||
# SUBTRACT BASE CPP /Fr
|
||||
# ADD CPP /nologo /G6 /W4 /GX /O2 /I "../game" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "BOTLIB" /D "WIN32" /D "_JK2" /D "FINAL_BUILD" /YX /FD /c
|
||||
# SUBTRACT CPP /Fr
|
||||
# ADD BASE RSC /l 0x409 /d "NDebug"
|
||||
# ADD RSC /l 0x409 /d "NDebug"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "botlib - Win32 Release JK2"
|
||||
# Name "botlib - Win32 Debug JK2"
|
||||
# Name "botlib - Win32 Final JK2"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_bspq3.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_cluster.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_debug.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_entity.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_file.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_main.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_move.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_optimize.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_reach.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_route.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_routealt.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_sample.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_ai_char.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_ai_chat.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_ai_gen.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_ai_goal.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_ai_move.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_ai_weap.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_ai_weight.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_ea.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_interface.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\l_crc.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\l_libvar.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\l_log.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\l_memory.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\l_precomp.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\l_script.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\l_struct.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\aasfile.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\be_aas.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_bsp.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_cluster.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_debug.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_def.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_entity.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_file.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_funcs.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_main.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_move.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_optimize.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_reach.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_route.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_routealt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_aas_sample.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\be_ai_char.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\be_ai_chat.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\be_ai_gen.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\be_ai_goal.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\be_ai_move.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\be_ai_weap.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_ai_weight.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\be_ea.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\be_interface.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\botlib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\qcommon\cm_public.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\qcommon\disablewarnings.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\l_crc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\l_libvar.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\l_log.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\l_memory.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\l_precomp.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\l_script.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\l_struct.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\l_utils.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\q_shared.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\qcommon\qcommon.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\qcommon\qfiles.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\server\server.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\surfaceflags.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\qcommon\tags.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
134
CODEmp/botlib/l_crc.cpp
Normal file
134
CODEmp/botlib/l_crc.cpp
Normal file
|
@ -0,0 +1,134 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: l_crc.c
|
||||
*
|
||||
* desc: CRC calculation
|
||||
*
|
||||
* $Archive: /MissionPack/CODE/botlib/l_crc.c $
|
||||
* $Author: Raduffy $
|
||||
* $Revision: 1 $
|
||||
* $Modtime: 12/20/99 8:42p $
|
||||
* $Date: 3/08/00 11:28a $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "../game/botlib.h"
|
||||
#include "be_interface.h" //for botimport.Print
|
||||
|
||||
|
||||
// FIXME: byte swap?
|
||||
|
||||
// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
|
||||
// and the initial and final xor values shown below... in other words, the
|
||||
// CCITT standard CRC used by XMODEM
|
||||
|
||||
#define CRC_INIT_VALUE 0xffff
|
||||
#define CRC_XOR_VALUE 0x0000
|
||||
|
||||
unsigned short crctable[257] =
|
||||
{
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
|
||||
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
|
||||
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
|
||||
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
|
||||
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
|
||||
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
|
||||
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
|
||||
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
|
||||
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
|
||||
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
|
||||
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
|
||||
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
|
||||
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
|
||||
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
|
||||
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
|
||||
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
|
||||
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
|
||||
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
|
||||
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
|
||||
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
|
||||
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
|
||||
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
|
||||
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
|
||||
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void CRC_Init(unsigned short *crcvalue)
|
||||
{
|
||||
*crcvalue = CRC_INIT_VALUE;
|
||||
} //end of the function CRC_Init
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void CRC_ProcessByte(unsigned short *crcvalue, byte data)
|
||||
{
|
||||
*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
|
||||
} //end of the function CRC_ProcessByte
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
unsigned short CRC_Value(unsigned short crcvalue)
|
||||
{
|
||||
return crcvalue ^ CRC_XOR_VALUE;
|
||||
} //end of the function CRC_Value
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
unsigned short CRC_ProcessString(unsigned char *data, int length)
|
||||
{
|
||||
unsigned short crcvalue;
|
||||
int i, ind;
|
||||
|
||||
CRC_Init(&crcvalue);
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
ind = (crcvalue >> 8) ^ data[i];
|
||||
if (ind < 0 || ind > 256) ind = 0;
|
||||
crcvalue = (crcvalue << 8) ^ crctable[ind];
|
||||
} //end for
|
||||
return CRC_Value(crcvalue);
|
||||
} //end of the function CRC_ProcessString
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void CRC_ContinueProcessString(unsigned short *crc, char *data, int length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
*crc = (*crc << 8) ^ crctable[(*crc >> 8) ^ data[i]];
|
||||
} //end for
|
||||
} //end of the function CRC_ProcessString
|
16
CODEmp/botlib/l_crc.h
Normal file
16
CODEmp/botlib/l_crc.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
//===========================================================================
|
||||
//
|
||||
// Name: l_crc.h
|
||||
// Function: for CRC checks
|
||||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||||
// Last update: 1997-12-31
|
||||
// Tab Size: 3
|
||||
//===========================================================================
|
||||
|
||||
typedef unsigned short crc_t;
|
||||
|
||||
void CRC_Init(unsigned short *crcvalue);
|
||||
void CRC_ProcessByte(unsigned short *crcvalue, byte data);
|
||||
unsigned short CRC_Value(unsigned short crcvalue);
|
||||
unsigned short CRC_ProcessString(unsigned char *data, int length);
|
||||
void CRC_ContinueProcessString(unsigned short *crc, char *data, int length);
|
277
CODEmp/botlib/l_libvar.cpp
Normal file
277
CODEmp/botlib/l_libvar.cpp
Normal file
|
@ -0,0 +1,277 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: l_libvar.c
|
||||
*
|
||||
* desc: bot library variables
|
||||
*
|
||||
* $Archive: /MissionPack/code/botlib/l_libvar.c $
|
||||
* $Author: Zaphod $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 11/21/00 11:33a $
|
||||
* $Date: 11/21/00 11:49a $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "l_memory.h"
|
||||
#include "l_libvar.h"
|
||||
|
||||
//list with library variables
|
||||
libvar_t *libvarlist;
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
float LibVarStringValue(char *string)
|
||||
{
|
||||
int dotfound = 0;
|
||||
float value = 0;
|
||||
|
||||
while(*string)
|
||||
{
|
||||
if (*string < '0' || *string > '9')
|
||||
{
|
||||
if (dotfound || *string != '.')
|
||||
{
|
||||
return 0;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
dotfound = 10;
|
||||
string++;
|
||||
} //end if
|
||||
} //end if
|
||||
if (dotfound)
|
||||
{
|
||||
value = value + (float) (*string - '0') / (float) dotfound;
|
||||
dotfound *= 10;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
value = value * 10.0 + (float) (*string - '0');
|
||||
} //end else
|
||||
string++;
|
||||
} //end while
|
||||
return value;
|
||||
} //end of the function LibVarStringValue
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
libvar_t *LibVarAlloc(char *var_name)
|
||||
{
|
||||
libvar_t *v;
|
||||
|
||||
v = (libvar_t *) GetMemory(sizeof(libvar_t) + strlen(var_name) + 1);
|
||||
Com_Memset(v, 0, sizeof(libvar_t));
|
||||
v->name = (char *) v + sizeof(libvar_t);
|
||||
strcpy(v->name, var_name);
|
||||
//add the variable in the list
|
||||
v->next = libvarlist;
|
||||
libvarlist = v;
|
||||
return v;
|
||||
} //end of the function LibVarAlloc
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void LibVarDeAlloc(libvar_t *v)
|
||||
{
|
||||
if (v->string) FreeMemory(v->string);
|
||||
FreeMemory(v);
|
||||
} //end of the function LibVarDeAlloc
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void LibVarDeAllocAll(void)
|
||||
{
|
||||
libvar_t *v;
|
||||
|
||||
for (v = libvarlist; v; v = libvarlist)
|
||||
{
|
||||
libvarlist = libvarlist->next;
|
||||
LibVarDeAlloc(v);
|
||||
} //end for
|
||||
libvarlist = NULL;
|
||||
} //end of the function LibVarDeAllocAll
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
libvar_t *LibVarGet(char *var_name)
|
||||
{
|
||||
libvar_t *v;
|
||||
|
||||
for (v = libvarlist; v; v = v->next)
|
||||
{
|
||||
if (!Q_stricmp(v->name, var_name))
|
||||
{
|
||||
return v;
|
||||
} //end if
|
||||
} //end for
|
||||
return NULL;
|
||||
} //end of the function LibVarGet
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
char *LibVarGetString(char *var_name)
|
||||
{
|
||||
libvar_t *v;
|
||||
|
||||
v = LibVarGet(var_name);
|
||||
if (v)
|
||||
{
|
||||
return v->string;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
return "";
|
||||
} //end else
|
||||
} //end of the function LibVarGetString
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
float LibVarGetValue(char *var_name)
|
||||
{
|
||||
libvar_t *v;
|
||||
|
||||
v = LibVarGet(var_name);
|
||||
if (v)
|
||||
{
|
||||
return v->value;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
} //end else
|
||||
} //end of the function LibVarGetValue
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
libvar_t *LibVar(char *var_name, char *value)
|
||||
{
|
||||
libvar_t *v;
|
||||
v = LibVarGet(var_name);
|
||||
if (v) return v;
|
||||
//create new variable
|
||||
v = LibVarAlloc(var_name);
|
||||
//variable string
|
||||
v->string = (char *) GetMemory(strlen(value) + 1);
|
||||
strcpy(v->string, value);
|
||||
//the value
|
||||
v->value = LibVarStringValue(v->string);
|
||||
//variable is modified
|
||||
v->modified = qtrue;
|
||||
//
|
||||
return v;
|
||||
} //end of the function LibVar
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
char *LibVarString(char *var_name, char *value)
|
||||
{
|
||||
libvar_t *v;
|
||||
|
||||
v = LibVar(var_name, value);
|
||||
return v->string;
|
||||
} //end of the function LibVarString
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
float LibVarValue(char *var_name, char *value)
|
||||
{
|
||||
libvar_t *v;
|
||||
|
||||
v = LibVar(var_name, value);
|
||||
return v->value;
|
||||
} //end of the function LibVarValue
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void LibVarSet(char *var_name, char *value)
|
||||
{
|
||||
libvar_t *v;
|
||||
|
||||
v = LibVarGet(var_name);
|
||||
if (v)
|
||||
{
|
||||
FreeMemory(v->string);
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
v = LibVarAlloc(var_name);
|
||||
} //end else
|
||||
//variable string
|
||||
v->string = (char *) GetMemory(strlen(value) + 1);
|
||||
strcpy(v->string, value);
|
||||
//the value
|
||||
v->value = LibVarStringValue(v->string);
|
||||
//variable is modified
|
||||
v->modified = qtrue;
|
||||
} //end of the function LibVarSet
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
qboolean LibVarChanged(char *var_name)
|
||||
{
|
||||
libvar_t *v;
|
||||
|
||||
v = LibVarGet(var_name);
|
||||
if (v)
|
||||
{
|
||||
return v->modified;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
return qfalse;
|
||||
} //end else
|
||||
} //end of the function LibVarChanged
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void LibVarSetNotModified(char *var_name)
|
||||
{
|
||||
libvar_t *v;
|
||||
|
||||
v = LibVarGet(var_name);
|
||||
if (v)
|
||||
{
|
||||
v->modified = qfalse;
|
||||
} //end if
|
||||
} //end of the function LibVarSetNotModified
|
46
CODEmp/botlib/l_libvar.h
Normal file
46
CODEmp/botlib/l_libvar.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: l_libvar.h
|
||||
*
|
||||
* desc: botlib vars
|
||||
*
|
||||
* $Archive: /source/code/botlib/l_libvar.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//library variable
|
||||
typedef struct libvar_s
|
||||
{
|
||||
char *name;
|
||||
char *string;
|
||||
int flags;
|
||||
qboolean modified; // set each time the cvar is changed
|
||||
float value;
|
||||
struct libvar_s *next;
|
||||
} libvar_t;
|
||||
|
||||
//removes all library variables
|
||||
void LibVarDeAllocAll(void);
|
||||
//gets the library variable with the given name
|
||||
libvar_t *LibVarGet(char *var_name);
|
||||
//gets the string of the library variable with the given name
|
||||
char *LibVarGetString(char *var_name);
|
||||
//gets the value of the library variable with the given name
|
||||
float LibVarGetValue(char *var_name);
|
||||
//creates the library variable if not existing already and returns it
|
||||
libvar_t *LibVar(char *var_name, char *value);
|
||||
//creates the library variable if not existing already and returns the value
|
||||
float LibVarValue(char *var_name, char *value);
|
||||
//creates the library variable if not existing already and returns the value string
|
||||
char *LibVarString(char *var_name, char *value);
|
||||
//sets the library variable
|
||||
void LibVarSet(char *var_name, char *value);
|
||||
//returns true if the library variable has been modified
|
||||
qboolean LibVarChanged(char *var_name);
|
||||
//sets the library variable to unmodified
|
||||
void LibVarSetNotModified(char *var_name);
|
||||
|
152
CODEmp/botlib/l_log.cpp
Normal file
152
CODEmp/botlib/l_log.cpp
Normal file
|
@ -0,0 +1,152 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: l_log.c
|
||||
*
|
||||
* desc: log file
|
||||
*
|
||||
* $Archive: /MissionPack/CODE/botlib/l_log.c $
|
||||
* $Author: Raduffy $
|
||||
* $Revision: 1 $
|
||||
* $Modtime: 12/20/99 8:43p $
|
||||
* $Date: 3/08/00 11:28a $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "../game/botlib.h"
|
||||
#include "be_interface.h" //for botimport.Print
|
||||
#include "l_libvar.h"
|
||||
|
||||
#define MAX_LOGFILENAMESIZE 1024
|
||||
|
||||
typedef struct logfile_s
|
||||
{
|
||||
char filename[MAX_LOGFILENAMESIZE];
|
||||
FILE *fp;
|
||||
int numwrites;
|
||||
} logfile_t;
|
||||
|
||||
static logfile_t logfile;
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void Log_Open(char *filename)
|
||||
{
|
||||
if (!LibVarValue("log", "0")) return;
|
||||
if (!filename || !strlen(filename))
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "openlog <filename>\n");
|
||||
return;
|
||||
} //end if
|
||||
if (logfile.fp)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "log file %s is already opened\n", logfile.filename);
|
||||
return;
|
||||
} //end if
|
||||
logfile.fp = fopen(filename, "wb");
|
||||
if (!logfile.fp)
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "can't open the log file %s\n", filename);
|
||||
return;
|
||||
} //end if
|
||||
strncpy(logfile.filename, filename, MAX_LOGFILENAMESIZE);
|
||||
botimport.Print(PRT_MESSAGE, "Opened log %s\n", logfile.filename);
|
||||
} //end of the function Log_Create
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void Log_Close(void)
|
||||
{
|
||||
if (!logfile.fp) return;
|
||||
if (fclose(logfile.fp))
|
||||
{
|
||||
botimport.Print(PRT_ERROR, "can't close log file %s\n", logfile.filename);
|
||||
return;
|
||||
} //end if
|
||||
logfile.fp = NULL;
|
||||
botimport.Print(PRT_MESSAGE, "Closed log %s\n", logfile.filename);
|
||||
} //end of the function Log_Close
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void Log_Shutdown(void)
|
||||
{
|
||||
if (logfile.fp) Log_Close();
|
||||
} //end of the function Log_Shutdown
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void QDECL Log_Write(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (!logfile.fp) return;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(logfile.fp, fmt, ap);
|
||||
va_end(ap);
|
||||
//fprintf(logfile.fp, "\r\n");
|
||||
fflush(logfile.fp);
|
||||
} //end of the function Log_Write
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void QDECL Log_WriteTimeStamped(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (!logfile.fp) return;
|
||||
fprintf(logfile.fp, "%d %02d:%02d:%02d:%02d ",
|
||||
logfile.numwrites,
|
||||
(int) (botlibglobals.time / 60 / 60),
|
||||
(int) (botlibglobals.time / 60),
|
||||
(int) (botlibglobals.time),
|
||||
(int) ((int) (botlibglobals.time * 100)) -
|
||||
((int) botlibglobals.time) * 100);
|
||||
va_start(ap, fmt);
|
||||
vfprintf(logfile.fp, fmt, ap);
|
||||
va_end(ap);
|
||||
fprintf(logfile.fp, "\r\n");
|
||||
logfile.numwrites++;
|
||||
fflush(logfile.fp);
|
||||
} //end of the function Log_Write
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
FILE *Log_FilePointer(void)
|
||||
{
|
||||
return logfile.fp;
|
||||
} //end of the function Log_FilePointer
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void Log_Flush(void)
|
||||
{
|
||||
if (logfile.fp) fflush(logfile.fp);
|
||||
} //end of the function Log_Flush
|
||||
|
29
CODEmp/botlib/l_log.h
Normal file
29
CODEmp/botlib/l_log.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: l_log.h
|
||||
*
|
||||
* desc: log file
|
||||
*
|
||||
* $Archive: /source/code/botlib/l_log.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//open a log file
|
||||
void Log_Open(char *filename);
|
||||
//close the current log file
|
||||
void Log_Close(void);
|
||||
//close log file if present
|
||||
void Log_Shutdown(void);
|
||||
//write to the current opened log file
|
||||
void QDECL Log_Write(char *fmt, ...);
|
||||
//write to the current opened log file with a time stamp
|
||||
void QDECL Log_WriteTimeStamped(char *fmt, ...);
|
||||
//returns a pointer to the log file
|
||||
FILE *Log_FilePointer(void);
|
||||
//flush log file
|
||||
void Log_Flush(void);
|
||||
|
446
CODEmp/botlib/l_memory.cpp
Normal file
446
CODEmp/botlib/l_memory.cpp
Normal file
|
@ -0,0 +1,446 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: l_memory.c
|
||||
*
|
||||
* desc: memory allocation
|
||||
*
|
||||
* $Archive: /MissionPack/code/botlib/l_memory.c $
|
||||
* $Author: Ttimo $
|
||||
* $Revision: 6 $
|
||||
* $Modtime: 4/22/01 8:52a $
|
||||
* $Date: 4/22/01 8:52a $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "../game/botlib.h"
|
||||
#include "l_log.h"
|
||||
#include "be_interface.h"
|
||||
|
||||
//#define MEMDEBUG
|
||||
//#define MEMORYMANEGER
|
||||
|
||||
#define MEM_ID 0x12345678l
|
||||
#define HUNK_ID 0x87654321l
|
||||
|
||||
int allocatedmemory;
|
||||
int totalmemorysize;
|
||||
int numblocks;
|
||||
|
||||
#ifdef MEMORYMANEGER
|
||||
|
||||
typedef struct memoryblock_s
|
||||
{
|
||||
unsigned long int id;
|
||||
void *ptr;
|
||||
int size;
|
||||
#ifdef MEMDEBUG
|
||||
char *label;
|
||||
char *file;
|
||||
int line;
|
||||
#endif //MEMDEBUG
|
||||
struct memoryblock_s *prev, *next;
|
||||
} memoryblock_t;
|
||||
|
||||
memoryblock_t *memory;
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void LinkMemoryBlock(memoryblock_t *block)
|
||||
{
|
||||
block->prev = NULL;
|
||||
block->next = memory;
|
||||
if (memory) memory->prev = block;
|
||||
memory = block;
|
||||
} //end of the function LinkMemoryBlock
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void UnlinkMemoryBlock(memoryblock_t *block)
|
||||
{
|
||||
if (block->prev) block->prev->next = block->next;
|
||||
else memory = block->next;
|
||||
if (block->next) block->next->prev = block->prev;
|
||||
} //end of the function UnlinkMemoryBlock
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
#ifdef MEMDEBUG
|
||||
void *GetMemoryDebug(unsigned long size, char *label, char *file, int line)
|
||||
#else
|
||||
void *GetMemory(unsigned long size)
|
||||
#endif //MEMDEBUG
|
||||
{
|
||||
void *ptr;
|
||||
memoryblock_t *block;
|
||||
assert(botimport.GetMemory); // bk001129 - was NULL'ed
|
||||
ptr = botimport.GetMemory(size + sizeof(memoryblock_t));
|
||||
block = (memoryblock_t *) ptr;
|
||||
block->id = MEM_ID;
|
||||
block->ptr = (char *) ptr + sizeof(memoryblock_t);
|
||||
block->size = size + sizeof(memoryblock_t);
|
||||
#ifdef MEMDEBUG
|
||||
block->label = label;
|
||||
block->file = file;
|
||||
block->line = line;
|
||||
#endif //MEMDEBUG
|
||||
LinkMemoryBlock(block);
|
||||
allocatedmemory += block->size;
|
||||
totalmemorysize += block->size + sizeof(memoryblock_t);
|
||||
numblocks++;
|
||||
return block->ptr;
|
||||
} //end of the function GetMemoryDebug
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
#ifdef MEMDEBUG
|
||||
void *GetClearedMemoryDebug(unsigned long size, char *label, char *file, int line)
|
||||
#else
|
||||
void *GetClearedMemory(unsigned long size)
|
||||
#endif //MEMDEBUG
|
||||
{
|
||||
void *ptr;
|
||||
#ifdef MEMDEBUG
|
||||
ptr = GetMemoryDebug(size, label, file, line);
|
||||
#else
|
||||
ptr = GetMemory(size);
|
||||
#endif //MEMDEBUG
|
||||
Com_Memset(ptr, 0, size);
|
||||
return ptr;
|
||||
} //end of the function GetClearedMemory
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
#ifdef MEMDEBUG
|
||||
void *GetHunkMemoryDebug(unsigned long size, char *label, char *file, int line)
|
||||
#else
|
||||
void *GetHunkMemory(unsigned long size)
|
||||
#endif //MEMDEBUG
|
||||
{
|
||||
void *ptr;
|
||||
memoryblock_t *block;
|
||||
|
||||
ptr = botimport.HunkAlloc(size + sizeof(memoryblock_t));
|
||||
block = (memoryblock_t *) ptr;
|
||||
block->id = HUNK_ID;
|
||||
block->ptr = (char *) ptr + sizeof(memoryblock_t);
|
||||
block->size = size + sizeof(memoryblock_t);
|
||||
#ifdef MEMDEBUG
|
||||
block->label = label;
|
||||
block->file = file;
|
||||
block->line = line;
|
||||
#endif //MEMDEBUG
|
||||
LinkMemoryBlock(block);
|
||||
allocatedmemory += block->size;
|
||||
totalmemorysize += block->size + sizeof(memoryblock_t);
|
||||
numblocks++;
|
||||
return block->ptr;
|
||||
} //end of the function GetHunkMemoryDebug
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
#ifdef MEMDEBUG
|
||||
void *GetClearedHunkMemoryDebug(unsigned long size, char *label, char *file, int line)
|
||||
#else
|
||||
void *GetClearedHunkMemory(unsigned long size)
|
||||
#endif //MEMDEBUG
|
||||
{
|
||||
void *ptr;
|
||||
#ifdef MEMDEBUG
|
||||
ptr = GetHunkMemoryDebug(size, label, file, line);
|
||||
#else
|
||||
ptr = GetHunkMemory(size);
|
||||
#endif //MEMDEBUG
|
||||
Com_Memset(ptr, 0, size);
|
||||
return ptr;
|
||||
} //end of the function GetClearedHunkMemory
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
memoryblock_t *BlockFromPointer(void *ptr, char *str)
|
||||
{
|
||||
memoryblock_t *block;
|
||||
|
||||
if (!ptr)
|
||||
{
|
||||
#ifdef MEMDEBUG
|
||||
//char *crash = (char *) NULL;
|
||||
//crash[0] = 1;
|
||||
botimport.Print(PRT_FATAL, "%s: NULL pointer\n", str);
|
||||
#endif // MEMDEBUG
|
||||
return NULL;
|
||||
} //end if
|
||||
block = (memoryblock_t *) ((char *) ptr - sizeof(memoryblock_t));
|
||||
if (block->id != MEM_ID && block->id != HUNK_ID)
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "%s: invalid memory block\n", str);
|
||||
return NULL;
|
||||
} //end if
|
||||
if (block->ptr != ptr)
|
||||
{
|
||||
botimport.Print(PRT_FATAL, "%s: memory block pointer invalid\n", str);
|
||||
return NULL;
|
||||
} //end if
|
||||
return block;
|
||||
} //end of the function BlockFromPointer
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void FreeMemory(void *ptr)
|
||||
{
|
||||
memoryblock_t *block;
|
||||
|
||||
block = BlockFromPointer(ptr, "FreeMemory");
|
||||
if (!block) return;
|
||||
UnlinkMemoryBlock(block);
|
||||
allocatedmemory -= block->size;
|
||||
totalmemorysize -= block->size + sizeof(memoryblock_t);
|
||||
numblocks--;
|
||||
//
|
||||
if (block->id == MEM_ID)
|
||||
{
|
||||
botimport.FreeMemory(block);
|
||||
} //end if
|
||||
} //end of the function FreeMemory
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AvailableMemory(void)
|
||||
{
|
||||
return botimport.AvailableMemory();
|
||||
} //end of the function AvailableMemory
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int MemoryByteSize(void *ptr)
|
||||
{
|
||||
memoryblock_t *block;
|
||||
|
||||
block = BlockFromPointer(ptr, "MemoryByteSize");
|
||||
if (!block) return 0;
|
||||
return block->size;
|
||||
} //end of the function MemoryByteSize
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void PrintUsedMemorySize(void)
|
||||
{
|
||||
botimport.Print(PRT_MESSAGE, "total allocated memory: %d KB\n", allocatedmemory >> 10);
|
||||
botimport.Print(PRT_MESSAGE, "total botlib memory: %d KB\n", totalmemorysize >> 10);
|
||||
botimport.Print(PRT_MESSAGE, "total memory blocks: %d\n", numblocks);
|
||||
} //end of the function PrintUsedMemorySize
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void PrintMemoryLabels(void)
|
||||
{
|
||||
memoryblock_t *block;
|
||||
int i;
|
||||
|
||||
PrintUsedMemorySize();
|
||||
i = 0;
|
||||
Log_Write("============= Botlib memory log ==============\r\n");
|
||||
Log_Write("\r\n");
|
||||
for (block = memory; block; block = block->next)
|
||||
{
|
||||
#ifdef MEMDEBUG
|
||||
if (block->id == HUNK_ID)
|
||||
{
|
||||
Log_Write("%6d, hunk %p, %8d: %24s line %6d: %s\r\n", i, block->ptr, block->size, block->file, block->line, block->label);
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
Log_Write("%6d, %p, %8d: %24s line %6d: %s\r\n", i, block->ptr, block->size, block->file, block->line, block->label);
|
||||
} //end else
|
||||
#endif //MEMDEBUG
|
||||
i++;
|
||||
} //end for
|
||||
} //end of the function PrintMemoryLabels
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void DumpMemory(void)
|
||||
{
|
||||
memoryblock_t *block;
|
||||
|
||||
for (block = memory; block; block = memory)
|
||||
{
|
||||
FreeMemory(block->ptr);
|
||||
} //end for
|
||||
totalmemorysize = 0;
|
||||
allocatedmemory = 0;
|
||||
} //end of the function DumpMemory
|
||||
|
||||
#else
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
#ifdef MEMDEBUG
|
||||
void *GetMemoryDebug(unsigned long size, char *label, char *file, int line)
|
||||
#else
|
||||
void *GetMemory(unsigned long size)
|
||||
#endif //MEMDEBUG
|
||||
{
|
||||
void *ptr;
|
||||
unsigned long int *memid;
|
||||
|
||||
ptr = botimport.GetMemory(size + sizeof(unsigned long int));
|
||||
if (!ptr) return NULL;
|
||||
memid = (unsigned long int *) ptr;
|
||||
*memid = MEM_ID;
|
||||
return (unsigned long int *) ((char *) ptr + sizeof(unsigned long int));
|
||||
} //end of the function GetMemory
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
#ifdef MEMDEBUG
|
||||
void *GetClearedMemoryDebug(unsigned long size, char *label, char *file, int line)
|
||||
#else
|
||||
void *GetClearedMemory(unsigned long size)
|
||||
#endif //MEMDEBUG
|
||||
{
|
||||
void *ptr;
|
||||
#ifdef MEMDEBUG
|
||||
ptr = GetMemoryDebug(size, label, file, line);
|
||||
#else
|
||||
ptr = GetMemory(size);
|
||||
#endif //MEMDEBUG
|
||||
Com_Memset(ptr, 0, size);
|
||||
return ptr;
|
||||
} //end of the function GetClearedMemory
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
#ifdef MEMDEBUG
|
||||
void *GetHunkMemoryDebug(unsigned long size, char *label, char *file, int line)
|
||||
#else
|
||||
void *GetHunkMemory(unsigned long size)
|
||||
#endif //MEMDEBUG
|
||||
{
|
||||
void *ptr;
|
||||
unsigned long int *memid;
|
||||
|
||||
ptr = botimport.HunkAlloc(size + sizeof(unsigned long int));
|
||||
if (!ptr) return NULL;
|
||||
memid = (unsigned long int *) ptr;
|
||||
*memid = HUNK_ID;
|
||||
return (unsigned long int *) ((char *) ptr + sizeof(unsigned long int));
|
||||
} //end of the function GetHunkMemory
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
#ifdef MEMDEBUG
|
||||
void *GetClearedHunkMemoryDebug(unsigned long size, char *label, char *file, int line)
|
||||
#else
|
||||
void *GetClearedHunkMemory(unsigned long size)
|
||||
#endif //MEMDEBUG
|
||||
{
|
||||
void *ptr;
|
||||
#ifdef MEMDEBUG
|
||||
ptr = GetHunkMemoryDebug(size, label, file, line);
|
||||
#else
|
||||
ptr = GetHunkMemory(size);
|
||||
#endif //MEMDEBUG
|
||||
Com_Memset(ptr, 0, size);
|
||||
return ptr;
|
||||
} //end of the function GetClearedHunkMemory
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void FreeMemory(void *ptr)
|
||||
{
|
||||
unsigned long int *memid;
|
||||
|
||||
memid = (unsigned long int *) ((char *) ptr - sizeof(unsigned long int));
|
||||
|
||||
if (*memid == MEM_ID)
|
||||
{
|
||||
botimport.FreeMemory(memid);
|
||||
} //end if
|
||||
} //end of the function FreeMemory
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int AvailableMemory(void)
|
||||
{
|
||||
return botimport.AvailableMemory();
|
||||
} //end of the function AvailableMemory
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void PrintUsedMemorySize(void)
|
||||
{
|
||||
} //end of the function PrintUsedMemorySize
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
void PrintMemoryLabels(void)
|
||||
{
|
||||
} //end of the function PrintMemoryLabels
|
||||
|
||||
#endif
|
59
CODEmp/botlib/l_memory.h
Normal file
59
CODEmp/botlib/l_memory.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: l_memory.h
|
||||
*
|
||||
* desc: memory management
|
||||
*
|
||||
* $Archive: /source/code/botlib/l_memory.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//#define MEMDEBUG
|
||||
|
||||
#ifdef MEMDEBUG
|
||||
#define GetMemory(size) GetMemoryDebug(size, #size, __FILE__, __LINE__);
|
||||
#define GetClearedMemory(size) GetClearedMemoryDebug(size, #size, __FILE__, __LINE__);
|
||||
//allocate a memory block of the given size
|
||||
void *GetMemoryDebug(unsigned long size, char *label, char *file, int line);
|
||||
//allocate a memory block of the given size and clear it
|
||||
void *GetClearedMemoryDebug(unsigned long size, char *label, char *file, int line);
|
||||
//
|
||||
#define GetHunkMemory(size) GetHunkMemoryDebug(size, #size, __FILE__, __LINE__);
|
||||
#define GetClearedHunkMemory(size) GetClearedHunkMemoryDebug(size, #size, __FILE__, __LINE__);
|
||||
//allocate a memory block of the given size
|
||||
void *GetHunkMemoryDebug(unsigned long size, char *label, char *file, int line);
|
||||
//allocate a memory block of the given size and clear it
|
||||
void *GetClearedHunkMemoryDebug(unsigned long size, char *label, char *file, int line);
|
||||
#else
|
||||
//allocate a memory block of the given size
|
||||
void *GetMemory(unsigned long size);
|
||||
//allocate a memory block of the given size and clear it
|
||||
void *GetClearedMemory(unsigned long size);
|
||||
//
|
||||
#ifdef BSPC
|
||||
#define GetHunkMemory GetMemory
|
||||
#define GetClearedHunkMemory GetClearedMemory
|
||||
#else
|
||||
//allocate a memory block of the given size
|
||||
void *GetHunkMemory(unsigned long size);
|
||||
//allocate a memory block of the given size and clear it
|
||||
void *GetClearedHunkMemory(unsigned long size);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//free the given memory block
|
||||
void FreeMemory(void *ptr);
|
||||
//returns the amount available memory
|
||||
int AvailableMemory(void);
|
||||
//prints the total used memory size
|
||||
void PrintUsedMemorySize(void);
|
||||
//print all memory blocks with label
|
||||
void PrintMemoryLabels(void);
|
||||
//returns the size of the memory block in bytes
|
||||
int MemoryByteSize(void *ptr);
|
||||
//free all allocated memory
|
||||
void DumpMemory(void);
|
3225
CODEmp/botlib/l_precomp.cpp
Normal file
3225
CODEmp/botlib/l_precomp.cpp
Normal file
File diff suppressed because it is too large
Load diff
163
CODEmp/botlib/l_precomp.h
Normal file
163
CODEmp/botlib/l_precomp.h
Normal file
|
@ -0,0 +1,163 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: l_precomp.h
|
||||
*
|
||||
* desc: pre compiler
|
||||
*
|
||||
* $Archive: /source/code/botlib/l_precomp.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH MAX_QPATH
|
||||
#endif
|
||||
|
||||
#ifndef PATH_SEPERATORSTR
|
||||
#if defined(WIN32)|defined(_WIN32)|defined(__NT__)|defined(__WINDOWS__)|defined(__WINDOWS_386__)
|
||||
#define PATHSEPERATOR_STR "\\"
|
||||
#else
|
||||
#define PATHSEPERATOR_STR "/"
|
||||
#endif
|
||||
#endif
|
||||
#ifndef PATH_SEPERATORCHAR
|
||||
#if defined(WIN32)|defined(_WIN32)|defined(__NT__)|defined(__WINDOWS__)|defined(__WINDOWS_386__)
|
||||
#define PATHSEPERATOR_CHAR '\\'
|
||||
#else
|
||||
#define PATHSEPERATOR_CHAR '/'
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(BSPC) && !defined(QDECL)
|
||||
#define QDECL
|
||||
#endif
|
||||
|
||||
|
||||
#define DEFINE_FIXED 0x0001
|
||||
|
||||
#define BUILTIN_LINE 1
|
||||
#define BUILTIN_FILE 2
|
||||
#define BUILTIN_DATE 3
|
||||
#define BUILTIN_TIME 4
|
||||
#define BUILTIN_STDC 5
|
||||
|
||||
#define INDENT_IF 0x0001
|
||||
#define INDENT_ELSE 0x0002
|
||||
#define INDENT_ELIF 0x0004
|
||||
#define INDENT_IFDEF 0x0008
|
||||
#define INDENT_IFNDEF 0x0010
|
||||
|
||||
//macro definitions
|
||||
typedef struct define_s
|
||||
{
|
||||
char *name; //define name
|
||||
int flags; //define flags
|
||||
int builtin; // > 0 if builtin define
|
||||
int numparms; //number of define parameters
|
||||
token_t *parms; //define parameters
|
||||
token_t *tokens; //macro tokens (possibly containing parm tokens)
|
||||
struct define_s *next; //next defined macro in a list
|
||||
struct define_s *hashnext; //next define in the hash chain
|
||||
} define_t;
|
||||
|
||||
//indents
|
||||
//used for conditional compilation directives:
|
||||
//#if, #else, #elif, #ifdef, #ifndef
|
||||
typedef struct indent_s
|
||||
{
|
||||
int type; //indent type
|
||||
int skip; //true if skipping current indent
|
||||
script_t *script; //script the indent was in
|
||||
struct indent_s *next; //next indent on the indent stack
|
||||
} indent_t;
|
||||
|
||||
//source file
|
||||
typedef struct source_s
|
||||
{
|
||||
char filename[1024]; //file name of the script
|
||||
char includepath[1024]; //path to include files
|
||||
punctuation_t *punctuations; //punctuations to use
|
||||
script_t *scriptstack; //stack with scripts of the source
|
||||
token_t *tokens; //tokens to read first
|
||||
define_t *defines; //list with macro definitions
|
||||
define_t **definehash; //hash chain with defines
|
||||
indent_t *indentstack; //stack with indents
|
||||
int skip; // > 0 if skipping conditional code
|
||||
token_t token; //last read token
|
||||
} source_t;
|
||||
|
||||
|
||||
//read a token from the source
|
||||
int PC_ReadToken(source_t *source, token_t *token);
|
||||
//expect a certain token
|
||||
int PC_ExpectTokenString(source_t *source, char *string);
|
||||
//expect a certain token type
|
||||
int PC_ExpectTokenType(source_t *source, int type, int subtype, token_t *token);
|
||||
//expect a token
|
||||
int PC_ExpectAnyToken(source_t *source, token_t *token);
|
||||
//returns true when the token is available
|
||||
int PC_CheckTokenString(source_t *source, char *string);
|
||||
//returns true an reads the token when a token with the given type is available
|
||||
int PC_CheckTokenType(source_t *source, int type, int subtype, token_t *token);
|
||||
//skip tokens until the given token string is read
|
||||
int PC_SkipUntilString(source_t *source, char *string);
|
||||
//unread the last token read from the script
|
||||
void PC_UnreadLastToken(source_t *source);
|
||||
//unread the given token
|
||||
void PC_UnreadToken(source_t *source, token_t *token);
|
||||
//read a token only if on the same line, lines are concatenated with a slash
|
||||
int PC_ReadLine(source_t *source, token_t *token);
|
||||
//returns true if there was a white space in front of the token
|
||||
int PC_WhiteSpaceBeforeToken(token_t *token);
|
||||
//add a define to the source
|
||||
int PC_AddDefine(source_t *source, char *string);
|
||||
//add a globals define that will be added to all opened sources
|
||||
int PC_AddGlobalDefine(char *string);
|
||||
//remove the given global define
|
||||
int PC_RemoveGlobalDefine(char *name);
|
||||
//remove all globals defines
|
||||
void PC_RemoveAllGlobalDefines(void);
|
||||
//add builtin defines
|
||||
void PC_AddBuiltinDefines(source_t *source);
|
||||
//set the source include path
|
||||
void PC_SetIncludePath(source_t *source, char *path);
|
||||
//set the punction set
|
||||
void PC_SetPunctuations(source_t *source, punctuation_t *p);
|
||||
//set the base folder to load files from
|
||||
void PC_SetBaseFolder(char *path);
|
||||
//load a source file
|
||||
source_t *LoadSourceFile(const char *filename);
|
||||
//load a source from memory
|
||||
source_t *LoadSourceMemory(char *ptr, int length, char *name);
|
||||
//free the given source
|
||||
void FreeSource(source_t *source);
|
||||
//print a source error
|
||||
void QDECL SourceError(source_t *source, char *str, ...);
|
||||
//print a source warning
|
||||
void QDECL SourceWarning(source_t *source, char *str, ...);
|
||||
|
||||
#ifdef BSPC
|
||||
// some of BSPC source does include game/q_shared.h and some does not
|
||||
// we define pc_token_s pc_token_t if needed (yes, it's ugly)
|
||||
#ifndef __Q_SHARED_H
|
||||
#define MAX_TOKENLENGTH 1024
|
||||
typedef struct pc_token_s
|
||||
{
|
||||
int type;
|
||||
int subtype;
|
||||
int intvalue;
|
||||
float floatvalue;
|
||||
char string[MAX_TOKENLENGTH];
|
||||
} pc_token_t;
|
||||
#endif //!_Q_SHARED_H
|
||||
#endif //BSPC
|
||||
|
||||
//
|
||||
int PC_LoadSourceHandle(const char *filename);
|
||||
int PC_FreeSourceHandle(int handle);
|
||||
int PC_ReadTokenHandle(int handle, pc_token_t *pc_token);
|
||||
int PC_SourceFileAndLine(int handle, char *filename, int *line);
|
||||
void PC_CheckOpenSourceHandles(void);
|
1418
CODEmp/botlib/l_script.cpp
Normal file
1418
CODEmp/botlib/l_script.cpp
Normal file
File diff suppressed because it is too large
Load diff
232
CODEmp/botlib/l_script.h
Normal file
232
CODEmp/botlib/l_script.h
Normal file
|
@ -0,0 +1,232 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: l_script.h
|
||||
*
|
||||
* desc: lexicographical parser
|
||||
*
|
||||
* $Archive: /source/code/botlib/l_script.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//undef if binary numbers of the form 0b... or 0B... are not allowed
|
||||
#define BINARYNUMBERS
|
||||
//undef if not using the token.intvalue and token.floatvalue
|
||||
#define NUMBERVALUE
|
||||
//use dollar sign also as punctuation
|
||||
#define DOLLAR
|
||||
|
||||
//maximum token length
|
||||
#define MAX_TOKEN 1024
|
||||
|
||||
#if defined(BSPC) && !defined(QDECL)
|
||||
#define QDECL
|
||||
#endif
|
||||
|
||||
|
||||
//script flags
|
||||
#define SCFL_NOERRORS 0x0001
|
||||
#define SCFL_NOWARNINGS 0x0002
|
||||
#define SCFL_NOSTRINGWHITESPACES 0x0004
|
||||
#define SCFL_NOSTRINGESCAPECHARS 0x0008
|
||||
#define SCFL_PRIMITIVE 0x0010
|
||||
#define SCFL_NOBINARYNUMBERS 0x0020
|
||||
#define SCFL_NONUMBERVALUES 0x0040
|
||||
|
||||
//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
|
||||
|
||||
//string sub type
|
||||
//---------------
|
||||
// the length of the string
|
||||
//literal sub type
|
||||
//----------------
|
||||
// the ASCII code of the literal
|
||||
//number sub type
|
||||
//---------------
|
||||
#define TT_DECIMAL 0x0008 // decimal number
|
||||
#define TT_HEX 0x0100 // hexadecimal number
|
||||
#define TT_OCTAL 0x0200 // octal number
|
||||
#ifdef BINARYNUMBERS
|
||||
#define TT_BINARY 0x0400 // binary number
|
||||
#endif //BINARYNUMBERS
|
||||
#define TT_FLOAT 0x0800 // floating point number
|
||||
#define TT_INTEGER 0x1000 // integer number
|
||||
#define TT_LONG 0x2000 // long number
|
||||
#define TT_UNSIGNED 0x4000 // unsigned number
|
||||
//punctuation sub type
|
||||
//--------------------
|
||||
#define P_RSHIFT_ASSIGN 1
|
||||
#define P_LSHIFT_ASSIGN 2
|
||||
#define P_PARMS 3
|
||||
#define P_PRECOMPMERGE 4
|
||||
|
||||
#define P_LOGIC_AND 5
|
||||
#define P_LOGIC_OR 6
|
||||
#define P_LOGIC_GEQ 7
|
||||
#define P_LOGIC_LEQ 8
|
||||
#define P_LOGIC_EQ 9
|
||||
#define P_LOGIC_UNEQ 10
|
||||
|
||||
#define P_MUL_ASSIGN 11
|
||||
#define P_DIV_ASSIGN 12
|
||||
#define P_MOD_ASSIGN 13
|
||||
#define P_ADD_ASSIGN 14
|
||||
#define P_SUB_ASSIGN 15
|
||||
#define P_INC 16
|
||||
#define P_DEC 17
|
||||
|
||||
#define P_BIN_AND_ASSIGN 18
|
||||
#define P_BIN_OR_ASSIGN 19
|
||||
#define P_BIN_XOR_ASSIGN 20
|
||||
#define P_RSHIFT 21
|
||||
#define P_LSHIFT 22
|
||||
|
||||
#define P_POINTERREF 23
|
||||
#define P_CPP1 24
|
||||
#define P_CPP2 25
|
||||
#define P_MUL 26
|
||||
#define P_DIV 27
|
||||
#define P_MOD 28
|
||||
#define P_ADD 29
|
||||
#define P_SUB 30
|
||||
#define P_ASSIGN 31
|
||||
|
||||
#define P_BIN_AND 32
|
||||
#define P_BIN_OR 33
|
||||
#define P_BIN_XOR 34
|
||||
#define P_BIN_NOT 35
|
||||
|
||||
#define P_LOGIC_NOT 36
|
||||
#define P_LOGIC_GREATER 37
|
||||
#define P_LOGIC_LESS 38
|
||||
|
||||
#define P_REF 39
|
||||
#define P_COMMA 40
|
||||
#define P_SEMICOLON 41
|
||||
#define P_COLON 42
|
||||
#define P_QUESTIONMARK 43
|
||||
|
||||
#define P_PARENTHESESOPEN 44
|
||||
#define P_PARENTHESESCLOSE 45
|
||||
#define P_BRACEOPEN 46
|
||||
#define P_BRACECLOSE 47
|
||||
#define P_SQBRACKETOPEN 48
|
||||
#define P_SQBRACKETCLOSE 49
|
||||
#define P_BACKSLASH 50
|
||||
|
||||
#define P_PRECOMP 51
|
||||
#define P_DOLLAR 52
|
||||
#define P_ATSIGN 53
|
||||
//name sub type
|
||||
//-------------
|
||||
// the length of the name
|
||||
|
||||
//punctuation
|
||||
typedef struct punctuation_s
|
||||
{
|
||||
char *p; //punctuation character(s)
|
||||
int n; //punctuation indication
|
||||
struct punctuation_s *next; //next punctuation
|
||||
} punctuation_t;
|
||||
|
||||
//token
|
||||
typedef struct token_s
|
||||
{
|
||||
char string[MAX_TOKEN]; //available token
|
||||
int type; //last read token type
|
||||
int subtype; //last read token sub type
|
||||
#ifdef NUMBERVALUE
|
||||
unsigned long int intvalue; //integer value
|
||||
long double floatvalue; //floating point value
|
||||
#endif //NUMBERVALUE
|
||||
char *whitespace_p; //start of white space before token
|
||||
char *endwhitespace_p; //start of white space before token
|
||||
int line; //line the token was on
|
||||
int linescrossed; //lines crossed in white space
|
||||
struct token_s *next; //next token in chain
|
||||
} token_t;
|
||||
|
||||
//script file
|
||||
typedef struct script_s
|
||||
{
|
||||
char filename[1024]; //file name of the script
|
||||
char *buffer; //buffer containing the script
|
||||
char *script_p; //current pointer in the script
|
||||
char *end_p; //pointer to the end of the script
|
||||
char *lastscript_p; //script pointer before reading token
|
||||
char *whitespace_p; //begin of the white space
|
||||
char *endwhitespace_p; //end of the white space
|
||||
int length; //length of the script in bytes
|
||||
int line; //current line in script
|
||||
int lastline; //line before reading token
|
||||
int tokenavailable; //set by UnreadLastToken
|
||||
int flags; //several script flags
|
||||
punctuation_t *punctuations; //the punctuations used in the script
|
||||
punctuation_t **punctuationtable;
|
||||
token_t token; //available token
|
||||
struct script_s *next; //next script in a chain
|
||||
} script_t;
|
||||
|
||||
//read a token from the script
|
||||
int PS_ReadToken(script_t *script, token_t *token);
|
||||
//expect a certain token
|
||||
int PS_ExpectTokenString(script_t *script, char *string);
|
||||
//expect a certain token type
|
||||
int PS_ExpectTokenType(script_t *script, int type, int subtype, token_t *token);
|
||||
//expect a token
|
||||
int PS_ExpectAnyToken(script_t *script, token_t *token);
|
||||
//returns true when the token is available
|
||||
int PS_CheckTokenString(script_t *script, char *string);
|
||||
//returns true an reads the token when a token with the given type is available
|
||||
int PS_CheckTokenType(script_t *script, int type, int subtype, token_t *token);
|
||||
//skip tokens until the given token string is read
|
||||
int PS_SkipUntilString(script_t *script, char *string);
|
||||
//unread the last token read from the script
|
||||
void PS_UnreadLastToken(script_t *script);
|
||||
//unread the given token
|
||||
void PS_UnreadToken(script_t *script, token_t *token);
|
||||
//returns the next character of the read white space, returns NULL if none
|
||||
char PS_NextWhiteSpaceChar(script_t *script);
|
||||
//remove any leading and trailing double quotes from the token
|
||||
void StripDoubleQuotes(char *string);
|
||||
//remove any leading and trailing single quotes from the token
|
||||
void StripSingleQuotes(char *string);
|
||||
//read a possible signed integer
|
||||
signed long int ReadSignedInt(script_t *script);
|
||||
//read a possible signed floating point number
|
||||
long double ReadSignedFloat(script_t *script);
|
||||
//set an array with punctuations, NULL restores default C/C++ set
|
||||
void SetScriptPunctuations(script_t *script, punctuation_t *p);
|
||||
//set script flags
|
||||
void SetScriptFlags(script_t *script, int flags);
|
||||
//get script flags
|
||||
int GetScriptFlags(script_t *script);
|
||||
//reset a script
|
||||
void ResetScript(script_t *script);
|
||||
//returns true if at the end of the script
|
||||
int EndOfScript(script_t *script);
|
||||
//returns a pointer to the punctuation with the given number
|
||||
char *PunctuationFromNum(script_t *script, int num);
|
||||
//load a script from the given file at the given offset with the given length
|
||||
script_t *LoadScriptFile(const char *filename);
|
||||
//load a script from the given memory with the given length
|
||||
script_t *LoadScriptMemory(char *ptr, int length, char *name);
|
||||
//free a script
|
||||
void FreeScript(script_t *script);
|
||||
//set the base folder to load files from
|
||||
void PS_SetBaseFolder(char *path);
|
||||
//print a script error with filename and line number
|
||||
void QDECL ScriptError(script_t *script, char *str, ...);
|
||||
//print a script warning with filename and line number
|
||||
void QDECL ScriptWarning(script_t *script, char *str, ...);
|
||||
|
||||
|
||||
|
445
CODEmp/botlib/l_struct.cpp
Normal file
445
CODEmp/botlib/l_struct.cpp
Normal file
|
@ -0,0 +1,445 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: l_struct.c
|
||||
*
|
||||
* desc: structure reading / writing
|
||||
*
|
||||
* $Archive: /MissionPack/CODE/botlib/l_struct.c $
|
||||
* $Author: Raduffy $
|
||||
* $Revision: 1 $
|
||||
* $Modtime: 12/20/99 8:43p $
|
||||
* $Date: 3/08/00 11:28a $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef BOTLIB
|
||||
#include "../game/q_shared.h"
|
||||
#include "../game/botlib.h" //for the include of be_interface.h
|
||||
#include "l_script.h"
|
||||
#include "l_precomp.h"
|
||||
#include "l_struct.h"
|
||||
#include "l_utils.h"
|
||||
#include "be_interface.h"
|
||||
#endif //BOTLIB
|
||||
|
||||
#ifdef BSPC
|
||||
//include files for usage in the BSP Converter
|
||||
#include "../bspc/qbsp.h"
|
||||
#include "../bspc/l_log.h"
|
||||
#include "../bspc/l_mem.h"
|
||||
#include "l_precomp.h"
|
||||
#include "l_struct.h"
|
||||
|
||||
#define qtrue true
|
||||
#define qfalse false
|
||||
#endif //BSPC
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
fielddef_t *FindField(fielddef_t *defs, char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; defs[i].name; i++)
|
||||
{
|
||||
if (!strcmp(defs[i].name, name)) return &defs[i];
|
||||
} //end for
|
||||
return NULL;
|
||||
} //end of the function FindField
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
qboolean ReadNumber(source_t *source, fielddef_t *fd, void *p)
|
||||
{
|
||||
token_t token;
|
||||
int negative = qfalse;
|
||||
long int intval, intmin = 0, intmax = 0;
|
||||
double floatval;
|
||||
|
||||
if (!PC_ExpectAnyToken(source, &token)) return (qboolean)0;
|
||||
|
||||
//check for minus sign
|
||||
if (token.type == TT_PUNCTUATION)
|
||||
{
|
||||
if (fd->type & FT_UNSIGNED)
|
||||
{
|
||||
SourceError(source, "expected unsigned value, found %s", token.string);
|
||||
return (qboolean)0;
|
||||
} //end if
|
||||
//if not a minus sign
|
||||
if (strcmp(token.string, "-"))
|
||||
{
|
||||
SourceError(source, "unexpected punctuation %s", token.string);
|
||||
return (qboolean)0;
|
||||
} //end if
|
||||
negative = qtrue;
|
||||
//read the number
|
||||
if (!PC_ExpectAnyToken(source, &token)) return (qboolean)0;
|
||||
} //end if
|
||||
//check if it is a number
|
||||
if (token.type != TT_NUMBER)
|
||||
{
|
||||
SourceError(source, "expected number, found %s", token.string);
|
||||
return (qboolean)0;
|
||||
} //end if
|
||||
//check for a float value
|
||||
if (token.subtype & TT_FLOAT)
|
||||
{
|
||||
if ((fd->type & FT_TYPE) != FT_FLOAT)
|
||||
{
|
||||
SourceError(source, "unexpected float");
|
||||
return (qboolean)0;
|
||||
} //end if
|
||||
floatval = token.floatvalue;
|
||||
if (negative) floatval = -floatval;
|
||||
if (fd->type & FT_BOUNDED)
|
||||
{
|
||||
if (floatval < fd->floatmin || floatval > fd->floatmax)
|
||||
{
|
||||
SourceError(source, "float out of range [%f, %f]", fd->floatmin, fd->floatmax);
|
||||
return (qboolean)0;
|
||||
} //end if
|
||||
} //end if
|
||||
*(float *) p = (float) floatval;
|
||||
return (qboolean)1;
|
||||
} //end if
|
||||
//
|
||||
intval = token.intvalue;
|
||||
if (negative) intval = -intval;
|
||||
//check bounds
|
||||
if ((fd->type & FT_TYPE) == FT_CHAR)
|
||||
{
|
||||
if (fd->type & FT_UNSIGNED) {intmin = 0; intmax = 255;}
|
||||
else {intmin = -128; intmax = 127;}
|
||||
} //end if
|
||||
if ((fd->type & FT_TYPE) == FT_INT)
|
||||
{
|
||||
if (fd->type & FT_UNSIGNED) {intmin = 0; intmax = 65535;}
|
||||
else {intmin = -32768; intmax = 32767;}
|
||||
} //end else if
|
||||
if ((fd->type & FT_TYPE) == FT_CHAR || (fd->type & FT_TYPE) == FT_INT)
|
||||
{
|
||||
if (fd->type & FT_BOUNDED)
|
||||
{
|
||||
intmin = Maximum(intmin, fd->floatmin);
|
||||
intmax = Minimum(intmax, fd->floatmax);
|
||||
} //end if
|
||||
if (intval < intmin || intval > intmax)
|
||||
{
|
||||
SourceError(source, "value %d out of range [%d, %d]", intval, intmin, intmax);
|
||||
return (qboolean)0;
|
||||
} //end if
|
||||
} //end if
|
||||
else if ((fd->type & FT_TYPE) == FT_FLOAT)
|
||||
{
|
||||
if (fd->type & FT_BOUNDED)
|
||||
{
|
||||
if (intval < fd->floatmin || intval > fd->floatmax)
|
||||
{
|
||||
SourceError(source, "value %d out of range [%f, %f]", intval, fd->floatmin, fd->floatmax);
|
||||
return (qboolean)0;
|
||||
} //end if
|
||||
} //end if
|
||||
} //end else if
|
||||
//store the value
|
||||
if ((fd->type & FT_TYPE) == FT_CHAR)
|
||||
{
|
||||
if (fd->type & FT_UNSIGNED) *(unsigned char *) p = (unsigned char) intval;
|
||||
else *(char *) p = (char) intval;
|
||||
} //end if
|
||||
else if ((fd->type & FT_TYPE) == FT_INT)
|
||||
{
|
||||
if (fd->type & FT_UNSIGNED) *(unsigned int *) p = (unsigned int) intval;
|
||||
else *(int *) p = (int) intval;
|
||||
} //end else
|
||||
else if ((fd->type & FT_TYPE) == FT_FLOAT)
|
||||
{
|
||||
*(float *) p = (float) intval;
|
||||
} //end else
|
||||
return (qboolean)1;
|
||||
} //end of the function ReadNumber
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
qboolean ReadChar(source_t *source, fielddef_t *fd, void *p)
|
||||
{
|
||||
token_t token;
|
||||
|
||||
if (!PC_ExpectAnyToken(source, &token)) return (qboolean)0;
|
||||
|
||||
//take literals into account
|
||||
if (token.type == TT_LITERAL)
|
||||
{
|
||||
StripSingleQuotes(token.string);
|
||||
*(char *) p = token.string[0];
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
PC_UnreadLastToken(source);
|
||||
if (!ReadNumber(source, fd, p)) return (qboolean)0;
|
||||
} //end if
|
||||
return (qboolean)1;
|
||||
} //end of the function ReadChar
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int ReadString(source_t *source, fielddef_t *fd, void *p)
|
||||
{
|
||||
token_t token;
|
||||
|
||||
if (!PC_ExpectTokenType(source, TT_STRING, 0, &token)) return 0;
|
||||
//remove the double quotes
|
||||
StripDoubleQuotes(token.string);
|
||||
//copy the string
|
||||
strncpy((char *) p, token.string, MAX_STRINGFIELD);
|
||||
//make sure the string is closed with a zero
|
||||
((char *)p)[MAX_STRINGFIELD-1] = '\0';
|
||||
//
|
||||
return 1;
|
||||
} //end of the function ReadString
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int ReadStructure(source_t *source, structdef_t *def, char *structure)
|
||||
{
|
||||
token_t token;
|
||||
fielddef_t *fd;
|
||||
void *p;
|
||||
int num;
|
||||
|
||||
if (!PC_ExpectTokenString(source, "{")) return 0;
|
||||
while(1)
|
||||
{
|
||||
if (!PC_ExpectAnyToken(source, &token)) return qfalse;
|
||||
//if end of structure
|
||||
if (!strcmp(token.string, "}")) break;
|
||||
//find the field with the name
|
||||
fd = FindField(def->fields, token.string);
|
||||
if (!fd)
|
||||
{
|
||||
SourceError(source, "unknown structure field %s", token.string);
|
||||
return qfalse;
|
||||
} //end if
|
||||
if (fd->type & FT_ARRAY)
|
||||
{
|
||||
num = fd->maxarray;
|
||||
if (!PC_ExpectTokenString(source, "{")) return qfalse;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
num = 1;
|
||||
} //end else
|
||||
p = (void *)(structure + fd->offset);
|
||||
while (num-- > 0)
|
||||
{
|
||||
if (fd->type & FT_ARRAY)
|
||||
{
|
||||
if (PC_CheckTokenString(source, "}")) break;
|
||||
} //end if
|
||||
switch(fd->type & FT_TYPE)
|
||||
{
|
||||
case FT_CHAR:
|
||||
{
|
||||
if (!ReadChar(source, fd, p)) return qfalse;
|
||||
p = (char *) p + sizeof(char);
|
||||
break;
|
||||
} //end case
|
||||
case FT_INT:
|
||||
{
|
||||
if (!ReadNumber(source, fd, p)) return qfalse;
|
||||
p = (char *) p + sizeof(int);
|
||||
break;
|
||||
} //end case
|
||||
case FT_FLOAT:
|
||||
{
|
||||
if (!ReadNumber(source, fd, p)) return qfalse;
|
||||
p = (char *) p + sizeof(float);
|
||||
break;
|
||||
} //end case
|
||||
case FT_STRING:
|
||||
{
|
||||
if (!ReadString(source, fd, p)) return qfalse;
|
||||
p = (char *) p + MAX_STRINGFIELD;
|
||||
break;
|
||||
} //end case
|
||||
case FT_STRUCT:
|
||||
{
|
||||
if (!fd->substruct)
|
||||
{
|
||||
SourceError(source, "BUG: no sub structure defined");
|
||||
return qfalse;
|
||||
} //end if
|
||||
ReadStructure(source, fd->substruct, (char *) p);
|
||||
p = (char *) p + fd->substruct->size;
|
||||
break;
|
||||
} //end case
|
||||
} //end switch
|
||||
if (fd->type & FT_ARRAY)
|
||||
{
|
||||
if (!PC_ExpectAnyToken(source, &token)) return qfalse;
|
||||
if (!strcmp(token.string, "}")) break;
|
||||
if (strcmp(token.string, ","))
|
||||
{
|
||||
SourceError(source, "expected a comma, found %s", token.string);
|
||||
return qfalse;
|
||||
} //end if
|
||||
} //end if
|
||||
} //end while
|
||||
} //end while
|
||||
return qtrue;
|
||||
} //end of the function ReadStructure
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int WriteIndent(FILE *fp, int indent)
|
||||
{
|
||||
while(indent-- > 0)
|
||||
{
|
||||
if (fprintf(fp, "\t") < 0) return qfalse;
|
||||
} //end while
|
||||
return qtrue;
|
||||
} //end of the function WriteIndent
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int WriteFloat(FILE *fp, float value)
|
||||
{
|
||||
char buf[128];
|
||||
int l;
|
||||
|
||||
sprintf(buf, "%f", value);
|
||||
l = strlen(buf);
|
||||
//strip any trailing zeros
|
||||
while(l-- > 1)
|
||||
{
|
||||
if (buf[l] != '0' && buf[l] != '.') break;
|
||||
if (buf[l] == '.')
|
||||
{
|
||||
buf[l] = 0;
|
||||
break;
|
||||
} //end if
|
||||
buf[l] = 0;
|
||||
} //end while
|
||||
//write the float to file
|
||||
if (fprintf(fp, "%s", buf) < 0) return 0;
|
||||
return 1;
|
||||
} //end of the function WriteFloat
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int WriteStructWithIndent(FILE *fp, structdef_t *def, char *structure, int indent)
|
||||
{
|
||||
int i, num;
|
||||
void *p;
|
||||
fielddef_t *fd;
|
||||
|
||||
if (!WriteIndent(fp, indent)) return qfalse;
|
||||
if (fprintf(fp, "{\r\n") < 0) return qfalse;
|
||||
|
||||
indent++;
|
||||
for (i = 0; def->fields[i].name; i++)
|
||||
{
|
||||
fd = &def->fields[i];
|
||||
if (!WriteIndent(fp, indent)) return qfalse;
|
||||
if (fprintf(fp, "%s\t", fd->name) < 0) return qfalse;
|
||||
p = (void *)(structure + fd->offset);
|
||||
if (fd->type & FT_ARRAY)
|
||||
{
|
||||
num = fd->maxarray;
|
||||
if (fprintf(fp, "{") < 0) return qfalse;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
num = 1;
|
||||
} //end else
|
||||
while(num-- > 0)
|
||||
{
|
||||
switch(fd->type & FT_TYPE)
|
||||
{
|
||||
case FT_CHAR:
|
||||
{
|
||||
if (fprintf(fp, "%d", *(char *) p) < 0) return qfalse;
|
||||
p = (char *) p + sizeof(char);
|
||||
break;
|
||||
} //end case
|
||||
case FT_INT:
|
||||
{
|
||||
if (fprintf(fp, "%d", *(int *) p) < 0) return qfalse;
|
||||
p = (char *) p + sizeof(int);
|
||||
break;
|
||||
} //end case
|
||||
case FT_FLOAT:
|
||||
{
|
||||
if (!WriteFloat(fp, *(float *)p)) return qfalse;
|
||||
p = (char *) p + sizeof(float);
|
||||
break;
|
||||
} //end case
|
||||
case FT_STRING:
|
||||
{
|
||||
if (fprintf(fp, "\"%s\"", (char *) p) < 0) return qfalse;
|
||||
p = (char *) p + MAX_STRINGFIELD;
|
||||
break;
|
||||
} //end case
|
||||
case FT_STRUCT:
|
||||
{
|
||||
if (!WriteStructWithIndent(fp, fd->substruct, structure, indent)) return qfalse;
|
||||
p = (char *) p + fd->substruct->size;
|
||||
break;
|
||||
} //end case
|
||||
} //end switch
|
||||
if (fd->type & FT_ARRAY)
|
||||
{
|
||||
if (num > 0)
|
||||
{
|
||||
if (fprintf(fp, ",") < 0) return qfalse;
|
||||
} //end if
|
||||
else
|
||||
{
|
||||
if (fprintf(fp, "}") < 0) return qfalse;
|
||||
} //end else
|
||||
} //end if
|
||||
} //end while
|
||||
if (fprintf(fp, "\r\n") < 0) return qfalse;
|
||||
} //end for
|
||||
indent--;
|
||||
|
||||
if (!WriteIndent(fp, indent)) return qfalse;
|
||||
if (fprintf(fp, "}\r\n") < 0) return qfalse;
|
||||
return qtrue;
|
||||
} //end of the function WriteStructWithIndent
|
||||
//===========================================================================
|
||||
//
|
||||
// Parameter: -
|
||||
// Returns: -
|
||||
// Changes Globals: -
|
||||
//===========================================================================
|
||||
int WriteStructure(FILE *fp, structdef_t *def, char *structure)
|
||||
{
|
||||
return WriteStructWithIndent(fp, def, structure, 0);
|
||||
} //end of the function WriteStructure
|
||||
|
58
CODEmp/botlib/l_struct.h
Normal file
58
CODEmp/botlib/l_struct.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: l_struct.h
|
||||
*
|
||||
* desc: structure reading/writing
|
||||
*
|
||||
* $Archive: /source/code/botlib/l_struct.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#define MAX_STRINGFIELD 80
|
||||
//field types
|
||||
#define FT_CHAR 1 // char
|
||||
#define FT_INT 2 // int
|
||||
#define FT_FLOAT 3 // float
|
||||
#define FT_STRING 4 // char [MAX_STRINGFIELD]
|
||||
#define FT_STRUCT 6 // struct (sub structure)
|
||||
//type only mask
|
||||
#define FT_TYPE 0x00FF // only type, clear subtype
|
||||
//sub types
|
||||
#define FT_ARRAY 0x0100 // array of type
|
||||
#define FT_BOUNDED 0x0200 // bounded value
|
||||
#define FT_UNSIGNED 0x0400
|
||||
|
||||
//structure field definition
|
||||
typedef struct fielddef_s
|
||||
{
|
||||
char *name; //name of the field
|
||||
int offset; //offset in the structure
|
||||
int type; //type of the field
|
||||
//type specific fields
|
||||
int maxarray; //maximum array size
|
||||
float floatmin, floatmax; //float min and max
|
||||
struct structdef_s *substruct; //sub structure
|
||||
} fielddef_t;
|
||||
|
||||
//structure definition
|
||||
typedef struct structdef_s
|
||||
{
|
||||
int size;
|
||||
fielddef_t *fields;
|
||||
} structdef_t;
|
||||
|
||||
//read a structure from a script
|
||||
int ReadStructure(source_t *source, structdef_t *def, char *structure);
|
||||
//write a structure to a file
|
||||
int WriteStructure(FILE *fp, structdef_t *def, char *structure);
|
||||
//writes indents
|
||||
int WriteIndent(FILE *fp, int indent);
|
||||
//writes a float without traling zeros
|
||||
int WriteFloat(FILE *fp, float value);
|
||||
|
||||
|
18
CODEmp/botlib/l_utils.h
Normal file
18
CODEmp/botlib/l_utils.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* name: l_util.h
|
||||
*
|
||||
* desc: utils
|
||||
*
|
||||
* $Archive: /source/code/botlib/l_util.h $
|
||||
* $Author: Mrelusive $
|
||||
* $Revision: 2 $
|
||||
* $Modtime: 10/05/99 3:32p $
|
||||
* $Date: 10/05/99 3:42p $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define Vector2Angles(v,a) vectoangles(v,a)
|
||||
#define MAX_PATH MAX_QPATH
|
||||
#define Maximum(x,y) (x > y ? x : y)
|
||||
#define Minimum(x,y) (x < y ? x : y)
|
3
CODEmp/cgame/JK2_cgame.def
Normal file
3
CODEmp/cgame/JK2_cgame.def
Normal file
|
@ -0,0 +1,3 @@
|
|||
EXPORTS
|
||||
vmMain
|
||||
dllEntry
|
399
CODEmp/cgame/JK2_cgame.dsp
Normal file
399
CODEmp/cgame/JK2_cgame.dsp
Normal file
|
@ -0,0 +1,399 @@
|
|||
# Microsoft Developer Studio Project File - Name="JK2cgame" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=JK2cgame - Win32 Release JK2
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "JK2_cgame.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "JK2_cgame.mak" CFG="JK2cgame - Win32 Release JK2"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "JK2cgame - Win32 Release JK2" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "JK2cgame - Win32 Debug JK2" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "JK2cgame - Win32 Final JK2" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""$/General/code/cgame", UPCAAAAA"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "JK2cgame - Win32 Release JK2"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "JK2cgame___Win32_Release_TA"
|
||||
# PROP BASE Intermediate_Dir "JK2cgame___Win32_Release_TA"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "../Release"
|
||||
# PROP Intermediate_Dir "../Release/JK2cgame"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /G6 /W4 /GX /O2 /D "WIN32" /D "NDebug" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /G6 /W4 /GX /Zi /O2 /I ".." /I "./../game" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "MISSIONPACK" /D "_JK2" /YX /FD /c
|
||||
# SUBTRACT CPP /Fr
|
||||
# ADD BASE MTL /nologo /D "NDebug" /mktyplib203 /o "NUL" /win32
|
||||
# ADD MTL /nologo /D "NDebug" /mktyplib203 /o "NUL" /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDebug"
|
||||
# ADD RSC /l 0x409 /d "NDebug"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 /nologo /base:"0x30000000" /subsystem:windows /dll /map /machine:I386 /def:".\JK2_cgame.def" /out:"../Release/cgamex86.dll"
|
||||
# SUBTRACT BASE LINK32 /debug
|
||||
# ADD LINK32 /nologo /base:"0x30000000" /subsystem:windows /dll /map /debug /machine:I386 /def:".\JK2_cgame.def" /out:"../Release/cgamex86.dll"
|
||||
|
||||
!ELSEIF "$(CFG)" == "JK2cgame - Win32 Debug JK2"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "JK2cgame___Win32_Debug_TA"
|
||||
# PROP BASE Intermediate_Dir "JK2cgame___Win32_Debug_TA"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "../Debug"
|
||||
# PROP Intermediate_Dir "../Debug/JK2cgame"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /G5 /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_Debug" /D "_WINDOWS" /FR /YX /FD /c
|
||||
# ADD CPP /nologo /G6 /MTd /W3 /Gm /GX /ZI /Od /I ".." /I "./../game" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "MISSIONPACK" /D "_JK2" /D "JK2AWARDS" /FR /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_Debug" /mktyplib203 /o "NUL" /win32
|
||||
# ADD MTL /nologo /D "_Debug" /mktyplib203 /o "NUL" /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_Debug"
|
||||
# ADD RSC /l 0x409 /d "_Debug"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 /nologo /base:"0x30000000" /subsystem:windows /dll /map /debug /machine:I386 /out:"..\Debug/cgamex86.dll"
|
||||
# SUBTRACT BASE LINK32 /profile /nodefaultlib
|
||||
# ADD LINK32 /nologo /base:"0x30000000" /subsystem:windows /dll /map /debug /machine:I386 /def:".\JK2_cgame.def" /out:"..\Debug\cgamex86.dll"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "JK2cgame - Win32 Final JK2"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "../Final"
|
||||
# PROP BASE Intermediate_Dir "../Final/JK2cgame"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "../Final"
|
||||
# PROP Intermediate_Dir "../Final/JK2cgame"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /G6 /W4 /GX /Zi /O2 /I ".." /I "../../jk2/game" /D "NDebug" /D "WIN32" /D "_WINDOWS" /D "MISSIONPACK" /D "_JK2" /YX /FD /c
|
||||
# SUBTRACT BASE CPP /Fr
|
||||
# ADD CPP /nologo /G6 /W4 /GX /O2 /I ".." /I "./../game" /D "NDEBUG" /D "_WINDOWS" /D "MISSIONPACK" /D "WIN32" /D "_JK2" /D "FINAL_BUILD" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDebug" /mktyplib203 /o "NUL" /win32
|
||||
# ADD MTL /nologo /D "NDebug" /mktyplib203 /o "NUL" /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDebug"
|
||||
# ADD RSC /l 0x409 /d "NDebug"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 /nologo /base:"0x30000000" /subsystem:windows /dll /map /machine:I386 /def:".\JK2_cgame.def" /out:"../Final/cgamex86.dll"
|
||||
# ADD LINK32 /nologo /base:"0x30000000" /subsystem:windows /dll /map /machine:I386 /def:".\JK2_cgame.def" /out:"../Final/cgamex86.dll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "JK2cgame - Win32 Release JK2"
|
||||
# Name "JK2cgame - Win32 Debug JK2"
|
||||
# Name "JK2cgame - Win32 Final JK2"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "c"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\bg_lib.c
|
||||
# PROP BASE Exclude_From_Build 1
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\bg_misc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\bg_panimate.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\bg_pmove.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\bg_saber.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\bg_slidemove.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\bg_weapons.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_consolecmds.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_draw.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_drawtools.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_effects.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_ents.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_event.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_info.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_light.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_localents.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_main.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_marks.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_newDraw.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_players.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_playerstate.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_predict.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_saga.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_scoreboard.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_servercmds.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_snapshot.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_syscalls.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_turret.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_view.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_weaponinit.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_weapons.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\fx_blaster.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\fx_bowcaster.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\fx_bryarpistol.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\fx_demp2.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\fx_disruptor.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\fx_flechette.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\fx_force.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\fx_heavyrepeater.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\fx_rocketlauncher.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\q_math.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\q_shared.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\ui\ui_shared.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\anims.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\animtable.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\bg_local.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\bg_public.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\bg_saga.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\bg_weapons.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_lights.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_local.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_public.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\qcommon\disablewarnings.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\fx_local.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\ghoul2\G2.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\ui\keycodes.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\ui\menudef.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\q_shared.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\qcommon\qfiles.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\game\surfaceflags.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\qcommon\tags.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tr_types.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\ui\ui_shared.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cg_syscalls.asm
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\JK2_cgame.def
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
1257
CODEmp/cgame/animtable.h
Normal file
1257
CODEmp/cgame/animtable.h
Normal file
File diff suppressed because it is too large
Load diff
578
CODEmp/cgame/cg_consolecmds.c
Normal file
578
CODEmp/cgame/cg_consolecmds.c
Normal file
|
@ -0,0 +1,578 @@
|
|||
// Copyright (C) 1999-2000 Id Software, Inc.
|
||||
//
|
||||
// cg_consolecmds.c -- text commands typed in at the local console, or
|
||||
// executed by a key binding
|
||||
|
||||
#include "cg_local.h"
|
||||
#include "../ui/ui_shared.h"
|
||||
extern menuDef_t *menuScoreboard;
|
||||
|
||||
|
||||
|
||||
void CG_TargetCommand_f( void ) {
|
||||
int targetNum;
|
||||
char test[4];
|
||||
|
||||
targetNum = CG_CrosshairPlayer();
|
||||
if (!targetNum ) {
|
||||
return;
|
||||
}
|
||||
|
||||
trap_Argv( 1, test, 4 );
|
||||
trap_SendConsoleCommand( va( "gc %i %i", targetNum, atoi( test ) ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
CG_SizeUp_f
|
||||
|
||||
Keybinding command
|
||||
=================
|
||||
*/
|
||||
static void CG_SizeUp_f (void) {
|
||||
trap_Cvar_Set("cg_viewsize", va("%i",(int)(cg_viewsize.integer+10)));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
CG_SizeDown_f
|
||||
|
||||
Keybinding command
|
||||
=================
|
||||
*/
|
||||
static void CG_SizeDown_f (void) {
|
||||
trap_Cvar_Set("cg_viewsize", va("%i",(int)(cg_viewsize.integer-10)));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
CG_Viewpos_f
|
||||
|
||||
Debugging command to print the current position
|
||||
=============
|
||||
*/
|
||||
static void CG_Viewpos_f (void) {
|
||||
CG_Printf ("%s (%i %i %i) : %i\n", cgs.mapname, (int)cg.refdef.vieworg[0],
|
||||
(int)cg.refdef.vieworg[1], (int)cg.refdef.vieworg[2],
|
||||
(int)cg.refdefViewAngles[YAW]);
|
||||
}
|
||||
|
||||
|
||||
static void CG_ScoresDown_f( void ) {
|
||||
|
||||
CG_BuildSpectatorString();
|
||||
if ( cg.scoresRequestTime + 2000 < cg.time ) {
|
||||
// the scores are more than two seconds out of data,
|
||||
// so request new ones
|
||||
cg.scoresRequestTime = cg.time;
|
||||
trap_SendClientCommand( "score" );
|
||||
|
||||
// leave the current scores up if they were already
|
||||
// displayed, but if this is the first hit, clear them out
|
||||
if ( !cg.showScores ) {
|
||||
cg.showScores = qtrue;
|
||||
cg.numScores = 0;
|
||||
}
|
||||
} else {
|
||||
// show the cached contents even if they just pressed if it
|
||||
// is within two seconds
|
||||
cg.showScores = qtrue;
|
||||
}
|
||||
}
|
||||
|
||||
static void CG_ScoresUp_f( void ) {
|
||||
if ( cg.showScores ) {
|
||||
cg.showScores = qfalse;
|
||||
cg.scoreFadeTime = cg.time;
|
||||
}
|
||||
}
|
||||
|
||||
extern menuDef_t *menuScoreboard;
|
||||
void Menu_Reset(); // FIXME: add to right include file
|
||||
|
||||
static void CG_LoadHud_f( void) {
|
||||
char buff[1024];
|
||||
const char *hudSet;
|
||||
memset(buff, 0, sizeof(buff));
|
||||
|
||||
String_Init();
|
||||
Menu_Reset();
|
||||
|
||||
trap_Cvar_VariableStringBuffer("cg_hudFiles", buff, sizeof(buff));
|
||||
hudSet = buff;
|
||||
if (hudSet[0] == '\0') {
|
||||
hudSet = "ui/hud.txt";
|
||||
}
|
||||
|
||||
CG_LoadMenus(hudSet);
|
||||
menuScoreboard = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void CG_scrollScoresDown_f( void) {
|
||||
if (menuScoreboard && cg.scoreBoardShowing) {
|
||||
Menu_ScrollFeeder(menuScoreboard, FEEDER_SCOREBOARD, qtrue);
|
||||
Menu_ScrollFeeder(menuScoreboard, FEEDER_REDTEAM_LIST, qtrue);
|
||||
Menu_ScrollFeeder(menuScoreboard, FEEDER_BLUETEAM_LIST, qtrue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void CG_scrollScoresUp_f( void) {
|
||||
if (menuScoreboard && cg.scoreBoardShowing) {
|
||||
Menu_ScrollFeeder(menuScoreboard, FEEDER_SCOREBOARD, qfalse);
|
||||
Menu_ScrollFeeder(menuScoreboard, FEEDER_REDTEAM_LIST, qfalse);
|
||||
Menu_ScrollFeeder(menuScoreboard, FEEDER_BLUETEAM_LIST, qfalse);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void CG_spWin_f( void) {
|
||||
trap_Cvar_Set("cg_cameraOrbit", "2");
|
||||
trap_Cvar_Set("cg_cameraOrbitDelay", "35");
|
||||
trap_Cvar_Set("cg_thirdPerson", "1");
|
||||
trap_Cvar_Set("cg_thirdPersonAngle", "0");
|
||||
trap_Cvar_Set("cg_thirdPersonRange", "100");
|
||||
CG_AddBufferedSound(cgs.media.winnerSound);
|
||||
//trap_S_StartLocalSound(cgs.media.winnerSound, CHAN_ANNOUNCER);
|
||||
CG_CenterPrint("YOU WIN!", SCREEN_HEIGHT * .30, 0);
|
||||
}
|
||||
|
||||
static void CG_spLose_f( void) {
|
||||
trap_Cvar_Set("cg_cameraOrbit", "2");
|
||||
trap_Cvar_Set("cg_cameraOrbitDelay", "35");
|
||||
trap_Cvar_Set("cg_thirdPerson", "1");
|
||||
trap_Cvar_Set("cg_thirdPersonAngle", "0");
|
||||
trap_Cvar_Set("cg_thirdPersonRange", "100");
|
||||
CG_AddBufferedSound(cgs.media.loserSound);
|
||||
//trap_S_StartLocalSound(cgs.media.loserSound, CHAN_ANNOUNCER);
|
||||
CG_CenterPrint("YOU LOSE...", SCREEN_HEIGHT * .30, 0);
|
||||
}
|
||||
|
||||
|
||||
static void CG_TellTarget_f( void ) {
|
||||
int clientNum;
|
||||
char command[128];
|
||||
char message[128];
|
||||
|
||||
clientNum = CG_CrosshairPlayer();
|
||||
if ( clientNum == -1 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
trap_Args( message, 128 );
|
||||
Com_sprintf( command, 128, "tell %i %s", clientNum, message );
|
||||
trap_SendClientCommand( command );
|
||||
}
|
||||
|
||||
static void CG_TellAttacker_f( void ) {
|
||||
int clientNum;
|
||||
char command[128];
|
||||
char message[128];
|
||||
|
||||
clientNum = CG_LastAttacker();
|
||||
if ( clientNum == -1 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
trap_Args( message, 128 );
|
||||
Com_sprintf( command, 128, "tell %i %s", clientNum, message );
|
||||
trap_SendClientCommand( command );
|
||||
}
|
||||
|
||||
static void CG_VoiceTellTarget_f( void ) {
|
||||
int clientNum;
|
||||
char command[128];
|
||||
char message[128];
|
||||
|
||||
clientNum = CG_CrosshairPlayer();
|
||||
if ( clientNum == -1 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
trap_Args( message, 128 );
|
||||
Com_sprintf( command, 128, "vtell %i %s", clientNum, message );
|
||||
trap_SendClientCommand( command );
|
||||
}
|
||||
|
||||
static void CG_VoiceTellAttacker_f( void ) {
|
||||
int clientNum;
|
||||
char command[128];
|
||||
char message[128];
|
||||
|
||||
clientNum = CG_LastAttacker();
|
||||
if ( clientNum == -1 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
trap_Args( message, 128 );
|
||||
Com_sprintf( command, 128, "vtell %i %s", clientNum, message );
|
||||
trap_SendClientCommand( command );
|
||||
}
|
||||
|
||||
static void CG_NextTeamMember_f( void ) {
|
||||
CG_SelectNextPlayer();
|
||||
}
|
||||
|
||||
static void CG_PrevTeamMember_f( void ) {
|
||||
CG_SelectPrevPlayer();
|
||||
}
|
||||
|
||||
// ASS U ME's enumeration order as far as task specific orders, OFFENSE is zero, CAMP is last
|
||||
//
|
||||
static void CG_NextOrder_f( void ) {
|
||||
clientInfo_t *ci = cgs.clientinfo + cg.snap->ps.clientNum;
|
||||
if (ci) {
|
||||
if (!ci->teamLeader && sortedTeamPlayers[cg_currentSelectedPlayer.integer] != cg.snap->ps.clientNum) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (cgs.currentOrder < TEAMTASK_CAMP) {
|
||||
cgs.currentOrder++;
|
||||
|
||||
if (cgs.currentOrder == TEAMTASK_RETRIEVE) {
|
||||
if (!CG_OtherTeamHasFlag()) {
|
||||
cgs.currentOrder++;
|
||||
}
|
||||
}
|
||||
|
||||
if (cgs.currentOrder == TEAMTASK_ESCORT) {
|
||||
if (!CG_YourTeamHasFlag()) {
|
||||
cgs.currentOrder++;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
cgs.currentOrder = TEAMTASK_OFFENSE;
|
||||
}
|
||||
cgs.orderPending = qtrue;
|
||||
cgs.orderTime = cg.time + 3000;
|
||||
}
|
||||
|
||||
|
||||
static void CG_ConfirmOrder_f (void ) {
|
||||
trap_SendConsoleCommand(va("cmd vtell %d %s\n", cgs.acceptLeader, VOICECHAT_YES));
|
||||
trap_SendConsoleCommand("+button5; wait; -button5");
|
||||
if (cg.time < cgs.acceptOrderTime) {
|
||||
trap_SendClientCommand(va("teamtask %d\n", cgs.acceptTask));
|
||||
cgs.acceptOrderTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void CG_DenyOrder_f (void ) {
|
||||
trap_SendConsoleCommand(va("cmd vtell %d %s\n", cgs.acceptLeader, VOICECHAT_NO));
|
||||
trap_SendConsoleCommand("+button6; wait; -button6");
|
||||
if (cg.time < cgs.acceptOrderTime) {
|
||||
cgs.acceptOrderTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void CG_TaskOffense_f (void ) {
|
||||
if (cgs.gametype == GT_CTF || cgs.gametype == GT_CTY) {
|
||||
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONGETFLAG));
|
||||
} else {
|
||||
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONOFFENSE));
|
||||
}
|
||||
trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_OFFENSE));
|
||||
}
|
||||
|
||||
static void CG_TaskDefense_f (void ) {
|
||||
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONDEFENSE));
|
||||
trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_DEFENSE));
|
||||
}
|
||||
|
||||
static void CG_TaskPatrol_f (void ) {
|
||||
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONPATROL));
|
||||
trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_PATROL));
|
||||
}
|
||||
|
||||
static void CG_TaskCamp_f (void ) {
|
||||
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONCAMPING));
|
||||
trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_CAMP));
|
||||
}
|
||||
|
||||
static void CG_TaskFollow_f (void ) {
|
||||
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONFOLLOW));
|
||||
trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_FOLLOW));
|
||||
}
|
||||
|
||||
static void CG_TaskRetrieve_f (void ) {
|
||||
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONRETURNFLAG));
|
||||
trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_RETRIEVE));
|
||||
}
|
||||
|
||||
static void CG_TaskEscort_f (void ) {
|
||||
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONFOLLOWCARRIER));
|
||||
trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_ESCORT));
|
||||
}
|
||||
|
||||
static void CG_TaskOwnFlag_f (void ) {
|
||||
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_IHAVEFLAG));
|
||||
}
|
||||
|
||||
static void CG_TauntKillInsult_f (void ) {
|
||||
trap_SendConsoleCommand("cmd vsay kill_insult\n");
|
||||
}
|
||||
|
||||
static void CG_TauntPraise_f (void ) {
|
||||
trap_SendConsoleCommand("cmd vsay praise\n");
|
||||
}
|
||||
|
||||
static void CG_TauntTaunt_f (void ) {
|
||||
trap_SendConsoleCommand("cmd vtaunt\n");
|
||||
}
|
||||
|
||||
static void CG_TauntDeathInsult_f (void ) {
|
||||
trap_SendConsoleCommand("cmd vsay death_insult\n");
|
||||
}
|
||||
|
||||
static void CG_TauntGauntlet_f (void ) {
|
||||
trap_SendConsoleCommand("cmd vsay kill_guantlet\n");
|
||||
}
|
||||
|
||||
static void CG_TaskSuicide_f (void ) {
|
||||
int clientNum;
|
||||
char command[128];
|
||||
|
||||
clientNum = CG_CrosshairPlayer();
|
||||
if ( clientNum == -1 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Com_sprintf( command, 128, "tell %i suicide", clientNum );
|
||||
trap_SendClientCommand( command );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
CG_TeamMenu_f
|
||||
==================
|
||||
*/
|
||||
/*
|
||||
static void CG_TeamMenu_f( void ) {
|
||||
if (trap_Key_GetCatcher() & KEYCATCH_CGAME) {
|
||||
CG_EventHandling(CGAME_EVENT_NONE);
|
||||
trap_Key_SetCatcher(0);
|
||||
} else {
|
||||
CG_EventHandling(CGAME_EVENT_TEAMMENU);
|
||||
//trap_Key_SetCatcher(KEYCATCH_CGAME);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
==================
|
||||
CG_EditHud_f
|
||||
==================
|
||||
*/
|
||||
/*
|
||||
static void CG_EditHud_f( void ) {
|
||||
//cls.keyCatchers ^= KEYCATCH_CGAME;
|
||||
//VM_Call (cgvm, CG_EVENT_HANDLING, (cls.keyCatchers & KEYCATCH_CGAME) ? CGAME_EVENT_EDITHUD : CGAME_EVENT_NONE);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
CG_StartOrbit_f
|
||||
==================
|
||||
*/
|
||||
|
||||
static void CG_StartOrbit_f( void ) {
|
||||
char var[MAX_TOKEN_CHARS];
|
||||
|
||||
trap_Cvar_VariableStringBuffer( "developer", var, sizeof( var ) );
|
||||
if ( !atoi(var) ) {
|
||||
return;
|
||||
}
|
||||
if (cg_cameraOrbit.value != 0) {
|
||||
trap_Cvar_Set ("cg_cameraOrbit", "0");
|
||||
trap_Cvar_Set("cg_thirdPerson", "0");
|
||||
} else {
|
||||
trap_Cvar_Set("cg_cameraOrbit", "5");
|
||||
trap_Cvar_Set("cg_thirdPerson", "1");
|
||||
trap_Cvar_Set("cg_thirdPersonAngle", "0");
|
||||
trap_Cvar_Set("cg_thirdPersonRange", "100");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static void CG_Camera_f( void ) {
|
||||
char name[1024];
|
||||
trap_Argv( 1, name, sizeof(name));
|
||||
if (trap_loadCamera(name)) {
|
||||
cg.cameraMode = qtrue;
|
||||
trap_startCamera(cg.time);
|
||||
} else {
|
||||
CG_Printf ("Unable to load camera %s\n",name);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
char *cmd;
|
||||
void (*function)(void);
|
||||
} consoleCommand_t;
|
||||
|
||||
static consoleCommand_t commands[] = {
|
||||
{ "testgun", CG_TestGun_f },
|
||||
{ "testmodel", CG_TestModel_f },
|
||||
{ "nextframe", CG_TestModelNextFrame_f },
|
||||
{ "prevframe", CG_TestModelPrevFrame_f },
|
||||
{ "nextskin", CG_TestModelNextSkin_f },
|
||||
{ "prevskin", CG_TestModelPrevSkin_f },
|
||||
{ "viewpos", CG_Viewpos_f },
|
||||
{ "+scores", CG_ScoresDown_f },
|
||||
{ "-scores", CG_ScoresUp_f },
|
||||
// { "+zoom", CG_ZoomDown_f },
|
||||
// { "-zoom", CG_ZoomUp_f },
|
||||
{ "sizeup", CG_SizeUp_f },
|
||||
{ "sizedown", CG_SizeDown_f },
|
||||
{ "weapnext", CG_NextWeapon_f },
|
||||
{ "weapprev", CG_PrevWeapon_f },
|
||||
{ "weapon", CG_Weapon_f },
|
||||
{ "tell_target", CG_TellTarget_f },
|
||||
{ "tell_attacker", CG_TellAttacker_f },
|
||||
{ "vtell_target", CG_VoiceTellTarget_f },
|
||||
{ "vtell_attacker", CG_VoiceTellAttacker_f },
|
||||
{ "tcmd", CG_TargetCommand_f },
|
||||
{ "loadhud", CG_LoadHud_f },
|
||||
{ "nextTeamMember", CG_NextTeamMember_f },
|
||||
{ "prevTeamMember", CG_PrevTeamMember_f },
|
||||
{ "nextOrder", CG_NextOrder_f },
|
||||
{ "confirmOrder", CG_ConfirmOrder_f },
|
||||
{ "denyOrder", CG_DenyOrder_f },
|
||||
{ "taskOffense", CG_TaskOffense_f },
|
||||
{ "taskDefense", CG_TaskDefense_f },
|
||||
{ "taskPatrol", CG_TaskPatrol_f },
|
||||
{ "taskCamp", CG_TaskCamp_f },
|
||||
{ "taskFollow", CG_TaskFollow_f },
|
||||
{ "taskRetrieve", CG_TaskRetrieve_f },
|
||||
{ "taskEscort", CG_TaskEscort_f },
|
||||
{ "taskSuicide", CG_TaskSuicide_f },
|
||||
{ "taskOwnFlag", CG_TaskOwnFlag_f },
|
||||
{ "tauntKillInsult", CG_TauntKillInsult_f },
|
||||
{ "tauntPraise", CG_TauntPraise_f },
|
||||
{ "tauntTaunt", CG_TauntTaunt_f },
|
||||
{ "tauntDeathInsult", CG_TauntDeathInsult_f },
|
||||
{ "tauntGauntlet", CG_TauntGauntlet_f },
|
||||
{ "spWin", CG_spWin_f },
|
||||
{ "spLose", CG_spLose_f },
|
||||
{ "scoresDown", CG_scrollScoresDown_f },
|
||||
{ "scoresUp", CG_scrollScoresUp_f },
|
||||
{ "startOrbit", CG_StartOrbit_f },
|
||||
//{ "camera", CG_Camera_f },
|
||||
{ "loaddeferred", CG_LoadDeferredPlayers },
|
||||
{ "invnext", CG_NextInventory_f },
|
||||
{ "invprev", CG_PrevInventory_f },
|
||||
{ "forcenext", CG_NextForcePower_f },
|
||||
{ "forceprev", CG_PrevForcePower_f }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
CG_ConsoleCommand
|
||||
|
||||
The string has been tokenized and can be retrieved with
|
||||
Cmd_Argc() / Cmd_Argv()
|
||||
=================
|
||||
*/
|
||||
qboolean CG_ConsoleCommand( void ) {
|
||||
const char *cmd;
|
||||
int i;
|
||||
|
||||
cmd = CG_Argv(0);
|
||||
|
||||
for ( i = 0 ; i < sizeof( commands ) / sizeof( commands[0] ) ; i++ ) {
|
||||
if ( !Q_stricmp( cmd, commands[i].cmd ) ) {
|
||||
commands[i].function();
|
||||
return qtrue;
|
||||
}
|
||||
}
|
||||
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
CG_InitConsoleCommands
|
||||
|
||||
Let the client system know about all of our commands
|
||||
so it can perform tab completion
|
||||
=================
|
||||
*/
|
||||
void CG_InitConsoleCommands( void ) {
|
||||
int i;
|
||||
|
||||
for ( i = 0 ; i < sizeof( commands ) / sizeof( commands[0] ) ; i++ ) {
|
||||
trap_AddCommand( commands[i].cmd );
|
||||
}
|
||||
|
||||
//
|
||||
// the game server will interpret these commands, which will be automatically
|
||||
// forwarded to the server after they are not recognized locally
|
||||
//
|
||||
trap_AddCommand ("forcechanged");
|
||||
trap_AddCommand ("sv_invnext");
|
||||
trap_AddCommand ("sv_invprev");
|
||||
trap_AddCommand ("sv_forcenext");
|
||||
trap_AddCommand ("sv_forceprev");
|
||||
trap_AddCommand ("sv_saberswitch");
|
||||
trap_AddCommand ("engage_duel");
|
||||
trap_AddCommand ("force_heal");
|
||||
trap_AddCommand ("force_speed");
|
||||
trap_AddCommand ("force_throw");
|
||||
trap_AddCommand ("force_pull");
|
||||
trap_AddCommand ("force_distract");
|
||||
trap_AddCommand ("force_rage");
|
||||
trap_AddCommand ("force_protect");
|
||||
trap_AddCommand ("force_absorb");
|
||||
trap_AddCommand ("force_healother");
|
||||
trap_AddCommand ("force_forcepowerother");
|
||||
trap_AddCommand ("force_seeing");
|
||||
trap_AddCommand ("use_seeker");
|
||||
trap_AddCommand ("use_field");
|
||||
trap_AddCommand ("use_bacta");
|
||||
trap_AddCommand ("use_electrobinoculars");
|
||||
trap_AddCommand ("zoom");
|
||||
trap_AddCommand ("use_sentry");
|
||||
trap_AddCommand ("bot_order");
|
||||
trap_AddCommand ("saberAttackCycle");
|
||||
trap_AddCommand ("kill");
|
||||
trap_AddCommand ("say");
|
||||
trap_AddCommand ("say_team");
|
||||
trap_AddCommand ("tell");
|
||||
trap_AddCommand ("vsay");
|
||||
trap_AddCommand ("vsay_team");
|
||||
trap_AddCommand ("vtell");
|
||||
trap_AddCommand ("vtaunt");
|
||||
trap_AddCommand ("vosay");
|
||||
trap_AddCommand ("vosay_team");
|
||||
trap_AddCommand ("votell");
|
||||
trap_AddCommand ("give");
|
||||
trap_AddCommand ("god");
|
||||
trap_AddCommand ("notarget");
|
||||
trap_AddCommand ("noclip");
|
||||
trap_AddCommand ("team");
|
||||
trap_AddCommand ("follow");
|
||||
trap_AddCommand ("levelshot");
|
||||
trap_AddCommand ("addbot");
|
||||
trap_AddCommand ("setviewpos");
|
||||
trap_AddCommand ("callvote");
|
||||
trap_AddCommand ("vote");
|
||||
trap_AddCommand ("callteamvote");
|
||||
trap_AddCommand ("teamvote");
|
||||
trap_AddCommand ("stats");
|
||||
trap_AddCommand ("teamtask");
|
||||
trap_AddCommand ("loaddefered"); // spelled wrong, but not changing for demo
|
||||
}
|
4086
CODEmp/cgame/cg_draw.c
Normal file
4086
CODEmp/cgame/cg_draw.c
Normal file
File diff suppressed because it is too large
Load diff
629
CODEmp/cgame/cg_drawtools.c
Normal file
629
CODEmp/cgame/cg_drawtools.c
Normal file
|
@ -0,0 +1,629 @@
|
|||
/*
|
||||
// this line must stay at top so the whole PCH thing works...
|
||||
#include "cg_headers.h"
|
||||
|
||||
//#include "cg_local.h"
|
||||
#include "cg_media.h"
|
||||
#include "cg_text.h"
|
||||
*/
|
||||
|
||||
// Copyright (C) 1999-2000 Id Software, Inc.
|
||||
//
|
||||
// cg_drawtools.c -- helper functions called by cg_draw, cg_scoreboard, cg_info, etc
|
||||
#include "cg_local.h"
|
||||
#include "../game/q_shared.h"
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
UI_DrawRect
|
||||
|
||||
Coordinates are 640*480 virtual values
|
||||
=================
|
||||
*/
|
||||
void CG_DrawRect( float x, float y, float width, float height, float size, const float *color ) {
|
||||
trap_R_SetColor( color );
|
||||
|
||||
CG_DrawTopBottom(x, y, width, height, size);
|
||||
CG_DrawSides(x, y, width, height, size);
|
||||
|
||||
trap_R_SetColor( NULL );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
CG_GetColorForHealth
|
||||
=================
|
||||
*/
|
||||
void CG_GetColorForHealth( int health, int armor, vec4_t hcolor ) {
|
||||
int count;
|
||||
int max;
|
||||
|
||||
// calculate the total points of damage that can
|
||||
// be sustained at the current health / armor level
|
||||
if ( health <= 0 ) {
|
||||
VectorClear( hcolor ); // black
|
||||
hcolor[3] = 1;
|
||||
return;
|
||||
}
|
||||
count = armor;
|
||||
max = health * ARMOR_PROTECTION / ( 1.0 - ARMOR_PROTECTION );
|
||||
if ( max < count ) {
|
||||
count = max;
|
||||
}
|
||||
health += count;
|
||||
|
||||
// set the color based on health
|
||||
hcolor[0] = 1.0;
|
||||
hcolor[3] = 1.0;
|
||||
if ( health >= 100 ) {
|
||||
hcolor[2] = 1.0;
|
||||
} else if ( health < 66 ) {
|
||||
hcolor[2] = 0;
|
||||
} else {
|
||||
hcolor[2] = ( health - 66 ) / 33.0;
|
||||
}
|
||||
|
||||
if ( health > 60 ) {
|
||||
hcolor[1] = 1.0;
|
||||
} else if ( health < 30 ) {
|
||||
hcolor[1] = 0;
|
||||
} else {
|
||||
hcolor[1] = ( health - 30 ) / 30.0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CG_DrawSides
|
||||
|
||||
Coords are virtual 640x480
|
||||
================
|
||||
*/
|
||||
void CG_DrawSides(float x, float y, float w, float h, float size) {
|
||||
size *= cgs.screenXScale;
|
||||
trap_R_DrawStretchPic( x, y, size, h, 0, 0, 0, 0, cgs.media.whiteShader );
|
||||
trap_R_DrawStretchPic( x + w - size, y, size, h, 0, 0, 0, 0, cgs.media.whiteShader );
|
||||
}
|
||||
|
||||
void CG_DrawTopBottom(float x, float y, float w, float h, float size) {
|
||||
size *= cgs.screenYScale;
|
||||
trap_R_DrawStretchPic( x, y, w, size, 0, 0, 0, 0, cgs.media.whiteShader );
|
||||
trap_R_DrawStretchPic( x, y + h - size, w, size, 0, 0, 0, 0, cgs.media.whiteShader );
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------
|
||||
CGC_FillRect2
|
||||
real coords
|
||||
-------------------------
|
||||
*/
|
||||
void CG_FillRect2( float x, float y, float width, float height, const float *color ) {
|
||||
trap_R_SetColor( color );
|
||||
trap_R_DrawStretchPic( x, y, width, height, 0, 0, 0, 0, cgs.media.whiteShader);
|
||||
trap_R_SetColor( NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CG_FillRect
|
||||
|
||||
Coordinates are 640*480 virtual values
|
||||
=================
|
||||
*/
|
||||
void CG_FillRect( float x, float y, float width, float height, const float *color ) {
|
||||
trap_R_SetColor( color );
|
||||
|
||||
trap_R_DrawStretchPic( x, y, width, height, 0, 0, 0, 0, cgs.media.whiteShader);
|
||||
|
||||
trap_R_SetColor( NULL );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
CG_DrawPic
|
||||
|
||||
Coordinates are 640*480 virtual values
|
||||
A width of 0 will draw with the original image width
|
||||
=================
|
||||
*/
|
||||
void CG_DrawPic( float x, float y, float width, float height, qhandle_t hShader ) {
|
||||
trap_R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, hShader );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CG_DrawRotatePic
|
||||
|
||||
Coordinates are 640*480 virtual values
|
||||
A width of 0 will draw with the original image width
|
||||
rotates around the upper right corner of the passed in point
|
||||
=================
|
||||
*/
|
||||
void CG_DrawRotatePic( float x, float y, float width, float height,float angle, qhandle_t hShader ) {
|
||||
trap_R_DrawRotatePic( x, y, width, height, 0, 0, 1, 1, angle, hShader );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CG_DrawRotatePic2
|
||||
|
||||
Coordinates are 640*480 virtual values
|
||||
A width of 0 will draw with the original image width
|
||||
Actually rotates around the center point of the passed in coordinates
|
||||
=================
|
||||
*/
|
||||
void CG_DrawRotatePic2( float x, float y, float width, float height,float angle, qhandle_t hShader ) {
|
||||
trap_R_DrawRotatePic2( x, y, width, height, 0, 0, 1, 1, angle, hShader );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
CG_DrawChar
|
||||
|
||||
Coordinates and size in 640*480 virtual screen size
|
||||
===============
|
||||
*/
|
||||
void CG_DrawChar( int x, int y, int width, int height, int ch ) {
|
||||
int row, col;
|
||||
float frow, fcol;
|
||||
float size;
|
||||
float ax, ay, aw, ah;
|
||||
float size2;
|
||||
|
||||
ch &= 255;
|
||||
|
||||
if ( ch == ' ' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
ax = x;
|
||||
ay = y;
|
||||
aw = width;
|
||||
ah = height;
|
||||
|
||||
row = ch>>4;
|
||||
col = ch&15;
|
||||
|
||||
frow = row*0.0625;
|
||||
fcol = col*0.0625;
|
||||
size = 0.03125;
|
||||
size2 = 0.0625;
|
||||
|
||||
trap_R_DrawStretchPic( ax, ay, aw, ah, fcol, frow, fcol + size, frow + size2,
|
||||
cgs.media.charsetShader );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CG_DrawStringExt
|
||||
|
||||
Draws a multi-colored string with a drop shadow, optionally forcing
|
||||
to a fixed color.
|
||||
|
||||
Coordinates are at 640 by 480 virtual resolution
|
||||
==================
|
||||
*/
|
||||
void CG_DrawStringExt( int x, int y, const char *string, const float *setColor,
|
||||
qboolean forceColor, qboolean shadow, int charWidth, int charHeight, int maxChars )
|
||||
{
|
||||
vec4_t color;
|
||||
const char *s;
|
||||
int xx;
|
||||
|
||||
// draw the drop shadow
|
||||
if (shadow) {
|
||||
color[0] = color[1] = color[2] = 0;
|
||||
color[3] = setColor[3];
|
||||
trap_R_SetColor( color );
|
||||
s = string;
|
||||
xx = x;
|
||||
while ( *s ) {
|
||||
if ( Q_IsColorString( s ) ) {
|
||||
s += 2;
|
||||
continue;
|
||||
}
|
||||
CG_DrawChar( xx + 2, y + 2, charWidth, charHeight, *s );
|
||||
xx += charWidth;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
// draw the colored text
|
||||
s = string;
|
||||
xx = x;
|
||||
trap_R_SetColor( setColor );
|
||||
while ( *s ) {
|
||||
if ( Q_IsColorString( s ) ) {
|
||||
if ( !forceColor ) {
|
||||
memcpy( color, g_color_table[ColorIndex(*(s+1))], sizeof( color ) );
|
||||
color[3] = setColor[3];
|
||||
trap_R_SetColor( color );
|
||||
}
|
||||
s += 2;
|
||||
continue;
|
||||
}
|
||||
CG_DrawChar( xx, y, charWidth, charHeight, *s );
|
||||
xx += charWidth;
|
||||
s++;
|
||||
}
|
||||
trap_R_SetColor( NULL );
|
||||
}
|
||||
|
||||
void CG_DrawBigString( int x, int y, const char *s, float alpha ) {
|
||||
float color[4];
|
||||
|
||||
color[0] = color[1] = color[2] = 1.0;
|
||||
color[3] = alpha;
|
||||
CG_DrawStringExt( x, y, s, color, qfalse, qtrue, BIGCHAR_WIDTH, BIGCHAR_HEIGHT, 0 );
|
||||
}
|
||||
|
||||
void CG_DrawBigStringColor( int x, int y, const char *s, vec4_t color ) {
|
||||
CG_DrawStringExt( x, y, s, color, qtrue, qtrue, BIGCHAR_WIDTH, BIGCHAR_HEIGHT, 0 );
|
||||
}
|
||||
|
||||
void CG_DrawSmallString( int x, int y, const char *s, float alpha ) {
|
||||
float color[4];
|
||||
|
||||
color[0] = color[1] = color[2] = 1.0;
|
||||
color[3] = alpha;
|
||||
CG_DrawStringExt( x, y, s, color, qfalse, qfalse, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );
|
||||
}
|
||||
|
||||
void CG_DrawSmallStringColor( int x, int y, const char *s, vec4_t color ) {
|
||||
CG_DrawStringExt( x, y, s, color, qtrue, qfalse, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CG_DrawStrlen
|
||||
|
||||
Returns character count, skiping color escape codes
|
||||
=================
|
||||
*/
|
||||
int CG_DrawStrlen( const char *str ) {
|
||||
const char *s = str;
|
||||
int count = 0;
|
||||
|
||||
while ( *s ) {
|
||||
if ( Q_IsColorString( s ) ) {
|
||||
s += 2;
|
||||
} else {
|
||||
count++;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CG_TileClearBox
|
||||
|
||||
This repeats a 64*64 tile graphic to fill the screen around a sized down
|
||||
refresh window.
|
||||
=============
|
||||
*/
|
||||
static void CG_TileClearBox( int x, int y, int w, int h, qhandle_t hShader ) {
|
||||
float s1, t1, s2, t2;
|
||||
|
||||
s1 = x/64.0;
|
||||
t1 = y/64.0;
|
||||
s2 = (x+w)/64.0;
|
||||
t2 = (y+h)/64.0;
|
||||
trap_R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, hShader );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
CG_TileClear
|
||||
|
||||
Clear around a sized down screen
|
||||
==============
|
||||
*/
|
||||
void CG_TileClear( void ) {
|
||||
int top, bottom, left, right;
|
||||
int w, h;
|
||||
|
||||
w = cgs.glconfig.vidWidth;
|
||||
h = cgs.glconfig.vidHeight;
|
||||
|
||||
if ( cg.refdef.x == 0 && cg.refdef.y == 0 &&
|
||||
cg.refdef.width == w && cg.refdef.height == h ) {
|
||||
return; // full screen rendering
|
||||
}
|
||||
|
||||
top = cg.refdef.y;
|
||||
bottom = top + cg.refdef.height-1;
|
||||
left = cg.refdef.x;
|
||||
right = left + cg.refdef.width-1;
|
||||
|
||||
// clear above view screen
|
||||
CG_TileClearBox( 0, 0, w, top, cgs.media.backTileShader );
|
||||
|
||||
// clear below view screen
|
||||
CG_TileClearBox( 0, bottom, w, h - bottom, cgs.media.backTileShader );
|
||||
|
||||
// clear left of view screen
|
||||
CG_TileClearBox( 0, top, left, bottom - top + 1, cgs.media.backTileShader );
|
||||
|
||||
// clear right of view screen
|
||||
CG_TileClearBox( right, top, w - right, bottom - top + 1, cgs.media.backTileShader );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
CG_FadeColor
|
||||
================
|
||||
*/
|
||||
float *CG_FadeColor( int startMsec, int totalMsec ) {
|
||||
static vec4_t color;
|
||||
int t;
|
||||
|
||||
if ( startMsec == 0 ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
t = cg.time - startMsec;
|
||||
|
||||
if ( t >= totalMsec ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// fade out
|
||||
if ( totalMsec - t < FADE_TIME ) {
|
||||
color[3] = ( totalMsec - t ) * 1.0/FADE_TIME;
|
||||
} else {
|
||||
color[3] = 1.0;
|
||||
}
|
||||
color[0] = color[1] = color[2] = 1;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
CG_ColorForHealth
|
||||
=================
|
||||
*/
|
||||
void CG_ColorForGivenHealth( vec4_t hcolor, int health )
|
||||
{
|
||||
// set the color based on health
|
||||
hcolor[0] = 1.0;
|
||||
if ( health >= 100 )
|
||||
{
|
||||
hcolor[2] = 1.0;
|
||||
}
|
||||
else if ( health < 66 )
|
||||
{
|
||||
hcolor[2] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hcolor[2] = ( health - 66 ) / 33.0;
|
||||
}
|
||||
|
||||
if ( health > 60 )
|
||||
{
|
||||
hcolor[1] = 1.0;
|
||||
}
|
||||
else if ( health < 30 )
|
||||
{
|
||||
hcolor[1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hcolor[1] = ( health - 30 ) / 30.0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CG_ColorForHealth
|
||||
=================
|
||||
*/
|
||||
void CG_ColorForHealth( vec4_t hcolor )
|
||||
{
|
||||
int health;
|
||||
int count;
|
||||
int max;
|
||||
|
||||
// calculate the total points of damage that can
|
||||
// be sustained at the current health / armor level
|
||||
health = cg.snap->ps.stats[STAT_HEALTH];
|
||||
|
||||
if ( health <= 0 )
|
||||
{
|
||||
VectorClear( hcolor ); // black
|
||||
hcolor[3] = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
count = cg.snap->ps.stats[STAT_ARMOR];
|
||||
max = health * ARMOR_PROTECTION / ( 1.0 - ARMOR_PROTECTION );
|
||||
if ( max < count )
|
||||
{
|
||||
count = max;
|
||||
}
|
||||
health += count;
|
||||
|
||||
hcolor[3] = 1.0;
|
||||
CG_ColorForGivenHealth( hcolor, health );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
CG_DrawNumField
|
||||
|
||||
Take x,y positions as if 640 x 480 and scales them to the proper resolution
|
||||
|
||||
==============
|
||||
*/
|
||||
void CG_DrawNumField (int x, int y, int width, int value,int charWidth,int charHeight,int style,qboolean zeroFill)
|
||||
{
|
||||
char num[16], *ptr;
|
||||
int l;
|
||||
int frame;
|
||||
int xWidth;
|
||||
int i = 0;
|
||||
|
||||
if (width < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// draw number string
|
||||
if (width > 5) {
|
||||
width = 5;
|
||||
}
|
||||
|
||||
switch ( width ) {
|
||||
case 1:
|
||||
value = value > 9 ? 9 : value;
|
||||
value = value < 0 ? 0 : value;
|
||||
break;
|
||||
case 2:
|
||||
value = value > 99 ? 99 : value;
|
||||
value = value < -9 ? -9 : value;
|
||||
break;
|
||||
case 3:
|
||||
value = value > 999 ? 999 : value;
|
||||
value = value < -99 ? -99 : value;
|
||||
break;
|
||||
case 4:
|
||||
value = value > 9999 ? 9999 : value;
|
||||
value = value < -999 ? -999 : value;
|
||||
break;
|
||||
}
|
||||
|
||||
Com_sprintf (num, sizeof(num), "%i", value);
|
||||
l = strlen(num);
|
||||
if (l > width)
|
||||
l = width;
|
||||
|
||||
// FIXME: Might need to do something different for the chunky font??
|
||||
switch(style)
|
||||
{
|
||||
case NUM_FONT_SMALL:
|
||||
xWidth = charWidth;
|
||||
break;
|
||||
case NUM_FONT_CHUNKY:
|
||||
xWidth = (charWidth/1.2f) + 2;
|
||||
break;
|
||||
default:
|
||||
case NUM_FONT_BIG:
|
||||
xWidth = (charWidth/2) + 7;//(charWidth/6);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( zeroFill )
|
||||
{
|
||||
for (i = 0; i < (width - l); i++ )
|
||||
{
|
||||
switch(style)
|
||||
{
|
||||
case NUM_FONT_SMALL:
|
||||
CG_DrawPic( x,y, charWidth, charHeight, cgs.media.smallnumberShaders[0] );
|
||||
break;
|
||||
case NUM_FONT_CHUNKY:
|
||||
CG_DrawPic( x,y, charWidth, charHeight, cgs.media.chunkyNumberShaders[0] );
|
||||
break;
|
||||
default:
|
||||
case NUM_FONT_BIG:
|
||||
CG_DrawPic( x,y, charWidth, charHeight, cgs.media.numberShaders[0] );
|
||||
break;
|
||||
}
|
||||
x += 2 + (xWidth);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x += 2 + (xWidth)*(width - l);
|
||||
}
|
||||
|
||||
ptr = num;
|
||||
while (*ptr && l)
|
||||
{
|
||||
if (*ptr == '-')
|
||||
frame = STAT_MINUS;
|
||||
else
|
||||
frame = *ptr -'0';
|
||||
|
||||
switch(style)
|
||||
{
|
||||
case NUM_FONT_SMALL:
|
||||
CG_DrawPic( x,y, charWidth, charHeight, cgs.media.smallnumberShaders[frame] );
|
||||
x++; // For a one line gap
|
||||
break;
|
||||
case NUM_FONT_CHUNKY:
|
||||
CG_DrawPic( x,y, charWidth, charHeight, cgs.media.chunkyNumberShaders[frame] );
|
||||
break;
|
||||
default:
|
||||
case NUM_FONT_BIG:
|
||||
CG_DrawPic( x,y, charWidth, charHeight, cgs.media.numberShaders[frame] );
|
||||
break;
|
||||
}
|
||||
|
||||
x += (xWidth);
|
||||
ptr++;
|
||||
l--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "../ui/ui_shared.h" // for some text style junk
|
||||
void UI_DrawProportionalString( int x, int y, const char* str, int style, vec4_t color )
|
||||
{
|
||||
// having all these different style defines (1 for UI, one for CG, and now one for the re->font stuff)
|
||||
// is dumb, but for now...
|
||||
//
|
||||
int iStyle = 0;
|
||||
int iMenuFont = (style & UI_SMALLFONT) ? FONT_SMALL : FONT_MEDIUM;
|
||||
|
||||
switch (style & (UI_LEFT|UI_CENTER|UI_RIGHT))
|
||||
{
|
||||
default:
|
||||
case UI_LEFT:
|
||||
{
|
||||
// nada...
|
||||
}
|
||||
break;
|
||||
|
||||
case UI_CENTER:
|
||||
{
|
||||
x -= CG_Text_Width(str, 1.0, iMenuFont) / 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case UI_RIGHT:
|
||||
{
|
||||
x -= CG_Text_Width(str, 1.0, iMenuFont) / 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (style & UI_DROPSHADOW)
|
||||
{
|
||||
iStyle = ITEM_TEXTSTYLE_SHADOWED;
|
||||
}
|
||||
else
|
||||
if ( style & (UI_BLINK|UI_PULSE) )
|
||||
{
|
||||
iStyle = ITEM_TEXTSTYLE_BLINK;
|
||||
}
|
||||
|
||||
CG_Text_Paint(x, y, 1.0, color, str, 0, 0, iStyle, iMenuFont);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
1325
CODEmp/cgame/cg_effects.c
Normal file
1325
CODEmp/cgame/cg_effects.c
Normal file
File diff suppressed because it is too large
Load diff
2576
CODEmp/cgame/cg_ents.c
Normal file
2576
CODEmp/cgame/cg_ents.c
Normal file
File diff suppressed because it is too large
Load diff
2071
CODEmp/cgame/cg_event.c
Normal file
2071
CODEmp/cgame/cg_event.c
Normal file
File diff suppressed because it is too large
Load diff
350
CODEmp/cgame/cg_info.c
Normal file
350
CODEmp/cgame/cg_info.c
Normal file
|
@ -0,0 +1,350 @@
|
|||
// Copyright (C) 1999-2000 Id Software, Inc.
|
||||
//
|
||||
// cg_info.c -- display information while data is being loading
|
||||
|
||||
#include "cg_local.h"
|
||||
|
||||
#define MAX_LOADING_PLAYER_ICONS 16
|
||||
#define MAX_LOADING_ITEM_ICONS 26
|
||||
|
||||
static int loadingPlayerIconCount;
|
||||
static int loadingItemIconCount;
|
||||
static qhandle_t loadingPlayerIcons[MAX_LOADING_PLAYER_ICONS];
|
||||
static qhandle_t loadingItemIcons[MAX_LOADING_ITEM_ICONS];
|
||||
|
||||
void CG_LoadBar(void);
|
||||
|
||||
/*
|
||||
===================
|
||||
CG_DrawLoadingIcons
|
||||
===================
|
||||
*/
|
||||
static void CG_DrawLoadingIcons( void ) {
|
||||
int n;
|
||||
int x, y;
|
||||
|
||||
for( n = 0; n < loadingPlayerIconCount; n++ ) {
|
||||
x = 16 + n * 78;
|
||||
y = 324-40;
|
||||
CG_DrawPic( x, y, 64, 64, loadingPlayerIcons[n] );
|
||||
}
|
||||
|
||||
for( n = 0; n < loadingItemIconCount; n++ ) {
|
||||
y = 400-40;
|
||||
if( n >= 13 ) {
|
||||
y += 40;
|
||||
}
|
||||
x = 16 + n % 13 * 48;
|
||||
CG_DrawPic( x, y, 32, 32, loadingItemIcons[n] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
======================
|
||||
CG_LoadingString
|
||||
|
||||
======================
|
||||
*/
|
||||
void CG_LoadingString( const char *s ) {
|
||||
Q_strncpyz( cg.infoScreenText, s, sizeof( cg.infoScreenText ) );
|
||||
|
||||
trap_UpdateScreen();
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
CG_LoadingItem
|
||||
===================
|
||||
*/
|
||||
void CG_LoadingItem( int itemNum ) {
|
||||
gitem_t *item;
|
||||
|
||||
item = &bg_itemlist[itemNum];
|
||||
|
||||
if ( item->icon && loadingItemIconCount < MAX_LOADING_ITEM_ICONS ) {
|
||||
loadingItemIcons[loadingItemIconCount++] = trap_R_RegisterShaderNoMip( item->icon );
|
||||
}
|
||||
|
||||
CG_LoadingString( item->pickup_name );
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
CG_LoadingClient
|
||||
===================
|
||||
*/
|
||||
void CG_LoadingClient( int clientNum ) {
|
||||
const char *info;
|
||||
char *skin;
|
||||
char personality[MAX_QPATH];
|
||||
char model[MAX_QPATH];
|
||||
char iconName[MAX_QPATH];
|
||||
|
||||
info = CG_ConfigString( CS_PLAYERS + clientNum );
|
||||
|
||||
if ( loadingPlayerIconCount < MAX_LOADING_PLAYER_ICONS ) {
|
||||
Q_strncpyz( model, Info_ValueForKey( info, "model" ), sizeof( model ) );
|
||||
skin = Q_strrchr( model, '/' );
|
||||
if ( skin ) {
|
||||
*skin++ = '\0';
|
||||
} else {
|
||||
skin = "default";
|
||||
}
|
||||
|
||||
Com_sprintf( iconName, MAX_QPATH, "models/players/%s/icon_%s.tga", model, skin );
|
||||
|
||||
loadingPlayerIcons[loadingPlayerIconCount] = trap_R_RegisterShaderNoMip( iconName );
|
||||
if ( !loadingPlayerIcons[loadingPlayerIconCount] ) {
|
||||
Com_sprintf( iconName, MAX_QPATH, "models/players/characters/%s/icon_%s.tga", model, skin );
|
||||
loadingPlayerIcons[loadingPlayerIconCount] = trap_R_RegisterShaderNoMip( iconName );
|
||||
}
|
||||
if ( !loadingPlayerIcons[loadingPlayerIconCount] ) {
|
||||
Com_sprintf( iconName, MAX_QPATH, "models/players/%s/icon_%s.tga", DEFAULT_MODEL, "default" );
|
||||
loadingPlayerIcons[loadingPlayerIconCount] = trap_R_RegisterShaderNoMip( iconName );
|
||||
}
|
||||
if ( loadingPlayerIcons[loadingPlayerIconCount] ) {
|
||||
loadingPlayerIconCount++;
|
||||
}
|
||||
}
|
||||
|
||||
Q_strncpyz( personality, Info_ValueForKey( info, "n" ), sizeof(personality) );
|
||||
Q_CleanStr( personality );
|
||||
|
||||
/*
|
||||
if( cgs.gametype == GT_SINGLE_PLAYER ) {
|
||||
trap_S_RegisterSound( va( "sound/player/announce/%s.wav", personality ));
|
||||
}
|
||||
*/
|
||||
|
||||
CG_LoadingString( personality );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
CG_DrawInformation
|
||||
|
||||
Draw all the status / pacifier stuff during level loading
|
||||
====================
|
||||
*/
|
||||
void CG_DrawInformation( void ) {
|
||||
const char *s;
|
||||
const char *info;
|
||||
const char *sysInfo;
|
||||
int y;
|
||||
int value, valueNOFP;
|
||||
qhandle_t levelshot;
|
||||
char buf[1024];
|
||||
|
||||
info = CG_ConfigString( CS_SERVERINFO );
|
||||
sysInfo = CG_ConfigString( CS_SYSTEMINFO );
|
||||
|
||||
s = Info_ValueForKey( info, "mapname" );
|
||||
levelshot = trap_R_RegisterShaderNoMip( va( "levelshots/%s", s ) );
|
||||
if ( !levelshot ) {
|
||||
levelshot = trap_R_RegisterShaderNoMip( "menu/art/unknownmap" );
|
||||
}
|
||||
trap_R_SetColor( NULL );
|
||||
CG_DrawPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, levelshot );
|
||||
|
||||
CG_LoadBar();
|
||||
|
||||
// draw the icons of things as they are loaded
|
||||
// CG_DrawLoadingIcons();
|
||||
|
||||
// the first 150 rows are reserved for the client connection
|
||||
// screen to write into
|
||||
if ( cg.infoScreenText[0] ) {
|
||||
UI_DrawProportionalString( 320, 128-32, va("Loading... %s", cg.infoScreenText),
|
||||
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
|
||||
} else {
|
||||
UI_DrawProportionalString( 320, 128-32, "Awaiting snapshot...",
|
||||
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
|
||||
}
|
||||
|
||||
// draw info string information
|
||||
|
||||
y = 180-32;
|
||||
|
||||
// don't print server lines if playing a local game
|
||||
trap_Cvar_VariableStringBuffer( "sv_running", buf, sizeof( buf ) );
|
||||
if ( !atoi( buf ) ) {
|
||||
// server hostname
|
||||
Q_strncpyz(buf, Info_ValueForKey( info, "sv_hostname" ), 1024);
|
||||
Q_CleanStr(buf);
|
||||
UI_DrawProportionalString( 320, y, buf,
|
||||
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
|
||||
y += PROP_HEIGHT;
|
||||
|
||||
// pure server
|
||||
s = Info_ValueForKey( sysInfo, "sv_pure" );
|
||||
if ( s[0] == '1' ) {
|
||||
UI_DrawProportionalString( 320, y, "Pure Server",
|
||||
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
|
||||
y += PROP_HEIGHT;
|
||||
}
|
||||
|
||||
// server-specific message of the day
|
||||
s = CG_ConfigString( CS_MOTD );
|
||||
if ( s[0] ) {
|
||||
UI_DrawProportionalString( 320, y, s,
|
||||
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
|
||||
y += PROP_HEIGHT;
|
||||
}
|
||||
|
||||
// some extra space after hostname and motd
|
||||
y += 10;
|
||||
}
|
||||
|
||||
// map-specific message (long map name)
|
||||
s = CG_ConfigString( CS_MESSAGE );
|
||||
if ( s[0] ) {
|
||||
UI_DrawProportionalString( 320, y, s,
|
||||
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
|
||||
y += PROP_HEIGHT;
|
||||
}
|
||||
|
||||
// cheats warning
|
||||
s = Info_ValueForKey( sysInfo, "sv_cheats" );
|
||||
if ( s[0] == '1' ) {
|
||||
UI_DrawProportionalString( 320, y, va("%s", (char *)CG_GetStripEdString("INGAMETEXT", "CHEATSAREENABLED")),
|
||||
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
|
||||
y += PROP_HEIGHT;
|
||||
}
|
||||
|
||||
// game type
|
||||
switch ( cgs.gametype ) {
|
||||
case GT_FFA:
|
||||
s = "Free For All";
|
||||
break;
|
||||
case GT_HOLOCRON:
|
||||
s = "Holocron FFA";
|
||||
break;
|
||||
case GT_JEDIMASTER:
|
||||
s = "Jedi Master";
|
||||
break;
|
||||
case GT_SINGLE_PLAYER:
|
||||
s = "Single Player";
|
||||
break;
|
||||
case GT_TOURNAMENT:
|
||||
s = "Duel";
|
||||
break;
|
||||
case GT_TEAM:
|
||||
s = "Team FFA";
|
||||
break;
|
||||
case GT_SAGA:
|
||||
s = "Saga";
|
||||
break;
|
||||
case GT_CTF:
|
||||
s = "Capture The Flag";
|
||||
break;
|
||||
case GT_CTY:
|
||||
s = "Capture The Ysalimari";
|
||||
break;
|
||||
default:
|
||||
s = "Unknown Gametype";
|
||||
break;
|
||||
}
|
||||
UI_DrawProportionalString( 320, y, s,
|
||||
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
|
||||
y += PROP_HEIGHT;
|
||||
|
||||
value = atoi( Info_ValueForKey( info, "timelimit" ) );
|
||||
if ( value ) {
|
||||
UI_DrawProportionalString( 320, y, va( "%s %i", (char *)CG_GetStripEdString("INGAMETEXT", "TIMELIMIT"), value ),
|
||||
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
|
||||
y += PROP_HEIGHT;
|
||||
}
|
||||
|
||||
if (cgs.gametype < GT_CTF ) {
|
||||
value = atoi( Info_ValueForKey( info, "fraglimit" ) );
|
||||
if ( value ) {
|
||||
UI_DrawProportionalString( 320, y, va( "%s %i", (char *)CG_GetStripEdString("INGAMETEXT", "FRAGLIMIT"), value ),
|
||||
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
|
||||
y += PROP_HEIGHT;
|
||||
}
|
||||
|
||||
if (cgs.gametype == GT_TOURNAMENT)
|
||||
{
|
||||
value = atoi( Info_ValueForKey( info, "duel_fraglimit" ) );
|
||||
if ( value ) {
|
||||
UI_DrawProportionalString( 320, y, va( "%s %i", (char *)CG_GetStripEdString("INGAMETEXT", "WINLIMIT"), value ),
|
||||
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
|
||||
y += PROP_HEIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cgs.gametype >= GT_CTF) {
|
||||
value = atoi( Info_ValueForKey( info, "capturelimit" ) );
|
||||
if ( value ) {
|
||||
UI_DrawProportionalString( 320, y, va( "%s %i", (char *)CG_GetStripEdString("INGAMETEXT", "CAPTURELIMIT"), value ),
|
||||
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
|
||||
y += PROP_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
if (cgs.gametype >= GT_TEAM)
|
||||
{
|
||||
value = atoi( Info_ValueForKey( info, "g_forceBasedTeams" ) );
|
||||
if ( value ) {
|
||||
UI_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStripEdString("INGAMETEXT", "FORCEBASEDTEAMS") ),
|
||||
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
|
||||
y += PROP_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
valueNOFP = atoi( Info_ValueForKey( info, "g_forcePowerDisable" ) );
|
||||
|
||||
value = atoi( Info_ValueForKey( info, "g_maxForceRank" ) );
|
||||
if ( value && !valueNOFP ) {
|
||||
UI_DrawProportionalString( 320, y, va( "%s %i", (char *)CG_GetStripEdString("INGAMETEXT", "MAXFORCERANK"), value ),
|
||||
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
|
||||
y += PROP_HEIGHT;
|
||||
}
|
||||
else if (!valueNOFP)
|
||||
{
|
||||
UI_DrawProportionalString( 320, y, va( "%s 20", (char *)CG_GetStripEdString("INGAMETEXT", "MAXFORCERANK") ),
|
||||
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
|
||||
y += PROP_HEIGHT;
|
||||
}
|
||||
|
||||
value = atoi( Info_ValueForKey( info, "g_weaponDisable" ) );
|
||||
if ( cgs.gametype != GT_JEDIMASTER && value ) {
|
||||
UI_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStripEdString("INGAMETEXT", "SABERONLYSET") ),
|
||||
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
|
||||
y += PROP_HEIGHT;
|
||||
}
|
||||
|
||||
if ( valueNOFP ) {
|
||||
UI_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStripEdString("INGAMETEXT", "NOFPSET") ),
|
||||
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
|
||||
y += PROP_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
CG_LoadBar
|
||||
===================
|
||||
*/
|
||||
void CG_LoadBar(void)
|
||||
{
|
||||
int x,y,i,xLength,height,pad;
|
||||
|
||||
y = 442;
|
||||
pad = 5;
|
||||
x = 202 + pad;
|
||||
height = 12;
|
||||
xLength = 21;
|
||||
|
||||
trap_R_SetColor( colorWhite );
|
||||
CG_DrawPic(166,428,640-(164*2), 32, cgs.media.loadBarLEDSurround);
|
||||
|
||||
for (i=0;i < cg.loadLCARSStage;i++)
|
||||
{
|
||||
CG_DrawPic(x + (i*pad) + (i*xLength),y, 32, 8, cgs.media.loadBarLED);
|
||||
}
|
||||
}
|
||||
|
85
CODEmp/cgame/cg_light.c
Normal file
85
CODEmp/cgame/cg_light.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
#include "cg_local.h"
|
||||
|
||||
#if !defined(CG_LIGHTS_H_INC)
|
||||
#include "cg_lights.h"
|
||||
#endif
|
||||
|
||||
static clightstyle_t cl_lightstyle[MAX_LIGHT_STYLES];
|
||||
static int lastofs;
|
||||
|
||||
/*
|
||||
================
|
||||
FX_ClearLightStyles
|
||||
================
|
||||
*/
|
||||
void CG_ClearLightStyles (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset (cl_lightstyle, 0, sizeof(cl_lightstyle));
|
||||
lastofs = -1;
|
||||
|
||||
for(i=0;i<MAX_LIGHT_STYLES*3;i++)
|
||||
{
|
||||
CG_SetLightstyle (i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FX_RunLightStyles
|
||||
================
|
||||
*/
|
||||
void CG_RunLightStyles (void)
|
||||
{
|
||||
int ofs;
|
||||
int i;
|
||||
clightstyle_t *ls;
|
||||
|
||||
ofs = cg.time / 50;
|
||||
// if (ofs == lastofs)
|
||||
// return;
|
||||
lastofs = ofs;
|
||||
|
||||
for (i=0,ls=cl_lightstyle ; i<MAX_LIGHT_STYLES ; i++, ls++)
|
||||
{
|
||||
if (!ls->length)
|
||||
{
|
||||
ls->value[0] = ls->value[1] = ls->value[2] = ls->value[3] = 255;
|
||||
}
|
||||
else if (ls->length == 1)
|
||||
{
|
||||
ls->value[0] = ls->map[0][0];
|
||||
ls->value[1] = ls->map[0][1];
|
||||
ls->value[2] = ls->map[0][2];
|
||||
ls->value[3] = 255; //ls->map[0][3];
|
||||
}
|
||||
else
|
||||
{
|
||||
ls->value[0] = ls->map[ofs%ls->length][0];
|
||||
ls->value[1] = ls->map[ofs%ls->length][1];
|
||||
ls->value[2] = ls->map[ofs%ls->length][2];
|
||||
ls->value[3] = 255; //ls->map[ofs%ls->length][3];
|
||||
}
|
||||
trap_R_SetLightStyle(i, *(int*)ls->value);
|
||||
}
|
||||
}
|
||||
|
||||
void CG_SetLightstyle (int i)
|
||||
{
|
||||
const char *s;
|
||||
int j, k;
|
||||
|
||||
s = CG_ConfigString( i+CS_LIGHT_STYLES );
|
||||
j = strlen (s);
|
||||
if (j >= MAX_QPATH)
|
||||
{
|
||||
Com_Error (ERR_DROP, "svc_lightstyle length=%i", j);
|
||||
}
|
||||
|
||||
cl_lightstyle[(i/3)].length = j;
|
||||
for (k=0 ; k<j ; k++)
|
||||
{
|
||||
cl_lightstyle[(i/3)].map[k][(i%3)] = (float)(s[k]-'a')/(float)('z'-'a') * 255.0;
|
||||
}
|
||||
}
|
16
CODEmp/cgame/cg_lights.h
Normal file
16
CODEmp/cgame/cg_lights.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#if !defined(CG_LIGHTS_H_INC)
|
||||
#define CG_LIGHTS_H_INC
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int length;
|
||||
color4ub_t value;
|
||||
color4ub_t map[MAX_QPATH];
|
||||
} clightstyle_t;
|
||||
|
||||
void CG_ClearLightStyles (void);
|
||||
void CG_RunLightStyles (void);
|
||||
void CG_SetLightstyle (int i);
|
||||
|
||||
#endif // CG_LIGHTS_H_INC
|
2158
CODEmp/cgame/cg_local.h
Normal file
2158
CODEmp/cgame/cg_local.h
Normal file
File diff suppressed because it is too large
Load diff
861
CODEmp/cgame/cg_localents.c
Normal file
861
CODEmp/cgame/cg_localents.c
Normal file
|
@ -0,0 +1,861 @@
|
|||
// Copyright (C) 1999-2000 Id Software, Inc.
|
||||
//
|
||||
|
||||
// cg_localents.c -- every frame, generate renderer commands for locally
|
||||
// processed entities, like smoke puffs, gibs, shells, etc.
|
||||
|
||||
#include "cg_local.h"
|
||||
|
||||
#define MAX_LOCAL_ENTITIES 512
|
||||
localEntity_t cg_localEntities[MAX_LOCAL_ENTITIES];
|
||||
localEntity_t cg_activeLocalEntities; // double linked list
|
||||
localEntity_t *cg_freeLocalEntities; // single linked list
|
||||
|
||||
/*
|
||||
===================
|
||||
CG_InitLocalEntities
|
||||
|
||||
This is called at startup and for tournement restarts
|
||||
===================
|
||||
*/
|
||||
void CG_InitLocalEntities( void ) {
|
||||
int i;
|
||||
|
||||
memset( cg_localEntities, 0, sizeof( cg_localEntities ) );
|
||||
cg_activeLocalEntities.next = &cg_activeLocalEntities;
|
||||
cg_activeLocalEntities.prev = &cg_activeLocalEntities;
|
||||
cg_freeLocalEntities = cg_localEntities;
|
||||
for ( i = 0 ; i < MAX_LOCAL_ENTITIES - 1 ; i++ ) {
|
||||
cg_localEntities[i].next = &cg_localEntities[i+1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
CG_FreeLocalEntity
|
||||
==================
|
||||
*/
|
||||
void CG_FreeLocalEntity( localEntity_t *le ) {
|
||||
if ( !le->prev ) {
|
||||
CG_Error( "CG_FreeLocalEntity: not active" );
|
||||
}
|
||||
|
||||
// remove from the doubly linked active list
|
||||
le->prev->next = le->next;
|
||||
le->next->prev = le->prev;
|
||||
|
||||
// the free list is only singly linked
|
||||
le->next = cg_freeLocalEntities;
|
||||
cg_freeLocalEntities = le;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
CG_AllocLocalEntity
|
||||
|
||||
Will allways succeed, even if it requires freeing an old active entity
|
||||
===================
|
||||
*/
|
||||
localEntity_t *CG_AllocLocalEntity( void ) {
|
||||
localEntity_t *le;
|
||||
|
||||
if ( !cg_freeLocalEntities ) {
|
||||
// no free entities, so free the one at the end of the chain
|
||||
// remove the oldest active entity
|
||||
CG_FreeLocalEntity( cg_activeLocalEntities.prev );
|
||||
}
|
||||
|
||||
le = cg_freeLocalEntities;
|
||||
cg_freeLocalEntities = cg_freeLocalEntities->next;
|
||||
|
||||
memset( le, 0, sizeof( *le ) );
|
||||
|
||||
// link into the active list
|
||||
le->next = cg_activeLocalEntities.next;
|
||||
le->prev = &cg_activeLocalEntities;
|
||||
cg_activeLocalEntities.next->prev = le;
|
||||
cg_activeLocalEntities.next = le;
|
||||
return le;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================================================================================
|
||||
|
||||
FRAGMENT PROCESSING
|
||||
|
||||
A fragment localentity interacts with the environment in some way (hitting walls),
|
||||
or generates more localentities along a trail.
|
||||
|
||||
====================================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
================
|
||||
CG_BloodTrail
|
||||
|
||||
Leave expanding blood puffs behind gibs
|
||||
================
|
||||
*/
|
||||
void CG_BloodTrail( localEntity_t *le ) {
|
||||
int t;
|
||||
int t2;
|
||||
int step;
|
||||
vec3_t newOrigin;
|
||||
localEntity_t *blood;
|
||||
|
||||
step = 150;
|
||||
t = step * ( (cg.time - cg.frametime + step ) / step );
|
||||
t2 = step * ( cg.time / step );
|
||||
|
||||
for ( ; t <= t2; t += step ) {
|
||||
BG_EvaluateTrajectory( &le->pos, t, newOrigin );
|
||||
|
||||
blood = CG_SmokePuff( newOrigin, vec3_origin,
|
||||
20, // radius
|
||||
1, 1, 1, 1, // color
|
||||
2000, // trailTime
|
||||
t, // startTime
|
||||
0, // fadeInTime
|
||||
0, // flags
|
||||
cgs.media.bloodTrailShader );
|
||||
// use the optimized version
|
||||
blood->leType = LE_FALL_SCALE_FADE;
|
||||
// drop a total of 40 units over its lifetime
|
||||
blood->pos.trDelta[2] = 40;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
CG_FragmentBounceMark
|
||||
================
|
||||
*/
|
||||
void CG_FragmentBounceMark( localEntity_t *le, trace_t *trace ) {
|
||||
int radius;
|
||||
|
||||
if ( le->leMarkType == LEMT_BLOOD ) {
|
||||
|
||||
radius = 16 + (rand()&31);
|
||||
CG_ImpactMark( cgs.media.bloodMarkShader, trace->endpos, trace->plane.normal, random()*360,
|
||||
1,1,1,1, qtrue, radius, qfalse );
|
||||
} else if ( le->leMarkType == LEMT_BURN ) {
|
||||
|
||||
radius = 8 + (rand()&15);
|
||||
CG_ImpactMark( cgs.media.burnMarkShader, trace->endpos, trace->plane.normal, random()*360,
|
||||
1,1,1,1, qtrue, radius, qfalse );
|
||||
}
|
||||
|
||||
|
||||
// don't allow a fragment to make multiple marks, or they
|
||||
// pile up while settling
|
||||
le->leMarkType = LEMT_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CG_FragmentBounceSound
|
||||
================
|
||||
*/
|
||||
void CG_FragmentBounceSound( localEntity_t *le, trace_t *trace ) {
|
||||
if ( le->leBounceSoundType == LEBS_BLOOD ) {
|
||||
// half the gibs will make splat sounds
|
||||
/*
|
||||
if ( rand() & 1 ) {
|
||||
int r = rand()&3;
|
||||
sfxHandle_t s;
|
||||
|
||||
if ( r == 0 ) {
|
||||
s = cgs.media.gibBounce1Sound;
|
||||
} else if ( r == 1 ) {
|
||||
s = cgs.media.gibBounce2Sound;
|
||||
} else {
|
||||
s = cgs.media.gibBounce3Sound;
|
||||
}
|
||||
trap_S_StartSound( trace->endpos, ENTITYNUM_WORLD, CHAN_AUTO, s );
|
||||
|
||||
}
|
||||
*/
|
||||
} else if ( le->leBounceSoundType == LEBS_BRASS ) {
|
||||
|
||||
}
|
||||
|
||||
// don't allow a fragment to make multiple bounce sounds,
|
||||
// or it gets too noisy as they settle
|
||||
le->leBounceSoundType = LEBS_NONE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
CG_ReflectVelocity
|
||||
================
|
||||
*/
|
||||
void CG_ReflectVelocity( localEntity_t *le, trace_t *trace ) {
|
||||
vec3_t velocity;
|
||||
float dot;
|
||||
int hitTime;
|
||||
|
||||
// reflect the velocity on the trace plane
|
||||
hitTime = cg.time - cg.frametime + cg.frametime * trace->fraction;
|
||||
BG_EvaluateTrajectoryDelta( &le->pos, hitTime, velocity );
|
||||
dot = DotProduct( velocity, trace->plane.normal );
|
||||
VectorMA( velocity, -2*dot, trace->plane.normal, le->pos.trDelta );
|
||||
|
||||
VectorScale( le->pos.trDelta, le->bounceFactor, le->pos.trDelta );
|
||||
|
||||
VectorCopy( trace->endpos, le->pos.trBase );
|
||||
le->pos.trTime = cg.time;
|
||||
|
||||
// check for stop, making sure that even on low FPS systems it doesn't bobble
|
||||
if ( trace->allsolid ||
|
||||
( trace->plane.normal[2] > 0 &&
|
||||
( le->pos.trDelta[2] < 40 || le->pos.trDelta[2] < -cg.frametime * le->pos.trDelta[2] ) ) ) {
|
||||
le->pos.trType = TR_STATIONARY;
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CG_AddFragment
|
||||
================
|
||||
*/
|
||||
void CG_AddFragment( localEntity_t *le ) {
|
||||
vec3_t newOrigin;
|
||||
trace_t trace;
|
||||
|
||||
if (le->forceAlpha)
|
||||
{
|
||||
le->refEntity.renderfx |= RF_FORCE_ENT_ALPHA;
|
||||
le->refEntity.shaderRGBA[3] = le->forceAlpha;
|
||||
}
|
||||
|
||||
if ( le->pos.trType == TR_STATIONARY ) {
|
||||
// sink into the ground if near the removal time
|
||||
int t;
|
||||
float t_e;
|
||||
|
||||
t = le->endTime - cg.time;
|
||||
if ( t < (SINK_TIME*2) ) {
|
||||
le->refEntity.renderfx |= RF_FORCE_ENT_ALPHA;
|
||||
t_e = (float)((float)(le->endTime - cg.time)/(SINK_TIME*2));
|
||||
t_e = (int)((t_e)*255);
|
||||
|
||||
if (t_e > 255)
|
||||
{
|
||||
t_e = 255;
|
||||
}
|
||||
if (t_e < 1)
|
||||
{
|
||||
t_e = 1;
|
||||
}
|
||||
|
||||
if (le->refEntity.shaderRGBA[3] && t_e > le->refEntity.shaderRGBA[3])
|
||||
{
|
||||
t_e = le->refEntity.shaderRGBA[3];
|
||||
}
|
||||
|
||||
le->refEntity.shaderRGBA[3] = t_e;
|
||||
|
||||
trap_R_AddRefEntityToScene( &le->refEntity );
|
||||
} else {
|
||||
trap_R_AddRefEntityToScene( &le->refEntity );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// calculate new position
|
||||
BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin );
|
||||
|
||||
// trace a line from previous position to new position
|
||||
CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID );
|
||||
if ( trace.fraction == 1.0 ) {
|
||||
// still in free fall
|
||||
VectorCopy( newOrigin, le->refEntity.origin );
|
||||
|
||||
if ( le->leFlags & LEF_TUMBLE ) {
|
||||
vec3_t angles;
|
||||
|
||||
BG_EvaluateTrajectory( &le->angles, cg.time, angles );
|
||||
AnglesToAxis( angles, le->refEntity.axis );
|
||||
}
|
||||
|
||||
trap_R_AddRefEntityToScene( &le->refEntity );
|
||||
|
||||
// add a blood trail
|
||||
if ( le->leBounceSoundType == LEBS_BLOOD ) {
|
||||
CG_BloodTrail( le );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// if it is in a nodrop zone, remove it
|
||||
// this keeps gibs from waiting at the bottom of pits of death
|
||||
// and floating levels
|
||||
if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) {
|
||||
CG_FreeLocalEntity( le );
|
||||
return;
|
||||
}
|
||||
|
||||
if (!trace.startsolid)
|
||||
{
|
||||
// leave a mark
|
||||
CG_FragmentBounceMark( le, &trace );
|
||||
|
||||
// do a bouncy sound
|
||||
CG_FragmentBounceSound( le, &trace );
|
||||
|
||||
if (le->bounceSound)
|
||||
{ //specified bounce sound (debris)
|
||||
trap_S_StartSound(le->pos.trBase, ENTITYNUM_WORLD, CHAN_AUTO, le->bounceSound);
|
||||
}
|
||||
|
||||
// reflect the velocity on the trace plane
|
||||
CG_ReflectVelocity( le, &trace );
|
||||
|
||||
trap_R_AddRefEntityToScene( &le->refEntity );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================================================
|
||||
|
||||
TRIVIAL LOCAL ENTITIES
|
||||
|
||||
These only do simple scaling or modulation before passing to the renderer
|
||||
=====================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
====================
|
||||
CG_AddFadeRGB
|
||||
====================
|
||||
*/
|
||||
void CG_AddFadeRGB( localEntity_t *le ) {
|
||||
refEntity_t *re;
|
||||
float c;
|
||||
|
||||
re = &le->refEntity;
|
||||
|
||||
c = ( le->endTime - cg.time ) * le->lifeRate;
|
||||
c *= 0xff;
|
||||
|
||||
re->shaderRGBA[0] = le->color[0] * c;
|
||||
re->shaderRGBA[1] = le->color[1] * c;
|
||||
re->shaderRGBA[2] = le->color[2] * c;
|
||||
re->shaderRGBA[3] = le->color[3] * c;
|
||||
|
||||
trap_R_AddRefEntityToScene( re );
|
||||
}
|
||||
|
||||
static void CG_AddFadeScaleModel( localEntity_t *le )
|
||||
{
|
||||
refEntity_t *ent = &le->refEntity;
|
||||
|
||||
float frac = ( cg.time - le->startTime )/((float)( le->endTime - le->startTime ));
|
||||
|
||||
frac *= frac * frac; // yes, this is completely ridiculous...but it causes the shell to grow slowly then "explode" at the end
|
||||
|
||||
ent->nonNormalizedAxes = qtrue;
|
||||
|
||||
AxisCopy( axisDefault, ent->axis );
|
||||
|
||||
VectorScale( ent->axis[0], le->radius * frac, ent->axis[0] );
|
||||
VectorScale( ent->axis[1], le->radius * frac, ent->axis[1] );
|
||||
VectorScale( ent->axis[2], le->radius * 0.5f * frac, ent->axis[2] );
|
||||
|
||||
frac = 1.0f - frac;
|
||||
|
||||
ent->shaderRGBA[0] = le->color[0] * frac;
|
||||
ent->shaderRGBA[1] = le->color[1] * frac;
|
||||
ent->shaderRGBA[2] = le->color[2] * frac;
|
||||
ent->shaderRGBA[3] = le->color[3] * frac;
|
||||
|
||||
// add the entity
|
||||
trap_R_AddRefEntityToScene( ent );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CG_AddMoveScaleFade
|
||||
==================
|
||||
*/
|
||||
static void CG_AddMoveScaleFade( localEntity_t *le ) {
|
||||
refEntity_t *re;
|
||||
float c;
|
||||
vec3_t delta;
|
||||
float len;
|
||||
|
||||
re = &le->refEntity;
|
||||
|
||||
if ( le->fadeInTime > le->startTime && cg.time < le->fadeInTime ) {
|
||||
// fade / grow time
|
||||
c = 1.0 - (float) ( le->fadeInTime - cg.time ) / ( le->fadeInTime - le->startTime );
|
||||
}
|
||||
else {
|
||||
// fade / grow time
|
||||
c = ( le->endTime - cg.time ) * le->lifeRate;
|
||||
}
|
||||
|
||||
re->shaderRGBA[3] = 0xff * c * le->color[3];
|
||||
|
||||
if ( !( le->leFlags & LEF_PUFF_DONT_SCALE ) ) {
|
||||
re->radius = le->radius * ( 1.0 - c ) + 8;
|
||||
}
|
||||
|
||||
BG_EvaluateTrajectory( &le->pos, cg.time, re->origin );
|
||||
|
||||
// if the view would be "inside" the sprite, kill the sprite
|
||||
// so it doesn't add too much overdraw
|
||||
VectorSubtract( re->origin, cg.refdef.vieworg, delta );
|
||||
len = VectorLength( delta );
|
||||
if ( len < le->radius ) {
|
||||
CG_FreeLocalEntity( le );
|
||||
return;
|
||||
}
|
||||
|
||||
trap_R_AddRefEntityToScene( re );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CG_AddPuff
|
||||
==================
|
||||
*/
|
||||
static void CG_AddPuff( localEntity_t *le ) {
|
||||
refEntity_t *re;
|
||||
float c;
|
||||
vec3_t delta;
|
||||
float len;
|
||||
|
||||
re = &le->refEntity;
|
||||
|
||||
// fade / grow time
|
||||
c = ( le->endTime - cg.time ) / (float)( le->endTime - le->startTime );
|
||||
|
||||
re->shaderRGBA[0] = le->color[0] * c;
|
||||
re->shaderRGBA[1] = le->color[1] * c;
|
||||
re->shaderRGBA[2] = le->color[2] * c;
|
||||
|
||||
if ( !( le->leFlags & LEF_PUFF_DONT_SCALE ) ) {
|
||||
re->radius = le->radius * ( 1.0 - c ) + 8;
|
||||
}
|
||||
|
||||
BG_EvaluateTrajectory( &le->pos, cg.time, re->origin );
|
||||
|
||||
// if the view would be "inside" the sprite, kill the sprite
|
||||
// so it doesn't add too much overdraw
|
||||
VectorSubtract( re->origin, cg.refdef.vieworg, delta );
|
||||
len = VectorLength( delta );
|
||||
if ( len < le->radius ) {
|
||||
CG_FreeLocalEntity( le );
|
||||
return;
|
||||
}
|
||||
|
||||
trap_R_AddRefEntityToScene( re );
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
CG_AddScaleFade
|
||||
|
||||
For rocket smokes that hang in place, fade out, and are
|
||||
removed if the view passes through them.
|
||||
There are often many of these, so it needs to be simple.
|
||||
===================
|
||||
*/
|
||||
static void CG_AddScaleFade( localEntity_t *le ) {
|
||||
refEntity_t *re;
|
||||
float c;
|
||||
vec3_t delta;
|
||||
float len;
|
||||
|
||||
re = &le->refEntity;
|
||||
|
||||
// fade / grow time
|
||||
c = ( le->endTime - cg.time ) * le->lifeRate;
|
||||
|
||||
re->shaderRGBA[3] = 0xff * c * le->color[3];
|
||||
re->radius = le->radius * ( 1.0 - c ) + 8;
|
||||
|
||||
// if the view would be "inside" the sprite, kill the sprite
|
||||
// so it doesn't add too much overdraw
|
||||
VectorSubtract( re->origin, cg.refdef.vieworg, delta );
|
||||
len = VectorLength( delta );
|
||||
if ( len < le->radius ) {
|
||||
CG_FreeLocalEntity( le );
|
||||
return;
|
||||
}
|
||||
|
||||
trap_R_AddRefEntityToScene( re );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
CG_AddFallScaleFade
|
||||
|
||||
This is just an optimized CG_AddMoveScaleFade
|
||||
For blood mists that drift down, fade out, and are
|
||||
removed if the view passes through them.
|
||||
There are often 100+ of these, so it needs to be simple.
|
||||
=================
|
||||
*/
|
||||
static void CG_AddFallScaleFade( localEntity_t *le ) {
|
||||
refEntity_t *re;
|
||||
float c;
|
||||
vec3_t delta;
|
||||
float len;
|
||||
|
||||
re = &le->refEntity;
|
||||
|
||||
// fade time
|
||||
c = ( le->endTime - cg.time ) * le->lifeRate;
|
||||
|
||||
re->shaderRGBA[3] = 0xff * c * le->color[3];
|
||||
|
||||
re->origin[2] = le->pos.trBase[2] - ( 1.0 - c ) * le->pos.trDelta[2];
|
||||
|
||||
re->radius = le->radius * ( 1.0 - c ) + 16;
|
||||
|
||||
// if the view would be "inside" the sprite, kill the sprite
|
||||
// so it doesn't add too much overdraw
|
||||
VectorSubtract( re->origin, cg.refdef.vieworg, delta );
|
||||
len = VectorLength( delta );
|
||||
if ( len < le->radius ) {
|
||||
CG_FreeLocalEntity( le );
|
||||
return;
|
||||
}
|
||||
|
||||
trap_R_AddRefEntityToScene( re );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
CG_AddExplosion
|
||||
================
|
||||
*/
|
||||
static void CG_AddExplosion( localEntity_t *ex ) {
|
||||
refEntity_t *ent;
|
||||
|
||||
ent = &ex->refEntity;
|
||||
|
||||
// add the entity
|
||||
trap_R_AddRefEntityToScene(ent);
|
||||
|
||||
// add the dlight
|
||||
if ( ex->light ) {
|
||||
float light;
|
||||
|
||||
light = (float)( cg.time - ex->startTime ) / ( ex->endTime - ex->startTime );
|
||||
if ( light < 0.5 ) {
|
||||
light = 1.0;
|
||||
} else {
|
||||
light = 1.0 - ( light - 0.5 ) * 2;
|
||||
}
|
||||
light = ex->light * light;
|
||||
trap_R_AddLightToScene(ent->origin, light, ex->lightColor[0], ex->lightColor[1], ex->lightColor[2] );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CG_AddSpriteExplosion
|
||||
================
|
||||
*/
|
||||
static void CG_AddSpriteExplosion( localEntity_t *le ) {
|
||||
refEntity_t re;
|
||||
float c;
|
||||
|
||||
re = le->refEntity;
|
||||
|
||||
c = ( le->endTime - cg.time ) / ( float ) ( le->endTime - le->startTime );
|
||||
if ( c > 1 ) {
|
||||
c = 1.0; // can happen during connection problems
|
||||
}
|
||||
|
||||
re.shaderRGBA[0] = 0xff;
|
||||
re.shaderRGBA[1] = 0xff;
|
||||
re.shaderRGBA[2] = 0xff;
|
||||
re.shaderRGBA[3] = 0xff * c * 0.33;
|
||||
|
||||
re.reType = RT_SPRITE;
|
||||
re.radius = 42 * ( 1.0 - c ) + 30;
|
||||
|
||||
trap_R_AddRefEntityToScene( &re );
|
||||
|
||||
// add the dlight
|
||||
if ( le->light ) {
|
||||
float light;
|
||||
|
||||
light = (float)( cg.time - le->startTime ) / ( le->endTime - le->startTime );
|
||||
if ( light < 0.5 ) {
|
||||
light = 1.0;
|
||||
} else {
|
||||
light = 1.0 - ( light - 0.5 ) * 2;
|
||||
}
|
||||
light = le->light * light;
|
||||
trap_R_AddLightToScene(re.origin, light, le->lightColor[0], le->lightColor[1], le->lightColor[2] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
CG_AddRefEntity
|
||||
===================
|
||||
*/
|
||||
void CG_AddRefEntity( localEntity_t *le ) {
|
||||
if (le->endTime < cg.time) {
|
||||
CG_FreeLocalEntity( le );
|
||||
return;
|
||||
}
|
||||
trap_R_AddRefEntityToScene( &le->refEntity );
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
CG_AddScorePlum
|
||||
===================
|
||||
*/
|
||||
#define NUMBER_SIZE 8
|
||||
|
||||
void CG_AddScorePlum( localEntity_t *le ) {
|
||||
refEntity_t *re;
|
||||
vec3_t origin, delta, dir, vec, up = {0, 0, 1};
|
||||
float c, len;
|
||||
int i, score, digits[10], numdigits, negative;
|
||||
|
||||
re = &le->refEntity;
|
||||
|
||||
c = ( le->endTime - cg.time ) * le->lifeRate;
|
||||
|
||||
score = le->radius;
|
||||
if (score < 0) {
|
||||
re->shaderRGBA[0] = 0xff;
|
||||
re->shaderRGBA[1] = 0x11;
|
||||
re->shaderRGBA[2] = 0x11;
|
||||
}
|
||||
else {
|
||||
re->shaderRGBA[0] = 0xff;
|
||||
re->shaderRGBA[1] = 0xff;
|
||||
re->shaderRGBA[2] = 0xff;
|
||||
if (score >= 50) {
|
||||
re->shaderRGBA[1] = 0;
|
||||
} else if (score >= 20) {
|
||||
re->shaderRGBA[0] = re->shaderRGBA[1] = 0;
|
||||
} else if (score >= 10) {
|
||||
re->shaderRGBA[2] = 0;
|
||||
} else if (score >= 2) {
|
||||
re->shaderRGBA[0] = re->shaderRGBA[2] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
if (c < 0.25)
|
||||
re->shaderRGBA[3] = 0xff * 4 * c;
|
||||
else
|
||||
re->shaderRGBA[3] = 0xff;
|
||||
|
||||
re->radius = NUMBER_SIZE / 2;
|
||||
|
||||
VectorCopy(le->pos.trBase, origin);
|
||||
origin[2] += 110 - c * 100;
|
||||
|
||||
VectorSubtract(cg.refdef.vieworg, origin, dir);
|
||||
CrossProduct(dir, up, vec);
|
||||
VectorNormalize(vec);
|
||||
|
||||
VectorMA(origin, -10 + 20 * sin(c * 2 * M_PI), vec, origin);
|
||||
|
||||
// if the view would be "inside" the sprite, kill the sprite
|
||||
// so it doesn't add too much overdraw
|
||||
VectorSubtract( origin, cg.refdef.vieworg, delta );
|
||||
len = VectorLength( delta );
|
||||
if ( len < 20 ) {
|
||||
CG_FreeLocalEntity( le );
|
||||
return;
|
||||
}
|
||||
|
||||
negative = qfalse;
|
||||
if (score < 0) {
|
||||
negative = qtrue;
|
||||
score = -score;
|
||||
}
|
||||
|
||||
for (numdigits = 0; !(numdigits && !score); numdigits++) {
|
||||
digits[numdigits] = score % 10;
|
||||
score = score / 10;
|
||||
}
|
||||
|
||||
if (negative) {
|
||||
digits[numdigits] = 10;
|
||||
numdigits++;
|
||||
}
|
||||
|
||||
for (i = 0; i < numdigits; i++) {
|
||||
VectorMA(origin, (float) (((float) numdigits / 2) - i) * NUMBER_SIZE, vec, re->origin);
|
||||
re->customShader = cgs.media.numberShaders[digits[numdigits-1-i]];
|
||||
trap_R_AddRefEntityToScene( re );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
CG_AddOLine
|
||||
|
||||
For forcefields/other rectangular things
|
||||
===================
|
||||
*/
|
||||
void CG_AddOLine( localEntity_t *le )
|
||||
{
|
||||
refEntity_t *re;
|
||||
float frac, alpha;
|
||||
|
||||
re = &le->refEntity;
|
||||
|
||||
frac = (cg.time - le->startTime) / ( float ) ( le->endTime - le->startTime );
|
||||
if ( frac > 1 )
|
||||
frac = 1.0; // can happen during connection problems
|
||||
else if (frac < 0)
|
||||
frac = 0.0;
|
||||
|
||||
// Use the liferate to set the scale over time.
|
||||
re->data.line.width = le->data.line.width + (le->data.line.dwidth * frac);
|
||||
if (re->data.line.width <= 0)
|
||||
{
|
||||
CG_FreeLocalEntity( le );
|
||||
return;
|
||||
}
|
||||
|
||||
// We will assume here that we want additive transparency effects.
|
||||
alpha = le->alpha + (le->dalpha * frac);
|
||||
re->shaderRGBA[0] = 0xff * alpha;
|
||||
re->shaderRGBA[1] = 0xff * alpha;
|
||||
re->shaderRGBA[2] = 0xff * alpha;
|
||||
re->shaderRGBA[3] = 0xff * alpha; // Yes, we could apply c to this too, but fading the color is better for lines.
|
||||
|
||||
re->shaderTexCoord[0] = 1;
|
||||
re->shaderTexCoord[1] = 1;
|
||||
|
||||
re->rotation = 90;
|
||||
|
||||
re->reType = RT_ORIENTEDLINE;
|
||||
|
||||
trap_R_AddRefEntityToScene( re );
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
CG_AddLine
|
||||
|
||||
for beams and the like.
|
||||
===================
|
||||
*/
|
||||
void CG_AddLine( localEntity_t *le )
|
||||
{
|
||||
refEntity_t *re;
|
||||
|
||||
re = &le->refEntity;
|
||||
|
||||
re->reType = RT_LINE;
|
||||
|
||||
trap_R_AddRefEntityToScene( re );
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
/*
|
||||
===================
|
||||
CG_AddLocalEntities
|
||||
|
||||
===================
|
||||
*/
|
||||
void CG_AddLocalEntities( void ) {
|
||||
localEntity_t *le, *next;
|
||||
|
||||
// walk the list backwards, so any new local entities generated
|
||||
// (trails, marks, etc) will be present this frame
|
||||
le = cg_activeLocalEntities.prev;
|
||||
for ( ; le != &cg_activeLocalEntities ; le = next ) {
|
||||
// grab next now, so if the local entity is freed we
|
||||
// still have it
|
||||
next = le->prev;
|
||||
|
||||
if ( cg.time >= le->endTime ) {
|
||||
CG_FreeLocalEntity( le );
|
||||
continue;
|
||||
}
|
||||
switch ( le->leType ) {
|
||||
default:
|
||||
CG_Error( "Bad leType: %i", le->leType );
|
||||
break;
|
||||
|
||||
case LE_MARK:
|
||||
break;
|
||||
|
||||
case LE_SPRITE_EXPLOSION:
|
||||
CG_AddSpriteExplosion( le );
|
||||
break;
|
||||
|
||||
case LE_EXPLOSION:
|
||||
CG_AddExplosion( le );
|
||||
break;
|
||||
|
||||
case LE_FADE_SCALE_MODEL:
|
||||
CG_AddFadeScaleModel( le );
|
||||
break;
|
||||
|
||||
case LE_FRAGMENT: // gibs and brass
|
||||
CG_AddFragment( le );
|
||||
break;
|
||||
|
||||
case LE_PUFF:
|
||||
CG_AddPuff( le );
|
||||
break;
|
||||
|
||||
case LE_MOVE_SCALE_FADE: // water bubbles
|
||||
CG_AddMoveScaleFade( le );
|
||||
break;
|
||||
|
||||
case LE_FADE_RGB: // teleporters, railtrails
|
||||
CG_AddFadeRGB( le );
|
||||
break;
|
||||
|
||||
case LE_FALL_SCALE_FADE: // gib blood trails
|
||||
CG_AddFallScaleFade( le );
|
||||
break;
|
||||
|
||||
case LE_SCALE_FADE: // rocket trails
|
||||
CG_AddScaleFade( le );
|
||||
break;
|
||||
|
||||
case LE_SCOREPLUM:
|
||||
CG_AddScorePlum( le );
|
||||
break;
|
||||
|
||||
case LE_OLINE:
|
||||
CG_AddOLine( le );
|
||||
break;
|
||||
|
||||
case LE_SHOWREFENTITY:
|
||||
CG_AddRefEntity( le );
|
||||
break;
|
||||
|
||||
case LE_LINE: // oriented lines for FX
|
||||
CG_AddLine( le );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
2690
CODEmp/cgame/cg_main.c
Normal file
2690
CODEmp/cgame/cg_main.c
Normal file
File diff suppressed because it is too large
Load diff
2258
CODEmp/cgame/cg_marks.c
Normal file
2258
CODEmp/cgame/cg_marks.c
Normal file
File diff suppressed because it is too large
Load diff
0
CODEmp/cgame/cg_media.h
Normal file
0
CODEmp/cgame/cg_media.h
Normal file
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue