]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_main.c
CPMA-style cl_movement physics settings possible! Variables for it:
[xonotic/darkplaces.git] / sv_main.c
index be2111c0d4b6e48770cac9b365b5ad1058334ab0..1bff09322e614cb87682c411c58aedba10187d66 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -50,6 +50,10 @@ cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2", "maximum cosine angle for quake's ver
 cvar_t sv_airaccel_qw = {0, "sv_airaccel_qw", "1", "ratio of QW-style air control as opposed to simple acceleration"};
 cvar_t sv_airaccel_sideways_friction = {0, "sv_airaccel_sideways_friction", "", "anti-sideways movement stabilization (reduces speed gain when zigzagging)"};
 cvar_t sv_airaccelerate = {0, "sv_airaccelerate", "-1", "rate at which a player accelerates to sv_maxairspeed while in the air, if less than 0 the sv_accelerate variable is used instead"};
+cvar_t sv_airstopaccelerate = {0, "sv_airstopaccelerate", "0", "when set, replacement for sv_airaccelerate when moving backwards"};
+cvar_t sv_airstrafeaccelerate = {0, "sv_airstrafeaccelerate", "0", "when set, replacement for sv_airaccelerate when just strafing"};
+cvar_t sv_maxairstrafespeed = {0, "sv_maxairstrafespeed", "0", "when set, replacement for sv_maxairspeed when just strafing"};
+cvar_t sv_aircontrol = {0, "sv_aircontrol", "0", "CPMA-style air control"};
 cvar_t sv_allowdownloads = {0, "sv_allowdownloads", "1", "whether to allow clients to download files from the server (does not affect http downloads)"};
 cvar_t sv_allowdownloads_archive = {0, "sv_allowdownloads_archive", "0", "whether to allow downloads of archives (pak/pk3)"};
 cvar_t sv_allowdownloads_config = {0, "sv_allowdownloads_config", "0", "whether to allow downloads of config files (cfg)"};
@@ -59,6 +63,7 @@ cvar_t sv_areagrid_mingridsize = {CVAR_NOTIFY, "sv_areagrid_mingridsize", "64",
 cvar_t sv_checkforpacketsduringsleep = {0, "sv_checkforpacketsduringsleep", "0", "uses select() function to wait between frames which can be interrupted by packets being received, instead of Sleep()/usleep()/SDL_Sleep() functions which do not check for packets"};
 cvar_t sv_clmovement_enable = {0, "sv_clmovement_enable", "1", "whether to allow clients to use cl_movement prediction, which can cause choppy movement on the server which may annoy other players"};
 cvar_t sv_clmovement_minping = {0, "sv_clmovement_minping", "0", "if client ping is below this time in milliseconds, then their ability to use cl_movement prediction is disabled for a while (as they don't need it)"};
+cvar_t sv_clmovement_maxnetfps = {0, "sv_clmovement_maxnetfps", "0", "max amount of movement packets to accept per second"};
 cvar_t sv_clmovement_minping_disabletime = {0, "sv_clmovement_minping_disabletime", "1000", "when client falls below minping, disable their prediction for this many milliseconds (should be at least 1000 or else their prediction may turn on/off frequently)"};
 cvar_t sv_clmovement_inputtimeout = {0, "sv_clmovement_inputtimeout", "0.2", "when a client does not send input for this many seconds, force them to move anyway (unlike QuakeWorld)"};
 cvar_t sv_cullentities_nevercullbmodels = {0, "sv_cullentities_nevercullbmodels", "0", "if enabled the clients are always notified of moving doors and lifts and other submodels of world (warning: eats a lot of network bandwidth on some levels!)"};
@@ -157,6 +162,7 @@ cvar_t cutscene = {0, "cutscene", "1", "enables cutscenes in nehahra, can be use
 cvar_t sv_autodemo_perclient = {CVAR_SAVE, "sv_autodemo_perclient", "0", "set to 1 to enable autorecorded per-client demos (they'll start to record at the beginning of a match); set it to 2 to also record client->server packets (for debugging)"};
 cvar_t sv_autodemo_perclient_nameformat = {CVAR_SAVE, "sv_autodemo_perclient_nameformat", "sv_autodemos/%Y-%m-%d_%H-%M", "The format of the sv_autodemo_perclient filename, followed by the map name, the client number and the IP address + port number, separated by underscores (the date is encoded using strftime escapes)" };
 
+cvar_t halflifebsp = {0, "halflifebsp", "0", "indicates the current map is hlbsp format (useful to know because of different bounding box sizes)"};
 
 server_t sv;
 server_static_t svs;
@@ -327,6 +333,10 @@ void SV_Init (void)
        Cvar_RegisterVariable (&sv_airaccel_qw);
        Cvar_RegisterVariable (&sv_airaccel_sideways_friction);
        Cvar_RegisterVariable (&sv_airaccelerate);
+       Cvar_RegisterVariable (&sv_airstopaccelerate);
+       Cvar_RegisterVariable (&sv_airstrafeaccelerate);
+       Cvar_RegisterVariable (&sv_maxairstrafespeed);
+       Cvar_RegisterVariable (&sv_aircontrol);
        Cvar_RegisterVariable (&sv_allowdownloads);
        Cvar_RegisterVariable (&sv_allowdownloads_archive);
        Cvar_RegisterVariable (&sv_allowdownloads_config);
@@ -335,6 +345,7 @@ void SV_Init (void)
        Cvar_RegisterVariable (&sv_areagrid_mingridsize);
        Cvar_RegisterVariable (&sv_checkforpacketsduringsleep);
        Cvar_RegisterVariable (&sv_clmovement_enable);
+       Cvar_RegisterVariable (&sv_clmovement_maxnetfps);
        Cvar_RegisterVariable (&sv_clmovement_minping);
        Cvar_RegisterVariable (&sv_clmovement_minping_disabletime);
        Cvar_RegisterVariable (&sv_clmovement_inputtimeout);
@@ -438,7 +449,16 @@ void SV_Init (void)
        Cvar_RegisterVariable (&sv_autodemo_perclient);
        Cvar_RegisterVariable (&sv_autodemo_perclient_nameformat);
 
+       Cvar_RegisterVariable (&halflifebsp);
+
        // any special defaults for gamemodes go here
+       if (gamemode == GAME_NEHAHRA)
+       {
+               // Nehahra pushable crates malfunction in some levels if this is on
+               Cvar_SetValueQuick (&sv_gameplayfix_upwardvelocityclearsongroundflag, 0);
+               // Nehahra NPC AI is confused by this feature
+               Cvar_SetValueQuick (&sv_gameplayfix_blowupfallenzombies, 0);
+       }
        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.
@@ -800,7 +820,7 @@ void SV_SendServerinfo (client_t *client)
                        sb.data = (unsigned char *) buf;
                        sb.maxsize = sizeof(buf);
                        i = 0;
-                       while(MakeDownloadPacket(sv.csqc_progname, sv.csqc_progdata, sv.csqc_progsize, sv.csqc_progcrc, i++, &sb, sv.protocol))
+                       while(MakeDownloadPacket(sv.csqc_progname, svs.csqc_progdata, sv.csqc_progsize, sv.csqc_progcrc, i++, &sb, sv.protocol))
                                SV_WriteDemoMessage(client, &sb, false);
                }
 
@@ -1310,7 +1330,7 @@ void SV_MarkWriteEntityStateToClient(entity_state_t *s)
                        ed = PRVM_EDICT_NUM(s->number);
 
                        // if not touching a visible leaf
-                       if (sv_cullentities_pvs.integer && sv.writeentitiestoclient_pvsbytes)
+                       if (sv_cullentities_pvs.integer && !r_novis.integer && sv.writeentitiestoclient_pvsbytes)
                        {
                                if (ed->priv.server->pvs_numclusters < 0)
                                {
@@ -1644,6 +1664,10 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t
        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_MOVEVARS_AIRSTOPACCELERATE] = sv_airstopaccelerate.value;
+       statsf[STAT_MOVEVARS_AIRSTRAFEACCELERATE] = sv_airstrafeaccelerate.value;
+       statsf[STAT_MOVEVARS_MAXAIRSTRAFESPEED] = sv_maxairstrafespeed.value;
+       statsf[STAT_MOVEVARS_AIRCONTROL] = sv_aircontrol.value;
        statsf[STAT_FRAGLIMIT] = fraglimit.value;
        statsf[STAT_TIMELIMIT] = timelimit.value;
 
@@ -2234,9 +2258,9 @@ static void SV_Download_f(void)
                Con_DPrintf("Downloading %s to %s\n", host_client->download_name, host_client->name);
 
                if(host_client->download_deflate)
-                       host_client->download_file = FS_FileFromData(sv.csqc_progdata_deflated, sv.csqc_progsize_deflated, true);
+                       host_client->download_file = FS_FileFromData(svs.csqc_progdata_deflated, svs.csqc_progsize_deflated, true);
                else
-                       host_client->download_file = FS_FileFromData(sv.csqc_progdata, sv.csqc_progsize, true);
+                       host_client->download_file = FS_FileFromData(svs.csqc_progdata, sv.csqc_progsize, true);
                
                // no, no space is needed between %s and %s :P
                Host_ClientCommands("\ncl_downloadbegin %i %s%s\n", (int)FS_FileSize(host_client->download_file), host_client->download_name, extensions);
@@ -2399,7 +2423,7 @@ int SV_ModelIndex(const char *s, int precachemode)
                                if (precachemode == 1)
                                        Con_Printf("SV_ModelIndex(\"%s\"): not precached (fix your code), precaching anyway\n", filename);
                                strlcpy(sv.model_precache[i], filename, sizeof(sv.model_precache[i]));
-                               sv.models[i] = Mod_ForName (sv.model_precache[i], true, false, false);
+                               sv.models[i] = Mod_ForName (sv.model_precache[i], true, false, s[0] == '*' ? sv.modelname : NULL);
                                if (sv.state != ss_loading)
                                {
                                        MSG_WriteByte(&sv.reliable_datagram, svc_precache);
@@ -2638,37 +2662,37 @@ void SV_Prepare_CSQC(void)
 {
        fs_offset_t progsize;
 
-       if(sv.csqc_progdata)
+       if(svs.csqc_progdata)
        {
                Con_DPrintf("Unloading old CSQC data.\n");
-               Mem_Free(sv.csqc_progdata);
-               if(sv.csqc_progdata_deflated)
-                       Mem_Free(sv.csqc_progdata_deflated);
+               Mem_Free(svs.csqc_progdata);
+               if(svs.csqc_progdata_deflated)
+                       Mem_Free(svs.csqc_progdata_deflated);
        }
 
-       sv.csqc_progdata = NULL;
-       sv.csqc_progdata_deflated = NULL;
+       svs.csqc_progdata = NULL;
+       svs.csqc_progdata_deflated = NULL;
        
        Con_Print("Loading csprogs.dat\n");
 
        sv.csqc_progname[0] = 0;
-       sv.csqc_progdata = FS_LoadFile(csqc_progname.string, sv_mempool, false, &progsize);
+       svs.csqc_progdata = FS_LoadFile(csqc_progname.string, sv_mempool, false, &progsize);
 
        if(progsize > 0)
        {
                size_t deflated_size;
                
                sv.csqc_progsize = (int)progsize;
-               sv.csqc_progcrc = CRC_Block(sv.csqc_progdata, progsize);
+               sv.csqc_progcrc = CRC_Block(svs.csqc_progdata, progsize);
                strlcpy(sv.csqc_progname, csqc_progname.string, sizeof(sv.csqc_progname));
                Con_Printf("server detected csqc progs file \"%s\" with size %i and crc %i\n", sv.csqc_progname, sv.csqc_progsize, sv.csqc_progcrc);
 
                Con_Print("Compressing csprogs.dat\n");
                //unsigned char *FS_Deflate(const unsigned char *data, size_t size, size_t *deflated_size, int level, mempool_t *mempool);
-               sv.csqc_progdata_deflated = FS_Deflate(sv.csqc_progdata, progsize, &deflated_size, -1, sv_mempool);
-               sv.csqc_progsize_deflated = (int)deflated_size;
+               svs.csqc_progdata_deflated = FS_Deflate(svs.csqc_progdata, progsize, &deflated_size, -1, sv_mempool);
+               svs.csqc_progsize_deflated = (int)deflated_size;
                Con_Printf("Deflated: %g%%\n", 100.0 - 100.0 * (deflated_size / (float)progsize));
-               Con_DPrintf("Uncompressed: %u\nCompressed:   %u\n", (unsigned)sv.csqc_progsize, (unsigned)sv.csqc_progsize_deflated);
+               Con_DPrintf("Uncompressed: %u\nCompressed:   %u\n", (unsigned)sv.csqc_progsize, (unsigned)svs.csqc_progsize_deflated);
        }
 }
 
@@ -2701,7 +2725,7 @@ void SV_SaveSpawnparms (void)
 
 /*
 ================
-SV_/pawnServer
+SV_SpawnServer
 
 This is called at the start of each level
 ================
@@ -2743,7 +2767,10 @@ void SV_SpawnServer (const char *server)
                SV_VM_End();
        }
 
-       worldmodel = Mod_ForName(modelname, false, true, true);
+       // free q3 shaders so that any newly downloaded shaders will be active
+       Mod_FreeQ3Shaders();
+
+       worldmodel = Mod_ForName(modelname, false, true, NULL);
        if (!worldmodel || !worldmodel->TraceBox)
        {
                Con_Printf("Couldn't load map %s\n", modelname);
@@ -2792,13 +2819,6 @@ void SV_SpawnServer (const char *server)
        //Cvar_SetValue ("skill", (float)current_skill);
        current_skill = (int)(skill.value + 0.5);
 
-       if(sv.csqc_progdata)
-       {
-               Con_DPrintf("Unloading CSQC data.\n");
-               Mem_Free(sv.csqc_progdata);
-               if(sv.csqc_progdata_deflated)
-                       Mem_Free(sv.csqc_progdata_deflated);
-       }
 //
 // set up the new server
 //
@@ -2807,6 +2827,8 @@ void SV_SpawnServer (const char *server)
        // level's data which is no longer valiud
        cls.signon = 0;
 
+       Cvar_SetValue("halflifebsp", worldmodel->brush.ishlbsp);
+
        if(*sv_random_seed.string)
        {
                srand(sv_random_seed.integer);
@@ -2874,7 +2896,7 @@ void SV_SpawnServer (const char *server)
        for (i = 1;i < sv.worldmodel->brush.numsubmodels;i++)
        {
                dpsnprintf(sv.model_precache[i+1], sizeof(sv.model_precache[i+1]), "*%i", i);
-               sv.models[i+1] = Mod_ForName (sv.model_precache[i+1], false, false, false);
+               sv.models[i+1] = Mod_ForName (sv.model_precache[i+1], false, false, sv.modelname);
        }
 
 //
@@ -2929,22 +2951,26 @@ void SV_SpawnServer (const char *server)
        VectorClear(prog->edicts->fields.server->angles);
 
 // all setup is completed, any further precache statements are errors
-       sv.state = ss_active;
+//     sv.state = ss_active; // LordHavoc: workaround for svc_precache bug
        prog->allowworldwrites = false;
 
 // run two frames to allow everything to settle
+       prog->globals.server->time = sv.time = 1.0001;
        for (i = 0;i < 2;i++)
        {
                sv.frametime = 0.1;
                SV_Physics ();
        }
 
-       Mod_PurgeUnused();
+       if (cls.state == ca_dedicated)
+               Mod_PurgeUnused();
 
 // create a baseline for more efficient communications
        if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
                SV_CreateBaseline ();
-       
+
+       sv.state = ss_active; // LordHavoc: workaround for svc_precache bug
+
        // to prevent network timeouts
        realtime = Sys_DoubleTime();