]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_main.c
implemented q3 shader keyword polygonoffset
[xonotic/darkplaces.git] / sv_main.c
index 6c4516dfedd4c9783c9433203250524db77b1326..17dbf2c38bc57d2f7d6a62fc97153e98ce7bb5e1 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -76,9 +76,11 @@ cvar_t sv_fixedframeratesingleplayer = {0, "sv_fixedframeratesingleplayer", "0",
 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"};
@@ -340,9 +342,11 @@ void SV_Init (void)
        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);
@@ -419,6 +423,11 @@ void SV_Init (void)
                // 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);
 }
@@ -586,6 +595,69 @@ void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int v
        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();
+}
+
 /*
 ==============================================================================
 
@@ -714,7 +786,7 @@ void SV_SendServerinfo (client_t *client)
        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));
@@ -1490,12 +1562,12 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t
                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)
@@ -1593,8 +1665,8 @@ static void SV_SendClientDatagram (client_t *client)
                // 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
        {
@@ -1684,9 +1756,9 @@ static void SV_SendClientDatagram (client_t *client)
        }
 
 // 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)
 }
 
 /*
@@ -2262,7 +2334,10 @@ void SV_SpawnServer (const char *server)
        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);
@@ -2646,7 +2721,14 @@ static void SV_VM_Setup(void)
        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";