]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Combine client/server waypointsprites
authorTimePath <andrew.hardaker1995@gmail.com>
Mon, 24 Aug 2015 06:54:19 +0000 (16:54 +1000)
committerTimePath <andrew.hardaker1995@gmail.com>
Mon, 24 Aug 2015 06:54:19 +0000 (16:54 +1000)
21 files changed:
qcsrc/client/main.qc
qcsrc/client/progs.src
qcsrc/client/view.qc
qcsrc/client/waypointsprites.qc [deleted file]
qcsrc/client/waypointsprites.qh [deleted file]
qcsrc/common/mutators/mutator/waypointsprites.qc
qcsrc/common/mutators/mutator/waypointsprites.qh [new file with mode: 0644]
qcsrc/common/triggers/func/breakable.qc
qcsrc/server/cl_client.qc
qcsrc/server/cl_impulse.qc
qcsrc/server/cl_player.qc
qcsrc/server/g_damage.qc
qcsrc/server/g_world.qc
qcsrc/server/mutators/gamemode.qh
qcsrc/server/mutators/mutator.qh
qcsrc/server/progs.src
qcsrc/server/race.qc
qcsrc/server/t_items.qc
qcsrc/server/waypointsprites.qc [deleted file]
qcsrc/server/waypointsprites.qh [deleted file]
qcsrc/server/weapons/selection.qc

index e39b3346a354ec5fc5b7f1d80a6c3cc9286f1670..0894b59911a0ad2e59672f0eb7814e1336103e5c 100644 (file)
@@ -22,7 +22,6 @@
 #include "tuba.qh"
 #include "t_items.qh"
 #include "wall.qh"
-#include "waypointsprites.qh"
 
 #include "../common/vehicles/all.qh"
 
index 9b687532ff43cb4a091d3eeb7cbc8010941f5dee..723b398060a16a5507c0d4bf8d7cd40527aa56b4 100644 (file)
@@ -34,7 +34,6 @@ tuba.qc
 t_items.qc
 view.qc
 wall.qc
-waypointsprites.qc
 
 command/all.qc
 
index e846a662b17996bd89b92854f6867aa22b22f240..2bc260ffcfcefc294e8aeb3f0f7bd0a171b026b4 100644 (file)
@@ -8,7 +8,6 @@
 #include "noise.qh"
 #include "scoreboard.qh"
 #include "shownames.qh"
-#include "waypointsprites.qh"
 
 #include "mutators/events.qh"
 
diff --git a/qcsrc/client/waypointsprites.qc b/qcsrc/client/waypointsprites.qc
deleted file mode 100644 (file)
index aa5ec5f..0000000
+++ /dev/null
@@ -1,756 +0,0 @@
-#include "waypointsprites.qh"
-#include "_all.qh"
-
-#include "hud.qh"
-#include "teamradar.qh"
-
-#include "../common/buffs.qh"
-#include "../common/constants.qh"
-#include "../common/teams.qh"
-
-#include "../common/weapons/all.qh"
-
-#include "../csqcmodellib/interpolate.qh"
-
-#include "../warpzonelib/mathlib.qh"
-
-.float alpha;
-
-void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f)
-{
-       vector v1, v2, v3, v4;
-
-       hotspot = -1 * hotspot;
-
-       // hotspot-relative coordinates of the corners
-       v1 = hotspot;
-       v2 = hotspot + '1 0 0' * sz.x;
-       v3 = hotspot + '1 0 0' * sz.x + '0 1 0' * sz.y;
-       v4 = hotspot                  + '0 1 0' * sz.y;
-
-       // rotate them, and make them absolute
-       rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed
-       v1 = rotate(v1, rot) + org;
-       v2 = rotate(v2, rot) + org;
-       v3 = rotate(v3, rot) + org;
-       v4 = rotate(v4, rot) + org;
-
-       // draw them
-       R_BeginPolygon(pic, f);
-       R_PolygonVertex(v1, '0 0 0', rgb, a);
-       R_PolygonVertex(v2, '1 0 0', rgb, a);
-       R_PolygonVertex(v3, '1 1 0', rgb, a);
-       R_PolygonVertex(v4, '0 1 0', rgb, a);
-       R_EndPolygon();
-}
-
-void drawquad(vector o, vector ri, vector up, string pic, vector rgb, float a, float f)
-{
-       R_BeginPolygon(pic, f);
-       R_PolygonVertex(o, '0 0 0', rgb, a);
-       R_PolygonVertex(o + ri, '1 0 0', rgb, a);
-       R_PolygonVertex(o + up + ri, '1 1 0', rgb, a);
-       R_PolygonVertex(o + up, '0 1 0', rgb, a);
-       R_EndPolygon();
-}
-
-void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, float width, float theheight, float margin, float border, float align, vector rgb, float a, vector hrgb, float ha, float f)
-{
-       vector o, ri, up;
-       float owidth; // outer width
-
-       hotspot = -1 * hotspot;
-
-       // hotspot-relative coordinates of the healthbar corners
-       o = hotspot;
-       ri = '1 0 0';
-       up = '0 1 0';
-
-       rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed
-       o = rotate(o, rot) + org;
-       ri = rotate(ri, rot);
-       up = rotate(up, rot);
-
-       owidth = width + 2 * border;
-       o = o - up * (margin + border + theheight) + ri * (sz.x - owidth) * 0.5;
-
-       drawquad(o - up * border,                               ri * owidth,    up * border, "", rgb,  a,  f);
-       drawquad(o + up * theheight,                               ri * owidth,    up * border, "", rgb,  a,  f);
-       drawquad(o,                                             ri * border,    up * theheight, "", rgb,  a,  f);
-       drawquad(o + ri * (owidth - border),                    ri * border,    up * theheight, "", rgb,  a,  f);
-       drawquad(o + ri * (border + align * ((1 - h) * width)), ri * width * h, up * theheight, "", hrgb, ha, f);
-}
-
-// returns location of sprite text
-vector drawspritearrow(vector o, float ang, vector rgb, float a, float t)
-{
-       float size   = 9.0 * t;
-       float border = 1.5 * t;
-       float margin = 4.0 * t;
-
-       float borderDiag = border * 1.414;
-       vector arrowX  = eX * size;
-       vector arrowY  = eY * (size+borderDiag);
-       vector borderX = eX * (size+borderDiag);
-       vector borderY = eY * (size+borderDiag+border);
-
-       R_BeginPolygon("", DRAWFLAG_NORMAL);
-       R_PolygonVertex(o,                                  '0 0 0', '0 0 0', a);
-       R_PolygonVertex(o + rotate(arrowY  - borderX, ang), '0 0 0', '0 0 0', a);
-       R_PolygonVertex(o + rotate(borderY - borderX, ang), '0 0 0', '0 0 0', a);
-       R_PolygonVertex(o + rotate(borderY + borderX, ang), '0 0 0', '0 0 0', a);
-       R_PolygonVertex(o + rotate(arrowY  + borderX, ang), '0 0 0', '0 0 0', a);
-       R_EndPolygon();
-
-       R_BeginPolygon("", DRAWFLAG_ADDITIVE);
-       R_PolygonVertex(o + rotate(eY * borderDiag, ang), '0 0 0', rgb, a);
-       R_PolygonVertex(o + rotate(arrowY - arrowX, ang), '0 0 0', rgb, a);
-       R_PolygonVertex(o + rotate(arrowY + arrowX, ang), '0 0 0', rgb, a);
-       R_EndPolygon();
-
-       return o + rotate(eY * (borderDiag+size+margin), ang);
-}
-
-// returns location of sprite healthbar
-vector drawspritetext(vector o, float ang, float minwidth, vector rgb, float a, vector fontsize, string s)
-{
-       float algnx, algny;
-       float sw, w, h;
-       float aspect, sa, ca;
-
-       sw = stringwidth(s, false, fontsize);
-       if(sw > minwidth)
-               w = sw;
-       else
-               w = minwidth;
-       h = fontsize.y;
-
-       // how do corners work?
-       aspect = vid_conwidth / vid_conheight;
-       sa = sin(ang);
-       ca = cos(ang) * aspect;
-       if(fabs(sa) > fabs(ca))
-       {
-               algnx = (sa < 0);
-               algny = 0.5 - 0.5 * ca / fabs(sa);
-       }
-       else
-       {
-               algnx = 0.5 - 0.5 * sa / fabs(ca);
-               algny = (ca < 0);
-       }
-
-       // align
-       o.x -= w * algnx;
-       o.y -= h * algny;
-
-       // we want to be onscreen
-       if(o.x < 0)
-               o.x = 0;
-       if(o.y < 0)
-               o.y = 0;
-       if(o.x > vid_conwidth - w)
-               o.x = vid_conwidth - w;
-       if(o.y > vid_conheight - h)
-               o.x = vid_conheight - h;
-
-       o.x += 0.5 * (w - sw);
-
-       drawstring(o, s, fontsize, rgb, a, DRAWFLAG_NORMAL);
-
-       o.x += 0.5 * sw;
-       o.y += 0.5 * h;
-
-       return o;
-}
-
-float spritelookupblinkvalue(string s)
-{
-       if(substring(s, 0, 4) == "wpn-")
-       if(get_weaponinfo(stof(substring(s, 4, strlen(s)))).spawnflags & WEP_FLAG_SUPERWEAPON)
-               return 2;
-
-       FOREACH(ITEMS, it.m_waypoint == s, LAMBDA(
-               return it.m_waypointblink;
-       ));
-
-       switch(s)
-       {
-               case "ons-cp-atck":      return 2;
-               case "ons-cp-dfnd":      return 0.5;
-               case "item-invis":       return 2;
-               case "item-extralife":   return 2;
-               case "item-speed":       return 2;
-               case "tagged-target":    return 2;
-               default:                 return 1;
-       }
-}
-vector spritelookupcolor(string s, vector def)
-{
-       if(substring(s, 0, 4) == "wpn-")
-               return (get_weaponinfo(stof(substring(s, 4, strlen(s)))).wpcolor);
-
-       switch(s)
-       {
-               case "keycarrier-friend": return '0 1 0';
-               default:                  return def;
-       }
-}
-string spritelookuptext(string s)
-{
-       if(substring(s, 0, 4) == "wpn-") { return (get_weaponinfo(stof(substring(s, 4, strlen(s)))).message); }
-       if (substring(s, 0, 5) == "buff-")
-       {
-               entity buff = BUFF_NULL;
-               FOREACH(BUFFS, it.m_sprite == s, LAMBDA(
-                       buff = it;
-                       break;
-               ));
-               return buff.m_prettyName;
-       }
-
-       switch(s)
-       {
-               case "as-push": return _("Push");
-               case "as-destroy": return _("Destroy");
-               case "as-defend": return _("Defend");
-               case "bluebase": return _("Blue base");
-               case "danger": return _("DANGER");
-               case "enemyflagcarrier": return _("Enemy carrier");
-               case "flagcarrier": return _("Flag carrier");
-               case "flagdropped": return _("Dropped flag");
-               case "helpme": return _("Help me!");
-               case "here": return _("Here");
-               case "key-dropped": return _("Dropped key");
-               case "keycarrier-blue": return _("Key carrier");
-               case "keycarrier-finish": return _("Run here");
-               case "keycarrier-friend": return _("Key carrier");
-               case "keycarrier-pink": return _("Key carrier");
-               case "keycarrier-red": return _("Key carrier");
-               case "keycarrier-yellow": return _("Key carrier");
-               case "redbase": return _("Red base");
-               case "yellowbase": return _("Yellow base");
-               case "neutralbase": return _("White base");
-               case "pinkbase": return _("Pink base");
-               case "waypoint": return _("Waypoint");
-               case "ons-gen": return _("Generator");
-               case "ons-gen-shielded": return _("Generator");
-               case "ons-cp": return _("Control point");
-               case "ons-cp-atck": return _("Control point");
-               case "ons-cp-dfnd": return _("Control point");
-               case "race-checkpoint": return _("Checkpoint");
-               case "race-finish": return _("Finish");
-               case "race-start": return _("Start");
-               case "race-start-finish": return (race_checkpointtime || race_mycheckpointtime) ? _("Finish") : _("Start");
-               case "goal": return _("Goal");
-               case "nb-ball": return _("Ball");
-               case "ka-ball": return _("Ball");
-               case "ka-ballcarrier": return _("Ball carrier");
-               case "dom-neut": return _("Control point");
-               case "dom-red": return _("Control point");
-               case "dom-blue": return _("Control point");
-               case "dom-yellow": return _("Control point");
-               case "dom-pink": return _("Control point");
-               case "item-invis": return _("Invisibility");
-               case "item-extralife": return _("Extra life");
-               case "item-speed": return _("Speed");
-               case "frozen": return _("Frozen!");
-               case "tagged-target": return _("Tagged");
-               case "vehicle": return _("Vehicle");
-               case "intruder": return _("Intruder!");
-               default: return s;
-       }
-}
-
-vector fixrgbexcess_move(vector rgb, vector src, vector dst)
-{
-       vector yvec = '0.299 0.587 0.114';
-       return rgb + dst * ((src * yvec) / (dst * yvec)) * ((rgb - '1 1 1') * src);
-}
-vector fixrgbexcess(vector rgb)
-{
-       if(rgb.x > 1)
-       {
-               rgb = fixrgbexcess_move(rgb, '1 0 0', '0 1 1');
-               if(rgb.y > 1)
-               {
-                       rgb = fixrgbexcess_move(rgb, '0 1 0', '0 0 1');
-                       if(rgb.z > 1)
-                               rgb.z = 1;
-               }
-               else if(rgb.z > 1)
-               {
-                       rgb = fixrgbexcess_move(rgb, '0 0 1', '0 1 0');
-                       if(rgb.y > 1)
-                               rgb.y = 1;
-               }
-       }
-       else if(rgb.y > 1)
-       {
-               rgb = fixrgbexcess_move(rgb, '0 1 0', '1 0 1');
-               if(rgb.x > 1)
-               {
-                       rgb = fixrgbexcess_move(rgb, '1 0 0', '0 0 1');
-                       if(rgb.z > 1)
-                               rgb.z = 1;
-               }
-               else if(rgb.z > 1)
-               {
-                       rgb = fixrgbexcess_move(rgb, '0 0 1', '1 0 0');
-                       if(rgb.x > 1)
-                               rgb.x = 1;
-               }
-       }
-       else if(rgb.z > 1)
-       {
-               rgb = fixrgbexcess_move(rgb, '0 0 1', '1 1 0');
-               if(rgb.x > 1)
-               {
-                       rgb = fixrgbexcess_move(rgb, '1 0 0', '0 1 0');
-                       if(rgb.y > 1)
-                               rgb.y = 1;
-               }
-               else if(rgb.y > 1)
-               {
-                       rgb = fixrgbexcess_move(rgb, '0 1 0', '1 0 0');
-                       if(rgb.x > 1)
-                               rgb.x = 1;
-               }
-       }
-       return rgb;
-}
-
-void Draw_WaypointSprite()
-{
-       string spriteimage;
-       float t;
-
-       if(self.lifetime)
-               self.alpha = pow(bound(0, (self.fadetime - time) / self.lifetime, 1), waypointsprite_timealphaexponent);
-       else
-               self.alpha = 1;
-
-       if(self.hideflags & 2)
-               return; // radar only
-
-       if(autocvar_cl_hidewaypoints >= 2)
-               return;
-
-       if(self.hideflags & 1)
-               if(autocvar_cl_hidewaypoints)
-                       return; // fixed waypoint
-
-       InterpolateOrigin_Do();
-
-       t = GetPlayerColor(player_localnum) + 1;
-
-       spriteimage = "";
-
-       // choose the sprite
-       switch(self.rule)
-       {
-               case SPRITERULE_SPECTATOR:
-                       if(!(
-                               (autocvar_g_waypointsprite_itemstime == 1 && t == NUM_SPECTATOR + 1)
-                       ||      (autocvar_g_waypointsprite_itemstime == 2 && (t == NUM_SPECTATOR + 1 || warmup_stage))
-                               ))
-                               return;
-                       spriteimage = self.netname;
-                       break;
-               case SPRITERULE_DEFAULT:
-                       if(self.team)
-                       {
-                               if(self.team == t)
-                                       spriteimage = self.netname;
-                               else
-                                       spriteimage = "";
-                       }
-                       else
-                               spriteimage = self.netname;
-                       break;
-               case SPRITERULE_TEAMPLAY:
-                       if(t == NUM_SPECTATOR + 1)
-                               spriteimage = self.netname3;
-                       else if(self.team == t)
-                               spriteimage = self.netname2;
-                       else
-                               spriteimage = self.netname;
-                       break;
-               default:
-                       error("Invalid waypointsprite rule!");
-                       break;
-       }
-
-       if(spriteimage == "")
-               return;
-
-       ++waypointsprite_newcount;
-
-       float dist;
-       dist = vlen(self.origin - view_origin);
-
-       float a;
-       a = self.alpha * autocvar_hud_panel_fg_alpha;
-
-       if(self.maxdistance > waypointsprite_normdistance)
-               a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent);
-       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;
-       rgb = self.teamradar_color;
-       rgb = spritelookupcolor(spriteimage, rgb);
-       if(rgb == '0 0 0')
-       {
-               self.teamradar_color = '1 0 1';
-               printf("WARNING: sprite of name %s has no color, using pink so you notice it\n", spriteimage);
-       }
-
-       if(time - floor(time) > 0.5)
-       {
-               if(self.helpme && time < self.helpme)
-                       a *= SPRITE_HELPME_BLINK;
-               else if(!self.lifetime) // fading out waypoints don't blink
-                       a *= spritelookupblinkvalue(spriteimage);
-       }
-
-       if(a > 1)
-       {
-               rgb *= a;
-               a = 1;
-       }
-
-       if(a <= 0.003)
-               return;
-
-       rgb = fixrgbexcess(rgb);
-
-       vector o;
-       float ang;
-
-       o = project_3d_to_2d(self.origin);
-       if(o.z < 0
-       || o.x < (vid_conwidth * waypointsprite_edgeoffset_left)
-       || o.y < (vid_conheight * waypointsprite_edgeoffset_top)
-       || o.x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))
-       || o.y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
-       {
-               // scale it to be just in view
-               vector d;
-               float f1, f2;
-
-               d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
-               ang = atan2(-d.x, -d.y);
-               if(o.z < 0)
-                       ang += M_PI;
-
-               f1 = d.x / vid_conwidth;
-               f2 = d.y / vid_conheight;
-
-               if(max(f1, -f1) > max(f2, -f2))
-               {
-                       if(d.z * f1 > 0)
-                       {
-                               // RIGHT edge
-                               d = d * ((0.5 - waypointsprite_edgeoffset_right) / f1);
-                       }
-                       else
-                       {
-                               // LEFT edge
-                               d = d * (-(0.5 - waypointsprite_edgeoffset_left) / f1);
-                       }
-               }
-               else
-               {
-                       if(d.z * f2 > 0)
-                       {
-                               // BOTTOM edge
-                               d = d * ((0.5 - waypointsprite_edgeoffset_bottom) / f2);
-                       }
-                       else
-                       {
-                               // TOP edge
-                               d = d * (-(0.5 - waypointsprite_edgeoffset_top) / f2);
-                       }
-               }
-
-               o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
-       }
-       else
-       {
-#if 1
-               ang = M_PI;
-#else
-               vector d;
-               d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
-               ang = atan2(-d.x, -d.y);
-#endif
-       }
-       o.z = 0;
-
-       float edgedistance_min, crosshairdistance;
-               edgedistance_min = min((o.y - (vid_conheight * waypointsprite_edgeoffset_top)),
-       (o.x - (vid_conwidth * waypointsprite_edgeoffset_left)),
-       (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) - o.x,
-       (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)) - o.y);
-
-       float vidscale;
-       vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
-
-       crosshairdistance = sqrt( pow(o.x - vid_conwidth/2, 2) + pow(o.y - vid_conheight/2, 2) );
-
-       t = waypointsprite_scale * vidscale;
-       a *= waypointsprite_alpha;
-
-       {
-               a = a * (1 - (1 - waypointsprite_distancefadealpha) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
-               t = t * (1 - (1 - waypointsprite_distancefadescale) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
-       }
-       if (edgedistance_min < waypointsprite_edgefadedistance) {
-               a = a * (1 - (1 - waypointsprite_edgefadealpha) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
-               t = t * (1 - (1 - waypointsprite_edgefadescale) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
-       }
-       if(crosshairdistance < waypointsprite_crosshairfadedistance) {
-               a = a * (1 - (1 - waypointsprite_crosshairfadealpha) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
-               t = t * (1 - (1 - waypointsprite_crosshairfadescale) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
-       }
-
-       if(self.build_finished)
-       {
-               if(time < self.build_finished + 0.25)
-               {
-                       if(time < self.build_started)
-                               self.health = self.build_starthealth;
-                       else if(time < self.build_finished)
-                               self.health = (time - self.build_started) / (self.build_finished - self.build_started) * (1 - self.build_starthealth) + self.build_starthealth;
-                       else
-                               self.health = 1;
-               }
-               else
-                       self.health = -1;
-       }
-
-       o = drawspritearrow(o, ang, rgb, a, SPRITE_ARROW_SCALE * t);
-
-       string txt;
-       if(autocvar_g_waypointsprite_spam && waypointsprite_count >= autocvar_g_waypointsprite_spam)
-               txt = _("Spam");
-       else
-               txt = spritelookuptext(spriteimage);
-       if(self.helpme && time < self.helpme)
-               txt = sprintf(_("%s needing help!"), txt);
-       if(autocvar_g_waypointsprite_uppercase)
-               txt = strtoupper(txt);
-
-       draw_beginBoldFont();
-       if(self.health >= 0)
-       {
-               o = drawspritetext(o, ang, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
-
-               float align, marg;
-               if(self.build_finished)
-                       align = 0.5;
-               else
-                       align = 0;
-               if(cos(ang) > 0)
-                       marg = -(SPRITE_HEALTHBAR_MARGIN + SPRITE_HEALTHBAR_HEIGHT + 2 * SPRITE_HEALTHBAR_BORDER) * t - 0.5 * waypointsprite_fontsize;
-               else
-                       marg = SPRITE_HEALTHBAR_MARGIN * t + 0.5 * waypointsprite_fontsize;
-               drawhealthbar(
-                               o,
-                               0,
-                               self.health,
-                               '0 0 0',
-                               '0 0 0',
-                               SPRITE_HEALTHBAR_WIDTH * t,
-                               SPRITE_HEALTHBAR_HEIGHT * t,
-                               marg,
-                               SPRITE_HEALTHBAR_BORDER * t,
-                               align,
-                               rgb,
-                               a * SPRITE_HEALTHBAR_BORDERALPHA,
-                               rgb,
-                               a * SPRITE_HEALTHBAR_HEALTHALPHA,
-                               DRAWFLAG_NORMAL
-                            );
-       }
-       else
-       {
-               o = drawspritetext(o, ang, 0, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
-       }
-       draw_endBoldFont();
-}
-
-void Ent_RemoveWaypointSprite()
-{
-       if(self.netname)
-               strunzone(self.netname);
-       if(self.netname2)
-               strunzone(self.netname2);
-       if(self.netname3)
-               strunzone(self.netname3);
-}
-
-/** flags origin [team displayrule] [spritename] [spritename2] [spritename3] [lifetime maxdistance hideable] */
-void Ent_WaypointSprite()
-{
-       int sendflags, f, t;
-       sendflags = ReadByte();
-
-       if(!self.spawntime)
-               self.spawntime = time;
-
-       self.draw2d = Draw_WaypointSprite;
-
-       InterpolateOrigin_Undo();
-       self.iflags |= IFLAG_ORIGIN;
-
-       if(sendflags & 0x80)
-       {
-               t = ReadByte();
-               if(t < 192)
-               {
-                       self.health = t / 191.0;
-                       self.build_finished = 0;
-               }
-               else
-               {
-                       t = (t - 192) * 256 + ReadByte();
-                       self.build_started = servertime;
-                       if(self.build_finished)
-                               self.build_starthealth = bound(0, self.health, 1);
-                       else
-                               self.build_starthealth = 0;
-                       self.build_finished = servertime + t / 32;
-               }
-       }
-       else
-       {
-               self.health = -1;
-               self.build_finished = 0;
-       }
-
-       if(sendflags & 64)
-       {
-               // unfortunately, this needs to be exact (for the 3D display)
-               self.origin_x = ReadCoord();
-               self.origin_y = ReadCoord();
-               self.origin_z = ReadCoord();
-               setorigin(self, self.origin);
-       }
-
-       if(sendflags & 1)
-       {
-               self.team = ReadByte();
-               self.rule = ReadByte();
-       }
-
-       if(sendflags & 2)
-       {
-               if(self.netname)
-                       strunzone(self.netname);
-               self.netname = strzone(ReadString());
-       }
-
-       if(sendflags & 4)
-       {
-               if(self.netname2)
-                       strunzone(self.netname2);
-               self.netname2 = strzone(ReadString());
-       }
-
-       if(sendflags & 8)
-       {
-               if(self.netname3)
-                       strunzone(self.netname3);
-               self.netname3 = strzone(ReadString());
-       }
-
-       if(sendflags & 16)
-       {
-               self.lifetime = ReadCoord();
-               self.fadetime = ReadCoord();
-               self.maxdistance = ReadShort();
-               self.hideflags = ReadByte();
-       }
-
-       if(sendflags & 32)
-       {
-               f = ReadByte();
-               self.teamradar_icon = (f & 0x7F);
-               if(f & 0x80)
-               {
-                       self.(teamradar_times[self.teamradar_time_index]) = time;
-                       self.teamradar_time_index = (self.teamradar_time_index + 1) % MAX_TEAMRADAR_TIMES;
-               }
-               self.teamradar_color_x = ReadByte() / 255.0;
-               self.teamradar_color_y = ReadByte() / 255.0;
-               self.teamradar_color_z = ReadByte() / 255.0;
-               self.helpme = ReadByte() * 0.1;
-               if(self.helpme > 0)
-                       self.helpme += servertime;
-       }
-
-       InterpolateOrigin_Note();
-
-       self.entremove = Ent_RemoveWaypointSprite;
-}
-
-void WaypointSprite_Load_Frames(string ext)
-{
-       float dh, n, i, o, f;
-       string s, sname, sframes;
-       dh = search_begin(strcat("models/sprites/*_frame*", ext), false, false);
-       if (dh < 0)
-                return;
-       float ext_len = strlen(ext);
-       n = search_getsize(dh);
-       for(i = 0; i < n; ++i)
-       {
-               s = search_getfilename(dh, i);
-               s = substring(s, 15, strlen(s) - 15 - ext_len); // strip models/sprites/ and extension
-
-               o = strstrofs(s, "_frame", 0);
-               sname = strcat("/spriteframes/", substring(s, 0, o));
-               sframes = substring(s, o + 6, strlen(s) - o - 6);
-               f = stof(sframes) + 1;
-               db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname)))));
-       }
-       search_end(dh);
-}
-
-void WaypointSprite_Load()
-{
-       waypointsprite_fadedistance = vlen(mi_scale);
-       waypointsprite_normdistance = autocvar_g_waypointsprite_normdistance;
-       waypointsprite_minscale = autocvar_g_waypointsprite_minscale;
-       waypointsprite_minalpha = autocvar_g_waypointsprite_minalpha;
-       waypointsprite_distancealphaexponent = autocvar_g_waypointsprite_distancealphaexponent;
-       waypointsprite_timealphaexponent = autocvar_g_waypointsprite_timealphaexponent;
-       waypointsprite_scale = autocvar_g_waypointsprite_scale;
-       waypointsprite_fontsize = autocvar_g_waypointsprite_fontsize;
-       waypointsprite_edgefadealpha = autocvar_g_waypointsprite_edgefadealpha;
-       waypointsprite_edgefadescale = autocvar_g_waypointsprite_edgefadescale;
-       waypointsprite_edgefadedistance = autocvar_g_waypointsprite_edgefadedistance;
-       waypointsprite_edgeoffset_bottom = autocvar_g_waypointsprite_edgeoffset_bottom;
-       waypointsprite_edgeoffset_left = autocvar_g_waypointsprite_edgeoffset_left;
-       waypointsprite_edgeoffset_right = autocvar_g_waypointsprite_edgeoffset_right;
-       waypointsprite_edgeoffset_top = autocvar_g_waypointsprite_edgeoffset_top;
-       waypointsprite_crosshairfadealpha = autocvar_g_waypointsprite_crosshairfadealpha;
-       waypointsprite_crosshairfadescale = autocvar_g_waypointsprite_crosshairfadescale;
-       waypointsprite_crosshairfadedistance = autocvar_g_waypointsprite_crosshairfadedistance;
-       waypointsprite_distancefadealpha = autocvar_g_waypointsprite_distancefadealpha;
-       waypointsprite_distancefadescale = autocvar_g_waypointsprite_distancefadescale;
-       waypointsprite_distancefadedistance = waypointsprite_fadedistance * autocvar_g_waypointsprite_distancefadedistancemultiplier;
-       waypointsprite_alpha = autocvar_g_waypointsprite_alpha * (1 - autocvar__menu_alpha);
-
-       if(!waypointsprite_initialized)
-       {
-               WaypointSprite_Load_Frames(".tga");
-               WaypointSprite_Load_Frames(".jpg");
-               waypointsprite_initialized = true;
-       }
-
-       waypointsprite_count = waypointsprite_newcount;
-       waypointsprite_newcount = 0;
-}
diff --git a/qcsrc/client/waypointsprites.qh b/qcsrc/client/waypointsprites.qh
deleted file mode 100644 (file)
index cb4f7ad..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-#ifndef WAYPOINTSPRITES_H
-#define WAYPOINTSPRITES_H
-
-
-float waypointsprite_initialized;
-float waypointsprite_fadedistance;
-float waypointsprite_normdistance;
-float waypointsprite_minscale;
-float waypointsprite_minalpha;
-float waypointsprite_distancealphaexponent;
-float waypointsprite_timealphaexponent;
-float waypointsprite_scale;
-float waypointsprite_fontsize;
-float waypointsprite_edgefadealpha;
-float waypointsprite_edgefadescale;
-float waypointsprite_edgefadedistance;
-float waypointsprite_edgeoffset_bottom;
-float waypointsprite_edgeoffset_left;
-float waypointsprite_edgeoffset_right;
-float waypointsprite_edgeoffset_top;
-float waypointsprite_crosshairfadealpha;
-float waypointsprite_crosshairfadescale;
-float waypointsprite_crosshairfadedistance;
-float waypointsprite_distancefadealpha;
-float waypointsprite_distancefadescale;
-float waypointsprite_distancefadedistance;
-float waypointsprite_alpha;
-
-entityclass(WaypointSprite);
-class(WaypointSprite) .float helpme;
-class(WaypointSprite) .float rule;
-class(WaypointSprite) .string netname; // primary picture
-class(WaypointSprite) .string netname2; // secondary picture
-class(WaypointSprite) .string netname3; // tertiary picture
-class(WaypointSprite) .int team; // team that gets netname2
-class(WaypointSprite) .float lifetime;
-class(WaypointSprite) .float fadetime;
-class(WaypointSprite) .float maxdistance;
-class(WaypointSprite) .int hideflags;
-class(WaypointSprite) .float spawntime;
-class(WaypointSprite) .float health;
-class(WaypointSprite) .float build_started;
-class(WaypointSprite) .float build_starthealth;
-class(WaypointSprite) .float build_finished;
-
-const float SPRITE_HEALTHBAR_WIDTH = 144;
-const float SPRITE_HEALTHBAR_HEIGHT = 9;
-const float SPRITE_HEALTHBAR_MARGIN = 6;
-const float SPRITE_HEALTHBAR_BORDER = 2;
-const float SPRITE_HEALTHBAR_BORDERALPHA = 1;
-const float SPRITE_HEALTHBAR_HEALTHALPHA = 0.5;
-const float SPRITE_ARROW_SCALE = 1.0;
-const float SPRITE_HELPME_BLINK = 2;
-
-float waypointsprite_count, waypointsprite_newcount;
-
-void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f);
-
-void drawquad(vector o, vector ri, vector up, string pic, vector rgb, float a, float f);
-
-void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, float width, float height, float margin, float border, float align, vector rgb, float a, vector hrgb, float ha, float f);
-
-// returns location of sprite text
-vector drawspritearrow(vector o, float ang, vector rgb, float a, float t);
-
-// returns location of sprite healthbar
-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);
-string spritelookuptext(string s);
-
-vector fixrgbexcess_move(vector rgb, vector src, vector dst);
-vector fixrgbexcess(vector rgb);
-
-void Draw_WaypointSprite();
-
-// they are drawn using a .draw function
-
-void Ent_RemoveWaypointSprite();
-
-void Ent_WaypointSprite();
-
-void WaypointSprite_Load_Frames(string ext);
-
-void WaypointSprite_Load();
-
-#endif
index f8055ad95454920792beba2e8feb733a45260c9f..f048c8837d85211e98cc43e59f1f323638b9c10f 100644 (file)
@@ -1,5 +1,112 @@
+#include "waypointsprites.qh"
+
 REGISTER_MUTATOR(waypointsprites, true);
 
+#ifdef SVQC
+/** flags origin [team displayrule] [spritename] [spritename2] [spritename3] [lifetime maxdistance hideable] */
+float WaypointSprite_SendEntity(entity to, float sendflags)
+{
+    WriteMutator(MSG_ENTITY, waypointsprites);
+
+    sendflags = sendflags & 0x7F;
+
+    if (g_nexball)
+        sendflags &= ~0x80;
+    else if (self.max_health || (self.pain_finished && (time < self.pain_finished + 0.25)))
+        sendflags |= 0x80;
+
+    WriteByte(MSG_ENTITY, sendflags);
+
+    if (sendflags & 0x80)
+    {
+        if (self.max_health)
+        {
+            WriteByte(MSG_ENTITY, (self.health / self.max_health) * 191.0);
+        }
+        else
+        {
+            float dt = self.pain_finished - time;
+            dt = bound(0, dt * 32, 16383);
+            WriteByte(MSG_ENTITY, (dt & 0xFF00) / 256 + 192);
+            WriteByte(MSG_ENTITY, (dt & 0x00FF));
+        }
+    }
+
+    if (sendflags & 64)
+    {
+        WriteCoord(MSG_ENTITY, self.origin.x);
+        WriteCoord(MSG_ENTITY, self.origin.y);
+        WriteCoord(MSG_ENTITY, self.origin.z);
+    }
+
+    if (sendflags & 1)
+    {
+        WriteByte(MSG_ENTITY, self.team);
+        WriteByte(MSG_ENTITY, self.rule);
+    }
+
+    if (sendflags & 2)
+        WriteString(MSG_ENTITY, self.model1);
+
+    if (sendflags & 4)
+        WriteString(MSG_ENTITY, self.model2);
+
+    if (sendflags & 8)
+        WriteString(MSG_ENTITY, self.model3);
+
+    if (sendflags & 16)
+    {
+        WriteCoord(MSG_ENTITY, self.fade_time);
+        WriteCoord(MSG_ENTITY, self.teleport_time);
+        WriteShort(MSG_ENTITY, self.fade_rate); // maxdist
+        float f = 0;
+        if (self.currentammo)
+            f |= 1; // hideable
+        if (self.exteriormodeltoclient == to)
+            f |= 2; // my own
+        if (g_onslaught)
+        {
+            if (self.owner.classname == "onslaught_controlpoint")
+            {
+                entity wp_owner = self.owner;
+                entity e = WaypointSprite_getviewentity(to);
+                if (SAME_TEAM(e, wp_owner) && wp_owner.goalentity.health >= wp_owner.goalentity.max_health) { f |= 2; }
+                if (!ons_ControlPoint_Attackable(wp_owner, e.team)) { f |= 2; }
+            }
+            if (self.owner.classname == "onslaught_generator")
+            {
+                entity wp_owner = self.owner;
+                if (wp_owner.isshielded && wp_owner.health >= wp_owner.max_health) { f |= 2; }
+                if (wp_owner.health <= 0) { f |= 2; }
+            }
+        }
+        WriteByte(MSG_ENTITY, f);
+    }
+
+    if (sendflags & 32)
+    {
+        WriteByte(MSG_ENTITY, self.cnt); // icon on radar
+        WriteByte(MSG_ENTITY, self.colormod.x * 255.0);
+        WriteByte(MSG_ENTITY, self.colormod.y * 255.0);
+        WriteByte(MSG_ENTITY, self.colormod.z * 255.0);
+
+        if (WaypointSprite_isteammate(self.owner, WaypointSprite_getviewentity(to)))
+        {
+            float dt = (self.waypointsprite_helpmetime - time) / 0.1;
+            if (dt < 0)
+                dt = 0;
+            if (dt > 255)
+                dt = 255;
+            WriteByte(MSG_ENTITY, dt);
+        }
+        else
+            WriteByte(MSG_ENTITY, 0);
+    }
+
+    return true;
+}
+#endif
+
 #ifdef CSQC
 void Ent_WaypointSprite();
 MUTATOR_HOOKFUNCTION(waypointsprites, CSQC_Ent_Update) {
@@ -8,4 +115,1096 @@ MUTATOR_HOOKFUNCTION(waypointsprites, CSQC_Ent_Update) {
     Ent_WaypointSprite();
     return true;
 }
+
+void Ent_RemoveWaypointSprite()
+{
+    if (self.netname) strunzone(self.netname);
+    if (self.netname2) strunzone(self.netname2);
+    if (self.netname3) strunzone(self.netname3);
+}
+
+/** flags origin [team displayrule] [spritename] [spritename2] [spritename3] [lifetime maxdistance hideable] */
+void Ent_WaypointSprite()
+{
+    int sendflags = ReadByte();
+
+    if (!self.spawntime)
+        self.spawntime = time;
+
+    self.draw2d = Draw_WaypointSprite;
+
+    InterpolateOrigin_Undo();
+    self.iflags |= IFLAG_ORIGIN;
+
+    if (sendflags & 0x80)
+    {
+        int t = ReadByte();
+        if (t < 192)
+        {
+            self.health = t / 191.0;
+            self.build_finished = 0;
+        }
+        else
+        {
+            t = (t - 192) * 256 + ReadByte();
+            self.build_started = servertime;
+            if (self.build_finished)
+                self.build_starthealth = bound(0, self.health, 1);
+            else
+                self.build_starthealth = 0;
+            self.build_finished = servertime + t / 32;
+        }
+    }
+    else
+    {
+        self.health = -1;
+        self.build_finished = 0;
+    }
+
+    if (sendflags & 64)
+    {
+        // unfortunately, this needs to be exact (for the 3D display)
+        self.origin_x = ReadCoord();
+        self.origin_y = ReadCoord();
+        self.origin_z = ReadCoord();
+        setorigin(self, self.origin);
+    }
+
+    if (sendflags & 1)
+    {
+        self.team = ReadByte();
+        self.rule = ReadByte();
+    }
+
+    if (sendflags & 2)
+    {
+        if (self.netname)
+            strunzone(self.netname);
+        self.netname = strzone(ReadString());
+    }
+
+    if (sendflags & 4)
+    {
+        if (self.netname2)
+            strunzone(self.netname2);
+        self.netname2 = strzone(ReadString());
+    }
+
+    if (sendflags & 8)
+    {
+        if (self.netname3)
+            strunzone(self.netname3);
+        self.netname3 = strzone(ReadString());
+    }
+
+    if (sendflags & 16)
+    {
+        self.lifetime = ReadCoord();
+        self.fadetime = ReadCoord();
+        self.maxdistance = ReadShort();
+        self.hideflags = ReadByte();
+    }
+
+    if (sendflags & 32)
+    {
+        int f = ReadByte();
+        self.teamradar_icon = (f & 0x7F);
+        if (f & 0x80)
+        {
+            self.(teamradar_times[self.teamradar_time_index]) = time;
+            self.teamradar_time_index = (self.teamradar_time_index + 1) % MAX_TEAMRADAR_TIMES;
+        }
+        self.teamradar_color_x = ReadByte() / 255.0;
+        self.teamradar_color_y = ReadByte() / 255.0;
+        self.teamradar_color_z = ReadByte() / 255.0;
+        self.helpme = ReadByte() * 0.1;
+        if (self.helpme > 0)
+            self.helpme += servertime;
+    }
+
+    InterpolateOrigin_Note();
+
+    self.entremove = Ent_RemoveWaypointSprite;
+}
+#endif
+
+#ifdef CSQC
+float spritelookupblinkvalue(string s)
+{
+    if (substring(s, 0, 4) == "wpn-")
+    if (get_weaponinfo(stof(substring(s, 4, strlen(s)))).spawnflags & WEP_FLAG_SUPERWEAPON)
+        return 2;
+
+    FOREACH(ITEMS, it.m_waypoint == s, LAMBDA(
+        return it.m_waypointblink;
+    ));
+
+    switch (s)
+    {
+        case "ons-cp-atck":      return 2;
+        case "ons-cp-dfnd":      return 0.5;
+        case "item-invis":       return 2;
+        case "item-extralife":   return 2;
+        case "item-speed":       return 2;
+        case "tagged-target":    return 2;
+        default:                 return 1;
+    }
+}
+
+vector spritelookupcolor(string s, vector def)
+{
+    if (substring(s, 0, 4) == "wpn-")
+        return (get_weaponinfo(stof(substring(s, 4, strlen(s)))).wpcolor);
+
+    switch (s)
+    {
+        case "keycarrier-friend": return '0 1 0';
+        default:                  return def;
+    }
+}
+
+string spritelookuptext(string s)
+{
+    if (substring(s, 0, 4) == "wpn-") { return (get_weaponinfo(stof(substring(s, 4, strlen(s)))).message); }
+    if (substring(s, 0, 5) == "buff-")
+    {
+        entity buff = BUFF_NULL;
+        FOREACH(BUFFS, it.m_sprite == s, LAMBDA(
+            buff = it;
+            break;
+        ));
+        return buff.m_prettyName;
+    }
+
+    switch (s)
+    {
+        case "as-push": return _("Push");
+        case "as-destroy": return _("Destroy");
+        case "as-defend": return _("Defend");
+        case "bluebase": return _("Blue base");
+        case "danger": return _("DANGER");
+        case "enemyflagcarrier": return _("Enemy carrier");
+        case "flagcarrier": return _("Flag carrier");
+        case "flagdropped": return _("Dropped flag");
+        case "helpme": return _("Help me!");
+        case "here": return _("Here");
+        case "key-dropped": return _("Dropped key");
+        case "keycarrier-blue": return _("Key carrier");
+        case "keycarrier-finish": return _("Run here");
+        case "keycarrier-friend": return _("Key carrier");
+        case "keycarrier-pink": return _("Key carrier");
+        case "keycarrier-red": return _("Key carrier");
+        case "keycarrier-yellow": return _("Key carrier");
+        case "redbase": return _("Red base");
+        case "yellowbase": return _("Yellow base");
+        case "neutralbase": return _("White base");
+        case "pinkbase": return _("Pink base");
+        case "waypoint": return _("Waypoint");
+        case "ons-gen": return _("Generator");
+        case "ons-gen-shielded": return _("Generator");
+        case "ons-cp": return _("Control point");
+        case "ons-cp-atck": return _("Control point");
+        case "ons-cp-dfnd": return _("Control point");
+        case "race-checkpoint": return _("Checkpoint");
+        case "race-finish": return _("Finish");
+        case "race-start": return _("Start");
+        case "race-start-finish": return (race_checkpointtime || race_mycheckpointtime) ? _("Finish") : _("Start");
+        case "goal": return _("Goal");
+        case "nb-ball": return _("Ball");
+        case "ka-ball": return _("Ball");
+        case "ka-ballcarrier": return _("Ball carrier");
+        case "dom-neut": return _("Control point");
+        case "dom-red": return _("Control point");
+        case "dom-blue": return _("Control point");
+        case "dom-yellow": return _("Control point");
+        case "dom-pink": return _("Control point");
+        case "item-invis": return _("Invisibility");
+        case "item-extralife": return _("Extra life");
+        case "item-speed": return _("Speed");
+        case "frozen": return _("Frozen!");
+        case "tagged-target": return _("Tagged");
+        case "vehicle": return _("Vehicle");
+        case "intruder": return _("Intruder!");
+        default: return s;
+    }
+}
+#endif
+
+#ifdef CSQC
+void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f)
+{
+    vector v1, v2, v3, v4;
+
+    hotspot = -1 * hotspot;
+
+    // hotspot-relative coordinates of the corners
+    v1 = hotspot;
+    v2 = hotspot + '1 0 0' * sz.x;
+    v3 = hotspot + '1 0 0' * sz.x + '0 1 0' * sz.y;
+    v4 = hotspot                  + '0 1 0' * sz.y;
+
+    // rotate them, and make them absolute
+    rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed
+    v1 = rotate(v1, rot) + org;
+    v2 = rotate(v2, rot) + org;
+    v3 = rotate(v3, rot) + org;
+    v4 = rotate(v4, rot) + org;
+
+    // draw them
+    R_BeginPolygon(pic, f);
+    R_PolygonVertex(v1, '0 0 0', rgb, a);
+    R_PolygonVertex(v2, '1 0 0', rgb, a);
+    R_PolygonVertex(v3, '1 1 0', rgb, a);
+    R_PolygonVertex(v4, '0 1 0', rgb, a);
+    R_EndPolygon();
+}
+
+void drawquad(vector o, vector ri, vector up, string pic, vector rgb, float a, float f)
+{
+    R_BeginPolygon(pic, f);
+    R_PolygonVertex(o, '0 0 0', rgb, a);
+    R_PolygonVertex(o + ri, '1 0 0', rgb, a);
+    R_PolygonVertex(o + up + ri, '1 1 0', rgb, a);
+    R_PolygonVertex(o + up, '0 1 0', rgb, a);
+    R_EndPolygon();
+}
+
+void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, float width, float theheight, float margin, float border, float align, vector rgb, float a, vector hrgb, float ha, float f)
+{
+    vector o, ri, up;
+    float owidth; // outer width
+
+    hotspot = -1 * hotspot;
+
+    // hotspot-relative coordinates of the healthbar corners
+    o = hotspot;
+    ri = '1 0 0';
+    up = '0 1 0';
+
+    rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed
+    o = rotate(o, rot) + org;
+    ri = rotate(ri, rot);
+    up = rotate(up, rot);
+
+    owidth = width + 2 * border;
+    o = o - up * (margin + border + theheight) + ri * (sz.x - owidth) * 0.5;
+
+    drawquad(o - up * border,                               ri * owidth,    up * border,    "", rgb,  a,  f);
+    drawquad(o + up * theheight,                            ri * owidth,    up * border,    "", rgb,  a,  f);
+    drawquad(o,                                             ri * border,    up * theheight, "", rgb,  a,  f);
+    drawquad(o + ri * (owidth - border),                    ri * border,    up * theheight, "", rgb,  a,  f);
+    drawquad(o + ri * (border + align * ((1 - h) * width)), ri * width * h, up * theheight, "", hrgb, ha, f);
+}
+
+// returns location of sprite text
+vector drawspritearrow(vector o, float ang, vector rgb, float a, float t)
+{
+    float size   = 9.0 * t;
+    float border = 1.5 * t;
+    float margin = 4.0 * t;
+
+    float borderDiag = border * 1.414;
+    vector arrowX  = eX * size;
+    vector arrowY  = eY * (size+borderDiag);
+    vector borderX = eX * (size+borderDiag);
+    vector borderY = eY * (size+borderDiag+border);
+
+    R_BeginPolygon("", DRAWFLAG_NORMAL);
+    R_PolygonVertex(o,                                  '0 0 0', '0 0 0', a);
+    R_PolygonVertex(o + rotate(arrowY  - borderX, ang), '0 0 0', '0 0 0', a);
+    R_PolygonVertex(o + rotate(borderY - borderX, ang), '0 0 0', '0 0 0', a);
+    R_PolygonVertex(o + rotate(borderY + borderX, ang), '0 0 0', '0 0 0', a);
+    R_PolygonVertex(o + rotate(arrowY  + borderX, ang), '0 0 0', '0 0 0', a);
+    R_EndPolygon();
+
+    R_BeginPolygon("", DRAWFLAG_ADDITIVE);
+    R_PolygonVertex(o + rotate(eY * borderDiag, ang), '0 0 0', rgb, a);
+    R_PolygonVertex(o + rotate(arrowY - arrowX, ang), '0 0 0', rgb, a);
+    R_PolygonVertex(o + rotate(arrowY + arrowX, ang), '0 0 0', rgb, a);
+    R_EndPolygon();
+
+    return o + rotate(eY * (borderDiag+size+margin), ang);
+}
+
+// returns location of sprite healthbar
+vector drawspritetext(vector o, float ang, float minwidth, vector rgb, float a, vector fontsize, string s)
+{
+    float algnx, algny;
+    float sw, w, h;
+    float aspect, sa, ca;
+
+    sw = stringwidth(s, false, fontsize);
+    if (sw > minwidth)
+        w = sw;
+    else
+        w = minwidth;
+    h = fontsize.y;
+
+    // how do corners work?
+    aspect = vid_conwidth / vid_conheight;
+    sa = sin(ang);
+    ca = cos(ang) * aspect;
+    if (fabs(sa) > fabs(ca))
+    {
+        algnx = (sa < 0);
+        algny = 0.5 - 0.5 * ca / fabs(sa);
+    }
+    else
+    {
+        algnx = 0.5 - 0.5 * sa / fabs(ca);
+        algny = (ca < 0);
+    }
+
+    // align
+    o.x -= w * algnx;
+    o.y -= h * algny;
+
+    // we want to be onscreen
+    if (o.x < 0)
+        o.x = 0;
+    if (o.y < 0)
+        o.y = 0;
+    if (o.x > vid_conwidth - w)
+        o.x = vid_conwidth - w;
+    if (o.y > vid_conheight - h)
+        o.x = vid_conheight - h;
+
+    o.x += 0.5 * (w - sw);
+
+    drawstring(o, s, fontsize, rgb, a, DRAWFLAG_NORMAL);
+
+    o.x += 0.5 * sw;
+    o.y += 0.5 * h;
+
+    return o;
+}
+
+vector fixrgbexcess_move(vector rgb, vector src, vector dst)
+{
+    vector yvec = '0.299 0.587 0.114';
+    return rgb + dst * ((src * yvec) / (dst * yvec)) * ((rgb - '1 1 1') * src);
+}
+
+vector fixrgbexcess(vector rgb)
+{
+    if (rgb.x > 1) {
+        rgb = fixrgbexcess_move(rgb, '1 0 0', '0 1 1');
+        if (rgb.y > 1) {
+            rgb = fixrgbexcess_move(rgb, '0 1 0', '0 0 1');
+            if (rgb.z > 1) rgb.z = 1;
+        } else if (rgb.z > 1) {
+            rgb = fixrgbexcess_move(rgb, '0 0 1', '0 1 0');
+            if (rgb.y > 1) rgb.y = 1;
+        }
+    } else if (rgb.y > 1) {
+        rgb = fixrgbexcess_move(rgb, '0 1 0', '1 0 1');
+        if (rgb.x > 1) {
+            rgb = fixrgbexcess_move(rgb, '1 0 0', '0 0 1');
+            if (rgb.z > 1) rgb.z = 1;
+        } else if (rgb.z > 1) {
+            rgb = fixrgbexcess_move(rgb, '0 0 1', '1 0 0');
+            if (rgb.x > 1) rgb.x = 1;
+        }
+    } else if (rgb.z > 1) {
+        rgb = fixrgbexcess_move(rgb, '0 0 1', '1 1 0');
+        if (rgb.x > 1) {
+            rgb = fixrgbexcess_move(rgb, '1 0 0', '0 1 0');
+            if (rgb.y > 1) rgb.y = 1;
+        } else if (rgb.y > 1) {
+            rgb = fixrgbexcess_move(rgb, '0 1 0', '1 0 0');
+            if (rgb.x > 1) rgb.x = 1;
+        }
+    }
+    return rgb;
+}
+
+void Draw_WaypointSprite()
+{
+    if (self.lifetime)
+        self.alpha = pow(bound(0, (self.fadetime - time) / self.lifetime, 1), waypointsprite_timealphaexponent);
+    else
+        self.alpha = 1;
+
+    if (self.hideflags & 2)
+        return; // radar only
+
+    if (autocvar_cl_hidewaypoints >= 2)
+        return;
+
+    if (self.hideflags & 1)
+        if (autocvar_cl_hidewaypoints)
+            return; // fixed waypoint
+
+    InterpolateOrigin_Do();
+
+    float t = GetPlayerColor(player_localnum) + 1;
+
+    string spriteimage = "";
+
+    // choose the sprite
+    switch (self.rule)
+    {
+        case SPRITERULE_SPECTATOR:
+            if (!(
+                (autocvar_g_waypointsprite_itemstime == 1 && t == NUM_SPECTATOR + 1)
+            || (autocvar_g_waypointsprite_itemstime == 2 && (t == NUM_SPECTATOR + 1 || warmup_stage))
+                ))
+                return;
+            spriteimage = self.netname;
+            break;
+        case SPRITERULE_DEFAULT:
+            if (self.team)
+            {
+                if (self.team == t)
+                    spriteimage = self.netname;
+                else
+                    spriteimage = "";
+            }
+            else
+                spriteimage = self.netname;
+            break;
+        case SPRITERULE_TEAMPLAY:
+            if (t == NUM_SPECTATOR + 1)
+                spriteimage = self.netname3;
+            else if (self.team == t)
+                spriteimage = self.netname2;
+            else
+                spriteimage = self.netname;
+            break;
+        default:
+            error("Invalid waypointsprite rule!");
+            break;
+    }
+
+    if (spriteimage == "")
+        return;
+
+    ++waypointsprite_newcount;
+
+    float dist;
+    dist = vlen(self.origin - view_origin);
+
+    float a;
+    a = self.alpha * autocvar_hud_panel_fg_alpha;
+
+    if (self.maxdistance > waypointsprite_normdistance)
+        a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent);
+    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);
+    if (rgb == '0 0 0')
+    {
+        self.teamradar_color = '1 0 1';
+        printf("WARNING: sprite of name %s has no color, using pink so you notice it\n", spriteimage);
+    }
+
+    if (time - floor(time) > 0.5)
+    {
+        if (self.helpme && time < self.helpme)
+            a *= SPRITE_HELPME_BLINK;
+        else if (!self.lifetime) // fading out waypoints don't blink
+            a *= spritelookupblinkvalue(spriteimage);
+    }
+
+    if (a > 1)
+    {
+        rgb *= a;
+        a = 1;
+    }
+
+    if (a <= 0.003)
+        return;
+
+    rgb = fixrgbexcess(rgb);
+
+    vector o;
+    float ang;
+
+    o = project_3d_to_2d(self.origin);
+    if (o.z < 0
+    || o.x < (vid_conwidth * waypointsprite_edgeoffset_left)
+    || o.y < (vid_conheight * waypointsprite_edgeoffset_top)
+    || o.x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))
+    || o.y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
+    {
+        // scale it to be just in view
+        vector d;
+        float f1, f2;
+
+        d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
+        ang = atan2(-d.x, -d.y);
+        if (o.z < 0)
+            ang += M_PI;
+
+        f1 = d.x / vid_conwidth;
+        f2 = d.y / vid_conheight;
+
+        if (max(f1, -f1) > max(f2, -f2)) {
+            if (d.z * f1 > 0) {
+                // RIGHT edge
+                d = d * ((0.5 - waypointsprite_edgeoffset_right) / f1);
+            } else {
+                // LEFT edge
+                d = d * (-(0.5 - waypointsprite_edgeoffset_left) / f1);
+            }
+        } else {
+            if (d.z * f2 > 0) {
+                // BOTTOM edge
+                d = d * ((0.5 - waypointsprite_edgeoffset_bottom) / f2);
+            } else {
+                // TOP edge
+                d = d * (-(0.5 - waypointsprite_edgeoffset_top) / f2);
+            }
+        }
+
+        o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
+    }
+    else
+    {
+#if 1
+        ang = M_PI;
+#else
+        vector d;
+        d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
+        ang = atan2(-d.x, -d.y);
+#endif
+    }
+    o.z = 0;
+
+    float edgedistance_min = min((o.y - (vid_conheight * waypointsprite_edgeoffset_top)),
+    (o.x - (vid_conwidth * waypointsprite_edgeoffset_left)),
+    (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) - o.x,
+    (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)) - o.y);
+
+    float vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
+
+    float crosshairdistance = sqrt( pow(o.x - vid_conwidth/2, 2) + pow(o.y - vid_conheight/2, 2) );
+
+    t = waypointsprite_scale * vidscale;
+    a *= waypointsprite_alpha;
+
+    {
+        a = a * (1 - (1 - waypointsprite_distancefadealpha) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
+        t = t * (1 - (1 - waypointsprite_distancefadescale) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
+    }
+    if (edgedistance_min < waypointsprite_edgefadedistance) {
+        a = a * (1 - (1 - waypointsprite_edgefadealpha) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
+        t = t * (1 - (1 - waypointsprite_edgefadescale) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
+    }
+    if (crosshairdistance < waypointsprite_crosshairfadedistance) {
+        a = a * (1 - (1 - waypointsprite_crosshairfadealpha) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
+        t = t * (1 - (1 - waypointsprite_crosshairfadescale) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
+    }
+
+    if (self.build_finished)
+    {
+        if (time < self.build_finished + 0.25)
+        {
+            if (time < self.build_started)
+                self.health = self.build_starthealth;
+            else if (time < self.build_finished)
+                self.health = (time - self.build_started) / (self.build_finished - self.build_started) * (1 - self.build_starthealth) + self.build_starthealth;
+            else
+                self.health = 1;
+        }
+        else
+            self.health = -1;
+    }
+
+    o = drawspritearrow(o, ang, rgb, a, SPRITE_ARROW_SCALE * t);
+
+    string txt;
+    if (autocvar_g_waypointsprite_spam && waypointsprite_count >= autocvar_g_waypointsprite_spam)
+        txt = _("Spam");
+    else
+        txt = spritelookuptext(spriteimage);
+    if (self.helpme && time < self.helpme)
+        txt = sprintf(_("%s needing help!"), txt);
+    if (autocvar_g_waypointsprite_uppercase)
+        txt = strtoupper(txt);
+
+    draw_beginBoldFont();
+    if (self.health >= 0)
+    {
+        o = drawspritetext(o, ang, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
+
+        float align, marg;
+        if (self.build_finished)
+            align = 0.5;
+        else
+            align = 0;
+        if (cos(ang) > 0)
+            marg = -(SPRITE_HEALTHBAR_MARGIN + SPRITE_HEALTHBAR_HEIGHT + 2 * SPRITE_HEALTHBAR_BORDER) * t - 0.5 * waypointsprite_fontsize;
+        else
+            marg = SPRITE_HEALTHBAR_MARGIN * t + 0.5 * waypointsprite_fontsize;
+        drawhealthbar(
+                o,
+                0,
+                self.health,
+                '0 0 0',
+                '0 0 0',
+                SPRITE_HEALTHBAR_WIDTH * t,
+                SPRITE_HEALTHBAR_HEIGHT * t,
+                marg,
+                SPRITE_HEALTHBAR_BORDER * t,
+                align,
+                rgb,
+                a * SPRITE_HEALTHBAR_BORDERALPHA,
+                rgb,
+                a * SPRITE_HEALTHBAR_HEALTHALPHA,
+                DRAWFLAG_NORMAL
+                 );
+    }
+    else
+    {
+        o = drawspritetext(o, ang, 0, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
+    }
+    draw_endBoldFont();
+}
+
+void WaypointSprite_Load_Frames(string ext)
+{
+    int dh = search_begin(strcat("models/sprites/*_frame*", ext), false, false);
+    if (dh < 0) return;
+    int ext_len = strlen(ext);
+    int n = search_getsize(dh);
+    for (int i = 0; i < n; ++i)
+    {
+        string s = search_getfilename(dh, i);
+        s = substring(s, 15, strlen(s) - 15 - ext_len); // strip models/sprites/ and extension
+
+        int o = strstrofs(s, "_frame", 0);
+        string sname = strcat("/spriteframes/", substring(s, 0, o));
+        string sframes = substring(s, o + 6, strlen(s) - o - 6);
+        int f = stof(sframes) + 1;
+        db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname)))));
+    }
+    search_end(dh);
+}
+
+void WaypointSprite_Load()
+{
+    waypointsprite_fadedistance = vlen(mi_scale);
+    waypointsprite_normdistance = autocvar_g_waypointsprite_normdistance;
+    waypointsprite_minscale = autocvar_g_waypointsprite_minscale;
+    waypointsprite_minalpha = autocvar_g_waypointsprite_minalpha;
+    waypointsprite_distancealphaexponent = autocvar_g_waypointsprite_distancealphaexponent;
+    waypointsprite_timealphaexponent = autocvar_g_waypointsprite_timealphaexponent;
+    waypointsprite_scale = autocvar_g_waypointsprite_scale;
+    waypointsprite_fontsize = autocvar_g_waypointsprite_fontsize;
+    waypointsprite_edgefadealpha = autocvar_g_waypointsprite_edgefadealpha;
+    waypointsprite_edgefadescale = autocvar_g_waypointsprite_edgefadescale;
+    waypointsprite_edgefadedistance = autocvar_g_waypointsprite_edgefadedistance;
+    waypointsprite_edgeoffset_bottom = autocvar_g_waypointsprite_edgeoffset_bottom;
+    waypointsprite_edgeoffset_left = autocvar_g_waypointsprite_edgeoffset_left;
+    waypointsprite_edgeoffset_right = autocvar_g_waypointsprite_edgeoffset_right;
+    waypointsprite_edgeoffset_top = autocvar_g_waypointsprite_edgeoffset_top;
+    waypointsprite_crosshairfadealpha = autocvar_g_waypointsprite_crosshairfadealpha;
+    waypointsprite_crosshairfadescale = autocvar_g_waypointsprite_crosshairfadescale;
+    waypointsprite_crosshairfadedistance = autocvar_g_waypointsprite_crosshairfadedistance;
+    waypointsprite_distancefadealpha = autocvar_g_waypointsprite_distancefadealpha;
+    waypointsprite_distancefadescale = autocvar_g_waypointsprite_distancefadescale;
+    waypointsprite_distancefadedistance = waypointsprite_fadedistance * autocvar_g_waypointsprite_distancefadedistancemultiplier;
+    waypointsprite_alpha = autocvar_g_waypointsprite_alpha * (1 - autocvar__menu_alpha);
+
+    if (!waypointsprite_initialized)
+    {
+        WaypointSprite_Load_Frames(".tga");
+        WaypointSprite_Load_Frames(".jpg");
+        waypointsprite_initialized = true;
+    }
+
+    waypointsprite_count = waypointsprite_newcount;
+    waypointsprite_newcount = 0;
+}
+#endif
+
+#ifdef SVQC
+void WaypointSprite_UpdateSprites(entity e, string m1, string m2, string m3)
+{
+    if (m1 != e.model1)
+    {
+        e.model1 = m1;
+        e.SendFlags |= 2;
+    }
+    if (m2 != e.model2)
+    {
+        e.model2 = m2;
+        e.SendFlags |= 4;
+    }
+    if (m3 != e.model3)
+    {
+        e.model3 = m3;
+        e.SendFlags |= 8;
+    }
+}
+
+void WaypointSprite_UpdateHealth(entity e, float f)
+{
+    f = bound(0, f, e.max_health);
+    if (f != e.health || e.pain_finished)
+    {
+        e.health = f;
+        e.pain_finished = 0;
+        e.SendFlags |= 0x80;
+    }
+}
+
+void WaypointSprite_UpdateMaxHealth(entity e, float f)
+{
+    if (f != e.max_health || e.pain_finished)
+    {
+        e.max_health = f;
+        e.pain_finished = 0;
+        e.SendFlags |= 0x80;
+    }
+}
+
+void WaypointSprite_UpdateBuildFinished(entity e, float f)
+{
+    if (f != e.pain_finished || e.max_health)
+    {
+        e.max_health = 0;
+        e.pain_finished = f;
+        e.SendFlags |= 0x80;
+    }
+}
+
+void WaypointSprite_UpdateOrigin(entity e, vector o)
+{
+    if (o != e.origin)
+    {
+        setorigin(e, o);
+        e.SendFlags |= 64;
+    }
+}
+
+void WaypointSprite_UpdateRule(entity e, float t, float r)
+{
+    // no check, as this is never called without doing an actual change (usually only once)
+    e.rule = r;
+    e.team = t;
+    e.SendFlags |= 1;
+}
+
+void WaypointSprite_UpdateTeamRadar(entity e, float 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);
+    e.colormod = col;
+    e.SendFlags |= 32;
+}
+
+void WaypointSprite_Ping(entity e)
+{
+    // anti spam
+    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.SendFlags |= 32;
+}
+
+void WaypointSprite_HelpMePing(entity e)
+{
+    WaypointSprite_Ping(e);
+    e.waypointsprite_helpmetime = time + waypointsprite_deployed_lifetime;
+    e.SendFlags |= 32;
+}
+
+void WaypointSprite_FadeOutIn(entity e, float t)
+{
+    if (!e.fade_time)
+    {
+        e.fade_time = t;
+        e.teleport_time = time + t;
+    }
+    else if (t < (e.teleport_time - time))
+    {
+        // accelerate the waypoint's dying
+        // ensure:
+        //   (e.teleport_time - time) / wp.fade_time stays
+        //   e.teleport_time = time + fadetime
+        float current_fadetime;
+        current_fadetime = e.teleport_time - time;
+        e.teleport_time = time + t;
+        e.fade_time = e.fade_time * t / current_fadetime;
+    }
+
+    e.SendFlags |= 16;
+}
+
+void WaypointSprite_Init()
+{
+    waypointsprite_limitedrange = autocvar_sv_waypointsprite_limitedrange;
+    waypointsprite_deployed_lifetime = autocvar_sv_waypointsprite_deployed_lifetime;
+    waypointsprite_deadlifetime = autocvar_sv_waypointsprite_deadlifetime;
+}
+
+void WaypointSprite_InitClient(entity e)
+{
+}
+
+void WaypointSprite_Kill(entity wp)
+{
+    if (!wp) return;
+    if (wp.owner) wp.owner.(wp.owned_by_field) = world;
+    remove(wp);
+}
+
+void WaypointSprite_Disown(entity wp, float fadetime)
+{
+    if (!wp) return;
+    if (wp.classname != "sprite_waypoint")
+    {
+        backtrace("Trying to disown a non-waypointsprite");
+        return;
+    }
+    if (wp.owner)
+    {
+        if (wp.exteriormodeltoclient == wp.owner)
+            wp.exteriormodeltoclient = world;
+        wp.owner.(wp.owned_by_field) = world;
+        wp.owner = world;
+
+        WaypointSprite_FadeOutIn(wp, fadetime);
+    }
+}
+
+void WaypointSprite_Think()
+{
+    bool doremove = false;
+
+    if (self.fade_time && time >= self.teleport_time)
+    {
+        doremove = true;
+    }
+
+    if (self.exteriormodeltoclient)
+        WaypointSprite_UpdateOrigin(self, self.exteriormodeltoclient.origin + self.view_ofs);
+
+    if (doremove)
+        WaypointSprite_Kill(self);
+    else
+        self.nextthink = time; // WHY?!?
+}
+
+float WaypointSprite_visible_for_player(entity e)
+{
+    // personal waypoints
+    if (self.enemy && self.enemy != e)
+        return false;
+
+    // team waypoints
+    if (self.rule == SPRITERULE_SPECTATOR)
+    {
+        if (!autocvar_sv_itemstime)
+            return false;
+        if (!warmup_stage && IS_PLAYER(e))
+            return false;
+    }
+    else if (self.team && self.rule == SPRITERULE_DEFAULT)
+    {
+        if (self.team != e.team)
+            return false;
+        if (!IS_PLAYER(e))
+            return false;
+    }
+
+    return true;
+}
+
+entity WaypointSprite_getviewentity(entity e)
+{
+    if (IS_SPEC(e)) e = e.enemy;
+    /* TODO idea (check this breaks nothing)
+    else if (e.classname == "observer")
+        e = world;
+    */
+    return e;
+}
+
+float WaypointSprite_isteammate(entity e, entity e2)
+{
+    if (teamplay)
+        return e2.team == e.team;
+    return e2 == e;
+}
+
+float WaypointSprite_Customize()
+{
+    // this is not in SendEntity because it shall run every frame, not just every update
+
+    // make spectators see what the player would see
+    entity e = WaypointSprite_getviewentity(other);
+
+    if (MUTATOR_CALLHOOK(CustomizeWaypoint, self, other))
+        return false;
+
+    return self.waypointsprite_visible_for_player(e);
+}
+
+float WaypointSprite_SendEntity(entity to, float sendflags);
+
+void WaypointSprite_Reset()
+{
+    // if a WP wants to time out, let it time out immediately; other WPs ought to be reset/killed by their owners
+
+    if (self.fade_time) // there was there before: || g_keyhunt, do we really need this?
+        WaypointSprite_Kill(self);
+}
+
+entity WaypointSprite_Spawn(
+    string spr, // sprite
+    float _lifetime, float maxdistance, // lifetime, max distance
+    entity ref, vector ofs, // position
+    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, vector rgb // initial icon and color
+)
+{
+    entity wp = new(sprite_waypoint);
+    wp.teleport_time = time + _lifetime;
+    wp.fade_time = _lifetime;
+    wp.exteriormodeltoclient = ref;
+    if (ref)
+    {
+        wp.view_ofs = ofs;
+        setorigin(wp, ref.origin + ofs);
+    }
+    else
+        setorigin(wp, ofs);
+    wp.enemy = showto;
+    wp.team = t;
+    wp.owner = own;
+    wp.currentammo = hideable;
+    if (own)
+    {
+        if (own.(ownfield))
+            remove(own.(ownfield));
+        own.(ownfield) = wp;
+        wp.owned_by_field = ownfield;
+    }
+    wp.fade_rate = maxdistance;
+    wp.think = WaypointSprite_Think;
+    wp.nextthink = time;
+    wp.model1 = spr;
+    wp.customizeentityforclient = WaypointSprite_Customize;
+    wp.waypointsprite_visible_for_player = WaypointSprite_visible_for_player;
+    wp.reset2 = WaypointSprite_Reset;
+    wp.cnt = icon;
+    wp.colormod = rgb;
+    Net_LinkEntity(wp, false, 0, WaypointSprite_SendEntity);
+    return wp;
+}
+
+entity WaypointSprite_SpawnFixed(
+    string spr,
+    vector ofs,
+    entity own,
+    .entity ownfield,
+    float icon, vector rgb // initial icon and color
+)
+{
+    return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, own, ownfield, true, icon, rgb);
+}
+
+entity WaypointSprite_DeployFixed(
+    string spr,
+    float limited_range,
+    vector ofs,
+    float icon, vector rgb // initial icon and color
+)
+{
+    float t;
+    if (teamplay)
+        t = self.team;
+    else
+        t = 0;
+    float maxdistance;
+    if (limited_range)
+        maxdistance = waypointsprite_limitedrange;
+    else
+        maxdistance = 0;
+    return WaypointSprite_Spawn(spr, waypointsprite_deployed_lifetime, maxdistance, world, ofs, world, t, self, waypointsprite_deployed_fixed, false, icon, rgb);
+}
+
+entity WaypointSprite_DeployPersonal(
+    string spr,
+    vector ofs,
+    float icon, vector rgb // initial icon and color
+)
+{
+    return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, self, waypointsprite_deployed_personal, false, icon, rgb);
+}
+
+entity WaypointSprite_Attach(
+    string spr,
+    float limited_range,
+    float icon, vector rgb // initial icon and color
+)
+{
+    float t;
+    if (self.waypointsprite_attachedforcarrier)
+        return world; // can't attach to FC
+    if (teamplay)
+        t = self.team;
+    else
+        t = 0;
+    float maxdistance;
+    if (limited_range)
+        maxdistance = waypointsprite_limitedrange;
+    else
+        maxdistance = 0;
+    return WaypointSprite_Spawn(spr, waypointsprite_deployed_lifetime, maxdistance, self, '0 0 64', world, t, self, waypointsprite_attached, false, icon, rgb);
+}
+
+entity WaypointSprite_AttachCarrier(
+    string spr,
+    entity carrier,
+    float icon, vector rgb // initial icon and color
+)
+{
+    WaypointSprite_Kill(carrier.waypointsprite_attached); // FC overrides attached
+    entity e = WaypointSprite_Spawn(spr, 0, 0, carrier, '0 0 64', world, carrier.team, carrier, waypointsprite_attachedforcarrier, false, icon, rgb);
+    if (e)
+    {
+        WaypointSprite_UpdateMaxHealth(e, '1 0 0' * healtharmor_maxdamage(start_health, start_armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON) * 2);
+        WaypointSprite_UpdateHealth(e, '1 0 0' * healtharmor_maxdamage(carrier.health, carrier.armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON));
+    }
+    return e;
+}
+
+void WaypointSprite_DetachCarrier(entity carrier)
+{
+    WaypointSprite_Disown(carrier.waypointsprite_attachedforcarrier, waypointsprite_deadlifetime);
+}
+
+void WaypointSprite_ClearPersonal()
+{
+    WaypointSprite_Kill(self.waypointsprite_deployed_personal);
+}
+
+void WaypointSprite_ClearOwned()
+{
+    WaypointSprite_Kill(self.waypointsprite_deployed_fixed);
+    WaypointSprite_Kill(self.waypointsprite_deployed_personal);
+    WaypointSprite_Kill(self.waypointsprite_attached);
+}
+
+void WaypointSprite_PlayerDead()
+{
+    WaypointSprite_Disown(self.waypointsprite_attached, waypointsprite_deadlifetime);
+    WaypointSprite_DetachCarrier(self);
+}
+
+void WaypointSprite_PlayerGone()
+{
+    WaypointSprite_Disown(self.waypointsprite_deployed_fixed, waypointsprite_deadlifetime);
+    WaypointSprite_Kill(self.waypointsprite_deployed_personal);
+    WaypointSprite_Disown(self.waypointsprite_attached, waypointsprite_deadlifetime);
+    WaypointSprite_DetachCarrier(self);
+}
 #endif
diff --git a/qcsrc/common/mutators/mutator/waypointsprites.qh b/qcsrc/common/mutators/mutator/waypointsprites.qh
new file mode 100644 (file)
index 0000000..bd26112
--- /dev/null
@@ -0,0 +1,201 @@
+#ifndef WAYPOINTSPRITES_H
+#define WAYPOINTSPRITES_H
+
+#ifdef CSQC
+entityclass(WaypointSprite);
+class(WaypointSprite) .float helpme;
+class(WaypointSprite) .float rule;
+class(WaypointSprite) .string netname; // primary picture
+class(WaypointSprite) .string netname2; // secondary picture
+class(WaypointSprite) .string netname3; // tertiary picture
+class(WaypointSprite) .int team; // team that gets netname2
+class(WaypointSprite) .float lifetime;
+class(WaypointSprite) .float fadetime;
+class(WaypointSprite) .float maxdistance;
+class(WaypointSprite) .int hideflags;
+class(WaypointSprite) .float spawntime;
+class(WaypointSprite) .float health;
+class(WaypointSprite) .float build_started;
+class(WaypointSprite) .float build_starthealth;
+class(WaypointSprite) .float build_finished;
+
+float waypointsprite_initialized;
+float waypointsprite_fadedistance;
+float waypointsprite_normdistance;
+float waypointsprite_minscale;
+float waypointsprite_minalpha;
+float waypointsprite_distancealphaexponent;
+float waypointsprite_timealphaexponent;
+float waypointsprite_scale;
+float waypointsprite_fontsize;
+float waypointsprite_edgefadealpha;
+float waypointsprite_edgefadescale;
+float waypointsprite_edgefadedistance;
+float waypointsprite_edgeoffset_bottom;
+float waypointsprite_edgeoffset_left;
+float waypointsprite_edgeoffset_right;
+float waypointsprite_edgeoffset_top;
+float waypointsprite_crosshairfadealpha;
+float waypointsprite_crosshairfadescale;
+float waypointsprite_crosshairfadedistance;
+float waypointsprite_distancefadealpha;
+float waypointsprite_distancefadescale;
+float waypointsprite_distancefadedistance;
+float waypointsprite_alpha;
+
+const float SPRITE_HEALTHBAR_WIDTH = 144;
+const float SPRITE_HEALTHBAR_HEIGHT = 9;
+const float SPRITE_HEALTHBAR_MARGIN = 6;
+const float SPRITE_HEALTHBAR_BORDER = 2;
+const float SPRITE_HEALTHBAR_BORDERALPHA = 1;
+const float SPRITE_HEALTHBAR_HEALTHALPHA = 0.5;
+const float SPRITE_ARROW_SCALE = 1.0;
+const float SPRITE_HELPME_BLINK = 2;
+
+float waypointsprite_count, waypointsprite_newcount;
+
+void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f);
+
+void drawquad(vector o, vector ri, vector up, string pic, vector rgb, float a, float f);
+
+void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, float width, float height, float margin, float border, float align, vector rgb, float a, vector hrgb, float ha, float f);
+
+// returns location of sprite text
+vector drawspritearrow(vector o, float ang, vector rgb, float a, float t);
+
+// returns location of sprite healthbar
+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);
+string spritelookuptext(string s);
+
+vector fixrgbexcess_move(vector rgb, vector src, vector dst);
+vector fixrgbexcess(vector rgb);
+
+// they are drawn using a .draw function
+
+void Ent_RemoveWaypointSprite();
+
+void Ent_WaypointSprite();
+
+void WaypointSprite_Load_Frames(string ext);
+
+void WaypointSprite_Load();
+.float alpha;
+void Draw_WaypointSprite();
+#endif
+
+#ifdef SVQC
+..entity owned_by_field;
+.float rule;
+.string model1;
+.string model2;
+.string model3;
+
+.float(entity) waypointsprite_visible_for_player;
+
+void WaypointSprite_UpdateSprites(entity e, string m1, string m2, string m3);
+
+void WaypointSprite_UpdateHealth(entity e, float f);
+
+void WaypointSprite_UpdateMaxHealth(entity e, float f);
+
+void WaypointSprite_UpdateBuildFinished(entity e, float f);
+
+void WaypointSprite_UpdateOrigin(entity e, vector o);
+
+void WaypointSprite_UpdateRule(entity e, float t, float r);
+
+void WaypointSprite_UpdateTeamRadar(entity e, float icon, vector col);
+
+.float waypointsprite_pingtime;
+.float waypointsprite_helpmetime;
+void WaypointSprite_Ping(entity e);
+
+float waypointsprite_limitedrange, waypointsprite_deployed_lifetime, waypointsprite_deadlifetime;
+
+void WaypointSprite_HelpMePing(entity e);
+
+void WaypointSprite_FadeOutIn(entity e, float t);
+
+void WaypointSprite_Init();
+void WaypointSprite_InitClient(entity e);
+
+void WaypointSprite_Kill(entity wp);
+
+void WaypointSprite_Disown(entity wp, float fadetime);
+
+void WaypointSprite_Think();
+
+float WaypointSprite_visible_for_player(entity e);
+
+entity WaypointSprite_getviewentity(entity e);
+
+float WaypointSprite_isteammate(entity e, entity e2);
+
+float WaypointSprite_Customize();
+
+float WaypointSprite_SendEntity(entity to, float sendflags);
+
+void WaypointSprite_Reset();
+
+entity WaypointSprite_Spawn(
+    string spr, // sprite
+    float lifetime, float maxdistance, // lifetime, max distance
+    entity ref, vector ofs, // position
+    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, vector rgb // initial icon and color
+);
+
+entity WaypointSprite_SpawnFixed(
+    string spr,
+    vector ofs,
+    entity own,
+    .entity ownfield,
+    float icon, vector rgb // initial icon and color
+);
+
+.entity waypointsprite_deployed_fixed;
+entity WaypointSprite_DeployFixed(
+    string spr,
+    float limited_range,
+    vector ofs,
+    float icon, vector rgb // initial icon and color
+);
+
+.entity waypointsprite_deployed_personal;
+entity WaypointSprite_DeployPersonal(
+    string spr,
+    vector ofs,
+    float icon, vector rgb // initial icon and color
+);
+
+.entity waypointsprite_attached;
+.entity waypointsprite_attachedforcarrier;
+entity WaypointSprite_Attach(
+    string spr,
+    float limited_range,
+    float icon, vector rgb // initial icon and color
+);
+
+entity WaypointSprite_AttachCarrier(
+    string spr,
+    entity carrier,
+    float icon, vector rgb // initial icon and color
+);
+
+void WaypointSprite_DetachCarrier(entity carrier);
+
+void WaypointSprite_ClearPersonal();
+
+void WaypointSprite_ClearOwned();
+
+void WaypointSprite_PlayerDead();
+
+void WaypointSprite_PlayerGone();
+#endif
+
+#endif
index 15d7035ce68e32f9731f13b51b3b9fd760dfc586..12a225ad9ef8966888aad0a94b1593affbe3636b 100644 (file)
@@ -3,7 +3,6 @@
 #include "../../../server/_all.qh"
 
 #include "../../../server/g_subs.qh"
-#include "../../../server/waypointsprites.qh"
 #include "../../../server/g_damage.qh"
 #include "../../../server/bot/bot.qh"
 #include "../../common/csqcmodel_settings.qh"
index 9a832efd4d67449fdb99f533603e427adf0356ac..8caae09ddc08d158307bcd5191c01ef2da3ab811 100644 (file)
@@ -1,7 +1,5 @@
 #include "cl_client.qh"
 
-#include "waypointsprites.qh"
-
 #include "anticheat.qh"
 #include "cl_impulse.qh"
 #include "cl_player.qh"
@@ -35,6 +33,8 @@
 
 #include "../common/items/all.qc"
 
+#include "../common/mutators/mutator/waypointsprites.qh"
+
 #include "../common/triggers/subs.qh"
 #include "../common/triggers/triggers.qh"
 #include "../common/triggers/trigger/secret.qh"
index 45708409c5fe9731e95088dee3fcb9779b15daa1..692b0c269e1aa4aa7fa34a72893aab8c63b48a5f 100644 (file)
@@ -10,7 +10,6 @@
 #include "weapons/selection.qh"
 #include "weapons/tracing.qh"
 #include "weapons/weaponsystem.qh"
-#include "waypointsprites.qh"
 
 #include "../common/weapons/all.qh"
 
index e3bb91e3954bfe112009a2d0a28d2549797993f0..d554ad2962a78c2a4ea5cb631260e59f94562ee9 100644 (file)
@@ -9,7 +9,6 @@
 #include "miscfunctions.qh"
 #include "portals.qh"
 #include "teamplay.qh"
-#include "waypointsprites.qh"
 #include "weapons/throwing.qh"
 #include "command/common.qh"
 #include "../common/animdecide.qh"
index 9791bbd2933ceac46d4e54e91fc7f0a6132978ad..238040406b5627ca0c7ce5f8c2166de6fe11fc56 100644 (file)
@@ -4,7 +4,6 @@
 #include "g_hook.qh"
 #include "mutators/mutators_include.qh"
 #include "scores.qh"
-#include "waypointsprites.qh"
 #include "spawnpoints.qh"
 #include "t_items.qh"
 #include "../common/vehicles/all.qh"
index 0fc713f69ab2d4e7f92a43b4c648d487bf4dd5b9..e8d6465591cfe345e8f38080a0110779d788047e 100644 (file)
@@ -18,7 +18,6 @@
 #include "race.qh"
 #include "scores.qh"
 #include "teamplay.qh"
-#include "waypointsprites.qh"
 #include "weapons/weaponstats.qh"
 #include "../common/buffs.qh"
 #include "../common/constants.qh"
index 32e48f370162f6c89c4c11b8c4fb0e26aa802bec..d272af85796edc6e2c206fb454a4f36cd3ec05ac 100644 (file)
@@ -11,7 +11,6 @@
 #include "../round_handler.qh"
 #include "../scores.qh"
 #include "../scores_rules.qh"
-#include "../waypointsprites.qh"
 
 #include "../bot/bot.qh"
 #include "../bot/navigation.qh"
index f23f42a8924dd717ab63e900f57d13be6ea0f4ff..fa4c9ec8fbccd535a81233ea900a9d5e1aeab565 100644 (file)
@@ -12,7 +12,6 @@
 #include "../round_handler.qh"
 #include "../scores.qh"
 #include "../scores_rules.qh"
-#include "../waypointsprites.qh"
 
 #include "../bot/bot.qh"
 #include "../bot/navigation.qh"
index 3d39893d06401c9989255ba5935ac317c215f259..318d1f874ef74a8b057a967ed973db337592cd3f 100644 (file)
@@ -47,7 +47,6 @@ t_halflife.qc
 t_items.qc
 t_quake3.qc
 t_quake.qc
-waypointsprites.qc
 
 bot/aim.qc
 bot/bot.qc
index 4482fe327901b7e42a4e91da460fc596f6f3d525..cc6d8c4f53a98040de7b0e81c735b074e211446a 100644 (file)
@@ -5,7 +5,6 @@
 #include "portals.qh"
 #include "scores.qh"
 #include "spawnpoints.qh"
-#include "waypointsprites.qh"
 #include "bot/waypoints.qh"
 #include "bot/navigation.qh"
 #include "command/getreplies.qh"
index e281cfacf604d6bb1b405f488c2ec090dbd93e7f..a0dbb61d2caaf63aa5c6d4b1a62c09e89e896599 100644 (file)
@@ -5,8 +5,6 @@
 #if defined(SVQC)
     #include "_all.qh"
 
-    #include "waypointsprites.qh"
-
     #include "bot/bot.qh"
     #include "bot/waypoints.qh"
 
diff --git a/qcsrc/server/waypointsprites.qc b/qcsrc/server/waypointsprites.qc
deleted file mode 100644 (file)
index 8c47014..0000000
+++ /dev/null
@@ -1,523 +0,0 @@
-#include "waypointsprites.qh"
-
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
-    #include "../common/constants.qh"
-    #include "../common/util.qh"
-    #include "../common/buffs.qh"
-    #include "autocvars.qh"
-    #include "constants.qh"
-    #include "defs.qh"
-    #include "../common/deathtypes.qh"
-    #include "mutators/mutators_include.qh"
-    #include "../common/mapinfo.qh"
-    #include "miscfunctions.qh"
-#endif
-
-void WaypointSprite_UpdateSprites(entity e, string m1, string m2, string m3)
-{
-       if(m1 != e.model1)
-       {
-               e.model1 = m1;
-               e.SendFlags |= 2;
-       }
-       if(m2 != e.model2)
-       {
-               e.model2 = m2;
-               e.SendFlags |= 4;
-       }
-       if(m3 != e.model3)
-       {
-               e.model3 = m3;
-               e.SendFlags |= 8;
-       }
-}
-
-void WaypointSprite_UpdateHealth(entity e, float f)
-{
-       f = bound(0, f, e.max_health);
-       if(f != e.health || e.pain_finished)
-       {
-               e.health = f;
-               e.pain_finished = 0;
-               e.SendFlags |= 0x80;
-       }
-}
-
-void WaypointSprite_UpdateMaxHealth(entity e, float f)
-{
-       if(f != e.max_health || e.pain_finished)
-       {
-               e.max_health = f;
-               e.pain_finished = 0;
-               e.SendFlags |= 0x80;
-       }
-}
-
-void WaypointSprite_UpdateBuildFinished(entity e, float f)
-{
-       if(f != e.pain_finished || e.max_health)
-       {
-               e.max_health = 0;
-               e.pain_finished = f;
-               e.SendFlags |= 0x80;
-       }
-}
-
-void WaypointSprite_UpdateOrigin(entity e, vector o)
-{
-       if(o != e.origin)
-       {
-               setorigin(e, o);
-               e.SendFlags |= 64;
-       }
-}
-
-void WaypointSprite_UpdateRule(entity e, float t, float r)
-{
-       // no check, as this is never called without doing an actual change (usually only once)
-       e.rule = r;
-       e.team = t;
-       e.SendFlags |= 1;
-}
-
-void WaypointSprite_UpdateTeamRadar(entity e, float 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);
-       e.colormod = col;
-       e.SendFlags |= 32;
-}
-
-void WaypointSprite_Ping(entity e)
-{
-       // anti spam
-       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.SendFlags |= 32;
-}
-
-void WaypointSprite_HelpMePing(entity e)
-{
-       WaypointSprite_Ping(e);
-       e.waypointsprite_helpmetime = time + waypointsprite_deployed_lifetime;
-       e.SendFlags |= 32;
-}
-
-void WaypointSprite_FadeOutIn(entity e, float t)
-{
-       if(!e.fade_time)
-       {
-               e.fade_time = t;
-               e.teleport_time = time + t;
-       }
-       else if(t < (e.teleport_time - time))
-       {
-               // accelerate the waypoint's dying
-               // ensure:
-               //   (e.teleport_time - time) / wp.fade_time stays
-               //   e.teleport_time = time + fadetime
-               float current_fadetime;
-               current_fadetime = e.teleport_time - time;
-               e.teleport_time = time + t;
-               e.fade_time = e.fade_time * t / current_fadetime;
-       }
-
-       e.SendFlags |= 16;
-}
-
-void WaypointSprite_Init()
-{
-       waypointsprite_limitedrange = autocvar_sv_waypointsprite_limitedrange;
-       waypointsprite_deployed_lifetime = autocvar_sv_waypointsprite_deployed_lifetime;
-       waypointsprite_deadlifetime = autocvar_sv_waypointsprite_deadlifetime;
-}
-
-void WaypointSprite_InitClient(entity e)
-{
-}
-
-void WaypointSprite_Kill(entity wp)
-{
-       if(!wp)
-               return;
-       if(wp.owner)
-               wp.owner.(wp.owned_by_field) = world;
-       remove(wp);
-}
-
-void WaypointSprite_Disown(entity wp, float fadetime)
-{
-       if(!wp)
-               return;
-       if(wp.classname != "sprite_waypoint")
-       {
-               backtrace("Trying to disown a non-waypointsprite");
-               return;
-       }
-       if(wp.owner)
-       {
-               if(wp.exteriormodeltoclient == wp.owner)
-                       wp.exteriormodeltoclient = world;
-               wp.owner.(wp.owned_by_field) = world;
-               wp.owner = world;
-
-               WaypointSprite_FadeOutIn(wp, fadetime);
-       }
-}
-
-void WaypointSprite_Think()
-{
-       float doremove;
-
-       doremove = false;
-
-       if(self.fade_time)
-       {
-               if(time >= self.teleport_time)
-                       doremove = true;
-       }
-
-       if(self.exteriormodeltoclient)
-               WaypointSprite_UpdateOrigin(self, self.exteriormodeltoclient.origin + self.view_ofs);
-
-       if(doremove)
-               WaypointSprite_Kill(self);
-       else
-               self.nextthink = time; // WHY?!?
-}
-
-float WaypointSprite_visible_for_player(entity e)
-{
-       // personal waypoints
-       if(self.enemy)
-               if(self.enemy != e)
-                       return false;
-
-       // team waypoints
-       if(self.rule == SPRITERULE_SPECTATOR)
-       {
-               if(!autocvar_sv_itemstime)
-                       return FALSE;
-               if(!warmup_stage && IS_PLAYER(e))
-                       return FALSE;
-       }
-       else if(self.team && self.rule == SPRITERULE_DEFAULT)
-       {
-               if(self.team != e.team)
-                       return false;
-               if (!IS_PLAYER(e))
-                       return false;
-       }
-
-       return true;
-}
-
-entity WaypointSprite_getviewentity(entity e)
-{
-       if(IS_SPEC(e))
-               e = e.enemy;
-       /* TODO idea (check this breaks nothing)
-       else if(e.classname == "observer")
-               e = world;
-       */
-       return e;
-}
-
-float WaypointSprite_isteammate(entity e, entity e2)
-{
-       if(teamplay)
-       {
-               if(e2.team != e.team)
-                       return false;
-       }
-       else
-       {
-               if(e2 != e)
-                       return false;
-       }
-       return true;
-}
-
-float WaypointSprite_Customize()
-{
-       // this is not in SendEntity because it shall run every frame, not just every update
-
-       // make spectators see what the player would see
-       entity e = WaypointSprite_getviewentity(other);
-
-       if(MUTATOR_CALLHOOK(CustomizeWaypoint, self, other))
-               return false;
-
-       return self.waypointsprite_visible_for_player(e);
-}
-
-float WaypointSprite_SendEntity(entity to, float sendflags)
-{
-       float dt;
-
-       WriteMutator(MSG_ENTITY, waypointsprites);
-
-       sendflags = sendflags & 0x7F;
-
-       if(g_nexball)
-               sendflags &= ~0x80;
-       else if(self.max_health || (self.pain_finished && (time < self.pain_finished + 0.25)))
-               sendflags |= 0x80;
-
-       WriteByte(MSG_ENTITY, sendflags);
-
-       if(sendflags & 0x80)
-       {
-               if(self.max_health)
-               {
-                       WriteByte(MSG_ENTITY, (self.health / self.max_health) * 191.0);
-               }
-               else
-               {
-                       dt = self.pain_finished - time;
-                       dt = bound(0, dt * 32, 16383);
-                       WriteByte(MSG_ENTITY, (dt & 0xFF00) / 256 + 192);
-                       WriteByte(MSG_ENTITY, (dt & 0x00FF));
-               }
-       }
-
-       if(sendflags & 64)
-       {
-               WriteCoord(MSG_ENTITY, self.origin.x);
-               WriteCoord(MSG_ENTITY, self.origin.y);
-               WriteCoord(MSG_ENTITY, self.origin.z);
-       }
-
-       if(sendflags & 1)
-       {
-               WriteByte(MSG_ENTITY, self.team);
-               WriteByte(MSG_ENTITY, self.rule);
-       }
-
-       if(sendflags & 2)
-               WriteString(MSG_ENTITY, self.model1);
-
-       if(sendflags & 4)
-               WriteString(MSG_ENTITY, self.model2);
-
-       if(sendflags & 8)
-               WriteString(MSG_ENTITY, self.model3);
-
-       if(sendflags & 16)
-       {
-               WriteCoord(MSG_ENTITY, self.fade_time);
-               WriteCoord(MSG_ENTITY, self.teleport_time);
-               WriteShort(MSG_ENTITY, self.fade_rate); // maxdist
-               float f = 0;
-               if(self.currentammo)
-                       f |= 1; // hideable
-               if(self.exteriormodeltoclient == to)
-                       f |= 2; // my own
-               if(g_onslaught)
-               {
-                       if(self.owner.classname == "onslaught_controlpoint")
-                       {
-                               entity wp_owner = self.owner;
-                               entity e = WaypointSprite_getviewentity(to);
-                               if(SAME_TEAM(e, wp_owner) && wp_owner.goalentity.health >= wp_owner.goalentity.max_health) { f |= 2; }
-                               if(!ons_ControlPoint_Attackable(wp_owner, e.team)) { f |= 2; }
-                       }
-                       if(self.owner.classname == "onslaught_generator")
-                       {
-                               entity wp_owner = self.owner;
-                               if(wp_owner.isshielded && wp_owner.health >= wp_owner.max_health) { f |= 2; }
-                               if(wp_owner.health <= 0) { f |= 2; }
-                       }
-               }
-               WriteByte(MSG_ENTITY, f);
-       }
-
-       if(sendflags & 32)
-       {
-               WriteByte(MSG_ENTITY, self.cnt); // icon on radar
-               WriteByte(MSG_ENTITY, self.colormod.x * 255.0);
-               WriteByte(MSG_ENTITY, self.colormod.y * 255.0);
-               WriteByte(MSG_ENTITY, self.colormod.z * 255.0);
-
-               if(WaypointSprite_isteammate(self.owner, WaypointSprite_getviewentity(to)))
-               {
-                       dt = (self.waypointsprite_helpmetime - time) / 0.1;
-                       if(dt < 0)
-                               dt = 0;
-                       if(dt > 255)
-                               dt = 255;
-                       WriteByte(MSG_ENTITY, dt);
-               }
-               else
-                       WriteByte(MSG_ENTITY, 0);
-       }
-
-       return true;
-}
-
-void WaypointSprite_Reset()
-{
-       // if a WP wants to time out, let it time out immediately; other WPs ought to be reset/killed by their owners
-
-       if(self.fade_time) // there was there before: || g_keyhunt, do we really need this?
-               WaypointSprite_Kill(self);
-}
-
-entity WaypointSprite_Spawn(
-       string spr, // sprite
-       float _lifetime, float maxdistance, // lifetime, max distance
-       entity ref, vector ofs, // position
-       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, vector rgb // initial icon and color
-)
-{
-       entity wp;
-       wp = spawn();
-       wp.classname = "sprite_waypoint";
-       wp.teleport_time = time + _lifetime;
-       wp.fade_time = _lifetime;
-       wp.exteriormodeltoclient = ref;
-       if(ref)
-       {
-               wp.view_ofs = ofs;
-               setorigin(wp, ref.origin + ofs);
-       }
-       else
-               setorigin(wp, ofs);
-       wp.enemy = showto;
-       wp.team = t;
-       wp.owner = own;
-       wp.currentammo = hideable;
-       if (own)
-       {
-               if (own.(ownfield))
-                       remove(own.(ownfield));
-               own.(ownfield) = wp;
-               wp.owned_by_field = ownfield;
-       }
-       wp.fade_rate = maxdistance;
-       wp.think = WaypointSprite_Think;
-       wp.nextthink = time;
-       wp.model1 = spr;
-       wp.customizeentityforclient = WaypointSprite_Customize;
-       wp.waypointsprite_visible_for_player = WaypointSprite_visible_for_player;
-       wp.reset2 = WaypointSprite_Reset;
-       wp.cnt = icon;
-       wp.colormod = rgb;
-       Net_LinkEntity(wp, false, 0, WaypointSprite_SendEntity);
-       return wp;
-}
-
-entity WaypointSprite_SpawnFixed(
-       string spr,
-       vector ofs,
-       entity own,
-       .entity ownfield,
-       float icon, vector rgb // initial icon and color
-)
-{
-       return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, own, ownfield, true, icon, rgb);
-}
-
-entity WaypointSprite_DeployFixed(
-       string spr,
-       float limited_range,
-       vector ofs,
-       float icon, vector rgb // initial icon and color
-)
-{
-       float t, maxdistance;
-       if(teamplay)
-               t = self.team;
-       else
-               t = 0;
-       if(limited_range)
-               maxdistance = waypointsprite_limitedrange;
-       else
-               maxdistance = 0;
-       return WaypointSprite_Spawn(spr, waypointsprite_deployed_lifetime, maxdistance, world, ofs, world, t, self, waypointsprite_deployed_fixed, false, icon, rgb);
-}
-
-entity WaypointSprite_DeployPersonal(
-       string spr,
-       vector ofs,
-       float icon, vector rgb // initial icon and color
-)
-{
-       return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, self, waypointsprite_deployed_personal, false, icon, rgb);
-}
-
-entity WaypointSprite_Attach(
-       string spr,
-       float limited_range,
-       float icon, vector rgb // initial icon and color
-)
-{
-       float t, maxdistance;
-       if(self.waypointsprite_attachedforcarrier)
-               return world; // can't attach to FC
-       if(teamplay)
-               t = self.team;
-       else
-               t = 0;
-       if(limited_range)
-               maxdistance = waypointsprite_limitedrange;
-       else
-               maxdistance = 0;
-       return WaypointSprite_Spawn(spr, waypointsprite_deployed_lifetime, maxdistance, self, '0 0 64', world, t, self, waypointsprite_attached, false, icon, rgb);
-}
-
-entity WaypointSprite_AttachCarrier(
-       string spr,
-       entity carrier,
-       float icon, vector rgb // initial icon and color
-)
-{
-       entity e;
-       WaypointSprite_Kill(carrier.waypointsprite_attached); // FC overrides attached
-       e = WaypointSprite_Spawn(spr, 0, 0, carrier, '0 0 64', world, carrier.team, carrier, waypointsprite_attachedforcarrier, false, icon, rgb);
-       if(e)
-       {
-               WaypointSprite_UpdateMaxHealth(e, '1 0 0' * healtharmor_maxdamage(start_health, start_armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON) * 2);
-               WaypointSprite_UpdateHealth(e, '1 0 0' * healtharmor_maxdamage(carrier.health, carrier.armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON));
-       }
-       return e;
-}
-
-void WaypointSprite_DetachCarrier(entity carrier)
-{
-       WaypointSprite_Disown(carrier.waypointsprite_attachedforcarrier, waypointsprite_deadlifetime);
-}
-
-void WaypointSprite_ClearPersonal()
-{
-       WaypointSprite_Kill(self.waypointsprite_deployed_personal);
-}
-
-void WaypointSprite_ClearOwned()
-{
-       WaypointSprite_Kill(self.waypointsprite_deployed_fixed);
-       WaypointSprite_Kill(self.waypointsprite_deployed_personal);
-       WaypointSprite_Kill(self.waypointsprite_attached);
-}
-
-void WaypointSprite_PlayerDead()
-{
-       WaypointSprite_Disown(self.waypointsprite_attached, waypointsprite_deadlifetime);
-       WaypointSprite_DetachCarrier(self);
-}
-
-void WaypointSprite_PlayerGone()
-{
-       WaypointSprite_Disown(self.waypointsprite_deployed_fixed, waypointsprite_deadlifetime);
-       WaypointSprite_Kill(self.waypointsprite_deployed_personal);
-       WaypointSprite_Disown(self.waypointsprite_attached, waypointsprite_deadlifetime);
-       WaypointSprite_DetachCarrier(self);
-}
diff --git a/qcsrc/server/waypointsprites.qh b/qcsrc/server/waypointsprites.qh
deleted file mode 100644 (file)
index 430e583..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-#ifndef SERVER_WAYPOINTSPRITES_H
-#define SERVER_WAYPOINTSPRITES_H
-
-..entity owned_by_field;
-.float rule;
-.string model1;
-.string model2;
-.string model3;
-
-.float(entity) waypointsprite_visible_for_player;
-
-void WaypointSprite_UpdateSprites(entity e, string m1, string m2, string m3);
-
-void WaypointSprite_UpdateHealth(entity e, float f);
-
-void WaypointSprite_UpdateMaxHealth(entity e, float f);
-
-void WaypointSprite_UpdateBuildFinished(entity e, float f);
-
-void WaypointSprite_UpdateOrigin(entity e, vector o);
-
-void WaypointSprite_UpdateRule(entity e, float t, float r);
-
-void WaypointSprite_UpdateTeamRadar(entity e, float icon, vector col);
-
-.float waypointsprite_pingtime;
-.float waypointsprite_helpmetime;
-void WaypointSprite_Ping(entity e);
-
-float waypointsprite_limitedrange, waypointsprite_deployed_lifetime, waypointsprite_deadlifetime;
-
-void WaypointSprite_HelpMePing(entity e);
-
-void WaypointSprite_FadeOutIn(entity e, float t);
-
-void WaypointSprite_Init();
-void WaypointSprite_InitClient(entity e);
-
-void WaypointSprite_Kill(entity wp);
-
-void WaypointSprite_Disown(entity wp, float fadetime);
-
-void WaypointSprite_Think();
-
-float WaypointSprite_visible_for_player(entity e);
-
-entity WaypointSprite_getviewentity(entity e);
-
-float WaypointSprite_isteammate(entity e, entity e2);
-
-float WaypointSprite_Customize();
-
-float WaypointSprite_SendEntity(entity to, float sendflags);
-
-void WaypointSprite_Reset();
-
-entity WaypointSprite_Spawn(
-       string spr, // sprite
-       float lifetime, float maxdistance, // lifetime, max distance
-       entity ref, vector ofs, // position
-       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, vector rgb // initial icon and color
-);
-
-entity WaypointSprite_SpawnFixed(
-       string spr,
-       vector ofs,
-       entity own,
-       .entity ownfield,
-       float icon, vector rgb // initial icon and color
-);
-
-.entity waypointsprite_deployed_fixed;
-entity WaypointSprite_DeployFixed(
-       string spr,
-       float limited_range,
-       vector ofs,
-       float icon, vector rgb // initial icon and color
-);
-
-.entity waypointsprite_deployed_personal;
-entity WaypointSprite_DeployPersonal(
-       string spr,
-       vector ofs,
-       float icon, vector rgb // initial icon and color
-);
-
-.entity waypointsprite_attached;
-.entity waypointsprite_attachedforcarrier;
-entity WaypointSprite_Attach(
-       string spr,
-       float limited_range,
-       float icon, vector rgb // initial icon and color
-);
-
-entity WaypointSprite_AttachCarrier(
-       string spr,
-       entity carrier,
-       float icon, vector rgb // initial icon and color
-);
-
-void WaypointSprite_DetachCarrier(entity carrier);
-
-void WaypointSprite_ClearPersonal();
-
-void WaypointSprite_ClearOwned();
-
-void WaypointSprite_PlayerDead();
-
-void WaypointSprite_PlayerGone();
-#endif
index 868d6b041b0dc9207fa5fbe6920ad6286d04699e..1190dceb1c58a0cbc2f17762305ba75502f05628 100644 (file)
@@ -3,7 +3,6 @@
 
 #include "weaponsystem.qh"
 #include "../t_items.qh"
-#include "../waypointsprites.qh"
 #include "../../common/constants.qh"
 #include "../../common/util.qh"
 #include "../../common/weapons/all.qh"