10 Mar 2018
This commit is contained in:
parent
49c19a90ab
commit
e96b555d6b
|
@ -19,6 +19,7 @@
|
||||||
#include "pm_defs.h"
|
#include "pm_defs.h"
|
||||||
#include "pmtrace.h"
|
#include "pmtrace.h"
|
||||||
#include "pm_shared.h"
|
#include "pm_shared.h"
|
||||||
|
#include "com_weapons.h"
|
||||||
|
|
||||||
#define DLLEXPORT __declspec( dllexport )
|
#define DLLEXPORT __declspec( dllexport )
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@ void Game_AddObjects( void );
|
||||||
extern vec3_t v_origin;
|
extern vec3_t v_origin;
|
||||||
|
|
||||||
int g_iAlive = 1;
|
int g_iAlive = 1;
|
||||||
|
int g_iLaserDot = 0;
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
@ -89,6 +91,8 @@ void DLLEXPORT HUD_TxferLocalOverrides( struct entity_state_s *state, const stru
|
||||||
{
|
{
|
||||||
VectorCopy( client->origin, state->origin );
|
VectorCopy( client->origin, state->origin );
|
||||||
|
|
||||||
|
g_iLaserDot = (client->flags & FL_LASERDOT) ? 1 : 0;
|
||||||
|
|
||||||
// Spectator
|
// Spectator
|
||||||
state->iuser1 = client->iuser1;
|
state->iuser1 = client->iuser1;
|
||||||
state->iuser2 = client->iuser2;
|
state->iuser2 = client->iuser2;
|
||||||
|
@ -504,6 +508,60 @@ void Beams( void )
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
TEMPENTITY *m_pLaserSpot = NULL;
|
||||||
|
|
||||||
|
void CL_UpdateLaserSpot( void )
|
||||||
|
{
|
||||||
|
cl_entity_t *player = gEngfuncs.GetLocalPlayer();
|
||||||
|
|
||||||
|
if( !player ) return;
|
||||||
|
|
||||||
|
if(( g_iLaserDot && cl_lw->value ) && !m_pLaserSpot )
|
||||||
|
{
|
||||||
|
// create laserspot
|
||||||
|
int m_iSpotModel = gEngfuncs.pEventAPI->EV_FindModelIndex( "sprites/laserdot.spr" );
|
||||||
|
|
||||||
|
m_pLaserSpot = gEngfuncs.pEfxAPI->R_TempSprite( Vector( 0, 0, 0), Vector( 0, 0, 0), 1.0, m_iSpotModel, kRenderGlow, kRenderFxNoDissipation, 1.0, 9999, FTENT_SPRCYCLE );
|
||||||
|
if( !m_pLaserSpot ) return;
|
||||||
|
|
||||||
|
m_pLaserSpot->entity.curstate.rendercolor.r = 200;
|
||||||
|
m_pLaserSpot->entity.curstate.rendercolor.g = 12;
|
||||||
|
m_pLaserSpot->entity.curstate.rendercolor.b = 12;
|
||||||
|
// gEngfuncs.Con_Printf( "CLaserSpot::Create()\n" );
|
||||||
|
}
|
||||||
|
else if(( !g_iLaserDot || !cl_lw->value ) && m_pLaserSpot )
|
||||||
|
{
|
||||||
|
// destroy laserspot
|
||||||
|
// gEngfuncs.Con_Printf( "CLaserSpot::Killed()\n" );
|
||||||
|
m_pLaserSpot->die = 0.0f;
|
||||||
|
m_pLaserSpot = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if( !m_pLaserSpot )
|
||||||
|
{
|
||||||
|
// inactive
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert( m_pLaserSpot != NULL );
|
||||||
|
|
||||||
|
Vector forward, vecSrc, vecEnd, origin, angles, view_ofs;
|
||||||
|
|
||||||
|
gEngfuncs.GetViewAngles( (float *)angles );
|
||||||
|
|
||||||
|
AngleVectors( angles, forward, NULL, NULL );
|
||||||
|
gEngfuncs.pEventAPI->EV_LocalPlayerViewheight( view_ofs );
|
||||||
|
|
||||||
|
vecSrc = player->origin + view_ofs;
|
||||||
|
vecEnd = vecSrc + forward * 8192.0f;
|
||||||
|
|
||||||
|
pmtrace_t *trace = gEngfuncs.PM_TraceLine( vecSrc, vecEnd, PM_TRACELINE_ANYVISIBLE, 2, -1 );
|
||||||
|
|
||||||
|
// update laserspot endpos
|
||||||
|
m_pLaserSpot->entity.origin = trace->endpos;
|
||||||
|
m_pLaserSpot->die = gEngfuncs.GetClientTime() + 0.1f;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=========================
|
=========================
|
||||||
HUD_CreateEntities
|
HUD_CreateEntities
|
||||||
|
@ -535,6 +593,8 @@ void DLLEXPORT HUD_CreateEntities( void )
|
||||||
#if defined( BEAM_TEST )
|
#if defined( BEAM_TEST )
|
||||||
Beams();
|
Beams();
|
||||||
#endif
|
#endif
|
||||||
|
// predictable laserdot
|
||||||
|
CL_UpdateLaserSpot();
|
||||||
|
|
||||||
// Add in any game specific objects
|
// Add in any game specific objects
|
||||||
Game_AddObjects();
|
Game_AddObjects();
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#define FL_ONTRAIN (1<<24) // Player is _controlling_ a train, so movement commands should be ignored on client during prediction.
|
#define FL_ONTRAIN (1<<24) // Player is _controlling_ a train, so movement commands should be ignored on client during prediction.
|
||||||
#define FL_WORLDBRUSH (1<<25) // Not moveable/removeable brush entity (really part of the world, but represented as an entity for transparency or something)
|
#define FL_WORLDBRUSH (1<<25) // Not moveable/removeable brush entity (really part of the world, but represented as an entity for transparency or something)
|
||||||
#define FL_SPECTATOR (1<<26) // This client is a spectator, don't run touch functions, etc.
|
#define FL_SPECTATOR (1<<26) // This client is a spectator, don't run touch functions, etc.
|
||||||
|
#define FL_LASERDOT (1<<27) // Predicted laser spot from rocket launcher
|
||||||
|
|
||||||
#define FL_CUSTOMENTITY (1<<29) // This is a custom entity
|
#define FL_CUSTOMENTITY (1<<29) // This is a custom entity
|
||||||
#define FL_KILLME (1<<30) // This entity is marked for death -- This allows the engine to kill ents at the appropriate time
|
#define FL_KILLME (1<<30) // This entity is marked for death -- This allows the engine to kill ents at the appropriate time
|
||||||
|
@ -113,8 +114,6 @@
|
||||||
#define EF_LIGHT 64 // rocket flare glow sprite
|
#define EF_LIGHT 64 // rocket flare glow sprite
|
||||||
#define EF_NODRAW 128 // don't draw entity
|
#define EF_NODRAW 128 // don't draw entity
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define EF_WATERSIDES (1<<26) // Do not remove sides for func_water entity
|
#define EF_WATERSIDES (1<<26) // Do not remove sides for func_water entity
|
||||||
#define EF_FULLBRIGHT (1<<27) // Just get fullbright
|
#define EF_FULLBRIGHT (1<<27) // Just get fullbright
|
||||||
#define EF_NOSHADOW (1<<28) // ignore shadow for this entity
|
#define EF_NOSHADOW (1<<28) // ignore shadow for this entity
|
||||||
|
|
|
@ -44,8 +44,6 @@ typedef struct event_api_s
|
||||||
void ( *EV_KillEvents )( int entnum, const char *eventname );
|
void ( *EV_KillEvents )( int entnum, const char *eventname );
|
||||||
|
|
||||||
// Xash3D extension
|
// Xash3D extension
|
||||||
unsigned short (*EV_IndexForEvent)( const char *name );
|
|
||||||
const char *(*EV_EventForIndex)( unsigned short index );
|
|
||||||
void ( *EV_PlayerTraceExt )( float *start, float *end, int traceFlags, int (*pfnIgnore)( struct physent_s *pe ), struct pmtrace_s *tr );
|
void ( *EV_PlayerTraceExt )( float *start, float *end, int traceFlags, int (*pfnIgnore)( struct physent_s *pe ), struct pmtrace_s *tr );
|
||||||
const char *(*EV_SoundForIndex)( int index );
|
const char *(*EV_SoundForIndex)( int index );
|
||||||
struct msurface_s *( *EV_TraceSurface )( int ground, float *vstart, float *vend );
|
struct msurface_s *( *EV_TraceSurface )( int ground, float *vstart, float *vend );
|
||||||
|
|
|
@ -209,13 +209,13 @@ typedef struct render_api_s
|
||||||
|
|
||||||
// Misc renderer functions
|
// Misc renderer functions
|
||||||
void (*GL_DrawParticles)( const struct ref_viewpass_s *rvp, qboolean trans_pass, float frametime );
|
void (*GL_DrawParticles)( const struct ref_viewpass_s *rvp, qboolean trans_pass, float frametime );
|
||||||
void (*EnvShot)( const float *vieworg, const char *name, qboolean skyshot, int shotsize ); // creates a cubemap or skybox into gfx\env folder
|
void (*EnvShot)( const float *vieworg, const char *name, qboolean skyshot, int shotsize ); // store skybox into gfx\env folder
|
||||||
int (*SPR_LoadExt)( const char *szPicName, unsigned int texFlags ); // extended version of SPR_Load
|
int (*SPR_LoadExt)( const char *szPicName, unsigned int texFlags ); // extended version of SPR_Load
|
||||||
colorVec (*LightVec)( const float *start, const float *end, float *lightspot );
|
colorVec (*LightVec)( const float *start, const float *end, float *lightspot );
|
||||||
struct mstudiotex_s *( *StudioGetTexture )( struct cl_entity_s *e );
|
struct mstudiotex_s *( *StudioGetTexture )( struct cl_entity_s *e );
|
||||||
const struct ref_overview_s *( *GetOverviewParms )( void );
|
const struct ref_overview_s *( *GetOverviewParms )( void );
|
||||||
void (*R_Reserved0)( void ); // for potential interface expansion without broken compatibility
|
const char *( *GetFileByIndex )( int fileindex );
|
||||||
void (*R_Reserved1)( void );
|
void (*R_Reserved1)( void ); // for potential interface expansion without broken compatibility
|
||||||
void (*R_Reserved2)( void );
|
void (*R_Reserved2)( void );
|
||||||
|
|
||||||
// static allocations
|
// static allocations
|
||||||
|
@ -245,8 +245,6 @@ typedef struct render_interface_s
|
||||||
void (*GL_BuildLightmaps)( void );
|
void (*GL_BuildLightmaps)( void );
|
||||||
// setup map bounds for ortho-projection when we in dev_overview mode
|
// setup map bounds for ortho-projection when we in dev_overview mode
|
||||||
void (*GL_OrthoBounds)( const float *mins, const float *maxs );
|
void (*GL_OrthoBounds)( const float *mins, const float *maxs );
|
||||||
// handle decals which hit mod_studio or mod_sprite
|
|
||||||
void (*R_StudioDecalShoot)( int decalTexture, struct cl_entity_s *ent, const float *start, const float *pos, int flags, modelstate_t *state );
|
|
||||||
// prepare studio decals for save
|
// prepare studio decals for save
|
||||||
int (*R_CreateStudioDecalList)( decallist_t *pList, int count );
|
int (*R_CreateStudioDecalList)( decallist_t *pList, int count );
|
||||||
// clear decals by engine request (e.g. for demo recording or vid_restart)
|
// clear decals by engine request (e.g. for demo recording or vid_restart)
|
||||||
|
|
26
dlls/rpg.cpp
26
dlls/rpg.cpp
|
@ -47,13 +47,21 @@ LINK_ENTITY_TO_CLASS( laser_spot, CLaserSpot );
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
//=========================================================
|
//=========================================================
|
||||||
CLaserSpot *CLaserSpot::CreateSpot( void )
|
CLaserSpot *CLaserSpot::CreateSpot( edict_t *pOwner )
|
||||||
{
|
{
|
||||||
CLaserSpot *pSpot = GetClassPtr( (CLaserSpot *)NULL );
|
CLaserSpot *pSpot = GetClassPtr( (CLaserSpot *)NULL );
|
||||||
pSpot->Spawn();
|
pSpot->Spawn();
|
||||||
|
|
||||||
pSpot->pev->classname = MAKE_STRING("laser_spot");
|
pSpot->pev->classname = MAKE_STRING("laser_spot");
|
||||||
|
|
||||||
|
if( pOwner )
|
||||||
|
{
|
||||||
|
// predictable laserspot
|
||||||
|
pSpot->pev->flags |= FL_SKIPLOCALHOST;
|
||||||
|
pOwner->v.flags |= FL_LASERDOT;
|
||||||
|
pSpot->pev->owner = pOwner;
|
||||||
|
}
|
||||||
|
|
||||||
return pSpot;
|
return pSpot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +87,9 @@ void CLaserSpot::Spawn( void )
|
||||||
void CLaserSpot::Suspend( float flSuspendTime )
|
void CLaserSpot::Suspend( float flSuspendTime )
|
||||||
{
|
{
|
||||||
pev->effects |= EF_NODRAW;
|
pev->effects |= EF_NODRAW;
|
||||||
|
|
||||||
|
if( !FNullEnt( pev->owner ))
|
||||||
|
pev->owner->v.flags &= ~FL_LASERDOT;
|
||||||
|
|
||||||
SetThink( Revive );
|
SetThink( Revive );
|
||||||
pev->nextthink = gpGlobals->time + flSuspendTime;
|
pev->nextthink = gpGlobals->time + flSuspendTime;
|
||||||
|
@ -91,9 +102,20 @@ void CLaserSpot::Revive( void )
|
||||||
{
|
{
|
||||||
pev->effects &= ~EF_NODRAW;
|
pev->effects &= ~EF_NODRAW;
|
||||||
|
|
||||||
|
if( !FNullEnt( pev->owner ))
|
||||||
|
pev->owner->v.flags |= FL_LASERDOT;
|
||||||
|
|
||||||
SetThink( NULL );
|
SetThink( NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CLaserSpot :: Killed( entvars_t *pevAttacker, int iGib )
|
||||||
|
{
|
||||||
|
// tell the owner about laserspot
|
||||||
|
if( !FNullEnt( pev->owner ))
|
||||||
|
pev->owner->v.flags &= ~FL_LASERDOT;
|
||||||
|
CBaseEntity :: Killed( pevAttacker, iGib );
|
||||||
|
}
|
||||||
|
|
||||||
void CLaserSpot::Precache( void )
|
void CLaserSpot::Precache( void )
|
||||||
{
|
{
|
||||||
PRECACHE_MODEL("sprites/laserdot.spr");
|
PRECACHE_MODEL("sprites/laserdot.spr");
|
||||||
|
@ -557,7 +579,7 @@ void CRpg::UpdateSpot( void )
|
||||||
{
|
{
|
||||||
if (!m_pSpot)
|
if (!m_pSpot)
|
||||||
{
|
{
|
||||||
m_pSpot = CLaserSpot::CreateSpot();
|
m_pSpot = CLaserSpot::CreateSpot( m_pPlayer->edict());
|
||||||
}
|
}
|
||||||
|
|
||||||
UTIL_MakeVectors( m_pPlayer->pev->v_angle );
|
UTIL_MakeVectors( m_pPlayer->pev->v_angle );
|
||||||
|
|
|
@ -671,8 +671,8 @@ class CLaserSpot : public CBaseEntity
|
||||||
public:
|
public:
|
||||||
void Suspend( float flSuspendTime );
|
void Suspend( float flSuspendTime );
|
||||||
void EXPORT Revive( void );
|
void EXPORT Revive( void );
|
||||||
|
void Killed( entvars_t *pevAttacker, int iGib );
|
||||||
static CLaserSpot *CreateSpot( void );
|
static CLaserSpot *CreateSpot( edict_t *pOwner );
|
||||||
};
|
};
|
||||||
|
|
||||||
class CRpg : public CBasePlayerWeapon
|
class CRpg : public CBasePlayerWeapon
|
||||||
|
|
|
@ -60,7 +60,8 @@ qboolean CL_CheckFile( sizebuf_t *msg, resource_t *pResource )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( FS_FileExists( filepath, false ))
|
// don't request downloads from local client it's silly
|
||||||
|
if( Host_IsLocalClient() || FS_FileExists( filepath, false ))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if( cls.demoplayback )
|
if( cls.demoplayback )
|
||||||
|
|
|
@ -135,7 +135,7 @@ word CL_EventIndex( const char *name )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if( !name || !name[0] )
|
if( !COM_CheckString( name ))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for( i = 1; i < MAX_EVENTS && cl.event_precache[i][0]; i++ )
|
for( i = 1; i < MAX_EVENTS && cl.event_precache[i][0]; i++ )
|
||||||
|
@ -146,20 +146,6 @@ word CL_EventIndex( const char *name )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
CL_EventIndex
|
|
||||||
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
const char *CL_IndexEvent( word index )
|
|
||||||
{
|
|
||||||
if( index < 0 || index >= MAX_EVENTS )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return cl.event_precache[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
CL_RegisterEvent
|
CL_RegisterEvent
|
||||||
|
|
|
@ -868,12 +868,6 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
|
||||||
// Clear loading plaque.
|
// Clear loading plaque.
|
||||||
CL_SignonReply ();
|
CL_SignonReply ();
|
||||||
}
|
}
|
||||||
else if( cls.state == ca_active )
|
|
||||||
{
|
|
||||||
// g-cont: now stair climbing interpolation
|
|
||||||
// is prepared for a new level and ready to use
|
|
||||||
cl.first_frame = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return playerbytes;
|
return playerbytes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3566,9 +3566,7 @@ static event_api_t gEventApi =
|
||||||
pfnTraceTexture,
|
pfnTraceTexture,
|
||||||
pfnStopAllSounds,
|
pfnStopAllSounds,
|
||||||
pfnKillEvents,
|
pfnKillEvents,
|
||||||
CL_EventIndex, // Xash3D added
|
CL_PlayerTraceExt, // Xash3D added
|
||||||
CL_IndexEvent,
|
|
||||||
CL_PlayerTraceExt,
|
|
||||||
CL_SoundFromIndex,
|
CL_SoundFromIndex,
|
||||||
pfnTraceSurface,
|
pfnTraceSurface,
|
||||||
pfnGetMoveVars,
|
pfnGetMoveVars,
|
||||||
|
|
|
@ -174,7 +174,7 @@ void CL_CheckClientState( void )
|
||||||
cls.state = ca_active;
|
cls.state = ca_active;
|
||||||
cls.changelevel = false; // changelevel is done
|
cls.changelevel = false; // changelevel is done
|
||||||
cls.changedemo = false; // changedemo is done
|
cls.changedemo = false; // changedemo is done
|
||||||
cl.first_frame = true;
|
cl.first_frame = true; // first rendering frame
|
||||||
|
|
||||||
SCR_MakeLevelShot(); // make levelshot if needs
|
SCR_MakeLevelShot(); // make levelshot if needs
|
||||||
Cvar_SetValue( "scr_loading", 0.0f ); // reset progress bar
|
Cvar_SetValue( "scr_loading", 0.0f ); // reset progress bar
|
||||||
|
@ -183,7 +183,6 @@ void CL_CheckClientState( void )
|
||||||
Con_DPrintf( "client connected at %.2f sec\n", Sys_DoubleTime() - cls.timestart );
|
Con_DPrintf( "client connected at %.2f sec\n", Sys_DoubleTime() - cls.timestart );
|
||||||
if(( cls.demoplayback || cls.disable_servercount != cl.servercount ) && cl.video_prepped )
|
if(( cls.demoplayback || cls.disable_servercount != cl.servercount ) && cl.video_prepped )
|
||||||
SCR_EndLoadingPlaque(); // get rid of loading plaque
|
SCR_EndLoadingPlaque(); // get rid of loading plaque
|
||||||
cl.first_frame = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2344,6 +2343,8 @@ qboolean CL_PrecacheResources( void )
|
||||||
Q_strncpy( host.draw_decals[pRes->nIndex], pRes->szFileName, sizeof( host.draw_decals[0] ));
|
Q_strncpy( host.draw_decals[pRes->nIndex], pRes->szFileName, sizeof( host.draw_decals[0] ));
|
||||||
break;
|
break;
|
||||||
case t_generic:
|
case t_generic:
|
||||||
|
Q_strncpy( cl.files_precache[pRes->nIndex], pRes->szFileName, sizeof( cl.files_precache[0] ));
|
||||||
|
cl.numfiles = Q_max( cl.numfiles, pRes->nIndex + 1 );
|
||||||
break;
|
break;
|
||||||
case t_eventscript:
|
case t_eventscript:
|
||||||
Q_strncpy( cl.event_precache[pRes->nIndex], pRes->szFileName, sizeof( cl.event_precache[0] ));
|
Q_strncpy( cl.event_precache[pRes->nIndex], pRes->szFileName, sizeof( cl.event_precache[0] ));
|
||||||
|
@ -2359,6 +2360,7 @@ qboolean CL_PrecacheResources( void )
|
||||||
|
|
||||||
// make sure modelcount is in-range
|
// make sure modelcount is in-range
|
||||||
cl.nummodels = bound( 0, cl.nummodels, MAX_MODELS );
|
cl.nummodels = bound( 0, cl.nummodels, MAX_MODELS );
|
||||||
|
cl.numfiles = bound( 0, cl.numfiles, MAX_CUSTOM );
|
||||||
S_EndRegistration();
|
S_EndRegistration();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -45,7 +45,7 @@ const char *svc_strings[svc_lastmsg+1] =
|
||||||
"svc_updateuserinfo",
|
"svc_updateuserinfo",
|
||||||
"svc_deltatable",
|
"svc_deltatable",
|
||||||
"svc_clientdata",
|
"svc_clientdata",
|
||||||
"svc_studiodecal",
|
"svc_fileindex",
|
||||||
"svc_pings",
|
"svc_pings",
|
||||||
"svc_particle",
|
"svc_particle",
|
||||||
"svc_restoresound",
|
"svc_restoresound",
|
||||||
|
@ -1543,24 +1543,17 @@ prceache model from server
|
||||||
*/
|
*/
|
||||||
void CL_PrecacheModel( sizebuf_t *msg )
|
void CL_PrecacheModel( sizebuf_t *msg )
|
||||||
{
|
{
|
||||||
const char *s;
|
int modelIndex;
|
||||||
int i;
|
|
||||||
|
|
||||||
i = MSG_ReadUBitLong( msg, MAX_MODEL_BITS );
|
modelIndex = MSG_ReadUBitLong( msg, MAX_MODEL_BITS );
|
||||||
s = MSG_ReadString( msg );
|
|
||||||
|
|
||||||
if( i < 0 || i >= MAX_MODELS )
|
if( modelIndex < 0 || modelIndex >= MAX_MODELS )
|
||||||
Host_Error( "CL_PrecacheModel: bad modelindex %i\n", i );
|
Host_Error( "CL_PrecacheModel: bad modelindex %i\n", modelIndex );
|
||||||
|
|
||||||
if( i == WORLD_INDEX )
|
cl.models[modelIndex] = Mod_ForName( MSG_ReadString( msg ), false, false );
|
||||||
cl.models[i] = Mod_LoadWorld( s, false );
|
|
||||||
else cl.models[i] = Mod_FindName( s, false );
|
|
||||||
|
|
||||||
if( i >= cl.nummodels )
|
cl.nummodels = Q_max( cl.nummodels, modelIndex + 1 );
|
||||||
{
|
cl.nummodels = bound( 0, cl.nummodels, MAX_MODELS );
|
||||||
cl.nummodels = i + 1;
|
|
||||||
cl.nummodels = Q_min( cl.nummodels, MAX_MODELS );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1609,6 +1602,28 @@ void CL_PrecacheEvent( sizebuf_t *msg )
|
||||||
CL_SetEventIndex( cl.event_precache[eventIndex], eventIndex );
|
CL_SetEventIndex( cl.event_precache[eventIndex], eventIndex );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
CL_PrecacheFile
|
||||||
|
|
||||||
|
prceache generic resource from server
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
void CL_PrecacheFile( sizebuf_t *msg )
|
||||||
|
{
|
||||||
|
int fileIndex;
|
||||||
|
|
||||||
|
fileIndex = MSG_ReadUBitLong( msg, MAX_CUSTOM_BITS );
|
||||||
|
|
||||||
|
if( fileIndex < 0 || fileIndex >= MAX_CUSTOM )
|
||||||
|
Host_Error( "CL_PrecacheFile: bad fileindex %i\n", fileIndex );
|
||||||
|
|
||||||
|
Q_strncpy( cl.files_precache[fileIndex], MSG_ReadString( msg ), sizeof( cl.files_precache[0] ));
|
||||||
|
|
||||||
|
cl.numfiles = Q_max( cl.numfiles, fileIndex + 1 );
|
||||||
|
cl.numfiles = bound( 0, cl.numfiles, MAX_CUSTOM );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
CL_UpdateUserPings
|
CL_UpdateUserPings
|
||||||
|
@ -1969,53 +1984,6 @@ void CL_ParseDirector( sizebuf_t *msg )
|
||||||
clgame.dllFuncs.pfnDirectorMessage( iSize, pbuf );
|
clgame.dllFuncs.pfnDirectorMessage( iSize, pbuf );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
==============
|
|
||||||
CL_ParseStudioDecal
|
|
||||||
|
|
||||||
Studio Decal message. Used by engine in case
|
|
||||||
we need save\restore decals
|
|
||||||
==============
|
|
||||||
*/
|
|
||||||
void CL_ParseStudioDecal( sizebuf_t *msg )
|
|
||||||
{
|
|
||||||
modelstate_t state;
|
|
||||||
vec3_t start, pos;
|
|
||||||
int decalIndex, entityIndex;
|
|
||||||
int modelIndex = 0;
|
|
||||||
int i, flags;
|
|
||||||
|
|
||||||
MSG_ReadVec3Coord( msg, pos );
|
|
||||||
MSG_ReadVec3Coord( msg, start );
|
|
||||||
decalIndex = MSG_ReadWord( msg );
|
|
||||||
entityIndex = MSG_ReadWord( msg );
|
|
||||||
flags = MSG_ReadByte( msg );
|
|
||||||
|
|
||||||
state.sequence = MSG_ReadShort( msg );
|
|
||||||
state.frame = MSG_ReadShort( msg );
|
|
||||||
state.blending[0] = MSG_ReadByte( msg );
|
|
||||||
state.blending[1] = MSG_ReadByte( msg );
|
|
||||||
for( i = 0; i < 4; i++ )
|
|
||||||
state.controller[i] = MSG_ReadByte( msg );
|
|
||||||
for( i = 0; i < 16; i++ )
|
|
||||||
state.poseparam[i] = MSG_ReadByte( msg );
|
|
||||||
modelIndex = MSG_ReadWord( msg );
|
|
||||||
state.body = MSG_ReadByte( msg );
|
|
||||||
state.skin = MSG_ReadByte( msg );
|
|
||||||
state.scale = MSG_ReadWord( msg );
|
|
||||||
|
|
||||||
if( clgame.drawFuncs.R_StudioDecalShoot != NULL )
|
|
||||||
{
|
|
||||||
int decalTexture = CL_DecalIndex( decalIndex );
|
|
||||||
cl_entity_t *ent = CL_GetEntityByIndex( entityIndex );
|
|
||||||
|
|
||||||
if( ent && !ent->model && modelIndex != 0 )
|
|
||||||
ent->model = CL_ModelHandle( modelIndex );
|
|
||||||
|
|
||||||
clgame.drawFuncs.R_StudioDecalShoot( decalTexture, ent, start, pos, flags, &state );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==============
|
==============
|
||||||
CL_ParseScreenShake
|
CL_ParseScreenShake
|
||||||
|
@ -2347,12 +2315,12 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||||
SCR_BeginLoadingPlaque( cl.background );
|
SCR_BeginLoadingPlaque( cl.background );
|
||||||
cls.changedemo = true;
|
cls.changedemo = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CL_ClearState ();
|
||||||
|
CL_InitEdicts (); // re-arrange edicts
|
||||||
}
|
}
|
||||||
else MsgDev( D_INFO, "Server disconnected, reconnecting\n" );
|
else MsgDev( D_INFO, "Server disconnected, reconnecting\n" );
|
||||||
|
|
||||||
CL_ClearState ();
|
|
||||||
CL_InitEdicts (); // re-arrange edicts
|
|
||||||
|
|
||||||
if( cls.demoplayback )
|
if( cls.demoplayback )
|
||||||
{
|
{
|
||||||
cl.background = (cls.demonum != -1) ? true : false;
|
cl.background = (cls.demonum != -1) ? true : false;
|
||||||
|
@ -2403,8 +2371,8 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||||
CL_ParseClientData( msg );
|
CL_ParseClientData( msg );
|
||||||
cl.frames[cl.parsecountmod].graphdata.client += MSG_GetNumBytesRead( msg ) - bufStart;
|
cl.frames[cl.parsecountmod].graphdata.client += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||||
break;
|
break;
|
||||||
case svc_studiodecal:
|
case svc_fileindex:
|
||||||
CL_ParseStudioDecal( msg );
|
CL_PrecacheFile( msg );
|
||||||
break;
|
break;
|
||||||
case svc_pings:
|
case svc_pings:
|
||||||
CL_UpdateUserPings( msg );
|
CL_UpdateUserPings( msg );
|
||||||
|
|
|
@ -319,6 +319,9 @@ void SCR_BeginLoadingPlaque( qboolean is_background )
|
||||||
if( cls.state == ca_disconnected || cls.disable_screen )
|
if( cls.state == ca_disconnected || cls.disable_screen )
|
||||||
return; // already set
|
return; // already set
|
||||||
|
|
||||||
|
if( cls.key_dest == key_console )
|
||||||
|
return;
|
||||||
|
|
||||||
cls.draw_changelevel = !is_background;
|
cls.draw_changelevel = !is_background;
|
||||||
SCR_UpdateScreen();
|
SCR_UpdateScreen();
|
||||||
cls.disable_screen = host.realtime;
|
cls.disable_screen = host.realtime;
|
||||||
|
|
|
@ -141,6 +141,9 @@ void CL_AddClientResources( void )
|
||||||
char filepath[MAX_QPATH];
|
char filepath[MAX_QPATH];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||||
|
return;
|
||||||
|
|
||||||
// check sprites first
|
// check sprites first
|
||||||
for( i = 0; i < ARRAYSIZE( cl_default_sprites ); i++ )
|
for( i = 0; i < ARRAYSIZE( cl_default_sprites ); i++ )
|
||||||
{
|
{
|
||||||
|
|
|
@ -143,7 +143,11 @@ void V_SetRefParams( ref_params_t *fd )
|
||||||
fd->demoplayback = cls.demoplayback;
|
fd->demoplayback = cls.demoplayback;
|
||||||
fd->hardware = 1; // OpenGL
|
fd->hardware = 1; // OpenGL
|
||||||
|
|
||||||
if( cl.first_frame ) fd->smoothing = true; // NOTE: currently this used to prevent ugly un-duck effect while level is changed
|
if( cl.first_frame )
|
||||||
|
{
|
||||||
|
cl.first_frame = false; // now can be unlocked
|
||||||
|
fd->smoothing = true; // NOTE: currently this used to prevent ugly un-duck effect while level is changed
|
||||||
|
}
|
||||||
else fd->smoothing = cl.local.pushmsec; // enable smoothing in multiplayer by server request (AMX uses)
|
else fd->smoothing = cl.local.pushmsec; // enable smoothing in multiplayer by server request (AMX uses)
|
||||||
|
|
||||||
// get pointers to movement vars and user cmd
|
// get pointers to movement vars and user cmd
|
||||||
|
|
|
@ -267,9 +267,11 @@ typedef struct
|
||||||
|
|
||||||
char sound_precache[MAX_SOUNDS][MAX_QPATH];
|
char sound_precache[MAX_SOUNDS][MAX_QPATH];
|
||||||
char event_precache[MAX_EVENTS][MAX_QPATH];
|
char event_precache[MAX_EVENTS][MAX_QPATH];
|
||||||
|
char files_precache[MAX_CUSTOM][MAX_QPATH];
|
||||||
lightstyle_t lightstyles[MAX_LIGHTSTYLES];
|
lightstyle_t lightstyles[MAX_LIGHTSTYLES];
|
||||||
model_t *models[MAX_MODELS+1]; // precached models (plus sentinel slot)
|
model_t *models[MAX_MODELS+1]; // precached models (plus sentinel slot)
|
||||||
int nummodels;
|
int nummodels;
|
||||||
|
int numfiles;
|
||||||
|
|
||||||
consistency_t consistency_list[MAX_MODELS];
|
consistency_t consistency_list[MAX_MODELS];
|
||||||
int num_consistency;
|
int num_consistency;
|
||||||
|
@ -776,9 +778,8 @@ void CL_QueueEvent( int flags, int index, float delay, event_args_t *args );
|
||||||
void CL_PlaybackEvent( int flags, const edict_t *pInvoker, word eventindex, float delay, float *origin,
|
void CL_PlaybackEvent( int flags, const edict_t *pInvoker, word eventindex, float delay, float *origin,
|
||||||
float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 );
|
float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 );
|
||||||
void CL_RegisterEvent( int lastnum, const char *szEvName, pfnEventHook func );
|
void CL_RegisterEvent( int lastnum, const char *szEvName, pfnEventHook func );
|
||||||
word CL_EventIndex( const char *name );
|
|
||||||
const char *CL_IndexEvent( word index );
|
|
||||||
void CL_ResetEvent( event_info_t *ei );
|
void CL_ResetEvent( event_info_t *ei );
|
||||||
|
word CL_EventIndex( const char *name );
|
||||||
void CL_FireEvents( void );
|
void CL_FireEvents( void );
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -1402,6 +1402,19 @@ static uint pfnFileBufferCRC32( const void *buffer, const int length )
|
||||||
|
|
||||||
return modelCRC;
|
return modelCRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
CL_GenericHandle
|
||||||
|
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
const char *CL_GenericHandle( int fileindex )
|
||||||
|
{
|
||||||
|
if( fileindex < 0 || fileindex >= MAX_CUSTOM )
|
||||||
|
return 0;
|
||||||
|
return cl.files_precache[fileindex];
|
||||||
|
}
|
||||||
|
|
||||||
static render_api_t gRenderAPI =
|
static render_api_t gRenderAPI =
|
||||||
{
|
{
|
||||||
|
@ -1456,7 +1469,7 @@ static render_api_t gRenderAPI =
|
||||||
R_LightVec,
|
R_LightVec,
|
||||||
R_StudioGetTexture,
|
R_StudioGetTexture,
|
||||||
GL_GetOverviewParms,
|
GL_GetOverviewParms,
|
||||||
NULL,
|
CL_GenericHandle,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
R_Mem_Alloc,
|
R_Mem_Alloc,
|
||||||
|
|
|
@ -147,6 +147,287 @@ long COM_RandomLong( long lLow, long lHigh )
|
||||||
return lLow + (n % x);
|
return lLow + (n % x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============================================================================
|
||||||
|
|
||||||
|
LZSS Compression
|
||||||
|
|
||||||
|
===============================================================================
|
||||||
|
*/
|
||||||
|
#define LZSS_ID (('S'<<24)|('S'<<16)|('Z'<<8)|('L'))
|
||||||
|
#define LZSS_LOOKSHIFT 4
|
||||||
|
#define LZSS_WINDOW_SIZE 4096
|
||||||
|
#define LZSS_LOOKAHEAD BIT( LZSS_LOOKSHIFT )
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned int id;
|
||||||
|
unsigned short size;
|
||||||
|
} lzss_header_t;
|
||||||
|
|
||||||
|
// expected to be sixteen bytes
|
||||||
|
typedef struct lzss_node_s
|
||||||
|
{
|
||||||
|
const byte *data;
|
||||||
|
struct lzss_node_s *prev;
|
||||||
|
struct lzss_node_s *next;
|
||||||
|
char pad[4];
|
||||||
|
} lzss_node_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
lzss_node_t *start;
|
||||||
|
lzss_node_t *end;
|
||||||
|
} lzss_list_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
lzss_list_t *hash_table;
|
||||||
|
lzss_node_t *hash_node;
|
||||||
|
int window_size;
|
||||||
|
} lzss_state_t;
|
||||||
|
|
||||||
|
qboolean LZSS_IsCompressed( const byte *source )
|
||||||
|
{
|
||||||
|
lzss_header_t *phdr = (lzss_header_t *)source;
|
||||||
|
|
||||||
|
if( phdr && phdr->id == LZSS_ID )
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint LZSS_GetActualSize( const byte *source )
|
||||||
|
{
|
||||||
|
lzss_header_t *phdr = (lzss_header_t *)source;
|
||||||
|
|
||||||
|
if( phdr && phdr->id == LZSS_ID )
|
||||||
|
return phdr->size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LZSS_BuildHash( lzss_state_t *state, const byte *source )
|
||||||
|
{
|
||||||
|
lzss_list_t *list;
|
||||||
|
lzss_node_t *node;
|
||||||
|
unsigned int targetindex = (uint)source & ( state->window_size - 1 );
|
||||||
|
|
||||||
|
node = &state->hash_node[targetindex];
|
||||||
|
|
||||||
|
if( node->data )
|
||||||
|
{
|
||||||
|
list = &state->hash_table[*node->data];
|
||||||
|
if( node->prev )
|
||||||
|
{
|
||||||
|
list->end = node->prev;
|
||||||
|
node->prev->next = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list->start = NULL;
|
||||||
|
list->end = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list = &state->hash_table[*source];
|
||||||
|
node->data = source;
|
||||||
|
node->prev = NULL;
|
||||||
|
node->next = list->start;
|
||||||
|
if( list->start )
|
||||||
|
list->start->prev = node;
|
||||||
|
else list->end = node;
|
||||||
|
list->start = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte *LZSS_CompressNoAlloc( lzss_state_t *state, byte *pInput, int input_length, byte *pOutputBuf, uint *pOutputSize )
|
||||||
|
{
|
||||||
|
byte *pStart = pOutputBuf; // allocate the output buffer, compressed buffer is expected to be less, caller will free
|
||||||
|
byte *pEnd = pStart + input_length - sizeof( lzss_header_t ) - 8; // prevent compression failure
|
||||||
|
lzss_header_t *header = (lzss_header_t *)pStart;
|
||||||
|
byte *pOutput = pStart + sizeof( lzss_header_t );
|
||||||
|
const byte *pEncodedPosition = NULL;
|
||||||
|
byte *pLookAhead = pInput;
|
||||||
|
byte *pWindow = pInput;
|
||||||
|
int i, putCmdByte = 0;
|
||||||
|
byte *pCmdByte = NULL;
|
||||||
|
|
||||||
|
if( input_length <= sizeof( lzss_header_t ) + 8 )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// set LZSS header
|
||||||
|
header->id = LZSS_ID;
|
||||||
|
header->size = input_length;
|
||||||
|
|
||||||
|
// create the compression work buffers, small enough (~64K) for stack
|
||||||
|
state->hash_table = (lzss_list_t *)_alloca( 256 * sizeof( lzss_list_t ));
|
||||||
|
memset( state->hash_table, 0, 256 * sizeof( lzss_list_t ));
|
||||||
|
state->hash_node = (lzss_node_t *)_alloca( state->window_size * sizeof( lzss_node_t ));
|
||||||
|
memset( state->hash_node, 0, state->window_size * sizeof( lzss_node_t ));
|
||||||
|
|
||||||
|
while( input_length > 0 )
|
||||||
|
{
|
||||||
|
int lookAheadLength = input_length < LZSS_LOOKAHEAD ? input_length : LZSS_LOOKAHEAD;
|
||||||
|
lzss_node_t *hash = state->hash_table[pLookAhead[0]].start;
|
||||||
|
int encoded_length = 0;
|
||||||
|
|
||||||
|
pWindow = pLookAhead - state->window_size;
|
||||||
|
|
||||||
|
if( pWindow < pInput )
|
||||||
|
pWindow = pInput;
|
||||||
|
|
||||||
|
if( !putCmdByte )
|
||||||
|
{
|
||||||
|
pCmdByte = pOutput++;
|
||||||
|
*pCmdByte = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
putCmdByte = ( putCmdByte + 1 ) & 0x07;
|
||||||
|
|
||||||
|
while( hash != NULL )
|
||||||
|
{
|
||||||
|
int length = lookAheadLength;
|
||||||
|
int match_length = 0;
|
||||||
|
|
||||||
|
while( length-- && hash->data[match_length] == pLookAhead[match_length] )
|
||||||
|
match_length++;
|
||||||
|
|
||||||
|
if( match_length > encoded_length )
|
||||||
|
{
|
||||||
|
encoded_length = match_length;
|
||||||
|
pEncodedPosition = hash->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( match_length == lookAheadLength )
|
||||||
|
break;
|
||||||
|
|
||||||
|
hash = hash->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( encoded_length >= 3 )
|
||||||
|
{
|
||||||
|
*pCmdByte = (*pCmdByte >> 1) | 0x80;
|
||||||
|
*pOutput++ = (( pLookAhead - pEncodedPosition - 1 ) >> LZSS_LOOKSHIFT );
|
||||||
|
*pOutput++ = (( pLookAhead - pEncodedPosition - 1 ) << LZSS_LOOKSHIFT ) | ( encoded_length - 1 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*pCmdByte = ( *pCmdByte >> 1 );
|
||||||
|
*pOutput++ = *pLookAhead;
|
||||||
|
encoded_length = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i = 0; i < encoded_length; i++ )
|
||||||
|
{
|
||||||
|
LZSS_BuildHash( state, pLookAhead++ );
|
||||||
|
}
|
||||||
|
|
||||||
|
input_length -= encoded_length;
|
||||||
|
|
||||||
|
if( pOutput >= pEnd )
|
||||||
|
{
|
||||||
|
// compression is worse, abandon
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( input_length != 0 )
|
||||||
|
{
|
||||||
|
// unexpected failure
|
||||||
|
Assert( 0 );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !putCmdByte )
|
||||||
|
{
|
||||||
|
pCmdByte = pOutput++;
|
||||||
|
*pCmdByte = 0x01;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*pCmdByte = (( *pCmdByte >> 1 ) | 0x80 ) >> ( 7 - putCmdByte );
|
||||||
|
}
|
||||||
|
|
||||||
|
// put two ints at end of buffer
|
||||||
|
*pOutput++ = 0;
|
||||||
|
*pOutput++ = 0;
|
||||||
|
|
||||||
|
if( pOutputSize )
|
||||||
|
*pOutputSize = pOutput - pStart;
|
||||||
|
|
||||||
|
return pStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte *LZSS_Compress( byte *pInput, int inputLength, uint *pOutputSize )
|
||||||
|
{
|
||||||
|
byte *pStart = (byte *)malloc( inputLength );
|
||||||
|
byte *pFinal = NULL;
|
||||||
|
lzss_state_t state;
|
||||||
|
|
||||||
|
memset( &state, 0, sizeof( state ));
|
||||||
|
state.window_size = LZSS_WINDOW_SIZE;
|
||||||
|
|
||||||
|
pFinal = LZSS_CompressNoAlloc( &state, pInput, inputLength, pStart, pOutputSize );
|
||||||
|
|
||||||
|
if( !pFinal )
|
||||||
|
{
|
||||||
|
free( pStart );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint LZSS_Decompress( const byte *pInput, byte *pOutput )
|
||||||
|
{
|
||||||
|
uint totalBytes = 0;
|
||||||
|
int getCmdByte = 0;
|
||||||
|
int cmdByte = 0;
|
||||||
|
uint actualSize = LZSS_GetActualSize( pInput );
|
||||||
|
|
||||||
|
if( !actualSize )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pInput += sizeof( lzss_header_t );
|
||||||
|
|
||||||
|
while( 1 )
|
||||||
|
{
|
||||||
|
if( !getCmdByte )
|
||||||
|
cmdByte = *pInput++;
|
||||||
|
getCmdByte = ( getCmdByte + 1 ) & 0x07;
|
||||||
|
|
||||||
|
if( cmdByte & 0x01 )
|
||||||
|
{
|
||||||
|
int position = *pInput++ << LZSS_LOOKSHIFT;
|
||||||
|
int i, count;
|
||||||
|
byte *pSource;
|
||||||
|
|
||||||
|
position |= ( *pInput >> LZSS_LOOKSHIFT );
|
||||||
|
count = ( *pInput++ & 0x0F ) + 1;
|
||||||
|
|
||||||
|
if( count == 1 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
pSource = pOutput - position - 1;
|
||||||
|
for( i = 0; i < count; i++ )
|
||||||
|
*pOutput++ = *pSource++;
|
||||||
|
totalBytes += count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*pOutput++ = *pInput++;
|
||||||
|
totalBytes++;
|
||||||
|
}
|
||||||
|
cmdByte = cmdByte >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( totalBytes != actualSize )
|
||||||
|
{
|
||||||
|
Assert( 0 );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return totalBytes;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
============
|
============
|
||||||
COM_FileBase
|
COM_FileBase
|
||||||
|
|
|
@ -866,7 +866,6 @@ struct pmtrace_s *PM_TraceLine( float *start, float *end, int flags, int usehull
|
||||||
void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch );
|
void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch );
|
||||||
void SV_StartMusic( const char *curtrack, const char *looptrack, long position );
|
void SV_StartMusic( const char *curtrack, const char *looptrack, long position );
|
||||||
void SV_CreateDecal( struct sizebuf_s *msg, const float *origin, int decalIndex, int entityIndex, int modelIndex, int flags, float scale );
|
void SV_CreateDecal( struct sizebuf_s *msg, const float *origin, int decalIndex, int entityIndex, int modelIndex, int flags, float scale );
|
||||||
void SV_CreateStudioDecal( struct sizebuf_s *bf, const float *v0, const float *v1, int decal, int ent, int model, int flags, struct modelstate_s *s );
|
|
||||||
void Log_Printf( const char *fmt, ... );
|
void Log_Printf( const char *fmt, ... );
|
||||||
struct sizebuf_s *SV_GetReliableDatagram( void );
|
struct sizebuf_s *SV_GetReliableDatagram( void );
|
||||||
void SV_BroadcastCommand( const char *fmt, ... );
|
void SV_BroadcastCommand( const char *fmt, ... );
|
||||||
|
@ -945,6 +944,10 @@ void Cmd_AutoComplete( char *complete_string );
|
||||||
void COM_SetRandomSeed( long lSeed );
|
void COM_SetRandomSeed( long lSeed );
|
||||||
long COM_RandomLong( long lMin, long lMax );
|
long COM_RandomLong( long lMin, long lMax );
|
||||||
float COM_RandomFloat( float fMin, float fMax );
|
float COM_RandomFloat( float fMin, float fMax );
|
||||||
|
qboolean LZSS_IsCompressed( const byte *source );
|
||||||
|
uint LZSS_GetActualSize( const byte *source );
|
||||||
|
byte *LZSS_Compress( byte *pInput, int inputLength, uint *pOutputSize );
|
||||||
|
uint LZSS_Decompress( const byte *pInput, byte *pOutput );
|
||||||
const byte *GL_TextureData( unsigned int texnum );
|
const byte *GL_TextureData( unsigned int texnum );
|
||||||
void GL_FreeImage( const char *name );
|
void GL_FreeImage( const char *name );
|
||||||
void VID_InitDefaultResolution( void );
|
void VID_InitDefaultResolution( void );
|
||||||
|
|
|
@ -1008,6 +1008,7 @@ void Con_Print( const char *txt )
|
||||||
{
|
{
|
||||||
static int cr_pending = 0;
|
static int cr_pending = 0;
|
||||||
static char buf[MAX_PRINT_MSG];
|
static char buf[MAX_PRINT_MSG];
|
||||||
|
static qboolean inupdate;
|
||||||
static int bufpos = 0;
|
static int bufpos = 0;
|
||||||
int c, mask = 0;
|
int c, mask = 0;
|
||||||
|
|
||||||
|
@ -1056,6 +1057,16 @@ void Con_Print( const char *txt )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( cls.state != ca_disconnected && cls.state < ca_active && !cl.video_prepped && !cls.disable_screen )
|
||||||
|
{
|
||||||
|
if( !inupdate )
|
||||||
|
{
|
||||||
|
inupdate = true;
|
||||||
|
SCR_UpdateScreen ();
|
||||||
|
inupdate = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -440,17 +440,9 @@ void Host_RestartDecals( void )
|
||||||
|
|
||||||
decalIndex = pfnDecalIndex( entry->name );
|
decalIndex = pfnDecalIndex( entry->name );
|
||||||
|
|
||||||
// BSP and studio decals has different messages
|
// studiodecals will be restored at game-side
|
||||||
if( entry->flags & FDECAL_STUDIO )
|
if( !FBitSet( entry->flags, FDECAL_STUDIO ))
|
||||||
{
|
|
||||||
// NOTE: studio decal trace start saved into impactPlaneNormal
|
|
||||||
SV_CreateStudioDecal( msg, entry->position, entry->impactPlaneNormal, decalIndex, entry->entityIndex,
|
|
||||||
modelIndex, entry->flags, &entry->studio_state );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SV_CreateDecal( msg, entry->position, decalIndex, entry->entityIndex, modelIndex, entry->flags, entry->scale );
|
SV_CreateDecal( msg, entry->position, decalIndex, entry->entityIndex, modelIndex, entry->flags, entry->scale );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Z_Free( host.decalList );
|
Z_Free( host.decalList );
|
||||||
|
|
|
@ -106,7 +106,8 @@ static void Mod_FreeModel( model_t *mod )
|
||||||
if( !mod || !mod->name[0] )
|
if( !mod || !mod->name[0] )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Mod_FreeUserData( mod );
|
if( mod->name[0] != '*' )
|
||||||
|
Mod_FreeUserData( mod );
|
||||||
|
|
||||||
// select the properly unloader
|
// select the properly unloader
|
||||||
switch( mod->type )
|
switch( mod->type )
|
||||||
|
@ -405,6 +406,9 @@ void Mod_PurgeStudioCache( void )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
// release previois map
|
||||||
|
Mod_FreeModel( mod_known ); // world is stuck on slot #0 always
|
||||||
|
|
||||||
// we should release all the world submodels
|
// we should release all the world submodels
|
||||||
// and clear studio sequences
|
// and clear studio sequences
|
||||||
for( i = 1; i < mod_numknown; i++ )
|
for( i = 1; i < mod_numknown; i++ )
|
||||||
|
@ -438,9 +442,6 @@ model_t *Mod_LoadWorld( const char *name, qboolean preload )
|
||||||
// free sequence files on studiomodels
|
// free sequence files on studiomodels
|
||||||
Mod_PurgeStudioCache();
|
Mod_PurgeStudioCache();
|
||||||
|
|
||||||
// release previois map
|
|
||||||
Mod_FreeModel( mod_known ); // world is stuck on slot #0 always
|
|
||||||
|
|
||||||
// load the newmap
|
// load the newmap
|
||||||
world.loading = true;
|
world.loading = true;
|
||||||
pworld = Mod_FindName( name, false );
|
pworld = Mod_FindName( name, false );
|
||||||
|
|
|
@ -1105,6 +1105,68 @@ void NET_SendPacket( netsrc_t sock, size_t length, const void *data, netadr_t to
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
====================
|
||||||
|
NET_BufferToBufferCompress
|
||||||
|
|
||||||
|
generic fast compression
|
||||||
|
====================
|
||||||
|
*/
|
||||||
|
qboolean NET_BufferToBufferCompress( char *dest, uint *destLen, char *source, uint sourceLen )
|
||||||
|
{
|
||||||
|
uint uCompressedLen = 0;
|
||||||
|
byte *pbOut = NULL;
|
||||||
|
|
||||||
|
memcpy( dest, source, sourceLen );
|
||||||
|
pbOut = LZSS_Compress( source, sourceLen, &uCompressedLen );
|
||||||
|
|
||||||
|
if( pbOut && uCompressedLen > 0 && uCompressedLen <= *destLen )
|
||||||
|
{
|
||||||
|
memcpy( dest, pbOut, uCompressedLen );
|
||||||
|
*destLen = uCompressedLen;
|
||||||
|
free( pbOut );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( pbOut ) free( pbOut );
|
||||||
|
memcpy( dest, source, sourceLen );
|
||||||
|
*destLen = sourceLen;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
====================
|
||||||
|
NET_BufferToBufferDecompress
|
||||||
|
|
||||||
|
generic fast decompression
|
||||||
|
====================
|
||||||
|
*/
|
||||||
|
qboolean NET_BufferToBufferDecompress( char *dest, uint *destLen, char *source, uint sourceLen )
|
||||||
|
{
|
||||||
|
if( LZSS_IsCompressed( source ))
|
||||||
|
{
|
||||||
|
uint uDecompressedLen = LZSS_GetActualSize( source );
|
||||||
|
|
||||||
|
if( uDecompressedLen <= *destLen )
|
||||||
|
{
|
||||||
|
*destLen = LZSS_Decompress( source, dest );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy( dest, source, sourceLen );
|
||||||
|
*destLen = sourceLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
====================
|
====================
|
||||||
NET_IPSocket
|
NET_IPSocket
|
||||||
|
|
|
@ -51,6 +51,8 @@ qboolean NET_StringToAdr( const char *string, netadr_t *adr );
|
||||||
qboolean NET_CompareAdr( const netadr_t a, const netadr_t b );
|
qboolean NET_CompareAdr( const netadr_t a, const netadr_t b );
|
||||||
qboolean NET_CompareBaseAdr( const netadr_t a, const netadr_t b );
|
qboolean NET_CompareBaseAdr( const netadr_t a, const netadr_t b );
|
||||||
qboolean NET_GetPacket( netsrc_t sock, netadr_t *from, byte *data, size_t *length );
|
qboolean NET_GetPacket( netsrc_t sock, netadr_t *from, byte *data, size_t *length );
|
||||||
|
qboolean NET_BufferToBufferCompress( char *dest, uint *destLen, char *source, uint sourceLen );
|
||||||
|
qboolean NET_BufferToBufferDecompress( char *dest, uint *destLen, char *source, uint sourceLen );
|
||||||
void NET_SendPacket( netsrc_t sock, size_t length, const void *data, netadr_t to );
|
void NET_SendPacket( netsrc_t sock, size_t length, const void *data, netadr_t to );
|
||||||
void NET_ClearLagData( qboolean bClient, qboolean bServer );
|
void NET_ClearLagData( qboolean bClient, qboolean bServer );
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ GNU General Public License for more details.
|
||||||
#define svc_updateuserinfo 13 // [byte] playernum, [string] userinfo
|
#define svc_updateuserinfo 13 // [byte] playernum, [string] userinfo
|
||||||
#define svc_deltatable 14 // [table header][...]
|
#define svc_deltatable 14 // [table header][...]
|
||||||
#define svc_clientdata 15 // [...]
|
#define svc_clientdata 15 // [...]
|
||||||
#define svc_studiodecal 16 // [float*3][float*3][short][short][byte]
|
#define svc_fileindex 16 // [index][filepath]
|
||||||
#define svc_pings 17 // [bit][idx][ping][packet_loss]
|
#define svc_pings 17 // [bit][idx][ping][packet_loss]
|
||||||
#define svc_particle 18 // [float*3][char*3][byte][byte]
|
#define svc_particle 18 // [float*3][char*3][byte][byte]
|
||||||
#define svc_restoresound 19 // <see code>
|
#define svc_restoresound 19 // <see code>
|
||||||
|
@ -125,7 +125,8 @@ GNU General Public License for more details.
|
||||||
#define MAX_EDICTS_BYTES ((MAX_EDICTS + 7) / 8)
|
#define MAX_EDICTS_BYTES ((MAX_EDICTS + 7) / 8)
|
||||||
#define LAST_EDICT (MAX_EDICTS - 1)
|
#define LAST_EDICT (MAX_EDICTS - 1)
|
||||||
|
|
||||||
#define MAX_CUSTOM 1024 // max custom resources per level
|
#define MAX_CUSTOM_BITS 10
|
||||||
|
#define MAX_CUSTOM (1<<MAX_CUSTOM_BITS)// 10 bits == 1024 generic file
|
||||||
#define MAX_USER_MESSAGES 197 // another 58 messages reserved for engine routines
|
#define MAX_USER_MESSAGES 197 // another 58 messages reserved for engine routines
|
||||||
#define MAX_DLIGHTS 32 // dynamic lights (rendered per one frame)
|
#define MAX_DLIGHTS 32 // dynamic lights (rendered per one frame)
|
||||||
#define MAX_ELIGHTS 64 // entity only point lights
|
#define MAX_ELIGHTS 64 // entity only point lights
|
||||||
|
|
|
@ -477,11 +477,14 @@ long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo )
|
||||||
else host.status = HOST_CRASHED;
|
else host.status = HOST_CRASHED;
|
||||||
|
|
||||||
Con_Printf( "unhandled exception: %p at address %p\n", pInfo->ExceptionRecord->ExceptionAddress, pInfo->ExceptionRecord->ExceptionCode );
|
Con_Printf( "unhandled exception: %p at address %p\n", pInfo->ExceptionRecord->ExceptionAddress, pInfo->ExceptionRecord->ExceptionCode );
|
||||||
#ifdef NDEBUG
|
|
||||||
// no reason to call debugger in release build - just exit
|
if( !host_developer.value )
|
||||||
Sys_Quit();
|
{
|
||||||
return EXCEPTION_CONTINUE_EXECUTION;
|
// for non-development mode
|
||||||
#endif
|
Sys_Quit();
|
||||||
|
return EXCEPTION_CONTINUE_EXECUTION;
|
||||||
|
}
|
||||||
|
|
||||||
// all other states keep unchanged to let debugger find bug
|
// all other states keep unchanged to let debugger find bug
|
||||||
Con_DestroyConsole();
|
Con_DestroyConsole();
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,7 +202,6 @@ typedef struct server_s
|
||||||
|
|
||||||
// statistics
|
// statistics
|
||||||
int ignored_static_ents;
|
int ignored_static_ents;
|
||||||
int ignored_studio_decals;
|
|
||||||
int ignored_world_decals;
|
int ignored_world_decals;
|
||||||
int static_ents_overflow;
|
int static_ents_overflow;
|
||||||
} server_t;
|
} server_t;
|
||||||
|
|
|
@ -542,7 +542,7 @@ void SV_SendResources( sv_client_t *cl, sizebuf_t *msg )
|
||||||
MSG_WriteLong( msg, svs.spawncount );
|
MSG_WriteLong( msg, svs.spawncount );
|
||||||
MSG_WriteLong( msg, 0 );
|
MSG_WriteLong( msg, 0 );
|
||||||
|
|
||||||
if( sv_downloadurl.string && sv_downloadurl.string[0] && Q_strlen( sv_downloadurl.string ) < 256 )
|
if( COM_CheckString( sv_downloadurl.string ) && Q_strlen( sv_downloadurl.string ) < 256 )
|
||||||
{
|
{
|
||||||
MSG_BeginServerCmd( msg, svc_resourcelocation );
|
MSG_BeginServerCmd( msg, svc_resourcelocation );
|
||||||
MSG_WriteString( msg, sv_downloadurl.string );
|
MSG_WriteString( msg, sv_downloadurl.string );
|
||||||
|
|
|
@ -490,57 +490,6 @@ void SV_CreateDecal( sizebuf_t *msg, const float *origin, int decalIndex, int en
|
||||||
MSG_WriteWord( msg, scale * 4096 );
|
MSG_WriteWord( msg, scale * 4096 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
=======================
|
|
||||||
SV_CreateStudioDecal
|
|
||||||
|
|
||||||
NOTE: static decals only accepted when game is loading
|
|
||||||
=======================
|
|
||||||
*/
|
|
||||||
void SV_CreateStudioDecal( sizebuf_t *msg, const float *origin, const float *start, int decalIndex, int entityIndex, int modelIndex, int flags, modelstate_t *state )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if( msg == &sv.signon && sv.state != ss_loading )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// bad model or bad entity (e.g. changelevel)
|
|
||||||
if( !entityIndex || !modelIndex )
|
|
||||||
return;
|
|
||||||
|
|
||||||
Assert( origin != NULL );
|
|
||||||
Assert( start != NULL );
|
|
||||||
|
|
||||||
// this can happens if serialized map contain 4096 static decals...
|
|
||||||
if( MSG_GetNumBytesLeft( msg ) < 50 )
|
|
||||||
{
|
|
||||||
sv.ignored_studio_decals++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static decals are posters, it's always reliable
|
|
||||||
MSG_BeginServerCmd( msg, svc_studiodecal );
|
|
||||||
MSG_WriteVec3Coord( msg, origin );
|
|
||||||
MSG_WriteVec3Coord( msg, start );
|
|
||||||
MSG_WriteWord( msg, decalIndex );
|
|
||||||
MSG_WriteWord( msg, entityIndex );
|
|
||||||
MSG_WriteByte( msg, flags );
|
|
||||||
|
|
||||||
// write model state
|
|
||||||
MSG_WriteShort( msg, state->sequence );
|
|
||||||
MSG_WriteShort( msg, state->frame );
|
|
||||||
MSG_WriteByte( msg, state->blending[0] );
|
|
||||||
MSG_WriteByte( msg, state->blending[1] );
|
|
||||||
for( i = 0; i < 4; i++ )
|
|
||||||
MSG_WriteByte( msg, state->controller[i] );
|
|
||||||
for( i = 0; i < 16; i++ )
|
|
||||||
MSG_WriteByte( msg, state->poseparam[i] );
|
|
||||||
MSG_WriteWord( msg, modelIndex );
|
|
||||||
MSG_WriteByte( msg, state->body );
|
|
||||||
MSG_WriteByte( msg, state->skin );
|
|
||||||
MSG_WriteWord( msg, state->scale );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=======================
|
=======================
|
||||||
SV_CreateStaticEntity
|
SV_CreateStaticEntity
|
||||||
|
@ -3016,13 +2965,13 @@ edict_t *pfnPEntityOfEntIndex( int iEntIndex )
|
||||||
{
|
{
|
||||||
edict_t *pEdict = EDICT_NUM( iEntIndex );
|
edict_t *pEdict = EDICT_NUM( iEntIndex );
|
||||||
|
|
||||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
if( !iEntIndex || FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||||
return pEdict; // just get access to array
|
return pEdict; // just get access to array
|
||||||
|
|
||||||
if( SV_IsValidEdict( pEdict ) && pEdict->pvPrivateData )
|
if( SV_IsValidEdict( pEdict ) && pEdict->pvPrivateData )
|
||||||
return pEdict;
|
return pEdict;
|
||||||
|
|
||||||
// g-cont: clients can be acessed even without private data!
|
// g-cont: world and clients can be acessed even without private data!
|
||||||
if( SV_IsValidEdict( pEdict ) && SV_IsPlayerIndex( iEntIndex ))
|
if( SV_IsValidEdict( pEdict ) && SV_IsPlayerIndex( iEntIndex ))
|
||||||
return pEdict;
|
return pEdict;
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,16 +195,17 @@ int SV_GenericIndex( const char *filename )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( sv.state != ss_loading )
|
|
||||||
{
|
|
||||||
// g-cont. can we downloading resources in-game ? need testing
|
|
||||||
Host_Error( "SV_PrecacheGeneric: ( %s ). Precache can only be done in spawn functions.", name );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// register new generic resource
|
// register new generic resource
|
||||||
Q_strncpy( sv.files_precache[i], name, sizeof( sv.files_precache[i] ));
|
Q_strncpy( sv.files_precache[i], name, sizeof( sv.files_precache[i] ));
|
||||||
|
|
||||||
|
if( sv.state != ss_loading )
|
||||||
|
{
|
||||||
|
// send the update to everyone
|
||||||
|
MSG_BeginServerCmd( &sv.reliable_datagram, svc_fileindex );
|
||||||
|
MSG_WriteUBitLong( &sv.reliable_datagram, i, MAX_CUSTOM_BITS );
|
||||||
|
MSG_WriteString( &sv.reliable_datagram, name );
|
||||||
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,8 +543,8 @@ void SV_ActivateServer( int runPhysics )
|
||||||
if( sv.ignored_static_ents )
|
if( sv.ignored_static_ents )
|
||||||
Con_Printf( S_WARN "%i static entities was rejected due buffer overflow\n", sv.ignored_static_ents );
|
Con_Printf( S_WARN "%i static entities was rejected due buffer overflow\n", sv.ignored_static_ents );
|
||||||
|
|
||||||
if( sv.ignored_studio_decals || sv.ignored_world_decals )
|
if( sv.ignored_world_decals )
|
||||||
Con_Printf( S_WARN "%i static decals was rejected due buffer overflow\n", sv.ignored_studio_decals + sv.ignored_world_decals );
|
Con_Printf( S_WARN "%i static decals was rejected due buffer overflow\n", sv.ignored_world_decals );
|
||||||
|
|
||||||
if( svs.maxclients > 1 )
|
if( svs.maxclients > 1 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -447,15 +447,14 @@ void ReapplyDecal( SAVERESTOREDATA *pSaveData, decallist_t *entry, qboolean adja
|
||||||
if( SV_RestoreCustomDecal( entry, pEdict, adjacent ))
|
if( SV_RestoreCustomDecal( entry, pEdict, adjacent ))
|
||||||
return; // decal was sucessfully restored at the game-side
|
return; // decal was sucessfully restored at the game-side
|
||||||
|
|
||||||
|
// studio decals are handled at game-side
|
||||||
|
if( FBitSet( flags, FDECAL_STUDIO ))
|
||||||
|
return;
|
||||||
|
|
||||||
// NOTE: at this point all decal indexes is valid
|
// NOTE: at this point all decal indexes is valid
|
||||||
decalIndex = pfnDecalIndex( entry->name );
|
decalIndex = pfnDecalIndex( entry->name );
|
||||||
|
|
||||||
if( FBitSet( flags, FDECAL_STUDIO ))
|
if( adjacent && entityIndex != 0 && !SV_IsValidEdict( pEdict ))
|
||||||
{
|
|
||||||
// NOTE: studio decal trace start saved into impactPlaneNormal
|
|
||||||
SV_CreateStudioDecal( &sv.signon, entry->position, entry->impactPlaneNormal, decalIndex, entityIndex, modelIndex, flags, &entry->studio_state );
|
|
||||||
}
|
|
||||||
else if( adjacent && entityIndex != 0 && !SV_IsValidEdict( pEdict ))
|
|
||||||
{
|
{
|
||||||
vec3_t testspot, testend;
|
vec3_t testspot, testend;
|
||||||
trace_t tr;
|
trace_t tr;
|
||||||
|
|
Reference in New Issue