Xonotic
shownames.qc
Go to the documentation of this file.
1 #include "shownames.qh"
2 
3 #include <client/draw.qh>
4 #include <client/hud/_mod.qh>
5 #include <client/view.qh>
6 #include <common/constants.qh>
7 #include <common/ent_cs.qh>
8 #include <common/net_linked.qh>
10 #include <common/teams.qh>
12 
13 // this.isactive = player is in range and coordinates/status (health and armor) are up to date
14 // this.origin = player origin
15 // this.healthvalue
16 // this.armorvalue
17 // this.sameteam = player is on same team as local client
18 // this.fadedelay = time to wait before name tag starts fading in for enemies
19 // this.pointtime = last time you pointed at this player
20 // this.csqcmodel_isdead = value of csqcmodel_isdead to know when the player is dead or not
21 
23 STATIC_INIT(shownames_ent)
24 {
25  shownames_ent = LL_NEW();
26  for (int i = 0; i < maxclients; ++i)
27  {
28  entity e = new_pure(shownames_tag);
29  e.sv_entnum = i + 1;
30  LL_PUSH(shownames_ent, e);
31  }
32 }
33 
34 // used by the antioverlap code
35 .vector box_ofs;
36 .vector box_org;
37 
38 const float SHOWNAMES_FADESPEED = 4;
39 const float SHOWNAMES_FADEDELAY = 0;
41 {
42  if (this.sv_entnum == current_player + 1) // self or spectatee
43  {
45  return;
46 
49  {
50  return;
51  }
52  }
53 
54  if (!this.sameteam && !autocvar_hud_shownames_enemies) return;
55  bool hit;
56  if (!autocvar_hud_shownames_crosshairdistance && this.sameteam)
57  {
58  hit = true;
59  }
60  else
61  {
62  traceline(view_origin, this.origin, MOVE_NOMONSTERS, this);
63  hit = !(trace_fraction < 1 && (trace_networkentity != this.sv_entnum && trace_ent.entnum != this.sv_entnum));
64  }
65  // handle tag fading
66  int overlap = -1;
69  {
71  float w = o.x - vid_conwidth / 2;
72  float h = o.y - vid_conheight / 2;
73  if (d * d > w * w + h * h) this.pointtime = time;
75  overlap = 1;
77  overlap = 0;
78  }
79 
80  // o.z is < 0 when o is behind me
81  #define OFF_SCREEN(o) (o.z < 0 || o.x < 0 || o.y < 0 || o.x > vid_conwidth || o.y > vid_conheight)
82  if (overlap == -1 && autocvar_hud_shownames_antioverlap)
83  {
84  // fade tag out if another tag that is closer to you overlaps
85  entity entcs = NULL;
86  LL_EACH(shownames_ent, it != this, {
87  entcs = entcs_receiver(i);
88  if (!(entcs && entcs.has_origin))
89  continue;
90  vector eo = project_3d_to_2d(it.origin + eZ * autocvar_hud_shownames_offset);
91  if (OFF_SCREEN(eo)) continue;
92  eo.z = 0;
93  if (boxesoverlap(this.box_org - this.box_ofs, this.box_org + this.box_ofs, it.box_org - it.box_ofs, it.box_org + it.box_ofs)
94  && vlen2(it.origin - view_origin) < vlen2(this.origin - view_origin))
95  {
96  overlap = 1;
97  break;
98  }
99  });
100  }
101  if (!this.fadedelay) this.fadedelay = time + SHOWNAMES_FADEDELAY;
102  if (this.csqcmodel_isdead) // dead player, fade out slowly
103  {
104  this.alpha = max(0, this.alpha - SHOWNAMES_FADESPEED * 0.25 * frametime);
105  }
106  else if (!this.sameteam && !hit) // view blocked, fade out
107  {
108  this.alpha = max(0, this.alpha - SHOWNAMES_FADESPEED * frametime);
109  this.fadedelay = 0; // reset fade in delay, enemy has left the view
110  }
111  else if (OFF_SCREEN(o)) // out of view, fade out
112  {
113  this.alpha = max(0, this.alpha - SHOWNAMES_FADESPEED * frametime);
114  }
115  else if (overlap > 0) // tag overlap detected, fade out
116  {
118  if (this.alpha >= minalpha)
119  this.alpha = max(minalpha, this.alpha - SHOWNAMES_FADESPEED * frametime);
120  else
121  this.alpha = min(minalpha, this.alpha + SHOWNAMES_FADESPEED * frametime);
122  }
123  else if (this.sameteam) // fade in for team mates
124  {
125  this.alpha = min(1, this.alpha + SHOWNAMES_FADESPEED * frametime);
126  }
127  else if (time > this.fadedelay || this.alpha > 0) // fade in for enemies
128  {
129  this.alpha = min(1, this.alpha + SHOWNAMES_FADESPEED * frametime);
130  }
131  float a = autocvar_hud_shownames_alpha * this.alpha;
132  if (!this.sameteam || (this.sv_entnum == player_localentnum))
133  {
134  float f = entcs_GetAlpha(this.sv_entnum - 1);
135  if (f == 0) f = 1;
136  if (f < 0) f = 0;
137  a *= f;
138  }
139  if (MUTATOR_CALLHOOK(ShowNames_Draw, this, a)) return;
140  a = M_ARGV(1, float);
141  float dist = -1; // dist will be calculated only when really needed to avoid wasting a vlen call
143  {
144  float max_dist = min(autocvar_hud_shownames_maxdistance, max_shot_distance);
145  if (vdist(this.origin - view_origin, >=, max_dist))
146  return;
148  {
150  if (dist == -1)
151  dist = vlen(this.origin - view_origin);
152  a *= (f - max(0, dist - autocvar_hud_shownames_mindistance)) / f;
153  }
154  }
155  else if (vdist(this.origin - view_origin, >=, max_shot_distance))
156  return;
157  if (!a || o.z < 0) return;
158 
159  o.z = 0;
160  float resize = 1;
162  {
163  // limit resize so its never smaller than 0.5... gets unreadable
165  if (dist == -1)
166  dist = vlen(this.origin - view_origin);
167  resize = 0.5 + 0.5 * (f - max(0, dist - autocvar_hud_shownames_mindistance)) / f;
168  }
170  vector myPos = o - vec2(0.5 * mySize.x, mySize.y);
171  mySize.x *= resize;
172  mySize.y *= resize;
173  myPos.x += 0.5 * (mySize.x / resize - mySize.x);
174  myPos.y += (mySize.y / resize - mySize.y);
175 
176  this.box_org = myPos + mySize / 2;
177  this.box_ofs = mySize / 2;
178 
179  float namewidth = mySize.x;
180  if (autocvar_hud_shownames_status && this.sameteam && !this.csqcmodel_isdead)
181  {
182  vector pos = myPos + eY * autocvar_hud_shownames_fontsize * resize;
183  vector sz = vec2(0.5 * mySize.x, resize * autocvar_hud_shownames_statusbar_height);
184 
185  this.box_ofs.x = max(mySize.x / 2, sz.x); // sz.x is already half as wide
186  this.box_ofs.y += sz.y / 2;
187  this.box_org.y = myPos.y + (mySize.y + sz.y) / 2;
188  // antioverlap debug code
189  //drawfill(this.box_org - this.box_ofs, this.box_ofs * 2, '1 1 1', a / 2, DRAWFLAG_NORMAL);
190 
192  drawfill(pos + eX * 0.25 * mySize.x, sz, '0.7 0.7 0.7', a / 2, DRAWFLAG_NORMAL);
193  if (this.healthvalue > 0)
194  {
195  HUD_Panel_DrawProgressBar(pos, sz, "nametag_statusbar",
196  this.healthvalue / autocvar_hud_panel_healtharmor_maxhealth, false, 1, '1 0 0', a,
198  }
199  if (GetResource(this, RES_ARMOR) > 0)
200  {
201  HUD_Panel_DrawProgressBar(pos + eX * 0.5 * mySize.x, sz, "nametag_statusbar",
202  GetResource(this, RES_ARMOR) / autocvar_hud_panel_healtharmor_maxarmor, false, 0, '0 1 0', a,
204  }
205  }
206  // antioverlap debug code
207  //else drawfill(this.box_org - this.box_ofs, this.box_ofs * 2, '1 1 1', a / 2, DRAWFLAG_NORMAL);
208 
209  string s = entcs_GetName(this.sv_entnum - 1);
211  s = playername(s, entcs_GetTeam(this.sv_entnum - 1), true);
212  drawfontscale = '1 1 0' * resize;
213  s = textShortenToWidth(s, namewidth, '1 1 0' * autocvar_hud_shownames_fontsize, stringwidth_colors);
214  float width = stringwidth(s, true, '1 1 0' * autocvar_hud_shownames_fontsize);
215  myPos.x = o.x - (width * resize) / 2;
217  drawfontscale = '1 1 0';
218 }
219 
221 {
222  if (!autocvar_hud_shownames) return;
223  LL_EACH(shownames_ent, true, {
224  entity entcs = entcs_receiver(i);
225  if (!entcs)
226  {
227  make_pure(it);
228  continue;
229  }
230  make_impure(it);
231  assert(getthink(entcs), eprint(entcs));
232  getthink(entcs)(entcs);
233  if (!entcs.has_origin) continue;
234  if (entcs.m_entcs_private)
235  {
236  it.healthvalue = entcs.healthvalue;
237  SetResourceExplicit(it, RES_ARMOR, GetResource(entcs, RES_ARMOR));
238  it.sameteam = true;
239  }
240  else
241  {
242  it.healthvalue = 0;
243  SetResourceExplicit(it, RES_ARMOR, 0);
244  it.sameteam = false;
245  }
246  bool dead = entcs_IsDead(i) || entcs_IsSpectating(i);
247  if ((!it.csqcmodel_isdead || it.alpha > 0) && entcs.origin != it.origin)
248  setorigin(it, entcs.origin);
249  it.csqcmodel_isdead = dead;
250  Draw_ShowNames(it);
251  });
252 }
bool autocvar_hud_shownames
Definition: shownames.qh:3
float vid_conheight
#define assert(expr,...)
Definition: log.qh:8
float alpha
Definition: items.qc:14
float current_player
Definition: hud.qh:182
STATIC_INIT(shownames_ent)
Definition: shownames.qc:23
void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, float length_ratio, bool vertical, float baralign, vector theColor, float theAlpha, int drawflag)
Definition: hud.qc:270
vector project_3d_to_2d(vector vec)
Definition: view.qc:359
const vector eY
Definition: vector.qh:45
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
Definition: cl_resources.qc:15
#define getthink(e)
vector box_org
Definition: shownames.qc:36
#define LL_EACH(list, cond, body)
Definition: linkedlist.qh:73
bool csqcmodel_isdead
#define stringwidth
Definition: csprogsdefs.qh:29
float trace_networkentity
entity() spawn
int sv_entnum
Definition: main.qh:155
bool autocvar_hud_shownames_self
Definition: shownames.qh:8
vector view_origin
Definition: main.qh:93
float maxclients
Definition: csprogsdefs.qc:21
string textShortenToWidth(string theText, float maxWidth, vector theFontSize, textLengthUpToWidth_widthFunction_t tw)
Definition: util.qc:956
vector drawfontscale
Definition: draw.qh:3
origin
Definition: ent_cs.qc:114
void Draw_ShowNames(entity this)
Definition: shownames.qc:40
float vid_conwidth
LinkedList shownames_ent
Definition: shownames.qc:22
float autocvar_hud_shownames_maxdistance
Definition: shownames.qh:18
#define make_impure(e)
Definition: oo.qh:15
entity trace_ent
Definition: csprogsdefs.qc:40
bool autocvar_hud_shownames_antioverlap
Definition: shownames.qh:19
entity LL_PUSH(LinkedList this, entity e)
Push to tail.
Definition: linkedlist.qh:21
const float SHOWNAMES_FADEDELAY
Definition: shownames.qc:39
#define OFF_SCREEN(o)
const float MOVE_NOMONSTERS
Definition: csprogsdefs.qc:253
#define vlen2(v)
Definition: vector.qh:4
ERASEABLE float boxesoverlap(vector m1, vector m2, vector m3, vector m4)
requires that m2>m1 in all coordinates, and that m4>m3
Definition: vector.qh:73
bool autocvar_hud_shownames_resize
Definition: shownames.qh:16
float autocvar_hud_shownames_crosshairdistance
Definition: shownames.qh:5
float autocvar_hud_shownames_aspect
Definition: shownames.qh:12
float autocvar_hud_shownames_alpha
Definition: shownames.qh:15
#define NULL
Definition: post.qh:17
float frametime
Definition: csprogsdefs.qc:17
const float DRAWFLAG_NORMAL
Definition: csprogsdefs.qc:317
int autocvar_hud_panel_healtharmor_maxhealth
Definition: healtharmor.qh:12
bool autocvar_hud_shownames_enemies
Definition: shownames.qh:4
#define make_pure(e)
Definition: oo.qh:12
float teamplay
Definition: progsdefs.qc:31
#define M_ARGV(x, type)
Definition: events.qh:17
float autocvar_hud_shownames_crosshairdistance_antioverlap
Definition: shownames.qh:7
float autocvar_hud_shownames_antioverlap_minalpha
Definition: shownames.qh:20
float player_localentnum
Definition: csprogsdefs.qc:19
float autocvar_hud_shownames_offset
Definition: shownames.qh:21
vector(float skel, float bonenum) _skel_get_boneabs_hidden
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
Definition: cl_resources.qc:10
float spectatee_status
Definition: main.qh:166
float autocvar_hud_shownames_crosshairdistance_time
Definition: shownames.qh:6
const vector eX
Definition: vector.qh:44
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition: vector.qh:8
const vector eZ
Definition: vector.qh:46
bool autocvar_hud_shownames_status
Definition: shownames.qh:9
vector box_ofs
Definition: shownames.qc:35
int autocvar_hud_panel_healtharmor_maxarmor
Definition: healtharmor.qh:11
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
float spectatee_status_changed_time
Definition: main.qh:167
#define vec2(...)
Definition: vector.qh:90
float autocvar_hud_shownames_statusbar_height
Definition: shownames.qh:10
#define new_pure(class)
purely logical entities (.origin doesn&#39;t work)
Definition: oo.qh:62
setorigin(ent, v)
int autocvar_hud_shownames_decolorize
Definition: shownames.qh:14
int autocvar_chase_active
Definition: view.qh:17
float autocvar_hud_shownames_statusbar_highlight
Definition: shownames.qh:11
float time
Definition: csprogsdefs.qc:16
float trace_fraction
Definition: csprogsdefs.qc:36
Header file that describes the resource system.
void Draw_ShowNames_All()
Definition: shownames.qc:220
float autocvar_hud_shownames_fontsize
Definition: shownames.qh:13
#define LL_NEW()
Definition: linkedlist.qh:14
const float SHOWNAMES_FADESPEED
Definition: shownames.qc:38
float autocvar_hud_shownames_mindistance
Definition: shownames.qh:17