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_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);
// 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);
}
+ if (gamemode == GAME_ROGUE)
+ {
+ // rogue mission pack has a guardian boss that does not wake up if findradius returns one of the entities around its spawn area
+ Cvar_SetValueQuick (&sv_gameplayfix_findradiusdistancetobox, 0);
+ }
sv_mempool = Mem_AllocPool("server", 0, NULL);
}
SV_FlushBroadcastMessages();
}
+/*
+==================
+SV_StartPointSound
+
+Nearly the same logic as SV_StartSound, except an origin
+instead of an entity is provided and channel is omitted.
+
+The entity sent to the client is 0 (world) and the channel
+is 0 (CHAN_AUTO). SND_LARGEENTITY will never occur in this
+function, therefore the check for it is omitted.
+
+==================
+*/
+void SV_StartPointSound (vec3_t origin, const char *sample, int volume, float attenuation)
+{
+ int sound_num, field_mask, i;
+
+ if (volume < 0 || volume > 255)
+ {
+ Con_Printf ("SV_StartPointSound: volume = %i\n", volume);
+ return;
+ }
+
+ if (attenuation < 0 || attenuation > 4)
+ {
+ Con_Printf ("SV_StartPointSound: attenuation = %f\n", attenuation);
+ return;
+ }
+
+ if (sv.datagram.cursize > MAX_PACKETFRAGMENT-21)
+ return;
+
+ // find precache number for sound
+ sound_num = SV_SoundIndex(sample, 1);
+ if (!sound_num)
+ return;
+
+ field_mask = 0;
+ if (volume != DEFAULT_SOUND_PACKET_VOLUME)
+ field_mask |= SND_VOLUME;
+ if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
+ field_mask |= SND_ATTENUATION;
+ if (sound_num >= 256)
+ field_mask |= SND_LARGESOUND;
+
+// directed messages go only to the entity they are targeted on
+ 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, (int)(attenuation*64));
+ // Always write entnum 0 for the world entity
+ MSG_WriteShort (&sv.datagram, (0<<3) | 0);
+ if (field_mask & SND_LARGESOUND)
+ MSG_WriteShort (&sv.datagram, sound_num);
+ else
+ MSG_WriteByte (&sv.datagram, sound_num);
+ for (i = 0;i < 3;i++)
+ MSG_WriteCoord (&sv.datagram, origin[i], sv.protocol);
+ SV_FlushBroadcastMessages();
+}
+
/*
==============================================================================
MSG_WriteByte (&client->netconnection->message, 1);
client->spawned = false; // need prespawn, spawn, etc
- client->sendsignon = true; // send this message, this will be cleared later
+ 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));
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)
// the client off if they overflow, and quake protocol shows less than
// the full entity set if rate limited
clientrate = max(NET_MINRATE, client->rate);
- maxsize = 1400;
- maxsize2 = 1400;
+ maxsize = 1024;
+ maxsize2 = 1024;
}
else
{
}
// send the datagram
- NetConn_SendUnreliableMessage (client->netconnection, &msg, sv.protocol, clientrate, !client->spawned && !client->sendsignon);
- if (!client->netconnection->message.cursize)
- client->sendsignon = false;
+ 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)
}
/*
Con_DPrintf("SpawnServer: %s\n", server);
if (cls.state != ca_dedicated)
+ {
SCR_BeginLoadingPlaque();
+ S_StopAllSounds();
+ }
dpsnprintf (modelname, sizeof(modelname), "maps/%s.bsp", server);
worldmodel = Mod_ForName(modelname, false, true, true);
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";