]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/client/tturrets.qc
Merge remote branch 'origin/master' into tzork/turrets-csqc
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / tturrets.qc
1 string tid2info_base;
2 string tid2info_head;
3 string tid2info_name;
4 vector  tid2info_min;
5 vector  tid2info_max;
6
7 void turrets_precache()
8 {
9     precache_model ("models/turrets/ewheel-base2.md3");
10     precache_model ("models/turrets/ewheel-gun1.md3");
11     precache_model ("models/turrets/base.md3");
12     precache_model ("models/turrets/flac.md3");
13     precache_model ("models/turrets/reactor.md3");
14     precache_model ("models/turrets/hellion.md3");
15     precache_model ("models/turrets/hk.md3");
16     precache_model ("models/turrets/machinegun.md3");
17     precache_model ("models/turrets/mlrs.md3");
18     precache_model ("models/turrets/phaser.md3");
19     precache_model ("models/turrets/phaser_beam.md3");
20     precache_model ("models/turrets/plasma.md3");
21     precache_model ("models/turrets/plasmad.md3");
22     precache_model ("models/turrets/tesla_head.md3");
23     precache_model ("models/turrets/tesla_base.md3");
24     precache_model ("models/turrets/walker_head_minigun.md3");
25     precache_model ("models/turrets/walker_body.md3");
26     precache_model ("models/turrets/rocket.md3");
27     
28     precache_sound ("turrets/phaser.wav");
29     precache_sound ("weapons/rocket_impact.wav");
30     precache_sound ("weapons/uzi_fire.wav");
31 }
32
33 void turret_tid2info(float _tid)
34 {
35     tid2info_base = "models/turrets/base.md3";
36     tid2info_min = '-32 -32 0';
37     tid2info_max = '32 32 64';
38
39     switch(_tid)
40     {
41         case TID_EWHEEL:
42             tid2info_base = "models/turrets/ewheel-base2.md3";
43             tid2info_head = "models/turrets/ewheel-gun1.md3";
44             tid2info_name = "eWheel";
45             break;
46         case TID_FLAC:
47             tid2info_head = "models/turrets/flac.md3";
48             tid2info_name = "Flac Cannon";
49             break;
50         case TID_FUSION:
51             tid2info_head = "models/turrets/reactor.md3";
52             tid2info_name = "Fusion Reactor";
53             tid2info_min = '-34 -34 0';
54             tid2info_max = '34 34 90';
55             break;
56         case TID_HELLION:
57             tid2info_head = "models/turrets/hellion.md3";
58             tid2info_name = "Hellion";
59             break;
60         case TID_HK:
61             tid2info_head = "models/turrets/hk.md3";
62             tid2info_name = "Hunter-Killer";
63             break;
64         case TID_MACHINEGUN:
65             tid2info_head = "models/turrets/machinegun.md3";
66             tid2info_name = "Machinegun";
67             break;
68         case TID_MLRS:
69             tid2info_head = "models/turrets/mlrs.md3";
70             tid2info_name = "MLRS";
71             break;
72         case TID_PHASER:
73             tid2info_head = "models/turrets/phaser.md3";
74             tid2info_name = "Phaser";
75             break;
76         case TID_PLASMA:
77             tid2info_head = "models/turrets/plasma.md3";
78             tid2info_name = "Plasma";
79             break;
80         case TID_PLASMA_DUAL:
81             tid2info_head = "models/turrets/plasmad.md3";
82             tid2info_name = "Dual Plasma";
83             break;
84         case TID_TESLA:
85             tid2info_base = "models/turrets/tesla_base.md3";
86             tid2info_head = "models/turrets/tesla_head.md3";
87             tid2info_name = "Tesla coil";
88             tid2info_min = '-60 -60 0';
89             tid2info_max  ='60 60 128';
90             break;
91         case TID_WALKER:
92             tid2info_base = "models/turrets/walker_body.md3";
93             tid2info_head = "models/turrets/walker_head_minigun.md3";
94             tid2info_name = "Walker";
95             tid2info_min = '-70 -70 0';
96             tid2info_max = '70 70 95';
97             break;
98     }    
99 }
100
101 void turret_remove()
102 {
103     turret_tid2info(self.turret_type);
104     dprint("Removing ", tid2info_name, " turrret.\n");
105     
106     remove(self.tur_head);
107     self.tur_head = world;    
108 }
109
110 void turret_changeteam()
111 {
112         self.colormod = '0 0 0';
113         
114         switch(self.team)
115         {
116         case COLOR_TEAM1: // Red
117             self.colormod = '2 0.5 0.5';
118             break;
119
120         case COLOR_TEAM2: // Blue
121             self.colormod = '0.5 0.5 2';
122             break;
123
124         case COLOR_TEAM3: // Yellow
125             self.colormod = '1.4 1.4 0.6';
126             break;
127
128         case COLOR_TEAM4: // Pink
129             self.colormod = '1.4 0.6 1.4';
130             break;
131         }
132         
133         self.tur_head.colormod = self.colormod;    
134 }
135
136 void turret_head_draw()
137 {    
138     self.drawmask = MASK_NORMAL;
139 }
140
141 void turret_draw()
142 {        
143     float dt;
144
145     self.drawmask = MASK_NORMAL;
146     
147     dt = time - self.move_time;
148     self.move_time = time;
149     if(dt <= 0)
150         return;
151     
152     self.tur_head.angles += dt * self.tur_head.move_avelocity;
153
154     if (self.health < 127)
155     if(random() < 0.25)
156         te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);    
157 }
158
159 void turret_moving_head_draw()
160 {        
161     self.drawmask = MASK_NORMAL;
162 }
163
164 void turret_moving_draw()
165 {        
166     float dt;
167
168     self.drawmask = MASK_NORMAL;
169         
170     dt = time - self.move_time;
171     self.move_time = time;
172     if(dt <= 0)
173         return;
174     
175     fixedmakevectors(self.angles);
176     movelib_groundalign4point(300, 100, 0.25);
177     
178     setorigin(self, self.origin + self.velocity * dt);
179     if(self.turret_type == TID_WALKER)
180         setorigin(self.tur_head, gettaginfo(self, gettagindex(self, "tag_head")));
181     else
182         setorigin(self.tur_head, self.origin);
183     self.tur_head.angles += dt * self.tur_head.move_avelocity;
184     
185     //self.angles_y += (self.move_angles_y - self.angles_y)* dt;
186     
187     if (self.health < 127)
188     if(random() < 0.25)
189         te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);    
190 }
191
192 void turret_construct()
193 {    
194     if(self.tur_head == world)
195         self.tur_head = spawn();
196     
197     turret_tid2info(self.turret_type);
198     dprint("Constructing ", tid2info_name , " turret (", ftos(self.turret_type), ")\n");
199
200     setorigin(self, self.origin);
201     setmodel(self, tid2info_base);
202     setmodel(self.tur_head, tid2info_head);
203     setsize(self, tid2info_min, tid2info_max);
204     setsize(self.tur_head, '0 0 0', '0 0 0');
205     setorigin(self.tur_head, gettaginfo(self, gettagindex(self, "tag_head")));
206
207     self.tur_head.classname     = "turret_head";
208     self.tur_head.owner         = self;
209     self.tur_head.move_movetype = MOVETYPE_NOCLIP;
210     self.move_movetype          = MOVETYPE_NOCLIP;
211     self.tur_head.angles        = self.angles;
212     self.health                 = 255;
213     self.solid                  = SOLID_BBOX;
214     self.tur_head.solid         = SOLID_NOT;
215     self.movetype               = MOVETYPE_NOCLIP;
216     self.tur_head.movetype      = MOVETYPE_NOCLIP;    
217     self.draw                   = turret_draw;
218     self.tur_head.draw          = turret_head_draw;
219     self.entremove              = turret_remove;
220
221     if(self.turret_type == TID_EWHEEL || self.turret_type == TID_WALKER)
222     {
223         self.gravity            = 1;
224         self.move_movetype      = MOVETYPE_BOUNCE;
225         self.move_origin        = self.origin;                
226         self.move_time          = time;        
227         self.draw               = turret_moving_draw;
228         self.tur_head.draw      = turret_moving_head_draw;
229     }
230 }
231
232 entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode);
233 void turret_gibboom();
234 void turret_gib_draw()
235 {
236     Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
237     
238     self.drawmask = MASK_NORMAL;
239         
240         if(self.cnt)
241         {
242             if(time >= self.nextthink)
243             {
244             turret_gibboom();
245             remove(self);
246             }
247         }
248         else
249         {
250         self.alpha = bound(0, self.nextthink - time, 1);
251         if(self.alpha < ALPHA_MIN_VISIBLE)
252             remove(self);           
253         }
254 }
255
256 void turret_gibboom()
257 {
258     float i;
259     
260     sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
261     pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
262
263     for (i = 1; i < 5; i = i + 1)
264         turret_gibtoss(strcat("models/turrets/head-gib", ftos(i), ".md3"), self.origin, self.velocity + randomvec() * 700, '0 0 0', FALSE);
265 }
266
267 entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode)
268 {
269     entity gib;
270
271     gib = spawn();
272     setorigin(gib, _from);
273     setmodel(gib, _model);
274     gib.colormod    = _cmod;
275         gib.solid       = SOLID_CORPSE;
276     gib.draw        = turret_gib_draw;    
277     gib.cnt         = _explode;
278     
279     if(_explode)
280     {
281         gib.nextthink = time + 0.2 * (autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15));
282         gib.effects = EF_FLAME;
283     }        
284     else
285         gib.nextthink = time + autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15);
286     
287     gib.gravity         = 1;
288         gib.move_movetype   = MOVETYPE_BOUNCE;
289         gib.move_origin     = gib.origin = _from;
290         gib.move_velocity   = _to;      
291         gib.move_avelocity  = prandomvec() * 32;
292         gib.move_time       = time;
293         gib.damageforcescale = 1;
294         
295         return gib;
296 }
297
298 void turret_die()
299 {    
300     entity headgib;
301     
302     setmodel(self, "");
303     setmodel(self.tur_head, "");
304     sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
305     pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
306     turret_tid2info(self.turret_type);
307     dprint("Turret ", tid2info_name, " dies.\n");
308     
309     // Base
310     if(self.turret_type == TID_EWHEEL)
311         turret_gibtoss(tid2info_base, self.origin, self.velocity, '-1 -1 -1', FALSE);
312     else if (self.turret_type == TID_WALKER)
313         turret_gibtoss(tid2info_base, self.origin, self.velocity, '-1 -1 -1', FALSE);
314     else if (self.turret_type == TID_TESLA)
315         turret_gibtoss(tid2info_base, self.origin, self.velocity, '-1 -1 -1', FALSE);
316     else
317     {        
318         if (random() > 0.5)
319         {
320             turret_gibtoss("models/turrets/base-gib2.md3", self.origin + '0 0 2', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
321             turret_gibtoss("models/turrets/base-gib3.md3", self.origin + '0 0 2', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
322             turret_gibtoss("models/turrets/base-gib4.md3", self.origin + '0 0 2', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
323         }
324         else
325             turret_gibtoss("models/turrets/base-gib1.md3", self.origin + '0 0 4', '0 0 0', '0 0 0', TRUE);
326     }
327     
328     headgib = turret_gibtoss(tid2info_head, self.origin + '0 0 32', '0 0 200' + randomvec() * 200, '-1 -1 -1', TRUE);
329     headgib.angles = headgib.move_angles = self.tur_head.angles;
330     headgib.avelocity = headgib.move_avelocity = self.tur_head.move_avelocity + randomvec() * 45;
331     headgib.avelocity_y = headgib.move_avelocity_y = headgib.move_avelocity_y * 5;
332     headgib.gravity = 0.5;
333 }
334
335 void ent_turret()
336 {
337     float sf;
338     sf = ReadByte();
339
340         if(sf & TNSF_SETUP)
341         {           
342             self.turret_type = ReadByte();
343                     
344             self.origin_x = ReadCoord();
345             self.origin_y = ReadCoord();
346             self.origin_z = ReadCoord();
347             
348             self.angles_x = ReadAngle();
349             self.angles_y = ReadAngle();
350             
351             turret_construct();
352     }
353     
354     if(sf & TNSF_ANG)
355     {
356         self.tur_head.move_angles_x = ReadShort();
357         self.tur_head.move_angles_y = ReadShort();
358         self.tur_head.angles = self.angles + self.tur_head.move_angles;
359     }
360     
361     if(sf & TNSF_AVEL)
362     {
363         self.tur_head.move_avelocity_x = ReadShort();
364         self.tur_head.move_avelocity_y = ReadShort();            
365     }
366     
367     if(sf & TNSF_MOVE)
368     {
369         self.origin_x = ReadShort();
370         self.origin_y = ReadShort();
371         self.origin_z = ReadShort();
372         setorigin(self, self.origin);
373         
374         self.velocity_x = ReadShort();
375         self.velocity_y = ReadShort();
376         self.velocity_z = ReadShort();
377         
378         self.angles_y       = ReadShort();
379         self.move_time      = time;
380         self.move_velocity  = self.velocity;
381         self.move_origin    = self.origin;
382     }
383         
384     if(sf & TNSF_ANIM)
385     {
386         self.frame1time = ReadCoord();
387         self.frame      = ReadByte();
388     }
389
390     if(sf & TNSF_STATUS)
391     {        
392         float _team;
393         _team = ReadByte();
394         _team -= 1; // /&)=(%&#)&%)/#&)=½!!!½!!". thanks.
395         self.health = ReadByte();
396         if(_team != self.team)
397         {
398             self.team = _team;
399             turret_changeteam();        
400         }
401     } 
402     
403     if(self.health == 0)
404         turret_die();
405 }