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