From: bones_was_here Date: Fri, 25 Sep 2020 11:34:16 +0000 (+1000) Subject: Merge branch 'master' into bones_was_here/q3compat X-Git-Tag: xonotic-v0.8.5~352^2~25 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=dc02e4d78fb0e67b47a0c1e150b4c18c0711b8bf;p=xonotic%2Fxonotic-data.pk3dir.git Merge branch 'master' into bones_was_here/q3compat --- dc02e4d78fb0e67b47a0c1e150b4c18c0711b8bf diff --cc qcsrc/server/miscfunctions.qc index 7da78ca02,d45131837..f910b9f91 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@@ -1210,178 -317,3 +317,59 @@@ float MoveToRandomMapLocation(entity e { return MoveToRandomLocationWithinBounds(e, world.mins, world.maxs, goodcontents, badcontents, badsurfaceflags, attempts, maxaboveground, minviewdistance); } + - void write_recordmarker(entity pl, float tstart, float dt) - { - GameLogEcho(strcat(":recordset:", ftos(pl.playerid), ":", ftos(dt))); - - // also write a marker into demo files for demotc-race-record-extractor to find - stuffcmd(pl, - strcat( - strcat("//", strconv(2, 0, 0, GetGametype()), " RECORD SET ", TIME_ENCODED_TOSTRING(TIME_ENCODE(dt))), - " ", ftos(tstart), " ", ftos(dt), "\n")); - } - - void attach_sameorigin(entity e, entity to, string tag) - { - vector org, t_forward, t_left, t_up, e_forward, e_up; - float tagscale; - - org = e.origin - gettaginfo(to, gettagindex(to, tag)); - tagscale = (vlen(v_forward) ** -2); // undo a scale on the tag - t_forward = v_forward * tagscale; - t_left = v_right * -tagscale; - t_up = v_up * tagscale; - - e.origin_x = org * t_forward; - e.origin_y = org * t_left; - e.origin_z = org * t_up; - - // current forward and up directions - if (substring(e.model, 0, 1) == "*") // bmodels have their own rules - e.angles = AnglesTransform_FromVAngles(e.angles); - else - e.angles = AnglesTransform_FromAngles(e.angles); - fixedmakevectors(e.angles); - - // untransform forward, up! - e_forward.x = v_forward * t_forward; - e_forward.y = v_forward * t_left; - e_forward.z = v_forward * t_up; - e_up.x = v_up * t_forward; - e_up.y = v_up * t_left; - e_up.z = v_up * t_up; - - e.angles = fixedvectoangles2(e_forward, e_up); - if (substring(e.model, 0, 1) == "*") // bmodels have their own rules - e.angles = AnglesTransform_ToVAngles(e.angles); - else - e.angles = AnglesTransform_ToAngles(e.angles); - - setattachment(e, to, tag); - setorigin(e, e.origin); - } - - void detach_sameorigin(entity e) - { - vector org; - org = gettaginfo(e, 0); - e.angles = fixedvectoangles2(v_forward, v_up); - if (substring(e.model, 0, 1) == "*") // bmodels have their own rules - e.angles = AnglesTransform_ToVAngles(e.angles); - else - e.angles = AnglesTransform_ToAngles(e.angles); - setorigin(e, org); - setattachment(e, NULL, ""); - setorigin(e, e.origin); - } - - void follow_sameorigin(entity e, entity to) - { - set_movetype(e, MOVETYPE_FOLLOW); // make the hole follow - e.aiment = to; // make the hole follow bmodel - e.punchangle = to.angles; // the original angles of bmodel - e.view_ofs = e.origin - to.origin; // relative origin - e.v_angle = e.angles - to.angles; // relative angles - } - - #if 0 - // TODO: unused, likely for a reason, possibly needs extensions (allow setting the new movetype as a parameter?) - void unfollow_sameorigin(entity e) - { - set_movetype(e, MOVETYPE_NONE); - } - #endif - - .string aiment_classname; - .float aiment_deadflag; - void SetMovetypeFollow(entity ent, entity e) - { - // FIXME this may not be warpzone aware - set_movetype(ent, MOVETYPE_FOLLOW); // make the hole follow - ent.solid = SOLID_NOT; // MOVETYPE_FOLLOW is always non-solid - this means this cannot be teleported by warpzones any more! Instead, we must notice when our owner gets teleported. - ent.aiment = e; // make the hole follow bmodel - ent.punchangle = e.angles; // the original angles of bmodel - ent.view_ofs = ent.origin - e.origin; // relative origin - ent.v_angle = ent.angles - e.angles; // relative angles - ent.aiment_classname = strzone(e.classname); - ent.aiment_deadflag = e.deadflag; - } - void UnsetMovetypeFollow(entity ent) - { - set_movetype(ent, MOVETYPE_FLY); - PROJECTILE_MAKETRIGGER(ent); - ent.aiment = NULL; - } - float LostMovetypeFollow(entity ent) - { - /* - if(ent.move_movetype != MOVETYPE_FOLLOW) - if(ent.aiment) - error("???"); - */ - if(ent.aiment) - { - if(ent.aiment.classname != ent.aiment_classname) - return 1; - if(ent.aiment.deadflag != ent.aiment_deadflag) - return 1; - } - return 0; - } - +string GetField_fullspawndata(entity e, string f, ...) +/* Retrieves the value of a map entity field from fullspawndata + * This bypasses field value changes made by the engine, + * eg string-to-float and escape sequence substitution. + * + * Avoids the need to declare fields just to read them once :) + * + * Returns the last instance of the field to match DarkPlaces behaviour. + * Path support: converts \ to / and tests the file if a third (bool, true) arg is passed. + * Returns string_null if the entity does not have the field, or the file is not in the VFS. + * + * FIXME: entities with //comments are not supported. + */ +{ + string v = string_null; + + if (!e.fullspawndata) + { + LOG_WARNF("^1EDICT %s (classname %s) has no fullspawndata, engine lacks support?", ftos(num_for_edict(e)), e.classname); + return v; + } + + if (strstrofs(e.fullspawndata, "//", 0) >= 0) + { + // tokenize and tokenize_console return early if "//" is reached, + // which can leave an odd number of tokens and break key:value pairing. + LOG_WARNF("^1EDICT %s fullspawndata contains unsupported //comment^7%s", ftos(num_for_edict(e)), e.fullspawndata); + return v; + } + + //print(sprintf("%s(EDICT %s, FIELD %s)\n", __FUNC__, ftos(num_for_edict(e)), f)); + //print(strcat("FULLSPAWNDATA:", e.fullspawndata, "\n")); + + // tokenize treats \ as an escape, but tokenize_console returns the required literal + for (int t = tokenize_console(e.fullspawndata) - 3; t > 0; t -= 2) + { + //print(sprintf("\tTOKEN %s:%s\t%s:%s\n", ftos(t), ftos(t + 1), argv(t), argv(t + 1))); + if (argv(t) == f) + { + v = argv(t + 1); + break; + } + } + + //print(strcat("RESULT: ", v, "\n\n")); + + if (v && ...(0, bool) == true) + { + v = strreplace("\\", "/", v); + if (whichpack(v) == "") + return string_null; + } + + return v; +}