*/
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);
- for (i=0 ; i<MAX_MODELS ; i++)
+ for (i = 0;i < MAX_MODELS;i++)
sprintf (localmodels[i], "*%i", i);
}
if (sv.datagram.cursize > MAX_DATAGRAM-16)
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, 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)
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)
*/
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;
+ float movelerp, moveilerp, nextfullupdate;
edict_t *ent;
eval_t *val;
entity_state_t *baseline; // LordHavoc: delta or startup baseline
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
}
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++)
+ 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
+ {
+ // not visible
+ continue;
+ }
}
}
+ if ((val = GETEDICTFIELDVALUE(ent, eval_exteriormodeltoclient)) && val->edict == clentnum)
+ bits = bits | U_EXTERIORMODEL;
+
// don't send if flagged for NODRAW and there are no effects
alpha = 255;
scale = 16;
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
+ 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 = 0;
- if (alpha > 255) alpha = 255;
+
+ if (alpha == 0)
+ alpha = 255;
+ alpha = bound(0, alpha, 255);
if ((val = GETEDICTFIELDVALUE(ent, eval_glow_size)))
glowsize = (int) val->_float >> 2;
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;
- }
+ 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 == 0) // no effects
+ if (glowsize == 0 && (bits & U_GLOWTRAIL) == 0) // no effects
{
if (ent->v.modelindex && pr_strings[ent->v.model]) // model
{
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;
}
// send an update
- bits = 0;
+ baseline = &ent->baseline;
- dodelta = FALSE;
- if ((int)ent->v.effects & EF_DELTA)
- dodelta = sv.time < client->nextfullupdate[e]; // every half second a full update is forced
-
- if (dodelta)
+ if (((int)ent->v.effects & EF_DELTA) && sv_deltacompress.value)
{
- bits |= U_DELTA;
- baseline = &ent->deltabaseline;
+ // 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
- {
- client->nextfullupdate[e] = sv.time + 0.5;
- baseline = &ent->baseline;
- }
+ nextfullupdate = realtime + 0.5f;
+
+ // restore nextfullupdate since this is being sent
+ 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);
}
}
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;
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.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);
}
*/
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]);
}
}
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;
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 ();