vkQuake2 doxygen  1.0 dev
m_tank.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 
19 */
20 /*
21 ==============================================================================
22 
23 TANK
24 
25 ==============================================================================
26 */
27 
28 #include "g_local.h"
29 #include "m_tank.h"
30 
31 
32 void tank_refire_rocket (edict_t *self);
33 void tank_doattack_rocket (edict_t *self);
34 void tank_reattack_blaster (edict_t *self);
35 
36 static int sound_thud;
37 static int sound_pain;
38 static int sound_idle;
39 static int sound_die;
40 static int sound_step;
41 static int sound_sight;
42 static int sound_windup;
43 static int sound_strike;
44 
45 //
46 // misc
47 //
48 
49 void tank_sight (edict_t *self, edict_t *other)
50 {
51  gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
52 }
53 
54 
55 void tank_footstep (edict_t *self)
56 {
57  gi.sound (self, CHAN_BODY, sound_step, 1, ATTN_NORM, 0);
58 }
59 
60 void tank_thud (edict_t *self)
61 {
62  gi.sound (self, CHAN_BODY, sound_thud, 1, ATTN_NORM, 0);
63 }
64 
65 void tank_windup (edict_t *self)
66 {
67  gi.sound (self, CHAN_WEAPON, sound_windup, 1, ATTN_NORM, 0);
68 }
69 
70 void tank_idle (edict_t *self)
71 {
72  gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
73 }
74 
75 
76 //
77 // stand
78 //
79 
81 {
82  ai_stand, 0, NULL,
83  ai_stand, 0, NULL,
84  ai_stand, 0, NULL,
85  ai_stand, 0, NULL,
86  ai_stand, 0, NULL,
87  ai_stand, 0, NULL,
88  ai_stand, 0, NULL,
89  ai_stand, 0, NULL,
90  ai_stand, 0, NULL,
91  ai_stand, 0, NULL,
92  ai_stand, 0, NULL,
93  ai_stand, 0, NULL,
94  ai_stand, 0, NULL,
95  ai_stand, 0, NULL,
96  ai_stand, 0, NULL,
97  ai_stand, 0, NULL,
98  ai_stand, 0, NULL,
99  ai_stand, 0, NULL,
100  ai_stand, 0, NULL,
101  ai_stand, 0, NULL,
102  ai_stand, 0, NULL,
103  ai_stand, 0, NULL,
104  ai_stand, 0, NULL,
105  ai_stand, 0, NULL,
106  ai_stand, 0, NULL,
107  ai_stand, 0, NULL,
108  ai_stand, 0, NULL,
109  ai_stand, 0, NULL,
110  ai_stand, 0, NULL,
111  ai_stand, 0, NULL
112 };
114 
115 void tank_stand (edict_t *self)
116 {
117  self->monsterinfo.currentmove = &tank_move_stand;
118 }
119 
120 
121 //
122 // walk
123 //
124 
125 void tank_walk (edict_t *self);
126 
128 {
129  ai_walk, 0, NULL,
130  ai_walk, 6, NULL,
131  ai_walk, 6, NULL,
133 };
135 
137 {
138  ai_walk, 4, NULL,
139  ai_walk, 5, NULL,
140  ai_walk, 3, NULL,
141  ai_walk, 2, NULL,
142  ai_walk, 5, NULL,
143  ai_walk, 5, NULL,
144  ai_walk, 4, NULL,
146  ai_walk, 3, NULL,
147  ai_walk, 5, NULL,
148  ai_walk, 4, NULL,
149  ai_walk, 5, NULL,
150  ai_walk, 7, NULL,
151  ai_walk, 7, NULL,
152  ai_walk, 6, NULL,
154 };
156 
158 {
159  ai_walk, 3, NULL,
160  ai_walk, 3, NULL,
161  ai_walk, 2, NULL,
162  ai_walk, 2, NULL,
164 };
166 
167 void tank_walk (edict_t *self)
168 {
169  self->monsterinfo.currentmove = &tank_move_walk;
170 }
171 
172 
173 //
174 // run
175 //
176 
177 void tank_run (edict_t *self);
178 
180 {
181  ai_run, 0, NULL,
182  ai_run, 6, NULL,
183  ai_run, 6, NULL,
184  ai_run, 11, tank_footstep
185 };
187 
189 {
190  ai_run, 4, NULL,
191  ai_run, 5, NULL,
192  ai_run, 3, NULL,
193  ai_run, 2, NULL,
194  ai_run, 5, NULL,
195  ai_run, 5, NULL,
196  ai_run, 4, NULL,
197  ai_run, 4, tank_footstep,
198  ai_run, 3, NULL,
199  ai_run, 5, NULL,
200  ai_run, 4, NULL,
201  ai_run, 5, NULL,
202  ai_run, 7, NULL,
203  ai_run, 7, NULL,
204  ai_run, 6, NULL,
206 };
208 
210 {
211  ai_run, 3, NULL,
212  ai_run, 3, NULL,
213  ai_run, 2, NULL,
214  ai_run, 2, NULL,
216 };
218 
219 void tank_run (edict_t *self)
220 {
221  if (self->enemy && self->enemy->client)
222  self->monsterinfo.aiflags |= AI_BRUTAL;
223  else
224  self->monsterinfo.aiflags &= ~AI_BRUTAL;
225 
226  if (self->monsterinfo.aiflags & AI_STAND_GROUND)
227  {
228  self->monsterinfo.currentmove = &tank_move_stand;
229  return;
230  }
231 
232  if (self->monsterinfo.currentmove == &tank_move_walk ||
233  self->monsterinfo.currentmove == &tank_move_start_run)
234  {
235  self->monsterinfo.currentmove = &tank_move_run;
236  }
237  else
238  {
239  self->monsterinfo.currentmove = &tank_move_start_run;
240  }
241 }
242 
243 //
244 // pain
245 //
246 
248 {
249  ai_move, 0, NULL,
250  ai_move, 0, NULL,
251  ai_move, 0, NULL,
252  ai_move, 0, NULL
253 };
255 
257 {
258  ai_move, 0, NULL,
259  ai_move, 0, NULL,
260  ai_move, 0, NULL,
261  ai_move, 0, NULL,
262  ai_move, 0, NULL
263 };
265 
267 {
268  ai_move, -7, NULL,
269  ai_move, 0, NULL,
270  ai_move, 0, NULL,
271  ai_move, 0, NULL,
272  ai_move, 2, NULL,
273  ai_move, 0, NULL,
274  ai_move, 0, NULL,
275  ai_move, 3, NULL,
276  ai_move, 0, NULL,
277  ai_move, 2, NULL,
278  ai_move, 0, NULL,
279  ai_move, 0, NULL,
280  ai_move, 0, NULL,
281  ai_move, 0, NULL,
282  ai_move, 0, NULL,
284 };
286 
287 
288 void tank_pain (edict_t *self, edict_t *other, float kick, int damage)
289 {
290  if (self->health < (self->max_health / 2))
291  self->s.skinnum |= 1;
292 
293  if (damage <= 10)
294  return;
295 
296  if (level.time < self->pain_debounce_time)
297  return;
298 
299  if (damage <= 30)
300  if (random() > 0.2)
301  return;
302 
303  // If hard or nightmare, don't go into pain while attacking
304  if ( skill->value >= 2)
305  {
306  if ( (self->s.frame >= FRAME_attak301) && (self->s.frame <= FRAME_attak330) )
307  return;
308  if ( (self->s.frame >= FRAME_attak101) && (self->s.frame <= FRAME_attak116) )
309  return;
310  }
311 
312  self->pain_debounce_time = level.time + 3;
313  gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
314 
315  if (skill->value == 3)
316  return; // no pain anims in nightmare
317 
318  if (damage <= 30)
319  self->monsterinfo.currentmove = &tank_move_pain1;
320  else if (damage <= 60)
321  self->monsterinfo.currentmove = &tank_move_pain2;
322  else
323  self->monsterinfo.currentmove = &tank_move_pain3;
324 };
325 
326 
327 //
328 // attacks
329 //
330 
331 void TankBlaster (edict_t *self)
332 {
334  vec3_t start;
335  vec3_t end;
336  vec3_t dir;
337  int flash_number;
338 
339  if (self->s.frame == FRAME_attak110)
340  flash_number = MZ2_TANK_BLASTER_1;
341  else if (self->s.frame == FRAME_attak113)
342  flash_number = MZ2_TANK_BLASTER_2;
343  else // (self->s.frame == FRAME_attak116)
344  flash_number = MZ2_TANK_BLASTER_3;
345 
346  AngleVectors (self->s.angles, forward, right, NULL);
347  G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
348 
349  VectorCopy (self->enemy->s.origin, end);
350  end[2] += self->enemy->viewheight;
351  VectorSubtract (end, start, dir);
352 
353  monster_fire_blaster (self, start, dir, 30, 800, flash_number, EF_BLASTER);
354 }
355 
356 void TankStrike (edict_t *self)
357 {
358  gi.sound (self, CHAN_WEAPON, sound_strike, 1, ATTN_NORM, 0);
359 }
360 
361 void TankRocket (edict_t *self)
362 {
364  vec3_t start;
365  vec3_t dir;
366  vec3_t vec;
367  int flash_number;
368 
369  if (self->s.frame == FRAME_attak324)
370  flash_number = MZ2_TANK_ROCKET_1;
371  else if (self->s.frame == FRAME_attak327)
372  flash_number = MZ2_TANK_ROCKET_2;
373  else // (self->s.frame == FRAME_attak330)
374  flash_number = MZ2_TANK_ROCKET_3;
375 
376  AngleVectors (self->s.angles, forward, right, NULL);
377  G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
378 
379  VectorCopy (self->enemy->s.origin, vec);
380  vec[2] += self->enemy->viewheight;
381  VectorSubtract (vec, start, dir);
382  VectorNormalize (dir);
383 
384  monster_fire_rocket (self, start, dir, 50, 550, flash_number);
385 }
386 
388 {
389  vec3_t dir;
390  vec3_t vec;
391  vec3_t start;
393  int flash_number;
394 
395  flash_number = MZ2_TANK_MACHINEGUN_1 + (self->s.frame - FRAME_attak406);
396 
397  AngleVectors (self->s.angles, forward, right, NULL);
398  G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
399 
400  if (self->enemy)
401  {
402  VectorCopy (self->enemy->s.origin, vec);
403  vec[2] += self->enemy->viewheight;
404  VectorSubtract (vec, start, vec);
405  vectoangles (vec, vec);
406  dir[0] = vec[0];
407  }
408  else
409  {
410  dir[0] = 0;
411  }
412  if (self->s.frame <= FRAME_attak415)
413  dir[1] = self->s.angles[1] - 8 * (self->s.frame - FRAME_attak411);
414  else
415  dir[1] = self->s.angles[1] + 8 * (self->s.frame - FRAME_attak419);
416  dir[2] = 0;
417 
418  AngleVectors (dir, forward, NULL, NULL);
419 
420  monster_fire_bullet (self, start, forward, 20, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number);
421 }
422 
423 
425 {
426  ai_charge, 0, NULL,
427  ai_charge, 0, NULL,
428  ai_charge, 0, NULL,
429  ai_charge, 0, NULL,
430  ai_charge, -1, NULL,
431  ai_charge, -2, NULL,
432  ai_charge, -1, NULL,
433  ai_charge, -1, NULL,
434  ai_charge, 0, NULL,
435  ai_charge, 0, TankBlaster, // 10
436  ai_charge, 0, NULL,
437  ai_charge, 0, NULL,
439  ai_charge, 0, NULL,
440  ai_charge, 0, NULL,
441  ai_charge, 0, TankBlaster // 16
442 };
444 
446 {
447  ai_charge, 0, NULL,
448  ai_charge, 0, NULL,
450  ai_charge, 0, NULL,
451  ai_charge, 0, NULL,
452  ai_charge, 0, TankBlaster // 16
453 };
455 
457 {
458  ai_move, 0, NULL, // 17
459  ai_move, 0, NULL,
460  ai_move, 2, NULL,
461  ai_move, 3, NULL,
462  ai_move, 2, NULL,
463  ai_move, -2, tank_footstep // 22
464 };
466 
468 {
469  if (skill->value >= 2)
470  if (visible (self, self->enemy))
471  if (self->enemy->health > 0)
472  if (random() <= 0.6)
473  {
474  self->monsterinfo.currentmove = &tank_move_reattack_blast;
475  return;
476  }
477  self->monsterinfo.currentmove = &tank_move_attack_post_blast;
478 }
479 
480 
482 {
483  self->enemy = NULL;
484  tank_run (self);
485 }
486 
488 {
489  ai_move, 3, NULL,
490  ai_move, 2, NULL,
491  ai_move, 2, NULL,
492  ai_move, 1, NULL,
493  ai_move, 6, NULL,
494  ai_move, 7, NULL,
496  ai_move, 2, NULL,
497  ai_move, 1, NULL,
498  ai_move, 2, NULL,
500  ai_move, 2, NULL,
501  ai_move, 0, NULL,
502  ai_move, 0, NULL,
503  ai_move, 0, NULL,
504  ai_move, 0, NULL,
505  ai_move, -2, NULL,
506  ai_move, -2, NULL,
507  ai_move, 0, tank_windup,
508  ai_move, 0, NULL,
509  ai_move, 0, NULL,
510  ai_move, 0, NULL,
511  ai_move, 0, NULL,
512  ai_move, 0, NULL,
513  ai_move, 0, NULL,
514  ai_move, 0, TankStrike,
515  ai_move, 0, NULL,
516  ai_move, -1, NULL,
517  ai_move, -1, NULL,
518  ai_move, -1, NULL,
519  ai_move, -1, NULL,
520  ai_move, -1, NULL,
521  ai_move, -3, NULL,
522  ai_move, -10, NULL,
523  ai_move, -10, NULL,
524  ai_move, -2, NULL,
525  ai_move, -3, NULL,
527 };
529 
531 {
532  ai_charge, 0, NULL,
533  ai_charge, 0, NULL,
534  ai_charge, 0, NULL,
535  ai_charge, 0, NULL,
536  ai_charge, 0, NULL,
537  ai_charge, 0, NULL,
538  ai_charge, 0, NULL,
539  ai_charge, 0, NULL,
540  ai_charge, 0, NULL,
541  ai_charge, 0, NULL, // 10
542 
543  ai_charge, 0, NULL,
544  ai_charge, 1, NULL,
545  ai_charge, 2, NULL,
546  ai_charge, 7, NULL,
547  ai_charge, 7, NULL,
549  ai_charge, 0, NULL,
550  ai_charge, 0, NULL,
551  ai_charge, 0, NULL,
552  ai_charge, 0, NULL, // 20
553 
554  ai_charge, -3, NULL
555 };
557 
559 {
560  ai_charge, -3, NULL, // Loop Start 22
561  ai_charge, 0, NULL,
562  ai_charge, 0, TankRocket, // 24
563  ai_charge, 0, NULL,
564  ai_charge, 0, NULL,
565  ai_charge, 0, TankRocket,
566  ai_charge, 0, NULL,
567  ai_charge, 0, NULL,
568  ai_charge, -1, TankRocket // 30 Loop End
569 };
571 
573 {
574  ai_charge, 0, NULL, // 31
575  ai_charge, -1, NULL,
576  ai_charge, -1, NULL,
577  ai_charge, 0, NULL,
578  ai_charge, 2, NULL,
579  ai_charge, 3, NULL,
580  ai_charge, 4, NULL,
581  ai_charge, 2, NULL,
582  ai_charge, 0, NULL,
583  ai_charge, 0, NULL, // 40
584 
585  ai_charge, 0, NULL,
586  ai_charge, -9, NULL,
587  ai_charge, -8, NULL,
588  ai_charge, -7, NULL,
589  ai_charge, -1, NULL,
591  ai_charge, 0, NULL,
592  ai_charge, 0, NULL,
593  ai_charge, 0, NULL,
594  ai_charge, 0, NULL, // 50
595 
596  ai_charge, 0, NULL,
597  ai_charge, 0, NULL,
598  ai_charge, 0, NULL
599 };
601 
603 {
604  ai_charge, 0, NULL,
605  ai_charge, 0, NULL,
606  ai_charge, 0, NULL,
607  ai_charge, 0, NULL,
608  ai_charge, 0, NULL,
609  NULL, 0, TankMachineGun,
610  NULL, 0, TankMachineGun,
611  NULL, 0, TankMachineGun,
612  NULL, 0, TankMachineGun,
613  NULL, 0, TankMachineGun,
614  NULL, 0, TankMachineGun,
615  NULL, 0, TankMachineGun,
616  NULL, 0, TankMachineGun,
617  NULL, 0, TankMachineGun,
618  NULL, 0, TankMachineGun,
619  NULL, 0, TankMachineGun,
620  NULL, 0, TankMachineGun,
621  NULL, 0, TankMachineGun,
622  NULL, 0, TankMachineGun,
623  NULL, 0, TankMachineGun,
624  NULL, 0, TankMachineGun,
625  NULL, 0, TankMachineGun,
626  NULL, 0, TankMachineGun,
627  NULL, 0, TankMachineGun,
628  ai_charge, 0, NULL,
629  ai_charge, 0, NULL,
630  ai_charge, 0, NULL,
631  ai_charge, 0, NULL,
632  ai_charge, 0, NULL
633 };
635 
637 {
638  // Only on hard or nightmare
639  if ( skill->value >= 2 )
640  if (self->enemy->health > 0)
641  if (visible(self, self->enemy) )
642  if (random() <= 0.4)
643  {
644  self->monsterinfo.currentmove = &tank_move_attack_fire_rocket;
645  return;
646  }
647  self->monsterinfo.currentmove = &tank_move_attack_post_rocket;
648 }
649 
651 {
652  self->monsterinfo.currentmove = &tank_move_attack_fire_rocket;
653 }
654 
655 void tank_attack(edict_t *self)
656 {
657  vec3_t vec;
658  float range;
659  float r;
660 
661  if (self->enemy->health < 0)
662  {
663  self->monsterinfo.currentmove = &tank_move_attack_strike;
664  self->monsterinfo.aiflags &= ~AI_BRUTAL;
665  return;
666  }
667 
668  VectorSubtract (self->enemy->s.origin, self->s.origin, vec);
669  range = VectorLength (vec);
670 
671  r = random();
672 
673  if (range <= 125)
674  {
675  if (r < 0.4)
676  self->monsterinfo.currentmove = &tank_move_attack_chain;
677  else
678  self->monsterinfo.currentmove = &tank_move_attack_blast;
679  }
680  else if (range <= 250)
681  {
682  if (r < 0.5)
683  self->monsterinfo.currentmove = &tank_move_attack_chain;
684  else
685  self->monsterinfo.currentmove = &tank_move_attack_blast;
686  }
687  else
688  {
689  if (r < 0.33)
690  self->monsterinfo.currentmove = &tank_move_attack_chain;
691  else if (r < 0.66)
692  {
693  self->monsterinfo.currentmove = &tank_move_attack_pre_rocket;
694  self->pain_debounce_time = level.time + 5.0; // no pain for a while
695  }
696  else
697  self->monsterinfo.currentmove = &tank_move_attack_blast;
698  }
699 }
700 
701 
702 //
703 // death
704 //
705 
706 void tank_dead (edict_t *self)
707 {
708  VectorSet (self->mins, -16, -16, -16);
709  VectorSet (self->maxs, 16, 16, -0);
710  self->movetype = MOVETYPE_TOSS;
711  self->svflags |= SVF_DEADMONSTER;
712  self->nextthink = 0;
713  gi.linkentity (self);
714 }
715 
717 {
718  ai_move, -7, NULL,
719  ai_move, -2, NULL,
720  ai_move, -2, NULL,
721  ai_move, 1, NULL,
722  ai_move, 3, NULL,
723  ai_move, 6, NULL,
724  ai_move, 1, NULL,
725  ai_move, 1, NULL,
726  ai_move, 2, NULL,
727  ai_move, 0, NULL,
728  ai_move, 0, NULL,
729  ai_move, 0, NULL,
730  ai_move, -2, NULL,
731  ai_move, 0, NULL,
732  ai_move, 0, NULL,
733  ai_move, -3, NULL,
734  ai_move, 0, NULL,
735  ai_move, 0, NULL,
736  ai_move, 0, NULL,
737  ai_move, 0, NULL,
738  ai_move, 0, NULL,
739  ai_move, 0, NULL,
740  ai_move, -4, NULL,
741  ai_move, -6, NULL,
742  ai_move, -4, NULL,
743  ai_move, -5, NULL,
744  ai_move, -7, NULL,
745  ai_move, -15, tank_thud,
746  ai_move, -5, NULL,
747  ai_move, 0, NULL,
748  ai_move, 0, NULL,
749  ai_move, 0, NULL
750 };
752 
753 void tank_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
754 {
755  int n;
756 
757 // check for gib
758  if (self->health <= self->gib_health)
759  {
760  gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
761  for (n= 0; n < 1 /*4*/; n++)
762  ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
763  for (n= 0; n < 4; n++)
764  ThrowGib (self, "models/objects/gibs/sm_metal/tris.md2", damage, GIB_METALLIC);
765  ThrowGib (self, "models/objects/gibs/chest/tris.md2", damage, GIB_ORGANIC);
766  ThrowHead (self, "models/objects/gibs/gear/tris.md2", damage, GIB_METALLIC);
767  self->deadflag = DEAD_DEAD;
768  return;
769  }
770 
771  if (self->deadflag == DEAD_DEAD)
772  return;
773 
774 // regular death
775  gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0);
776  self->deadflag = DEAD_DEAD;
777  self->takedamage = DAMAGE_YES;
778 
779  self->monsterinfo.currentmove = &tank_move_death;
780 
781 }
782 
783 
784 //
785 // monster_tank
786 //
787 
788 /*QUAKED monster_tank (1 .5 0) (-32 -32 -16) (32 32 72) Ambush Trigger_Spawn Sight
789 */
790 /*QUAKED monster_tank_commander (1 .5 0) (-32 -32 -16) (32 32 72) Ambush Trigger_Spawn Sight
791 */
793 {
794  if (deathmatch->value)
795  {
796  G_FreeEdict (self);
797  return;
798  }
799 
800  self->s.modelindex = gi.modelindex ("models/monsters/tank/tris.md2");
801  VectorSet (self->mins, -32, -32, -16);
802  VectorSet (self->maxs, 32, 32, 72);
803  self->movetype = MOVETYPE_STEP;
804  self->solid = SOLID_BBOX;
805 
806  sound_pain = gi.soundindex ("tank/tnkpain2.wav");
807  sound_thud = gi.soundindex ("tank/tnkdeth2.wav");
808  sound_idle = gi.soundindex ("tank/tnkidle1.wav");
809  sound_die = gi.soundindex ("tank/death.wav");
810  sound_step = gi.soundindex ("tank/step.wav");
811  sound_windup = gi.soundindex ("tank/tnkatck4.wav");
812  sound_strike = gi.soundindex ("tank/tnkatck5.wav");
813  sound_sight = gi.soundindex ("tank/sight1.wav");
814 
815  gi.soundindex ("tank/tnkatck1.wav");
816  gi.soundindex ("tank/tnkatk2a.wav");
817  gi.soundindex ("tank/tnkatk2b.wav");
818  gi.soundindex ("tank/tnkatk2c.wav");
819  gi.soundindex ("tank/tnkatk2d.wav");
820  gi.soundindex ("tank/tnkatk2e.wav");
821  gi.soundindex ("tank/tnkatck3.wav");
822 
823  if (strcmp(self->classname, "monster_tank_commander") == 0)
824  {
825  self->health = 1000;
826  self->gib_health = -225;
827  }
828  else
829  {
830  self->health = 750;
831  self->gib_health = -200;
832  }
833 
834  self->mass = 500;
835 
836  self->pain = tank_pain;
837  self->die = tank_die;
838  self->monsterinfo.stand = tank_stand;
839  self->monsterinfo.walk = tank_walk;
840  self->monsterinfo.run = tank_run;
841  self->monsterinfo.dodge = NULL;
842  self->monsterinfo.attack = tank_attack;
843  self->monsterinfo.melee = NULL;
844  self->monsterinfo.sight = tank_sight;
845  self->monsterinfo.idle = tank_idle;
846 
847  gi.linkentity (self);
848 
849  self->monsterinfo.currentmove = &tank_move_stand;
850  self->monsterinfo.scale = MODEL_SCALE;
851 
852  walkmonster_start(self);
853 
854  if (strcmp(self->classname, "monster_tank_commander") == 0)
855  self->s.skinnum = 2;
856 }
FRAME_attak401
#define FRAME_attak401
Definition: m_boss32.h:233
tank_windup
void tank_windup(edict_t *self)
Definition: m_tank.c:65
gi
game_import_t gi
Definition: g_main.c:25
G_ProjectSource
void G_ProjectSource(vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result)
Definition: g_utils.c:25
deathmatch
cvar_t * deathmatch
Definition: g_main.c:35
FRAME_pain205
#define FRAME_pain205
Definition: m_brain.h:137
tank_die
void tank_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
Definition: m_tank.c:753
tank_move_reattack_blast
mmove_t tank_move_reattack_blast
Definition: m_tank.c:454
DEAD_DEAD
#define DEAD_DEAD
Definition: g_local.h:115
tank_frames_stop_run
mframe_t tank_frames_stop_run[]
Definition: m_tank.c:209
FRAME_pain301
#define FRAME_pain301
Definition: m_actor.h:104
AI_BRUTAL
#define AI_BRUTAL
Definition: g_local.h:138
tank_idle
void tank_idle(edict_t *self)
Definition: m_tank.c:70
FRAME_attak429
#define FRAME_attak429
Definition: m_tank.h:220
DEFAULT_BULLET_HSPREAD
#define DEFAULT_BULLET_HSPREAD
Definition: g_local.h:670
ThrowGib
void ThrowGib(edict_t *self, char *gibname, int damage, int type)
Definition: g_misc.c:135
FRAME_walk21
#define FRAME_walk21
Definition: m_boss31.h:207
VectorSubtract
#define VectorSubtract(a, b, c)
Definition: q_shared.h:163
FRAME_walk05
#define FRAME_walk05
Definition: m_actor.h:279
tank_stand
void tank_stand(edict_t *self)
Definition: m_tank.c:115
MZ2_TANK_ROCKET_3
#define MZ2_TANK_ROCKET_3
Definition: q_shared.h:694
ai_charge
void ai_charge(edict_t *self, float dist)
Definition: g_ai.c:194
SOLID_BBOX
@ SOLID_BBOX
Definition: game.h:37
MZ2_TANK_BLASTER_2
#define MZ2_TANK_BLASTER_2
Definition: q_shared.h:671
tank_frames_attack_pre_rocket
mframe_t tank_frames_attack_pre_rocket[]
Definition: m_tank.c:530
tank_move_stop_walk
mmove_t tank_move_stop_walk
Definition: m_tank.c:165
tank_move_stop_run
mmove_t tank_move_stop_run
Definition: m_tank.c:217
FRAME_attak353
#define FRAME_attak353
Definition: m_tank.h:191
FRAME_stand01
#define FRAME_stand01
Definition: m_boss31.h:136
sound_pain
static int sound_pain
Definition: m_tank.c:37
tank_poststrike
void tank_poststrike(edict_t *self)
Definition: m_tank.c:481
tank_thud
void tank_thud(edict_t *self)
Definition: m_tank.c:60
FRAME_walk04
#define FRAME_walk04
Definition: m_actor.h:278
FRAME_death101
#define FRAME_death101
Definition: m_actor.h:28
FRAME_death132
#define FRAME_death132
Definition: m_soldier.h:327
AI_STAND_GROUND
#define AI_STAND_GROUND
Definition: g_local.h:129
MODEL_SCALE
#define MODEL_SCALE
Definition: m_actor.h:506
FRAME_attak419
#define FRAME_attak419
Definition: m_boss32.h:251
tank_move_start_walk
mmove_t tank_move_start_walk
Definition: m_tank.c:134
DAMAGE_YES
@ DAMAGE_YES
Definition: g_local.h:89
game_import_t::sound
void(* sound)(edict_t *ent, int channel, int soundindex, float volume, float attenuation, float timeofs)
Definition: game.h:109
ATTN_IDLE
#define ATTN_IDLE
Definition: q_shared.h:996
MZ2_TANK_ROCKET_1
#define MZ2_TANK_ROCKET_1
Definition: q_shared.h:692
tank_frames_death1
mframe_t tank_frames_death1[]
Definition: m_tank.c:716
tank_frames_run
mframe_t tank_frames_run[]
Definition: m_tank.c:188
range
GLsizei range
Definition: qgl_win.c:121
sound_sight
static int sound_sight
Definition: m_tank.c:41
ATTN_NORM
#define ATTN_NORM
Definition: q_shared.h:995
FRAME_pain101
#define FRAME_pain101
Definition: m_actor.h:98
walkmonster_start
void walkmonster_start(edict_t *self)
Definition: g_monster.c:692
MOVETYPE_STEP
@ MOVETYPE_STEP
Definition: g_local.h:196
FRAME_attak111
#define FRAME_attak111
Definition: m_boss31.h:34
sound_idle
static int sound_idle
Definition: m_tank.c:38
tank_move_pain1
mmove_t tank_move_pain1
Definition: m_tank.c:254
sound_windup
static int sound_windup
Definition: m_tank.c:42
FRAME_attak201
#define FRAME_attak201
Definition: m_boss31.h:42
SVF_DEADMONSTER
#define SVF_DEADMONSTER
Definition: game.h:28
tank_move_attack_blast
mmove_t tank_move_attack_blast
Definition: m_tank.c:443
tank_frames_start_walk
mframe_t tank_frames_start_walk[]
Definition: m_tank.c:127
AngleVectors
void AngleVectors(vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
Definition: q_shared.c:93
MZ2_TANK_MACHINEGUN_1
#define MZ2_TANK_MACHINEGUN_1
Definition: q_shared.h:673
monster_flash_offset
vec3_t monster_flash_offset[]
Definition: m_flash.c:27
CHAN_VOICE
#define CHAN_VOICE
Definition: q_shared.h:985
FRAME_attak406
#define FRAME_attak406
Definition: m_boss32.h:238
tank_move_death
mmove_t tank_move_death
Definition: m_tank.c:751
vectoangles
void vectoangles(vec3_t vec, vec3_t angles)
Definition: g_utils.c:356
DEFAULT_BULLET_VSPREAD
#define DEFAULT_BULLET_VSPREAD
Definition: g_local.h:671
FRAME_pain316
#define FRAME_pain316
Definition: m_boss31.h:126
FRAME_attak117
#define FRAME_attak117
Definition: m_boss31.h:40
edict_s
Definition: g_local.h:968
G_FreeEdict
void G_FreeEdict(edict_t *e)
Definition: g_utils.c:452
GIB_METALLIC
#define GIB_METALLIC
Definition: g_local.h:126
sound_thud
static int sound_thud
Definition: m_tank.c:36
r
GLdouble GLdouble r
Definition: qgl_win.c:336
TankRocket
void TankRocket(edict_t *self)
Definition: m_tank.c:361
FRAME_attak110
#define FRAME_attak110
Definition: m_boss31.h:33
FRAME_stand30
#define FRAME_stand30
Definition: m_boss2.h:24
tank_frames_attack_blast
mframe_t tank_frames_attack_blast[]
Definition: m_tank.c:424
game_import_t::soundindex
int(* soundindex)(char *name)
Definition: game.h:122
forward
static vec3_t forward
Definition: p_view.c:29
EF_BLASTER
#define EF_BLASTER
Definition: q_shared.h:564
VectorLength
vec_t VectorLength(vec3_t v)
Definition: q_shared.c:762
FRAME_attak331
#define FRAME_attak331
Definition: m_float.h:124
tank_frames_reattack_blast
mframe_t tank_frames_reattack_blast[]
Definition: m_tank.c:445
game_import_t::modelindex
int(* modelindex)(char *name)
Definition: game.h:121
TankMachineGun
void TankMachineGun(edict_t *self)
Definition: m_tank.c:387
tank_doattack_rocket
void tank_doattack_rocket(edict_t *self)
Definition: m_tank.c:650
FRAME_attak301
#define FRAME_attak301
Definition: m_boss32.h:225
mframe_t
Definition: g_local.h:403
FRAME_attak116
#define FRAME_attak116
Definition: m_boss31.h:39
mmove_t
Definition: g_local.h:410
sound_step
static int sound_step
Definition: m_tank.c:40
FRAME_attak415
#define FRAME_attak415
Definition: m_boss32.h:247
tank_frames_stop_walk
mframe_t tank_frames_stop_walk[]
Definition: m_tank.c:157
tank_footstep
void tank_footstep(edict_t *self)
Definition: m_tank.c:55
cvar_s::value
float value
Definition: q_shared.h:331
SP_monster_tank
void SP_monster_tank(edict_t *self)
Definition: m_tank.c:792
tank_frames_attack_post_rocket
mframe_t tank_frames_attack_post_rocket[]
Definition: m_tank.c:572
ai_walk
void ai_walk(edict_t *self, float dist)
Definition: g_ai.c:163
random
#define random()
Definition: g_local.h:515
FRAME_attak324
#define FRAME_attak324
Definition: m_float.h:117
VectorNormalize
vec_t VectorNormalize(vec3_t v)
Definition: q_shared.c:681
NULL
#define NULL
Definition: q_shared.h:67
tank_frames_attack_post_blast
mframe_t tank_frames_attack_post_blast[]
Definition: m_tank.c:456
tank_walk
void tank_walk(edict_t *self)
Definition: m_tank.c:167
FRAME_attak327
#define FRAME_attak327
Definition: m_float.h:120
FRAME_walk20
#define FRAME_walk20
Definition: m_boss2.h:93
sound_die
static int sound_die
Definition: m_tank.c:39
monster_fire_bullet
void monster_fire_bullet(edict_t *self, vec3_t start, vec3_t dir, int damage, int kick, int hspread, int vspread, int flashtype)
Definition: g_monster.c:31
tank_frames_stand
mframe_t tank_frames_stand[]
Definition: m_tank.c:80
monster_fire_rocket
void monster_fire_rocket(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int flashtype)
Definition: g_monster.c:71
skill
cvar_t * skill
Definition: g_main.c:38
tank_move_attack_post_rocket
mmove_t tank_move_attack_post_rocket
Definition: m_tank.c:600
MZ2_TANK_ROCKET_2
#define MZ2_TANK_ROCKET_2
Definition: q_shared.h:693
tank_run
void tank_run(edict_t *self)
Definition: m_tank.c:219
ai_move
void ai_move(edict_t *self, float dist)
Definition: g_ai.c:92
tank_frames_attack_fire_rocket
mframe_t tank_frames_attack_fire_rocket[]
Definition: m_tank.c:558
monster_fire_blaster
void monster_fire_blaster(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int flashtype, int effect)
Definition: g_monster.c:51
MZ2_TANK_BLASTER_3
#define MZ2_TANK_BLASTER_3
Definition: q_shared.h:672
tank_move_attack_pre_rocket
mmove_t tank_move_attack_pre_rocket
Definition: m_tank.c:556
VectorCopy
#define VectorCopy(a, b)
Definition: q_shared.h:165
sound_strike
static int sound_strike
Definition: m_tank.c:43
tank_frames_start_run
mframe_t tank_frames_start_run[]
Definition: m_tank.c:179
visible
qboolean visible(edict_t *self, edict_t *other)
Definition: g_ai.c:287
m_tank.h
tank_move_attack_chain
mmove_t tank_move_attack_chain
Definition: m_tank.c:634
CHAN_WEAPON
#define CHAN_WEAPON
Definition: q_shared.h:984
tank_move_attack_strike
mmove_t tank_move_attack_strike
Definition: m_tank.c:528
tank_move_walk
mmove_t tank_move_walk
Definition: m_tank.c:155
level
GLint level
Definition: qgl_win.c:116
ai_run
void ai_run(edict_t *self, float dist)
Definition: g_ai.c:914
FRAME_attak411
#define FRAME_attak411
Definition: m_boss32.h:243
tank_frames_pain1
mframe_t tank_frames_pain1[]
Definition: m_tank.c:247
FRAME_attak238
#define FRAME_attak238
Definition: m_tank.h:138
FRAME_walk01
#define FRAME_walk01
Definition: m_actor.h:275
GIB_ORGANIC
#define GIB_ORGANIC
Definition: g_local.h:125
tank_frames_pain3
mframe_t tank_frames_pain3[]
Definition: m_tank.c:266
FRAME_attak330
#define FRAME_attak330
Definition: m_float.h:123
tank_frames_attack_strike
mframe_t tank_frames_attack_strike[]
Definition: m_tank.c:487
tank_pain
void tank_pain(edict_t *self, edict_t *other, float kick, int damage)
Definition: m_tank.c:288
tank_attack
void tank_attack(edict_t *self)
Definition: m_tank.c:655
ThrowHead
void ThrowHead(edict_t *self, char *gibname, int damage, int type)
Definition: g_misc.c:183
tank_sight
void tank_sight(edict_t *self, edict_t *other)
Definition: m_tank.c:49
FRAME_pain201
#define FRAME_pain201
Definition: m_actor.h:101
tank_refire_rocket
void tank_refire_rocket(edict_t *self)
Definition: m_tank.c:636
TankStrike
void TankStrike(edict_t *self)
Definition: m_tank.c:356
MOVETYPE_TOSS
@ MOVETYPE_TOSS
Definition: g_local.h:198
tank_dead
void tank_dead(edict_t *self)
Definition: m_tank.c:706
tank_frames_pain2
mframe_t tank_frames_pain2[]
Definition: m_tank.c:256
VectorSet
#define VectorSet(v, x, y, z)
Definition: q_shared.h:168
right
GLdouble right
Definition: qgl_win.c:159
tank_move_run
mmove_t tank_move_run
Definition: m_tank.c:207
tank_move_attack_post_blast
mmove_t tank_move_attack_post_blast
Definition: m_tank.c:465
tank_move_start_run
mmove_t tank_move_start_run
Definition: m_tank.c:186
CHAN_BODY
#define CHAN_BODY
Definition: q_shared.h:987
FRAME_pain104
#define FRAME_pain104
Definition: m_brain.h:115
tank_reattack_blaster
void tank_reattack_blaster(edict_t *self)
Definition: m_tank.c:467
game_import_t::linkentity
void(* linkentity)(edict_t *ent)
Definition: game.h:138
tank_frames_attack_chain
mframe_t tank_frames_attack_chain[]
Definition: m_tank.c:602
tank_frames_walk
mframe_t tank_frames_walk[]
Definition: m_tank.c:136
FRAME_attak113
#define FRAME_attak113
Definition: m_boss31.h:36
FRAME_attak321
#define FRAME_attak321
Definition: m_float.h:114
vec3_t
vec_t vec3_t[3]
Definition: q_shared.h:134
TankBlaster
void TankBlaster(edict_t *self)
Definition: m_tank.c:331
MZ2_TANK_BLASTER_1
#define MZ2_TANK_BLASTER_1
Definition: q_shared.h:670
FRAME_attak322
#define FRAME_attak322
Definition: m_float.h:115
FRAME_walk25
#define FRAME_walk25
Definition: m_boss31.h:211
tank_move_pain3
mmove_t tank_move_pain3
Definition: m_tank.c:285
ai_stand
void ai_stand(edict_t *self, float dist)
Definition: g_ai.c:106
tank_move_attack_fire_rocket
mmove_t tank_move_attack_fire_rocket
Definition: m_tank.c:570
FRAME_attak101
#define FRAME_attak101
Definition: m_boss31.h:24
tank_move_stand
mmove_t tank_move_stand
Definition: m_tank.c:113
FRAME_attak122
#define FRAME_attak122
Definition: m_chick.h:45
g_local.h
tank_move_pain2
mmove_t tank_move_pain2
Definition: m_tank.c:264