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