]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cmd.c
fix a crash
[xonotic/darkplaces.git] / cmd.c
diff --git a/cmd.c b/cmd.c
index cbff83aa2f063312760a3bafa1c1963467018ecc..a395eed658b9a65d8c95517ed3fb53e0820de83a 100644 (file)
--- a/cmd.c
+++ b/cmd.c
@@ -26,6 +26,8 @@ typedef struct cmdalias_s
        struct cmdalias_s *next;
        char name[MAX_ALIAS_NAME];
        char *value;
+       qboolean initstate; // indicates this command existed at init
+       char *initialvalue; // backup copy of value at init
 } cmdalias_t;
 
 static cmdalias_t *cmd_alias;
@@ -492,6 +494,24 @@ static void Cmd_Exec_f (void)
        Cbuf_InsertText ("\n");
        Cbuf_InsertText (f);
        Mem_Free(f);
+
+       // special defaults for specific games go here, these execute before default.cfg
+       // Nehahra pushable crates malfunction in some levels if this is on
+       // Nehahra NPC AI is confused by blowupfallenzombies
+       if (gamemode == GAME_NEHAHRA)
+               Cbuf_InsertText("\nsv_gameplayfix_upwardvelocityclearsongroundflag 0\nsv_gameplayfix_blowupfallenzombies 0\n\n");
+       // 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.
+       // hipnotic mission pack has issues with bobbing water entities 'jittering' between different heights on alternate frames at the default 0.0138889 ticrate, 0.02 avoids this issue
+       // hipnotic mission pack has issues in their proximity mine sticking code, which causes them to bounce off.
+       if (gamemode == GAME_HIPNOTIC)
+               Cbuf_InsertText("\nsv_gameplayfix_blowupfallenzombies 0\nsys_ticrate 0.02\nsv_gameplayfix_slidemoveprojectiles 0\n\n");
+       // rogue mission pack has a guardian boss that does not wake up if findradius returns one of the entities around its spawn area
+       if (gamemode == GAME_ROGUE)
+               Cbuf_InsertText("\nsv_gameplayfix_findradiusdistancetobox 0\n\n");
+       if (gamemode == GAME_NEXUIZ)
+               Cbuf_InsertText("\nsv_gameplayfix_q2airaccelerate 1\nsv_gameplayfix_stepmultipletimes 1\n\n");
+       if (gamemode == GAME_TENEBRAE)
+               Cbuf_InsertText("\nr_shadow_gloss 2\nr_shadow_bumpscale_basetexture 4\n\n");
 }
 
 
@@ -652,11 +672,11 @@ static void Cmd_Alias_f (void)
 // copy the rest of the command line
        cmd[0] = 0;             // start out with a null string
        c = Cmd_Argc();
-       for (i=2 ; i< c ; i++)
+       for (i=2 ; i < c ; i++)
        {
-               strlcat (cmd, Cmd_Argv(i), sizeof (cmd));
-               if (i != c)
+               if (i != 2)
                        strlcat (cmd, " ", sizeof (cmd));
+               strlcat (cmd, Cmd_Argv(i), sizeof (cmd));
        }
        strlcat (cmd, "\n", sizeof (cmd));
 
@@ -694,6 +714,8 @@ static void Cmd_UnAlias_f (void)
                {
                        if(!strcmp(s, a->name))
                        {
+                               if (a->initstate) // we can not remove init aliases
+                                       continue;
                                if(a == cmd_alias)
                                        cmd_alias = a->next;
                                if(p)
@@ -724,6 +746,7 @@ typedef struct cmd_function_s
        xcommand_t consolefunction;
        xcommand_t clientfunction;
        qboolean csqcfunc;
+       qboolean initstate; // indicates this command existed at init
 } cmd_function_t;
 
 static int cmd_argc;
@@ -801,57 +824,63 @@ static const char *Cmd_GetDirectCvarValue(const char *varname, cmdalias_t *alias
        return NULL;
 }
 
-qboolean Cmd_QuoteString(char *out, size_t outlen, const char *in, const char *quoteset)
+qboolean Cmd_QuoteString(char *out, size_t outlen, const char *in, const char *quoteset, qboolean putquotes)
 {
        qboolean quote_quot = !!strchr(quoteset, '"');
        qboolean quote_backslash = !!strchr(quoteset, '\\');
        qboolean quote_dollar = !!strchr(quoteset, '$');
 
+       if(putquotes)
+       {
+               if(outlen <= 2)
+               {
+                       *out++ = 0;
+                       return false;
+               }
+               *out++ = '"'; --outlen;
+               --outlen;
+       }
+
        while(*in)
        {
                if(*in == '"' && quote_quot)
                {
                        if(outlen <= 2)
-                       {
-                               *out++ = 0;
-                               return false;
-                       }
+                               goto fail;
                        *out++ = '\\'; --outlen;
                        *out++ = '"'; --outlen;
                }
                else if(*in == '\\' && quote_backslash)
                {
                        if(outlen <= 2)
-                       {
-                               *out++ = 0;
-                               return false;
-                       }
+                               goto fail;
                        *out++ = '\\'; --outlen;
                        *out++ = '\\'; --outlen;
                }
                else if(*in == '$' && quote_dollar)
                {
                        if(outlen <= 2)
-                       {
-                               *out++ = 0;
-                               return false;
-                       }
+                               goto fail;
                        *out++ = '$'; --outlen;
                        *out++ = '$'; --outlen;
                }
                else
                {
                        if(outlen <= 1)
-                       {
-                               *out++ = 0;
-                               return false;
-                       }
+                               goto fail;
                        *out++ = *in; --outlen;
                }
                ++in;
        }
+       if(putquotes)
+               *out++ = '"';
        *out++ = 0;
        return true;
+fail:
+       if(putquotes)
+               *out++ = '"';
+       *out++ = 0;
+       return false;
 }
 
 static const char *Cmd_GetCvarValue(const char *var, size_t varlen, cmdalias_t *alias)
@@ -907,7 +936,7 @@ static char asis[] = "asis"; // just to suppress const char warnings
        {
                // quote it so it can be used inside double quotes
                // we just need to replace " by \", and of course, double backslashes
-               Cmd_QuoteString(varval, sizeof(varval), varstr, "\"\\");
+               Cmd_QuoteString(varval, sizeof(varval), varstr, "\"\\", false);
                return varval;
        }
        else if(!strcmp(varfunc, "asis"))
@@ -1055,7 +1084,7 @@ static void Cmd_ExecuteAlias (cmdalias_t *alias)
        // Note: Cbuf_PreprocessString will be called on this string AGAIN! So we
        // have to make sure that no second variable expansion takes place, otherwise
        // alias parameters containing dollar signs can have bad effects.
-       Cmd_QuoteString(buffer2, sizeof(buffer2), buffer, "$");
+       Cmd_QuoteString(buffer2, sizeof(buffer2), buffer, "$", false);
        Cbuf_InsertText( buffer2 );
 }
 
@@ -1868,3 +1897,61 @@ int Cmd_CheckParm (const char *parm)
        return 0;
 }
 
+
+
+void Cmd_SaveInitState(void)
+{
+       cmd_function_t *f;
+       cmdalias_t *a;
+       for (f = cmd_functions;f;f = f->next)
+               f->initstate = true;
+       for (a = cmd_alias;a;a = a->next)
+       {
+               a->initstate = true;
+               a->initialvalue = Mem_strdup(zonemempool, a->value);
+       }
+       Cvar_SaveInitState();
+}
+
+void Cmd_RestoreInitState(void)
+{
+       cmd_function_t *f, **fp;
+       cmdalias_t *a, **ap;
+       for (fp = &cmd_functions;(f = *fp);)
+       {
+               if (f->initstate)
+                       fp = &f->next;
+               else
+               {
+                       // destroy this command, it didn't exist at init
+                       Con_DPrintf("Cmd_RestoreInitState: Destroying command %s\n", f->name);
+                       *fp = f->next;
+                       Z_Free(f);
+               }
+       }
+       for (ap = &cmd_alias;(a = *ap);)
+       {
+               if (a->initstate)
+               {
+                       // restore this alias, it existed at init
+                       if (strcmp(a->value ? a->value : "", a->initialvalue ? a->initialvalue : ""))
+                       {
+                               Con_DPrintf("Cmd_RestoreInitState: Restoring alias %s\n", a->name);
+                               if (a->value)
+                                       Z_Free(a->value);
+                               a->value = Mem_strdup(zonemempool, a->initialvalue);
+                       }
+                       ap = &a->next;
+               }
+               else
+               {
+                       // free this alias, it didn't exist at init...
+                       Con_DPrintf("Cmd_RestoreInitState: Destroying alias %s\n", a->name);
+                       *ap = a->next;
+                       if (a->value)
+                               Z_Free(a->value);
+                       Z_Free(a);
+               }
+       }
+       Cvar_RestoreInitState();
+}