diff --git a/include/QF/cmd.h b/include/QF/cmd.h index e8a9b58c5..d50184f08 100644 --- a/include/QF/cmd.h +++ b/include/QF/cmd.h @@ -116,7 +116,7 @@ char *Cmd_CompleteAlias (char *partial); int Cmd_Argc (void); char *Cmd_Argv (int arg); -char *Cmd_Args (void); +char *Cmd_Args (int start); // The functions that execute commands get their parameters with these // functions. Cmd_Argv () will return an empty string, not a NULL // if arg > argc, so string operations are always safe. diff --git a/libs/util/cmd.c b/libs/util/cmd.c index d44386c73..6a0d89148 100644 --- a/libs/util/cmd.c +++ b/libs/util/cmd.c @@ -409,7 +409,7 @@ Cmd_Alias_f (void) } // copy the rest of the command line - cmd = malloc (strlen (Cmd_Args ()) + 2);// can never be longer + cmd = malloc (strlen (Cmd_Args (1)) + 2);// can never be longer cmd[0] = 0; // start out with a null string c = Cmd_Argc (); for (i = 2; i < c; i++) { @@ -468,7 +468,7 @@ typedef struct cmd_function_s { static int cmd_argc; static char *cmd_argv[MAX_ARGS]; static char *cmd_null_string = ""; -static char *cmd_args = NULL; +static char *cmd_args[MAX_ARGS]; @@ -500,11 +500,11 @@ Cmd_Argv (int arg) Returns a single string containing argv(1) to argv(argc()-1) */ char * -Cmd_Args (void) +Cmd_Args (int start) { - if (!cmd_args) + if (start >= cmd_argc || !cmd_args[start]) return ""; - return cmd_args; + return cmd_args[start]; } @@ -522,7 +522,7 @@ Cmd_TokenizeString (char *text) argv_idx = 0; cmd_argc = 0; - cmd_args = NULL; + memset (cmd_args, 0, sizeof (cmd_args)); while (1) { // skip whitespace up to a /n @@ -539,8 +539,8 @@ Cmd_TokenizeString (char *text) if (!*text) return; - if (cmd_argc == 1) - cmd_args = text; + if (cmd_argc < MAX_ARGS) + cmd_args[cmd_argc] = text; text = COM_Parse (text); if (!text) diff --git a/nq/source/cl_cmd.c b/nq/source/cl_cmd.c index d724c82e6..695c6fa66 100644 --- a/nq/source/cl_cmd.c +++ b/nq/source/cl_cmd.c @@ -64,7 +64,7 @@ Cmd_ForwardToServer (void) SZ_Print (&cls.message, " "); } if (Cmd_Argc () > 1) - SZ_Print (&cls.message, Cmd_Args ()); + SZ_Print (&cls.message, Cmd_Args (1)); else SZ_Print (&cls.message, "\n"); } diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index 822ada586..1d6d790bd 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -926,7 +926,7 @@ Host_Name_f (void) if (Cmd_Argc () == 2) newName = Cmd_Argv (1); else - newName = Cmd_Args (); + newName = Cmd_Args (1); newName[15] = 0; if (cmd_source == src_command) { @@ -985,7 +985,7 @@ Host_Say (qboolean teamonly) save = host_client; - p = Cmd_Args (); + p = Cmd_Args (1); // remove quotes if present if (*p == '"') { p++; @@ -1052,7 +1052,7 @@ Host_Tell_f (void) strcpy (text, host_client->name); strcat (text, ": "); - p = Cmd_Args (); + p = Cmd_Args (1); // remove quotes if present if (*p == '"') { @@ -1367,7 +1367,7 @@ Host_Kick_f (void) return; if (Cmd_Argc () > 2) { - message = COM_Parse (Cmd_Args ()); + message = COM_Parse (Cmd_Args (1)); if (byNumber) { message++; // skip the # while (*message == ' ') // skip white space diff --git a/qw/source/cl_cmd.c b/qw/source/cl_cmd.c index a65696f55..753a302e6 100644 --- a/qw/source/cl_cmd.c +++ b/qw/source/cl_cmd.c @@ -71,7 +71,7 @@ Cmd_ForwardToServer (void) !strcasecmp (Cmd_Argv (0), "say_team")) { char *s; - s = Team_ParseSay (Cmd_Args ()); + s = Team_ParseSay (Cmd_Args (1)); if (*s && *s < 32 && *s != 10) { // otherwise the server would eat leading characters // less than 32 or greater than 127 @@ -83,7 +83,7 @@ Cmd_ForwardToServer (void) return; } - SZ_Print (&cls.netchan.message, Cmd_Args ()); + SZ_Print (&cls.netchan.message, Cmd_Args (1)); } } @@ -107,7 +107,7 @@ Cmd_ForwardToServer_f (void) if (Cmd_Argc () > 1) { MSG_WriteByte (&cls.netchan.message, clc_stringcmd); - SZ_Print (&cls.netchan.message, Cmd_Args ()); + SZ_Print (&cls.netchan.message, Cmd_Args (1)); } } diff --git a/qw/source/sv_ccmds.c b/qw/source/sv_ccmds.c index 477547ac2..d4750ecbf 100644 --- a/qw/source/sv_ccmds.c +++ b/qw/source/sv_ccmds.c @@ -59,6 +59,46 @@ char fp_msg[255] = { 0 }; extern cvar_t *cl_warncmd; extern redirect_t sv_redirected; +qboolean +SV_Match_User (const char *substr, int *uidp) +{ + int i, j; + int count = 0; + char *str; + client_t *cl; + + if (!substr[0]) { + *uidp = 0; + Con_Printf ("Too many matches, ignoring command!\n"); + return false; + } + for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) { + if (!cl->state) + continue; + str = strchr (cl->name, substr[0]); + while (str) { + for (j = 0; substr[j] && str[j]; j++) + if (sys_char_map[(byte)substr[j]] != sys_char_map[(byte)str[j]]) + break; + if (!substr[j]) { // found a match; + *uidp = cl->userid; + count++; + Con_Printf ("User %04d matches with name: %s\n", + *uidp, cl->name); + str = 0; + } else { + str = strchr (str + 1, substr[0]); + } + } + } + if (count > 1) { + *uidp = 0; + Con_Printf ("Too many matches, ignoring command!\n"); + } + if (count) + return true; + return false; +} /* OPERATOR CONSOLE ONLY COMMANDS @@ -367,7 +407,16 @@ SV_Kick_f (void) client_t *cl; int uid; - uid = atoi (Cmd_Argv (1)); + if (Cmd_Argc () != 2) { + Con_Printf ("usage: kick \n"); + return; + } + if (SV_Match_User (Cmd_Argv(1), &uid)) { + if (!uid) + return; + } else { + uid = atoi (Cmd_Argv (1)); + } for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) { if (!cl->state) @@ -484,6 +533,51 @@ SV_Status_f (void) Con_Printf ("\n"); } +void +SV_Tell (const char *prefix) +{ + int i; + int uid; + client_t *cl; + char *p; + char text[512]; + + if (Cmd_Argc () < 3) { + Con_Printf ("usage: tell \n"); + return; + } + if (SV_Match_User (Cmd_Argv(1), &uid)) { + if (!uid) + return; + } else { + uid = atoi (Cmd_Argv(1)); + } + + p = Cmd_Args (2); + if (*p == '"') { + p++; + p[strlen (p) - 1] = 0; + } + // construct "[PRIVATE] Console> " + sprintf (text, "[\xd0\xd2\xc9\xd6\xc1\xd4\xc5] %s\x8d ", prefix); + i = strlen (text); + strncat (text, p, sizeof (text) - 1 - i); + text[sizeof (text) - 1] = 0; + for (; text[i];) + text[i++] |= 0x80; // non-bold text + for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) { + if (!cl->state) + continue; + if (cl->userid == uid) { + SV_ClientPrintf(cl, PRINT_CHAT, "\n"); // bell + SV_ClientPrintf(cl, PRINT_HIGH, "%s\n", text); + SV_ClientPrintf(cl, PRINT_CHAT, "%s", ""); // bell + return; + } + } + Con_Printf ("Couldn't find user %s\n", Cmd_Argv(1)); +} + void SV_ConSay (const char *prefix) { @@ -495,7 +589,7 @@ SV_ConSay (const char *prefix) if (Cmd_Argc () < 2) return; - p = Cmd_Args (); + p = Cmd_Args (1); if (*p == '"') { p++; p[strlen (p) - 1] = 0; @@ -516,6 +610,18 @@ SV_ConSay (const char *prefix) } } +/* + SV_Tell_f +*/ +void +SV_Tell_f (void) +{ + if (rcon_from_user) + SV_Tell("Admin"); + else + SV_Tell("Console"); +} + /* SV_ConSay_f */ @@ -901,12 +1007,12 @@ SV_InitOperatorCommands (void) Cmd_AddCommand ("maplist", COM_Maplist_f, "List all maps on the server"); - Cmd_AddCommand ("say", SV_ConSay_f, "Say something to everyone on the server, will show up as the name 'Console' (or 'Admin') in game"); - Cmd_AddCommand ("sayinfo", SV_ConSay_Info_f, "Say something to everyone on the server, will show up as the name 'Info' in game"); + Cmd_AddCommand ("say", SV_ConSay_f, "Say something to everyone on the server. Will show up as the name 'Console' (or 'Admin') in game"); + Cmd_AddCommand ("sayinfo", SV_ConSay_Info_f, "Say something to everyone on the server. Will show up as the name 'Info' in game"); + Cmd_AddCommand ("tell", SV_Tell_f, "Say something to a specific user on the server. Will show up as the name 'Console' (or 'Admin') in game"); + //XXX Cmd_AddCommand ("ban", SV_Ban_f); //XXX Cmd_AddCommand ("cuff", SV_Cuff_f); //XXX Cmd_AddCommand ("mute", SV_Mute_f); - //XXX Cmd_AddCommand ("tell", SV_Tell_f); - //XXX Cmd_AddCommand ("ban", SV_Ban_f); cl_warncmd = Cvar_Get ("cl_warncmd", "1", CVAR_NONE, NULL, diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index f1732ca80..f5ef73588 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -810,7 +810,7 @@ SV_Say (qboolean team) host_client->whensaid[host_client->whensaidhead] = realtime; } - p = Cmd_Args (); + p = Cmd_Args (1); if (*p == '"') { p++; @@ -844,7 +844,6 @@ SV_Say (qboolean team) } } - /* SV_Say_f */ diff --git a/qw/source/teamplay.c b/qw/source/teamplay.c index deb17e69d..4ea860f35 100644 --- a/qw/source/teamplay.c +++ b/qw/source/teamplay.c @@ -361,7 +361,7 @@ locs_loc (void) return; } if (Cmd_Argc () >= 3) - desc = Cmd_Args () + strlen(Cmd_Argv(1)) + 1; + desc = Cmd_Args (2); mapname = malloc(sizeof(cl.worldmodel->name)); if (!mapname) Sys_Error ("Can't duplicate mapname!"); diff --git a/tools/qwaq/main.c b/tools/qwaq/main.c index 1749833d7..146ebd331 100644 --- a/tools/qwaq/main.c +++ b/tools/qwaq/main.c @@ -75,7 +75,6 @@ main () printf (" %d", func->parm_size[j]); printf ("\n"); } -#if 0 printf ("\n"); for (i = 0; i < progs.progs->numglobaldefs; i++) { ddef_t *def = &progs.pr_globaldefs[i]; @@ -83,6 +82,7 @@ main () printf ("%s %d %d %s\n", type_name[def->type & ~DEF_SAVEGLOBAL], (def->type & DEF_SAVEGLOBAL) != 0, def->ofs, PR_GetString (&progs, def->s_name)); } printf ("\n"); +#if 0 for (i = 0; i < progs.progs->numfielddefs; i++) { ddef_t *def = &progs.pr_fielddefs[i]; diff --git a/tools/qwaq/main.qc b/tools/qwaq/main.qc index 71913cdfe..a6329ee43 100644 --- a/tools/qwaq/main.qc +++ b/tools/qwaq/main.qc @@ -63,3 +63,59 @@ void () eek = self.origin = self.origin + '1 2 3'; traceoff(); }; + +.string classname; +.string netname; +float (entity tester) IsBuilding = +{ + if ( + tester.classname == "building_sentrygun" || + tester.classname == "building_sentrygun_base" || + tester.classname == "building_tesla" || + tester.classname == "building_dispenser" || + tester.classname == "building_camera" || + tester.classname == "building_arawana" || + tester.classname == "building_teleporter"|| + tester.classname == "building_fieldgen"|| + tester.classname == "building_sensor" + ) + return 1; + return 0; +}; +float(entity thing) IsMonster = +{ + if (thing.classname=="monster_shambler") + return 1; + if (thing.classname=="monster_demon1") + return 1; + if (thing.classname=="monster_wizard") + return 1; + if (thing.classname=="monster_army") + return 1; + + if (thing.classname=="monster_knight") + return 1; + if (thing.classname=="monster_hknight") + return 1; + + return 0; +}; +string(entity thething) GetEnemyName = +{ + if (thething.classname == "player") + return thething.netname; + + if (IsMonster(thething)) + return ""; + + if (IsBuilding(thething)) + return ""; + + if (thething.classname == "grenade" && thething.netname == "land_mine") + return "land mine"; + + if (thething.classname != "") + return thething.classname; + + return "unknown stuff"; +};