24 Nov 2009
This commit is contained in:
parent
acd933e18a
commit
1fb626fca8
|
@ -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>
|
|
@ -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>
|
|
@ -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();
|
||||
|
|
|
@ -171,7 +171,7 @@ float READ_ANGLE( void )
|
|||
|
||||
Vector READ_DIR( void )
|
||||
{
|
||||
return BitsToDir( READ_SHORT() );
|
||||
return BitsToDir( READ_BYTE() );
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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>
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 ));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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( ));
|
||||
}
|
||||
|
|
|
@ -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" );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -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
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 );
|
||||
|
|
|
@ -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__)
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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...
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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 );
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 );
|
||||
}
|
|
@ -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:
|
||||
|
|
|
@ -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 ));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
165
launch/crclib.c
165
launch/crclib.c
|
@ -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
|
||||
|
|
|
@ -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" );
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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 ))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
100
snd_al/s_load.c
100
snd_al/s_load.c
|
@ -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 ));
|
||||
}
|
|
@ -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>
|
|
@ -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
|
||||
|
|
|
@ -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 ));
|
||||
}
|
|
@ -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>
|
|
@ -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,
|
||||
|
|
15
todo.log
15
todo.log
|
@ -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
|
||||
|
|
428
vid_gl/cin.c
428
vid_gl/cin.c
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
94
vid_gl/cin.h
94
vid_gl/cin.h
|
@ -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);
|
||||
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
112
vid_gl/r_cin.c
112
vid_gl/r_cin.c
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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>
|
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
Reference in New Issue