X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fcommon%2Futil.qc;h=89eae22239d20c16166768b48f9274bf682bd3fa;hb=451c0fbf5473c6acc88bafaa0e9c14e5afd3764e;hp=afd7f1c5ce25ea2bad16b2d3dda0c58c30d4ddad;hpb=8a000d27bdf428db93e0304c4fdee5a26b89e9e8;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/common/util.qc b/qcsrc/common/util.qc index afd7f1c5c..d1503a7b6 100644 --- a/qcsrc/common/util.qc +++ b/qcsrc/common/util.qc @@ -148,7 +148,7 @@ void wordwrap_cb(string s, float l, void(string) callback) float dist_point_line(vector p, vector l0, vector ldir) { ldir = normalize(ldir); - + // remove the component in line direction p = p - (p * ldir) * ldir; @@ -203,7 +203,6 @@ string ftos_decimals(float number, float decimals) return sprintf("%.*f", decimals, number); } -float time; vector colormapPaletteColor(float c, float isPants) { switch(c) @@ -242,7 +241,7 @@ vector colormapPaletteColor(float c, float isPants) string fstrunzone(string s) { string sc; - if not(s) + if (!s) return s; sc = strcat(s, ""); strunzone(s); @@ -265,7 +264,7 @@ void db_save(float db, string pFilename) { float fh, i, n; fh = fopen(pFilename, FILE_WRITE); - if(fh < 0) + if(fh < 0) { print(strcat("^1Can't write DB to ", pFilename)); return; @@ -459,7 +458,7 @@ string ScoreString(float pFlags, float pValue) valstr = TIME_ENCODED_TOSTRING(pValue); else valstr = ftos(pValue); - + return valstr; } @@ -665,7 +664,7 @@ string fixPriorityList(string order, float from, float to, float subtract, float neworder = strcat(neworder, ftos(w), " "); } } - + return substring(neworder, 0, strlen(neworder) - 1); } @@ -678,7 +677,7 @@ string mapPriorityList(string order, string(string) mapfunc) neworder = ""; for(i = 0; i < n; ++i) neworder = strcat(neworder, mapfunc(argv(i)), " "); - + return substring(neworder, 0, strlen(neworder) - 1); } @@ -703,7 +702,7 @@ string swapInPriorityList(string order, float i, float j) } return substring(s, 0, strlen(s) - 1); } - + return order; } @@ -867,7 +866,7 @@ float cvar_settemp(string tmp_cvar, string tmp_value) created_saved_value = 0; - if not(tmp_cvar || tmp_value) + if (!(tmp_cvar || tmp_value)) { dprint("Error: Invalid usage of cvar_settemp(string, string); !\n"); return 0; @@ -901,8 +900,8 @@ float cvar_settemp(string tmp_cvar, string tmp_value) float cvar_settemp_restore() { - float i; - entity e; + float i = 0; + entity e = world; while((e = find(e, classname, "saved_cvar_value"))) { if(cvar_type(e.netname)) @@ -1101,7 +1100,7 @@ vector rgb_to_hsv(vector rgb) hsv_y = 0; else hsv_y = 1 - mi/ma; - + return hsv; } @@ -1119,7 +1118,7 @@ vector rgb_to_hsl(vector rgb) ma = max(rgb_x, rgb_y, rgb_z); hsl_x = rgb_mi_ma_to_hue(rgb, mi, ma); - + hsl_z = 0.5 * (mi + ma); if(mi == ma) hsl_y = 0; @@ -1127,7 +1126,7 @@ vector rgb_to_hsl(vector rgb) hsl_y = (ma - mi) / (2*hsl_z); else // if(hsl_z > 0.5) hsl_y = (ma - mi) / (2 - 2*hsl_z); - + return hsl; } @@ -1139,7 +1138,7 @@ vector hsl_to_rgb(vector hsl) maminusmi = hsl_y * 2 * hsl_z; else maminusmi = hsl_y * (2 - 2 * hsl_z); - + // hsl_z = 0.5 * mi + 0.5 * ma // maminusmi = - mi + ma mi = hsl_z - 0.5 * maminusmi; @@ -1200,7 +1199,7 @@ float textLengthUpToWidth(string theText, float maxWidth, vector theSize, textLe // terminate, as the range still halves each time - but nevertheless, it is // guaranteed that it finds ONE valid cutoff place (where "left" is in // range, and "right" is outside). - + // terencehill: the following code detects truncated ^xrgb tags (e.g. ^x or ^x4) // and decrease left on the basis of the chars detected of the truncated tag // Even if the ^xrgb tag is not complete/correct, left is decreased @@ -1228,7 +1227,7 @@ float textLengthUpToWidth(string theText, float maxWidth, vector theSize, textLe } } } - + return left; } @@ -1264,7 +1263,7 @@ float textLengthUpToLength(string theText, float maxWidth, textLengthUpToLength_ // terminate, as the range still halves each time - but nevertheless, it is // guaranteed that it finds ONE valid cutoff place (where "left" is in // range, and "right" is outside). - + // terencehill: the following code detects truncated ^xrgb tags (e.g. ^x or ^x4) // and decrease left on the basis of the chars detected of the truncated tag // Even if the ^xrgb tag is not complete/correct, left is decreased @@ -1292,7 +1291,7 @@ float textLengthUpToLength(string theText, float maxWidth, textLengthUpToLength_ } } } - + return left; } @@ -1339,7 +1338,7 @@ string getWrappedLine(float w, vector theFontSize, textLengthUpToWidth_widthFunc string s; s = getWrappedLine_remaining; - + if(w <= 0) { getWrappedLine_remaining = string_null; @@ -1385,7 +1384,7 @@ string getWrappedLineLen(float w, textLengthUpToLength_lenFunction_t tw) string s; s = getWrappedLine_remaining; - + if(w <= 0) { getWrappedLine_remaining = string_null; @@ -1476,8 +1475,12 @@ float isGametypeInFilter(float gt, float tp, float ts, string pattern) if(strstrofs(strcat(",", pattern, ","), subpattern, 0) < 0) if(strstrofs(strcat(",", pattern, ","), subpattern2, 0) < 0) if(strstrofs(strcat(",", pattern, ","), subpattern3, 0) < 0) - if((!subpattern4) || strstrofs(strcat(",", pattern, ","), subpattern4, 0) < 0) - return 0; + { + if (!subpattern4) + return 0; + if(strstrofs(strcat(",", pattern, ","), subpattern4, 0) < 0) + return 0; + } } return 1; } @@ -1709,7 +1712,7 @@ void check_unacceptable_compiler_bugs() error("fteqcc bug introduced with revision 3178 detected. Please upgrade fteqcc to a later revision, downgrade fteqcc to revision 3177, or pester Spike until he fixes it. You can set _allow_unacceptable_compiler_bugs 1 to skip this check, but expect stuff to be horribly broken then."); string s = ""; - if not(s) + if (!s) error("The empty string counts as false. We do not want that!"); } @@ -1828,10 +1831,13 @@ void RandomSelection_Add(entity e, float f, string s, float weight, float priori } } -vector healtharmor_maxdamage(float h, float a, float armorblock) +#ifndef MENUQC +vector healtharmor_maxdamage(float h, float a, float armorblock, float deathtype) { // NOTE: we'll always choose the SMALLER value... float healthdamage, armordamage, armorideal; + if (deathtype == DEATH_DROWN) // Why should armor help here... + armorblock = 0; vector v; healthdamage = (h - 1) / (1 - armorblock); // damage we can take if we could use more health armordamage = a + (h - 1); // damage we can take if we could use more armor @@ -1850,14 +1856,17 @@ vector healtharmor_maxdamage(float h, float a, float armorblock) return v; } -vector healtharmor_applydamage(float a, float armorblock, float damage) +vector healtharmor_applydamage(float a, float armorblock, float deathtype, float damage) { vector v; + if (deathtype == DEATH_DROWN) // Why should armor help here... + armorblock = 0; v_y = bound(0, damage * armorblock, a); // save v_x = bound(0, damage - v_y, damage); // take v_z = 0; return v; } +#endif string getcurrentmod() { @@ -1880,6 +1889,22 @@ float ReadInt24_t() v += ReadByte(); // note: this is unsigned return v; } +vector ReadInt48_t() +{ + vector v; + v_x = ReadInt24_t(); + v_y = ReadInt24_t(); + v_z = 0; + return v; +} +vector ReadInt72_t() +{ + vector v; + v_x = ReadInt24_t(); + v_y = ReadInt24_t(); + v_z = ReadInt24_t(); + return v; +} #else void WriteInt24_t(float dst, float val) { @@ -1887,6 +1912,17 @@ void WriteInt24_t(float dst, float val) WriteShort(dst, (v = floor(val / 256))); WriteByte(dst, val - v * 256); // 0..255 } +void WriteInt48_t(float dst, vector val) +{ + WriteInt24_t(dst, val_x); + WriteInt24_t(dst, val_y); +} +void WriteInt72_t(float dst, vector val) +{ + WriteInt24_t(dst, val_x); + WriteInt24_t(dst, val_y); + WriteInt24_t(dst, val_z); +} #endif #endif @@ -1997,7 +2033,7 @@ string get_model_datafilename(string m, float sk, string fil) float get_model_parameters(string m, float sk) { string fn, s, c; - float fh; + float fh, i; get_model_parameters_modelname = string_null; get_model_parameters_modelskin = -1; @@ -2007,9 +2043,21 @@ float get_model_parameters(string m, float sk) get_model_parameters_weight = -1; get_model_parameters_age = -1; get_model_parameters_desc = string_null; + get_model_parameters_bone_upperbody = string_null; + get_model_parameters_bone_weapon = string_null; + for(i = 0; i < MAX_AIM_BONES; ++i) + { + get_model_parameters_bone_aim[i] = string_null; + get_model_parameters_bone_aimweight[i] = 0; + } + get_model_parameters_fixbone = 0; - if not(m) + if (!m) return 1; + + if(substring(m, -9, 5) == "_lod1" || substring(m, -9, 5) == "_lod2") + m = strcat(substring(m, 0, -10), substring(m, -4, -1)); + if(sk < 0) { if(substring(m, -4, -1) != ".txt") @@ -2058,6 +2106,18 @@ float get_model_parameters(string m, float sk) get_model_parameters_weight = stof(s); if(c == "age") get_model_parameters_age = stof(s); + if(c == "bone_upperbody") + get_model_parameters_bone_upperbody = s; + if(c == "bone_weapon") + get_model_parameters_bone_weapon = s; + for(i = 0; i < MAX_AIM_BONES; ++i) + if(c == strcat("bone_aim", ftos(i))) + { + get_model_parameters_bone_aimweight[i] = stof(car(s)); + get_model_parameters_bone_aim[i] = cdr(s); + } + if(c == "fixbone") + get_model_parameters_fixbone = stof(s); } while((s = fgets(fh))) @@ -2226,11 +2286,11 @@ float xdecode(string s) float lowestbit(float f) { - f &~= f * 2; - f &~= f * 4; - f &~= f * 16; - f &~= f * 256; - f &~= f * 65536; + f &= ~(f * 2); + f &= ~(f * 4); + f &= ~(f * 16); + f &= ~(f * 256); + f &= ~(f * 65536); return f; } @@ -2263,12 +2323,12 @@ float InterpretBoolean(string input) case "true": case "on": return TRUE; - + case "no": case "false": case "off": return FALSE; - + default: return stof(input); } } @@ -2399,7 +2459,7 @@ float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor) /* // if this is the case, the possible zeros of the first derivative are outside // 0..1 - We can calculate this condition as condition + We can calculate this condition as condition if(se <= 3) return TRUE; */ @@ -2432,6 +2492,28 @@ float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor) // (3, [0..3]) // (3.5, [0.2..2.3]) // (4, 1) + + /* + On another note: + inflection point is always at (2s + e - 3) / (3s + 3e - 6). + + s + e - 2 == 0: no inflection + + s + e > 2: + 0 < inflection < 1 if: + 0 < 2s + e - 3 < 3s + 3e - 6 + 2s + e > 3 and 2e + s > 3 + + s + e < 2: + 0 < inflection < 1 if: + 0 > 2s + e - 3 > 3s + 3e - 6 + 2s + e < 3 and 2e + s < 3 + + Therefore: there is an inflection point iff: + e outside (3 - s)/2 .. 3 - s*2 + + in other words, if (s,e) in triangle (1,1)(0,3)(0,1.5) or in triangle (1,1)(3,0)(1.5,0) + */ } .float FindConnectedComponent_processing; @@ -2475,3 +2557,198 @@ void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t for(queue_start = e; queue_start; queue_start = queue_start.fld) queue_start.FindConnectedComponent_processing = 0; } + +// todo: this sucks, lets find a better way to do backtraces? +#ifndef MENUQC +void backtrace(string msg) +{ + float dev, war; + #ifdef SVQC + dev = autocvar_developer; + war = autocvar_prvm_backtraceforwarnings; + #else + dev = cvar("developer"); + war = cvar("prvm_backtraceforwarnings"); + #endif + cvar_set("developer", "1"); + cvar_set("prvm_backtraceforwarnings", "1"); + print("\n"); + print("--- CUT HERE ---\nWARNING: "); + print(msg); + print("\n"); + remove(world); // isn't there any better way to cause a backtrace? + print("\n--- CUT UNTIL HERE ---\n"); + cvar_set("developer", ftos(dev)); + cvar_set("prvm_backtraceforwarnings", ftos(war)); +} +#endif + +// color code replace, place inside of sprintf and parse the string +string CCR(string input) +{ + // See the autocvar declarations in util.qh for default values + + // foreground/normal colors + input = strreplace("^F1", strcat("^", autocvar_hud_colorset_foreground_1), input); + input = strreplace("^F2", strcat("^", autocvar_hud_colorset_foreground_2), input); + input = strreplace("^F3", strcat("^", autocvar_hud_colorset_foreground_3), input); + input = strreplace("^F4", strcat("^", autocvar_hud_colorset_foreground_4), input); + + // "kill" colors + input = strreplace("^K1", strcat("^", autocvar_hud_colorset_kill_1), input); + input = strreplace("^K2", strcat("^", autocvar_hud_colorset_kill_2), input); + input = strreplace("^K3", strcat("^", autocvar_hud_colorset_kill_3), input); + + // background colors + input = strreplace("^BG", strcat("^", autocvar_hud_colorset_background), input); + input = strreplace("^N", "^7", input); // "none"-- reset to white... + return input; +} + +vector vec3(float x, float y, float z) +{ + vector v; + v_x = x; + v_y = y; + v_z = z; + return v; +} + +#ifndef MENUQC +vector animfixfps(entity e, vector a, vector b) +{ + // multi-frame anim: keep as-is + if(a_y == 1) + { + float dur; + dur = frameduration(e.modelindex, a_x); + if(dur <= 0 && b_y) + { + a = b; + dur = frameduration(e.modelindex, a_x); + } + if(dur > 0) + a_z = 1.0 / dur; + } + return a; +} +#endif + +#ifdef SVQC +void dedicated_print(string input) // print(), but only print if the server is not local +{ + if(server_is_dedicated) { print(input); } +} +#endif + +#ifndef MENUQC +float Announcer_PickNumber(float type, float num) +{ + switch(type) + { + case CNT_GAMESTART: + { + switch(num) + { + case 10: return ANNCE_NUM_GAMESTART_10; + case 9: return ANNCE_NUM_GAMESTART_9; + case 8: return ANNCE_NUM_GAMESTART_8; + case 7: return ANNCE_NUM_GAMESTART_7; + case 6: return ANNCE_NUM_GAMESTART_6; + case 5: return ANNCE_NUM_GAMESTART_5; + case 4: return ANNCE_NUM_GAMESTART_4; + case 3: return ANNCE_NUM_GAMESTART_3; + case 2: return ANNCE_NUM_GAMESTART_2; + case 1: return ANNCE_NUM_GAMESTART_1; + } + break; + } + case CNT_IDLE: + { + switch(num) + { + case 10: return ANNCE_NUM_IDLE_10; + case 9: return ANNCE_NUM_IDLE_9; + case 8: return ANNCE_NUM_IDLE_8; + case 7: return ANNCE_NUM_IDLE_7; + case 6: return ANNCE_NUM_IDLE_6; + case 5: return ANNCE_NUM_IDLE_5; + case 4: return ANNCE_NUM_IDLE_4; + case 3: return ANNCE_NUM_IDLE_3; + case 2: return ANNCE_NUM_IDLE_2; + case 1: return ANNCE_NUM_IDLE_1; + } + break; + } + case CNT_KILL: + { + switch(num) + { + case 10: return ANNCE_NUM_KILL_10; + case 9: return ANNCE_NUM_KILL_9; + case 8: return ANNCE_NUM_KILL_8; + case 7: return ANNCE_NUM_KILL_7; + case 6: return ANNCE_NUM_KILL_6; + case 5: return ANNCE_NUM_KILL_5; + case 4: return ANNCE_NUM_KILL_4; + case 3: return ANNCE_NUM_KILL_3; + case 2: return ANNCE_NUM_KILL_2; + case 1: return ANNCE_NUM_KILL_1; + } + break; + } + case CNT_RESPAWN: + { + switch(num) + { + case 10: return ANNCE_NUM_RESPAWN_10; + case 9: return ANNCE_NUM_RESPAWN_9; + case 8: return ANNCE_NUM_RESPAWN_8; + case 7: return ANNCE_NUM_RESPAWN_7; + case 6: return ANNCE_NUM_RESPAWN_6; + case 5: return ANNCE_NUM_RESPAWN_5; + case 4: return ANNCE_NUM_RESPAWN_4; + case 3: return ANNCE_NUM_RESPAWN_3; + case 2: return ANNCE_NUM_RESPAWN_2; + case 1: return ANNCE_NUM_RESPAWN_1; + } + break; + } + case CNT_ROUNDSTART: + { + switch(num) + { + case 10: return ANNCE_NUM_ROUNDSTART_10; + case 9: return ANNCE_NUM_ROUNDSTART_9; + case 8: return ANNCE_NUM_ROUNDSTART_8; + case 7: return ANNCE_NUM_ROUNDSTART_7; + case 6: return ANNCE_NUM_ROUNDSTART_6; + case 5: return ANNCE_NUM_ROUNDSTART_5; + case 4: return ANNCE_NUM_ROUNDSTART_4; + case 3: return ANNCE_NUM_ROUNDSTART_3; + case 2: return ANNCE_NUM_ROUNDSTART_2; + case 1: return ANNCE_NUM_ROUNDSTART_1; + } + break; + } + default: + { + switch(num) + { + case 10: return ANNCE_NUM_10; + case 9: return ANNCE_NUM_9; + case 8: return ANNCE_NUM_8; + case 7: return ANNCE_NUM_7; + case 6: return ANNCE_NUM_6; + case 5: return ANNCE_NUM_5; + case 4: return ANNCE_NUM_4; + case 3: return ANNCE_NUM_3; + case 2: return ANNCE_NUM_2; + case 1: return ANNCE_NUM_1; + } + break; + } + } + return NOTIF_ABORT; // abort sending if none of these numbers were right +} +#endif