20 Oct 2010
This commit is contained in:
parent
6b87c02012
commit
19d558fbcd
|
@ -159,7 +159,7 @@ typedef struct enginefuncs_s
|
|||
int (*pfnCompareFileTime)( const char *filename1, const char *filename2, int *iCompare );
|
||||
void (*pfnGetGameDir)( char *szGetGameDir );
|
||||
void (*pfnHostError)( const char *szFmt, ... );
|
||||
void (*pfnFadeClientVolume)( const edict_t *pEdict, float fadePercent, float fadeOutSeconds, float holdTime, float fadeInSeconds );
|
||||
void (*pfnFadeClientVolume)( const edict_t *pEdict, int fadePercent, int fadeOutSeconds, int holdTime, int fadeInSeconds );
|
||||
void (*pfnSetClientMaxspeed)( const edict_t *pEdict, float fNewMaxspeed );
|
||||
edict_t *(*pfnCreateFakeClient)( const char *netname ); // returns NULL if fake client can't be created
|
||||
void (*pfnRunPlayerMove)( edict_t *fakeclient, const float *viewangles, float forwardmove, float sidemove, float upmove, word buttons, byte impulse, byte msec );
|
||||
|
@ -199,6 +199,8 @@ typedef struct enginefuncs_s
|
|||
void (*pfnForceUnmodified)( FORCE_TYPE type, float *mins, float *maxs, const char *filename );
|
||||
void (*pfnGetPlayerStats)( const edict_t *pClient, int *ping, int *packet_loss );
|
||||
void (*pfnAddServerCommand)( const char *cmd_name, void (*function)(void), const char *cmd_desc );
|
||||
int (*pfnVoice_GetClientListening)( int iReceiver, int iSender );
|
||||
int (*pfnVoice_SetClientListening)( int iReceiver, int iSender, int bListen );
|
||||
const char *(*pfnGetPlayerAuthId)( edict_t *e );
|
||||
// ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 138
|
||||
} enginefuncs_t;
|
||||
|
@ -345,8 +347,8 @@ typedef struct
|
|||
// returns string describing current .dll. E.g., TeamFotrress 2, Half-Life
|
||||
const char *(*pfnGetGameDescription)( void );
|
||||
|
||||
// Notify dll about a player customization. (completely ignored in Xash3D)
|
||||
void (*pfnPlayerCustomization)( edict_t *pEntity, void *pUnused );
|
||||
// Notify dll about a player customization.
|
||||
void (*pfnPlayerCustomization)( edict_t *pEntity, customization_t *pCustom );
|
||||
|
||||
// Spectator funcs
|
||||
void (*pfnSpectatorConnect)( edict_t *pEntity );
|
||||
|
|
|
@ -854,11 +854,42 @@ void Sys_Error( const char *error_string )
|
|||
================
|
||||
PlayerCustomization
|
||||
|
||||
Completely ignored in Xash3D
|
||||
A new player customization has been registered on the server
|
||||
UNDONE: This only sets the # of frames of the spray can logo
|
||||
animation right now.
|
||||
================
|
||||
*/
|
||||
void PlayerCustomization( edict_t *pEntity, void *pCust )
|
||||
void PlayerCustomization( edict_t *pEntity, customization_t *pCust )
|
||||
{
|
||||
entvars_t *pev = &pEntity->v;
|
||||
CBasePlayer *pPlayer = (CBasePlayer *)GET_PRIVATE(pEntity);
|
||||
|
||||
if (!pPlayer)
|
||||
{
|
||||
ALERT(at_console, "PlayerCustomization: Couldn't get player!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pCust)
|
||||
{
|
||||
ALERT(at_console, "PlayerCustomization: NULL customization!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (pCust->resource.type)
|
||||
{
|
||||
case t_decal:
|
||||
pPlayer->SetCustomDecalFrames(pCust->nUserData2); // Second int is max # of frames.
|
||||
break;
|
||||
case t_sound:
|
||||
case t_skin:
|
||||
case t_model:
|
||||
// Ignore for now.
|
||||
break;
|
||||
default:
|
||||
ALERT(at_console, "PlayerCustomization: Unknown customization type!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -33,7 +33,7 @@ extern void ParmsChangeLevel( void );
|
|||
extern void ClientPrecache( void );
|
||||
|
||||
extern const char *GetGameDescription( void );
|
||||
extern void PlayerCustomization( edict_t *pEntity, void *pUnused );
|
||||
extern void PlayerCustomization( edict_t *pEntity, customization_t *pCustom );
|
||||
|
||||
extern void SpectatorConnect ( edict_t *pEntity );
|
||||
extern void SpectatorDisconnect ( edict_t *pEntity );
|
||||
|
|
|
@ -29,14 +29,14 @@ const char *svc_strings[256] =
|
|||
"svc_serverdata",
|
||||
"svc_restore",
|
||||
"svc_updateuserinfo",
|
||||
"svc_usermessage",
|
||||
"svc_unused14",
|
||||
"svc_clientdata",
|
||||
"svc_download",
|
||||
"svc_updatepings",
|
||||
"svc_particle",
|
||||
"svc_frame",
|
||||
"svc_spawnstatic",
|
||||
"svc_crosshairangle",
|
||||
"svc_unused21",
|
||||
"svc_spawnbaseline",
|
||||
"svc_temp_entity",
|
||||
"svc_setpause",
|
||||
|
@ -46,7 +46,7 @@ const char *svc_strings[256] =
|
|||
"svc_event_reliable",
|
||||
"svc_ambientsound",
|
||||
"svc_intermission",
|
||||
"svc_soundfade",
|
||||
"svc_unused31",
|
||||
"svc_cdtrack",
|
||||
"svc_serverinfo",
|
||||
"svc_deltatable",
|
||||
|
@ -54,7 +54,7 @@ const char *svc_strings[256] =
|
|||
"svc_bspdecal",
|
||||
"svc_roomtype",
|
||||
"svc_addangle",
|
||||
"svc_unused39",
|
||||
"svc_usermessage",
|
||||
"svc_packetentities",
|
||||
"svc_deltapacketentities",
|
||||
"svc_chokecount",
|
||||
|
@ -62,8 +62,8 @@ const char *svc_strings[256] =
|
|||
"svc_unused44",
|
||||
"svc_unused45",
|
||||
"svc_unused46",
|
||||
"svc_unused47",
|
||||
"svc_unused48",
|
||||
"svc_crosshairangle",
|
||||
"svc_soundfade",
|
||||
"svc_unused49",
|
||||
"svc_unused50",
|
||||
"svc_director",
|
||||
|
@ -521,10 +521,10 @@ void CL_ParseSoundFade( sizebuf_t *msg )
|
|||
float fadePercent, fadeOutSeconds;
|
||||
float holdTime, fadeInSeconds;
|
||||
|
||||
fadePercent = BF_ReadFloat( msg );
|
||||
fadeOutSeconds = BF_ReadFloat( msg );
|
||||
holdTime = BF_ReadFloat( msg );
|
||||
fadeInSeconds = BF_ReadFloat( msg );
|
||||
fadePercent = (float)BF_ReadByte( msg );
|
||||
holdTime = (float)BF_ReadByte( msg );
|
||||
fadeOutSeconds = (float)BF_ReadByte( msg );
|
||||
fadeInSeconds = (float)BF_ReadByte( msg );
|
||||
|
||||
S_FadeClientVolume( fadePercent, fadeOutSeconds, holdTime, fadeInSeconds );
|
||||
}
|
||||
|
@ -807,6 +807,7 @@ void CL_ParseAddAngle( sizebuf_t *msg )
|
|||
add_angle = BF_ReadBitAngle( msg, 16 );
|
||||
cl.refdef.cl_viewangles[1] += add_angle;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CL_ParseCrosshairAngle
|
||||
|
@ -816,8 +817,8 @@ offset crosshair angles
|
|||
*/
|
||||
void CL_ParseCrosshairAngle( sizebuf_t *msg )
|
||||
{
|
||||
cl.refdef.crosshairangle[0] = BF_ReadBitAngle( msg, 8 );
|
||||
cl.refdef.crosshairangle[1] = BF_ReadBitAngle( msg, 8 );
|
||||
cl.refdef.crosshairangle[0] = BF_ReadChar( msg ) * 0.2f;
|
||||
cl.refdef.crosshairangle[1] = BF_ReadChar( msg ) * 0.2f;
|
||||
cl.refdef.crosshairangle[2] = 0.0f; // not used for screen space
|
||||
}
|
||||
|
||||
|
@ -833,9 +834,9 @@ void CL_RegisterUserMessage( sizebuf_t *msg )
|
|||
char *pszName;
|
||||
int svc_num, size;
|
||||
|
||||
pszName = BF_ReadString( msg );
|
||||
svc_num = BF_ReadByte( msg );
|
||||
size = BF_ReadByte( msg );
|
||||
pszName = BF_ReadString( msg );
|
||||
|
||||
// important stuff
|
||||
if( size == 0xFF ) size = -1;
|
||||
|
|
|
@ -1,194 +0,0 @@
|
|||
//=======================================================================
|
||||
// Copyright XashXT Group 2010 ©
|
||||
// cm_light.c - lighting info for GETENTITYILLUM
|
||||
//=======================================================================
|
||||
|
||||
#include "cm_local.h"
|
||||
#include "edict.h"
|
||||
#include "mathlib.h"
|
||||
|
||||
static vec3_t cm_pointColor;
|
||||
static float cm_modulate;
|
||||
|
||||
/*
|
||||
=================
|
||||
CM_RecursiveLightPoint
|
||||
=================
|
||||
*/
|
||||
static bool CM_RecursiveLightPoint( mnode_t *node, const vec3_t start, const vec3_t end )
|
||||
{
|
||||
int side;
|
||||
mplane_t *plane;
|
||||
msurface_t *surf;
|
||||
mtexinfo_t *tex;
|
||||
vec3_t mid, scale;
|
||||
float front, back, frac;
|
||||
int i, map, size, s, t;
|
||||
byte *lm;
|
||||
|
||||
// didn't hit anything
|
||||
if( !node->plane ) return false;
|
||||
|
||||
// calculate mid point
|
||||
plane = node->plane;
|
||||
if( plane->type < 3 )
|
||||
{
|
||||
front = start[plane->type] - plane->dist;
|
||||
back = end[plane->type] - plane->dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
front = DotProduct( start, plane->normal ) - plane->dist;
|
||||
back = DotProduct( end, plane->normal ) - plane->dist;
|
||||
}
|
||||
|
||||
side = front < 0;
|
||||
if(( back < 0 ) == side )
|
||||
return CM_RecursiveLightPoint( node->children[side], start, end );
|
||||
|
||||
frac = front / ( front - back );
|
||||
|
||||
VectorLerp( start, frac, end, mid );
|
||||
|
||||
// co down front side
|
||||
if( CM_RecursiveLightPoint( node->children[side], start, mid ))
|
||||
return true; // hit something
|
||||
|
||||
if(( back < 0 ) == side )
|
||||
return false;// didn't hit anything
|
||||
|
||||
// check for impact on this node
|
||||
surf = node->firstface;
|
||||
|
||||
for( i = 0; i < node->numfaces; i++, surf++ )
|
||||
{
|
||||
tex = surf->texinfo;
|
||||
|
||||
if( surf->flags & SURF_DRAWTILED )
|
||||
continue; // no lightmaps
|
||||
|
||||
s = DotProduct( mid, tex->vecs[0] ) + tex->vecs[0][3] - surf->texturemins[0];
|
||||
t = DotProduct( mid, tex->vecs[1] ) + tex->vecs[1][3] - surf->texturemins[1];
|
||||
|
||||
if(( s < 0 || s > surf->extents[0] ) || ( t < 0 || t > surf->extents[1] ))
|
||||
continue;
|
||||
|
||||
s >>= 4;
|
||||
t >>= 4;
|
||||
|
||||
if( !surf->samples )
|
||||
return true;
|
||||
|
||||
VectorClear( cm_pointColor );
|
||||
|
||||
lm = surf->samples + 3 * (t * ((surf->extents[0] >> 4) + 1) + s);
|
||||
size = ((surf->extents[0] >> 4) + 1) * ((surf->extents[1] >> 4) + 1) * 3;
|
||||
|
||||
for( map = 0; map < surf->numstyles; map++ )
|
||||
{
|
||||
VectorScale( cm.lightstyle[surf->styles[map]].rgb, cm_modulate, scale );
|
||||
|
||||
cm_pointColor[0] += lm[0] * scale[0];
|
||||
cm_pointColor[1] += lm[1] * scale[1];
|
||||
cm_pointColor[2] += lm[2] * scale[2];
|
||||
|
||||
lm += size; // skip to next lightmap
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// go down back side
|
||||
return CM_RecursiveLightPoint( node->children[!side], mid, end );
|
||||
}
|
||||
|
||||
void CM_RunLightStyles( float time )
|
||||
{
|
||||
int i, ofs;
|
||||
clightstyle_t *ls;
|
||||
float l;
|
||||
|
||||
if( !worldmodel ) return;
|
||||
|
||||
// run lightstyles animation
|
||||
ofs = (time * 10);
|
||||
|
||||
if( ofs == cm.lastofs ) return;
|
||||
cm.lastofs = ofs;
|
||||
|
||||
for( i = 0, ls = cm.lightstyle; i < MAX_LIGHTSTYLES; i++, ls++ )
|
||||
{
|
||||
if( ls->length == 0 ) l = 0.0f;
|
||||
else if( ls->length == 1 ) l = ls->map[0];
|
||||
else l = ls->map[ofs%ls->length];
|
||||
|
||||
VectorSet( ls->rgb, l, l, l );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_AddLightStyle
|
||||
|
||||
needs to get correct working SV_LightPoint
|
||||
==================
|
||||
*/
|
||||
void CM_SetLightStyle( int style, const char* s )
|
||||
{
|
||||
int j, k;
|
||||
|
||||
j = com.strlen( s );
|
||||
cm.lightstyle[style].length = j;
|
||||
|
||||
for( k = 0; k < j; k++ )
|
||||
cm.lightstyle[style].map[k] = (float)( s[k]-'a' ) / (float)( 'm'-'a' );
|
||||
}
|
||||
|
||||
void CM_ClearLightStyles( void )
|
||||
{
|
||||
clightstyle_t *ls;
|
||||
int i;
|
||||
|
||||
Mem_Set( cm.lightstyle, 0, sizeof( cm.lightstyle ));
|
||||
|
||||
for( i = 0, ls = cm.lightstyle; i < MAX_LIGHTSTYLES; i++, ls++ )
|
||||
VectorSet( cm.lightstyle[i].rgb, 1.0f, 1.0f, 1.0f );
|
||||
cm.lastofs = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CM_LightEntity
|
||||
|
||||
grab the ambient lighting color for current point
|
||||
==================
|
||||
*/
|
||||
int CM_LightEntity( edict_t *pEdict )
|
||||
{
|
||||
vec3_t start, end;
|
||||
|
||||
if( !pEdict ) return 0;
|
||||
if( pEdict->v.effects & EF_FULLBRIGHT || !worldmodel->lightdata )
|
||||
{
|
||||
return 255;
|
||||
}
|
||||
|
||||
if( pEdict->v.flags & FL_CLIENT )
|
||||
{
|
||||
// client has more precision light level
|
||||
// that come from client
|
||||
return pEdict->v.light_level;
|
||||
}
|
||||
|
||||
VectorCopy( pEdict->v.origin, start );
|
||||
VectorCopy( pEdict->v.origin, end );
|
||||
|
||||
if( pEdict->v.effects & EF_INVLIGHT )
|
||||
end[2] = start[2] + 8192;
|
||||
else end[2] = start[2] - 8192;
|
||||
VectorSet( cm_pointColor, 1.0f, 1.0f, 1.0f );
|
||||
|
||||
cm_modulate = cm_lighting_modulate->value * (1.0 / 255);
|
||||
CM_RecursiveLightPoint( worldmodel->nodes, start, end );
|
||||
|
||||
return VectorAvg( cm_pointColor );
|
||||
}
|
|
@ -11,9 +11,6 @@
|
|||
#include "eiface.h"
|
||||
#include "com_model.h"
|
||||
|
||||
#define FMOVE_IGNORE_GLASS 0x100
|
||||
#define FMOVE_SIMPLEBOX 0x200
|
||||
|
||||
// 1/32 epsilon to keep floating point happy
|
||||
#define DIST_EPSILON (1.0f / 32.0f)
|
||||
#define FRAC_EPSILON (1.0f / 1024.0f)
|
||||
|
@ -22,14 +19,6 @@
|
|||
#define DVIS_PHS 1
|
||||
|
||||
extern cvar_t *cm_novis;
|
||||
extern cvar_t *cm_lighting_modulate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int length;
|
||||
float map[MAX_STRING];
|
||||
vec3_t rgb; // 0.0 - 2.0
|
||||
} clightstyle_t;
|
||||
|
||||
typedef struct leaflist_s
|
||||
{
|
||||
|
@ -55,24 +44,12 @@ typedef struct clipmap_s
|
|||
vec3_t hull_sizes[4]; // hull sizes
|
||||
|
||||
script_t *entityscript; // only actual for world
|
||||
|
||||
// run local lightstyles to get SV_LightPoint grab the actual information
|
||||
clightstyle_t lightstyle[MAX_LIGHTSTYLES];
|
||||
int lastofs;
|
||||
} clipmap_t;
|
||||
|
||||
extern clipmap_t cm;
|
||||
extern model_t *loadmodel;
|
||||
extern model_t *worldmodel;
|
||||
|
||||
//
|
||||
// cm_light.c
|
||||
//
|
||||
void CM_RunLightStyles( float time );
|
||||
void CM_SetLightStyle( int style, const char* val );
|
||||
int CM_LightEntity( edict_t *pEdict );
|
||||
void CM_ClearLightStyles( void );
|
||||
|
||||
//
|
||||
// cm_test.c
|
||||
//
|
||||
|
|
|
@ -25,7 +25,6 @@ model_t *worldmodel;
|
|||
|
||||
// cvars
|
||||
cvar_t *cm_novis;
|
||||
cvar_t *cm_lighting_modulate;
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
@ -106,7 +105,6 @@ static void CM_FreeModel( model_t *mod )
|
|||
bool CM_InitPhysics( void )
|
||||
{
|
||||
cm_novis = Cvar_Get( "cm_novis", "0", 0, "force to ignore server visibility" );
|
||||
cm_lighting_modulate = Cvar_Get( "r_lighting_modulate", "1", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "lightstyles modulate scale" );
|
||||
|
||||
Mem_Set( cm.nullrow, 0xFF, MAX_MAP_LEAFS / 8 );
|
||||
return true;
|
||||
|
@ -1025,11 +1023,8 @@ void CM_BeginRegistration( const char *name, bool clientload, uint *checksum )
|
|||
if( checksum ) *checksum = cm.checksum;
|
||||
if( !clientload )
|
||||
{
|
||||
// reset entity script...
|
||||
// reset the entity script
|
||||
Com_ResetScript( cm.entityscript );
|
||||
|
||||
// ..and lightstyles
|
||||
CM_ClearLightStyles();
|
||||
}
|
||||
sv_models[1] = cm_models; // make link to world
|
||||
|
||||
|
@ -1048,7 +1043,6 @@ void CM_BeginRegistration( const char *name, bool clientload, uint *checksum )
|
|||
|
||||
if( checksum ) *checksum = cm.checksum;
|
||||
|
||||
CM_ClearLightStyles();
|
||||
CM_CalcPHS ();
|
||||
}
|
||||
|
||||
|
|
|
@ -22,14 +22,14 @@
|
|||
#define svc_serverdata 11 // [long] protocol ...
|
||||
#define svc_restore 12 // restore saved game on the client
|
||||
#define svc_updateuserinfo 13 // [byte] playernum, [string] userinfo
|
||||
#define svc_usermessage 14 // [string][byte] REG_USER_MSG stuff
|
||||
|
||||
#define svc_clientdata 15 // [...]
|
||||
#define svc_download 16 // [short] size [size bytes]
|
||||
#define svc_updatepings 17 // [bit][idx][ping][packet_loss]
|
||||
#define svc_particle 18 // [float*3][char*3][byte][byte]
|
||||
#define svc_frame 19 // <OBSOLETE>
|
||||
#define svc_spawnstatic 20 // creates a static client entity
|
||||
#define svc_crosshairangle 21 // [short][short][short]
|
||||
|
||||
#define svc_spawnbaseline 22 // <see code>
|
||||
#define svc_temp_entity 23 // <variable sized>
|
||||
#define svc_setpause 24 // [byte] 0 = unpaused, 1 = paused
|
||||
|
@ -39,7 +39,7 @@
|
|||
#define svc_event_reliable 28 // playback event directly from message, not queue
|
||||
#define svc_ambientsound 29 // <see code>
|
||||
#define svc_intermission 30 // empty message (event)
|
||||
#define svc_soundfade 31 // [float*4] sound fade parms
|
||||
|
||||
#define svc_cdtrack 32 // [byte] track [byte] looptrack
|
||||
#define svc_serverinfo 33 // [string] key [string] value
|
||||
#define svc_deltatable 34 // [table header][...]
|
||||
|
@ -47,11 +47,14 @@
|
|||
#define svc_bspdecal 36 // [float*3][short][short][short]
|
||||
#define svc_roomtype 37 // [short] room type
|
||||
#define svc_addangle 38 // [angle] add angles when client turn on mover
|
||||
|
||||
#define svc_usermessage 39 // [byte][byte][string] REG_USER_MSG stuff
|
||||
#define svc_packetentities 40 // [short][...]
|
||||
#define svc_deltapacketentities 41 // [short][byte][...]
|
||||
#define svc_chokecount 42 // [byte]
|
||||
|
||||
#define svc_crosshairangle 47 // [byte][byte]
|
||||
#define svc_soundfade 48 // [float*4] sound fade parms
|
||||
|
||||
#define svc_director 51 // <variable sized>
|
||||
#define svc_lastmsg 64 // start user messages at this point
|
||||
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
#define MOVE_MISSILE 2 // extra size for monsters
|
||||
#define MOVE_WORLDONLY 3 // clip only world
|
||||
|
||||
#define FMOVE_IGNORE_GLASS 0x100
|
||||
#define FMOVE_SIMPLEBOX 0x200
|
||||
|
||||
#define CONTENTS_NONE 0 // no custom contents specified
|
||||
|
||||
/*
|
||||
|
|
|
@ -178,10 +178,6 @@ SOURCE=.\client\cl_world.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\common\cm_light.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\common\cm_model.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -63,6 +63,29 @@ typedef enum
|
|||
cs_spawned // client is fully in game
|
||||
} cl_state_t;
|
||||
|
||||
// server lightstyles (used for GetEntityIllum)
|
||||
typedef struct
|
||||
{
|
||||
int length;
|
||||
float map[MAX_STRING];
|
||||
vec3_t rgb; // 0.0 - 2.0
|
||||
} sv_lightstyle_t;
|
||||
|
||||
// instanced baselines container
|
||||
typedef struct
|
||||
{
|
||||
int count;
|
||||
string_t classnames[64];
|
||||
entity_state_t baselines[64];
|
||||
} sv_baselines_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
FORCE_TYPE force_state;
|
||||
vec3_t mins, maxs;
|
||||
} sv_consistency_t;
|
||||
|
||||
typedef struct server_s
|
||||
{
|
||||
sv_state_t state; // precache commands are only valid during load
|
||||
|
@ -80,6 +103,11 @@ typedef struct server_s
|
|||
|
||||
char configstrings[MAX_CONFIGSTRINGS][CS_SIZE];
|
||||
|
||||
sv_consistency_t consistency_files[MAX_MODELS];
|
||||
int num_consistency_files;
|
||||
|
||||
sv_baselines_t instanced; // instanced baselines
|
||||
|
||||
// unreliable data to send to clients.
|
||||
sizebuf_t datagram;
|
||||
byte datagram_buf[NET_MAX_PAYLOAD];
|
||||
|
@ -97,6 +125,9 @@ typedef struct server_s
|
|||
|
||||
model_t *worldmodel; // pointer to world
|
||||
|
||||
// run local lightstyles to let SV_LightPoint grab the actual information
|
||||
sv_lightstyle_t lightstyle[MAX_LIGHTSTYLES];
|
||||
|
||||
bool write_bad_message; // just for debug
|
||||
bool paused;
|
||||
} server_t;
|
||||
|
@ -179,6 +210,8 @@ typedef struct sv_client_s
|
|||
|
||||
int challenge; // challenge of this user, randomly generated
|
||||
int userid; // identifying number on server
|
||||
int authentication_method;
|
||||
uint WonID; // WonID
|
||||
} sv_client_t;
|
||||
|
||||
/*
|
||||
|
@ -321,6 +354,7 @@ extern cvar_t *sv_gravity;
|
|||
extern cvar_t *sv_stopspeed;
|
||||
extern cvar_t *sv_check_errors;
|
||||
extern cvar_t *sv_reconnect_limit;
|
||||
extern cvar_t *sv_lighting_modulate;
|
||||
extern cvar_t *rcon_password;
|
||||
extern cvar_t *hostname;
|
||||
extern cvar_t *sv_stepheight;
|
||||
|
@ -407,6 +441,7 @@ void SV_DirectConnect( netadr_t from );
|
|||
void SV_TogglePause( const char *msg );
|
||||
void SV_PutClientInServer( edict_t *ent );
|
||||
bool SV_ShouldUpdatePing( sv_client_t *cl );
|
||||
const char *SV_GetClientIDString( sv_client_t *cl );
|
||||
void SV_FullClientUpdate( sv_client_t *cl, sizebuf_t *msg );
|
||||
void SV_FullUpdateMovevars( sv_client_t *cl, sizebuf_t *msg );
|
||||
void SV_GetPlayerStats( sv_client_t *cl, int *ping, int *packet_loss );
|
||||
|
@ -523,5 +558,8 @@ void SV_LinkEdict( edict_t *ent, bool touch_triggers );
|
|||
void SV_TouchLinks( edict_t *ent, areanode_t *node );
|
||||
int SV_TruePointContents( const vec3_t p );
|
||||
int SV_PointContents( const vec3_t p );
|
||||
void SV_RunLightStyles( void );
|
||||
void SV_SetLightStyle( int style, const char* s );
|
||||
int SV_LightForEntity( edict_t *pEdict );
|
||||
|
||||
#endif//SERVER_H
|
|
@ -252,6 +252,9 @@ edict_t *SV_FakeConnect( const char *netname )
|
|||
|
||||
// setup fake client name
|
||||
Info_SetValueForKey( userinfo, "name", netname );
|
||||
Info_SetValueForKey( userinfo, "model", "gordon" );
|
||||
Info_SetValueForKey( userinfo, "topcolor", "1" );
|
||||
Info_SetValueForKey( userinfo, "bottomcolor", "1" );
|
||||
|
||||
// force the IP key/value pair so the game can filter based on ip
|
||||
Info_SetValueForKey( userinfo, "ip", "127.0.0.1" );
|
||||
|
@ -287,6 +290,7 @@ edict_t *SV_FakeConnect( const char *netname )
|
|||
newcl->challenge = -1; // fake challenge
|
||||
newcl->fakeclient = true;
|
||||
newcl->delta_sequence = -1;
|
||||
newcl->userid = g_userid++; // create unique userid
|
||||
ent->v.flags |= FL_FAKECLIENT; // mark it as fakeclient
|
||||
|
||||
// get the game a chance to reject this connection or modify the userinfo
|
||||
|
@ -491,6 +495,50 @@ char *SV_StatusString( void )
|
|||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
SV_GetClientIDString
|
||||
|
||||
Returns a pointer to a static char for most likely only printing.
|
||||
===============
|
||||
*/
|
||||
const char *SV_GetClientIDString( sv_client_t *cl )
|
||||
{
|
||||
static char result[CS_SIZE];
|
||||
|
||||
result[0] = '\0';
|
||||
|
||||
if( !cl )
|
||||
{
|
||||
MsgDev( D_ERROR, "SV_GetClientIDString: invalid client\n" );
|
||||
return result;
|
||||
}
|
||||
|
||||
if( cl->authentication_method == 0 )
|
||||
{
|
||||
// probably some old compatibility code.
|
||||
com.snprintf( result, sizeof( result ), "%010lu", cl->WonID );
|
||||
}
|
||||
else if( cl->authentication_method == 2 )
|
||||
{
|
||||
if( NET_IsLocalAddress( cl->netchan.remote_address ))
|
||||
{
|
||||
com.strncpy( result, "VALVE_ID_LOOPBACK", sizeof( result ));
|
||||
}
|
||||
else if( cl->WonID == 0 )
|
||||
{
|
||||
com.strncpy( result, "VALVE_ID_PENDING", sizeof( result ));
|
||||
}
|
||||
else
|
||||
{
|
||||
com.snprintf( result, sizeof( result ), "VALVE_%010lu", cl->WonID );
|
||||
}
|
||||
}
|
||||
else com.strncpy( result, "UNKNOWN", sizeof( result ));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_Status
|
||||
|
@ -1017,9 +1065,9 @@ void SV_UserMessages_f( sv_client_t *cl )
|
|||
if( message->name[0] )
|
||||
{
|
||||
BF_WriteByte( &cl->netchan.message, svc_usermessage );
|
||||
BF_WriteString( &cl->netchan.message, message->name );
|
||||
BF_WriteByte( &cl->netchan.message, message->number );
|
||||
BF_WriteByte( &cl->netchan.message, (byte)message->size );
|
||||
BF_WriteString( &cl->netchan.message, message->name );
|
||||
}
|
||||
start++;
|
||||
}
|
||||
|
|
|
@ -1106,7 +1106,7 @@ int pfnGetEntityIllum( edict_t* pEnt )
|
|||
MsgDev( D_WARN, "SV_GetEntityIllum: invalid entity %s\n", SV_ClassName( pEnt ));
|
||||
return 0;
|
||||
}
|
||||
return CM_LightEntity( pEnt );
|
||||
return SV_LightForEntity( pEnt );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2018,7 +2018,7 @@ void pfnLightStyle( int style, const char* val )
|
|||
if( style >= MAX_LIGHTSTYLES )
|
||||
Host_Error( "SV_LightStyle: style: %i >= %d", style, MAX_LIGHTSTYLES );
|
||||
|
||||
CM_SetLightStyle( style, val ); // update info for SV_LightPoint
|
||||
SV_SetLightStyle( style, val ); // update info for SV_LightPoint
|
||||
SV_ConfigString( CS_LIGHTSTYLES + style, val );
|
||||
}
|
||||
|
||||
|
@ -2527,11 +2527,8 @@ edict_t* pfnFindEntityByVars( entvars_t *pvars )
|
|||
for( i = 0; i < svgame.numEntities; i++ )
|
||||
{
|
||||
e = EDICT_NUM( i );
|
||||
if( !memcmp( &e->v, pvars, sizeof( entvars_t )))
|
||||
{
|
||||
MsgDev( D_INFO, "FindEntityByVars: %s\n", SV_ClassName( e ));
|
||||
if( &e->v == pvars )
|
||||
return e; // found it
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -2605,9 +2602,9 @@ int pfnRegUserMsg( const char *pszName, int iSize )
|
|||
{
|
||||
// tell the client about new user message
|
||||
BF_WriteByte( &sv.reliable_datagram, svc_usermessage );
|
||||
BF_WriteString( &sv.reliable_datagram, svgame.msg[i].name );
|
||||
BF_WriteByte( &sv.reliable_datagram, svgame.msg[i].number );
|
||||
BF_WriteByte( &sv.reliable_datagram, (byte)iSize );
|
||||
BF_WriteString( &sv.reliable_datagram, svgame.msg[i].name );
|
||||
}
|
||||
|
||||
return svgame.msg[i].number;
|
||||
|
@ -2622,7 +2619,7 @@ animating studiomodel
|
|||
*/
|
||||
void pfnAnimationAutomove( const edict_t* pEdict, float flTime )
|
||||
{
|
||||
// FIXME: implement
|
||||
// this is empty in the original HL
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2801,9 +2798,14 @@ void pfnCrosshairAngle( const edict_t *pClient, float pitch, float yaw )
|
|||
// fakeclients ignores it silently
|
||||
if( client->fakeclient ) return;
|
||||
|
||||
if( pitch > 180.0f ) pitch -= 360;
|
||||
if( pitch < -180.0f ) pitch += 360;
|
||||
if( yaw > 180.0f ) yaw -= 360;
|
||||
if( yaw < -180.0f ) yaw += 360;
|
||||
|
||||
BF_WriteByte( &client->netchan.message, svc_crosshairangle );
|
||||
BF_WriteBitAngle( &client->netchan.message, pitch, 8 );
|
||||
BF_WriteBitAngle( &client->netchan.message, yaw, 8 );
|
||||
BF_WriteChar( &client->netchan.message, pitch * 5 );
|
||||
BF_WriteChar( &client->netchan.message, yaw * 5 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2916,7 +2918,22 @@ pfnGetPlayerWONId
|
|||
*/
|
||||
uint pfnGetPlayerWONId( edict_t *e )
|
||||
{
|
||||
// FIXME: implement
|
||||
int i;
|
||||
sv_client_t *cl;
|
||||
|
||||
if( sv.state != ss_active )
|
||||
return -1;
|
||||
|
||||
if( !SV_ClientFromEdict( e, false ))
|
||||
return -1;
|
||||
|
||||
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
|
||||
{
|
||||
if( cl->edict == e && cl->authentication_method == 0 )
|
||||
{
|
||||
return cl->WonID;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -2954,7 +2971,7 @@ pfnFadeClientVolume
|
|||
|
||||
=============
|
||||
*/
|
||||
void pfnFadeClientVolume( const edict_t *pEdict, float fadePercent, float fadeOutSeconds, float holdTime, float fadeInSeconds )
|
||||
void pfnFadeClientVolume( const edict_t *pEdict, int fadePercent, int fadeOutSeconds, int holdTime, int fadeInSeconds )
|
||||
{
|
||||
sv_client_t *cl;
|
||||
|
||||
|
@ -2965,17 +2982,20 @@ void pfnFadeClientVolume( const edict_t *pEdict, float fadePercent, float fadeOu
|
|||
return;
|
||||
}
|
||||
|
||||
if( cl->fakeclient ) return;
|
||||
|
||||
BF_WriteByte( &cl->netchan.message, svc_soundfade );
|
||||
BF_WriteFloat( &cl->netchan.message, fadePercent );
|
||||
BF_WriteFloat( &cl->netchan.message, fadeOutSeconds );
|
||||
BF_WriteFloat( &cl->netchan.message, holdTime );
|
||||
BF_WriteFloat( &cl->netchan.message, fadeInSeconds );
|
||||
BF_WriteByte( &cl->netchan.message, fadePercent );
|
||||
BF_WriteByte( &cl->netchan.message, holdTime );
|
||||
BF_WriteByte( &cl->netchan.message, fadeOutSeconds );
|
||||
BF_WriteByte( &cl->netchan.message, fadeInSeconds );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnSetClientMaxspeed
|
||||
|
||||
fakeclients can be changed speed to
|
||||
=============
|
||||
*/
|
||||
void pfnSetClientMaxspeed( const edict_t *pEdict, float fNewMaxspeed )
|
||||
|
@ -3053,7 +3073,15 @@ returns actual entity count
|
|||
*/
|
||||
int pfnNumberOfEntities( void )
|
||||
{
|
||||
return svgame.numEntities;
|
||||
int i, total = 0;
|
||||
|
||||
for( i = 0; i < svgame.numEntities; i++ )
|
||||
{
|
||||
if( !svgame.edicts[i].free )
|
||||
total++;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3420,6 +3448,8 @@ pfnCheckVisibility
|
|||
*/
|
||||
int pfnCheckVisibility( const edict_t *ent, byte *pset )
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if( !SV_IsValidEdict( ent ))
|
||||
{
|
||||
MsgDev( D_WARN, "SV_CheckVisibility: invalid entity %s\n", SV_ClassName( ent ));
|
||||
|
@ -3442,6 +3472,8 @@ int pfnCheckVisibility( const edict_t *ent, byte *pset )
|
|||
|
||||
if( i == ent->num_leafs )
|
||||
return 0; // not visible
|
||||
|
||||
result = 1; // visible passed by leafs
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3454,6 +3486,8 @@ int pfnCheckVisibility( const edict_t *ent, byte *pset )
|
|||
// too many leafs for individual check, go by headnode
|
||||
if( !SV_HeadnodeVisible( node, pset ))
|
||||
return 0;
|
||||
|
||||
result = 2; // visible passed by headnode
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -3462,9 +3496,10 @@ int pfnCheckVisibility( const edict_t *ent, byte *pset )
|
|||
{
|
||||
if( !CM_BoxVisible( ent->v.absmin, ent->v.absmax, pset ))
|
||||
return 0;
|
||||
result = 3; // visible passed by BoxVisible
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3520,8 +3555,18 @@ pfnCreateInstancedBaseline
|
|||
*/
|
||||
int pfnCreateInstancedBaseline( int classname, struct entity_state_s *baseline )
|
||||
{
|
||||
// FIXME: implement
|
||||
return 0;
|
||||
int i;
|
||||
|
||||
if( !baseline ) return -1;
|
||||
|
||||
i = sv.instanced.count;
|
||||
if( i > 62 ) return 0;
|
||||
|
||||
sv.instanced.classnames[i] = classname;
|
||||
sv.instanced.baselines[i] = *baseline;
|
||||
sv.instanced.count++;
|
||||
|
||||
return i+1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3548,7 +3593,7 @@ int pfnGetPlayerUserId( edict_t *e )
|
|||
sv_client_t *cl;
|
||||
int i;
|
||||
|
||||
if( !svs.initialized )
|
||||
if( sv.state != ss_active )
|
||||
return -1;
|
||||
|
||||
if( !SV_ClientFromEdict( e, false ))
|
||||
|
@ -3615,7 +3660,7 @@ void pfnGetPlayerStats( const edict_t *pClient, int *ping, int *packet_loss )
|
|||
return;
|
||||
}
|
||||
|
||||
if( ping ) *ping = cl->ping * 1000;
|
||||
if( ping ) *ping = cl->ping * 1000; // this is should be cl->latency not ping!
|
||||
if( packet_loss ) *packet_loss = cl->packet_loss;
|
||||
}
|
||||
|
||||
|
@ -3638,7 +3683,46 @@ pfnForceUnmodified
|
|||
*/
|
||||
void pfnForceUnmodified( FORCE_TYPE type, float *mins, float *maxs, const char *filename )
|
||||
{
|
||||
// FIXME: implement
|
||||
sv_consistency_t *pData;
|
||||
int i;
|
||||
|
||||
if( !filename || !*filename )
|
||||
{
|
||||
Host_Error( "SV_ForceUnmodified: bad filename string.\n" );
|
||||
}
|
||||
|
||||
if( sv.state == ss_loading )
|
||||
{
|
||||
for( i = 0, pData = sv.consistency_files; i < MAX_MODELS; i++, pData++ )
|
||||
{
|
||||
if( !pData->name )
|
||||
{
|
||||
pData->name = filename;
|
||||
pData->force_state = type;
|
||||
|
||||
if( mins ) VectorCopy( mins, pData->mins );
|
||||
if( maxs ) VectorCopy( maxs, pData->maxs );
|
||||
return;
|
||||
}
|
||||
else if( !com.strcmp( filename, pData->name ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
Host_Error( "SV_ForceUnmodified: MAX_MODELS limit exceeded\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0, pData = sv.consistency_files; i < MAX_MODELS; i++, pData++ )
|
||||
{
|
||||
if( !pData->name || com.strcmp( filename, pData->name ))
|
||||
continue;
|
||||
|
||||
// if we are here' we found a match.
|
||||
return;
|
||||
}
|
||||
Host_Error( "SV_ForceUnmodified: can only be done during precache\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3652,6 +3736,56 @@ void pfnAddServerCommand( const char *cmd_name, void (*function)(void), const ch
|
|||
Cmd_AddCommand( cmd_name, function, cmd_desc );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnVoice_GetClientListening
|
||||
|
||||
=============
|
||||
*/
|
||||
bool pfnVoice_GetClientListening( int iReceiver, int iSender )
|
||||
{
|
||||
int iMaxClients = sv_maxclients->integer;
|
||||
|
||||
if( !svs.initialized ) return false;
|
||||
|
||||
if( iReceiver <= 0 || iReceiver > iMaxClients || iSender <= 0 || iSender > iMaxClients )
|
||||
{
|
||||
MsgDev( D_ERROR, "Voice_GetClientListening: invalid client indexes (%i, %i).\n", iReceiver, iSender );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((svs.clients[iSender].listeners & ( 1 << iReceiver )) != 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnVoice_SetClientListening
|
||||
|
||||
=============
|
||||
*/
|
||||
bool pfnVoice_SetClientListening( int iReceiver, int iSender, bool bListen )
|
||||
{
|
||||
int iMaxClients = sv_maxclients->integer;
|
||||
|
||||
if( !svs.initialized ) return false;
|
||||
|
||||
if( iReceiver <= 0 || iReceiver > iMaxClients || iSender <= 0 || iSender > iMaxClients )
|
||||
{
|
||||
MsgDev( D_ERROR, "Voice_SetClientListening: invalid client indexes (%i, %i).\n", iReceiver, iSender );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( bListen )
|
||||
{
|
||||
svs.clients[iSender].listeners |= (1 << iReceiver);
|
||||
}
|
||||
else
|
||||
{
|
||||
svs.clients[iSender].listeners &= ~(1 << iReceiver);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnGetPlayerAuthId
|
||||
|
@ -3663,7 +3797,38 @@ return nullstring for now
|
|||
*/
|
||||
const char *pfnGetPlayerAuthId( edict_t *e )
|
||||
{
|
||||
return "";
|
||||
sv_client_t *cl;
|
||||
static string result;
|
||||
int i;
|
||||
|
||||
if( sv.state != ss_active || !SV_IsValidEdict( e ))
|
||||
{
|
||||
result[0] = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
|
||||
{
|
||||
if( cl->edict == e )
|
||||
{
|
||||
if( cl->fakeclient )
|
||||
{
|
||||
com.strncat( result, "BOT", sizeof( result ));
|
||||
}
|
||||
else if( cl->authentication_method == 0 )
|
||||
{
|
||||
com.snprintf( result, sizeof( result ), "%u", (uint)cl->WonID );
|
||||
}
|
||||
else
|
||||
{
|
||||
com.snprintf( result, sizeof( result ), "%s", SV_GetClientIDString( cl ));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result[0] = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
// engine callbacks
|
||||
|
@ -3810,6 +3975,8 @@ static enginefuncs_t gEngfuncs =
|
|||
pfnForceUnmodified,
|
||||
pfnGetPlayerStats,
|
||||
pfnAddServerCommand,
|
||||
pfnVoice_GetClientListening,
|
||||
pfnVoice_SetClientListening,
|
||||
pfnGetPlayerAuthId,
|
||||
};
|
||||
|
||||
|
|
|
@ -94,6 +94,9 @@ void SV_CreateBaseline( void )
|
|||
if( !SV_IsValidEdict( pEdict )) continue;
|
||||
SV_BaselineForEntity( pEdict );
|
||||
}
|
||||
|
||||
// create the instanced baselines
|
||||
svgame.dllFuncs.pfnCreateInstancedBaselines();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -40,6 +40,7 @@ cvar_t *sv_waterfriction;
|
|||
cvar_t *sv_synchthink;
|
||||
cvar_t *sv_stopspeed;
|
||||
cvar_t *hostname;
|
||||
cvar_t *sv_lighting_modulate;
|
||||
cvar_t *sv_maxclients;
|
||||
cvar_t *sv_check_errors;
|
||||
cvar_t *sv_footsteps;
|
||||
|
@ -621,6 +622,7 @@ void SV_Init( void )
|
|||
physinfo = Cvar_Get( "@physinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only
|
||||
serverinfo = Cvar_Get( "@serverinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only
|
||||
public_server = Cvar_Get ("public", "0", 0, "change server type from private to public" );
|
||||
sv_lighting_modulate = Cvar_Get( "r_lighting_modulate", "1", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "lightstyles modulate scale" );
|
||||
sv_reconnect_limit = Cvar_Get ("sv_reconnect_limit", "3", CVAR_ARCHIVE, "max reconnect attempts" );
|
||||
sv_failuretime = Cvar_Get( "sv_failuretime", "0.5", 0, "after this long without a packet from client, don't send any more until client starts sending again" );
|
||||
sv_unlag = Cvar_Get( "sv_unlag", "1", 0, "allow lag compensation on server-side" );
|
||||
|
|
|
@ -1577,7 +1577,7 @@ void SV_Physics( void )
|
|||
}
|
||||
|
||||
// animate lightstyles (used for GetEntityIllum)
|
||||
CM_RunLightStyles( sv.time );
|
||||
SV_RunLightStyles ();
|
||||
|
||||
// at end of frame kill all entities which supposed to it
|
||||
SV_FreeOldEntities();
|
||||
|
|
|
@ -28,6 +28,8 @@ typedef struct moveclip_s
|
|||
int hull; // -1 to let entity select hull
|
||||
} moveclip_t;
|
||||
|
||||
static int sv_lastofs; // lightstyles code use this
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
|
@ -336,9 +338,17 @@ SV_ClearWorld
|
|||
*/
|
||||
void SV_ClearWorld( void )
|
||||
{
|
||||
sv_lightstyle_t *ls;
|
||||
int i;
|
||||
|
||||
SV_InitBoxHull(); // for box testing
|
||||
SV_InitStudioHull(); // for hitbox testing
|
||||
|
||||
// clear lightstyles
|
||||
for( i = 0, ls = sv.lightstyle; i < MAX_LIGHTSTYLES; i++, ls++ )
|
||||
VectorSet( sv.lightstyle[i].rgb, 1.0f, 1.0f, 1.0f );
|
||||
sv_lastofs = -1;
|
||||
|
||||
Mem_Set( sv_areanodes, 0, sizeof( sv_areanodes ));
|
||||
sv_numareanodes = 0;
|
||||
|
||||
|
@ -1360,4 +1370,184 @@ trace_t SV_MoveToss( edict_t *tossent, edict_t *ignore )
|
|||
VectorCopy( original_avelocity, tossent->v.avelocity );
|
||||
|
||||
return trace;
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
LIGHTING INFO
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
static vec3_t sv_pointColor;
|
||||
static float sv_modulate;
|
||||
|
||||
/*
|
||||
=================
|
||||
SV_RecursiveLightPoint
|
||||
=================
|
||||
*/
|
||||
static bool SV_RecursiveLightPoint( mnode_t *node, const vec3_t start, const vec3_t end )
|
||||
{
|
||||
int side;
|
||||
mplane_t *plane;
|
||||
msurface_t *surf;
|
||||
mtexinfo_t *tex;
|
||||
vec3_t mid, scale;
|
||||
float front, back, frac;
|
||||
int i, map, size, s, t;
|
||||
byte *lm;
|
||||
|
||||
// didn't hit anything
|
||||
if( !node->plane ) return false;
|
||||
|
||||
// calculate mid point
|
||||
plane = node->plane;
|
||||
if( plane->type < 3 )
|
||||
{
|
||||
front = start[plane->type] - plane->dist;
|
||||
back = end[plane->type] - plane->dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
front = DotProduct( start, plane->normal ) - plane->dist;
|
||||
back = DotProduct( end, plane->normal ) - plane->dist;
|
||||
}
|
||||
|
||||
side = front < 0;
|
||||
if(( back < 0 ) == side )
|
||||
return SV_RecursiveLightPoint( node->children[side], start, end );
|
||||
|
||||
frac = front / ( front - back );
|
||||
|
||||
VectorLerp( start, frac, end, mid );
|
||||
|
||||
// co down front side
|
||||
if( SV_RecursiveLightPoint( node->children[side], start, mid ))
|
||||
return true; // hit something
|
||||
|
||||
if(( back < 0 ) == side )
|
||||
return false;// didn't hit anything
|
||||
|
||||
// check for impact on this node
|
||||
surf = node->firstface;
|
||||
|
||||
for( i = 0; i < node->numfaces; i++, surf++ )
|
||||
{
|
||||
tex = surf->texinfo;
|
||||
|
||||
if( surf->flags & SURF_DRAWTILED )
|
||||
continue; // no lightmaps
|
||||
|
||||
s = DotProduct( mid, tex->vecs[0] ) + tex->vecs[0][3] - surf->texturemins[0];
|
||||
t = DotProduct( mid, tex->vecs[1] ) + tex->vecs[1][3] - surf->texturemins[1];
|
||||
|
||||
if(( s < 0 || s > surf->extents[0] ) || ( t < 0 || t > surf->extents[1] ))
|
||||
continue;
|
||||
|
||||
s >>= 4;
|
||||
t >>= 4;
|
||||
|
||||
if( !surf->samples )
|
||||
return true;
|
||||
|
||||
VectorClear( sv_pointColor );
|
||||
|
||||
lm = surf->samples + 3 * (t * ((surf->extents[0] >> 4) + 1) + s);
|
||||
size = ((surf->extents[0] >> 4) + 1) * ((surf->extents[1] >> 4) + 1) * 3;
|
||||
|
||||
for( map = 0; map < surf->numstyles; map++ )
|
||||
{
|
||||
VectorScale( sv.lightstyle[surf->styles[map]].rgb, sv_modulate, scale );
|
||||
|
||||
sv_pointColor[0] += lm[0] * scale[0];
|
||||
sv_pointColor[1] += lm[1] * scale[1];
|
||||
sv_pointColor[2] += lm[2] * scale[2];
|
||||
|
||||
lm += size; // skip to next lightmap
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// go down back side
|
||||
return SV_RecursiveLightPoint( node->children[!side], mid, end );
|
||||
}
|
||||
|
||||
void SV_RunLightStyles( void )
|
||||
{
|
||||
int i, ofs;
|
||||
sv_lightstyle_t *ls;
|
||||
float l;
|
||||
|
||||
// run lightstyles animation
|
||||
ofs = (sv.time * 10);
|
||||
|
||||
if( ofs == sv_lastofs ) return;
|
||||
sv_lastofs = ofs;
|
||||
|
||||
for( i = 0, ls = sv.lightstyle; i < MAX_LIGHTSTYLES; i++, ls++ )
|
||||
{
|
||||
if( ls->length == 0 ) l = 0.0f;
|
||||
else if( ls->length == 1 ) l = ls->map[0];
|
||||
else l = ls->map[ofs%ls->length];
|
||||
|
||||
VectorSet( ls->rgb, l, l, l );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_AddLightStyle
|
||||
|
||||
needs to get correct working SV_LightPoint
|
||||
==================
|
||||
*/
|
||||
void SV_SetLightStyle( int style, const char* s )
|
||||
{
|
||||
int j, k;
|
||||
|
||||
j = com.strlen( s );
|
||||
sv.lightstyle[style].length = j;
|
||||
|
||||
for( k = 0; k < j; k++ )
|
||||
sv.lightstyle[style].map[k] = (float)( s[k]-'a' ) / (float)( 'm'-'a' );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_LightForEntity
|
||||
|
||||
grab the ambient lighting color for current point
|
||||
==================
|
||||
*/
|
||||
int SV_LightForEntity( edict_t *pEdict )
|
||||
{
|
||||
vec3_t start, end;
|
||||
|
||||
if( !pEdict ) return 0;
|
||||
if( pEdict->v.effects & EF_FULLBRIGHT || !sv.worldmodel->lightdata )
|
||||
{
|
||||
return 255;
|
||||
}
|
||||
|
||||
if( pEdict->v.flags & FL_CLIENT )
|
||||
{
|
||||
// client has more precision light level
|
||||
// that come from client
|
||||
return pEdict->v.light_level;
|
||||
}
|
||||
|
||||
VectorCopy( pEdict->v.origin, start );
|
||||
VectorCopy( pEdict->v.origin, end );
|
||||
|
||||
if( pEdict->v.effects & EF_INVLIGHT )
|
||||
end[2] = start[2] + 8192;
|
||||
else end[2] = start[2] - 8192;
|
||||
VectorSet( sv_pointColor, 1.0f, 1.0f, 1.0f );
|
||||
|
||||
sv_modulate = sv_lighting_modulate->value * (1.0f / 255);
|
||||
SV_RecursiveLightPoint( worldmodel->nodes, start, end );
|
||||
|
||||
return VectorAvg( sv_pointColor );
|
||||
}
|
Reference in New Issue