24 Nov 2009

This commit is contained in:
g-cont 2009-11-24 00:00:00 +03:00 committed by Alibek Omarov
parent acd933e18a
commit 1fb626fca8
100 changed files with 4479 additions and 4298 deletions

View File

@ -1,16 +0,0 @@
<html>
<body>
<pre>
<h1>Build Log</h1>
<h3>
--------------------Configuration: baserc - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
<h3>Results</h3>
baserc.dll - 0 error(s), 0 warning(s)
</pre>
</body>
</html>

View File

@ -1,16 +0,0 @@
<html>
<body>
<pre>
<h1>Build Log</h1>
<h3>
--------------------Configuration: client - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
<h3>Results</h3>
client.dll - 0 error(s), 0 warning(s)
</pre>
</body>
</html>

View File

@ -241,6 +241,80 @@ void CL_SparkParticles( const Vector org, const Vector dir )
}
}
/*
=================
CL_RicochetSparks
=================
*/
void CL_RicochetSparks( const Vector org, float scale )
{
cparticle_t src;
int i, flags;
// sparks
flags = (PARTICLE_STRETCH|PARTICLE_BOUNCE|PARTICLE_FRICTION);
for( i = 0; i < 16; i++ )
{
src.origin.x = org[0] + RANDOM_FLOAT( -1, 1 );
src.origin.y = org[1] + RANDOM_FLOAT( -1, 1 );
src.origin.z = org[2] + RANDOM_FLOAT( -1, 1 );
src.velocity.x = RANDOM_FLOAT( -60, 60 );
src.velocity.y = RANDOM_FLOAT( -60, 60 );
src.velocity.z = RANDOM_FLOAT( -60, 60 );
src.accel.x = src.accel.y = 0;
src.accel.z = -120 + RANDOM_FLOAT( -60, 60 );
src.color = Vector( 1.0, 1.0f, 1.0f );
src.colorVelocity = Vector( 0, 0, 0 );
src.alpha = 1.0;
src.alphaVelocity = -8.0;
src.radius = scale + RANDOM_FLOAT( -0.2, 0.2 );
src.radiusVelocity = 0;
src.length = scale + RANDOM_FLOAT( -0.2, 0.2 );
src.lengthVelocity = scale + RANDOM_FLOAT( -0.2, 0.2 );
src.rotation = 0;
src.bounceFactor = 0.2;
if( !g_engfuncs.pEfxAPI->R_AllocParticle( &src, gHUD.m_hSparks, flags ))
return;
}
}
void CL_SmokeParticles( const Vector pos, int count )
{
cparticle_t src;
int i, flags;
if( !CVAR_GET_FLOAT( "cl_particles" ))
return;
// smoke
flags = PARTICLE_VERTEXLIGHT;
for( i = 0; i < count; i++ )
{
src.origin.x = pos.x + RANDOM_FLOAT( -10, 10 );
src.origin.y = pos.y + RANDOM_FLOAT( -10, 10 );
src.origin.z = pos.z + RANDOM_FLOAT( -10, 10 );
src.velocity.x = RANDOM_FLOAT( -10, 10 );
src.velocity.y = RANDOM_FLOAT( -10, 10 );
src.velocity.z = RANDOM_FLOAT( -10, 10 ) + RANDOM_FLOAT( -5, 5 ) + 25;
src.accel = Vector( 0, 0, 0 );
src.color = Vector( 0, 0, 0 );
src.colorVelocity = Vector( 0.75, 0.75, 0.75 );
src.alpha = 0.5;
src.alphaVelocity = RANDOM_FLOAT( -0.1, -0.2 );
src.radius = 30 + RANDOM_FLOAT( -15, 15 );
src.radiusVelocity = 15 + RANDOM_FLOAT( -7.5, 7.5 );
src.length = 1;
src.lengthVelocity = 0;
src.rotation = RANDOM_LONG( 0, 360 );
if( !g_engfuncs.pEfxAPI->R_AllocParticle( &src, gHUD.m_hSmoke, flags ))
return;
}
}
/*
=================
CL_BulletParticles
@ -444,6 +518,22 @@ void HUD_ParseTempEntity( void )
g_engfuncs.pEfxAPI->CL_FindExplosionPlane( pos, 1.0f, dir );
CL_SparkParticles( pos, dir );
break;
case TE_ARMOR_RICOCHET:
pos.x = READ_COORD();
pos.y = READ_COORD();
pos.z = READ_COORD();
radius = READ_BYTE() / 10.0f;
CL_RicochetSparks( pos, radius );
break;
case TE_SMOKE:
pos.x = READ_COORD();
pos.y = READ_COORD();
pos.z = READ_COORD();
READ_SHORT(); // FIXME: use sprite index as shader index
scale = READ_BYTE();
READ_BYTE(); // FIMXE: use framerate
CL_SmokeParticles( pos, scale );
break;
case TE_TELEPORT:
pos.x = READ_COORD();
pos.y = READ_COORD();

View File

@ -171,7 +171,7 @@ float READ_ANGLE( void )
Vector READ_DIR( void )
{
return BitsToDir( READ_SHORT() );
return BitsToDir( READ_BYTE() );
}
//

View File

@ -30,6 +30,9 @@ extern cvar_t *cm_debugsize;
#define PLANE_NORMAL_EPSILON 0.00001f
#define PLANE_DIST_EPSILON 0.01f
// 1/32 epsilon to keep floating point happy
#define SURFACE_CLIP_EPSILON (0.03125)
typedef struct
{
cplane_t *plane;
@ -82,6 +85,7 @@ typedef struct
modtype_t type; // model type
vec3_t mins, maxs; // model boundbox
byte *extradata; // studiomodels extradata
byte *submodels; // animations ptr
int numframes; // sprite framecount
cleaf_t leaf; // holds the markbrushes and markfaces
@ -251,7 +255,11 @@ void CM_FreeWorld( void );
//
bool CM_SpriteModel( byte *buffer, size_t filesize );
bool CM_StudioModel( byte *buffer, size_t filesize );
void CM_StudioInitBoxHull( void );
void CM_StudioGetAttachment( edict_t *e, int iAttachment, float *org, float *ang );
bool CM_StudioTrace( trace_t *tr, edict_t *e, const vec3_t p1, const vec3_t p2 );
void CM_GetBonePosition( edict_t* e, int iBone, float *rgflOrigin, float *rgflAngles );
//
// cm_trace.c
//

View File

@ -80,6 +80,8 @@ physic_exp_t DLLEXPORT *CreateAPI ( stdlib_api_t *input, physic_imp_t *engfuncs
Phys.Mod_GetType = CM_ModelType;
Phys.Mod_GetBounds = CM_ModelBounds;
Phys.Mod_GetFrames = CM_ModelFrames;
Phys.Mod_GetAttachment = CM_StudioGetAttachment;
Phys.Mod_GetBonePos = CM_GetBonePosition;
Phys.GetShaderName = CM_ShaderName;
Phys.Mod_Extradata = CM_Extradata;
Phys.GetEntityScript = CM_EntityScript;
@ -89,6 +91,7 @@ physic_exp_t DLLEXPORT *CreateAPI ( stdlib_api_t *input, physic_imp_t *engfuncs
Phys.PointContents2 = CM_TransformedPointContents;
Phys.BoxTrace1 = CM_BoxTrace;
Phys.BoxTrace2 = CM_TransformedBoxTrace;
Phys.HitboxTrace = CM_StudioTrace;
Phys.TempModel = CM_TempBoxModel;

View File

@ -771,6 +771,7 @@ void CM_BeginRegistration( const char *name, bool clientload, uint *checksum )
if( cm.numverts ) Mem_Free( cm.vertices );
CM_InitBoxHull ();
CM_StudioInitBoxHull (); // hitbox tracing
Mem_Set( cm.areaportals, 0, sizeof( cm.areaportals ));
CM_FloodAreaConnections ();

View File

@ -1,11 +1,12 @@
//=======================================================================
// Copyright XashXT Group 2009 ©
// cm_studio.c - stduio models
// cm_studio.c - stduio models tracing
//=======================================================================
#include "cm_local.h"
#include "mathlib.h"
#include "matrix_lib.h"
#include "byteorder.h"
#include "const.h"
struct
@ -15,7 +16,8 @@ struct
dstudiobodyparts_t *bodypart;
matrix4x4 rotmatrix;
matrix4x4 bones[MAXSTUDIOBONES];
uint bodycount;
cplane_t planes[12];
trace_t trace;
} studio;
/*
@ -39,62 +41,380 @@ int CM_StudioExtractBbox( dstudiohdr_t *phdr, int sequence, float *mins, float *
/*
====================
CM_StudioCalcBoneQuaterion
CM_StudioSetUpTransform
====================
*/
void CM_StudioCalcBoneQuaterion( dstudiobone_t *pbone, float *q )
void CM_StudioSetUpTransform( edict_t *e )
{
int i;
vec3_t angle1;
float *ang, *org, scale = 1.0f;
for(i = 0; i < 3; i++) angle1[i] = pbone->value[i+3];
AngleQuaternion( angle1, q );
org = e->v.origin;
ang = e->v.angles;
if( e->v.scale != 0.0f )
scale = e->v.scale;
Matrix4x4_CreateFromEntity( studio.rotmatrix, org[0], org[1], org[2], ang[PITCH], ang[YAW], ang[ROLL], scale );
}
/*
====================
StudioCalcBoneAdj
====================
*/
void CM_StudioCalcBoneAdj( float dadt, float *adj, const byte *pcontroller1, const byte *pcontroller2 )
{
int i, j;
float value;
dstudiobonecontroller_t *pbonecontroller;
pbonecontroller = (dstudiobonecontroller_t *)((byte *)studio.hdr + studio.hdr->bonecontrollerindex);
for( j = 0; j < studio.hdr->numbonecontrollers; j++ )
{
i = pbonecontroller[j].index;
if( i == 4 ) continue; // ignore mouth
if( i <= MAXSTUDIOCONTROLLERS )
{
// check for 360% wrapping
if( pbonecontroller[j].type & STUDIO_RLOOP )
{
if( abs( pcontroller1[i] - pcontroller2[i] ) > 128 )
{
int a, b;
a = (pcontroller1[j] + 128) % 256;
b = (pcontroller2[j] + 128) % 256;
value = ((a * dadt) + (b * (1 - dadt)) - 128) * (360.0/256.0) + pbonecontroller[j].start;
}
else
{
value = ((pcontroller1[i] * dadt + (pcontroller2[i]) * (1.0 - dadt))) * (360.0/256.0) + pbonecontroller[j].start;
}
}
else
{
value = (pcontroller1[i] * dadt + pcontroller2[i] * (1.0 - dadt)) / 255.0;
if( value < 0 ) value = 0;
if( value > 1.0 ) value = 1.0;
value = (1.0 - value) * pbonecontroller[j].start + value * pbonecontroller[j].end;
}
}
switch( pbonecontroller[j].type & STUDIO_TYPES )
{
case STUDIO_XR:
case STUDIO_YR:
case STUDIO_ZR:
adj[j] = value * (M_PI / 180.0);
break;
case STUDIO_X:
case STUDIO_Y:
case STUDIO_Z:
adj[j] = value;
break;
}
}
}
/*
====================
CM_StudioCalcBoneQuaterion
====================
*/
void CM_StudioCalcBoneQuaterion( int frame, float s, dstudiobone_t *pbone, dstudioanim_t *panim, float *adj, float *q )
{
int j, k;
vec4_t q1, q2;
vec3_t angle1, angle2;
dstudioanimvalue_t *panimvalue;
for( j = 0; j < 3; j++ )
{
if( panim->offset[j+3] == 0 )
{
angle2[j] = angle1[j] = pbone->value[j+3]; // default;
}
else
{
panimvalue = (dstudioanimvalue_t *)((byte *)panim + panim->offset[j+3]);
k = frame;
// debug
if( panimvalue->num.total < panimvalue->num.valid )
k = 0;
while( panimvalue->num.total <= k )
{
k -= panimvalue->num.total;
panimvalue += panimvalue->num.valid + 1;
// DEBUG
if( panimvalue->num.total < panimvalue->num.valid )
k = 0;
}
// Bah, missing blend!
if( panimvalue->num.valid > k )
{
angle1[j] = panimvalue[k+1].value;
if( panimvalue->num.valid > k + 1 )
{
angle2[j] = panimvalue[k+2].value;
}
else
{
if( panimvalue->num.total > k + 1 )
angle2[j] = angle1[j];
else angle2[j] = panimvalue[panimvalue->num.valid+2].value;
}
}
else
{
angle1[j] = panimvalue[panimvalue->num.valid].value;
if( panimvalue->num.total > k + 1 )
{
angle2[j] = angle1[j];
}
else
{
angle2[j] = panimvalue[panimvalue->num.valid + 2].value;
}
}
angle1[j] = pbone->value[j+3] + angle1[j] * pbone->scale[j+3];
angle2[j] = pbone->value[j+3] + angle2[j] * pbone->scale[j+3];
}
if( pbone->bonecontroller[j+3] != -1 )
{
angle1[j] += adj[pbone->bonecontroller[j+3]];
angle2[j] += adj[pbone->bonecontroller[j+3]];
}
}
if( !VectorCompare( angle1, angle2 ))
{
AngleQuaternion( angle1, q1 );
AngleQuaternion( angle2, q2 );
QuaternionSlerp( q1, q2, s, q );
}
else
{
AngleQuaternion( angle1, q );
}
}
/*
====================
CM_StudioCalcBonePosition
====================
*/
void CM_StudioCalcBonePosition( dstudiobone_t *pbone, float *pos )
void CM_StudioCalcBonePosition( int frame, float s, dstudiobone_t *pbone, dstudioanim_t *panim, float *adj, float *pos )
{
int i;
for(i = 0; i < 3; i++) pos[i] = pbone->value[i];
int j, k;
dstudioanimvalue_t *panimvalue;
for( j = 0; j < 3; j++ )
{
pos[j] = pbone->value[j]; // default;
if( panim->offset[j] != 0.0f )
{
panimvalue = (dstudioanimvalue_t *)((byte *)panim + panim->offset[j]);
k = frame;
// debug
if( panimvalue->num.total < panimvalue->num.valid )
k = 0;
// find span of values that includes the frame we want
while( panimvalue->num.total <= k )
{
k -= panimvalue->num.total;
panimvalue += panimvalue->num.valid + 1;
// DEBUG
if( panimvalue->num.total < panimvalue->num.valid )
k = 0;
}
// if we're inside the span
if( panimvalue->num.valid > k )
{
// and there's more data in the span
if( panimvalue->num.valid > k + 1 )
{
pos[j] += (panimvalue[k+1].value * (1.0 - s) + s * panimvalue[k+2].value) * pbone->scale[j];
}
else
{
pos[j] += panimvalue[k+1].value * pbone->scale[j];
}
}
else
{
// are we at the end of the repeating values section and there's another section with data?
if( panimvalue->num.total <= k + 1 )
{
pos[j] += (panimvalue[panimvalue->num.valid].value * (1.0 - s) + s * panimvalue[panimvalue->num.valid + 2].value) * pbone->scale[j];
}
else
{
pos[j] += panimvalue[panimvalue->num.valid].value * pbone->scale[j];
}
}
}
if( pbone->bonecontroller[j] != -1 && adj )
{
pos[j] += adj[pbone->bonecontroller[j]];
}
}
}
/*
====================
CM_StudioSetUpTransform
CM_StudioCalcRotations
====================
*/
void CM_StudioSetUpTransform ( void )
void CM_StudioCalcRotations( edict_t *e, float pos[][3], vec4_t *q, dstudioseqdesc_t *pseqdesc, dstudioanim_t *panim, float f )
{
vec3_t mins, maxs, angles;
vec3_t modelpos;
int i;
int frame;
dstudiobone_t *pbone;
float adj[MAXSTUDIOCONTROLLERS];
float s, dadt = 1.0f; // noInterp
CM_StudioExtractBbox( studio.hdr, 0, mins, maxs );// adjust model center
VectorAdd( mins, maxs, modelpos );
VectorScale( modelpos, -0.5, modelpos );
if( f > pseqdesc->numframes - 1 )
f = 0;
else if( f < -0.01 )
f = -0.01;
VectorSet( angles, 0.0f, -90.0f, 90.0f ); // rotate matrix for 90 degrees
AngleVectors( angles, studio.rotmatrix[0], studio.rotmatrix[2], studio.rotmatrix[1] );
frame = (int)f;
s = (f - frame);
studio.rotmatrix[0][3] = modelpos[0];
studio.rotmatrix[1][3] = modelpos[1];
studio.rotmatrix[2][3] = modelpos[2];
studio.rotmatrix[2][2] *= -1;
// add in programtic controllers
pbone = (dstudiobone_t *)((byte *)studio.hdr + studio.hdr->boneindex);
CM_StudioCalcBoneAdj( dadt, adj, e->v.controller, e->v.controller );
for (i = 0; i < studio.hdr->numbones; i++, pbone++, panim++)
{
CM_StudioCalcBoneQuaterion( frame, s, pbone, panim, adj, q[i] );
CM_StudioCalcBonePosition( frame, s, pbone, panim, adj, pos[i] );
}
if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f;
if( pseqdesc->motiontype & STUDIO_Y ) pos[pseqdesc->motionbone][1] = 0.0f;
if( pseqdesc->motiontype & STUDIO_Z ) pos[pseqdesc->motionbone][2] = 0.0f;
s = 0 * ((1.0 - (f - (int)(f))) / (pseqdesc->numframes)) * e->v.framerate;
if( pseqdesc->motiontype & STUDIO_LX ) pos[pseqdesc->motionbone][0] += s * pseqdesc->linearmovement[0];
if( pseqdesc->motiontype & STUDIO_LY ) pos[pseqdesc->motionbone][1] += s * pseqdesc->linearmovement[1];
if( pseqdesc->motiontype & STUDIO_LZ ) pos[pseqdesc->motionbone][2] += s * pseqdesc->linearmovement[2];
}
void CM_StudioCalcRotations ( float pos[][3], vec4_t *q )
{
dstudiobone_t *pbone = (dstudiobone_t *)((byte *)studio.hdr + studio.hdr->boneindex);
int i;
/*
====================
StudioEstimateFrame
for (i = 0; i < studio.hdr->numbones; i++, pbone++ )
====================
*/
float CM_StudioEstimateFrame( edict_t *e, dstudioseqdesc_t *pseqdesc )
{
double f;
if( pseqdesc->numframes <= 1 )
f = 0;
else f = (e->v.frame * (pseqdesc->numframes - 1)) / 256.0;
if( pseqdesc->flags & STUDIO_LOOPING )
{
CM_StudioCalcBoneQuaterion( pbone, q[i] );
CM_StudioCalcBonePosition( pbone, pos[i]);
if( pseqdesc->numframes > 1 )
f -= (int)(f / (pseqdesc->numframes - 1)) * (pseqdesc->numframes - 1);
if( f < 0 ) f += (pseqdesc->numframes - 1);
}
else
{
if( f >= pseqdesc->numframes - 1.001 )
f = pseqdesc->numframes - 1.001;
if( f < 0.0 ) f = 0.0;
}
return f;
}
/*
====================
CM_StudioSlerpBones
====================
*/
void CM_StudioSlerpBones( vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s )
{
int i;
vec4_t q3;
float s1;
s = bound( 0.0f, s, 1.0f );
s1 = 1.0f - s;
for( i = 0; i < studio.hdr->numbones; i++ )
{
QuaternionSlerp( q1[i], q2[i], s, q3 );
q1[i][0] = q3[0];
q1[i][1] = q3[1];
q1[i][2] = q3[2];
q1[i][3] = q3[3];
pos1[i][0] = pos1[i][0] * s1 + pos2[i][0] * s;
pos1[i][1] = pos1[i][1] * s1 + pos2[i][1] * s;
pos1[i][2] = pos1[i][2] * s1 + pos2[i][2] * s;
}
}
/*
====================
CM_StudioGetAnim
====================
*/
dstudioanim_t *CM_StudioGetAnim( cmodel_t *m_pSubModel, dstudioseqdesc_t *pseqdesc )
{
dstudioseqgroup_t *pseqgroup;
byte *paSequences;
size_t filesize;
byte *buf;
Com_Assert( m_pSubModel == NULL );
pseqgroup = (dstudioseqgroup_t *)((byte *)studio.hdr + studio.hdr->seqgroupindex) + pseqdesc->seqgroup;
if( pseqdesc->seqgroup == 0 )
return (dstudioanim_t *)((byte *)studio.hdr + pseqgroup->data + pseqdesc->animindex);
paSequences = (void *)m_pSubModel->submodels;
if( paSequences == NULL )
{
// allocate sequence groups if needs
paSequences = (byte *)Mem_Alloc( m_pSubModel->mempool, sizeof( paSequences ) * MAXSTUDIOGROUPS );
m_pSubModel->submodels = (void *)paSequences; // just a container
}
if(((dstudiomodel_t *)&(paSequences[pseqdesc->seqgroup])) == NULL )
{
dstudioseqgroup_t *pseqhdr;
buf = FS_LoadFile( pseqgroup->name, &filesize );
if( !buf || !filesize || IDSEQGRPHEADER != LittleLong(*(uint *)buf ))
Host_Error( "CM_StudioGetAnim: can't load %s\n", pseqgroup->name );
pseqhdr = (dstudioseqgroup_t *)buf;
MsgDev( D_INFO, "loading %s\n", pseqgroup->name );
paSequences = (byte *)Mem_Alloc( m_pSubModel->mempool, filesize );
m_pSubModel->submodels = (void *)paSequences; // just a container
Mem_Copy( &paSequences[pseqdesc->seqgroup], buf, filesize );
Mem_Free( buf );
}
return (dstudioanim_t *)((byte *)paSequences[pseqdesc->seqgroup] + pseqdesc->animindex );
}
/*
@ -102,35 +422,353 @@ void CM_StudioCalcRotations ( float pos[][3], vec4_t *q )
CM_StudioSetupBones
====================
*/
void CM_StudioSetupBones( void )
void CM_StudioSetupBones( edict_t *e )
{
int i;
int i, oldseq;
double f;
dstudiobone_t *pbones;
dstudioseqdesc_t *pseqdesc;
dstudioanim_t *panim;
static float pos[MAXSTUDIOBONES][3];
static vec4_t q[MAXSTUDIOBONES];
matrix4x4 bonematrix;
CM_StudioCalcRotations( pos, q );
static float pos2[MAXSTUDIOBONES][3];
static vec4_t q2[MAXSTUDIOBONES];
static float pos3[MAXSTUDIOBONES][3];
static vec4_t q3[MAXSTUDIOBONES];
static float pos4[MAXSTUDIOBONES][3];
static vec4_t q4[MAXSTUDIOBONES];
oldseq = e->v.sequence; // TraceCode can't change sequence
if( e->v.sequence >= studio.hdr->numseq ) e->v.sequence = 0;
pseqdesc = (dstudioseqdesc_t *)((byte *)studio.hdr + studio.hdr->seqindex) + e->v.sequence;
f = CM_StudioEstimateFrame( e, pseqdesc );
panim = CM_StudioGetAnim( CM_ClipHandleToModel( e->v.modelindex ), pseqdesc );
CM_StudioCalcRotations( e, pos, q, pseqdesc, panim, f );
if( pseqdesc->numblends > 1 )
{
float s;
float dadt = 1.0f;
panim += studio.hdr->numbones;
CM_StudioCalcRotations( e, pos2, q2, pseqdesc, panim, f );
s = (e->v.blending[0] * dadt + e->v.blending[0] * (1.0 - dadt)) / 255.0;
CM_StudioSlerpBones( q, pos, q2, pos2, s );
if( pseqdesc->numblends == 4 )
{
panim += studio.hdr->numbones;
CM_StudioCalcRotations( e, pos3, q3, pseqdesc, panim, f );
panim += studio.hdr->numbones;
CM_StudioCalcRotations( e, pos4, q4, pseqdesc, panim, f );
s = (e->v.blending[0] * dadt + e->v.blending[0] * (1.0 - dadt)) / 255.0;
CM_StudioSlerpBones( q3, pos3, q4, pos4, s );
s = (e->v.blending[1] * dadt + e->v.blending[1] * (1.0 - dadt)) / 255.0;
CM_StudioSlerpBones( q, pos, q3, pos3, s );
}
}
pbones = (dstudiobone_t *)((byte *)studio.hdr + studio.hdr->boneindex);
for (i = 0; i < studio.hdr->numbones; i++)
for( i = 0; i < studio.hdr->numbones; i++ )
{
Matrix4x4_FromOriginQuat( bonematrix, pos[i][0], pos[i][1], pos[i][2], q[i][0], q[i][1], q[i][2], q[i][3] );
if( pbones[i].parent == -1 ) Matrix4x4_ConcatTransforms( studio.bones[i], studio.rotmatrix, bonematrix );
if( pbones[i].parent == -1 )
Matrix4x4_ConcatTransforms( studio.bones[i], studio.rotmatrix, bonematrix );
else Matrix4x4_ConcatTransforms( studio.bones[i], studio.bones[pbones[i].parent], bonematrix );
}
e->v.sequence = oldseq; // restore original value
}
/*
====================
StudioCalcAttachments
====================
*/
static void CM_StudioCalcAttachments( edict_t *e, int iAttachment, float *org, float *ang )
{
int i;
dstudioattachment_t *pAtt;
vec3_t axis[3];
vec3_t localOrg, localAng;
if( studio.hdr->numattachments > MAXSTUDIOATTACHMENTS )
{
studio.hdr->numattachments = MAXSTUDIOATTACHMENTS; // reduce it
MsgDev( D_WARN, "CM_StudioCalcAttahments: too many attachments on %s\n", studio.hdr->name );
}
iAttachment = bound( 0, iAttachment, studio.hdr->numattachments );
// calculate attachment points
pAtt = (dstudioattachment_t *)((byte *)studio.hdr + studio.hdr->attachmentindex);
for( i = 0; i < studio.hdr->numattachments; i++ )
{
if( i == iAttachment )
{
// compute pos and angles
Matrix4x4_VectorTransform( studio.bones[pAtt[i].bone], pAtt[i].org, localOrg );
Matrix4x4_VectorTransform( studio.bones[pAtt[i].bone], pAtt[i].vectors[0], axis[0] );
Matrix4x4_VectorTransform( studio.bones[pAtt[i].bone], pAtt[i].vectors[1], axis[1] );
Matrix4x4_VectorTransform( studio.bones[pAtt[i].bone], pAtt[i].vectors[2], axis[2] );
Matrix3x3_ToAngles( axis, localAng, true ); // FIXME: dll's uses FLU ?
if( org ) VectorCopy( localOrg, org );
if( ang ) VectorCopy( localAng, ang );
break; // done
}
}
}
void CM_StudioSetupModel ( int bodypart, int body )
void CM_StudioInitBoxHull( void )
{
int index;
int i, side;
cplane_t *p;
if(bodypart > studio.hdr->numbodyparts) bodypart = 0;
studio.bodypart = (dstudiobodyparts_t *)((byte *)studio.hdr + studio.hdr->bodypartindex) + bodypart;
for( i = 0; i < 6; i++ )
{
side = i & 1;
index = body / studio.bodypart->base;
index = index % studio.bodypart->nummodels;
studio.submodel = (dstudiomodel_t *)((byte *)studio.hdr + studio.bodypart->modelindex) + index;
// planes
p = &studio.planes[i*2];
p->type = i>>1;
p->signbits = 0;
VectorClear( p->normal );
p->normal[i>>1] = 1.0f;
p = &studio.planes[i*2+1];
p->type = 3 + (i>>1);
p->signbits = 0;
VectorClear( p->normal );
p->normal[i>>1] = -1;
p->signbits = SignbitsForPlane( p->normal );
}
}
void CM_StudioBoxHullFromBounds( const vec3_t mins, const vec3_t maxs )
{
studio.planes[0].dist = maxs[0];
studio.planes[1].dist = -maxs[0];
studio.planes[2].dist = mins[0];
studio.planes[3].dist = -mins[0];
studio.planes[4].dist = maxs[1];
studio.planes[5].dist = -maxs[1];
studio.planes[6].dist = mins[1];
studio.planes[7].dist = -mins[1];
studio.planes[8].dist = maxs[2];
studio.planes[9].dist = -maxs[2];
studio.planes[10].dist = mins[2];
studio.planes[11].dist = -mins[2];
}
bool CM_StudioSetup( edict_t *e )
{
cmodel_t *mod = CM_ClipHandleToModel( e->v.modelindex );
if( mod && mod->type == mod_studio && mod->extradata )
{
studio.hdr = (dstudiohdr_t *)mod->extradata;
CM_StudioSetUpTransform( e );
CM_StudioSetupBones( e );
return true;
}
return false;
}
bool CM_StudioTraceBox( vec3_t start, vec3_t end )
{
int i;
cplane_t *plane, *clipplane;
float enterFrac, leaveFrac;
bool getout, startout;
float d1, d2;
float f;
enterFrac = -1.0;
leaveFrac = 1.0;
clipplane = NULL;
getout = false;
startout = false;
// compare the trace against all planes of the brush
// find the latest time the trace crosses a plane towards the interior
// and the earliest time the trace crosses a plane towards the exterior
for( i = 0; i < 6; i++ )
{
plane = studio.planes + i * 2 + (i & 1);
d1 = DotProduct( start, plane->normal ) - plane->dist;
d2 = DotProduct( end, plane->normal ) - plane->dist;
if( d2 > 0.0f ) getout = TRUE; // endpoint is not in solid
if( d1 > 0.0f ) startout = TRUE;
// if completely in front of face, no intersection with the entire brush
if( d1 > 0 && ( d2 >= SURFACE_CLIP_EPSILON || d2 >= d1 ))
return false;
// if it doesn't cross the plane, the plane isn't relevent
if( d1 <= 0 && d2 <= 0 )
continue;
// crosses face
if( d1 > d2 )
{
// enter
f = (d1 - SURFACE_CLIP_EPSILON) / (d1 - d2);
if( f < 0.0f ) f = 0.0f;
if( f > enterFrac )
{
enterFrac = f;
clipplane = plane;
}
}
else
{
// leave
f = (d1 + SURFACE_CLIP_EPSILON) / (d1 - d2);
if( f > 1.0f ) f = 1.0f;
if( f < leaveFrac )
{
leaveFrac = f;
}
}
}
// all planes have been checked, and the trace was not
// completely outside the brush
if( !startout )
{
// original point was inside brush
if( !getout ) studio.trace.flFraction = 0.0f;
return true;
}
if( enterFrac < leaveFrac )
{
if( enterFrac > -1 && enterFrac < studio.trace.flFraction )
{
if( enterFrac < 0.0f )
enterFrac = 0.0f;
studio.trace.flFraction = enterFrac;
VectorCopy( clipplane->normal, studio.trace.vecPlaneNormal );
studio.trace.flPlaneDist = clipplane->dist;
return true;
}
}
return false;
}
bool CM_StudioTrace( trace_t *tr, edict_t *e, const vec3_t start, const vec3_t end )
{
matrix4x4 m;
vec3_t transformedStart, transformedEnd;
int i, outBone;
if( !CM_StudioSetup( e ) || !studio.hdr->numhitboxes )
{
tr->iHitgroup = -1;
return false;
}
Mem_Set( &studio.trace, 0, sizeof( trace_t ));
studio.trace.flFraction = 1.0f;
studio.trace.iHitgroup = -1;
outBone = -1;
for( i = 0; i < studio.hdr->numhitboxes; i++ )
{
dstudiobbox_t *phitbox = (dstudiobbox_t *)((byte*)studio.hdr + studio.hdr->hitboxindex) + i;
Matrix4x4_Invert_Simple( m, studio.bones[phitbox->bone] );
Matrix4x4_VectorTransform( m, start, transformedStart );
Matrix4x4_VectorTransform( m, end, transformedEnd );
CM_StudioBoxHullFromBounds( phitbox->bbmin, phitbox->bbmax );
if( CM_StudioTraceBox( transformedStart, transformedEnd ))
{
outBone = phitbox->bone;
studio.trace.iHitgroup = phitbox->group;
}
if( studio.trace.flFraction == 0.0f )
break;
}
// all hitboxes were swept, get trace result
if( outBone >= 0 )
{
if( tr )
{
tr->flFraction = studio.trace.flFraction;
tr->iHitgroup = studio.trace.iHitgroup;
Matrix4x4_VectorRotate( studio.bones[outBone], studio.trace.vecEndPos, tr->vecEndPos );
if( tr->flFraction == 1.0f ) VectorCopy( end, tr->vecEndPos );
else
{
dstudiobone_t *pbone = (dstudiobone_t *)((byte*)studio.hdr + studio.hdr->boneindex) + outBone;
tr->pTexName = pbone->name; // debug
tr->iContents = (e->v.health > 0.0f ) ? BASECONT_BODY : BASECONT_CORPSE;
VectorLerp( start, tr->flFraction, end, tr->vecEndPos );
}
tr->flPlaneDist = DotProduct( tr->vecEndPos, tr->vecPlaneNormal );
}
return true;
}
return false;
}
void CM_StudioGetAttachment( edict_t *e, int iAttachment, float *org, float *ang )
{
if( !CM_StudioSetup( e ) || studio.hdr->numattachments <= 0 )
{
// reset attachments
if( org ) VectorCopy( e->v.origin, org );
if( ang ) VectorCopy( e->v.angles, ang );
return;
}
CM_StudioCalcAttachments( e, iAttachment, org, ang );
}
void CM_GetBonePosition( edict_t* e, int iBone, float *org, float *ang )
{
matrix3x3 axis;
if( !CM_StudioSetup( e ) || studio.hdr->numbones <= 0 )
{
// reset bones
if( org ) VectorCopy( e->v.origin, org );
if( ang ) VectorCopy( e->v.angles, ang );
return;
}
iBone = bound( 0, iBone, studio.hdr->numbones );
Matrix3x3_FromMatrix4x4( axis, studio.bones[iBone] );
if( org ) Matrix4x4_OriginFromMatrix( studio.bones[iBone], org );
if( ang ) Matrix3x3_ToAngles( axis, ang, true );
}
bool CM_StudioModel( byte *buffer, uint filesize )

View File

@ -438,6 +438,7 @@ void CM_BoxTrace( trace_t *tr, const vec3_t start, const vec3_t end, vec3_t mins
// fill in a default trace
Mem_Set( tr, 0, sizeof( *tr ));
tr->flFraction = trace_realfraction = 1.0f;
tr->iHitgroup = -1;
if( !cm.numnodes ) // map not loaded
return;

View File

@ -1,16 +0,0 @@
<html>
<body>
<pre>
<h1>Build Log</h1>
<h3>
--------------------Configuration: cms_qf - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
<h3>Results</h3>
cms_qf.dll - 0 error(s), 0 warning(s)
</pre>
</body>
</html>

View File

@ -82,6 +82,7 @@ typedef struct
modtype_t type; // model type
vec3_t mins, maxs; // model boundbox
byte *extradata; // studiomodels extradata
byte *submodels; // animations ptr
int numframes; // sprite framecount
cleaf_t leaf; // collision leaf
@ -366,6 +367,10 @@ void CM_FreeWorld( void );
//
bool CM_SpriteModel( byte *buffer, size_t filesize );
bool CM_StudioModel( byte *buffer, size_t filesize );
void CM_StudioInitBoxHull( void );
void CM_StudioGetAttachment( edict_t *e, int iAttachment, float *org, float *ang );
bool CM_StudioTrace( trace_t *tr, edict_t *e, const vec3_t p1, const vec3_t p2 );
void CM_GetBonePosition( edict_t* e, int iBone, float *rgflOrigin, float *rgflAngles );
//
// cm_polylib.c

View File

@ -80,6 +80,8 @@ physic_exp_t DLLEXPORT *CreateAPI ( stdlib_api_t *input, physic_imp_t *engfuncs
Phys.Mod_GetType = CM_ModelType;
Phys.Mod_GetBounds = CM_ModelBounds;
Phys.Mod_GetFrames = CM_ModelFrames;
Phys.Mod_GetAttachment = CM_StudioGetAttachment;
Phys.Mod_GetBonePos = CM_GetBonePosition;
Phys.GetShaderName = CM_ShaderName;
Phys.Mod_Extradata = CM_Extradata;
Phys.GetEntityScript = CM_EntityScript;
@ -89,6 +91,7 @@ physic_exp_t DLLEXPORT *CreateAPI ( stdlib_api_t *input, physic_imp_t *engfuncs
Phys.PointContents2 = CM_TransformedPointContents;
Phys.BoxTrace1 = CM_BoxTrace;
Phys.BoxTrace2 = CM_TransformedBoxTrace;
Phys.HitboxTrace = CM_StudioTrace;
Phys.TempModel = CM_TempBoxModel;

View File

@ -1064,7 +1064,9 @@ void CM_BeginRegistration( const char *name, bool clientload, uint *checksum )
MsgDev( D_INFO, "CM_CreateCollisionTree: %i total invalid bevels\n", cm.numInvalidBevels );
BSP_CreateBrushSideWindings ();
CM_InitBoxHull ();
CM_StudioInitBoxHull (); // hitbox tracing
Mem_Set( cm.areaportals, 0, sizeof( cm.areaportals ));
CM_FloodAreaConnections ();

View File

@ -1,11 +1,12 @@
//=======================================================================
// Copyright XashXT Group 2009 ©
// cm_studio.c - stduio models
// cm_studio.c - stduio models tracing
//=======================================================================
#include "cm_local.h"
#include "mathlib.h"
#include "matrix_lib.h"
#include "byteorder.h"
#include "const.h"
struct
@ -15,7 +16,8 @@ struct
dstudiobodyparts_t *bodypart;
matrix4x4 rotmatrix;
matrix4x4 bones[MAXSTUDIOBONES];
uint bodycount;
cplane_t planes[12];
trace_t trace;
} studio;
/*
@ -39,62 +41,380 @@ int CM_StudioExtractBbox( dstudiohdr_t *phdr, int sequence, float *mins, float *
/*
====================
CM_StudioCalcBoneQuaterion
CM_StudioSetUpTransform
====================
*/
void CM_StudioCalcBoneQuaterion( dstudiobone_t *pbone, float *q )
void CM_StudioSetUpTransform( edict_t *e )
{
int i;
vec3_t angle1;
float *ang, *org, scale = 1.0f;
for(i = 0; i < 3; i++) angle1[i] = pbone->value[i+3];
AngleQuaternion( angle1, q );
org = e->v.origin;
ang = e->v.angles;
if( e->v.scale != 0.0f )
scale = e->v.scale;
Matrix4x4_CreateFromEntity( studio.rotmatrix, org[0], org[1], org[2], ang[PITCH], ang[YAW], ang[ROLL], scale );
}
/*
====================
StudioCalcBoneAdj
====================
*/
void CM_StudioCalcBoneAdj( float dadt, float *adj, const byte *pcontroller1, const byte *pcontroller2 )
{
int i, j;
float value;
dstudiobonecontroller_t *pbonecontroller;
pbonecontroller = (dstudiobonecontroller_t *)((byte *)studio.hdr + studio.hdr->bonecontrollerindex);
for( j = 0; j < studio.hdr->numbonecontrollers; j++ )
{
i = pbonecontroller[j].index;
if( i == 4 ) continue; // ignore mouth
if( i <= MAXSTUDIOCONTROLLERS )
{
// check for 360% wrapping
if( pbonecontroller[j].type & STUDIO_RLOOP )
{
if( abs( pcontroller1[i] - pcontroller2[i] ) > 128 )
{
int a, b;
a = (pcontroller1[j] + 128) % 256;
b = (pcontroller2[j] + 128) % 256;
value = ((a * dadt) + (b * (1 - dadt)) - 128) * (360.0/256.0) + pbonecontroller[j].start;
}
else
{
value = ((pcontroller1[i] * dadt + (pcontroller2[i]) * (1.0 - dadt))) * (360.0/256.0) + pbonecontroller[j].start;
}
}
else
{
value = (pcontroller1[i] * dadt + pcontroller2[i] * (1.0 - dadt)) / 255.0;
if( value < 0 ) value = 0;
if( value > 1.0 ) value = 1.0;
value = (1.0 - value) * pbonecontroller[j].start + value * pbonecontroller[j].end;
}
}
switch( pbonecontroller[j].type & STUDIO_TYPES )
{
case STUDIO_XR:
case STUDIO_YR:
case STUDIO_ZR:
adj[j] = value * (M_PI / 180.0);
break;
case STUDIO_X:
case STUDIO_Y:
case STUDIO_Z:
adj[j] = value;
break;
}
}
}
/*
====================
CM_StudioCalcBoneQuaterion
====================
*/
void CM_StudioCalcBoneQuaterion( int frame, float s, dstudiobone_t *pbone, dstudioanim_t *panim, float *adj, float *q )
{
int j, k;
vec4_t q1, q2;
vec3_t angle1, angle2;
dstudioanimvalue_t *panimvalue;
for( j = 0; j < 3; j++ )
{
if( panim->offset[j+3] == 0 )
{
angle2[j] = angle1[j] = pbone->value[j+3]; // default;
}
else
{
panimvalue = (dstudioanimvalue_t *)((byte *)panim + panim->offset[j+3]);
k = frame;
// debug
if( panimvalue->num.total < panimvalue->num.valid )
k = 0;
while( panimvalue->num.total <= k )
{
k -= panimvalue->num.total;
panimvalue += panimvalue->num.valid + 1;
// DEBUG
if( panimvalue->num.total < panimvalue->num.valid )
k = 0;
}
// Bah, missing blend!
if( panimvalue->num.valid > k )
{
angle1[j] = panimvalue[k+1].value;
if( panimvalue->num.valid > k + 1 )
{
angle2[j] = panimvalue[k+2].value;
}
else
{
if( panimvalue->num.total > k + 1 )
angle2[j] = angle1[j];
else angle2[j] = panimvalue[panimvalue->num.valid+2].value;
}
}
else
{
angle1[j] = panimvalue[panimvalue->num.valid].value;
if( panimvalue->num.total > k + 1 )
{
angle2[j] = angle1[j];
}
else
{
angle2[j] = panimvalue[panimvalue->num.valid + 2].value;
}
}
angle1[j] = pbone->value[j+3] + angle1[j] * pbone->scale[j+3];
angle2[j] = pbone->value[j+3] + angle2[j] * pbone->scale[j+3];
}
if( pbone->bonecontroller[j+3] != -1 )
{
angle1[j] += adj[pbone->bonecontroller[j+3]];
angle2[j] += adj[pbone->bonecontroller[j+3]];
}
}
if( !VectorCompare( angle1, angle2 ))
{
AngleQuaternion( angle1, q1 );
AngleQuaternion( angle2, q2 );
QuaternionSlerp( q1, q2, s, q );
}
else
{
AngleQuaternion( angle1, q );
}
}
/*
====================
CM_StudioCalcBonePosition
====================
*/
void CM_StudioCalcBonePosition( dstudiobone_t *pbone, float *pos )
void CM_StudioCalcBonePosition( int frame, float s, dstudiobone_t *pbone, dstudioanim_t *panim, float *adj, float *pos )
{
int i;
for(i = 0; i < 3; i++) pos[i] = pbone->value[i];
int j, k;
dstudioanimvalue_t *panimvalue;
for( j = 0; j < 3; j++ )
{
pos[j] = pbone->value[j]; // default;
if( panim->offset[j] != 0.0f )
{
panimvalue = (dstudioanimvalue_t *)((byte *)panim + panim->offset[j]);
k = frame;
// debug
if( panimvalue->num.total < panimvalue->num.valid )
k = 0;
// find span of values that includes the frame we want
while( panimvalue->num.total <= k )
{
k -= panimvalue->num.total;
panimvalue += panimvalue->num.valid + 1;
// DEBUG
if( panimvalue->num.total < panimvalue->num.valid )
k = 0;
}
// if we're inside the span
if( panimvalue->num.valid > k )
{
// and there's more data in the span
if( panimvalue->num.valid > k + 1 )
{
pos[j] += (panimvalue[k+1].value * (1.0 - s) + s * panimvalue[k+2].value) * pbone->scale[j];
}
else
{
pos[j] += panimvalue[k+1].value * pbone->scale[j];
}
}
else
{
// are we at the end of the repeating values section and there's another section with data?
if( panimvalue->num.total <= k + 1 )
{
pos[j] += (panimvalue[panimvalue->num.valid].value * (1.0 - s) + s * panimvalue[panimvalue->num.valid + 2].value) * pbone->scale[j];
}
else
{
pos[j] += panimvalue[panimvalue->num.valid].value * pbone->scale[j];
}
}
}
if( pbone->bonecontroller[j] != -1 && adj )
{
pos[j] += adj[pbone->bonecontroller[j]];
}
}
}
/*
====================
CM_StudioSetUpTransform
CM_StudioCalcRotations
====================
*/
void CM_StudioSetUpTransform ( void )
void CM_StudioCalcRotations( edict_t *e, float pos[][3], vec4_t *q, dstudioseqdesc_t *pseqdesc, dstudioanim_t *panim, float f )
{
vec3_t mins, maxs, angles;
vec3_t modelpos;
int i;
int frame;
dstudiobone_t *pbone;
float adj[MAXSTUDIOCONTROLLERS];
float s, dadt = 1.0f; // noInterp
CM_StudioExtractBbox( studio.hdr, 0, mins, maxs );// adjust model center
VectorAdd( mins, maxs, modelpos );
VectorScale( modelpos, -0.5, modelpos );
if( f > pseqdesc->numframes - 1 )
f = 0;
else if( f < -0.01 )
f = -0.01;
VectorSet( angles, 0.0f, -90.0f, 90.0f ); // rotate matrix for 90 degrees
AngleVectors( angles, studio.rotmatrix[0], studio.rotmatrix[2], studio.rotmatrix[1] );
frame = (int)f;
s = (f - frame);
studio.rotmatrix[0][3] = modelpos[0];
studio.rotmatrix[1][3] = modelpos[1];
studio.rotmatrix[2][3] = modelpos[2];
studio.rotmatrix[2][2] *= -1;
// add in programtic controllers
pbone = (dstudiobone_t *)((byte *)studio.hdr + studio.hdr->boneindex);
CM_StudioCalcBoneAdj( dadt, adj, e->v.controller, e->v.controller );
for (i = 0; i < studio.hdr->numbones; i++, pbone++, panim++)
{
CM_StudioCalcBoneQuaterion( frame, s, pbone, panim, adj, q[i] );
CM_StudioCalcBonePosition( frame, s, pbone, panim, adj, pos[i] );
}
if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f;
if( pseqdesc->motiontype & STUDIO_Y ) pos[pseqdesc->motionbone][1] = 0.0f;
if( pseqdesc->motiontype & STUDIO_Z ) pos[pseqdesc->motionbone][2] = 0.0f;
s = 0 * ((1.0 - (f - (int)(f))) / (pseqdesc->numframes)) * e->v.framerate;
if( pseqdesc->motiontype & STUDIO_LX ) pos[pseqdesc->motionbone][0] += s * pseqdesc->linearmovement[0];
if( pseqdesc->motiontype & STUDIO_LY ) pos[pseqdesc->motionbone][1] += s * pseqdesc->linearmovement[1];
if( pseqdesc->motiontype & STUDIO_LZ ) pos[pseqdesc->motionbone][2] += s * pseqdesc->linearmovement[2];
}
void CM_StudioCalcRotations ( float pos[][3], vec4_t *q )
{
dstudiobone_t *pbone = (dstudiobone_t *)((byte *)studio.hdr + studio.hdr->boneindex);
int i;
/*
====================
StudioEstimateFrame
for (i = 0; i < studio.hdr->numbones; i++, pbone++ )
====================
*/
float CM_StudioEstimateFrame( edict_t *e, dstudioseqdesc_t *pseqdesc )
{
double f;
if( pseqdesc->numframes <= 1 )
f = 0;
else f = (e->v.frame * (pseqdesc->numframes - 1)) / 256.0;
if( pseqdesc->flags & STUDIO_LOOPING )
{
CM_StudioCalcBoneQuaterion( pbone, q[i] );
CM_StudioCalcBonePosition( pbone, pos[i]);
if( pseqdesc->numframes > 1 )
f -= (int)(f / (pseqdesc->numframes - 1)) * (pseqdesc->numframes - 1);
if( f < 0 ) f += (pseqdesc->numframes - 1);
}
else
{
if( f >= pseqdesc->numframes - 1.001 )
f = pseqdesc->numframes - 1.001;
if( f < 0.0 ) f = 0.0;
}
return f;
}
/*
====================
CM_StudioSlerpBones
====================
*/
void CM_StudioSlerpBones( vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s )
{
int i;
vec4_t q3;
float s1;
s = bound( 0.0f, s, 1.0f );
s1 = 1.0f - s;
for( i = 0; i < studio.hdr->numbones; i++ )
{
QuaternionSlerp( q1[i], q2[i], s, q3 );
q1[i][0] = q3[0];
q1[i][1] = q3[1];
q1[i][2] = q3[2];
q1[i][3] = q3[3];
pos1[i][0] = pos1[i][0] * s1 + pos2[i][0] * s;
pos1[i][1] = pos1[i][1] * s1 + pos2[i][1] * s;
pos1[i][2] = pos1[i][2] * s1 + pos2[i][2] * s;
}
}
/*
====================
CM_StudioGetAnim
====================
*/
dstudioanim_t *CM_StudioGetAnim( cmodel_t *m_pSubModel, dstudioseqdesc_t *pseqdesc )
{
dstudioseqgroup_t *pseqgroup;
byte *paSequences;
size_t filesize;
byte *buf;
Com_Assert( m_pSubModel == NULL );
pseqgroup = (dstudioseqgroup_t *)((byte *)studio.hdr + studio.hdr->seqgroupindex) + pseqdesc->seqgroup;
if( pseqdesc->seqgroup == 0 )
return (dstudioanim_t *)((byte *)studio.hdr + pseqgroup->data + pseqdesc->animindex);
paSequences = (void *)m_pSubModel->submodels;
if( paSequences == NULL )
{
// allocate sequence groups if needs
paSequences = (byte *)Mem_Alloc( m_pSubModel->mempool, sizeof( paSequences ) * MAXSTUDIOGROUPS );
m_pSubModel->submodels = (void *)paSequences; // just a container
}
if(((dstudiomodel_t *)&(paSequences[pseqdesc->seqgroup])) == NULL )
{
dstudioseqgroup_t *pseqhdr;
buf = FS_LoadFile( pseqgroup->name, &filesize );
if( !buf || !filesize || IDSEQGRPHEADER != LittleLong(*(uint *)buf ))
Host_Error( "CM_StudioGetAnim: can't load %s\n", pseqgroup->name );
pseqhdr = (dstudioseqgroup_t *)buf;
MsgDev( D_INFO, "loading %s\n", pseqgroup->name );
paSequences = (byte *)Mem_Alloc( m_pSubModel->mempool, filesize );
m_pSubModel->submodels = (void *)paSequences; // just a container
Mem_Copy( &paSequences[pseqdesc->seqgroup], buf, filesize );
Mem_Free( buf );
}
return (dstudioanim_t *)((byte *)paSequences[pseqdesc->seqgroup] + pseqdesc->animindex );
}
/*
@ -102,35 +422,353 @@ void CM_StudioCalcRotations ( float pos[][3], vec4_t *q )
CM_StudioSetupBones
====================
*/
void CM_StudioSetupBones( void )
void CM_StudioSetupBones( edict_t *e )
{
int i;
int i, oldseq;
double f;
dstudiobone_t *pbones;
dstudioseqdesc_t *pseqdesc;
dstudioanim_t *panim;
static float pos[MAXSTUDIOBONES][3];
static vec4_t q[MAXSTUDIOBONES];
matrix4x4 bonematrix;
CM_StudioCalcRotations( pos, q );
static float pos2[MAXSTUDIOBONES][3];
static vec4_t q2[MAXSTUDIOBONES];
static float pos3[MAXSTUDIOBONES][3];
static vec4_t q3[MAXSTUDIOBONES];
static float pos4[MAXSTUDIOBONES][3];
static vec4_t q4[MAXSTUDIOBONES];
oldseq = e->v.sequence; // TraceCode can't change sequence
if( e->v.sequence >= studio.hdr->numseq ) e->v.sequence = 0;
pseqdesc = (dstudioseqdesc_t *)((byte *)studio.hdr + studio.hdr->seqindex) + e->v.sequence;
f = CM_StudioEstimateFrame( e, pseqdesc );
panim = CM_StudioGetAnim( CM_ClipHandleToModel( e->v.modelindex ), pseqdesc );
CM_StudioCalcRotations( e, pos, q, pseqdesc, panim, f );
if( pseqdesc->numblends > 1 )
{
float s;
float dadt = 1.0f;
panim += studio.hdr->numbones;
CM_StudioCalcRotations( e, pos2, q2, pseqdesc, panim, f );
s = (e->v.blending[0] * dadt + e->v.blending[0] * (1.0 - dadt)) / 255.0;
CM_StudioSlerpBones( q, pos, q2, pos2, s );
if( pseqdesc->numblends == 4 )
{
panim += studio.hdr->numbones;
CM_StudioCalcRotations( e, pos3, q3, pseqdesc, panim, f );
panim += studio.hdr->numbones;
CM_StudioCalcRotations( e, pos4, q4, pseqdesc, panim, f );
s = (e->v.blending[0] * dadt + e->v.blending[0] * (1.0 - dadt)) / 255.0;
CM_StudioSlerpBones( q3, pos3, q4, pos4, s );
s = (e->v.blending[1] * dadt + e->v.blending[1] * (1.0 - dadt)) / 255.0;
CM_StudioSlerpBones( q, pos, q3, pos3, s );
}
}
pbones = (dstudiobone_t *)((byte *)studio.hdr + studio.hdr->boneindex);
for (i = 0; i < studio.hdr->numbones; i++)
for( i = 0; i < studio.hdr->numbones; i++ )
{
Matrix4x4_FromOriginQuat( bonematrix, pos[i][0], pos[i][1], pos[i][2], q[i][0], q[i][1], q[i][2], q[i][3] );
if( pbones[i].parent == -1 ) Matrix4x4_ConcatTransforms( studio.bones[i], studio.rotmatrix, bonematrix );
if( pbones[i].parent == -1 )
Matrix4x4_ConcatTransforms( studio.bones[i], studio.rotmatrix, bonematrix );
else Matrix4x4_ConcatTransforms( studio.bones[i], studio.bones[pbones[i].parent], bonematrix );
}
e->v.sequence = oldseq; // restore original value
}
/*
====================
StudioCalcAttachments
====================
*/
static void CM_StudioCalcAttachments( edict_t *e, int iAttachment, float *org, float *ang )
{
int i;
dstudioattachment_t *pAtt;
vec3_t axis[3];
vec3_t localOrg, localAng;
if( studio.hdr->numattachments > MAXSTUDIOATTACHMENTS )
{
studio.hdr->numattachments = MAXSTUDIOATTACHMENTS; // reduce it
MsgDev( D_WARN, "CM_StudioCalcAttahments: too many attachments on %s\n", studio.hdr->name );
}
iAttachment = bound( 0, iAttachment, studio.hdr->numattachments );
// calculate attachment points
pAtt = (dstudioattachment_t *)((byte *)studio.hdr + studio.hdr->attachmentindex);
for( i = 0; i < studio.hdr->numattachments; i++ )
{
if( i == iAttachment )
{
// compute pos and angles
Matrix4x4_VectorTransform( studio.bones[pAtt[i].bone], pAtt[i].org, localOrg );
Matrix4x4_VectorTransform( studio.bones[pAtt[i].bone], pAtt[i].vectors[0], axis[0] );
Matrix4x4_VectorTransform( studio.bones[pAtt[i].bone], pAtt[i].vectors[1], axis[1] );
Matrix4x4_VectorTransform( studio.bones[pAtt[i].bone], pAtt[i].vectors[2], axis[2] );
Matrix3x3_ToAngles( axis, localAng, true ); // FIXME: dll's uses FLU ?
if( org ) VectorCopy( localOrg, org );
if( ang ) VectorCopy( localAng, ang );
break; // done
}
}
}
void CM_StudioSetupModel ( int bodypart, int body )
void CM_StudioInitBoxHull( void )
{
int index;
int i, side;
cplane_t *p;
if(bodypart > studio.hdr->numbodyparts) bodypart = 0;
studio.bodypart = (dstudiobodyparts_t *)((byte *)studio.hdr + studio.hdr->bodypartindex) + bodypart;
for( i = 0; i < 6; i++ )
{
side = i & 1;
index = body / studio.bodypart->base;
index = index % studio.bodypart->nummodels;
studio.submodel = (dstudiomodel_t *)((byte *)studio.hdr + studio.bodypart->modelindex) + index;
// planes
p = &studio.planes[i*2];
p->type = i>>1;
p->signbits = 0;
VectorClear( p->normal );
p->normal[i>>1] = 1.0f;
p = &studio.planes[i*2+1];
p->type = 3 + (i>>1);
p->signbits = 0;
VectorClear( p->normal );
p->normal[i>>1] = -1;
p->signbits = SignbitsForPlane( p->normal );
}
}
void CM_StudioBoxHullFromBounds( const vec3_t mins, const vec3_t maxs )
{
studio.planes[0].dist = maxs[0];
studio.planes[1].dist = -maxs[0];
studio.planes[2].dist = mins[0];
studio.planes[3].dist = -mins[0];
studio.planes[4].dist = maxs[1];
studio.planes[5].dist = -maxs[1];
studio.planes[6].dist = mins[1];
studio.planes[7].dist = -mins[1];
studio.planes[8].dist = maxs[2];
studio.planes[9].dist = -maxs[2];
studio.planes[10].dist = mins[2];
studio.planes[11].dist = -mins[2];
}
bool CM_StudioSetup( edict_t *e )
{
cmodel_t *mod = CM_ClipHandleToModel( e->v.modelindex );
if( mod && mod->type == mod_studio && mod->extradata )
{
studio.hdr = (dstudiohdr_t *)mod->extradata;
CM_StudioSetUpTransform( e );
CM_StudioSetupBones( e );
return true;
}
return false;
}
bool CM_StudioTraceBox( vec3_t start, vec3_t end )
{
int i;
cplane_t *plane, *clipplane;
float enterFrac, leaveFrac;
bool getout, startout;
float d1, d2;
float f;
enterFrac = -1.0;
leaveFrac = 1.0;
clipplane = NULL;
getout = false;
startout = false;
// compare the trace against all planes of the brush
// find the latest time the trace crosses a plane towards the interior
// and the earliest time the trace crosses a plane towards the exterior
for( i = 0; i < 6; i++ )
{
plane = studio.planes + i * 2 + (i & 1);
d1 = DotProduct( start, plane->normal ) - plane->dist;
d2 = DotProduct( end, plane->normal ) - plane->dist;
if( d2 > 0.0f ) getout = TRUE; // endpoint is not in solid
if( d1 > 0.0f ) startout = TRUE;
// if completely in front of face, no intersection with the entire brush
if( d1 > 0 && ( d2 >= SURFACE_CLIP_EPSILON || d2 >= d1 ))
return false;
// if it doesn't cross the plane, the plane isn't relevent
if( d1 <= 0 && d2 <= 0 )
continue;
// crosses face
if( d1 > d2 )
{
// enter
f = (d1 - SURFACE_CLIP_EPSILON) / (d1 - d2);
if( f < 0.0f ) f = 0.0f;
if( f > enterFrac )
{
enterFrac = f;
clipplane = plane;
}
}
else
{
// leave
f = (d1 + SURFACE_CLIP_EPSILON) / (d1 - d2);
if( f > 1.0f ) f = 1.0f;
if( f < leaveFrac )
{
leaveFrac = f;
}
}
}
// all planes have been checked, and the trace was not
// completely outside the brush
if( !startout )
{
// original point was inside brush
if( !getout ) studio.trace.flFraction = 0.0f;
return true;
}
if( enterFrac < leaveFrac )
{
if( enterFrac > -1 && enterFrac < studio.trace.flFraction )
{
if( enterFrac < 0.0f )
enterFrac = 0.0f;
studio.trace.flFraction = enterFrac;
VectorCopy( clipplane->normal, studio.trace.vecPlaneNormal );
studio.trace.flPlaneDist = clipplane->dist;
return true;
}
}
return false;
}
bool CM_StudioTrace( trace_t *tr, edict_t *e, const vec3_t start, const vec3_t end )
{
matrix4x4 m;
vec3_t transformedStart, transformedEnd;
int i, outBone;
if( !CM_StudioSetup( e ) || !studio.hdr->numhitboxes )
{
tr->iHitgroup = -1;
return false;
}
Mem_Set( &studio.trace, 0, sizeof( trace_t ));
studio.trace.flFraction = 1.0f;
studio.trace.iHitgroup = -1;
outBone = -1;
for( i = 0; i < studio.hdr->numhitboxes; i++ )
{
dstudiobbox_t *phitbox = (dstudiobbox_t *)((byte*)studio.hdr + studio.hdr->hitboxindex) + i;
Matrix4x4_Invert_Simple( m, studio.bones[phitbox->bone] );
Matrix4x4_VectorTransform( m, start, transformedStart );
Matrix4x4_VectorTransform( m, end, transformedEnd );
CM_StudioBoxHullFromBounds( phitbox->bbmin, phitbox->bbmax );
if( CM_StudioTraceBox( transformedStart, transformedEnd ))
{
outBone = phitbox->bone;
studio.trace.iHitgroup = phitbox->group;
}
if( studio.trace.flFraction == 0.0f )
break;
}
// all hitboxes were swept, get trace result
if( outBone >= 0 )
{
if( tr )
{
tr->flFraction = studio.trace.flFraction;
tr->iHitgroup = studio.trace.iHitgroup;
Matrix4x4_VectorRotate( studio.bones[outBone], studio.trace.vecEndPos, tr->vecEndPos );
if( tr->flFraction == 1.0f ) VectorCopy( end, tr->vecEndPos );
else
{
dstudiobone_t *pbone = (dstudiobone_t *)((byte*)studio.hdr + studio.hdr->boneindex) + outBone;
tr->pTexName = pbone->name; // debug
tr->iContents = (e->v.health > 0.0f ) ? BASECONT_BODY : BASECONT_CORPSE;
VectorLerp( start, tr->flFraction, end, tr->vecEndPos );
}
tr->flPlaneDist = DotProduct( tr->vecEndPos, tr->vecPlaneNormal );
}
return true;
}
return false;
}
void CM_StudioGetAttachment( edict_t *e, int iAttachment, float *org, float *ang )
{
if( !CM_StudioSetup( e ) || studio.hdr->numattachments <= 0 )
{
// reset attachments
if( org ) VectorCopy( e->v.origin, org );
if( ang ) VectorCopy( e->v.angles, ang );
return;
}
CM_StudioCalcAttachments( e, iAttachment, org, ang );
}
void CM_GetBonePosition( edict_t* e, int iBone, float *org, float *ang )
{
matrix3x3 axis;
if( !CM_StudioSetup( e ) || studio.hdr->numbones <= 0 )
{
// reset bones
if( org ) VectorCopy( e->v.origin, org );
if( ang ) VectorCopy( e->v.angles, ang );
return;
}
iBone = bound( 0, iBone, studio.hdr->numbones );
Matrix3x3_FromMatrix4x4( axis, studio.bones[iBone] );
if( org ) Matrix4x4_OriginFromMatrix( studio.bones[iBone], org );
if( ang ) Matrix3x3_ToAngles( axis, ang, true );
}
bool CM_StudioModel( byte *buffer, uint filesize )

View File

@ -1,16 +0,0 @@
<html>
<body>
<pre>
<h1>Build Log</h1>
<h3>
--------------------Configuration: cms_xr - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
<h3>Results</h3>
cms_xr.dll - 0 error(s), 0 warning(s)
</pre>
</body>
</html>

View File

@ -24,6 +24,8 @@ typedef struct movevars_s movevars_t;
typedef struct usercmd_s usercmd_t;
typedef struct cl_priv_s cl_priv_t;
typedef struct sv_priv_s sv_priv_t;
typedef unsigned short CRC16_t;
typedef unsigned long CRC32_t;
typedef float vec_t;
#define _INTEGRAL_MAX_BITS 64

View File

@ -26,40 +26,8 @@
#define ATTN_RICOCHET 1.5f
#define ATTN_GUNFIRE 0.27f
typedef enum
{
SNDLVL_NONE = 0,
SNDLVL_25dB = 25,
SNDLVL_30dB = 30,
SNDLVL_35dB = 35,
SNDLVL_40dB = 40,
SNDLVL_45dB = 45,
SNDLVL_50dB = 50, // 3.9
SNDLVL_55dB = 55, // 3.0
SNDLVL_IDLE = 60, // 2.0
SNDLVL_60dB = 60, // 2.0
SNDLVL_65dB = 65, // 1.5
SNDLVL_STATIC = 66, // 1.25
SNDLVL_70dB = 70, // 1.0
SNDLVL_NORM = 75,
SNDLVL_75dB = 75, // 0.8
SNDLVL_80dB = 80, // 0.7
SNDLVL_TALKING = 80, // 0.7
SNDLVL_85dB = 85, // 0.6
SNDLVL_90dB = 90, // 0.5
SNDLVL_95dB = 95,
SNDLVL_100dB = 100, // 0.4
SNDLVL_105dB = 105,
SNDLVL_110dB = 110,
SNDLVL_120dB = 120,
SNDLVL_130dB = 130,
SNDLVL_GUNFIRE = 140, // 0.27
SNDLVL_140dB = 140, // 0.2
SNDLVL_150dB = 150, // 0.2
} soundlevel_t;
// common conversion tools
#define ATTN_TO_SNDLVL( a ) (soundlevel_t)(int)((a) ? (50 + 20 / ((float)a)) : 0 )
#define ATTN_TO_SNDLVL( a ) (int)((a) ? (50 + 20 / ((float)a)) : 0 )
#define SNDLVL_TO_ATTN( a ) ((a > 50) ? (20.0f / (float)(a - 50)) : 4.0 )
#define SND_CHANGE_VOL (1<<0) // change sound vol
@ -137,7 +105,7 @@ typedef enum
#define FL_NOTARGET (1<<7) // mark all npc's as neytral
#define FL_SKIPLOCALHOST (1<<8) // Don't send entity to local host, it's predicting this entity itself
#define FL_ONGROUND (1<<9) // at rest / on the ground
#define FL_PARTIALONGROUND (1<<10) // not corners are valid
#define FL_PARTIALGROUND (1<<10) // not corners are valid
#define FL_WATERJUMP (1<<11) // water jumping
#define FL_FROZEN (1<<12) // stop moving, but continue thinking (e.g. for thirdperson camera)
#define FL_FAKECLIENT (1<<13) // JAC: fake client, simulated server side; don't send network messages to them
@ -224,6 +192,12 @@ typedef enum
WALKMOVE_WORLDONLY, // doesn't hit ANY entities, no matter what the solid type
WALKMOVE_CHECKONLY // move, but don't touch triggers
} walkmove_t;
// monster's move to origin stuff
#define MOVE_START_TURN_DIST 64 // when this far away from moveGoal, start turning to face next goal
#define MOVE_STUCK_DIST 32 // if a monster can't step this far, it is stuck.
#define MOVE_NORMAL 0 // normal move in the direction monster is facing
#define MOVE_STRAFE 1 // moves in direction specified, no matter which way monster is facing
// edict movetype
typedef enum

View File

@ -67,8 +67,8 @@ typedef struct enginefuncs_s
int (*pfnModelFrames)( int modelIndex );
void (*pfnSetSize)( edict_t *e, const float *rgflMin, const float *rgflMax );
void (*pfnChangeLevel)( const char* s1, const char* s2 );
edict_t* (*pfnFindClientInPHS)( edict_t *pEdict ); // was pfnGetSpawnParms
edict_t* (*pfnEntitiesInPHS)( edict_t *pplayer ); // was pfnSaveSpawnParms
edict_t* (*pfnFindClientInPHS)( edict_t *pEdict ); // was pfnGetSpawnParms
edict_t* (*pfnEntitiesInPHS)( edict_t *pplayer ); // was pfnSaveSpawnParms
float (*pfnVecToYaw)( const float *rgflVector );
void (*pfnVecToAngles)( const float *rgflVectorIn, float *rgflVectorOut );
void (*pfnMoveToOrigin)( edict_t *ent, const float *pflGoal, float dist, int iMoveType );
@ -85,7 +85,7 @@ typedef struct enginefuncs_s
void (*pfnRemoveEntity)( edict_t* e );
edict_t* (*pfnCreateNamedEntity)( string_t className );
void (*pfnMakeStatic)( edict_t *ent );
void (*pfnLinkEdict)( edict_t *e ); // was pfnEntIsOnFloor
void (*pfnLinkEdict)( edict_t *e, int touch_triggers ); // was pfnEntIsOnFloor
int (*pfnDropToFloor)( edict_t* e );
int (*pfnWalkMove)( edict_t *ent, float yaw, float dist, int iMode );
void (*pfnSetOrigin)( edict_t *e, const float *rgflOrigin );
@ -94,7 +94,7 @@ typedef struct enginefuncs_s
void (*pfnTraceLine)( const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr );
void (*pfnTraceToss)( edict_t* pent, edict_t* pentToIgnore, TraceResult *ptr );
int (*pfnTraceMonsterHull)( edict_t *pEdict, const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr );
void (*pfnTraceHull)( const float *v1, const float *mins, const float *maxs, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr );
void (*pfnTraceHull)( const float *v1, const float *v2, int fNoMonsters, int hullNumber, edict_t *pentToSkip, TraceResult *ptr );
void (*pfnTraceModel)( const float *v1, const float *v2, edict_t *pent, TraceResult *ptr );
const char *(*pfnTraceTexture)( edict_t *pTextureEntity, const float *v1, const float *v2 );
void (*pfnTraceSphere)( const float *v1, const float *v2, int fNoMonsters, float radius, edict_t *pentToSkip, TraceResult *ptr );
@ -105,7 +105,7 @@ typedef struct enginefuncs_s
void (*pfnParticleEffect)( const float *org, const float *dir, float color, float count );
void (*pfnLightStyle)( int style, char* val );
int (*pfnDecalIndex)( const char *name );
int (*pfnPointContents)( const float *rgflVector);
int (*pfnPointContents)( const float *rgflVector );
void (*pfnMessageBegin)( int msg_dest, int msg_type, const float *pOrigin, edict_t *ed );
void (*pfnMessageEnd)( void );
void (*pfnWriteByte)( int iValue );
@ -122,11 +122,11 @@ typedef struct enginefuncs_s
void (*pfnCVarSetFloat)( const char *szVarName, float flValue );
void (*pfnCVarSetString)( const char *szVarName, const char *szValue );
void (*pfnAlertMessage)( ALERT_TYPE level, char *szFmt, ... );
void (*pfnWriteFloat)( float flValue ); // was pfnEngineFprintf
void (*pfnEngineFprintf)( void *pfile, char *szFmt, ... );
void* (*pfnPvAllocEntPrivateData)( edict_t *pEdict, long cb );
void* (*pfnPvEntPrivateData)( edict_t *pEdict );
void (*pfnFreeEntPrivateData)( edict_t *pEdict );
const char *(*pfnGetString)( string_t iString ); // was pfnSzFromIndex
const char *(*pfnSzFromIndex)( string_t iString );
string_t (*pfnAllocString)( const char *szValue );
entvars_t *(*pfnGetVarsOfEnt)( edict_t *pEdict );
edict_t* (*pfnPEntityOfEntOffset)( int iEntOffset );
@ -136,7 +136,7 @@ typedef struct enginefuncs_s
edict_t* (*pfnFindEntityByVars)( entvars_t* pvars );
void* (*pfnGetModelPtr)( edict_t* pEdict );
int (*pfnRegUserMsg)( const char *pszName, int iSize );
void (*pfnAnimationAutomove)( const edict_t* pEdict, float flTime );
void (*pfnAreaPortal)( edict_t *pEdict, int enable ); // was pfnAnimationAutomove
void (*pfnGetBonePosition)( const edict_t* pEdict, int iBone, float *rgflOrigin, float *rgflAngles );
dword (*pfnFunctionFromName)( const char *pName );
const char *(*pfnNameForFunction)( dword function );
@ -146,10 +146,10 @@ typedef struct enginefuncs_s
const char *(*pfnCmd_Argv)( int argc );
int (*pfnCmd_Argc)( void );
void (*pfnGetAttachment)( const edict_t *pEdict, int iAttachment, float *rgflOrigin, float *rgflAngles );
void (*pfnCRC_Init)( word *pulCRC );
void (*pfnCRC_ProcessBuffer)( word *pulCRC, void *p, int len );
void (*pfnCRC_ProcessByte)( word *pulCRC, byte ch );
word (*pfnCRC_Final)( word pulCRC );
void (*pfnCRC_Init)( CRC32_t *pulCRC );
void (*pfnCRC_ProcessBuffer)( CRC32_t *pulCRC, void *p, int len );
void (*pfnCRC_ProcessByte)( CRC32_t *pulCRC, byte ch );
CRC32_t (*pfnCRC_Final)( CRC32_t pulCRC );
long (*pfnRandomLong)( long lLow, long lHigh );
float (*pfnRandomFloat)( float flLow, float flHigh );
void (*pfnSetView)( const edict_t *pClient, const edict_t *pViewent );
@ -161,12 +161,12 @@ typedef struct enginefuncs_s
int (*pfnCompareFileTime)( const char *filename1, const char *filename2, int *iCompare );
void (*pfnGetGameDir)( char *szGetGameDir );
void (*pfnClassifyEdict)( edict_t *pEdict, int ed_type ); // was pfnCvar_RegisterVariable
void (*pfnAreaPortal)( edict_t *pEdict, BOOL enable ); // was pfnFadeClientVolume
void (*pfnFadeClientVolume)( const edict_t *pEdict, int fadePercent, int fadeOutSeconds, int holdTime, int fadeInSeconds );
void (*pfnSetClientMaxspeed)( const edict_t *pEdict, float fNewMaxspeed );
edict_t *(*pfnCreateFakeClient)( const char *netname ); // returns NULL if fake client can't be created
void (*pfnThinkFakeClient)( edict_t *client, usercmd_t *cmd ); // was pfnRunPlayerMove, like it
int (*pfnFileExists)( const char *filename ); // was pfnNumberOfEntities - see gpGlobals->numEntities
char* (*pfnGetInfoKeyBuffer)( edict_t *e ); // passing in NULL gets the serverinfo
char* (*pfnGetInfoKeyBuffer)( edict_t *e ); // passing in NULL gets the serverinfo
char* (*pfnInfoKeyValue)( char *infobuffer, char *key );
void (*pfnSetKeyValue)( char *infobuffer, char *key, char *value );
void (*pfnSetClientKeyValue)( int clientIndex, char *infobuffer, char *key, char *value );
@ -184,16 +184,27 @@ typedef struct enginefuncs_s
const char *(*pfnGetPhysicsInfoString)( const edict_t *pClient );
word (*pfnPrecacheEvent)( int type, const char *psz );
void (*pfnPlaybackEvent)( int flags, const edict_t *pInvoker, word eventindex, float delay, event_args_t *args );
long (*pfnFWrite)(void *file, const void* data, size_t datasize);// was pfnSetFatPVS
long (*pfnFRead)( void *file, void* buffer, size_t buffersize ); // was pfnSetFatPAS
void *(*pfnFOpen)( const char* path, const char* mode ); // was pfnCheckVisibility
int (*pfnFClose)( void *file ); // was pfnDeltaSetField
void (*pfnDropClient)( int clientIndex ); // was pfnDeltaUnsetField
void (*pfnHostError)( const char *szFmt, ... ); // was pfnDeltaAddEncoder
void (*pfnGetPlayerPing)( const edict_t *pClient, int *ping ); // was pfnGetCurrentPlayer
BOOL (*pfnCanSkipPlayer)( const edict_t *player );
// after this point enginefuncs_t completely unmatched with Half-Life interface
byte* (*pfnSetFatPVS)( const float *org, int portal );
byte* (*pfnSetFatPHS)( const float *org, int portal );
int (*pfnCheckVisibility)( const edict_t *entity, unsigned char *pset );
void* (*pfnFOpen)( const char* path, const char* mode ); // was pfnDeltaSetField
long (*pfnFRead)( void *file, void* buffer, size_t buffersize ); // was pfnDeltaUnsetField
long (*pfnFWrite)(void *file, const void* data, size_t datasize);// was pfnDeltaAddEncoder
int (*pfnFClose)( void *file ); // was pfnGetCurrentPlayer
int (*pfnCanSkipPlayer)( const edict_t *player );
int (*pfnFGets)( void *file, byte *string, size_t bufsize ); // was fnDeltaFindField
int (*pfnFSeek)( void *file, long offset, int whence ); // was pfnDeltaSetFieldByIndex
long (*pfnFTell)( void *file ); // was pfnDeltaUnsetFieldByIndex
void (*pfnSetGroupMask)( int mask, int op );
void (*pfnDropClient)( int clientIndex ); // was pfnCreateInstancedBaseline
void (*pfnHostError)( const char *szFmt, ... ); // was pfnCvar_DirectSet
char *(*pfnParseToken)( const char **data_p ); // was pfnForceUnmodified
void (*pfnGetPlayerStats)( const edict_t *pClient, int *ping, int *packet_loss );
int (*pfnAreasConnected)( edict_t *pClient, edict_t *pEdict ); // was pfnAddServerCommand
void* (*pfnLoadLibrary)( const char *name ); // was pfnVoice_GetClientListening
void* (*pfnGetProcAddress)( void *hInstance, const char *name ); // was pfnVoice_SetClientListening
void (*pfnFreeLibrary)( void *hInstance ); // was pfnGetPlayerAuthId
// ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 138
} enginefuncs_t;
// passed to pfnKeyValue
@ -354,12 +365,16 @@ typedef struct
void (*pfnPM_Move)( playermove_t *ppmove, int server );
void (*pfnPM_Init)( playermove_t *ppmove );
char (*pfnPM_FindTextureType)( const char *name );
int (*pfnShouldCollide)( edict_t *pentTouched, edict_t *pentOther );
void (*pfnUpdateEntityState)( struct entity_state_s *to, edict_t *from, int baseline );
void (*pfnOnFreeEntPrivateData)( edict_t *pEnt );
void (*pfnGameShutdown)( void );
void (*pfnSetupVisibility)( edict_t *pViewEntity, edict_t *pClient, byte **pvs, byte **phs );
void (*pfnPhysicsEntity)( edict_t *pEntity ); // was pfnUpdateClientData
int (*pfnAddToFullPack)( edict_t *pClient, edict_t *pEntity, int hostflags );
void (*pfnEndFrame)( void ); // was pfnCreateBaseline
int (*pfnShouldCollide)( edict_t *pTouch, edict_t *pOther ); // was pfnCreateBaseline
void (*pfnUpdateEntityState)( struct entity_state_s *to, edict_t *from, int baseline ); // was pfnRegisterEncoders
void (*pfnOnFreeEntPrivateData)( edict_t *pEnt ); // was pfnGetWeaponData
void (*pfnCmdStart)( const edict_t *player, const usercmd_t *cmd, unsigned int random_seed );
void (*pfnCmdEnd)( const edict_t *player );
void (*pfnGameShutdown)( void ); // was pfnConnectionlessPacket
} DLL_FUNCTIONS;
typedef int (*SERVERAPI)( DLL_FUNCTIONS *pFunctionTable, enginefuncs_t* engfuncs, globalvars_t *pGlobals );

View File

@ -72,7 +72,7 @@ void CL_PlayVideo_f( void )
Cbuf_AddText(va("killserver\n; wait\n; movie %s\n;", Cmd_Argv(1)));
return;
}
SCR_PlayCinematic( Cmd_Argv(1), 0 );
SCR_PlayCinematic( Cmd_Argv( 1 ));
}
/*

View File

@ -270,7 +270,7 @@ DECALS MANAGEMENT
==============================================================
*/
#define MAX_DECALS 256
#define MAX_DRAWDECALS 256
#define MAX_DECAL_VERTS 128
#define MAX_DECAL_FRAGMENTS 64
@ -288,13 +288,13 @@ typedef struct cdecal_s
poly_t *poly;
} cdecal_t;
static cdecal_t cl_decals[MAX_DECALS];
static cdecal_t cl_decals_headnode, *cl_free_decals;
static cdecal_t cl_decals[MAX_DRAWDECALS];
static cdecal_t cl_decals_headnode, *cl_free_decals;
static poly_t cl_decal_polys[MAX_DECALS];
static vec3_t cl_decal_verts[MAX_DECALS][MAX_DECAL_VERTS];
static vec2_t cl_decal_stcoords[MAX_DECALS][MAX_DECAL_VERTS];
static rgba_t cl_decal_colors[MAX_DECALS][MAX_DECAL_VERTS];
static poly_t cl_decal_polys[MAX_DRAWDECALS];
static vec3_t cl_decal_verts[MAX_DRAWDECALS][MAX_DECAL_VERTS];
static vec2_t cl_decal_stcoords[MAX_DRAWDECALS][MAX_DECAL_VERTS];
static rgba_t cl_decal_colors[MAX_DRAWDECALS][MAX_DECAL_VERTS];
/*
=================
@ -313,9 +313,9 @@ void CL_ClearDecals( void )
cl_decals_headnode.prev = &cl_decals_headnode;
cl_decals_headnode.next = &cl_decals_headnode;
for( i = 0; i < MAX_DECALS; i++ )
for( i = 0; i < MAX_DRAWDECALS; i++ )
{
if( i < MAX_DECALS - 1 )
if( i < MAX_DRAWDECALS - 1 )
cl_decals[i].next = &cl_decals[i+1];
cl_decals[i].poly = &cl_decal_polys[i];
@ -393,7 +393,7 @@ void CL_SpawnDecal( vec3_t org, vec3_t dir, float rot, float rad, float *col, fl
rgba_t color;
// invalid decal
if( rad <= 0 || VectorCompare( dir, vec3_origin ))
if( rad <= 0 || VectorIsNull( dir ))
return;
// calculate orientation matrix
@ -417,9 +417,17 @@ void CL_SpawnDecal( vec3_t org, vec3_t dir, float rot, float rad, float *col, fl
VectorScale( axis[1], rad, axis[1] );
VectorScale( axis[2], rad, axis[2] );
dietime = cl.time + (die * 1000);
fadefreq = 0.001f / min( fadetime, die );
fadetime = cl.time + (die - min( fadetime, die )) * 1000;
if( die == -1.0f )
{
dietime = -1.0f;
fadefreq = fadetime = 1.0f;
}
else
{
dietime = cl.time + (die * 1000);
fadefreq = 0.001f / min( fadetime, die );
fadetime = cl.time + (die - min( fadetime, die )) * 1000;
}
for( i = 0, fr = fragments; i < numfragments; i++, fr++ )
{
@ -476,6 +484,13 @@ void CL_AddDecals( void )
{
next = dl->prev;
if( dl->die == -1.0f )
{
// static decals not fading, not removes
re->AddPolygon( dl->poly );
continue;
}
// it's time to DIE
if( dl->die <= cl.time )
{
@ -525,6 +540,57 @@ void CL_AddDecals( void )
}
}
void CL_FindExplosionPlane( const vec3_t origin, float radius, vec3_t result )
{
static vec3_t planes[6] = {{0, 0, 1}, {0, 1, 0}, {1, 0, 0}, {0, 0, -1}, {0, -1, 0}, {-1, 0, 0}};
float best = 1.0f;
vec3_t point, dir;
trace_t trace;
int i;
if( !result ) return;
VectorClear( dir );
for( i = 0; i < 6; i++ )
{
VectorMA( origin, radius, planes[i], point );
trace = CL_Trace( origin, vec3_origin, vec3_origin, point, MOVE_WORLDONLY, NULL, MASK_SOLID );
if( trace.fAllSolid || trace.flFraction == 1.0f )
continue;
if( trace.flFraction < best )
{
best = trace.flFraction;
VectorCopy( trace.vecPlaneNormal, dir );
}
}
VectorCopy( dir, result );
}
/*
===============
CL_SpawnStaticDecal
===============
*/
void CL_SpawnStaticDecal( vec3_t origin, int decalIndex, int entityIndex, int modelIndex )
{
vec4_t col = { 1.0f, 1.0f, 1.0f, 1.0f };
float radius = 32.0f;
vec3_t dir;
if( entityIndex != 0 )
{
MsgDev( D_ERROR, "Current Xash version allows static decals only on world surfaces\n" );
return;
}
CL_FindExplosionPlane( origin, radius, dir );
decalIndex = bound( 0, decalIndex, MAX_DECALS - 1 );
CL_SpawnDecal( origin, dir, 90.0f, radius, col, -1.0f, 0.0f, 0, cl.decal_shaders[decalIndex] );
}
/*
===============
pfnAddDecal
@ -577,9 +643,10 @@ struct cparticle_s
rgba_t pColor[4];
};
cparticle_t *cl_active_particles, *cl_free_particles;
cparticle_t *cl_active_particles, *cl_free_particles;
static cparticle_t cl_particle_list[MAX_PARTICLES];
static vec3_t cl_particle_velocities[NUMVERTEXNORMALS];
static vec3_t cl_particle_velocities[NUMVERTEXNORMALS];
static vec3_t cl_particlePalette[256];
/*
=================
@ -627,6 +694,10 @@ void CL_ClearParticles( void )
{
int i;
cparticle_t *p;
rgbdata_t *pic;
byte buf[1]; // fake stub
pic = FS_LoadImage( "#quake.pal", buf, 768 );
cl_active_particles = NULL;
cl_free_particles = cl_particle_list;
@ -642,11 +713,23 @@ void CL_ClearParticles( void )
cl_particle_velocities[i][1] = (rand() & 255) * 0.01f;
cl_particle_velocities[i][2] = (rand() & 255) * 0.01f;
}
for( i = 0, p = cl_particle_list; i < MAX_PARTICLES; i++, p++ )
{
p->pStcoords[0][0] = p->pStcoords[2][1] = p->pStcoords[1][0] = p->pStcoords[1][1] = 0;
p->pStcoords[0][1] = p->pStcoords[2][0] = p->pStcoords[3][0] = p->pStcoords[3][1] = 1;
}
// Xash3D have built-in Quake1 palette - use it
for( i = 0; pic && i < 256; i++ )
{
cl_particlePalette[i][0] = pic->palette[i*4+0] * (1.0f / 255);
cl_particlePalette[i][1] = pic->palette[i*4+1] * (1.0f / 255);
cl_particlePalette[i][2] = pic->palette[i*4+2] * (1.0f / 255);
}
if( pic ) FS_FreeImage( pic );
else MsgDev( D_WARN, "SV_InitParticles: palette not installed\n" );
}
/*
@ -852,6 +935,17 @@ void CL_AddParticles( void )
*(int *)p->pColor[2] = *(int *)modulate;
*(int *)p->pColor[3] = *(int *)modulate;
if( radius == 1.0f )
{
float scale = 0.0f;
// hack a scale up to keep quake particles from disapearing
scale += (origin[0] - cl.refdef.vieworg[0]) * cl.refdef.forward[0];
scale += (origin[1] - cl.refdef.vieworg[1]) * cl.refdef.forward[1];
scale += (origin[2] - cl.refdef.vieworg[2]) * cl.refdef.forward[2];
if( scale >= 20 ) radius = 1.0f + scale * 0.004f;
}
if( length != 1 )
{
// find orientation vectors
@ -934,6 +1028,45 @@ void CL_AddParticles( void )
cl_active_particles = active;
}
/*
===============
CL_ParticleEffect
old good quake1 particles
===============
*/
void CL_ParticleEffect( const vec3_t org, const vec3_t dir, int color, int count )
{
int i, pal;
cparticle_t src;
for( i = 0; i < count; i++ )
{
src.origin[0] = org[0] + RANDOM_FLOAT( -8, 8 );
src.origin[1] = org[1] + RANDOM_FLOAT( -8, 8 );
src.origin[2] = org[2] + RANDOM_FLOAT( -8, 8 );
src.velocity[0] = dir[0] * 15;
src.velocity[1] = dir[1] * 15;
src.velocity[2] = dir[2] * 15;
pal = (color & ~7) + (rand() & 7);
src.color[0] = cl_particlePalette[pal][0];
src.color[1] = cl_particlePalette[pal][1];
src.color[2] = cl_particlePalette[pal][2];
VectorClear( src.colorVelocity );
VectorClear( src.accel );
src.alpha = 1.0;
src.alphaVelocity = -8.0 + RANDOM_FLOAT( 1.0, 5.0 ); // lifetime
src.radius = 1.0; // quake particles have constant sizes
src.radiusVelocity = 0;
src.length = 1;
src.lengthVelocity = 0;
src.rotation = 0; // quake particles doesn't rotating
if( !pfnAddParticle( &src, cls.particle, 0 ))
return;
}
}
/*
===============
pfnAddParticle

View File

@ -181,8 +181,6 @@ void CL_ParsePacketEntities( sizebuf_t *msg, frame_t *oldframe, frame_t *newfram
oldnum = oldstate->number;
}
}
for( ; EDICT_NUM( clgame.globals->numEntities - 1 )->free; clgame.globals->numEntities-- );
}
/*
@ -312,6 +310,7 @@ void CL_AddPacketEntities( frame_t *frame )
// NOTE: skyportal entity never added to rendering
if( ed_type == ED_SKYPORTAL ) cl.render_flags |= RDF_SKYPORTALINVIEW;
}
for( ; EDICT_NUM( clgame.globals->numEntities - 1 )->free; clgame.globals->numEntities-- );
if( cl.oldframe && !memcmp( cl.oldframe->areabits, cl.frame.areabits, sizeof( cl.frame.areabits )))
cl.render_flags |= RDF_OLDAREABITS;

View File

@ -7,8 +7,8 @@
#include "client.h"
#include "byteorder.h"
#include "matrix_lib.h"
#include "com_library.h"
#include "const.h"
#include "com_library.h"
#include "triangle_api.h"
#include "effects_api.h"
@ -965,7 +965,7 @@ pfnCenterPrint
called once from message
=============
*/
void pfnCenterPrint( const char *text, int y, int charWidth )
void CL_CenterPrint( const char *text, int y, int charWidth )
{
char *s;
@ -1315,43 +1315,6 @@ const char *CL_GetString( string_t iString )
{
return StringTable_GetString( clgame.hStringTable, iString );
}
/*
=============
CL_LoadLibrary
=============
*/
static void *CL_LoadLibrary( const char *name )
{
string libpath;
Com_BuildPath( name, libpath );
return Com_LoadLibrary( libpath );
}
/*
=============
CL_GetProcAddress
=============
*/
static void *CL_GetProcAddress( void *hInstance, const char *name )
{
if( !hInstance ) return NULL;
return Com_GetProcAddress( hInstance, name );
}
/*
=============
CL_FreeLibrary
=============
*/
static void CL_FreeLibrary( void *hInstance )
{
Com_FreeLibrary( hInstance );
}
/*
=================
@ -1361,30 +1324,7 @@ pfnFindExplosionPlane
*/
static void pfnFindExplosionPlane( const float *origin, float radius, float *result )
{
static vec3_t planes[6] = {{0, 0, 1}, {0, 1, 0}, {1, 0, 0}, {0, 0, -1}, {0, -1, 0}, {-1, 0, 0}};
float best = 1.0f;
vec3_t point, dir;
trace_t trace;
int i;
if( !result ) return;
VectorClear( dir );
for( i = 0; i < 6; i++ )
{
VectorMA( origin, radius, planes[i], point );
trace = CL_Trace( origin, vec3_origin, vec3_origin, point, MOVE_WORLDONLY, NULL, MASK_SOLID );
if( trace.fAllSolid || trace.flFraction == 1.0f )
continue;
if( trace.flFraction < best )
{
best = trace.flFraction;
VectorCopy( trace.vecPlaneNormal, dir );
}
}
VectorCopy( dir, result );
CL_FindExplosionPlane( origin, radius, result );
}
/*
@ -1780,7 +1720,7 @@ static cl_enginefuncs_t gEngfuncs =
pfnPlaySoundByIndex,
AngleVectors,
pfnDrawCenterPrint,
pfnCenterPrint,
CL_CenterPrint,
pfnDrawString,
pfnGetDrawParms,
pfnSetDrawParms,
@ -1812,9 +1752,9 @@ static cl_enginefuncs_t gEngfuncs =
pfnLoadFile,
pfnFileExists,
pfnGetGameDir,
CL_LoadLibrary,
CL_GetProcAddress,
CL_FreeLibrary,
pfnLoadLibrary,
pfnGetProcAddress,
pfnFreeLibrary,
Host_Error,
&gTriApi,
&gEfxApi

View File

@ -635,9 +635,9 @@ void CL_WritePacket( void )
}
// send a userinfo update if needed
if( userinfo_modified )
if( userinfo->modified )
{
userinfo_modified = false;
userinfo->modified = false;
MSG_WriteByte( &cls.netchan.message, clc_userinfo );
MSG_WriteString( &cls.netchan.message, Cvar_Userinfo( ));
}

View File

@ -1,23 +1,7 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// cl_main.c -- client main loop
//=======================================================================
// Copyright XashXT Group 2009 ©
// cl_main.c - client main loop
//=======================================================================
#include "common.h"
#include "client.h"
@ -37,6 +21,7 @@ cvar_t *cl_particlelod;
cvar_t *cl_shownet;
cvar_t *cl_showmiss;
cvar_t *cl_mouselook;
cvar_t *userinfo;
//
// userinfo
@ -49,11 +34,10 @@ cvar_t *topcolor;
cvar_t *bottomcolor;
cvar_t *rate;
client_static_t cls;
client_t cl;
client_static_t cls;
clgame_static_t clgame;
extern cvar_t *allow_download;
//======================================================================
//======================================================================
@ -172,8 +156,8 @@ void CL_SendConnectPacket (void)
if( adr.port == 0 ) adr.port = BigShort( PORT_SERVER );
port = Cvar_VariableValue( "net_qport" );
userinfo_modified = false;
Netchan_OutOfBandPrint(NS_CLIENT, adr, "connect %i %i %i \"%s\"\n", PROTOCOL_VERSION, port, cls.challenge, Cvar_Userinfo());
userinfo->modified = false;
Netchan_OutOfBandPrint( NS_CLIENT, adr, "connect %i %i %i \"%s\"\n", PROTOCOL_VERSION, port, cls.challenge, Cvar_Userinfo( ));
}
/*
@ -221,17 +205,17 @@ CL_Connect_f
================
*/
void CL_Connect_f (void)
void CL_Connect_f( void )
{
char *server;
if (Cmd_Argc() != 2)
if( Cmd_Argc() != 2 )
{
Msg ("usage: connect <server>\n");
Msg( "Usage: connect <server>\n" );
return;
}
if(Host_ServerState())
if( Host_ServerState())
{
// if running a local server, kill it and reissue
com.strncpy( host.finalmsg, "Server quit\n", MAX_STRING );
@ -239,12 +223,12 @@ void CL_Connect_f (void)
}
else CL_Disconnect();
server = Cmd_Argv (1);
server = Cmd_Argv( 1 );
CL_Disconnect();
cls.state = ca_connecting;
com.strncpy (cls.servername, server, sizeof(cls.servername)-1);
com.strncpy( cls.servername, server, sizeof( cls.servername ));
cls.connect_time = MAX_HEARTBEAT; // CL_CheckForResend() will fire immediately
}
@ -253,20 +237,19 @@ void CL_Connect_f (void)
=====================
CL_Rcon_f
Send the rest of the command line over as
an unconnected command.
Send the rest of the command line over as
an unconnected command.
=====================
*/
void CL_Rcon_f (void)
void CL_Rcon_f( void )
{
char message[1024];
int i;
netadr_t to;
int i;
if (!rcon_client_password->string)
if( !rcon_client_password->string )
{
Msg ("You must set 'rcon_password' before\n"
"issuing an rcon command.\n");
Msg( "You must set 'rcon_password' before\n" "issuing an rcon command.\n" );
return;
}
@ -276,35 +259,33 @@ void CL_Rcon_f (void)
message[3] = (char)255;
message[4] = 0;
com.strcat (message, "rcon ");
com.strcat( message, "rcon " );
com.strcat( message, rcon_client_password->string );
com.strcat( message, " " );
com.strcat (message, rcon_client_password->string);
com.strcat (message, " ");
for (i=1 ; i<Cmd_Argc() ; i++)
for( i = 1; i < Cmd_Argc(); i++ )
{
com.strcat (message, Cmd_Argv(i));
com.strcat (message, " ");
com.strcat( message, Cmd_Argv( i ));
com.strcat( message, " " );
}
if (cls.state >= ca_connected)
if( cls.state >= ca_connected )
{
to = cls.netchan.remote_address;
}
else
{
if (!com.strlen(rcon_address->string))
if( !com.strlen( rcon_address->string ))
{
Msg ("You must either be connected,\n"
"or set the 'rcon_address' cvar\n"
"to issue rcon commands\n");
Msg( "You must either be connected,\n" "or set the 'rcon_address' cvar\n" "to issue rcon commands\n" );
return;
}
NET_StringToAdr (rcon_address->string, &to);
if (to.port == 0)
to.port = BigShort (PORT_SERVER);
NET_StringToAdr( rcon_address->string, &to );
if( to.port == 0 ) to.port = BigShort( PORT_SERVER );
}
NET_SendPacket (NS_CLIENT, com.strlen(message)+1, message, to);
NET_SendPacket( NS_CLIENT, com.strlen( message ) + 1, message, to );
}
@ -385,7 +366,7 @@ packet <destination> <contents>
Contents allows \n escape character
====================
*/
void CL_Packet_f (void)
void CL_Packet_f( void )
{
char send[2048];
int i, l;
@ -666,8 +647,8 @@ void CL_ParseStatusMessage( netadr_t from, sizebuf_t *msg )
s = MSG_ReadString( msg );
Msg ("%s\n", s);
CL_ParseServerStatus( NET_AdrToString(from), s );
Msg( "%s\n", s );
CL_ParseServerStatus( NET_AdrToString( from ), s );
}
//===================================================================
@ -842,7 +823,7 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
// echo request from server
if( !com.strcmp( c, "echo" ))
{
Netchan_OutOfBandPrint( NS_CLIENT, from, "%s", Cmd_Argv(1) );
Netchan_OutOfBandPrint( NS_CLIENT, from, "%s", Cmd_Argv( 1 ));
return;
}
@ -853,7 +834,6 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
CL_Disconnect();
return;
}
Msg( "Unknown command.\n" );
}
@ -940,21 +920,29 @@ void CL_ReadPackets( void )
CL_Userinfo_f
==============
*/
void CL_Userinfo_f (void)
void CL_Userinfo_f( void )
{
Msg( "User info settings:\n" );
Info_Print( Cvar_Userinfo());
Info_Print( Cvar_Userinfo( ));
}
/*
==============
CL_Physinfo_f
==============
*/
void CL_Physinfo_f( void )
{
Msg( "Phys info settings:\n" );
Info_Print( cl.physinfo );
}
int precache_check; // for autodownload of precache items
int precache_spawncount;
int precache_tex;
// ENV_CNT is map load, ENV_CNT+1 is first cubemap
#define ENV_CNT MAX_CONFIGSTRINGS
#define TEXTURE_CNT (ENV_CNT+13)
static const char *env_suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
#define TEXTURE_CNT (ENV_CNT+1)
void CL_RequestNextDownload( void )
{
@ -974,22 +962,29 @@ void CL_RequestNextDownload( void )
if(!CL_CheckOrDownloadFile( cl.configstrings[CS_MODELS+1] ))
return; // started a download map
}
if( precache_check >= CS_MODELS && precache_check < CS_MODELS+MAX_MODELS )
{
while( precache_check < CS_MODELS+MAX_MODELS && cl.configstrings[precache_check][0])
{
if( cl.configstrings[precache_check][0] == '*' || cl.configstrings[precache_check][0] == '#' )
{
precache_check++; // ignore bsp models or built-in models
continue;
}
com.sprintf( fn, "%s", cl.configstrings[precache_check++]);
if(!CL_CheckOrDownloadFile( fn )) return; // started a download
}
precache_check = CS_SOUNDS;
}
if( precache_check >= CS_SOUNDS && precache_check < CS_SOUNDS+MAX_SOUNDS )
{
{
if( precache_check == CS_SOUNDS ) precache_check++; // zero is blank
while( precache_check < CS_SOUNDS+MAX_SOUNDS && cl.configstrings[precache_check][0])
{
// sound pathes from model events
if( cl.configstrings[precache_check][0] == '*' )
if( cl.configstrings[precache_check][0] == '*' || cl.configstrings[precache_check][0] == '#' )
{
precache_check++;
continue;
@ -997,8 +992,26 @@ void CL_RequestNextDownload( void )
com.sprintf( fn, "sound/%s", cl.configstrings[precache_check++]);
if(!CL_CheckOrDownloadFile( fn )) return; // started a download
}
precache_check = CS_GENERICS;
}
if( precache_check >= CS_GENERICS && precache_check < CS_GENERICS+MAX_GENERICS )
{
if( precache_check == CS_GENERICS ) precache_check++; // zero is blank
while( precache_check < CS_GENERICS+MAX_GENERICS && cl.configstrings[precache_check][0] )
{
// generic recources - pakfiles, wadfiles etc
if( cl.configstrings[precache_check][0] == '#' )
{
precache_check++;
continue;
}
com.sprintf( fn, "%s", cl.configstrings[precache_check++]);
if(!CL_CheckOrDownloadFile( fn )) return; // started a download
}
precache_check = ENV_CNT;
}
if( precache_check == ENV_CNT )
{
precache_check = ENV_CNT + 1;
@ -1010,40 +1023,20 @@ void CL_RequestNextDownload( void )
return;
}
}
if( precache_check > ENV_CNT && precache_check < TEXTURE_CNT )
{
if( allow_download->value )
{
while( precache_check < TEXTURE_CNT )
{
int n = precache_check++ - ENV_CNT - 1;
if( n & 1 ) com.sprintf( fn, "env/%s.dds", cl.configstrings[CS_SKYNAME] ); // cubemap pack
else com.sprintf( fn, "env/%s%s.tga", cl.configstrings[CS_SKYNAME], env_suf[n/2] );
if(!CL_CheckOrDownloadFile( fn )) return; // started a download
}
com.sprintf( fn, "env/%s.dds", cl.configstrings[CS_SKYNAME] ); // cubemap pack
if( !CL_CheckOrDownloadFile( fn )) return; // started a download
}
precache_check = TEXTURE_CNT;
}
// skip textures: use generic for downloading packs
if( precache_check == TEXTURE_CNT )
{
precache_check = TEXTURE_CNT+1;
precache_tex = 0;
}
// confirm existance of textures, download any that don't exist
if( precache_check == TEXTURE_CNT + 1 )
{
if( allow_download->value )
{
while( precache_tex < CM_NumShaders( ))
{
com.sprintf( fn, "%s", CM_GetShaderName( precache_tex++ ));
if( !CL_CheckOrDownloadFile( fn )) return; // started a download
}
}
precache_check = TEXTURE_CNT + 999;
}
CL_PrepSound();
CL_PrepVideo();
@ -1111,6 +1104,7 @@ void CL_InitLocal( void )
topcolor = Cvar_Get( "topcolor", "0", CVAR_USERINFO | CVAR_ARCHIVE, "player top color" );
bottomcolor = Cvar_Get( "bottomcolor", "0", CVAR_USERINFO | CVAR_ARCHIVE, "player bottom color" );
rate = Cvar_Get( "rate", "25000", CVAR_USERINFO | CVAR_ARCHIVE, "player network rate" ); // FIXME
userinfo = Cvar_Get( "@userinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only
cl_showfps = Cvar_Get( "cl_showfps", "1", CVAR_ARCHIVE, "show client fps" );
// register our commands
@ -1120,6 +1114,7 @@ void CL_InitLocal( void )
Cmd_AddCommand ("freeserverlist", CL_FreeServerList_f, "clear info about local servers" );
Cmd_AddCommand ("userinfo", CL_Userinfo_f, "print current client userinfo" );
Cmd_AddCommand ("physinfo", CL_Physinfo_f, "print current client physinfo" );
Cmd_AddCommand ("changing", CL_Changing_f, "sent by server to tell client to wait for level change" );
Cmd_AddCommand ("disconnect", CL_Disconnect_f, "disconnect from server" );
Cmd_AddCommand ("record", CL_Record_f, "record a demo" );

View File

@ -1,23 +1,7 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// cl_parse.c -- parse a message received from the server
//=======================================================================
// Copyright XashXT Group 2009 ©
// cl_parse.c -- parse a message received from the server
//=======================================================================
#include "common.h"
#include "client.h"
@ -26,7 +10,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
char *svc_strings[256] =
{
"svc_bad",
// user messages space
"svc_nop",
"svc_disconnect",
"svc_reconnect",
@ -36,15 +20,20 @@ char *svc_strings[256] =
"svc_spawnbaseline",
"svc_download",
"svc_playerinfo",
"svc_physinfo",
"svc_packetentities",
"svc_frame",
"svc_sound",
"svc_setangle",
"svc_setview",
"svc_print",
"svc_centerprint",
"svc_crosshairangle",
"svc_setpause",
"svc_movevars",
"svc_particle",
"svc_soundfade",
"svc_bspdecal"
};
/*
@ -254,6 +243,47 @@ void CL_ParseMovevars( sizebuf_t *msg )
Mem_Copy( &clgame.oldmovevars, &clgame.movevars, sizeof( movevars_t ));
}
/*
==================
CL_ParseParticles
==================
*/
void CL_ParseParticles( sizebuf_t *msg )
{
vec3_t org, dir;
int i, count, color;
MSG_ReadPos( msg, org );
for( i = 0; i < 3; i++ )
dir[i] = MSG_ReadChar( msg ) * (1.0f / 16);
count = MSG_ReadByte( msg );
color = MSG_ReadByte( msg );
CL_ParticleEffect( org, dir, color, count );
}
/*
==================
CL_ParseStaticDecal
==================
*/
void CL_ParseStaticDecal( sizebuf_t *msg )
{
vec3_t origin;
int decalIndex, entityIndex, modelIndex;
MSG_ReadPos( msg, origin );
decalIndex = MSG_ReadWord( msg );
entityIndex = MSG_ReadShort( msg );
modelIndex = MSG_ReadWord( msg );
CL_SpawnStaticDecal( origin, decalIndex, entityIndex, modelIndex );
}
/*
=====================================================================
@ -435,7 +465,7 @@ CL_ParseServerMessage
void CL_ParseServerMessage( sizebuf_t *msg )
{
char *s;
int cmd;
int i, cmd;
// parse the message
while( 1 )
@ -500,15 +530,30 @@ void CL_ParseServerMessage( sizebuf_t *msg )
case svc_crosshairangle:
CL_ParseCrosshairAngle( msg );
break;
case svc_physinfo:
com.strncpy( cl.physinfo, MSG_ReadString( msg ), sizeof( cl.physinfo ));
break;
case svc_print:
i = MSG_ReadByte( msg );
if( i == PRINT_CHAT ) // chat
S_StartLocalSound( "misc/talk.wav", 1.0f, 100, NULL );
Con_Print( va( "^6%s\n", MSG_ReadString( msg )));
break;
case svc_centerprint:
CL_CenterPrint( MSG_ReadString( msg ), SCREEN_HEIGHT/2, BIGCHAR_WIDTH );
break;
case svc_setpause:
cl.refdef.paused = (MSG_ReadByte( msg ) != 0 );
break;
case svc_movevars:
CL_ParseMovevars( msg );
break;
case svc_particle:
CL_ParseParticles( msg );
break;
case svc_bspdecal:
CL_ParseStaticDecal( msg );
break;
case svc_frame:
CL_ParseFrame( msg );
break;

View File

@ -248,55 +248,6 @@ void SCR_DrawSmallStringExt( int x, int y, const char *string, rgba_t setColor,
re->SetColor( NULL );
}
/*
==============================================================================
Cinematic user interface
==============================================================================
*/
bool SCR_PlayCinematic( char *name, int bits )
{
string path;
if( cls.state == ca_cinematic )
SCR_StopCinematic();
com.sprintf( path, "media/%s", name );
FS_DefaultExtension( path, ".dpv" );
S_StopAllSounds();
UI_SetActiveMenu( UI_CLOSEMENU );
//S_StartStreaming();
if( CIN_PlayCinematic( path ))
{
SCR_RunCinematic(); // load first frame
return true;
}
return false;
}
bool SCR_CinActive( void )
{
return (cls.state == ca_cinematic);
}
void SCR_DrawCinematic( void )
{
CIN_DrawCinematic();
}
void SCR_RunCinematic( void )
{
CIN_RunCinematic();
}
void SCR_StopCinematic( void )
{
CIN_StopCinematic();
S_StopAllSounds();
}
/*
==============
SCR_DrawNet
@ -472,8 +423,9 @@ void SCR_RegisterShaders( void )
// register console images
cls.consoleFont = re->RegisterShader( va( "gfx/fonts/%s", con_font->string ), SHADER_FONT );
cls.clientFont = re->RegisterShader( va( "gfx/fonts/%s", cl_font->string ), SHADER_FONT );
cls.netIcon = re->RegisterShader( "#net.png", SHADER_NOMIP ); // internal recource
cls.fillShader = re->RegisterShader( "*white", SHADER_FONT ); // used for FillRGBA
cls.netIcon = re->RegisterShader( "#net.png", SHADER_NOMIP ); // internal recource
cls.fillShader = re->RegisterShader( "*white", SHADER_FONT ); // used for FillRGBA
cls.particle = re->RegisterShader( "*particle", SHADER_FONT ); // Q1 particlefont
if( host.developer )
cls.consoleBack = re->RegisterShader( "gfx/conback", SHADER_NOMIP );
@ -522,6 +474,7 @@ void SCR_Init( void )
SCR_RegisterShaders();
UI_Init();
UI_SetActiveMenu( UI_MAINMENU );
SCR_InitCinematic();
scr_init = true;
}

195
engine/client/cl_video.c Normal file
View File

@ -0,0 +1,195 @@
//=======================================================================
// Copyright XashXT Group 2009 ©
// cl_video.c - roq video player
//=======================================================================
#include "common.h"
#include "client.h"
/*
=================================================================
ROQ PLAYING
=================================================================
*/
/*
==================
SCR_StopCinematic
==================
*/
void SCR_StopCinematic( void )
{
cinematics_t *cin = cl.cin;
if( !cin || !cin->file )
return;
cl.cin = NULL;
cin->time = 0; // done
cin->pic = NULL;
cin->pic_pending = NULL;
if( cin->file ) FS_Close( cin->file );
cin->file = NULL;
Mem_Free( cin->name );
cin->name = NULL;
if( cin->vid_buffer )
{
Mem_Free( cin->vid_buffer );
cin->vid_buffer = NULL;
}
cls.state = ca_disconnected;
UI_SetActiveMenu( UI_MAINMENU );
}
//==========================================================================
/*
==================
SCR_InitCinematic
==================
*/
void SCR_InitCinematic( void )
{
CIN_Init ();
}
/*
==================
SCR_InitCinematic
==================
*/
uint SCR_GetCinematicTime( void )
{
cinematics_t *cin = cl.cin;
return (cin ? cin->time : 0);
}
/*
==================
SCR_RunCinematic
==================
*/
void SCR_RunCinematic( void )
{
uint frame;
cinematics_t *cin = cl.cin;
if( !cin || cin->time == 0 )
{
SCR_StopCinematic ();
return;
}
frame = (Host_Milliseconds() - cin->time) * (float)(RoQ_FRAMERATE) / 1000;
if( frame <= cin->frame ) return;
if( frame > cin->frame + 1 )
{
MsgDev( D_WARN, "dropped frame: %i > %i\n", frame, cin->frame + 1 );
cin->time = Host_Milliseconds() - cin->frame * 1000 / RoQ_FRAMERATE;
}
cin->pic = cin->pic_pending;
cin->pic_pending = CIN_ReadNextFrame( cin, false );
if( !cin->pic_pending )
{
SCR_StopCinematic ();
return;
}
}
/*
==================
SCR_DrawCinematic
Returns true if a cinematic is active, meaning the view rendering
should be skipped
==================
*/
bool SCR_DrawCinematic( void )
{
cinematics_t *cin = cl.cin;
float x, y, w, h;
if( !re || !cin || cin->time <= 0 )
return false;
if( !cin->pic )
return true;
x = y = 0;
w = SCREEN_WIDTH;
h = SCREEN_HEIGHT;
SCR_AdjustSize( &x, &y, &w, &h );
re->DrawStretchRaw( x, y, w, h, cin->width, cin->height, cin->pic, true );
return true;
}
/*
==================
SCR_PlayCinematic
==================
*/
bool SCR_PlayCinematic( const char *arg )
{
size_t name_size;
static cinematics_t clientCin;
cinematics_t *cin = cl.cin = &clientCin;
droqchunk_t *chunk = &cin->chunk;
if( cls.state == ca_cinematic )
{
// first stop the old movie
SCR_StopCinematic ();
}
name_size = com.strlen( "media/" ) + com.strlen( arg ) + com.strlen( ".roq" ) + 1;
cin->name = Mem_Alloc( cls.mempool, name_size );
com.snprintf( cin->name, name_size, "media/%s", arg );
FS_DefaultExtension( cin->name, ".roq" );
// nasty hack
cin->s_rate = 22050;
cin->s_width = 2;
cin->width = cin->height = 0;
cin->frame = 0;
cin->file = FS_Open( cin->name, "rb" );
if( !cin->file )
{
MsgDev( D_INFO, "SCR_PlayCinematic: unable to find %s\n", cin->name );
SCR_StopCinematic ();
return false;
}
// read header
CIN_ReadChunk( cin );
if( chunk->id != RoQ_HEADER1 || chunk->size != RoQ_HEADER2 || chunk->argument != RoQ_HEADER3 )
{
MsgDev( D_ERROR, "%s invalid header chunk %x\n", cin->name, chunk->id );
SCR_StopCinematic();
return false;
}
UI_SetActiveMenu( UI_CLOSEMENU );
S_StopAllSounds();
S_StartStreaming();
cls.state = ca_cinematic;
cin->headerlen = FS_Tell( cin->file );
cin->frame = 0;
cin->pic = cin->pic_pending = CIN_ReadNextFrame( cin, false );
cin->time = Host_Milliseconds ();
return true;
}

View File

@ -1,23 +1,7 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// cl_view.c -- player rendering positioning
//=======================================================================
// Copyright XashXT Group 2009 ©
// cl_view.c - player rendering positioning
//=======================================================================
#include "common.h"
#include "client.h"

View File

@ -1,23 +1,7 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// client.h -- primary header for client
//=======================================================================
// Copyright XashXT Group 2009 ©
// client.h -- primary header for client
//=======================================================================
#ifndef CLIENT_H
#define CLIENT_H
@ -104,6 +88,8 @@ typedef struct
ref_params_t refdef; // shared refdef
client_data_t data; // hud data
cinematics_t *cin;
// predicting stuff
vec3_t predicted_origins[CMD_BACKUP];// for debug comparing against server
@ -121,6 +107,7 @@ typedef struct
int servercount; // server identification for prespawns
int serverframetime; // server frametime
char configstrings[MAX_CONFIGSTRINGS][CS_SIZE];
char physinfo[MAX_INFO_STRING]; // physics info string
entity_state_t entity_curstates[MAX_PARSE_ENTITIES];
entity_state_t entity_baselines[MAX_EDICTS]; // keep all baselines in one global array
@ -322,6 +309,7 @@ typedef struct
shader_t clientFont; // current client font
shader_t consoleBack; // console background
shader_t fillShader; // used for emulate FillRGBA to avoid wrong draw-sort
shader_t particle; // used for drawing quake1 particles (SV_ParticleEffect)
shader_t netIcon; // netIcon displayed bad network connection
file_t *download; // file transfer from server
@ -389,6 +377,7 @@ extern cvar_t *cl_levelshot_name;
extern cvar_t *scr_centertime;
extern cvar_t *scr_download;
extern cvar_t *scr_loading;
extern cvar_t *userinfo;
extern cvar_t *con_font;
//=============================================================================
@ -396,14 +385,6 @@ extern cvar_t *con_font;
bool CL_CheckOrDownloadFile( const char *filename );
//=================================================
//
// cinematic.c
//
bool CIN_PlayCinematic( const char *filename ); // play cinematic with specified name
void CIN_DrawCinematic( void ); // draw current frame
void CIN_RunCinematic( void ); // decompress next frame
void CIN_StopCinematic( void ); // stop video playing
void CL_TeleportSplash( vec3_t org );
int CL_ParseEntityBits( sizebuf_t *msg, uint *bits );
void CL_ParseFrame( sizebuf_t *msg );
@ -503,6 +484,7 @@ void CL_InitEdict( edict_t *pEdict );
void CL_FreeEdict( edict_t *pEdict );
string_t CL_AllocString( const char *szValue );
const char *CL_GetString( string_t iString );
void CL_CenterPrint( const char *text, int y, int charWidth );
_inline edict_t *CL_EDICT_NUM( int n, const char *file, const int line )
{
@ -575,10 +557,13 @@ void CL_AddDecals( void );
void CL_ClearEffects( void );
void CL_TestLights( void );
void CL_TestEntities( void );
void CL_FindExplosionPlane( const vec3_t origin, float radius, vec3_t result );
bool pfnAddParticle( cparticle_t *src, HSPRITE shader, int flags );
void pfnAddDecal( float *org, float *dir, float *rgba, float rot, float rad, HSPRITE hSpr, int flags );
void pfnAddDLight( const float *org, const float *rgb, float radius, float time, int flags, int key );
void CL_ParticleEffect( const vec3_t org, const vec3_t dir, int color, int count ); // q1 legacy
void CL_SpawnStaticDecal( vec3_t origin, int decalIndex, int entityIndex, int modelIndex );
//
// cl_pred.c
//
@ -635,14 +620,13 @@ void Field_Draw( field_t *edit, int x, int y, int width, bool showCursor );
void Field_BigDraw( field_t *edit, int x, int y, int width, bool showCursor );
//
// cl_cin.c
// cl_video.c
//
bool SCR_PlayCinematic( char *name, int bits );
void SCR_DrawCinematic( void );
void SCR_InitCinematic( void );
bool SCR_PlayCinematic( const char *name );
bool SCR_DrawCinematic( void );
void SCR_RunCinematic( void );
void SCR_StopCinematic( void );
void SCR_ResetCinematic( void );
int SCR_GetCinematicState( void );
void CL_PlayVideo_f( void );
#endif//CLIENT_H

View File

@ -23,7 +23,6 @@
#define MAX_ENTNUMBER 99999 // for server and client parsing
#define MAX_HEARTBEAT -99999 // connection time
#define MAX_EVENTS 1024 // system events
/*
==============================================================
@ -36,6 +35,7 @@
#define SCREEN_HEIGHT 480
extern cvar_t *scr_width;
extern cvar_t *scr_height;
extern cvar_t *allow_download;
/*
==============================================================
@ -98,9 +98,6 @@ extern host_parm_t host;
//
// host.c
//
void Host_Init( const int argc, const char **argv );
void Host_Main( void );
void Host_Free( void );
void Host_SetServerState( int state );
int Host_ServerState( void );
int Host_CompareFileTime( long ft1, long ft2 );
@ -153,6 +150,9 @@ byte* pfnLoadFile( const char *filename, int *pLength );
char *pfnParseToken( const char **data_p );
void pfnFreeFile( void *buffer );
int pfnFileExists( const char *filename );
void *pfnLoadLibrary( const char *name );
void *pfnGetProcAddress( void *hInstance, const char *name );
void pfnFreeLibrary( void *hInstance );
long pfnRandomLong( long lLow, long lHigh );
float pfnRandomFloat( float flLow, float flHigh );
void pfnAlertMessage( ALERT_TYPE level, char *szFmt, ... );
@ -160,6 +160,7 @@ void *pfnFOpen( const char* path, const char* mode );
long pfnFWrite( void *file, const void* data, size_t datasize );
long pfnFRead( void *file, void* buffer, size_t buffersize );
int pfnFGets( void *file, byte *string, size_t bufsize );
void pfnEngineFprintf( void *pfile, char *szFmt, ... );
int pfnFSeek( void *file, long offset, int whence );
int pfnFClose( void *file );
long pfnFTell( void *file );
@ -195,6 +196,13 @@ int Key_GetKey( const char *binding );
void Key_EnumCmds_f( void );
void Key_SetKeyDest( int key_dest );
//
// cinematic.c
//
void CIN_Init( void );
void CIN_ReadChunk( cinematics_t *cin );
byte *CIN_ReadNextFrame( cinematics_t *cin, bool silent );
int CL_GetServerTime( void );
float CL_GetLerpFrac( void );
void CL_CharEvent( int key );
@ -221,13 +229,12 @@ void CL_ForceSnd( void );
void SCR_Init( void );
void SCR_UpdateScreen( void );
void SCR_Shutdown( void );
bool SCR_CinActive( void );
void Con_Print( const char *txt );
char *Info_ValueForKey( const char *s, const char *key );
void Info_RemoveKey( char *s, char *key );
void Info_SetValueForKey( char *s, char *key, char *value );
bool Info_Validate( char *s );
void Info_Print( char *s );
bool Info_RemoveKey( char *s, const char *key );
bool Info_SetValueForKey( char *s, const char *key, const char *value );
bool Info_Validate( const char *s );
void Info_Print( const char *s );
char *Cvar_Userinfo( void );
char *Cvar_Serverinfo( void );
void Cmd_WriteVariables( file_t *f );

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,11 @@
#define MOVE_NORMAL 0 // normal trace
#define MOVE_NOMONSTERS 1 // ignore monsters (edicts with flags (FL_MONSTER|FL_FAKECLIENT|FL_CLIENT) set)
#define MOVE_WORLDONLY 2 // clip only world
#define MOVE_MISSILE 2 // extra size for monsters
#define MOVE_WORLDONLY 3 // clip only world
#define FTRACE_IGNORE_GLASS 0x100
#define FTRACE_SIMPLEBOX 0x200
/*
===============================================================================
@ -54,12 +58,15 @@ typedef struct moveclip_s
vec3_t boxmaxs;
float *mins;
float *maxs; // size of the moving object
vec3_t mins2;
vec3_t maxs2;
const float *start;
const float *end;
trace_t trace;
edict_t *passedict;
uint umask; // contents mask
trType_t type;
int flags; // trace flags
} moveclip_t;
// linked list

View File

@ -341,7 +341,7 @@ bool Cmd_GetMovieList( const char *s, char *completedname, int length )
string matchbuf;
int i, nummovies;
t = FS_Search(va("media/%s*.dpv", s ), true);
t = FS_Search(va("media/%s*.roq", s ), true);
if(!t) return false;
FS_FileBase(t->filenames[0], matchbuf );
@ -352,7 +352,7 @@ bool Cmd_GetMovieList( const char *s, char *completedname, int length )
{
const char *ext = FS_FileExtension( t->filenames[i] );
if( com.stricmp( ext, "dpv" )) continue;
if( com.stricmp( ext, "roq" )) continue;
FS_FileBase(t->filenames[i], matchbuf );
Msg("%16s\n", matchbuf );
nummovies++;

View File

@ -9,6 +9,7 @@
#include "const.h"
#include "client.h"
#include "cvardef.h"
#include "com_library.h"
/*
==============
@ -366,6 +367,61 @@ long pfnFTell( void *file )
return FS_Tell( file );
}
/*
=============
pfnEngineFprintf
=============
*/
void pfnEngineFprintf( void *file, char *szFmt, ... )
{
char buffer[2048]; // must support > 1k messages
va_list args;
va_start( args, szFmt );
com.vsnprintf( buffer, 2048, szFmt, args );
va_end( args );
FS_Print( file, buffer );
}
/*
=============
pfnLoadLibrary
=============
*/
void *pfnLoadLibrary( const char *name )
{
string libpath;
Com_BuildPath( name, libpath );
return Com_LoadLibrary( libpath );
}
/*
=============
pfnGetProcAddress
=============
*/
void *pfnGetProcAddress( void *hInstance, const char *name )
{
if( !hInstance ) return NULL;
return Com_GetProcAddress( hInstance, name );
}
/*
=============
pfnFreeLibrary
=============
*/
void pfnFreeLibrary( void *hInstance )
{
Com_FreeLibrary( hInstance );
}
/*
=============
pfnGetGameDir

View File

@ -9,7 +9,7 @@
#define MAX_INFO_KEY 64
#define MAX_INFO_VALUE 64
static char sv_info[MAX_INFO_STRING*4];
static char infostring[MAX_INFO_STRING*4];
/*
=======================================================================
@ -24,42 +24,44 @@ Info_Print
printing current key-value pair
===============
*/
void Info_Print( char *s )
void Info_Print( const char *s )
{
char key[512];
char value[512];
char key[MAX_INFO_STRING];
char value[MAX_INFO_STRING];
char *o;
int l;
if( *s == '\\' )s++;
if( *s == '\\' ) s++;
while (*s)
while( *s )
{
o = key;
while (*s && *s != '\\') *o++ = *s++;
while( *s && *s != '\\' )
*o++ = *s++;
l = o - key;
if (l < 20)
if( l < 20 )
{
memset (o, ' ', 20-l);
Mem_Set( o, ' ', 20 - l );
key[20] = 0;
}
else *o = 0;
Msg ("%s", key);
Msg( "%s", key );
if (!*s)
if( !*s )
{
Msg ("MISSING VALUE\n");
Msg( "(null)\n" );
return;
}
o = value;
s++;
while (*s && *s != '\\') *o++ = *s++;
while( *s && *s != '\\' )
*o++ = *s++;
*o = 0;
if (*s) s++;
Msg ("%s\n", value);
if( *s ) s++;
Msg( "%s\n", value );
}
}
@ -73,8 +75,8 @@ key and returns the associated value, or an empty string.
*/
char *Info_ValueForKey( const char *s, const char *key )
{
char pkey[512];
static char value[2][512]; // use two buffers so compares work without stomping on each other
char pkey[MAX_INFO_STRING];
static char value[2][MAX_INFO_STRING]; // use two buffers so compares work without stomping on each other
static int valueindex;
char *o;
@ -85,63 +87,67 @@ char *Info_ValueForKey( const char *s, const char *key )
o = pkey;
while( *s != '\\' && *s != '\n' )
{
if(!*s) return "";
if( !*s ) return "";
*o++ = *s++;
}
*o = 0;
s++;
o = value[valueindex];
while( *s != '\\' && *s != '\n' && *s)
while( *s != '\\' && *s != '\n' && *s )
{
if (!*s) return "";
if( !*s ) return "";
*o++ = *s++;
}
*o = 0;
if(!com.strcmp( key, pkey )) return value[valueindex];
if(!*s) return "";
if( !com.strcmp( key, pkey ))
return value[valueindex];
if( !*s ) return "";
s++;
}
}
void Info_RemoveKey (char *s, char *key)
bool Info_RemoveKey( char *s, const char *key )
{
char *start;
char pkey[512];
char value[512];
char pkey[MAX_INFO_STRING];
char value[MAX_INFO_STRING];
char *o;
if (com.strstr (key, "\\")) return;
if( com.strstr( key, "\\" ))
return false;
while (1)
while( 1 )
{
start = s;
if (*s == '\\') s++;
if( *s == '\\' ) s++;
o = pkey;
while (*s != '\\')
while( *s != '\\' )
{
if (!*s) return;
if( !*s ) return false;
*o++ = *s++;
}
*o = 0;
s++;
o = value;
while (*s != '\\' && *s)
while( *s != '\\' && *s )
{
if (!*s) return;
if( !*s ) return false;
*o++ = *s++;
}
*o = 0;
if (!com.strcmp (key, pkey) )
if( !com.strcmp( key, pkey ))
{
com.strcpy (start, s); // remove this part
return;
com.strcpy( start, s ); // remove this part
return true;
}
if (!*s) return;
if( !*s ) return false;
}
}
@ -153,77 +159,85 @@ Some characters are illegal in info strings because they
can mess up the server's parsing
==================
*/
bool Info_Validate (char *s)
bool Info_Validate( const char *s )
{
if (com.strstr (s, "\"")) return false;
if (com.strstr (s, ";")) return false;
if( com.strstr( s, "\"" )) return false;
if( com.strstr( s, ";" )) return false;
return true;
}
void Info_SetValueForKey (char *s, char *key, char *value)
bool Info_SetValueForKey( char *s, const char *key, const char *value )
{
char newi[MAX_INFO_STRING], *v;
int c, maxsize = MAX_INFO_STRING;
if (com.strstr (key, "\\") || com.strstr (value, "\\") )
if( com.strstr( key, "\\" ) || com.strstr( value, "\\" ))
{
Msg ("Can't use keys or values with a \\\n");
return;
MsgDev( D_ERROR, "SetValueForKey: can't use keys or values with a \\\n" );
return false;
}
if (com.strstr (key, ";") )
if( com.strstr( key, ";" ))
{
Msg ("Can't use keys or values with a semicolon\n");
return;
}
if (com.strstr (key, "\"") || com.strstr (value, "\"") )
{
Msg ("Can't use keys or values with a \"\n");
return;
}
if (com.strlen(key) > MAX_INFO_KEY - 1 || com.strlen(value) > MAX_INFO_KEY-1)
{
Msg ("Keys and values must be < 64 characters.\n");
return;
MsgDev( D_ERROR, "SetValueForKey: can't use keys or values with a semicolon\n" );
return false;
}
Info_RemoveKey (s, key);
if (!value || !com.strlen(value)) return;
com.sprintf (newi, "\\%s\\%s", key, value);
if (com.strlen(newi) + com.strlen(s) > maxsize)
if( com.strstr( key, "\"" ) || com.strstr( value, "\"" ))
{
Msg ("Info string length exceeded\n");
return;
MsgDev( D_ERROR, "SetValueForKey: can't use keys or values with a \"\n" );
return false;
}
if( com.strlen( key ) > MAX_INFO_KEY - 1 || com.strlen( value ) > MAX_INFO_KEY - 1 )
{
MsgDev( D_ERROR, "SetValueForKey: keys and values must be < %i characters.\n", MAX_INFO_KEY );
return false;
}
Info_RemoveKey( s, key );
if( !value || !com.strlen( value ))
return true; // just clear variable
com.sprintf( newi, "\\%s\\%s", key, value );
if( com.strlen( newi ) + com.strlen( s ) > maxsize )
{
MsgDev( D_ERROR, "SetValueForKey: info string length exceeded\n" );
return true; // info changed, new value can't saved
}
// only copy ascii values
s += com.strlen(s);
s += com.strlen( s );
v = newi;
while (*v)
while( *v )
{
c = *v++;
c &= 127; // strip high bits
if (c >= 32 && c < 127) *s++ = c;
if( c >= 32 && c < 127 )
*s++ = c;
}
*s = 0;
// all done
return true;
}
static void Cvar_LookupBitInfo( const char *name, const char *string, const char *info, void *unused )
{
Info_SetValueForKey( (char *)info, (char *)name, (char *)string );
Info_SetValueForKey( (char *)info, name, string );
}
char *Cvar_Userinfo( void )
{
sv_info[0] = 0; // clear previous calls
Cvar_LookupVars( CVAR_USERINFO, sv_info, NULL, Cvar_LookupBitInfo );
return sv_info;
infostring[0] = 0; // clear previous calls
Cvar_LookupVars( CVAR_USERINFO, infostring, NULL, Cvar_LookupBitInfo );
return infostring;
}
char *Cvar_Serverinfo( void )
{
sv_info[0] = 0; // clear previous calls
Cvar_LookupVars( CVAR_SERVERINFO, sv_info, NULL, Cvar_LookupBitInfo );
return sv_info;
infostring[0] = 0; // clear previous calls
Cvar_LookupVars( CVAR_SERVERINFO, infostring, NULL, Cvar_LookupBitInfo );
return infostring;
}

View File

@ -481,7 +481,7 @@ void _MSG_WriteString( sizebuf_t *sb, const char *s, const char *filename, int f
}
}
void _MSG_WritePos( sizebuf_t *sb, vec3_t pos, const char *filename, int fileline )
void _MSG_WritePos( sizebuf_t *sb, const vec3_t pos, const char *filename, int fileline )
{
_MSG_WriteFloat( sb, pos[0], filename, fileline );
_MSG_WriteFloat( sb, pos[1], filename, fileline );

View File

@ -61,15 +61,20 @@ enum svc_ops_e
svc_spawnbaseline, // valid only at spawn
svc_download, // [short] size [size bytes]
svc_playerinfo, // [long]
svc_physinfo, // [physinfo string]
svc_packetentities, // [...]
svc_frame, // server frame
svc_sound, // <see code>
svc_setangle, // [short short short] set the view angle to this absolute value
svc_setview, // [short] entity number
svc_print, // [byte] id [string] null terminated string
svc_centerprint, // [string] to put in center of the screen
svc_crosshairangle, // [short][short][short]
svc_setpause, // [byte] 0 = unpaused, 1 = paused
svc_movevars // [movevars_t]
svc_movevars, // [movevars_t]
svc_particle, // [float*3][char*3][byte][byte]
svc_soundfade, // FIMXE: implement (just reserve a number)
svc_bspdecal // [float*3][short][short][short]
};
// client to server
@ -148,7 +153,9 @@ static const net_desc_t NWDesc[] =
#define CS_MODELS 32 // configstrings starts here
#define CS_SOUNDS (CS_MODELS+MAX_MODELS) // sound names
#define CS_DECALS (CS_SOUNDS+MAX_SOUNDS) // server decal indexes
#define CS_CLASSNAMES (CS_DECALS+MAX_DECALS) // edicts classnames
#define CS_EVENTS (CS_DECALS+MAX_DECALS) // queue events
#define CS_GENERICS (CS_EVENTS+MAX_EVENTS) // edicts classnames
#define CS_CLASSNAMES (CS_GENERICS+MAX_GENERICS) // generic resources (e.g. color decals)
#define CS_LIGHTSTYLES (CS_CLASSNAMES+MAX_CLASSNAMES) // lightstyle patterns
#define CS_USER_MESSAGES (CS_LIGHTSTYLES+MAX_LIGHTSTYLES) // names of user messages
#define MAX_CONFIGSTRINGS (CS_USER_MESSAGES+MAX_USER_MESSAGES) // total count
@ -172,12 +179,12 @@ void _MSG_WriteDouble( sizebuf_t *sb, double f, const char *filename, int fileli
void _MSG_WriteAngle8( sizebuf_t *sb, float f, const char *filename, int fileline );
void _MSG_WriteAngle16( sizebuf_t *sb, float f, const char *filename, int fileline );
void _MSG_WriteCoord16( sizebuf_t *sb, float f, const char *filename, int fileline );
void _MSG_WritePos( sizebuf_t *sb, vec3_t pos, const char *filename, int fileline );
void _MSG_WritePos( sizebuf_t *sb, const vec3_t pos, const char *filename, int fileline );
void _MSG_WriteData( sizebuf_t *sb, const void *data, size_t length, const char *filename, int fileline );
void _MSG_WriteDeltaUsercmd( sizebuf_t *sb, usercmd_t *from, usercmd_t *cmd, const char *filename, const int fileline );
bool _MSG_WriteDeltaMovevars( sizebuf_t *sb, movevars_t *from, movevars_t *cmd, const char *filename, const int fileline );
void _MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *msg, bool force, bool newentity, const char *file, int line );
void _MSG_Send( msgtype_t to, vec3_t origin, const edict_t *ent, const char *filename, int fileline );
void _MSG_Send( msgtype_t to, const vec3_t origin, const edict_t *ent, const char *filename, int fileline );
#define MSG_Begin( x ) _MSG_Begin( x, __FILE__, __LINE__)
#define MSG_WriteChar(x,y) _MSG_WriteBits (x, y, NWDesc[NET_CHAR].name, NET_CHAR, __FILE__, __LINE__)

View File

@ -18,6 +18,8 @@ extern vsound_exp_t *se;
#define CM_SetAreaPortals if( pe ) pe->SetAreaPortals
#define CM_GetAreaPortals if( pe ) pe->GetAreaPortals
#define CM_SetAreaPortalState if( pe ) pe->SetAreaPortalState
#define CM_GetAttachment if( pe ) pe->Mod_GetAttachment
#define CM_GetBonePosition if( pe ) pe->Mod_GetBonePos
#define CM_EndRegistration if( pe ) pe->EndRegistration
#define CM_Frame if( pe ) pe->Frame
@ -87,7 +89,7 @@ _inline int CM_LeafCluster( int leafnum )
return pe->LeafCluster( leafnum );
}
_inline int CM_PointLeafnum( vec3_t origin )
_inline int CM_PointLeafnum( const vec3_t origin )
{
if( !pe ) return -1;
return pe->PointLeafnum( origin );
@ -163,6 +165,13 @@ _inline void CM_TransformedBoxTrace( trace_t *tr, const vec3_t p1, const vec3_t
else CM_BoxTrace( tr, p1, p2, mins, maxs, model, mask, type );
}
_inline bool CM_HitboxTrace( trace_t *tr, edict_t *e, const vec3_t p1, const vec3_t p2 )
{
if( pe ) return pe->HitboxTrace( tr, e, p1, p2 );
else tr->iHitgroup = -1;
return false;
}
_inline model_t CM_TempModel( const vec3_t mins, const vec3_t maxs, bool capsule )
{
if( !pe ) return 1; // world

View File

@ -1,35 +0,0 @@
//=======================================================================
// Copyright XashXT Group 2008 ©
// ui_edict.h - uimenu prvm edict
//=======================================================================
#ifndef UI_EDICT_H
#define UI_EDICT_H
struct ui_globalvars_s
{
int pad[34];
int pev;
float time;
func_t m_init;
func_t m_shutdown;
func_t m_show;
func_t m_hide;
func_t m_draw;
func_t m_endofcredits;
func_t m_keydown;
};
struct ui_entvars_s
{
string_t name;
string_t type;
string_t parent;
int _parent;
int _child;
int _next;
int _prev;
};
#define PROG_CRC_UIMENU 2158
#endif//UI_EDICT_H

View File

@ -1,27 +0,0 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// engine.c - engine entry base
//=======================================================================
#include "common.h"
/*
=================
Base Entry Point
=================
*/
launch_exp_t DLLEXPORT *CreateAPI( stdlib_api_t *input, void *unused )
{
static launch_exp_t Host;
com = *input;
Host.api_size = sizeof( launch_exp_t );
Host.com_size = sizeof( stdlib_api_t );
Host.Init = Host_Init;
Host.Main = Host_Main;
Host.Free = Host_Free;
Host.CPrint = Host_Print;
return &Host;
}

View File

@ -158,6 +158,10 @@ SOURCE=.\client\cl_scrn.c
# End Source File
# Begin Source File
SOURCE=.\client\cl_video.c
# End Source File
# Begin Source File
SOURCE=.\client\cl_view.c
# End Source File
# Begin Source File
@ -190,10 +194,6 @@ SOURCE=.\common\engfuncs.c
# End Source File
# Begin Source File
SOURCE=.\engine.c
# End Source File
# Begin Source File
SOURCE=.\host.c
# End Source File
# Begin Source File
@ -378,7 +378,7 @@ SOURCE=..\pm_shared\pm_shared.h
# End Source File
# Begin Source File
SOURCE=.\safeproc.h
SOURCE=.\common\safeproc.h
# End Source File
# Begin Source File

View File

@ -1,16 +0,0 @@
<html>
<body>
<pre>
<h1>Build Log</h1>
<h3>
--------------------Configuration: engine - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
<h3>Results</h3>
engine.dll - 0 error(s), 0 warning(s)
</pre>
</body>
</html>

View File

@ -7,6 +7,7 @@
#include "input.h"
#define MAX_RENDERS 8 // max libraries to keep tracking
#define MAX_SYSEVENTS 1024 // system events
physic_exp_t *pe;
render_exp_t *re;
@ -187,6 +188,8 @@ bool Host_InitRender( void )
ri.GetLocalPlayer = CL_GetLocalPlayer;
ri.GetMaxClients = CL_GetMaxClients;
ri.GetLerpFrac = CL_GetLerpFrac;
ri.RoQ_ReadChunk = CIN_ReadChunk;
ri.RoQ_ReadNextFrame = CIN_ReadNextFrame;
ri.WndProc = IN_WndProc;
Sys_LoadLibrary( host_video->string, &render_dll );
@ -449,9 +452,9 @@ void Host_PushEvent( sys_event_t *event )
sys_event_t *ev;
static bool overflow = false;
ev = &host.events[host.events_head & (MAX_EVENTS-1)];
ev = &host.events[host.events_head & (MAX_SYSEVENTS-1)];
if( host.events_head - host.events_tail >= MAX_EVENTS )
if( host.events_head - host.events_tail >= MAX_SYSEVENTS )
{
if( !overflow )
{
@ -477,7 +480,7 @@ sys_event_t Host_GetEvent( void )
if( host.events_head > host.events_tail )
{
host.events_tail++;
return host.events[(host.events_tail - 1)&(MAX_EVENTS-1)];
return host.events[(host.events_tail - 1) & (MAX_SYSEVENTS-1)];
}
return Sys_GetEvent();
}
@ -574,9 +577,7 @@ int Host_ModifyTime( int msec )
{
// clients of remote servers do not want to clamp time, because
// it would skew their view of the server's time temporarily
if( SCR_CinActive( ))
clamp_time = (1000 / host_maxfps->integer);
else clamp_time = 5000;
clamp_time = 5000;
}
if( msec > clamp_time ) msec = clamp_time;
@ -862,7 +863,7 @@ void Host_Init( const int argc, const char **argv )
Cmd_AddCommand( "snd_restart", Host_SndRestart_f, "restarts audio system" );
}
Cmd_AddCommand( "phys_restart", Host_PhysRestart_f, "restarts physic system" );
Cmd_AddCommand( "cmap_restart", Host_PhysRestart_f, "restarts physic system" );
Cmd_AddCommand( "game", Host_ChangeGame_f, "change game" ); // allow to change game from the console
host.frametime[0] = Host_Milliseconds();
host.errorframe = 0;
@ -904,4 +905,25 @@ void Host_Free( void )
Host_FreeVprogs();
Host_FreePhysic();
Host_FreeCommon();
}
/*
=================
Engine entry point
=================
*/
launch_exp_t DLLEXPORT *CreateAPI( stdlib_api_t *input, void *unused )
{
static launch_exp_t Host;
com = *input;
Host.api_size = sizeof( launch_exp_t );
Host.com_size = sizeof( stdlib_api_t );
Host.Init = Host_Init;
Host.Main = Host_Main;
Host.Free = Host_Free;
Host.CPrint = Host_Print;
return &Host;
}

View File

@ -1,23 +1,8 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
//=======================================================================
// Copyright XashXT Group 2009 ©
// server.h - primary header for server
//=======================================================================
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// server.h
#ifndef SERVER_H
#define SERVER_H
@ -101,7 +86,10 @@ typedef struct sv_client_s
{
cl_state_t state;
char userinfo[MAX_INFO_STRING]; // name, etc
char userinfo[MAX_INFO_STRING]; // name, etc (received from client)
char physinfo[MAX_INFO_STRING]; // set on server (transmit to client)
bool physinfo_modified; // transmit at next opportunity
int lastframe; // for delta compression
usercmd_t lastcmd; // for filling in big drops
@ -160,6 +148,7 @@ struct sv_priv_s
int areanum, areanum2;
bool linked; // passed through SV_LinkEdict
bool stuck; // entity stucked in brush
bool suspended; // suspended on a brush entity
size_t pvdata_size; // member size of alloceed pvPrivateData
// (used by SV_CopyEdict)
entity_state_t s; // baseline (this is a player_state too)
@ -271,7 +260,6 @@ extern cvar_t *sv_stopspeed;
extern cvar_t *sv_fps; // running server at
extern cvar_t *sv_enforcetime;
extern cvar_t *sv_reconnect_limit;
extern cvar_t *allow_download;
extern cvar_t *rcon_password;
extern cvar_t *hostname;
extern cvar_t *sv_stepheight;
@ -286,21 +274,23 @@ extern sv_client_t *sv_client;
//
// sv_main.c
//
void SV_FinalMessage (char *message, bool reconnect);
void SV_DropClient (sv_client_t *drop);
void SV_FinalMessage( char *message, bool reconnect );
void SV_DropClient( sv_client_t *drop );
int SV_ModelIndex (const char *name);
int SV_SoundIndex (const char *name);
int SV_ClassIndex (const char *name);
int SV_DecalIndex (const char *name);
int SV_UserMessageIndex (const char *name);
int SV_ModelIndex( const char *name );
int SV_SoundIndex( const char *name );
int SV_ClassIndex( const char *name );
int SV_DecalIndex( const char *name );
int SV_EventIndex( const char *name );
int SV_GenericIndex( const char *name );
int SV_UserMessageIndex( const char *name );
void SV_WriteClientdataToMessage (sv_client_t *client, sizebuf_t *msg);
void SV_ExecuteUserCommand (char *s);
void SV_InitOperatorCommands( void );
void SV_KillOperatorCommands( void );
void SV_SendServerinfo (sv_client_t *client);
void SV_UserinfoChanged (sv_client_t *cl);
void SV_SendServerinfo( sv_client_t *client );
void SV_UserinfoChanged( sv_client_t *cl, const char *userinfo );
void Master_Heartbeat (void);
void Master_Packet (void);
@ -325,12 +315,15 @@ bool SV_CheckWater( edict_t *ent );
int SV_TryUnstick( edict_t *ent, vec3_t oldvel );
void SV_CheckStuck( edict_t *ent );
bool SV_RunThink( edict_t *ent );
void SV_UnstickEntity( edict_t *ent );
//
// sv_move.c
//
bool SV_movestep( edict_t *ent, vec3_t move, bool relink, bool noenemy, bool settrace );
bool SV_CheckBottom( edict_t *ent );
bool SV_WalkMove( edict_t *ent, vec3_t move, int iMode );
void SV_MoveToOrigin( edict_t *ed, const vec3_t goal, float dist, int iMode );
bool SV_CheckBottom( edict_t *ent, int iMode );
float SV_VecToYaw( const vec3_t src );
//
// sv_send.c
@ -353,6 +346,10 @@ bool SV_ClientConnect( edict_t *ent, char *userinfo );
void SV_ClientThink( sv_client_t *cl, usercmd_t *cmd );
void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg );
void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg );
edict_t *SV_FakeConnect( const char *netname );
void SV_PreRunCmd( sv_client_t *cl, usercmd_t *ucmd );
void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd );
void SV_PostRunCmd( sv_client_t *cl );
void SV_SetIdealPitch( sv_client_t *cl );
void SV_InitClientMove( void );
@ -388,6 +385,7 @@ void SV_SpawnEntities( const char *mapname, script_t *entities );
edict_t* SV_AllocPrivateData( edict_t *ent, string_t className );
string_t SV_AllocString( const char *szValue );
const char *SV_GetString( string_t iString );
void SV_SetClientMaxspeed( sv_client_t *cl, float fNewMaxspeed );
bool SV_MapIsValid( const char *filename, const char *spawn_entity );
void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch );
script_t *CM_GetEntityScript( void );
@ -447,7 +445,8 @@ void SV_LinkEdict( edict_t *ent, bool touch_triggers );
void SV_TouchLinks( edict_t *ent, areanode_t *node );
edict_t *SV_TestPlayerPosition( const vec3_t origin, edict_t *pass, TraceResult *trace );
int SV_PointContents( const vec3_t p );
trace_t SV_ClipMoveToEntity( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, uint mask );
trace_t SV_ClipMoveToEntity( edict_t *e, const vec3_t p0, vec3_t b0, vec3_t b1, const vec3_t p1, uint mask, int flags );
int SV_BaseContents( const vec3_t p, edict_t *e );
// mins and maxs are relative
// if the entire move stays in a solid volume, trace.allsolid will be set,

View File

@ -88,9 +88,9 @@ void SV_DirectConnect( netadr_t from )
return;
}
qport = com.atoi(Cmd_Argv(2));
challenge = com.atoi(Cmd_Argv(3));
com.strncpy( userinfo, Cmd_Argv( 4 ), sizeof(userinfo) - 1);
qport = com.atoi( Cmd_Argv( 2 ));
challenge = com.atoi( Cmd_Argv( 3 ));
com.strncpy( userinfo, Cmd_Argv( 4 ), sizeof( userinfo ) - 1);
userinfo[sizeof(userinfo) - 1] = 0;
// quick reject
@ -192,8 +192,7 @@ gotnewcl:
}
// parse some info from the info strings
com.strncpy( newcl->userinfo, userinfo, sizeof(newcl->userinfo) - 1);
SV_UserinfoChanged( newcl );
SV_UserinfoChanged( newcl, userinfo );
// send the connect packet to the client
Netchan_OutOfBandPrint( NS_SERVER, from, "client_connect" );
@ -219,18 +218,20 @@ gotnewcl:
SV_FakeConnect
A connection request that came from the game module
UNDONE: not called anymore
==================
*/
void SV_FakeConnect( char *cl_userinfo )
edict_t *SV_FakeConnect( const char *netname )
{
int i, edictnum;
char userinfo[MAX_INFO_STRING];
sv_client_t temp, *cl, *newcl;
edict_t *ent;
if( !cl_userinfo ) cl_userinfo = "";
com.strncpy( userinfo, cl_userinfo, sizeof( userinfo ));
if( !netname ) netname = "";
userinfo[0] = '\0';
// setup fake client name
Info_SetValueForKey( userinfo, "name", netname );
// force the IP key/value pair so the game can filter based on ip
Info_SetValueForKey( userinfo, "ip", "127.0.0.1" );
@ -249,7 +250,7 @@ void SV_FakeConnect( char *cl_userinfo )
if( !newcl )
{
MsgDev( D_INFO, "SV_DirectConnect: rejected a connection.\n");
return;
return NULL;
}
// build a new connection
@ -269,16 +270,17 @@ void SV_FakeConnect( char *cl_userinfo )
if( !SV_ClientConnect( ent, userinfo ))
{
MsgDev( D_ERROR, "SV_DirectConnect: game rejected a connection.\n" );
return;
return NULL;
}
// parse some info from the info strings
com.strncpy( newcl->userinfo, userinfo, sizeof( newcl->userinfo ) - 1);
SV_UserinfoChanged( newcl );
SV_UserinfoChanged( newcl, userinfo );
newcl->state = cs_spawned;
newcl->lastmessage = svs.realtime; // don't timeout
newcl->lastconnect = svs.realtime;
return ent;
}
/*
@ -377,6 +379,7 @@ void SV_FlushRedirect( netadr_t adr, int dest, char *buf )
case RD_CLIENT:
if( !sv_client ) return; // client not set
MSG_WriteByte( &sv_client->netchan.message, svc_print );
MSG_WriteByte( &sv_client->netchan.message, PRINT_HIGH );
MSG_WriteString( &sv_client->netchan.message, buf );
break;
case RD_NONE:
@ -566,6 +569,9 @@ void SV_PutClientInServer( edict_t *ent )
if( !sv.changelevel && !sv.loadgame )
{
// setup maxspeed and refresh physinfo
SV_SetClientMaxspeed( client, sv_maxspeed->value );
// fisrt entering
svgame.dllFuncs.pfnClientPutInServer( ent );
@ -900,13 +906,17 @@ Pull specific info from a newly changed userinfo string
into a more C freindly form.
=================
*/
void SV_UserinfoChanged( sv_client_t *cl )
void SV_UserinfoChanged( sv_client_t *cl, const char *userinfo )
{
char *val;
int i;
if( !userinfo || !userinfo[0] ) return; // ignored
com.strncpy( cl->userinfo, userinfo, sizeof( cl->userinfo ));
// name for C code (make colored string)
com.snprintf( cl->name, sizeof(cl->name), "^2%s", Info_ValueForKey( cl->userinfo, "name"));
com.snprintf( cl->name, sizeof( cl->name ), "^2%s", Info_ValueForKey( cl->userinfo, "name" ));
// rate command
val = Info_ValueForKey( cl->userinfo, "rate" );
@ -921,9 +931,12 @@ void SV_UserinfoChanged( sv_client_t *cl )
// msg command
val = Info_ValueForKey( cl->userinfo, "msg" );
if( com.strlen( val ))
{
cl->messagelevel = com.atoi( val );
}
// call prog code to allow overrides
svgame.globals->time = sv.time * 0.001f;
svgame.globals->frametime = sv.frametime * 0.001f;
svgame.dllFuncs.pfnClientUserInfoChanged( cl->edict, cl->userinfo );
}
/*
@ -933,14 +946,7 @@ SV_UpdateUserinfo_f
*/
static void SV_UpdateUserinfo_f( sv_client_t *cl )
{
com.strncpy( cl->userinfo, Cmd_Argv(1), sizeof(cl->userinfo));
SV_UserinfoChanged( cl );
// call prog code to allow overrides
svgame.globals->time = sv.time * 0.001f;
svgame.globals->frametime = sv.frametime * 0.001f;
svgame.dllFuncs.pfnClientUserInfoChanged( cl->edict, cl->userinfo );
SV_UserinfoChanged( cl, Cmd_Argv( 1 ));
}
ucmd_t ucmds[] =
@ -1013,7 +1019,7 @@ MULTICAST_PVS send to clients potentially visible from org
MULTICAST_PHS send to clients potentially hearable from org
=================
*/
void _MSG_Send( msgtype_t msg_type, vec3_t origin, const edict_t *ent, const char *filename, int fileline )
void _MSG_Send( msgtype_t msg_type, const vec3_t origin, const edict_t *ent, const char *filename, int fileline )
{
byte *mask = NULL;
int leafnum = 0, cluster = 0;
@ -1160,6 +1166,7 @@ void PM_ClientPrintf( int index, char *fmt, ... )
va_end( argptr );
MSG_WriteByte( &cl->netchan.message, svc_print );
MSG_WriteByte( &cl->netchan.message, PRINT_HIGH );
MSG_WriteString( &cl->netchan.message, string );
}
@ -1201,7 +1208,7 @@ const char *PM_TraceTexture( edict_t *pTextureEntity, const float *v1, const flo
Host_Error( "TraceTexture: NAN errors detected ('%f %f %f', '%f %f %f'\n", v1[0], v1[1], v1[2], v2[0], v2[1], v2[2] );
if( !pTextureEntity || pTextureEntity->free ) return NULL;
return SV_ClipMoveToEntity( pTextureEntity, v1, vec3_origin, vec3_origin, v2, MASK_SOLID ).pTexName;
return SV_ClipMoveToEntity( pTextureEntity, v1, vec3_origin, vec3_origin, v2, MASK_SOLID, 0 ).pTexName;
}
/*
@ -1225,7 +1232,7 @@ TraceResult PM_TraceModel( edict_t *pEnt, const vec3_t start, const vec3_t end )
svgame.pmove->usehull = bound( 0, svgame.pmove->usehull, 3 );
mins = svgame.pmove->player_mins[svgame.pmove->usehull];
maxs = svgame.pmove->player_maxs[svgame.pmove->usehull];
result = SV_ClipMoveToEntity( pEnt, start, mins, maxs, end, umask );
result = SV_ClipMoveToEntity( pEnt, start, mins, maxs, end, umask, FTRACE_SIMPLEBOX );
Mem_Copy( &out, &result, sizeof( TraceResult ));
return out;
@ -1264,6 +1271,11 @@ edict_t *PM_TestPlayerPosition( const vec3_t origin, TraceResult *trace )
return SV_TestPlayerPosition( origin, svgame.pmove->player, trace );
}
int PM_PointContents( const vec3_t p )
{
return World_ConvertContents( SV_BaseContents( p, svgame.pmove->player ));
}
/*
===============
SV_InitClientMove
@ -1277,12 +1289,17 @@ void SV_InitClientMove( void )
svgame.pmove->movevars = &svgame.movevars;
// init hulls
VectorCopy( GI->client_mins[0], svgame.pmove->player_mins[2] ); // copy point hull
VectorCopy( GI->client_maxs[0], svgame.pmove->player_maxs[2] );
VectorCopy( GI->client_mins[1], svgame.pmove->player_mins[0] ); // copy human hull
VectorCopy( GI->client_maxs[1], svgame.pmove->player_maxs[0] );
VectorCopy( GI->client_mins[2], svgame.pmove->player_mins[3] ); // copy large hull
VectorCopy( GI->client_maxs[2], svgame.pmove->player_maxs[3] );
VectorCopy( GI->client_mins[3], svgame.pmove->player_mins[1] ); // copy head hull
VectorCopy( GI->client_maxs[3], svgame.pmove->player_maxs[1] );
for( i = 0; i < PM_MAXHULLS; i++ )
{
VectorCopy( GI->client_mins[i], svgame.pmove->player_mins[i] );
VectorCopy( GI->client_maxs[i], svgame.pmove->player_maxs[i] );
svgame.pmove->player_view[i] = GI->viewheight[i];
}
// common utilities
svgame.pmove->PM_Info_ValueForKey = Info_ValueForKey;
@ -1290,7 +1307,7 @@ void SV_InitClientMove( void )
svgame.pmove->ClientPrintf = PM_ClientPrintf;
svgame.pmove->AlertMessage = pfnAlertMessage;
svgame.pmove->PM_GetString = SV_GetString;
svgame.pmove->PM_PointContents = SV_PointContents;
svgame.pmove->PM_PointContents = PM_PointContents;
svgame.pmove->PM_PlayerTrace = PM_PlayerTrace;
svgame.pmove->PM_TraceTexture = PM_TraceTexture;
svgame.pmove->PM_GetEntityByIndex = PM_GetEntityByIndex;
@ -1385,7 +1402,7 @@ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd )
svgame.pmove->multiplayer = (sv_maxclients->integer > 1) ? true : false;
svgame.pmove->realtime = svs.realtime * 0.001f;
svgame.pmove->frametime = ucmd->msec * 0.001f;
com.strncpy( svgame.pmove->physinfo, cl->userinfo, MAX_INFO_STRING );
com.strncpy( svgame.pmove->physinfo, cl->physinfo, MAX_INFO_STRING );
svgame.pmove->serverflags = svgame.globals->serverflags;
svgame.pmove->clientmaxspeed = clent->v.maxspeed;
svgame.pmove->maxspeed = svgame.movevars.maxspeed;
@ -1951,7 +1968,7 @@ void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg )
case clc_nop:
break;
case clc_userinfo:
SV_UpdateUserinfo_f( cl );
SV_UserinfoChanged( cl, MSG_ReadString( msg ));
break;
case clc_move:
if( move_issued ) return; // someone is trying to cheat...

View File

@ -32,6 +32,7 @@ void SV_ClientPrintf( sv_client_t *cl, int level, char *fmt, ... )
va_end( argptr );
MSG_WriteByte( &cl->netchan.message, svc_print );
MSG_WriteByte( &cl->netchan.message, level );
MSG_WriteString( &cl->netchan.message, string );
}
@ -62,6 +63,7 @@ void SV_BroadcastPrintf( int level, char *fmt, ... )
if( cl->edict && (cl->edict->v.flags & FL_FAKECLIENT ))
continue;
MSG_WriteByte( &cl->netchan.message, svc_print );
MSG_WriteByte( &cl->netchan.message, level );
MSG_WriteString( &cl->netchan.message, string );
}
}

View File

@ -47,7 +47,7 @@ Copy entvars into entity state
void SV_UpdateEntityState( edict_t *ent, bool baseline )
{
sv_client_t *client = ent->pvServerData->client;
if( !ent->pvServerData->s.classname )
ent->pvServerData->s.classname = SV_ClassIndex( STRING( ent->v.classname ));
@ -357,6 +357,14 @@ void SV_WriteFrameToClient( sv_client_t *cl, sizebuf_t *msg )
}
}
// refresh physinfo if needs
if( cl->physinfo_modified )
{
cl->physinfo_modified = false;
MSG_WriteByte( msg, svc_physinfo );
MSG_WriteString( msg, cl->physinfo );
}
MSG_WriteByte( msg, svc_frame );
MSG_WriteLong( msg, sv.framenum );
MSG_WriteLong( msg, sv.time ); // send a servertime each frame

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +1,7 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//=======================================================================
// Copyright XashXT Group 2009 ©
// sv_init.c - server initialize operations
//=======================================================================
#include "common.h"
#include "server.h"
@ -82,6 +67,16 @@ int SV_DecalIndex( const char *name )
return SV_FindIndex( name, CS_DECALS, MAX_DECALS, true );
}
int SV_EventIndex( const char *name )
{
return SV_FindIndex( name, CS_EVENTS, MAX_EVENTS, true );
}
int SV_GenericIndex( const char *name )
{
return SV_FindIndex( name, CS_GENERICS, MAX_GENERICS, true );
}
int SV_ClassIndex( const char *name )
{
return SV_FindIndex( name, CS_CLASSNAMES, MAX_CLASSNAMES, true );

View File

@ -1,6 +1,6 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// sv_utils.c - server vm utils
// sv_main.c - server main loop
//=======================================================================
#include "common.h"
@ -488,8 +488,8 @@ void SV_Init( void )
timeout = Cvar_Get( "timeout", "125", 0, "connection timeout" );
zombietime = Cvar_Get( "zombietime", "2", 0, "timeout for clients-zombie (who died but not respawned)" );
sv_pausable = Cvar_Get( "pausable", "1", 0, "allow players to pause or not" );
sv_enforcetime = Cvar_Get ("sv_enforcetime", "0", 0, "client enforce time" );
allow_download = Cvar_Get ("allow_download", "1", CVAR_ARCHIVE, "allow download resources" );
sv_enforcetime = Cvar_Get( "sv_enforcetime", "0", 0, "client enforce time" );
allow_download = Cvar_Get( "allow_download", "0", CVAR_ARCHIVE, "allow download resources" );
sv_noreload = Cvar_Get( "sv_noreload", "0", 0, "ignore savepoints for singleplayer" );
sv_wallbounce = Cvar_Get( "sv_wallbounce", "1.0", 0, "bounce factor for client with MOVETYPE_BOUNCE" );
sv_spectatormaxspeed = Cvar_Get( "sv_spectatormaxspeed", "500", 0, "spectator maxspeed" );
@ -535,6 +535,7 @@ void SV_FinalMessage( char *message, bool reconnect )
MSG_Init( &msg, msg_buf, sizeof( msg_buf ));
MSG_WriteByte( &msg, svc_print );
MSG_WriteByte( &msg, PRINT_HIGH );
MSG_WriteString( &msg, message );
if( reconnect )

View File

@ -18,9 +18,10 @@ is not a staircase.
=============
*/
bool SV_CheckBottom( edict_t *ent )
bool SV_CheckBottom( edict_t *ent, int iMode )
{
vec3_t mins, maxs, start, stop;
bool realcheck = false;
float mid, bottom;
trace_t trace;
int x, y;
@ -38,21 +39,30 @@ bool SV_CheckBottom( edict_t *ent )
{
start[0] = x ? maxs[0] : mins[0];
start[1] = y ? maxs[1] : mins[1];
if( SV_PointContents( start ) != CONTENTS_SOLID )
goto realcheck;
if( SV_BaseContents( start, ent ) & MASK_SOLID )
{
realcheck = true;
break;
}
}
if( realcheck )
break;
}
return true; // we got out easy
realcheck:
if( !realcheck )
return true; // we got out easy
// check it for real...
start[2] = mins[2];
start[2] = mins[2] + svgame.movevars.stepsize;
// the midpoint must be within 16 of the bottom
start[0] = stop[0] = (mins[0] + maxs[0]) * 0.5f;
start[1] = stop[1] = (mins[1] + maxs[1]) * 0.5f;
stop[2] = start[2] - 2 * sv_stepheight->value;
trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent );
stop[2] = start[2] - 2 * svgame.movevars.stepsize;
if( iMode == WALKMOVE_WORLDONLY )
trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_WORLDONLY, ent );
else trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_NORMAL|FTRACE_SIMPLEBOX, ent );
if( trace.flFraction == 1.0f )
return false;
@ -66,300 +76,246 @@ realcheck:
start[0] = stop[0] = x ? maxs[0] : mins[0];
start[1] = stop[1] = y ? maxs[1] : mins[1];
trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent );
if( iMode == WALKMOVE_WORLDONLY )
trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_WORLDONLY, ent );
else trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_NORMAL|FTRACE_SIMPLEBOX, ent );
if( trace.flFraction != 1.0f && trace.vecEndPos[2] > bottom )
bottom = trace.vecEndPos[2];
if( trace.flFraction == 1.0f || mid - trace.vecEndPos[2] > sv_stepheight->value )
if( trace.flFraction == 1.0f || mid - trace.vecEndPos[2] > svgame.movevars.stepsize )
return false;
}
}
return true;
}
/*
=============
SV_movestep
SV_VecToYaw
Called by monster program code.
The move will be adjusted for slopes and stairs, but if the move isn't
possible, no move is done and false is returned
converts dir to yaw
=============
*/
bool SV_movestep( edict_t *ent, vec3_t move, bool relink, bool noenemy, bool settrace )
float SV_VecToYaw( const vec3_t src )
{
float yaw;
if( src[1] == 0 && src[0] == 0 )
{
yaw = 0;
}
else
{
yaw = (int)( com.atan2( src[1], src[0] ) * 180 / M_PI );
if( yaw < 0 ) yaw += 360;
}
return yaw;
}
//============================================================================
/*
======================
SV_WalkMove
======================
*/
bool SV_WalkMove( edict_t *ent, vec3_t move, int iMode )
{
float dz;
vec3_t oldorg, neworg;
vec3_t end, endpos;
edict_t *enemy;
trace_t trace;
int i;
vec3_t oldorg, neworg, end;
edict_t *groundent = NULL;
bool relink;
if( iMode == WALKMOVE_NORMAL )
relink = true;
else relink = false;
// try the move
VectorCopy (ent->v.origin, oldorg);
VectorAdd (ent->v.origin, move, neworg);
// flying monsters don't step up
if( ent->v.flags & (FL_SWIM|FL_FLY))
VectorCopy( ent->v.origin, oldorg );
// flying pawns don't step up
if( ent->v.flags & ( FL_SWIM|FL_FLY ))
{
// try one move with vertical motion, then one without
for( i = 0; i < 2; i++ )
VectorAdd( oldorg, move, neworg );
if( iMode == WALKMOVE_WORLDONLY )
trace = SV_Move( oldorg, ent->v.mins, ent->v.maxs, neworg, MOVE_WORLDONLY, ent );
else trace = SV_Move( oldorg, ent->v.mins, ent->v.maxs, neworg, MOVE_NORMAL|FTRACE_SIMPLEBOX, ent );
if( trace.flFraction == 1.0f )
{
VectorAdd( ent->v.origin, move, neworg );
if( noenemy ) enemy = EDICT_NUM( 0 );
else
{
enemy = ent->v.enemy;
if( i == 0 && enemy != EDICT_NUM( 0 ))
{
dz = ent->v.origin[2] - ent->v.enemy->v.origin[2];
if( dz > 40 ) neworg[2] -= 8;
if( dz < 30 ) neworg[2] += 8;
}
}
trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, neworg, MOVE_NORMAL, ent );
if(( ent->v.flags & FL_SWIM ) && !( SV_BaseContents(trace.vecEndPos, ent) & MASK_WATER ))
return false; // swimming pawn left water
if( trace.flFraction == 1.0f )
{
VectorCopy( trace.vecEndPos, endpos );
if( ent->v.flags & FL_SWIM && SV_PointContents( endpos ) == CONTENTS_EMPTY )
return false; // swim monster left water
VectorCopy( trace.vecEndPos, ent->v.origin );
VectorCopy( endpos, ent->v.origin );
if( relink ) SV_LinkEdict( ent, true );
return true;
}
if( enemy == EDICT_NUM( 0 )) break;
if( !VectorCompare( ent->v.origin, oldorg ))
SV_LinkEdict( ent, relink );
return true;
}
return false;
}
VectorAdd( oldorg, move, neworg );
// push down from a step height above the wished position
neworg[2] += sv_stepheight->value;
neworg[2] += svgame.movevars.stepsize;
VectorCopy( neworg, end );
end[2] -= sv_stepheight->value * 2;
trace = SV_Move( neworg, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent );
end[2] -= svgame.movevars.stepsize * 2;
if( iMode == WALKMOVE_WORLDONLY )
trace = SV_Move( neworg, ent->v.mins, ent->v.maxs, end, MOVE_WORLDONLY, ent );
else trace = SV_Move( neworg, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL|FTRACE_SIMPLEBOX, ent );
if( trace.fAllSolid )
{
Msg( "WalkMove: all solid\n" );
return false;
}
if( trace.fStartSolid )
{
neworg[2] -= sv_stepheight->value;
trace = SV_Move( neworg, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent );
neworg[2] -= svgame.movevars.stepsize;
if( iMode == WALKMOVE_WORLDONLY )
trace = SV_Move( neworg, ent->v.mins, ent->v.maxs, end, MOVE_WORLDONLY, ent );
else trace = SV_Move( neworg, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL|FTRACE_SIMPLEBOX, ent );
if( trace.fAllSolid || trace.fStartSolid )
{
Msg( "WalkMove: all solid || start solid\n" );
return false;
}
}
if( trace.flFraction == 1.0f )
{
// if monster had the ground pulled out, go ahead and fall
if( ent->v.flags & FL_PARTIALONGROUND )
if( ent->v.flags & FL_PARTIALGROUND )
{
VectorAdd( ent->v.origin, move, ent->v.origin );
if( relink ) SV_LinkEdict( ent, true );
if( !VectorCompare( ent->v.origin, oldorg ))
SV_LinkEdict( ent, relink );
ent->v.flags &= ~FL_ONGROUND;
return true;
}
Msg( "WalkMove: walked off and edge\n" );
return false; // walked off an edge
}
// check point traces down for dangling corners
VectorCopy( trace.vecEndPos, ent->v.origin );
groundent = trace.pHit;
if(!SV_CheckBottom( ent ))
// check our pos
if( iMode == WALKMOVE_WORLDONLY )
trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_WORLDONLY, ent );
else trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NORMAL|FTRACE_SIMPLEBOX, ent );
if( trace.fStartSolid )
{
if( ent->v.flags & FL_PARTIALONGROUND )
{
// entity had floor mostly pulled out from underneath it
// and is trying to correct
if( relink ) SV_LinkEdict( ent, true );
return true;
}
VectorCopy( oldorg, ent->v.origin );
Msg( "WalkMove: start solid\n" );
return false;
}
if( ent->v.flags & FL_PARTIALONGROUND )
ent->v.flags &= ~FL_PARTIALONGROUND;
if( !SV_CheckBottom( ent, iMode ))
{
if( ent->v.flags & FL_PARTIALGROUND )
{
// actor had floor mostly pulled out from underneath it
// and is trying to correct
if( !VectorCompare( ent->v.origin, oldorg ))
SV_LinkEdict( ent, relink );
Msg( "WalkMove: partialground - ok\n" );
return true;
}
ent->v.groundentity = trace.pHit;
ent->v.flags |= FL_PARTIALGROUND;
VectorCopy( oldorg, ent->v.origin );
Msg( "WalkMove: restore old pos\n" );
return false;
}
if( ent->v.flags & FL_PARTIALGROUND )
ent->v.flags &= ~FL_PARTIALGROUND;
ent->v.groundentity = groundent;
// the move is ok
if( relink ) SV_LinkEdict( ent, true );
if( !VectorCompare( ent->v.origin, oldorg ))
SV_LinkEdict( ent, relink );
return true;
}
//============================================================================
/*
======================
SV_StepDirection
Turns to the movement direction, and walks the current distance if
facing it.
======================
*/
bool SV_StepDirection( edict_t *ent, float yaw, float dist )
bool SV_StepDirection( edict_t *ent, float yaw, float dist, int iMode )
{
vec3_t move, oldorigin;
float delta;
ent->v.ideal_yaw = yaw;
ent->v.angles[1] = SV_AngleMod( ent->v.ideal_yaw, anglemod( ent->v.angles[1] ), ent->v.yaw_speed );
yaw = yaw * M_PI*2 / 360;
move[0] = cos(yaw)*dist;
move[1] = sin(yaw)*dist;
move[2] = 0;
VectorSet( move, com.cos( yaw ) * dist, com.sin( yaw ) * dist, 0.0f );
VectorCopy( ent->v.origin, oldorigin );
if(SV_movestep( ent, move, false, false, false ))
if( SV_WalkMove( ent, move, WALKMOVE_NORMAL ))
{
delta = ent->v.angles[YAW] - ent->v.ideal_yaw;
if( delta > 45 && delta < 315 )
{
// not turned far enough, so don't take the step
VectorCopy( oldorigin, ent->v.origin );
if( iMode != MOVE_STRAFE )
{
delta = ent->v.angles[YAW] - ent->v.ideal_yaw;
if( delta > 45 && delta < 315 )
{
// not turned far enough, so don't take the step
VectorCopy( oldorigin, ent->v.origin );
}
}
SV_LinkEdict( ent, true );
SV_LinkEdict( ent, false );
return true;
}
SV_LinkEdict( ent, true );
SV_LinkEdict( ent, false );
return false;
}
/*
======================
SV_FixCheckBottom
SV_MoveToOrigin
Turns to the movement direction, and walks the current distance if
facing it.
======================
*/
void SV_FixCheckBottom( edict_t *ent )
*/
void SV_MoveToOrigin( edict_t *ed, const vec3_t goal, float dist, int iMode )
{
ent->v.flags |= FL_PARTIALONGROUND;
}
float yaw, distToGoal;
vec3_t vecDist;
/*
================
SV_NewChaseDir
================
*/
void SV_NewChaseDir( edict_t *actor, edict_t *enemy, float dist )
{
float deltax, deltay;
float d[3], tdir, olddir, turnaround;
olddir = anglemod((int)(actor->v.ideal_yaw / 45 ) * 45 );
turnaround = anglemod( olddir - 180 );
deltax = enemy->v.origin[0] - actor->v.origin[0];
deltay = enemy->v.origin[1] - actor->v.origin[1];
if( deltax > 10 ) d[1]= 0;
else if( deltax < -10 ) d[1] = 180;
else d[1] = -1;
if( deltay < -10 ) d[2] = 270;
else if( deltay > 10 ) d[2] = 90;
else d[2] = -1;
// try direct route
if( d[1] != -1 && d[2] != -1 )
if( iMode == MOVE_STRAFE )
{
if( d[1] == 0 ) tdir = d[2] == 90 ? 45 : 315;
else tdir = d[2] == 90 ? 135 : 215;
if( tdir != turnaround && SV_StepDirection( actor, tdir, dist ))
return;
}
// try other directions
if((( rand()&3 ) & 1 ) || fabs(deltay) > fabs( deltax ))
{
tdir = d[1];
d[1] = d[2];
d[2] = tdir;
}
if( d[1] != -1 && d[1] != turnaround && SV_StepDirection( actor, d[1], dist ))
return;
if( d[2] != -1 && d[2] != turnaround && SV_StepDirection( actor, d[2], dist ))
return;
// there is no direct path to the player, so pick another direction
if( olddir != -1 && SV_StepDirection( actor, olddir, dist ))
return;
// randomly determine direction of search
if( rand() & 1 )
{
for( tdir = 0; tdir <= 315; tdir += 45 )
if( tdir != turnaround && SV_StepDirection( actor, tdir, dist ))
return;
vec3_t delta;
VectorSubtract( goal, ed->v.origin, delta );
VectorNormalizeFast( delta );
yaw = SV_VecToYaw( delta );
}
else
{
for( tdir = 315; tdir >= 0; tdir -= 45 )
if( tdir != turnaround && SV_StepDirection( actor, tdir, dist ))
return;
yaw = ed->v.ideal_yaw;
}
if( turnaround != -1 && SV_StepDirection( actor, turnaround, dist ))
return;
actor->v.ideal_yaw = olddir; // can't move
VectorSubtract( ed->v.origin, goal, vecDist );
distToGoal = com.sqrt( vecDist[0] * vecDist[0] + vecDist[1] * vecDist[1] );
if( dist > distToGoal ) dist = distToGoal;
// if a bridge was pulled out from underneath a monster, it may not have
// a valid standing position at all
if(!SV_CheckBottom( actor )) SV_FixCheckBottom( actor );
}
/*
======================
SV_CloseEnough
======================
*/
bool SV_CloseEnough( edict_t *ent, edict_t *goal, float dist )
{
int i;
for( i = 0; i < 3; i++ )
{
if( goal->v.absmin[i] > ent->v.absmax[i] + dist )
return false;
if( goal->v.absmax[i] < ent->v.absmin[i] - dist )
return false;
}
return true;
}
/*
======================
SV_MoveToGoal
======================
*/
bool SV_MoveToGoal( edict_t *ent, edict_t *goal, float dist )
{
if(!(ent->v.flags & (FL_FLY|FL_SWIM|FL_ONGROUND)))
{
return false;
}
// if the next step hits the enemy, return immediately
if( ent->v.enemy != EDICT_NUM( 0 ) && SV_CloseEnough( ent, goal, dist ))
return false;
// bump around...
if(( rand() & 3) == 1 || !SV_StepDirection( ent, ent->v.ideal_yaw, dist ))
{
SV_NewChaseDir( ent, goal, dist );
}
return true;
SV_StepDirection( ed, yaw, dist, iMode );
}

View File

@ -64,6 +64,10 @@ static bool SV_TestEntityPosition( edict_t *ent )
return false;
}
void SV_UnstickEntity( edict_t *ent )
{
}
/*
================
SV_CheckAllEnts
@ -1058,7 +1062,7 @@ void SV_Physics_Step( edict_t *ent )
// let dead monsters who aren't completely onground slide
if( wasonground )
{
if( !( ent->v.health <= 0.0f && !SV_CheckBottom( ent )))
if( !( ent->v.health <= 0.0f && !SV_CheckBottom( ent, WALKMOVE_NORMAL )))
{
vel = ent->v.velocity;
speed = com.sqrt( vel[0] * vel[0] + vel[1] * vel[1] );
@ -1310,159 +1314,6 @@ int SV_TryUnstick( edict_t *ent, vec3_t oldvel )
return 7; // still not moving
}
int SV_SetOnGround( edict_t *ent )
{
vec3_t end;
trace_t trace;
if( ent->v.flags & FL_ONGROUND )
return 1;
end[0] = ent->v.origin[0];
end[1] = ent->v.origin[1];
end[2] = ent->v.origin[2] + ent->v.mins[2] - 1;
trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent );
if( trace.flFraction <= DIST_EPSILON && trace.vecPlaneNormal[2] >= 0.7f )
{
ent->v.flags |= FL_ONGROUND;
ent->v.groundentity = trace.pHit;
return 1;
}
return 0;
}
/*
=====================
SV_WalkMove
Only used by players
======================
*/
void SV_WalkMove( edict_t *ent )
{
int clip, oldonground, originalmove_clip, originalmove_flags;
edict_t *originalmove_groundentity;
vec3_t upmove, downmove, start_origin, start_velocity;
vec3_t originalmove_origin, originalmove_velocity;
trace_t downtrace, steptrace;
Com_Assert( ent->pvServerData->client == NULL );
SV_CheckVelocity( ent );
// do a regular slide move unless it looks like you ran into a step
oldonground = (ent->v.flags & FL_ONGROUND);
ent->v.flags &= ~FL_ONGROUND;
VectorCopy( ent->v.origin, start_origin );
VectorCopy( ent->v.velocity, start_velocity );
clip = SV_FlyMove( ent, svgame.globals->frametime, NULL );
Msg( "ent->velocity.z %g\n", ent->v.velocity[2] );
SV_SetOnGround( ent );
SV_CheckVelocity( ent );
VectorCopy( ent->v.origin, originalmove_origin );
VectorCopy( ent->v.velocity, originalmove_velocity );
originalmove_clip = clip;
originalmove_flags = ent->v.flags;
originalmove_groundentity = ent->v.groundentity;
if( ent->v.flags & FL_WATERJUMP )
return;
// if move didn't block on a step, return
if( clip & 2 )
{
// if move was not trying to move into the step, return
if( fabs( start_velocity[0] ) < DIST_EPSILON && fabs( start_velocity[1] ) < DIST_EPSILON )
return;
if( ent->v.movetype != MOVETYPE_FLY )
{
// return if gibbed by a trigger
if( ent->v.movetype != MOVETYPE_WALK )
return;
// only step up while jumping if that is enabled
if( !oldonground && ent->v.waterlevel == 0 )
return;
}
// try moving up and forward to go up a step
// back to start pos
VectorCopy( start_origin, ent->v.origin );
VectorCopy( start_velocity, ent->v.velocity );
// move up
VectorClear( upmove );
upmove[2] = sv_stepheight->value;
SV_PushEntity( ent, upmove ); // FIXME: don't link?
// move forward
ent->v.velocity[2] = 0;
clip = SV_FlyMove( ent, svgame.globals->frametime, &steptrace );
ent->v.velocity[2] += start_velocity[2];
SV_CheckVelocity( ent );
// check for stuckness, possibly due to the limited precision of floats
// in the clipping hulls
if( clip && fabs( originalmove_origin[1] - ent->v.origin[1]) < DIST_EPSILON
&& fabs( originalmove_origin[0] - ent->v.origin[0] ) < DIST_EPSILON )
{
Msg( "wall\n" );
// stepping up didn't make any progress, revert to original move
VectorCopy( originalmove_origin, ent->v.origin );
VectorCopy( originalmove_velocity, ent->v.velocity );
//clip = originalmove_clip;
ent->v.flags = originalmove_flags;
ent->v.groundentity = originalmove_groundentity;
// now try to unstick if needed
//clip = SV_TryUnstick( ent, oldvel );
return;
}
//Con_Printf("step - ");
// extra friction based on view angle
if( clip & 2 ) SV_WallFriction( ent, &steptrace );
}
else if( !oldonground || start_velocity[2] > 0 || ent->v.flags & FL_ONGROUND || ent->v.waterlevel >= 2 )
return;
// move down
VectorClear( downmove );
downmove[2] = -sv_stepheight->value + start_velocity[2] * svgame.globals->frametime;
downtrace = SV_PushEntity( ent, downmove ); // FIXME: don't link?
if( downtrace.flFraction < 1 && downtrace.vecPlaneNormal[2] > 0.7f )
{
ent->v.flags |= FL_ONGROUND;
ent->v.groundentity = downtrace.pHit;
}
else
{
// if the push down didn't end up on good ground, use the move without
// the step up. This happens near wall / slope combinations, and can
// cause the player to hop up higher on a slope too steep to climb
VectorCopy( originalmove_origin, ent->v.origin );
VectorCopy( originalmove_velocity, ent->v.velocity );
// clip = originalmove_clip;
ent->v.flags = originalmove_flags;
ent->v.groundentity = originalmove_groundentity;
}
SV_SetOnGround( ent );
SV_CheckVelocity( ent );
}
/*
====================
SV_Physics_Conveyor
@ -1552,14 +1403,6 @@ static void SV_Physics_Entity( edict_t *ent )
case MOVETYPE_PUSHSTEP:
SV_Physics_Step( ent );
break;
case MOVETYPE_WALK:
if( !SV_RunThink( ent )) return;
if(!SV_CheckWater( ent ) && !( ent->v.flags & FL_WATERJUMP ))
SV_AddGravity( ent );
SV_CheckStuck( ent );
SV_WalkMove( ent );
SV_LinkEdict( ent, true );
break;
case MOVETYPE_FLY:
case MOVETYPE_TOSS:
case MOVETYPE_BOUNCE:

View File

@ -400,7 +400,7 @@ Handles selection or creation of a clipping hull, and offseting (and
eventually rotation) of the end points
==================
*/
trace_t SV_ClipMoveToEntity( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, uint umask )
trace_t SV_ClipMoveToEntity( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, uint umask, int flags )
{
trace_t trace;
model_t handle;
@ -428,15 +428,48 @@ trace_t SV_ClipMoveToEntity( edict_t *ent, const vec3_t start, vec3_t mins, vec3
if( ent == svgame.edicts )
CM_BoxTrace( &trace, start, end, mins, maxs, handle, umask, TR_AABB );
else if( !(flags & FTRACE_SIMPLEBOX) && CM_GetModelType( ent->v.modelindex ) == mod_studio )
{
if( CM_HitboxTrace( &trace, ent, start, end )); // continue tracing bbox if hitbox missing
else CM_TransformedBoxTrace( &trace, start, end, mins, maxs, handle, umask, origin, angles, TR_AABB );
}
else CM_TransformedBoxTrace( &trace, start, end, mins, maxs, handle, umask, origin, angles, TR_AABB );
// did we clip the move?
if( trace.flFraction < 1.0f || trace.fStartSolid )
trace.pHit = ent;
return trace;
}
trace_t SV_CombineTraces( trace_t *cliptrace, trace_t *trace, edict_t *touch, bool is_bmodel )
{
if( trace->fAllSolid )
{
cliptrace->fAllSolid = true;
trace->pHit = touch;
}
else if( trace->fStartSolid )
{
if( is_bmodel )
cliptrace->fStartStuck = true;
cliptrace->fStartSolid = true;
trace->pHit = touch;
}
if( trace->flFraction < cliptrace->flFraction )
{
bool oldStart;
// make sure we keep a startsolid from a previous trace
oldStart = cliptrace->fStartSolid;
trace->pHit = touch;
cliptrace = trace;
cliptrace->fStartSolid |= oldStart;
}
return *cliptrace;
}
/*
====================
SV_ClipToLinks
@ -467,12 +500,41 @@ void SV_ClipToLinks( areanode_t *node, moveclip_t *clip )
if( clip->type == MOVE_NOMONSTERS && touch->v.solid != SOLID_BSP )
continue;
if( clip->type == MOVE_WORLDONLY )
{
// accept only real bsp models with FL_WORLDBRUSH set
if( CM_GetModelType( touch->v.modelindex ) == mod_brush && touch->v.flags & FL_WORLDBRUSH );
else continue;
}
if( !BoundsIntersect( clip->boxmins, clip->boxmaxs, touch->v.absmin, touch->v.absmax ))
continue;
if( clip->passedict && !VectorIsNull( clip->passedict->v.size ) && VectorIsNull( touch->v.size ))
continue; // points never interact
if( clip->flags & FTRACE_IGNORE_GLASS && CM_GetModelType( touch->v.modelindex ) == mod_brush )
{
vec3_t point;
// we can ignore brushes with rendermode != kRenderNormal
switch( touch->v.rendermode )
{
case kRenderTransTexture:
case kRenderTransAlpha:
case kRenderTransAdd:
if( touch->v.renderamt < 200 )
continue;
// check for translucent contents
if( VectorIsNull( touch->v.origin ))
VectorAverage( touch->v.absmin, touch->v.absmax, point );
else VectorCopy( touch->v.origin, point );
if( SV_BaseContents( point, NULL ) & BASECONT_TRANSLUCENT )
continue; // glass detected
default: break;
}
}
// might intersect, so do an exact clip
if( clip->trace.fAllSolid ) return;
@ -484,20 +546,10 @@ void SV_ClipToLinks( areanode_t *node, moveclip_t *clip )
continue; // don't clip against owner
}
trace = SV_ClipMoveToEntity( touch, clip->start, clip->mins, clip->maxs, clip->end, clip->umask );
if( trace.fAllSolid || trace.fStartSolid || trace.flFraction < clip->trace.flFraction )
{
trace.pHit = touch;
if( clip->trace.fStartSolid )
{
clip->trace = trace;
clip->trace.fStartSolid = true;
}
else clip->trace = trace;
}
else if( trace.fStartSolid )
clip->trace.fStartSolid = true;
if( touch->v.flags & FL_MONSTER )
trace = SV_ClipMoveToEntity( touch, clip->start, clip->mins2, clip->maxs2, clip->end, clip->umask, clip->flags );
else trace = SV_ClipMoveToEntity( touch, clip->start, clip->mins, clip->maxs, clip->end, clip->umask, clip->flags );
clip->trace = SV_CombineTraces( &clip->trace, &trace, touch, touch->v.solid == SOLID_BSP );
}
// recurse down both sides
@ -541,6 +593,7 @@ SV_Move
trace_t SV_Move( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, int type, edict_t *e )
{
moveclip_t clip;
int i;
Mem_Set( &clip, 0, sizeof( moveclip_t ));
@ -548,19 +601,30 @@ trace_t SV_Move( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end,
clip.end = end;
clip.mins = mins;
clip.maxs = maxs;
clip.type = type;
clip.type = (type & 0xFF);
clip.flags = (type & 0xFF00);
clip.passedict = e;
clip.umask = World_MaskForEdict( e );
// clip to world
clip.trace = SV_ClipMoveToEntity( EDICT_NUM( 0 ), start, mins, maxs, end, clip.umask );
clip.trace = SV_ClipMoveToEntity( EDICT_NUM( 0 ), start, mins, maxs, end, clip.umask, 0 );
// skip tracing against entities
if( type == MOVE_WORLDONLY )
return clip.trace;
if( type == MOVE_MISSILE )
{
for( i = 0; i < 3; i++ )
{
clip.mins2[i] = -15;
clip.maxs2[i] = 15;
}
}
else
{
VectorCopy( mins, clip.mins2 );
VectorCopy( maxs, clip.maxs2 );
}
// create the bounding box of the entire move
SV_MoveBounds( start, clip.mins, clip.maxs, end, clip.boxmins, clip.boxmaxs );
SV_MoveBounds( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs );
// clip to entities
SV_ClipToLinks( sv_areanodes, &clip );
@ -616,7 +680,7 @@ SV_PointContents
=============
*/
int SV_BaseContents( const vec3_t p )
int SV_BaseContents( const vec3_t p, edict_t *e )
{
model_t handle;
float *angles;
@ -624,6 +688,9 @@ int SV_BaseContents( const vec3_t p )
edict_t *touch[MAX_EDICTS];
edict_t *hit;
// sanity check
if( !p ) return 0;
// get base contents from world
contents = CM_PointContents( p, 0 );
@ -634,6 +701,7 @@ int SV_BaseContents( const vec3_t p )
{
hit = touch[i];
if( hit == e ) continue;
if( hit->v.flags & (FL_CLIENT|FL_FAKECLIENT|FL_MONSTER))
{
// never get contents from alives
@ -655,7 +723,7 @@ int SV_BaseContents( const vec3_t p )
int SV_PointContents( const vec3_t p )
{
return World_ConvertContents( SV_BaseContents( p ));
return World_ConvertContents( SV_BaseContents( p, NULL ));
}
/*

View File

@ -12,10 +12,13 @@ and the initial and final xor values shown below... in other words, the
CCITT standard CRC used by XMODEM
=============================================================================
*/
#define NUM_BYTES 256
#define CRC_INIT_VALUE 0xffff
#define CRC_XOR_VALUE 0x0000
#define CRC32_INIT_VALUE 0xFFFFFFFFUL
#define CRC32_XOR_VALUE 0xFFFFFFFFUL
static word crctable[256] =
static const CRC16_t crctable[NUM_BYTES] =
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
@ -51,6 +54,74 @@ static word crctable[256] =
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
static const CRC32_t crc32table[NUM_BYTES] =
{
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
static byte chktbl[1024] =
{
0x84, 0x47, 0x51, 0xc1, 0x93, 0x22, 0x21, 0x24, 0x2f, 0x66, 0x60, 0x4d, 0xb0, 0x7c, 0xda,
@ -119,19 +190,19 @@ static byte chktbl[1024] =
0x39, 0x4f, 0xdd, 0xe4, 0xb6, 0x19, 0x27, 0xfb, 0xb8, 0xf5, 0x32, 0x73, 0xe5, 0xcb, 0x32
};
void CRC_Init( word *crcvalue )
void CRC_Init( CRC16_t *crcvalue )
{
*crcvalue = CRC_INIT_VALUE;
}
void CRC_ProcessByte( word *crcvalue, byte data )
void CRC_ProcessByte( CRC16_t *crcvalue, byte data )
{
*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
}
word CRC_Block( byte *start, int count )
CRC16_t CRC_Block( byte *start, int count )
{
word crc;
CRC16_t crc;
CRC_Init (&crc);
while(count--) CRC_ProcessByte( &crc, *start++ );
@ -149,7 +220,7 @@ For proxy protecting
byte CRC_BlockSequence(byte *base, int length, int sequence)
{
int n, x;
word crc;
CRC16_t crc;
byte *p, chkb[60 + 4];
if (sequence < 0) sequence = abs(sequence);
@ -171,6 +242,88 @@ byte CRC_BlockSequence(byte *base, int length, int sequence)
return crc;
}
void CRC32_Init( CRC32_t *pulCRC )
{
*pulCRC = CRC32_INIT_VALUE;
}
void CRC32_Final( CRC32_t *pulCRC )
{
*pulCRC ^= CRC32_XOR_VALUE;
}
void CRC32_ProcessByte( CRC32_t *pulCRC, byte ch )
{
CRC32_t ulCrc = *pulCRC;
ulCrc ^= ch;
ulCrc = crc32table[(byte)ulCrc] ^ (ulCrc >> 8);
*pulCRC = ulCrc;
}
void CRC32_ProcessBuffer( CRC32_t *pulCRC, const void *pBuffer, int nBuffer )
{
CRC32_t ulCrc = *pulCRC;
byte *pb = (byte *)pBuffer;
uint nFront;
int nMain;
JustAfew:
switch( nBuffer )
{
case 7: ulCrc = crc32table[*pb++ ^ (byte)ulCrc] ^ (ulCrc >> 8);
case 6: ulCrc = crc32table[*pb++ ^ (byte)ulCrc] ^ (ulCrc >> 8);
case 5: ulCrc = crc32table[*pb++ ^ (byte)ulCrc] ^ (ulCrc >> 8);
case 4:
ulCrc ^= *(CRC32_t *)pb; // warning, this only works on little-endian.
ulCrc = crc32table[(byte)ulCrc] ^ (ulCrc >> 8);
ulCrc = crc32table[(byte)ulCrc] ^ (ulCrc >> 8);
ulCrc = crc32table[(byte)ulCrc] ^ (ulCrc >> 8);
ulCrc = crc32table[(byte)ulCrc] ^ (ulCrc >> 8);
*pulCRC = ulCrc;
return;
case 3: ulCrc = crc32table[*pb++ ^ (byte)ulCrc] ^ (ulCrc >> 8);
case 2: ulCrc = crc32table[*pb++ ^ (byte)ulCrc] ^ (ulCrc >> 8);
case 1: ulCrc = crc32table[*pb++ ^ (byte)ulCrc] ^ (ulCrc >> 8);
case 0: *pulCRC = ulCrc;
return;
}
// We may need to do some alignment work up front, and at the end, so that
// the main loop is aligned and only has to worry about 8 byte at a time.
// The low-order two bits of pb and nBuffer in total control the
// upfront work.
nFront = ((uint)pb) & 3;
nBuffer -= nFront;
switch( nFront )
{
case 3: ulCrc = crc32table[*pb++ ^ (byte)ulCrc] ^ (ulCrc >> 8);
case 2: ulCrc = crc32table[*pb++ ^ (byte)ulCrc] ^ (ulCrc >> 8);
case 1: ulCrc = crc32table[*pb++ ^ (byte)ulCrc] ^ (ulCrc >> 8);
}
nMain = nBuffer >> 3;
while( nMain-- )
{
ulCrc ^= *(CRC32_t *)pb; // warning, this only works on little-endian.
ulCrc = crc32table[(byte)ulCrc] ^ (ulCrc >> 8);
ulCrc = crc32table[(byte)ulCrc] ^ (ulCrc >> 8);
ulCrc = crc32table[(byte)ulCrc] ^ (ulCrc >> 8);
ulCrc = crc32table[(byte)ulCrc] ^ (ulCrc >> 8);
ulCrc ^= *(CRC32_t *)(pb + 4);// warning, this only works on little-endian.
ulCrc = crc32table[(byte)ulCrc] ^ (ulCrc >> 8);
ulCrc = crc32table[(byte)ulCrc] ^ (ulCrc >> 8);
ulCrc = crc32table[(byte)ulCrc] ^ (ulCrc >> 8);
ulCrc = crc32table[(byte)ulCrc] ^ (ulCrc >> 8);
pb += 8;
}
nBuffer &= 7;
goto JustAfew;
}
/*
=============================================================================
MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm

View File

@ -8,11 +8,12 @@
#define MAX_CVARS 2048
#define FILE_HASH_SIZE 256
int cvar_numIndexes;
int cvar_modifiedFlags;
cvar_t cvar_indexes[MAX_CVARS];
cvar_t *cvar_vars;
static cvar_t* hashTable[FILE_HASH_SIZE];
int cvar_numIndexes;
int cvar_modifiedFlags;
cvar_t cvar_indexes[MAX_CVARS];
static cvar_t *hashTable[FILE_HASH_SIZE];
cvar_t *cvar_vars;
cvar_t *userinfo;
/*
================
@ -151,19 +152,19 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags, const
return NULL;
}
if (!Cvar_ValidateString(var_name, false))
if( !Cvar_ValidateString( var_name, false ))
{
MsgDev(D_WARN, "invalid info cvar name string %s\n", var_name );
var_value = "noname";
}
if(!Cvar_ValidateString( var_value, true ))
if( !Cvar_ValidateString( var_value, true ))
{
MsgDev(D_WARN, "invalid cvar value string: %s\n", var_value );
var_value = "default";
}
// check for command coexisting
if(Cmd_Exists(var_name))
if( Cmd_Exists( var_name ))
{
MsgDev(D_WARN, "Cvar_Get: %s is a command\n", var_name );
return NULL;
@ -362,6 +363,9 @@ cvar_t *Cvar_Set2 (const char *var_name, const char *value, bool force)
var->modified = true;
var->modificationCount++;
if( var->flags & CVAR_USERINFO )
userinfo->modified = true; // transmit at next oportunity
// free the old value string
Mem_Free( var->string );
@ -402,7 +406,7 @@ void Cvar_FullSet( char *var_name, char *value, int flags )
cvar_t *var;
var = Cvar_FindVar (var_name);
if(!var)
if( !var )
{
// create it
Cvar_Get( var_name, value, flags, "" );
@ -413,7 +417,7 @@ void Cvar_FullSet( char *var_name, char *value, int flags )
if( var->flags & CVAR_USERINFO )
{
// transmit at next oportunity
com.userinfo_modified = true;
userinfo->modified = true;
}
Mem_Free( var->string ); // free the old value string
@ -867,7 +871,8 @@ void Cvar_Init( void )
cvar_vars = NULL;
cvar_numIndexes = cvar_modifiedFlags = 0;
ZeroMemory( cvar_indexes, sizeof( cvar_t ) * MAX_CVARS );
ZeroMemory( hashTable, sizeof(*hashTable ) * FILE_HASH_SIZE );
ZeroMemory( hashTable, sizeof( *hashTable ) * FILE_HASH_SIZE );
userinfo = Cvar_Get( "@userinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only
Cmd_AddCommand ("toggle", Cvar_Toggle_f, "toggles a console variable's values (use for more info)" );
Cmd_AddCommand ("set", Cvar_Set_f, "create or change the value of a console variable" );

View File

@ -7,14 +7,13 @@
/*
=================
Base Entry Point
Main Entry Point
=================
*/
DLLEXPORT int CreateAPI( char *hostname, bool console )
DLLEXPORT int CreateAPI( const char *hostname, bool console )
{
// member name
com_strncpy( Sys.progname, hostname, sizeof(Sys.progname));
Sys.hooked_out = console; // set mode
com_strncpy( Sys.progname, hostname, sizeof( Sys.progname ));
Sys.hooked_out = console;
Sys_Init();
Sys.Main();

View File

@ -1398,10 +1398,10 @@ void FS_CreateGameInfo( const char *filename )
com.strncat( buffer, "\nctf_spawn\t\t\"info_player_ctf\"", MAX_SYSPATH );
com.strncat( buffer, "\ncoop_spawn\t\"info_player_coop\"", MAX_SYSPATH );
com.strncat( buffer, "\nteam_spawn\t\"info_player_team\"", MAX_SYSPATH );
com.strncat( buffer, "\nhull0\t\t( -16 -16 -36 ) ( 16 16 36 )", MAX_SYSPATH );
com.strncat( buffer, "\nhull1\t\t( -16 -16 -18 ) ( 16 16 18 )", MAX_SYSPATH );
com.strncat( buffer, "\nhull2\t\t( 0 0 0 ) ( 0 0 0 )", MAX_SYSPATH );
com.strncat( buffer, "\nhull3\t\t( -32 -32 -32 ) ( 32 32 32 )", MAX_SYSPATH );
com.strncat( buffer, "\nhull0\t\t( 0 0 0 ) ( 0 0 0 )", MAX_SYSPATH );
com.strncat( buffer, "\nhull1\t\t( -16 -16 -36 ) ( 16 16 36 )", MAX_SYSPATH );
com.strncat( buffer, "\nhull2\t\t( -32 -32 -32 ) ( 32 32 32 )", MAX_SYSPATH );
com.strncat( buffer, "\nhull3\t\t( -16 -16 -18 ) ( 16 16 18 )", MAX_SYSPATH );
com.strncat( buffer, "\nviewheight0\t\"28\"", MAX_SYSPATH );
com.strncat( buffer, "\nviewheight1\t\"12\"", MAX_SYSPATH );
com.strncat( buffer, "\nmax_edicts\t\"1024\"", MAX_SYSPATH );
@ -1448,14 +1448,14 @@ static bool FS_ParseGameInfo( const char *filename, gameinfo_t *GameInfo )
com.strncpy( GameInfo->team_entity, "info_player_team", MAX_STRING );
com.strncpy( GameInfo->startmap, "newmap", MAX_STRING );
VectorSet( GameInfo->client_mins[0], -16, -16, -36 );
VectorSet( GameInfo->client_maxs[0], 16, 16, 36 );
VectorSet( GameInfo->client_mins[1], -16, -16, -18 );
VectorSet( GameInfo->client_maxs[1], 16, 16, 18 );
VectorSet( GameInfo->client_mins[2], 0, 0, 0 );
VectorSet( GameInfo->client_maxs[2], 0, 0, 0 );
VectorSet( GameInfo->client_mins[3], -32, -32, -32 );
VectorSet( GameInfo->client_maxs[3], 32, 32, 32 );
VectorSet( GameInfo->client_mins[0], 0, 0, 0 );
VectorSet( GameInfo->client_maxs[0], 0, 0, 0 );
VectorSet( GameInfo->client_mins[1], -16, -16, -36 );
VectorSet( GameInfo->client_maxs[1], 16, 16, 36 );
VectorSet( GameInfo->client_mins[2], -32, -32, -32 );
VectorSet( GameInfo->client_maxs[2], 32, 32, 32 );
VectorSet( GameInfo->client_mins[3], -16, -16, -18 );
VectorSet( GameInfo->client_maxs[3], 16, 16, 18 );
while( script )
{

View File

@ -445,12 +445,16 @@ bool VFS_Eof( vfile_t* file);
//
// crclib.c
//
void CRC_Init(word *crcvalue);
word CRC_Block (byte *start, int count);
void CRC_ProcessByte(word *crcvalue, byte data);
byte CRC_BlockSequence(byte *base, int length, int sequence);
uint Com_BlockChecksum (void *buffer, int length);
uint Com_BlockChecksumKey(void *buffer, int length, int key);
void CRC_Init( CRC16_t *crcvalue );
CRC16_t CRC_Block( byte *start, int count );
void CRC_ProcessByte( CRC16_t *crcvalue, byte data );
byte CRC_BlockSequence( byte *base, int length, int sequence );
uint Com_BlockChecksum( void *buffer, int length );
uint Com_BlockChecksumKey( void *buffer, int length, int key );
void CRC32_ProcessBuffer( CRC32_t *pulCRC, const void *pBuffer, int nBuffer );
void CRC32_ProcessByte( CRC32_t *pulCRC, byte ch );
void CRC32_Init( CRC32_t *pulCRC );
void CRC32_Final( CRC32_t *pulCRC );
//
// parselib.c

View File

@ -1,64 +0,0 @@
<html>
<body>
<pre>
<h1>Build Log</h1>
<h3>
--------------------Configuration: launch - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
Creating temporary file "C:\DOCUME~1\ĚČŘŔ\LOCALS~1\Temp\RSPF9F.tmp" with contents
[
/nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "./" /I "imagelib" /I "../public" /I "../common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"..\temp\launch\!debug/" /Fo"..\temp\launch\!debug/" /Fd"..\temp\launch\!debug/" /FD /GZ /c
"D:\Xash3D\src_main\launch\filesystem.c"
]
Creating command line "cl.exe @"C:\DOCUME~1\ĚČŘŔ\LOCALS~1\Temp\RSPF9F.tmp""
Creating temporary file "C:\DOCUME~1\ĚČŘŔ\LOCALS~1\Temp\RSPFA0.tmp" with contents
[
zlib.lib png.lib jpg.lib user32.lib gdi32.lib shell32.lib advapi32.lib winmm.lib /nologo /dll /incremental:yes /pdb:"..\temp\launch\!debug/launch.pdb" /debug /machine:I386 /nodefaultlib:"libc.lib" /out:"..\temp\launch\!debug/launch.dll" /implib:"..\temp\launch\!debug/launch.lib" /pdbtype:sept /libpath:"./imagelib"
"\Xash3D\src_main\temp\launch\!debug\cmd.obj"
"\Xash3D\src_main\temp\launch\!debug\console.obj"
"\Xash3D\src_main\temp\launch\!debug\cpuinfo.obj"
"\Xash3D\src_main\temp\launch\!debug\crclib.obj"
"\Xash3D\src_main\temp\launch\!debug\cvar.obj"
"\Xash3D\src_main\temp\launch\!debug\export.obj"
"\Xash3D\src_main\temp\launch\!debug\filesystem.obj"
"\Xash3D\src_main\temp\launch\!debug\img_bmp.obj"
"\Xash3D\src_main\temp\launch\!debug\img_dds.obj"
"\Xash3D\src_main\temp\launch\!debug\img_jpg.obj"
"\Xash3D\src_main\temp\launch\!debug\img_main.obj"
"\Xash3D\src_main\temp\launch\!debug\img_pcx.obj"
"\Xash3D\src_main\temp\launch\!debug\img_png.obj"
"\Xash3D\src_main\temp\launch\!debug\img_tga.obj"
"\Xash3D\src_main\temp\launch\!debug\img_utils.obj"
"\Xash3D\src_main\temp\launch\!debug\img_vtf.obj"
"\Xash3D\src_main\temp\launch\!debug\img_wad.obj"
"\Xash3D\src_main\temp\launch\!debug\memlib.obj"
"\Xash3D\src_main\temp\launch\!debug\network.obj"
"\Xash3D\src_main\temp\launch\!debug\parselib.obj"
"\Xash3D\src_main\temp\launch\!debug\patch.obj"
"\Xash3D\src_main\temp\launch\!debug\stdlib.obj"
"\Xash3D\src_main\temp\launch\!debug\system.obj"
"\Xash3D\src_main\temp\launch\!debug\utils.obj"
]
Creating command line "link.exe @"C:\DOCUME~1\ĚČŘŔ\LOCALS~1\Temp\RSPFA0.tmp""
Creating temporary file "C:\DOCUME~1\ĚČŘŔ\LOCALS~1\Temp\RSPFA1.bat" with contents
[
@echo off
copy \Xash3D\src_main\temp\launch\!debug\launch.dll "D:\Xash3D\bin\launch.dll"
]
Creating command line ""C:\DOCUME~1\ĚČŘŔ\LOCALS~1\Temp\RSPFA1.bat""
Compiling...
filesystem.c
Linking...
Creating library ..\temp\launch\!debug/launch.lib and object ..\temp\launch\!debug/launch.exp
<h3>Output Window</h3>
Performing Custom Build Step on \Xash3D\src_main\temp\launch\!debug\launch.dll
‘Ş®Ż¨ŕ®˘ ­® ä ©«®˘: 1.
<h3>Results</h3>
launch.dll - 0 error(s), 0 warning(s)
</pre>
</body>
</html>

View File

@ -58,6 +58,10 @@ void Sys_GetStdAPI( void )
com.crc_sequence = CRC_BlockSequence;
com.crc_blockchecksum = Com_BlockChecksum;
com.crc_blockchecksumkey = Com_BlockChecksumKey;
com.crc32_init = CRC32_Init;
com.crc32_block = CRC32_ProcessBuffer;
com.crc32_process = CRC32_ProcessByte;
com.crc32_final = CRC32_Final;
// memlib.c
com.memcpy = _crt_mem_copy; // first time using

View File

@ -14,8 +14,10 @@
#define MAX_LIGHTSTYLES 256 // can't be blindly increased
#define MAX_DECALS 256 // server decal indexes (different decalnames, not a render limit)
#define MAX_USER_MESSAGES 200 // another 56 messages reserved for engine routines
#define MAX_EVENTS 256 // playback events that can be queued (a byte range, don't touch)
#define MAX_GENERICS 256 // generic files that can download from server
#define MAX_CLASSNAMES 512 // maxcount of various edicts classnames
#define MAX_SOUNDS 512 // openal software limit
#define MAX_SOUNDS 1024 // max unique loaded sounds
#define MAX_MODELS 4096 // total count of brush & studio various models per one map
#define MAX_PARTICLES 32768 // per one frame
#define MAX_EDICTS 32768 // absolute limit that never be reached, (do not edit!)
@ -51,6 +53,7 @@ typedef struct trace_s
// private to engine
int iContents; // final pos contents
const char *pTexName; // texture name that we hitting (brushes and studiomodels)
int fStartStuck; // stuck on start trace
} trace_t;
/*

View File

@ -430,12 +430,16 @@ typedef struct stdilib_api_s
sys_event_t (*getevent)( void ); // get system events
// crclib.c funcs
void (*crc_init)(word *crcvalue); // set initial crc value
word (*crc_block)(byte *start, int count); // calculate crc block
void (*crc_process)(word *crcvalue, byte data); // process crc byte
byte (*crc_sequence)(byte *base, int length, int sequence); // calculate crc for sequence
uint (*crc_blockchecksum)(void *buffer, int length); // map checksum
uint (*crc_blockchecksumkey)(void *buf, int len, int key); // process key checksum
void (*crc_init)( CRC16_t *pusCRC ); // set initial crc value
CRC16_t (*crc_block)( byte *start, int count ); // calculate crc block
void (*crc_process)( CRC16_t *crcvalue, byte data ); // process crc byte
byte (*crc_sequence)( byte *base, int len, int sequence ); // calculate crc for sequence
uint (*crc_blockchecksum)( void *buffer, int length ); // map checksum
uint (*crc_blockchecksumkey)( void *buf, int len, int key );// process key checksum
void (*crc32_init)( CRC32_t *pulCRC );
void (*crc32_process)( CRC32_t *crcvalue, byte data ); // process crc32 byte
void (*crc32_block)( CRC32_t *pulCRC, const void *pBuffer, int nBuffer );
void (*crc32_final)( CRC32_t *pulCRC );
// memlib.c funcs
void (*memcpy)(void *dest, const void *src, size_t size, const char *file, int line);
@ -531,7 +535,6 @@ typedef struct stdilib_api_s
float (*Cvar_GetValue )(const char *name);
char *(*Cvar_GetString)(const char *name);
cvar_t *(*Cvar_FindVar)(const char *name);
bool userinfo_modified; // tell to client about userinfo modified
// console commands
void (*Cmd_Exec)(int exec_when, const char *text); // process cmd buffer
@ -554,8 +557,8 @@ typedef struct stdilib_api_s
int (*fgets)(file_t* file, byte *string, size_t bufsize ); // like a fgets, but can return EOF
int (*fseek)(file_t* file, fs_offset_t offset, int whence); // fseek, can seek in packfiles too
bool (*fremove)( const char *path ); // remove sepcified file
long (*ftell)(file_t* file); // like a ftell
bool (*feof)(file_t* file); // like a feof
long (*ftell)( file_t *file ); // like a ftell
bool (*feof)( file_t *file ); // like a feof
// virtual filesystem
vfile_t *(*vfcreate)( const byte *buffer, size_t buffsize ); // create virtual stream
@ -758,14 +761,14 @@ filesystem manager
#define FS_Close( file ) com.fclose( file )
#define FS_FileBase( x, y ) com.Com_FileBase( x, y )
#define FS_LoadInternal( x, y ) com.Com_LoadRes( x, y )
#define FS_Printf com.fprintf
#define FS_Print com.fprint
#define FS_Seek com.fseek
#define FS_Tell com.ftell
#define FS_Eof com.feof
#define FS_Getc com.fgetc
#define FS_Gets com.fgets
#define FS_Delete com.fremove
#define FS_Printf (*com.fprintf)
#define FS_Print (*com.fprint)
#define FS_Seek (*com.fseek)
#define FS_Tell (*com.ftell)
#define FS_Eof (*com.feof)
#define FS_Getc (*com.fgetc)
#define FS_Gets (*com.fgets)
#define FS_Delete (*com.fremove)
#define FS_Gamedir() com.SysInfo->GameInfo->gamedir
#define FS_Title() com.SysInfo->GameInfo->title
#define g_Instance() com.SysInfo->instance
@ -806,7 +809,6 @@ console variables
#define Cvar_VariableInteger com.Cvar_GetInteger
#define Cvar_VariableString com.Cvar_GetString
#define Cvar_FindVar com.Cvar_FindVar
#define userinfo_modified com.userinfo_modified
/*
===========================================
@ -874,6 +876,11 @@ crclib manager
#define CRC_Block com.crc_block
#define CRC_ProcessByte com.crc_process
#define CRC_Sequence com.crc_sequence
#define CRC32_Init com.crc32_init
#define CRC32_ProcessBuffer com.crc32_block
#define CRC32_ProcessByte com.crc32_process
#define CRC32_Final com.crc32_final
#define CRC_Sequence com.crc_sequence
#define Com_BlockChecksum com.crc_blockchecksum
#define Com_BlockChecksumKey com.crc_blockchecksumkey

View File

@ -51,7 +51,7 @@ typedef struct physic_exp_s
byte *(*ClusterPVS)( int cluster );
byte *(*ClusterPHS)( int cluster );
int (*LeafCluster)( int leafnum );
int (*PointLeafnum)( vec3_t p );
int (*PointLeafnum)( const vec3_t p );
int (*LeafArea)( int leafnum );
// map data
@ -59,6 +59,8 @@ typedef struct physic_exp_s
int (*NumBmodels)( void );
void (*Mod_GetBounds)( model_t handle, vec3_t mins, vec3_t maxs );
void (*Mod_GetFrames)( model_t handle, int *numFrames );
void (*Mod_GetAttachment)( edict_t *e, int iAttachment, float *org, float *ang );
void (*Mod_GetBonePos)( edict_t* e, int iBone, float *rgflOrigin, float *rgflAngles );
modtype_t (*Mod_GetType)( model_t handle );
const char *(*GetShaderName)( int index );
void *(*Mod_Extradata)( model_t handle );
@ -70,6 +72,7 @@ typedef struct physic_exp_s
int (*PointContents2)( const vec3_t p, model_t model, const vec3_t org, const vec3_t ang );
void (*BoxTrace1)( trace_t *results, const vec3_t p1, const vec3_t p2, vec3_t mins, vec3_t maxs, model_t model, int mask, trType_t type );
void (*BoxTrace2)( trace_t *results, const vec3_t p1, const vec3_t p2, vec3_t mins, vec3_t maxs, model_t model, int mask, const vec3_t org, const vec3_t ang, trType_t type );
bool (*HitboxTrace)( trace_t *tr, edict_t *e, const vec3_t p1, const vec3_t p2 );
model_t (*TempModel)( const vec3_t mins, const vec3_t maxs, bool capsule );
// needs to be removed

View File

@ -302,7 +302,7 @@ typedef enum
BASECONT_NODROP = BIT(29), // don't leave bodies or items (death fog, lava)
// content masks
MASK_SOLID = (BASECONT_SOLID),
MASK_SOLID = (BASECONT_SOLID|BASECONT_BODY),
MASK_PLAYERSOLID = (BASECONT_SOLID|BASECONT_PLAYERCLIP|BASECONT_BODY),
MASK_MONSTERSOLID = (BASECONT_SOLID|BASECONT_MONSTERCLIP|BASECONT_BODY),
MASK_DEADSOLID = (BASECONT_SOLID|BASECONT_PLAYERCLIP),
@ -628,6 +628,50 @@ typedef struct
#include "studio_ref.h"
/*
========================================================================
ROQ FILES
The .roq file are vector-compressed movies
========================================================================
*/
#define RoQ_HEADER1 4228
#define RoQ_HEADER2 -1
#define RoQ_HEADER3 30
#define RoQ_FRAMERATE 30
// RoQ markers
#define RoQ_INFO 0x1001
#define RoQ_QUAD_CODEBOOK 0x1002
#define RoQ_QUAD_VQ 0x1011
#define RoQ_SOUND_MONO 0x1020
#define RoQ_SOUND_STEREO 0x1021
// RoQ movie type
#define RoQ_ID_MOT 0x00
#define RoQ_ID_FCC 0x01
#define RoQ_ID_SLD 0x02
#define RoQ_ID_CCC 0x03
typedef struct
{
byte y[4];
byte u;
byte v;
} dcell_t;
typedef struct
{
byte idx[4];
} dquadcell_t;
typedef struct
{
word id;
uint size;
word argument;
} droqchunk_t;
/*
==============================================================================
SAVE FILE

View File

@ -88,6 +88,36 @@ typedef struct
byte seqblending[16]; // blending between sequence when it's changed
} prevframe_t;
typedef struct
{
char *name;
byte *mempool;
droqchunk_t chunk;
dcell_t cells[256];
dquadcell_t qcells[256];
byte *vid_buffer;
byte *vid_pic[2];
byte *pic;
byte *pic_pending;
bool new_frame;
int s_rate;
int s_width;
int s_channels;
int width;
int height;
file_t *file;
int headerlen;
uint time; // Sys_Milliseconds for first cinematic frame
uint frame;
} cinematics_t;
/*
==============================================================================
@ -155,6 +185,10 @@ typedef struct render_imp_s
edict_t *(*GetLocalPlayer)( void );
int (*GetMaxClients)( void );
float (*GetLerpFrac)( void );
// RoQ decoder imports
void (*RoQ_ReadChunk)( cinematics_t *cin );
byte *(*RoQ_ReadNextFrame)( cinematics_t *cin, bool silent );
} render_imp_t;
#endif//RENDER_API_H

View File

@ -315,12 +315,12 @@ void CBaseEntity :: ClearPointers( void )
//=========================================================
BOOL CBaseEntity :: FVisible ( const Vector &vecOrigin )
{
TraceResult tr;
TraceResult tr;
Vector vecLookerOrigin;
vecLookerOrigin = EyePosition();//look through the caller's 'eyes'
vecLookerOrigin = EyePosition(); // look through the caller's 'eyes'
UTIL_TraceLine(vecLookerOrigin, vecOrigin, ignore_monsters, ignore_glass, ENT(pev)/*pentIgnore*/, &tr);
UTIL_TraceLine( vecLookerOrigin, vecOrigin, ignore_monsters, ignore_glass, ENT( pev ), &tr );
if (tr.flFraction != 1.0)
return FALSE;
@ -331,9 +331,9 @@ BOOL CBaseEntity :: FVisible ( const Vector &vecOrigin )
// FVisible - returns true if a line can be traced from
// the caller's eyes to the target
//=========================================================
BOOL CBaseEntity :: FVisible ( CBaseEntity *pEntity )
BOOL CBaseEntity :: FVisible( CBaseEntity *pEntity )
{
TraceResult tr;
TraceResult tr;
Vector vecLookerOrigin;
Vector vecTargetOrigin;
@ -341,15 +341,15 @@ BOOL CBaseEntity :: FVisible ( CBaseEntity *pEntity )
return FALSE;
// don't look through water
if ((pev->waterlevel != 3 && pEntity->pev->waterlevel == 3) || (pev->waterlevel == 3 && pEntity->pev->waterlevel == 0))
if(( pev->waterlevel != 3 && pEntity->pev->waterlevel == 3 ) || ( pev->waterlevel == 3 && pEntity->pev->waterlevel != 3 ))
return FALSE;
vecLookerOrigin = pev->origin + pev->view_ofs;//look through the caller's 'eyes'
vecLookerOrigin = pev->origin + pev->view_ofs; // look through the caller's 'eyes'
vecTargetOrigin = pEntity->EyePosition();
UTIL_TraceLine(vecLookerOrigin, vecTargetOrigin, ignore_monsters, ignore_glass, ENT(pev)/*pentIgnore*/, &tr);
UTIL_TraceLine( vecLookerOrigin, vecTargetOrigin, ignore_monsters, ignore_glass, ENT( pev ), &tr );
if (tr.flFraction != 1.0 && tr.pHit != ENT(pEntity->pev))
if( tr.flFraction != 1.0 && tr.pHit != ENT( pEntity->pev ))
return FALSE;
return TRUE;
}
@ -706,6 +706,7 @@ CBaseEntity * CBaseEntity::CreateGib( char *szName, char *szModel )
if( FNullEnt( pent )) return NULL;
pEntity = Instance( pent );
pEntity->SetObjectClass( );
DispatchSpawn( pEntity->edict() );
if( !FStringNull( model ))

View File

@ -1254,7 +1254,7 @@ void CPendulum :: SetSwing( float speed )
{
UTIL_SetAvelocity( this, g_vecZero );
m_iState = STATE_OFF;
LINK_ENTITY( ENT( pev ));
LINK_ENTITY( ENT( pev ), false );
}
}
else

View File

@ -59,11 +59,16 @@ public:
Msg( "Can't find decal %s\n", pkvd->szValue );
}
}
void PostSpawn( void ) { if( FStringNull( pev->targetname )) MakeDecal(); }
void PostActivate( void ) { if( FStringNull( pev->targetname )) MakeDecal(); }
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { MakeDecal(); }
void MakeDecal( void )
{
if ( pev->skin < 0 ) { REMOVE_ENTITY(ENT(pev)); return; }
if ( pev->skin < 0 )
{
REMOVE_ENTITY( ENT( pev ));
return;
}
TraceResult trace;
int entityIndex, modelIndex;

View File

@ -284,7 +284,7 @@ void CBasePlayerWeapon :: Spawn( void )
pev->movetype = MOVETYPE_TOSS;
pev->solid = SOLID_BBOX;
pev->sequence = 1; // set world animation
UTIL_SetOrigin( this, pev->origin );
UTIL_SetModel( ENT( pev ), iWorldModel( ));
SetObjectClass( ED_NORMAL );

View File

@ -1145,6 +1145,7 @@ void UpdateEntityState( entity_state_t *to, edict_t *from, int baseline )
to->weaponmodel = MODEL_INDEX( STRING( pNet->pev->weaponmodel ));
else to->weaponmodel = 0;
to->weapons = pNet->pev->weapons;
to->maxspeed = pNet->pev->maxspeed;
// clamp fov
if( pNet->pev->fov < 0.0 ) pNet->pev->fov = 0.0;
@ -1182,6 +1183,50 @@ void UpdateEntityState( entity_state_t *to, edict_t *from, int baseline )
}
}
/*
=================
CmdStart
We're about to run this usercmd for the specified player. We can set up groupinfo and masking here, etc.
This is the time to examine the usercmd for anything extra. This call happens even if think does not.
=================
*/
void CmdStart( const edict_t *player, const usercmd_t *cmd, unsigned int random_seed )
{
entvars_t *pev = (entvars_t *)&player->v;
CBasePlayer *pl = ( CBasePlayer *) CBasePlayer::Instance( pev );
if( !pl )
return;
if ( pl->pev->groupinfo != 0 )
{
UTIL_SetGroupTrace( pl->pev->groupinfo, GROUP_OP_AND );
}
pl->random_seed = random_seed;
}
/*
=================
CmdEnd
Each cmdstart is exactly matched with a cmd end, clean up any group trace flags, etc. here
=================
*/
void CmdEnd( const edict_t *player )
{
entvars_t *pev = (entvars_t *)&player->v;
CBasePlayer *pl = ( CBasePlayer *) CBasePlayer::Instance( pev );
if( !pl )
return;
if ( pl->pev->groupinfo != 0 )
{
UTIL_UnsetGroupTrace();
}
}
void ClientPrecache( void )
{
// Material System!!! move this in next versions
@ -1278,7 +1323,136 @@ const char *GetGameDescription( void )
COM_FreeFile( afile );
return text;
}
return "Half-Life";
return "Xash3D";
}
////////////////////////////////////////////////////////
// PAS and PVS routines for client messaging
//
/*
================
SetupVisibility
A client can have a separate "view entity" indicating that his/her view should depend on the origin of that
view entity. If that's the case, then pViewEntity will be non-NULL and will be used. Otherwise, the current
entity's origin is used. Either is offset by the view_ofs to get the eye position.
From the eye position, we set up the PAS and PVS to use for filtering network messages to the client. At this point, we could
override the actual PAS or PVS values, or use a different origin.
NOTE: Do not cache the values of pas and pvs, as they depend on reusable memory in the engine, they are only good for this one frame
================
*/
void SetupVisibility( edict_t *pViewEntity, edict_t *pClient, byte **pvs, byte **pas )
{
Vector org;
edict_t *pView = pClient;
// Find the client's PVS
if ( pViewEntity )
{
pView = pViewEntity;
}
CBasePlayer *pPlayer = (CBasePlayer *)CBaseEntity::Instance( pClient );
if (pPlayer && pPlayer->viewFlags & 1)
{
CBaseEntity *pViewEnt = pPlayer->pViewEnt;
if(pPlayer->pViewEnt->edict())pView = pViewEnt->edict();
}
if ( pClient->v.flags & FL_PROXY )
{
*pvs = NULL; // the spectator proxy sees
*pas = NULL; // and hears everything
return;
}
org = pView->v.origin + pView->v.view_ofs;
if ( pView->v.flags & FL_DUCKING )
{
org = org + ( VEC_HULL_MIN - VEC_DUCK_HULL_MIN );
}
*pvs = ENGINE_SET_PVS ( (float *)&org, false );
*pas = ENGINE_SET_PHS ( (float *)&org, false );
}
/*
AddToFullPack
Return 1 if the entity state has been filled in for the ent and the entity will be propagated to the client, 0 otherwise
state is the server maintained copy of the state info that is transmitted to the client
a MOD could alter values copied into state to send the "host" a different look for a particular entity update, etc.
e and ent are the entity that is being added to the update, if 1 is returned
host is the player's edict of the player whom we are sending the update to
player is 1 if the ent/e is a player and 0 otherwise
pSet is either the PAS or PVS that we previous set up. We can use it to ask the engine to filter the entity against the PAS or PVS.
we could also use the pas/ pvs that we set in SetupVisibility, if we wanted to. Caching the value is valid in that case, but still only for the current frame
*/
int AddToFullPack( edict_t *pClient, edict_t *pEntity, int hostflags )
{
// Work In Progress: not used
#if 0
int i;
// don't send if flagged for NODRAW and it's not the host getting the message
if ( ( ent->v.effects == EF_NODRAW ) && ( ent != host ) ) return 0;
// Ignore ents without valid / visible models
if ( !ent->v.modelindex || !STRING( ent->v.model ) )
return 0;
// Don't send spectators to other players
if ( ( ent->v.flags & FL_SPECTATOR ) && ( ent != host ) )
{
return 0;
}
// Ignore if not the host and not touching a PVS/PAS leaf
// If pSet is NULL, then the test will always succeed and the entity will be added to the update
if ( ent != host )
{
if ( !ENGINE_CHECK_VISIBILITY( (const struct edict_s *)ent, pSet ) )
{
if ( !(ent->v.flags & FL_SKYENTITY) ) return 0;
}
}
// Don't send entity to local client if the client says it's predicting the entity itself.
if ( ent->v.flags & FL_SKIPLOCALHOST )
{
if ( ( hostflags & 1 ) && ( ent->v.owner == host ) )
return 0;
}
if ( host->v.groupinfo )
{
UTIL_SetGroupTrace( host->v.groupinfo, GROUP_OP_AND );
// Should always be set, of course
if ( ent->v.groupinfo )
{
if ( g_groupop == GROUP_OP_AND )
{
if ( !(ent->v.groupinfo & host->v.groupinfo ) )
return 0;
}
else if ( g_groupop == GROUP_OP_NAND )
{
if ( ent->v.groupinfo & host->v.groupinfo )
return 0;
}
}
UTIL_UnsetGroupTrace();
}
#endif
return 1;
}
//=======================================================================

View File

@ -42,21 +42,11 @@ extern void SpectatorDisconnect ( edict_t *pEntity );
extern void SpectatorThink ( edict_t *pEntity );
extern void SetupVisibility( edict_t *pViewEntity, edict_t *pClient, unsigned char **pvs, unsigned char **pas );
extern void UpdateClientData ( const struct edict_s *ent, int sendweapons, struct clientdata_s *cd );
extern int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet );
extern void CreateBaseline( int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec3_t player_mins, vec3_t player_maxs );
extern void RegisterEncoders( void );
extern int AddToFullPack( edict_t *pClient, edict_t *pEntity, int hostflags );
extern int GetWeaponData( struct edict_s *player, struct weapon_data_s *info );
extern void CmdStart( const edict_t *player, const struct usercmd_s *cmd, unsigned int random_seed );
extern void CmdStart( const edict_t *player, const usercmd_t *cmd, unsigned int random_seed );
extern void CmdEnd ( const edict_t *player );
extern int ConnectionlessPacket( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size );
extern int GetHullBounds( int hullnumber, float *mins, float *maxs );
extern void CreateInstancedBaselines ( void );
extern int InconsistentFile( const edict_t *player, const char *filename, char *disconnect_message );
extern int AllowLagCompensation( void );
extern int g_serveractive;
// messages affect only player

View File

@ -77,10 +77,18 @@ static DLL_FUNCTIONS gFunctionTable =
PM_Move, // pfnPM_Move
PM_Init, // pfnPM_Init
PM_FindTextureType, // pfnPM_FindTextureType
SetupVisibility, // pfnSetupVisibility
DispatchFrame, // pfnPhysicsEntity
AddToFullPack, // pfnAddtoFullPack
EndFrame, // pfnEndFrame
ShouldCollide, // pfnShouldCollide
UpdateEntityState, // pfnUpdateEntityState
OnFreeEntPrivateData, // pfnOnFreeEntPrivateData
CmdStart, // pfnCmdStart
CmdEnd, // pfnCmdEnd
GameDLLShutdown, // pfnGameShutdown
};

View File

@ -14,7 +14,6 @@
****/
#ifndef ENGINECALLBACK_H
#define ENGINECALLBACK_H
#pragma once
// Must be provided by user of this code
extern enginefuncs_t g_engfuncs;
@ -60,9 +59,10 @@ extern enginefuncs_t g_engfuncs;
#define LIGHT_STYLE (*g_engfuncs.pfnLightStyle)
#define DECAL_INDEX (*g_engfuncs.pfnDecalIndex)
#define POINT_CONTENTS (*g_engfuncs.pfnPointContents)
#define CRC_INIT (*g_engfuncs.pfnCRC_Init)
#define CRC_PROCESS_BUFFER (*g_engfuncs.pfnCRC_ProcessBuffer)
#define CRC_FINAL (*g_engfuncs.pfnCRC_Final)
#define CRC32_INIT (*g_engfuncs.pfnCRC_Init)
#define CRC32_PROCESS_BUFFER (*g_engfuncs.pfnCRC_ProcessBuffer)
#define CRC32_PROCESS_BYTE (*g_engfuncs.pfnCRC32_ProcessByte)
#define CRC32_FINAL (*g_engfuncs.pfnCRC_Final)
#define RANDOM_LONG (*g_engfuncs.pfnRandomLong)
#define RANDOM_FLOAT (*g_engfuncs.pfnRandomFloat)
#define CLASSIFY_EDICT (*g_engfuncs.pfnClassifyEdict)
@ -80,10 +80,17 @@ inline void MESSAGE_BEGIN( int msg_dest, int msg_type, const float *pOrigin = NU
#define WRITE_LONG (*g_engfuncs.pfnWriteLong)
#define WRITE_ANGLE (*g_engfuncs.pfnWriteAngle)
#define WRITE_COORD (*g_engfuncs.pfnWriteCoord)
#define WRITE_FLOAT (*g_engfuncs.pfnWriteFloat)
inline void WRITE_FLOAT( float flValue )
{
union { float f; int l; } dat;
dat.f = flValue;
WRITE_LONG( dat.l );
}
#define WRITE_STRING (*g_engfuncs.pfnWriteString)
#define WRITE_ENTITY (*g_engfuncs.pfnWriteEntity)
#define WRITE_DIR( dir ) WRITE_SHORT(DirToBits( dir ))
#define WRITE_DIR( dir ) WRITE_BYTE(DirToBits( dir ))
#define CVAR_REGISTER (*g_engfuncs.pfnCVarRegister)
#define CVAR_GET_FLOAT (*g_engfuncs.pfnCVarGetFloat)
#define CVAR_GET_STRING (*g_engfuncs.pfnCVarGetString)
@ -104,7 +111,7 @@ inline void *GET_PRIVATE( edict_t *pent )
// leave macros as legacy
#define ALLOC_STRING (*g_engfuncs.pfnAllocString)
#define MAKE_STRING (*g_engfuncs.pfnAllocString)
#define STRING (*g_engfuncs.pfnGetString)
#define STRING (*g_engfuncs.pfnSzFromIndex)
#define FREE_PRIVATE (*g_engfuncs.pfnFreeEntPrivateData)
#define FIND_ENTITY_BY_STRING (*g_engfuncs.pfnFindEntityByString)
@ -118,6 +125,7 @@ inline void *GET_PRIVATE( edict_t *pent )
#define FUNCTION_FROM_NAME (*g_engfuncs.pfnFunctionFromName)
#define NAME_FOR_FUNCTION (*g_engfuncs.pfnNameForFunction)
#define TRACE_TEXTURE (*g_engfuncs.pfnTraceTexture)
#define CLIENT_PRINTF (*g_engfuncs.pfnClientPrintf)
#define CMD_ARGS (*g_engfuncs.pfnCmd_Args)
#define CMD_ARGC (*g_engfuncs.pfnCmd_Argc)
#define CMD_ARGV (*g_engfuncs.pfnCmd_Argv)
@ -133,8 +141,14 @@ inline void *GET_PRIVATE( edict_t *pent )
#define ENGINE_CANSKIP (*g_engfuncs.pfnCanSkipPlayer)
#define PRECACHE_EVENT (*g_engfuncs.pfnPrecacheEvent)
#define PLAYBACK_EVENT_FULL (*g_engfuncs.pfnPlaybackEvent)
#define ENGINE_SET_PVS (*g_engfuncs.pfnSetFatPVS)
#define ENGINE_SET_PHS (*g_engfuncs.pfnSetFatPHS)
#define ENGINE_CHECK_PVS (*g_engfuncs.pfnCheckVisibility)
#define IS_MAP_VALID (*g_engfuncs.pfnIsMapValid)
#define IS_DEDICATED_SERVER (*g_engfuncs.pfnIsDedicatedServer)
#define HOST_ERROR (*g_engfuncs.pfnHostError)
#define ENGINE_GETPHYSINFO (*g_engfuncs.pfnGetPhysicsInfoString)
#define ENGINE_SETGROUPMASK (*g_engfuncs.pfnSetGroupMask)
#define PLAYER_CNX_STATS (*g_engfuncs.pfnGetPlayerStats)
#endif //ENGINECALLBACK_H
#endif //ENGINECALLBACK_H

View File

@ -1399,7 +1399,7 @@ float UTIL_AngleDistance( float next, float cur )
return delta;
}
BOOL UTIL_EntIsVisible( entvars_t* pev, entvars_t* pevTarget)
BOOL UTIL_EntIsVisible( entvars_t* pev, entvars_t* pevTarget )
{
Vector vecSpot1 = pev->origin + pev->view_ofs;
Vector vecSpot2 = pevTarget->origin + pevTarget->view_ofs;
@ -1602,6 +1602,46 @@ float UTIL_SharedRandomFloat( unsigned int seed, float low, float high )
}
}
int g_groupmask = 0;
int g_groupop = 0;
// Normal overrides
void UTIL_SetGroupTrace( int groupmask, int op )
{
g_groupmask = groupmask;
g_groupop = op;
ENGINE_SETGROUPMASK( g_groupmask, g_groupop );
}
void UTIL_UnsetGroupTrace( void )
{
g_groupmask = 0;
g_groupop = 0;
ENGINE_SETGROUPMASK( 0, 0 );
}
// Smart version, it'll clean itself up when it pops off stack
UTIL_GroupTrace::UTIL_GroupTrace( int groupmask, int op )
{
m_oldgroupmask = g_groupmask;
m_oldgroupop = g_groupop;
g_groupmask = groupmask;
g_groupop = op;
ENGINE_SETGROUPMASK( g_groupmask, g_groupop );
}
UTIL_GroupTrace::~UTIL_GroupTrace( void )
{
g_groupmask = m_oldgroupmask;
g_groupop = m_oldgroupop;
ENGINE_SETGROUPMASK( g_groupmask, g_groupop );
}
#ifdef DEBUG
edict_t *DBG_EntOfVars( const entvars_t *pev )
{
@ -1706,16 +1746,11 @@ Vector UTIL_AxisRotationToVec( const Vector &vecAxis, float flDegs )
return Vector(rgflVecOut);
}
// float UTIL_MoveToOrigin( edict_t *pent, const Vector vecGoal, float flDist, int iMoveType )
void UTIL_MoveToOrigin( edict_t *pent, const Vector &vecGoal, float flDist, int iMoveType )
{
float rgfl[3];
vecGoal.CopyToArray(rgfl);
// return MOVE_TO_ORIGIN ( pent, rgfl, flDist, iMoveType );
MOVE_TO_ORIGIN ( pent, rgfl, flDist, iMoveType );
MOVE_TO_ORIGIN( pent, vecGoal, flDist, iMoveType );
}
int UTIL_EntitiesInBox( CBaseEntity **pList, int listMax, const Vector &mins, const Vector &maxs, int flagMask )
{
edict_t *pEdict = g_engfuncs.pfnPEntityOfEntIndex( 1 );
@ -2326,30 +2361,7 @@ void UTIL_TraceLine( const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTE
void UTIL_TraceHull( const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, int hullNumber, edict_t *pentIgnore, TraceResult *ptr )
{
Vector mins, maxs;
switch( hullNumber )
{
case human_hull:
mins = Vector( -16, -16, 0 );
maxs = Vector( 16, 16, 72 );
break;
case large_hull:
mins = Vector( -32, -32,-32 );
maxs = Vector( 32, 32, 32 );
break;
case head_hull: // ducked
mins = Vector( -16, -16,-18 );
maxs = Vector( 16, 16, 18 );
break;
case point_hull:
default:
mins = g_vecZero;
maxs = g_vecZero;
break;
}
TRACE_HULL( vecStart, mins, maxs, vecEnd, (igmon == ignore_monsters ? TRUE : FALSE), pentIgnore, ptr );
TRACE_HULL( vecStart, vecEnd, (igmon == ignore_monsters ? TRUE : FALSE), hullNumber, pentIgnore, ptr );
}
void UTIL_TraceModel( const Vector &vecStart, const Vector &vecEnd, int hullNumber, edict_t *pentModel, TraceResult *ptr )
@ -2749,7 +2761,7 @@ void UTIL_Ricochet( const Vector &position, float scale )
WRITE_COORD( position.x );
WRITE_COORD( position.y );
WRITE_COORD( position.z );
WRITE_BYTE( (int)(scale*10) );
WRITE_BYTE( (int)( scale * 10 ));
MESSAGE_END();
}

View File

@ -216,14 +216,6 @@ inline BOOL FStringNull( Vector vString ) { return vString == Vector( 0, 0, 0);
#define cchMapNameMost 32
typedef enum
{
point_hull = 0,
human_hull = 1,
large_hull = 2,
head_hull = 3
};
// Dot products for view cone checking
#define VIEW_FIELD_FULL (float)-1.0 // +-180 degrees
#define VIEW_FIELD_WIDE (float)-0.7 // +-135 degrees 0.1 // +-85 degrees, used for full FOV checks
@ -370,8 +362,11 @@ extern void UTIL_ScreenFade( const Vector &color, float fadeTime, float fadeHold
extern void UTIL_SetFog ( Vector color, int iFadeTime, int iStartDist, int iEndDist, int playernum = 1 );
extern void UTIL_SetFogAll ( Vector color, int iFadeTime, int iStartDist, int iEndDist );
typedef enum { ignore_monsters=1, dont_ignore_monsters=0, missile=2 } IGNORE_MONSTERS;
typedef enum { ignore_glass=1, dont_ignore_glass=0 } IGNORE_GLASS;
// hull enumerator
typedef enum { point_hull = 0, human_hull = 1, large_hull = 2, head_hull = 3 };
typedef enum { ignore_monsters = 1, dont_ignore_monsters = 0, missile = 2 } IGNORE_MONSTERS;
typedef enum { ignore_glass = 1, dont_ignore_glass = 0 } IGNORE_GLASS;
extern void UTIL_TraceLine (const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, edict_t *pentIgnore, TraceResult *ptr);
extern void UTIL_TraceLine (const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, IGNORE_GLASS ignoreGlass, edict_t *pentIgnore, TraceResult *ptr);
extern void UTIL_TraceHull (const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, int hullNumber, edict_t *pentIgnore, TraceResult *ptr);
@ -651,6 +646,31 @@ void EMIT_GROUPNAME_SUIT(edict_t *entity, const char *groupname);
#define RANDOM_SOUND_ARRAY( array ) (array) [ RANDOM_LONG(0,ARRAYSIZE( (array) )-1) ]
#define PLAYBACK_EVENT( flags, who, index ) PLAYBACK_EVENT_FULL( flags, who, index, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, 0, 0 );
#define PLAYBACK_EVENT_DELAY( flags, who, index, delay ) PLAYBACK_EVENT_FULL( flags, who, index, delay, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, 0, 0, 0 );
#define GROUP_OP_AND 0
#define GROUP_OP_NAND 1
extern int g_groupmask;
extern int g_groupop;
class UTIL_GroupTrace
{
public:
UTIL_GroupTrace( int groupmask, int op );
~UTIL_GroupTrace( void );
private:
int m_oldgroupmask, m_oldgroupop;
};
void UTIL_SetGroupTrace( int groupmask, int op );
void UTIL_UnsetGroupTrace( void );
int UTIL_SharedRandomLong( unsigned int seed, int low, int high );
float UTIL_SharedRandomFloat( unsigned int seed, float low, float high );
int UTIL_SharedRandomLong( unsigned int seed, int low, int high );
float UTIL_SharedRandomFloat( unsigned int seed, float low, float high );

View File

@ -664,10 +664,10 @@ void CBarney::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir
}
break;
case 10:
if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_CLUB))
if ( bitsDamageType & ( DMG_BULLET|DMG_SLASH|DMG_CLUB ))
{
flDamage -= 20;
if (flDamage <= 0)
if( flDamage <= 0.0f )
{
UTIL_Ricochet( ptr->vecEndPos, 1.0 );
flDamage = 0.01;

View File

@ -2116,10 +2116,6 @@ void CBaseMonster :: StartMonster ( void )
{
Msg("%s \"%s\" stuck in wall--level design error\n", STRING(pev->classname), STRING(pev->targetname));
pev->effects = EF_BRIGHTFIELD;
// HACKHACK: this is for pre-alpha version
// remove stucked zombies on a start.bsp
UTIL_Remove( this );
}
}
else
@ -2932,9 +2928,9 @@ void CBaseMonster::ReportAIState( void )
ALERT( level, "No Schedule, " );
if ( m_hEnemy != NULL )
ALERT( level, "\nEnemy is %s", STRING(m_hEnemy->pev->classname) );
ALERT( level, "\nEnemy is %s, ", STRING(m_hEnemy->pev->classname) );
else
ALERT( level, "No enemy" );
ALERT( level, "No enemy, " );
if ( IsMoving() )
{
@ -3494,7 +3490,7 @@ void CBaseMonster :: SetState ( MONSTERSTATE State )
void CBaseMonster :: RunAI ( void )
{
// to test model's eye height
//UTIL_ParticleEffect ( pev->origin + pev->view_ofs, g_vecZero, 255, 10 );
// UTIL_ParticleEffect ( pev->origin + pev->view_ofs, g_vecZero, 255, 10 );
// IDLE sound permitted in ALERT state is because monsters were silent in ALERT state. Only play IDLE sound in IDLE state
// once we have sounds for that state.

View File

@ -62,17 +62,6 @@
#define SF_MONSTER_TURRET_STARTINACTIVE 64
#define SF_MONSTER_WAIT_UNTIL_PROVOKED 64 // don't attack the player unless provoked
// MoveToOrigin stuff
#define MOVE_START_TURN_DIST 64 // when this far away from moveGoal, start turning to face next goal
#define MOVE_STUCK_DIST 32 // if a monster can't step this far, it is stuck.
// MoveToOrigin stuff
#define MOVE_NORMAL 0// normal move in the direction monster is facing
#define MOVE_STRAFE 1// moves in direction specified, no matter which way monster is facing
// spawn flags 256 and above are already taken by the engine
extern void UTIL_MoveToOrigin( edict_t* pent, const Vector &vecGoal, float flDist, int iMoveType );

View File

@ -775,14 +775,14 @@ int CGraph :: FindShortestPath ( int *piPath, int iStart, int iDest, int iHull,
return iNumPathNodes;
}
inline USHORT Hash( void *p, int len )
inline ULONG Hash( void *p, int len )
{
word usCrc;
CRC32_t ulCrc;
CRC_INIT( &usCrc );
CRC_PROCESS_BUFFER( &usCrc, p, len );
CRC32_INIT( &ulCrc );
CRC32_PROCESS_BUFFER( &ulCrc, p, len );
return CRC_FINAL( usCrc );
return CRC32_FINAL( ulCrc );
}
void inline CalcBounds(int &Lower, int &Upper, int Goal, int Best)
@ -2659,13 +2659,14 @@ void CGraph::HashInsert(int iSrcNode, int iDestNode, int iKey)
np.iSrc = iSrcNode;
np.iDest = iDestNode;
word usHash;
CRC_INIT( &usHash );
CRC_PROCESS_BUFFER( &usHash, &np, sizeof( np ));
usHash = CRC_FINAL( usHash );
CRC32_t dwHash;
int di = m_HashPrimes[usHash & 15];
int i = (usHash>>4) % m_nHashLinks;
CRC32_INIT( &dwHash );
CRC32_PROCESS_BUFFER( &dwHash, &np, sizeof( np ));
dwHash = CRC32_FINAL( dwHash );
int di = m_HashPrimes[dwHash & 15];
int i = (dwHash>>4) % m_nHashLinks;
while( m_pHashLinks[i] != ENTRY_STATE_EMPTY )
{
@ -2683,13 +2684,13 @@ void CGraph::HashSearch( int iSrcNode, int iDestNode, int &iKey )
np.iSrc = iSrcNode;
np.iDest = iDestNode;
word usHash;
CRC_INIT( &usHash );
CRC_PROCESS_BUFFER( &usHash, &np, sizeof( np ));
usHash = CRC_FINAL( usHash );
CRC32_t dwHash;
CRC32_INIT( &dwHash );
CRC32_PROCESS_BUFFER( &dwHash, &np, sizeof( np ));
dwHash = CRC32_FINAL( dwHash );
int di = m_HashPrimes[usHash & 15];
int i = (usHash >> 4) % m_nHashLinks;
int di = m_HashPrimes[dwHash & 15];
int i = (dwHash >> 4) % m_nHashLinks;
while( m_pHashLinks[i] != ENTRY_STATE_EMPTY )
{

View File

@ -3372,7 +3372,7 @@ void CBasePlayer::CheatImpulseCommands( int iImpulse )
edict_t *pWorld = g_engfuncs.pfnPEntityOfEntIndex( 0 );
Vector start = pev->origin + pev->view_ofs;
Vector end = start + gpGlobals->v_forward * 1024;
UTIL_TraceLine( start, end, ignore_monsters, edict(), &tr );
UTIL_TraceLine( start, end, dont_ignore_monsters, edict(), &tr );
if ( tr.pHit ) pWorld = tr.pHit;
const char *pTextureName = TRACE_TEXTURE( pWorld, start, end );
pEntity = UTIL_FindEntityForward( this );
@ -3382,7 +3382,7 @@ void CBasePlayer::CheatImpulseCommands( int iImpulse )
if ( pMonster ) pMonster->ReportAIState();
else pEntity->Use( this, this, USE_SHOWINFO, 0 );
}
else if ( pTextureName ) ALERT( at_console, "Texture: %s\n", pTextureName );
if ( pTextureName ) ALERT( at_console, "Texture: %s\n", pTextureName );
}
break;

View File

@ -460,27 +460,29 @@ void CBaseTurret::Ping( void )
}
void CBaseTurret::EyeOn( )
void CBaseTurret :: EyeOn( void )
{
if (m_pEyeGlow)
if( m_pEyeGlow )
{
if (m_eyeBrightness != 255)
if( m_eyeBrightness != 255 )
{
m_eyeBrightness = 255;
pev->skin = 1; // enable glow
}
m_pEyeGlow->SetBrightness( m_eyeBrightness );
}
}
void CBaseTurret::EyeOff( )
void CBaseTurret :: EyeOff( void )
{
if (m_pEyeGlow)
if( m_pEyeGlow )
{
if (m_eyeBrightness > 0)
if( m_eyeBrightness > 0 )
{
m_eyeBrightness = max( 0, m_eyeBrightness - 30 );
m_pEyeGlow->SetBrightness( m_eyeBrightness );
if( m_eyeBrightness < 50 ) pev->skin = 0;
}
}
}

View File

@ -1,101 +0,0 @@
<html>
<body>
<pre>
<h1>Build Log</h1>
<h3>
--------------------Configuration: server - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP104E.tmp" with contents
[
/nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "./" /I "ents" /I "game" /I "global" /I "monsters" /I "../common" /I "../pm_shared" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"..\temp\server\!debug/" /Fo"..\temp\server\!debug/" /Fd"..\temp\server\!debug/" /FD /c
"D:\Xash3D\src_main\server\ents\baserockets.cpp"
]
Creating command line "cl.exe @"C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP104E.tmp""
Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP104F.tmp" with contents
[
msvcrtd.lib /nologo /subsystem:windows /dll /incremental:yes /pdb:"..\temp\server\!debug/server.pdb" /debug /machine:I386 /nodefaultlib:"libc.lib" /def:".\server.def" /out:"..\temp\server\!debug/server.dll" /implib:"..\temp\server\!debug/server.lib" /pdbtype:sept
"\Xash3D\src_main\temp\server\!debug\ai_sound.obj"
"\Xash3D\src_main\temp\server\!debug\animating.obj"
"\Xash3D\src_main\temp\server\!debug\animation.obj"
"\Xash3D\src_main\temp\server\!debug\apache.obj"
"\Xash3D\src_main\temp\server\!debug\barnacle.obj"
"\Xash3D\src_main\temp\server\!debug\barney.obj"
"\Xash3D\src_main\temp\server\!debug\basebrush.obj"
"\Xash3D\src_main\temp\server\!debug\baseentity.obj"
"\Xash3D\src_main\temp\server\!debug\basefunc.obj"
"\Xash3D\src_main\temp\server\!debug\basefx.obj"
"\Xash3D\src_main\temp\server\!debug\baseinfo.obj"
"\Xash3D\src_main\temp\server\!debug\baseitem.obj"
"\Xash3D\src_main\temp\server\!debug\baselogic.obj"
"\Xash3D\src_main\temp\server\!debug\basemonster.obj"
"\Xash3D\src_main\temp\server\!debug\basemover.obj"
"\Xash3D\src_main\temp\server\!debug\baseother.obj"
"\Xash3D\src_main\temp\server\!debug\basepath.obj"
"\Xash3D\src_main\temp\server\!debug\basephys.obj"
"\Xash3D\src_main\temp\server\!debug\baserockets.obj"
"\Xash3D\src_main\temp\server\!debug\basetank.obj"
"\Xash3D\src_main\temp\server\!debug\basetrigger.obj"
"\Xash3D\src_main\temp\server\!debug\baseutil.obj"
"\Xash3D\src_main\temp\server\!debug\baseweapon.obj"
"\Xash3D\src_main\temp\server\!debug\baseworld.obj"
"\Xash3D\src_main\temp\server\!debug\client.obj"
"\Xash3D\src_main\temp\server\!debug\combat.obj"
"\Xash3D\src_main\temp\server\!debug\decals.obj"
"\Xash3D\src_main\temp\server\!debug\defaultai.obj"
"\Xash3D\src_main\temp\server\!debug\dll_int.obj"
"\Xash3D\src_main\temp\server\!debug\flyingmonster.obj"
"\Xash3D\src_main\temp\server\!debug\game.obj"
"\Xash3D\src_main\temp\server\!debug\gamerules.obj"
"\Xash3D\src_main\temp\server\!debug\generic.obj"
"\Xash3D\src_main\temp\server\!debug\globals.obj"
"\Xash3D\src_main\temp\server\!debug\gman.obj"
"\Xash3D\src_main\temp\server\!debug\hassassin.obj"
"\Xash3D\src_main\temp\server\!debug\headcrab.obj"
"\Xash3D\src_main\temp\server\!debug\hgrunt.obj"
"\Xash3D\src_main\temp\server\!debug\leech.obj"
"\Xash3D\src_main\temp\server\!debug\lights.obj"
"\Xash3D\src_main\temp\server\!debug\multiplay_gamerules.obj"
"\Xash3D\src_main\temp\server\!debug\nodes.obj"
"\Xash3D\src_main\temp\server\!debug\osprey.obj"
"\Xash3D\src_main\temp\server\!debug\parent.obj"
"\Xash3D\src_main\temp\server\!debug\player.obj"
"\Xash3D\src_main\temp\server\!debug\pm_shared.obj"
"\Xash3D\src_main\temp\server\!debug\rat.obj"
"\Xash3D\src_main\temp\server\!debug\roach.obj"
"\Xash3D\src_main\temp\server\!debug\saverestore.obj"
"\Xash3D\src_main\temp\server\!debug\scientist.obj"
"\Xash3D\src_main\temp\server\!debug\scripted.obj"
"\Xash3D\src_main\temp\server\!debug\sfx.obj"
"\Xash3D\src_main\temp\server\!debug\singleplay_gamerules.obj"
"\Xash3D\src_main\temp\server\!debug\sound.obj"
"\Xash3D\src_main\temp\server\!debug\spectator.obj"
"\Xash3D\src_main\temp\server\!debug\squadmonster.obj"
"\Xash3D\src_main\temp\server\!debug\talkmonster.obj"
"\Xash3D\src_main\temp\server\!debug\teamplay_gamerules.obj"
"\Xash3D\src_main\temp\server\!debug\turret.obj"
"\Xash3D\src_main\temp\server\!debug\utils.obj"
"\Xash3D\src_main\temp\server\!debug\weapon_generic.obj"
"\Xash3D\src_main\temp\server\!debug\zombie.obj"
]
Creating command line "link.exe @"C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP104F.tmp""
Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP1050.bat" with contents
[
@echo off
copy \Xash3D\src_main\temp\server\!debug\server.dll "D:\Xash3D\bin\server.dll"
]
Creating command line ""C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP1050.bat""
Compiling...
baserockets.cpp
Linking...
<h3>Output Window</h3>
Performing Custom Build Step on \Xash3D\src_main\temp\server\!debug\server.dll
‘ª®¯¨à®¢ ­® ä ©«®¢: 1.
<h3>Results</h3>
server.dll - 0 error(s), 0 warning(s)
</pre>
</body>
</html>

View File

@ -6,11 +6,18 @@
#include "sound.h"
#include "s_stream.h"
// during registration it is possible to have more sounds
// than could actually be referenced during gameplay,
// because we don't want to free anything until we are
// sure we won't need it.
#define MAX_SFX 4096
static sfx_t s_knownSfx[MAX_SFX];
static int s_numSfx = 0;
int s_registration_sequence = 0;
bool s_registering = false;
#define MAX_SFX_HASH (MAX_SFX/4)
static sfx_t s_knownSfx[MAX_SFX];
static sfx_t *s_sfxHashList[MAX_SFX_HASH];
static int s_numSfx = 0;
bool s_registering = false;
int s_registration_sequence = 0;
typedef struct loadformat_s
{
@ -39,6 +46,8 @@ void S_SoundList_f( void )
if( sfx->loaded )
{
samples += sfx->samples;
if( sfx->loopstart >= 0 ) Msg( "L" );
else Msg( " " );
Msg( "%8i ", sfx->samples );
Msg( "%5i ", sfx->rate );
@ -562,33 +571,33 @@ S_FindSound
*/
sfx_t *S_FindSound( const char *name )
{
sfx_t *sfx;
int i;
sfx_t *sfx;
uint hash;
if( !name || !name[0] ) return NULL;
if( com.strlen(name) >= MAX_STRING )
if( com.strlen( name ) >= MAX_STRING )
{
MsgDev( D_ERROR, "S_FindSound: sound name too long: %s", name );
return NULL;
}
// see if already loaded
for( i = 0; i < s_numSfx; i++ )
{
sfx = &s_knownSfx[i];
if( !sfx->name[0] ) continue;
if( !com.strcmp( name, sfx->name ))
hash = Com_HashKey( name, MAX_SFX_HASH );
for( sfx = s_sfxHashList[hash]; sfx; sfx = sfx->hashNext )
{
if( !com.strcmp( sfx->name, name ))
{
// prolonge registration
sfx->registration_sequence = s_registration_sequence;
sfx->touchFrame = s_registration_sequence;
return sfx;
}
}
}
// find a free sfx slot spot
for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++)
{
if(!sfx->name[0]) break; // free spot
if( !sfx->name[0] ) break; // free spot
}
if( i == s_numSfx )
{
@ -601,13 +610,50 @@ sfx_t *S_FindSound( const char *name )
}
sfx = &s_knownSfx[i];
Mem_Set( sfx, 0, sizeof(*sfx));
Mem_Set( sfx, 0, sizeof( *sfx ));
com.strncpy( sfx->name, name, MAX_STRING );
sfx->registration_sequence = s_registration_sequence;
sfx->touchFrame = s_registration_sequence;
sfx->hashValue = Com_HashKey( sfx->name, MAX_SFX_HASH );
// link it in
sfx->hashNext = s_sfxHashList[sfx->hashValue];
s_sfxHashList[sfx->hashValue] = sfx;
return sfx;
}
/*
==================
S_FreeSound
==================
*/
static void S_FreeSound( sfx_t *sfx )
{
sfx_t *hashSfx;
sfx_t **prev;
if( !sfx || !sfx->name[0] ) return;
// de-link it from the hash tree
prev = &s_sfxHashList[sfx->hashValue];
while( 1 )
{
hashSfx = *prev;
if( !hashSfx )
break;
if( hashSfx == sfx )
{
*prev = hashSfx->hashNext;
break;
}
prev = &hashSfx->hashNext;
}
palDeleteBuffers( 1, &sfx->bufferNum );
Mem_Set( sfx, 0, sizeof( *sfx ));
}
/*
=====================
S_BeginRegistration
@ -633,12 +679,8 @@ void S_EndRegistration( void )
for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ )
{
if( !sfx->name[0] ) continue;
if( sfx->registration_sequence != s_registration_sequence )
{
// don't need this sound
palDeleteBuffers( 1, &sfx->bufferNum );
Mem_Set( sfx, 0, sizeof( sfx_t )); // free spot
}
if( sfx->touchFrame != s_registration_sequence )
S_FreeSound( sfx ); // don't need this sound
}
// load everything in
@ -653,6 +695,7 @@ void S_EndRegistration( void )
/*
=================
S_RegisterSound
=================
*/
sound_t S_RegisterSound( const char *name )
@ -665,7 +708,7 @@ sound_t S_RegisterSound( const char *name )
sfx = S_FindSound( name );
if( !sfx ) return -1;
sfx->registration_sequence = s_registration_sequence;
sfx->touchFrame = s_registration_sequence;
if( !s_registering ) S_LoadSound( sfx );
return sfx - s_knownSfx;
@ -695,13 +738,10 @@ void S_FreeSounds( void )
S_StopAllSounds();
// free all sounds
for (i = 0; i < s_numSfx; i++)
{
sfx = &s_knownSfx[i];
if( !sfx->loaded ) continue;
palDeleteBuffers(1, &sfx->bufferNum);
}
for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ )
S_FreeSound( sfx );
Mem_Set( s_knownSfx, 0, sizeof(s_knownSfx));
s_numSfx = 0;
Mem_Set( s_knownSfx, 0, sizeof( s_knownSfx ));
Mem_Set( s_sfxHashList, 0, sizeof( s_sfxHashList ));
}

View File

@ -1,16 +0,0 @@
<html>
<body>
<pre>
<h1>Build Log</h1>
<h3>
--------------------Configuration: snd_al - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
<h3>Results</h3>
snd_al.dll - 0 error(s), 0 warning(s)
</pre>
</body>
</html>

View File

@ -55,8 +55,10 @@ typedef struct sfx_s
uint format;
uint bufferNum;
int touchFrame;
bool default_sound;
int registration_sequence;
uint hashValue;
struct sfx_s *hashNext;
} sfx_t;
typedef struct

View File

@ -11,8 +11,10 @@
// because we don't want to free anything until we are
// sure we won't need it.
#define MAX_SFX 4096
#define MAX_SFX_HASH (MAX_SFX/4)
static sfx_t s_knownSfx[MAX_SFX];
static sfx_t *s_sfxHashList[MAX_SFX_HASH];
static int s_numSfx = 0;
bool s_registering = false;
int s_registration_sequence = 0;
@ -39,7 +41,7 @@ void S_SoundList_f( void )
for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ )
{
if( !sfx->registration_sequence )
if( !sfx->touchFrame )
continue;
sc = sfx->cache;
@ -478,9 +480,9 @@ sfx_t *S_FindSound( const char *name )
{
int i;
sfx_t *sfx;
uint hash;
if( !name || !name[0] ) return NULL;
if( com.strlen( name ) >= MAX_STRING )
{
MsgDev( D_ERROR, "S_FindSound: sound name too long: %s", name );
@ -488,14 +490,13 @@ sfx_t *S_FindSound( const char *name )
}
// see if already loaded
for( i = 0; i < s_numSfx; i++ )
hash = Com_HashKey( name, MAX_SFX_HASH );
for( sfx = s_sfxHashList[hash]; sfx; sfx = sfx->hashNext )
{
sfx = &s_knownSfx[i];
if( !com.strcmp( sfx->name, name ))
{
// prolonge registration
sfx->registration_sequence = s_registration_sequence;
sfx->touchFrame = s_registration_sequence;
return sfx;
}
}
@ -518,11 +519,48 @@ sfx_t *S_FindSound( const char *name )
sfx = &s_knownSfx[i];
Mem_Set( sfx, 0, sizeof( *sfx ));
com.strncpy( sfx->name, name, MAX_STRING );
sfx->registration_sequence = s_registration_sequence;
sfx->touchFrame = s_registration_sequence;
sfx->hashValue = Com_HashKey( sfx->name, MAX_SFX_HASH );
// link it in
sfx->hashNext = s_sfxHashList[sfx->hashValue];
s_sfxHashList[sfx->hashValue] = sfx;
return sfx;
}
/*
==================
S_FreeSound
==================
*/
static void S_FreeSound( sfx_t *sfx )
{
sfx_t *hashSfx;
sfx_t **prev;
if( !sfx || !sfx->name[0] ) return;
// de-link it from the hash tree
prev = &s_sfxHashList[sfx->hashValue];
while( 1 )
{
hashSfx = *prev;
if( !hashSfx )
break;
if( hashSfx == sfx )
{
*prev = hashSfx->hashNext;
break;
}
prev = &hashSfx->hashNext;
}
if( sfx->cache ) Mem_Free( sfx->cache );
Mem_Set( sfx, 0, sizeof( *sfx ));
}
/*
=====================
S_BeginRegistration
@ -550,12 +588,8 @@ void S_EndRegistration( void )
for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ )
{
if( !sfx->name[0] ) continue;
if( sfx->registration_sequence != s_registration_sequence )
{
// don't need this sound
if( sfx->cache ) Mem_Free( sfx->cache );
Mem_Set( sfx, 0, sizeof( *sfx ));
}
if( sfx->touchFrame != s_registration_sequence )
S_FreeSound( sfx ); // don't need this sound
}
// load everything in
@ -583,7 +617,7 @@ sound_t S_RegisterSound( const char *name )
sfx = S_FindSound( name );
if( !sfx ) return -1;
sfx->registration_sequence = s_registration_sequence;
sfx->touchFrame = s_registration_sequence;
if( !s_registering ) S_LoadSound( sfx );
return sfx - s_knownSfx;
@ -614,12 +648,9 @@ void S_FreeSounds( void )
// free all sounds
for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ )
{
if( !sfx->name[0] ) continue;
if( sfx->cache ) Mem_Free( sfx->cache );
Mem_Set( sfx, 0, sizeof( *sfx ));
}
S_FreeSound( sfx );
Mem_Set( s_knownSfx, 0, sizeof(s_knownSfx));
s_numSfx = 0;
Mem_Set( s_knownSfx, 0, sizeof( s_knownSfx ));
Mem_Set( s_sfxHashList, 0, sizeof( s_sfxHashList ));
}

View File

@ -1,16 +0,0 @@
<html>
<body>
<pre>
<h1>Build Log</h1>
<h3>
--------------------Configuration: snd_dx - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
<h3>Results</h3>
snd_dx.dll - 0 error(s), 0 warning(s)
</pre>
</body>
</html>

View File

@ -38,8 +38,10 @@ typedef struct sfx_s
string name;
sfxcache_t *cache;
int registration_sequence;
int touchFrame;
bool default_sound;
uint hashValue;
struct sfx_s *hashNext;
} sfx_t;
// a playsound_t will be generated by each call to S_StartSound,

View File

@ -162,11 +162,22 @@ Beta 13.12.09
135. implement dsp, lipsync and vox
136. re-vision uimenu
137. complete rewriting physic.dll OK
138. implement hashtable for loaded sounds
138. implement hashtable for loaded sounds OK
139. finalize client API's
140. net_msg is buggly!!!! OK
141. get physic code from Lazarus
142. completely match cl\sv iface with HL1
142. finalize CL_Move and CL_LinkEdict
143. implement pmove OK
144. usercmd sends right OK
145. gl_invalid_value mirrors bug OK
146. implement RoQ back OK
147. implement studio trace OK
148. implement pfnGetEntityIllum
149. implement pfnEmitAmbientSound
150. implement pfnTraceSphere
151. implement pfnFadeClientVolume
152. implement ÑRC32 OK
153. implement physinfo strings OK
154. fix downloading issues OK
155. implement pfnPlaybackEvent
156. allowing to use russian letters

View File

@ -1,428 +0,0 @@
/*
Copyright (C) 2002-2003 Victor Luchits
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "r_local.h"
#include "cin.h"
#include "mathlib.h"
#include "byteorder.h"
static short snd_sqr_arr[256];
/*
==================
RoQ_Init
==================
*/
void RoQ_Init( void )
{
int i;
for( i = 0; i < 128; i++ )
{
snd_sqr_arr[i] = i * i;
snd_sqr_arr[i + 128] = -(i * i);
}
}
/*
==================
RoQ_ReadChunk
==================
*/
void RoQ_ReadChunk( cinematics_t *cin )
{
roq_chunk_t *chunk = &cin->chunk;
FS_Read( cin->file, &chunk->id, sizeof(short));
FS_Read( cin->file, &chunk->size, sizeof(int));
FS_Read( cin->file, &chunk->argument, sizeof( short ));
chunk->id = LittleShort( chunk->id );
chunk->size = LittleLong( chunk->size );
chunk->argument = LittleShort( chunk->argument );
}
/*
==================
RoQ_SkipBlock
==================
*/
static _inline void RoQ_SkipBlock( cinematics_t *cin, int size )
{
FS_Seek( cin->file, size, SEEK_CUR );
}
/*
==================
RoQ_SkipChunk
==================
*/
void RoQ_SkipChunk( cinematics_t *cin )
{
RoQ_SkipBlock( cin, cin->chunk.size );
}
/*
==================
RoQ_ReadInfo
==================
*/
void RoQ_ReadInfo( cinematics_t *cin )
{
short t[4];
FS_Read( cin->file, t, sizeof( short ) * 4 );
if( cin->width != LittleShort( t[0] ) || cin->height != LittleShort( t[1] ))
{
cin->width = LittleShort( t[0] );
cin->height = LittleShort( t[1] );
if( cin->vid_buffer )
Mem_Free( cin->vid_buffer );
// default to 255 for alpha
if( cin->mempool )
cin->vid_buffer = Mem_Alloc( cin->mempool, cin->width * cin->height * 4 * 2 );
else cin->vid_buffer = Mem_Alloc( r_temppool, cin->width * cin->height * 4 * 2 );
Mem_Set( cin->vid_buffer, 0xFF, cin->width * cin->height * 4 * 2 );
cin->vid_pic[0] = cin->vid_buffer;
cin->vid_pic[1] = cin->vid_buffer + cin->width * cin->height * 4;
}
}
/*
==================
RoQ_ReadCodebook
==================
*/
void RoQ_ReadCodebook( cinematics_t *cin )
{
int nv1, nv2;
roq_chunk_t *chunk = &cin->chunk;
nv1 = (chunk->argument >> 8) & 0xFF;
if( !nv1 )
nv1 = 256;
nv2 = chunk->argument & 0xFF;
if( !nv2 && (nv1 * 6 < chunk->size) )
nv2 = 256;
FS_Read( cin->file, cin->cells, sizeof(roq_cell_t)*nv1 );
FS_Read( cin->file, cin->qcells, sizeof(roq_qcell_t)*nv2 );
}
/*
==================
RoQ_ApplyVector2x2
==================
*/
static void RoQ_DecodeBlock( byte *dst0, byte *dst1, const byte *src0, const byte *src1, float u, float v )
{
int c[3];
// convert YCbCr to RGB
VectorSet( c, 1.402f * v, -0.34414f * u - 0.71414f * v, 1.772f * u );
// 1st pixel
dst0[0] = bound( 0, c[0] + src0[0], 255 );
dst0[1] = bound( 0, c[1] + src0[0], 255 );
dst0[2] = bound( 0, c[2] + src0[0], 255 );
// 2nd pixel
dst0[4] = bound( 0, c[0] + src0[1], 255 );
dst0[5] = bound( 0, c[1] + src0[1], 255 );
dst0[6] = bound( 0, c[2] + src0[1], 255 );
// 3rd pixel
dst1[0] = bound( 0, c[0] + src1[0], 255 );
dst1[1] = bound( 0, c[1] + src1[0], 255 );
dst1[2] = bound( 0, c[2] + src1[0], 255 );
// 4th pixel
dst1[4] = bound( 0, c[0] + src1[1], 255 );
dst1[5] = bound( 0, c[1] + src1[1], 255 );
dst1[6] = bound( 0, c[2] + src1[1], 255 );
}
/*
==================
RoQ_ApplyVector2x2
==================
*/
static void RoQ_ApplyVector2x2( cinematics_t *cin, int x, int y, const roq_cell_t *cell )
{
byte *dst0, *dst1;
dst0 = cin->vid_pic[0] + (y * cin->width + x) * 4;
dst1 = dst0 + cin->width * 4;
RoQ_DecodeBlock( dst0, dst1, cell->y, cell->y+2, (float)((int)cell->u-128), (float)((int)cell->v-128) );
}
/*
==================
RoQ_ApplyVector4x4
==================
*/
static void RoQ_ApplyVector4x4( cinematics_t *cin, int x, int y, const roq_cell_t *cell )
{
byte *dst0, *dst1;
byte p[4];
float u, v;
u = (float)((int)cell->u - 128);
v = (float)((int)cell->v - 128);
p[0] = p[1] = cell->y[0];
p[2] = p[3] = cell->y[1];
dst0 = cin->vid_pic[0] + (y * cin->width + x) * 4; dst1 = dst0 + cin->width * 4;
RoQ_DecodeBlock( dst0, dst0+8, p, p+2, u, v );
RoQ_DecodeBlock( dst1, dst1+8, p, p+2, u, v );
p[0] = p[1] = cell->y[2];
p[2] = p[3] = cell->y[3];
dst0 += cin->width * 4 * 2; dst1 += cin->width * 4 * 2;
RoQ_DecodeBlock( dst0, dst0+8, p, p+2, u, v );
RoQ_DecodeBlock( dst1, dst1+8, p, p+2, u, v );
}
/*
==================
RoQ_ApplyMotion4x4
==================
*/
static void RoQ_ApplyMotion4x4( cinematics_t *cin, int x, int y, byte mv, char mean_x, char mean_y )
{
int x0, y0;
byte *src, *dst;
// calc source coords
x0 = x + 8 - (mv >> 4) - mean_x;
y0 = y + 8 - (mv & 0xF) - mean_y;
src = cin->vid_pic[1] + (y0 * cin->width + x0) * 4;
dst = cin->vid_pic[0] + (y * cin->width + x) * 4;
for( y = 0; y < 4; y++, src += cin->width * 4, dst += cin->width * 4 )
Mem_Copy( dst, src, 4 * 4 );
}
/*
==================
RoQ_ApplyMotion8x8
==================
*/
static void RoQ_ApplyMotion8x8( cinematics_t *cin, int x, int y, byte mv, char mean_x, char mean_y )
{
int x0, y0;
byte *src, *dst;
// calc source coords
x0 = x + 8 - (mv >> 4) - mean_x;
y0 = y + 8 - (mv & 0xF) - mean_y;
src = cin->vid_pic[1] + (y0 * cin->width + x0) * 4;
dst = cin->vid_pic[0] + (y * cin->width + x) * 4;
for( y = 0; y < 8; y++, src += cin->width * 4, dst += cin->width * 4 )
Mem_Copy( dst, src, 8 * 4 );
}
/*
==================
RoQ_ReadVideo
==================
*/
#define RoQ_READ_BLOCK 0x4000
byte *RoQ_ReadVideo( cinematics_t *cin )
{
roq_chunk_t *chunk = &cin->chunk;
int i, vqflg, vqflg_pos, vqid;
int xpos, ypos, x, y, xp, yp;
byte c, *tp;
roq_qcell_t *qcell;
byte raw[RoQ_READ_BLOCK];
unsigned remaining, bpos, read;
vqflg = 0;
vqflg_pos = -1;
xpos = ypos = 0;
#define RoQ_ReadRaw() read = min( sizeof( raw ), remaining ); remaining -= read; FS_Read( cin->file, raw, read );
#define RoQ_ReadByte(x) if( bpos >= read ) { RoQ_ReadRaw (); bpos = 0; } (x) = raw[bpos++];
#define RoQ_ReadShort(x) if( bpos+1 == read ) { c = raw[bpos]; RoQ_ReadRaw (); (x)=(raw[0] << 8)|c; bpos=1; } \
else { if( bpos+1 > read ) { RoQ_ReadRaw (); bpos = 0; } (x)=(raw[bpos+1] << 8)|raw[bpos]; bpos+=2; }
#define RoQ_ReadFlag() if( vqflg_pos < 0 ) { RoQ_ReadShort( vqflg ); vqflg_pos = 7; } \
vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; vqflg_pos--;
for( bpos = read = 0, remaining = chunk->size; bpos < read || remaining; ) {
for( yp = ypos; yp < ypos + 16; yp += 8 )
for( xp = xpos; xp < xpos + 16; xp += 8 ) {
RoQ_ReadFlag ();
switch( vqid ) {
case RoQ_ID_MOT:
break;
case RoQ_ID_FCC:
RoQ_ReadByte( c );
RoQ_ApplyMotion8x8( cin, xp, yp, c, ( char )((chunk->argument >> 8) & 0xff), (char)(chunk->argument & 0xff) );
break;
case RoQ_ID_SLD:
RoQ_ReadByte( c );
qcell = cin->qcells + c;
RoQ_ApplyVector4x4( cin, xp, yp, cin->cells + qcell->idx[0] );
RoQ_ApplyVector4x4( cin, xp+4, yp, cin->cells + qcell->idx[1] );
RoQ_ApplyVector4x4( cin, xp, yp+4, cin->cells + qcell->idx[2] );
RoQ_ApplyVector4x4( cin, xp+4, yp+4, cin->cells + qcell->idx[3] );
break;
case RoQ_ID_CCC:
for( i = 0; i < 4; i++ ) {
x = xp; if( i & 0x01 ) x += 4;
y = yp; if( i & 0x02 ) y += 4;
RoQ_ReadFlag ();
switch( vqid ) {
case RoQ_ID_MOT:
break;
case RoQ_ID_FCC:
RoQ_ReadByte( c );
RoQ_ApplyMotion4x4( cin, x, y, c, ( char )((chunk->argument >> 8) & 0xff), (char)(chunk->argument & 0xff) );
break;
case RoQ_ID_SLD:
RoQ_ReadByte( c );
qcell = cin->qcells + c;
RoQ_ApplyVector2x2( cin, x, y, cin->cells + qcell->idx[0] );
RoQ_ApplyVector2x2( cin, x+2, y, cin->cells + qcell->idx[1] );
RoQ_ApplyVector2x2( cin, x, y+2, cin->cells + qcell->idx[2] );
RoQ_ApplyVector2x2( cin, x+2, y+2, cin->cells + qcell->idx[3] );
break;
case RoQ_ID_CCC:
RoQ_ReadByte( c ); RoQ_ApplyVector2x2( cin, x, y, cin->cells + c );
RoQ_ReadByte( c ); RoQ_ApplyVector2x2( cin, x+2, y, cin->cells + c );
RoQ_ReadByte( c ); RoQ_ApplyVector2x2( cin, x, y+2, cin->cells + c );
RoQ_ReadByte( c ); RoQ_ApplyVector2x2( cin, x+2, y+2, cin->cells + c );
break;
default:
MsgDev( D_WARN, "Unknown vq code: %d\n", vqid );
break;
}
}
break;
default:
MsgDev( D_WARN, "Unknown vq code: %d\n", vqid );
break;
}
}
xpos += 16;
if( xpos >= cin->width ) {
xpos -= cin->width;
ypos += 16;
if( ypos >= cin->height )
{
RoQ_SkipBlock( cin, remaining ); // ignore remaining trash
break;
}
}
}
if( cin->frame++ == 0 )
{
// copy initial values to back buffer for motion
Mem_Copy( cin->vid_pic[1], cin->vid_pic[0], cin->width * cin->height * 4 );
}
else
{
// swap buffers
tp = cin->vid_pic[0]; cin->vid_pic[0] = cin->vid_pic[1]; cin->vid_pic[1] = tp;
}
return cin->vid_pic[1];
}
/*
==================
RoQ_ReadAudio
==================
*/
void RoQ_ReadAudio( cinematics_t *cin )
{
int i;
int snd_left, snd_right;
byte raw[RoQ_READ_BLOCK];
short samples[RoQ_READ_BLOCK];
roq_chunk_t *chunk = &cin->chunk;
unsigned int remaining, read;
if( chunk->id == RoQ_SOUND_MONO )
{
snd_left = chunk->argument;
snd_right = 0;
}
else
{
snd_left = chunk->argument & 0xff00;
snd_right = (chunk->argument & 0xff) << 8;
}
for( remaining = chunk->size; remaining > 0; remaining -= read )
{
read = min( sizeof( raw ), remaining );
FS_Read( cin->file, raw, read );
if( chunk->id == RoQ_SOUND_MONO )
{
for( i = 0; i < read; i++ )
{
snd_left += snd_sqr_arr[raw[i]];
samples[i] = (short)snd_left;
snd_left = (short)snd_left;
}
// S_RawSamples( read, cin->s_rate, 2, 1, (byte *)samples );
}
else if( chunk->id == RoQ_SOUND_STEREO )
{
for( i = 0; i < read; i += 2 )
{
snd_left += snd_sqr_arr[raw[i]];
samples[i+0] = (short)snd_left;
snd_left = (short)snd_left;
snd_right += snd_sqr_arr[raw[i+1]];
samples[i+1] = (short)snd_right;
snd_right = (short)snd_right;
}
// S_RawSamples( read / 2, cin->s_rate, 2, 2, (byte *)samples );
}
}
}

View File

@ -1,94 +0,0 @@
/*
Copyright (C) 2002-2003 Victor Luchits
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#define RoQ_HEADER1 4228
#define RoQ_HEADER2 -1
#define RoQ_HEADER3 30
#define RoQ_FRAMERATE 30
#define RoQ_INFO 0x1001
#define RoQ_QUAD_CODEBOOK 0x1002
#define RoQ_QUAD_VQ 0x1011
#define RoQ_SOUND_MONO 0x1020
#define RoQ_SOUND_STEREO 0x1021
#define RoQ_ID_MOT 0x00
#define RoQ_ID_FCC 0x01
#define RoQ_ID_SLD 0x02
#define RoQ_ID_CCC 0x03
typedef struct
{
byte y[4], u, v;
} roq_cell_t;
typedef struct
{
byte idx[4];
} roq_qcell_t;
typedef struct
{
unsigned short id;
unsigned int size;
unsigned short argument;
} roq_chunk_t;
typedef struct
{
char *name;
roq_chunk_t chunk;
roq_cell_t cells[256];
roq_qcell_t qcells[256];
byte *vid_buffer;
byte *vid_pic[2];
bool new_frame;
int s_rate;
int s_width;
int s_channels;
int width;
int height;
file_t *file;
int headerlen;
float time; // Sys_Milliseconds for first cinematic frame
uint frame;
byte *pic;
byte *pic_pending;
byte *mempool;
} cinematics_t;
void RoQ_Init (void);
void RoQ_ReadChunk (cinematics_t *cin);
void RoQ_SkipChunk (cinematics_t *cin);
void RoQ_ReadInfo (cinematics_t *cin);
void RoQ_ReadCodebook (cinematics_t *cin);
byte *RoQ_ReadVideo (cinematics_t *cin);
void RoQ_ReadAudio (cinematics_t *cin);

View File

@ -1,987 +0,0 @@
//=======================================================================
// Copyright XashXT Group 2008 ©
// r_alias.c - Quake1 models loading & drawing
//=======================================================================
#include "r_local.h"
#include "mathlib.h"
#include "quatlib.h"
#include "byteorder.h"
static mesh_t alias_mesh;
static float alias_mins[3];
static float alias_maxs[3];
static float alias_radius;
maliashdr_t *pheader;
typedef struct
{
char name[16]; // frame name
daliastrivertx_t *data; // frame data
} aliasframe_t;
aliasframe_t frames[MAXALIASFRAMES];
int numframes;
/*
=================
Mod_FloodFillSkin
Fill background pixels so mipmapping doesn't have haloes - Ed
=================
*/
typedef struct
{
short x, y;
} floodfill_t;
// must be a power of 2
#define FLOODFILL_FIFO_SIZE 0x1000
#define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
#define FLOODFILL_STEP( off, dx, dy ) \
{ \
if( pos[off] == fillcolor ) \
{ \
pos[off] = 255; \
fifo[inpt].x = x + ( dx ); \
fifo[inpt].y = y + ( dy ); \
inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
} \
else if( pos[off] != 255 ) fdc = pos[off]; \
}
/*
=================
Mod_AliasLoadFrame
=================
*/
void *Mod_AliasLoadFrame( void *pin, maliasframedesc_t *frame )
{
daliastrivertx_t *pinframe;
daliasframe_t *pdaliasframe;
int i;
pdaliasframe = (daliasframe_t *)pin;
com.strncpy( frame->name, pdaliasframe->name, sizeof( frame->name ));
frame->firstpose = numframes;
frame->numposes = 1;
for( i = 0; i < 3; i++ )
{
// these are byte values, so we don't have to worry about endianness
frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
frame->bboxmin.v[i] = pdaliasframe->bboxmax.v[i];
}
pinframe = (daliastrivertx_t *)(pdaliasframe + 1);
frames[numframes++].data = pinframe;
pinframe += pheader->numverts;
return (void *)pinframe;
}
/*
=================
Mod_AliasLoadGroup
=================
*/
void *Mod_AliasLoadGroup( void *pin, maliasframedesc_t *frame )
{
daliasgroup_t *pingroup;
int i, numframes;
daliasinterval_t *pin_intervals;
void *ptemp;
pingroup = (daliasgroup_t *)pin;
numframes = LittleLong( pingroup->numframes );
frame->firstpose = numframes;
frame->numposes = numframes;
for( i = 0; i < 3; i++ )
{
// these are byte values, so we don't have to worry about endianness
frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
frame->bboxmin.v[i] = pingroup->bboxmax.v[i];
}
pin_intervals = (daliasinterval_t *)(pingroup + 1);
frame->interval = LittleFloat( pin_intervals->interval );
pin_intervals += numframes;
ptemp = (void *)pin_intervals;
for( i = 0; i < numframes; i++ )
{
frames[numframes++].data = (daliastrivertx_t *)((daliasframe_t *)ptemp + 1);
ptemp = (daliastrivertx_t *)((daliasframe_t *)ptemp + 1) + pheader->numverts;
}
return ptemp;
}
void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
{
byte fillcolor = *skin; // assume this is the pixel to fill
floodfill_t fifo[FLOODFILL_FIFO_SIZE];
int inpt = 0, outpt = 0;
int filledcolor = -1;
rgbdata_t *pal = FS_LoadImage( "#quake1.pal", skin, 768 );
uint *d_8to24table = (uint *)pal->palette;
int i;
if( filledcolor == -1 )
{
filledcolor = 0;
// attempt to find opaque black
for( i = 0; i < 256; ++i )
{
if( d_8to24table[i] == (255<<0)) // alpha 1.0
{
filledcolor = i;
break;
}
}
}
// can't fill to filled color or to transparent color (used as visited marker)
if(( fillcolor == filledcolor ) || ( fillcolor == 255 )) return;
fifo[inpt].x = 0, fifo[inpt].y = 0;
inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
while( outpt != inpt )
{
int x = fifo[outpt].x, y = fifo[outpt].y;
int fdc = filledcolor;
byte *pos = &skin[x + skinwidth * y];
outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
if( x > 0 ) FLOODFILL_STEP( -1, -1, 0 );
if( x < skinwidth - 1 ) FLOODFILL_STEP( 1, 1, 0 );
if( y > 0 ) FLOODFILL_STEP( -skinwidth, 0, -1 );
if( y < skinheight - 1 ) FLOODFILL_STEP( skinwidth, 0, 1 );
skin[x + skinwidth * y] = fdc;
}
FS_FreeImage( pal );
}
/*
===============
Mod_AliasLoadSkins
===============
*/
void *Mod_AliasLoadSkins( ref_model_t *mod, int numskins, daliasskintype_t *pskintype )
{
int i, j, k, s;
string shadername;
string modname;
byte *skin;
int groupskins;
daliasskingroup_t *pinskingroup;
daliasskininterval_t *pinskinintervals;
dstudiotexture_t *ptexture; // apply studio header for alias texture
texture_t *tex;
FS_FileBase( mod->name, modname );
skin = (byte *)(pskintype + 1);
if( numskins < 1 || numskins > MAX_SKINS )
Host_Error( "Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins );
s = pheader->skinwidth * pheader->skinheight;
ptexture = Mod_Malloc( mod, sizeof( *ptexture ));
ptexture->height = pheader->skinheight;
ptexture->width = pheader->skinwidth;
ptexture->flags = STUDIO_NF_QUAKESKIN; // indicates alias models
for( i = 0; i < numskins; i++ )
{
if( pskintype->type == SKIN_SINGLE )
{
Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
com.sprintf( shadername, "%s.mdl/%s_%i.bmp", modname, modname, i );
com.sprintf( ptexture->name, "Alias( %s_%i )", modname, i );
ptexture->index = (int)skin;// don't copy, just set ptr
tex = R_FindTexture( ptexture->name, (byte *)ptexture, s, 0 );
R_ShaderAddStageTexture( tex );
pheader->skins[i][0] = pheader->skins[i][1] = pheader->skins[i][2] =
pheader->skins[i][3] = R_LoadShader( shadername, SHADER_ALIAS, false, tex->flags, SHADER_INVALID );
pskintype = (daliasskintype_t *)((byte *)(pskintype + 1) + s );
}
else
{
// animating skin group. yuck.
pskintype++;
pinskingroup = (daliasskingroup_t *)pskintype;
groupskins = LittleLong( pinskingroup->numskins );
pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
pskintype = (void *)(pinskinintervals + groupskins);
for( j = 0; j < groupskins; j++ )
{
skin = (byte *)(pskintype + 1);
Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
com.sprintf( shadername, "%s.mdl/%s_%i_%i", modname, modname, i, j );
com.sprintf( ptexture->name, "Alias( %s_%i_%i )", modname, i, j );
ptexture->index = (int)skin;// don't copy, just set ptr
tex = R_FindTexture( ptexture->name, (byte *)ptexture, s, 0 );
R_ShaderAddStageTexture( tex );
pheader->skins[i][j&3] = R_LoadShader( shadername, SHADER_ALIAS, false, tex->flags, SHADER_INVALID );
pskintype = (daliasskintype_t *)((byte *)(pskintype) + s );
}
for( k = j; j < 4; j++ )
pheader->skins[i][j&3] = pheader->skins[i][j - k];
}
}
Mem_Free( ptexture );
return (void *)pskintype;
}
/*
=================
Mod_AliasCalculateVertexNormals
=================
*/
static void Mod_AliasCalculateVertexNormals( int numElems, elem_t *elems, int numVerts, maliasvertex_t *v )
{
int i, j, k, vertRemap[MAXALIASVERTS];
vec3_t dir1, dir2, normal, trnormals[MAXALIASTRIS];
int numUniqueVerts, uniqueVerts[MAXALIASVERTS];
byte latlongs[MAXALIASVERTS][2];
// count unique verts
for( i = 0, numUniqueVerts = 0; i < numVerts; i++ )
{
for( j = 0; j < numUniqueVerts; j++ )
{
if( VectorCompare( v[uniqueVerts[j]].point, v[i].point ))
{
vertRemap[i] = j;
break;
}
}
if( j == numUniqueVerts )
{
vertRemap[i] = numUniqueVerts;
uniqueVerts[numUniqueVerts++] = i;
}
}
for( i = 0, j = 0; i < numElems; i += 3, j++ )
{
// calculate two mostly perpendicular edge directions
VectorSubtract( v[elems[i+0]].point, v[elems[i+1]].point, dir1 );
VectorSubtract( v[elems[i+2]].point, v[elems[i+1]].point, dir2 );
// we have two edge directions, we can calculate a third vector from
// them, which is the direction of the surface normal
CrossProduct( dir1, dir2, trnormals[j] );
VectorNormalize( trnormals[j] );
}
// sum all triangle normals
for( i = 0; i < numUniqueVerts; i++ )
{
VectorClear( normal );
for( j = 0, k = 0; j < numElems; j += 3, k++ )
{
if( vertRemap[elems[j+0]] == i || vertRemap[elems[j+1]] == i || vertRemap[elems[j+2]] == i )
VectorAdd( normal, trnormals[k], normal );
}
VectorNormalize( normal );
NormToLatLong( normal, latlongs[i] );
}
// copy normals back
for( i = 0; i < numVerts; i++ )
*(short *)v[i].latlong = *(short *)latlongs[vertRemap[i]];
}
/*
=================
Mod_AliasBuildMeshesForFrame0
=================
*/
static void Mod_AliasBuildMeshesForFrame0( ref_model_t *mod )
{
int i, j, k;
size_t size;
maliasframe_t *frame;
maliasmodel_t *aliasmodel = (maliasmodel_t *)mod->extradata;
frame = &aliasmodel->frames[0];
for( k = 0; k < aliasmodel->nummeshes; k++ )
{
maliasmesh_t *mesh = &aliasmodel->meshes[k];
size = sizeof( vec4_t ) + sizeof( vec4_t ); // xyz and normals
if( GL_Support( R_SHADER_GLSL100_EXT )) size += sizeof( vec4_t ); // s-vectors
size *= mesh->numverts;
mesh->xyzArray = ( vec4_t * )Mod_Malloc( mod, size );
mesh->normalsArray = ( vec4_t * )( ( byte * )mesh->xyzArray + mesh->numverts * sizeof( vec4_t ));
if( GL_Support( R_SHADER_GLSL100_EXT ))
mesh->sVectorsArray = (vec4_t *)((byte *)mesh->normalsArray + mesh->numverts * sizeof( vec4_t ));
for( i = 0; i < mesh->numverts; i++ )
{
for( j = 0; j < 3; j++ )
mesh->xyzArray[i][j] = frame->translate[j] + frame->scale[j] * mesh->vertexes[i].point[j];
mesh->xyzArray[i][3] = 1;
R_LatLongToNorm( mesh->vertexes[i].latlong, mesh->normalsArray[i] );
mesh->normalsArray[i][3] = 0;
}
if( GL_Support( R_SHADER_GLSL100_EXT ))
R_BuildTangentVectors( mesh->numverts, mesh->xyzArray, mesh->normalsArray, mesh->stArray, mesh->numtris, mesh->elems, mesh->sVectorsArray );
}
}
/*
=================
Mod_QAliasLoadModel
=================
*/
void Mod_QAliasLoadModel( ref_model_t *mod, ref_model_t *parent, const void *buffer )
{
int i, j, k;
daliashdr_t *pinmodel;
daliastexcoord_t *pinst;
daliastriangle_t *pintri;
daliasframetype_t *pframetype;
daliasskintype_t *pskintype;
int indremap[MAXALIASTRIS*3];
elem_t ptempelem[MAXALIASTRIS*3], ptempstelem[MAXALIASTRIS*3];
int version, numverts, numelems;
maliasmodel_t *poutmodel;
maliasmesh_t *poutmesh;
elem_t *poutelem;
vec2_t *poutcoord;
maliasframe_t *poutframe;
maliasvertex_t *poutvertex;
maliasskin_t *poutskin;
pinmodel = (daliashdr_t *)buffer;
version = LittleLong( pinmodel->version );
if( version != QALIAS_VERSION )
Host_Error( "%s has wrong version number (%i should be %i)\n", mod->name, version, QALIAS_VERSION );
// allocate space for a working header, plus all the data except the frames,
// skin and group info
pheader = Mod_Malloc( mod, sizeof( maliashdr_t ) + (LittleLong( pinmodel->numframes ) - 1) * sizeof( pheader->frames[0] ));
mod->extradata = poutmodel = Mod_Malloc( mod, sizeof( maliasmodel_t ) );
mod->type = mod_alias;
// endian-adjust and copy the data, starting with the alias model header
pheader->flags = LittleLong( pinmodel->flags );
pheader->boundingradius = LittleFloat( pinmodel->boundingradius );
poutmodel->numskins = pheader->numskins = LittleLong( pinmodel->numskins );
pheader->skinwidth = LittleLong( pinmodel->skinwidth );
pheader->skinheight = LittleLong( pinmodel->skinheight );
if( pheader->skinheight > MAX_LBM_HEIGHT || pheader->skinwidth > MAX_LBM_WIDTH )
Host_Error( "model %s has a skin taller than %dx%d\n", mod->name, MAX_LBM_WIDTH, MAX_LBM_HEIGHT );
pheader->numframes = LittleLong( pinmodel->numframes );
if( pheader->numframes < 1 ) Host_Error( "Mod_LoadAliasModel: model %s has no frames\n", mod->name );
if( pheader->numframes > MAXALIASFRAMES ) Host_Error( "Mod_LoadAliasModel: model %s has too many frames\n", mod->name );
pheader->size = LittleFloat( pinmodel->size ) * (1.0f / 11.0f);
pheader->synctype = LittleLong( pinmodel->synctype );
poutmodel->numtags = 0;
poutmodel->tags = NULL;
poutmodel->nummeshes = 1;
poutmesh = poutmodel->meshes = Mod_Malloc( mod, sizeof( maliasmesh_t ));
com.strncpy( poutmesh->name, "default", MD3_MAX_PATH );
for( i = 0; i < 3; i++ )
{
pheader->scale[i] = LittleFloat( pinmodel->scale[i] );
pheader->scale_origin[i] = LittleFloat( pinmodel->scale_origin[i] );
pheader->eyeposition[i] = LittleFloat( pinmodel->eyeposition[i] );
}
poutmesh->numverts = pheader->numverts = LittleLong( pinmodel->numverts );
if( pheader->numverts <= 0 ) Host_Error( "model %s has no vertices\n", mod->name );
if( pheader->numverts > MAXALIASVERTS ) Host_Error( "model %s has too many vertices\n", mod->name );
poutmesh->numtris = pheader->numtris = LittleLong( pinmodel->numtris );
if( pheader->numtris <= 0 ) Host_Error( "model %s has no triangles\n", mod->name );
if( pheader->numtris > MAXALIASTRIS ) Host_Error( "model %s has too many triangles\n", mod->name );
// load the skins
pskintype = (daliasskintype_t *)&pinmodel[1];
pskintype = Mod_AliasLoadSkins( mod, pheader->numskins, pskintype );
numelems = poutmesh->numtris * 3;
poutelem = poutmesh->elems = Mod_Malloc( mod, numelems * sizeof( elem_t ));
// load triangle lists
pinst = (daliastexcoord_t *)pskintype;
pintri = (daliastriangle_t *)&pinst[pheader->numverts];
for( i = 0, k = 0; i < poutmesh->numtris; i++, k += 3 )
{
for( j = 0; j < 3; j++ )
{
// matches for vertexes and stcoords
ptempelem[k+j] = ( elem_t )LittleLong( pintri[i].vertindex[j] );
ptempstelem[k+j] = ( elem_t )LittleLong( pintri[i].vertindex[j] );
}
}
//
// build list of unique vertexes
//
numverts = 0;
memset( indremap, -1, MAXALIASTRIS * 3 * sizeof( int ));
for( i = 0; i < numelems; i++ )
{
if( indremap[i] != -1 )
continue;
// remap duplicates
for( j = i + 1; j < numelems; j++ )
{
if( ( ptempelem[j] == ptempelem[i] )
&& ( pinst[ptempstelem[j]].s == pinst[ptempstelem[i]].s )
&& ( pinst[ptempstelem[j]].t == pinst[ptempstelem[i]].t )
&& ( pinst[ptempstelem[j]].onseam == pinst[ptempstelem[i]].onseam ))
{
indremap[j] = i;
poutelem[j] = numverts;
}
}
// add unique vertex
indremap[i] = i;
poutelem[i] = numverts++;
}
Msg( "%s: remapped %i verts to %i (%i tris)\n", mod->name, poutmesh->numverts, numverts, poutmesh->numtris );
poutmesh->numverts = numverts;
// load base s and t vertices
poutcoord = poutmesh->stArray = Mod_Malloc( mod, numelems * sizeof( vec2_t ));
for( i = 0; i < numelems; i++ )
{
if( indremap[i] == i )
{
poutcoord[poutelem[i]][0] = ((float)LittleShort( pinst[ptempstelem[i]].s ) + 0.5f ) / pheader->skinwidth;
poutcoord[poutelem[i]][1] = ((float)LittleShort( pinst[ptempstelem[i]].t ) + 0.5f ) / pheader->skinheight;
}
}
// load the frames
numframes = 0;
pframetype = (daliasframetype_t *)&pintri[pheader->numtris];
for( i = 0; i < pheader->numframes; i++ )
{
frametype_t frametype;
frametype = LittleLong( pframetype->type );
switch( frametype )
{
case FRAME_SINGLE:
pframetype = (daliasframetype_t *)Mod_AliasLoadFrame( pframetype+1, &pheader->frames[i] );
break;
case FRAME_GROUP:
pframetype = (daliasframetype_t *)Mod_AliasLoadGroup( pframetype+1, &pheader->frames[i] );
break;
}
if( pframetype == NULL ) break; // technically an error
}
poutmodel->numframes = pheader->numposes = numframes;
poutframe = poutmodel->frames = Mod_Malloc( mod, poutmodel->numframes * ( sizeof( maliasframe_t ) + numverts * sizeof( maliasvertex_t )));
poutvertex = poutmesh->vertexes = ( maliasvertex_t *)((byte *)poutframe + poutmodel->numframes * sizeof( maliasframe_t ));
for( i = 0; i < poutmodel->numframes; i++, poutframe++, poutvertex += poutmesh->numverts )
{
for( j = 0; j < 3; j++ )
{
poutframe->scale[j] = LittleFloat( pinmodel->scale[j] );
poutframe->translate[j] = LittleFloat( pinmodel->scale_origin[j] );
}
for( j = 0; j < numelems; j++ )
{
// verts are all 8 bit, so no swapping needed
if( indremap[j] == j )
{
poutvertex[poutelem[j]].point[0] = (short)frames[i].data[ptempelem[j]].v[0];
poutvertex[poutelem[j]].point[1] = (short)frames[i].data[ptempelem[j]].v[1];
poutvertex[poutelem[j]].point[2] = (short)frames[i].data[ptempelem[j]].v[2];
}
}
Mod_AliasCalculateVertexNormals( numelems, poutelem, poutmesh->numverts, poutvertex );
VectorCopy( poutframe->translate, poutframe->mins );
VectorMA( poutframe->translate, 255, poutframe->scale, poutframe->maxs );
poutframe->radius = RadiusFromBounds( poutframe->mins, poutframe->maxs );
mod->radius = max( mod->radius, poutframe->radius );
AddPointToBounds( poutframe->mins, mod->mins, mod->maxs );
AddPointToBounds( poutframe->maxs, mod->mins, mod->maxs );
}
// build S and T vectors for frame 0
Mod_AliasBuildMeshesForFrame0( mod );
// register all skins
poutskin = poutmodel->skins = Mod_Malloc( mod, poutmodel->numskins * sizeof( maliasskin_t ) );
for( i = 0; i < poutmodel->numskins; i++, poutskin++ )
poutskin->shader = pheader->skins[i][0];
Mem_Free( pheader );
mod->touchFrame = tr.registration_sequence; // register model
}
/*
=============
R_AliasModelLerpBBox
=============
*/
static void R_AliasModelLerpBBox( ref_entity_t *e, ref_model_t *mod )
{
int i;
maliasmodel_t *aliasmodel = ( maliasmodel_t * )mod->extradata;
maliasframe_t *pframe, *poldframe;
float *thismins, *oldmins, *thismaxs, *oldmaxs;
if( !aliasmodel->nummeshes )
{
alias_radius = 0;
ClearBounds( alias_mins, alias_maxs );
return;
}
if( ( e->frame >= aliasmodel->numframes ) || ( e->frame < 0 ) )
{
MsgDev( D_ERROR, "R_DrawAliasModel %s: no such frame %g\n", mod->name, e->frame );
e->frame = 0;
}
if( ( e->prev.frame >= aliasmodel->numframes ) || ( e->prev.frame < 0 ) )
{
MsgDev( D_ERROR, "R_DrawAliasModel %s: no such oldframe %g\n", mod->name, e->prev.frame );
e->prev.frame = 0;
}
pframe = aliasmodel->frames + (int)e->frame;
poldframe = aliasmodel->frames + (int)e->prev.frame;
// compute axially aligned mins and maxs
if( pframe == poldframe )
{
VectorCopy( pframe->mins, alias_mins );
VectorCopy( pframe->maxs, alias_maxs );
alias_radius = pframe->radius;
}
else
{
thismins = pframe->mins;
thismaxs = pframe->maxs;
oldmins = poldframe->mins;
oldmaxs = poldframe->maxs;
for( i = 0; i < 3; i++ )
{
alias_mins[i] = min( thismins[i], oldmins[i] );
alias_maxs[i] = max( thismaxs[i], oldmaxs[i] );
}
alias_radius = RadiusFromBounds( thismins, thismaxs );
}
if( e->scale != 1.0f )
{
VectorScale( alias_mins, e->scale, alias_mins );
VectorScale( alias_maxs, e->scale, alias_maxs );
alias_radius *= e->scale;
}
}
/*
=============
R_DrawAliasFrameLerp
Interpolates between two frames and origins
=============
*/
static void R_DrawAliasFrameLerp( const meshbuffer_t *mb, float backlerp )
{
int i, meshnum;
int features;
float backv[3], frontv[3];
vec3_t normal, oldnormal;
bool unlockVerts, calcVerts, calcNormals, calcSTVectors;
vec3_t move;
maliasframe_t *frame, *oldframe;
maliasmesh_t *mesh;
maliasvertex_t *v, *ov;
ref_entity_t *e = RI.currententity;
ref_model_t *mod = Mod_ForHandle( mb->LODModelHandle );
maliasmodel_t *model = ( maliasmodel_t * )mod->extradata;
ref_shader_t *shader;
static maliasmesh_t *alias_prevmesh;
static ref_shader_t *alias_prevshader;
static int alias_framecount, alias_riparams;
if( alias_riparams != RI.params || RI.params & RP_SHADOWMAPVIEW )
{
alias_riparams = RI.params; // do not try to lock arrays between RI updates
alias_framecount = !r_framecount;
}
meshnum = -mb->infokey - 1;
if( meshnum < 0 || meshnum >= model->nummeshes )
return;
mesh = model->meshes + meshnum;
frame = model->frames + (int)e->frame;
oldframe = model->frames + (int)e->prev.frame;
for( i = 0; i < 3; i++ )
move[i] = frame->translate[i] + ( oldframe->translate[i] - frame->translate[i] ) * backlerp;
MB_NUM2SHADER( mb->shaderkey, shader );
features = MF_NONBATCHED | shader->features;
if( RI.params & RP_SHADOWMAPVIEW )
{
features &= ~( MF_COLORS|MF_SVECTORS|MF_ENABLENORMALS );
if( !( shader->features & MF_DEFORMVS ) )
features &= ~MF_NORMALS;
}
else
{
if( ( features & MF_SVECTORS ) || r_shownormals->integer )
features |= MF_NORMALS;
if( e->outlineHeight )
features |= MF_NORMALS|(GL_Support( R_SHADER_GLSL100_EXT ) ? MF_ENABLENORMALS : 0);
}
calcNormals = calcSTVectors = false;
calcNormals = (( features & MF_NORMALS ) != 0 ) && (( e->frame != 0 ) || ( e->prev.frame != 0 ));
if( alias_framecount == r_framecount && RI.previousentity && RI.previousentity->model == e->model && alias_prevmesh == mesh && alias_prevshader == shader )
{
ref_entity_t *pe = RI.previousentity;
if( pe->frame == e->frame && pe->prev.frame == e->prev.frame && ( pe->backlerp == e->backlerp || e->frame == e->prev.frame ))
{
unlockVerts = ((( features & MF_DEFORMVS )));
calcNormals = ( calcNormals && ( shader->features & SHADER_DEFORM_NORMAL ));
}
}
unlockVerts = true;
calcSTVectors = ( ( features & MF_SVECTORS ) != 0 ) && calcNormals;
alias_prevmesh = mesh;
alias_prevshader = shader;
alias_framecount = r_framecount;
if( unlockVerts )
{
if( !e->frame && !e->prev.frame )
{
calcVerts = false;
if( calcNormals )
{
v = mesh->vertexes;
for( i = 0; i < mesh->numverts; i++, v++ )
R_LatLongToNorm( v->latlong, inNormalsArray[i] );
}
}
else if( e->frame == e->prev.frame )
{
calcVerts = true;
for( i = 0; i < 3; i++ )
frontv[i] = frame->scale[i];
v = mesh->vertexes + (int)e->frame * mesh->numverts;
for( i = 0; i < mesh->numverts; i++, v++ )
{
Vector4Set( inVertsArray[i],
move[0] + v->point[0]*frontv[0],
move[1] + v->point[1]*frontv[1],
move[2] + v->point[2]*frontv[2], 1 );
if( calcNormals )
R_LatLongToNorm( v->latlong, inNormalsArray[i] );
}
}
else
{
calcVerts = true;
for( i = 0; i < 3; i++ )
{
backv[i] = backlerp * oldframe->scale[i];
frontv[i] = ( 1.0f - backlerp ) * frame->scale[i];
}
v = mesh->vertexes + (int)e->frame * mesh->numverts;
ov = mesh->vertexes + (int)e->prev.frame * mesh->numverts;
for( i = 0; i < mesh->numverts; i++, v++, ov++ )
{
Vector4Set( inVertsArray[i],
move[0] + v->point[0]*frontv[0] + ov->point[0]*backv[0],
move[1] + v->point[1]*frontv[1] + ov->point[1]*backv[1],
move[2] + v->point[2]*frontv[2] + ov->point[2]*backv[2], 1 );
if( calcNormals )
{
R_LatLongToNorm( v->latlong, normal );
R_LatLongToNorm( ov->latlong, oldnormal );
VectorSet( inNormalsArray[i],
normal[0] + ( oldnormal[0] - normal[0] ) * backlerp,
normal[1] + ( oldnormal[1] - normal[1] ) * backlerp,
normal[2] + ( oldnormal[2] - normal[2] ) * backlerp );
}
}
}
if( calcSTVectors )
R_BuildTangentVectors( mesh->numverts, inVertsArray, inNormalsArray, mesh->stArray, mesh->numtris, mesh->elems, inSVectorsArray );
alias_mesh.xyzArray = calcVerts ? inVertsArray : mesh->xyzArray;
}
else
{
features |= MF_KEEPLOCK;
}
alias_mesh.elems = mesh->elems;
alias_mesh.numElems = mesh->numtris * 3;
alias_mesh.numVertexes = mesh->numverts;
alias_mesh.stArray = mesh->stArray;
if( features & MF_NORMALS )
alias_mesh.normalsArray = calcNormals ? inNormalsArray : mesh->normalsArray;
if( features & MF_SVECTORS )
alias_mesh.sVectorsArray = calcSTVectors ? inSVectorsArray : mesh->sVectorsArray;
R_RotateForEntity( e );
R_PushMesh( &alias_mesh, features );
R_RenderMeshBuffer( mb );
}
/*
=================
R_DrawAliasModel
=================
*/
void R_DrawAliasModel( const meshbuffer_t *mb )
{
ref_entity_t *e = RI.currententity;
if( OCCLUSION_QUERIES_ENABLED( RI ) && OCCLUSION_TEST_ENTITY( e ) )
{
ref_shader_t *shader;
MB_NUM2SHADER( mb->shaderkey, shader );
if( !R_GetOcclusionQueryResultBool( shader->type == SHADER_PLANAR_SHADOW ? OQ_PLANARSHADOW : OQ_ENTITY,
e - r_entities, true ) )
return;
}
// hack the depth range to prevent view model from poking into walls
if( e->ent_type == ED_VIEWMODEL )
{
pglDepthRange( gldepthmin, gldepthmin + 0.3 * ( gldepthmax - gldepthmin ) );
// backface culling for left-handed weapons
if( r_lefthand->integer == 1 )
GL_FrontFace( !glState.frontFace );
}
if( !r_lerpmodels->integer )
e->backlerp = 0;
R_DrawAliasFrameLerp( mb, e->backlerp );
if( e->ent_type == ED_VIEWMODEL )
{
pglDepthRange( gldepthmin, gldepthmax );
// backface culling for left-handed weapons
if( r_lefthand->integer == 1 )
GL_FrontFace( !glState.frontFace );
}
}
/*
=================
R_AliasModelBBox
=================
*/
float R_AliasModelBBox( ref_entity_t *e, vec3_t mins, vec3_t maxs )
{
ref_model_t *mod = e->model;
if( !mod ) return 0;
R_AliasModelLerpBBox( e, mod );
VectorCopy( alias_mins, mins );
VectorCopy( alias_maxs, maxs );
return alias_radius;
}
/*
=================
R_CullAliasModel
=================
*/
bool R_CullAliasModel( ref_entity_t *e )
{
int i, j, clipped;
bool frustum, query;
uint modhandle, numtris;
ref_model_t *mod = e->model;
ref_shader_t *shader;
meshbuffer_t *mb;
maliasmodel_t *aliasmodel;
maliasmesh_t *mesh;
if(!( aliasmodel = (( maliasmodel_t * )mod->extradata )) || !aliasmodel->nummeshes )
return true;
R_AliasModelLerpBBox( e, mod );
modhandle = Mod_Handle( mod );
clipped = R_CullModel( e, alias_mins, alias_maxs, alias_radius );
frustum = clipped & 1;
if( clipped & 2 )
return true;
query = OCCLUSION_QUERIES_ENABLED( RI ) && OCCLUSION_TEST_ENTITY( e ) ? true : false;
if( !frustum && query )
R_IssueOcclusionQuery( R_GetOcclusionQueryNum( OQ_ENTITY, e - r_entities ), e, alias_mins, alias_maxs );
if( ( RI.refdef.rdflags & RDF_NOWORLDMODEL )
|| ( r_shadows->integer != SHADOW_PLANAR && !( r_shadows->integer == SHADOW_MAPPING && ( e->flags & EF_PLANARSHADOW )))
|| R_CullPlanarShadow( e, alias_mins, alias_maxs, query ) )
return frustum; // entity is not in PVS or shadow is culled away by frustum culling
numtris = 0;
for( i = 0, mesh = aliasmodel->meshes; i < aliasmodel->nummeshes; i++, mesh++ )
{
shader = NULL;
if( e->skinfile )
shader = R_FindShaderForSkinFile( e->skinfile, mesh->name );
else if(( e->skin >= 0 ) && ( e->skin < aliasmodel->numskins ))
shader = aliasmodel->skins[e->skin].shader;
else if( mesh->numskins )
{
for( j = 0; j < mesh->numskins; j++ )
{
shader = mesh->skins[j].shader;
if( shader && shader->sort <= SORT_ALPHATEST )
break;
shader = NULL;
}
}
if( shader && ( shader->sort <= SORT_ALPHATEST ))
{
mb = R_AddMeshToList( MB_MODEL, NULL, R_PlanarShadowShader(), -( i+1 ));
if( mb ) mb->LODModelHandle = modhandle;
}
}
return frustum;
}
/*
=================
R_AddAliasModelToList
=================
*/
void R_AddAliasModelToList( ref_entity_t *e )
{
int i, j;
uint modhandle, entnum = e - r_entities;
mfog_t *fog = NULL;
ref_model_t *mod = e->model;
ref_shader_t *shader;
maliasmodel_t *aliasmodel;
maliasmesh_t *mesh;
aliasmodel = (maliasmodel_t *)mod->extradata;
modhandle = Mod_Handle( mod );
if( RI.params & RP_SHADOWMAPVIEW )
{
if( r_entShadowBits[entnum] & RI.shadowGroup->bit )
{
if( !r_shadows_self_shadow->integer )
r_entShadowBits[entnum] &= ~RI.shadowGroup->bit;
if( e->ent_type == ED_VIEWMODEL )
return;
}
else
{
R_AliasModelLerpBBox( e, mod );
if( !R_CullModel( e, alias_mins, alias_maxs, alias_radius ) )
r_entShadowBits[entnum] |= RI.shadowGroup->bit;
return; // mark as shadowed, proceed with caster otherwise
}
}
else
{
fog = R_FogForSphere( e->origin, alias_radius );
#if 0
if( !( e->ent_type == ED_VIEWMODEL ) && fog )
{
R_AliasModelLerpBBox( e, mod );
if( R_CompletelyFogged( fog, e->origin, alias_radius ))
return;
}
#endif
}
for( i = 0, mesh = aliasmodel->meshes; i < aliasmodel->nummeshes; i++, mesh++ )
{
shader = NULL;
if( e->skinfile ) shader = R_FindShaderForSkinFile( e->skinfile, mesh->name );
else if( ( e->skin >= 0 ) && ( e->skin < aliasmodel->numskins ))
shader = aliasmodel->skins[e->skin].shader;
else if( mesh->numskins )
{
for( j = 0; j < mesh->numskins; j++ )
{
shader = mesh->skins[j].shader;
if( shader ) R_AddModelMeshToList( modhandle, fog, shader, i );
}
continue;
}
if( shader ) R_AddModelMeshToList( modhandle, fog, shader, i );
}
}

View File

@ -1269,6 +1269,8 @@ static _inline texture_t *R_ShaderpassTex( const ref_stage_t *pass, int unit )
case mod_brush:
case mod_world:
return pass->textures[bound( 0, (int)RI.currententity->frame, pass->num_textures - 1)];
case mod_studio:
return pass->textures[bound( 0, (int)RI.currententity->skin, pass->num_textures - 1)];
}
}
}

View File

@ -1,45 +1,28 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
//=======================================================================
// Copyright XashXT Group 2009 ©
// r_cin.c - plays videotextures
//=======================================================================
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// r_cin.c
#include "r_local.h"
#include "cin.h"
#define MAX_CINEMATICS 256
typedef struct r_cinhandle_s
{
unsigned int id;
uint id;
char *name;
cinematics_t *cin;
cinematics_t *cin;
texture_t *image;
struct r_cinhandle_s *prev, *next;
struct r_cinhandle_s *prev, *next;
} r_cinhandle_t;
static byte *r_cinMemPool;
static r_cinhandle_t *r_cinematics;
static r_cinhandle_t r_cinematics_headnode, *r_free_cinematics;
static r_cinhandle_t *r_cinematics;
static r_cinhandle_t r_cinematics_headnode, *r_free_cinematics;
#define Cin_Malloc(size) Mem_Alloc(r_cinMemPool,size)
#define Cin_Free(data) Mem_Free(data)
#define Cin_Malloc( size ) Mem_Alloc( r_cinMemPool, size )
#define Cin_Free( data ) Mem_Free( data )
/*
==================
@ -48,28 +31,12 @@ R_ReadNextRoQFrame
*/
static byte *R_ReadNextRoQFrame( cinematics_t *cin )
{
roq_chunk_t *chunk = &cin->chunk;
return ri.RoQ_ReadNextFrame( cin, true );
}
while( !FS_Eof( cin->file ) )
{
RoQ_ReadChunk( cin );
if( FS_Eof( cin->file ) )
return NULL;
if( chunk->size <= 0 )
continue;
if( chunk->id == RoQ_INFO )
RoQ_ReadInfo( cin );
else if( chunk->id == RoQ_QUAD_VQ )
return RoQ_ReadVideo( cin );
else if( chunk->id == RoQ_QUAD_CODEBOOK )
RoQ_ReadCodebook( cin );
else
RoQ_SkipChunk( cin );
}
return NULL;
static void R_ReadRoQChunk( cinematics_t *cin )
{
ri.RoQ_ReadChunk( cin );
}
/*
@ -82,8 +49,8 @@ static void R_RunRoQ( cinematics_t *cin )
uint frame;
frame = (RI.refdef.time - cin->time) * (float)(RoQ_FRAMERATE);
if( frame <= cin->frame )
return;
if( frame <= cin->frame ) return;
if( frame > cin->frame + 1 )
cin->time = RI.refdef.time - cin->frame / RoQ_FRAMERATE;
@ -97,7 +64,6 @@ static void R_RunRoQ( cinematics_t *cin )
cin->pic_pending = R_ReadNextRoQFrame( cin );
cin->time = RI.refdef.time;
}
cin->new_frame = true;
}
@ -120,7 +86,7 @@ static void R_StopRoQ( cinematics_t *cin )
}
if( cin->name )
{
Mem_Free( cin->name );
Mem_Free( (char *)cin->name );
cin->name = NULL;
}
if( cin->vid_buffer )
@ -137,20 +103,20 @@ R_OpenCinematics
*/
static cinematics_t *R_OpenCinematics( char *filename )
{
file_t *file;
cinematics_t *cin = NULL;
roq_chunk_t *chunk = &cin->chunk;
file_t *file;
cinematics_t *cin = NULL;
droqchunk_t *chunk = &cin->chunk;
if((file = FS_Open( filename, "rb" )) == NULL )
if(( file = FS_Open( filename, "rb" )) == NULL )
return NULL;
cin = Cin_Malloc( sizeof( cinematics_t ) );
cin = Cin_Malloc( sizeof( cinematics_t ));
cin->name = filename;
cin->file = file;
cin->mempool = r_cinMemPool;
// read header
RoQ_ReadChunk( cin );
R_ReadRoQChunk( cin );
chunk = &cin->chunk;
if( chunk->id != RoQ_HEADER1 || chunk->size != RoQ_HEADER2 || chunk->argument != RoQ_HEADER3 )
@ -260,15 +226,14 @@ void R_InitCinematics( void )
int i;
r_cinMemPool = Mem_AllocPool( "Cinematics" );
r_cinematics = Cin_Malloc( sizeof( r_cinhandle_t ) * MAX_CINEMATICS );
memset( r_cinematics, 0, sizeof( r_cinhandle_t ) * MAX_CINEMATICS );
// link cinemtics
r_free_cinematics = r_cinematics;
r_cinematics_headnode.id = 0;
r_cinematics_headnode.prev = &r_cinematics_headnode;
r_cinematics_headnode.next = &r_cinematics_headnode;
for( i = 0; i < MAX_CINEMATICS - 1; i++ )
{
if( i < MAX_CINEMATICS - 1 )
@ -301,9 +266,9 @@ void R_RunAllCinematics( void )
R_UploadCinematics
==================
*/
texture_t *R_UploadCinematics( unsigned int id )
texture_t *R_UploadCinematics( uint id )
{
Com_Assert( (id > 0 && id <= MAX_CINEMATICS) == 0 );
Com_Assert( !( id > 0 && id <= MAX_CINEMATICS ));
return R_ResampleCinematicFrame( r_cinematics + id - 1 );
}
@ -312,16 +277,17 @@ texture_t *R_UploadCinematics( unsigned int id )
R_StartCinematic
==================
*/
unsigned int R_StartCinematics( const char *arg )
uint R_StartCinematics( const char *arg )
{
char *name = NULL, uploadName[128];
size_t name_size;
cinematics_t *cin = NULL;
r_cinhandle_t *handle, *hnode, *next;
char *name = NULL;
string uploadName;
size_t name_size;
cinematics_t *cin = NULL;
r_cinhandle_t *handle, *hnode, *next;
name_size = strlen( "video/" ) + strlen( arg ) + strlen( ".roq" ) + 1;
name_size = com.strlen( "media/" ) + com.strlen( arg ) + com.strlen( ".roq" ) + 1;
name = Cin_Malloc( name_size );
com.snprintf( name, name_size, "video/%s", arg );
com.snprintf( name, name_size, "media/%s", arg );
FS_DefaultExtension( name, ".roq" );
// find cinematics with the same name
@ -372,9 +338,9 @@ unsigned int R_StartCinematics( const char *arg )
R_FreeCinematics
=================
*/
void R_FreeCinematics( unsigned int id )
void R_FreeCinematics( uint id )
{
r_cinhandle_t *handle;
r_cinhandle_t *handle;
handle = r_cinematics + id - 1;
if( !handle->cin )
@ -404,7 +370,7 @@ R_ShutdownCinematics
*/
void R_ShutdownCinematics( void )
{
r_cinhandle_t *handle, *hnode, *next;
r_cinhandle_t *handle, *hnode, *next;
if( !r_cinMemPool )
return;

View File

@ -97,7 +97,7 @@ void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, f
R_DrawStretchRaw
=============
*/
void R_DrawStretchRaw( int x, int y, int w, int h, int cols, int rows, const byte *data, bool redraw )
void R_DrawStretchRaw( int x, int y, int w, int h, int cols, int rows, const byte *data, bool dirty )
{
if( !GL_Support( R_ARB_TEXTURE_NPOT_EXT ))
{
@ -116,20 +116,21 @@ void R_DrawStretchRaw( int x, int y, int w, int h, int cols, int rows, const byt
if( rows > glConfig.max_2d_texture_size )
Host_Error( "R_DrawStretchRaw: size exceeds hardware limits (%i > %i)\n", rows, glConfig.max_2d_texture_size );
pglFinish();
GL_Bind( 0, tr.cinTexture );
if( cols == tr.cinTexture->width && rows == tr.cinTexture->height )
{
pglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
if( dirty ) pglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
}
else
{
tr.cinTexture->width = cols;
tr.cinTexture->height = rows;
pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
if( dirty ) pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
}
R_CheckForErrors();
if( redraw ) return;
pglBegin( GL_QUADS );
pglTexCoord2f( 0, 0 );

View File

@ -1,16 +0,0 @@
<html>
<body>
<pre>
<h1>Build Log</h1>
<h3>
--------------------Configuration: render - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
<h3>Results</h3>
render.dll - 0 error(s), 0 warning(s)
</pre>
</body>
</html>

View File

@ -114,10 +114,6 @@ SOURCE="$(InputPath)"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\cin.c
# End Source File
# Begin Source File
SOURCE=.\r_backend.c
# End Source File
# Begin Source File
@ -206,10 +202,6 @@ SOURCE=.\r_surf.c
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
# Begin Source File
SOURCE=.\cin.h
# End Source File
# Begin Source File
SOURCE=.\r_backend.h
# End Source File
# Begin Source File

View File

@ -1,16 +0,0 @@
<html>
<body>
<pre>
<h1>Build Log</h1>
<h3>
--------------------Configuration: vid_gl - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
<h3>Results</h3>
vid_gl.dll - 0 error(s), 0 warning(s)
</pre>
</body>
</html>

View File

@ -1,16 +0,0 @@
<html>
<body>
<pre>
<h1>Build Log</h1>
<h3>
--------------------Configuration: vprogs - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
<h3>Results</h3>
vprogs.dll - 0 error(s), 0 warning(s)
</pre>
</body>
</html>

View File

@ -1,16 +0,0 @@
<html>
<body>
<pre>
<h1>Build Log</h1>
<h3>
--------------------Configuration: xtools - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
<h3>Results</h3>
xtools.dll - 0 error(s), 0 warning(s)
</pre>
</body>
</html>