]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - sv_main.c
sv_airstrafeaccel_qw cvar for tuning CPMA-style physics
[xonotic/darkplaces.git] / sv_main.c
index e1330214f43ddec39920509273a658bb3e1b8ef8..ad9a3a1384c5bf7d15ff7fbf0c77c5ee31db9b7e 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -33,6 +33,11 @@ extern cvar_t net_connecttimeout;
 void VM_CustomStats_Clear (void);
 void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats);
 
+cvar_t sv_worldmessage = {CVAR_READONLY, "sv_worldmessage", "", "title of current level"};
+cvar_t sv_worldname = {CVAR_READONLY, "sv_worldname", "", "name of current worldmodel"};
+cvar_t sv_worldnamenoextension = {CVAR_READONLY, "sv_worldnamenoextension", "", "name of current worldmodel without extension"};
+cvar_t sv_worldbasename = {CVAR_READONLY, "sv_worldbasename", "", "name of current worldmodel without maps/ prefix or extension"};
+
 cvar_t coop = {0, "coop","0", "coop mode, 0 = no coop, 1 = coop mode, multiple players playing through the singleplayer game (coop mode also shuts off deathmatch)"};
 cvar_t deathmatch = {0, "deathmatch","0", "deathmatch mode, values depend on mod but typically 0 = no deathmatch, 1 = normal deathmatch with respawning weapons, 2 = weapons stay (players can only pick up new weapons)"};
 cvar_t fraglimit = {CVAR_NOTIFY, "fraglimit","0", "ends level if this many frags is reached by any player"};
@@ -53,7 +58,9 @@ cvar_t sv_airaccelerate = {0, "sv_airaccelerate", "-1", "rate at which a player
 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_airstrafeaccel_qw = {0, "sv_airstrafeaccel_qw", "0", "when set, replacement for sv_airaccel_qw when just strafing"};
 cvar_t sv_aircontrol = {0, "sv_aircontrol", "0", "CPMA-style air control"};
+cvar_t sv_aircontrol_power = {0, "sv_aircontrol_power", "2", "CPMA-style air control exponent"};
 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)"};
@@ -175,6 +182,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 sv_autodemo_perclient_discardable = {CVAR_SAVE, "sv_autodemo_perclient_discardable", "0", "Allow game code to decide whether a demo should be kept or discarded."};
 
 cvar_t halflifebsp = {0, "halflifebsp", "0", "indicates the current map is hlbsp format (useful to know because of different bounding box sizes)"};
 
@@ -338,6 +346,12 @@ void SV_Init (void)
        extern cvar_t csqc_progname;    //[515]: csqc crc check and right csprogs name according to progs.dat
        extern cvar_t csqc_progcrc;
        extern cvar_t csqc_progsize;
+
+       Cvar_RegisterVariable(&sv_worldmessage);
+       Cvar_RegisterVariable(&sv_worldname);
+       Cvar_RegisterVariable(&sv_worldnamenoextension);
+       Cvar_RegisterVariable(&sv_worldbasename);
+
        Cvar_RegisterVariable (&csqc_progname);
        Cvar_RegisterVariable (&csqc_progcrc);
        Cvar_RegisterVariable (&csqc_progsize);
@@ -366,7 +380,9 @@ void SV_Init (void)
        Cvar_RegisterVariable (&sv_airstopaccelerate);
        Cvar_RegisterVariable (&sv_airstrafeaccelerate);
        Cvar_RegisterVariable (&sv_maxairstrafespeed);
+       Cvar_RegisterVariable (&sv_airstrafeaccel_qw);
        Cvar_RegisterVariable (&sv_aircontrol);
+       Cvar_RegisterVariable (&sv_aircontrol_power);
        Cvar_RegisterVariable (&sv_allowdownloads);
        Cvar_RegisterVariable (&sv_allowdownloads_archive);
        Cvar_RegisterVariable (&sv_allowdownloads_config);
@@ -492,6 +508,7 @@ void SV_Init (void)
 
        Cvar_RegisterVariable (&sv_autodemo_perclient);
        Cvar_RegisterVariable (&sv_autodemo_perclient_nameformat);
+       Cvar_RegisterVariable (&sv_autodemo_perclient_discardable);
 
        Cvar_RegisterVariable (&halflifebsp);
 
@@ -527,14 +544,12 @@ void SV_Init (void)
 
 static void SV_SaveEntFile_f(void)
 {
-       char basename[MAX_QPATH];
        if (!sv.active || !sv.worldmodel)
        {
                Con_Print("Not running a server\n");
                return;
        }
-       FS_StripExtension(sv.worldmodel->name, basename, sizeof(basename));
-       FS_WriteFile(va("%s.ent", basename), sv.worldmodel->brush.entities, (fs_offset_t)strlen(sv.worldmodel->brush.entities));
+       FS_WriteFile(va("%s.ent", sv.worldnamenoextension), sv.worldmodel->brush.entities, (fs_offset_t)strlen(sv.worldmodel->brush.entities));
 }
 
 
@@ -831,20 +846,15 @@ void SV_SendServerinfo (client_t *client)
        if(sv_autodemo_perclient.integer && client->netconnection)
        {
                char demofile[MAX_OSPATH];
-               char levelname[MAX_QPATH];
                char ipaddress[MAX_QPATH];
                size_t i;
 
                // start a new demo file
-               strlcpy(levelname, FS_FileWithoutPath(sv.worldmodel->name), sizeof(levelname));
-               if (strrchr(levelname, '.'))
-                       *(strrchr(levelname, '.')) = 0;
-
                LHNETADDRESS_ToString(&(client->netconnection->peeraddress), ipaddress, sizeof(ipaddress), true);
                for(i = 0; ipaddress[i]; ++i)
                        if(!isalnum(ipaddress[i]))
                                ipaddress[i] = '-';
-               dpsnprintf (demofile, sizeof(demofile), "%s_%s_%d_%s.dem", Sys_TimeString (sv_autodemo_perclient_nameformat.string), levelname, PRVM_NUM_FOR_EDICT(client->edict), ipaddress);
+               dpsnprintf (demofile, sizeof(demofile), "%s_%s_%d_%s.dem", Sys_TimeString (sv_autodemo_perclient_nameformat.string), sv.worldbasename, PRVM_NUM_FOR_EDICT(client->edict), ipaddress);
 
                SV_StartDemoRecording(client, demofile, -1);
        }
@@ -1958,7 +1968,9 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t
        statsf[STAT_MOVEVARS_AIRSTOPACCELERATE] = sv_airstopaccelerate.value;
        statsf[STAT_MOVEVARS_AIRSTRAFEACCELERATE] = sv_airstrafeaccelerate.value;
        statsf[STAT_MOVEVARS_MAXAIRSTRAFESPEED] = sv_maxairstrafespeed.value;
+       statsf[STAT_MOVEVARS_AIRSTRAFEACCEL_QW] = sv_airstrafeaccel_qw.value;
        statsf[STAT_MOVEVARS_AIRCONTROL] = sv_aircontrol.value;
+       statsf[STAT_MOVEVARS_AIRCONTROL_POWER] = sv_aircontrol_power.value;
        statsf[STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL] = sv_warsowbunny_airforwardaccel.value;
        statsf[STAT_MOVEVARS_WARSOWBUNNY_ACCEL] = sv_warsowbunny_accel.value;
        statsf[STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED] = sv_warsowbunny_topspeed.value;
@@ -2366,7 +2378,7 @@ static void SV_UpdateToReliableMessages (void)
                        }
 
                        if( oldclientcamera != host_client->clientcamera ) {
-                               MSG_WriteByte (&sv.reliable_datagram, svc_setview );
+                               MSG_WriteByte (&host_client->netconnection->message, svc_setview );
                                MSG_WriteShort (&host_client->netconnection->message, host_client->clientcamera);
                        }
                }
@@ -2713,7 +2725,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, s[0] == '*' ? sv.modelname : NULL);
+                               sv.models[i] = Mod_ForName (sv.model_precache[i], true, false, s[0] == '*' ? sv.worldname : NULL);
                                if (sv.state != ss_loading)
                                {
                                        MSG_WriteByte(&sv.reliable_datagram, svc_precache);
@@ -2808,7 +2820,7 @@ int SV_ParticleEffectIndex(const char *name)
                        if (filepass == 0)
                                dpsnprintf(filename, sizeof(filename), "effectinfo.txt");
                        else if (filepass == 1)
-                               dpsnprintf(filename, sizeof(filename), "maps/%s_effectinfo.txt", sv.name);
+                               dpsnprintf(filename, sizeof(filename), "%s_effectinfo.txt", sv.worldnamenoextension);
                        else
                                break;
                        filedata = FS_LoadFile(filename, tempmempool, true, &filesize);
@@ -3056,7 +3068,7 @@ void SV_SpawnServer (const char *server)
        int i;
        char *entities;
        dp_model_t *worldmodel;
-       char modelname[sizeof(sv.modelname)];
+       char modelname[sizeof(sv.worldname)];
 
        Con_DPrintf("SpawnServer: %s\n", server);
 
@@ -3090,7 +3102,7 @@ void SV_SpawnServer (const char *server)
        // free q3 shaders so that any newly downloaded shaders will be active
        Mod_FreeQ3Shaders();
 
-       worldmodel = Mod_ForName(modelname, false, developer.integer != 0, NULL);
+       worldmodel = Mod_ForName(modelname, false, developer.integer > 0, NULL);
        if (!worldmodel || !worldmodel->TraceBox)
        {
                Con_Printf("Couldn't load map %s\n", modelname);
@@ -3159,7 +3171,15 @@ void SV_SpawnServer (const char *server)
 
        sv.active = true;
 
+       // set level base name variables for later use
        strlcpy (sv.name, server, sizeof (sv.name));
+       strlcpy(sv.worldname, modelname, sizeof(sv.worldname));
+       FS_StripExtension(sv.worldname, sv.worldnamenoextension, sizeof(sv.worldnamenoextension));
+       strlcpy(sv.worldbasename, !strncmp(sv.worldnamenoextension, "maps/", 5) ? sv.worldnamenoextension + 5 : sv.worldnamenoextension, sizeof(sv.worldbasename));
+       //Cvar_SetQuick(&sv_worldmessage, sv.worldmessage); // set later after QC is spawned
+       Cvar_SetQuick(&sv_worldname, sv.worldname);
+       Cvar_SetQuick(&sv_worldnamenoextension, sv.worldnamenoextension);
+       Cvar_SetQuick(&sv_worldbasename, sv.worldbasename);
 
        sv.protocol = Protocol_EnumForName(sv_protocolname.string);
        if (sv.protocol == PROTOCOL_UNKNOWN)
@@ -3199,25 +3219,23 @@ void SV_SpawnServer (const char *server)
        Mod_ClearUsed();
        worldmodel->used = true;
 
-       strlcpy (sv.name, server, sizeof (sv.name));
-       strlcpy(sv.modelname, modelname, sizeof(sv.modelname));
        sv.worldmodel = worldmodel;
        sv.models[1] = sv.worldmodel;
 
 //
 // clear world interaction links
 //
-       World_SetSize(&sv.world, sv.worldmodel->name, sv.worldmodel->normalmins, sv.worldmodel->normalmaxs);
+       World_SetSize(&sv.world, sv.worldname, sv.worldmodel->normalmins, sv.worldmodel->normalmaxs);
        World_Start(&sv.world);
 
        strlcpy(sv.sound_precache[0], "", sizeof(sv.sound_precache[0]));
 
        strlcpy(sv.model_precache[0], "", sizeof(sv.model_precache[0]));
-       strlcpy(sv.model_precache[1], sv.modelname, sizeof(sv.model_precache[1]));
+       strlcpy(sv.model_precache[1], sv.worldname, sizeof(sv.model_precache[1]));
        for (i = 1;i < sv.worldmodel->brush.numsubmodels && i+1 < MAX_MODELS;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, sv.modelname);
+               sv.models[i+1] = Mod_ForName (sv.model_precache[i+1], false, false, sv.worldname);
        }
        if(i < sv.worldmodel->brush.numsubmodels)
                Con_Printf("Too many submodels (MAX_MODELS is %i)\n", MAX_MODELS);
@@ -3229,7 +3247,7 @@ void SV_SpawnServer (const char *server)
        ent = PRVM_EDICT_NUM(0);
        memset (ent->fields.server, 0, prog->progs->entityfields * 4);
        ent->priv.server->free = false;
-       ent->fields.server->model = PRVM_SetEngineString(sv.modelname);
+       ent->fields.server->model = PRVM_SetEngineString(sv.worldname);
        ent->fields.server->modelindex = 1;             // world model
        ent->fields.server->solid = SOLID_BSP;
        ent->fields.server->movetype = MOVETYPE_PUSH;
@@ -3260,9 +3278,9 @@ void SV_SpawnServer (const char *server)
        }
 
        // load replacement entity file if found
-       if (sv_entpatch.integer && (entities = (char *)FS_LoadFile(va("maps/%s.ent", sv.name), tempmempool, true, NULL)))
+       if (sv_entpatch.integer && (entities = (char *)FS_LoadFile(va("%s.ent", sv.worldnamenoextension), tempmempool, true, NULL)))
        {
-               Con_Printf("Loaded maps/%s.ent\n", sv.name);
+               Con_Printf("Loaded %s.ent\n", sv.worldnamenoextension);
                PRVM_ED_LoadFromFile (entities);
                Mem_Free(entities);
        }
@@ -3325,6 +3343,10 @@ void SV_SpawnServer (const char *server)
                }
        }
 
+       // update the map title cvar
+       strlcpy(sv.worldmessage, PRVM_GetString(prog->edicts->fields.server->message), sizeof(sv.worldmessage)); // map title (not related to filename)
+       Cvar_SetQuick(&sv_worldmessage, sv.worldmessage);
+
        Con_DPrint("Server spawned.\n");
        NetConn_Heartbeat (2);
 
@@ -3346,7 +3368,7 @@ static void SV_VM_CB_EndIncreaseEdicts(void)
        prvm_edict_t *ent;
 
        // link every entity except world
-       for (i = 1, ent = prog->edicts;i < prog->max_edicts;i++, ent++)
+       for (i = 1, ent = prog->edicts;i < prog->num_edicts;i++, ent++)
                if (!ent->priv.server->free)
                        SV_LinkEdict(ent);
 }