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