Jedi Outcast v054

This commit is contained in:
unknown 2013-04-04 09:52:42 -05:00
commit 0c7c4bdee2
972 changed files with 686197 additions and 0 deletions

BIN
CODEmp/Debug/botlib.lib Normal file

Binary file not shown.

BIN
CODEmp/Debug/cgamex86.lib Normal file

Binary file not shown.

Binary file not shown.

BIN
CODEmp/Debug/uix86.lib Normal file

Binary file not shown.

BIN
CODEmp/Final/botlib.lib Normal file

Binary file not shown.

BIN
CODEmp/Final/cgamex86.lib Normal file

Binary file not shown.

Binary file not shown.

BIN
CODEmp/Final/uix86.lib Normal file

Binary file not shown.

BIN
CODEmp/Release/botlib.lib Normal file

Binary file not shown.

BIN
CODEmp/Release/cgamex86.lib Normal file

Binary file not shown.

Binary file not shown.

BIN
CODEmp/Release/uix86.lib Normal file

Binary file not shown.

156
CODEmp/Splines/Splines.dsp Normal file
View 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

View 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;
}

View 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__ */

View 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 );
}

View 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__ */

View 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;
}
}

View 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__ */

View 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;
}

View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

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
View 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
View 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
View 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
View 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
*/

View 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);

View 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

File diff suppressed because it is too large Load diff

View 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

View 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);
}

View 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
View 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

View 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

View 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);

View 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

View 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

View 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

View 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

View 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 );

File diff suppressed because it is too large Load diff

View 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);

View 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

View 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);

File diff suppressed because it is too large Load diff

View 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);

File diff suppressed because it is too large Load diff

View 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);

View 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

View 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);

File diff suppressed because it is too large Load diff

View 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);

View 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

File diff suppressed because it is too large Load diff

117
CODEmp/botlib/be_ai_gen.cpp Normal file
View 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

File diff suppressed because it is too large Load diff

3593
CODEmp/botlib/be_ai_move.cpp Normal file

File diff suppressed because it is too large Load diff

View 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

View 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

View 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
View 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

View 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;
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

163
CODEmp/botlib/l_precomp.h Normal file
View 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

File diff suppressed because it is too large Load diff

232
CODEmp/botlib/l_script.h Normal file
View 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
View 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
View 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
View 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)

View file

@ -0,0 +1,3 @@
EXPORTS
vmMain
dllEntry

399
CODEmp/cgame/JK2_cgame.dsp Normal file
View 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

File diff suppressed because it is too large Load diff

View 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

File diff suppressed because it is too large Load diff

629
CODEmp/cgame/cg_drawtools.c Normal file
View 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

File diff suppressed because it is too large Load diff

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

File diff suppressed because it is too large Load diff

350
CODEmp/cgame/cg_info.c Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

861
CODEmp/cgame/cg_localents.c Normal file
View 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

File diff suppressed because it is too large Load diff

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
View file

Some files were not shown because too many files have changed in this diff Show more