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