From: terencehill Date: Wed, 6 Sep 2017 16:36:50 +0000 (+0200) Subject: Merge branch 'master' into terencehill/bot_waypoints X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=commitdiff_plain;h=678127044857fb9b89f06faf7a3313bdeb43205c;hp=-c Merge branch 'master' into terencehill/bot_waypoints --- 678127044857fb9b89f06faf7a3313bdeb43205c diff --combined qcsrc/server/command/sv_cmd.qc index 43ce29160,f5569c08f..6de4507b1 --- a/qcsrc/server/command/sv_cmd.qc +++ b/qcsrc/server/command/sv_cmd.qc @@@ -1095,9 -1095,15 +1095,15 @@@ void GameCommand_moveplayer(float reque // If so, lets continue and finally move the player client.team_forced = 0; - MoveToTeam(client, team_id, 6); - successful = strcat(successful, (successful ? ", " : ""), playername(client, false)); - LOG_INFO("Player ", ftos(GetFilteredNumber(t)), " (", playername(client, false), ") has been moved to the ", Team_ColoredFullName(team_id), "^7."); + if (MoveToTeam(client, team_id, 6)) + { + successful = strcat(successful, (successful ? ", " : ""), playername(client, false)); + LOG_INFO("Player ", ftos(GetFilteredNumber(t)), " (", playername(client, false), ") has been moved to the ", Team_ColoredFullName(team_id), "^7."); + } + else + { + LOG_INFO("Unable to move player ", ftos(GetFilteredNumber(t)), " (", playername(client, false), ")"); + } continue; } else @@@ -1568,13 -1574,11 +1574,13 @@@ void GameCommand_trace(float request, f case "walk": { - if (argc == 4) + if (argc == 4 || argc == 5) { e = nextent(NULL); - if (tracewalk(e, stov(argv(2)), e.mins, e.maxs, stov(argv(3)), MOVE_NORMAL)) LOG_INFO("can walk"); - else LOG_INFO("cannot walk"); + if (tracewalk(e, stov(argv(2)), e.mins, e.maxs, stov(argv(3)), stof(argv(4)), MOVE_NORMAL)) + LOG_INFO("can walk"); + else + LOG_INFO("cannot walk"); return; } } @@@ -1600,9 -1604,7 +1606,9 @@@ LOG_INFO("Incorrect parameters for ^2trace^7"); case CMD_REQUEST_USAGE: { - LOG_INFO("Usage:^3 sv_cmd trace command (startpos endpos)"); + LOG_INFO("Usage:^3 sv_cmd trace command [startpos endpos] [endpos_height]"); + LOG_INFO(" Where startpos and endpos are parameters for 'walk' and 'showline' commands,"); + LOG_INFO(" 'endpos_height' is an optional parameter for 'walk' command,"); LOG_INFO(" Full list of commands here: \"debug, debug2, walk, showline.\""); LOG_INFO("See also: ^2bbox, gettaginfo^7"); return; diff --combined qcsrc/server/sv_main.qc index fcae79ea6,68e7b375b..34f3cdc21 --- a/qcsrc/server/sv_main.qc +++ b/qcsrc/server/sv_main.qc @@@ -217,6 -217,8 +217,6 @@@ void StartFrame( if (timeout_status == TIMEOUT_LEADTIME) // just before the timeout (when timeout_status will be TIMEOUT_ACTIVE) orig_slowmo = autocvar_slowmo; // slowmo will be restored after the timeout - skill = autocvar_skill; - // detect when the pre-game countdown (if any) has ended and the game has started bool game_delay = (time < game_starttime); if (autocvar_sv_eventlog && game_delay_last && !game_delay) @@@ -245,6 -247,77 +245,77 @@@ .string gametypefilter; .string cvarfilter; bool DoesQ3ARemoveThisEntity(entity this); + + /** + * Evaluate an expression of the form: [+ | -]? [var[op]val | [op]var | val | var] ... + * +: all must match. this is the default + * -: one must NOT match + * + * var>x + * var=x + * var<=x + * var==x + * var!=x + * var===x + * var!==x + */ + bool expr_evaluate(string s) + { + bool ret = false; + if (str2chr(s, 0) == '+') { + s = substring(s, 1, -1); + } else if (str2chr(s, 0) == '-') { + ret = true; + s = substring(s, 1, -1); + } + bool expr_fail = false; + for (int i = 0, n = tokenize_console(s); i < n; ++i) { + int o; + string k, v; + s = argv(i); + #define X(expr) \ + if (expr) { \ + continue; \ + } else { \ + expr_fail = true; \ + break; \ + } + #define BINOP(op, len, expr) \ + if ((o = strstrofs(s, op, 0)) >= 0) { \ + k = substring(s, 0, o); \ + v = substring(s, o + len, -1); \ + X(expr); \ + } + BINOP(">=", 2, cvar(k) >= stof(v)); + BINOP("<=", 2, cvar(k) <= stof(v)); + BINOP(">", 1, cvar(k) > stof(v)); + BINOP("<", 1, cvar(k) < stof(v)); + BINOP("==", 2, cvar(k) == stof(v)); + BINOP("!=", 2, cvar(k) != stof(v)); + BINOP("===", 3, cvar_string(k) == v); + BINOP("!==", 3, cvar_string(k) != v); + { + k = s; + bool b = true; + if (str2chr(k, 0) == '!') { + k = substring(s, 1, -1); + b = false; + } + float f = stof(k); + bool isnum = ftos(f) == k; + X(boolean(isnum ? f : cvar(k)) == b); + } + #undef BINOP + #undef X + } + if (!expr_fail) { + ret = !ret; + } + // now ret is true if we want to keep the item, and false if we want to get rid of it + return ret; + } + void SV_OnEntityPreSpawnFunction(entity this) { __spawnfunc_expecting = true; @@@ -253,168 -326,49 +324,52 @@@ if (this.gametypefilter != "") if (!isGametypeInFilter(MapInfo_LoadedGametype, teamplay, have_team_spawns, this.gametypefilter)) { - delete(this); - __spawnfunc_expecting = false; - return; + goto cleanup; } - if(this.cvarfilter != "") - { - float n, i, o, inv; - string s, k, v; - inv = 0; - - s = this.cvarfilter; - if(substring(s, 0, 1) == "+") - { - s = substring(s, 1, -1); - } - else if(substring(s, 0, 1) == "-") - { - inv = 1; - s = substring(s, 1, -1); - } - - n = tokenize_console(s); - for(i = 0; i < n; ++i) - { - s = argv(i); - // syntax: - // var>x - // var=x - // var<=x - // var==x - // var!=x - // var===x - // var!==x - if((o = strstrofs(s, ">=", 0)) >= 0) - { - k = substring(s, 0, o); - v = substring(s, o+2, -1); - if(cvar(k) < stof(v)) - goto cvar_fail; - } - else if((o = strstrofs(s, "<=", 0)) >= 0) - { - k = substring(s, 0, o); - v = substring(s, o+2, -1); - if(cvar(k) > stof(v)) - goto cvar_fail; - } - else if((o = strstrofs(s, ">", 0)) >= 0) - { - k = substring(s, 0, o); - v = substring(s, o+1, -1); - if(cvar(k) <= stof(v)) - goto cvar_fail; - } - else if((o = strstrofs(s, "<", 0)) >= 0) - { - k = substring(s, 0, o); - v = substring(s, o+1, -1); - if(cvar(k) >= stof(v)) - goto cvar_fail; - } - else if((o = strstrofs(s, "==", 0)) >= 0) - { - k = substring(s, 0, o); - v = substring(s, o+2, -1); - if(cvar(k) != stof(v)) - goto cvar_fail; - } - else if((o = strstrofs(s, "!=", 0)) >= 0) - { - k = substring(s, 0, o); - v = substring(s, o+2, -1); - if(cvar(k) == stof(v)) - goto cvar_fail; - } - else if((o = strstrofs(s, "===", 0)) >= 0) - { - k = substring(s, 0, o); - v = substring(s, o+2, -1); - if(cvar_string(k) != v) - goto cvar_fail; - } - else if((o = strstrofs(s, "!==", 0)) >= 0) - { - k = substring(s, 0, o); - v = substring(s, o+2, -1); - if(cvar_string(k) == v) - goto cvar_fail; - } - else if(substring(s, 0, 1) == "!") - { - k = substring(s, 1, -1); - if(cvar(k)) - goto cvar_fail; - } - else - { - k = s; - if (!cvar(k)) - goto cvar_fail; - } - } - inv = !inv; - LABEL(cvar_fail) - // now inv is 1 if we want to keep the item, and 0 if we want to get rid of it - if (!inv) - { - //print("cvarfilter fail\n"); - delete(this); - __spawnfunc_expecting = false; - return; - } + if (this.cvarfilter != "" && !expr_evaluate(this.cvarfilter)) { + goto cleanup; } - if(DoesQ3ARemoveThisEntity(this)) - { - delete(this); - __spawnfunc_expecting = false; - return; + if (DoesQ3ARemoveThisEntity(this)) { + goto cleanup; } set_movetype(this, this.movetype); - if(this.monster_attack) + if (this.monster_attack) { IL_PUSH(g_monster_targets, this); + } // support special -1 and -2 angle from radiant - if (this.angles == '0 -1 0') + if (this.angles == '0 -1 0') { this.angles = '-90 0 0'; - else if (this.angles == '0 -2 0') + } else if (this.angles == '0 -2 0') { this.angles = '+90 0 0'; - - if(this.originjitter.x != 0) - this.origin_x = this.origin.x + (random() * 2 - 1) * this.originjitter.x; - if(this.originjitter.y != 0) - this.origin_y = this.origin.y + (random() * 2 - 1) * this.originjitter.y; - if(this.originjitter.z != 0) - this.origin_z = this.origin.z + (random() * 2 - 1) * this.originjitter.z; - if(this.anglesjitter.x != 0) - this.angles_x = this.angles.x + (random() * 2 - 1) * this.anglesjitter.x; - if(this.anglesjitter.y != 0) - this.angles_y = this.angles.y + (random() * 2 - 1) * this.anglesjitter.y; - if(this.anglesjitter.z != 0) - this.angles_z = this.angles.z + (random() * 2 - 1) * this.anglesjitter.z; - if(this.anglejitter != 0) - this.angles_y = this.angles.y + (random() * 2 - 1) * this.anglejitter; - - if(MUTATOR_CALLHOOK(OnEntityPreSpawn, this)) - { - delete(this); - __spawnfunc_expecting = false; - return; + } + + #define X(out, in) MACRO_BEGIN \ + if (in != 0) { out = out + (random() * 2 - 1) * in; } \ + MACRO_END + X(this.origin.x, this.originjitter.x); X(this.origin.y, this.originjitter.y); X(this.origin.z, this.originjitter.z); + X(this.angles.x, this.anglesjitter.x); X(this.angles.y, this.anglesjitter.y); X(this.angles.z, this.anglesjitter.z); + X(this.angles.y, this.anglejitter); + #undef X + + if (MUTATOR_CALLHOOK(OnEntityPreSpawn, this)) { + goto cleanup; } + return; + LABEL(cleanup) + builtin_remove(this); + __spawnfunc_expecting = false; } void WarpZone_PostInitialize_Callback() { // create waypoint links for warpzones + entity tracetest_ent = spawn(); + setsize(tracetest_ent, PL_MIN_CONST, PL_MAX_CONST); + tracetest_ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP; //for(entity e = warpzone_first; e; e = e.warpzone_next) for(entity e = NULL; (e = find(e, classname, "trigger_warpzone")); ) { @@@ -425,7 -379,6 +380,7 @@@ dst = (e.enemy.absmin + e.enemy.absmax) * 0.5; makevectors(e.enemy.warpzone_angles); dst = dst + ((e.enemy.warpzone_origin - dst) * v_forward) * v_forward - 16 * v_right; - waypoint_spawnforteleporter_v(e, src, dst, 0); + waypoint_spawnforteleporter_wz(e, src, dst, 0, -v_up, tracetest_ent); } + delete(tracetest_ent); }