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