Changed protocol version to 57.

Fixed an old protocol bug in how extended HUD stats were sent to the client.
Changed protocol for svc_sound servercommand to separate channel and entity values from a merged short to a byte and a short.
More improvements to Tactician Gunner prox aiming safety in missionpack DLL.
Fixed SV_CheckVelocity() sv_velocity cap in missionpack, 3ZB2, and Zaero game DLLs.
This commit is contained in:
Knightmare66 2021-08-04 02:15:24 -04:00
parent cedf3628ac
commit c531db636d
14 changed files with 148 additions and 54 deletions

View file

@ -52,12 +52,17 @@ void SV_CheckVelocity (edict_t *ent)
// //
// bound velocity // bound velocity
// //
for (i=0 ; i<3 ; i++) /* for (i=0 ; i<3 ; i++)
{ {
if (ent->velocity[i] > sv_maxvelocity->value) if (ent->velocity[i] > sv_maxvelocity->value)
ent->velocity[i] = sv_maxvelocity->value; ent->velocity[i] = sv_maxvelocity->value;
else if (ent->velocity[i] < -sv_maxvelocity->value) else if (ent->velocity[i] < -sv_maxvelocity->value)
ent->velocity[i] = -sv_maxvelocity->value; ent->velocity[i] = -sv_maxvelocity->value;
} */
if (VectorLength(ent->velocity) > sv_maxvelocity->value)
{
VectorNormalize (ent->velocity);
VectorScale (ent->velocity, sv_maxvelocity->value, ent->velocity);
} }
} }

View file

@ -55,8 +55,8 @@ void SV_CheckVelocity(edict_t *ent)
if (VectorLength(ent->velocity) > sv_maxvelocity->value) if (VectorLength(ent->velocity) > sv_maxvelocity->value)
{ {
VectorNormalize(ent->velocity); VectorNormalize (ent->velocity);
VectorScale(ent->velocity, sv_maxvelocity->value, ent->velocity); VectorScale (ent->velocity, sv_maxvelocity->value, ent->velocity);
} }
//DH-- //DH--
} }

View file

@ -630,8 +630,9 @@ void CL_ParsePlayerstate (frame_t *oldframe, frame_t *newframe)
{ {
int flags; int flags;
player_state_t *state; player_state_t *state;
int i; int i, j;
int statbits; int statbits; // still used by legacy protocol
int statbitarray[(MAX_STATS+31)>>5]; // derived from MAX_STATS
state = &newframe->playerstate; state = &newframe->playerstate;
@ -747,7 +748,7 @@ void CL_ParsePlayerstate (frame_t *oldframe, frame_t *newframe)
if (statbits & (1<<i) ) if (statbits & (1<<i) )
state->stats[i] = MSG_ReadShort(&net_message); state->stats[i] = MSG_ReadShort(&net_message);
} // end old CL_ParsePlayerstate code } // end old CL_ParsePlayerstate code
else //new CL_ParsePlayerstate code else // new CL_ParsePlayerstate code
{ {
// Knightmare 4/5/2002- read as long // Knightmare 4/5/2002- read as long
flags = MSG_ReadLong (&net_message); flags = MSG_ReadLong (&net_message);
@ -897,10 +898,16 @@ void CL_ParsePlayerstate (frame_t *oldframe, frame_t *newframe)
state->rdflags = MSG_ReadByte (&net_message); state->rdflags = MSG_ReadByte (&net_message);
// parse stats // parse stats
statbits = MSG_ReadLong (&net_message); /* statbits = MSG_ReadLong (&net_message);
for (i = 0; i < MAX_STATS; i++) for (i = 0; i < MAX_STATS; i++)
if (statbits & (1<<i) ) if (statbits & (1<<i) )
state->stats[i] = MSG_ReadShort(&net_message); state->stats[i] = MSG_ReadShort(&net_message);
*/
for (j = 0; j < (MAX_STATS+31)>>5; j++)
statbitarray[j] = MSG_ReadLong (&net_message);
for (i = 0; i < MAX_STATS; i++)
if ( statbitarray[i>>5] & (1<<(i&31)) )
state->stats[i] = MSG_ReadShort(&net_message);
} // end new CL_ParsePlayerstate code } // end new CL_ParsePlayerstate code
} }

View file

@ -126,15 +126,10 @@ void CL_ParseServerData (void)
// BIG HACK to let demos from release work with the 3.0x patch!!! // BIG HACK to let demos from release work with the 3.0x patch!!!
// Knightmare- also allow connectivity with servers using the old protocol // Knightmare- also allow connectivity with servers using the old protocol
// if (Com_ServerState() && (i < PROTOCOL_VERSION) /*== 35*/) if ( LegacyProtocol() ) { } // do nothing
if ( LegacyProtocol() ) {} // do nothing else if ( (i != PROTOCOL_VERSION) && (i != OLD_PROTOCOL_VERSION) ) {
/* else if (i == OLD_PROTOCOL_VERSION)
Cvar_ForceSet ("cl_servertrick", "1");
else if (i == PROTOCOL_VERSION)
Cvar_ForceSet ("cl_servertrick", "0"); // force this off for local games
else if (i != PROTOCOL_VERSION) */
else if ( (i != PROTOCOL_VERSION) && (i != OLD_PROTOCOL_VERSION) )
Com_Error (ERR_DROP, "Server returned version %i, not %i or %i", i, PROTOCOL_VERSION, OLD_PROTOCOL_VERSION); Com_Error (ERR_DROP, "Server returned version %i, not %i or %i", i, PROTOCOL_VERSION, OLD_PROTOCOL_VERSION);
}
cl.servercount = MSG_ReadLong (&net_message); cl.servercount = MSG_ReadLong (&net_message);
cl.attractloop = MSG_ReadByte (&net_message); cl.attractloop = MSG_ReadByte (&net_message);
@ -582,7 +577,7 @@ void CL_ParseStartSoundPacket(void)
sound_num = MSG_ReadByte (&net_message); sound_num = MSG_ReadByte (&net_message);
else else
sound_num = MSG_ReadShort (&net_message); sound_num = MSG_ReadShort (&net_message);
//end Knightmare // end Knightmare
if (flags & SND_VOLUME) if (flags & SND_VOLUME)
volume = MSG_ReadByte (&net_message) / 255.0; volume = MSG_ReadByte (&net_message) / 255.0;
@ -599,14 +594,24 @@ void CL_ParseStartSoundPacket(void)
else else
ofs = 0; ofs = 0;
if (flags & SND_ENT) if (flags & SND_ENT) // entity relative
{ // entity reletive {
channel = MSG_ReadShort(&net_message); // Knightmare 8/2/21- read channel and ent as a combined short only if playing old demos or
ent = channel>>3; // connected to server using old protocol; otherwise, read as a byte and a short
if ( LegacyProtocol() )
{
channel = MSG_ReadShort(&net_message);
ent = channel >> 3;
channel &= 7;
}
else
{
channel = MSG_ReadByte(&net_message);
ent = (unsigned short)MSG_ReadShort(&net_message); // make sure this doesn't turn negative!
}
if (ent > MAX_EDICTS) if (ent > MAX_EDICTS)
Com_Error (ERR_DROP,"CL_ParseStartSoundPacket: ent = %i", ent); Com_Error (ERR_DROP,"CL_ParseStartSoundPacket: ent = %i", ent);
// end Knightmare
channel &= 7;
} }
else else
{ {

View file

@ -450,8 +450,8 @@ if parsing of old protocol should be used.
*/ */
qboolean LegacyProtocol (void) qboolean LegacyProtocol (void)
{ {
//if (dedicated->integer) // Server always uses new protocol // if (dedicated->integer) // Server always uses new protocol
// return false; // return false;
if ( (Com_ServerState() && cls.serverProtocol <= OLD_PROTOCOL_VERSION) if ( (Com_ServerState() && cls.serverProtocol <= OLD_PROTOCOL_VERSION)
|| (cls.serverProtocol == OLD_PROTOCOL_VERSION) ) || (cls.serverProtocol == OLD_PROTOCOL_VERSION) )
return true; return true;

View file

@ -38,6 +38,9 @@ Changes as of v0.20 update 8:
- Added client detection of server protocol from challenge message. Client also auto-reconnects with cl_servertrick - Added client detection of server protocol from challenge message. Client also auto-reconnects with cl_servertrick
set correspondingly when a "wrong version" rejection message is received. set correspondingly when a "wrong version" rejection message is received.
- Changed protocol version to 57. This was necessitated by fixing an old protocol bug in how extended HUD stats were sent to the client.
Also changed protocol for svc_sound servercommand to separate channel and entity values from a merged short to a byte and a short.
- Added cel shading support. Uses cvars r_celshading to enable, and r_celshading_width for line width (1-10). - Added cel shading support. Uses cvars r_celshading to enable, and r_celshading_width for line width (1-10).
- Added Z-Pass shadow mode due to patent issues w/ commercial games. Set the cvar r_shadow_zfail to 0 to enable this. - Added Z-Pass shadow mode due to patent issues w/ commercial games. Set the cvar r_shadow_zfail to 0 to enable this.

View file

@ -2629,7 +2629,7 @@ struct edict_s
char *datafile; char *datafile;
// Mappack- for the camera to backup the players position, ammo, powerups, etc // Mappack- for the camera to backup the players position, ammo, powerups, etc
backup_t backup; //this holds the client data backup_t backup; // this holds the client data
vec3_t fog_color; vec3_t fog_color;
int fog_model; int fog_model;

View file

@ -165,12 +165,12 @@ SV_CheckVelocity
*/ */
void SV_CheckVelocity (edict_t *ent) void SV_CheckVelocity (edict_t *ent)
{ {
int i; // int i;
// //
// bound velocity // bound velocity
// //
for (i=0 ; i<3 ; i++) /* for (i=0 ; i<3 ; i++)
{ {
if (ent->velocity[i] > sv_maxvelocity->value) if (ent->velocity[i] > sv_maxvelocity->value)
ent->velocity[i] = sv_maxvelocity->value; ent->velocity[i] = sv_maxvelocity->value;
@ -181,6 +181,16 @@ void SV_CheckVelocity (edict_t *ent)
ent->relative_velocity[i] = sv_maxvelocity->value; ent->relative_velocity[i] = sv_maxvelocity->value;
else if (ent->relative_velocity[i] < -sv_maxvelocity->value) else if (ent->relative_velocity[i] < -sv_maxvelocity->value)
ent->relative_velocity[i] = -sv_maxvelocity->value; ent->relative_velocity[i] = -sv_maxvelocity->value;
} */
if (VectorLength(ent->velocity) > sv_maxvelocity->value)
{
VectorNormalize (ent->velocity);
VectorScale (ent->velocity, sv_maxvelocity->value, ent->velocity);
}
if (VectorLength(ent->relative_velocity) > sv_maxvelocity->value)
{
VectorNormalize (ent->relative_velocity);
VectorScale (ent->relative_velocity, sv_maxvelocity->value, ent->relative_velocity);
} }
} }

View file

@ -41,7 +41,7 @@ static int tactician_sound_sight;
#define GRENADE_VELOCITY 632.4555320337f #define GRENADE_VELOCITY 632.4555320337f
#define GRENADE_VELOCITY_SQUARED 400000.0f #define GRENADE_VELOCITY_SQUARED 400000.0f
// Knightmare- placement spread for Tactician Gunner prox mines // Knightmare- placement spread for Tactician Gunner prox mines
#define GUNNER_PROX_SPREAD 40.0f #define GUNNER_PROX_SPREAD 48.0f
#define HALF_GUNNER_PROX_SPREAD (GUNNER_PROX_SPREAD * 0.5f) #define HALF_GUNNER_PROX_SPREAD (GUNNER_PROX_SPREAD * 0.5f)
void gunner_idlesound (edict_t *self) void gunner_idlesound (edict_t *self)
@ -535,6 +535,7 @@ qboolean gunner_grenade_check (edict_t *self)
if (tr.ent == self->enemy || tr.fraction == 1) if (tr.ent == self->enemy || tr.fraction == 1)
{ // Knightmare- added close-range prox safety check { // Knightmare- added close-range prox safety check
if (isProx) { if (isProx) {
VectorCopy (target, self->aim_point); // save this aim location in case later safety check fails
if (gunner_prox_safety_check(self, start, target)) if (gunner_prox_safety_check(self, start, target))
return true; return true;
} }
@ -548,6 +549,7 @@ qboolean gunner_grenade_check (edict_t *self)
if (tr.ent == self->enemy || tr.fraction == 1) if (tr.ent == self->enemy || tr.fraction == 1)
{ // Knightmare- added close-range prox safety check { // Knightmare- added close-range prox safety check
if (isProx) { if (isProx) {
VectorCopy (target, self->aim_point); // save this aim location in case later safety check fails
if (gunner_prox_safety_check(self, start, target)) if (gunner_prox_safety_check(self, start, target))
return true; return true;
} }
@ -685,8 +687,12 @@ void GunnerGrenade (edict_t *self)
float spread; float spread;
// float pitch; // float pitch;
// PMM // PMM
vec3_t target; vec3_t target, leadTarget;
qboolean blindfire = false; qboolean blindfire = false;
qboolean leadingTarget = false;
qboolean targetSafe = false;
qboolean leadSafe = false;
qboolean isProx = (self->moreflags & FL2_COMMANDER);
//PGM //PGM
if (!self->enemy || !self->enemy->inuse) if (!self->enemy || !self->enemy->inuse)
@ -750,8 +756,52 @@ void GunnerGrenade (edict_t *self)
if (self->enemy->absmin[2] <= self->absmax[2]) if (self->enemy->absmin[2] <= self->absmax[2])
target[2] = self->enemy->absmin[2]; target[2] = self->enemy->absmin[2];
// lead target... 20, 35, 50, 65 chance of leading
if ( random() < (0.2 + skill->value * 0.15) )
{
float dist, time;
VectorSubtract (target, start, aim);
dist = VectorLength (aim);
time = dist / GRENADE_VELOCITY; // Not correct, but better than nothin'
VectorMA (target, time, self->enemy->velocity, leadTarget);
if (!isProx) // delay copying for prox safety check
VectorCopy (leadTarget, target);
leadingTarget = true;
}
if (isProx) // Knightmare- run another safety check before firing, so players can't trick us into self-damage
{
if ( gunner_prox_safety_check(self, start, target) ) {
VectorCopy (target, self->aim_point); // save this target point
targetSafe = true;
}
if ( leadingTarget && gunner_prox_safety_check(self, start, leadTarget) ) {
VectorCopy (leadTarget, target); // copy lead point over target
leadSafe = true;
}
if ( !targetSafe && !leadSafe ) {
VectorCopy (self->aim_point, target); // revert to prev target point
}
/* if ((g_showlogic) && (g_showlogic->value))
{
if ( targetSafe && leadSafe )
gi.dprintf ("GunnerGrenade: safe to fire at and lead target, saving target point.\n");
else if ( targetSafe && leadingTarget && !leadSafe )
gi.dprintf ("GunnerGrenade: safe to fire at but not lead target, saving target point.\n");
else if ( targetSafe && !leadingTarget )
gi.dprintf ("GunnerGrenade: safe to fire at target, saving target point.\n");
else if ( !targetSafe && leadSafe )
gi.dprintf ("GunnerGrenade: safe to lead target only, not saving target point.\n");
else if ( !targetSafe && !leadSafe && leadingTarget )
gi.dprintf ("GunnerGrenade: NOT safe to fire at or lead target, reverting to prev target point.\n");
else if ( !targetSafe && !leadSafe && !leadingTarget )
gi.dprintf ("GunnerGrenade: NOT safe to fire at target, reverting to prev target point.\n");
} */
}
// Knightmare- spread out Tactician Gunner's prox mines so they don't collide // Knightmare- spread out Tactician Gunner's prox mines so they don't collide
if (self->moreflags & FL2_COMMANDER) if (isProx)
{ {
target[0] += crandom() * GUNNER_PROX_SPREAD; target[0] += crandom() * GUNNER_PROX_SPREAD;
target[1] += crandom() * GUNNER_PROX_SPREAD; target[1] += crandom() * GUNNER_PROX_SPREAD;
@ -765,16 +815,7 @@ void GunnerGrenade (edict_t *self)
target[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility); target[2] += crandom() * 320 * (FOG_CANSEEGOOD - self->monsterinfo.visibility);
} }
// lead target... 20, 35, 50, 65 chance of leading // Leading code was here
if ( random() < (0.2 + skill->value * 0.15) )
{
float dist, time;
VectorSubtract (target, start, aim);
dist = VectorLength (aim);
time = dist / GRENADE_VELOCITY; // Not correct, but better than nothin'
VectorMA (target, time, self->enemy->velocity, target);
}
// aim up if they're on the same level as me and far away. // aim up if they're on the same level as me and far away.
// if ((range > 512) && (aim[2] < 64) && (aim[2] > -64)) // if ((range > 512) && (aim[2] < 64) && (aim[2] > -64))
@ -810,8 +851,7 @@ void GunnerGrenade (edict_t *self)
// VectorMA (forward, spread, right, aim); // VectorMA (forward, spread, right, aim);
// VectorMA (aim, pitch, up, aim); // VectorMA (aim, pitch, up, aim);
// Knightmare- Tactician Gunner fires prox mines if (isProx) // Knightmare- Tactician Gunner fires prox mines
if (self->moreflags & FL2_COMMANDER)
{ {
float prox_timer = (blindfire) ? 60.0f : 30.0f; float prox_timer = (blindfire) ? 60.0f : 30.0f;
monster_fire_prox (self, start, aim, 90, 1, GRENADE_VELOCITY, 20, prox_timer, 192, flash_number); monster_fire_prox (self, start, aim, 90, 1, GRENADE_VELOCITY, 20, prox_timer, 192, flash_number);

View file

@ -363,7 +363,7 @@ void Turret_Railgun_Aim (edict_t *self)
end[2]+=self->enemy->viewheight; end[2]+=self->enemy->viewheight;
else else
end[2]+=22; end[2]+=22;
VectorCopy (end, self->aim_point); //save for aiming the shot VectorCopy (end, self->aim_point); // save for aiming the shot
self->think = Turret_Railgun_Fire; self->think = Turret_Railgun_Fire;
self->nextthink = level.time + 2 * FRAMETIME; self->nextthink = level.time + 2 * FRAMETIME;

View file

@ -239,7 +239,7 @@ PROTOCOL
// protocol.h -- communications protocols // protocol.h -- communications protocols
#define PROTOCOL_VERSION 56 // changed from 0.19, was 35 #define PROTOCOL_VERSION 57 // changed from 0.19, was 35
#define R1Q2_PROTOCOL_VERSION 35 #define R1Q2_PROTOCOL_VERSION 35
#define OLD_PROTOCOL_VERSION 34 #define OLD_PROTOCOL_VERSION 34

View file

@ -223,11 +223,12 @@ SV_WritePlayerstateToClient
*/ */
void SV_WritePlayerstateToClient (client_frame_t *from, client_frame_t *to, sizebuf_t *msg) void SV_WritePlayerstateToClient (client_frame_t *from, client_frame_t *to, sizebuf_t *msg)
{ {
int i; int i, j;
int pflags; int pflags;
player_state_t *ps, *ops; player_state_t *ps, *ops;
player_state_t dummy; player_state_t dummy;
int statbits; // int statbits;
int statbitarray[(MAX_STATS+31)>>5]; // derived from MAX_STATS
ps = &to->ps; ps = &to->ps;
if (!from) if (!from)
@ -432,7 +433,7 @@ void SV_WritePlayerstateToClient (client_frame_t *from, client_frame_t *to, size
MSG_WriteChar (msg, ps->gunangles[2]*4); MSG_WriteChar (msg, ps->gunangles[2]*4);
} }
#ifdef NEW_PLAYER_STATE_MEMBERS //Knightmare added #ifdef NEW_PLAYER_STATE_MEMBERS // Knightmare added
if (pflags & PS_WEAPONSKIN) if (pflags & PS_WEAPONSKIN)
MSG_WriteShort (msg, ps->gunskin); MSG_WriteShort (msg, ps->gunskin);
@ -454,7 +455,7 @@ void SV_WritePlayerstateToClient (client_frame_t *from, client_frame_t *to, size
if (pflags & PS_STOPSPEED) if (pflags & PS_STOPSPEED)
MSG_WriteShort (msg, ps->stopspeed); MSG_WriteShort (msg, ps->stopspeed);
#endif //end Knightmare #endif // end Knightmare
if (pflags & PS_BLEND) if (pflags & PS_BLEND)
{ {
@ -469,7 +470,7 @@ void SV_WritePlayerstateToClient (client_frame_t *from, client_frame_t *to, size
MSG_WriteByte (msg, ps->rdflags); MSG_WriteByte (msg, ps->rdflags);
// send stats // send stats
statbits = 0; /* statbits = 0;
for (i=0 ; i<MAX_STATS ; i++) for (i=0 ; i<MAX_STATS ; i++)
if (ps->stats[i] != ops->stats[i]) if (ps->stats[i] != ops->stats[i])
statbits |= 1<<i; statbits |= 1<<i;
@ -477,6 +478,17 @@ void SV_WritePlayerstateToClient (client_frame_t *from, client_frame_t *to, size
for (i=0 ; i<MAX_STATS ; i++) for (i=0 ; i<MAX_STATS ; i++)
if (statbits & (1<<i) ) if (statbits & (1<<i) )
MSG_WriteShort (msg, ps->stats[i]); MSG_WriteShort (msg, ps->stats[i]);
*/
for (j = 0; j < (MAX_STATS+31)>>5; j++)
statbitarray[j] = 0;
for (i=0; i<MAX_STATS; i++)
if (ps->stats[i] != ops->stats[i])
statbitarray[i>>5] |= 1<<(i&31);
for (j = 0; j < (MAX_STATS+31)>>5; j++)
MSG_WriteLong (msg, statbitarray[j]);
for (i=0; i<MAX_STATS; i++)
if ( statbitarray[i>>5] & (1<<(i&31)) )
MSG_WriteShort (msg, ps->stats[i]);
} }

View file

@ -311,7 +311,9 @@ void SV_StartSound (vec3_t origin, edict_t *entity, int channel,
else else
use_phs = true; use_phs = true;
sendchan = (ent<<3) | (channel&7); // Knightmare 8/2/21- changed to a full byte instead of 3 bits
// sendchan = (ent<<3) | (channel&7);
sendchan = (channel & 255);
flags = 0; flags = 0;
if (volume != DEFAULT_SOUND_PACKET_VOLUME) if (volume != DEFAULT_SOUND_PACKET_VOLUME)
@ -350,7 +352,7 @@ void SV_StartSound (vec3_t origin, edict_t *entity, int channel,
MSG_WriteByte (&sv.multicast, svc_sound); MSG_WriteByte (&sv.multicast, svc_sound);
MSG_WriteByte (&sv.multicast, flags); MSG_WriteByte (&sv.multicast, flags);
//Knightmare- 12/23/2001- changed to short // Knightmare- 12/23/2001- changed to short
MSG_WriteShort (&sv.multicast, soundindex); MSG_WriteShort (&sv.multicast, soundindex);
if (flags & SND_VOLUME) if (flags & SND_VOLUME)
@ -361,12 +363,17 @@ void SV_StartSound (vec3_t origin, edict_t *entity, int channel,
MSG_WriteByte (&sv.multicast, timeofs*1000); MSG_WriteByte (&sv.multicast, timeofs*1000);
if (flags & SND_ENT) if (flags & SND_ENT)
MSG_WriteShort (&sv.multicast, sendchan); {
// Knightmare 8/2/21- changed ent and channel to byte and a short
// MSG_WriteShort (&sv.multicast, sendchan);
MSG_WriteByte (&sv.multicast, sendchan);
MSG_WriteShort (&sv.multicast, ent);
}
if (flags & SND_POS) if (flags & SND_POS)
MSG_WritePos (&sv.multicast, origin); MSG_WritePos (&sv.multicast, origin);
// if the sound doesn't attenuate,send it to everyone // if the sound doesn't attenuate, send it to everyone
// (global radio chatter, voiceovers, etc) // (global radio chatter, voiceovers, etc)
if (attenuation == ATTN_NONE) if (attenuation == ATTN_NONE)
use_phs = false; use_phs = false;

View file

@ -57,12 +57,17 @@ void SV_CheckVelocity (edict_t *ent)
// //
// bound velocity // bound velocity
// //
for (i=0 ; i<3 ; i++) /* for (i=0 ; i<3 ; i++)
{ {
if (ent->velocity[i] > sv_maxvelocity->value) if (ent->velocity[i] > sv_maxvelocity->value)
ent->velocity[i] = sv_maxvelocity->value; ent->velocity[i] = sv_maxvelocity->value;
else if (ent->velocity[i] < -sv_maxvelocity->value) else if (ent->velocity[i] < -sv_maxvelocity->value)
ent->velocity[i] = -sv_maxvelocity->value; ent->velocity[i] = -sv_maxvelocity->value;
} */
if (VectorLength(ent->velocity) > sv_maxvelocity->value)
{
VectorNormalize (ent->velocity);
VectorScale (ent->velocity, sv_maxvelocity->value, ent->velocity);
} }
} }