13 Jul 2017

This commit is contained in:
g-cont 2017-07-13 00:00:00 +03:00 committed by Alibek Omarov
parent 320523bb7d
commit 9a33012580
25 changed files with 454 additions and 196 deletions

View File

@ -413,43 +413,24 @@ Alias models are position independent, so the cache manager can move them.
#define MAXALIASTRIS 4096 #define MAXALIASTRIS 4096
#define MAX_SKINS 32 #define MAX_SKINS 32
// This mirrors trivert_t in trilib.h, is present so Quake knows how to
// load this data
typedef struct typedef struct
{ {
byte v[3]; byte v[3];
byte lightnormalindex; byte lightnormalindex;
} mtrivertex_t; } trivertex_t;
typedef struct typedef struct
{ {
int firstpose; int firstpose;
int numposes; int numposes;
trivertex_t bboxmin;
trivertex_t bboxmax;
float interval; float interval;
mtrivertex_t bboxmin;
mtrivertex_t bboxmax;
int frame;
char name[16]; char name[16];
} maliasframedesc_t; } maliasframedesc_t;
typedef struct
{
mtrivertex_t bboxmin;
mtrivertex_t bboxmax;
int frame;
} maliasgroupdesc_t;
typedef struct
{
int numframes;
int intervals;
maliasgroupdesc_t frames[1];
} maliasgroup_t;
typedef struct mtriangle_s
{
int facesfront;
int vertindex[3];
} mtriangle_t;
typedef struct typedef struct
{ {
int ident; int ident;
@ -470,9 +451,10 @@ typedef struct
int numposes; int numposes;
int poseverts; int poseverts;
mtrivertex_t *posedata; // numposes * poseverts trivert_t trivertex_t *posedata; // numposes * poseverts trivert_t
int *commands; // gl command list with embedded s/t int *commands; // gl command list with embedded s/t
int gl_texturenum[MAX_SKINS][4]; unsigned short gl_texturenum[MAX_SKINS][4];
unsigned short fb_texturenum[MAX_SKINS][4];
int *texels[MAX_SKINS]; // only for player skins int *texels[MAX_SKINS]; // only for player skins
maliasframedesc_t frames[1]; // variable sized maliasframedesc_t frames[1]; // variable sized
} aliashdr_t; } aliashdr_t;

View File

@ -18,10 +18,10 @@ GNU General Public License for more details.
// list of engine features that can be enabled through callback SV_CheckFeatures // list of engine features that can be enabled through callback SV_CheckFeatures
#define ENGINE_WRITE_LARGE_COORD (1<<0) // replace standard message WRITE_COORD with big message for support more than 8192 units in world #define ENGINE_WRITE_LARGE_COORD (1<<0) // replace standard message WRITE_COORD with big message for support more than 8192 units in world
// reserved #define ENGINE_QUAKE_COMPATIBLE (1<<1) // make engine compatible with quake (flags and effects)
#define ENGINE_LOAD_DELUXEDATA (1<<2) // loading deluxemap for map (if present) #define ENGINE_LOAD_DELUXEDATA (1<<2) // loading deluxemap for map (if present)
#define ENGINE_TRANSFORM_TRACE_AABB (1<<3) // transform trace bbox into local space of rotating bmodels #define ENGINE_TRANSFORM_TRACE_AABB (1<<3) // transform trace bbox into local space of rotating bmodels
#define ENGINE_LARGE_LIGHTMAPS (1<<4) // change lightmap sizes from 128x128 to 256x256 #define ENGINE_LARGE_LIGHTMAPS (1<<4) // change lightmap sizes from 128x128 to 1024x1024
#define ENGINE_COMPENSATE_QUAKE_BUG (1<<5) // compensate stupid quake bug (inverse pitch) for mods where this bug is fixed #define ENGINE_COMPENSATE_QUAKE_BUG (1<<5) // compensate stupid quake bug (inverse pitch) for mods where this bug is fixed
#define ENGINE_DISABLE_HDTEXTURES (1<<6) // disable support of HD-textures in case custom renderer have separate way to load them #define ENGINE_DISABLE_HDTEXTURES (1<<6) // disable support of HD-textures in case custom renderer have separate way to load them
#define ENGINE_COMPUTE_STUDIO_LERP (1<<7) // enable MOVETYPE_STEP lerping back in engine #define ENGINE_COMPUTE_STUDIO_LERP (1<<7) // enable MOVETYPE_STEP lerping back in engine

View File

@ -29,6 +29,16 @@ Alias models are position independent, so the cache manager can move them.
#define ALIAS_VERSION 6 #define ALIAS_VERSION 6
// client-side model flags
#define ALIAS_ROCKET 0x0001 // leave a trail
#define ALIAS_GRENADE 0x0002 // leave a trail
#define ALIAS_GIB 0x0004 // leave a trail
#define ALIAS_ROTATE 0x0008 // rotate (bonus items)
#define ALIAS_TRACER 0x0010 // green split trail
#define ALIAS_ZOMGIB 0x0020 // small blood trail
#define ALIAS_TRACER2 0x0040 // orange split trail + rotate
#define ALIAS_TRACER3 0x0080 // purple trail
// must match definition in sprite.h // must match definition in sprite.h
#ifndef SYNCTYPE_T #ifndef SYNCTYPE_T
#define SYNCTYPE_T #define SYNCTYPE_T
@ -87,26 +97,18 @@ typedef struct dtriangle_s
#define DT_FACES_FRONT 0x0010 #define DT_FACES_FRONT 0x0010
#define ALIAS_ONSEAM 0x0020 #define ALIAS_ONSEAM 0x0020
// This mirrors trivert_t in trilib.h, is present so Quake knows how to
// load this data
typedef struct typedef struct
{ {
byte v[3]; trivertex_t bboxmin; // lightnormal isn't used
byte lightnormalindex; trivertex_t bboxmax; // lightnormal isn't used
} dtrivertex_t;
typedef struct
{
dtrivertex_t bboxmin; // lightnormal isn't used
dtrivertex_t bboxmax; // lightnormal isn't used
char name[16]; // frame name from grabbing char name[16]; // frame name from grabbing
} daliasframe_t; } daliasframe_t;
typedef struct typedef struct
{ {
int numframes; int numframes;
dtrivertex_t bboxmin; // lightnormal isn't used trivertex_t bboxmin; // lightnormal isn't used
dtrivertex_t bboxmax; // lightnormal isn't used trivertex_t bboxmax; // lightnormal isn't used
} daliasgroup_t; } daliasgroup_t;
typedef struct typedef struct

View File

@ -123,6 +123,21 @@ qboolean CL_CompareTimestamps( float t1, float t2 )
return (( iTime1 - iTime2 ) <= 1 ); return (( iTime1 - iTime2 ) <= 1 );
} }
/*
==================
CL_EntityIgnoreLerp
some ents will be ignore lerping
==================
*/
qboolean CL_EntityIgnoreLerp( cl_entity_t *e )
{
if( e->model && e->model->type == mod_alias )
return false;
return (e->curstate.movetype == MOVETYPE_NONE) ? true : false;
}
/* /*
================== ==================
CL_EntityCustomLerp CL_EntityCustomLerp
@ -190,12 +205,14 @@ CL_UpdateLatchedVars
*/ */
void CL_UpdateLatchedVars( cl_entity_t *ent ) void CL_UpdateLatchedVars( cl_entity_t *ent )
{ {
if( !ent->model || ent->model->type != mod_studio ) if( !ent->model || ( ent->model->type != mod_alias && ent->model->type != mod_studio ))
return; // below fields used only for studio interpolation return; // below fields used only for alias and studio interpolation
VectorCopy( ent->prevstate.origin, ent->latched.prevorigin ); VectorCopy( ent->prevstate.origin, ent->latched.prevorigin );
VectorCopy( ent->prevstate.angles, ent->latched.prevangles ); VectorCopy( ent->prevstate.angles, ent->latched.prevangles );
if( ent->model->type == mod_alias )
ent->latched.prevframe = ent->prevstate.frame;
ent->latched.prevanimtime = ent->prevstate.animtime; ent->latched.prevanimtime = ent->prevstate.animtime;
if( ent->curstate.sequence != ent->prevstate.sequence ) if( ent->curstate.sequence != ent->prevstate.sequence )
@ -217,8 +234,8 @@ CL_ResetLatchedVars
*/ */
void CL_ResetLatchedVars( cl_entity_t *ent, qboolean full_reset ) void CL_ResetLatchedVars( cl_entity_t *ent, qboolean full_reset )
{ {
if( !ent->model || ent->model->type != mod_studio ) if( !ent->model || ( ent->model->type != mod_alias && ent->model->type != mod_studio ))
return; // below fields used only for studio interpolation return; // below fields used only for alias and studio interpolation
if( full_reset ) if( full_reset )
{ {
@ -226,7 +243,10 @@ void CL_ResetLatchedVars( cl_entity_t *ent, qboolean full_reset )
memcpy( ent->latched.prevblending, ent->curstate.blending, sizeof( ent->latched.prevblending )); memcpy( ent->latched.prevblending, ent->curstate.blending, sizeof( ent->latched.prevblending ));
ent->latched.sequencetime = ent->curstate.animtime; ent->latched.sequencetime = ent->curstate.animtime;
memcpy( ent->latched.prevcontroller, ent->curstate.controller, sizeof( ent->latched.prevcontroller )); memcpy( ent->latched.prevcontroller, ent->curstate.controller, sizeof( ent->latched.prevcontroller ));
ent->latched.prevframe = CL_GetStudioEstimatedFrame( ent ); if( ent->model->type == mod_studio )
ent->latched.prevframe = CL_GetStudioEstimatedFrame( ent );
else if( ent->model->type == mod_alias )
ent->latched.prevframe = ent->curstate.frame;
ent->prevstate = ent->curstate; ent->prevstate = ent->curstate;
} }
@ -262,7 +282,7 @@ void CL_ProcessEntityUpdate( cl_entity_t *ent )
if( CL_EntityCustomLerp( ent ) && !parametric ) if( CL_EntityCustomLerp( ent ) && !parametric )
ent->curstate.animtime = ent->curstate.msg_time; ent->curstate.animtime = ent->curstate.msg_time;
if( !CL_CompareTimestamps( ent->curstate.animtime, ent->prevstate.animtime ) || ent->curstate.movetype == MOVETYPE_NONE ) if( !CL_CompareTimestamps( ent->curstate.animtime, ent->prevstate.animtime ) || CL_EntityIgnoreLerp( ent ))
{ {
CL_UpdateLatchedVars( ent ); CL_UpdateLatchedVars( ent );
CL_UpdatePositions( ent ); CL_UpdatePositions( ent );
@ -679,7 +699,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
CL_WriteDemoJumpTime(); CL_WriteDemoJumpTime();
// sentinel count. save it for debug checking // sentinel count. save it for debug checking
count = MSG_ReadUBitLong( msg, MAX_VISIBLE_PACKET_BITS ) + 1; count = ( MSG_ReadUBitLong( msg, MAX_VISIBLE_PACKET_BITS ) + 1 ) & 1023;
newframe = &cl.frames[cl.parsecountmod]; newframe = &cl.frames[cl.parsecountmod];
// allocate parse entities // allocate parse entities
@ -912,8 +932,8 @@ qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType )
// apply client-side effects // apply client-side effects
CL_AddEntityEffects( ent ); CL_AddEntityEffects( ent );
// studiomodel efefcts only // alias & studiomodel efefcts
CL_AddStudioEffects( ent ); CL_AddModelEffects( ent );
} }
return true; return true;

View File

@ -1335,6 +1335,8 @@ pfnSPR_Draw
*/ */
static void pfnSPR_Draw( int frame, int x, int y, const wrect_t *prc ) static void pfnSPR_Draw( int frame, int x, int y, const wrect_t *prc )
{ {
pglDisable( GL_BLEND );
SPR_DrawGeneric( frame, x, y, -1, -1, prc ); SPR_DrawGeneric( frame, x, y, -1, -1, prc );
} }

View File

@ -2198,6 +2198,7 @@ void CL_InitLocal( void )
Cmd_AddCommand ("stop", CL_Stop_f, "stop playing or recording a demo" ); Cmd_AddCommand ("stop", CL_Stop_f, "stop playing or recording a demo" );
Cmd_AddCommand ("info", NULL, "collect info about local servers with specified protocol" ); Cmd_AddCommand ("info", NULL, "collect info about local servers with specified protocol" );
Cmd_AddCommand ("escape", CL_Escape_f, "escape from game to menu" ); Cmd_AddCommand ("escape", CL_Escape_f, "escape from game to menu" );
Cmd_AddCommand ("togglemenu", CL_Escape_f, "toggle between game and menu" );
Cmd_AddCommand ("pointfile", CL_ReadPointFile_f, "show leaks on a map (if present of course)" ); Cmd_AddCommand ("pointfile", CL_ReadPointFile_f, "show leaks on a map (if present of course)" );
Cmd_AddCommand ("linefile", CL_ReadLineFile_f, "show leaks on a map (if present of course)" ); Cmd_AddCommand ("linefile", CL_ReadLineFile_f, "show leaks on a map (if present of course)" );
Cmd_AddCommand ("fullserverinfo", CL_FullServerinfo_f, "sent by server when serverinfo changes" ); Cmd_AddCommand ("fullserverinfo", CL_FullServerinfo_f, "sent by server when serverinfo changes" );

View File

@ -1321,6 +1321,11 @@ void CL_PredictMovement( qboolean repredicting )
if( !CL_IsPredicted( )) if( !CL_IsPredicted( ))
{ {
// keep onground actual
if( FBitSet( frame->clientdata.flags, FL_ONGROUND ))
cl.local.onground = frame->playerstate[cl.playernum].onground;
else cl.local.onground = -1;
cl.local.viewmodel = to->client.viewmodel; cl.local.viewmodel = to->client.viewmodel;
cl.local.repredicting = false; cl.local.repredicting = false;
cl.local.moving = false; cl.local.moving = false;

View File

@ -2689,7 +2689,7 @@ void CL_AddEntityEffects( cl_entity_t *ent )
if( FBitSet( ent->curstate.effects, EF_DIMLIGHT )) if( FBitSet( ent->curstate.effects, EF_DIMLIGHT ))
{ {
if( ent->player ) if( ent->player && !FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
{ {
CL_UpdateFlashlight( ent ); CL_UpdateFlashlight( ent );
} }
@ -2728,17 +2728,24 @@ void CL_AddEntityEffects( cl_entity_t *ent )
/* /*
================ ================
CL_AddStudioEffects CL_AddModelEffects
these effects will be enable by flag in model header these effects will be enable by flag in model header
================ ================
*/ */
void CL_AddStudioEffects( cl_entity_t *ent ) void CL_AddModelEffects( cl_entity_t *ent )
{ {
vec3_t oldorigin; vec3_t oldorigin;
if( !ent->model || ent->model->type != mod_studio ) if( !ent->model ) return;
return;
switch( ent->model->type )
{
case mod_alias:
case mod_studio:
break;
default: return;
}
VectorCopy( ent->latched.prevorigin, oldorigin ); VectorCopy( ent->latched.prevorigin, oldorigin );

View File

@ -81,7 +81,7 @@ struct dlight_s *CL_AllocDlight( int key );
struct dlight_s *CL_AllocElight( int key ); struct dlight_s *CL_AllocElight( int key );
void CL_UpdateFlashlight( cl_entity_t *pEnt ); void CL_UpdateFlashlight( cl_entity_t *pEnt );
void CL_AddEntityEffects( cl_entity_t *ent ); void CL_AddEntityEffects( cl_entity_t *ent );
void CL_AddStudioEffects( cl_entity_t *ent ); void CL_AddModelEffects( cl_entity_t *ent );
void CL_DecalShoot( int textureIndex, int entityIndex, int modelIndex, float *pos, int flags ); void CL_DecalShoot( int textureIndex, int entityIndex, int modelIndex, float *pos, int flags );
void CL_DecalRemoveAll( int textureIndex ); void CL_DecalRemoveAll( int textureIndex );
int CL_DecalIndexFromName( const char *name ); int CL_DecalIndexFromName( const char *name );

View File

@ -89,11 +89,16 @@ void V_SetupViewModel( void )
view->curstate.colormap = (info->topcolor & 0xFFFF)|((info->bottomcolor << 8) & 0xFFFF); view->curstate.colormap = (info->topcolor & 0xFFFF)|((info->bottomcolor << 8) & 0xFFFF);
view->curstate.number = cl.playernum + 1; view->curstate.number = cl.playernum + 1;
view->index = cl.playernum + 1; view->index = cl.playernum + 1;
view->curstate.frame = 0.0f;
view->model = Mod_Handle( cl.local.viewmodel ); view->model = Mod_Handle( cl.local.viewmodel );
view->curstate.modelindex = cl.local.viewmodel; view->curstate.modelindex = cl.local.viewmodel;
view->curstate.animtime = cl.local.weaponstarttime;
view->curstate.sequence = cl.local.weaponsequence; view->curstate.sequence = cl.local.weaponsequence;
// alias models has another animation methods
if( view->model && view->model->type == mod_studio )
{
view->curstate.animtime = cl.local.weaponstarttime;
view->curstate.frame = 0.0f;
}
} }
/* /*

View File

@ -31,10 +31,12 @@ typedef struct
double time; double time;
double frametime; double frametime;
int framecount; // alias framecount int framecount; // alias framecount
qboolean interpolate;
float ambientlight; float ambientlight;
float shadelight; float shadelight;
vec3_t lightvec; // averaging light direction vec3_t lightvec; // averaging light direction
vec3_t lightvec_local; // light direction in local space
vec3_t lightspot; // shadow spot vec3_t lightspot; // shadow spot
vec3_t lightcolor; // averaging lightcolor vec3_t lightcolor; // averaging lightcolor
int oldpose; // shadow used int oldpose; // shadow used
@ -52,8 +54,8 @@ ALIAS MODEL DISPLAY LIST GENERATION
================================================================= =================================================================
*/ */
static aliashdr_t *m_pAliasHeader; static aliashdr_t *m_pAliasHeader;
static mtrivertex_t *g_poseverts[MAXALIASFRAMES]; static trivertex_t *g_poseverts[MAXALIASFRAMES];
static mtriangle_t g_triangles[MAXALIASTRIS]; static dtriangle_t g_triangles[MAXALIASTRIS];
static stvert_t g_stverts[MAXALIASVERTS]; static stvert_t g_stverts[MAXALIASVERTS];
static qboolean g_used[8192]; static qboolean g_used[8192];
@ -71,12 +73,21 @@ static int g_numcommands;
static int g_vertexorder[8192]; static int g_vertexorder[8192];
static int g_numorder; static int g_numorder;
static int g_allverts, g_alltris;
static int g_stripverts[128]; static int g_stripverts[128];
static int g_striptris[128]; static int g_striptris[128];
static int g_stripcount; static int g_stripcount;
/*
====================
R_StudioInit
====================
*/
void R_AliasInit( void )
{
g_alias.interpolate = true;
}
/* /*
================ ================
StripLength StripLength
@ -85,7 +96,7 @@ StripLength
static int StripLength( int starttri, int startv ) static int StripLength( int starttri, int startv )
{ {
int m1, m2, j, k; int m1, m2, j, k;
mtriangle_t *last, *check; dtriangle_t *last, *check;
g_used[starttri] = 2; g_used[starttri] = 2;
@ -151,7 +162,7 @@ FanLength
static int FanLength( int starttri, int startv ) static int FanLength( int starttri, int startv )
{ {
int m1, m2, j, k; int m1, m2, j, k;
mtriangle_t *last, *check; dtriangle_t *last, *check;
g_used[starttri] = 2; g_used[starttri] = 2;
@ -290,9 +301,6 @@ void BuildTris( void )
g_commands[g_numcommands++] = 0; // end of list marker g_commands[g_numcommands++] = 0; // end of list marker
MsgDev( D_REPORT, "%3i tri %3i vert %3i cmd\n", m_pAliasHeader->numtris, g_numorder, g_numcommands ); MsgDev( D_REPORT, "%3i tri %3i vert %3i cmd\n", m_pAliasHeader->numtris, g_numorder, g_numcommands );
g_alltris += m_pAliasHeader->numtris;
g_allverts += g_numorder;
} }
/* /*
@ -300,13 +308,11 @@ void BuildTris( void )
GL_MakeAliasModelDisplayLists GL_MakeAliasModelDisplayLists
================ ================
*/ */
void GL_MakeAliasModelDisplayLists( model_t *m, aliashdr_t *hdr ) void GL_MakeAliasModelDisplayLists( model_t *m )
{ {
mtrivertex_t *verts; trivertex_t *verts;
int i, j; int i, j;
m_pAliasHeader = hdr; // (aliashdr_t *)Mod_AliasExtradata (m);
BuildTris( ); BuildTris( );
// save the data out // save the data out
@ -315,7 +321,8 @@ void GL_MakeAliasModelDisplayLists( model_t *m, aliashdr_t *hdr )
m_pAliasHeader->commands = Mem_Alloc( m->mempool, g_numcommands * 4 ); m_pAliasHeader->commands = Mem_Alloc( m->mempool, g_numcommands * 4 );
memcpy( m_pAliasHeader->commands, g_commands, g_numcommands * 4 ); memcpy( m_pAliasHeader->commands, g_commands, g_numcommands * 4 );
m_pAliasHeader->posedata = verts = Mem_Alloc( m->mempool, m_pAliasHeader->numposes * m_pAliasHeader->poseverts * sizeof( mtrivertex_t )); m_pAliasHeader->posedata = Mem_Alloc( m->mempool, m_pAliasHeader->numposes * m_pAliasHeader->poseverts * sizeof( trivertex_t ));
verts = m_pAliasHeader->posedata;
for( i = 0; i < m_pAliasHeader->numposes; i++ ) for( i = 0; i < m_pAliasHeader->numposes; i++ )
{ {
@ -338,8 +345,8 @@ Mod_LoadAliasFrame
*/ */
void *Mod_LoadAliasFrame( void *pin, maliasframedesc_t *frame ) void *Mod_LoadAliasFrame( void *pin, maliasframedesc_t *frame )
{ {
dtrivertex_t *pinframe;
daliasframe_t *pdaliasframe; daliasframe_t *pdaliasframe;
trivertex_t *pinframe;
int i; int i;
pdaliasframe = (daliasframe_t *)pin; pdaliasframe = (daliasframe_t *)pin;
@ -354,12 +361,11 @@ void *Mod_LoadAliasFrame( void *pin, maliasframedesc_t *frame )
frame->bboxmax.v[i] = pdaliasframe->bboxmax.v[i]; frame->bboxmax.v[i] = pdaliasframe->bboxmax.v[i];
} }
pinframe = (dtrivertex_t *)(pdaliasframe + 1); pinframe = (trivertex_t *)(pdaliasframe + 1);
g_poseverts[g_posenum] = (mtrivertex_t *)pinframe;
g_posenum++;
g_poseverts[g_posenum] = (trivertex_t *)pinframe;
pinframe += m_pAliasHeader->numverts; pinframe += m_pAliasHeader->numverts;
g_posenum++;
return (void *)pinframe; return (void *)pinframe;
} }
@ -390,16 +396,16 @@ void *Mod_LoadAliasGroup( void *pin, maliasframedesc_t *frame )
pin_intervals = (daliasinterval_t *)(pingroup + 1); pin_intervals = (daliasinterval_t *)(pingroup + 1);
// all the intervals are always equal 0.1 so we don't care about them
frame->interval = pin_intervals->interval; frame->interval = pin_intervals->interval;
pin_intervals += numframes; pin_intervals += numframes;
ptemp = (void *)pin_intervals; ptemp = (void *)pin_intervals;
for( i = 0; i < numframes; i++ ) for( i = 0; i < numframes; i++ )
{ {
g_poseverts[g_posenum] = (mtrivertex_t *)((daliasframe_t *)ptemp + 1); g_poseverts[g_posenum] = (trivertex_t *)((daliasframe_t *)ptemp + 1);
ptemp = (trivertex_t *)((daliasframe_t *)ptemp + 1) + m_pAliasHeader->numverts;
g_posenum++; g_posenum++;
ptemp = ((daliasframe_t *)ptemp + 1) + m_pAliasHeader->numverts;
} }
return ptemp; return ptemp;
@ -477,18 +483,28 @@ Mod_CreateSkinData
rgbdata_t *Mod_CreateSkinData( byte *data, int width, int height ) rgbdata_t *Mod_CreateSkinData( byte *data, int width, int height )
{ {
static rgbdata_t skin; static rgbdata_t skin;
int i;
skin.width = width; skin.width = width;
skin.height = height; skin.height = height;
skin.depth = 1; skin.depth = 1;
skin.type = PF_INDEXED_24; skin.type = PF_INDEXED_24;
SetBits( skin.flags, IMAGE_HAS_COLOR ); skin.flags = IMAGE_HAS_COLOR;
skin.encode = DXT_ENCODE_DEFAULT; skin.encode = DXT_ENCODE_DEFAULT;
skin.numMips = 1; skin.numMips = 1;
skin.buffer = data; skin.buffer = data;
skin.palette = (byte *)&clgame.palette; skin.palette = (byte *)&clgame.palette;
skin.size = width * height; skin.size = width * height;
for( i = 0; i < skin.width * skin.height; i++ )
{
if( data[i] > 224 && data[i] != 255 )
{
SetBits( skin.flags, IMAGE_HAS_LUMA );
break;
}
}
// make an copy // make an copy
return FS_CopyImage( &skin ); return FS_CopyImage( &skin );
} }
@ -500,10 +516,10 @@ Mod_LoadAllSkins
*/ */
void *Mod_LoadAllSkins( int numskins, daliasskintype_t *pskintype ) void *Mod_LoadAllSkins( int numskins, daliasskintype_t *pskintype )
{ {
char name[32];
daliasskingroup_t *pinskingroup;
daliasskininterval_t *pinskinintervals; daliasskininterval_t *pinskinintervals;
int size, groupskins; int size, groupskins;
string name, lumaname;
daliasskingroup_t *pinskingroup;
int i, j, k; int i, j, k;
byte *skin; byte *skin;
rgbdata_t *pic; rgbdata_t *pic;
@ -526,6 +542,7 @@ void *Mod_LoadAllSkins( int numskins, daliasskintype_t *pskintype )
memcpy( m_pAliasHeader->texels[i], (byte *)(pskintype + 1), size ); memcpy( m_pAliasHeader->texels[i], (byte *)(pskintype + 1), size );
Q_snprintf( name, sizeof( name ), "%s:frame%i", loadmodel->name, i ); Q_snprintf( name, sizeof( name ), "%s:frame%i", loadmodel->name, i );
Q_snprintf( lumaname, sizeof( lumaname ), "%s:luma%i", loadmodel->name, i );
pic = Mod_CreateSkinData( (byte *)(pskintype + 1), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight ); pic = Mod_CreateSkinData( (byte *)(pskintype + 1), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
m_pAliasHeader->gl_texturenum[i][0] = m_pAliasHeader->gl_texturenum[i][0] =
@ -533,6 +550,17 @@ void *Mod_LoadAllSkins( int numskins, daliasskintype_t *pskintype )
m_pAliasHeader->gl_texturenum[i][2] = m_pAliasHeader->gl_texturenum[i][2] =
m_pAliasHeader->gl_texturenum[i][3] = GL_LoadTextureInternal( name, pic, 0, false ); m_pAliasHeader->gl_texturenum[i][3] = GL_LoadTextureInternal( name, pic, 0, false );
FS_FreeImage( pic ); FS_FreeImage( pic );
if( R_GetTexture( m_pAliasHeader->gl_texturenum[i][0] )->flags & TF_HAS_LUMA )
{
pic = Mod_CreateSkinData( (byte *)(pskintype + 1), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
m_pAliasHeader->fb_texturenum[i][0] =
m_pAliasHeader->fb_texturenum[i][1] =
m_pAliasHeader->fb_texturenum[i][2] =
m_pAliasHeader->fb_texturenum[i][3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA, false );
FS_FreeImage( pic );
}
pskintype = (daliasskintype_t *)((byte *)(pskintype + 1) + size); pskintype = (daliasskintype_t *)((byte *)(pskintype + 1) + size);
} }
else else
@ -555,12 +583,23 @@ void *Mod_LoadAllSkins( int numskins, daliasskintype_t *pskintype )
Q_snprintf( name, sizeof( name ), "%s_%i_%i", loadmodel->name, i, j ); Q_snprintf( name, sizeof( name ), "%s_%i_%i", loadmodel->name, i, j );
pic = Mod_CreateSkinData( (byte *)(pskintype), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight ); pic = Mod_CreateSkinData( (byte *)(pskintype), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
m_pAliasHeader->gl_texturenum[i][j & 3] = GL_LoadTextureInternal( name, pic, 0, false ); m_pAliasHeader->gl_texturenum[i][j & 3] = GL_LoadTextureInternal( name, pic, 0, false );
pskintype = (daliasskintype_t *)((byte *)(pskintype) + size);
FS_FreeImage( pic ); FS_FreeImage( pic );
if( R_GetTexture( m_pAliasHeader->gl_texturenum[i][j & 3] )->flags & TF_HAS_LUMA )
{
Q_snprintf( lumaname, sizeof( lumaname ), "%s_%i_%i_luma", loadmodel->name, i, j );
pic = Mod_CreateSkinData((byte *)(pskintype), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
m_pAliasHeader->fb_texturenum[i][j & 3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA, false );
FS_FreeImage( pic );
}
pskintype = (daliasskintype_t *)((byte *)(pskintype) + size);
} }
for( k = j; j < 4; j++ ) for( k = j; j < 4; j++ )
{
m_pAliasHeader->gl_texturenum[i][j & 3] = m_pAliasHeader->gl_texturenum[i][j - k]; m_pAliasHeader->gl_texturenum[i][j & 3] = m_pAliasHeader->gl_texturenum[i][j - k];
m_pAliasHeader->fb_texturenum[i][j & 3] = m_pAliasHeader->fb_texturenum[i][j - k];
}
} }
} }
@ -573,25 +612,25 @@ void *Mod_LoadAllSkins( int numskins, daliasskintype_t *pskintype )
Mod_CalcAliasBounds Mod_CalcAliasBounds
================= =================
*/ */
void Mod_CalcAliasBounds( aliashdr_t *a ) void Mod_CalcAliasBounds( model_t *mod )
{ {
int i, j, k; int i, j, k;
float radius; float radius;
float dist; float dist;
vec3_t v; vec3_t v;
ClearBounds( loadmodel->mins, loadmodel->maxs ); ClearBounds( mod->mins, mod->maxs );
radius = 0.0f; radius = 0.0f;
// process verts // process verts
for( i = 0; i < a->numposes; i++ ) for( i = 0; i < m_pAliasHeader->numposes; i++ )
{ {
for( j = 0; j < a->numverts; j++ ) for( j = 0; j < m_pAliasHeader->numverts; j++ )
{ {
for( k = 0; k < 3; k++ ) for( k = 0; k < 3; k++ )
v[k] = g_poseverts[i][j].v[k] * m_pAliasHeader->scale[k] + m_pAliasHeader->scale_origin[k]; v[k] = g_poseverts[i][j].v[k] * m_pAliasHeader->scale[k] + m_pAliasHeader->scale_origin[k];
AddPointToBounds( v, loadmodel->mins, loadmodel->maxs ); AddPointToBounds( v, mod->mins, mod->maxs );
dist = DotProduct( v, v ); dist = DotProduct( v, v );
if( radius < dist ) if( radius < dist )
@ -599,7 +638,7 @@ void Mod_CalcAliasBounds( aliashdr_t *a )
} }
} }
loadmodel->radius = sqrt( radius ); mod->radius = sqrt( radius );
} }
/* /*
@ -631,7 +670,7 @@ void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded )
// allocate space for a working header, plus all the data except the frames, // allocate space for a working header, plus all the data except the frames,
// skin and group info // skin and group info
size = sizeof( aliashdr_t ) + (pinmodel->numframes - 1) * sizeof( m_pAliasHeader->frames[0] ); size = sizeof( aliashdr_t ) + (pinmodel->numframes - 1) * sizeof( maliasframedesc_t );
m_pAliasHeader = Mem_Alloc( mod->mempool, size ); m_pAliasHeader = Mem_Alloc( mod->mempool, size );
mod->flags = pinmodel->flags; // share effects flags mod->flags = pinmodel->flags; // share effects flags
@ -722,11 +761,12 @@ void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded )
} }
m_pAliasHeader->numposes = g_posenum; m_pAliasHeader->numposes = g_posenum;
Mod_CalcAliasBounds( m_pAliasHeader );
Mod_CalcAliasBounds( mod );
mod->type = mod_alias; mod->type = mod_alias;
// build the draw lists // build the draw lists
GL_MakeAliasModelDisplayLists( mod, m_pAliasHeader ); GL_MakeAliasModelDisplayLists( mod );
// move the complete, relocatable alias model to the cache // move the complete, relocatable alias model to the cache
loadmodel->cache.data = m_pAliasHeader; loadmodel->cache.data = m_pAliasHeader;
@ -742,7 +782,7 @@ Mod_UnloadAliasModel
void Mod_UnloadAliasModel( model_t *mod ) void Mod_UnloadAliasModel( model_t *mod )
{ {
aliashdr_t *palias; aliashdr_t *palias;
int i; int i, j;
ASSERT( mod != NULL ); ASSERT( mod != NULL );
@ -752,12 +792,16 @@ void Mod_UnloadAliasModel( model_t *mod )
palias = mod->cache.data; palias = mod->cache.data;
if( !palias ) return; // already freed if( !palias ) return; // already freed
// FIXME: check animating groups too?
for( i = 0; i < MAX_SKINS; i++ ) for( i = 0; i < MAX_SKINS; i++ )
{ {
if( !palias->gl_texturenum[i][0] ) if( !palias->gl_texturenum[i][0] )
continue; break;
GL_FreeTexture( palias->gl_texturenum[i][0] );
for( j = 0; j < 4; j++ )
{
GL_FreeTexture( palias->gl_texturenum[i][j] );
GL_FreeTexture( palias->fb_texturenum[i][j] );
}
} }
Mem_FreePool( &mod->mempool ); Mem_FreePool( &mod->mempool );
@ -962,6 +1006,10 @@ void R_AliasSetupLighting( alight_t *plight )
g_alias.shadelight = plight->shadelight; g_alias.shadelight = plight->shadelight;
VectorCopy( plight->plightvec, g_alias.lightvec ); VectorCopy( plight->plightvec, g_alias.lightvec );
VectorCopy( plight->color, g_alias.lightcolor ); VectorCopy( plight->color, g_alias.lightcolor );
// transform back to local space
Matrix4x4_VectorIRotate( RI.objectMatrix, g_alias.lightvec, g_alias.lightvec_local );
VectorNormalize( g_alias.lightvec_local );
} }
/* /*
@ -975,7 +1023,7 @@ void R_AliasLighting( float *lv, const vec3_t normal )
float illum = g_alias.ambientlight; float illum = g_alias.ambientlight;
float r, lightcos; float r, lightcos;
lightcos = DotProduct( normal, g_alias.lightvec ); // -1 colinear, 1 opposite lightcos = DotProduct( normal, g_alias.lightvec_local ); // -1 colinear, 1 opposite
if( lightcos > 1.0f ) lightcos = 1.0f; if( lightcos > 1.0f ) lightcos = 1.0f;
illum += g_alias.shadelight; illum += g_alias.shadelight;
@ -1010,8 +1058,8 @@ GL_DrawAliasFrame
void GL_DrawAliasFrame( aliashdr_t *paliashdr ) void GL_DrawAliasFrame( aliashdr_t *paliashdr )
{ {
float lv_tmp; float lv_tmp;
mtrivertex_t *verts0; trivertex_t *verts0;
mtrivertex_t *verts1; trivertex_t *verts1;
vec3_t vert, norm; vec3_t vert, norm;
int *order; int *order;
int count; int count;
@ -1040,7 +1088,15 @@ void GL_DrawAliasFrame( aliashdr_t *paliashdr )
do do
{ {
// texture coordinates come from the draw list // texture coordinates come from the draw list
pglTexCoord2f (((float *)order)[0], ((float *)order)[1]); if( glState.activeTMU > 0 )
{
GL_MultiTexCoord2f( GL_TEXTURE0, ((float *)order)[0], ((float *)order)[1] );
GL_MultiTexCoord2f( GL_TEXTURE1, ((float *)order)[0], ((float *)order)[1] );
}
else
{
pglTexCoord2f (((float *)order)[0], ((float *)order)[1]);
}
order += 2; order += 2;
VectorLerp( m_bytenormals[verts0->lightnormalindex], g_alias.lerpfrac, m_bytenormals[verts1->lightnormalindex], norm ); VectorLerp( m_bytenormals[verts0->lightnormalindex], g_alias.lerpfrac, m_bytenormals[verts1->lightnormalindex], norm );
@ -1063,8 +1119,8 @@ GL_DrawAliasShadow
*/ */
void GL_DrawAliasShadow( aliashdr_t *paliashdr ) void GL_DrawAliasShadow( aliashdr_t *paliashdr )
{ {
mtrivertex_t *verts0; trivertex_t *verts0;
mtrivertex_t *verts1; trivertex_t *verts1;
float vec_x, vec_y; float vec_x, vec_y;
vec3_t av, point; vec3_t av, point;
int *order; int *order;
@ -1133,50 +1189,87 @@ void GL_DrawAliasShadow( aliashdr_t *paliashdr )
pglDisable( GL_STENCIL_TEST ); pglDisable( GL_STENCIL_TEST );
} }
/*
====================
R_AliasLerpMovement
====================
*/
void R_AliasLerpMovement( cl_entity_t *e )
{
float f = 1.0f;
// don't do it if the goalstarttime hasn't updated in a while.
// NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit
// was increased to 1.0 s., which is 2x the max lag we are accounting for.
if( g_alias.interpolate && ( g_alias.time < e->curstate.animtime + 1.0f ) && ( e->curstate.animtime != e->latched.prevanimtime ))
f = ( g_alias.time - e->curstate.animtime ) / ( e->curstate.animtime - e->latched.prevanimtime );
g_alias.lerpfrac = bound( 0.0f, f, 1.0f );
if( e->player || e->curstate.movetype != MOVETYPE_STEP )
return; // monsters only
// Msg( "%4.2f %.2f %.2f\n", f, e->curstate.animtime, g_studio.time );
VectorLerp( e->latched.prevorigin, f, e->curstate.origin, e->origin );
if( !VectorCompare( e->curstate.angles, e->latched.prevangles ))
{
vec4_t q, q1, q2;
AngleQuaternion( e->curstate.angles, q1, false );
AngleQuaternion( e->latched.prevangles, q2, false );
QuaternionSlerp( q2, q1, f, q );
QuaternionAngle( q, e->angles );
}
else VectorCopy( e->curstate.angles, e->angles );
// NOTE: this completely over control about angles and don't broke interpolation
if( FBitSet( e->model->flags, ALIAS_ROTATE ))
e->angles[1] = anglemod( 100.0f * g_alias.time );
}
/* /*
================= =================
R_SetupAliasFrame R_SetupAliasFrame
================= =================
*/ */
void R_SetupAliasFrame( aliashdr_t *paliashdr, float f ) void R_SetupAliasFrame( cl_entity_t *e, aliashdr_t *paliashdr )
{ {
int newpose, oldpose; int newpose, oldpose;
int newframe, oldframe; int newframe, oldframe;
int oldnumposes; int numposes, cycle;
int newnumposes;
float interval; float interval;
oldframe = (int)Q_floor( f ); oldframe = e->latched.prevframe;
newframe = (int)Q_ceil( f ); newframe = e->curstate.frame;
g_alias.lerpfrac = ( cl.time * 10 );
g_alias.lerpfrac -= (int)g_alias.lerpfrac; if(( newframe >= paliashdr->numframes ) || ( newframe < 0 ))
{
MsgDev( D_ERROR, "R_SetupAliasFrame: no such frame %d\n", newframe );
newframe = 0;
}
if(( oldframe >= paliashdr->numframes ) || ( oldframe < 0 )) if(( oldframe >= paliashdr->numframes ) || ( oldframe < 0 ))
oldframe = newframe;
numposes = paliashdr->frames[newframe].numposes;
if( numposes > 1 )
{ {
MsgDev( D_ERROR, "R_SetupAliasFrame: no such frame %d\n", oldframe ); oldpose = newpose = paliashdr->frames[newframe].firstpose;
oldframe = 0; interval = 1.0f / paliashdr->frames[newframe].interval;
cycle = (int)(g_alias.time * interval);
oldpose += (cycle + 0) % numposes; // lerpframe from
newpose += (cycle + 1) % numposes; // lerpframe to
g_alias.lerpfrac = ( g_alias.time * interval );
g_alias.lerpfrac -= (int)g_alias.lerpfrac;
} }
else
if( newframe >= paliashdr->numframes )
newframe = oldframe;
oldpose = paliashdr->frames[oldframe].firstpose;
newpose = paliashdr->frames[newframe].firstpose;
oldnumposes = paliashdr->frames[oldframe].numposes;
newnumposes = paliashdr->frames[oldframe].numposes;
// FIXME: group framelerping is incorrect
if( oldnumposes > 1 )
{ {
interval = paliashdr->frames[oldframe].interval; oldpose = paliashdr->frames[oldframe].firstpose;
oldpose += (int)(cl.time / interval) % oldnumposes; newpose = paliashdr->frames[newframe].firstpose;
}
if( newnumposes > 1 )
{
interval = paliashdr->frames[newframe].interval;
newpose += (int)(cl.time / interval) % newnumposes;
} }
g_alias.oldpose = oldpose; g_alias.oldpose = oldpose;
@ -1185,6 +1278,69 @@ void R_SetupAliasFrame( aliashdr_t *paliashdr, float f )
GL_DrawAliasFrame( paliashdr ); GL_DrawAliasFrame( paliashdr );
} }
/*
===============
R_StudioDrawAbsBBox
===============
*/
static void R_AliasDrawAbsBBox( cl_entity_t *e, const vec3_t absmin, const vec3_t absmax )
{
vec3_t p[8];
int i;
// looks ugly, skip
if( r_drawentities->value != 5 || e == &clgame.viewent )
return;
// compute a full bounding box
for( i = 0; i < 8; i++ )
{
p[i][0] = ( i & 1 ) ? absmin[0] : absmax[0];
p[i][1] = ( i & 2 ) ? absmin[1] : absmax[1];
p[i][2] = ( i & 4 ) ? absmin[2] : absmax[2];
}
GL_Bind( GL_TEXTURE0, tr.whiteTexture );
TriColor4f( 0.5f, 0.5f, 1.0f, 0.5f );
TriRenderMode( kRenderTransAdd );
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
TriBegin( TRI_QUADS );
for( i = 0; i < 6; i++ )
{
TriBrightness( g_alias.shadelight / 255.0f );
TriVertex3fv( p[boxpnt[i][0]] );
TriVertex3fv( p[boxpnt[i][1]] );
TriVertex3fv( p[boxpnt[i][2]] );
TriVertex3fv( p[boxpnt[i][3]] );
}
TriEnd();
TriRenderMode( kRenderNormal );
}
/*
================
R_AliasSetupTimings
init current time for a given model
================
*/
static void R_AliasSetupTimings( void )
{
if( RI.drawWorld )
{
// synchronize with server time
g_alias.time = cl.time;
}
else
{
// menu stuff
g_alias.time = host.realtime;
}
}
/* /*
================= =================
R_DrawAliasModel R_DrawAliasModel
@ -1197,13 +1353,12 @@ void R_DrawAliasModel( cl_entity_t *e )
vec3_t absmin, absmax; vec3_t absmin, absmax;
int anim, skin; int anim, skin;
alight_t lighting; alight_t lighting;
float frame; vec3_t dir, angles;
vec3_t dir;
clmodel = RI.currententity->model; clmodel = RI.currententity->model;
VectorAdd( RI.currententity->origin, clmodel->mins, absmin ); VectorAdd( e->origin, clmodel->mins, absmin );
VectorAdd( RI.currententity->origin, clmodel->maxs, absmax ); VectorAdd( e->origin, clmodel->maxs, absmax );
if( R_CullModel( e, absmin, absmax )) if( R_CullModel( e, absmin, absmax ))
return; return;
@ -1214,15 +1369,26 @@ void R_DrawAliasModel( cl_entity_t *e )
m_pAliasHeader = (aliashdr_t *)Mod_AliasExtradata( RI.currententity->model ); m_pAliasHeader = (aliashdr_t *)Mod_AliasExtradata( RI.currententity->model );
if( !m_pAliasHeader ) return; if( !m_pAliasHeader ) return;
// init time
R_AliasSetupTimings();
// HACKHACK: keep the angles unchanged
VectorCopy( e->angles, angles );
R_AliasLerpMovement( e );
if( !FBitSet( host.features, ENGINE_COMPENSATE_QUAKE_BUG ))
e->angles[PITCH] = -e->angles[PITCH]; // stupid quake bug
// don't rotate clients, only aim
if( e->player ) e->angles[PITCH] = 0.0f;
// //
// get lighting information // get lighting information
// //
lighting.plightvec = dir; lighting.plightvec = dir;
R_AliasDynamicLight( e, &lighting ); R_AliasDynamicLight( e, &lighting );
// model and frame independant
R_AliasSetupLighting( &lighting );
r_stats.c_alias_polys += m_pAliasHeader->numtris; r_stats.c_alias_polys += m_pAliasHeader->numtris;
// //
@ -1231,28 +1397,47 @@ void R_DrawAliasModel( cl_entity_t *e )
R_RotateForEntity( e ); R_RotateForEntity( e );
pglTranslatef( m_pAliasHeader->scale_origin[0], m_pAliasHeader->scale_origin[1], m_pAliasHeader->scale_origin[2] ); // model and frame independant
pglScalef( m_pAliasHeader->scale[0], m_pAliasHeader->scale[1], m_pAliasHeader->scale[2] ); R_AliasSetupLighting( &lighting );
anim = (int)(cl.time * 10) & 3; pglTranslatef( m_pAliasHeader->scale_origin[0], m_pAliasHeader->scale_origin[1], m_pAliasHeader->scale_origin[2] );
if( tr.fFlipViewModel )
pglScalef( m_pAliasHeader->scale[0], -m_pAliasHeader->scale[1], m_pAliasHeader->scale[2] );
else pglScalef( m_pAliasHeader->scale[0], m_pAliasHeader->scale[1], m_pAliasHeader->scale[2] );
anim = (int)(g_alias.time * 10) & 3;
skin = bound( 0, RI.currententity->curstate.skin, m_pAliasHeader->numskins - 1 ); skin = bound( 0, RI.currententity->curstate.skin, m_pAliasHeader->numskins - 1 );
if( r_lightmap->value && !r_fullbright->value ) if( r_lightmap->value && !r_fullbright->value )
GL_Bind( GL_TEXTURE0, tr.whiteTexture ); GL_Bind( GL_TEXTURE0, tr.whiteTexture );
else GL_Bind( GL_TEXTURE0, m_pAliasHeader->gl_texturenum[skin][anim] ); else GL_Bind( GL_TEXTURE0, m_pAliasHeader->gl_texturenum[skin][anim] );
pglShadeModel( GL_SMOOTH );
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
frame = RI.currententity->curstate.frame; if( m_pAliasHeader->fb_texturenum[skin][anim] )
frame = fmod( cl.time * 10, m_pAliasHeader->numframes ); {
R_SetupAliasFrame( m_pAliasHeader, frame ); GL_Bind( GL_TEXTURE1, m_pAliasHeader->fb_texturenum[skin][anim] );
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD );
}
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); pglShadeModel( GL_SMOOTH );
R_SetupAliasFrame( e, m_pAliasHeader );
if( m_pAliasHeader->fb_texturenum[skin][anim] )
GL_CleanUpTextureUnits( 1 );
pglShadeModel( GL_FLAT ); pglShadeModel( GL_FLAT );
R_LoadIdentity(); R_LoadIdentity();
// get lerped origin
VectorAdd( e->origin, clmodel->mins, absmin );
VectorAdd( e->origin, clmodel->maxs, absmax );
R_AliasDrawAbsBBox( e, absmin, absmax );
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
if( r_shadows.value ) if( r_shadows.value )
{ {
// need to compute transformation matrix // need to compute transformation matrix
@ -1272,6 +1457,8 @@ void R_DrawAliasModel( cl_entity_t *e )
R_LoadIdentity(); R_LoadIdentity();
} }
// HACKHACK: keep the angles unchanged
VectorCopy( angles, e->angles );
} }
//================================================================================== //==================================================================================

View File

@ -47,7 +47,7 @@ extern byte *r_temppool;
#define RP_FLIPFRONTFACE BIT( 4 ) // e.g. for mirrors drawing #define RP_FLIPFRONTFACE BIT( 4 ) // e.g. for mirrors drawing
#define RP_NONVIEWERREF (RP_MIRRORVIEW|RP_ENVVIEW) #define RP_NONVIEWERREF (RP_MIRRORVIEW|RP_ENVVIEW)
#define R_StudioOpaque( rm ) ( rm == kRenderNormal || rm == kRenderTransAlpha ) #define R_ModelOpaque( rm ) ( rm == kRenderNormal || rm == kRenderTransAlpha )
#define RP_LOCALCLIENT( e ) ((e) != NULL && (e)->index == ( cl.playernum + 1 ) && e->player ) #define RP_LOCALCLIENT( e ) ((e) != NULL && (e)->index == ( cl.playernum + 1 ) && e->player )
#define RP_NORMALPASS() ((RI.params & RP_NONVIEWERREF) == 0 ) #define RP_NORMALPASS() ((RI.params & RP_NONVIEWERREF) == 0 )
@ -205,6 +205,7 @@ typedef struct
qboolean ignore_lightgamma; qboolean ignore_lightgamma;
qboolean fCustomRendering; qboolean fCustomRendering;
qboolean fResetVis; qboolean fResetVis;
qboolean fFlipViewModel;
byte visbytes[(MAX_MAP_LEAFS+7)/8]; // member custom PVS byte visbytes[(MAX_MAP_LEAFS+7)/8]; // member custom PVS
int lightstylevalue[MAX_LIGHTSTYLES]; // value 0 - 65536 int lightstylevalue[MAX_LIGHTSTYLES]; // value 0 - 65536
@ -430,6 +431,7 @@ void R_DrawStudioModel( cl_entity_t *e );
// //
void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded ); void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded );
void R_DrawAliasModel( cl_entity_t *e ); void R_DrawAliasModel( cl_entity_t *e );
void R_AliasInit( void );
// //
// gl_warp.c // gl_warp.c

View File

@ -55,7 +55,6 @@ typedef struct
int framecount; // studio framecount int framecount; // studio framecount
qboolean interpolate; qboolean interpolate;
int rendermode; int rendermode;
qboolean flipmodel; // viewmodel is flipped
float blend; // blend value float blend; // blend value
// bones // bones
@ -214,12 +213,12 @@ static void R_StudioSetupTimings( void )
/* /*
================ ================
R_StudioFlipViewModel R_AllowFlipViewModel
should a flip the viewmodel if cl_righthand is set to 1 should a flip the viewmodel if cl_righthand is set to 1
================ ================
*/ */
static qboolean R_StudioFlipViewModel( cl_entity_t *e ) static qboolean R_AllowFlipViewModel( cl_entity_t *e )
{ {
if( cl_righthand && cl_righthand->value > 0 ) if( cl_righthand && cl_righthand->value > 0 )
{ {
@ -537,7 +536,7 @@ void R_StudioSetUpTransform( cl_entity_t *e )
Matrix3x4_CreateFromEntity( g_studio.rotationmatrix, angles, origin, 1.0f ); Matrix3x4_CreateFromEntity( g_studio.rotationmatrix, angles, origin, 1.0f );
if( g_studio.flipmodel ) if( tr.fFlipViewModel )
{ {
g_studio.rotationmatrix[0][1] = -g_studio.rotationmatrix[0][1]; g_studio.rotationmatrix[0][1] = -g_studio.rotationmatrix[0][1];
g_studio.rotationmatrix[1][1] = -g_studio.rotationmatrix[1][1]; g_studio.rotationmatrix[1][1] = -g_studio.rotationmatrix[1][1];
@ -1933,7 +1932,7 @@ void R_LightLambert( vec4_t light[MAX_LOCALLIGHTS], vec3_t normal, vec3_t color
{ {
float r, r2; float r, r2;
if( g_studio.flipmodel ) if( tr.fFlipViewModel )
r = DotProduct( normal, light[i] ); r = DotProduct( normal, light[i] );
else r = -DotProduct( normal, light[i] ); else r = -DotProduct( normal, light[i] );
@ -2329,7 +2328,7 @@ static void R_StudioDrawPoints( void )
pglAlphaFunc( GL_GREATER, 0.5f ); pglAlphaFunc( GL_GREATER, 0.5f );
pglDepthMask( GL_TRUE ); pglDepthMask( GL_TRUE );
} }
else if( FBitSet( g_nFaceFlags, STUDIO_NF_ADDITIVE ) && R_StudioOpaque( RI.currententity->curstate.rendermode )) else if( FBitSet( g_nFaceFlags, STUDIO_NF_ADDITIVE ) && R_ModelOpaque( RI.currententity->curstate.rendermode ))
{ {
pglBlendFunc( GL_SRC_ALPHA, GL_ONE ); pglBlendFunc( GL_SRC_ALPHA, GL_ONE );
pglDepthMask( GL_FALSE ); pglDepthMask( GL_FALSE );
@ -2349,7 +2348,7 @@ static void R_StudioDrawPoints( void )
pglAlphaFunc( GL_NOTEQUAL, 0.0f ); pglAlphaFunc( GL_NOTEQUAL, 0.0f );
pglDisable( GL_ALPHA_TEST ); pglDisable( GL_ALPHA_TEST );
} }
else if( FBitSet( g_nFaceFlags, STUDIO_NF_ADDITIVE ) && R_StudioOpaque( RI.currententity->curstate.rendermode )) else if( FBitSet( g_nFaceFlags, STUDIO_NF_ADDITIVE ) && R_ModelOpaque( RI.currententity->curstate.rendermode ))
{ {
pglDepthMask( GL_TRUE ); pglDepthMask( GL_TRUE );
pglDisable( GL_BLEND ); pglDisable( GL_BLEND );
@ -3443,7 +3442,7 @@ void R_RunViewmodelEvents( void )
RI.currententity = &clgame.viewent; RI.currententity = &clgame.viewent;
if( !RI.currententity->model ) if( !RI.currententity->model || RI.currententity->model->type != mod_studio )
return; return;
R_StudioSetupTimings(); R_StudioSetupTimings();
@ -3478,7 +3477,7 @@ void R_DrawViewModel( void )
return; return;
tr.blend = CL_FxBlend( view ) / 255.0f; tr.blend = CL_FxBlend( view ) / 255.0f;
if( !R_StudioOpaque( view->curstate.rendermode ) && tr.blend <= 0.0f ) if( !R_ModelOpaque( view->curstate.rendermode ) && tr.blend <= 0.0f )
return; // invisible ? return; // invisible ?
RI.currententity = view; RI.currententity = view;
@ -3486,29 +3485,36 @@ void R_DrawViewModel( void )
if( !RI.currententity->model ) if( !RI.currententity->model )
return; return;
R_StudioSetupTimings();
// hack the depth range to prevent view model from poking into walls // hack the depth range to prevent view model from poking into walls
pglDepthRange( gldepthmin, gldepthmin + 0.3f * ( gldepthmax - gldepthmin )); pglDepthRange( gldepthmin, gldepthmin + 0.3f * ( gldepthmax - gldepthmin ));
RI.currentmodel = RI.currententity->model; RI.currentmodel = RI.currententity->model;
// backface culling for left-handed weapons // backface culling for left-handed weapons
if( R_StudioFlipViewModel( RI.currententity ) || g_iBackFaceCull ) if( R_AllowFlipViewModel( RI.currententity ) || g_iBackFaceCull )
{ {
GL_FrontFace( !glState.frontFace ); GL_FrontFace( !glState.frontFace );
g_studio.flipmodel = true; tr.fFlipViewModel = true;
} }
R_StudioDrawModelInternal( RI.currententity, STUDIO_RENDER ); switch( RI.currententity->model->type )
{
case mod_alias:
R_DrawAliasModel( RI.currententity );
break;
case mod_studio:
R_StudioSetupTimings();
R_StudioDrawModelInternal( RI.currententity, STUDIO_RENDER );
break;
}
// restore depth range // restore depth range
pglDepthRange( gldepthmin, gldepthmax ); pglDepthRange( gldepthmin, gldepthmax );
// backface culling for left-handed weapons // backface culling for left-handed weapons
if( R_StudioFlipViewModel( RI.currententity ) || g_iBackFaceCull ) if( R_AllowFlipViewModel( RI.currententity ) || g_iBackFaceCull )
{ {
GL_FrontFace( !glState.frontFace ); GL_FrontFace( !glState.frontFace );
g_studio.flipmodel = false; tr.fFlipViewModel = false;
} }
} }

View File

@ -1880,6 +1880,7 @@ qboolean R_Init( void )
R_InitImages(); R_InitImages();
R_SpriteInit(); R_SpriteInit();
R_StudioInit(); R_StudioInit();
R_AliasInit();
R_ClearDecals(); R_ClearDecals();
R_ClearScene(); R_ClearScene();

View File

@ -1178,7 +1178,7 @@ void Cmd_Init( void )
Cmd_AddCommand( "echo", Cmd_Echo_f, "print a message to the console (useful in scripts)" ); Cmd_AddCommand( "echo", Cmd_Echo_f, "print a message to the console (useful in scripts)" );
Cmd_AddCommand( "wait", Cmd_Wait_f, "make script execution wait for some rendered frames" ); Cmd_AddCommand( "wait", Cmd_Wait_f, "make script execution wait for some rendered frames" );
Cmd_AddCommand( "cmdlist", Cmd_List_f, "display all console commands beginning with the specified prefix" ); Cmd_AddCommand( "cmdlist", Cmd_List_f, "display all console commands beginning with the specified prefix" );
Cmd_AddCommand( "stuffcmds", Cmd_StuffCmds_f, va( "execute commandline parameters (must be present in %s.rc script)", SI.ModuleName )); Cmd_AddCommand( "stuffcmds", Cmd_StuffCmds_f, "execute commandline parameters (must be present in .rc script)" );
Cmd_AddCommand( "cmd", Cmd_ForwardToServer, "send a console commandline to the server" ); Cmd_AddCommand( "cmd", Cmd_ForwardToServer, "send a console commandline to the server" );
Cmd_AddCommand( "alias", Cmd_Alias_f, "create a script function. Without arguments show the list of all alias" ); Cmd_AddCommand( "alias", Cmd_Alias_f, "create a script function. Without arguments show the list of all alias" );
Cmd_AddCommand( "unalias", Cmd_UnAlias_f, "remove a script function" ); Cmd_AddCommand( "unalias", Cmd_UnAlias_f, "remove a script function" );

View File

@ -44,6 +44,7 @@ extern "C" {
#define BIT( n ) (1<<( n )) #define BIT( n ) (1<<( n ))
#define GAMMA ( 2.2 ) // Valve Software gamma #define GAMMA ( 2.2 ) // Valve Software gamma
#define INVGAMMA ( 1.0 / 2.2 ) // back to 1.0 #define INVGAMMA ( 1.0 / 2.2 ) // back to 1.0
#define TEXGAMMA ( 0.9 ) // compensate dim textures
#define SetBits( iBitVector, bits ) ((iBitVector) = (iBitVector) | (bits)) #define SetBits( iBitVector, bits ) ((iBitVector) = (iBitVector) | (bits))
#define ClearBits( iBitVector, bits ) ((iBitVector) = (iBitVector) & ~(bits)) #define ClearBits( iBitVector, bits ) ((iBitVector) = (iBitVector) & ~(bits))
#define FBitSet( iBitVector, bit ) ((iBitVector) & (bit)) #define FBitSet( iBitVector, bit ) ((iBitVector) & (bit))
@ -211,7 +212,9 @@ typedef struct gameinfo_s
typedef struct sysinfo_s typedef struct sysinfo_s
{ {
string ModuleName; // exe.filename string exeName; // exe.filename
string rcName; // .rc script name
string basedirName; // name of base directory
gameinfo_t *GameInfo; // current GameInfo gameinfo_t *GameInfo; // current GameInfo
gameinfo_t *games[MAX_MODS]; // environment games (founded at each engine start) gameinfo_t *games[MAX_MODS]; // environment games (founded at each engine start)
int numgames; int numgames;

View File

@ -863,6 +863,10 @@ void FS_Rescan( void )
if( Q_stricmp( GI->basedir, GI->falldir ) && Q_stricmp( GI->gamedir, GI->falldir )) if( Q_stricmp( GI->basedir, GI->falldir ) && Q_stricmp( GI->gamedir, GI->falldir ))
FS_AddGameHierarchy( GI->falldir, 0 ); FS_AddGameHierarchy( GI->falldir, 0 );
FS_AddGameHierarchy( GI->gamedir, FS_GAMEDIR_PATH ); FS_AddGameHierarchy( GI->gamedir, FS_GAMEDIR_PATH );
if( FS_FileExists( va( "%s.rc", SI.basedirName ), false ))
Q_strncpy( SI.rcName, SI.basedirName, sizeof( SI.rcName )); // e.g. valve.rc
else Q_strncpy( SI.rcName, SI.exeName, sizeof( SI.rcName )); // e.g. quake.rc
} }
/* /*
@ -989,7 +993,7 @@ void FS_CreateDefaultGameInfo( const char *filename )
Q_strncpy( defGI.title, "New Game", sizeof( defGI.title )); Q_strncpy( defGI.title, "New Game", sizeof( defGI.title ));
Q_strncpy( defGI.gamedir, gs_basedir, sizeof( defGI.gamedir )); Q_strncpy( defGI.gamedir, gs_basedir, sizeof( defGI.gamedir ));
Q_strncpy( defGI.basedir, SI.ModuleName, sizeof( defGI.basedir )); Q_strncpy( defGI.basedir, SI.basedirName, sizeof( defGI.basedir ));
Q_strncpy( defGI.sp_entity, "info_player_start", sizeof( defGI.sp_entity )); Q_strncpy( defGI.sp_entity, "info_player_start", sizeof( defGI.sp_entity ));
Q_strncpy( defGI.mp_entity, "info_player_deathmatch", sizeof( defGI.mp_entity )); Q_strncpy( defGI.mp_entity, "info_player_deathmatch", sizeof( defGI.mp_entity ));
Q_strncpy( defGI.dll_path, "cl_dlls", sizeof( defGI.dll_path )); Q_strncpy( defGI.dll_path, "cl_dlls", sizeof( defGI.dll_path ));
@ -1025,7 +1029,7 @@ static qboolean FS_ParseLiblistGam( const char *filename, const char *gamedir, g
Q_strncpy( GameInfo->title, "New Game", sizeof( GameInfo->title )); Q_strncpy( GameInfo->title, "New Game", sizeof( GameInfo->title ));
Q_strncpy( GameInfo->gamedir, gamedir, sizeof( GameInfo->gamedir )); Q_strncpy( GameInfo->gamedir, gamedir, sizeof( GameInfo->gamedir ));
Q_strncpy( GameInfo->basedir, SI.ModuleName, sizeof( GameInfo->basedir )); Q_strncpy( GameInfo->basedir, SI.basedirName, sizeof( GameInfo->basedir ));
Q_strncpy( GameInfo->sp_entity, "info_player_start", sizeof( GameInfo->sp_entity )); Q_strncpy( GameInfo->sp_entity, "info_player_start", sizeof( GameInfo->sp_entity ));
Q_strncpy( GameInfo->mp_entity, "info_player_deathmatch", sizeof( GameInfo->mp_entity )); Q_strncpy( GameInfo->mp_entity, "info_player_deathmatch", sizeof( GameInfo->mp_entity ));
Q_strncpy( GameInfo->game_dll, "dlls/hl.dll", sizeof( GameInfo->game_dll )); Q_strncpy( GameInfo->game_dll, "dlls/hl.dll", sizeof( GameInfo->game_dll ));
@ -1409,18 +1413,18 @@ void FS_Init( void )
SI.numgames = 0; SI.numgames = 0;
if( !Sys_GetParmFromCmdLine( "-game", gs_basedir )) if( !Sys_GetParmFromCmdLine( "-game", gs_basedir ))
Q_strcpy( gs_basedir, SI.ModuleName ); // default dir Q_strcpy( gs_basedir, SI.basedirName ); // default dir
if( FS_CheckNastyPath( gs_basedir, true )) if( FS_CheckNastyPath( gs_basedir, true ))
{ {
MsgDev( D_ERROR, "FS_Init: invalid game directory \"%s\"\n", gs_basedir ); MsgDev( D_ERROR, "FS_Init: invalid game directory \"%s\"\n", gs_basedir );
Q_strcpy( gs_basedir, SI.ModuleName ); // default dir Q_strcpy( gs_basedir, SI.basedirName ); // default dir
} }
// validate directories // validate directories
for( i = 0; i < dirs.numstrings; i++ ) for( i = 0; i < dirs.numstrings; i++ )
{ {
if( !Q_stricmp( SI.ModuleName, dirs.strings[i] )) if( !Q_stricmp( SI.basedirName, dirs.strings[i] ))
hasDefaultDir = true; hasDefaultDir = true;
if( !Q_stricmp( gs_basedir, dirs.strings[i] )) if( !Q_stricmp( gs_basedir, dirs.strings[i] ))
@ -1430,7 +1434,7 @@ void FS_Init( void )
if( i == dirs.numstrings ) if( i == dirs.numstrings )
{ {
MsgDev( D_INFO, "FS_Init: game directory \"%s\" not exist\n", gs_basedir ); MsgDev( D_INFO, "FS_Init: game directory \"%s\" not exist\n", gs_basedir );
if( hasDefaultDir ) Q_strncpy( gs_basedir, SI.ModuleName, sizeof( gs_basedir )); // default dir if( hasDefaultDir ) Q_strncpy( gs_basedir, SI.basedirName, sizeof( gs_basedir )); // default dir
} }
// build list of game directories here // build list of game directories here

View File

@ -62,7 +62,7 @@ void BuildGammaTable( float lightgamma, float brightness )
for( i = 0; i < 256; i++ ) for( i = 0; i < 256; i++ )
{ {
f = 255.0 * pow(( float )i / 255.0f, g1 ); f = 255.0 * pow(( float )i / 255.0f, TEXGAMMA );
inf = (int)(f + 0.5f); inf = (int)(f + 0.5f);
texgammatable[i] = bound( 0, inf, 255 ); texgammatable[i] = bound( 0, inf, 255 );
} }

View File

@ -831,7 +831,7 @@ void Host_InitCommon( const char *hostname, qboolean bChangeGame )
// we can specified custom name, from Sys_NewInstance // we can specified custom name, from Sys_NewInstance
if( GetModuleFileName( NULL, szTemp, sizeof( szTemp )) && !host.change_game ) if( GetModuleFileName( NULL, szTemp, sizeof( szTemp )) && !host.change_game )
FS_FileBase( szTemp, SI.ModuleName ); FS_FileBase( szTemp, SI.exeName );
FS_ExtractFilePath( szTemp, szRootPath ); FS_ExtractFilePath( szTemp, szRootPath );
if( Q_stricmp( host.rootdir, szRootPath )) if( Q_stricmp( host.rootdir, szRootPath ))
@ -840,15 +840,15 @@ void Host_InitCommon( const char *hostname, qboolean bChangeGame )
SetCurrentDirectory( host.rootdir ); SetCurrentDirectory( host.rootdir );
} }
if( SI.ModuleName[0] == '#' ) host.type = HOST_DEDICATED; if( SI.exeName[0] == '#' ) host.type = HOST_DEDICATED;
// determine host type // determine host type
if( progname[0] == '#' ) if( progname[0] == '#' )
{ {
Q_strncpy( SI.ModuleName, progname + 1, sizeof( SI.ModuleName )); Q_strncpy( SI.basedirName, progname + 1, sizeof( SI.basedirName ));
host.type = HOST_DEDICATED; host.type = HOST_DEDICATED;
} }
else Q_strncpy( SI.ModuleName, progname, sizeof( SI.ModuleName )); else Q_strncpy( SI.basedirName, progname, sizeof( SI.basedirName ));
if( Sys_CheckParm( "-dedicated" )) if( Sys_CheckParm( "-dedicated" ))
host.type = HOST_DEDICATED; host.type = HOST_DEDICATED;
@ -996,7 +996,7 @@ int EXPORT Host_Main( const char *progname, int bChangeGame, pfnChangeGame func
case HOST_NORMAL: case HOST_NORMAL:
Con_ShowConsole( false ); // hide console Con_ShowConsole( false ); // hide console
// execute startup config and cmdline // execute startup config and cmdline
Cbuf_AddText( va( "exec %s.rc\n", SI.ModuleName )); Cbuf_AddText( va( "exec %s.rc\n", SI.rcName ));
Cbuf_Execute(); Cbuf_Execute();
if( !host.config_executed ) if( !host.config_executed )
{ {

View File

@ -37,8 +37,8 @@ keyname_t keynames[] =
{ {
{"TAB", K_TAB, "" }, {"TAB", K_TAB, "" },
{"ENTER", K_ENTER, "" }, {"ENTER", K_ENTER, "" },
{"ESCAPE", K_ESCAPE, "cancelselect" }, // hardcoded {"ESCAPE", K_ESCAPE, "escape" }, // hardcoded
{"SPACE", K_SPACE, "+moveup" }, {"SPACE", K_SPACE, "+jump" },
{"BACKSPACE", K_BACKSPACE, "" }, {"BACKSPACE", K_BACKSPACE, "" },
{"UPARROW", K_UPARROW, "+forward" }, {"UPARROW", K_UPARROW, "+forward" },
{"DOWNARROW", K_DOWNARROW, "+back" }, {"DOWNARROW", K_DOWNARROW, "+back" },
@ -59,7 +59,7 @@ keyname_t keynames[] =
{"F9", K_F9, "" }, {"F9", K_F9, "" },
{"F10", K_F10, "menu_main" }, {"F10", K_F10, "menu_main" },
{"F11", K_F11, "" }, {"F11", K_F11, "" },
{"F12", K_F12, "screenshot" }, {"F12", K_F12, "snapshot" },
{"INS", K_INS, "" }, {"INS", K_INS, "" },
{"DEL", K_DEL, "+lookdown" }, {"DEL", K_DEL, "+lookdown" },
{"PGDN", K_PGDN, "+lookup" }, {"PGDN", K_PGDN, "+lookup" },

View File

@ -956,7 +956,7 @@ static void Mod_LoadTextures( const dlump_t *l )
int size = (int)sizeof( mip_t ) + ((mt->width * mt->height * 85)>>6); int size = (int)sizeof( mip_t ) + ((mt->width * mt->height * 85)>>6);
if( bmodel_version >= HLBSP_VERSION ) size += sizeof( short ) + 768; if( bmodel_version >= HLBSP_VERSION ) size += sizeof( short ) + 768;
tx->fb_texturenum = GL_LoadTexture( texname, (byte *)mt, size, TF_NOMIPMAP|TF_MAKELUMA, NULL ); tx->fb_texturenum = GL_LoadTexture( texname, (byte *)mt, size, TF_MAKELUMA, NULL );
} }
else else
{ {
@ -982,7 +982,7 @@ static void Mod_LoadTextures( const dlump_t *l )
} }
// okay, loading it from wad or hi-res version // okay, loading it from wad or hi-res version
tx->fb_texturenum = GL_LoadTexture( texname, src, srcSize, TF_NOMIPMAP|TF_MAKELUMA, NULL ); tx->fb_texturenum = GL_LoadTexture( texname, src, srcSize, TF_MAKELUMA, NULL );
if( src ) Mem_Free( src ); if( src ) Mem_Free( src );
if( !tx->fb_texturenum && load_external_luma ) if( !tx->fb_texturenum && load_external_luma )

View File

@ -621,6 +621,7 @@ void SV_InitSaveRestore( void );
// //
void SV_GetTrueOrigin( sv_client_t *cl, int edictnum, vec3_t origin ); void SV_GetTrueOrigin( sv_client_t *cl, int edictnum, vec3_t origin );
void SV_GetTrueMinMax( sv_client_t *cl, int edictnum, vec3_t mins, vec3_t maxs ); void SV_GetTrueMinMax( sv_client_t *cl, int edictnum, vec3_t mins, vec3_t maxs );
qboolean SV_PlayerIsFrozen( edict_t *pClient );
// //
// sv_world.c // sv_world.c

View File

@ -2289,7 +2289,7 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
cl->packet_loss = packet_loss; cl->packet_loss = packet_loss;
// check for pause or frozen // check for pause or frozen
if( sv.paused || sv.loadgame || sv.background || !CL_IsInGame() || ( player->v.flags & FL_FROZEN )) if( sv.paused || sv.loadgame || sv.background || !CL_IsInGame() || SV_PlayerIsFrozen( player ))
{ {
for( i = 0; i < numcmds; i++ ) for( i = 0; i < numcmds; i++ )
{ {
@ -2299,7 +2299,7 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
cmds[i].upmove = 0; cmds[i].upmove = 0;
cmds[i].buttons = 0; cmds[i].buttons = 0;
if( player->v.flags & FL_FROZEN || sv.background ) if( SV_PlayerIsFrozen( player ) || sv.background )
cmds[i].impulse = 0; cmds[i].impulse = 0;
VectorCopy( cmds[i].viewangles, player->v.v_angle ); VectorCopy( cmds[i].viewangles, player->v.v_angle );
@ -2345,8 +2345,11 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
frame->ping_time -= cl->lastcmd.msec * 0.5f / 1000.0f; frame->ping_time -= cl->lastcmd.msec * 0.5f / 1000.0f;
frame->ping_time = Q_max( 0.0f, frame->ping_time ); frame->ping_time = Q_max( 0.0f, frame->ping_time );
if( player->v.animtime > svgame.globals->time + sv.frametime ) if( Mod_GetType( player->v.modelindex ) == mod_studio )
player->v.animtime = svgame.globals->time + sv.frametime; {
if( player->v.animtime > svgame.globals->time + sv.frametime )
player->v.animtime = svgame.globals->time + sv.frametime;
}
} }
/* /*

View File

@ -164,7 +164,9 @@ float SV_AngleMod( float ideal, float current, float speed )
{ {
float move; float move;
if( anglemod( current ) == ideal ) // already there? current = anglemod( current );
if( current == ideal ) // already there?
return current; return current;
move = ideal - current; move = ideal - current;
@ -2566,9 +2568,9 @@ void pfnMessageEnd( void )
MSG_Clear( &sv.multicast ); MSG_Clear( &sv.multicast );
return; return;
} }
}
sv.multicast.pData[svgame.msg_size_index] = svgame.msg_realsize; sv.multicast.pData[svgame.msg_size_index] = svgame.msg_realsize;
}
} }
else if( svgame.msg[svgame.msg_index].size != -1 ) else if( svgame.msg[svgame.msg_index].size != -1 )
{ {
@ -2919,15 +2921,30 @@ SV_AllocString
allocate new engine string allocate new engine string
============= =============
*/ */
string_t SV_AllocString( const char *szValue ) string_t SV_AllocString( const char *szString )
{ {
const char *newString; char *out, *out_p;
int i, l;
if( svgame.physFuncs.pfnAllocString != NULL ) if( svgame.physFuncs.pfnAllocString != NULL )
return svgame.physFuncs.pfnAllocString( szValue ); return svgame.physFuncs.pfnAllocString( szString );
newString = _copystring( svgame.stringspool, szValue, __FILE__, __LINE__ ); l = Q_strlen( szString ) + 1;
return newString - svgame.globals->pStringBase;
out = out_p = Mem_Alloc( svgame.stringspool, l );
for( i = 0; i < l; i++ )
{
if( szString[i] == '\\' && i < l - 1 )
{
i++;
if( szString[i] == 'n')
*out_p++ = '\n';
else *out_p++ = '\\';
}
else *out_p++ = szString[i];
}
return out - svgame.globals->pStringBase;
} }
/* /*

View File

@ -37,6 +37,16 @@ void SV_ConvertPMTrace( trace_t *out, pmtrace_t *in, edict_t *ent )
out->ent = ent; out->ent = ent;
} }
qboolean SV_PlayerIsFrozen( edict_t *pClient )
{
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
return false;
if( FBitSet( pClient->v.flags, FL_FROZEN ))
return true;
return false;
}
void SV_ClipPMoveToEntity( physent_t *pe, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, pmtrace_t *tr ) void SV_ClipPMoveToEntity( physent_t *pe, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, pmtrace_t *tr )
{ {
ASSERT( tr != NULL ); ASSERT( tr != NULL );
@ -728,14 +738,14 @@ static void SV_FinishPMove( playermove_t *pmove, sv_client_t *cl )
VectorCopy( pmove->vuser3, clent->v.vuser3 ); VectorCopy( pmove->vuser3, clent->v.vuser3 );
VectorCopy( pmove->vuser4, clent->v.vuser4 ); VectorCopy( pmove->vuser4, clent->v.vuser4 );
if( svgame.pmove->onground == -1 ) if( pmove->onground == -1 )
{ {
clent->v.flags &= ~FL_ONGROUND; clent->v.flags &= ~FL_ONGROUND;
} }
else if( pmove->onground >= 0 && pmove->onground < pmove->numphysent ) else if( pmove->onground >= 0 && pmove->onground < pmove->numphysent )
{ {
clent->v.flags |= FL_ONGROUND; clent->v.flags |= FL_ONGROUND;
clent->v.groundentity = EDICT_NUM( svgame.pmove->physents[svgame.pmove->onground].info ); clent->v.groundentity = EDICT_NUM( pmove->physents[pmove->onground].info );
} }
// angles // angles