]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'TimePath/gamesettings' into 'master'
authorTimePath <andrew.hardaker1995@gmail.com>
Wed, 26 Aug 2015 12:28:58 +0000 (12:28 +0000)
committerTimePath <andrew.hardaker1995@gmail.com>
Wed, 26 Aug 2015 12:28:58 +0000 (12:28 +0000)
Game settings as list

Finally something to do away with all those tabs

* Makes it possible for mutators to add settings panels
* Adds one for damage text

![](https://dl.dropboxusercontent.com/u/42745598/screenshots/2015-08-25_22-12-51.png)

See merge request !205

54 files changed:
_hud_common.cfg
qcsrc/client/autocvars.qh
qcsrc/client/casings.qc
qcsrc/client/csqcmodel_hooks.qc
qcsrc/client/main.qc
qcsrc/client/mutators/events.qh
qcsrc/client/player_skeleton.qc
qcsrc/client/progs.src
qcsrc/client/view.qc
qcsrc/client/waypointsprites.qc [deleted file]
qcsrc/client/waypointsprites.qh [deleted file]
qcsrc/common/minigames/minigame/pong.qc
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/mutators/all.inc
qcsrc/common/mutators/mutator/itemstime.qc
qcsrc/common/mutators/mutator/waypoints/all.inc [new file with mode: 0644]
qcsrc/common/mutators/mutator/waypoints/all.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc [new file with mode: 0644]
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/waypointsprites.qc [deleted file]
qcsrc/common/notifications.qh
qcsrc/common/triggers/func/breakable.qc
qcsrc/common/util.qc
qcsrc/common/vehicles/sv_vehicles.qc
qcsrc/common/weapons/w_seeker.qc
qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc
qcsrc/server/autocvars.qh
qcsrc/server/cl_client.qc
qcsrc/server/cl_impulse.qc
qcsrc/server/cl_player.qc
qcsrc/server/command/vote.qc
qcsrc/server/g_damage.qc
qcsrc/server/g_world.qc
qcsrc/server/mutators/events.qh
qcsrc/server/mutators/gamemode.qh
qcsrc/server/mutators/gamemode_assault.qc
qcsrc/server/mutators/gamemode_ctf.qc
qcsrc/server/mutators/gamemode_ctf.qh
qcsrc/server/mutators/gamemode_domination.qc
qcsrc/server/mutators/gamemode_keepaway.qc
qcsrc/server/mutators/gamemode_keyhunt.qc
qcsrc/server/mutators/gamemode_nexball.qc
qcsrc/server/mutators/gamemode_nexball.qh
qcsrc/server/mutators/gamemode_onslaught.qc
qcsrc/server/mutators/mutator.qh
qcsrc/server/mutators/mutator_buffs.qc
qcsrc/server/progs.src
qcsrc/server/race.qc
qcsrc/server/t_items.qc
qcsrc/server/teamplay.qc
qcsrc/server/waypointsprites.qc [deleted file]
qcsrc/server/waypointsprites.qh [deleted file]
qcsrc/server/weapons/selection.qc
xonotic-credits.txt

index d409ee1e6736499f3a0b2ce7eddca51bbec1f89f..f17e7ac60b33c2040f94c7f67836cbb19e68c896 100644 (file)
@@ -43,6 +43,7 @@ seta hud_panel_phisics_update_interval 0.0666 "how often (in seconds) numeric va
 
 seta hud_panel_itemstime_progressbar_maxtime "30" "when left time is at least this amount, the status bar is full"
 seta hud_panel_itemstime_hidespawned "1" "if 1 hide an item from the panel when all the occurrences of it are available again; if 2 hide it when at least one occurrence is available again"
+seta hud_panel_itemstime_hidelarge "0" "if 1 hide large armor and health from the panel"
 
 // hud panel aliases
 alias hud_panel_radar_rotate "toggle hud_panel_radar_rotation 0 1 2 3 4"
index a9a442b308f5068fa005b35f5d8baae579bda85e..b128f01a7fc12945f605676a4248a557334374b1 100644 (file)
@@ -158,32 +158,6 @@ float autocvar_g_balance_tuba_fadetime;
 float autocvar_g_balance_tuba_volume;
 int autocvar_g_balance_tuba_pitchstep;
 float autocvar_g_warmup_limit;
-bool autocvar_g_waypointsprite_uppercase;
-float autocvar_g_waypointsprite_alpha;
-float autocvar_g_waypointsprite_crosshairfadealpha;
-float autocvar_g_waypointsprite_crosshairfadedistance;
-float autocvar_g_waypointsprite_crosshairfadescale;
-float autocvar_g_waypointsprite_distancealphaexponent;
-float autocvar_g_waypointsprite_distancefadealpha;
-float autocvar_g_waypointsprite_distancefadedistancemultiplier;
-float autocvar_g_waypointsprite_distancefadescale;
-float autocvar_g_waypointsprite_edgefadealpha;
-float autocvar_g_waypointsprite_edgefadedistance;
-float autocvar_g_waypointsprite_edgefadescale;
-float autocvar_g_waypointsprite_edgeoffset_bottom;
-float autocvar_g_waypointsprite_edgeoffset_left;
-float autocvar_g_waypointsprite_edgeoffset_right;
-float autocvar_g_waypointsprite_edgeoffset_top;
-float autocvar_g_waypointsprite_fontsize;
-int autocvar_g_waypointsprite_itemstime;
-float autocvar_g_waypointsprite_minalpha;
-float autocvar_g_waypointsprite_minscale;
-float autocvar_g_waypointsprite_normdistance;
-float autocvar_g_waypointsprite_scale;
-int autocvar_g_waypointsprite_spam;
-float autocvar_g_waypointsprite_timealphaexponent;
-bool autocvar_g_waypointsprite_turrets = true;
-float autocvar_g_waypointsprite_turrets_maxdist = 5000;
 bool autocvar_hud_cursormode = true;
 float autocvar_hud_colorflash_alpha;
 bool autocvar_hud_configure_checkcollisions;
@@ -272,16 +246,6 @@ float autocvar_hud_panel_healtharmor_progressbar_gfx_damage;
 float autocvar_hud_panel_healtharmor_progressbar_gfx_lowhealth;
 float autocvar_hud_panel_healtharmor_progressbar_gfx_smooth;
 int autocvar_hud_panel_healtharmor_text;
-int autocvar_hud_panel_itemstime = 2;
-float autocvar_hud_panel_itemstime_dynamicsize = 1;
-float autocvar_hud_panel_itemstime_ratio = 2;
-int autocvar_hud_panel_itemstime_iconalign;
-bool autocvar_hud_panel_itemstime_progressbar = 0;
-float autocvar_hud_panel_itemstime_progressbar_maxtime = 30;
-string autocvar_hud_panel_itemstime_progressbar_name = "progressbar";
-float autocvar_hud_panel_itemstime_progressbar_reduced;
-bool autocvar_hud_panel_itemstime_hidespawned = 1;
-int autocvar_hud_panel_itemstime_text = 1;
 bool autocvar_hud_panel_infomessages;
 bool autocvar_hud_panel_infomessages_flip;
 bool autocvar_hud_panel_modicons;
index 09c2e685365f8915633d7c954e96d2af62dfd7ba..61d7f10ba5c9be8715e8d9e833a53b41de9dd188 100644 (file)
@@ -146,10 +146,10 @@ void Casings_Precache()
 {
        precache_model("models/casing_shell.mdl");
        precache_model("models/casing_bronze.iqm");
-       precache_sound(W_Sound("brass1.wav"));
-       precache_sound(W_Sound("brass2.wav"));
-       precache_sound(W_Sound("brass3.wav"));
-       precache_sound(W_Sound("casings1.wav"));
-       precache_sound(W_Sound("casings2.wav"));
-       precache_sound(W_Sound("casings3.wav"));
+       precache_sound(W_Sound("brass1"));
+       precache_sound(W_Sound("brass2"));
+       precache_sound(W_Sound("brass3"));
+       precache_sound(W_Sound("casings1"));
+       precache_sound(W_Sound("casings2"));
+       precache_sound(W_Sound("casings3"));
 }
index 91f3bfb4c6410f6b163e38eba85b882635bd6cfa..227341ae3d4936458a81d1369e89e1fa8e92d492 100644 (file)
@@ -12,6 +12,8 @@
 #include "../common/teams.qh"
 #include "../common/triggers/trigger/viewloc.qh"
 
+#include "mutators/events.qh"
+
 #include "../csqcmodellib/cl_model.qh"
 #include "../csqcmodellib/cl_player.qh"
 #include "../csqcmodellib/interpolate.qh"
@@ -407,6 +409,8 @@ void CSQCModel_AutoTagIndex_Apply(void)
        if(self.viewloc.entnum != self.tag_networkviewloc)
                self.viewloc = findfloat(world, entnum, self.tag_networkviewloc);
 
+       MUTATOR_CALLHOOK(TagIndex_Update, self);
+
        if(self.tag_networkentity)
        {
                // we are ATTACHED!
@@ -464,6 +468,8 @@ void CSQCModel_AutoTagIndex_Apply(void)
                                        if(!self.tag_index)
                                                self.tag_index = gettagindex(self.tag_entity, "tag_shot");
                                }
+
+                               MUTATOR_CALLHOOK(TagIndex_Apply, self);
                        }
                        else
                        {
index fac620461785a032d241cfe720fbb8e631c4ee2b..da485708e8e2a6c753339cdbde1f950f537b6ab7 100644 (file)
@@ -22,7 +22,6 @@
 #include "tuba.qh"
 #include "t_items.qh"
 #include "wall.qh"
-#include "waypointsprites.qh"
 
 #include "../common/vehicles/all.qh"
 
@@ -88,7 +87,6 @@ void menu_sub_null()
 }
 
 string forcefog;
-void WaypointSprite_Load();
 void ConsoleCommand_macro_init();
 void CSQC_Init(void)
 {
@@ -157,8 +155,6 @@ void CSQC_Init(void)
 
        initialize_minigames();
 
-       WaypointSprite_Load();
-
        // precaches
        precache_model("null");
        precache_sound("misc/hit.wav");
index 16ae922f220ba774fb3dfdc892eb411de9b89da1..86be898d9bae6942a29b43995086cd1ab23ec656 100644 (file)
@@ -76,4 +76,39 @@ MUTATOR_HOOKABLE(EditProjectile, EV_EditProjectile);
 /* Called when projectiles are precached */
 MUTATOR_HOOKABLE(PrecacheProjectiles, EV_NO_ARGS);
 
+/** Called when updating the attached tags index */
+#define EV_TagIndex_Update(i, o) \
+    /** entity id */ i(entity, self) \
+    /**/
+MUTATOR_HOOKABLE(TagIndex_Update, EV_TagIndex_Update);
+
+/** Called when setting the attached tags */
+#define EV_TagIndex_Apply(i, o) \
+    /** entity id */ i(entity, self) \
+    /**/
+MUTATOR_HOOKABLE(TagIndex_Apply, EV_TagIndex_Apply);
+
+/** Called when setting up skeleton bones */
+#define EV_Skeleton_CheckBones(i, o) \
+    /** entity id */ i(entity, self) \
+    /**/
+MUTATOR_HOOKABLE(Skeleton_CheckBones, EV_Skeleton_CheckBones);
+
+/** Called when setting up bones from the loaded model */
+#define EV_Skeleton_CheckModel(i, o) \
+    /** entity id */ i(entity, self) \
+    /**/
+MUTATOR_HOOKABLE(Skeleton_CheckModel, EV_Skeleton_CheckModel);
+
+/** Called when clearing the global parameters for a model */
+MUTATOR_HOOKABLE(ClearModelParams, EV_NO_ARGS);
+
+/** Called when getting the global parameters for a model */
+#define EV_GetModelParams(i, o) \
+    /** entity id */ i(string, checkmodel_input) \
+    /** entity id */ i(string, checkmodel_command) \
+    /**/
+string checkmodel_input, checkmodel_command;
+MUTATOR_HOOKABLE(GetModelParams, EV_GetModelParams);
+
 #endif
index 4039c905c1f135f3afea1e2e6d1e76d7c65947c5..96b91d1c8042d4a7611e47da81b778443c625dbe 100644 (file)
@@ -23,6 +23,7 @@ void skeleton_loadinfo(entity e)
                e.bone_weapon = gettagindex(e, "tag_weapon");
        if(!e.bone_weapon)
                e.bone_weapon = gettagindex(e, "bip01 r hand");
+       MUTATOR_CALLHOOK(Skeleton_CheckBones, e);
        for(i = 0; i < MAX_AIM_BONES; ++i)
        {
                e.(bone_aim[i]) = 0;
@@ -37,6 +38,7 @@ void skeleton_loadinfo(entity e)
                        e.fixbone = get_model_parameters_fixbone;
                if(get_model_parameters_bone_weapon)
                        e.bone_weapon = gettagindex(e, get_model_parameters_bone_weapon);
+               MUTATOR_CALLHOOK(Skeleton_CheckModel, e);
                for(i = 0; i < MAX_AIM_BONES; ++i)
                {
                        if(get_model_parameters_bone_aim[i])
index ce31eb6474a1d8a1a0bf16635d8e0f128a4da644..b9006dd2c637fe4a675326d6d0d5148bb6f5c871 100644 (file)
@@ -36,7 +36,6 @@ tuba.qc
 t_items.qc
 view.qc
 wall.qc
-waypointsprites.qc
 
 command/all.qc
 
index 533668297cbca345752c1f524282a8a008a84010..9b4eddd4891d7e4f80f4ccd4af9157b7c927b4cb 100644 (file)
@@ -8,7 +8,6 @@
 #include "noise.qh"
 #include "scoreboard.qh"
 #include "shownames.qh"
-#include "waypointsprites.qh"
 
 #include "mutators/events.qh"
 
@@ -1014,6 +1013,7 @@ float cl_notice_run();
 float prev_myteam;
 int lasthud;
 float vh_notice_time;
+void WaypointSprite_Load();
 void CSQC_UpdateView(float w, float h)
 {
        entity e;
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 7cb37de3c713c02643e9aee0c079788cea2b723c..6aca04cf95f4675f90e318b02af6c479080d0e9f 100644 (file)
@@ -470,7 +470,7 @@ int pong_server_event(entity minigame, string event, ...)
 
 #elif defined(CSQC)
 
-#include "waypointsprites.qh" // drawrotpic
+void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f);
 
 float pong_team_to_angle(int nteam)
 {
@@ -667,4 +667,4 @@ int pong_client_event(entity minigame, string event, ...)
 
        return false;
 }
-#endif
\ No newline at end of file
+#endif
index 249e6f97eb768be7fed885364f200b0915d91baf..6a3553b1cc3b141f97811f7a537312a2eac289a8 100644 (file)
@@ -1144,7 +1144,9 @@ float monster_spawn()
 
        MonsterSound(monstersound_spawn, 0, false, CH_VOICE);
 
-       WaypointSprite_Spawn(M_NAME(self.monsterid), 0, 1024, self, '0 0 1' * (self.maxs.z + 15), world, self.team, self, sprite, true, RADARICON_DANGER, ((self.team) ? Team_ColorRGB(self.team) : '1 0 0'));
+       entity wp = WaypointSprite_Spawn(WP_Monster, 0, 1024, self, '0 0 1' * (self.maxs.z + 15), world, self.team, self, sprite, true, RADARICON_DANGER);
+       wp.wp_extra = self.monsterid;
+       wp.colormod = ((self.team) ? Team_ColorRGB(self.team) : '1 0 0');
        if(!(self.spawnflags & MONSTERFLAG_INVINCIBLE))
        {
                WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
index 0471dff7cd700623d9c28941e4495791643e7216..ffdc453f1b52cffbedc87544d1884703f11df913 100644 (file)
@@ -1,3 +1,3 @@
 #include "mutator/damagetext.qc"
 #include "mutator/itemstime.qc"
-#include "mutator/waypointsprites.qc"
+#include "mutator/waypoints/waypointsprites.qc"
index f0db281af8c522f3d23e06898f6f745fca7fa69d..ee571790a3859f8f7bf88b470d5a5e867d01bce4 100644 (file)
@@ -24,19 +24,37 @@ MUTATOR_HOOKFUNCTION(itemstime, CSQC_Parse_TempEntity) {
 }
 #endif
 
+#ifdef CSQC
+int autocvar_hud_panel_itemstime = 2;
+float autocvar_hud_panel_itemstime_dynamicsize = 1;
+float autocvar_hud_panel_itemstime_ratio = 2;
+int autocvar_hud_panel_itemstime_iconalign;
+bool autocvar_hud_panel_itemstime_progressbar = 0;
+float autocvar_hud_panel_itemstime_progressbar_maxtime = 30;
+string autocvar_hud_panel_itemstime_progressbar_name = "progressbar";
+float autocvar_hud_panel_itemstime_progressbar_reduced;
+bool autocvar_hud_panel_itemstime_hidespawned = 1;
+bool autocvar_hud_panel_itemstime_hidelarge = false;
+int autocvar_hud_panel_itemstime_text = 1;
+#define hud_panel_itemstime_hidelarge autocvar_hud_panel_itemstime_hidelarge
+#endif
+
 #ifdef SVQC
+#define hud_panel_itemstime_hidelarge false
+#endif
 
-bool Item_ItemsTime_Allow(entity e)
+bool Item_ItemsTime_Allow(GameItem it, WepSet _weapons)
 {
-    GameItem it = e.itemdef;
-       return (false
-       || it.instanceOfPowerup
-       || it == ITEM_ArmorMega     || it == ITEM_ArmorLarge
-       || it == ITEM_HealthMega    || it == ITEM_HealthLarge
-       || (e.weapons & WEPSET_SUPERWEAPONS)
-       );
+    return (false
+    || it.instanceOfPowerup
+    || it == ITEM_ArmorMega     || (it == ITEM_ArmorLarge && !hud_panel_itemstime_hidelarge)
+    || it == ITEM_HealthMega    || (it == ITEM_HealthLarge && !hud_panel_itemstime_hidelarge)
+    || (_weapons & WEPSET_SUPERWEAPONS)
+    );
 }
 
+#ifdef SVQC
+
 float it_times[MAX_ITEMS];
 
 void Item_ItemsTime_Init()
@@ -128,6 +146,15 @@ float Item_ItemsTime_UpdateTime(entity e, float t)
 
 MUTATOR_HOOKFUNCTION(itemstime, reset_map_global) {
     Item_ItemsTime_ResetTimes();
+    // ALL the times need to be reset before .reset()ing each item
+    // since Item_Reset schedules respawn of superweapons and powerups
+    for (self = world; (self = nextent(self)); )
+    if (IS_NOT_A_CLIENT(self))
+    {
+        if (self.reset)
+            Item_ItemsTime_SetTime(self, 0);
+    }
+    Item_ItemsTime_SetTimesForAllPlayers();
 }
 
 MUTATOR_HOOKFUNCTION(itemstime, MakePlayerObserver) {
@@ -222,17 +249,19 @@ void HUD_ItemsTime()
         ItemsTime_time[ITEM_Shield.m_id] = time + 4;
     }
 
-    float i;
-    float count = 0;
+    int count = 0;
     if (autocvar_hud_panel_itemstime_hidespawned == 1)
-        for (i = 0; i < MAX_ITEMS; ++i)
+        FOREACH(ITEMS, Item_ItemsTime_Allow(it, '0 0 0'), LAMBDA(
             count += (ItemsTime_time[i] > time || -ItemsTime_time[i] > time);
+        ));
     else if (autocvar_hud_panel_itemstime_hidespawned == 2)
-        for (i = 0; i < MAX_ITEMS; ++i)
+        FOREACH(ITEMS, Item_ItemsTime_Allow(it, '0 0 0'), LAMBDA(
             count += (ItemsTime_time[i] > time);
+        ));
     else
-        for (i = 0; i < MAX_ITEMS; ++i)
+        FOREACH(ITEMS, Item_ItemsTime_Allow(it, '0 0 0'), LAMBDA(
             count += (ItemsTime_time[i] != -1);
+        ));
     if (count == 0)
         return;
 
@@ -303,7 +332,7 @@ void HUD_ItemsTime()
 
     float row = 0, column = 0;
     bool item_available;
-    FOREACH(ITEMS, ItemsTime_time[i] != -1, LAMBDA(
+    FOREACH(ITEMS, Item_ItemsTime_Allow(it, '0 0 0') && ItemsTime_time[i] != -1, LAMBDA(
         float item_time = ItemsTime_time[i];
         if (item_time < -1)
         {
diff --git a/qcsrc/common/mutators/mutator/waypoints/all.inc b/qcsrc/common/mutators/mutator/waypoints/all.inc
new file mode 100644 (file)
index 0000000..e1153c2
--- /dev/null
@@ -0,0 +1,68 @@
+/** If you register a new waypoint, make sure to add it to this list */
+REGISTER_WAYPOINT(, "", '0 0 0', 1);
+#define WP_Null WP_
+
+REGISTER_WAYPOINT(Waypoint, _("Waypoint"), '0 1 1', 1);
+REGISTER_WAYPOINT(Helpme, _("Help me!"), '1 0.5 0', 1);
+REGISTER_WAYPOINT(Here, _("Here"), '0 1 0', 1);
+REGISTER_WAYPOINT(Danger, _("DANGER"), '1 0.5 0', 1);
+
+REGISTER_WAYPOINT(Frozen, _("Frozen!"), '0.25 0.90 1', 1);
+
+REGISTER_WAYPOINT(Item, _("Item"), '1 0 1', 1);
+
+REGISTER_WAYPOINT(RaceCheckpoint, _("Checkpoint"), '1 0.5 0', 1);
+REGISTER_WAYPOINT(RaceFinish, _("Finish"), '1 0.5 0', 1);
+REGISTER_WAYPOINT(RaceStart, _("Start"), '1 0.5 0', 1);
+REGISTER_WAYPOINT(RaceStartFinish, _("Start"), '1 0.5 0', 1);
+
+REGISTER_WAYPOINT(Assault, _("<placeholder>"), '1 0.5 0', 1);
+REGISTER_WAYPOINT(AssaultDefend, _("Defend"), '1 0.5 0', 1);
+REGISTER_WAYPOINT(AssaultDestroy, _("Destroy"), '1 0.5 0', 1);
+REGISTER_WAYPOINT(AssaultPush, _("Push"), '1 0.5 0', 1);
+
+REGISTER_WAYPOINT(FlagCarrier, _("Flag carrier"), '0.8 0.8 0', 1);
+REGISTER_WAYPOINT(FlagCarrierEnemy, _("Enemy carrier"), '1 1 1', 1);
+REGISTER_WAYPOINT(FlagDropped, _("Dropped flag"), '1 1 1', 1);
+REGISTER_WAYPOINT(FlagBaseNeutral, _("White base"), '0.8 0.8 0', 1);
+REGISTER_WAYPOINT(FlagBaseRed, _("Red base"), '0.8 0.8 0', 1);
+REGISTER_WAYPOINT(FlagBaseBlue, _("Blue base"), '0.8 0.8 0', 1);
+REGISTER_WAYPOINT(FlagBaseYellow, _("Yellow base"), '0.8 0.8 0', 1);
+REGISTER_WAYPOINT(FlagBasePink, _("Pink base"), '0.8 0.8 0', 1);
+
+REGISTER_WAYPOINT(DomNeut, _("Control point"), '0 1 1', 1);
+REGISTER_WAYPOINT(DomRed, _("Control point"), '0 1 1', 1);
+REGISTER_WAYPOINT(DomBlue, _("Control point"), '0 1 1', 1);
+REGISTER_WAYPOINT(DomYellow, _("Control point"), '0 1 1', 1);
+REGISTER_WAYPOINT(DomPink, _("Control point"), '0 1 1', 1);
+
+REGISTER_WAYPOINT(KeyDropped, _("Dropped key"), '0 1 1', 1);
+REGISTER_WAYPOINT(KeyCarrierFriend, _("Key carrier"), '0 1 0', 1);
+REGISTER_WAYPOINT(KeyCarrierFinish, _("Run here"), '0 1 1', 1);
+REGISTER_WAYPOINT(KeyCarrierRed, _("Key carrier"), '0 1 1', 1);
+REGISTER_WAYPOINT(KeyCarrierBlue, _("Key carrier"), '0 1 1', 1);
+REGISTER_WAYPOINT(KeyCarrierYellow, _("Key carrier"), '0 1 1', 1);
+REGISTER_WAYPOINT(KeyCarrierPink, _("Key carrier"), '0 1 1', 1);
+
+REGISTER_WAYPOINT(KaBall, _("Ball"), '0 1 1', 1);
+REGISTER_WAYPOINT(KaBallCarrier, _("Ball carrier"), '1 0 0', 1);
+
+REGISTER_WAYPOINT(NbBall, _("Ball"), '0.91 0.85 0.62', 1);
+REGISTER_WAYPOINT(NbGoal, _("Goal"), '1 0.5 0', 1);
+
+REGISTER_WAYPOINT(OnsCP, _("Control point"), '1 0.5 0', 1);
+REGISTER_WAYPOINT(OnsCPDefend, _("Control point"), '1 0.5 0', 0.5);
+REGISTER_WAYPOINT(OnsCPAttack, _("Control point"), '1 0.5 0', 2);
+REGISTER_WAYPOINT(OnsGen, _("Generator"), '1 0.5 0', 1);
+REGISTER_WAYPOINT(OnsGenShielded, _("Generator"), '1 0.5 0', 1);
+
+REGISTER_WAYPOINT(Buff, _("Buff"), '1 0.5 0', 1);
+
+REGISTER_WAYPOINT(Weapon, _("Weapon"), '0 0 0', 1);
+
+REGISTER_WAYPOINT(Monster, _("Monster"), '1 0 0', 1);
+
+REGISTER_WAYPOINT(Vehicle, _("Vehicle"), '1 1 1', 1);
+REGISTER_WAYPOINT(VehicleIntruder, _("Intruder!"), '1 1 1', 1);
+
+REGISTER_WAYPOINT(Seeker, _("Tagged"), '0.5 1 0', 2);
diff --git a/qcsrc/common/mutators/mutator/waypoints/all.qh b/qcsrc/common/mutators/mutator/waypoints/all.qh
new file mode 100644 (file)
index 0000000..9670a6f
--- /dev/null
@@ -0,0 +1,35 @@
+#include "../../../registry.qh"
+
+#ifndef WAYPOINTS_ALL_H
+#define WAYPOINTS_ALL_H
+
+#include "waypointsprites.qh"
+
+void RegisterWaypoints();
+const int MAX_WAYPOINTS = 240;
+entity WAYPOINTS[MAX_WAYPOINTS], WAYPOINTS_first, WAYPOINTS_last;
+int WAYPOINT_COUNT;
+/** If you register a new waypoint, make sure to add it to all.inc */
+#define REGISTER_WAYPOINT_(id, init) REGISTER(RegisterWaypoints, WP, WAYPOINTS, WAYPOINT_COUNT, id, m_id, init)
+REGISTER_REGISTRY(RegisterWaypoints)
+
+CLASS(Waypoint, Object)
+    ATTRIB(Waypoint, m_id, int, 0)
+    ATTRIB(Waypoint, netname, string, string_null)
+    ATTRIB(Waypoint, m_name, string, string_null)
+    ATTRIB(Waypoint, m_color, vector, '1 1 1')
+    ATTRIB(Waypoint, m_blink, int, 1)
+    CONSTRUCTOR(Waypoint, string _netname, string _name, vector _color, int _blink) {
+        CONSTRUCT(Waypoint);
+        this.netname = _netname;
+        this.m_name = _name;
+        this.m_color = _color;
+        this.m_blink = _blink;
+    }
+ENDCLASS(Waypoint)
+
+#define REGISTER_WAYPOINT(id, text, color, blink) REGISTER_WAYPOINT_(id, NEW(Waypoint, #id, text, color, blink))
+
+#include "all.inc"
+
+#endif
diff --git a/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc b/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc
new file mode 100644 (file)
index 0000000..c5fa1ac
--- /dev/null
@@ -0,0 +1,1161 @@
+#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);
+    WriteByte(MSG_ENTITY, self.wp_extra);
+
+    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) {
+    if (MUTATOR_RETURNVALUE) return false;
+    if (!ReadMutatorEquals(mutator_argv_int_0, waypointsprites)) return false;
+    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();
+    self.wp_extra = 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 (s == WP_Weapon.netname) {
+        if (get_weaponinfo(self.wp_extra).spawnflags & WEP_FLAG_SUPERWEAPON)
+            return 2;
+    }
+    if (s == WP_Item.netname) return ITEMS[self.wp_extra].m_waypointblink;
+
+    switch (s)
+    {
+        case "item-invis":       return 2;
+        case "item-extralife":   return 2;
+        case "item-speed":       return 2;
+        default:                 return 1;
+    }
+}
+
+vector spritelookupcolor(string s, vector def)
+{
+    if (s == WP_Weapon.netname) return get_weaponinfo(self.wp_extra).wpcolor;
+    if (s == WP_Item.netname) return ITEMS[self.wp_extra].m_color;
+    if (s == WP_Buff.netname) return BUFFS[self.wp_extra].m_color;
+    return def;
+}
+
+string spritelookuptext(string s)
+{
+    if (s == WP_RaceStartFinish.netname) return (race_checkpointtime || race_mycheckpointtime) ? _("Finish") : _("Start");
+    if (s == WP_Weapon.netname) return get_weaponinfo(self.wp_extra).message;
+    if (s == WP_Item.netname) return ITEMS[self.wp_extra].m_waypoint;
+    if (s == WP_Buff.netname) return BUFFS[self.wp_extra].m_prettyName;
+    if (s == WP_Monster.netname) return get_monsterinfo(self.wp_extra).monster_name;
+
+    // need to loop, as our netname could be one of three
+    FOREACH(WAYPOINTS, it.netname == s, LAMBDA(
+        return it.m_name;
+    ));
+
+    switch (s)
+    {
+        case "item-invis": return _("Invisibility");
+        case "item-extralife": return _("Extra life");
+        case "item-speed": return _("Speed");
+        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();
+STATIC_INIT(WaypointSprite_Load) {
+    WaypointSprite_Load();
+    WaypointSprite_Load_Frames(".tga");
+    WaypointSprite_Load_Frames(".jpg");
+}
+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);
+
+    waypointsprite_count = waypointsprite_newcount;
+    waypointsprite_newcount = 0;
+}
+#endif
+
+#ifdef SVQC
+void WaypointSprite_UpdateSprites(entity e, entity _m1, entity _m2, entity _m3)
+{
+    string m1 = _m1.netname;
+    string m2 = _m2.netname;
+    string m3 = _m3.netname;
+    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(
+    entity 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 // initial icon
+)
+{
+    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.netname;
+    wp.customizeentityforclient = WaypointSprite_Customize;
+    wp.waypointsprite_visible_for_player = WaypointSprite_visible_for_player;
+    wp.reset2 = WaypointSprite_Reset;
+    wp.cnt = icon;
+    wp.colormod = spr.m_color;
+    Net_LinkEntity(wp, false, 0, WaypointSprite_SendEntity);
+    return wp;
+}
+
+entity WaypointSprite_SpawnFixed(
+    entity spr,
+    vector ofs,
+    entity own,
+    .entity ownfield,
+    float icon // initial icon
+)
+{
+    return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, own, ownfield, true, icon);
+}
+
+entity WaypointSprite_DeployFixed(
+    entity spr,
+    float limited_range,
+    vector ofs,
+    float icon // initial icon
+)
+{
+    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);
+}
+
+entity WaypointSprite_DeployPersonal(
+    entity spr,
+    vector ofs,
+    float icon // initial icon
+)
+{
+    return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, self, waypointsprite_deployed_personal, false, icon);
+}
+
+entity WaypointSprite_Attach(
+    entity spr,
+    float limited_range,
+    float icon // initial icon
+)
+{
+    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);
+}
+
+entity WaypointSprite_AttachCarrier(
+    entity spr,
+    entity carrier,
+    float icon // 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);
+    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/waypoints/waypointsprites.qh b/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qh
new file mode 100644 (file)
index 0000000..d6ea518
--- /dev/null
@@ -0,0 +1,236 @@
+#ifndef WAYPOINTSPRITES_H
+#define WAYPOINTSPRITES_H
+
+#include "all.qh"
+
+/** Additional networked waypoint state, used for items, weapons, buffs */
+.int wp_extra;
+
+#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;
+
+bool autocvar_g_waypointsprite_uppercase;
+float autocvar_g_waypointsprite_alpha;
+float autocvar_g_waypointsprite_crosshairfadealpha;
+float autocvar_g_waypointsprite_crosshairfadedistance;
+float autocvar_g_waypointsprite_crosshairfadescale;
+float autocvar_g_waypointsprite_distancealphaexponent;
+float autocvar_g_waypointsprite_distancefadealpha;
+float autocvar_g_waypointsprite_distancefadedistancemultiplier;
+float autocvar_g_waypointsprite_distancefadescale;
+float autocvar_g_waypointsprite_edgefadealpha;
+float autocvar_g_waypointsprite_edgefadedistance;
+float autocvar_g_waypointsprite_edgefadescale;
+float autocvar_g_waypointsprite_edgeoffset_bottom;
+float autocvar_g_waypointsprite_edgeoffset_left;
+float autocvar_g_waypointsprite_edgeoffset_right;
+float autocvar_g_waypointsprite_edgeoffset_top;
+float autocvar_g_waypointsprite_fontsize;
+int autocvar_g_waypointsprite_itemstime;
+float autocvar_g_waypointsprite_minalpha;
+float autocvar_g_waypointsprite_minscale;
+float autocvar_g_waypointsprite_normdistance;
+float autocvar_g_waypointsprite_scale;
+int autocvar_g_waypointsprite_spam;
+float autocvar_g_waypointsprite_timealphaexponent;
+bool autocvar_g_waypointsprite_turrets = true;
+float autocvar_g_waypointsprite_turrets_maxdist = 5000;
+
+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
+float autocvar_sv_waypointsprite_deadlifetime;
+float autocvar_sv_waypointsprite_deployed_lifetime;
+float autocvar_sv_waypointsprite_limitedrange;
+
+..entity owned_by_field;
+.float rule;
+.string model1;
+.string model2;
+.string model3;
+
+.float(entity) waypointsprite_visible_for_player;
+
+void WaypointSprite_UpdateSprites(entity e, entity m1, entity m2, entity 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(
+    entity 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 // initial icon
+);
+
+entity WaypointSprite_SpawnFixed(
+    entity spr,
+    vector ofs,
+    entity own,
+    .entity ownfield,
+    float icon // initial icon
+);
+
+.entity waypointsprite_deployed_fixed;
+entity WaypointSprite_DeployFixed(
+    entity spr,
+    float limited_range,
+    vector ofs,
+    float icon // initial icon
+);
+
+.entity waypointsprite_deployed_personal;
+entity WaypointSprite_DeployPersonal(
+    entity spr,
+    vector ofs,
+    float icon // initial icon
+);
+
+.entity waypointsprite_attached;
+.entity waypointsprite_attachedforcarrier;
+entity WaypointSprite_Attach(
+    entity spr,
+    float limited_range,
+    float icon // initial icon
+);
+
+entity WaypointSprite_AttachCarrier(
+    entity spr,
+    entity carrier,
+    float icon // initial icon
+);
+
+void WaypointSprite_DetachCarrier(entity carrier);
+
+void WaypointSprite_ClearPersonal();
+
+void WaypointSprite_ClearOwned();
+
+void WaypointSprite_PlayerDead();
+
+void WaypointSprite_PlayerGone();
+#endif
+
+#endif
diff --git a/qcsrc/common/mutators/mutator/waypointsprites.qc b/qcsrc/common/mutators/mutator/waypointsprites.qc
deleted file mode 100644 (file)
index f8055ad..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-REGISTER_MUTATOR(waypointsprites, true);
-
-#ifdef CSQC
-void Ent_WaypointSprite();
-MUTATOR_HOOKFUNCTION(waypointsprites, CSQC_Ent_Update) {
-    if (MUTATOR_RETURNVALUE) return false;
-    if (!ReadMutatorEquals(mutator_argv_int_0, waypointsprites)) return false;
-    Ent_WaypointSprite();
-    return true;
-}
-#endif
index cc7b397a49ad3d63855336fd89b1667bebfe9bbe..cde5576897f502d0b890d6085a51cf035dc70f9e 100644 (file)
@@ -346,6 +346,7 @@ void Send_Notification_WOCOVA(
     MULTITEAM_INFO##teams(default,prefix,strnum,flnum,args,hudargs,icon,normal,gentle)
 
 #define MSG_INFO_NOTIFICATIONS \
+    MSG_INFO_NOTIF(1, INFO_CONNECTING,                     1, 0, "s1", "",                          "",                     _("^BG%s^BG is connecting..."), "") \
     MSG_INFO_NOTIF(2, INFO_CHAT_NOSPECTATORS,              0, 0, "", "",                            "",                     _("^F4NOTE: ^BGSpectator chat is not sent to players during the match"), "") \
     MULTITEAM_INFO(1, INFO_CTF_CAPTURE_, 4,                1, 0, "s1", "s1",                        "notify_%s_captured",   _("^BG%s^BG captured the ^TC^TT^BG flag"), "") \
     MULTITEAM_INFO(1, INFO_CTF_CAPTURE_BROKEN_, 4,         2, 2, "s1 f1p2dec s2 f2p2dec", "s1",     "notify_%s_captured",   _("^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds, breaking ^BG%s^BG's previous record of ^F2%s^BG seconds"), "") \
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 5479698acadb11d2fb1080d446e5926ce82a33d1..c1ae4ad1aa99f430e7227b7ed34aadb9e4e5d51e 100644 (file)
@@ -5,6 +5,7 @@
     #include "../client/defs.qh"
     #include "constants.qh"
     #include "../warpzonelib/mathlib.qh"
+       #include "../client/mutators/events.qh"
     #include "mapinfo.qh"
     #include "notifications.qh"
     #include "deathtypes.qh"
@@ -16,6 +17,7 @@
     #include "constants.qh"
     #include "../server/autocvars.qh"
     #include "../server/defs.qh"
+       #include "../server/mutators/events.qh"
     #include "notifications.qh"
     #include "deathtypes.qh"
     #include "mapinfo.qh"
@@ -2059,6 +2061,10 @@ float get_model_parameters(string m, float sk)
        }
        get_model_parameters_fixbone = 0;
 
+#ifndef MENUQC
+       MUTATOR_CALLHOOK(ClearModelParams);
+#endif
+
        if (!m)
                return 1;
 
@@ -2120,6 +2126,9 @@ float get_model_parameters(string m, float sk)
                        get_model_parameters_bone_upperbody = s;
                if(c == "bone_weapon")
                        get_model_parameters_bone_weapon = s;
+       #ifndef MENUQC
+               MUTATOR_CALLHOOK(GetModelParams, c, s);
+       #endif
                for(int i = 0; i < MAX_AIM_BONES; ++i)
                        if(c == strcat("bone_aim", ftos(i)))
                        {
index dbc7964b09769eb53370f60fe70dbe62c5527ce1..d55f797443a96baa60cff7591a60b09566d0f6f0 100644 (file)
@@ -529,7 +529,8 @@ void vehicles_showwp()
                rgb = Team_ColorRGB(self.team);
        else
                rgb = '1 1 1';
-       WaypointSprite_Spawn("vehicle", 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP, rgb);
+       entity wp = WaypointSprite_Spawn(WP_Vehicle, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP);
+       wp.colormod = rgb;
        if(self.waypointsprite_attached)
        {
                WaypointSprite_UpdateRule(self.waypointsprite_attached, self.wp00.team, SPRITERULE_DEFAULT);
@@ -1023,8 +1024,10 @@ void vehicles_enter(entity pl, entity veh)
 
                Send_Notification(NOTIF_ONE, pl, MSG_CENTER, CENTER_VEHICLE_STEAL_SELF);
 
-               if(autocvar_g_vehicles_steal_show_waypoint)
-                       WaypointSprite_Spawn("intruder", 0, 0, pl, '0 0 68', world, veh.team, veh, wps_intruder, true, RADARICON_DANGER, Team_ColorRGB(pl.team));
+               if (autocvar_g_vehicles_steal_show_waypoint) {
+                       entity wp = WaypointSprite_Spawn(WP_VehicleIntruder, 0, 0, pl, '0 0 68', world, veh.team, veh, wps_intruder, true, RADARICON_DANGER);
+                       wp.colormod = Team_ColorRGB(pl.team);
+               }
        }
        else return;
 
index 8d8a24194d6eb18da941774188c5cd8068f9abc6..71938bfcc5d93b2644572fb53a4e41c33ad8c4f0 100644 (file)
@@ -250,7 +250,7 @@ void W_Seeker_Fire_Missile(vector f_diff, entity m_target)
        W_DecreaseAmmo(WEP_CVAR(seeker, missile_ammo));
 
        makevectors(self.v_angle);
-       W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', false, 2, W_Sound("seeker_fire.wav"), CH_WEAPON_A, 0);
+       W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', false, 2, W_Sound("seeker_fire"), CH_WEAPON_A, 0);
        w_shotorg += f_diff;
        Send_Effect("seeker_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
 
@@ -546,7 +546,7 @@ void W_Seeker_Tag_Touch(void)
 
                if(WEP_CVAR(seeker, type) == 1)
                {
-                       WaypointSprite_Spawn("tagged-target", WEP_CVAR(seeker, tag_tracker_lifetime), 0, other, '0 0 64', self.realowner, 0, other, wps_tag_tracker, true, RADARICON_TAGGED, '0.5 1 0');
+                       WaypointSprite_Spawn(WP_Seeker, WEP_CVAR(seeker, tag_tracker_lifetime), 0, other, '0 0 64', self.realowner, 0, other, wps_tag_tracker, true, RADARICON_TAGGED);
                        WaypointSprite_UpdateRule(other.wps_tag_tracker, 0, SPRITERULE_DEFAULT);
                }
        }
index be5eef529d6b2f244b39ce8f58fa76d828d54675..1124044e362e23e57ee719688f6ab8e4088505e5 100644 (file)
@@ -40,6 +40,8 @@ void XonoticHUDItemsTimeDialog_fill(entity me)
                me.TD(me, 1, 2.6, e = makeXonoticSlider(2, 8, 0.5, "hud_panel_itemstime_ratio"));
        me.TR(me);
                me.TD(me, 1, 4, e = makeXonoticCheckBox(0, "hud_panel_itemstime_hidespawned", _("Hide spawned items")));
+       me.TR(me);
+               me.TD(me, 1, 4, e = makeXonoticCheckBox(0, "hud_panel_itemstime_hidelarge", _("Hide large armor and health")));
        me.TR(me);
                me.TD(me, 1, 4, e = makeXonoticCheckBox(0, "hud_panel_itemstime_dynamicsize", _("Dynamic size")));
 }
index cf1d1fc16c40293b830df0b46dec7b4ab0073f5d..63cd6379c8bd537c99bc1cbbbb53462c104de64e 100644 (file)
@@ -641,9 +641,6 @@ float autocvar_sv_vote_stop;
 float autocvar_sv_vote_timeout;
 float autocvar_sv_vote_wait;
 bool autocvar_sv_vote_gamestart;
-float autocvar_sv_waypointsprite_deadlifetime;
-float autocvar_sv_waypointsprite_deployed_lifetime;
-float autocvar_sv_waypointsprite_limitedrange;
 string autocvar_sv_weaponstats_file;
 float autocvar_sv_gibhealth;
 float autocvar_sys_ticrate;
index ee3fc76ffb693fdee0d3d926f4e4e7ea746697a0..40775abee330a29a25ae781017f49e27aaec92dc 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/waypoints/all.qh"
+
 #include "../common/triggers/subs.qh"
 #include "../common/triggers/triggers.qh"
 #include "../common/triggers/trigger/secret.qh"
index 64fb50df83a9db913302bc7ee4fd2d869d0c9b4c..45174f2c6008e2c8f914088b8bd9b83090f4c0a5 100644 (file)
@@ -10,7 +10,6 @@
 #include "weapons/selection.qh"
 #include "weapons/tracing.qh"
 #include "weapons/weaponsystem.qh"
-#include "waypointsprites.qh"
 
 #include "../common/minigames/sv_minigames.qh"
 
@@ -174,14 +173,14 @@ void ImpulseCommands (void)
                switch(imp)
                {
                        case 30:
-                               wp = WaypointSprite_DeployPersonal("waypoint", self.origin, RADARICON_WAYPOINT, '0 1 1');
+                               wp = WaypointSprite_DeployPersonal(WP_Waypoint, self.origin, RADARICON_WAYPOINT);
                                if(wp)
                                        WaypointSprite_Ping(wp);
                                sprint(self, "personal waypoint spawned at location\n");
                                break;
                        case 31:
                                WarpZone_crosshair_trace(self);
-                               wp = WaypointSprite_DeployPersonal("waypoint", trace_endpos, RADARICON_WAYPOINT, '0 1 1');
+                               wp = WaypointSprite_DeployPersonal(WP_Waypoint, trace_endpos, RADARICON_WAYPOINT);
                                if(wp)
                                        WaypointSprite_Ping(wp);
                                sprint(self, "personal waypoint spawned at crosshair\n");
@@ -189,7 +188,7 @@ void ImpulseCommands (void)
                        case 32:
                                if(vlen(self.death_origin))
                                {
-                                       wp = WaypointSprite_DeployPersonal("waypoint", self.death_origin, RADARICON_WAYPOINT, '0 1 1');
+                                       wp = WaypointSprite_DeployPersonal(WP_Waypoint, self.death_origin, RADARICON_WAYPOINT);
                                        if(wp)
                                                WaypointSprite_Ping(wp);
                                        sprint(self, "personal waypoint spawned at death location\n");
@@ -200,7 +199,7 @@ void ImpulseCommands (void)
                                {
                                        if (!MUTATOR_CALLHOOK(HelpMePing, self))
                                        {
-                                               wp = WaypointSprite_Attach("helpme", true, RADARICON_HELPME, '1 0.5 0');
+                                               wp = WaypointSprite_Attach(WP_Helpme, true, RADARICON_HELPME);
                                                if(!wp)
                                                        WaypointSprite_HelpMePing(self.waypointsprite_attachedforcarrier);
                                                else
@@ -210,14 +209,14 @@ void ImpulseCommands (void)
                                }
                                break;
                        case 34:
-                               wp = WaypointSprite_DeployFixed("here", false, self.origin, RADARICON_HERE, '0 1 0');
+                               wp = WaypointSprite_DeployFixed(WP_Here, false, self.origin, RADARICON_HERE);
                                if(wp)
                                        WaypointSprite_Ping(wp);
                                sprint(self, "HERE spawned at location\n");
                                break;
                        case 35:
                                WarpZone_crosshair_trace(self);
-                               wp = WaypointSprite_DeployFixed("here", false, trace_endpos, RADARICON_HERE, '0 1 0');
+                               wp = WaypointSprite_DeployFixed(WP_Here, false, trace_endpos, RADARICON_HERE);
                                if(wp)
                                        WaypointSprite_Ping(wp);
                                sprint(self, "HERE spawned at crosshair\n");
@@ -225,21 +224,21 @@ void ImpulseCommands (void)
                        case 36:
                                if(vlen(self.death_origin))
                                {
-                                       wp = WaypointSprite_DeployFixed("here", false, self.death_origin, RADARICON_HERE, '0 1 0');
+                                       wp = WaypointSprite_DeployFixed(WP_Here, false, self.death_origin, RADARICON_HERE);
                                        if(wp)
                                                WaypointSprite_Ping(wp);
                                        sprint(self, "HERE spawned at death location\n");
                                }
                                break;
                        case 37:
-                               wp = WaypointSprite_DeployFixed("danger", false, self.origin, RADARICON_DANGER, '1 0.5 0');
+                               wp = WaypointSprite_DeployFixed(WP_Danger, false, self.origin, RADARICON_DANGER);
                                if(wp)
                                        WaypointSprite_Ping(wp);
                                sprint(self, "DANGER spawned at location\n");
                                break;
                        case 38:
                                WarpZone_crosshair_trace(self);
-                               wp = WaypointSprite_DeployFixed("danger", false, trace_endpos, RADARICON_DANGER, '1 0.5 0');
+                               wp = WaypointSprite_DeployFixed(WP_Danger, false, trace_endpos, RADARICON_DANGER);
                                if(wp)
                                        WaypointSprite_Ping(wp);
                                sprint(self, "DANGER spawned at crosshair\n");
@@ -247,7 +246,7 @@ void ImpulseCommands (void)
                        case 39:
                                if(vlen(self.death_origin))
                                {
-                                       wp = WaypointSprite_DeployFixed("danger", false, self.death_origin, RADARICON_DANGER, '1 0.5 0');
+                                       wp = WaypointSprite_DeployFixed(WP_Danger, false, self.death_origin, RADARICON_DANGER);
                                        if(wp)
                                                WaypointSprite_Ping(wp);
                                        sprint(self, "DANGER spawned at death location\n");
index 46d1b2cbd0ba08c81b08d4ce4a606fc8309d01d6..9ba3b27cb0bafb4fca55e7264cddec5bf0353462 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 0ced8bb1fbdbc7f4e8ac63a030ec62bdb14c0e04..4be48e124e82b98d38fb26c41c5df7dfe18efc29 100644 (file)
@@ -357,15 +357,6 @@ void reset_map(float dorespawn)
 
        MUTATOR_CALLHOOK(reset_map_global);
 
-       // ALL the times need to be reset before .reset()ing each item
-       // since Item_Reset schedules respawn of superweapons and powerups
-       for(self = world; (self = nextent(self)); )
-       if(IS_NOT_A_CLIENT(self))
-       {
-               if(self.reset)
-                       Item_ItemsTime_SetTime(self, 0);
-       }
-
        for(self = world; (self = nextent(self)); )
        if(IS_NOT_A_CLIENT(self))
        {
@@ -393,8 +384,6 @@ void reset_map(float dorespawn)
                }
        }
 
-       Item_ItemsTime_SetTimesForAllPlayers();
-
        FOR_EACH_PLAYER(self)
        if(self.frozen)
                Unfreeze(self);
index 9791bbd2933ceac46d4e54e91fc7f0a6132978ad..967a475e17c577e3929bed7a10e0307f1bda0627 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"
@@ -595,7 +594,7 @@ void Freeze (entity targ, float freeze_time, float frozen_type, float show_waypo
 
        // add waypoint
        if(show_waypoint)
-               WaypointSprite_Spawn("frozen", 0, 0, targ, '0 0 64', world, targ.team, targ, waypointsprite_attached, true, RADARICON_WAYPOINT, '0.25 0.90 1');
+               WaypointSprite_Spawn(WP_Frozen, 0, 0, targ, '0 0 64', world, targ.team, targ, waypointsprite_attached, true, RADARICON_WAYPOINT);
 }
 
 void Unfreeze (entity targ)
index d743a2cba0027eac2242779e6c69e7b4fec504bb..722a8da753cd7158b72cb5d4cca6e47968b6ddaa 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 71542d543646272a29184fefad9194f175e475f3..fb3fbd107e247fd0db7f0a392b6b2724762c5854 100644 (file)
@@ -536,4 +536,15 @@ enum {
        MUT_ACCADD_INVALID, // return this flag to make the function always continue
        MUT_ACCADD_INDIFFERENT // return this flag to make the function always return
 };
+
+/** Called when clearing the global parameters for a model */
+MUTATOR_HOOKABLE(ClearModelParams, EV_NO_ARGS);
+
+/** Called when getting the global parameters for a model */
+#define EV_GetModelParams(i, o) \
+    /** entity id */ i(string, checkmodel_input) \
+    /** entity id */ i(string, checkmodel_command) \
+    /**/
+string checkmodel_input, checkmodel_command;
+MUTATOR_HOOKABLE(GetModelParams, EV_GetModelParams);
 #endif
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 4700c57d87e94501159972903b3200b617fce604..65b0ee793245b0bb7a36b00396e1b4c9c61f0bbd 100644 (file)
@@ -131,20 +131,20 @@ void target_objective_decrease_activate()
                                ent.sprite = world;
                }
 
-               spr = WaypointSprite_SpawnFixed("<placeholder>", 0.5 * (ent.absmin + ent.absmax), ent, assault_sprite, RADARICON_OBJECTIVE, '1 0.5 0');
+               spr = WaypointSprite_SpawnFixed(WP_Assault, 0.5 * (ent.absmin + ent.absmax), ent, assault_sprite, RADARICON_OBJECTIVE);
                spr.assault_decreaser = self;
                spr.waypointsprite_visible_for_player = assault_decreaser_sprite_visible;
                spr.classname = "sprite_waypoint";
                WaypointSprite_UpdateRule(spr, assault_attacker_team, SPRITERULE_TEAMPLAY);
                if(ent.classname == "func_assault_destructible")
                {
-                       WaypointSprite_UpdateSprites(spr, "as-defend", "as-destroy", "as-destroy");
+                       WaypointSprite_UpdateSprites(spr, WP_AssaultDefend, WP_AssaultDestroy, WP_AssaultDestroy);
                        WaypointSprite_UpdateMaxHealth(spr, ent.max_health);
                        WaypointSprite_UpdateHealth(spr, ent.health);
                        ent.sprite = spr;
                }
                else
-                       WaypointSprite_UpdateSprites(spr, "as-defend", "as-push", "as-push");
+                       WaypointSprite_UpdateSprites(spr, WP_AssaultDefend, WP_AssaultPush, WP_AssaultPush);
        }
 }
 
@@ -553,8 +553,8 @@ MUTATOR_HOOKFUNCTION(assault_PlayerSpawn)
 
 MUTATOR_HOOKFUNCTION(assault_TurretSpawn)
 {
-       if (!self.team)
-               self.team = 14;
+       if(!self.team || self.team == MAX_SHOT_DISTANCE)
+               self.team = 5; // this gets reversed when match starts?
 
        return false;
 }
index 87bbb3b991afe114420f92646dc67e161b3f7dd5..6ebf651f246e3c980af4e1b31189b8bc1db99f36 100644 (file)
@@ -53,7 +53,7 @@ void ctf_CaptureRecord(entity flag, entity player)
 
 void ctf_FlagcarrierWaypoints(entity player)
 {
-       WaypointSprite_Spawn("flagcarrier", 0, 0, player, FLAG_WAYPOINT_OFFSET, world, player.team, player, wps_flagcarrier, true, RADARICON_FLAG, WPCOLOR_FLAGCARRIER(player.team));
+       WaypointSprite_Spawn(WP_FlagCarrier, 0, 0, player, FLAG_WAYPOINT_OFFSET, world, player.team, player, wps_flagcarrier, true, RADARICON_FLAG);
        WaypointSprite_UpdateMaxHealth(player.wps_flagcarrier, '1 0 0' * healtharmor_maxdamage(start_health, start_armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON) * 2);
        WaypointSprite_UpdateHealth(player.wps_flagcarrier, '1 0 0' * healtharmor_maxdamage(player.health, player.armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON));
        WaypointSprite_UpdateTeamRadar(player.wps_flagcarrier, RADARICON_FLAGCARRIER, WPCOLOR_FLAGCARRIER(player.team));
@@ -248,8 +248,10 @@ void ctf_Handle_Drop(entity flag, entity player, int droptype)
        PlayerScore_Add(player, SP_CTF_DROPS, 1);
 
        // waypoints
-       if(autocvar_g_ctf_flag_dropped_waypoint)
-               WaypointSprite_Spawn("flagdropped", 0, 0, flag, FLAG_WAYPOINT_OFFSET, world, ((autocvar_g_ctf_flag_dropped_waypoint == 2) ? 0 : player.team), flag, wps_flagdropped, true, RADARICON_FLAG, WPCOLOR_DROPPEDFLAG(flag.team));
+       if(autocvar_g_ctf_flag_dropped_waypoint) {
+               entity wp = WaypointSprite_Spawn(WP_FlagDropped, 0, 0, flag, FLAG_WAYPOINT_OFFSET, world, ((autocvar_g_ctf_flag_dropped_waypoint == 2) ? 0 : player.team), flag, wps_flagdropped, true, RADARICON_FLAG);
+               wp.colormod = WPCOLOR_DROPPEDFLAG(flag.team);
+       }
 
        if(autocvar_g_ctf_flag_return_time || (autocvar_g_ctf_flag_return_damage && autocvar_g_ctf_flag_health))
        {
@@ -712,7 +714,8 @@ void ctf_CheckStalemate(void)
                {
                        if((tmp_entity.owner) && (!tmp_entity.owner.wps_enemyflagcarrier))
                        {
-                               WaypointSprite_Spawn(((ctf_oneflag) ? "flagcarrier" : "enemyflagcarrier"), 0, 0, tmp_entity.owner, FLAG_WAYPOINT_OFFSET, world, 0, tmp_entity.owner, wps_enemyflagcarrier, true, RADARICON_FLAG, WPCOLOR_ENEMYFC(tmp_entity.owner.team));
+                               entity wp = WaypointSprite_Spawn(((ctf_oneflag) ? WP_FlagCarrier : WP_FlagCarrierEnemy), 0, 0, tmp_entity.owner, FLAG_WAYPOINT_OFFSET, world, 0, tmp_entity.owner, wps_enemyflagcarrier, true, RADARICON_FLAG);
+                               wp.colormod = WPCOLOR_ENEMYFC(tmp_entity.owner.team);
                                tmp_entity.owner.wps_enemyflagcarrier.customizeentityforclient = ctf_Stalemate_Customize;
                        }
                }
@@ -1063,18 +1066,18 @@ void ctf_DelayedFlagSetup(void) // called after a flag is placed on a map by ctf
        self.bot_basewaypoint = self.nearestwaypoint;
 
        // waypointsprites
-       string basename = "base";
-
-       switch(self.team)
+       entity basename;
+       switch (self.team)
        {
-               case NUM_TEAM_1: basename = "redbase"; break;
-               case NUM_TEAM_2: basename = "bluebase"; break;
-               case NUM_TEAM_3: basename = "yellowbase"; break;
-               case NUM_TEAM_4: basename = "pinkbase"; break;
-               default: basename = "neutralbase"; break;
+               case NUM_TEAM_1: basename = WP_FlagBaseRed; break;
+               case NUM_TEAM_2: basename = WP_FlagBaseBlue; break;
+               case NUM_TEAM_3: basename = WP_FlagBaseYellow; break;
+               case NUM_TEAM_4: basename = WP_FlagBasePink; break;
+               default: basename = WP_FlagBaseNeutral; break;
        }
 
-       WaypointSprite_SpawnFixed(basename, self.origin + FLAG_WAYPOINT_OFFSET, self, wps_flagbase, RADARICON_FLAG, ((self.team) ? Team_ColorRGB(self.team) : '1 1 1'));
+       entity wp = WaypointSprite_SpawnFixed(basename, self.origin + FLAG_WAYPOINT_OFFSET, self, wps_flagbase, RADARICON_FLAG);
+       wp.colormod = ((self.team) ? Team_ColorRGB(self.team) : '1 1 1');
        WaypointSprite_UpdateTeamRadar(self.wps_flagbase, RADARICON_FLAG, ((self.team) ? colormapPaletteColor(self.team - 1, false) : '1 1 1'));
 
        // captureshield setup
@@ -2126,7 +2129,7 @@ MUTATOR_HOOKFUNCTION(ctf_HelpMePing)
        }
        else // create a normal help me waypointsprite
        {
-               WaypointSprite_Spawn("helpme", waypointsprite_deployed_lifetime, waypointsprite_limitedrange, self, FLAG_WAYPOINT_OFFSET, world, self.team, self, wps_helpme, false, RADARICON_HELPME, '1 0.5 0');
+               WaypointSprite_Spawn(WP_Helpme, waypointsprite_deployed_lifetime, waypointsprite_limitedrange, self, FLAG_WAYPOINT_OFFSET, world, self.team, self, wps_helpme, false, RADARICON_HELPME);
                WaypointSprite_Ping(self.wps_helpme);
        }
 
index a9e83a2a57e12da08a884645e70e7691ae5d17c9..b5ff1774a136441373a9ba2d4250a3b48f187bb7 100644 (file)
@@ -37,7 +37,7 @@ const float VEHICLE_FLAG_SCALE = 1.0;
 
 // waypoint colors
 #define WPCOLOR_ENEMYFC(t) ((t) ? colormapPaletteColor(t - 1, false) * 0.75 : '1 1 1')
-#define WPCOLOR_FLAGCARRIER(t) ('0.8 0.8 0')
+#define WPCOLOR_FLAGCARRIER(t) (WP_FlagCarrier.m_color)
 #define WPCOLOR_DROPPEDFLAG(t) ((t) ? ('0.25 0.25 0.25' + colormapPaletteColor(t - 1, false)) * 0.5 : '1 1 1')
 
 // sounds
index c365eddd300a9cb4a32fddc34c9760d8abe50e23..d10cedcd887b99697fc8c1b765b58aaf948db09e 100644 (file)
@@ -24,7 +24,6 @@ void dompoint_captured ()
 {
        entity head;
        float old_delay, old_team, real_team;
-       string msg = "dom-neut";
 
        // now that the delay has expired, switch to the latest team to lay claim to this point
        head = self.owner;
@@ -80,15 +79,16 @@ void dompoint_captured ()
        self.delay = old_delay;
        self.team = old_team;
 
+       entity msg = WP_DomNeut;
        switch(self.team)
        {
-               case NUM_TEAM_1: msg = "dom-red"; break;
-               case NUM_TEAM_2: msg = "dom-blue"; break;
-               case NUM_TEAM_3: msg = "dom-yellow"; break;
-               case NUM_TEAM_4: msg = "dom-pink"; break;
+               case NUM_TEAM_1: msg = WP_DomRed; break;
+               case NUM_TEAM_2: msg = WP_DomBlue; break;
+               case NUM_TEAM_3: msg = WP_DomYellow; break;
+               case NUM_TEAM_4: msg = WP_DomPink; break;
        }
 
-       WaypointSprite_UpdateSprites(self.sprite, msg, "", "");
+       WaypointSprite_UpdateSprites(self.sprite, msg, WP_Null, WP_Null);
 
        total_pps = 0, pps_red = 0, pps_blue = 0, pps_yellow = 0, pps_pink = 0;
        for(head = world; (head = find(head, classname, "dom_controlpoint")) != world; )
@@ -226,7 +226,7 @@ void dompointtouch()
        if(head == world)
                return;
 
-       WaypointSprite_UpdateSprites(self.sprite, "dom-neut", "", "");
+       WaypointSprite_UpdateSprites(self.sprite, WP_DomNeut, WP_Null, WP_Null);
        WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_DOMPOINT, '0 1 1');
        WaypointSprite_Ping(self.sprite);
 
@@ -292,7 +292,7 @@ void dom_controlpoint_setup()
        droptofloor();
 
        waypoint_spawnforitem(self);
-       WaypointSprite_SpawnFixed("dom-neut", self.origin + '0 0 32', self, sprite, RADARICON_DOMPOINT, '0 1 1');
+       WaypointSprite_SpawnFixed(WP_DomNeut, self.origin + '0 0 32', self, sprite, RADARICON_DOMPOINT);
 }
 
 float total_controlpoints, redowned, blueowned, yellowowned, pinkowned;
index 8cc302486f8d0ef635745c1d1b25cb5d2fb37c96..01695f5e2f1bbd62a5428fcc94d609bac9d19430 100644 (file)
@@ -50,7 +50,7 @@ void ka_RespawnBall() // runs whenever the ball needs to be relocated
        Send_Effect("electro_combo", oldballorigin, '0 0 0', 1);
        Send_Effect("electro_combo", self.origin, '0 0 0', 1);
 
-       WaypointSprite_Spawn("ka-ball", 0, 0, self, '0 0 64', world, self.team, self, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER, '0 1 1');
+       WaypointSprite_Spawn(WP_KaBall, 0, 0, self, '0 0 64', world, self.team, self, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER);
        WaypointSprite_Ping(self.waypointsprite_attachedforcarrier);
 
        sound(self, CH_TRIGGER, "keepaway/respawn.wav", VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
@@ -118,7 +118,7 @@ void ka_TouchEvent() // runs any time that the ball comes in contact with someth
        PlayerScore_Add(other, SP_KEEPAWAY_PICKUPS, 1);
 
        // waypoints
-       WaypointSprite_AttachCarrier("ka-ballcarrier", other, RADARICON_FLAGCARRIER, '1 0 0');
+       WaypointSprite_AttachCarrier(WP_KaBallCarrier, other, RADARICON_FLAGCARRIER);
        other.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = ka_ballcarrier_waypointsprite_visible_for_player;
        WaypointSprite_UpdateRule(other.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
        WaypointSprite_Ping(other.waypointsprite_attachedforcarrier);
@@ -160,7 +160,7 @@ void ka_DropEvent(entity plyr) // runs any time that a player is supposed to los
        // PlayerScore_Add(plyr, SP_KEEPAWAY_DROPS, 1); Not anymore, this is 100% the same as pickups and is useless.
 
        // waypoints
-       WaypointSprite_Spawn("ka-ball", 0, 0, ball, '0 0 64', world, ball.team, ball, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER, '0 1 1');
+       WaypointSprite_Spawn(WP_KaBall, 0, 0, ball, '0 0 64', world, ball.team, ball, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER);
        WaypointSprite_UpdateRule(ball.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
        WaypointSprite_Ping(ball.waypointsprite_attachedforcarrier);
        WaypointSprite_Kill(plyr.waypointsprite_attachedforcarrier);
index 5fa2f6db2b7a9ea384a442664612681cca80f108..1de67e2b071a44872a482ad5de4ec7296141ebc4 100644 (file)
@@ -351,17 +351,18 @@ void kh_Key_AssignTo(entity key, entity player)  // runs every time a key is pic
                if(key.kh_next == world)
                {
                        // player is now a key carrier
-                       WaypointSprite_AttachCarrier("", player, RADARICON_FLAGCARRIER, colormapPaletteColor(player.team - 1, 0));
+                       entity wp = WaypointSprite_AttachCarrier(WP_Null, player, RADARICON_FLAGCARRIER);
+                       wp.colormod = colormapPaletteColor(player.team - 1, 0);
                        player.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = kh_KeyCarrier_waypointsprite_visible_for_player;
                        WaypointSprite_UpdateRule(player.waypointsprite_attachedforcarrier, player.team, SPRITERULE_TEAMPLAY);
                        if(player.team == NUM_TEAM_1)
-                               WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-red", "keycarrier-friend", "keycarrier-red");
+                               WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, WP_KeyCarrierRed, WP_KeyCarrierFriend, WP_KeyCarrierRed);
                        else if(player.team == NUM_TEAM_2)
-                               WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-blue", "keycarrier-friend", "keycarrier-blue");
+                               WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, WP_KeyCarrierBlue, WP_KeyCarrierFriend, WP_KeyCarrierBlue);
                        else if(player.team == NUM_TEAM_3)
-                               WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-yellow", "keycarrier-friend", "keycarrier-yellow");
+                               WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, WP_KeyCarrierYellow, WP_KeyCarrierFriend, WP_KeyCarrierYellow);
                        else if(player.team == NUM_TEAM_4)
-                               WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-pink", "keycarrier-friend", "keycarrier-pink");
+                               WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, WP_KeyCarrierPink, WP_KeyCarrierFriend, WP_KeyCarrierPink);
                        if(!kh_no_radar_circles)
                                WaypointSprite_Ping(player.waypointsprite_attachedforcarrier);
                }
@@ -383,8 +384,12 @@ void kh_Key_AssignTo(entity key, entity player)  // runs every time a key is pic
                        // audit all key carrier sprites, update them to RUN HERE
                        FOR_EACH_KH_KEY(k)
                        {
-                               if(k.owner)
-                                       WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, k.owner.waypointsprite_attachedforcarrier.model1, "keycarrier-finish", k.owner.waypointsprite_attachedforcarrier.model3);
+                               if (!k.owner) continue;
+                               entity first = WP_Null;
+                               FOREACH(WAYPOINTS, it.netname == k.owner.waypointsprite_attachedforcarrier.model1, LAMBDA(first = it; break));
+                               entity third = WP_Null;
+                               FOREACH(WAYPOINTS, it.netname == k.owner.waypointsprite_attachedforcarrier.model3, LAMBDA(third = it; break));
+                               WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, first, WP_KeyCarrierFinish, third);
                        }
                }
                else
@@ -394,8 +399,12 @@ void kh_Key_AssignTo(entity key, entity player)  // runs every time a key is pic
                        // audit all key carrier sprites, update them to RUN HERE
                        FOR_EACH_KH_KEY(k)
                        {
-                               if(k.owner)
-                                       WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, k.owner.waypointsprite_attachedforcarrier.model1, "keycarrier-friend", k.owner.waypointsprite_attachedforcarrier.model3);
+                               if (!k.owner) continue;
+                               entity first = WP_Null;
+                               FOREACH(WAYPOINTS, it.netname == k.owner.waypointsprite_attachedforcarrier.model1, LAMBDA(first = it; break));
+                               entity third = WP_Null;
+                               FOREACH(WAYPOINTS, it.netname == k.owner.waypointsprite_attachedforcarrier.model3, LAMBDA(third = it; break));
+                               WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, first, WP_KeyCarrierFriend, third);
                        }
                }
        }
@@ -773,7 +782,7 @@ void kh_Key_Spawn(entity initial_owner, float angle, float i)  // runs every tim
 
        Send_Notification(NOTIF_ONE, initial_owner, MSG_CENTER, APP_TEAM_NUM_4(initial_owner.team, CENTER_KEYHUNT_START_));
 
-       WaypointSprite_Spawn("key-dropped", 0, 0, key, '0 0 1' * KH_KEY_WP_ZSHIFT, world, key.team, key, waypointsprite_attachedforcarrier, false, RADARICON_FLAG, '0 1 1');
+       WaypointSprite_Spawn(WP_KeyDropped, 0, 0, key, '0 0 1' * KH_KEY_WP_ZSHIFT, world, key.team, key, waypointsprite_attachedforcarrier, false, RADARICON_FLAG);
        key.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = kh_Key_waypointsprite_visible_for_player;
 
        kh_Key_AssignTo(key, initial_owner);
index 22ad6aa92c4c5d27628eabcefa9c5dbf1eb73225..456d0df1f962f6fb4cb099faea1aea1b5741c827 100644 (file)
@@ -144,7 +144,7 @@ void GiveBall(entity plyr, entity ball)
        ball.effects |= EF_NOSHADOW;
        ball.scale = 1; // scale down.
 
-       WaypointSprite_AttachCarrier("nb-ball", plyr, RADARICON_FLAGCARRIER, BALL_SPRITECOLOR);
+       WaypointSprite_AttachCarrier(WP_NbBall, plyr, RADARICON_FLAGCARRIER);
        WaypointSprite_UpdateRule(plyr.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
 
        if(autocvar_g_nexball_basketball_delay_hold)
@@ -188,7 +188,7 @@ void DropBall(entity ball, vector org, vector vel)
        }
 
        WaypointSprite_Kill(ball.owner.waypointsprite_attachedforcarrier);
-       WaypointSprite_Spawn("nb-ball", 0, 0, ball, '0 0 64', world, ball.team, ball, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER, BALL_SPRITECOLOR); // no health bar please
+       WaypointSprite_Spawn(WP_NbBall, 0, 0, ball, '0 0 64', world, ball.team, ball, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER); // no health bar please
        WaypointSprite_UpdateRule(ball.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
 
        ball.owner.ballcarried = world;
@@ -530,7 +530,7 @@ void SpawnBall(void)
        precache_sound(self.noise1);
        precache_sound(self.noise2);
 
-       WaypointSprite_AttachCarrier("nb-ball", self, RADARICON_FLAGCARRIER, BALL_SPRITECOLOR); // the ball's team is not set yet, no rule update needed
+       WaypointSprite_AttachCarrier(WP_NbBall, self, RADARICON_FLAGCARRIER); // the ball's team is not set yet, no rule update needed
 
        self.reset = ball_restart;
        self.think = InitBall;
@@ -589,7 +589,8 @@ void SpawnGoal(void)
 
        if(self.team != GOAL_OUT && Team_TeamToNumber(self.team) != -1)
        {
-               WaypointSprite_SpawnFixed("goal", (self.absmin + self.absmax) * 0.5, self, sprite, RADARICON_NONE, ((self.team) ? Team_ColorRGB(self.team) : '1 0.5 0'));
+               entity wp = WaypointSprite_SpawnFixed(WP_NbGoal, (self.absmin + self.absmax) * 0.5, self, sprite, RADARICON_NONE);
+               wp.colormod = ((self.team) ? Team_ColorRGB(self.team) : '1 0.5 0');
                self.sprite.customizeentityforclient = nb_Goal_Customize;
        }
 
index 199e15c3befe5590e21887e5d62667a5961ec4ed..e28fad883ca85f8f6afc30496aedc7b21c48a657 100644 (file)
@@ -6,7 +6,6 @@ const float BALL_EFFECTMASK = 1229;
 const vector BALL_MINS = '-16 -16 -16'; // The model is 24*24*24
 const vector BALL_MAXS = '16 16 16';
 const vector BALL_ATTACHORG = '3 0 16';
-const vector BALL_SPRITECOLOR = '0.91 0.85 0.62';
 const float BALL_FOOT = 1;
 const float BALL_BASKET = 2;
 //spawnflags
index 9b356404dca9948803c46081013acd7a7540a5fa..73c37997a5ae713f848943e231379568a88401ed 100644 (file)
@@ -604,26 +604,25 @@ void ons_ControlPoint_Icon_Spawn(entity cp, entity player)
        onslaught_controlpoint_icon_link(e, ons_ControlPoint_Icon_BuildThink);
 }
 
-string ons_ControlPoint_Waypoint(entity e)
+entity ons_ControlPoint_Waypoint(entity e)
 {
        if(e.team)
        {
                int a = ons_ControlPoint_Attackable(e, e.team);
 
-               if(a == -2) { return "ons-cp-dfnd"; } // defend now
-               if(a == -1 || a == 1 || a == 2) { return "ons-cp"; } // touch
-               if(a == 3 || a == 4) { return "ons-cp-atck"; } // attack
+               if(a == -2) { return WP_OnsCPDefend; } // defend now
+               if(a == -1 || a == 1 || a == 2) { return WP_OnsCP; } // touch
+               if(a == 3 || a == 4) { return WP_OnsCPAttack; } // attack
        }
        else
-               return "ons-cp";
+               return WP_OnsCP;
 
-       return "";
+       return WP_Null;
 }
 
 void ons_ControlPoint_UpdateSprite(entity e)
 {
-       string s1;
-       s1 = ons_ControlPoint_Waypoint(e);
+       entity s1 = ons_ControlPoint_Waypoint(e);
        WaypointSprite_UpdateSprites(e.sprite, s1, s1, s1);
 
        bool sh;
@@ -807,7 +806,7 @@ void ons_ControlPoint_Setup(entity cp)
        }
 
        // waypointsprites
-       WaypointSprite_SpawnFixed(string_null, self.origin + CPGEN_WAYPOINT_OFFSET, self, sprite, RADARICON_NONE, '0 0 0');
+       WaypointSprite_SpawnFixed(WP_Null, self.origin + CPGEN_WAYPOINT_OFFSET, self, sprite, RADARICON_NONE);
        WaypointSprite_UpdateRule(self.sprite, self.team, SPRITERULE_TEAMPLAY);
 
        InitializeEntity(cp, ons_DelayedControlPoint_Setup, INITPRIO_SETLOCATION);
@@ -818,16 +817,16 @@ void ons_ControlPoint_Setup(entity cp)
 // Main Generator Functions
 // =========================
 
-string ons_Generator_Waypoint(entity e)
+entity ons_Generator_Waypoint(entity e)
 {
-       if(e.isshielded)
-               return "ons-gen-shielded";
-       return "ons-gen";
+       if (e.isshielded)
+               return WP_OnsGenShielded;
+       return WP_OnsGen;
 }
 
 void ons_Generator_UpdateSprite(entity e)
 {
-       string s1 = ons_Generator_Waypoint(e);
+       entity s1 = ons_Generator_Waypoint(e);
        WaypointSprite_UpdateSprites(e.sprite, s1, s1, s1);
 
        if(e.lastteam != e.team + 2 || e.lastshielded != e.isshielded)
@@ -1061,7 +1060,7 @@ void ons_GeneratorSetup(entity gen) // called when spawning a generator entity o
        droptofloor();
 
        // waypointsprites
-       WaypointSprite_SpawnFixed(string_null, self.origin + CPGEN_WAYPOINT_OFFSET, self, sprite, RADARICON_NONE, '0 0 0');
+       WaypointSprite_SpawnFixed(WP_Null, self.origin + CPGEN_WAYPOINT_OFFSET, self, sprite, RADARICON_NONE);
        WaypointSprite_UpdateRule(self.sprite, self.team, SPRITERULE_TEAMPLAY);
        WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
        WaypointSprite_UpdateHealth(self.sprite, self.health);
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 f6a881f7b667a83994d31627b3dc013709dbccea..d4bdd50d2974a5005a4d2b9f872d002b6aaec24d 100644 (file)
@@ -89,7 +89,8 @@ float buff_Waypoint_visible_for_player(entity plr)
 void buff_Waypoint_Spawn(entity e)
 {
        entity buff = buff_FirstFromFlags(e.buffs);
-       WaypointSprite_Spawn(buff.m_sprite, 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs.z, world, e.team, e, buff_waypoint, true, RADARICON_POWERUP, e.glowmod);
+       entity wp = WaypointSprite_Spawn(WP_Buff, 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs.z, world, e.team, e, buff_waypoint, true, RADARICON_POWERUP);
+       wp.wp_extra = buff.m_id;
        WaypointSprite_UpdateTeamRadar(e.buff_waypoint, RADARICON_POWERUP, e.glowmod);
        e.buff_waypoint.waypointsprite_visible_for_player = buff_Waypoint_visible_for_player;
 }
index e5b443e961a50a4141e8f3d98b29d2e25a1637d4..4aea59eb6d87b05dedd0c0064e9fa776975ff784 100644 (file)
@@ -48,7 +48,6 @@ t_halflife.qc
 t_items.qc
 t_quake3.qc
 t_quake.qc
-waypointsprites.qc
 
 bot/aim.qc
 bot/bot.qc
index 4482fe327901b7e42a4e91da460fc596f6f3d525..eab7017d1cb877ccc78e15c57c5849503f76fa55 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"
@@ -828,9 +827,9 @@ void trigger_race_checkpoint_verify()
                if(defrag_ents)
                {
                        for(cp = world; (cp = find(cp, classname, "target_startTimer"));)
-                               WaypointSprite_UpdateSprites(cp.sprite, "race-start", "", "");
+                               WaypointSprite_UpdateSprites(cp.sprite, WP_RaceStart, WP_Null, WP_Null);
                        for(cp = world; (cp = find(cp, classname, "target_stopTimer"));)
-                               WaypointSprite_UpdateSprites(cp.sprite, "race-finish", "", "");
+                               WaypointSprite_UpdateSprites(cp.sprite, WP_RaceFinish, WP_Null, WP_Null);
 
                        for(cp = world; (cp = find(cp, classname, "target_checkpoint"));)
                        {
@@ -863,9 +862,9 @@ void trigger_race_checkpoint_verify()
                                if(cp.sprite)
                                {
                                        if(cp.race_checkpoint == 0)
-                                               WaypointSprite_UpdateSprites(cp.sprite, "race-start", "", "");
+                                               WaypointSprite_UpdateSprites(cp.sprite, WP_RaceStart, WP_Null, WP_Null);
                                        else if(cp.race_checkpoint == race_timed_checkpoint)
-                                               WaypointSprite_UpdateSprites(cp.sprite, "race-finish", "", "");
+                                               WaypointSprite_UpdateSprites(cp.sprite, WP_RaceFinish, WP_Null, WP_Null);
                                }
                }
        }
@@ -968,9 +967,9 @@ void spawnfunc_trigger_race_checkpoint()
        if(!self.race_penalty)
        {
                if(self.race_checkpoint)
-                       WaypointSprite_SpawnFixed("race-checkpoint", o, self, sprite, RADARICON_NONE, '1 0.5 0');
+                       WaypointSprite_SpawnFixed(WP_RaceCheckpoint, o, self, sprite, RADARICON_NONE);
                else
-                       WaypointSprite_SpawnFixed("race-start-finish", o, self, sprite, RADARICON_NONE, '1 0.5 0');
+                       WaypointSprite_SpawnFixed(WP_RaceStartFinish, o, self, sprite, RADARICON_NONE);
        }
 
        self.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player;
@@ -1011,9 +1010,9 @@ void spawnfunc_target_checkpoint() // defrag entity
        race_timed_checkpoint = 1;
 
        if(self.race_checkpoint == 0)
-               WaypointSprite_SpawnFixed("race-start", o, self, sprite, RADARICON_NONE, '1 0.5 0');
+               WaypointSprite_SpawnFixed(WP_RaceStart, o, self, sprite, RADARICON_NONE);
        else
-               WaypointSprite_SpawnFixed("race-checkpoint", o, self, sprite, RADARICON_NONE, '1 0.5 0');
+               WaypointSprite_SpawnFixed(WP_RaceCheckpoint, o, self, sprite, RADARICON_NONE);
 
        self.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player;
 
index 3c944619bfa693a259e86fe808de93a15ec342ae..45fcbd7613358223fbb8e239da11789035aae715 100644 (file)
@@ -5,8 +5,6 @@
 #if defined(SVQC)
     #include "_all.qh"
 
-    #include "waypointsprites.qh"
-
     #include "bot/bot.qh"
     #include "bot/waypoints.qh"
 
@@ -412,7 +410,7 @@ void Item_Think()
        }
 }
 
-bool Item_ItemsTime_Allow(entity e);
+bool Item_ItemsTime_Allow(GameItem it, WepSet _weapons);
 float Item_ItemsTime_UpdateTime(entity e, float t);
 void Item_ItemsTime_SetTime(entity e, float t);
 void Item_ItemsTime_SetTimesForAllPlayers();
@@ -429,7 +427,7 @@ void Item_Respawn (void)
                sound (self, CH_TRIGGER, "misc/itemrespawn.wav", VOL_BASE, ATTEN_NORM); // play respawn sound
        setorigin (self, self.origin);
 
-    if (Item_ItemsTime_Allow(self))
+    if (Item_ItemsTime_Allow(self.itemdef, self.weapons))
        {
                float t = Item_ItemsTime_UpdateTime(self, 0);
                Item_ItemsTime_SetTime(self, t);
@@ -457,40 +455,22 @@ void Item_RespawnCountdown (void)
                self.count += 1;
                if(self.count == 1)
                {
-                       string name = string_null;
-                       vector rgb = '1 0 1';
+                       MUTATOR_CALLHOOK(Item_RespawnCountdown, string_null, '0 0 0');
+                       int wpextra = 0;
             entity e = self.itemdef;
-            if (e) {
-                name = e.m_waypoint;
-                rgb = e.m_color;
-            }
-                       MUTATOR_CALLHOOK(Item_RespawnCountdown, name, rgb);
-                       name = item_name;
-                       rgb = item_color;
-                       if(self.flags & FL_WEAPON)
-                       {
+            if (e) wpextra = e.m_id;
+                       if (self.flags & FL_WEAPON) {
                                entity wi = get_weaponinfo(self.weapon);
-                               if(wi)
-                               {
-                                       name = wi.wpmodel;
-                                       rgb = '1 0 0';
-                               }
-                       }
-                       if(name)
-                       {
-                               WaypointSprite_Spawn(name, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP, rgb);
-                               if(self.waypointsprite_attached)
-                               {
-                                       if (self.items == IT_HEALTH || self.items == IT_ARMOR)
-                                               WaypointSprite_UpdateRule(self.waypointsprite_attached, 0, SPRITERULE_SPECTATOR);
-                                       WaypointSprite_UpdateBuildFinished(self.waypointsprite_attached, time + ITEM_RESPAWN_TICKS);
-                               }
-                       }
-                       else
-                       {
-                               print("Unknown powerup-marked item is wanting to respawn\n");
-                               localcmd(sprintf("prvm_edict server %d\n", num_for_edict(self)));
+                               if (wi) wpextra = wi.m_id;
                        }
+            entity wp = WaypointSprite_Spawn(WP_Item, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP);
+            wp.wp_extra = wpextra;
+            if(self.waypointsprite_attached)
+            {
+                if (self.items == IT_HEALTH || self.items == IT_ARMOR)
+                    WaypointSprite_UpdateRule(self.waypointsprite_attached, 0, SPRITERULE_SPECTATOR);
+                WaypointSprite_UpdateBuildFinished(self.waypointsprite_attached, time + ITEM_RESPAWN_TICKS);
+            }
                }
 
                if(self.waypointsprite_attached)
@@ -529,7 +509,7 @@ void Item_RespawnThink()
 
 void Item_ScheduleRespawnIn(entity e, float t)
 {
-       if (Item_ItemsTime_Allow(e))
+       if (Item_ItemsTime_Allow(e.itemdef, e.weapons))
        {
                e.think = Item_RespawnCountdown;
                e.nextthink = time + max(0, t - ITEM_RESPAWN_TICKS);
index b50c49eb5a0eb21ea00220485eb5b9f8060f90e8..f75df5e38a6a6fe3daa1e53c2a964402292f07eb 100644 (file)
@@ -846,7 +846,11 @@ void SV_ChangeTeam(float _color)
                TeamchangeFrags(self);
        }
 
-       SetPlayerTeam(self, dteam, steam, false);
+       // since this is an engine function, and gamecode doesn't have any calls earlier than this, do the connecting message here
+       if(!IS_CLIENT(self))
+               Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_CONNECTING, self.netname);
+
+       SetPlayerTeam(self, dteam, steam, !IS_CLIENT(self));
 
        if(IS_PLAYER(self) && steam != dteam)
        {
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 f6882302e433a1074def91289732cd3dfb65a06e..d563ac2d84eb3cd01ebf85e8ac8a054c53432b5e 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"
@@ -92,15 +91,16 @@ float client_hasweapon(entity cl, float wpn, float andammo, float complain)
                                                continue;
                                        if(!(e.flags & FL_ITEM))
                                                continue;
-                                       WaypointSprite_Spawn(
-                                               (get_weaponinfo(wpn)).wpmodel,
+                                       entity wp = WaypointSprite_Spawn(
+                                               WP_Weapon,
                                                1, 0,
                                                world, e.origin + ('0 0 1' * e.maxs.z) * 1.2,
                                                self, 0,
                                                world, enemy,
                                                0,
-                                               RADARICON_NONE, '0 0 0'
+                                               RADARICON_NONE
                                        );
+                                       wp.wp_extra = wpn;
                                }
                        }
                }
index 57fcfc8d423e363f0d2055e1fbfc2db4fc714d8c..deacbcc3ba61090a12d20deb78c0c12e36906c8e 100644 (file)
@@ -178,6 +178,7 @@ RedGuff
 Yannick "SpiKe" Le Guen
 
 *German
+Brot
 cvcxc
 Erik "Ablu" Schilling
 Jope "Sless" Withers