Xonotic
waypointsprites.qc
Go to the documentation of this file.
1 #include "waypointsprites.qh"
2 
3 REGISTER_MUTATOR(waypointsprites, true);
4 
5 REGISTER_NET_LINKED(waypointsprites)
6 
7 #ifdef SVQC
8 bool WaypointSprite_SendEntity(entity this, entity to, float sendflags)
9 {
10  WriteHeader(MSG_ENTITY, waypointsprites);
11 
12  sendflags = sendflags & 0x7F;
13 
14  if (this.max_health || (this.pain_finished && (time < this.pain_finished + 0.25)))
15  sendflags |= 0x80;
16 
17  int hide_flags = 0;
18  if(this.currentammo == 1) hide_flags |= 1; // hideable
19  else if(this.currentammo == 2) hide_flags |= 2; // radar only
20  if(this.exteriormodeltoclient == to) hide_flags |= 2; // my own
21 
22  MUTATOR_CALLHOOK(SendWaypoint, this, to, sendflags, hide_flags);
23  sendflags = M_ARGV(2, int);
24  hide_flags = M_ARGV(3, int);
25 
26  WriteByte(MSG_ENTITY, sendflags);
27  WriteByte(MSG_ENTITY, this.wp_extra);
28 
29  if (sendflags & 0x80)
30  {
31  if (this.max_health)
32  {
33  WriteByte(MSG_ENTITY, (GetResource(this, RES_HEALTH) / this.max_health) * 191.0);
34  }
35  else
36  {
37  float dt = this.pain_finished - time;
38  dt = bound(0, dt * 32, 16383);
39  WriteByte(MSG_ENTITY, (dt & 0xFF00) / 256 + 192);
40  WriteByte(MSG_ENTITY, (dt & 0x00FF));
41  }
42  }
43 
44  if (sendflags & 64)
45  {
46  WriteVector(MSG_ENTITY, this.origin);
47  }
48 
49  if (sendflags & 1)
50  {
51  WriteByte(MSG_ENTITY, this.team);
52  WriteByte(MSG_ENTITY, this.rule);
53  }
54 
55  if (sendflags & 2)
56  WriteString(MSG_ENTITY, this.model1);
57 
58  if (sendflags & 4)
59  WriteString(MSG_ENTITY, this.model2);
60 
61  if (sendflags & 8)
62  WriteString(MSG_ENTITY, this.model3);
63 
64  if (sendflags & 16)
65  {
66  WriteCoord(MSG_ENTITY, this.fade_time);
67  WriteCoord(MSG_ENTITY, this.teleport_time);
68  WriteShort(MSG_ENTITY, bound(0, this.fade_rate, 32767)); // maxdist
69  WriteByte(MSG_ENTITY, hide_flags);
70  }
71 
72  if (sendflags & 32)
73  {
74  WriteByte(MSG_ENTITY, this.cnt); // icon on radar
75  WriteByte(MSG_ENTITY, this.colormod.x * 255.0);
76  WriteByte(MSG_ENTITY, this.colormod.y * 255.0);
77  WriteByte(MSG_ENTITY, this.colormod.z * 255.0);
78 
79  if (WaypointSprite_isteammate(this.owner, WaypointSprite_getviewentity(to)))
80  {
81  float dt = bound(0, (this.waypointsprite_helpmetime - time) / 0.1, 255);
82  WriteByte(MSG_ENTITY, dt);
83  }
84  else
85  WriteByte(MSG_ENTITY, 0);
86  }
87 
88  return true;
89 }
90 #endif
91 
92 #ifdef CSQC
93 void Ent_WaypointSprite(entity this, bool isnew);
94 NET_HANDLE(waypointsprites, bool isnew) {
95  Ent_WaypointSprite(this, isnew);
96  return true;
97 }
98 
99 void Ent_RemoveWaypointSprite(entity this)
100 {
101  strfree(this.netname);
102  strfree(this.netname2);
103  strfree(this.netname3);
104 }
105 
106 void Ent_WaypointSprite(entity this, bool isnew)
107 {
108  int sendflags = ReadByte();
109  this.wp_extra = ReadByte();
110 
111  if (!this.spawntime)
112  this.spawntime = time;
113 
114  this.draw2d = Draw_WaypointSprite;
115  if (isnew) {
116  IL_PUSH(g_drawables_2d, this);
117  IL_PUSH(g_radaricons, this);
118  }
119 
121  this.iflags |= IFLAG_ORIGIN;
122 
123  if (sendflags & 0x80)
124  {
125  int t = ReadByte();
126  if (t < 192)
127  {
128  SetResourceExplicit(this, RES_HEALTH, t / 191.0);
129  this.build_finished = 0;
130  }
131  else
132  {
133  t = (t - 192) * 256 + ReadByte();
134  this.build_started = servertime;
135  if (this.build_finished)
136  this.build_starthealth = bound(0, GetResource(this, RES_HEALTH), 1);
137  else
138  this.build_starthealth = 0;
139  this.build_finished = servertime + t / 32;
140  }
141  }
142  else
143  {
144  SetResourceExplicit(this, RES_HEALTH, -1);
145  this.build_finished = 0;
146  }
147 
148  if (sendflags & 64)
149  {
150  // unfortunately, this needs to be exact (for the 3D display)
151  this.origin = ReadVector();
152  setorigin(this, this.origin);
153  }
154 
155  if (sendflags & 1)
156  {
157  this.team = ReadByte();
158  this.rule = ReadByte();
159  }
160 
161  if (sendflags & 2)
162  {
163  strcpy(this.netname, ReadString());
164  }
165 
166  if (sendflags & 4)
167  {
168  strcpy(this.netname2, ReadString());
169  }
170 
171  if (sendflags & 8)
172  {
173  strcpy(this.netname3, ReadString());
174  }
175 
176  if (sendflags & 16)
177  {
178  this.lifetime = ReadCoord();
179  this.fadetime = ReadCoord();
180  this.maxdistance = ReadShort();
181  this.hideflags = ReadByte();
182  }
183 
184  if (sendflags & 32)
185  {
186  int f = ReadByte();
187  this.teamradar_icon = f & BITS(7);
188  if (f & BIT(7))
189  {
190  this.(teamradar_times[this.teamradar_time_index]) = time;
191  this.teamradar_time_index = (this.teamradar_time_index + 1) % MAX_TEAMRADAR_TIMES;
192  }
193  this.teamradar_color_x = ReadByte() / 255.0;
194  this.teamradar_color_y = ReadByte() / 255.0;
195  this.teamradar_color_z = ReadByte() / 255.0;
196  this.helpme = ReadByte() * 0.1;
197  if (this.helpme > 0)
198  this.helpme += servertime;
199  }
200 
202 
203  this.entremove = Ent_RemoveWaypointSprite;
204 }
205 #endif
206 
207 #ifdef CSQC
208 float spritelookupblinkvalue(entity this, string s)
209 {
210  if (s == WP_Weapon.netname) {
212  return 2;
213  }
214  if (s == WP_Item.netname) return REGISTRY_GET(Items, this.wp_extra).m_waypointblink;
215  if(s == WP_FlagReturn.netname) return 2;
216 
217  return 1;
218 }
219 
220 vector spritelookupcolor(entity this, string s, vector def)
221 {
222  if (s == WP_Weapon.netname || s == RADARICON_Weapon.netname) return REGISTRY_GET(Weapons, this.wp_extra).wpcolor;
223  if (s == WP_Item.netname || s == RADARICON_Item.netname) return REGISTRY_GET(Items, this.wp_extra).m_color;
224  if (MUTATOR_CALLHOOK(WP_Format, this, s))
225  {
226  return M_ARGV(2, vector);
227  }
228  return def;
229 }
230 
231 string spritelookuptext(entity this, string s)
232 {
233  if(autocvar_g_waypointsprite_spam && waypointsprite_count >= autocvar_g_waypointsprite_spam)
234  return "Spam"; // no need to translate this debug string
235  if (s == WP_RaceStartFinish.netname) return (race_checkpointtime || race_mycheckpointtime) ? _("Finish") : _("Start");
236  if (s == WP_Weapon.netname) return REGISTRY_GET(Weapons, this.wp_extra).m_name;
237  if (s == WP_Item.netname) return REGISTRY_GET(Items, this.wp_extra).m_waypoint;
238  if (s == WP_Monster.netname) return get_monsterinfo(this.wp_extra).monster_name;
239  if (MUTATOR_CALLHOOK(WP_Format, this, s))
240  {
241  return M_ARGV(3, string);
242  }
243 
244  // need to loop, as our netname could be one of three
245  FOREACH(Waypoints, it.netname == s, {
246  return it.m_name;
247  });
248 
249  return s;
250 }
251 
252 string spritelookupicon(entity this, string s)
253 {
254  // TODO: needs icons! //if (s == WP_RaceStartFinish.netname) return (race_checkpointtime || race_mycheckpointtime) ? _("Finish") : _("Start");
255  if (s == WP_Weapon.netname) return REGISTRY_GET(Weapons, this.wp_extra).model2;
256  if (s == WP_Item.netname) return REGISTRY_GET(Items, this.wp_extra).m_icon;
257  if (s == WP_Vehicle.netname) return REGISTRY_GET(Vehicles, this.wp_extra).m_icon;
258  //if (s == WP_Monster.netname) return get_monsterinfo(this.wp_extra).m_icon;
259  if (MUTATOR_CALLHOOK(WP_Format, this, s))
260  {
261  return M_ARGV(4, string);
262  }
263 
264  // need to loop, as our netname could be one of three
265  FOREACH(Waypoints, it.netname == s, {
266  return it.m_icon;
267  });
268 
269  return s;
270 }
271 #endif
272 
273 #ifdef CSQC
274 void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f)
275 {
276  vector v1, v2, v3, v4;
277 
278  hotspot = -1 * hotspot;
279 
280  // hotspot-relative coordinates of the corners
281  v1 = hotspot;
282  v2 = hotspot + '1 0 0' * sz.x;
283  v3 = hotspot + '1 0 0' * sz.x + '0 1 0' * sz.y;
284  v4 = hotspot + '0 1 0' * sz.y;
285 
286  // rotate them, and make them absolute
287  rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed
288  v1 = Rotate(v1, rot) + org;
289  v2 = Rotate(v2, rot) + org;
290  v3 = Rotate(v3, rot) + org;
291  v4 = Rotate(v4, rot) + org;
292 
293  // draw them
294  R_BeginPolygon(pic, f, true);
295  R_PolygonVertex(v1, '0 0 0', rgb, a);
296  R_PolygonVertex(v2, '1 0 0', rgb, a);
297  R_PolygonVertex(v3, '1 1 0', rgb, a);
298  R_PolygonVertex(v4, '0 1 0', rgb, a);
299  R_EndPolygon();
300 }
301 
302 void drawquad(vector o, vector ri, vector up, string pic, vector rgb, float a, float f)
303 {
304  R_BeginPolygon(pic, f, true);
305  R_PolygonVertex(o, '0 0 0', rgb, a);
306  R_PolygonVertex(o + ri, '1 0 0', rgb, a);
307  R_PolygonVertex(o + up + ri, '1 1 0', rgb, a);
308  R_PolygonVertex(o + up, '0 1 0', rgb, a);
309  R_EndPolygon();
310 }
311 
312 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)
313 {
314  vector o, ri, up;
315  float owidth; // outer width
316 
317  hotspot = -1 * hotspot;
318 
319  // hotspot-relative coordinates of the healthbar corners
320  o = hotspot;
321  ri = '1 0 0';
322  up = '0 1 0';
323 
324  rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed
325  o = Rotate(o, rot) + org;
326  ri = Rotate(ri, rot);
327  up = Rotate(up, rot);
328 
329  owidth = width + 2 * border;
330  o = o - up * (margin + border + theheight) + ri * (sz.x - owidth) * 0.5;
331 
332  drawquad(o - up * border, ri * owidth, up * border, "", rgb, a, f);
333  drawquad(o + up * theheight, ri * owidth, up * border, "", rgb, a, f);
334  drawquad(o, ri * border, up * theheight, "", rgb, a, f);
335  drawquad(o + ri * (owidth - border), ri * border, up * theheight, "", rgb, a, f);
336  drawquad(o + ri * (border + align * ((1 - h) * width)), ri * width * h, up * theheight, "", hrgb, ha, f);
337 }
338 
339 // returns location of sprite text
340 vector drawspritearrow(vector o, float ang, vector rgb, float a, float t)
341 {
342  float size = 9.0 * t;
343  float border = 1.5 * t;
344  float margin = 4.0 * t;
345 
346  float borderDiag = border * M_SQRT2;
347  vector arrowX = eX * size;
348  vector arrowY = eY * (size+borderDiag);
349  vector borderX = eX * (size+borderDiag);
350  vector borderY = eY * (size+borderDiag+border);
351 
352  R_BeginPolygon("", DRAWFLAG_NORMAL, true);
353  R_PolygonVertex(o, '0 0 0', '0 0 0', a);
354  R_PolygonVertex(o + Rotate(arrowY - borderX, ang), '0 0 0', '0 0 0', a);
355  R_PolygonVertex(o + Rotate(borderY - borderX, ang), '0 0 0', '0 0 0', a);
356  R_PolygonVertex(o + Rotate(borderY + borderX, ang), '0 0 0', '0 0 0', a);
357  R_PolygonVertex(o + Rotate(arrowY + borderX, ang), '0 0 0', '0 0 0', a);
358  R_EndPolygon();
359 
360  R_BeginPolygon("", DRAWFLAG_ADDITIVE, true);
361  R_PolygonVertex(o + Rotate(eY * borderDiag, ang), '0 0 0', rgb, a);
362  R_PolygonVertex(o + Rotate(arrowY - arrowX, ang), '0 0 0', rgb, a);
363  R_PolygonVertex(o + Rotate(arrowY + arrowX, ang), '0 0 0', rgb, a);
364  R_EndPolygon();
365 
366  return o + Rotate(eY * (borderDiag+size+margin), ang);
367 }
368 
369 // returns location of sprite healthbar
370 vector drawsprite_TextOrIcon(bool is_text, vector o, float ang, float minwidth, vector rgb, float a, vector sz, string str)
371 {
372  float algnx, algny;
373  float sw, w, h;
374  float aspect, sa, ca;
375 
376  if (is_text)
377  sw = stringwidth(str, false, sz);
378  else
379  sw = sz.x;
380 
381  if (sw > minwidth)
382  w = sw;
383  else
384  w = minwidth;
385  h = sz.y;
386 
387  // how do corners work?
388  aspect = vid_conwidth / vid_conheight;
389  sa = sin(ang);
390  ca = cos(ang) * aspect;
391  if (fabs(sa) > fabs(ca))
392  {
393  algnx = (sa < 0);
394  float f = fabs(sa);
395  algny = 0.5 - 0.5 * (f ? (ca / f) : 0);
396  }
397  else
398  {
399  float f = fabs(ca);
400  algnx = 0.5 - 0.5 * (f ? (sa / f) : 0);
401  algny = (ca < 0);
402  }
403 
404  // align
405  o.x -= w * algnx;
406  o.y -= h * algny;
407 
408  // we want to be onscreen
409  if (o.x < 0)
410  o.x = 0;
411  if (o.y < 0)
412  o.y = 0;
413  if (o.x > vid_conwidth - w)
414  o.x = vid_conwidth - w;
415  if (o.y > vid_conheight - h)
416  o.y = vid_conheight - h;
417 
418  o.x += 0.5 * (w - sw);
419 
420  if (is_text)
421  drawstring(o, str, sz, rgb, a, DRAWFLAG_NORMAL);
422  else
423  drawpic(o, str, sz, rgb, a, DRAWFLAG_NORMAL);
424 
425  o.x += 0.5 * sw;
426  o.y += 0.5 * h;
427 
428  return o;
429 }
430 
431 vector fixrgbexcess_move(vector rgb, vector src, vector dst)
432 {
433  vector yvec = '0.299 0.587 0.114';
434  return rgb + dst * ((src * yvec) / (dst * yvec)) * ((rgb - '1 1 1') * src);
435 }
436 
437 vector fixrgbexcess(vector rgb)
438 {
439  if (rgb.x > 1) {
440  rgb = fixrgbexcess_move(rgb, '1 0 0', '0 1 1');
441  if (rgb.y > 1) {
442  rgb = fixrgbexcess_move(rgb, '0 1 0', '0 0 1');
443  if (rgb.z > 1) rgb.z = 1;
444  } else if (rgb.z > 1) {
445  rgb = fixrgbexcess_move(rgb, '0 0 1', '0 1 0');
446  if (rgb.y > 1) rgb.y = 1;
447  }
448  } else if (rgb.y > 1) {
449  rgb = fixrgbexcess_move(rgb, '0 1 0', '1 0 1');
450  if (rgb.x > 1) {
451  rgb = fixrgbexcess_move(rgb, '1 0 0', '0 0 1');
452  if (rgb.z > 1) rgb.z = 1;
453  } else if (rgb.z > 1) {
454  rgb = fixrgbexcess_move(rgb, '0 0 1', '1 0 0');
455  if (rgb.x > 1) rgb.x = 1;
456  }
457  } else if (rgb.z > 1) {
458  rgb = fixrgbexcess_move(rgb, '0 0 1', '1 1 0');
459  if (rgb.x > 1) {
460  rgb = fixrgbexcess_move(rgb, '1 0 0', '0 1 0');
461  if (rgb.y > 1) rgb.y = 1;
462  } else if (rgb.y > 1) {
463  rgb = fixrgbexcess_move(rgb, '0 1 0', '1 0 0');
464  if (rgb.x > 1) rgb.x = 1;
465  }
466  }
467  return rgb;
468 }
469 
470 void Draw_WaypointSprite(entity this)
471 {
472  if (this.lifetime > 0)
473  this.alpha = (bound(0, (this.fadetime - time) / this.lifetime, 1) ** waypointsprite_timealphaexponent);
474  else
475  this.alpha = 1;
476 
477  if (this.hideflags & 2)
478  return; // radar only
479 
480  if (autocvar_cl_hidewaypoints >= 2)
481  return;
482 
483  if ((this.hideflags & 1) && autocvar_cl_hidewaypoints)
484  return; // fixed waypoint
485 
486  InterpolateOrigin_Do(this);
487 
488  float t = entcs_GetTeam(player_localnum) + 1;
489  string spriteimage = "";
490 
491  // choose the sprite
492  switch (this.rule)
493  {
495  if (!(
496  (autocvar_g_waypointsprite_itemstime == 1 && t == NUM_SPECTATOR + 1)
497  || (autocvar_g_waypointsprite_itemstime == 2 && (t == NUM_SPECTATOR + 1 || warmup_stage || STAT(ITEMSTIME) == 2))
498  ))
499  return;
500  spriteimage = this.netname;
501  break;
502  case SPRITERULE_DEFAULT:
503  if (this.team)
504  {
505  if (this.team == t)
506  spriteimage = this.netname;
507  else
508  spriteimage = "";
509  }
510  else
511  spriteimage = this.netname;
512  break;
513  case SPRITERULE_TEAMPLAY:
514  if (t == NUM_SPECTATOR + 1)
515  spriteimage = this.netname3;
516  else if (this.team == t)
517  spriteimage = this.netname2;
518  else
519  spriteimage = this.netname;
520  break;
521  default:
522  error("Invalid waypointsprite rule!");
523  break;
524  }
525 
526  if (spriteimage == "")
527  return;
528 
529  ++waypointsprite_newcount;
530 
531  float dist = vlen(this.origin - view_origin);
532  float a = this.alpha * autocvar_hud_panel_fg_alpha;
533 
534  if(this.maxdistance > 0)
535  {
536  // restrict maximum normal distance to the waypoint's maximum distance to prevent exploiting cvars
537  float maxnormdistance = bound(0, waypointsprite_normdistance, this.maxdistance - 1);
538  a *= (bound(0, (this.maxdistance - dist) / (this.maxdistance - maxnormdistance), 1) ** waypointsprite_distancealphaexponent);
539  }
540 
541  vector rgb = spritelookupcolor(this, spriteimage, this.teamradar_color);
542  if (rgb == '0 0 0')
543  {
544  this.teamradar_color = '1 0 1';
545  LOG_INFOF("WARNING: sprite of name %s has no color, using pink so you notice it", spriteimage);
546  }
547 
548  float health_val = GetResource(this, RES_HEALTH);
549  float blink_time = (health_val >= 0) ? (health_val * 10) : time;
550  if (blink_time - floor(blink_time) > 0.5)
551  {
552  if (this.helpme && time < this.helpme)
553  a *= SPRITE_HELPME_BLINK;
554  else if (!this.lifetime) // fading out waypoints don't blink
555  a *= spritelookupblinkvalue(this, spriteimage);
556  }
557 
558  if (a > 1)
559  {
560  rgb *= a;
561  a = 1;
562  }
563 
564  if (a <= 0.003)
565  return;
566 
567  rgb = fixrgbexcess(rgb);
568 
569  vector o;
570  float ang;
571 
572  o = project_3d_to_2d(this.origin);
573  if (o.z < 0
574  || o.x < (vid_conwidth * waypointsprite_edgeoffset_left)
575  || o.y < (vid_conheight * waypointsprite_edgeoffset_top)
576  || o.x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))
577  || o.y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
578  {
579  // scale it to be just in view
580  vector d;
581 
582  d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
583  ang = atan2(-d.x, -d.y);
584  if (o.z < 0)
585  ang += M_PI;
586 
587  float f1 = d.x / vid_conwidth;
588  float f2 = d.y / vid_conheight;
589  if (f1 == 0) { f1 = 0.000001; }
590  if (f2 == 0) { f2 = 0.000001; }
591 
592  if (max(f1, -f1) > max(f2, -f2)) {
593  if (d.z * f1 > 0) {
594  // RIGHT edge
595  d = d * ((0.5 - waypointsprite_edgeoffset_right) / f1);
596  } else {
597  // LEFT edge
598  d = d * (-(0.5 - waypointsprite_edgeoffset_left) / f1);
599  }
600  } else {
601  if (d.z * f2 > 0) {
602  // BOTTOM edge
603  d = d * ((0.5 - waypointsprite_edgeoffset_bottom) / f2);
604  } else {
605  // TOP edge
606  d = d * (-(0.5 - waypointsprite_edgeoffset_top) / f2);
607  }
608  }
609 
610  o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
611  }
612  else
613  {
614 #if 1
615  ang = M_PI;
616 #else
617  vector d;
618  d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
619  ang = atan2(-d.x, -d.y);
620 #endif
621  }
622  o.z = 0;
623 
624  float edgedistance_min = min((o.y - (vid_conheight * waypointsprite_edgeoffset_top)),
625  (o.x - (vid_conwidth * waypointsprite_edgeoffset_left)),
626  (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) - o.x,
627  (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)) - o.y);
628 
629  float crosshairdistance = sqrt( ((o.x - vid_conwidth/2) ** 2) + ((o.y - vid_conheight/2) ** 2) );
630 
631  t = waypointsprite_scale;
632  a *= waypointsprite_alpha;
633 
634  {
635  a = a * (1 - (1 - waypointsprite_distancefadealpha) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
636  t = t * (1 - (1 - waypointsprite_distancefadescale) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
637  }
638  if (edgedistance_min < waypointsprite_edgefadedistance) {
639  a = a * (1 - (1 - waypointsprite_edgefadealpha) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
640  t = t * (1 - (1 - waypointsprite_edgefadescale) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
641  }
642  if (crosshairdistance < waypointsprite_crosshairfadedistance) {
643  a = a * (1 - (1 - waypointsprite_crosshairfadealpha) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
644  t = t * (1 - (1 - waypointsprite_crosshairfadescale) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
645  }
646 
647  if (this.build_finished)
648  {
649  if (time < this.build_finished + 0.25)
650  {
651  if (time < this.build_started)
652  SetResourceExplicit(this, RES_HEALTH, this.build_starthealth);
653  else if (time < this.build_finished)
654  SetResourceExplicit(this, RES_HEALTH, (time - this.build_started) / (this.build_finished - this.build_started) * (1 - this.build_starthealth) + this.build_starthealth);
655  else
657  }
658  else
659  SetResourceExplicit(this, RES_HEALTH, -1);
660  }
661 
662  o = drawspritearrow(o, ang, rgb, a, SPRITE_ARROW_SCALE * t);
663 
664  string pic = "";
665  bool is_text = true;
666  if (!autocvar_g_waypointsprite_text)
667  {
668  string spr_icon = spritelookupicon(this, spriteimage);
669  pic = spr_icon;
670  bool icon_found = !(!spr_icon || spr_icon == "");
671  if (icon_found) // it's valid, but let's make sure it exists!
672  {
673  pic = strcat(hud_skin_path, "/", spr_icon);
674  if(precache_pic(pic) == "")
675  {
676  pic = strcat("gfx/hud/default/", spr_icon);
677  if(!precache_pic(pic))
678  icon_found = false;
679  }
680  }
681  if (icon_found)
682  is_text = false;
683  }
684 
685  vector sz;
686  vector txt_color;
687  string txt = string_null;
688  if (is_text)
689  {
690  txt = spritelookuptext(this, spriteimage);
691  if (this.helpme && time < this.helpme)
692  txt = sprintf(_("%s needing help!"), txt);
693  if (autocvar_g_waypointsprite_uppercase)
694  txt = strtoupper(txt);
695  txt_color = rgb;
696  sz = waypointsprite_fontsize * '1 1 0';
697  }
698  else
699  {
700  // for convenience icon path and color are saved to txt and txt_color
701  txt = pic;
702  txt_color = ((autocvar_g_waypointsprite_iconcolor) ? '1 1 1' : rgb);
703  sz = autocvar_g_waypointsprite_iconsize * '1 1 0';
704  }
705 
707  if (GetResource(this, RES_HEALTH) >= 0)
708  {
709  float align = 0, marg;
710  if (this.build_finished)
711  align = 0.5;
712  else
713  align = 0;
714  if (cos(ang) > 0)
715  marg = -(SPRITE_HEALTHBAR_MARGIN + SPRITE_HEALTHBAR_HEIGHT + 2 * SPRITE_HEALTHBAR_BORDER) * t - 0.5 * sz.y;
716  else
717  marg = SPRITE_HEALTHBAR_MARGIN * t + 0.5 * sz.y;
718 
719  float minwidth = (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t;
720  o = drawsprite_TextOrIcon(is_text, o, ang, minwidth, txt_color, a, sz, txt);
721  drawhealthbar(
722  o,
723  0,
724  GetResource(this, RES_HEALTH),
725  '0 0 0',
726  '0 0 0',
727  SPRITE_HEALTHBAR_WIDTH * t,
728  SPRITE_HEALTHBAR_HEIGHT * t,
729  marg,
730  SPRITE_HEALTHBAR_BORDER * t,
731  align,
732  rgb,
733  a * SPRITE_HEALTHBAR_BORDERALPHA,
734  rgb,
735  a * SPRITE_HEALTHBAR_HEALTHALPHA,
737  );
738  }
739  else
740  {
741  drawsprite_TextOrIcon(is_text, o, ang, 0, txt_color, a, sz, txt);
742  }
743 
745 }
746 
747 void WaypointSprite_Load_Frames(string ext)
748 {
749  int dh = search_begin(strcat("models/sprites/*_frame*", ext), false, false);
750  if (dh < 0) return;
751  int ext_len = strlen(ext);
752  int n = search_getsize(dh);
753  for (int i = 0; i < n; ++i)
754  {
755  string s = search_getfilename(dh, i);
756  s = substring(s, 15, strlen(s) - 15 - ext_len); // strip models/sprites/ and extension
757 
758  int o = strstrofs(s, "_frame", 0);
759  string sname = strcat("/spriteframes/", substring(s, 0, o));
760  string sframes = substring(s, o + 6, strlen(s) - o - 6);
761  int f = stof(sframes) + 1;
762  db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname)))));
763  }
764  search_end(dh);
765 }
766 
767 void WaypointSprite_Load();
768 STATIC_INIT(WaypointSprite_Load) {
769  WaypointSprite_Load();
770  WaypointSprite_Load_Frames(".tga");
771  WaypointSprite_Load_Frames(".jpg");
772 }
773 void WaypointSprite_Load()
774 {
775  waypointsprite_fadedistance = vlen(mi_scale);
776  waypointsprite_normdistance = autocvar_g_waypointsprite_normdistance;
777  waypointsprite_minscale = autocvar_g_waypointsprite_minscale;
778  waypointsprite_minalpha = autocvar_g_waypointsprite_minalpha;
779  waypointsprite_distancealphaexponent = autocvar_g_waypointsprite_distancealphaexponent;
780  waypointsprite_timealphaexponent = autocvar_g_waypointsprite_timealphaexponent;
781  waypointsprite_scale = autocvar_g_waypointsprite_scale;
782  waypointsprite_fontsize = autocvar_g_waypointsprite_fontsize;
783  waypointsprite_edgefadealpha = autocvar_g_waypointsprite_edgefadealpha;
784  waypointsprite_edgefadescale = autocvar_g_waypointsprite_edgefadescale;
785  waypointsprite_edgefadedistance = autocvar_g_waypointsprite_edgefadedistance;
786  waypointsprite_edgeoffset_bottom = autocvar_g_waypointsprite_edgeoffset_bottom;
787  waypointsprite_edgeoffset_left = autocvar_g_waypointsprite_edgeoffset_left;
788  waypointsprite_edgeoffset_right = autocvar_g_waypointsprite_edgeoffset_right;
789  waypointsprite_edgeoffset_top = autocvar_g_waypointsprite_edgeoffset_top;
790  waypointsprite_crosshairfadealpha = autocvar_g_waypointsprite_crosshairfadealpha;
791  waypointsprite_crosshairfadescale = autocvar_g_waypointsprite_crosshairfadescale;
792  waypointsprite_crosshairfadedistance = autocvar_g_waypointsprite_crosshairfadedistance;
793  waypointsprite_distancefadealpha = autocvar_g_waypointsprite_distancefadealpha;
794  waypointsprite_distancefadescale = autocvar_g_waypointsprite_distancefadescale;
795  waypointsprite_distancefadedistance = waypointsprite_fadedistance * autocvar_g_waypointsprite_distancefadedistancemultiplier;
796  waypointsprite_alpha = autocvar_g_waypointsprite_alpha * (1 - autocvar__menu_alpha);
797 
798  waypointsprite_count = waypointsprite_newcount;
799  waypointsprite_newcount = 0;
800 }
801 #endif
802 
803 #ifdef SVQC
804 void WaypointSprite_UpdateSprites(entity e, entity _m1, entity _m2, entity _m3)
805 {
806  string m1 = _m1.netname;
807  string m2 = _m2.netname;
808  string m3 = _m3.netname;
809  if (m1 != e.model1)
810  {
811  e.model1 = m1;
812  e.SendFlags |= 2;
813  }
814  if (m2 != e.model2)
815  {
816  e.model2 = m2;
817  e.SendFlags |= 4;
818  }
819  if (m3 != e.model3)
820  {
821  e.model3 = m3;
822  e.SendFlags |= 8;
823  }
824 }
825 
826 void WaypointSprite_UpdateHealth(entity e, float f)
827 {
828  f = bound(0, f, e.max_health);
829  float step = e.max_health / 40;
830  if ((floor(f / step) != floor(GetResource(e, RES_HEALTH) / step)) || e.pain_finished)
831  {
833  e.pain_finished = 0;
834  e.SendFlags |= 0x80;
835  }
836 }
837 
838 void WaypointSprite_UpdateMaxHealth(entity e, float f)
839 {
840  if (f != e.max_health || e.pain_finished)
841  {
842  e.max_health = f;
843  e.pain_finished = 0;
844  e.SendFlags |= 0x80;
845  }
846 }
847 
848 void WaypointSprite_UpdateBuildFinished(entity e, float f)
849 {
850  if (f != e.pain_finished || e.max_health)
851  {
852  e.max_health = 0;
853  e.pain_finished = f;
854  e.SendFlags |= 0x80;
855  }
856 }
857 
858 void WaypointSprite_UpdateOrigin(entity e, vector o)
859 {
860  if (o != e.origin)
861  {
862  setorigin(e, o);
863  e.SendFlags |= 64;
864  }
865 }
866 
867 void WaypointSprite_UpdateRule(entity e, float t, float r)
868 {
869  // no check, as this is never called without doing an actual change (usually only once)
870  e.rule = r;
871  e.team = t;
872  e.SendFlags |= 1;
873 }
874 
875 void WaypointSprite_UpdateTeamRadar(entity e, entity icon, vector col)
876 {
877  // no check, as this is never called without doing an actual change (usually only once)
878  int i = icon.m_id;
879  int new_cnt = (e.cnt & BIT(7)) | (i & BITS(7));
880  if (new_cnt != e.cnt || col != e.colormod)
881  {
882  e.cnt = new_cnt;
883  e.colormod = col;
884  e.SendFlags |= 32;
885  }
886 }
887 
888 void WaypointSprite_Ping(entity e)
889 {
890  // anti spam
891  if (time < e.waypointsprite_pingtime) return;
892  e.waypointsprite_pingtime = time + 0.3;
893  // ALWAYS sends (this causes a radar circle), thus no check
894  e.cnt |= BIT(7);
895  e.SendFlags |= 32;
896 }
897 
898 void WaypointSprite_HelpMePing(entity e)
899 {
900  WaypointSprite_Ping(e);
901  e.waypointsprite_helpmetime = time + waypointsprite_deployed_lifetime;
902  e.SendFlags |= 32;
903 }
904 
905 void WaypointSprite_FadeOutIn(entity e, float t)
906 {
907  if (!e.fade_time)
908  {
909  e.fade_time = t;
910  e.teleport_time = time + t;
911  }
912  else if (t < (e.teleport_time - time))
913  {
914  // accelerate the waypoint's dying
915  // ensure:
916  // (e.teleport_time - time) / wp.fade_time stays
917  // e.teleport_time = time + fadetime
918  float current_fadetime = e.teleport_time - time;
919  e.teleport_time = time + t;
920  if (e.fade_time < 0)
921  e.fade_time = -e.fade_time;
922  e.fade_time = e.fade_time * t / current_fadetime;
923  }
924 
925  e.SendFlags |= 16;
926 }
927 
928 void WaypointSprite_Init()
929 {
930  waypointsprite_limitedrange = autocvar_sv_waypointsprite_limitedrange;
931  waypointsprite_deployed_lifetime = autocvar_sv_waypointsprite_deployed_lifetime;
932  waypointsprite_deadlifetime = autocvar_sv_waypointsprite_deadlifetime;
933 }
934 
935 void WaypointSprite_Kill(entity wp)
936 {
937  if (!wp) return;
938  if (wp.owner) wp.owner.(wp.owned_by_field) = NULL;
939  delete(wp);
940 }
941 
942 void WaypointSprite_Disown(entity wp, float fadetime)
943 {
944  if (!wp) return;
945  if (wp.classname != "sprite_waypoint")
946  {
947  backtrace("Trying to disown a non-waypointsprite");
948  return;
949  }
950  if (wp.owner)
951  {
952  if (wp.exteriormodeltoclient == wp.owner)
953  wp.exteriormodeltoclient = NULL;
954  wp.owner.(wp.owned_by_field) = NULL;
955  wp.owner = NULL;
956 
957  WaypointSprite_FadeOutIn(wp, fadetime);
958  }
959 }
960 
961 void WaypointSprite_Think(entity this)
962 {
963  bool doremove = false;
964 
965  if (this.fade_time && time >= this.teleport_time)
966  {
967  doremove = true;
968  }
969 
970  if (this.exteriormodeltoclient)
971  WaypointSprite_UpdateOrigin(this, this.exteriormodeltoclient.origin + this.view_ofs);
972 
973  if (doremove)
974  WaypointSprite_Kill(this);
975  else
976  this.nextthink = time; // WHY?!?
977 }
978 
979 bool WaypointSprite_visible_for_player(entity this, entity player, entity view)
980 {
981  // personal waypoints
982  if (this.enemy && this.enemy != view)
983  return false;
984 
985  // team waypoints
986  if (this.rule == SPRITERULE_SPECTATOR)
987  {
988  if (!autocvar_sv_itemstime)
989  return false;
990  if (!warmup_stage && IS_PLAYER(view) && autocvar_sv_itemstime != 2)
991  return false;
992  }
993  else if (this.team && this.rule == SPRITERULE_DEFAULT)
994  {
995  if (this.team != view.team)
996  return false;
997  if (!IS_PLAYER(view))
998  return false;
999  }
1000 
1001  return true;
1002 }
1003 
1004 entity WaypointSprite_getviewentity(entity e)
1005 {
1006  if (IS_SPEC(e)) e = e.enemy;
1007  /* TODO idea (check this breaks nothing)
1008  else if (e.classname == "observer")
1009  e = NULL;
1010  */
1011  return e;
1012 }
1013 
1014 float WaypointSprite_isteammate(entity e, entity e2)
1015 {
1016  if (teamplay)
1017  return e2.team == e.team;
1018  return e2 == e;
1019 }
1020 
1021 bool WaypointSprite_Customize(entity this, entity client)
1022 {
1023  // this is not in SendEntity because it shall run every frame, not just every update
1024 
1025  // make spectators see what the player would see
1026  entity e = WaypointSprite_getviewentity(client);
1027 
1028  if (MUTATOR_CALLHOOK(CustomizeWaypoint, this, client))
1029  return false;
1030 
1031  return this.waypointsprite_visible_for_player(this, client, e);
1032 }
1033 
1034 bool WaypointSprite_SendEntity(entity this, entity to, float sendflags);
1035 
1036 void WaypointSprite_Reset(entity this)
1037 {
1038  // if a WP wants to time out, let it time out immediately; other WPs ought to be reset/killed by their owners
1039 
1040  if (this.fade_time)
1041  WaypointSprite_Kill(this);
1042 }
1043 
1044 entity WaypointSprite_Spawn(
1045  entity spr, // sprite
1046  float _lifetime, float maxdistance, // lifetime, max distance
1047  entity ref, vector ofs, // position
1048  entity showto, float t, // show to whom? Use a flag to indicate a team
1049  entity own, .entity ownfield, // remove when own gets killed
1050  float hideable, // true when it should be controlled by cl_hidewaypoints
1051  entity icon // initial icon
1052 )
1053 {
1054  entity wp = new(sprite_waypoint);
1055  wp.fade_time = _lifetime; // if negative tells client not to fade it out
1056  if(_lifetime < 0)
1057  _lifetime = -_lifetime;
1058  wp.teleport_time = time + _lifetime;
1059  wp.exteriormodeltoclient = ref;
1060  if (ref)
1061  {
1062  wp.view_ofs = ofs;
1063  setorigin(wp, ref.origin + ofs);
1064  }
1065  else
1066  setorigin(wp, ofs);
1067  wp.enemy = showto;
1068  wp.team = t;
1069  wp.owner = own;
1070  wp.currentammo = hideable;
1071  if (own)
1072  {
1073  if (own.(ownfield))
1074  delete(own.(ownfield));
1075  own.(ownfield) = wp;
1076  wp.owned_by_field = ownfield;
1077  }
1078  wp.fade_rate = maxdistance;
1079  setthink(wp, WaypointSprite_Think);
1080  wp.nextthink = time;
1081  wp.model1 = spr.netname;
1082  setcefc(wp, WaypointSprite_Customize);
1083  wp.waypointsprite_visible_for_player = WaypointSprite_visible_for_player;
1084  wp.reset2 = WaypointSprite_Reset;
1085  wp.cnt = icon.m_id;
1086  wp.colormod = spr.m_color;
1087  Net_LinkEntity(wp, false, 0, WaypointSprite_SendEntity);
1088  return wp;
1089 }
1090 
1091 entity WaypointSprite_SpawnFixed(
1092  entity spr,
1093  vector ofs,
1094  entity own,
1095  .entity ownfield,
1096  entity icon // initial icon
1097 )
1098 {
1099  return WaypointSprite_Spawn(spr, 0, 0, NULL, ofs, NULL, 0, own, ownfield, true, icon);
1100 }
1101 
1102 entity WaypointSprite_DeployFixed(
1103  entity spr,
1104  bool limited_range,
1105  entity player,
1106  vector ofs,
1107  entity icon // initial icon
1108 )
1109 {
1110  float t;
1111  if (teamplay)
1112  t = player.team;
1113  else
1114  t = 0;
1115  float maxdistance;
1116  if (limited_range)
1117  maxdistance = waypointsprite_limitedrange;
1118  else
1119  maxdistance = 0;
1120  return WaypointSprite_Spawn(spr, waypointsprite_deployed_lifetime, maxdistance, NULL, ofs, NULL, t, player, waypointsprite_deployed_fixed, false, icon);
1121 }
1122 
1123 entity WaypointSprite_DeployPersonal(
1124  entity spr,
1125  entity player,
1126  vector ofs,
1127  entity icon // initial icon
1128 )
1129 {
1130  return WaypointSprite_Spawn(spr, 0, 0, NULL, ofs, NULL, 0, player, waypointsprite_deployed_personal, false, icon);
1131 }
1132 
1133 entity WaypointSprite_Attach(
1134  entity spr,
1135  entity player,
1136  bool limited_range,
1137  entity icon // initial icon
1138 )
1139 {
1140  float t;
1141  if (player.waypointsprite_attachedforcarrier)
1142  return NULL; // can't attach to FC
1143  if (teamplay)
1144  t = player.team;
1145  else
1146  t = 0;
1147  float maxdistance;
1148  if (limited_range)
1149  maxdistance = waypointsprite_limitedrange;
1150  else
1151  maxdistance = 0;
1152  return WaypointSprite_Spawn(spr, waypointsprite_deployed_lifetime, maxdistance, player, '0 0 64', NULL, t, player, waypointsprite_attached, false, icon);
1153 }
1154 
1155 entity WaypointSprite_AttachCarrier(
1156  entity spr,
1157  entity carrier,
1158  entity icon // initial icon and color
1159 )
1160 {
1161  WaypointSprite_Kill(carrier.waypointsprite_attached); // FC overrides attached
1162  entity e = WaypointSprite_Spawn(spr, 0, 0, carrier, '0 0 64', NULL, carrier.team, carrier, waypointsprite_attachedforcarrier, false, icon);
1163  if (GetResource(carrier, RES_HEALTH))
1164  {
1165  WaypointSprite_UpdateMaxHealth(e, 2 * healtharmor_maxdamage(start_health, start_armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON.m_id).x);
1166  WaypointSprite_UpdateHealth(e, healtharmor_maxdamage(GetResource(carrier, RES_HEALTH), GetResource(carrier, RES_ARMOR), autocvar_g_balance_armor_blockpercent, DEATH_WEAPON.m_id).x);
1167  }
1168  return e;
1169 }
1170 
1171 void WaypointSprite_DetachCarrier(entity carrier)
1172 {
1173  WaypointSprite_Disown(carrier.waypointsprite_attachedforcarrier, waypointsprite_deadlifetime);
1174 }
1175 
1176 void WaypointSprite_ClearPersonal(entity this)
1177 {
1178  WaypointSprite_Kill(this.waypointsprite_deployed_personal);
1179 }
1180 
1181 void WaypointSprite_ClearOwned(entity this)
1182 {
1183  WaypointSprite_Kill(this.waypointsprite_deployed_fixed);
1184  WaypointSprite_Kill(this.waypointsprite_deployed_personal);
1185  WaypointSprite_Kill(this.waypointsprite_attached);
1186 }
1187 
1188 void WaypointSprite_PlayerDead(entity this)
1189 {
1190  WaypointSprite_Disown(this.waypointsprite_attached, waypointsprite_deadlifetime);
1191  WaypointSprite_DetachCarrier(this);
1192 }
1193 
1194 void WaypointSprite_PlayerGone(entity this)
1195 {
1196  WaypointSprite_Disown(this.waypointsprite_deployed_fixed, waypointsprite_deadlifetime);
1197  WaypointSprite_Kill(this.waypointsprite_deployed_personal);
1198  WaypointSprite_Disown(this.waypointsprite_attached, waypointsprite_deadlifetime);
1199  WaypointSprite_DetachCarrier(this);
1200 }
1201 #endif
const int SPRITERULE_SPECTATOR
float vid_conheight
const int MAX_TEAMRADAR_TIMES
Definition: teamradar.qh:3
void InterpolateOrigin_Note(entity this)
Definition: interpolate.qc:37
ERASEABLE void db_put(int db, string key, string value)
Definition: map.qh:101
#define draw_endBoldFont()
Definition: draw.qh:5
float alpha
Definition: items.qc:14
const int NUM_SPECTATOR
Definition: teams.qh:23
string string_null
Definition: nil.qh:9
#define REGISTER_NET_LINKED(id)
Definition: net.qh:67
int iflags
Definition: interpolate.qh:26
vector project_3d_to_2d(vector vec)
Definition: view.qc:359
const vector eY
Definition: vector.qh:45
void InterpolateOrigin_Undo(entity this)
snap origin to iorigin2 (actual origin)
Definition: interpolate.qc:159
vector colormod
Definition: powerups.qc:21
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 ReadString
float currentammo
Definition: progsdefs.qc:142
const int SPRITERULE_DEFAULT
float autocvar_hud_panel_fg_alpha
Definition: hud.qh:199
int team
Definition: main.qh:157
#define stringwidth
Definition: csprogsdefs.qh:29
#define draw_beginBoldFont()
Definition: draw.qh:4
float teleport_time
Definition: player.qh:212
fade_rate
Definition: projectile.qh:14
entity() spawn
#define REGISTRY_GET(id, i)
Definition: registry.qh:43
vector view_origin
Definition: main.qh:93
bool warmup_stage
Definition: main.qh:103
string netname
Definition: powerups.qc:20
#define NET_HANDLE(id, param)
Definition: net.qh:12
#define STATIC_INIT(func)
during worldspawn
Definition: static.qh:32
entity to
Definition: self.qh:96
origin
Definition: ent_cs.qc:114
int tempdb
Definition: main.qh:175
vector size
Definition: csprogsdefs.qc:114
float vid_conwidth
float spawnflags
Definition: progsdefs.qc:191
entity owner
Definition: main.qh:73
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1
Definition: all.inc:654
#define strcpy(this, s)
Definition: string.qh:49
const int SPRITERULE_TEAMPLAY
RES_HEALTH
Definition: ent_cs.qc:126
const float DRAWFLAG_ADDITIVE
Definition: csprogsdefs.qc:318
#define IS_SPEC(v)
Definition: utils.qh:10
string hud_skin_path
Definition: hud.qh:133
float autocvar__menu_alpha
Definition: hud.qh:184
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition: bits.qh:8
float lifetime
Definition: powerups.qc:23
entity enemy
Definition: sv_ctf.qh:143
entity exteriormodeltoclient
spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2 f1 f1points f2
Definition: all.inc:348
float cnt
Definition: powerups.qc:24
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
int wp_extra
Additional networked waypoint state, used for items, weapons, buffs.
#define LOG_INFOF(...)
Definition: log.qh:71
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
vector mi_scale
Definition: main.qh:25
#define NULL
Definition: post.qh:17
const float DRAWFLAG_NORMAL
Definition: csprogsdefs.qc:317
float max_health
#define backtrace(msg)
Definition: log.qh:105
const float M_SQRT2
Definition: mathlib.qh:114
#define strstrofs
Definition: dpextensions.qh:42
ERASEABLE string db_get(int db, string key)
Definition: map.qh:91
float teamplay
Definition: progsdefs.qc:31
#define M_ARGV(x, type)
Definition: events.qh:17
float nextthink
Definition: csprogsdefs.qc:121
float race_mycheckpointtime
Definition: racetimer.qh:31
vector(float skel, float bonenum) _skel_get_boneabs_hidden
const float M_PI
Definition: csprogsdefs.qc:269
float race_checkpointtime
Definition: racetimer.qh:11
const int IFLAG_ORIGIN
Definition: interpolate.qh:36
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
Definition: cl_resources.qc:10
float pain_finished
#define get_monsterinfo(i)
Definition: all.qh:6
float start_health
Definition: world.qh:98
const vector eX
Definition: vector.qh:44
float fade_time
Definition: common.qh:22
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
REGISTER_MUTATOR(waypointsprites, true)
entity int sendflags
Definition: self.qh:96
setorigin(ent, v)
#define setthink(e, f)
ERASEABLE vector Rotate(vector v, float a)
Definition: vector.qh:105
#define strfree(this)
Definition: string.qh:56
float servertime
Definition: main.qh:36
float autocvar_g_balance_armor_blockpercent
Definition: damage.qh:21
float spawntime
Definition: items.qh:15
float time
Definition: csprogsdefs.qc:16
float start_armorvalue
Definition: world.qh:99
IntrusiveList g_radaricons
Definition: main.qh:80
#define FOREACH(list, cond, body)
Definition: iter.qh:19
void InterpolateOrigin_Do(entity this)
set origin based on iorigin1 (old pos), iorigin2 (desired pos), and time
Definition: interpolate.qc:129
float player_localnum
Definition: csprogsdefs.qc:20
#define IS_PLAYER(v)
Definition: utils.qh:9
#define BITS(n)
Definition: bits.qh:9
const int WEP_FLAG_SUPERWEAPON
Definition: weapon.qh:202
IntrusiveList g_drawables_2d
Definition: main.qh:78