cvar_t sv_freezenonclients = {CVAR_NOTIFY, "sv_freezenonclients", "0", "freezes time, except for players, allowing you to walk around and take screenshots of explosions"};
cvar_t sv_friction = {CVAR_NOTIFY, "sv_friction","4", "how fast you slow down"};
cvar_t sv_gameplayfix_blowupfallenzombies = {0, "sv_gameplayfix_blowupfallenzombies", "1", "causes findradius to detect SOLID_NOT entities such as zombies and corpses on the floor, allowing splash damage to apply to them"};
+cvar_t sv_gameplayfix_delayprojectiles = {0, "sv_gameplayfix_delayprojectiles", "1", "causes entities to not move on the same frame they are spawned, meaning that projectiles wait until the next frame to perform their first move, giving proper interpolation and rocket trails, but making weapons harder to use at low framerates"};
cvar_t sv_gameplayfix_droptofloorstartsolid = {0, "sv_gameplayfix_droptofloorstartsolid", "1", "prevents items and monsters that start in a solid area from falling out of the level (makes droptofloor treat trace_startsolid as an acceptable outcome)"};
cvar_t sv_gameplayfix_findradiusdistancetobox = {0, "sv_gameplayfix_findradiusdistancetobox", "1", "causes findradius to check the distance to the corner of a box rather than the center of the box, makes findradius detect bmodels such as very large doors that would otherwise be unaffected by splash damage"};
cvar_t sv_gameplayfix_grenadebouncedownslopes = {0, "sv_gameplayfix_grenadebouncedownslopes", "1", "prevents MOVETYPE_BOUNCE (grenades) from getting stuck when fired down a downward sloping surface"};
+cvar_t sv_gameplayfix_multiplethinksperframe = {0, "sv_gameplayfix_multiplethinksperframe", "1", "allows entities to think more often than the server framerate, primarily useful for very high fire rate weapons"};
cvar_t sv_gameplayfix_noairborncorpse = {0, "sv_gameplayfix_noairborncorpse", "1", "causes entities (corpses) sitting ontop of moving entities (players) to fall when the moving entity (player) is no longer supporting them"};
cvar_t sv_gameplayfix_qwplayerphysics = {0, "sv_gameplayfix_qwplayerphysics", "1", "changes water jumping to make it easier to get out of water, and prevents friction on landing when bunnyhopping"};
cvar_t sv_gameplayfix_setmodelrealbox = {0, "sv_gameplayfix_setmodelrealbox", "1", "fixes a bug in Quake that made setmodel always set the entity box to ('-16 -16 -16', '16 16 16') rather than properly checking the model box, breaks some poorly coded mods"};
cvar_t sv_jumpstep = {CVAR_NOTIFY, "sv_jumpstep", "0", "whether you can step up while jumping (sv_gameplayfix_stepwhilejumping must also be 1)"};
cvar_t sv_jumpvelocity = {0, "sv_jumpvelocity", "270", "cvar that can be used by QuakeC code for jump velocity"};
cvar_t sv_maxairspeed = {0, "sv_maxairspeed", "30", "maximum speed a player can accelerate to when airborn (note that it is possible to completely stop by moving the opposite direction)"};
-cvar_t sv_maxrate = {CVAR_SAVE | CVAR_NOTIFY, "sv_maxrate", "10000", "upper limit on client rate cvar, should reflect your network connection quality"};
+cvar_t sv_maxrate = {CVAR_SAVE | CVAR_NOTIFY, "sv_maxrate", "1000000", "upper limit on client rate cvar, should reflect your network connection quality"};
cvar_t sv_maxspeed = {CVAR_NOTIFY, "sv_maxspeed", "320", "maximum speed a player can accelerate to when on ground (can be exceeded by tricks)"};
cvar_t sv_maxvelocity = {CVAR_NOTIFY, "sv_maxvelocity","2000", "universal speed limit on all entities"};
cvar_t sv_newflymove = {CVAR_NOTIFY, "sv_newflymove", "0", "enables simpler/buggier player physics (not recommended)"};
Cvar_RegisterVariable (&sv_freezenonclients);
Cvar_RegisterVariable (&sv_friction);
Cvar_RegisterVariable (&sv_gameplayfix_blowupfallenzombies);
+ Cvar_RegisterVariable (&sv_gameplayfix_delayprojectiles);
Cvar_RegisterVariable (&sv_gameplayfix_droptofloorstartsolid);
Cvar_RegisterVariable (&sv_gameplayfix_findradiusdistancetobox);
Cvar_RegisterVariable (&sv_gameplayfix_grenadebouncedownslopes);
+ Cvar_RegisterVariable (&sv_gameplayfix_multiplethinksperframe);
Cvar_RegisterVariable (&sv_gameplayfix_noairborncorpse);
Cvar_RegisterVariable (&sv_gameplayfix_qwplayerphysics);
Cvar_RegisterVariable (&sv_gameplayfix_setmodelrealbox);
}
Cvar_RegisterVariable (&cutscene); // for Nehahra but useful to other mods as well
+ // any special defaults for gamemodes go here
+ if (gamemode == GAME_HIPNOTIC)
+ {
+ // hipnotic mission pack has issues in their 'friendly monster' ai, which seem to attempt to attack themselves for some reason when findradius() returns non-solid entities.
+ Cvar_SetValueQuick (&sv_gameplayfix_blowupfallenzombies, 0);
+ }
+
sv_mempool = Mem_AllocPool("server", 0, NULL);
}
MSG_WriteByte (&client->netconnection->message, 1);
client->spawned = false; // need prespawn, spawn, etc
+ client->sendsignon = 1; // send this message, and increment to 2, 2 will be set to 0 by the prespawn command
// clear movement info until client enters the new level properly
memset(&client->cmd, 0, sizeof(client->cmd));
// prepare the unreliable message buffer
client->unreliablemsg.data = client->unreliablemsg_data;
client->unreliablemsg.maxsize = sizeof(client->unreliablemsg_data);
- // updated by receiving "rate" command from client
- client->rate = NET_MINRATE;
+ // updated by receiving "rate" command from client, this is also the default if not using a DP client
+ client->rate = 1000000000;
// no limits for local player
if (client->netconnection && LHNETADDRESS_GetAddressType(&client->netconnection->peeraddress) == LHNETADDRESSTYPE_LOOP)
client->rate = 1000000000;
//stats[STAT_MONSTERS] = prog->globals.server->killed_monsters;
// movement settings for prediction
+ // note: these are not sent in protocols with lower MAX_CL_STATS limits
statsf[STAT_MOVEVARS_TICRATE] = sys_ticrate.value;
statsf[STAT_MOVEVARS_TIMESCALE] = slowmo.value;
statsf[STAT_MOVEVARS_GRAVITY] = sv_gravity.value;
statsf[STAT_MOVEVARS_AIRACCELERATE] = sv_airaccelerate.value >= 0 ? sv_airaccelerate.value : sv_accelerate.value;
statsf[STAT_MOVEVARS_WATERACCELERATE] = sv_wateraccelerate.value >= 0 ? sv_wateraccelerate.value : sv_accelerate.value;
val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.gravity);
- statsf[STAT_MOVEVARS_ENTGRAVITY] = val ? val->_float : 1.0f;
+ statsf[STAT_MOVEVARS_ENTGRAVITY] = (val && val->_float != 0) ? val->_float : 1.0f;
statsf[STAT_MOVEVARS_JUMPVELOCITY] = sv_jumpvelocity.value;
statsf[STAT_MOVEVARS_EDGEFRICTION] = sv_edgefriction.value;
statsf[STAT_MOVEVARS_MAXAIRSPEED] = sv_maxairspeed.value;
statsf[STAT_MOVEVARS_STEPHEIGHT] = sv_stepheight.value;
statsf[STAT_MOVEVARS_AIRACCEL_QW] = sv_airaccel_qw.value;
statsf[STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION] = sv_airaccel_sideways_friction.value;
+ statsf[STAT_MOVEVARS_FRICTION] = sv_friction.value;
+ statsf[STAT_MOVEVARS_WATERFRICTION] = sv_waterfriction.value >= 0 ? sv_waterfriction.value : sv_friction.value;
+ statsf[STAT_FRAGLIMIT] = fraglimit.value;
+ statsf[STAT_TIMELIMIT] = timelimit.value;
if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
{
}
if (bits & (SU_VELOCITY1<<i))
{
- if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
+ if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
MSG_WriteChar(msg, (int)(ent->fields.server->velocity[i] * (1.0f / 16.0f)));
else
MSG_WriteCoord32f(msg, ent->fields.server->velocity[i]);
if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE || gamemode == GAME_NEXUIZ)
{
for (i = 0;i < 32;i++)
- if (stats[STAT_WEAPON] & (1<<i))
+ if (stats[STAT_ACTIVEWEAPON] & (1<<i))
break;
MSG_WriteByte (msg, i);
}
else
- MSG_WriteByte (msg, stats[STAT_WEAPON]);
+ MSG_WriteByte (msg, stats[STAT_ACTIVEWEAPON]);
if (bits & SU_VIEWZOOM)
{
if (sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
// no packet size limit support on older protocols because DP1-4 kick
// the client off if they overflow, and quake protocol shows less than
// the full entity set if rate limited
- maxsize = 1400;
- maxsize2 = 1400;
+ clientrate = max(NET_MINRATE, client->rate);
+ maxsize = 1024;
+ maxsize2 = 1024;
}
else
{
if (!NetConn_CanSend(client->netconnection))
{
// send the datagram
- //NetConn_SendUnreliableMessage (client->netconnection, &msg, sv.protocol, clientrate);
+ //NetConn_SendUnreliableMessage (client->netconnection, &msg, sv.protocol, clientrate, true);
return;
}
else if (host_client->spawned)
}
// send the datagram
- NetConn_SendUnreliableMessage (client->netconnection, &msg, sv.protocol, clientrate);
+ NetConn_SendUnreliableMessage (client->netconnection, &msg, sv.protocol, clientrate, client->sendsignon == 2);
+ if (client->sendsignon == 1 && !client->netconnection->message.cursize)
+ client->sendsignon = 2; // prevent reliable until client sends prespawn (this is the keepalive phase)
}
/*
if (strcmp(host_client->old_name, host_client->name))
{
if (host_client->spawned)
- SV_BroadcastPrintf("%s^%i changed name to %s\n", host_client->old_name, STRING_COLOR_DEFAULT, host_client->name);
+ SV_BroadcastPrintf("%s changed name to %s\n", host_client->old_name, host_client->name);
strlcpy(host_client->old_name, host_client->name, sizeof(host_client->old_name));
// send notification to all clients
MSG_WriteByte (&sv.reliable_datagram, svc_updatename);
host_client->download_expectedposition = 0;
host_client->download_started = false;
+ host_client->sendsignon = true; // make sure this message is sent
// the rest of the download process is handled in SV_SendClientDatagram
// and other code dealing with svc_downloaddata and clc_ackdownloaddata
prog->numbuiltins = vm_sv_numbuiltins;
prog->headercrc = PROGHEADER_CRC;
prog->max_edicts = 512;
- prog->limit_edicts = MAX_EDICTS;
+ if (sv.protocol == PROTOCOL_QUAKE)
+ prog->limit_edicts = 640; // before quake mission pack 1 this was 512
+ else if (sv.protocol == PROTOCOL_QUAKEDP)
+ prog->limit_edicts = 2048; // guessing
+ else if (sv.protocol == PROTOCOL_NEHAHRAMOVIE)
+ prog->limit_edicts = 2048; // guessing!
+ else
+ prog->limit_edicts = MAX_EDICTS;
prog->reserved_edicts = svs.maxclients;
prog->edictprivate_size = sizeof(edict_engineprivate_t);
prog->name = "server";