// works for up to 10 decimals!
string ftos_decimals(float number, float decimals)
{
+ // inhibit stupid negative zero
+ if(number == 0)
+ number = 0;
// we have sprintf...
return sprintf("%.*f", decimals, number);
}
{
switch(c)
{
- case 0: return '0.800000 0.800000 0.800000';
- case 1: return '0.600000 0.400000 0.000000';
+ case 0: return '1.000000 1.000000 1.000000';
+ case 1: return '1.000000 0.333333 0.000000';
case 2: return '0.000000 1.000000 0.501961';
case 3: return '0.000000 1.000000 0.000000';
case 4: return '1.000000 0.000000 0.000000';
- case 5: return '0.000000 0.658824 1.000000';
+ case 5: return '0.000000 0.666667 1.000000';
case 6: return '0.000000 1.000000 1.000000';
case 7: return '0.501961 1.000000 0.000000';
case 8: return '0.501961 0.000000 1.000000';
case 9: return '1.000000 0.000000 1.000000';
case 10: return '1.000000 0.000000 0.501961';
- case 11: return '0.600000 0.600000 0.600000';
+ case 11: return '0.000000 0.000000 1.000000';
case 12: return '1.000000 1.000000 0.000000';
- case 13: return '0.000000 0.313725 1.000000';
- case 14: return '1.000000 0.501961 0.000000';
+ case 13: return '0.000000 0.333333 1.000000';
+ case 14: return '1.000000 0.666667 0.000000';
case 15:
if(isPants)
return
}
#endif
-void cvar_settemp(string cv, string val)
+float cvar_settemp(string tmp_cvar, string tmp_value)
{
+ float created_saved_value;
entity e;
+
+ if not(tmp_cvar || tmp_value)
+ {
+ dprint("Error: Invalid usage of cvar_settemp(string, string); !\n");
+ return FALSE;
+ }
+
for(e = world; (e = find(e, classname, "saved_cvar_value")); )
- if(e.netname == cv)
- goto saved;
+ if(e.netname == tmp_cvar)
+ goto saved; // skip creation
+
+ // creating a new entity to keep track of this cvar
e = spawn();
e.classname = "saved_cvar_value";
- e.netname = strzone(cv);
- e.message = strzone(cvar_string(cv));
-:saved
- cvar_set(cv, val);
+ e.netname = strzone(tmp_cvar);
+ e.message = strzone(cvar_string(tmp_cvar));
+ created_saved_value = TRUE;
+
+ // an entity for this cvar already exists
+ :saved
+
+ // update the cvar to the value given
+ cvar_set(tmp_cvar, tmp_value);
+
+ return created_saved_value;
}
-void cvar_settemp_restore()
+float cvar_settemp_restore()
{
+ float i;
entity e;
while((e = find(world, classname, "saved_cvar_value")))
{
cvar_set(e.netname, e.message);
remove(e);
}
+
+ return i;
}
float almost_equals(float a, float b)
{
float eps;
eps = (max(a, -a) + max(c, -c)) * 0.001;
+ if(a > c)
+ eps = -eps;
return b == median(a - eps, b, c + eps);
}
tokenize_console("foo bar");
if(strcat(argv(0), substring("foo bar", 4, 7 - argv_start_index(1))) == "barbar")
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)
+ error("The empty string counts as false. We do not want that!");
}
float compressShotOrigin(vector v)
return f;
}
+/*
+string strlimitedlen(string input, string truncation, float strip_colors, float limit)
+{
+ if(strlen((strip_colors ? strdecolorize(input) : input)) <= limit)
+ return input;
+ else
+ return strcat(substring(input, 0, (strlen(input) - strlen(truncation))), truncation);
+}*/
+
+// escape the string to make it safe for consoles
+string MakeConsoleSafe(string input)
+{
+ input = strreplace("\n", "", input);
+ input = strreplace("\\", "\\\\", input);
+ input = strreplace("$", "$$", input);
+ input = strreplace("\"", "\\\"", input);
+ return input;
+}
+
+#ifndef MENUQC
+// get true/false value of a string with multiple different inputs
+float InterpretBoolean(string input)
+{
+ switch(strtolower(input))
+ {
+ case "yes":
+ case "true":
+ case "on":
+ return TRUE;
+
+ case "no":
+ case "false":
+ case "off":
+ return FALSE;
+
+ default: return stof(input);
+ }
+}
+#endif
+
#ifdef CSQC
entity ReadCSQCEntity()
{
}
cvar_settemp_restore(); // this must be done LAST, but in any case
}
+
+#define APPROXPASTTIME_ACCURACY_REQUIREMENT 0.05
+#define APPROXPASTTIME_MAX (16384 * APPROXPASTTIME_ACCURACY_REQUIREMENT)
+#define APPROXPASTTIME_RANGE (64 * APPROXPASTTIME_ACCURACY_REQUIREMENT)
+// this will use the value:
+// 128
+// accuracy near zero is APPROXPASTTIME_MAX/(256*255)
+// accuracy at x is 1/derivative, i.e.
+// APPROXPASTTIME_MAX * (1 + 256 * (dt / APPROXPASTTIME_MAX))^2 / 65536
+#ifdef SVQC
+void WriteApproxPastTime(float dst, float t)
+{
+ float dt = time - t;
+
+ // warning: this is approximate; do not resend when you don't have to!
+ // be careful with sendflags here!
+ // we want: 0 -> 0.05, 1 -> 0.1, ..., 255 -> 12.75
+
+ // map to range...
+ dt = 256 * (dt / ((APPROXPASTTIME_MAX / 256) + dt));
+
+ // round...
+ dt = rint(bound(0, dt, 255));
+
+ WriteByte(dst, dt);
+}
+#endif
+#ifdef CSQC
+float ReadApproxPastTime()
+{
+ float dt = ReadByte();
+
+ // map from range...PPROXPASTTIME_MAX / 256
+ dt = (APPROXPASTTIME_MAX / 256) * (dt / (256 - dt));
+
+ return servertime - dt;
+}
+#endif
+
+#ifndef MENUQC
+.float skeleton_bones_index;
+void Skeleton_SetBones(entity e)
+{
+ // set skeleton_bones to the total number of bones on the model
+ if(e.skeleton_bones_index == e.modelindex)
+ return; // same model, nothing to update
+
+ float skelindex;
+ skelindex = skel_create(e.modelindex);
+ e.skeleton_bones = skel_get_numbones(skelindex);
+ skel_delete(skelindex);
+ e.skeleton_bones_index = e.modelindex;
+}
+#endif
+
+string to_execute_next_frame;
+void execute_next_frame()
+{
+ if(to_execute_next_frame)
+ {
+ localcmd("\n", to_execute_next_frame, "\n");
+ strunzone(to_execute_next_frame);
+ to_execute_next_frame = string_null;
+ }
+}
+void queue_to_execute_next_frame(string s)
+{
+ if(to_execute_next_frame)
+ {
+ s = strcat(s, "\n", to_execute_next_frame);
+ strunzone(to_execute_next_frame);
+ }
+ to_execute_next_frame = strzone(s);
+}