]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cmd.c
added clearstencil parameter to R_Shadow_RenderMode_StencilShadowVolumes
[xonotic/darkplaces.git] / cmd.c
diff --git a/cmd.c b/cmd.c
index a59a46f6189e86fe3ed91c5ee282f31100ec107a..82a98ae5e56dc947e22bffcc9760781804536266 100644 (file)
--- a/cmd.c
+++ b/cmd.c
@@ -216,7 +216,7 @@ qboolean host_stuffcmdsrun = false;
 void Cmd_StuffCmds_f (void)
 {
        int             i, j, l;
-       // this is per command, and bounds checked (no buffer overflows)
+       // this is for all commandline options combined (and is bounds checked)
        char    build[MAX_INPUTLINE];
 
        if (Cmd_Argc () != 1)
@@ -230,11 +230,12 @@ void Cmd_StuffCmds_f (void)
                return;
 
        host_stuffcmdsrun = true;
+       build[0] = 0;
+       l = 0;
        for (i = 0;i < com_argc;i++)
        {
-               if (com_argv[i] && com_argv[i][0] == '+' && (com_argv[i][1] < '0' || com_argv[i][1] > '9'))
+               if (com_argv[i] && com_argv[i][0] == '+' && (com_argv[i][1] < '0' || com_argv[i][1] > '9') && l + strlen(com_argv[i]) - 1 <= sizeof(build) - 1)
                {
-                       l = 0;
                        j = 1;
                        while (com_argv[i][j])
                                build[l++] = com_argv[i][j++];
@@ -245,20 +246,24 @@ void Cmd_StuffCmds_f (void)
                                        continue;
                                if ((com_argv[i][0] == '+' || com_argv[i][0] == '-') && (com_argv[i][1] < '0' || com_argv[i][1] > '9'))
                                        break;
-                               if (l + strlen(com_argv[i]) + 5 > sizeof(build))
+                               if (l + strlen(com_argv[i]) + 4 > sizeof(build) - 1)
                                        break;
                                build[l++] = ' ';
-                               build[l++] = '\"';
+                               if (strchr(com_argv[i], ' '))
+                                       build[l++] = '\"';
                                for (j = 0;com_argv[i][j];j++)
                                        build[l++] = com_argv[i][j];
-                               build[l++] = '\"';
+                               if (strchr(com_argv[i], ' '))
+                                       build[l++] = '\"';
                        }
                        build[l++] = '\n';
-                       build[l++] = 0;
-                       Cbuf_InsertText (build);
                        i--;
                }
        }
+       // now terminate the combined string and prepend it to the command buffer
+       // we already reserved space for the terminator
+       build[l++] = 0;
+       Cbuf_InsertText (build);
 }
 
 
@@ -1164,6 +1169,7 @@ Sends an entire command string over to the server, unprocessed
 */
 void Cmd_ForwardStringToServer (const char *s)
 {
+       char temp[128];
        if (cls.state != ca_connected)
        {
                Con_Printf("Can't \"%s\", not connected\n", s);
@@ -1180,7 +1186,105 @@ void Cmd_ForwardStringToServer (const char *s)
                MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
        else
                MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
-       SZ_Write(&cls.netcon->message, (const unsigned char *)s, (int)strlen(s) + 1);
+       if ((!strncmp(s, "say ", 4) || !strncmp(s, "say_team ", 9)) && cl_locs_enable.integer)
+       {
+               // say/say_team commands can replace % character codes with status info
+               while (*s)
+               {
+                       if (*s == '%' && s[1])
+                       {
+                               // handle proquake message macros
+                               temp[0] = 0;
+                               switch (s[1])
+                               {
+                               case 'l': // current location
+                                       CL_Locs_FindLocationName(temp, sizeof(temp), cl.movement_origin);
+                                       break;
+                               case 'h': // current health
+                                       dpsnprintf(temp, sizeof(temp), "%i", cl.stats[STAT_HEALTH]);
+                                       break;
+                               case 'a': // current armor
+                                       dpsnprintf(temp, sizeof(temp), "%i", cl.stats[STAT_ARMOR]);
+                                       break;
+                               case 'x': // current rockets
+                                       dpsnprintf(temp, sizeof(temp), "%i", cl.stats[STAT_ROCKETS]);
+                                       break;
+                               case 'c': // current cells
+                                       dpsnprintf(temp, sizeof(temp), "%i", cl.stats[STAT_CELLS]);
+                                       break;
+                               // silly proquake macros
+                               case 'd': // loc at last death
+                                       CL_Locs_FindLocationName(temp, sizeof(temp), cl.lastdeathorigin);
+                                       break;
+                               case 't': // current time
+                                       dpsnprintf(temp, sizeof(temp), "%.0f:%.0f", floor(cl.time / 60), cl.time - floor(cl.time / 60) * 60);
+                                       break;
+                               case 'r': // rocket launcher status ("I have RL", "I need rockets", "I need RL")
+                                       if (!(cl.stats[STAT_ITEMS] & IT_ROCKET_LAUNCHER))
+                                               dpsnprintf(temp, sizeof(temp), "I need RL");
+                                       else if (!cl.stats[STAT_ROCKETS])
+                                               dpsnprintf(temp, sizeof(temp), "I need rockets");
+                                       else
+                                               dpsnprintf(temp, sizeof(temp), "I have RL");
+                                       break;
+                               case 'p': // powerup status (outputs "quad" "pent" and "eyes" according to status)
+                                       if (cl.stats[STAT_ITEMS] & IT_QUAD)
+                                       {
+                                               if (temp[0])
+                                                       strlcat(temp, " ", sizeof(temp));
+                                               strlcat(temp, "quad", sizeof(temp));
+                                       }
+                                       if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
+                                       {
+                                               if (temp[0])
+                                                       strlcat(temp, " ", sizeof(temp));
+                                               strlcat(temp, "pent", sizeof(temp));
+                                       }
+                                       if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
+                                       {
+                                               if (temp[0])
+                                                       strlcat(temp, " ", sizeof(temp));
+                                               strlcat(temp, "eyes", sizeof(temp));
+                                       }
+                                       break;
+                               case 'w': // weapon status (outputs "SSG:NG:SNG:GL:RL:LG" with the text between : characters omitted if you lack the weapon)
+                                       if (cl.stats[STAT_ITEMS] & IT_SUPER_SHOTGUN)
+                                               strlcat(temp, "SSG", sizeof(temp));
+                                       strlcat(temp, ":", sizeof(temp));
+                                       if (cl.stats[STAT_ITEMS] & IT_NAILGUN)
+                                               strlcat(temp, "NG", sizeof(temp));
+                                       strlcat(temp, ":", sizeof(temp));
+                                       if (cl.stats[STAT_ITEMS] & IT_SUPER_NAILGUN)
+                                               strlcat(temp, "SNG", sizeof(temp));
+                                       strlcat(temp, ":", sizeof(temp));
+                                       if (cl.stats[STAT_ITEMS] & IT_GRENADE_LAUNCHER)
+                                               strlcat(temp, "GL", sizeof(temp));
+                                       strlcat(temp, ":", sizeof(temp));
+                                       if (cl.stats[STAT_ITEMS] & IT_ROCKET_LAUNCHER)
+                                               strlcat(temp, "RL", sizeof(temp));
+                                       strlcat(temp, ":", sizeof(temp));
+                                       if (cl.stats[STAT_ITEMS] & IT_LIGHTNING)
+                                               strlcat(temp, "LG", sizeof(temp));
+                                       break;
+                               default:
+                                       // not a recognized macro, print it as-is...
+                                       temp[0] = s[0];
+                                       temp[1] = s[1];
+                                       temp[2] = 0;
+                                       break;
+                               }
+                               // write the resulting text
+                               SZ_Write(&cls.netcon->message, (unsigned char *)temp, strlen(temp));
+                               s += 2;
+                               continue;
+                       }
+                       MSG_WriteByte(&cls.netcon->message, *s);
+                       s++;
+               }
+               MSG_WriteByte(&cls.netcon->message, 0);
+       }
+       else // any other command is passed on as-is
+               SZ_Write(&cls.netcon->message, (const unsigned char *)s, (int)strlen(s) + 1);
 }
 
 /*