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.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
#include "quakedef.h"
+cvar_t sv_pvscheckentities = {0, "sv_pvscheckentities", "1"};
+cvar_t sv_vischeckentities = {0, "sv_vischeckentities", "1"};
+cvar_t sv_reportvischeckentities = {0, "sv_reportvischeckentities", "0"};
+int sv_vischeckentitycullcount = 0;
+
server_t sv;
server_static_t svs;
*/
void SV_Init (void)
{
- int i;
- extern cvar_t sv_maxvelocity;
- extern cvar_t sv_gravity;
- extern cvar_t sv_nostep;
- extern cvar_t sv_friction;
- extern cvar_t sv_edgefriction;
- extern cvar_t sv_stopspeed;
- extern cvar_t sv_maxspeed;
- extern cvar_t sv_accelerate;
- extern cvar_t sv_idealpitchscale;
- extern cvar_t sv_aim;
- extern cvar_t sv_predict;
+ int i;
Cvar_RegisterVariable (&sv_maxvelocity);
Cvar_RegisterVariable (&sv_gravity);
Cvar_RegisterVariable (&sv_aim);
Cvar_RegisterVariable (&sv_nostep);
Cvar_RegisterVariable (&sv_predict);
+ Cvar_RegisterVariable (&sv_deltacompress);
+ Cvar_RegisterVariable (&sv_pvscheckentities);
+ Cvar_RegisterVariable (&sv_vischeckentities);
+ Cvar_RegisterVariable (&sv_reportvischeckentities);
- for (i=0 ; i<MAX_MODELS ; i++)
+ for (i = 0;i < MAX_MODELS;i++)
sprintf (localmodels[i], "*%i", i);
}
=============================================================================
*/
-/*
+/*
==================
SV_StartParticle
int i, v;
if (sv.datagram.cursize > MAX_DATAGRAM-16)
- return;
+ return;
MSG_WriteByte (&sv.datagram, svc_particle);
- MSG_WriteCoord (&sv.datagram, org[0]);
- MSG_WriteCoord (&sv.datagram, org[1]);
- MSG_WriteCoord (&sv.datagram, org[2]);
+ MSG_WriteFloatCoord (&sv.datagram, org[0]);
+ MSG_WriteFloatCoord (&sv.datagram, org[1]);
+ MSG_WriteFloatCoord (&sv.datagram, org[2]);
for (i=0 ; i<3 ; i++)
{
v = dir[i]*16;
}
MSG_WriteByte (&sv.datagram, count);
MSG_WriteByte (&sv.datagram, color);
-}
+}
+
+/*
+==================
+SV_StartEffect
-/*
+Make sure the event gets sent to all clients
+==================
+*/
+void SV_StartEffect (vec3_t org, int modelindex, int startframe, int framecount, int framerate)
+{
+ if (sv.datagram.cursize > MAX_DATAGRAM-18)
+ return;
+ if (modelindex >= 256 || startframe >= 256)
+ {
+ MSG_WriteByte (&sv.datagram, svc_effect2);
+ MSG_WriteFloatCoord (&sv.datagram, org[0]);
+ MSG_WriteFloatCoord (&sv.datagram, org[1]);
+ MSG_WriteFloatCoord (&sv.datagram, org[2]);
+ MSG_WriteShort (&sv.datagram, modelindex);
+ MSG_WriteShort (&sv.datagram, startframe);
+ MSG_WriteByte (&sv.datagram, framecount);
+ MSG_WriteByte (&sv.datagram, framerate);
+ }
+ else
+ {
+ MSG_WriteByte (&sv.datagram, svc_effect);
+ MSG_WriteFloatCoord (&sv.datagram, org[0]);
+ MSG_WriteFloatCoord (&sv.datagram, org[1]);
+ MSG_WriteFloatCoord (&sv.datagram, org[2]);
+ MSG_WriteByte (&sv.datagram, modelindex);
+ MSG_WriteByte (&sv.datagram, startframe);
+ MSG_WriteByte (&sv.datagram, framecount);
+ MSG_WriteByte (&sv.datagram, framerate);
+ }
+}
+
+/*
==================
SV_StartSound
weapon, feet, etc.
Channel 0 is an auto-allocate channel, the others override anything
-allready running on that entity/channel pair.
+already running on that entity/channel pair.
An attenuation of 0 will play full volume everywhere in the level.
Larger attenuations will drop off. (max 4 attenuation)
==================
-*/
+*/
void SV_StartSound (edict_t *entity, int channel, char *sample, int volume,
float attenuation)
-{
+{
int sound_num;
int field_mask;
int i;
int ent;
-
+
if (volume < 0 || volume > 255)
Host_Error ("SV_StartSound: volume = %i", volume);
Host_Error ("SV_StartSound: channel = %i", channel);
if (sv.datagram.cursize > MAX_DATAGRAM-16)
- return;
+ return;
// find precache number for sound
for (sound_num=1 ; sound_num<MAX_SOUNDS
if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
field_mask |= SND_ATTENUATION;
-// directed messages go only to the entity the are targeted on
- MSG_WriteByte (&sv.datagram, svc_sound);
+// directed messages go only to the entity they are targeted on
+ if (sound_num >= 256)
+ MSG_WriteByte (&sv.datagram, svc_sound2);
+ else
+ MSG_WriteByte (&sv.datagram, svc_sound);
MSG_WriteByte (&sv.datagram, field_mask);
if (field_mask & SND_VOLUME)
MSG_WriteByte (&sv.datagram, volume);
if (field_mask & SND_ATTENUATION)
MSG_WriteByte (&sv.datagram, attenuation*64);
MSG_WriteShort (&sv.datagram, channel);
- MSG_WriteByte (&sv.datagram, sound_num);
+ if (sound_num >= 256)
+ MSG_WriteShort (&sv.datagram, sound_num);
+ else
+ MSG_WriteByte (&sv.datagram, sound_num);
for (i=0 ; i<3 ; i++)
- MSG_WriteCoord (&sv.datagram, entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i]));
+ MSG_WriteFloatCoord (&sv.datagram, entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i]));
}
/*
MSG_WriteString (&client->message,message);
MSG_WriteByte (&client->message, svc_serverinfo);
- MSG_WriteLong (&client->message, PROTOCOL_VERSION);
+ MSG_WriteLong (&client->message, DPPROTOCOL_VERSION);
MSG_WriteByte (&client->message, svs.maxclients);
if (!coop.value && deathmatch.value)
// set up the client_t
netconnection = client->netconnection;
-
+
if (sv.loadgame)
memcpy (spawn_parms, client->spawn_parms, sizeof(spawn_parms));
memset (client, 0, sizeof(*client));
else
{
// call the progs to get default spawn parms for the new client
- PR_ExecuteProgram (pr_global_struct->SetNewParms);
+ PR_ExecuteProgram (pr_global_struct->SetNewParms, "QC function SetNewParms is missing");
for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
client->spawn_parms[i] = (&pr_global_struct->parm1)[i];
}
//
// init a new client structure
- //
+ //
for (i=0 ; i<svs.maxclients ; i++)
if (!svs.clients[i].active)
break;
//=============================================================================
+int SV_BoxTouchingPVS (byte *pvs, vec3_t mins, vec3_t maxs, mnode_t *node)
+{
+ int leafnum;
+loc0:
+ if (node->contents < 0)
+ {
+ // leaf
+ if (node->contents == CONTENTS_SOLID)
+ return false;
+ leafnum = (mleaf_t *)node - sv.worldmodel->leafs - 1;
+ return pvs[leafnum >> 3] & (1 << (leafnum & 7));
+ }
+
+ // node - recurse down the BSP tree
+ switch (BOX_ON_PLANE_SIDE(mins, maxs, node->plane))
+ {
+ case 1: // front
+ node = node->children[0];
+ goto loc0;
+ case 2: // back
+ node = node->children[1];
+ goto loc0;
+ default: // crossing
+ if (node->children[0]->contents != CONTENTS_SOLID)
+ if (SV_BoxTouchingPVS (pvs, mins, maxs, node->children[0]))
+ return true;
+ node = node->children[1];
+ goto loc0;
+ }
+ // never reached
+ return false;
+}
+
+
/*
=============
SV_WriteEntitiesToClient
*/
void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
{
- int e, i, clentnum, bits, alpha, glowcolor, glowsize, scale, colormod, modred, modgreen, modblue, dodelta, effects;
+ int e, i, clentnum, bits, alpha, glowcolor, glowsize, scale, colormod, effects;
byte *pvs;
- vec3_t org, origin, angles;
- float movelerp, moveilerp;
+ vec3_t org, origin, angles, entmins, entmaxs;
+ float movelerp, moveilerp, nextfullupdate;
edict_t *ent;
eval_t *val;
entity_state_t *baseline; // LordHavoc: delta or startup baseline
+ trace_t trace;
// find the client's PVS
VectorAdd (clent->v.origin, clent->v.view_ofs, org);
pvs = SV_FatPVS (org);
/*
- if (dpprotocol)
- {
- MSG_WriteByte(msg, svc_playerposition);
- MSG_WriteFloat(msg, org[0]);
- MSG_WriteFloat(msg, org[1]);
- MSG_WriteFloat(msg, org[2]);
- }
+ // dp protocol
+ MSG_WriteByte(msg, svc_playerposition);
+ MSG_WriteFloat(msg, org[0]);
+ MSG_WriteFloat(msg, org[1]);
+ MSG_WriteFloat(msg, org[2]);
*/
clentnum = EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes
// send over all entities (except the client) that touch the pvs
ent = NEXT_EDICT(sv.edicts);
- for (e=1 ; e<sv.num_edicts ; e++, ent = NEXT_EDICT(ent))
+ for (e = 1;e < sv.num_edicts;e++, ent = NEXT_EDICT(ent))
{
bits = 0;
+
+ // prevent delta compression against this frame (unless actually sent, which will restore this later)
+ nextfullupdate = client->nextfullupdate[e];
+ client->nextfullupdate[e] = -1;
+
if (ent != clent) // LordHavoc: always send player
{
if ((val = GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
{
if (val->edict != clentnum)
- continue; // don't show to anyone else
+ {
+ // don't show to anyone else
+ continue;
+ }
else
bits |= U_VIEWMODEL; // show relative to the view
}
continue;
if ((val = GETEDICTFIELDVALUE(ent, eval_drawonlytoclient)) && val->edict && val->edict != clentnum)
continue;
- // ignore if not touching a PV leaf
- for (i=0 ; i < ent->num_leafs ; i++)
- if (pvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i]&7) ))
- break;
-
- if (i == ent->num_leafs)
- continue; // not visible
}
}
- // don't send if flagged for NODRAW and there are no effects
- alpha = 255;
- scale = 16;
glowsize = 0;
- glowcolor = 254;
- colormod = 255;
- effects = ent->v.effects;
-
- if ((val = GETEDICTFIELDVALUE(ent, eval_alpha)))
- if ((alpha = (int) (val->_float * 255.0)) == 0)
- alpha = 255;
- if ((val = GETEDICTFIELDVALUE(ent, eval_renderamt)) && val->_float != 0) // HalfLife support
- alpha = (int) val->_float;
- if (alpha < 0) alpha = 0;
- if (alpha > 255) alpha = 255;
if ((val = GETEDICTFIELDVALUE(ent, eval_glow_size)))
glowsize = (int) val->_float >> 2;
if (glowsize > 255) glowsize = 255;
if (glowsize < 0) glowsize = 0;
- if ((val = GETEDICTFIELDVALUE(ent, eval_scale)))
- if ((scale = (int) (val->_float * 16.0)) == 0) scale = 16;
- if (scale < 0) scale = 0;
- if (scale > 255) scale = 255;
-
if ((val = GETEDICTFIELDVALUE(ent, eval_glow_trail)))
if (val->_float != 0)
bits |= U_GLOWTRAIL;
- if ((val = GETEDICTFIELDVALUE(ent, eval_glow_color)))
- if (val->_float != 0)
- glowcolor = (int) val->_float;
-
- if ((val = GETEDICTFIELDVALUE(ent, eval_fullbright)))
- if (val->_float != 0)
- effects |= EF_FULLBRIGHT;
-
- if ((val = GETEDICTFIELDVALUE(ent, eval_colormod)))
- if (val->vector[0] != 0 || val->vector[1] != 0 || val->vector[2] != 0)
- {
- modred = val->vector[0] * 8.0;if (modred < 0) modred = 0;if (modred > 7) modred = 7;
- modgreen = val->vector[1] * 8.0;if (modgreen < 0) modgreen = 0;if (modgreen > 7) modgreen = 7;
- modblue = val->vector[2] * 4.0;if (modblue < 0) modblue = 0;if (modblue > 3) modblue = 3;
- colormod = (modred << 5) | (modgreen << 2) | modblue;
- }
-
- if (ent != clent)
- {
- if (glowsize == 0 && bits == 0) // no effects
- {
- if (ent->v.modelindex && pr_strings[ent->v.model]) // model
- {
- if (sv.models[ (int)ent->v.modelindex ]->flags == 0 && (ent->v.effects == EF_NODRAW || scale <= 0 || alpha <= 0))
- continue;
- }
- else // no model and no effects
+ if (ent->v.modelindex == 0 || pr_strings[ent->v.model] == 0) // no model
+ if (ent != clent) // LordHavoc: always send player
+ if (glowsize == 0 && (bits & U_GLOWTRAIL) == 0) // no effects
continue;
- }
- }
-
- if (msg->maxsize - msg->cursize < 32) // LordHavoc: increased check from 16 to 32
- {
- Con_Printf ("packet overflow\n");
- return;
- }
-
-// send an update
- bits = 0;
-
- dodelta = FALSE;
- if ((int)ent->v.effects & EF_DELTA)
- dodelta = cl.time < client->nextfullupdate[e]; // every half second a full update is forced
- if (dodelta)
- {
- bits |= U_DELTA;
- baseline = &ent->deltabaseline;
- }
- else
- {
- client->nextfullupdate[e] = cl.time + 0.5;
- baseline = &ent->baseline;
- }
-
- if (e >= 256)
- bits |= U_LONGENTITY;
- if (ent->v.movetype == MOVETYPE_STEP)
- bits |= U_STEP;
-
if (ent->v.movetype == MOVETYPE_STEP && ((int) ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM))) // monsters have smoothed walking/flying/swimming movement
{
if (!ent->steplerptime || ent->steplerptime > sv.time) // when the level just started...
angles[0] = angles[0] * movelerp + ent->stepoldangles[0];
angles[1] = angles[1] * movelerp + ent->stepoldangles[1];
angles[2] = angles[2] * movelerp + ent->stepoldangles[2];
- VectorMA(origin, host_client->latency, ent->v.velocity, origin);
+ //VectorMA(origin, host_client->latency, ent->v.velocity, origin);
}
else // copy as they are
{
-// VectorCopy(ent->v.origin, origin);
VectorCopy(ent->v.angles, angles);
- VectorMA(ent->v.origin, host_client->latency, ent->v.velocity, origin);
+ if (DotProduct(ent->v.velocity, ent->v.velocity) >= 1.0f)
+ {
+ VectorMA(ent->v.origin, host_client->latency, ent->v.velocity, origin);
+ // LordHavoc: trace predicted movement to avoid putting things in walls
+ trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, origin, MOVE_NORMAL, ent);
+ VectorCopy(trace.endpos, origin);
+ }
+ else
+ {
+ VectorCopy(ent->v.origin, origin);
+ }
if (ent->v.movetype == MOVETYPE_STEP) // monster, but airborn, update lerp info
{
// update lerp positions
}
}
+ // ent has survived every check so far, check if it is visible
+ if (ent != clent && ((bits & U_VIEWMODEL) == 0))
+ {
+ // use the predicted origin
+ entmins[0] = ent->v.mins[0] + origin[0] - 1.0f;
+ entmins[1] = ent->v.mins[1] + origin[1] - 1.0f;
+ entmins[2] = ent->v.mins[2] + origin[2] - 1.0f;
+ entmaxs[0] = ent->v.maxs[0] + origin[0] + 1.0f;
+ entmaxs[1] = ent->v.maxs[1] + origin[1] + 1.0f;
+ entmaxs[2] = ent->v.maxs[2] + origin[2] + 1.0f;
+
+ // if not touching a visible leaf
+ if (sv_pvscheckentities.value && !SV_BoxTouchingPVS(pvs, entmins, entmaxs, sv.worldmodel->nodes))
+ continue;
+
+ // or not visible through the portals
+ if (sv_vischeckentities.value && !Portal_CheckBox(sv.worldmodel, org, entmins, entmaxs))
+ {
+ sv_vischeckentitycullcount++;
+ continue;
+ }
+ }
+
+ alpha = 255;
+ scale = 16;
+ glowcolor = 254;
+ colormod = 255;
+ effects = ent->v.effects;
+
+ if ((val = GETEDICTFIELDVALUE(ent, eval_alpha)))
+ if (val->_float != 0)
+ alpha = (int) (val->_float * 255.0);
+
+ // HalfLife support
+ if ((val = GETEDICTFIELDVALUE(ent, eval_renderamt)))
+ if (val->_float != 0)
+ alpha = (int) val->_float;
+
+ if (alpha == 0)
+ alpha = 255;
+ alpha = bound(0, alpha, 255);
+
+ if ((val = GETEDICTFIELDVALUE(ent, eval_scale)))
+ if ((scale = (int) (val->_float * 16.0)) == 0) scale = 16;
+ if (scale < 0) scale = 0;
+ if (scale > 255) scale = 255;
+
+ if ((val = GETEDICTFIELDVALUE(ent, eval_glow_color)))
+ if (val->_float != 0)
+ glowcolor = (int) val->_float;
+
+ if ((val = GETEDICTFIELDVALUE(ent, eval_fullbright)))
+ if (val->_float != 0)
+ effects |= EF_FULLBRIGHT;
+
+ if ((val = GETEDICTFIELDVALUE(ent, eval_colormod)))
+ if (val->vector[0] != 0 || val->vector[1] != 0 || val->vector[2] != 0)
+ colormod = (bound(0, (int) (val->vector[0] * 8.0), 7) << 5) | (bound(0, (int) (val->vector[1] * 8.0), 7) << 2) | bound(0, (int) (val->vector[2] * 4.0), 3);
+
+ if (ent != clent)
+ {
+// if (glowsize == 0 && (bits & U_GLOWTRAIL) == 0) // no effects
+// {
+// if (ent->v.modelindex && pr_strings[ent->v.model]) // model
+// {
+ // don't send if flagged for NODRAW and there are no effects
+ if (sv.models[(int)ent->v.modelindex]->flags == 0 && ((effects & EF_NODRAW) || scale <= 0 || alpha <= 0))
+ continue;
+// }
+// else // no model and no effects
+// continue;
+// }
+ }
+
+ if (msg->maxsize - msg->cursize < 32) // LordHavoc: increased check from 16 to 32
+ {
+ Con_Printf ("packet overflow\n");
+ // mark the rest of the entities so they can't be delta compressed against this frame
+ for (;e < sv.num_edicts;e++)
+ client->nextfullupdate[e] = -1;
+ return;
+ }
+
+ if ((val = GETEDICTFIELDVALUE(ent, eval_exteriormodeltoclient)) && val->edict == clentnum)
+ bits = bits | U_EXTERIORMODEL;
+
+// send an update
+ baseline = &ent->baseline;
+
+ if (((int)ent->v.effects & EF_DELTA) && sv_deltacompress.value)
+ {
+ // every half second a full update is forced
+ if (realtime < client->nextfullupdate[e])
+ {
+ bits |= U_DELTA;
+ baseline = &ent->deltabaseline;
+ }
+ else
+ nextfullupdate = realtime + 0.5f;
+ }
+ else
+ nextfullupdate = realtime + 0.5f;
+
+ // restore nextfullupdate since this is being sent for real
+ client->nextfullupdate[e] = nextfullupdate;
+
+ if (e >= 256)
+ bits |= U_LONGENTITY;
+
+ if (ent->v.movetype == MOVETYPE_STEP)
+ bits |= U_STEP;
+
// LordHavoc: old stuff, but rewritten to have more exact tolerances
- if ((int)(origin[0]*8.0) != (int)(baseline->origin[0]*8.0)) bits |= U_ORIGIN1;
- if ((int)(origin[1]*8.0) != (int)(baseline->origin[1]*8.0)) bits |= U_ORIGIN2;
- if ((int)(origin[2]*8.0) != (int)(baseline->origin[2]*8.0)) bits |= U_ORIGIN3;
+// if ((int)(origin[0]*8.0) != (int)(baseline->origin[0]*8.0)) bits |= U_ORIGIN1;
+// if ((int)(origin[1]*8.0) != (int)(baseline->origin[1]*8.0)) bits |= U_ORIGIN2;
+// if ((int)(origin[2]*8.0) != (int)(baseline->origin[2]*8.0)) bits |= U_ORIGIN3;
+ if (origin[0] != baseline->origin[0]) bits |= U_ORIGIN1;
+ if (origin[1] != baseline->origin[1]) bits |= U_ORIGIN2;
+ if (origin[2] != baseline->origin[2]) bits |= U_ORIGIN3;
if ((int)(angles[0]*(256.0/360.0)) != (int)(baseline->angles[0]*(256.0/360.0))) bits |= U_ANGLE1;
if ((int)(angles[1]*(256.0/360.0)) != (int)(baseline->angles[1]*(256.0/360.0))) bits |= U_ANGLE2;
if ((int)(angles[2]*(256.0/360.0)) != (int)(baseline->angles[2]*(256.0/360.0))) bits |= U_ANGLE3;
- if (baseline->colormap != (int) ent->v.colormap) bits |= U_COLORMAP;
- if (baseline->skin != (int) ent->v.skin) bits |= U_SKIN;
+ if (baseline->colormap != (byte) ent->v.colormap) bits |= U_COLORMAP;
+ if (baseline->skin != (byte) ent->v.skin) bits |= U_SKIN;
if ((baseline->frame & 0x00FF) != ((int) ent->v.frame & 0x00FF)) bits |= U_FRAME;
if ((baseline->effects & 0x00FF) != ((int) ent->v.effects & 0x00FF)) bits |= U_EFFECTS;
- if (baseline->modelindex != (int) ent->v.modelindex) bits |= U_MODEL;
+ if ((baseline->modelindex & 0x00FF) != ((int) ent->v.modelindex & 0x00FF)) bits |= U_MODEL;
// LordHavoc: new stuff
if (baseline->alpha != alpha) bits |= U_ALPHA;
if (baseline->glowcolor != glowcolor) bits |= U_GLOWCOLOR;
if (baseline->colormod != colormod) bits |= U_COLORMOD;
if (((int) baseline->frame & 0xFF00) != ((int) ent->v.frame & 0xFF00)) bits |= U_FRAME2;
+ if (((int) baseline->frame & 0xFF00) != ((int) ent->v.modelindex & 0xFF00)) bits |= U_MODEL2;
// update delta baseline
VectorCopy(ent->v.origin, ent->deltabaseline.origin);
ent->deltabaseline.glowcolor = glowcolor;
ent->deltabaseline.colormod = colormod;
+ if (bits & (U_ALPHA | U_SCALE | U_EFFECTS2 | U_GLOWSIZE | U_GLOWCOLOR | U_COLORMOD | U_FRAME2 | U_MODEL2))
+ i = -1;
+
// write the message
if (bits >= 16777216)
bits |= U_EXTEND2;
if (bits & U_COLORMAP) MSG_WriteByte (msg, ent->v.colormap);
if (bits & U_SKIN) MSG_WriteByte (msg, ent->v.skin);
if (bits & U_EFFECTS) MSG_WriteByte (msg, ent->v.effects);
- if (bits & U_ORIGIN1) MSG_WriteCoord (msg, origin[0]);
+ if (bits & U_ORIGIN1) MSG_WriteFloatCoord (msg, origin[0]);
if (bits & U_ANGLE1) MSG_WriteAngle(msg, angles[0]);
- if (bits & U_ORIGIN2) MSG_WriteCoord (msg, origin[1]);
+ if (bits & U_ORIGIN2) MSG_WriteFloatCoord (msg, origin[1]);
if (bits & U_ANGLE2) MSG_WriteAngle(msg, angles[1]);
- if (bits & U_ORIGIN3) MSG_WriteCoord (msg, origin[2]);
+ if (bits & U_ORIGIN3) MSG_WriteFloatCoord (msg, origin[2]);
if (bits & U_ANGLE3) MSG_WriteAngle(msg, angles[2]);
// LordHavoc: new stuff
if (bits & U_GLOWCOLOR) MSG_WriteByte(msg, glowcolor);
if (bits & U_COLORMOD) MSG_WriteByte(msg, colormod);
if (bits & U_FRAME2) MSG_WriteByte(msg, (int)ent->v.frame >> 8);
+ if (bits & U_MODEL2) MSG_WriteByte(msg, (int)ent->v.modelindex >> 8);
}
+
+ if (sv_reportvischeckentities.value)
+ Con_Printf("sv_vischeck culled entities: %d\n", sv_vischeckentitycullcount);
+ sv_vischeckentitycullcount = 0;
}
/*
{
int e;
edict_t *ent;
-
+
ent = NEXT_EDICT(sv.edicts);
for (e=1 ; e<sv.num_edicts ; e++, ent = NEXT_EDICT(ent))
{
edict_t *other;
int items;
eval_t *val;
+ vec3_t punchvector;
//
// send a damage message
MSG_WriteByte (msg, ent->v.dmg_save);
MSG_WriteByte (msg, ent->v.dmg_take);
for (i=0 ; i<3 ; i++)
- MSG_WriteCoord (msg, other->v.origin[i] + 0.5*(other->v.mins[i] + other->v.maxs[i]));
-
+ MSG_WriteFloatCoord (msg, other->v.origin[i] + 0.5*(other->v.mins[i] + other->v.maxs[i]));
+
ent->v.dmg_take = 0;
ent->v.dmg_save = 0;
}
}
bits = 0;
-
+
if (ent->v.view_ofs[2] != DEFAULT_VIEWHEIGHT)
bits |= SU_VIEWHEIGHT;
-
+
if (ent->v.idealpitch)
bits |= SU_IDEALPITCH;
if ( ent->v.waterlevel >= 2)
bits |= SU_INWATER;
+ // dpprotocol
+ VectorClear(punchvector);
+ if ((val = GETEDICTFIELDVALUE(ent, eval_punchvector)))
+ VectorCopy(val->vector, punchvector);
+
for (i=0 ; i<3 ; i++)
{
if (ent->v.punchangle[i])
bits |= (SU_PUNCH1<<i);
+ if (punchvector[i]) // dpprotocol
+ bits |= (SU_PUNCHVEC1<<i); // dpprotocol
if (ent->v.velocity[i])
bits |= (SU_VELOCITY1<<i);
}
-
+
if (ent->v.weaponframe)
bits |= SU_WEAPONFRAME;
// if (ent->v.weapon)
bits |= SU_WEAPON;
+ if (bits >= 65536)
+ bits |= SU_EXTEND1;
+ if (bits >= 16777216)
+ bits |= SU_EXTEND2;
+
// send the data
MSG_WriteByte (msg, svc_clientdata);
MSG_WriteShort (msg, bits);
+ if (bits & SU_EXTEND1)
+ MSG_WriteByte(msg, bits >> 16);
+ if (bits & SU_EXTEND2)
+ MSG_WriteByte(msg, bits >> 24);
if (bits & SU_VIEWHEIGHT)
MSG_WriteChar (msg, ent->v.view_ofs[2]);
for (i=0 ; i<3 ; i++)
{
if (bits & (SU_PUNCH1<<i))
- MSG_WriteChar (msg, ent->v.punchangle[i]);
+ MSG_WritePreciseAngle(msg, ent->v.punchangle[i]); // dpprotocol
+ if (bits & (SU_PUNCHVEC1<<i)) // dpprotocol
+ MSG_WriteFloatCoord(msg, punchvector[i]); // dpprotocol
if (bits & (SU_VELOCITY1<<i))
MSG_WriteChar (msg, ent->v.velocity[i]/16);
}
SV_DropClient (true);// if the message couldn't send, kick off
return false;
}
-
+
return true;
}
*/
void SV_CreateBaseline (void)
{
- int i;
- edict_t *svent;
- int entnum;
-
- for (entnum = 0; entnum < sv.num_edicts ; entnum++)
+ int i, entnum, large;
+ edict_t *svent;
+
+ // LordHavoc: clear *all* states (note just active ones)
+ for (entnum = 0; entnum < MAX_EDICTS ; entnum++)
{
- // get the current server version
+ // get the current server version
svent = EDICT_NUM(entnum);
+
+ // LordHavoc: always clear state values, whether the entity is in use or not
+ ClearStateToDefault(&svent->baseline);
+
if (svent->free)
continue;
if (entnum > svs.maxclients && !svent->v.modelindex)
continue;
//
- // create entity baseline
+ // create entity baseline
//
VectorCopy (svent->v.origin, svent->baseline.origin);
VectorCopy (svent->v.angles, svent->baseline.angles);
else
{
svent->baseline.colormap = 0;
- svent->baseline.modelindex =
- SV_ModelIndex(pr_strings + svent->v.model);
+ svent->baseline.modelindex = svent->v.modelindex; //SV_ModelIndex(pr_strings + svent->v.model);
}
- svent->baseline.alpha = 255;
- svent->baseline.scale = 16;
- svent->baseline.glowsize = 0;
- svent->baseline.glowcolor = 254;
- svent->baseline.colormod = 255;
-
+
+ large = false;
+ if (svent->baseline.modelindex & 0xFF00 || svent->baseline.frame & 0xFF00)
+ large = true;
//
- // add to the message
+ // add to the message
//
- MSG_WriteByte (&sv.signon,svc_spawnbaseline);
- MSG_WriteShort (&sv.signon,entnum);
+ if (large)
+ MSG_WriteByte (&sv.signon, svc_spawnbaseline2);
+ else
+ MSG_WriteByte (&sv.signon, svc_spawnbaseline);
+ MSG_WriteShort (&sv.signon, entnum);
- MSG_WriteByte (&sv.signon, svent->baseline.modelindex);
- MSG_WriteByte (&sv.signon, svent->baseline.frame);
+ if (large)
+ {
+ MSG_WriteShort (&sv.signon, svent->baseline.modelindex);
+ MSG_WriteShort (&sv.signon, svent->baseline.frame);
+ }
+ else
+ {
+ MSG_WriteByte (&sv.signon, svent->baseline.modelindex);
+ MSG_WriteByte (&sv.signon, svent->baseline.frame);
+ }
MSG_WriteByte (&sv.signon, svent->baseline.colormap);
MSG_WriteByte (&sv.signon, svent->baseline.skin);
for (i=0 ; i<3 ; i++)
{
- MSG_WriteCoord(&sv.signon, svent->baseline.origin[i]);
+ MSG_WriteFloatCoord(&sv.signon, svent->baseline.origin[i]);
MSG_WriteAngle(&sv.signon, svent->baseline.angles[i]);
}
}
// call the progs to get default spawn parms for the new client
pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
- PR_ExecuteProgram (pr_global_struct->SetChangeParms);
+ PR_ExecuteProgram (pr_global_struct->SetChangeParms, "QC function SetChangeParms is missing");
for (j=0 ; j<NUM_SPAWN_PARMS ; j++)
host_client->spawn_parms[j] = (&pr_global_struct->parm1)[j];
}
sv.signon.maxsize = sizeof(sv.signon_buf);
sv.signon.cursize = 0;
sv.signon.data = sv.signon_buf;
-
+
// leave slots at start for clients only
sv.num_edicts = svs.maxclients+1;
for (i=0 ; i<svs.maxclients ; i++)
return;
}
sv.models[1] = sv.worldmodel;
-
+
//
// clear world interaction links
//
ent->v.modelindex = 1; // world model
ent->v.solid = SOLID_BSP;
ent->v.movetype = MOVETYPE_PUSH;
- ent->v.angles[0] = ent->v.angles[1] = ent->v.angles[2] = 0;
if (coop.value)
pr_global_struct->coop = coop.value;
ED_LoadFromFile (sv.worldmodel->entities);
// LordHavoc: clear world angles (to fix e3m3.bsp)
- sv.edicts->v.angles[0] = sv.edicts->v.angles[1] = sv.edicts->v.angles[2] = 0;
+ VectorClear(sv.edicts->v.angles);
sv.active = true;
// all setup is completed, any further precache statements are errors
sv.state = ss_active;
-
+
// run two frames to allow everything to settle
- host_frametime = 0.1;
+ sv.frametime = pr_global_struct->frametime = host_frametime = 0.1;
SV_Physics ();
SV_Physics ();
for (i=0,host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
if (host_client->active)
SV_SendServerinfo (host_client);
-
+
Con_DPrintf ("Server spawned.\n");
}