static void CL_RE_Trigger_Match_f (void) { int c; char *tr_name; char *s; pcre_trigger_t *rt; char *string; int result; int offsets[99]; c = Cmd_Argc(); if (c != 3) { Com_Printf ("re_trigger_match <trigger name> <string>\n"); return; } tr_name = Cmd_Argv(1); s = Cmd_Argv(2); for (rt = re_triggers; rt; rt = rt->next) if (!strcmp(rt->name, tr_name)) { result = pcre_exec (rt->regexp, rt->regexp_extra, s, strlen(s), 0, 0, offsets, 99); if (result >= 0) { rt->lasttime = cls.realtime; rt->counter++; Re_Trigger_Copy_Subpatterns (s, offsets, min (result,10), re_sub); if (!(rt->flags & RE_NOACTION)) { string = Cmd_AliasString (rt->name); if (string) { Cbuf_InsertTextEx (&cbuf_safe, "\nwait\n"); Cbuf_InsertTextEx (&cbuf_safe, string); Cbuf_ExecuteEx (&cbuf_safe); } else { Com_Printf ("re_trigger \"%s\" has no matching alias\n", rt->name); } } } return; } Com_Printf ("re_trigger \"%s\" not found\n", tr_name); }
qbool CL_SearchForReTriggers (const char *s, unsigned trigger_type) { pcre_trigger_t *rt; pcre_internal_trigger_t *irt; cmd_alias_t *trig_alias; qbool removestr = false; int result; int offsets[99]; int len = strlen(s); // internal triggers - always enabled if (trigger_type < RE_PRINT_ECHO) { allow_re_triggers = true; for (irt = internal_triggers; irt; irt = irt->next) { if (irt->flags & trigger_type) { result = pcre_exec (irt->regexp, irt->regexp_extra, s, len, 0, 0, offsets, 99); if (result >= 0) { Re_Trigger_Copy_Subpatterns (s, offsets, min(result,10), re_subi); irt->func (s); } } } if (!allow_re_triggers) return false; } // message triggers disabled if (!tp_msgtriggers.value) return false; // triggers banned by ruleset or FPD and we are a player if (((cl.fpd & FPD_NO_SOUNDTRIGGERS) || (cl.fpd & FPD_NO_TIMERS) || Rulesets_RestrictTriggers ()) && !cls.demoplayback && !cl.spectator) return false; // we are in spec/demo mode, so play triggers if user want it if ((cls.demoplayback || cl.spectator) && cl_restrictions.value) return false; // regexp triggers for (rt = re_triggers; rt; rt = rt->next) if ( (rt->flags & RE_ENABLED) && // enabled (rt->flags & trigger_type) && // mask fits rt->regexp && // regexp not empty (rt->min_interval == 0.0 || cls.realtime >= rt->min_interval + rt->lasttime)) // not too fast. // TODO: disable it ^^^ for FPD_NO_TIMERS case. // probably it dont solve re_trigger timers problem // you always trigger on statusbar(TF) or wp_stats (KTPro/KTX) messages and get 0.5~1.5 accuracy for your timer { result = pcre_exec (rt->regexp, rt->regexp_extra, s, len, 0, 0, offsets, 99); if (result >= 0) { rt->lasttime = cls.realtime; rt->counter++; Re_Trigger_Copy_Subpatterns (s, offsets, min(result,10), re_sub); if (!(rt->flags & RE_NOACTION)) { trig_alias = Cmd_FindAlias (rt->name); Print_current++; if (trig_alias) { Cbuf_InsertTextEx (&cbuf_safe, "\nwait\n"); Cbuf_InsertTextEx (&cbuf_safe, rt->name); Cbuf_ExecuteEx (&cbuf_safe); } else Com_Printf ("re_trigger \"%s\" has no matching alias\n", rt->name); Print_current--; } if (rt->flags & RE_REMOVESTR) removestr = true; if (rt->flags & RE_NOLOG) Print_flags[Print_current] |= PR_LOG_SKIP; if (rt->flags & RE_FINAL) break; } } if (removestr) Print_flags[Print_current] |= PR_SKIP; return removestr; }
/* ================ Cmd_If_f ================ */ void Cmd_If_f (void) { int i, c; char *op; qbool result; char buf[256]; c = Cmd_Argc (); if (c < 5) { Com_Printf ("usage: if <expr1> <op> <expr2> <command> [else <command>]\n"); return; } op = Cmd_Argv (2); if (!strcmp(op, "==") || !strcmp(op, "=") || !strcmp(op, "!=") || !strcmp(op, "<>")) { if (is_numeric(Cmd_Argv(1)) && is_numeric(Cmd_Argv(3))) result = Q_atof(Cmd_Argv(1)) == Q_atof(Cmd_Argv(3)); else result = !strcmp(Cmd_Argv(1), Cmd_Argv(3)); if (op[0] != '=') result = !result; } else if (!strcmp(op, ">")) result = Q_atof(Cmd_Argv(1)) > Q_atof(Cmd_Argv(3)); else if (!strcmp(op, "<")) result = Q_atof(Cmd_Argv(1)) < Q_atof(Cmd_Argv(3)); else if (!strcmp(op, ">=")) result = Q_atof(Cmd_Argv(1)) >= Q_atof(Cmd_Argv(3)); else if (!strcmp(op, "<=")) result = Q_atof(Cmd_Argv(1)) <= Q_atof(Cmd_Argv(3)); else if (!strcmp(op, "isin")) result = strstr(Cmd_Argv(3), Cmd_Argv(1)) != NULL; else if (!strcmp(op, "!isin")) result = strstr(Cmd_Argv(3), Cmd_Argv(1)) == NULL; else { Com_Printf ("unknown operator: %s\n", op); Com_Printf ("valid operators are ==, =, !=, <>, >, <, >=, <=, isin, !isin\n"); return; } buf[0] = '\0'; if (result) { for (i=4; i < c ; i++) { if ((i == 4) && !Q_stricmp(Cmd_Argv(i), "then")) continue; if (!Q_stricmp(Cmd_Argv(i), "else")) break; if (buf[0]) strcat (buf, " "); strcat (buf, Cmd_Argv(i)); } } else { for (i=4; i < c ; i++) { if (!Q_stricmp(Cmd_Argv(i), "else")) break; } if (i == c) return; for (i++ ; i < c ; i++) { if (buf[0]) strcat (buf, " "); strcat (buf, Cmd_Argv(i)); } } strcat (buf, "\n"); if (!cbuf_current) cbuf_current = &cbuf_main; Cbuf_InsertTextEx (cbuf_current, buf); }
void Cbuf_InsertText (const char *text) { Cbuf_InsertTextEx (&cbuf_main, text); }
/* ============ Cmd_ExecuteString A complete command line has been parsed, so try to execute it FIXME: this function is getting really messy... ============ */ void Cmd_ExecuteString (char *text) { cmd_function_t *cmd; cmd_alias_t *a; int key; static char buf[1024]; cbuf_t *inserttarget; #ifndef SERVERONLY char **s; #endif Cmd_ExpandString (text, buf); Cmd_TokenizeString (buf); // execute the command line if (!Cmd_Argc()) return; // no tokens inserttarget = &cbuf_main; #ifndef SERVERONLY if (cbuf_current == &cbuf_safe) inserttarget = &cbuf_safe; if (cbuf_current == &cbuf_svc) { if (CL_CheckServerCommand()) return; } #endif key = Com_HashKey (cmd_argv[0]); // check functions for (cmd=cmd_hash_array[key] ; cmd ; cmd=cmd->hash_next) { if (!Q_stricmp (cmd_argv[0], cmd->name)) { #ifndef SERVERONLY // special check for msg_trigger commands if (cbuf_current == &cbuf_safe) { for (s = safe_commands; *s; s++) { if (!Q_stricmp(cmd_argv[0], *s)) break; } if (!*s) { if (cl_warncmd.value || developer.value) Com_Printf ("\"%s\" cannot be used in message triggers\n", cmd_argv[0]); return; } } #endif if (cmd->function) cmd->function (); else Cmd_ForwardToServer (); return; } } // some bright guy decided to use "skill" as a mod command in Custom TF, sigh if (!strcmp(Cmd_Argv(0), "skill") && Cmd_Argc() == 1 && Cmd_FindAlias("skill")) goto checkaliases; // check cvars if (Cvar_Command()) return; // check alias checkaliases: for (a=cmd_alias_hash[key] ; a ; a=a->hash_next) { if (!Q_stricmp (cmd_argv[0], a->name)) { #ifndef SERVERONLY if (cbuf_current == &cbuf_svc) { Cbuf_AddText (a->value); Cbuf_AddText ("\n"); } else #endif { Cbuf_InsertTextEx (inserttarget, "\n"); // if the alias value is a command or cvar and // the alias is called with parameters, add them if (Cmd_Argc() > 1 && !strchr(a->value, ' ') && !strchr(a->value, '\t') && (Cvar_FindVar(a->value) || (Cmd_FindCommand(a->value) && a->value[0] != '+' && a->value[0] != '-'))) { Cbuf_InsertTextEx (inserttarget, Cmd_Args()); Cbuf_InsertTextEx (inserttarget, " "); } Cbuf_InsertTextEx (inserttarget, a->value); } return; } } if (Cmd_LegacyCommand()) return; if (!host_initialized && Cmd_Argc() > 1) { if (Cvar_CreateTempVar()) return; } #ifndef SERVERONLY if (cbuf_current != &cbuf_svc) #endif if (cl_warncmd.value || developer.value) Com_Printf ("Unknown command \"%s\"\n", Cmd_Argv(0)); }