]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
HUD hit indicator: allow displaying up to 10 indicators at the same time
authorterencehill <piuntn@gmail.com>
Wed, 14 Feb 2024 21:54:38 +0000 (22:54 +0100)
committerterencehill <piuntn@gmail.com>
Wed, 14 Feb 2024 22:22:49 +0000 (23:22 +0100)
qcsrc/client/view.qc
qcsrc/client/view.qh

index 900114588ece060a366b252b9303d6f38982051a..b2524b4553b030182a3851675ef15b6747915ce5 100644 (file)
@@ -753,49 +753,70 @@ void View_EventChase(entity this)
        }
 }
 
+#define HITINDICATOR_EXPIRED(i) (time >= HitIndicator_time[i] + autocvar_cl_hit_indicator_fade_time)
+
 void HitIndicatorUpdate(float dmg, entity attacker)
 {
-       if (time < HitIndicator_time + 1 && HitIndicator_attacker == attacker)
-               HitIndicator_damage += dmg;
+       int i = 0;
+       int first_free_spot = -1;
+       for (i = 0; i < HITINDICATOR_MAX_COUNT; ++i)
+       {
+               if (first_free_spot == -1 && HITINDICATOR_EXPIRED(i))
+                       first_free_spot = i;
+               else if (attacker == HitIndicator_attacker[i] && !HITINDICATOR_EXPIRED(i))
+                       break;
+       }
+
+       bool is_new = false;
+       if (i == HITINDICATOR_MAX_COUNT) // if no matching attacker found
+       {
+               if (first_free_spot == -1) // if no free spot found
+                       return; // too many hits, ignore this new hit
+               i = first_free_spot;
+               is_new = true;
+       }
+
+       HitIndicator_attacker[i] = attacker;
+       HitIndicator_time[i] = time;
+       if (is_new)
+               HitIndicator_damage[i] = dmg;
        else
-               HitIndicator_damage = dmg;
-       HitIndicator_attacker = attacker;
-       HitIndicator_time = time;
+               HitIndicator_damage[i] += dmg;
 }
 
 void HitIndicatorShow()
 {
-       if (!autocvar_cl_hit_indicator || autocvar_cl_hit_indicator_size <= 0
-               || autocvar_chase_active || time > HitIndicator_time + autocvar_cl_hit_indicator_fade_time)
-       {
+       if (!autocvar_cl_hit_indicator || autocvar_cl_hit_indicator_size <= 0 || autocvar_chase_active)
                return;
-       }
 
-       entity attacker = HitIndicator_attacker;
-       if (!attacker)
-               return;
+       for (int i = 0; i < HITINDICATOR_MAX_COUNT; ++i)
+       {
+               entity attacker = HitIndicator_attacker[i];
+               if (!attacker || HITINDICATOR_EXPIRED(i))
+                       continue;
 
-       // hide indicator if attacker is not visible (check ported from shownames.qc)
-       traceline(view_origin, attacker.origin, MOVE_NOMONSTERS, attacker);
-       if (trace_fraction < 1 && (trace_networkentity != attacker.sv_entnum && trace_ent.entnum != attacker.sv_entnum))
-               return;
+               // hide indicator if attacker is not visible (check ported from shownames.qc)
+               traceline(view_origin, attacker.origin, MOVE_NOMONSTERS, attacker);
+               if (trace_fraction < 1 && (trace_networkentity != attacker.sv_entnum && trace_ent.entnum != attacker.sv_entnum))
+                       continue;
 
-       vector org = project_3d_to_2d(attacker.origin);
-       vector scr_center = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
-       float radius = autocvar_cl_hit_indicator_radius * min(vid_conwidth, vid_conheight);
-       vector ofs = normalize(org - scr_center - org.z * eZ) * radius;
-       float ang = atan2(-ofs.x, -ofs.y);
-       if (org.z < 0)
-       {
-               ang += M_PI;
-               ofs = -ofs;
-       }
-       org = scr_center + ofs;
-       float alpha = autocvar_cl_hit_indicator_fade_alpha;
-       alpha *= 1 - (time - HitIndicator_time) / autocvar_cl_hit_indicator_fade_time;
-       float size = autocvar_cl_hit_indicator_size;
-       size = map_bound_ranges(HitIndicator_damage, 30, 90, size, size * 2);
-       drawspritearrow(org, ang, '1 0 0', alpha, size, true);
+               vector org = project_3d_to_2d(attacker.origin);
+               vector scr_center = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
+               float radius = autocvar_cl_hit_indicator_radius * min(vid_conwidth, vid_conheight);
+               vector ofs = normalize(org - scr_center - org.z * eZ) * radius;
+               float ang = atan2(-ofs.x, -ofs.y);
+               if (org.z < 0)
+               {
+                       ang += M_PI;
+                       ofs = -ofs;
+               }
+               org = scr_center + ofs;
+               float alpha = autocvar_cl_hit_indicator_fade_alpha;
+               alpha *= 1 - (time - HitIndicator_time[i]) / autocvar_cl_hit_indicator_fade_time;
+               float size = autocvar_cl_hit_indicator_size;
+               size = map_bound_ranges(HitIndicator_damage[i], 30, 90, size, size * 2);
+               drawspritearrow(org, ang, '1 0 0', alpha, size, true);
+       }
 }
 
 vector damage_blurpostprocess, content_blurpostprocess;
index 0a54db106afa637f39e58d2ff47e7e6fad029a2a..73412793e5e4b512a828c5db4487e606f9251392 100644 (file)
@@ -99,9 +99,10 @@ float autocvar_cl_hit_indicator_fade_alpha = 0.8;
 float autocvar_cl_hit_indicator_fade_time = 1.5;
 float autocvar_cl_hit_indicator_radius = 0.15;
 float autocvar_cl_hit_indicator_size = 1.1;
-entity HitIndicator_attacker;
-float HitIndicator_damage;
-int HitIndicator_time;
+const int HITINDICATOR_MAX_COUNT = 10;
+entity HitIndicator_attacker[HITINDICATOR_MAX_COUNT];
+float HitIndicator_damage[HITINDICATOR_MAX_COUNT];
+int HitIndicator_time[HITINDICATOR_MAX_COUNT];
 
 void calc_followmodel_ofs(entity view);