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;
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
65 return;
66
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
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)
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 {
126 txt = sprintf(_("%s under attack!"), txt);
127 }
128 else
129 a *= spritelookupblinkvalue(this, spriteimage);
130 }
131
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
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)),
160
161 float crosshairdistance = sqrt( ((o.x - vid_conwidth/2) ** 2) + ((o.y - vid_conheight/2) ** 2) );
162
165
166 {
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);
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 {
189 }
190 if(draw_healthbar)
191 {
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,
202 0,
203 rgb,
205 rgb,
208 );
209 }
210}
211
212void 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.m_name;
220
221 setorigin(this, this.origin);
222 _setmodel(this, tur.model);
223 _setmodel(this.tur_head, tur.head_model);
224 this.solid = SOLID_BBOX; // before setsize so it will be linked to the area grid
225 this.tur_head.solid = SOLID_NOT;
226 setsize(this, tur.m_mins, tur.m_maxs);
227 setsize(this.tur_head, '0 0 0', '0 0 0');
228
229 if(this.m_id == TUR_EWHEEL.m_id)
230 setattachment(this.tur_head, this, "");
231 else
232 setattachment(this.tur_head, this, "tag_head");
233
234 this.tur_head.classname = "turret_head";
235 this.tur_head.owner = this;
238 this.tur_head.angles = this.angles;
239 SetResourceExplicit(this, RES_HEALTH, 255);
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;
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
261entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode);
262void turret_gibboom(entity this);
264{
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
294entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode)
295{
296 entity gib;
297
298 traceline(_from, _to, MOVE_NOMONSTERS, NULL);
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
330{
331 sound (this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
332 pointparticles(EFFECT_ROCKET_EXPLODE, this.origin, '0 0 0', 1);
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
368NET_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}
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:59
void turret_construct(entity this, bool isnew)
void turret_gibboom(entity this)
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
int spawnflags
Definition ammo.qh:15
#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
angles_y
Definition ent_cs.qc:119
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:348
#define ReadVector()
Definition net.qh:367
#define ReadAngleVector2D()
Definition net.qh:370
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:121
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:187
const int TNSF_AVEL
Definition turret.qh:188
const int TNSF_SETUP
Definition turret.qh:186
const int TNSF_MOVE
Definition turret.qh:189
const int TNSF_ANIM
Definition turret.qh:191
const int TNSF_STATUS
Definition turret.qh:185
const int TUR_FLAG_MOVE
Definition turret.qh:150
#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