icculus quake2 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},
132  {ai_walk, 11, tank_footstep}
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},
145  {ai_walk, 4, tank_footstep},
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},
153  {ai_walk, 6, tank_footstep}
154 };
156 
158 {
159  {ai_walk, 3, NULL},
160  {ai_walk, 3, NULL},
161  {ai_walk, 2, NULL},
162  {ai_walk, 2, NULL},
163  {ai_walk, 4, tank_footstep}
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},
205  {ai_run, 6, tank_footstep}
206 };
208 
210 {
211  {ai_run, 3, NULL},
212  {ai_run, 3, NULL},
213  {ai_run, 2, NULL},
214  {ai_run, 2, NULL},
215  {ai_run, 4, tank_footstep}
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},
283  {ai_move, 0, tank_footstep}
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},
438  {ai_charge, 0, TankBlaster},
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},
449  {ai_charge, 0, TankBlaster},
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},
495  {ai_move, 9, tank_footstep},
496  {ai_move, 2, NULL},
497  {ai_move, 1, NULL},
498  {ai_move, 2, NULL},
499  {ai_move, 2, tank_footstep},
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},
526  {ai_move, -2, tank_footstep}
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},
548  {ai_charge, 7, tank_footstep},
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},
590  {ai_charge, -1, tank_footstep},
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:113
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:136
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:664
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:156
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:718
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:695
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:127
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:87
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:1020
MZ2_TANK_ROCKET_1
#define MZ2_TANK_ROCKET_1
Definition: q_shared.h:716
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:1019
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:194
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:697
monster_flash_offset
vec3_t monster_flash_offset[]
Definition: m_flash.c:27
CHAN_VOICE
#define CHAN_VOICE
Definition: q_shared.h:1009
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:665
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:962
G_FreeEdict
void G_FreeEdict(edict_t *e)
Definition: g_utils.c:452
GIB_METALLIC
#define GIB_METALLIC
Definition: g_local.h:124
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:560
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:401
FRAME_attak116
#define FRAME_attak116
Definition: m_boss31.h:39
mmove_t
Definition: g_local.h:408
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:324
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:509
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:60
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:717
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:696
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:158
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:1008
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:915
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:123
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:196
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:161
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:1011
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:127
TankBlaster
void TankBlaster(edict_t *self)
Definition: m_tank.c:331
MZ2_TANK_BLASTER_1
#define MZ2_TANK_BLASTER_1
Definition: q_shared.h:694
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