2004-08-23 00:15:46 +00:00
/*
Copyright ( C ) 1996 - 1997 Id Software , Inc .
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
# include "qwsvdef.h"
2004-11-29 01:21:00 +00:00
# ifndef CLIENTONLY
2004-08-23 00:15:46 +00:00
void SV_CleanupEnts ( void ) ;
extern qboolean pr_udc_exteffect_enabled ;
extern cvar_t sv_nailhack ;
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
The PVS must include a small area around the client to allow head bobbing
or other small motion on the client side . Otherwise , a bob might cause an
entity that should be visible to not show up , especially when the bob
crosses a waterline .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
int needcleanup ;
int fatbytes ;
qbyte fatpvs [ ( MAX_MAP_LEAFS + 1 ) / 4 ] ;
# ifdef Q2BSPS
2005-08-26 22:56:51 +00:00
void SV_Q2BSP_FatPVS ( model_t * mod , vec3_t org )
2004-08-23 00:15:46 +00:00
{
int leafs [ 64 ] ;
int i , j , count ;
int longs ;
qbyte * src ;
vec3_t mins , maxs ;
for ( i = 0 ; i < 3 ; i + + )
{
mins [ i ] = org [ i ] - 8 ;
maxs [ i ] = org [ i ] + 8 ;
}
2005-08-26 22:56:51 +00:00
count = CM_BoxLeafnums ( mod , mins , maxs , leafs , 64 , NULL ) ;
2004-08-23 00:15:46 +00:00
if ( count < 1 )
Sys_Error ( " SV_Q2FatPVS: count < 1 " ) ;
if ( sv . worldmodel - > fromgame = = fg_quake3 )
2005-08-26 22:56:51 +00:00
longs = CM_ClusterSize ( mod ) ;
2004-08-23 00:15:46 +00:00
else
2005-08-26 22:56:51 +00:00
longs = ( CM_NumClusters ( mod ) + 31 ) > > 5 ;
2004-08-23 00:15:46 +00:00
// convert leafs to clusters
for ( i = 0 ; i < count ; i + + )
2005-08-26 22:56:51 +00:00
leafs [ i ] = CM_LeafCluster ( mod , leafs [ i ] ) ;
2004-08-23 00:15:46 +00:00
2005-08-26 22:56:51 +00:00
CM_ClusterPVS ( mod , leafs [ 0 ] , fatpvs ) ;
2004-08-23 00:15:46 +00:00
// memcpy (fatpvs, CM_ClusterPVS(leafs[0]), longs<<2);
// or in all the other leaf bits
for ( i = 1 ; i < count ; i + + )
{
for ( j = 0 ; j < i ; j + + )
if ( leafs [ i ] = = leafs [ j ] )
break ;
if ( j ! = i )
continue ; // already have the cluster we want
2005-08-26 22:56:51 +00:00
src = CM_ClusterPVS ( mod , leafs [ i ] , NULL ) ;
2004-08-23 00:15:46 +00:00
for ( j = 0 ; j < longs ; j + + )
( ( long * ) fatpvs ) [ j ] | = ( ( long * ) src ) [ j ] ;
}
}
# endif
//=============================================================================
// because there can be a lot of nails, there is a special
// network protocol for them
# define MAX_NAILS 32
edict_t * nails [ MAX_NAILS ] ;
int numnails ;
int nailcount = 0 ;
extern int sv_nailmodel , sv_supernailmodel , sv_playermodel ;
qboolean demonails ;
# ifdef PEXT_LIGHTUPDATES
edict_t * light [ MAX_NAILS ] ;
int numlight ;
extern int sv_lightningmodel ;
# endif
2005-04-26 16:04:12 +00:00
static edict_t * csqcent [ MAX_EDICTS ] ;
static int csqcnuments ;
2005-02-12 18:56:04 +00:00
2004-08-23 00:15:46 +00:00
qboolean SV_AddNailUpdate ( edict_t * ent )
{
2005-03-28 00:11:59 +00:00
if ( ent - > v - > modelindex ! = sv_nailmodel
& & ent - > v - > modelindex ! = sv_supernailmodel )
2004-08-23 00:15:46 +00:00
return false ;
if ( sv_nailhack . value )
return false ;
2005-05-20 03:32:53 +00:00
demonails = false ;
2004-08-23 00:15:46 +00:00
if ( numnails = = MAX_NAILS )
return true ;
nails [ numnails ] = ent ;
numnails + + ;
return true ;
}
qboolean SV_DemoNailUpdate ( int i )
{
demonails = true ;
if ( numnails = = MAX_NAILS )
return true ;
nails [ numnails ] = ( edict_t * ) i ;
numnails + + ;
return true ;
}
# ifdef PEXT_LIGHTUPDATES
qboolean SV_AddLightUpdate ( edict_t * ent )
{
2005-03-28 00:11:59 +00:00
if ( ent - > v - > modelindex ! = sv_lightningmodel )
2004-08-23 00:15:46 +00:00
return false ;
if ( numlight = = MAX_NAILS )
return true ;
light [ numnails ] = ent ;
numlight + + ;
return true ;
}
# endif
void SV_EmitNailUpdate ( sizebuf_t * msg , qboolean recorder )
{
qbyte bits [ 6 ] ; // [48 bits] xyzpy 12 12 12 4 8
int n , i ;
edict_t * ent ;
int x , y , z , p , yaw ;
# ifdef PEXT_LIGHTUPDATES
if ( numlight )
{
MSG_WriteByte ( msg , svc_lightnings ) ;
MSG_WriteByte ( msg , numlight ) ;
for ( n = 0 ; n < numlight ; n + + )
{
ent = light [ n ] ;
2005-03-28 00:11:59 +00:00
x = ( int ) ( ent - > v - > origin [ 0 ] + 4096 ) > > 1 ;
y = ( int ) ( ent - > v - > origin [ 1 ] + 4096 ) > > 1 ;
z = ( int ) ( ent - > v - > origin [ 2 ] + 4096 ) > > 1 ;
p = ( int ) ( 16 * ent - > v - > angles [ 0 ] / 360 ) & 15 ;
yaw = ( int ) ( 256 * ent - > v - > angles [ 1 ] / 360 ) & 255 ;
2004-08-23 00:15:46 +00:00
bits [ 0 ] = x ;
bits [ 1 ] = ( x > > 8 ) | ( y < < 4 ) ;
bits [ 2 ] = ( y > > 4 ) ;
bits [ 3 ] = z ;
bits [ 4 ] = ( z > > 8 ) | ( p < < 4 ) ;
bits [ 5 ] = yaw ;
for ( i = 0 ; i < 6 ; i + + )
MSG_WriteByte ( msg , bits [ i ] ) ;
}
}
# endif
if ( ! numnails )
return ;
if ( recorder )
MSG_WriteByte ( msg , svc_nails2 ) ;
else
MSG_WriteByte ( msg , svc_nails ) ;
MSG_WriteByte ( msg , numnails ) ;
if ( demonails )
{
for ( n = 0 ; n < numnails ; n + + )
{
i = ( int ) ( nails [ n ] ) ;
if ( recorder ) {
if ( ! sv . demospikes [ i ] . id ) {
if ( ! ( ( + + nailcount ) & 255 ) ) nailcount + + ;
sv . demospikes [ i ] . id = nailcount & 255 ;
}
MSG_WriteByte ( msg , ( qbyte ) sv . demospikes [ i ] . id ) ;
}
x = ( int ) ( sv . demospikes [ i ] . org [ 0 ] + 4096 ) > > 1 ;
y = ( int ) ( sv . demospikes [ i ] . org [ 1 ] + 4096 ) > > 1 ;
z = ( int ) ( sv . demospikes [ i ] . org [ 2 ] + 4096 ) > > 1 ;
p = ( int ) ( sv . demospikes [ i ] . pitch ) & 15 ;
yaw = ( int ) ( sv . demospikes [ i ] . yaw ) & 255 ;
bits [ 0 ] = x ;
bits [ 1 ] = ( x > > 8 ) | ( y < < 4 ) ;
bits [ 2 ] = ( y > > 4 ) ;
bits [ 3 ] = z ;
bits [ 4 ] = ( z > > 8 ) | ( p < < 4 ) ;
bits [ 5 ] = yaw ;
for ( i = 0 ; i < 6 ; i + + )
MSG_WriteByte ( msg , bits [ i ] ) ;
}
return ;
}
for ( n = 0 ; n < numnails ; n + + )
{
ent = nails [ n ] ;
if ( recorder ) {
2005-03-28 00:11:59 +00:00
if ( ! ent - > v - > colormap ) {
2004-08-23 00:15:46 +00:00
if ( ! ( ( + + nailcount ) & 255 ) ) nailcount + + ;
2005-03-28 00:11:59 +00:00
ent - > v - > colormap = nailcount & 255 ;
2004-08-23 00:15:46 +00:00
}
2005-03-28 00:11:59 +00:00
MSG_WriteByte ( msg , ( qbyte ) ent - > v - > colormap ) ;
2004-08-23 00:15:46 +00:00
}
2005-03-28 00:11:59 +00:00
x = ( int ) ( ent - > v - > origin [ 0 ] + 4096 ) > > 1 ;
y = ( int ) ( ent - > v - > origin [ 1 ] + 4096 ) > > 1 ;
z = ( int ) ( ent - > v - > origin [ 2 ] + 4096 ) > > 1 ;
p = ( int ) ( 16 * ent - > v - > angles [ 0 ] / 360 ) & 15 ;
yaw = ( int ) ( 256 * ent - > v - > angles [ 1 ] / 360 ) & 255 ;
2004-08-23 00:15:46 +00:00
bits [ 0 ] = x ;
bits [ 1 ] = ( x > > 8 ) | ( y < < 4 ) ;
bits [ 2 ] = ( y > > 4 ) ;
bits [ 3 ] = z ;
bits [ 4 ] = ( z > > 8 ) | ( p < < 4 ) ;
bits [ 5 ] = yaw ;
for ( i = 0 ; i < 6 ; i + + )
MSG_WriteByte ( msg , bits [ i ] ) ;
}
}
2005-02-28 07:16:19 +00:00
//=============================================================================
//this is the bit of the code that sends the csqc entity deltas out.
//whenever the entity in question has a newer version than we sent to the client, we need to resend.
//So, we track the outgoing sequence that an entity was sent in, and the version.
//Upon detection of a dropped packet, we resend all entities who were last sent in that packet.
//When an entities' last sent version doesn't match the current version, we send.
static qboolean SV_AddCSQCUpdate ( client_t * client , edict_t * ent )
{
# ifndef PEXT_CSQC
return false ;
# else
2005-03-10 03:55:18 +00:00
if ( ! ( client - > csqcactive ) )
2005-02-28 07:16:19 +00:00
return false ;
2005-03-28 00:11:59 +00:00
if ( ! ent - > v - > SendEntity )
2005-02-28 07:16:19 +00:00
return false ;
csqcent [ csqcnuments + + ] = ent ;
return true ;
# endif
}
sizebuf_t csqcmsgbuffer ;
2005-02-12 18:56:04 +00:00
void SV_EmitCSQCUpdate ( client_t * client , sizebuf_t * msg )
{
2005-02-28 07:16:19 +00:00
# ifdef PEXT_CSQC
qbyte messagebuffer [ 1024 ] ;
int en ;
int currentsequence = client - > netchan . outgoing_sequence ;
unsigned short mask ;
globalvars_t * pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
edict_t * ent ;
qboolean writtenheader = false ;
// if (!csqcnuments)
// return;
2005-03-10 03:55:18 +00:00
if ( ! ( client - > csqcactive ) )
2005-02-28 07:16:19 +00:00
return ;
//FIXME: prioritise the list of csqc ents somehow
csqcmsgbuffer . data = messagebuffer ;
csqcmsgbuffer . maxsize = sizeof ( messagebuffer ) ;
csqcmsgbuffer . packing = msg - > packing ;
for ( en = 0 ; en < csqcnuments ; en + + )
{
ent = csqcent [ en ] ;
//prevent mishaps with entities being respawned and things.
2005-03-28 00:11:59 +00:00
if ( ( int ) ent - > v - > Version < sv . csqcentversion [ ent - > entnum ] )
ent - > v - > Version = sv . csqcentversion [ ent - > entnum ] ;
2005-02-28 07:16:19 +00:00
else
2005-03-28 00:11:59 +00:00
sv . csqcentversion [ ent - > entnum ] = ( int ) ent - > v - > Version ;
2005-02-28 07:16:19 +00:00
//If it's not changed, don't send
if ( client - > csqcentversions [ ent - > entnum ] = = sv . csqcentversion [ ent - > entnum ] )
continue ;
csqcmsgbuffer . cursize = 0 ;
csqcmsgbuffer . currentbit = 0 ;
//Ask CSQC to write a buffer for it.
G_INT ( OFS_PARM0 ) = EDICT_TO_PROG ( svprogfuncs , client - > edict ) ;
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , ent ) ;
2005-03-28 00:11:59 +00:00
PR_ExecuteProgram ( svprogfuncs , ent - > v - > SendEntity ) ;
2005-02-28 07:16:19 +00:00
if ( G_INT ( OFS_RETURN ) ) //0 means not to tell the client about it.
{
if ( msg - > cursize + csqcmsgbuffer . cursize + 5 > = msg - > maxsize )
{
if ( csqcmsgbuffer . cursize < 32 )
break ;
continue ;
}
if ( ! writtenheader )
{
writtenheader = true ;
MSG_WriteByte ( msg , svc_csqcentities ) ;
}
MSG_WriteShort ( msg , ent - > entnum ) ;
2005-03-20 02:57:11 +00:00
if ( sv . csqcdebug ) //optional extra.
{
if ( ! csqcmsgbuffer . cursize )
2005-03-28 00:11:59 +00:00
Con_Printf ( " Warning: empty csqc packet on %s \n " , svprogfuncs - > stringtable + ent - > v - > classname ) ;
2005-03-20 02:57:11 +00:00
MSG_WriteShort ( msg , csqcmsgbuffer . cursize ) ;
}
2005-02-28 07:16:19 +00:00
//FIXME: Add a developer mode to write the length of each entity.
SZ_Write ( msg , csqcmsgbuffer . data , csqcmsgbuffer . cursize ) ;
2005-04-16 16:21:27 +00:00
// Con_Printf("Sending update packet %i\n", ent->entnum);
2005-02-28 07:16:19 +00:00
}
else if ( sv . csqcentversion [ ent - > entnum ] )
{ //Don't want to send.
if ( ! writtenheader )
{
writtenheader = true ;
MSG_WriteByte ( msg , svc_csqcentities ) ;
}
2005-02-12 18:56:04 +00:00
2005-02-28 07:16:19 +00:00
mask = ( unsigned ) ent - > entnum | 0x8000 ;
MSG_WriteShort ( msg , mask ) ;
2005-04-16 16:21:27 +00:00
// Con_Printf("Sending remove 2 packet\n");
2005-02-28 07:16:19 +00:00
}
client - > csqcentversions [ ent - > entnum ] = sv . csqcentversion [ ent - > entnum ] ;
client - > csqcentsequence [ ent - > entnum ] = currentsequence ;
}
for ( en = 1 ; en < sv . num_edicts ; en + + )
{
if ( client - > csqcentversions [ en ] & & ( client - > csqcentversions [ en ] ! = sv . csqcentversion [ en ] ) )
{
ent = EDICT_NUM ( svprogfuncs , en ) ;
// if (!ent->isfree)
// continue;
if ( msg - > cursize + 5 > = msg - > maxsize ) //try removing next frame instead.
{
}
else
{
if ( ! writtenheader )
{
writtenheader = true ;
MSG_WriteByte ( msg , svc_csqcentities ) ;
}
2005-04-16 16:21:27 +00:00
// Con_Printf("Sending remove packet %i\n", en);
2005-02-28 07:16:19 +00:00
mask = ( unsigned ) en | 0x8000 ;
MSG_WriteShort ( msg , mask ) ;
client - > csqcentversions [ en ] = 0 ;
client - > csqcentsequence [ en ] = currentsequence ;
}
}
}
if ( writtenheader )
MSG_WriteShort ( msg , 0 ) ; //a 0 means no more.
csqcnuments = 0 ;
//prevent the qc from trying to use it at inopertune times.
csqcmsgbuffer . maxsize = 0 ;
csqcmsgbuffer . data = NULL ;
# endif
}
2005-03-10 03:55:18 +00:00
# ifdef PEXT_CSQC
2005-02-28 07:16:19 +00:00
void SV_CSQC_DroppedPacket ( client_t * client , int sequence )
{
int i ;
2005-03-10 03:55:18 +00:00
if ( ! ( client - > csqcactive ) ) //we don't need this, but it might be a little faster.
return ;
2005-02-28 07:16:19 +00:00
for ( i = 0 ; i < sv . num_edicts ; i + + )
if ( client - > csqcentsequence [ i ] = = sequence )
client - > csqcentversions [ i ] - - ; //do that update thang (but later).
2005-02-12 18:56:04 +00:00
}
2005-03-10 03:55:18 +00:00
# endif
2005-02-12 18:56:04 +00:00
2004-08-23 00:15:46 +00:00
//=============================================================================
/*
= = = = = = = = = = = = = = = = = =
SV_WriteDelta
Writes part of a packetentities message .
Can delta from either a baseline or a previous packet_entity
= = = = = = = = = = = = = = = = = =
*/
void SV_WriteDelta ( entity_state_t * from , entity_state_t * to , sizebuf_t * msg , qboolean force , unsigned int protext )
{
# ifdef PROTOCOLEXTENSIONS
int evenmorebits = 0 ;
# endif
int bits ;
int i ;
float miss ;
2004-12-08 04:14:52 +00:00
static entity_state_t defaultbaseline ;
if ( from = = & ( ( edict_t * ) NULL ) - > baseline )
from = & defaultbaseline ;
2004-08-23 00:15:46 +00:00
// send an update
bits = 0 ;
if ( to - > number > = 512 )
{
if ( to - > number > = 1024 )
{
if ( to - > number > = 1024 + 512 )
evenmorebits | = U_ENTITYDBL ;
evenmorebits | = U_ENTITYDBL2 ;
if ( to - > number > = 2048 )
SV_Error ( " Entity number >= 2048 " ) ;
}
else
evenmorebits | = U_ENTITYDBL ;
}
for ( i = 0 ; i < 3 ; i + + )
{
miss = to - > origin [ i ] - from - > origin [ i ] ;
if ( miss < - 0.1 | | miss > 0.1 )
{
bits | = U_ORIGIN1 < < i ;
}
}
if ( to - > angles [ 0 ] ! = from - > angles [ 0 ] )
bits | = U_ANGLE1 ;
if ( to - > angles [ 1 ] ! = from - > angles [ 1 ] )
bits | = U_ANGLE2 ;
if ( to - > angles [ 2 ] ! = from - > angles [ 2 ] )
bits | = U_ANGLE3 ;
if ( to - > colormap ! = from - > colormap )
bits | = U_COLORMAP ;
if ( to - > skinnum ! = from - > skinnum )
bits | = U_SKIN ;
if ( to - > frame ! = from - > frame )
bits | = U_FRAME ;
2005-08-26 22:56:51 +00:00
if ( ( to - > effects & 0x00ff ) ! = ( from - > effects & 0x00ff ) )
2004-08-23 00:15:46 +00:00
bits | = U_EFFECTS ;
2005-08-26 22:56:51 +00:00
if ( ( to - > effects & 0xff00 ) ! = ( from - > effects & 0xff00 ) )
evenmorebits | = U_EFFECTS16 ;
2004-08-23 00:15:46 +00:00
if ( to - > modelindex ! = from - > modelindex )
{
bits | = U_MODEL ;
if ( to - > modelindex > 255 )
evenmorebits | = U_MODELDBL ;
}
# ifdef PROTOCOLEXTENSIONS
# ifdef U_SCALE
if ( to - > scale ! = from - > scale & & protext & PEXT_SCALE )
evenmorebits | = U_SCALE ;
# endif
# ifdef U_TRANS
if ( to - > trans ! = from - > trans & & protext & PEXT_TRANS )
evenmorebits | = U_TRANS ;
# endif
# ifdef U_FATNESS
if ( to - > fatness ! = from - > fatness & & protext & PEXT_FATNESS )
evenmorebits | = U_FATNESS ;
# endif
2005-05-15 18:49:04 +00:00
if ( to - > hexen2flags ! = from - > hexen2flags & & protext & PEXT_HEXEN2 )
2004-08-23 00:15:46 +00:00
evenmorebits | = U_DRAWFLAGS ;
if ( to - > abslight ! = from - > abslight & & protext & PEXT_HEXEN2 )
evenmorebits | = U_ABSLIGHT ;
2005-07-01 19:23:00 +00:00
if ( to - > glowsize ! = from - > glowsize )
2005-05-17 02:36:54 +00:00
to - > dpflags | = 4 ;
2005-08-07 18:08:13 +00:00
if ( to - > dpflags ! = from - > dpflags & & protext & PEXT_DPFLAGS )
2005-05-15 18:49:04 +00:00
evenmorebits | = U_DPFLAGS ;
2005-08-07 18:08:13 +00:00
if ( ( to - > tagentity ! = from - > tagentity | | to - > tagindex ! = from - > tagindex ) & & protext & PEXT_DPFLAGS )
2005-07-01 19:23:00 +00:00
evenmorebits | = U_TAGINFO ;
2005-08-07 18:08:13 +00:00
if ( ( to - > light [ 0 ] ! = from - > light [ 0 ] | | to - > light [ 1 ] ! = from - > light [ 1 ] | | to - > light [ 2 ] ! = from - > light [ 2 ] | | to - > light [ 3 ] ! = from - > light [ 3 ] | | to - > lightstyle ! = from - > lightstyle | | to - > lightpflags ! = from - > lightstyle ) & & protext & PEXT_DPFLAGS )
evenmorebits | = U_LIGHT ;
2004-08-23 00:15:46 +00:00
if ( evenmorebits & 0xff00 )
evenmorebits | = U_YETMORE ;
if ( evenmorebits & 0x00ff )
bits | = U_EVENMORE ;
if ( bits & 511 )
bits | = U_MOREBITS ;
# endif
if ( to - > flags & U_SOLID )
bits | = U_SOLID ;
if ( msg - > cursize + 40 > msg - > maxsize )
{ //not enough space in the buffer, don't send the entity this frame. (not sending means nothing changes, and it takes no bytes!!)
* to = * from ;
return ;
}
//
// write the message
//
if ( ! to - > number )
SV_Error ( " Unset entity number " ) ;
if ( ! bits & & ! force )
return ; // nothing to send!
i = ( to - > number & 511 ) | ( bits & ~ 511 ) ;
if ( i & U_REMOVE )
Sys_Error ( " U_REMOVE " ) ;
MSG_WriteShort ( msg , i ) ;
if ( bits & U_MOREBITS )
MSG_WriteByte ( msg , bits & 255 ) ;
# ifdef PROTOCOLEXTENSIONS
if ( bits & U_EVENMORE )
MSG_WriteByte ( msg , evenmorebits & 255 ) ;
if ( evenmorebits & U_YETMORE )
MSG_WriteByte ( msg , ( evenmorebits > > 8 ) & 255 ) ;
# endif
if ( bits & U_MODEL )
MSG_WriteByte ( msg , to - > modelindex & 255 ) ;
if ( bits & U_FRAME )
MSG_WriteByte ( msg , to - > frame ) ;
if ( bits & U_COLORMAP )
MSG_WriteByte ( msg , to - > colormap ) ;
if ( bits & U_SKIN )
MSG_WriteByte ( msg , to - > skinnum ) ;
if ( bits & U_EFFECTS )
2005-08-26 22:56:51 +00:00
MSG_WriteByte ( msg , to - > effects & 0x00ff ) ;
2004-08-23 00:15:46 +00:00
if ( bits & U_ORIGIN1 )
2004-11-13 17:36:42 +00:00
MSG_WriteCoord ( msg , to - > origin [ 0 ] ) ;
2004-08-23 00:15:46 +00:00
if ( bits & U_ANGLE1 )
MSG_WriteAngle ( msg , to - > angles [ 0 ] ) ;
if ( bits & U_ORIGIN2 )
2004-11-13 17:36:42 +00:00
MSG_WriteCoord ( msg , to - > origin [ 1 ] ) ;
2004-08-23 00:15:46 +00:00
if ( bits & U_ANGLE2 )
MSG_WriteAngle ( msg , to - > angles [ 1 ] ) ;
if ( bits & U_ORIGIN3 )
2004-11-13 17:36:42 +00:00
MSG_WriteCoord ( msg , to - > origin [ 2 ] ) ;
2004-08-23 00:15:46 +00:00
if ( bits & U_ANGLE3 )
MSG_WriteAngle ( msg , to - > angles [ 2 ] ) ;
# ifdef U_SCALE
if ( evenmorebits & U_SCALE )
2005-07-01 19:23:00 +00:00
MSG_WriteByte ( msg , ( qbyte ) ( to - > scale ) ) ;
2004-08-23 00:15:46 +00:00
# endif
# ifdef U_TRANS
if ( evenmorebits & U_TRANS )
2005-07-01 19:23:00 +00:00
MSG_WriteByte ( msg , ( qbyte ) ( to - > trans ) ) ;
2004-08-23 00:15:46 +00:00
# endif
# ifdef U_FATNESS
if ( evenmorebits & U_FATNESS )
2005-07-01 19:23:00 +00:00
MSG_WriteChar ( msg , to - > fatness ) ;
2004-08-23 00:15:46 +00:00
# endif
if ( evenmorebits & U_DRAWFLAGS )
2005-05-15 18:49:04 +00:00
MSG_WriteByte ( msg , to - > hexen2flags ) ;
2004-08-23 00:15:46 +00:00
if ( evenmorebits & U_ABSLIGHT )
MSG_WriteByte ( msg , to - > abslight ) ;
2005-05-15 18:49:04 +00:00
if ( evenmorebits & U_DPFLAGS )
MSG_WriteByte ( msg , to - > dpflags ) ;
2005-07-01 19:23:00 +00:00
if ( evenmorebits & U_TAGINFO )
{
MSG_WriteShort ( msg , to - > tagentity ) ;
MSG_WriteShort ( msg , to - > tagindex ) ;
}
2005-08-07 18:08:13 +00:00
if ( evenmorebits & U_LIGHT )
{
MSG_WriteShort ( msg , to - > light [ 0 ] ) ;
MSG_WriteShort ( msg , to - > light [ 1 ] ) ;
MSG_WriteShort ( msg , to - > light [ 2 ] ) ;
MSG_WriteShort ( msg , to - > light [ 3 ] ) ;
MSG_WriteByte ( msg , to - > lightstyle ) ;
MSG_WriteByte ( msg , to - > lightpflags ) ;
}
2005-08-26 22:56:51 +00:00
if ( evenmorebits & U_EFFECTS16 )
MSG_WriteByte ( msg , ( to - > effects & 0xff00 ) > > 8 ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = =
SV_EmitPacketEntities
Writes a delta update of a packet_entities_t to the message .
= = = = = = = = = = = = =
*/
void SV_EmitPacketEntities ( client_t * client , packet_entities_t * to , sizebuf_t * msg )
{
edict_t * ent ;
client_frame_t * fromframe ;
packet_entities_t * from ;
int oldindex , newindex ;
int oldnum , newnum ;
int oldmax ;
// this is the frame that we are going to delta update from
if ( client - > delta_sequence ! = - 1 )
{
fromframe = & client - > frames [ client - > delta_sequence & UPDATE_MASK ] ;
from = & fromframe - > entities ;
oldmax = from - > num_entities ;
MSG_WriteByte ( msg , svc_deltapacketentities ) ;
MSG_WriteByte ( msg , client - > delta_sequence ) ;
}
else
{
oldmax = 0 ; // no delta update
from = NULL ;
MSG_WriteByte ( msg , svc_packetentities ) ;
}
newindex = 0 ;
oldindex = 0 ;
//Con_Printf ("---%i to %i ----\n", client->delta_sequence & UPDATE_MASK
// , client->netchan.outgoing_sequence & UPDATE_MASK);
while ( newindex < to - > num_entities | | oldindex < oldmax )
{
newnum = newindex > = to - > num_entities ? 9999 : to - > entities [ newindex ] . number ;
oldnum = oldindex > = oldmax ? 9999 : from - > entities [ oldindex ] . number ;
if ( newnum = = oldnum )
{ // delta update from old position
//Con_Printf ("delta %i\n", newnum);
# ifdef PROTOCOLEXTENSIONS
SV_WriteDelta ( & from - > entities [ oldindex ] , & to - > entities [ newindex ] , msg , false , client - > fteprotocolextensions ) ;
# else
SV_WriteDelta ( & from - > entities [ oldindex ] , & to - > entities [ newindex ] , msg , false ) ;
# endif
oldindex + + ;
newindex + + ;
continue ;
}
if ( newnum < oldnum )
{ // this is a new entity, send it from the baseline
ent = EDICT_NUM ( svprogfuncs , newnum ) ;
//Con_Printf ("baseline %i\n", newnum);
# ifdef PROTOCOLEXTENSIONS
SV_WriteDelta ( & ent - > baseline , & to - > entities [ newindex ] , msg , true , client - > fteprotocolextensions ) ;
# else
SV_WriteDelta ( & ent - > baseline , & to - > entities [ newindex ] , msg , true ) ;
# endif
newindex + + ;
continue ;
}
if ( newnum > oldnum )
{ // the old entity isn't present in the new message
//Con_Printf ("remove %i\n", oldnum);
MSG_WriteShort ( msg , oldnum | U_REMOVE ) ;
oldindex + + ;
continue ;
}
}
MSG_WriteShort ( msg , 0 ) ; // end of packetentities
}
2005-06-14 04:52:10 +00:00
# ifdef NQPROT
// reset all entity fields (typically used if status changed)
# define E5_FULLUPDATE (1<<0)
// E5_ORIGIN32=0: short[3] = s->origin[0] * 8, s->origin[1] * 8, s->origin[2] * 8
// E5_ORIGIN32=1: float[3] = s->origin[0], s->origin[1], s->origin[2]
# define E5_ORIGIN (1<<1)
// E5_ANGLES16=0: byte[3] = s->angle[0] * 256 / 360, s->angle[1] * 256 / 360, s->angle[2] * 256 / 360
// E5_ANGLES16=1: short[3] = s->angle[0] * 65536 / 360, s->angle[1] * 65536 / 360, s->angle[2] * 65536 / 360
# define E5_ANGLES (1<<2)
// E5_MODEL16=0: byte = s->modelindex
// E5_MODEL16=1: short = s->modelindex
# define E5_MODEL (1<<3)
// E5_FRAME16=0: byte = s->frame
// E5_FRAME16=1: short = s->frame
# define E5_FRAME (1<<4)
// byte = s->skin
# define E5_SKIN (1<<5)
// E5_EFFECTS16=0 && E5_EFFECTS32=0: byte = s->effects
// E5_EFFECTS16=1 && E5_EFFECTS32=0: short = s->effects
// E5_EFFECTS16=0 && E5_EFFECTS32=1: int = s->effects
// E5_EFFECTS16=1 && E5_EFFECTS32=1: int = s->effects
# define E5_EFFECTS (1<<6)
// bits >= (1<<8)
# define E5_EXTEND1 (1<<7)
// byte = s->renderflags
# define E5_FLAGS (1<<8)
// byte = bound(0, s->alpha * 255, 255)
# define E5_ALPHA (1<<9)
// byte = bound(0, s->scale * 16, 255)
# define E5_SCALE (1<<10)
// flag
# define E5_ORIGIN32 (1<<11)
// flag
# define E5_ANGLES16 (1<<12)
// flag
# define E5_MODEL16 (1<<13)
// byte = s->colormap
# define E5_COLORMAP (1<<14)
// bits >= (1<<16)
# define E5_EXTEND2 (1<<15)
// short = s->tagentity
// byte = s->tagindex
# define E5_ATTACHMENT (1<<16)
// short[4] = s->light[0], s->light[1], s->light[2], s->light[3]
// byte = s->lightstyle
// byte = s->lightpflags
# define E5_LIGHT (1<<17)
// byte = s->glowsize
// byte = s->glowcolor
# define E5_GLOW (1<<18)
// short = s->effects
# define E5_EFFECTS16 (1<<19)
// int = s->effects
# define E5_EFFECTS32 (1<<20)
// flag
# define E5_FRAME16 (1<<21)
// unused
2005-10-01 03:09:17 +00:00
# define E5_COLORMOD (1<<22)
2005-06-14 04:52:10 +00:00
// bits >= (1<<24)
# define E5_EXTEND3 (1<<23)
// unused
# define E5_UNUSED24 (1<<24)
// unused
# define E5_UNUSED25 (1<<25)
// unused
# define E5_UNUSED26 (1<<26)
// unused
# define E5_UNUSED27 (1<<27)
// unused
# define E5_UNUSED28 (1<<28)
// unused
# define E5_UNUSED29 (1<<29)
// unused
# define E5_UNUSED30 (1<<30)
// bits2 > 0
# define E5_EXTEND4 (1<<31)
void SVDP_EmitEntity ( entity_state_t * from , entity_state_t * to , sizebuf_t * msg , qboolean isnew )
{
int bits ;
2005-07-01 19:23:00 +00:00
if ( ! isnew & & ! memcmp ( from , to , sizeof ( entity_state_t ) ) )
{
to - > bitmask = 0 ;
2005-06-14 04:52:10 +00:00
return ; //didn't change
2005-07-01 19:23:00 +00:00
}
2005-06-14 04:52:10 +00:00
bits = 0 ;
if ( isnew )
2005-07-01 19:23:00 +00:00
{
2005-06-14 04:52:10 +00:00
bits | = E5_FULLUPDATE ;
2005-07-01 19:23:00 +00:00
to - > bitmask = 0 ; //no point...
}
2005-06-14 04:52:10 +00:00
if ( ! VectorCompare ( from - > origin , to - > origin ) )
bits | = E5_ORIGIN ;
if ( ! VectorCompare ( from - > angles , to - > angles ) )
bits | = E5_ANGLES ;
if ( from - > modelindex ! = to - > modelindex )
bits | = E5_MODEL ;
if ( from - > frame ! = to - > frame )
bits | = E5_FRAME ;
if ( from - > skinnum ! = to - > skinnum )
bits | = E5_SKIN ;
if ( from - > effects ! = to - > effects )
bits | = E5_EFFECTS ;
2005-07-01 19:23:00 +00:00
if ( from - > dpflags ! = to - > dpflags )
2005-06-14 04:52:10 +00:00
bits | = E5_FLAGS ;
if ( from - > trans ! = to - > trans )
bits | = E5_ALPHA ;
2005-07-01 19:23:00 +00:00
if ( from - > scale ! = to - > scale )
bits | = E5_SCALE ;
2005-06-14 04:52:10 +00:00
if ( from - > colormap ! = to - > colormap )
bits | = E5_COLORMAP ;
2005-07-01 19:23:00 +00:00
if ( from - > tagentity ! = to - > tagentity | | from - > tagindex ! = to - > tagindex )
bits | = E5_ATTACHMENT ;
2005-08-07 18:08:13 +00:00
if ( from - > light [ 0 ] ! = to - > light [ 0 ] | | from - > light [ 1 ] ! = to - > light [ 1 ] | | from - > light [ 2 ] ! = to - > light [ 2 ] | | from - > light [ 3 ] ! = to - > light [ 3 ] | | from - > lightstyle ! = to - > lightstyle | | from - > lightpflags ! = to - > lightpflags )
bits | = E5_LIGHT ;
2005-07-01 19:23:00 +00:00
if ( from - > glowsize ! = to - > glowsize | | from - > glowcolour ! = to - > glowcolour )
bits | = E5_GLOW ;
2005-10-01 03:09:17 +00:00
if ( from - > colormod [ 0 ] ! = to - > colormod [ 0 ] | | from - > colormod [ 1 ] ! = to - > colormod [ 1 ] | | from - > colormod [ 2 ] ! = to - > colormod [ 2 ] )
bits | = E5_COLORMOD ;
2005-06-14 04:52:10 +00:00
if ( ( bits & E5_ORIGIN ) & & ( /*!(to->flags & RENDER_LOWPRECISION) ||*/ to - > origin [ 0 ] < - 4096 | | to - > origin [ 0 ] > = 4096 | | to - > origin [ 1 ] < - 4096 | | to - > origin [ 1 ] > = 4096 | | to - > origin [ 2 ] < - 4096 | | to - > origin [ 2 ] > = 4096 ) )
bits | = E5_ORIGIN32 ;
if ( ( bits & E5_ANGLES ) /* && !(to->flags & RENDER_LOWPRECISION)*/ )
bits | = E5_ANGLES16 ;
if ( ( bits & E5_MODEL ) & & to - > modelindex > = 256 )
bits | = E5_MODEL16 ;
if ( ( bits & E5_FRAME ) & & to - > frame > = 256 )
bits | = E5_FRAME16 ;
if ( bits & E5_EFFECTS )
{
if ( to - > effects > = 65536 )
bits | = E5_EFFECTS32 ;
else if ( to - > effects > = 256 )
bits | = E5_EFFECTS16 ;
}
if ( bits > = 256 )
bits | = E5_EXTEND1 ;
if ( bits > = 65536 )
bits | = E5_EXTEND2 ;
if ( bits > = 16777216 )
bits | = E5_EXTEND3 ;
2005-07-01 19:23:00 +00:00
bits | = to - > bitmask ;
to - > bitmask = bits ;
2005-06-14 04:52:10 +00:00
if ( ! bits )
return ;
MSG_WriteShort ( msg , to - > number ) ;
MSG_WriteByte ( msg , bits & 0xFF ) ;
if ( bits & E5_EXTEND1 )
MSG_WriteByte ( msg , ( bits > > 8 ) & 0xFF ) ;
if ( bits & E5_EXTEND2 )
MSG_WriteByte ( msg , ( bits > > 16 ) & 0xFF ) ;
if ( bits & E5_EXTEND3 )
MSG_WriteByte ( msg , ( bits > > 24 ) & 0xFF ) ;
if ( bits & E5_FLAGS )
2005-07-01 19:23:00 +00:00
MSG_WriteByte ( msg , to - > dpflags ) ;
2005-06-14 04:52:10 +00:00
if ( bits & E5_ORIGIN )
{
if ( bits & E5_ORIGIN32 )
{
MSG_WriteFloat ( msg , to - > origin [ 0 ] ) ;
MSG_WriteFloat ( msg , to - > origin [ 1 ] ) ;
MSG_WriteFloat ( msg , to - > origin [ 2 ] ) ;
}
else
{
MSG_WriteShort ( msg , to - > origin [ 0 ] * 8 ) ;
MSG_WriteShort ( msg , to - > origin [ 1 ] * 8 ) ;
MSG_WriteShort ( msg , to - > origin [ 2 ] * 8 ) ;
}
}
if ( bits & E5_ANGLES )
{
if ( bits & E5_ANGLES16 )
{
MSG_WriteAngle16 ( msg , to - > angles [ 0 ] ) ;
MSG_WriteAngle16 ( msg , to - > angles [ 1 ] ) ;
MSG_WriteAngle16 ( msg , to - > angles [ 2 ] ) ;
}
else
{
MSG_WriteAngle8 ( msg , to - > angles [ 0 ] ) ;
MSG_WriteAngle8 ( msg , to - > angles [ 1 ] ) ;
MSG_WriteAngle8 ( msg , to - > angles [ 2 ] ) ;
}
}
if ( bits & E5_MODEL )
{
if ( bits & E5_MODEL16 )
MSG_WriteShort ( msg , to - > modelindex ) ;
else
MSG_WriteByte ( msg , to - > modelindex ) ;
}
if ( bits & E5_FRAME )
{
if ( bits & E5_FRAME16 )
MSG_WriteShort ( msg , to - > frame ) ;
else
MSG_WriteByte ( msg , to - > frame ) ;
}
if ( bits & E5_SKIN )
MSG_WriteByte ( msg , to - > skinnum ) ;
if ( bits & E5_EFFECTS )
{
if ( bits & E5_EFFECTS32 )
MSG_WriteLong ( msg , to - > effects ) ;
else if ( bits & E5_EFFECTS16 )
MSG_WriteShort ( msg , to - > effects ) ;
else
MSG_WriteByte ( msg , to - > effects ) ;
}
if ( bits & E5_ALPHA )
2005-07-01 19:23:00 +00:00
MSG_WriteByte ( msg , to - > trans ) ;
2005-06-14 04:52:10 +00:00
if ( bits & E5_SCALE )
MSG_WriteByte ( msg , to - > scale ) ;
if ( bits & E5_COLORMAP )
MSG_WriteByte ( msg , to - > colormap ) ;
2005-07-01 19:23:00 +00:00
if ( bits & E5_ATTACHMENT )
{
MSG_WriteShort ( msg , to - > tagentity ) ;
MSG_WriteByte ( msg , to - > tagindex ) ;
}
2005-08-07 18:08:13 +00:00
if ( bits & E5_LIGHT )
{
MSG_WriteShort ( msg , to - > light [ 0 ] ) ;
MSG_WriteShort ( msg , to - > light [ 1 ] ) ;
MSG_WriteShort ( msg , to - > light [ 2 ] ) ;
MSG_WriteShort ( msg , to - > light [ 3 ] ) ;
MSG_WriteByte ( msg , to - > lightstyle ) ;
MSG_WriteByte ( msg , to - > lightpflags ) ;
}
2005-07-01 19:23:00 +00:00
if ( bits & E5_GLOW )
{
MSG_WriteByte ( msg , to - > glowsize ) ;
MSG_WriteByte ( msg , to - > glowcolour ) ;
}
2005-10-01 03:09:17 +00:00
if ( bits & E5_COLORMOD )
{
MSG_WriteByte ( msg , to - > colormod [ 0 ] ) ;
MSG_WriteByte ( msg , to - > colormod [ 1 ] ) ;
MSG_WriteByte ( msg , to - > colormod [ 2 ] ) ;
}
2005-06-14 04:52:10 +00:00
}
2005-07-01 19:23:00 +00:00
entity_state_t defaultstate ;
2005-06-14 04:52:10 +00:00
void SVDP_EmitEntitiesUpdate ( client_t * client , packet_entities_t * to , sizebuf_t * msg )
{
edict_t * ent ;
client_frame_t * fromframe ;
packet_entities_t * from ;
int oldindex , newindex ;
int oldnum , newnum ;
int oldmax ;
2005-07-01 19:23:00 +00:00
client - > netchan . incoming_sequence + + ;
2005-06-14 04:52:10 +00:00
// this is the frame that we are going to delta update from
2005-07-01 19:23:00 +00:00
fromframe = & client - > frames [ ( client - > netchan . incoming_sequence - 2 ) & UPDATE_MASK ] ;
from = & fromframe - > entities ;
oldmax = from - > num_entities ;
// Con_Printf ("frame %i\n", client->netchan.incoming_sequence);
2005-06-14 04:52:10 +00:00
MSG_WriteByte ( msg , svcdp_entities ) ;
MSG_WriteLong ( msg , 0 ) ;
if ( client - > protocol = = SCP_DARKPLACES7 )
2005-06-22 17:10:13 +00:00
MSG_WriteLong ( msg , client - > last_sequence ) ;
2005-06-14 04:52:10 +00:00
for ( newindex = 0 ; newindex < to - > num_entities ; newindex + + )
to - > entities [ newindex ] . bitmask = 0 ;
2005-07-01 19:23:00 +00:00
//add in the bitmasks of dropped packets.
2005-06-14 04:52:10 +00:00
newindex = 0 ;
oldindex = 0 ;
//Con_Printf ("---%i to %i ----\n", client->delta_sequence & UPDATE_MASK
// , client->netchan.outgoing_sequence & UPDATE_MASK);
while ( newindex < to - > num_entities | | oldindex < oldmax )
{
newnum = newindex > = to - > num_entities ? 0x7fff : to - > entities [ newindex ] . number ;
oldnum = oldindex > = oldmax ? 0x7fff : from - > entities [ oldindex ] . number ;
if ( newnum = = oldnum )
{ // delta update from old position
//Con_Printf ("delta %i\n", newnum);
SVDP_EmitEntity ( & from - > entities [ oldindex ] , & to - > entities [ newindex ] , msg , false ) ;
oldindex + + ;
newindex + + ;
continue ;
}
if ( newnum < oldnum )
2005-07-01 19:23:00 +00:00
{ // this is a new entity, send it from the baseline... as far as dp understands it...
2005-06-14 04:52:10 +00:00
ent = EDICT_NUM ( svprogfuncs , newnum ) ;
//Con_Printf ("baseline %i\n", newnum);
2005-07-01 19:23:00 +00:00
SVDP_EmitEntity ( & defaultstate , & to - > entities [ newindex ] , msg , true ) ;
2005-06-14 04:52:10 +00:00
newindex + + ;
continue ;
}
if ( newnum > oldnum )
{ // the old entity isn't present in the new message
//Con_Printf ("remove %i\n", oldnum);
MSG_WriteShort ( msg , oldnum | 0x8000 ) ;
oldindex + + ;
continue ;
}
}
MSG_WriteShort ( msg , 0x8000 ) ;
}
# endif
2004-08-23 00:15:46 +00:00
int SV_HullNumForPlayer ( int h2hull , float * mins , float * maxs )
{
vec3_t size ;
int diff ;
int best ;
int hullnum , i ;
if ( sv . worldmodel - > fromgame = = fg_quake2 | | sv . worldmodel - > fromgame = = fg_quake3 )
{
VectorSubtract ( maxs , mins , size ) ;
return size [ 2 ] ; //clients are expected to decide themselves.
}
2004-08-31 23:58:18 +00:00
if ( h2hull )
2004-08-23 00:15:46 +00:00
return h2hull - 1 ;
hullnum = 0 ;
best = 8192 ;
//x/y pos/neg are assumed to be the same magnitute.
//y pos/height are assumed to be different from all the others.
for ( i = 0 ; i < MAX_MAP_HULLSM ; i + + )
{
# define sq(x) ((x)*(x))
diff = sq ( sv . worldmodel - > hulls [ i ] . clip_maxs [ 2 ] - maxs [ 2 ] ) +
sq ( sv . worldmodel - > hulls [ i ] . clip_mins [ 2 ] - mins [ 2 ] ) +
sq ( sv . worldmodel - > hulls [ i ] . clip_maxs [ 0 ] - maxs [ 0 ] ) +
sq ( sv . worldmodel - > hulls [ i ] . clip_mins [ 0 ] - mins [ 0 ] ) ;
if ( diff < best )
{
best = diff ;
hullnum = i ;
}
}
return hullnum ;
}
# if 1
typedef struct {
int playernum ;
qboolean onladder ;
usercmd_t * lastcmd ;
int modelindex ;
int modelindex2 ;
int frame ;
int weaponframe ;
float * angles ;
float * origin ;
float * velocity ;
int effects ;
int skin ;
float * mins ;
float * maxs ;
float scale ;
float transparency ;
float fatness ;
float localtime ;
int health ;
int spectator ; //0=send to a player. 1=non-tracked player, to a spec. 2=tracked player, to a spec(or self)
qboolean isself ;
int fteext ;
int zext ;
int hull ;
client_t * cl ;
} clstate_t ;
void SV_WritePlayerToClient ( sizebuf_t * msg , clstate_t * ent )
{
usercmd_t cmd ;
int msec ;
int hullnumber ;
int i ;
int pflags ;
int pm_type , pm_code ;
int zext = ent - > zext ;
pflags = PF_MSEC | PF_COMMAND ;
if ( ent - > modelindex ! = sv_playermodel )
pflags | = PF_MODEL ;
if ( ent - > velocity )
for ( i = 0 ; i < 3 ; i + + )
if ( ent - > velocity [ i ] )
pflags | = PF_VELOCITY1 < < i ;
if ( ent - > effects )
pflags | = PF_EFFECTS ;
if ( ent - > skin | | ent - > modelindex > = 256 )
pflags | = PF_SKINNUM ;
if ( ent - > health < = 0 )
pflags | = PF_DEAD ;
if ( progstype = = PROG_QW )
{
if ( ent - > mins [ 2 ] ! = - 24 )
pflags | = PF_GIB ;
}
else if ( progstype = = PROG_H2 )
{
// if (ent->maxs[2] != 56)
// pflags |= PF_GIB;
}
else
{
if ( ent - > mins [ 2 ] ! = - 24 )
pflags | = PF_GIB ;
}
if ( ent - > isself )
{
if ( ent - > spectator )
pflags & = PF_VELOCITY1 | PF_VELOCITY2 | PF_VELOCITY3 | PF_DEAD | PF_GIB ;
else
{ // don't send a lot of data on personal entity
pflags & = ~ ( PF_MSEC | PF_COMMAND ) ;
if ( ent - > weaponframe )
pflags | = PF_WEAPONFRAME ;
}
}
2005-01-26 03:39:47 +00:00
if ( ent - > spectator = = 2 & & ent - > weaponframe ) //it's not us, but we are spectating, so we need the correct weaponframe
2004-08-23 00:15:46 +00:00
pflags | = PF_WEAPONFRAME ;
2004-10-10 06:32:29 +00:00
if ( ! ent - > isself | | ent - > fteext & PEXT_SPLITSCREEN )
2004-08-23 00:15:46 +00:00
{
# ifdef PEXT_SCALE //this is graphics, not physics
if ( ent - > fteext & PEXT_SCALE )
{
2005-07-01 19:23:00 +00:00
if ( ent - > scale ) pflags | = PF_SCALE_Z ;
2004-08-23 00:15:46 +00:00
}
# endif
# ifdef PEXT_TRANS
if ( ent - > fteext & PEXT_TRANS )
{
2005-07-01 19:23:00 +00:00
if ( ent - > transparency ) pflags | = PF_TRANS_Z ;
2004-08-23 00:15:46 +00:00
}
# endif
# ifdef PEXT_FATNESS
if ( ent - > fteext & PEXT_FATNESS )
{
2005-07-01 19:23:00 +00:00
if ( ent - > fatness ) pflags | = PF_FATNESS_Z ;
2004-08-23 00:15:46 +00:00
}
# endif
}
# ifdef PEXT_HULLSIZE
if ( ent - > fteext & PEXT_HULLSIZE )
{
hullnumber = SV_HullNumForPlayer ( ent - > hull , ent - > mins , ent - > maxs ) ;
if ( hullnumber ! = 1 )
2005-07-01 19:23:00 +00:00
pflags | = PF_HULLSIZE_Z ;
2004-08-23 00:15:46 +00:00
}
else
hullnumber = 1 ;
# endif
if ( zext & Z_EXT_PM_TYPE )
{
if ( ent - > cl )
{
2004-08-31 23:58:18 +00:00
if ( ent - > cl - > viewent )
pm_type = PMC_NONE ;
else
pm_type = SV_PMTypeForClient ( ent - > cl ) ;
2004-08-23 00:15:46 +00:00
switch ( pm_type )
{
case PM_NORMAL : // Z_EXT_PM_TYPE protocol extension
if ( ent - > cl - > jump_held )
pm_code = PMC_NORMAL_JUMP_HELD ; // encode pm_type and jump_held into pm_code
else
pm_code = PMC_NORMAL ;
break ;
case PM_OLD_SPECTATOR :
pm_code = PMC_OLD_SPECTATOR ;
break ;
case PM_SPECTATOR : // Z_EXT_PM_TYPE_NEW protocol extension
pm_code = PMC_SPECTATOR ;
break ;
case PM_FLY :
pm_code = PMC_FLY ;
break ;
case PM_DEAD :
pm_code = PMC_NORMAL ;
break ;
case PM_NONE :
pm_code = PMC_NONE ;
break ;
default :
Sys_Error ( " SV_WritePlayersToClient: unexpected pm_type " ) ;
pm_code = 0 ;
}
}
else
2004-12-06 00:58:19 +00:00
pm_code = ( ent - > zext & Z_EXT_PM_TYPE_NEW ) ? PMC_SPECTATOR : PMC_OLD_SPECTATOR ; //(ent->spectator && ent->isself) ? PMC_OLD_SPECTATOR : PMC_NORMAL;
2004-08-23 00:15:46 +00:00
pflags | = pm_code < < PF_PMC_SHIFT ;
}
if ( pflags & 0xff0000 )
pflags | = PF_EXTRA_PFS ;
MSG_WriteByte ( msg , svc_playerinfo ) ;
MSG_WriteByte ( msg , ent - > playernum ) ;
MSG_WriteShort ( msg , pflags & 0xffff ) ;
if ( pflags & PF_EXTRA_PFS )
{
MSG_WriteByte ( msg , ( pflags & 0xff0000 ) > > 16 ) ;
}
//we need to tell the client that it's moved, as it's own origin might not be natural
2004-11-13 17:36:42 +00:00
for ( i = 0 ; i < 3 ; i + + )
MSG_WriteCoord ( msg , ent - > origin [ i ] + ( sv . demostatevalid ? 1 : 0 ) ) ;
2004-08-23 00:15:46 +00:00
MSG_WriteByte ( msg , ent - > frame ) ;
if ( pflags & PF_MSEC )
{
msec = 1000 * ( sv . time - ent - > localtime ) ;
if ( msec < 0 )
msec = 0 ;
if ( msec > 255 )
msec = 255 ;
MSG_WriteByte ( msg , msec ) ;
}
if ( pflags & PF_COMMAND )
{
if ( ent - > lastcmd )
cmd = * ent - > lastcmd ;
else
{
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
cmd . angles [ 0 ] = ent - > angles [ 0 ] * 65535 / 360.0f ;
cmd . angles [ 1 ] = ent - > angles [ 1 ] * 65535 / 360.0f ;
cmd . angles [ 2 ] = ent - > angles [ 2 ] * 65535 / 360.0f ;
}
if ( ent - > health < = 0 )
{ // don't show the corpse looking around...
cmd . angles [ 0 ] = 0 ;
cmd . angles [ 1 ] = ent - > angles [ 1 ] * 65535 / 360 ;
cmd . angles [ 0 ] = 0 ;
}
cmd . buttons = 0 ; // never send buttons
cmd . impulse = 0 ; // never send impulses
MSG_WriteDeltaUsercmd ( msg , & nullcmd , & cmd ) ;
}
if ( ent - > velocity )
{
for ( i = 0 ; i < 3 ; i + + )
if ( pflags & ( PF_VELOCITY1 < < i ) )
MSG_WriteShort ( msg , ent - > velocity [ i ] ) ;
}
else
{
for ( i = 0 ; i < 3 ; i + + )
if ( pflags & ( PF_VELOCITY1 < < i ) )
MSG_WriteShort ( msg , 0 ) ;
}
2005-01-26 03:39:47 +00:00
2004-08-23 00:15:46 +00:00
if ( pflags & PF_MODEL )
{
MSG_WriteByte ( msg , ent - > modelindex ) ;
}
if ( pflags & PF_SKINNUM )
MSG_WriteByte ( msg , ent - > skin | ( ( ( pflags & PF_MODEL ) & & ( ent - > modelindex > = 256 ) ) < < 7 ) ) ;
if ( pflags & PF_EFFECTS )
MSG_WriteByte ( msg , ent - > effects ) ;
if ( pflags & PF_WEAPONFRAME )
MSG_WriteByte ( msg , ent - > weaponframe ) ;
# ifdef PEXT_SCALE
2005-07-01 19:23:00 +00:00
if ( pflags & PF_SCALE_Z )
MSG_WriteByte ( msg , ent - > scale * 50 ) ;
2004-08-23 00:15:46 +00:00
# endif
# ifdef PEXT_TRANS
2005-07-01 19:23:00 +00:00
if ( pflags & PF_TRANS_Z )
MSG_WriteByte ( msg , ( qbyte ) ( ent - > transparency * 255 ) ) ;
2004-08-23 00:15:46 +00:00
# endif
# ifdef PEXT_FATNESS
2005-07-01 19:23:00 +00:00
if ( pflags & PF_FATNESS_Z )
MSG_WriteChar ( msg , ent - > fatness * 2 ) ;
2004-08-23 00:15:46 +00:00
# endif
# ifdef PEXT_HULLSIZE //shrunken or crouching in halflife levels. (possibly enlarged)
2005-07-01 19:23:00 +00:00
if ( pflags & PF_HULLSIZE_Z )
MSG_WriteChar ( msg , hullnumber + ( ent - > onladder ? 128 : 0 ) ) ; //physics.
2004-08-23 00:15:46 +00:00
# endif
}
# endif
2005-02-12 18:56:04 +00:00
# ifdef PEXT_SEEF1
2004-08-23 00:15:46 +00:00
# define EFNQ_DARKLIGHT 16
# define EFNQ_DARKFIELD 32
# define EFNQ_LIGHT 64
# define EFQW_DARKLIGHT 256
# define EFQW_DARKFIELD 512
# define EFQW_LIGHT 1024
2004-10-10 06:32:29 +00:00
void SV_RemoveEffect ( client_t * to , edict_t * ent , int seefmask )
2004-08-23 00:15:46 +00:00
{
specialenteffects_t * prev = NULL ;
specialenteffects_t * ef ;
int en = NUM_FOR_EDICT ( svprogfuncs , ent ) ;
for ( ef = to - > enteffects ; ef ; ef = ef - > next )
{
2004-10-10 06:32:29 +00:00
if ( ef - > entnum = = en & & ef - > efnum & seefmask )
2004-08-23 00:15:46 +00:00
{
if ( prev )
prev - > next = ef - > next ;
else
to - > enteffects = ef - > next ;
Z_Free ( ef ) ;
2004-10-10 06:32:29 +00:00
if ( ef - > efnum & seefmask & 1 > > SEEF_BRIGHTFIELD )
{
ClientReliableWrite_Begin ( to , svc_temp_entity , 4 ) ;
ClientReliableWrite_Byte ( to , TE_SEEF_BRIGHTFIELD ) ;
ClientReliableWrite_Short ( to , en | 0x8000 ) ;
}
if ( ef - > efnum & seefmask & 1 > > SEEF_DARKLIGHT )
{
ClientReliableWrite_Begin ( to , svc_temp_entity , 4 ) ;
ClientReliableWrite_Byte ( to , SEEF_DARKLIGHT ) ;
ClientReliableWrite_Short ( to , en | 0x8000 ) ;
}
if ( ef - > efnum & seefmask & 1 > > SEEF_DARKFIELD )
{
ClientReliableWrite_Begin ( to , svc_temp_entity , 4 ) ;
ClientReliableWrite_Byte ( to , SEEF_DARKFIELD ) ;
ClientReliableWrite_Short ( to , en | 0x8000 ) ;
}
if ( ef - > efnum & seefmask & 1 > > SEEF_LIGHT )
{
ClientReliableWrite_Begin ( to , svc_temp_entity , 4 ) ;
ClientReliableWrite_Byte ( to , SEEF_LIGHT ) ;
ClientReliableWrite_Short ( to , en | 0x8000 ) ;
}
2004-08-23 00:15:46 +00:00
return ;
}
prev = ef ;
}
}
void SV_AddEffect ( client_t * to , edict_t * ent , int seefno )
{
specialenteffects_t * prev = NULL ;
specialenteffects_t * ef ;
int en = NUM_FOR_EDICT ( svprogfuncs , ent ) ;
for ( ef = to - > enteffects ; ef ; ef = ef - > next )
{
2004-10-10 06:32:29 +00:00
if ( ef - > entnum = = en & & ef - > efnum = = 1 < < seefno )
2004-08-23 00:15:46 +00:00
{
2005-03-28 00:11:59 +00:00
if ( ef - > colour ! = ent - > v - > seefcolour | | ef - > offset ! = ent - > v - > seefoffset | | ef - > size [ 0 ] ! = ent - > v - > seefsizex | | ef - > size [ 1 ] ! = ent - > v - > seefsizey | | ef - > size [ 2 ] ! = ent - > v - > seefsizez | | ef - > die < sv . time )
2004-08-23 00:15:46 +00:00
{
if ( prev )
prev - > next = ef - > next ;
else
to - > enteffects = ef - > next ;
Z_Free ( ef ) ;
ef = NULL ;
break ;
}
return ; //still the same state.
}
prev = ef ;
}
ef = Z_Malloc ( sizeof ( specialenteffects_t ) ) ;
ef - > die = sv . time + 10 ;
ef - > next = to - > enteffects ;
to - > enteffects = ef ;
2004-10-10 06:32:29 +00:00
ef - > efnum = 1 < < seefno ;
2004-08-23 00:15:46 +00:00
ef - > entnum = en ;
2005-03-28 00:11:59 +00:00
ef - > colour = ent - > v - > seefcolour ;
2004-11-25 06:57:30 +00:00
if ( ! ef - > colour )
ef - > colour = 111 ;
2005-03-28 00:11:59 +00:00
ef - > offset = ent - > v - > seefoffset ;
ef - > size [ 0 ] = ent - > v - > seefsizex ;
2004-11-25 06:57:30 +00:00
if ( ! ef - > size [ 0 ] )
ef - > offset = 64 ;
2005-03-28 00:11:59 +00:00
ef - > size [ 1 ] = ent - > v - > seefsizey ;
2004-11-25 06:57:30 +00:00
if ( ! ef - > size [ 1 ] )
ef - > offset = 64 ;
2005-03-28 00:11:59 +00:00
ef - > size [ 2 ] = ent - > v - > seefsizez ;
2004-11-25 06:57:30 +00:00
if ( ! ef - > size [ 2 ] )
ef - > offset = 64 ;
2004-08-23 00:15:46 +00:00
ClientReliableWrite_Begin ( to , svc_temp_entity , 20 ) ;
ClientReliableWrite_Byte ( to , TE_SEEF_BRIGHTFIELD + seefno ) ;
ClientReliableWrite_Short ( to , en ) ;
switch ( seefno )
{
case SEEF_BRIGHTFIELD :
ClientReliableWrite_Coord ( to , ef - > size [ 0 ] ) ;
ClientReliableWrite_Coord ( to , ef - > size [ 1 ] ) ;
ClientReliableWrite_Coord ( to , ef - > size [ 2 ] ) ;
ClientReliableWrite_Char ( to , ef - > offset ) ;
ClientReliableWrite_Byte ( to , ef - > colour ) ;
break ;
case SEEF_DARKFIELD :
ClientReliableWrite_Byte ( to , ef - > colour ) ;
break ;
case SEEF_DARKLIGHT :
case SEEF_LIGHT :
ClientReliableWrite_Coord ( to , ef - > size [ 0 ] ) ;
ClientReliableWrite_Coord ( to , ef - > size [ 1 ] ) ;
break ;
}
}
2005-02-12 18:56:04 +00:00
# endif
2004-08-23 00:15:46 +00:00
void SV_SendExtraEntEffects ( client_t * to , edict_t * ent )
{
2005-02-12 18:56:04 +00:00
# ifdef PEXT_SEEF1
2004-10-10 06:32:29 +00:00
int removeeffects = 0 ;
if ( pr_udc_exteffect_enabled )
2004-08-23 00:15:46 +00:00
{
2004-10-10 06:32:29 +00:00
if ( to - > fteprotocolextensions & PEXT_SEEF1 )
2004-08-23 00:15:46 +00:00
{
2004-10-10 06:32:29 +00:00
if ( progstype ! = PROG_QW )
2004-08-23 00:15:46 +00:00
{
2005-03-28 00:11:59 +00:00
if ( ( int ) ent - > v - > effects & ( EF_BRIGHTFIELD | EFNQ_DARKLIGHT | EFNQ_DARKFIELD | EFNQ_LIGHT ) | | to - > enteffects )
2004-10-10 06:32:29 +00:00
{
2005-03-28 00:11:59 +00:00
if ( ( int ) ent - > v - > effects & EF_BRIGHTFIELD )
2004-10-10 06:32:29 +00:00
SV_AddEffect ( to , ent , SEEF_BRIGHTFIELD ) ;
else
removeeffects | = 1 < < SEEF_BRIGHTFIELD ;
2004-08-23 00:15:46 +00:00
2005-03-28 00:11:59 +00:00
if ( ( int ) ent - > v - > effects & EFNQ_DARKLIGHT )
2004-10-10 06:32:29 +00:00
SV_AddEffect ( to , ent , SEEF_DARKLIGHT ) ;
else
removeeffects | = 1 < < SEEF_DARKLIGHT ;
2004-08-23 00:15:46 +00:00
2005-03-28 00:11:59 +00:00
if ( ( int ) ent - > v - > effects & EFNQ_DARKFIELD )
2004-10-10 06:32:29 +00:00
SV_AddEffect ( to , ent , SEEF_DARKFIELD ) ;
else
removeeffects | = 1 < < SEEF_DARKFIELD ;
2004-08-23 00:15:46 +00:00
2005-03-28 00:11:59 +00:00
if ( ( int ) ent - > v - > effects & EFNQ_LIGHT )
2004-10-10 06:32:29 +00:00
SV_AddEffect ( to , ent , SEEF_LIGHT ) ;
else
removeeffects | = 1 < < SEEF_LIGHT ;
}
2004-08-23 00:15:46 +00:00
}
2004-10-10 06:32:29 +00:00
else
2004-08-23 00:15:46 +00:00
{
2005-03-28 00:11:59 +00:00
if ( ( int ) ent - > v - > effects & ( EF_BRIGHTFIELD | EFQW_DARKLIGHT | EFQW_DARKFIELD | EFQW_LIGHT ) | | to - > enteffects )
2004-10-10 06:32:29 +00:00
{
2005-03-28 00:11:59 +00:00
if ( ( int ) ent - > v - > effects & EF_BRIGHTFIELD )
2004-10-10 06:32:29 +00:00
SV_AddEffect ( to , ent , SEEF_BRIGHTFIELD ) ;
else
removeeffects | = 1 < < SEEF_BRIGHTFIELD ;
2004-08-23 00:15:46 +00:00
2005-03-28 00:11:59 +00:00
if ( ( int ) ent - > v - > effects & EFQW_DARKLIGHT )
2004-10-10 06:32:29 +00:00
SV_AddEffect ( to , ent , SEEF_DARKLIGHT ) ;
else
removeeffects | = 1 < < SEEF_DARKLIGHT ;
2004-08-23 00:15:46 +00:00
2005-03-28 00:11:59 +00:00
if ( ( int ) ent - > v - > effects & EFQW_DARKFIELD )
2004-10-10 06:32:29 +00:00
SV_AddEffect ( to , ent , SEEF_DARKFIELD ) ;
else
removeeffects | = 1 < < SEEF_DARKFIELD ;
2004-08-23 00:15:46 +00:00
2005-03-28 00:11:59 +00:00
if ( ( int ) ent - > v - > effects & EFQW_LIGHT )
2004-10-10 06:32:29 +00:00
SV_AddEffect ( to , ent , SEEF_LIGHT ) ;
else
removeeffects | = 1 < < SEEF_LIGHT ;
}
2004-08-23 00:15:46 +00:00
}
2004-10-10 06:32:29 +00:00
if ( to - > enteffects )
SV_RemoveEffect ( to , ent , removeeffects ) ;
2004-08-23 00:15:46 +00:00
}
}
2005-02-12 18:56:04 +00:00
# endif
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = =
SV_WritePlayersToClient
= = = = = = = = = = = = =
*/
void SV_WritePlayersToClient ( client_t * client , edict_t * clent , qbyte * pvs , sizebuf_t * msg )
{
qboolean isbot ;
int i , j ;
client_t * cl ;
edict_t * ent , * vent ;
int pflags ;
demo_frame_t * demo_frame ;
demo_client_t * dcl ;
# define DF_DEAD (1<<8)
# define DF_GIB (1<<9)
2005-01-26 03:39:47 +00:00
if ( clent = = NULL ) //write to demo file. (no PVS)
2004-08-23 00:15:46 +00:00
{
demo_frame = & demo . frames [ demo . parsecount & DEMO_FRAMES_MASK ] ;
for ( j = 0 , cl = svs . clients , dcl = demo_frame - > clients ; j < MAX_CLIENTS ; j + + , cl + + , dcl + + )
{
if ( cl - > state ! = cs_spawned )
continue ;
if ( sv . demostatevalid )
{
if ( client ! = cl )
continue ;
}
ent = cl - > edict ;
if ( cl - > viewent & & ent = = clent )
vent = EDICT_NUM ( svprogfuncs , cl - > viewent ) ;
else
vent = ent ;
if ( progstype ! = PROG_QW )
{
2005-03-28 00:11:59 +00:00
if ( ( int ) ent - > v - > effects & EF_MUZZLEFLASH )
2004-08-23 00:15:46 +00:00
{
if ( needcleanup < ( j + 1 ) )
{
needcleanup = ( j + 1 ) ;
MSG_WriteByte ( & sv . multicast , svc_muzzleflash ) ;
MSG_WriteShort ( & sv . multicast , ( j + 1 ) ) ;
2005-03-28 00:11:59 +00:00
SV_Multicast ( ent - > v - > origin , MULTICAST_PVS ) ;
2004-08-23 00:15:46 +00:00
}
}
}
if ( cl - > spectator )
continue ;
dcl - > parsecount = demo . parsecount ;
2005-03-28 00:11:59 +00:00
VectorCopy ( vent - > v - > origin , dcl - > info . origin ) ;
VectorCopy ( vent - > v - > angles , dcl - > info . angles ) ;
2004-08-23 00:15:46 +00:00
dcl - > info . angles [ 0 ] * = - 3 ;
dcl - > info . angles [ 2 ] = 0 ; // no roll angle
2005-03-28 00:11:59 +00:00
if ( ent - > v - > health < = 0 )
2004-08-23 00:15:46 +00:00
{ // don't show the corpse looking around...
dcl - > info . angles [ 0 ] = 0 ;
2005-03-28 00:11:59 +00:00
dcl - > info . angles [ 1 ] = vent - > v - > angles [ 1 ] ;
2004-08-23 00:15:46 +00:00
dcl - > info . angles [ 2 ] = 0 ;
}
if ( ent ! = vent )
{
dcl - > info . model = 0 ; //invisible.
dcl - > info . effects = 0 ;
}
else
{
2005-03-28 00:11:59 +00:00
dcl - > info . skinnum = ent - > v - > skin ;
dcl - > info . effects = ent - > v - > effects ;
dcl - > info . weaponframe = ent - > v - > weaponframe ;
dcl - > info . model = ent - > v - > modelindex ;
2004-08-23 00:15:46 +00:00
}
dcl - > sec = sv . time - cl - > localtime ;
2005-03-28 00:11:59 +00:00
dcl - > frame = ent - > v - > frame ;
2004-08-23 00:15:46 +00:00
dcl - > flags = 0 ;
dcl - > cmdtime = cl - > localtime ;
dcl - > fixangle = demo . fixangle [ j ] ;
demo . fixangle [ j ] = 0 ;
2005-03-28 00:11:59 +00:00
if ( ent - > v - > health < = 0 )
2004-08-23 00:15:46 +00:00
dcl - > flags | = DF_DEAD ;
2005-03-28 00:11:59 +00:00
if ( ent - > v - > mins [ 2 ] ! = - 24 )
2004-08-23 00:15:46 +00:00
dcl - > flags | = DF_GIB ;
continue ;
}
return ;
}
# ifdef NQPROT
2005-05-26 12:55:34 +00:00
if ( ! ISQWCLIENT ( client ) )
2004-08-23 00:15:46 +00:00
return ;
# endif
2005-01-26 03:39:47 +00:00
if ( sv . demostatevalid ) //this is a demo
2004-08-23 00:15:46 +00:00
{
2005-01-26 03:39:47 +00:00
usercmd_t cmd ;
vec3_t ang ;
vec3_t org ;
vec3_t vel ;
float lerp ;
2005-01-27 01:53:05 +00:00
float a1 , a2 ;
2005-01-26 03:39:47 +00:00
extern vec3_t player_mins , player_maxs ;
clstate_t clst ;
extern float olddemotime , nextdemotime ;
for ( i = 0 ; i < MAX_CLIENTS ; i + + )
2004-08-23 00:15:46 +00:00
{
2005-01-26 03:39:47 +00:00
//FIXME: Add PVS stuff.
2004-08-23 00:15:46 +00:00
2005-01-26 03:39:47 +00:00
if ( * sv . recordedplayer [ i ] . userinfo ) //if the client was active
2004-08-23 00:15:46 +00:00
{
clst . playernum = i ;
clst . onladder = 0 ;
clst . lastcmd = & cmd ;
clst . modelindex = sv . demostate [ i + 1 ] . modelindex ;
2005-01-26 03:39:47 +00:00
if ( ! clst . modelindex )
continue ;
2004-08-23 00:15:46 +00:00
clst . modelindex2 = 0 ;
clst . frame = sv . demostate [ i + 1 ] . frame ;
clst . weaponframe = sv . recordedplayer [ i ] . weaponframe ;
clst . angles = ang ;
clst . origin = org ;
clst . hull = 1 ;
2005-01-26 03:39:47 +00:00
clst . velocity = vel ;
2004-08-23 00:15:46 +00:00
clst . effects = sv . demostate [ i + 1 ] . effects ;
clst . skin = sv . demostate [ i + 1 ] . skinnum ;
clst . mins = player_mins ;
clst . maxs = player_maxs ;
clst . scale = sv . demostate [ i + 1 ] . scale ;
clst . transparency = sv . demostate [ i + 1 ] . trans ;
clst . fatness = sv . demostate [ i + 1 ] . fatness ;
clst . localtime = sv . time ; //sv.recordedplayer[j].updatetime;
clst . health = sv . recordedplayer [ i ] . stats [ STAT_HEALTH ] ;
2005-01-26 03:39:47 +00:00
clst . spectator = 2 ; //so that weaponframes work properly.
2004-08-23 00:15:46 +00:00
clst . isself = false ;
2005-01-26 03:39:47 +00:00
clst . fteext = 0 ; //client->fteprotocolextensions;
clst . zext = 0 ; //client->zquake_extensions;
2004-08-23 00:15:46 +00:00
clst . cl = NULL ;
2005-01-26 03:39:47 +00:00
lerp = ( realtime - olddemotime ) / ( nextdemotime - olddemotime ) ;
if ( lerp < 0 )
lerp = 0 ;
if ( lerp > 1 )
lerp = 1 ;
for ( j = 0 ; j < 3 ; j + + )
{
2005-01-27 01:53:05 +00:00
a1 = ( 360.0f / 256 ) * sv . recordedplayer [ i ] . oldang [ j ] ;
a2 = ( 360.0f / 256 ) * sv . demostate [ i + 1 ] . angles [ j ] ;
a2 = a2 - a1 ;
if ( a2 > 180 )
a2 - = 360 ;
if ( a2 < - 180 )
a2 + = 360 ;
ang [ j ] = ( a1 + ( a2 ) * lerp ) ;
2005-01-26 03:39:47 +00:00
org [ j ] = sv . recordedplayer [ i ] . oldorg [ j ] + ( sv . demostate [ i + 1 ] . origin [ j ] - sv . recordedplayer [ i ] . oldorg [ j ] ) * lerp ;
vel [ j ] = ( - sv . recordedplayer [ i ] . oldorg [ j ] + sv . demostate [ i + 1 ] . origin [ j ] ) * ( nextdemotime - olddemotime ) ;
}
2004-12-08 04:14:52 +00:00
2004-08-23 00:15:46 +00:00
ang [ 0 ] * = - 3 ;
// ang[0] = ang[1] = ang[2] = 0;
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
cmd . angles [ 0 ] = ang [ 0 ] * 65535 / 360.0f ;
cmd . angles [ 1 ] = ang [ 1 ] * 65535 / 360.0f ;
cmd . angles [ 2 ] = ang [ 2 ] * 65535 / 360.0f ;
cmd . msec = 50 ;
2005-01-26 03:39:47 +00:00
{ vec3_t f , r , u , v ;
2004-08-23 00:15:46 +00:00
vec_t VectorNormalize2 ( vec3_t , vec3_t ) ;
AngleVectors ( ang , f , r , u ) ;
2005-01-26 03:39:47 +00:00
VectorCopy ( vel , v ) ;
2004-08-23 00:15:46 +00:00
cmd . forwardmove = DotProduct ( f , v ) ;
cmd . sidemove = DotProduct ( r , v ) ;
cmd . upmove = DotProduct ( u , v ) ;
2005-01-26 03:39:47 +00:00
}
2004-08-23 00:15:46 +00:00
clst . lastcmd = NULL ;
SV_WritePlayerToClient ( msg , & clst ) ;
}
2005-01-26 03:39:47 +00:00
}
//now build the spectator's thingie
memset ( & clst , 0 , sizeof ( clst ) ) ;
clst . fteext = 0 ; //client->fteprotocolextensions;
clst . zext = 0 ; //client->zquake_extensions;
clst . playernum = MAX_CLIENTS - 1 ;
clst . isself = true ;
clst . modelindex = 0 ;
clst . hull = 1 ;
clst . frame = 0 ;
clst . localtime = sv . time ;
clst . mins = player_mins ;
clst . maxs = player_maxs ;
clst . angles = vec3_origin ; //not needed, as the client knows better than us anyway.
clst . origin = client - > specorigin ;
clst . velocity = client - > specvelocity ;
for ( client = client ; client ; client = client - > controller )
{
clst . health = 100 ;
if ( client - > spec_track )
{
clst . weaponframe = sv . recordedplayer [ client - > spec_track - 1 ] . weaponframe ;
clst . spectator = 2 ;
2004-12-08 04:14:52 +00:00
}
2005-01-26 03:39:47 +00:00
else
{
clst . weaponframe = 0 ;
clst . spectator = 1 ;
}
SV_WritePlayerToClient ( msg , & clst ) ;
clst . playernum - - ;
2004-08-23 00:15:46 +00:00
}
2005-01-26 03:39:47 +00:00
return ;
}
for ( j = 0 , cl = svs . clients ; j < sv . allocated_client_slots ; j + + , cl + + )
{
2005-08-26 22:56:51 +00:00
isbot = ! cl - > state & & cl - > name [ 0 ] | | cl - > protocol = = SCP_BAD ;
2005-01-25 05:01:30 +00:00
if ( cl - > state ! = cs_spawned ) //this includes bots
2005-05-08 16:46:27 +00:00
if ( ! isbot | | progstype = = PROG_QW ) //unless they're NQ bots...
2005-01-25 05:01:30 +00:00
continue ;
ent = cl - > edict ;
if ( cl - > viewent & & ent = = clent )
{
vent = EDICT_NUM ( svprogfuncs , cl - > viewent ) ;
if ( ! vent )
vent = ent ;
}
else
vent = ent ;
2004-08-23 00:15:46 +00:00
if ( progstype ! = PROG_QW )
{
2005-04-16 16:21:27 +00:00
if ( progstype = = PROG_H2 & & ( int ) ent - > v - > effects & H2EF_NODRAW & & ent ! = clent )
2004-08-23 00:15:46 +00:00
continue ;
2005-03-28 00:11:59 +00:00
if ( ( int ) ent - > v - > effects & EF_MUZZLEFLASH )
2004-08-23 00:15:46 +00:00
{
if ( needcleanup < ( j + 1 ) )
{
needcleanup = ( j + 1 ) ;
MSG_WriteByte ( & sv . multicast , svc_muzzleflash ) ;
MSG_WriteShort ( & sv . multicast , ( j + 1 ) ) ;
2005-03-28 00:11:59 +00:00
SV_Multicast ( ent - > v - > origin , MULTICAST_PVS ) ;
2004-08-23 00:15:46 +00:00
}
}
}
// ZOID visibility tracking
if ( ent ! = clent & &
! ( client - > spec_track & & client - > spec_track - 1 = = j ) )
{
if ( cl - > spectator )
continue ;
// ignore if not touching a PV leaf
2005-08-26 22:56:51 +00:00
if ( ! sv . worldmodel - > funcs . EdictInFatPVS ( sv . worldmodel , ent ) )
continue ;
2004-08-31 23:58:18 +00:00
2005-03-28 00:11:59 +00:00
if ( ! ( ( int ) clent - > v - > dimension_see & ( ( int ) ent - > v - > dimension_seen | ( int ) ent - > v - > dimension_ghost ) ) )
2004-08-31 23:58:18 +00:00
continue ; //not in this dimension - sorry...
2004-08-23 00:15:46 +00:00
}
2005-02-28 07:16:19 +00:00
if ( SV_AddCSQCUpdate ( client , ent ) )
2005-02-12 18:56:04 +00:00
continue ;
2004-08-23 00:15:46 +00:00
{
clstate_t clst ;
clst . playernum = j ;
2005-03-28 00:11:59 +00:00
clst . onladder = ( int ) ent - > v - > fteflags & FF_LADDER ;
2004-08-23 00:15:46 +00:00
clst . lastcmd = & cl - > lastcmd ;
2005-03-28 00:11:59 +00:00
clst . modelindex = vent - > v - > modelindex ;
clst . modelindex2 = vent - > v - > vweapmodelindex ;
clst . frame = vent - > v - > frame ;
clst . weaponframe = ent - > v - > weaponframe ;
clst . angles = ent - > v - > angles ;
clst . origin = vent - > v - > origin ;
clst . velocity = vent - > v - > velocity ;
clst . effects = ent - > v - > effects ;
2005-04-16 16:21:27 +00:00
if ( progstype = = PROG_H2 & & ( ( int ) vent - > v - > effects & H2EF_NODRAW ) )
2004-08-23 00:15:46 +00:00
{
clst . effects = 0 ;
clst . modelindex = 0 ;
}
2005-03-28 00:11:59 +00:00
clst . skin = vent - > v - > skin ;
clst . mins = vent - > v - > mins ;
clst . hull = vent - > v - > hull ;
clst . maxs = vent - > v - > maxs ;
clst . scale = vent - > v - > scale ;
clst . transparency = vent - > v - > alpha ;
2004-08-31 23:58:18 +00:00
//QSG_DIMENSION_PLANES - if the only shared dimensions are ghost dimensions, Set half alpha.
2005-03-28 00:11:59 +00:00
if ( ( ( int ) clent - > v - > dimension_see & ( int ) ent - > v - > dimension_ghost ) )
if ( ! ( ( int ) clent - > v - > dimension_see & ( ( int ) ent - > v - > dimension_seen & ~ ( int ) ent - > v - > dimension_ghost ) ) )
2004-09-04 17:55:12 +00:00
{
2005-03-28 00:11:59 +00:00
if ( ent - > v - > dimension_ghost_alpha )
clst . transparency * = ent - > v - > dimension_ghost_alpha ;
2004-09-04 17:55:12 +00:00
else
clst . transparency * = 0.5 ;
}
2004-08-31 23:58:18 +00:00
2005-03-28 00:11:59 +00:00
clst . fatness = vent - > v - > fatness ;
2004-08-23 00:15:46 +00:00
clst . localtime = cl - > localtime ;
2005-03-28 00:11:59 +00:00
clst . health = ent - > v - > health ;
2004-08-23 00:15:46 +00:00
clst . spectator = 0 ;
clst . fteext = client - > fteprotocolextensions ;
clst . zext = client - > zquake_extensions ;
clst . cl = cl ;
if ( ent ! = vent )
clst . modelindex = 0 ;
if ( sv . demostatevalid )
clst . health = 100 ;
clst . isself = false ;
2005-01-26 03:39:47 +00:00
if ( ( cl = = client | | cl - > controller = = client ) )
2004-08-23 00:15:46 +00:00
{
clst . isself = true ;
clst . spectator = 0 ;
if ( client - > spectator )
{
if ( client - > spec_track )
{
2005-01-26 03:39:47 +00:00
clst . spectator = 2 ;
2005-03-28 00:11:59 +00:00
clst . mins = svs . clients [ client - > spec_track - 1 ] . edict - > v - > mins ;
clst . maxs = svs . clients [ client - > spec_track - 1 ] . edict - > v - > maxs ;
clst . health = svs . clients [ client - > spec_track - 1 ] . edict - > v - > health ;
clst . weaponframe = svs . clients [ client - > spec_track - 1 ] . edict - > v - > weaponframe ;
2004-08-23 00:15:46 +00:00
}
else
2005-01-26 03:39:47 +00:00
{
clst . spectator = 1 ;
2004-08-23 00:15:46 +00:00
clst . health = 1 ;
2005-01-26 03:39:47 +00:00
}
2004-08-23 00:15:46 +00:00
}
}
2005-01-26 03:39:47 +00:00
else if ( client - > spectator )
2004-08-23 00:15:46 +00:00
{
clst . health = 100 ;
2005-01-26 03:39:47 +00:00
if ( client - > spec_track & & ent = = clent )
2004-08-23 00:15:46 +00:00
clst . spectator = 2 ;
else
clst . spectator = 1 ;
}
if ( isbot )
{
clst . lastcmd = NULL ;
clst . velocity = NULL ;
}
SV_WritePlayerToClient ( msg , & clst ) ;
}
//FIXME: Name flags
//player is visible, now would be a good time to update what the player is like.
pflags = 0 ;
2005-03-28 00:11:59 +00:00
if ( client - > fteprotocolextensions & PEXT_VWEAP & & client - > otherclientsknown [ j ] . vweap ! = ent - > v - > vweapmodelindex )
2004-08-23 00:15:46 +00:00
{
pflags | = 1 ;
2005-03-28 00:11:59 +00:00
client - > otherclientsknown [ j ] . vweap = ent - > v - > vweapmodelindex ;
2004-08-23 00:15:46 +00:00
}
if ( pflags )
{
ClientReliableWrite_Begin ( client , svc_ftesetclientpersist , 10 ) ;
ClientReliableWrite_Short ( client , pflags ) ;
if ( pflags & 1 )
ClientReliableWrite_Short ( client , client - > otherclientsknown [ j ] . vweap ) ;
ClientReliable_FinishWrite ( client ) ;
}
if ( ! sv . demostatevalid )
{
SV_SendExtraEntEffects ( client , cl - > edict ) ;
}
}
}
void SVNQ_EmitEntity ( sizebuf_t * msg , edict_t * ent , int entnum )
{
# define NQU_MOREBITS (1<<0)
# define NQU_ORIGIN1 (1<<1)
# define NQU_ORIGIN2 (1<<2)
# define NQU_ORIGIN3 (1<<3)
# define NQU_ANGLE2 (1<<4)
# define NQU_NOLERP (1<<5) // don't interpolate movement
# define NQU_FRAME (1<<6)
# define NQU_SIGNAL (1<<7) // just differentiates from other updates
// svc_update can pass all of the fast update bits, plus more
# define NQU_ANGLE1 (1<<8)
# define NQU_ANGLE3 (1<<9)
# define NQU_MODEL (1<<10)
# define NQU_COLORMAP (1<<11)
# define NQU_SKIN (1<<12)
# define NQU_EFFECTS (1<<13)
# define NQU_LONGENTITY (1<<14)
2004-11-20 00:54:23 +00:00
// LordHavoc's: protocol extension
# define DPU_EXTEND1 (1<<15)
// LordHavoc: first extend byte
# define DPU_DELTA (1<<16) // no data, while this is set the entity is delta compressed (uses previous frame as a baseline, meaning only things that have changed from the previous frame are sent, except for the forced full update every half second)
# define DPU_ALPHA (1<<17) // 1 byte, 0.0-1.0 maps to 0-255, not sent if exactly 1, and the entity is not sent if <=0 unless it has effects (model effects are checked as well)
# define DPU_SCALE (1<<18) // 1 byte, scale / 16 positive, not sent if 1.0
# define DPU_EFFECTS2 (1<<19) // 1 byte, this is .effects & 0xFF00 (second byte)
# define DPU_GLOWSIZE (1<<20) // 1 byte, encoding is float/4.0, unsigned, not sent if 0
# define DPU_GLOWCOLOR (1<<21) // 1 byte, palette index, default is 254 (white), this IS used for darklight (allowing colored darklight), however the particles from a darklight are always black, not sent if default value (even if glowsize or glowtrail is set)
// LordHavoc: colormod feature has been removed, because no one used it
# define DPU_COLORMOD (1<<22) // 1 byte, 3 bit red, 3 bit green, 2 bit blue, this lets you tint an object artifically, so you could make a red rocket, or a blue fiend...
# define DPU_EXTEND2 (1<<23) // another byte to follow
// LordHavoc: second extend byte
# define DPU_GLOWTRAIL (1<<24) // leaves a trail of particles (of color .glowcolor, or black if it is a negative glowsize)
# define DPU_VIEWMODEL (1<<25) // attachs the model to the view (origin and angles become relative to it), only shown to owner, a more powerful alternative to .weaponmodel and such
# define DPU_FRAME2 (1<<26) // 1 byte, this is .frame & 0xFF00 (second byte)
# define DPU_MODEL2 (1<<27) // 1 byte, this is .modelindex & 0xFF00 (second byte)
# define DPU_EXTERIORMODEL (1<<28) // causes this model to not be drawn when using a first person view (third person will draw it, first person will not)
# define DPU_UNUSED29 (1<<29) // future expansion
# define DPU_UNUSED30 (1<<30) // future expansion
# define DPU_EXTEND3 (1<<31) // another byte to follow, future expansion
2004-08-23 00:15:46 +00:00
int i , eff ;
float miss ;
2004-11-20 00:54:23 +00:00
unsigned int bits = 0 ;
int glowsize , glowcolor ;
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < 3 ; i + + )
{
2005-03-28 00:11:59 +00:00
miss = ent - > v - > origin [ i ] - ent - > baseline . origin [ i ] ;
2004-08-23 00:15:46 +00:00
if ( miss < - 0.1 | | miss > 0.1 )
bits | = NQU_ORIGIN1 < < i ;
}
2005-03-28 00:11:59 +00:00
if ( ent - > v - > angles [ 0 ] ! = ent - > baseline . angles [ 0 ] )
2004-08-23 00:15:46 +00:00
bits | = NQU_ANGLE1 ;
2005-03-28 00:11:59 +00:00
if ( ent - > v - > angles [ 1 ] ! = ent - > baseline . angles [ 1 ] )
2004-08-23 00:15:46 +00:00
bits | = NQU_ANGLE2 ;
2005-03-28 00:11:59 +00:00
if ( ent - > v - > angles [ 2 ] ! = ent - > baseline . angles [ 2 ] )
2004-08-23 00:15:46 +00:00
bits | = NQU_ANGLE3 ;
2005-03-28 00:11:59 +00:00
if ( ( ent - > v - > movetype = = MOVETYPE_STEP | | ( ent - > v - > movetype = = MOVETYPE_PUSH ) ) & & ( bits & ( U_ANGLE1 | U_ANGLE2 | U_ANGLE3 ) ) )
2004-08-23 00:15:46 +00:00
bits | = NQU_NOLERP ; // don't mess up the step animation
2005-03-28 00:11:59 +00:00
if ( ent - > baseline . colormap ! = ent - > v - > colormap & & ent - > v - > colormap > = 0 )
2004-08-23 00:15:46 +00:00
bits | = NQU_COLORMAP ;
2005-03-28 00:11:59 +00:00
if ( ent - > baseline . skinnum ! = ent - > v - > skin )
2004-08-23 00:15:46 +00:00
bits | = NQU_SKIN ;
2005-03-28 00:11:59 +00:00
if ( ent - > baseline . frame ! = ent - > v - > frame )
2004-08-23 00:15:46 +00:00
bits | = NQU_FRAME ;
2005-03-28 00:11:59 +00:00
eff = ent - > v - > effects ;
2004-08-23 00:15:46 +00:00
if ( ( ent - > baseline . effects & 0x00ff ) ! = ( ( int ) eff & 0x00ff ) )
bits | = NQU_EFFECTS ;
2004-11-20 00:54:23 +00:00
2005-05-26 12:55:34 +00:00
if ( ent - > baseline . modelindex ! = ent - > v - > modelindex )
2004-08-23 00:15:46 +00:00
bits | = NQU_MODEL ;
if ( entnum > = 256 )
bits | = NQU_LONGENTITY ;
2004-11-20 00:54:23 +00:00
2005-05-26 12:55:34 +00:00
if ( 1 )
2004-11-20 00:54:23 +00:00
{
2005-03-28 00:11:59 +00:00
if ( ent - > baseline . trans ! = ent - > v - > alpha )
if ( ! ( ent - > baseline . trans = = 1 & & ! ent - > v - > alpha ) )
2004-11-20 00:54:23 +00:00
bits | = DPU_ALPHA ;
2005-03-28 00:11:59 +00:00
if ( ent - > baseline . scale ! = ent - > v - > scale )
2005-05-17 02:36:54 +00:00
{
if ( ent - > v - > scale ! = 0 | | ent - > baseline . scale ! = 1 )
bits | = DPU_SCALE ;
}
2004-11-20 00:54:23 +00:00
2005-05-26 12:55:34 +00:00
if ( ent - > v - > modelindex > = 256 ) //as much as protocols can handle
bits | = DPU_MODEL2 ;
2004-11-20 00:54:23 +00:00
if ( ( ent - > baseline . effects & 0xff00 ) ! = ( ( int ) eff & 0xff00 ) )
bits | = DPU_EFFECTS2 ;
2005-05-26 12:55:34 +00:00
if ( ent - > v - > exteriormodeltoclient = = EDICT_TO_PROG ( svprogfuncs , host_client - > edict ) )
bits | = DPU_EXTERIORMODEL ;
if ( ent - > v - > viewmodelforclient = = EDICT_TO_PROG ( svprogfuncs , host_client - > edict ) )
bits | = DPU_VIEWMODEL ;
2004-11-20 00:54:23 +00:00
2005-05-19 02:53:03 +00:00
glowsize = ent - > v - > glow_size * 0.25f ;
glowcolor = ent - > v - > glow_color ;
2004-11-20 00:54:23 +00:00
if ( 0 ! = glowsize )
bits | = DPU_GLOWSIZE ;
if ( 0 ! = glowcolor )
bits | = DPU_GLOWCOLOR ;
}
2005-05-26 12:55:34 +00:00
else
{
if ( ent - > v - > modelindex > = 256 ) //as much as protocols can handle
return ;
if ( entnum > = 768 ) //too many for a conventional nq client.
return ;
}
2004-11-20 00:54:23 +00:00
if ( bits & 0xFF000000 )
bits | = DPU_EXTEND2 ;
2005-05-26 12:55:34 +00:00
if ( bits & 0xFF0000 )
bits | = DPU_EXTEND1 ;
if ( bits & 0xFF00 )
bits | = NQU_MOREBITS ;
2004-11-20 00:54:23 +00:00
2004-08-23 00:15:46 +00:00
//
// write the message
//
# ifdef PARANOID
MSG_WriteByte ( msg , ( bits | NQU_SIGNAL ) & 0xFF ) ; //gets caught on 'range error'
# else
MSG_WriteByte ( msg , bits | NQU_SIGNAL ) ;
# endif
2004-11-20 00:54:23 +00:00
if ( bits & NQU_MOREBITS ) MSG_WriteByte ( msg , bits > > 8 ) ;
if ( bits & DPU_EXTEND1 ) MSG_WriteByte ( msg , bits > > 16 ) ;
if ( bits & DPU_EXTEND2 ) MSG_WriteByte ( msg , bits > > 24 ) ;
2004-08-23 00:15:46 +00:00
if ( bits & NQU_LONGENTITY )
MSG_WriteShort ( msg , entnum ) ;
else
MSG_WriteByte ( msg , entnum ) ;
2005-03-28 00:11:59 +00:00
if ( bits & NQU_MODEL ) MSG_WriteByte ( msg , ent - > v - > modelindex ) ;
if ( bits & NQU_FRAME ) MSG_WriteByte ( msg , ent - > v - > frame ) ;
if ( bits & NQU_COLORMAP ) MSG_WriteByte ( msg , ent - > v - > colormap ) ;
if ( bits & NQU_SKIN ) MSG_WriteByte ( msg , ent - > v - > skin ) ;
2004-11-20 00:54:23 +00:00
if ( bits & NQU_EFFECTS ) MSG_WriteByte ( msg , eff & 0x00ff ) ;
2005-03-28 00:11:59 +00:00
if ( bits & NQU_ORIGIN1 ) MSG_WriteCoord ( msg , ent - > v - > origin [ 0 ] ) ;
if ( bits & NQU_ANGLE1 ) MSG_WriteAngle ( msg , ent - > v - > angles [ 0 ] ) ;
if ( bits & NQU_ORIGIN2 ) MSG_WriteCoord ( msg , ent - > v - > origin [ 1 ] ) ;
if ( bits & NQU_ANGLE2 ) MSG_WriteAngle ( msg , ent - > v - > angles [ 1 ] ) ;
if ( bits & NQU_ORIGIN3 ) MSG_WriteCoord ( msg , ent - > v - > origin [ 2 ] ) ;
if ( bits & NQU_ANGLE3 ) MSG_WriteAngle ( msg , ent - > v - > angles [ 2 ] ) ;
if ( bits & DPU_ALPHA ) MSG_WriteByte ( msg , ent - > v - > alpha * 255 ) ;
if ( bits & DPU_SCALE ) MSG_WriteByte ( msg , ent - > v - > scale * 16 ) ;
2004-11-20 00:54:23 +00:00
if ( bits & DPU_EFFECTS2 ) MSG_WriteByte ( msg , eff > > 8 ) ;
if ( bits & DPU_GLOWSIZE ) MSG_WriteByte ( msg , glowsize ) ;
if ( bits & DPU_GLOWCOLOR ) MSG_WriteByte ( msg , glowcolor ) ;
// if (bits & DPU_COLORMOD) MSG_WriteByte(msg, colormod);
2005-03-28 00:11:59 +00:00
if ( bits & DPU_FRAME2 ) MSG_WriteByte ( msg , ( int ) ent - > v - > frame > > 8 ) ;
if ( bits & DPU_MODEL2 ) MSG_WriteByte ( msg , ( int ) ent - > v - > modelindex > > 8 ) ;
2004-08-23 00:15:46 +00:00
}
typedef struct gibfilter_s {
struct gibfilter_s * next ;
int modelindex ;
int minframe ;
int maxframe ;
} gibfilter_t ;
gibfilter_t * gibfilter ;
void SV_GibFilterAdd ( char * modelname , int min , int max )
{
int i ;
gibfilter_t * gf ;
2005-09-08 01:48:07 +00:00
for ( i = 1 ; sv . model_precache [ i ] ; i + + )
2004-08-23 00:15:46 +00:00
if ( ! strcmp ( sv . model_precache [ i ] , modelname ) )
break ;
2005-09-08 01:48:07 +00:00
if ( ! sv . model_precache [ i ] )
2004-08-23 00:15:46 +00:00
{
Con_Printf ( " Filtered model \" %s \" was not precached \n " , modelname ) ;
return ; //model not in use.
}
gf = Z_Malloc ( sizeof ( gibfilter_t ) ) ;
gf - > modelindex = i ;
gf - > minframe = ( ( min = = - 1 ) ? 0 : min ) ;
gf - > maxframe = ( ( max = = - 1 ) ? 255 : max ) ;
gf - > next = gibfilter ;
gibfilter = gf ;
}
void SV_GibFilterInit ( void )
{
char buffer [ 2048 ] ;
char * file ;
int min , max ;
gibfilter_t * gf ;
while ( gibfilter )
{
gf = gibfilter ;
gibfilter = gibfilter - > next ;
Z_Free ( gf ) ;
}
file = COM_LoadStackFile ( " gibfiltr.cfg " , buffer , sizeof ( buffer ) ) ;
if ( ! file )
{
Con_Printf ( " gibfiltr.cfg file was not found. The gib filter will be disabled \n " ) ;
return ;
}
while ( file )
{
file = COM_Parse ( file ) ;
if ( ! file )
{
return ;
}
min = atoi ( com_token ) ;
file = COM_Parse ( file ) ; //handles nulls nicly
max = atoi ( com_token ) ;
file = COM_Parse ( file ) ;
if ( ! file )
{
Con_Printf ( " Sudden ending to gibfiltr.cfg \n " ) ;
return ;
}
SV_GibFilterAdd ( com_token , min , max ) ;
}
}
qboolean SV_GibFilter ( edict_t * ent )
{
2005-03-28 00:11:59 +00:00
int indx = ent - > v - > modelindex ;
int frame = ent - > v - > frame ;
2004-08-23 00:15:46 +00:00
gibfilter_t * gf ;
for ( gf = gibfilter ; gf ; gf = gf - > next )
{
if ( gf - > modelindex = = indx )
if ( frame > = gf - > minframe & & frame < = gf - > maxframe )
return true ;
}
return false ;
}
# ifdef Q2BSPS
static int clientarea ;
2005-08-26 22:56:51 +00:00
void Q2BSP_FatPVS ( model_t * mod , vec3_t org , qboolean add )
{ //fixme: this doesn't add
2004-08-23 00:15:46 +00:00
int leafnum ;
2005-08-26 22:56:51 +00:00
leafnum = CM_PointLeafnum ( mod , org ) ;
clientarea = CM_LeafArea ( mod , leafnum ) ;
2004-08-23 00:15:46 +00:00
2005-08-26 22:56:51 +00:00
SV_Q2BSP_FatPVS ( mod , org ) ;
2004-08-23 00:15:46 +00:00
}
2005-08-26 22:56:51 +00:00
qboolean Q2BSP_EdictInFatPVS ( model_t * mod , edict_t * ent )
2004-08-23 00:15:46 +00:00
{
int i , l ;
2005-08-26 22:56:51 +00:00
if ( ! CM_AreasConnected ( mod , clientarea , ent - > areanum ) )
2004-08-23 00:15:46 +00:00
{ // doors can legally straddle two areas, so
// we may need to check another one
if ( ! ent - > areanum2
2005-08-26 22:56:51 +00:00
| | ! CM_AreasConnected ( mod , clientarea , ent - > areanum2 ) )
2004-08-23 00:15:46 +00:00
return false ; // blocked by a door
}
if ( ent - > num_leafs = = - 1 )
{ // too many leafs for individual check, go by headnode
2005-08-26 22:56:51 +00:00
if ( ! CM_HeadnodeVisible ( mod , ent - > headnode , fatpvs ) )
2004-08-23 00:15:46 +00:00
return false ;
}
else
{ // check individual leafs
for ( i = 0 ; i < ent - > num_leafs ; i + + )
{
l = ent - > leafnums [ i ] ;
if ( fatpvs [ l > > 3 ] & ( 1 < < ( l & 7 ) ) )
break ;
}
if ( i = = ent - > num_leafs )
return false ; // not visible
}
return true ;
}
# endif
2005-02-12 18:56:04 +00:00
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = =
SV_WriteEntitiesToClient
Encodes the current state of the world as
a svc_packetentities messages and possibly
a svc_nails message and
svc_playerinfo messages
= = = = = = = = = = = = =
*/
void SV_WriteEntitiesToClient ( client_t * client , sizebuf_t * msg , qboolean ignorepvs )
{
# define DEPTHOPTIMISE
# ifdef DEPTHOPTIMISE
float distances [ MAX_EXTENDED_PACKET_ENTITIES ] ;
float dist ;
# endif
int e , i ;
qbyte * pvs ;
vec3_t org ;
edict_t * ent ;
packet_entities_t * pack ;
2004-12-08 04:14:52 +00:00
mvdentity_state_t * dement ;
2004-08-23 00:15:46 +00:00
edict_t * clent ;
client_frame_t * frame ;
entity_state_t * state ;
client_t * split ;
// this is the frame we are creating
frame = & client - > frames [ client - > netchan . incoming_sequence & UPDATE_MASK ] ;
// find the client's PVS
if ( ! ignorepvs )
{
clent = client - > edict ;
2005-03-28 00:11:59 +00:00
VectorAdd ( clent - > v - > origin , clent - > v - > view_ofs , org ) ;
2004-08-23 00:15:46 +00:00
2005-08-26 22:56:51 +00:00
sv . worldmodel - > funcs . FatPVS ( sv . worldmodel , org , false ) ;
2004-08-23 00:15:46 +00:00
# ifdef PEXT_VIEW2
2005-03-28 00:11:59 +00:00
if ( clent - > v - > view2 )
2005-08-26 22:56:51 +00:00
sv . worldmodel - > funcs . FatPVS ( sv . worldmodel , PROG_TO_EDICT ( svprogfuncs , clent - > v - > view2 ) - > v - > origin , true ) ;
2004-08-23 00:15:46 +00:00
# endif
for ( split = client - > controlled ; split ; split = split - > controlled )
2005-08-26 22:56:51 +00:00
sv . worldmodel - > funcs . FatPVS ( sv . worldmodel , split - > edict - > v - > origin , true ) ;
2004-08-23 00:15:46 +00:00
/*
if ( sv . worldmodel - > fromgame = = fg_doom )
{
}
else
# ifdef Q2BSPS
if ( sv . worldmodel - > fromgame = = fg_quake2 | | sv . worldmodel - > fromgame = = fg_quake3 )
{
leafnum = CM_PointLeafnum ( org ) ;
clientarea = CM_LeafArea ( leafnum ) ;
clientcluster = CM_LeafCluster ( leafnum ) ;
SV_Q2BSP_FatPVS ( org ) ;
}
else
# endif
{
SV_Q1BSP_FatPVS ( org ) ;
# ifdef PEXT_VIEW2
2005-03-28 00:11:59 +00:00
if ( clent - > v - > view2 )
SV_Q1BSP_AddToFatPVS ( PROG_TO_EDICT ( svprogfuncs , clent - > v - > view2 ) - > v - > origin , sv . worldmodel - > nodes ) ; //add a little more...
2004-08-23 00:15:46 +00:00
# endif
for ( split = client - > controlled ; split ; split = split - > controlled )
2005-03-28 00:11:59 +00:00
SV_Q1BSP_AddToFatPVS ( split - > edict - > v - > origin , sv . worldmodel - > nodes ) ; //add a little more...
2004-08-23 00:15:46 +00:00
}
*/
}
else
clent = NULL ;
pvs = fatpvs ;
2005-05-26 12:55:34 +00:00
host_client = client ;
2004-08-23 00:15:46 +00:00
// send over the players in the PVS
2005-02-12 18:56:04 +00:00
SV_WritePlayersToClient ( client , clent , pvs , msg ) ;
2004-08-23 00:15:46 +00:00
// put other visible entities into either a packet_entities or a nails message
pack = & frame - > entities ;
pack - > num_entities = 0 ;
numnails = 0 ;
# ifdef PEXT_LIGHTUPDATES
numlight = 0 ;
# endif
if ( sv . demostatevalid ) //generate info from demo stats
{
2004-12-08 04:14:52 +00:00
for ( e = 1 , dement = & sv . demostate [ e ] ; e < = sv . demomaxents ; e + + , dement + + )
2004-08-23 00:15:46 +00:00
{
if ( ! dement - > modelindex )
continue ;
if ( e > = 1 & & e < = MAX_CLIENTS )
continue ;
if ( pack - > num_entities = = pack - > max_entities )
continue ; // all full
//the entity would mess up the client and possibly disconnect them.
//FIXME: add an option to drop clients... entity fog could be killed in this way.
if ( e > = 512 & & ! ( client - > fteprotocolextensions & PEXT_ENTITYDBL ) )
continue ;
if ( e > = 1024 & & ! ( client - > fteprotocolextensions & PEXT_ENTITYDBL2 ) )
continue ;
2005-06-22 17:10:13 +00:00
// if (dement->modelindex >= 256 && !(client->fteprotocolextensions & PEXT_MODELDBL))
// continue;
2004-08-23 00:15:46 +00:00
state = & pack - > entities [ pack - > num_entities ] ;
pack - > num_entities + + ;
state - > number = e ;
2004-12-06 00:58:19 +00:00
state - > flags = EF_DIMLIGHT ;
2004-08-23 00:15:46 +00:00
VectorCopy ( dement - > origin , state - > origin ) ;
2004-12-08 04:14:52 +00:00
state - > angles [ 0 ] = dement - > angles [ 0 ] * 360.0f / 256 ;
state - > angles [ 1 ] = dement - > angles [ 1 ] * 360.0f / 256 ;
state - > angles [ 2 ] = dement - > angles [ 2 ] * 360.0f / 256 ;
2004-08-23 00:15:46 +00:00
state - > modelindex = dement - > modelindex ;
state - > frame = dement - > frame ;
state - > colormap = dement - > colormap ;
state - > skinnum = dement - > skinnum ;
state - > effects = dement - > effects ;
# ifdef PEXT_SCALE
state - > scale = dement - > scale ;
# endif
# ifdef PEXT_TRANS
state - > trans = dement - > trans ;
# endif
# ifdef PEXT_FATNESS
state - > fatness = dement - > fatness ;
# endif
}
for ( e = 0 ; e < sv . numdemospikes ; e + + )
{
if ( SV_DemoNailUpdate ( e ) )
continue ;
}
// encode the packet entities as a delta from the
// last packetentities acknowledged by the client
SV_EmitPacketEntities ( client , pack , msg ) ;
// now add the specialized nail update
SV_EmitNailUpdate ( msg , ignorepvs ) ;
return ;
}
if ( client - > viewent
# ifdef NQPROT
2005-06-14 04:52:10 +00:00
& & ISQWCLIENT ( client )
2004-08-23 00:15:46 +00:00
# endif
) //this entity is watching from outside themselves. The client is tricked into thinking that they themselves are in the view ent, and a new dummy ent (the old them) must be spawned.
{
distances [ 0 ] = 0 ;
state = & pack - > entities [ pack - > num_entities ] ;
pack - > num_entities + + ;
state - > number = client - svs . clients + 1 ;
state - > flags = 0 ;
2005-03-28 00:11:59 +00:00
VectorCopy ( clent - > v - > origin , state - > origin ) ;
VectorCopy ( clent - > v - > angles , state - > angles ) ;
state - > modelindex = clent - > v - > modelindex ;
state - > frame = clent - > v - > frame ;
state - > colormap = clent - > v - > colormap ;
state - > skinnum = clent - > v - > skin ;
state - > effects = clent - > v - > effects ;
2005-05-15 18:49:04 +00:00
state - > hexen2flags = clent - > v - > drawflags ;
2005-03-28 00:11:59 +00:00
state - > abslight = clent - > v - > abslight ;
2004-08-23 00:15:46 +00:00
# ifdef PEXT_SCALE
2005-07-01 19:23:00 +00:00
state - > scale = clent - > v - > scale * 16 ;
2005-07-08 00:37:52 +00:00
if ( ! state - > scale )
state - > scale = 1 * 16 ;
2004-08-23 00:15:46 +00:00
# endif
# ifdef PEXT_TRANS
2005-07-01 19:23:00 +00:00
state - > trans = clent - > v - > alpha * 255 ;
2005-07-08 00:37:52 +00:00
if ( ! state - > trans )
state - > trans = 255 ;
2004-08-23 00:15:46 +00:00
# endif
# ifdef PEXT_FATNESS
2005-07-01 19:23:00 +00:00
state - > fatness = clent - > v - > fatness * 2 ;
2004-08-23 00:15:46 +00:00
# endif
2005-04-16 16:21:27 +00:00
if ( state - > effects & QWEF_FLAG1 )
2004-08-23 00:15:46 +00:00
{
memcpy ( & pack - > entities [ pack - > num_entities ] , state , sizeof ( * state ) ) ;
state = & pack - > entities [ pack - > num_entities ] ;
pack - > num_entities + + ;
state - > modelindex = SV_ModelIndex ( " progs/flag.mdl " ) ;
state - > frame = 0 ;
state - > number + + ;
state - > skinnum = 0 ;
}
2005-04-16 16:21:27 +00:00
else if ( state - > effects & QWEF_FLAG2 )
2004-08-23 00:15:46 +00:00
{
memcpy ( & pack - > entities [ pack - > num_entities ] , state , sizeof ( * state ) ) ;
state = & pack - > entities [ pack - > num_entities ] ;
pack - > num_entities + + ;
state - > modelindex = SV_ModelIndex ( " progs/flag.mdl " ) ;
state - > frame = 0 ;
state - > number + + ;
state - > skinnum = 1 ;
}
}
# ifdef NQPROT
2005-06-14 04:52:10 +00:00
for ( e = ( ISQWCLIENT ( client ) ? sv . allocated_client_slots + 1 : 1 ) ; e < sv . num_edicts ; e + + )
2004-08-23 00:15:46 +00:00
# else
for ( e = sv . allocated_client_slots + 1 ; e < sv . num_edicts ; e + + )
# endif
{
ent = EDICT_NUM ( svprogfuncs , e ) ;
// ignore ents without visible models
2005-08-11 04:14:33 +00:00
if ( ! ent - > v - > SendEntity & & ( ! ent - > v - > modelindex | | ! * PR_GetString ( svprogfuncs , ent - > v - > model ) ) & & ! ( ( int ) ent - > v - > pflags & PFLAGS_FULLDYNAMIC ) )
2004-08-23 00:15:46 +00:00
continue ;
if ( progstype ! = PROG_QW )
{
2005-03-28 00:11:59 +00:00
if ( ( int ) ent - > v - > effects & EF_MUZZLEFLASH )
2004-08-23 00:15:46 +00:00
{
if ( needcleanup < e )
{
needcleanup = e ;
MSG_WriteByte ( & sv . multicast , svc_muzzleflash ) ;
MSG_WriteShort ( & sv . multicast , e ) ;
2005-03-28 00:11:59 +00:00
SV_Multicast ( ent - > v - > origin , MULTICAST_PVS ) ;
2004-08-23 00:15:46 +00:00
}
}
}
2005-05-26 12:55:34 +00:00
if ( ! ignorepvs & & ent ! = clent )
2004-08-23 00:15:46 +00:00
{
2005-03-20 02:57:11 +00:00
//branch out to the pvs testing.
2005-05-26 12:55:34 +00:00
if ( ent - > v - > viewmodelforclient = = EDICT_TO_PROG ( svprogfuncs , client - > edict ) )
{
//unconditional
}
2005-07-01 19:23:00 +00:00
else if ( ent - > v - > tag_entity )
2004-10-10 06:32:29 +00:00
{
edict_t * p = ent ;
int c = 10 ;
2005-07-01 19:23:00 +00:00
while ( p - > v - > tag_entity & & c - - > 0 )
2004-10-10 06:32:29 +00:00
{
2005-07-01 19:23:00 +00:00
p = EDICT_NUM ( svprogfuncs , p - > v - > tag_entity ) ;
2004-10-10 06:32:29 +00:00
}
2005-08-26 22:56:51 +00:00
if ( ! sv . worldmodel - > funcs . EdictInFatPVS ( sv . worldmodel , p ) )
2004-10-10 06:32:29 +00:00
continue ;
}
else
{
2005-08-26 22:56:51 +00:00
if ( ! sv . worldmodel - > funcs . EdictInFatPVS ( sv . worldmodel , ent ) )
2004-10-10 06:32:29 +00:00
continue ;
}
2004-08-23 00:15:46 +00:00
}
2005-05-26 12:55:34 +00:00
2004-08-23 00:15:46 +00:00
if ( client - > gibfilter & & SV_GibFilter ( ent ) )
continue ;
2005-03-28 00:11:59 +00:00
// if (strstr(sv.model_precache[(int)ent->v->modelindex], "gib"))
2004-08-23 00:15:46 +00:00
// continue;
2005-02-12 18:56:04 +00:00
2005-03-28 00:11:59 +00:00
if ( ent - > v - > nodrawtoclient ) //DP extension.
if ( ent - > v - > nodrawtoclient = = EDICT_TO_PROG ( svprogfuncs , client - > edict ) )
2004-08-23 00:15:46 +00:00
continue ;
2005-03-28 00:11:59 +00:00
if ( ent - > v - > drawonlytoclient )
if ( ent - > v - > drawonlytoclient ! = EDICT_TO_PROG ( svprogfuncs , client - > edict ) )
2004-11-13 17:36:42 +00:00
{
client_t * split ;
for ( split = client - > controlled ; split ; split = split - > controlled )
{
2005-03-28 00:11:59 +00:00
if ( split - > edict - > v - > view2 = = EDICT_TO_PROG ( svprogfuncs , ent ) )
2004-11-13 17:36:42 +00:00
break ;
}
if ( ! split )
continue ;
}
2004-08-31 23:58:18 +00:00
2004-09-04 17:55:12 +00:00
//QSG_DIMENSION_PLANES
2004-11-20 00:54:23 +00:00
if ( client - > edict )
2005-03-28 00:11:59 +00:00
if ( ! ( ( int ) client - > edict - > v - > dimension_see & ( ( int ) ent - > v - > dimension_seen | ( int ) ent - > v - > dimension_ghost ) ) )
2004-11-20 00:54:23 +00:00
continue ; //not in this dimension - sorry...
2004-09-04 17:55:12 +00:00
2005-02-28 07:16:19 +00:00
if ( SV_AddCSQCUpdate ( client , ent ) ) //csqc took it.
2005-02-12 18:56:04 +00:00
continue ;
2004-08-23 00:15:46 +00:00
# ifdef NQPROT
2005-06-14 04:52:10 +00:00
if ( client - > protocol = = SCP_NETQUAKE )
2004-08-23 00:15:46 +00:00
{
2005-05-26 12:55:34 +00:00
if ( msg - > cursize + 32 > msg - > maxsize )
break ;
SVNQ_EmitEntity ( msg , ent , e ) ;
2004-08-23 00:15:46 +00:00
continue ;
}
# endif
2005-06-14 04:52:10 +00:00
if ( ISQWCLIENT ( client ) )
if ( SV_AddNailUpdate ( ent ) )
continue ; // added to the special update list
2004-08-23 00:15:46 +00:00
# ifdef PEXT_LIGHTUPDATES
if ( client - > fteprotocolextensions & PEXT_LIGHTUPDATES )
if ( SV_AddLightUpdate ( ent ) )
continue ;
# endif
//the entity would mess up the client and possibly disconnect them.
//FIXME: add an option to drop clients... entity fog could be killed in this way.
if ( e > = 512 & & ! ( client - > fteprotocolextensions & PEXT_ENTITYDBL ) )
continue ;
if ( e > = 1024 & & ! ( client - > fteprotocolextensions & PEXT_ENTITYDBL2 ) )
continue ;
2005-03-28 00:11:59 +00:00
if ( ent - > v - > modelindex > = 256 & & ! ( client - > fteprotocolextensions & PEXT_MODELDBL ) )
2004-08-23 00:15:46 +00:00
continue ;
# ifdef DEPTHOPTIMISE
if ( clent )
{
//find distance based upon absolute mins/maxs so bsps are treated fairly.
2005-03-28 00:11:59 +00:00
VectorAdd ( ent - > v - > absmin , ent - > v - > absmax , org ) ;
VectorMA ( clent - > v - > origin , - 0.5 , org , org ) ;
2004-08-23 00:15:46 +00:00
dist = Length ( org ) ;
// add to the packetentities
if ( pack - > num_entities = = pack - > max_entities )
{
float furthestdist = - 1 ;
int best = - 1 ;
for ( i = 0 ; i < pack - > max_entities ; i + + )
if ( furthestdist < distances [ i ] )
{
furthestdist = distances [ i ] ;
best = i ;
}
if ( furthestdist > dist & & best ! = - 1 )
{
state = & pack - > entities [ best ] ;
// Con_Printf("Dropping ent %s\n", sv.model_precache[state->modelindex]);
memmove ( & distances [ best ] , & distances [ best + 1 ] , sizeof ( * distances ) * ( pack - > num_entities - best - 1 ) ) ;
memmove ( state , state + 1 , sizeof ( * state ) * ( pack - > num_entities - best - 1 ) ) ;
best = pack - > num_entities - 1 ;
distances [ best ] = dist ;
state = & pack - > entities [ best ] ;
}
else
continue ; // all full
}
else
{
state = & pack - > entities [ pack - > num_entities ] ;
distances [ pack - > num_entities ] = dist ;
pack - > num_entities + + ;
}
}
else
# endif
{
// add to the packetentities
if ( pack - > num_entities = = pack - > max_entities )
continue ; // all full
else
{
state = & pack - > entities [ pack - > num_entities ] ;
pack - > num_entities + + ;
}
}
2005-05-15 18:49:04 +00:00
// these are bits for the 'flags' field of the entity_state_t
# define RENDER_STEP 1
# define RENDER_GLOWTRAIL 2
# define RENDER_VIEWMODEL 4
# define RENDER_EXTERIORMODEL 8
# define RENDER_LOWPRECISION 16 // send as low precision coordinates to save bandwidth
# define RENDER_COLORMAPPED 32
state - > dpflags = 0 ;
if ( ent - > v - > viewmodelforclient )
{
if ( ent - > v - > viewmodelforclient = = EDICT_TO_PROG ( svprogfuncs , client - > edict ) )
state - > dpflags | = RENDER_VIEWMODEL ;
2005-07-16 00:53:08 +00:00
else
{ //noone else sees it.
pack - > num_entities - - ;
continue ;
}
2005-05-15 18:49:04 +00:00
}
if ( ent - > v - > exteriormodeltoclient )
{
if ( ent - > v - > exteriormodeltoclient = = EDICT_TO_PROG ( svprogfuncs , client - > edict ) )
2005-07-01 19:23:00 +00:00
state - > dpflags | = RENDER_EXTERIORMODEL ;
2005-05-15 18:49:04 +00:00
//everyone else sees it normally.
}
2004-08-23 00:15:46 +00:00
state - > number = e ;
state - > flags = 0 ;
2005-03-28 00:11:59 +00:00
VectorCopy ( ent - > v - > origin , state - > origin ) ;
VectorCopy ( ent - > v - > angles , state - > angles ) ;
state - > modelindex = ent - > v - > modelindex ;
state - > frame = ent - > v - > frame ;
state - > colormap = ent - > v - > colormap ;
state - > skinnum = ent - > v - > skin ;
state - > effects = ent - > v - > effects ;
2005-05-15 18:49:04 +00:00
state - > hexen2flags = ent - > v - > drawflags ;
2005-03-28 00:11:59 +00:00
state - > abslight = ( int ) ( ent - > v - > abslight * 255 ) & 255 ;
2005-07-01 19:23:00 +00:00
state - > tagentity = ent - > v - > tag_entity ;
state - > tagindex = ent - > v - > tag_index ;
2005-08-07 18:08:13 +00:00
state - > light [ 0 ] = ent - > v - > color [ 0 ] * 255 ;
state - > light [ 1 ] = ent - > v - > color [ 1 ] * 255 ;
state - > light [ 2 ] = ent - > v - > color [ 2 ] * 255 ;
state - > light [ 3 ] = ent - > v - > light_lev ;
state - > lightstyle = ent - > v - > style ;
state - > lightpflags = ent - > v - > pflags ;
if ( ( int ) ent - > v - > flags & FL_CLASS_DEPENDENT & & client - > playerclass ) //hexen2 wierdness.
2004-08-23 00:15:46 +00:00
{
char modname [ MAX_QPATH ] ;
Q_strncpyz ( modname , sv . model_precache [ state - > modelindex ] , sizeof ( modname ) ) ;
if ( strlen ( modname ) > 5 )
{
modname [ strlen ( modname ) - 5 ] = client - > playerclass + ' 0 ' ;
state - > modelindex = SV_ModelIndex ( modname ) ;
}
}
2005-07-08 00:37:52 +00:00
if ( /*progstype == PROG_H2 &&*/ ent - > v - > solid = = SOLID_BSP )
2004-11-17 17:40:39 +00:00
state - > angles [ 0 ] * = - 1 ;
2004-08-23 00:15:46 +00:00
if ( state - > effects & EF_FULLBRIGHT )
{
2005-05-17 02:36:54 +00:00
state - > hexen2flags | = MLS_FULLBRIGHT ;
2004-08-23 00:15:46 +00:00
}
2005-07-01 19:23:00 +00:00
if ( progstype ! = PROG_QW & & state - > effects & & ISQWCLIENT ( client ) ) //don't send extra nq effects to a qw client.
2005-05-15 18:49:04 +00:00
{
//EF_NODRAW doesn't draw the model.
//The client still needs to know about it though, as it might have other effects on it.
if ( progstype = = PROG_H2 )
{
if ( state - > effects & H2EF_NODRAW )
state - > modelindex = 0 ;
}
else
{
if ( state - > effects & NQEF_NODRAW )
state - > modelindex = 0 ;
}
2005-08-26 22:56:51 +00:00
state - > effects & = ~ ( QWEF_FLAG1 | QWEF_FLAG2 ) ;
2005-05-15 18:49:04 +00:00
}
2004-08-23 00:15:46 +00:00
2005-07-01 19:23:00 +00:00
state - > glowsize = ent - > v - > glow_size * 0.25 ;
state - > glowcolour = ent - > v - > glow_color ;
if ( ent - > v - > glow_trail )
state - > dpflags | = RENDER_GLOWTRAIL ;
2004-08-23 00:15:46 +00:00
# ifdef PEXT_SCALE
2005-07-01 19:23:00 +00:00
state - > scale = ent - > v - > scale * 16 ;
if ( ! ent - > v - > scale )
state - > scale = 1 * 16 ;
2004-08-23 00:15:46 +00:00
# endif
# ifdef PEXT_TRANS
2005-07-01 19:23:00 +00:00
state - > trans = ent - > v - > alpha * 255 ;
2005-05-15 18:49:04 +00:00
if ( ! ent - > v - > alpha )
2005-07-01 19:23:00 +00:00
state - > trans = 255 ;
2005-05-17 02:36:54 +00:00
2004-08-31 23:58:18 +00:00
//QSG_DIMENSION_PLANES - if the only shared dimensions are ghost dimensions, Set half alpha.
2004-11-20 00:54:23 +00:00
if ( client - > edict )
2005-03-28 00:11:59 +00:00
if ( ( ( int ) client - > edict - > v - > dimension_see & ( int ) ent - > v - > dimension_ghost ) )
if ( ! ( ( int ) client - > edict - > v - > dimension_see & ( ( int ) ent - > v - > dimension_seen & ~ ( int ) ent - > v - > dimension_ghost ) ) )
2004-11-20 00:54:23 +00:00
{
2005-03-28 00:11:59 +00:00
if ( ent - > v - > dimension_ghost_alpha )
state - > trans * = ent - > v - > dimension_ghost_alpha ;
2004-11-20 00:54:23 +00:00
else
state - > trans * = 0.5 ;
}
2004-08-23 00:15:46 +00:00
# endif
# ifdef PEXT_FATNESS
2005-07-01 19:23:00 +00:00
state - > fatness = ent - > v - > fatness * 2 ;
2004-08-23 00:15:46 +00:00
# endif
}
# ifdef NQPROT
2005-07-01 19:23:00 +00:00
if ( ISNQCLIENT ( client ) )
2005-06-14 04:52:10 +00:00
{
2005-07-01 19:23:00 +00:00
if ( client - > protocol = = SCP_DARKPLACES6 | | client - > protocol = = SCP_DARKPLACES7 )
{
SVDP_EmitEntitiesUpdate ( client , pack , msg ) ;
SV_EmitCSQCUpdate ( client , msg ) ;
return ;
}
else
{
client - > netchan . incoming_sequence + + ;
return ;
}
2005-06-14 04:52:10 +00:00
}
2004-08-23 00:15:46 +00:00
# endif
if ( ! sv . demostatevalid )
{
for ( i = 0 ; i < pack - > num_entities ; i + + )
{
SV_SendExtraEntEffects ( client , EDICT_NUM ( svprogfuncs , pack - > entities [ i ] . number ) ) ;
}
}
// encode the packet entities as a delta from the
// last packetentities acknowledged by the client
SV_EmitPacketEntities ( client , pack , msg ) ;
2005-02-28 07:16:19 +00:00
SV_EmitCSQCUpdate ( client , msg ) ;
2004-08-23 00:15:46 +00:00
// now add the specialized nail update
SV_EmitNailUpdate ( msg , ignorepvs ) ;
}
void SV_CleanupEnts ( void )
{
int e ;
edict_t * ent ;
if ( ! needcleanup )
return ;
for ( e = 1 ; e < = needcleanup ; e + + )
{
ent = EDICT_NUM ( svprogfuncs , e ) ;
2005-03-28 00:11:59 +00:00
if ( ( int ) ent - > v - > effects & EF_MUZZLEFLASH )
ent - > v - > effects = ( int ) ent - > v - > effects & ~ EF_MUZZLEFLASH ;
2004-08-23 00:15:46 +00:00
}
needcleanup = 0 ;
}
2004-11-29 01:21:00 +00:00
# endif