]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
HUD: implement a 2d directional hit indicator around the screen center when a player... terencehill/hud_hit_indicator
authorterencehill <piuntn@gmail.com>
Mon, 29 Jan 2024 11:26:40 +0000 (12:26 +0100)
committerterencehill <piuntn@gmail.com>
Mon, 29 Jan 2024 11:26:40 +0000 (12:26 +0100)
* only 1 indicator at a time
* starts fading out as soon as it's shown
* the higher the damage, the bigger the indicator size
* damage is accumulated for a second (and indicator gets bigger)
* not shown if the attacker is not visible
* not shown when chase_active is enabled

qcsrc/client/view.qc
qcsrc/client/view.qh
qcsrc/common/effects/qc/damageeffects.qc
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qh
qcsrc/common/turrets/cl_turrets.qc
xonotic-client.cfg

index a1e2c6f91e9cbc93edf121b0d57f85c0538dd6b3..de1d10aabf60a226d3753423aee52d5f356ffcb4 100644 (file)
@@ -753,16 +753,33 @@ void View_EventChase(entity this)
        }
 }
 
+void HitIndicatorUpdate(float dmg, int attacker)
+{
+       if (time < HitIndicator_time + 1 && HitIndicator_attacker == attacker)
+               HitIndicator_damage += dmg;
+       else
+               HitIndicator_damage = dmg;
+       HitIndicator_attacker = attacker;
+       HitIndicator_time = time;
+}
+
 void HitIndicatorShow()
 {
        if (!autocvar_cl_hit_indicator || autocvar_cl_hit_indicator_size <= 0
-               || time > HitIndicator_time + 1
-               || !HitIndicator_attacker || !CSQCModel_server2csqc(HitIndicator_attacker - 1))
+               || autocvar_chase_active || time > HitIndicator_time + autocvar_cl_hit_indicator_fade_time)
        {
                return;
        }
 
        entity attacker = CSQCModel_server2csqc(HitIndicator_attacker - 1);
+       if (!HitIndicator_attacker || !CSQCModel_server2csqc(HitIndicator_attacker - 1))
+               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))
+               return;
+
        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);
@@ -773,8 +790,12 @@ void HitIndicatorShow()
                ang += M_PI;
                ofs = -ofs;
        }
-       org = scr_centersss + ofs;
-       drawspritearrow(org, ang, '1 0 0', 0.8, autocvar_cl_hit_indicator_size);
+       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 damage_blurpostprocess, content_blurpostprocess;
index 76bedbdabc0f28be78cee9da61a5baf9669617ec..326706cef24b43e4c15bf43ce3d1c8b7c1510753 100644 (file)
@@ -95,9 +95,12 @@ bool autocvar_r_drawviewmodel;
 vector autocvar_cl_gunoffset;
 
 bool autocvar_cl_hit_indicator = 1;
+float autocvar_cl_hit_indicator_fade_alpha = 0.8;
+float autocvar_cl_hit_indicator_fade_time = 1;
 float autocvar_cl_hit_indicator_radius = 0.15;
 float autocvar_cl_hit_indicator_size = 1.1;
 int HitIndicator_attacker;
+int HitIndicator_damage;
 int HitIndicator_time;
 
 void calc_followmodel_ofs(entity view);
index d77af71f35ba8690c7fc214db921472a02eba8b6..38ada5fec712b969ac7988664261cb189ffb2343 100644 (file)
@@ -193,9 +193,10 @@ void DamageEffect(entity this, vector hitorg, float thedamage, int type, int spe
 NET_HANDLE(ENT_CLIENT_DAMAGEINFO, bool isNew)
 {
        float thedamage, rad, edge, thisdmg;
-       bool hitplayer = false, hitme = false;
+       bool hitplayer = false;
        int species, forcemul;
        vector force, thisforce;
+       float hitme_damage = 0;
 
        w_deathtype = ReadShort();
        w_issilent = (w_deathtype & 0x8000);
@@ -267,8 +268,8 @@ NET_HANDLE(ENT_CLIENT_DAMAGEINFO, bool isNew)
 
                DamageEffect(it, w_org, thisdmg, w_deathtype, species);
 
-               if(it == csqcplayer)
-                       hitme = true; // this impact damaged me
+               if(it == csqcplayer && attacker - 1 != player_localnum)
+                       hitme_damage = thisdmg; // this impact damaged me
                else if(it != csqcplayer && (it.isplayermodel & ISPLAYER_MODEL))
                        hitplayer = true; // this impact damaged another player
        });
@@ -408,11 +409,8 @@ NET_HANDLE(ENT_CLIENT_DAMAGEINFO, bool isNew)
 
        if(!DEATH_ISSPECIAL(w_deathtype))
        {
-               if(hitme)
-               {
-                       HitIndicator_attacker = attacker;
-                       HitIndicator_time = time;
-               }
+               if(hitme_damage > 0)
+                       HitIndicatorUpdate(hitme_damage, attacker);
 
                // TODO spawn particle effects and sounds based on w_deathtype
                if(!hitplayer || rad) // don't show ground impacts for hitscan weapons if a player was hit
index f19fc059e393661839737c680b3089491e7bd4db..c371778beac63ca08b71e7ea676e5d1d86390763 100644 (file)
@@ -337,10 +337,10 @@ void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, fl
 }
 
 // returns location of sprite text
-vector drawspritearrow(vector o, float ang, vector rgb, float a, float t)
+vector drawspritearrow(vector o, float ang, vector rgb, float a, float t, bool no_border)
 {
     float size   = 9.0 * t;
-    float border = 1.5 * t;
+    float border = no_border ? 0 : 1.5 * t;
     float margin = 4.0 * t;
 
     float borderDiag = border * M_SQRT2;
@@ -659,7 +659,7 @@ void Draw_WaypointSprite(entity this)
             SetResourceExplicit(this, RES_HEALTH, -1);
     }
 
-    o = drawspritearrow(o, ang, rgb, a, SPRITE_ARROW_SCALE * t);
+    o = drawspritearrow(o, ang, rgb, a, SPRITE_ARROW_SCALE * t, false);
 
        string pic = "";
        bool is_text = true;
index 2274da336e926e31baeeeb46d471653c793519f1..bc024179027b55055fa16fad6ef2eca251c427a4 100644 (file)
@@ -102,7 +102,7 @@ void drawquad(vector o, vector ri, vector up, string pic, vector rgb, float a, 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);
+vector drawspritearrow(vector o, float ang, vector rgb, float a, float t, bool no_border);
 
 // returns location of sprite healthbar
 vector drawsprite_TextOrIcon(bool is_text, vector o, float ang, float minwidth, vector rgb, float a, vector sz, string str);
index 219b23318c9ab6a68ae9be5f798de916b32659b9..e480dd49c399c70053b7454dc2f33165a6e8c54b 100644 (file)
@@ -181,7 +181,7 @@ void turret_draw2d(entity this)
 
        if(draw_healthbar || draw_text) // make sure it's actually being drawn
        {
-               o = drawspritearrow(o, M_PI, rgb, a, SPRITE_ARROW_SCALE * t);
+               o = drawspritearrow(o, M_PI, rgb, a, SPRITE_ARROW_SCALE * t, false);
        }
        if(draw_text)
        {
index 16f752b1f150db202dc73b87bfee143227dc4024..1ecd52e501ce3a687dbb747729cdf72cad778459 100644 (file)
@@ -202,6 +202,8 @@ seta cl_voice_directional 1 "0 = all voices are non-directional, 1 = all voices
 seta cl_voice_directional_taunt_attenuation 0.5 "this defines the distance from which taunts can be heard"
 
 seta cl_hit_indicator 1 "show a 2d directional indicator around the screen center when a player hits you"
+seta cl_hit_indicator_fade_time 1 "how long hit indicator takes to fade away"
+seta cl_hit_indicator_fade_alpha 1 "initial hit indicator alpha"
 seta cl_hit_indicator_radius 0.15 "show the directional indicator at this percentage of the screen from the center"
 seta cl_hit_indicator_size 1.1 "directional indicator size"