X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fcommon%2Futil.qc;h=9c9896ec6d03418a7f694c9338ee184f9538cf5a;hp=35ec9b2c58f96de0ac3aba803b52641394ada62c;hb=45d8904a100765555e622598a39967963733df1d;hpb=89f405ba71d1c354dca27a0af246f04fb9ec42e6 diff --git a/qcsrc/common/util.qc b/qcsrc/common/util.qc index 35ec9b2c58..9c9896ec6d 100644 --- a/qcsrc/common/util.qc +++ b/qcsrc/common/util.qc @@ -2,7 +2,7 @@ #if defined(CSQC) #include "constants.qh" - #include "../client/mutators/events.qh" + #include #include "mapinfo.qh" #include "notifications/all.qh" #include "scores.qh" @@ -10,14 +10,136 @@ #elif defined(MENUQC) #elif defined(SVQC) #include "constants.qh" - #include "../server/mutators/events.qh" + #include #include "notifications/all.qh" #include #include "scores.qh" #include "mapinfo.qh" #endif +#ifdef SVQC +float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomonsters, entity forent, float stopatentity, entity ignorestopatentity) // returns the number of traces done, for benchmarking +{ + vector pos, dir, t; + float nudge; + entity stopentity; + + //nudge = 2 * cvar("collision_impactnudge"); // why not? + nudge = 0.5; + + dir = normalize(v2 - v1); + + pos = v1 + dir * nudge; + + float c; + c = 0; + + for (;;) + { + if(pos * dir >= v2 * dir) + { + // went too far + trace_fraction = 1; + trace_endpos = v2; + return c; + } + + tracebox(pos, mi, ma, v2, nomonsters, forent); + ++c; + + if(c == 50) + { + LOG_TRACE("When tracing from ", vtos(v1), " to ", vtos(v2)); + LOG_TRACE(" Nudging gets us nowhere at ", vtos(pos)); + LOG_TRACE(" trace_endpos is ", vtos(trace_endpos)); + LOG_TRACE(" trace distance is ", ftos(vlen(pos - trace_endpos))); + } + + stopentity = trace_ent; + + if(trace_startsolid) + { + // we started inside solid. + // then trace from endpos to pos + t = trace_endpos; + tracebox(t, mi, ma, pos, nomonsters, forent); + ++c; + if(trace_startsolid) + { + // t is still inside solid? bad + // force advance, then, and retry + pos = t + dir * nudge; + + // but if we hit an entity, stop RIGHT before it + if(stopatentity && stopentity && stopentity != ignorestopatentity) + { + trace_ent = stopentity; + trace_endpos = t; + trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir); + return c; + } + } + else + { + // we actually LEFT solid! + trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir); + return c; + } + } + else + { + // pos is outside solid?!? but why?!? never mind, just return it. + trace_endpos = pos; + trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir); + return c; + } + } +} + +void traceline_inverted (vector v1, vector v2, float nomonsters, entity forent, float stopatentity, entity ignorestopatentity) +{ + tracebox_inverted(v1, '0 0 0', '0 0 0', v2, nomonsters, forent, stopatentity, ignorestopatentity); +} +#endif + #ifdef GAMEQC +/* +================== +findbetterlocation + +Returns a point at least 12 units away from walls +(useful for explosion animations, although the blast is performed where it really happened) +Ripped from DPMod +================== +*/ +vector findbetterlocation (vector org, float mindist) +{ + vector vec = mindist * '1 0 0'; + int c = 0; + while (c < 6) + { + traceline (org, org + vec, true, NULL); + vec = vec * -1; + if (trace_fraction < 1) + { + vector loc = trace_endpos; + traceline (loc, loc + vec, true, NULL); + if (trace_fraction >= 1) + org = loc + vec; + } + if (c & 1) + { + float h = vec.y; + vec.y = vec.x; + vec.x = vec.z; + vec.z = h; + } + c = c + 1; + } + + return org; +} + /* * Get "real" origin, in worldspace, even if ent is attached to something else. */ @@ -95,7 +217,8 @@ void wordwrap_cb(string s, float l, void(string) callback) s = strzone(s); lleft = l; - for (i = 0;i < strlen(s);++i) + int len = strlen(s); + for (i = 0; i < len; ++i) { if (substring(s, i, 2) == "\\n") { @@ -113,12 +236,12 @@ void wordwrap_cb(string s, float l, void(string) callback) if (lleft > 0) { callback(" "); - lleft = lleft - 1; + --lleft; } } else { - for (j = i+1;j < strlen(s);++j) + for (j = i+1; j < len; ++j) // ^^ this skips over the first character of a word, which // is ALWAYS part of the word // this is safe since if i+1 == strlen(s), i will become @@ -146,7 +269,7 @@ void wordwrap_cb(string s, float l, void(string) callback) lleft = l; } callback(substring(s, i, wlen)); - lleft = lleft - wlen; + lleft -= wlen; i = j - 1; } } @@ -336,19 +459,18 @@ STATIC_INIT(compressShortVector) if(cvar("developer")) { - LOG_INFO("Verifying vector compression table..."); + LOG_TRACE("Verifying vector compression table..."); for(i = 0x0F00; i < 0xFFFF; ++i) if(i != compressShortVector(decompressShortVector(i))) { - LOG_INFOF( + LOG_FATALF( "BROKEN vector compression: %s -> %s -> %s", ftos(i), vtos(decompressShortVector(i)), ftos(compressShortVector(decompressShortVector(i))) ); - error("b0rk"); } - LOG_INFO("Done."); + LOG_TRACE("Done."); } } @@ -1127,6 +1249,8 @@ vector healtharmor_applydamage(float a, float armorblock, int deathtype, float d vector v; if (DEATH_IS(deathtype, DEATH_DROWN)) // Why should armor help here... armorblock = 0; + if (deathtype & HITTYPE_ARMORPIERCE) + armorblock = 0; v.y = bound(0, damage * armorblock, a); // save v.x = bound(0, damage - v.y, damage); // take v.z = 0; @@ -1175,11 +1299,19 @@ float matchacl(string acl, string str) if(s == t) { r = d; + break; // if we found a killing case, apply it! other settings may be allowed in the future, but this one is caught } } return r; } +ERASEABLE +void write_String_To_File(int fh, string str, bool alsoprint) +{ + fputs(fh, str); + if (alsoprint) LOG_INFO(str); +} + string get_model_datafilename(string m, float sk, string fil) { if(m) @@ -1306,6 +1438,148 @@ float get_model_parameters(string m, float sk) return 1; } +string translate_key(string key) +{ + if (prvm_language == "en") return key; + + switch(key) + { + case "TAB": return _("TAB"); + case "ENTER": return _("ENTER"); + case "ESCAPE": return _("ESCAPE"); + case "SPACE": return _("SPACE"); + + case "BACKSPACE": return _("BACKSPACE"); + case "UPARROW": return _("UPARROW"); + case "DOWNARROW": return _("DOWNARROW"); + case "LEFTARROW": return _("LEFTARROW"); + case "RIGHTARROW": return _("RIGHTARROW"); + + case "ALT": return _("ALT"); + case "CTRL": return _("CTRL"); + case "SHIFT": return _("SHIFT"); + + case "F1": return _("F1"); + case "F2": return _("F2"); + case "F3": return _("F3"); + case "F4": return _("F4"); + case "F5": return _("F5"); + case "F6": return _("F6"); + case "F7": return _("F7"); + case "F8": return _("F8"); + case "F9": return _("F9"); + case "F10": return _("F10"); + case "F11": return _("F11"); + case "F12": return _("F12"); + + case "INS": return _("INS"); + case "DEL": return _("DEL"); + case "PGDN": return _("PGDN"); + case "PGUP": return _("PGUP"); + case "HOME": return _("HOME"); + case "END": return _("END"); + + case "PAUSE": return _("PAUSE"); + + case "NUMLOCK": return _("NUMLOCK"); + case "CAPSLOCK": return _("CAPSLOCK"); + case "SCROLLOCK": return _("SCROLLOCK"); + } + + if (substring(key, 0, 3) == "KP_") + { + string subkey = substring(key, 3, -1); + if (IS_DIGIT(substring(key, 3, 1))) // check only first digit + { + return sprintf(_("KP_%d"), stof(subkey)); + } + + switch(subkey) + { + case "INS": return sprintf(_("KP_%s"), _("INS")); + case "END": return sprintf(_("KP_%s"), _("END")); + case "DOWNARROW": return sprintf(_("KP_%s"), _("DOWNARROW")); + case "PGDN": return sprintf(_("KP_%s"), _("PGDN")); + case "LEFTARROW": return sprintf(_("KP_%s"), _("LEFTARROW")); + case "RIGHTARROW": return sprintf(_("KP_%s"), _("RIGHTARROW")); + case "HOME": return sprintf(_("KP_%s"), _("HOME")); + case "UPARROW": return sprintf(_("KP_%s"), _("UPARROW")); + case "PGUP": return sprintf(_("KP_%s"), _("PGUP")); + case "PERIOD": return sprintf(_("KP_%s"), _("PERIOD")); + case "DEL": return sprintf(_("KP_%s"), _("DEL")); + case "DIVIDE": return sprintf(_("KP_%s"), _("DIVIDE")); + case "SLASH": return sprintf(_("KP_%s"), _("SLASH")); + case "MULTIPLY": return sprintf(_("KP_%s"), _("MULTIPLY")); + case "MINUS": return sprintf(_("KP_%s"), _("MINUS")); + case "PLUS": return sprintf(_("KP_%s"), _("PLUS")); + case "ENTER": return sprintf(_("KP_%s"), _("ENTER")); + case "EQUALS": return sprintf(_("KP_%s"), _("EQUALS")); + default: return key; + } + } + + if (key == "PRINTSCREEN") return _("PRINTSCREEN"); + + if (substring(key, 0, 5) == "MOUSE") + return sprintf(_("MOUSE%d"), stof(substring(key, 5, -1))); + + if (key == "MWHEELUP") return _("MWHEELUP"); + if (key == "MWHEELDOWN") return _("MWHEELDOWN"); + + if (substring(key, 0,3) == "JOY") + return sprintf(_("JOY%d"), stof(substring(key, 3, -1))); + + if (substring(key, 0,3) == "AUX") + return sprintf(_("AUX%d"), stof(substring(key, 3, -1))); + + if (substring(key, 0, 4) == "X360_") + { + string subkey = substring(key, 4, -1); + switch(subkey) + { + case "DPAD_UP": return sprintf(_("X360_%s"), _("DPAD_UP")); + case "DPAD_DOWN": return sprintf(_("X360_%s"), _("DPAD_DOWN")); + case "DPAD_LEFT": return sprintf(_("X360_%s"), _("DPAD_LEFT")); + case "DPAD_RIGHT": return sprintf(_("X360_%s"), _("DPAD_RIGHT")); + case "START": return sprintf(_("X360_%s"), _("START")); + case "BACK": return sprintf(_("X360_%s"), _("BACK")); + case "LEFT_THUMB": return sprintf(_("X360_%s"), _("LEFT_THUMB")); + case "RIGHT_THUMB": return sprintf(_("X360_%s"), _("RIGHT_THUMB")); + case "LEFT_SHOULDER": return sprintf(_("X360_%s"), _("LEFT_SHOULDER")); + case "RIGHT_SHOULDER": return sprintf(_("X360_%s"), _("RIGHT_SHOULDER")); + case "LEFT_TRIGGER": return sprintf(_("X360_%s"), _("LEFT_TRIGGER")); + case "RIGHT_TRIGGER": return sprintf(_("X360_%s"), _("RIGHT_TRIGGER")); + case "LEFT_THUMB_UP": return sprintf(_("X360_%s"), _("LEFT_THUMB_UP")); + case "LEFT_THUMB_DOWN": return sprintf(_("X360_%s"), _("LEFT_THUMB_DOWN")); + case "LEFT_THUMB_LEFT": return sprintf(_("X360_%s"), _("LEFT_THUMB_LEFT")); + case "LEFT_THUMB_RIGHT": return sprintf(_("X360_%s"), _("LEFT_THUMB_RIGHT")); + case "RIGHT_THUMB_UP": return sprintf(_("X360_%s"), _("RIGHT_THUMB_UP")); + case "RIGHT_THUMB_DOWN": return sprintf(_("X360_%s"), _("RIGHT_THUMB_DOWN")); + case "RIGHT_THUMB_LEFT": return sprintf(_("X360_%s"), _("RIGHT_THUMB_LEFT")); + case "RIGHT_THUMB_RIGHT": return sprintf(_("X360_%s"), _("RIGHT_THUMB_RIGHT")); + default: return key; + } + } + + if (substring(key, 0, 4) == "JOY_") + { + string subkey = substring(key, 4, -1); + switch(subkey) + { + case "UP": return sprintf(_("JOY_%s"), _("UP")); + case "DOWN": return sprintf(_("JOY_%s"), _("DOWN")); + case "LEFT": return sprintf(_("JOY_%s"), _("LEFT")); + case "RIGHT": return sprintf(_("JOY_%s"), _("RIGHT")); + default: return key; + } + } + + if (substring(key, 0, 8) == "MIDINOTE") + return sprintf(_("MIDINOTE%d"), stof(substring(key, 8, -1))); + + return key; +} + // x-encoding (encoding as zero length invisible string) const string XENCODE_2 = "xX"; const string XENCODE_22 = "0123456789abcdefABCDEF";