#include "../common/mapinfo.qh"
#include "../common/nades/all.qh"
+#include "../common/mutators/mutator/waypoints/all.qh"
#include "../server/mutators/gamemode_ctf.qh"
#include "../common/stats.qh"
drawpic(coord - '8 8 0', "gfx/teamradar_icon_glow", '16 16 0', brightcolor, panel_fg_alpha, 0);
}
}
-
- draw_teamradar_icon(tm.origin, tm.teamradar_icon, tm, tm.teamradar_color, panel_fg_alpha);
+ entity icon = RadarIcons[tm.teamradar_icon];
+ draw_teamradar_icon(tm.origin, icon, tm, spritelookupcolor(tm, icon.netname, tm.teamradar_color), panel_fg_alpha);
}
for(tm = world; (tm = find(tm, classname, "entcs_receiver")); )
{
void Ent_RemoveEntCS()
{SELFPARAM();
- entcs_receiver[self.sv_entnum] = world;
+ entcs_receiver[self.sv_entnum] = NULL;
}
void Ent_ReadEntCS()
{SELFPARAM();
- int sf;
InterpolateOrigin_Undo();
-
self.classname = "entcs_receiver";
- sf = ReadByte();
+ int sf = ReadByte();
- if(sf & 1)
+ if(sf & BIT(0))
self.sv_entnum = ReadByte();
- if(sf & 2)
+ if (sf & BIT(1))
{
self.origin_x = ReadShort();
self.origin_y = ReadShort();
self.origin_z = ReadShort();
setorigin(self, self.origin);
}
- if(sf & 4)
+ if (sf & BIT(2))
{
self.angles_y = ReadByte() * 360.0 / 256;
self.angles_x = self.angles_z = 0;
}
- if(sf & 8)
+ if (sf & BIT(3))
self.healthvalue = ReadByte() * 10;
- if(sf & 16)
+ if (sf & BIT(4))
self.armorvalue = ReadByte() * 10;
entcs_receiver[self.sv_entnum] = self;
R_EndPolygon();
}
-void draw_teamradar_icon(vector coord, float icon, entity pingdata, vector rgb, float a)
+void draw_teamradar_icon(vector coord, entity icon, entity pingdata, vector rgb, float a)
{
coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(coord));
- drawpic(coord - '4 4 0', strcat("gfx/teamradar_icon_", ftos(icon)), '8 8 0', rgb, a, 0);
+ drawpic(coord - '4 4 0', strcat("gfx/teamradar_icon_", ftos(icon.m_radaricon)), '8 8 0', rgb, a, 0);
if(pingdata)
{
void draw_teamradar_player(vector coord3d, vector pangles, vector rgb);
-void draw_teamradar_icon(vector coord, float icon, entity pingdata, vector rgb, float a);
+void draw_teamradar_icon(vector coord, entity icon, entity pingdata, vector rgb, float a);
void draw_teamradar_link(vector start, vector end, int colors);
const int SPRITERULE_TEAMPLAY = 1;
const int SPRITERULE_SPECTATOR = 2;
-const int RADARICON_NONE = 0;
-const int RADARICON_FLAG = 1;
-const int RADARICON_FLAGCARRIER = 1;
-const int RADARICON_HERE = 1; // TODO make these 3 and 4, and make images for them
-const int RADARICON_DANGER = 1;
-const int RADARICON_WAYPOINT = 1;
-const int RADARICON_HELPME = 1;
-const int RADARICON_CONTROLPOINT = 1;
-const int RADARICON_GENERATOR = 1;
-const int RADARICON_OBJECTIVE = 1;
-const int RADARICON_DOMPOINT = 1;
-const int RADARICON_POWERUP = 1;
-const int RADARICON_TAGGED = 1;
-
///////////////////////////
// keys pressed
const int KEY_FORWARD = 1;
/** If you register a new waypoint, make sure to add it to this list */
-REGISTER_WAYPOINT(, "", '0 0 0', 1);
-#define WP_Null WP_
REGISTER_WAYPOINT(Waypoint, _("Waypoint"), '0 1 1', 1);
REGISTER_WAYPOINT(Helpme, _("Help me!"), '1 0.5 0', 1);
#define REGISTER_WAYPOINT(id, text, color, blink) REGISTER_WAYPOINT_(id, NEW(Waypoint, #id, text, color, blink))
+REGISTRY(RadarIcons, BITS(7))
+REGISTER_REGISTRY(RegisterRadarIcons)
+.int m_radaricon;
+#define REGISTER_RADARICON(id, num) REGISTER(RegisterRadarIcons, RADARICON, RadarIcons, id, m_id, new(RadarIcon)) { this.m_radaricon = num; this.netname = #id; }
+
+REGISTER_WAYPOINT(Null, "", '0 0 0', 1);
+
+REGISTER_RADARICON(NONE, 0);
+REGISTER_RADARICON(FLAG, 1);
+REGISTER_RADARICON(FLAGCARRIER, 1);
+
+// TODO make these 3 and 4, and make images for them
+REGISTER_RADARICON(HERE, 1);
+REGISTER_RADARICON(DANGER, 1);
+
+REGISTER_RADARICON(WAYPOINT, 1);
+REGISTER_RADARICON(HELPME, 1);
+REGISTER_RADARICON(CONTROLPOINT, 1);
+REGISTER_RADARICON(GENERATOR, 1);
+REGISTER_RADARICON(OBJECTIVE, 1);
+REGISTER_RADARICON(DOMPOINT, 1);
+REGISTER_RADARICON(TAGGED, 1);
+
+REGISTER_RADARICON(Buff, 1);
+REGISTER_RADARICON(Item, 1);
+REGISTER_RADARICON(Vehicle, 1);
+REGISTER_RADARICON(Weapon, 1);
+
#include "all.inc"
#endif
if (sendflags & 32)
{
int f = ReadByte();
- self.teamradar_icon = (f & 0x7F);
- if (f & 0x80)
+ self.teamradar_icon = f & BITS(7);
+ if (f & BIT(7))
{
self.(teamradar_times[self.teamradar_time_index]) = time;
self.teamradar_time_index = (self.teamradar_time_index + 1) % MAX_TEAMRADAR_TIMES;
return 1;
}
-vector spritelookupcolor(string s, vector def)
-{SELFPARAM();
- if (s == WP_Weapon.netname) return get_weaponinfo(self.wp_extra).wpcolor;
- if (s == WP_Item.netname) return Items[self.wp_extra].m_color;
- if (s == WP_Buff.netname) return Buffs[self.wp_extra].m_color;
+vector spritelookupcolor(entity this, string s, vector def)
+{
+ if (s == WP_Weapon.netname || s == RADARICON_Weapon.netname) return get_weaponinfo(this.wp_extra).wpcolor;
+ if (s == WP_Item.netname || s == RADARICON_Item.netname) return Items[this.wp_extra].m_color;
+ if (s == WP_Buff.netname || s == RADARICON_Buff.netname) return Buffs[this.wp_extra].m_color;
return def;
}
else if (self.maxdistance > 0)
a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
- vector rgb = spritelookupcolor(spriteimage, self.teamradar_color);
+ vector rgb = spritelookupcolor(self, spriteimage, self.teamradar_color);
if (rgb == '0 0 0')
{
self.teamradar_color = '1 0 1';
e.SendFlags |= 1;
}
-void WaypointSprite_UpdateTeamRadar(entity e, float icon, vector col)
+void WaypointSprite_UpdateTeamRadar(entity e, entity icon, vector col)
{
// no check, as this is never called without doing an actual change (usually only once)
- e.cnt = (icon & 0x7F) | (e.cnt & 0x80);
+ int i = icon.m_id;
+ e.cnt = (e.cnt & BIT(7)) | (i & BITS(7));
e.colormod = col;
e.SendFlags |= 32;
}
if (time < e.waypointsprite_pingtime) return;
e.waypointsprite_pingtime = time + 0.3;
// ALWAYS sends (this causes a radar circle), thus no check
- e.cnt |= 0x80;
+ e.cnt |= BIT(7);
e.SendFlags |= 32;
}
entity showto, float t, // show to whom? Use a flag to indicate a team
entity own, .entity ownfield, // remove when own gets killed
float hideable, // true when it should be controlled by cl_hidewaypoints
- float icon // initial icon
+ entity icon // initial icon
)
{
entity wp = new(sprite_waypoint);
wp.customizeentityforclient = WaypointSprite_Customize;
wp.waypointsprite_visible_for_player = WaypointSprite_visible_for_player;
wp.reset2 = WaypointSprite_Reset;
- wp.cnt = icon;
+ wp.cnt = icon.m_id;
wp.colormod = spr.m_color;
Net_LinkEntity(wp, false, 0, WaypointSprite_SendEntity);
return wp;
vector ofs,
entity own,
.entity ownfield,
- float icon // initial icon
+ entity icon // initial icon
)
{
return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, own, ownfield, true, icon);
entity spr,
float limited_range,
vector ofs,
- float icon // initial icon
+ entity icon // initial icon
)
{SELFPARAM();
float t;
entity WaypointSprite_DeployPersonal(
entity spr,
vector ofs,
- float icon // initial icon
+ entity icon // initial icon
)
{SELFPARAM();
return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, self, waypointsprite_deployed_personal, false, icon);
entity WaypointSprite_Attach(
entity spr,
float limited_range,
- float icon // initial icon
+ entity icon // initial icon
)
{SELFPARAM();
float t;
entity WaypointSprite_AttachCarrier(
entity spr,
entity carrier,
- float icon // initial icon and color
+ entity icon // initial icon and color
)
{
WaypointSprite_Kill(carrier.waypointsprite_attached); // FC overrides attached
vector drawspritetext(vector o, float ang, float minwidth, vector rgb, float a, vector fontsize, string s);
float spritelookupblinkvalue(string s);
-vector spritelookupcolor(string s, vector def);
+vector spritelookupcolor(entity this, string s, vector def);
string spritelookuptext(string s);
vector fixrgbexcess_move(vector rgb, vector src, vector dst);
void WaypointSprite_UpdateRule(entity e, float t, float r);
-void WaypointSprite_UpdateTeamRadar(entity e, float icon, vector col);
+void WaypointSprite_UpdateTeamRadar(entity e, entity icon, vector col);
.float waypointsprite_pingtime;
.float waypointsprite_helpmetime;
entity showto, float t, // show to whom? Use a flag to indicate a team
entity own, .entity ownfield, // remove when own gets killed
float hideable, // true when it should be controlled by cl_hidewaypoints
- float icon // initial icon
+ entity icon // initial icon
);
entity WaypointSprite_SpawnFixed(
vector ofs,
entity own,
.entity ownfield,
- float icon // initial icon
+ entity icon // initial icon
);
.entity waypointsprite_deployed_fixed;
entity spr,
float limited_range,
vector ofs,
- float icon // initial icon
+ entity icon // initial icon
);
.entity waypointsprite_deployed_personal;
entity WaypointSprite_DeployPersonal(
entity spr,
vector ofs,
- float icon // initial icon
+ entity icon // initial icon
);
.entity waypointsprite_attached;
entity WaypointSprite_Attach(
entity spr,
float limited_range,
- float icon // initial icon
+ entity icon // initial icon
);
entity WaypointSprite_AttachCarrier(
entity spr,
entity carrier,
- float icon // initial icon
+ entity icon // initial icon
);
void WaypointSprite_DetachCarrier(entity carrier);
string spriteimage = self.netname;
float a = self.alpha * autocvar_hud_panel_fg_alpha;
- vector rgb = spritelookupcolor(spriteimage, self.teamradar_color);
+ vector rgb = spritelookupcolor(self, spriteimage, self.teamradar_color);
if(self.maxdistance > waypointsprite_normdistance)
#define GET(name) name##get
#define GETTER(type, name) type GET(name)() { return name; }
-#define BIT(n) (1 << (n))
-#ifndef BRANCHLESS_BITSET
- #define BITSET(var, mask, flag) (flag ? (var) | (mask) : (var) &~ (mask))
-#else
- #define BITSET(var, mask, flag) ((var) ^ (-(flag) ^ (var)) & (mask))
-#endif
-
#endif
}
#endif
-string unescape(string in)
-{
- float i, len;
- string str, s;
-
- // but it doesn't seem to be necessary in my tests at least
- in = strzone(in);
-
- len = strlen(in);
- str = "";
- for(i = 0; i < len; ++i)
- {
- s = substring(in, i, 1);
- if(s == "\\")
- {
- s = substring(in, i+1, 1);
- if(s == "n")
- str = strcat(str, "\n");
- else if(s == "\\")
- str = strcat(str, "\\");
- else
- str = strcat(str, substring(in, i, 2));
- ++i;
- } else
- str = strcat(str, s);
- }
-
- strunzone(in);
- return str;
-}
-
void wordwrap_cb(string s, float l, void(string) callback)
{
string c;
strunzone(s);
}
-float dist_point_line(vector p, vector l0, vector ldir)
-{
- ldir = normalize(ldir);
-
- // remove the component in line direction
- p = p - (p * ldir) * ldir;
-
- // vlen of the remaining vector
- return vlen(p);
-}
-
void depthfirst(entity start, .entity up, .entity downleft, .entity right, void(entity, entity) funcPre, void(entity, entity) funcPost, entity pass)
{
entity e;
}
}
-float median(float a, float b, float c)
-{
- if(a < c)
- return bound(a, b, c);
- return bound(c, b, a);
-}
-
// converts a number to a string with the indicated number of decimals
// works for up to 10 decimals!
string ftos_decimals(float number, float decimals)
return sprintf("%.*f", decimals, number);
}
-vector colormapPaletteColor(float c, float isPants)
+vector colormapPaletteColor(float c, bool isPants)
{
- switch(c)
+ switch (c)
{
case 0: return '1.000000 1.000000 1.000000';
case 1: return '1.000000 0.333333 0.000000';
case 13: return '0.000000 0.333333 1.000000';
case 14: return '1.000000 0.666667 0.000000';
case 15:
- if(isPants)
+ if (isPants)
return
'1 0 0' * (0.502 + 0.498 * sin(time / 2.7182818285 + 0.0000000000))
+ '0 1 0' * (0.502 + 0.498 * sin(time / 2.7182818285 + 2.0943951024))
}
}
-// unzone the string, and return it as tempstring. Safe to be called on string_null
-string fstrunzone(string s)
-{
- string sc;
- if (!s)
- return s;
- sc = strcat(s, "");
- strunzone(s);
- return sc;
-}
-
// Databases (hash tables)
const float DB_BUCKETS = 8192;
void db_save(float db, string pFilename)
return i;
}
-float almost_equals(float a, float b)
-{
- float eps;
- eps = (max(a, -a) + max(b, -b)) * 0.001;
- if(a - b < eps && b - a < eps)
- return true;
- return false;
-}
-
-float almost_in_bounds(float a, float b, float c)
-{
- float eps;
- eps = (max(a, -a) + max(c, -c)) * 0.001;
- if(a > c)
- eps = -eps;
- return b == median(a - eps, b, c + eps);
-}
-
-float power2of(float e)
-{
- return pow(2, e);
-}
-float log2of(float x)
-{
- // NOTE: generated code
- if(x > 2048)
- if(x > 131072)
- if(x > 1048576)
- if(x > 4194304)
- return 23;
- else
- if(x > 2097152)
- return 22;
- else
- return 21;
- else
- if(x > 524288)
- return 20;
- else
- if(x > 262144)
- return 19;
- else
- return 18;
- else
- if(x > 16384)
- if(x > 65536)
- return 17;
- else
- if(x > 32768)
- return 16;
- else
- return 15;
- else
- if(x > 8192)
- return 14;
- else
- if(x > 4096)
- return 13;
- else
- return 12;
- else
- if(x > 32)
- if(x > 256)
- if(x > 1024)
- return 11;
- else
- if(x > 512)
- return 10;
- else
- return 9;
- else
- if(x > 128)
- return 8;
- else
- if(x > 64)
- return 7;
- else
- return 6;
- else
- if(x > 4)
- if(x > 16)
- return 5;
- else
- if(x > 8)
- return 4;
- else
- return 3;
- else
- if(x > 2)
- return 2;
- else
- if(x > 1)
- return 1;
- else
- return 0;
-}
-
float rgb_mi_ma_to_hue(vector rgb, float mi, float ma)
{
if(mi == ma)
);
}
-// requires that m2>m1 in all coordinates, and that m4>m3
-float boxesoverlap(vector m1, vector m2, vector m3, vector m4) {return m2_x >= m3_x && m1_x <= m4_x && m2_y >= m3_y && m1_y <= m4_y && m2_z >= m3_z && m1_z <= m4_z;}
-
-// requires the same, but is a stronger condition
-float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) {return smins.x >= bmins.x && smaxs.x <= bmaxs.x && smins.y >= bmins.y && smaxs.y <= bmaxs.y && smins.z >= bmins.z && smaxs.z <= bmaxs.z;}
-
-#ifndef MENUQC
-#endif
-
float textLengthUpToWidth(string theText, float maxWidth, vector theSize, textLengthUpToWidth_widthFunction_t w)
{
// STOP.
return 1;
}
-string substring_range(string s, float b, float e)
-{
- return substring(s, b, e - b);
-}
-
-string swapwords(string str, float i, float j)
-{
- float n;
- string s1, s2, s3, s4, s5;
- float si, ei, sj, ej, s0, en;
- n = tokenizebyseparator(str, " "); // must match g_maplist processing in ShuffleMaplist and "shuffle"
- si = argv_start_index(i);
- sj = argv_start_index(j);
- ei = argv_end_index(i);
- ej = argv_end_index(j);
- s0 = argv_start_index(0);
- en = argv_end_index(n-1);
- s1 = substring_range(str, s0, si);
- s2 = substring_range(str, si, ei);
- s3 = substring_range(str, ei, sj);
- s4 = substring_range(str, sj, ej);
- s5 = substring_range(str, ej, en);
- return strcat(s1, s4, s3, s2, s5);
-}
-
-string _shufflewords_str;
-void _shufflewords_swapfunc(float i, float j, entity pass)
-{
- _shufflewords_str = swapwords(_shufflewords_str, i, j);
-}
-string shufflewords(string str)
-{
- float n;
- _shufflewords_str = str;
- n = tokenizebyseparator(str, " ");
- shuffle(n, _shufflewords_swapfunc, world);
- str = _shufflewords_str;
- _shufflewords_str = string_null;
- return str;
-}
-
vector solve_quadratic(float a, float b, float c) // ax^2 + bx + c = 0
{
vector v;
return v;
}
-
-void RandomSelection_Init()
-{
- RandomSelection_totalweight = 0;
- RandomSelection_chosen_ent = world;
- RandomSelection_chosen_float = 0;
- RandomSelection_chosen_string = string_null;
- RandomSelection_best_priority = -1;
-}
-void RandomSelection_Add(entity e, float f, string s, float weight, float priority)
-{
- if(priority > RandomSelection_best_priority)
- {
- RandomSelection_best_priority = priority;
- RandomSelection_chosen_ent = e;
- RandomSelection_chosen_float = f;
- RandomSelection_chosen_string = s;
- RandomSelection_totalweight = weight;
- }
- else if(priority == RandomSelection_best_priority)
- {
- RandomSelection_totalweight += weight;
- if(random() * RandomSelection_totalweight <= weight)
- {
- RandomSelection_chosen_ent = e;
- RandomSelection_chosen_float = f;
- RandomSelection_chosen_string = s;
- }
- }
-}
-
#ifndef MENUQC
vector healtharmor_maxdamage(float h, float a, float armorblock, int deathtype)
{
return argv(n - 1);
}
-#ifndef MENUQC
-#ifdef CSQC
-int ReadInt24_t()
-{
- int v = ReadShort() * 256; // note: this is signed
- 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)
-{
- float v;
- 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
-
-float float2range11(float f)
-{
- // continuous function mapping all reals into -1..1
- return f / (fabs(f) + 1);
-}
-
-float float2range01(float f)
-{
- // continuous function mapping all reals into 0..1
- return 0.5 + 0.5 * float2range11(f);
-}
-
// from the GNU Scientific Library
float gsl_ran_gaussian_lastvalue;
float gsl_ran_gaussian_lastvalue_set;
}
}
-string car(string s)
-{
- float o;
- o = strstrofs(s, " ", 0);
- if(o < 0)
- return s;
- return substring(s, 0, o);
-}
-string cdr(string s)
-{
- float o;
- o = strstrofs(s, " ", 0);
- if(o < 0)
- return string_null;
- return substring(s, o + 1, strlen(s) - (o + 1));
-}
float matchacl(string acl, string str)
{
string t, s;
}
return r;
}
-float startsWith(string haystack, string needle)
-{
- return substring(haystack, 0, strlen(needle)) == needle;
-}
-float startsWithNocase(string haystack, string needle)
-{
- return strcasecmp(substring(haystack, 0, strlen(needle)), needle) == 0;
-}
string get_model_datafilename(string m, float sk, string fil)
{
return 1;
}
-vector vec2(vector v)
-{
- v.z = 0;
- return v;
-}
-
-#ifndef MENUQC
-vector NearestPointOnBox(entity box, vector org)
-{
- vector m1, m2, nearest;
-
- m1 = box.mins + box.origin;
- m2 = box.maxs + box.origin;
-
- nearest.x = bound(m1_x, org.x, m2_x);
- nearest.y = bound(m1_y, org.y, m2_y);
- nearest.z = bound(m1_z, org.z, m2_z);
-
- return nearest;
-}
-#endif
-
float vercmp_recursive(string v1, string v2)
{
float dot1, dot2;
return vercmp_recursive(v1, v2);
}
-float u8_strsize(string s)
-{
- float l, i, c;
- l = 0;
- for(i = 0; ; ++i)
- {
- c = str2chr(s, i);
- if(c <= 0)
- break;
- ++l;
- if(c >= 0x80)
- ++l;
- if(c >= 0x800)
- ++l;
- if(c >= 0x10000)
- ++l;
- }
- return l;
-}
-
// x-encoding (encoding as zero length invisible string)
const string XENCODE_2 = "xX";
const string XENCODE_22 = "0123456789abcdefABCDEF";
return ((a * 22 + b) * 22 + c) * 22 + d;
}
-int lowestbit(int f)
-{
- f &= ~(f * 2);
- f &= ~(f * 4);
- f &= ~(f * 16);
- f &= ~(f * 256);
- f &= ~(f * 65536);
- return f;
-}
-
/*
string strlimitedlen(string input, string truncation, float strip_colors, float limit)
{
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;
-}
-
#ifdef CSQC
entity ReadCSQCEntity()
{
to_execute_next_frame = strzone(s);
}
-float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float x)
-{
- return
- ((( startspeedfactor + endspeedfactor - 2
- ) * x - 2 * startspeedfactor - endspeedfactor + 3
- ) * x + startspeedfactor
- ) * x;
-}
-
-float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor)
-{
- if(startspeedfactor < 0 || endspeedfactor < 0)
- return false;
-
- /*
- // if this is the case, the possible zeros of the first derivative are outside
- // 0..1
- We can calculate this condition as condition
- if(se <= 3)
- return true;
- */
-
- // better, see below:
- if(startspeedfactor <= 3 && endspeedfactor <= 3)
- return true;
-
- // if this is the case, the first derivative has no zeros at all
- float se = startspeedfactor + endspeedfactor;
- float s_e = startspeedfactor - endspeedfactor;
- if(3 * (se - 4) * (se - 4) + s_e * s_e <= 12) // an ellipse
- return true;
-
- // Now let s <= 3, s <= 3, s+e >= 3 (triangle) then we get se <= 6 (top right corner).
- // we also get s_e <= 6 - se
- // 3 * (se - 4)^2 + (6 - se)^2
- // is quadratic, has value 12 at 3 and 6, and value < 12 in between.
- // Therefore, above "better" check works!
-
- return false;
-
- // known good cases:
- // (0, [0..3])
- // (0.5, [0..3.8])
- // (1, [0..4])
- // (1.5, [0..3.9])
- // (2, [0..3.7])
- // (2.5, [0..3.4])
- // (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;
void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass)
{
queue_start.FindConnectedComponent_processing = 0;
}
-#ifdef SVQC
-vector combine_to_vector(float x, float y, float z)
-{
- vector result; result_x = x; result_y = y; result_z = z;
- return result;
-}
-
-vector get_corner_position(entity box, float corner)
-{
- switch(corner)
- {
- case 1: return combine_to_vector(box.absmin.x, box.absmin.y, box.absmin.z);
- case 2: return combine_to_vector(box.absmax.x, box.absmin.y, box.absmin.z);
- case 3: return combine_to_vector(box.absmin.x, box.absmax.y, box.absmin.z);
- case 4: return combine_to_vector(box.absmin.x, box.absmin.y, box.absmax.z);
- case 5: return combine_to_vector(box.absmax.x, box.absmax.y, box.absmin.z);
- case 6: return combine_to_vector(box.absmin.x, box.absmax.y, box.absmax.z);
- case 7: return combine_to_vector(box.absmax.x, box.absmin.y, box.absmax.z);
- case 8: return combine_to_vector(box.absmax.x, box.absmax.y, box.absmax.z);
- default: return '0 0 0';
- }
-}
-#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)
{
return CONTENT_EMPTY;
}
#endif
-
-vector bezier_quadratic_getpoint(vector a, vector b, vector c, float t)
-{
- return
- (c - 2 * b + a) * (t * t) +
- (b - a) * (2 * t) +
- a;
-}
-
-vector bezier_quadratic_getderivative(vector a, vector b, vector c, float t)
-{
- return
- (c - 2 * b + a) * (2 * t) +
- (b - a) * 2;
-}
string records_reply[10];
#endif
-float RandomSelection_totalweight;
-float RandomSelection_best_priority;
-entity RandomSelection_chosen_ent;
-float RandomSelection_chosen_float;
-string RandomSelection_chosen_string;
-void RandomSelection_Init();
-void RandomSelection_Add(entity e, float f, string s, float weight, float priority);
-
#ifndef MENUQC
vector healtharmor_maxdamage(float h, float a, float armorblock, int deathtype); // returns vector: maxdamage, armorideal, 1 if fully armored
vector healtharmor_applydamage(float a, float armorblock, int deathtype, float damage); // returns vector: take, save, 0
string xencode(float f);
float xdecode(string s);
-int lowestbit(float f);
-
#ifdef CSQC
entity ReadCSQCEntity();
#endif
typedef float(entity a, entity b, entity pass) isConnectedFunction_t;
void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass);
-#ifdef SVQC
-vector combine_to_vector(float x, float y, float z);
-vector get_corner_position(entity box, float corner);
-#endif
-
// expand multiple arguments into one argument by stripping parenthesis
#define XPD(...) __VA_ARGS__
#define fprintf(file, ...) fputs(file, sprintf(__VA_ARGS__))
#define bprintf(...) bprint(sprintf(__VA_ARGS__))
-// color code replace, place inside of sprintf and parse the string... defaults described as constants
-// foreground/normal colors
-string autocvar_hud_colorset_foreground_1 = "2"; // F1 - Green // primary priority (important names, etc)
-string autocvar_hud_colorset_foreground_2 = "3"; // F2 - Yellow // secondary priority (items, locations, numbers, etc)
-string autocvar_hud_colorset_foreground_3 = "4"; // F3 - Blue // tertiary priority or relatively inconsequential text
-string autocvar_hud_colorset_foreground_4 = "1"; // F4 - Red // notice/attention grabbing texting
-// "kill" colors
-string autocvar_hud_colorset_kill_1 = "1"; // K1 - Red // "bad" or "dangerous" text (death messages against you, kill notifications, etc)
-string autocvar_hud_colorset_kill_2 = "3"; // K2 - Yellow // similar to above, but less important... OR, a highlight out of above message type
-string autocvar_hud_colorset_kill_3 = "4"; // K3 - Blue // "good" or "beneficial" text (you fragging someone, etc)
-// background color
-string autocvar_hud_colorset_background = "7"; // BG - White // neutral/unimportant text
-
string CCR(string input);
#ifndef MENUQC
rgb = Team_ColorRGB(self.team);
else
rgb = '1 1 1';
- entity wp = WaypointSprite_Spawn(WP_Vehicle, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP);
+ entity wp = WaypointSprite_Spawn(WP_Vehicle, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_Vehicle);
wp.colormod = rgb;
if(self.waypointsprite_attached)
{
);
// figure out the direction of force
- vel = normalize(combine_to_vector(head.velocity.x, head.velocity.y, 0));
+ vel = normalize(vec3(head.velocity.x, head.velocity.y, 0));
vel *=
(
bound(0, (vlen(vel) / autocvar_sv_maxspeed), 1)
#include "../warpzonelib/mathlib.qc"
#include "accumulate.qh"
+#include "bits.qh"
#include "counting.qh"
#include "cvar.qh"
#include "defer.qh"
#include "oo.qh"
#include "p2mathlib.qc"
#include "player.qh"
-#include "prandom.qc"
#include "progname.qh"
+#include "random.qc"
#include "registry.qh"
#include "replicate.qh"
#include "sort.qh"
--- /dev/null
+#ifndef BITS_H
+#define BITS_H
+
+#define BIT(n) (1 << (n))
+#define BITS(n) (BIT(n) - 1)
+#ifndef BRANCHLESS_BITSET
+ #define BITSET(var, mask, flag) (flag ? (var) | (mask) : (var) &~ (mask))
+#else
+ #define BITSET(var, mask, flag) ((var) ^ (-(flag) ^ (var)) & (mask))
+#endif
+
+int lowestbit(int f)
+{
+ f &= ~(f << 1);
+ f &= ~(f << 2);
+ f &= ~(f << 4);
+ f &= ~(f << 8);
+ f &= ~(f << 16);
+ return f;
+}
+
+#endif
void RegisterCvars(void(string name, string def, string desc, bool archive, string file) f) { }
+/** 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;
+}
+
void RegisterCvars_Set(string name, string def, string desc, bool archive, string file)
{
string val = string_null;
// Need to unset first to change the default
localcmd(sprintf("\nunset %s\n", name));
}
- localcmd(sprintf("\n%s %s \"%s\" \"%s\"\n", (archive ? "seta" : "set"), name, def, desc));
+ localcmd(sprintf("\n%s %s \"%s\" \"%s\"\n", (archive ? "seta" : "set"), name, MakeConsoleSafe(def), MakeConsoleSafe(desc)));
if (val) {
- localcmd(sprintf("\n%s \"%s\"\n", name, val));
+ localcmd(sprintf("\n%s \"%s\"\n", name, MakeConsoleSafe(val)));
}
}
void mean_accumulate(entity e, .float a, .float c, float mean, float value, float weight)
{
- if (weight == 0)
- return;
- if (mean == 0)
- e.(a) *= pow(value, weight);
- else
- e.(a) += pow(value, mean) * weight;
- e.(c) += weight;
+ if (weight == 0)
+ return;
+ if (mean == 0)
+ e.(a) *= pow(value, weight);
+ else
+ e.(a) += pow(value, mean) * weight;
+ e.(c) += weight;
}
float mean_evaluate(entity e, .float a, .float c, float mean)
{
- if (e.(c) == 0)
- return 0;
- if (mean == 0)
- return pow(e.(a), 1.0 / e.(c));
- else
- return pow(e.(a) / e.(c), 1.0 / mean);
+ if (e.(c) == 0)
+ return 0;
+ if (mean == 0)
+ return pow(e.(a), 1.0 / e.(c));
+ else
+ return pow(e.(a) / e.(c), 1.0 / mean);
}
#define MEAN_ACCUMULATE(prefix,v,w) mean_accumulate(self,prefix##_accumulator,prefix##_count,prefix##_mean,v,w)
Returns a random number between -1.0 and 1.0
==================
*/
-float crandom (void)
+float crandom()
{
- return 2 * (random () - 0.5);
+ return 2 * (random() - 0.5);
}
*/
-float angc (float a1, float a2)
+float angc(float a1, float a2)
{
- float a;
-
- while (a1 > 180)
- a1 = a1 - 360;
- while (a1 < -179)
- a1 = a1 + 360;
-
- while (a2 > 180)
- a2 = a2 - 360;
- while (a2 < -179)
- a2 = a2 + 360;
-
- a = a1 - a2;
- while (a > 180)
- a = a - 360;
- while (a < -179)
- a = a + 360;
-
- return a;
+ while (a1 > 180) a1 -= 360;
+ while (a1 < -179) a1 += 360;
+ while (a2 > 180) a2 -= 360;
+ while (a2 < -179) a2 += 360;
+ float a = a1 - a2;
+ while (a > 180) a -= 360;
+ while (a < -179) a += 360;
+ return a;
}
float fsnap(float val,float fsize)
vector lerpv(float t0, vector v0, float t1, vector v1, float t)
{
- return v0 + (v1 - v0) * ((t - t0) / (t1 - t0));
+ return v0 + (v1 - v0) * ((t - t0) / (t1 - t0));
+}
+
+vector bezier_quadratic_getpoint(vector a, vector b, vector c, float t)
+{
+ return
+ (c - 2 * b + a) * (t * t) +
+ (b - a) * (2 * t) +
+ a;
+}
+
+vector bezier_quadratic_getderivative(vector a, vector b, vector c, float t)
+{
+ return
+ (c - 2 * b + a) * (2 * t) +
+ (b - a) * 2;
+}
+
+float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float x)
+{
+ return
+ ((( startspeedfactor + endspeedfactor - 2
+ ) * x - 2 * startspeedfactor - endspeedfactor + 3
+ ) * x + startspeedfactor
+ ) * x;
+}
+
+bool cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor)
+{
+ if (startspeedfactor < 0 || endspeedfactor < 0)
+ return false;
+
+ /*
+ // if this is the case, the possible zeros of the first derivative are outside
+ // 0..1
+ We can calculate this condition as condition
+ if(se <= 3)
+ return true;
+ */
+
+ // better, see below:
+ if (startspeedfactor <= 3 && endspeedfactor <= 3)
+ return true;
+
+ // if this is the case, the first derivative has no zeros at all
+ float se = startspeedfactor + endspeedfactor;
+ float s_e = startspeedfactor - endspeedfactor;
+ if (3 * (se - 4) * (se - 4) + s_e * s_e <= 12) // an ellipse
+ return true;
+
+ // Now let s <= 3, s <= 3, s+e >= 3 (triangle) then we get se <= 6 (top right corner).
+ // we also get s_e <= 6 - se
+ // 3 * (se - 4)^2 + (6 - se)^2
+ // is quadratic, has value 12 at 3 and 6, and value < 12 in between.
+ // Therefore, above "better" check works!
+
+ return false;
+
+ // known good cases:
+ // (0, [0..3])
+ // (0.5, [0..3.8])
+ // (1, [0..4])
+ // (1.5, [0..3.9])
+ // (2, [0..3.7])
+ // (2.5, [0..3.4])
+ // (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)
+ */
+}
+
+/** continuous function mapping all reals into -1..1 */
+float float2range11(float f)
+{
+ return f / (fabs(f) + 1);
}
+/** continuous function mapping all reals into 0..1 */
+float float2range01(float f)
+{
+ return 0.5 + 0.5 * float2range11(f);
+}
+
+float median(float a, float b, float c)
+{
+ return (a < c) ? bound(a, b, c) : bound(c, b, a);
+}
+
+float almost_equals(float a, float b)
+{
+ float eps = (max(a, -a) + max(b, -b)) * 0.001;
+ return a - b < eps && b - a < eps;
+}
+
+float almost_in_bounds(float a, float b, float c)
+{
+ float eps = (max(a, -a) + max(c, -c)) * 0.001;
+ if (a > c)
+ eps = -eps;
+ return b == median(a - eps, b, c + eps);
+}
+
+float power2of(float e)
+{
+ return pow(2, e);
+}
+
+float log2of(float x)
+{
+ // NOTE: generated code
+ if (x > 2048)
+ if (x > 131072)
+ if (x > 1048576)
+ if (x > 4194304)
+ return 23;
+ else
+ if (x > 2097152)
+ return 22;
+ else
+ return 21;
+ else
+ if (x > 524288)
+ return 20;
+ else
+ if (x > 262144)
+ return 19;
+ else
+ return 18;
+ else
+ if (x > 16384)
+ if (x > 65536)
+ return 17;
+ else
+ if (x > 32768)
+ return 16;
+ else
+ return 15;
+ else
+ if (x > 8192)
+ return 14;
+ else
+ if (x > 4096)
+ return 13;
+ else
+ return 12;
+ else
+ if (x > 32)
+ if (x > 256)
+ if (x > 1024)
+ return 11;
+ else
+ if (x > 512)
+ return 10;
+ else
+ return 9;
+ else
+ if (x > 128)
+ return 8;
+ else
+ if (x > 64)
+ return 7;
+ else
+ return 6;
+ else
+ if (x > 4)
+ if (x > 16)
+ return 5;
+ else
+ if (x > 8)
+ return 4;
+ else
+ return 3;
+ else
+ if (x > 2)
+ return 2;
+ else
+ if (x > 1)
+ return 1;
+ else
+ return 0;
+}
+
+
#endif
}
}
+#ifndef MENUQC
+#ifdef CSQC
+int ReadInt24_t()
+{
+ int v = ReadShort() << 8; // note: this is signed
+ 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)
+{
+ float v;
+ WriteShort(dst, (v = floor(val >> 8)));
+ WriteByte(dst, val - (v << 8)); // 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
+
#endif
+++ /dev/null
-#include "prandom.qh"
-
-// prandom - PREDICTABLE random number generator (not seeded yet)
-
-#ifdef USE_PRANDOM
-float prandom_seed;
-float prandom()
-{
- float c;
- c = crc16(false, strcat(ftos(prandom_seed), ftos(prandom_seed + M_PI)));
- prandom_seed = c;
-
-#ifdef USE_PRANDOM_DEBUG
- LOG_TRACE("RANDOM -> ", ftos(c), "\n");
-#endif
-
- return c / 65536; // in [0..1[
-}
-
-vector prandomvec()
-{
- vector v;
-
- do
- {
- v.x = prandom();
- v.y = prandom();
- v.z = prandom();
- }
- while(v * v > 1);
-
- return v;
-}
-
-void psrandom(float seed)
-{
- prandom_seed = seed;
-#ifdef USE_PRANDOM_DEBUG
- LOG_TRACE("SRANDOM ", ftos(seed), "\n");
-#endif
-}
-
-#ifdef USE_PRANDOM_DEBUG
-void prandom_debug()
-{
- LOG_TRACE("Current random seed = ", ftos(prandom_seed), "\n");
-}
-#endif
-#endif
+++ /dev/null
-#ifndef PRANDOM_H
-#define PRANDOM_H
-
-// prandom - PREDICTABLE random number generator
-
-#define USE_PRANDOM
-
-#ifdef USE_PRANDOM
-float prandom();
-vector prandomvec();
-
-void psrandom(float seed);
-#ifdef USE_PRANDOM_DEBUG
-void prandom_debug();
-#else
-#define prandom_debug()
-#endif
-#else
-#define prandom random
-#define prandomvec randomvec
-#define psrandom(x)
-#define prandom_debug()
-#endif
-#endif
--- /dev/null
+#include "random.qh"
+
+void RandomSelection_Init()
+{
+ RandomSelection_totalweight = 0;
+ RandomSelection_chosen_ent = NULL;
+ RandomSelection_chosen_float = 0;
+ RandomSelection_chosen_string = string_null;
+ RandomSelection_best_priority = -1;
+}
+
+void RandomSelection_Add(entity e, float f, string s, float weight, float priority)
+{
+ if (priority > RandomSelection_best_priority)
+ {
+ RandomSelection_best_priority = priority;
+ RandomSelection_chosen_ent = e;
+ RandomSelection_chosen_float = f;
+ RandomSelection_chosen_string = s;
+ RandomSelection_totalweight = weight;
+ }
+ else if (priority == RandomSelection_best_priority)
+ {
+ RandomSelection_totalweight += weight;
+ if (random() * RandomSelection_totalweight <= weight)
+ {
+ RandomSelection_chosen_ent = e;
+ RandomSelection_chosen_float = f;
+ RandomSelection_chosen_string = s;
+ }
+ }
+}
+
+
+// prandom - PREDICTABLE random number generator (not seeded yet)
+
+#ifdef USE_PRANDOM
+float prandom_seed;
+float prandom()
+{
+ float c;
+ c = crc16(false, strcat(ftos(prandom_seed), ftos(prandom_seed + M_PI)));
+ prandom_seed = c;
+
+#ifdef USE_PRANDOM_DEBUG
+ LOG_TRACE("RANDOM -> ", ftos(c), "\n");
+#endif
+
+ return c / 65536; // in [0..1[
+}
+
+vector prandomvec()
+{
+ vector v;
+
+ do
+ {
+ v.x = prandom();
+ v.y = prandom();
+ v.z = prandom();
+ }
+ while(v * v > 1);
+
+ return v;
+}
+
+void psrandom(float seed)
+{
+ prandom_seed = seed;
+#ifdef USE_PRANDOM_DEBUG
+ LOG_TRACE("SRANDOM ", ftos(seed), "\n");
+#endif
+}
+
+#ifdef USE_PRANDOM_DEBUG
+void prandom_debug()
+{
+ LOG_TRACE("Current random seed = ", ftos(prandom_seed), "\n");
+}
+#endif
+#endif
--- /dev/null
+#ifndef RANDOM_H
+#define RANDOM_H
+
+float RandomSelection_totalweight;
+float RandomSelection_best_priority;
+entity RandomSelection_chosen_ent;
+float RandomSelection_chosen_float;
+string RandomSelection_chosen_string;
+
+void RandomSelection_Init();
+void RandomSelection_Add(entity e, float f, string s, float weight, float priority);
+
+// prandom - PREDICTABLE random number generator
+
+#define USE_PRANDOM
+
+#ifdef USE_PRANDOM
+float prandom();
+vector prandomvec();
+
+void psrandom(float seed);
+#ifdef USE_PRANDOM_DEBUG
+void prandom_debug();
+#else
+#define prandom_debug()
+#endif
+#else
+#define prandom random
+#define prandomvec randomvec
+#define psrandom(x)
+#define prandom_debug()
+#endif
+#endif
#ifndef SVQC
float stringwidth_colors(string s, vector theSize)
{
- return stringwidth(s, true, theSize);
+ return stringwidth(s, true, theSize);
}
float stringwidth_nocolors(string s, vector theSize)
{
- return stringwidth(s, false, theSize);
+ return stringwidth(s, false, theSize);
}
#endif
// TODO: macro
string seconds_tostring(float sec)
{
- float minutes;
- minutes = floor(sec / 60);
-
- sec -= minutes * 60;
- return sprintf("%d:%02d", minutes, sec);
+ float minutes = floor(sec / 60);
+ sec -= minutes * 60;
+ return sprintf("%d:%02d", minutes, sec);
}
int ColorTranslateMode;
string ColorTranslateRGB(string s)
{
- if(ColorTranslateMode & 1)
- return strdecolorize(s);
- else
- return s;
+ return (ColorTranslateMode & 1) ? strdecolorize(s) : s;
+}
+
+// color code replace, place inside of sprintf and parse the string... defaults described as constants
+// foreground/normal colors
+string autocvar_hud_colorset_foreground_1 = "2"; // F1 - Green // primary priority (important names, etc)
+string autocvar_hud_colorset_foreground_2 = "3"; // F2 - Yellow // secondary priority (items, locations, numbers, etc)
+string autocvar_hud_colorset_foreground_3 = "4"; // F3 - Blue // tertiary priority or relatively inconsequential text
+string autocvar_hud_colorset_foreground_4 = "1"; // F4 - Red // notice/attention grabbing texting
+// "kill" colors
+string autocvar_hud_colorset_kill_1 = "1"; // K1 - Red // "bad" or "dangerous" text (death messages against you, kill notifications, etc)
+string autocvar_hud_colorset_kill_2 = "3"; // K2 - Yellow // similar to above, but less important... OR, a highlight out of above message type
+string autocvar_hud_colorset_kill_3 = "4"; // K3 - Blue // "good" or "beneficial" text (you fragging someone, etc)
+// background color
+string autocvar_hud_colorset_background = "7"; // BG - White // neutral/unimportant text
+
+/** 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;
+}
+
+bool startsWith(string haystack, string needle)
+{
+ return substring(haystack, 0, strlen(needle)) == needle;
+}
+
+bool startsWithNocase(string haystack, string needle)
+{
+ return strcasecmp(substring(haystack, 0, strlen(needle)), needle) == 0;
+}
+
+/** unzone the string, and return it as tempstring. Safe to be called on string_null */
+string fstrunzone(string s)
+{
+ if (!s) return s;
+ string sc = strcat(s, "");
+ strunzone(s);
+ return sc;
+}
+
+string car(string s)
+{
+ int o = strstrofs(s, " ", 0);
+ if (o < 0) return s;
+ return substring(s, 0, o);
+}
+
+string cdr(string s)
+{
+ int o = strstrofs(s, " ", 0);
+ if (o < 0) return string_null;
+ return substring(s, o + 1, strlen(s) - (o + 1));
+}
+
+string substring_range(string s, float b, float e)
+{
+ return substring(s, b, e - b);
+}
+
+string swapwords(string str, float i, float j)
+{
+ float n;
+ string s1, s2, s3, s4, s5;
+ float si, ei, sj, ej, s0, en;
+ n = tokenizebyseparator(str, " "); // must match g_maplist processing in ShuffleMaplist and "shuffle"
+ si = argv_start_index(i);
+ sj = argv_start_index(j);
+ ei = argv_end_index(i);
+ ej = argv_end_index(j);
+ s0 = argv_start_index(0);
+ en = argv_end_index(n-1);
+ s1 = substring_range(str, s0, si);
+ s2 = substring_range(str, si, ei);
+ s3 = substring_range(str, ei, sj);
+ s4 = substring_range(str, sj, ej);
+ s5 = substring_range(str, ej, en);
+ return strcat(s1, s4, s3, s2, s5);
+}
+
+string _shufflewords_str;
+void _shufflewords_swapfunc(float i, float j, entity pass)
+{
+ _shufflewords_str = swapwords(_shufflewords_str, i, j);
+}
+string shufflewords(string str)
+{
+ _shufflewords_str = str;
+ int n = tokenizebyseparator(str, " ");
+ shuffle(n, _shufflewords_swapfunc, NULL);
+ str = _shufflewords_str;
+ _shufflewords_str = string_null;
+ return str;
+}
+
+string unescape(string in)
+{
+ in = strzone(in); // but it doesn't seem to be necessary in my tests at least
+
+ int len = strlen(in);
+ string str = "";
+ for (int i = 0; i < len; ++i) {
+ string s = substring(in, i, 1);
+ if (s == "\\") {
+ s = substring(in, i + 1, 1);
+ if (s == "n")
+ str = strcat(str, "\n");
+ else if (s == "\\")
+ str = strcat(str, "\\");
+ else
+ str = strcat(str, substring(in, i, 2));
+ ++i;
+ continue;
+ }
+ str = strcat(str, s);
+ }
+ strunzone(in);
+ return str;
+}
+
+string strwords(string s, int w)
+{
+ int endpos = 0;
+ for (; w && endpos >= 0; --w) endpos = strstrofs(s, " ", endpos + 1);
+ if (endpos < 0) return s;
+ return substring(s, 0, endpos);
+}
+
+bool strhasword(string s, string w)
+{
+ return strstrofs(strcat(" ", s, " "), strcat(" ", w, " "), 0) >= 0;
+}
+
+int u8_strsize(string s)
+{
+ int l = 0;
+ for (int i = 0, c; (c = str2chr(s, i)) > 0; ++i, ++l)
+ {
+ l += (c >= 0x80);
+ l += (c >= 0x800);
+ l += (c >= 0x10000);
+ }
+ return l;
}
#endif
vector randompos(vector m1, vector m2)
{
- vector v;
- m2 = m2 - m1;
- v_x = m2_x * random() + m1_x;
- v_y = m2_y * random() + m1_y;
- v_z = m2_z * random() + m1_z;
- return v;
+ vector v;
+ m2 = m2 - m1;
+ v_x = m2_x * random() + m1_x;
+ v_y = m2_y * random() + m1_y;
+ v_z = m2_z * random() + m1_z;
+ return v;
}
float vlen2d(vector v)
{
- return sqrt(v.x * v.x + v.y * v.y);
+ return sqrt(v.x * v.x + v.y * v.y);
}
float vlen_maxnorm2d(vector v)
{
- return max(v.x, v.y, -v.x, -v.y);
+ return max(v.x, v.y, -v.x, -v.y);
}
float vlen_minnorm2d(vector v)
{
- return min(max(v.x, -v.x), max(v.y, -v.y));
+ return min(max(v.x, -v.x), max(v.y, -v.y));
}
+float dist_point_line(vector p, vector l0, vector ldir)
+{
+ ldir = normalize(ldir);
+
+ // remove the component in line direction
+ p = p - (p * ldir) * ldir;
+
+ // vlen of the remaining vector
+ return vlen(p);
+}
+
+/** requires that m2>m1 in all coordinates, and that m4>m3 */
+float boxesoverlap(vector m1, vector m2, vector m3, vector m4) {return m2_x >= m3_x && m1_x <= m4_x && m2_y >= m3_y && m1_y <= m4_y && m2_z >= m3_z && m1_z <= m4_z;}
+
+/** requires the same as boxesoverlap, but is a stronger condition */
+float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) {return smins.x >= bmins.x && smaxs.x <= bmaxs.x && smins.y >= bmins.y && smaxs.y <= bmaxs.y && smins.z >= bmins.z && smaxs.z <= bmaxs.z;}
+
+
+vector vec2(vector v)
+{
+ v.z = 0;
+ return v;
+}
+
+vector vec3(float x, float y, float z)
+{
+ vector v; v.x = x; v.y = y; v.z = z;
+ return v;
+}
+
+#ifndef MENUQC
+vector get_corner_position(entity box, int corner)
+{
+ switch (corner) {
+ case 1: return vec3(box.absmin.x, box.absmin.y, box.absmin.z);
+ case 2: return vec3(box.absmax.x, box.absmin.y, box.absmin.z);
+ case 3: return vec3(box.absmin.x, box.absmax.y, box.absmin.z);
+ case 4: return vec3(box.absmin.x, box.absmin.y, box.absmax.z);
+ case 5: return vec3(box.absmax.x, box.absmax.y, box.absmin.z);
+ case 6: return vec3(box.absmin.x, box.absmax.y, box.absmax.z);
+ case 7: return vec3(box.absmax.x, box.absmin.y, box.absmax.z);
+ case 8: return vec3(box.absmax.x, box.absmax.y, box.absmax.z);
+ default: return '0 0 0';
+ }
+}
+
+vector NearestPointOnBox(entity box, vector org)
+{
+ vector m1 = box.mins + box.origin;
+ vector m2 = box.maxs + box.origin;
+
+ vector ret;
+ ret.x = bound(m1.x, org.x, m2.x);
+ ret.y = bound(m1.y, org.y, m2.y);
+ ret.z = bound(m1.z, org.z, m2.z);
+ return ret;
+}
+#endif
#endif
else
stuffcmd(self, "set _teams_available 0\n");
- attach_entcs();
+ attach_entcs(self);
bot_relinkplayerlist();
bot_clientdisconnect();
- if(self.entcs)
- detach_entcs();
+ detach_entcs(self);
if(autocvar_sv_eventlog)
GameLogEcho(strcat(":part:", ftos(self.playerid)));
+#include "ent_cs.qh"
#include "_all.qh"
-#include "defs.qh"
-#include "mutators/mutators_include.qh"
-
-/**
- * The point of these entities is to avoid the problems
- * with clientprediction.
- * If you add SendEntity to players, the engine will not
- * do any prediction anymore, and you'd have to write the whole
- * prediction code in CSQC, you want that? :P
- * Data can depend on gamemode. For now, it serves as GPS entities
- * in onslaught... YAY ;)
- */
-
-// Beware: do not redefine those in other files
-// and NO, you cannot use ".version", which already exists (at least
-// it did when I added this) But you have to use .Version
-// Capital V
-
-.entity entcs;
-
-void entcs_init()
-{
- LOG_INFO("Initializing ClientSide information entities\n");
-}
-
float entcs_customize()
-{SELFPARAM();
- entity o;
- o = self.owner;
+{
+ SELFPARAM();
+ entity o = self.owner;
if(o.deadflag != DEAD_NO)
return false;
if (!IS_PLAYER(o))
{
WriteByte(MSG_ENTITY, ENT_CLIENT_ENTCS);
WriteByte(MSG_ENTITY, sf);
- if(sf & 1)
- WriteByte(MSG_ENTITY, num_for_edict(self.owner)-1);
- if(sf & 2)
+ if(sf & BIT(0))
+ WriteByte(MSG_ENTITY, num_for_edict(self.owner) - 1);
+ if(sf & BIT(1))
{
WriteShort(MSG_ENTITY, self.origin.x);
WriteShort(MSG_ENTITY, self.origin.y);
WriteShort(MSG_ENTITY, self.origin.z);
}
- if(sf & 4)
+ if(sf & BIT(2))
WriteByte(MSG_ENTITY, self.angles.y * 256.0 / 360);
- if(sf & 8)
+ if(sf & BIT(3))
WriteByte(MSG_ENTITY, self.health / 10); // FIXME use a better scale?
- if(sf & 16)
+ if(sf & BIT(4))
WriteByte(MSG_ENTITY, self.armorvalue / 10); // FIXME use a better scale?
return true;
}
void entcs_think()
-{SELFPARAM();
+{
+ SELFPARAM();
self.nextthink = time + 0.033333333333; // increase this to like 0.15 once the client can do smoothing
-
- entity o;
- o = self.owner;
-
- if(o.origin != self.origin)
+ entity o = self.owner;
+ if (o.origin != self.origin)
{
setorigin(self, o.origin);
- self.SendFlags |= 2;
+ self.SendFlags |= BIT(1);
}
- if(o.angles.y != self.angles.y)
+ if (o.angles.y != self.angles.y)
{
self.angles = o.angles;
- self.SendFlags |= 4;
+ self.SendFlags |= BIT(2);
}
- if(o.health != self.health)
+ if (o.health != self.health)
{
self.health = o.health;
- self.SendFlags |= 8;
+ self.SendFlags |= BIT(3);
}
- if(o.armorvalue != self.armorvalue)
+ if (o.armorvalue != self.armorvalue)
{
self.armorvalue = o.armorvalue;
- self.SendFlags |= 16;
+ self.SendFlags |= BIT(4);
}
}
-entity attach_entcs()
-{SELFPARAM();
- entity ent;
-
- ent = spawn();
- ent.classname = "entcs_sender_v2";
- ent.owner = self;
+entity attach_entcs(entity e)
+{
+ entity ent = e.entcs = new(entcs_sender);
+ ent.owner = e;
ent.think = entcs_think;
ent.nextthink = time;
Net_LinkEntity(ent, false, 0, entcs_send);
ent.customizeentityforclient = entcs_customize;
- self.entcs = ent;
-
return ent;
}
-void detach_entcs()
-{SELFPARAM();
- remove(self.entcs);
- self.entcs = world;
+void detach_entcs(entity e)
+{
+ if (!e.entcs) return;
+ remove(e.entcs);
+ e.entcs = NULL;
}
* in onslaught... YAY ;)
*/
-// Beware: do not redefine those in other files
-// and NO, you cannot use ".version", which already exists (at least
-// it did when I added this) But you have to use .Version
-// Capital V
-
.entity entcs;
-void entcs_init();
-
float entcs_customize();
bool entcs_send(entity this, entity to, int sf);
void entcs_think();
-entity attach_entcs();
+entity attach_entcs(entity e);
+
+void detach_entcs(entity e);
-void detach_entcs();
#endif
return strcat("maps/", argv(position), ".bsp");
}
-string strwords(string s, float w)
-{
- float endpos;
- for(endpos = 0; w && endpos >= 0; --w)
- endpos = strstrofs(s, " ", endpos + 1);
- if(endpos < 0)
- return s;
- else
- return substring(s, 0, endpos);
-}
-
-float strhasword(string s, string w)
-{
- return strstrofs(strcat(" ", s, " "), strcat(" ", w, " "), 0) >= 0;
-}
-
void Map_MarkAsRecent(string m)
{
cvar_set("g_maplist_mostrecent", strwords(strcat(m, " ", autocvar_g_maplist_mostrecent), max(0, autocvar_g_maplist_mostrecent_count)));
void buff_Waypoint_Spawn(entity e)
{
entity buff = buff_FirstFromFlags(e.buffs);
- entity wp = WaypointSprite_Spawn(WP_Buff, 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs.z, world, e.team, e, buff_waypoint, true, RADARICON_POWERUP);
+ entity wp = WaypointSprite_Spawn(WP_Buff, 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs.z, world, e.team, e, buff_waypoint, true, RADARICON_Buff);
wp.wp_extra = buff.m_id;
- WaypointSprite_UpdateTeamRadar(e.buff_waypoint, RADARICON_POWERUP, e.glowmod);
+ WaypointSprite_UpdateTeamRadar(e.buff_waypoint, RADARICON_Buff, e.glowmod);
e.buff_waypoint.waypointsprite_visible_for_player = buff_Waypoint_visible_for_player;
}
{
entity wi = get_weaponinfo(self.weapon);
if (wi.m_id) {
- entity wp = WaypointSprite_Spawn(WP_Weapon, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP);
+ entity wp = WaypointSprite_Spawn(WP_Weapon, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_Weapon);
wp.wp_extra = wi.m_id;
break;
}
{
entity ii = self.itemdef;
if (ii.m_id) {
- entity wp = WaypointSprite_Spawn(WP_Item, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP);
+ entity wp = WaypointSprite_Spawn(WP_Item, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_Item);
wp.wp_extra = ii.m_id;
break;
}
MUTATOR_ADD(gamemode_invasion);
}
- if(teamplay)
- entcs_init();
-
cache_mutatormsg = strzone("");
cache_lastmutatormsg = strzone("");
void TeamchangeFrags(entity e);
-void entcs_init();
-
void LogTeamchange(float player_id, float team_number, float type);
void default_delayedinit();
case "ent_client_scoreinfo":
case "saved_cvar_value":
case "accuracy":
- case "entcs_sender_v2":
- case "entcs_receiver_v2":
+ case "entcs_sender":
+ case "entcs_receiver":
case "clientinit":
case "sprite_waypoint":
case "waypoint":