Merge branch 'master' into Mario/turrets
[xonotic/xonotic-data.pk3dir.git] /
1 #include "tturrets.qh"
2 #include "waypointsprites.qh"
3
4 #include "../server/movelib.qh"
5
6 string tid2info_base;
7 string tid2info_head;
8 string tid2info_name;
9 vector  tid2info_min;
10 vector  tid2info_max;
11
12 void turret_tid2info(float _tid);
13 void turret_precache(float _tid);
14 float turret_is_precache[TID_LAST];
15
16 void turrets_precache()
17 {
18     turret_precache(TID_COMMON);
19 }
20
21 void turret_precache(int _tid)
22 {
23     if (!turret_is_precache[TID_COMMON])
24     {
25         precache_sound ("weapons/rocket_impact.wav");
26         precache_model ("models/turrets/base-gib1.md3");
27         precache_model ("models/turrets/base-gib2.md3");
28         precache_model ("models/turrets/base-gib3.md3");
29         precache_model ("models/turrets/base-gib4.md3");
30         precache_model ("models/turrets/head-gib1.md3");
31         precache_model ("models/turrets/head-gib2.md3");
32         precache_model ("models/turrets/head-gib3.md3");
33         precache_model ("models/turrets/head-gib4.md3");
34         precache_model ("models/turrets/terrainbase.md3");
35         precache_model ("models/turrets/base.md3");
36         precache_model ("models/turrets/rocket.md3");
37     }
38     turret_tid2info(_tid);
39     if(turret_is_precache[_tid])
40         return;
41
42     switch(_tid)
43     {
44         case TID_EWHEEL:
45             precache_model ("models/turrets/ewheel-base2.md3");
46             precache_model ("models/turrets/ewheel-gun1.md3");
47             break;
48         case TID_FLAC:
49             precache_model ("models/turrets/flac.md3");
50             break;
51         case TID_FUSION:
52             precache_model ("models/turrets/reactor.md3");
53             break;
54         case TID_HELLION:
55             precache_model ("models/turrets/hellion.md3");
56             break;
57         case TID_HK:
58             precache_model ("models/turrets/hk.md3");
59             break;
60         case TID_MACHINEGUN:
61             precache_model ("models/turrets/machinegun.md3");
62             precache_sound ("weapons/uzi_fire.wav");
63             break;
64         case TID_MLRS:
65             precache_model ("models/turrets/mlrs.md3");
66             break;
67         case TID_PHASER:
68             precache_model ("models/turrets/phaser.md3");
69             precache_model ("models/turrets/phaser_beam.md3");
70             precache_sound ("turrets/phaser.wav");
71             break;
72         case TID_PLASMA:
73             precache_model ("models/turrets/plasma.md3");
74             break;
75         case TID_PLASMA_DUAL:
76             precache_model ("models/turrets/plasmad.md3");
77             break;
78         case TID_TESLA:
79             precache_model ("models/turrets/tesla_head.md3");
80             precache_model ("models/turrets/tesla_base.md3");
81             break;
82         case TID_WALKER:
83             precache_model ("models/turrets/walker_head_minigun.md3");
84             precache_model ("models/turrets/walker_body.md3");
85             precache_sound ("weapons/uzi_fire.wav");
86             break;
87     }
88     turret_is_precache[_tid] = true;
89 }
90
91 void turret_tid2info(float _tid)
92 {
93     tid2info_base = "models/turrets/base.md3";
94     tid2info_min = '-32 -32 0';
95     tid2info_max = '32 32 64';
96
97     switch(_tid)
98     {
99         case TID_EWHEEL:
100             tid2info_base = "models/turrets/ewheel-base2.md3";
101             tid2info_head = "models/turrets/ewheel-gun1.md3";
102             tid2info_name = "eWheel";
103             break;
104         case TID_FLAC:
105             tid2info_head = "models/turrets/flac.md3";
106             tid2info_name = "Flac Cannon";
107             break;
108         case TID_FUSION:
109             tid2info_head = "models/turrets/reactor.md3";
110             tid2info_name = "Fusion Reactor";
111             tid2info_min = '-34 -34 0';
112             tid2info_max = '34 34 90';
113             break;
114         case TID_HELLION:
115             tid2info_head = "models/turrets/hellion.md3";
116             tid2info_name = "Hellion";
117             break;
118         case TID_HK:
119             tid2info_head = "models/turrets/hk.md3";
120             tid2info_name = "Hunter-Killer";
121             break;
122         case TID_MACHINEGUN:
123             tid2info_head = "models/turrets/machinegun.md3";
124             tid2info_name = "Machinegun";
125             break;
126         case TID_MLRS:
127             tid2info_head = "models/turrets/mlrs.md3";
128             tid2info_name = "MLRS";
129             break;
130         case TID_PHASER:
131             tid2info_head = "models/turrets/phaser.md3";
132             tid2info_name = "Phaser";
133             break;
134         case TID_PLASMA:
135             tid2info_head = "models/turrets/plasma.md3";
136             tid2info_name = "Plasma";
137             break;
138         case TID_PLASMA_DUAL:
139             tid2info_head = "models/turrets/plasmad.md3";
140             tid2info_name = "Dual Plasma";
141             break;
142         case TID_TESLA:
143             tid2info_base = "models/turrets/tesla_base.md3";
144             tid2info_head = "models/turrets/tesla_head.md3";
145             tid2info_name = "Tesla coil";
146             tid2info_min = '-60 -60 0';
147             tid2info_max  ='60 60 128';
148             break;
149         case TID_WALKER:
150             tid2info_base = "models/turrets/walker_body.md3";
151             tid2info_head = "models/turrets/walker_head_minigun.md3";
152             tid2info_name = "Walker";
153             tid2info_min = '-70 -70 0';
154             tid2info_max = '70 70 95';
155             break;
156     }
157 }
158
159 void turret_remove()
160 {
161     remove(self.tur_head);
162     //remove(self.enemy);
163     self.tur_head = world;
164 }
165
166 .vector glowmod;
167 void turret_changeteam()
168 {
169         switch(self.team - 1)
170         {
171         case NUM_TEAM_1: // Red
172             self.glowmod = '2 0 0';
173             self.teamradar_color = '1 0 0';
174             break;
175
176         case NUM_TEAM_2: // Blue
177             self.glowmod = '0 0 2';
178             self.teamradar_color = '0 0 1';
179             break;
180
181         case NUM_TEAM_3: // Yellow
182             self.glowmod = '1 1 0';
183             self.teamradar_color = '1 1 0';
184             break;
185
186         case NUM_TEAM_4: // Pink
187             self.glowmod = '1 0 1';
188             self.teamradar_color = '1 0 1';
189             break;
190         }
191
192         if(self.team)
193         self.colormap = 1024 + (self.team - 1) * 17;
194
195         self.tur_head.colormap = self.colormap;
196         self.tur_head.glowmod = self.glowmod;
197
198 }
199
200 void turret_head_draw()
201 {
202     self.drawmask = MASK_NORMAL;
203 }
204
205 void turret_draw()
206 {
207     float dt;
208
209     dt = time - self.move_time;
210     self.move_time = time;
211     if(dt <= 0)
212         return;
213
214     self.tur_head.angles += dt * self.tur_head.move_avelocity;
215
216     if (self.health < 127)
217     {
218         dt = random();
219
220         if(dt < 0.03)
221             te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
222     }
223
224     if(self.health < 85)
225     if(dt < 0.01)
226         pointparticles(particleeffectnum("smoke_large"), (self.origin + (randomvec() * 80)), '0 0 0', 1);
227
228     if(self.health < 32)
229     if(dt < 0.015)
230         pointparticles(particleeffectnum("smoke_small"), (self.origin + (randomvec() * 80)), '0 0 0', 1);
231
232 }
233
234 void turret_draw2d()
235 {
236         if(self.netname == "")
237             return;
238
239         if(!autocvar_g_waypointsprite_turrets)
240                 return;
241
242     if(autocvar_cl_hidewaypoints)
243         return;
244
245         float dist = vlen(self.origin - view_origin);
246     float t = (GetPlayerColor(player_localnum) + 1);
247
248         vector o;
249         string txt;
250
251         if(autocvar_cl_vehicles_hud_tactical)
252         if(dist < 10240 && t != self.team)
253         {
254         // TODO: Vehicle tactical hud
255         o = project_3d_to_2d(self.origin + '0 0 32');
256         if(o.z < 0
257         || o.x < (vid_conwidth * waypointsprite_edgeoffset_left)
258         || o.y < (vid_conheight * waypointsprite_edgeoffset_top)
259         || o.x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))
260         || o.y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
261             return; // Dont draw wp's for turrets out of view
262         o.z = 0;
263         if(hud != HUD_NORMAL)
264         {
265             switch(hud)
266             {
267                 case HUD_SPIDERBOT:
268                 case HUD_WAKIZASHI:
269                 case HUD_RAPTOR:
270                 case HUD_BUMBLEBEE:
271                     if(self.turret_type == TID_EWHEEL || self.turret_type == TID_WALKER)
272                         txt = "gfx/vehicles/vth-mover.tga";
273                     else
274                         txt = "gfx/vehicles/vth-stationary.tga";
275
276                     vector pz = drawgetimagesize(txt) * 0.25;
277                     drawpic(o - pz * 0.5, txt, pz , '1 1 1', 0.75, DRAWFLAG_NORMAL);
278                     break;
279             }
280         }
281         }
282
283         if(dist > self.maxdistance)
284         return;
285
286         string spriteimage = self.netname;
287         float a = self.alpha * autocvar_hud_panel_fg_alpha;
288         vector rgb = spritelookupcolor(spriteimage, self.teamradar_color);
289
290
291         if(self.maxdistance > waypointsprite_normdistance)
292                 a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent);
293         else if(self.maxdistance > 0)
294                 a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
295
296         if(rgb == '0 0 0')
297         {
298                 self.teamradar_color = '1 0 1';
299                 printf("WARNING: sprite of name %s has no color, using pink so you notice it\n", spriteimage);
300         }
301
302         txt = self.netname;
303         if(autocvar_g_waypointsprite_spam && waypointsprite_count >= autocvar_g_waypointsprite_spam)
304                 txt = _("Spam");
305         else
306                 txt = spritelookuptext(spriteimage);
307
308         if(time - floor(time) > 0.5 && t == self.team)
309         {
310                 if(self.helpme && time < self.helpme)
311                 {
312                     a *= SPRITE_HELPME_BLINK;
313                     txt = sprintf(_("%s under attack!"), txt);
314                 }
315                 else
316                         a *= spritelookupblinkvalue(spriteimage);
317         }
318
319         if(autocvar_g_waypointsprite_uppercase)
320                 txt = strtoupper(txt);
321
322         if(a > 1)
323         {
324                 rgb *= a;
325                 a = 1;
326         }
327
328         if(a <= 0)
329             return;
330
331         rgb = fixrgbexcess(rgb);
332
333         o = project_3d_to_2d(self.origin + '0 0 64');
334         if(o.z < 0
335         || o.x < (vid_conwidth * waypointsprite_edgeoffset_left)
336         || o.y < (vid_conheight * waypointsprite_edgeoffset_top)
337         || o.x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))
338         || o.y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
339             return; // Dont draw wp's for turrets out of view
340
341         o.z = 0;
342
343         float edgedistance_min, crosshairdistance;
344                 edgedistance_min = min((o.y - (vid_conheight * waypointsprite_edgeoffset_top)),
345         (o.x - (vid_conwidth * waypointsprite_edgeoffset_left)),
346         (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) - o.x,
347         (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)) - o.y);
348
349         float vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
350
351         crosshairdistance = sqrt( pow(o.x - vid_conwidth/2, 2) + pow(o.y - vid_conheight/2, 2) );
352
353         t = waypointsprite_scale * vidscale;
354         a *= waypointsprite_alpha;
355
356         {
357                 a = a * (1 - (1 - waypointsprite_distancefadealpha) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
358                 t = t * (1 - (1 - waypointsprite_distancefadescale) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
359         }
360         if (edgedistance_min < waypointsprite_edgefadedistance) {
361                 a = a * (1 - (1 - waypointsprite_edgefadealpha) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
362                 t = t * (1 - (1 - waypointsprite_edgefadescale) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
363         }
364         if(crosshairdistance < waypointsprite_crosshairfadedistance) {
365                 a = a * (1 - (1 - waypointsprite_crosshairfadealpha) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
366                 t = t * (1 - (1 - waypointsprite_crosshairfadescale) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
367         }
368
369         o = drawspritearrow(o, M_PI, rgb, a, SPRITE_ARROW_SCALE * t);
370     o = drawspritetext(o, M_PI, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
371     drawhealthbar(
372             o,
373             0,
374             self.health / 255,
375             '0 0 0',
376             '0 0 0',
377             0.5 * SPRITE_HEALTHBAR_WIDTH * t,
378             0.5 * SPRITE_HEALTHBAR_HEIGHT * t,
379             SPRITE_HEALTHBAR_MARGIN * t + 0.5 * waypointsprite_fontsize,
380             SPRITE_HEALTHBAR_BORDER * t,
381             0,
382             rgb,
383             a * SPRITE_HEALTHBAR_BORDERALPHA,
384             rgb,
385             a * SPRITE_HEALTHBAR_HEALTHALPHA,
386             DRAWFLAG_NORMAL
387             );
388 }
389
390 void turret_walker_draw()
391 {
392     float dt;
393
394     dt = time - self.move_time;
395     self.move_time = time;
396     if(dt <= 0)
397         return;
398
399     fixedmakevectors(self.angles);
400     movelib_groundalign4point(300, 100, 0.25, 45);
401     setorigin(self, self.origin + self.velocity * dt);
402     self.tur_head.angles += dt * self.tur_head.move_avelocity;
403     self.angles_y = self.move_angles.y;
404
405     if (self.health < 127)
406     if(random() < 0.15)
407         te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
408 }
409
410 void turret_ewheel_draw()
411 {
412     float dt;
413
414     dt = time - self.move_time;
415     self.move_time = time;
416     if(dt <= 0)
417         return;
418
419     fixedmakevectors(self.angles);
420     setorigin(self, self.origin + self.velocity * dt);
421     self.tur_head.angles += dt * self.tur_head.move_avelocity;
422     self.angles_y = self.move_angles.y;
423
424     if (self.health < 127)
425     if(random() < 0.05)
426         te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
427 }
428
429 void turret_construct()
430 {
431     if(self.tur_head == world)
432         self.tur_head = spawn();
433
434     turret_tid2info(self.turret_type);
435     self.netname = tid2info_name;
436
437     setorigin(self, self.origin);
438     setmodel(self, tid2info_base);
439     setmodel(self.tur_head, tid2info_head);
440     setsize(self, tid2info_min, tid2info_max);
441     setsize(self.tur_head, '0 0 0', '0 0 0');
442
443     if(self.turret_type == TID_EWHEEL)
444         setattachment(self.tur_head, self, "");
445     else
446         setattachment(self.tur_head, self, "tag_head");
447
448     self.tur_head.classname     = "turret_head";
449     self.tur_head.owner         = self;
450     self.tur_head.move_movetype = MOVETYPE_NOCLIP;
451     self.move_movetype          = MOVETYPE_NOCLIP;
452     self.tur_head.angles        = self.angles;
453     self.health                 = 255;
454     self.solid                  = SOLID_BBOX;
455     self.tur_head.solid         = SOLID_NOT;
456     self.movetype               = MOVETYPE_NOCLIP;
457     self.tur_head.movetype      = MOVETYPE_NOCLIP;
458     self.draw                   = turret_draw;
459     self.entremove              = turret_remove;
460     self.drawmask               = MASK_NORMAL;
461     self.tur_head.drawmask      = MASK_NORMAL;
462     self.anim_start_time        = 0;
463     self.draw2d = turret_draw2d;
464     self.maxdistance = autocvar_g_waypointsprite_turrets_maxdist;
465     self.teamradar_color = '1 0 0';
466     self.alpha = 1;
467
468     if(self.turret_type == TID_EWHEEL || self.turret_type == TID_WALKER)
469     {
470         self.gravity            = 1;
471         self.movetype           = MOVETYPE_BOUNCE;
472         self.move_movetype      = MOVETYPE_BOUNCE;
473         self.move_origin        = self.origin;
474         self.move_time          = time;
475         switch(self.turret_type)
476         {
477             case TID_EWHEEL:
478                 self.draw               = turret_ewheel_draw;
479                 break;
480             case TID_WALKER:
481                 self.draw               = turret_walker_draw;
482                 break;
483
484         }
485     }
486 }
487
488 entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode);
489 void turret_gibboom();
490 void turret_gib_draw()
491 {
492     Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
493
494     self.drawmask = MASK_NORMAL;
495
496         if(self.cnt)
497         {
498             if(time >= self.nextthink)
499             {
500             turret_gibboom();
501             remove(self);
502             }
503         }
504         else
505         {
506         self.alpha = bound(0, self.nextthink - time, 1);
507         if(self.alpha < ALPHA_MIN_VISIBLE)
508             remove(self);
509         }
510 }
511
512 void turret_gibboom()
513 {
514     float i;
515
516     sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
517     pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
518
519     for (i = 1; i < 5; i = i + 1)
520         turret_gibtoss(strcat("models/turrets/head-gib", ftos(i), ".md3"), self.origin + '0 0 2', self.velocity + randomvec() * 700, '0 0 0', false);
521 }
522
523 entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode)
524 {
525     entity gib;
526
527     traceline(_from, _to, MOVE_NOMONSTERS, world);
528     if(trace_startsolid)
529         return world;
530
531     gib = spawn();
532     setorigin(gib, _from);
533     setmodel(gib, _model);
534     gib.colormod    = _cmod;
535         gib.solid       = SOLID_CORPSE;
536     gib.draw        = turret_gib_draw;
537     gib.cnt         = _explode;
538     setsize(gib, '-1 -1 -1', '1 1 1');
539     if(_explode)
540     {
541         gib.nextthink = time + 0.2 * (autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15));
542         gib.effects = EF_FLAME;
543     }
544     else
545         gib.nextthink = time + autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15);
546
547     gib.gravity         = 1;
548         gib.move_movetype   = MOVETYPE_BOUNCE;
549         gib.move_origin     = _from;
550         setorigin(gib,        _from);
551         gib.move_velocity   = _to;
552         gib.move_avelocity  = prandomvec() * 32;
553         gib.move_time       = time;
554         gib.damageforcescale = 1;
555         gib.classname = "turret_gib";
556
557         return gib;
558 }
559
560 void turret_die()
561 {
562
563     sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
564     pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
565     turret_tid2info(self.turret_type);
566     if (!autocvar_cl_nogibs)
567     {
568         // Base
569         if(self.turret_type == TID_EWHEEL)
570             turret_gibtoss(tid2info_base, self.origin + '0 0 18', self.velocity + '0 0 400' + '0.1 0.1 1' * (random() * 400), '-1 -1 -1', true);
571         else if (self.turret_type == TID_WALKER)
572             turret_gibtoss(tid2info_base, self.origin + '0 0 18', self.velocity + '0 0 300' + '0.1 0.1 1' * (random() * 200), '-1 -1 -1', true);
573         else if (self.turret_type == TID_TESLA)
574             turret_gibtoss(tid2info_base, self.origin + '0 0 18', '0 0 200', '-1 -1 -1', false);
575         else
576         {
577             if (random() > 0.5)
578             {
579                 turret_gibtoss("models/turrets/base-gib2.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', false);
580                 turret_gibtoss("models/turrets/base-gib3.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', false);
581                 turret_gibtoss("models/turrets/base-gib4.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', false);
582             }
583             else
584                 turret_gibtoss("models/turrets/base-gib1.md3", self.origin + '0 0 8', '0 0 0', '0 0 0', true);
585
586             entity headgib = turret_gibtoss(tid2info_head, self.origin + '0 0 32', '0 0 200' + randomvec() * 200, '-1 -1 -1', true);
587             if(headgib)
588             {
589                 headgib.angles = headgib.move_angles = self.tur_head.angles;
590                 headgib.avelocity = headgib.move_avelocity = self.tur_head.move_avelocity + randomvec() * 45;
591                 headgib.avelocity_y = headgib.move_avelocity_y = headgib.move_avelocity.y * 5;
592                 headgib.gravity = 0.5;
593             }
594         }
595     }
596
597     setmodel(self, "null");
598     setmodel(self.tur_head, "null");
599 }
600
601 void ent_turret()
602 {
603     int sf = ReadByte();
604
605         if(sf & TNSF_SETUP)
606         {
607             self.turret_type = ReadByte();
608
609             self.origin_x = ReadCoord();
610             self.origin_y = ReadCoord();
611             self.origin_z = ReadCoord();
612             setorigin(self, self.origin);
613
614             self.angles_x = ReadAngle();
615             self.angles_y = ReadAngle();
616
617             turret_precache(self.turret_type);
618             turret_construct();
619             self.colormap = 1024;
620             self.glowmod = '0 1 1';
621             self.tur_head.colormap = self.colormap;
622             self.tur_head.glowmod = self.glowmod;
623     }
624
625     if(sf & TNSF_ANG)
626     {
627         if(self.tur_head == world) // aparenly this can happpen before TNSF_SETUP. great.
628             self.tur_head = spawn();
629
630         self.tur_head.move_angles_x = ReadShort();
631         self.tur_head.move_angles_y = ReadShort();
632         //self.tur_head.angles = self.angles + self.tur_head.move_angles;
633         self.tur_head.angles = self.tur_head.move_angles;
634     }
635
636     if(sf & TNSF_AVEL)
637     {
638         if(self.tur_head == world) // aparenly this can happpen before TNSF_SETUP. great.
639             self.tur_head = spawn();
640
641         self.tur_head.move_avelocity_x = ReadShort();
642         self.tur_head.move_avelocity_y = ReadShort();
643     }
644
645     if(sf & TNSF_MOVE)
646     {
647         self.origin_x = ReadShort();
648         self.origin_y = ReadShort();
649         self.origin_z = ReadShort();
650         setorigin(self, self.origin);
651
652         self.velocity_x = ReadShort();
653         self.velocity_y = ReadShort();
654         self.velocity_z = ReadShort();
655
656         self.move_angles_y = ReadShort();
657
658         self.move_time     = time;
659         self.move_velocity = self.velocity;
660         self.move_origin   = self.origin;
661     }
662
663     if(sf & TNSF_ANIM)
664     {
665         self.frame1time = ReadCoord();
666         self.frame      = ReadByte();
667     }
668
669     if(sf & TNSF_STATUS)
670     {
671         int _tmp = ReadByte();
672         if(_tmp != self.team)
673         {
674             self.team = _tmp;
675             turret_changeteam();
676         }
677
678         _tmp = ReadByte();
679         if(_tmp == 0 && self.health != 0)
680             turret_die();
681         else if(self.health && self.health != _tmp)
682             self.helpme = servertime + 10;
683
684         self.health = _tmp;
685     }
686     //self.enemy.health = self.health / 255;
687 }