Xonotic
cl_turrets.qc
Go to the documentation of this file.
1 #include "cl_turrets.qh"
2 
3 void turret_remove(entity this)
4 {
5  delete(this.tur_head);
6  //remove(this.enemy);
7  this.tur_head = NULL;
8 }
9 
10 .vector glowmod;
12 {
13  this.glowmod = Team_ColorRGB(this.team - 1) * 2;
14  this.teamradar_color = Team_ColorRGB(this.team - 1);
15 
16  if(this.team)
17  this.colormap = 1024 + (this.team - 1) * 17;
18 
19  this.tur_head.colormap = this.colormap;
20  this.tur_head.glowmod = this.glowmod;
21 
22 }
23 
24 // unused?
26 {
27  this.drawmask = MASK_NORMAL;
28 }
29 
30 void turret_draw(entity this)
31 {
32  float dt;
33 
34  dt = time - this.move_time;
35  this.move_time = time;
36  if(dt <= 0)
37  return;
38 
39  this.tur_head.angles += dt * this.tur_head.avelocity;
40 
41  if (GetResource(this, RES_HEALTH) < 127)
42  {
43  dt = random();
44 
45  if(dt < 0.03)
46  te_spark(this.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
47  }
48 
49  if(GetResource(this, RES_HEALTH) < 85)
50  if(dt < 0.01)
51  pointparticles(EFFECT_SMOKE_LARGE, (this.origin + (randomvec() * 80)), '0 0 0', 1);
52 
53  if(GetResource(this, RES_HEALTH) < 32)
54  if(dt < 0.015)
55  pointparticles(EFFECT_SMOKE_SMALL, (this.origin + (randomvec() * 80)), '0 0 0', 1);
56 
57 }
58 
60 {
61  if(this.netname == "")
62  return;
63 
64  if(!autocvar_g_waypointsprite_turrets)
65  return;
66 
67  if(autocvar_cl_hidewaypoints)
68  return;
69 
70  float dist = vlen(this.origin - view_origin);
71  float t = (entcs_GetTeam(player_localnum) + 1);
72 
73  vector o;
74  string txt;
75 
77  if(dist < 10240 && t != this.team)
78  {
79  // TODO: Vehicle tactical hud
80  o = project_3d_to_2d(this.origin + '0 0 32');
81  if(o_z < 0
82  || o_x < (vid_conwidth * waypointsprite_edgeoffset_left)
83  || o_y < (vid_conheight * waypointsprite_edgeoffset_top)
84  || o_x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))
85  || o_y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
86  return; // Dont draw wp's for turrets out of view
87  o_z = 0;
88  if(hud != HUD_NORMAL)
89  {
91  txt = "gfx/vehicles/turret_moving";
92  else
93  txt = "gfx/vehicles/turret_stationary";
94 
96  drawpic(o - pz * 0.5, txt, pz , '1 1 1', 0.7, DRAWFLAG_NORMAL);
97  }
98  }
99 
100  if(dist > this.maxdistance)
101  return;
102 
103  string spriteimage = this.netname;
104  float a = this.alpha * autocvar_hud_panel_fg_alpha;
105  vector rgb = spritelookupcolor(this, spriteimage, this.teamradar_color);
106 
107 
108  if(this.maxdistance > waypointsprite_normdistance)
109  a *= (bound(0, (this.maxdistance - dist) / (this.maxdistance - waypointsprite_normdistance), 1) ** waypointsprite_distancealphaexponent);
110  else if(this.maxdistance > 0)
111  a *= (bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1) ** waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
112 
113  if(rgb == '0 0 0')
114  {
115  this.teamradar_color = '1 0 1';
116  LOG_INFOF("WARNING: sprite of name %s has no color, using pink so you notice it", spriteimage);
117  }
118 
119  txt = spritelookuptext(this, spriteimage);
120 
121  if(time - floor(time) > 0.5 && t == this.team)
122  {
123  if(this.helpme && time < this.helpme)
124  {
125  a *= SPRITE_HELPME_BLINK;
126  txt = sprintf(_("%s under attack!"), txt);
127  }
128  else
129  a *= spritelookupblinkvalue(this, spriteimage);
130  }
131 
132  if(autocvar_g_waypointsprite_uppercase)
133  txt = strtoupper(txt);
134 
135  if(a > 1)
136  {
137  rgb *= a;
138  a = 1;
139  }
140 
141  if(a <= 0)
142  return;
143 
144  rgb = fixrgbexcess(rgb);
145 
146  o = project_3d_to_2d(this.origin + '0 0 64');
147  if(o_z < 0
148  || o_x < (vid_conwidth * waypointsprite_edgeoffset_left)
149  || o_y < (vid_conheight * waypointsprite_edgeoffset_top)
150  || o_x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))
151  || o_y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
152  return; // Dont draw wp's for turrets out of view
153 
154  o_z = 0;
155 
156  float edgedistance_min = min((o.y - (vid_conheight * waypointsprite_edgeoffset_top)),
157  (o_x - (vid_conwidth * waypointsprite_edgeoffset_left)),
158  (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) - o_x,
159  (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)) - o_y);
160 
161  float crosshairdistance = sqrt( ((o.x - vid_conwidth/2) ** 2) + ((o.y - vid_conheight/2) ** 2) );
162 
163  t = waypointsprite_scale;
164  a *= waypointsprite_alpha;
165 
166  {
167  a = a * (1 - (1 - waypointsprite_distancefadealpha) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
168  t = t * (1 - (1 - waypointsprite_distancefadescale) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
169  }
170  if (edgedistance_min < waypointsprite_edgefadedistance) {
171  a = a * (1 - (1 - waypointsprite_edgefadealpha) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
172  t = t * (1 - (1 - waypointsprite_edgefadescale) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
173  }
174  if(crosshairdistance < waypointsprite_crosshairfadedistance) {
175  a = a * (1 - (1 - waypointsprite_crosshairfadealpha) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
176  t = t * (1 - (1 - waypointsprite_crosshairfadescale) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
177  }
178 
179  bool draw_healthbar = ((this.helpme && time < this.helpme) || !autocvar_g_waypointsprite_turrets_onlyhurt || hud != HUD_NORMAL);
180  bool draw_text = autocvar_g_waypointsprite_turrets_text;
181 
182  if(draw_healthbar || draw_text) // make sure it's actually being drawn
183  {
184  o = drawspritearrow(o, M_PI, rgb, a, SPRITE_ARROW_SCALE * t);
185  }
186  if(draw_text)
187  {
188  o = drawsprite_TextOrIcon(true, o, M_PI, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
189  }
190  if(draw_healthbar)
191  {
192  drawhealthbar(
193  o,
194  0,
195  GetResource(this, RES_HEALTH) / 255,
196  '0 0 0',
197  '0 0 0',
198  0.5 * SPRITE_HEALTHBAR_WIDTH * t,
199  0.5 * SPRITE_HEALTHBAR_HEIGHT * t,
200  SPRITE_HEALTHBAR_MARGIN * t + 0.5 * waypointsprite_fontsize,
201  SPRITE_HEALTHBAR_BORDER * t,
202  0,
203  rgb,
204  a * SPRITE_HEALTHBAR_BORDERALPHA,
205  rgb,
206  a * SPRITE_HEALTHBAR_HEALTHALPHA,
208  );
209  }
210 }
211 
212 void turret_construct(entity this, bool isnew)
213 {
214  entity tur = get_turretinfo(this.m_id);
215 
216  if(this.tur_head == NULL)
217  this.tur_head = spawn();
218 
219  this.netname = tur.turret_name;
220 
221  setorigin(this, this.origin);
222  _setmodel(this, tur.model);
223  _setmodel(this.tur_head, tur.head_model);
224  setsize(this, tur.m_mins, tur.m_maxs);
225  setsize(this.tur_head, '0 0 0', '0 0 0');
226 
227  if(this.m_id == TUR_EWHEEL.m_id)
228  setattachment(this.tur_head, this, "");
229  else
230  setattachment(this.tur_head, this, "tag_head");
231 
232  this.tur_head.classname = "turret_head";
233  this.tur_head.owner = this;
236  this.tur_head.angles = this.angles;
237  SetResourceExplicit(this, RES_HEALTH, 255);
238  this.solid = SOLID_BBOX;
239  this.tur_head.solid = SOLID_NOT;
242  this.draw = turret_draw;
243  this.entremove = turret_remove;
244  this.drawmask = MASK_NORMAL;
245  this.tur_head.drawmask = MASK_NORMAL;
246  this.anim_start_time = 0;
247  this.draw2d = turret_draw2d;
248  this.maxdistance = autocvar_g_waypointsprite_turrets_maxdist;
249  this.teamradar_color = '1 0 0';
250  this.alpha = 1;
251 
252  if(isnew)
253  {
254  IL_PUSH(g_drawables, this);
255  IL_PUSH(g_drawables_2d, this);
256  }
257 
258  tur.tr_setup(tur, this);
259 }
260 
261 entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode);
262 void turret_gibboom(entity this);
264 {
265  Movetype_Physics_MatchTicrate(this, autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
266 
267  this.drawmask = MASK_NORMAL;
268 
269  if(this.cnt)
270  {
271  if(time >= this.nextthink)
272  {
273  turret_gibboom(this);
274  delete(this);
275  }
276  }
277  else
278  {
279  this.alpha = bound(0, this.nextthink - time, 1);
280  if(this.alpha < ALPHA_MIN_VISIBLE)
281  delete(this);
282  }
283 }
284 
286 {
287  sound (this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
288  pointparticles(EFFECT_ROCKET_EXPLODE, this.origin, '0 0 0', 1);
289 
290  for (int j = 1; j < 5; j = j + 1)
291  turret_gibtoss(strcat("models/turrets/head-gib", ftos(j), ".md3"), this.origin + '0 0 2', this.velocity + randomvec() * 700, '0 0 0', false);
292 }
293 
294 entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode)
295 {
296  entity gib;
297 
298  traceline(_from, _to, MOVE_NOMONSTERS, NULL);
299  if(trace_startsolid)
300  return NULL;
301 
302  gib = new(turret_gib);
303  setorigin(gib, _from);
304  _setmodel(gib, _model);
305  gib.colormod = _cmod;
306  gib.solid = SOLID_CORPSE;
307  gib.draw = turret_gib_draw;
308  gib.cnt = _explode;
309  setsize(gib, '-1 -1 -1', '1 1 1');
310  if(_explode)
311  {
312  gib.nextthink = time + 0.2 * (autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15));
313  gib.effects = EF_FLAME;
314  }
315  else
316  gib.nextthink = time + autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15);
317 
318  gib.gravity = 1;
320  setorigin(gib, _from);
321  gib.velocity = _to;
322  gib.avelocity = prandomvec() * 32;
323  gib.move_time = time;
324  gib.damageforcescale = 1;
325 
326  return gib;
327 }
328 
329 void turret_die(entity this)
330 {
331  sound (this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
332  pointparticles(EFFECT_ROCKET_EXPLODE, this.origin, '0 0 0', 1);
333  if (!autocvar_cl_nogibs)
334  {
335  // Base
336  if(this.m_id == TUR_EWHEEL.m_id)
337  turret_gibtoss((get_turretinfo(this.m_id)).model, this.origin + '0 0 18', this.velocity + '0 0 400' + '0.1 0.1 1' * (random() * 400), '-1 -1 -1', true);
338  else if (this.m_id == TUR_WALKER.m_id)
339  turret_gibtoss((get_turretinfo(this.m_id)).model, this.origin + '0 0 18', this.velocity + '0 0 300' + '0.1 0.1 1' * (random() * 200), '-1 -1 -1', true);
340  else if (this.m_id == TUR_TESLA.m_id)
341  turret_gibtoss((get_turretinfo(this.m_id)).model, this.origin + '0 0 18', '0 0 200', '-1 -1 -1', false);
342  else
343  {
344  if (random() > 0.5)
345  {
346  turret_gibtoss("models/turrets/base-gib2.md3", this.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', false);
347  turret_gibtoss("models/turrets/base-gib3.md3", this.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', false);
348  turret_gibtoss("models/turrets/base-gib4.md3", this.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', false);
349  }
350  else
351  turret_gibtoss("models/turrets/base-gib1.md3", this.origin + '0 0 8', '0 0 0', '0 0 0', true);
352 
353  entity headgib = turret_gibtoss((get_turretinfo(this.m_id)).head_model, this.origin + '0 0 32', '0 0 200' + randomvec() * 200, '-1 -1 -1', true);
354  if(headgib)
355  {
356  headgib.angles = this.tur_head.angles;
357  headgib.avelocity = this.tur_head.avelocity + randomvec() * 45;
358  headgib.avelocity_y = headgib.avelocity_y * 5;
359  headgib.gravity = 0.5;
360  }
361  }
362  }
363 
364  setmodel(this, MDL_Null);
365  setmodel(this.tur_head, MDL_Null);
366 }
367 
368 NET_HANDLE(ENT_CLIENT_TURRET, bool isnew)
369 {
370  float sf;
371  sf = ReadByte();
372 
373  if(sf & TNSF_SETUP)
374  {
375  this.m_id = ReadByte();
376 
377  this.origin = ReadVector();
378  setorigin(this, this.origin);
379 
380  this.angles = ReadAngleVector2D();
381 
382  turret_construct(this, isnew);
383  this.colormap = 1024;
384  this.glowmod = '0 1 1';
385  this.tur_head.colormap = this.colormap;
386  this.tur_head.glowmod = this.glowmod;
387  }
388 
389  if(sf & TNSF_ANG)
390  {
391  if(this.tur_head == NULL) // aparenly this can happpen before TNSF_SETUP. great.
392  this.tur_head = spawn();
393 
394  this.tur_head.angles_x = ReadShort();
395  this.tur_head.angles_y = ReadShort();
396  //this.tur_head.angles = this.angles + this.tur_head.angles;
397  }
398 
399  if(sf & TNSF_AVEL)
400  {
401  if(this.tur_head == NULL) // aparenly this can happpen before TNSF_SETUP. great.
402  this.tur_head = spawn();
403 
404  this.tur_head.avelocity_x = ReadShort();
405  this.tur_head.avelocity_y = ReadShort();
406  }
407 
408  if(sf & TNSF_MOVE)
409  {
410  this.origin = ReadVector();
411  setorigin(this, this.origin);
412 
413  this.velocity = ReadVector();
414 
415  this.angles_y = ReadShort();
416 
417  this.move_time = time;
418  }
419 
420  if(sf & TNSF_ANIM)
421  {
422  this.frame1time = ReadCoord();
423  this.frame = ReadByte();
424  }
425 
426  if(sf & TNSF_STATUS)
427  {
428  float _tmp;
429  _tmp = ReadByte();
430  if(_tmp != this.team)
431  {
432  this.team = _tmp;
433  turret_changeteam(this);
434  }
435 
436  _tmp = ReadByte();
437  float myhp = GetResource(this, RES_HEALTH);
438  if(_tmp == 0 && myhp != 0)
439  turret_die(this);
440  else if(myhp && myhp > _tmp)
441  this.helpme = servertime + 10;
442  else if(myhp && myhp < _tmp)
443  this.helpme = 0; // we're being healed, don't spam help me waypoints
444 
445  SetResourceExplicit(this, RES_HEALTH, _tmp);
446  }
447  return true;
448 }
const float SOLID_NOT
Definition: csprogsdefs.qc:244
vector glowmod
Definition: cl_turrets.qc:10
float vid_conheight
#define get_turretinfo(i)
Definition: all.qh:9
const float ALPHA_MIN_VISIBLE
Definition: main.qh:128
float colormap
Definition: csprogsdefs.qc:131
float alpha
Definition: items.qc:14
NET_HANDLE(ENT_CLIENT_TURRET, bool isnew)
Definition: cl_turrets.qc:368
vector project_3d_to_2d(vector vec)
Definition: view.qc:359
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
const int TNSF_STATUS
Definition: turret.qh:168
const float EF_FLAME
Definition: csprogsdefs.qc:302
const int TNSF_ANIM
Definition: turret.qh:174
float autocvar_hud_panel_fg_alpha
Definition: hud.qh:199
int team
Definition: main.qh:157
void turret_head_draw(entity this)
Definition: cl_turrets.qc:25
vector Team_ColorRGB(int teamid)
Definition: teams.qh:76
entity tur_head
Definition: sv_turrets.qh:29
void turret_gibboom(entity this)
Definition: cl_turrets.qc:285
entity() spawn
float prandom()
Definition: random.qc:100
vector view_origin
Definition: main.qh:93
void turret_draw(entity this)
Definition: cl_turrets.qc:30
void turret_changeteam(entity this)
Definition: cl_turrets.qc:11
string netname
Definition: powerups.qc:20
bool autocvar_cl_vehicles_hud_tactical
Definition: cl_vehicles.qh:4
origin
Definition: ent_cs.qc:114
void turret_remove(entity this)
Definition: cl_turrets.qc:3
float MOVETYPE_BOUNCE
Definition: progsdefs.qc:256
float vid_conwidth
entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode)
Definition: cl_turrets.qc:294
float spawnflags
Definition: progsdefs.qc:191
vector drawgetimagesize(string pic)
const int TNSF_AVEL
Definition: turret.qh:171
string model
Definition: csprogsdefs.qc:108
#define setmodel(this, m)
Definition: model.qh:26
RES_HEALTH
Definition: ent_cs.qc:126
void turret_construct(entity this, bool isnew)
Definition: cl_turrets.qc:212
int m_id
Definition: effect.qh:19
const float MOVE_NOMONSTERS
Definition: csprogsdefs.qc:253
float cnt
Definition: powerups.qc:24
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy)
Definition: movetypes.qc:869
#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"))
#define pointparticles
Definition: csprogsdefs.qh:13
#define NULL
Definition: post.qh:17
const float DRAWFLAG_NORMAL
Definition: csprogsdefs.qc:317
float anim_start_time
Definition: turret.qh:173
const float VOL_BASE
Definition: sound.qh:36
const int TNSF_SETUP
Definition: turret.qh:169
const float MASK_NORMAL
Definition: csprogsdefs.qc:164
float drawmask
Definition: csprogsdefs.qc:95
const float ATTEN_NORM
Definition: sound.qh:30
float nextthink
Definition: csprogsdefs.qc:121
const int CH_SHOTS
Definition: sound.qh:14
void turret_draw2d(entity this)
Definition: cl_turrets.qc:59
vector(float skel, float bonenum) _skel_get_boneabs_hidden
const float M_PI
Definition: csprogsdefs.qc:269
float MOVETYPE_NOCLIP
Definition: progsdefs.qc:254
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
Definition: cl_resources.qc:10
float move_time
Definition: movetypes.qh:77
void turret_gib_draw(entity this)
Definition: cl_turrets.qc:263
vector prandomvec()
Definition: random.qc:113
const int TUR_FLAG_MOVE
Definition: turret.qh:133
const float SOLID_BBOX
Definition: csprogsdefs.qc:246
const int TNSF_ANG
Definition: turret.qh:170
float frame
primary framegroup animation (strength = 1 - lerpfrac - lerpfrac3 - lerpfrac4)
Definition: anim.qh:6
setorigin(ent, v)
vector angles
Definition: csprogsdefs.qc:104
void turret_die(entity this)
Definition: cl_turrets.qc:329
float trace_startsolid
Definition: csprogsdefs.qc:35
float servertime
Definition: main.qh:36
#define sound(e, c, s, v, a)
Definition: sound.qh:52
float time
Definition: csprogsdefs.qc:16
vector velocity
Definition: csprogsdefs.qc:103
const int TNSF_MOVE
Definition: turret.qh:172
float player_localnum
Definition: csprogsdefs.qc:20
IntrusiveList g_drawables
Definition: main.qh:77
void set_movetype(entity this, int mt)
float frame1time
start time of framegroup animation
Definition: anim.qh:22
float autocvar_cl_vehicles_crosshair_size
Definition: cl_vehicles.qh:7
IntrusiveList g_drawables_2d
Definition: main.qh:78
float solid
Definition: csprogsdefs.qc:99
const float SOLID_CORPSE
Definition: csprogsdefs.qc:249
int hud
Definition: main.qh:142