|
|
1.1 root 1: /*
2: ==============================================================================
3:
4: SOLDIER
5:
6: ==============================================================================
7: */
8:
9: #include "g_local.h"
10: #include "m_soldier.h"
11:
12:
13: static int sound_idle;
14: static int sound_sight1;
15: static int sound_sight2;
16: static int sound_pain_light;
17: static int sound_pain;
18: static int sound_pain_ss;
19: static int sound_death_light;
20: static int sound_death;
21: static int sound_death_ss;
22: static int sound_cock;
23:
24:
25: void soldier_idle (edict_t *self)
26: {
27: if (random() > 0.8)
28: gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
29: }
30:
31: void soldier_cock (edict_t *self)
32: {
33: if (self->s.frame == FRAME_stand322)
34: gi.sound (self, CHAN_WEAPON, sound_cock, 1, ATTN_IDLE, 0);
35: else
36: gi.sound (self, CHAN_WEAPON, sound_cock, 1, ATTN_NORM, 0);
37: }
38:
39:
40: // STAND
41:
42: void soldier_stand (edict_t *self);
43:
44: mframe_t soldier_frames_stand1 [] =
45: {
46: ai_stand, 0, soldier_idle,
47: ai_stand, 0, NULL,
48: ai_stand, 0, NULL,
49: ai_stand, 0, NULL,
50: ai_stand, 0, NULL,
51: ai_stand, 0, NULL,
52: ai_stand, 0, NULL,
53: ai_stand, 0, NULL,
54: ai_stand, 0, NULL,
55: ai_stand, 0, NULL,
56:
57: ai_stand, 0, NULL,
58: ai_stand, 0, NULL,
59: ai_stand, 0, NULL,
60: ai_stand, 0, NULL,
61: ai_stand, 0, NULL,
62: ai_stand, 0, NULL,
63: ai_stand, 0, NULL,
64: ai_stand, 0, NULL,
65: ai_stand, 0, NULL,
66: ai_stand, 0, NULL,
67:
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: };
79: mmove_t soldier_move_stand1 = {FRAME_stand101, FRAME_stand130, soldier_frames_stand1, soldier_stand};
80:
81: mframe_t soldier_frames_stand3 [] =
82: {
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: 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:
105: ai_stand, 0, NULL,
106: ai_stand, 0, soldier_cock,
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: ai_stand, 0, NULL,
113: ai_stand, 0, NULL,
114: ai_stand, 0, NULL,
115:
116: ai_stand, 0, NULL,
117: ai_stand, 0, NULL,
118: ai_stand, 0, NULL,
119: ai_stand, 0, NULL,
120: ai_stand, 0, NULL,
121: ai_stand, 0, NULL,
122: ai_stand, 0, NULL,
123: ai_stand, 0, NULL,
124: ai_stand, 0, NULL
125: };
126: mmove_t soldier_move_stand3 = {FRAME_stand301, FRAME_stand339, soldier_frames_stand3, soldier_stand};
127:
128: #if 0
129: mframe_t soldier_frames_stand4 [] =
130: {
131: ai_stand, 0, NULL,
132: ai_stand, 0, NULL,
133: ai_stand, 0, NULL,
134: ai_stand, 0, NULL,
135: ai_stand, 0, NULL,
136: ai_stand, 0, NULL,
137: ai_stand, 0, NULL,
138: ai_stand, 0, NULL,
139: ai_stand, 0, NULL,
140: ai_stand, 0, NULL,
141:
142: ai_stand, 0, NULL,
143: ai_stand, 0, NULL,
144: ai_stand, 0, NULL,
145: ai_stand, 0, NULL,
146: ai_stand, 0, NULL,
147: ai_stand, 0, NULL,
148: ai_stand, 0, NULL,
149: ai_stand, 0, NULL,
150: ai_stand, 0, NULL,
151: ai_stand, 0, NULL,
152:
153: ai_stand, 0, NULL,
154: ai_stand, 0, NULL,
155: ai_stand, 0, NULL,
156: ai_stand, 0, NULL,
157: ai_stand, 0, NULL,
158: ai_stand, 0, NULL,
159: ai_stand, 0, NULL,
160: ai_stand, 0, NULL,
161: ai_stand, 0, NULL,
162: ai_stand, 0, NULL,
163:
164: ai_stand, 0, NULL,
165: ai_stand, 0, NULL,
166: ai_stand, 0, NULL,
167: ai_stand, 0, NULL,
168: ai_stand, 0, NULL,
169: ai_stand, 0, NULL,
170: ai_stand, 0, NULL,
171: ai_stand, 0, NULL,
172: ai_stand, 0, NULL,
173: ai_stand, 0, NULL,
174:
175: ai_stand, 0, NULL,
176: ai_stand, 0, NULL,
177: ai_stand, 0, NULL,
178: ai_stand, 0, NULL,
179: ai_stand, 0, NULL,
180: ai_stand, 0, NULL,
181: ai_stand, 4, NULL,
182: ai_stand, 1, NULL,
183: ai_stand, -1, NULL,
184: ai_stand, -2, NULL,
185:
186: ai_stand, 0, NULL,
187: ai_stand, 0, NULL
188: };
189: mmove_t soldier_move_stand4 = {FRAME_stand401, FRAME_stand452, soldier_frames_stand4, NULL};
190: #endif
191:
192: void soldier_stand (edict_t *self)
193: {
194: if ((self->monsterinfo.currentmove == &soldier_move_stand3) || (random() < 0.8))
195: self->monsterinfo.currentmove = &soldier_move_stand1;
196: else
197: self->monsterinfo.currentmove = &soldier_move_stand3;
198: }
199:
200:
201: //
202: // WALK
203: //
204:
205: void soldier_walk1_random (edict_t *self)
206: {
207: if (random() > 0.1)
208: self->monsterinfo.nextframe = FRAME_walk101;
209: }
210:
211: mframe_t soldier_frames_walk1 [] =
212: {
213: ai_walk, 3, NULL,
214: ai_walk, 6, NULL,
215: ai_walk, 2, NULL,
216: ai_walk, 2, NULL,
217: ai_walk, 2, NULL,
218: ai_walk, 1, NULL,
219: ai_walk, 6, NULL,
220: ai_walk, 5, NULL,
221: ai_walk, 3, NULL,
222: ai_walk, -1, soldier_walk1_random,
223: ai_walk, 0, NULL,
224: ai_walk, 0, NULL,
225: ai_walk, 0, NULL,
226: ai_walk, 0, NULL,
227: ai_walk, 0, NULL,
228: ai_walk, 0, NULL,
229: ai_walk, 0, NULL,
230: ai_walk, 0, NULL,
231: ai_walk, 0, NULL,
232: ai_walk, 0, NULL,
233: ai_walk, 0, NULL,
234: ai_walk, 0, NULL,
235: ai_walk, 0, NULL,
236: ai_walk, 0, NULL,
237: ai_walk, 0, NULL,
238: ai_walk, 0, NULL,
239: ai_walk, 0, NULL,
240: ai_walk, 0, NULL,
241: ai_walk, 0, NULL,
242: ai_walk, 0, NULL,
243: ai_walk, 0, NULL,
244: ai_walk, 0, NULL,
245: ai_walk, 0, NULL
246: };
247: mmove_t soldier_move_walk1 = {FRAME_walk101, FRAME_walk133, soldier_frames_walk1, NULL};
248:
249: mframe_t soldier_frames_walk2 [] =
250: {
251: ai_walk, 4, NULL,
252: ai_walk, 4, NULL,
253: ai_walk, 9, NULL,
254: ai_walk, 8, NULL,
255: ai_walk, 5, NULL,
256: ai_walk, 1, NULL,
257: ai_walk, 3, NULL,
258: ai_walk, 7, NULL,
259: ai_walk, 6, NULL,
260: ai_walk, 7, NULL
261: };
262: mmove_t soldier_move_walk2 = {FRAME_walk209, FRAME_walk218, soldier_frames_walk2, NULL};
263:
264: void soldier_walk (edict_t *self)
265: {
266: if (random() < 0.5)
267: self->monsterinfo.currentmove = &soldier_move_walk1;
268: else
269: self->monsterinfo.currentmove = &soldier_move_walk2;
270: }
271:
272:
273: //
274: // RUN
275: //
276:
277: void soldier_run (edict_t *self);
278:
279: mframe_t soldier_frames_start_run [] =
280: {
281: ai_run, 7, NULL,
282: ai_run, 5, NULL
283: };
284: mmove_t soldier_move_start_run = {FRAME_run01, FRAME_run02, soldier_frames_start_run, soldier_run};
285:
286: mframe_t soldier_frames_run [] =
287: {
288: ai_run, 10, NULL,
289: ai_run, 11, NULL,
290: ai_run, 11, NULL,
291: ai_run, 16, NULL,
292: ai_run, 10, NULL,
293: ai_run, 15, NULL
294: };
295: mmove_t soldier_move_run = {FRAME_run03, FRAME_run08, soldier_frames_run, NULL};
296:
297: void soldier_run (edict_t *self)
298: {
299: if (self->monsterinfo.aiflags & AI_STAND_GROUND)
300: {
301: self->monsterinfo.currentmove = &soldier_move_stand1;
302: return;
303: }
304:
305: if (self->monsterinfo.currentmove == &soldier_move_walk1 ||
306: self->monsterinfo.currentmove == &soldier_move_walk2 ||
307: self->monsterinfo.currentmove == &soldier_move_start_run)
308: {
309: self->monsterinfo.currentmove = &soldier_move_run;
310: }
311: else
312: {
313: self->monsterinfo.currentmove = &soldier_move_start_run;
314: }
315: }
316:
317:
318: //
319: // PAIN
320: //
321:
322: mframe_t soldier_frames_pain1 [] =
323: {
324: ai_move, -3, NULL,
325: ai_move, 4, NULL,
326: ai_move, 1, NULL,
327: ai_move, 1, NULL,
328: ai_move, 0, NULL
329: };
330: mmove_t soldier_move_pain1 = {FRAME_pain101, FRAME_pain105, soldier_frames_pain1, soldier_run};
331:
332: mframe_t soldier_frames_pain2 [] =
333: {
334: ai_move, -13, NULL,
335: ai_move, -1, NULL,
336: ai_move, 2, NULL,
337: ai_move, 4, NULL,
338: ai_move, 2, NULL,
339: ai_move, 3, NULL,
340: ai_move, 2, NULL
341: };
342: mmove_t soldier_move_pain2 = {FRAME_pain201, FRAME_pain207, soldier_frames_pain2, soldier_run};
343:
344: mframe_t soldier_frames_pain3 [] =
345: {
346: ai_move, -8, NULL,
347: ai_move, 10, NULL,
348: ai_move, -4, NULL,
349: ai_move, -1, NULL,
350: ai_move, -3, NULL,
351: ai_move, 0, NULL,
352: ai_move, 3, NULL,
353: ai_move, 0, NULL,
354: ai_move, 0, NULL,
355: ai_move, 0, NULL,
356: ai_move, 0, NULL,
357: ai_move, 1, NULL,
358: ai_move, 0, NULL,
359: ai_move, 1, NULL,
360: ai_move, 2, NULL,
361: ai_move, 4, NULL,
362: ai_move, 3, NULL,
363: ai_move, 2, NULL
364: };
365: mmove_t soldier_move_pain3 = {FRAME_pain301, FRAME_pain318, soldier_frames_pain3, soldier_run};
366:
367: mframe_t soldier_frames_pain4 [] =
368: {
369: ai_move, 0, NULL,
370: ai_move, 0, NULL,
371: ai_move, 0, NULL,
372: ai_move, -10, NULL,
373: ai_move, -6, NULL,
374: ai_move, 8, NULL,
375: ai_move, 4, NULL,
376: ai_move, 1, NULL,
377: ai_move, 0, NULL,
378: ai_move, 2, NULL,
379: ai_move, 5, NULL,
380: ai_move, 2, NULL,
381: ai_move, -1, NULL,
382: ai_move, -1, NULL,
383: ai_move, 3, NULL,
384: ai_move, 2, NULL,
385: ai_move, 0, NULL
386: };
387: mmove_t soldier_move_pain4 = {FRAME_pain401, FRAME_pain417, soldier_frames_pain4, soldier_run};
388:
389:
390: void soldier_pain (edict_t *self, edict_t *other, float kick, int damage)
391: {
392: float r;
393: int n;
394:
395: if (self->health < (self->max_health / 2))
396: self->s.skinnum |= 1;
397:
398: if (level.time < self->pain_debounce_time)
399: {
400: if ((self->velocity[2] > 100) && ( (self->monsterinfo.currentmove == &soldier_move_pain1) || (self->monsterinfo.currentmove == &soldier_move_pain2) || (self->monsterinfo.currentmove == &soldier_move_pain3)))
401: self->monsterinfo.currentmove = &soldier_move_pain4;
402: return;
403: }
404:
405: self->pain_debounce_time = level.time + 3;
406:
407: n = self->s.skinnum | 1;
408: if (n == 1)
409: gi.sound (self, CHAN_VOICE, sound_pain_light, 1, ATTN_NORM, 0);
410: else if (n == 3)
411: gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
412: else
413: gi.sound (self, CHAN_VOICE, sound_pain_ss, 1, ATTN_NORM, 0);
414:
415: if (self->velocity[2] > 100)
416: {
417: self->monsterinfo.currentmove = &soldier_move_pain4;
418: return;
419: }
420:
421: if (skill->value == 3)
422: return; // no pain anims in nightmare
423:
424: r = random();
425:
426: if (r < 0.33)
427: self->monsterinfo.currentmove = &soldier_move_pain1;
428: else if (r < 0.66)
429: self->monsterinfo.currentmove = &soldier_move_pain2;
430: else
431: self->monsterinfo.currentmove = &soldier_move_pain3;
432: }
433:
434:
435: //
436: // ATTACK
437: //
438:
439: static int blaster_flash [] = {MZ2_SOLDIER_BLASTER_1, MZ2_SOLDIER_BLASTER_2, MZ2_SOLDIER_BLASTER_3, MZ2_SOLDIER_BLASTER_4, MZ2_SOLDIER_BLASTER_5, MZ2_SOLDIER_BLASTER_6, MZ2_SOLDIER_BLASTER_7, MZ2_SOLDIER_BLASTER_8};
440: static int shotgun_flash [] = {MZ2_SOLDIER_SHOTGUN_1, MZ2_SOLDIER_SHOTGUN_2, MZ2_SOLDIER_SHOTGUN_3, MZ2_SOLDIER_SHOTGUN_4, MZ2_SOLDIER_SHOTGUN_5, MZ2_SOLDIER_SHOTGUN_6, MZ2_SOLDIER_SHOTGUN_7, MZ2_SOLDIER_SHOTGUN_8};
441: static int machinegun_flash [] = {MZ2_SOLDIER_MACHINEGUN_1, MZ2_SOLDIER_MACHINEGUN_2, MZ2_SOLDIER_MACHINEGUN_3, MZ2_SOLDIER_MACHINEGUN_4, MZ2_SOLDIER_MACHINEGUN_5, MZ2_SOLDIER_MACHINEGUN_6, MZ2_SOLDIER_MACHINEGUN_7, MZ2_SOLDIER_MACHINEGUN_8};
442:
443: void soldier_fire (edict_t *self, int flash_number)
444: {
445: vec3_t start;
446: vec3_t forward, right, up;
447: vec3_t aim;
448: vec3_t dir;
449: vec3_t end;
450: float r, u;
451: int flash_index;
452:
453: if (self->s.skinnum < 2)
454: flash_index = blaster_flash[flash_number];
455: else if (self->s.skinnum < 4)
456: flash_index = shotgun_flash[flash_number];
457: else
458: flash_index = machinegun_flash[flash_number];
459:
460: AngleVectors (self->s.angles, forward, right, NULL);
461: G_ProjectSource (self->s.origin, monster_flash_offset[flash_index], forward, right, start);
462:
463: if (flash_number == 5 || flash_number == 6)
464: {
465: VectorCopy (forward, aim);
466: }
467: else
468: {
469: VectorCopy (self->enemy->s.origin, end);
470: end[2] += self->enemy->viewheight;
471: VectorSubtract (end, start, aim);
472: vectoangles (aim, dir);
473: AngleVectors (dir, forward, right, up);
474:
475: r = crandom()*1000;
476: u = crandom()*500;
477: VectorMA (start, 8192, forward, end);
478: VectorMA (end, r, right, end);
479: VectorMA (end, u, up, end);
480:
481: VectorSubtract (end, start, aim);
482: VectorNormalize (aim);
483: }
484:
485: if (self->s.skinnum <= 1)
486: {
487: monster_fire_blaster (self, start, aim, 5, 600, flash_index, EF_BLASTER);
488: }
489: else if (self->s.skinnum <= 3)
490: {
491: monster_fire_shotgun (self, start, aim, 2, 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, flash_index);
492: }
493: else
494: {
495: if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME))
496: self->monsterinfo.pausetime = level.time + (3 + rand() % 8) * FRAMETIME;
497:
498: monster_fire_bullet (self, start, aim, 2, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_index);
499:
500: if (level.time >= self->monsterinfo.pausetime)
501: self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
502: else
503: self->monsterinfo.aiflags |= AI_HOLD_FRAME;
504: }
505: }
506:
507: // ATTACK1 (blaster/shotgun)
508:
509: void soldier_fire1 (edict_t *self)
510: {
511: soldier_fire (self, 0);
512: }
513:
514: void soldier_attack1_refire1 (edict_t *self)
515: {
516: if (self->s.skinnum > 1)
517: return;
518:
519: if (self->enemy->health <= 0)
520: return;
521:
522: if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
523: self->monsterinfo.nextframe = FRAME_attak102;
524: else
525: self->monsterinfo.nextframe = FRAME_attak110;
526: }
527:
528: void soldier_attack1_refire2 (edict_t *self)
529: {
530: if (self->s.skinnum < 2)
531: return;
532:
533: if (self->enemy->health <= 0)
534: return;
535:
536: if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
537: self->monsterinfo.nextframe = FRAME_attak102;
538: }
539:
540: mframe_t soldier_frames_attack1 [] =
541: {
542: ai_charge, 0, NULL,
543: ai_charge, 0, NULL,
544: ai_charge, 0, soldier_fire1,
545: ai_charge, 0, NULL,
546: ai_charge, 0, NULL,
547: ai_charge, 0, soldier_attack1_refire1,
548: ai_charge, 0, NULL,
549: ai_charge, 0, soldier_cock,
550: ai_charge, 0, soldier_attack1_refire2,
551: ai_charge, 0, NULL,
552: ai_charge, 0, NULL,
553: ai_charge, 0, NULL
554: };
555: mmove_t soldier_move_attack1 = {FRAME_attak101, FRAME_attak112, soldier_frames_attack1, soldier_run};
556:
557: // ATTACK2 (blaster/shotgun)
558:
559: void soldier_fire2 (edict_t *self)
560: {
561: soldier_fire (self, 1);
562: }
563:
564: void soldier_attack2_refire1 (edict_t *self)
565: {
566: if (self->s.skinnum > 1)
567: return;
568:
569: if (self->enemy->health <= 0)
570: return;
571:
572: if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
573: self->monsterinfo.nextframe = FRAME_attak204;
574: else
575: self->monsterinfo.nextframe = FRAME_attak216;
576: }
577:
578: void soldier_attack2_refire2 (edict_t *self)
579: {
580: if (self->s.skinnum < 2)
581: return;
582:
583: if (self->enemy->health <= 0)
584: return;
585:
586: if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
587: self->monsterinfo.nextframe = FRAME_attak204;
588: }
589:
590: mframe_t soldier_frames_attack2 [] =
591: {
592: ai_charge, 0, NULL,
593: ai_charge, 0, NULL,
594: ai_charge, 0, NULL,
595: ai_charge, 0, NULL,
596: ai_charge, 0, soldier_fire2,
597: ai_charge, 0, NULL,
598: ai_charge, 0, NULL,
599: ai_charge, 0, soldier_attack2_refire1,
600: ai_charge, 0, NULL,
601: ai_charge, 0, NULL,
602: ai_charge, 0, NULL,
603: ai_charge, 0, NULL,
604: ai_charge, 0, soldier_cock,
605: ai_charge, 0, NULL,
606: ai_charge, 0, soldier_attack2_refire2,
607: ai_charge, 0, NULL,
608: ai_charge, 0, NULL,
609: ai_charge, 0, NULL
610: };
611: mmove_t soldier_move_attack2 = {FRAME_attak201, FRAME_attak218, soldier_frames_attack2, soldier_run};
612:
613: // ATTACK3 (duck and shoot)
614:
615: void soldier_duck_down (edict_t *self)
616: {
617: if (self->monsterinfo.aiflags & AI_DUCKED)
618: return;
619: self->monsterinfo.aiflags |= AI_DUCKED;
620: self->maxs[2] -= 32;
621: self->takedamage = DAMAGE_YES;
622: self->monsterinfo.pausetime = level.time + 1;
623: gi.linkentity (self);
624: }
625:
626: void soldier_duck_up (edict_t *self)
627: {
628: self->monsterinfo.aiflags &= ~AI_DUCKED;
629: self->maxs[2] += 32;
630: self->takedamage = DAMAGE_AIM;
631: gi.linkentity (self);
632: }
633:
634: void soldier_fire3 (edict_t *self)
635: {
636: soldier_duck_down (self);
637: soldier_fire (self, 2);
638: }
639:
640: void soldier_attack3_refire (edict_t *self)
641: {
642: if ((level.time + 0.4) < self->monsterinfo.pausetime)
643: self->monsterinfo.nextframe = FRAME_attak303;
644: }
645:
646: mframe_t soldier_frames_attack3 [] =
647: {
648: ai_charge, 0, NULL,
649: ai_charge, 0, NULL,
650: ai_charge, 0, soldier_fire3,
651: ai_charge, 0, NULL,
652: ai_charge, 0, NULL,
653: ai_charge, 0, soldier_attack3_refire,
654: ai_charge, 0, soldier_duck_up,
655: ai_charge, 0, NULL,
656: ai_charge, 0, NULL
657: };
658: mmove_t soldier_move_attack3 = {FRAME_attak301, FRAME_attak309, soldier_frames_attack3, soldier_run};
659:
660: // ATTACK4 (machinegun)
661:
662: void soldier_fire4 (edict_t *self)
663: {
664: soldier_fire (self, 3);
665: //
666: // if (self->enemy->health <= 0)
667: // return;
668: //
669: // if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
670: // self->monsterinfo.nextframe = FRAME_attak402;
671: }
672:
673: mframe_t soldier_frames_attack4 [] =
674: {
675: ai_charge, 0, NULL,
676: ai_charge, 0, NULL,
677: ai_charge, 0, soldier_fire4,
678: ai_charge, 0, NULL,
679: ai_charge, 0, NULL,
680: ai_charge, 0, NULL
681: };
682: mmove_t soldier_move_attack4 = {FRAME_attak401, FRAME_attak406, soldier_frames_attack4, soldier_run};
683:
684: #if 0
685: // ATTACK5 (prone)
686:
687: void soldier_fire5 (edict_t *self)
688: {
689: soldier_fire (self, 4);
690: }
691:
692: void soldier_attack5_refire (edict_t *self)
693: {
694: if (self->enemy->health <= 0)
695: return;
696:
697: if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
698: self->monsterinfo.nextframe = FRAME_attak505;
699: }
700:
701: mframe_t soldier_frames_attack5 [] =
702: {
703: ai_charge, 8, NULL,
704: ai_charge, 8, NULL,
705: ai_charge, 0, NULL,
706: ai_charge, 0, NULL,
707: ai_charge, 0, soldier_fire5,
708: ai_charge, 0, NULL,
709: ai_charge, 0, NULL,
710: ai_charge, 0, soldier_attack5_refire
711: };
712: mmove_t soldier_move_attack5 = {FRAME_attak501, FRAME_attak508, soldier_frames_attack5, soldier_run};
713: #endif
714:
715: // ATTACK6 (run & shoot)
716:
717: void soldier_fire8 (edict_t *self)
718: {
719: soldier_fire (self, 7);
720: }
721:
722: void soldier_attack6_refire (edict_t *self)
723: {
724: if (self->enemy->health <= 0)
725: return;
726:
727: if (range(self, self->enemy) < RANGE_MID)
728: return;
729:
730: if (skill->value == 3)
731: self->monsterinfo.nextframe = FRAME_runs03;
732: }
733:
734: mframe_t soldier_frames_attack6 [] =
735: {
736: ai_charge, 10, NULL,
737: ai_charge, 4, NULL,
738: ai_charge, 12, NULL,
739: ai_charge, 11, soldier_fire8,
740: ai_charge, 13, NULL,
741: ai_charge, 18, NULL,
742: ai_charge, 15, NULL,
743: ai_charge, 14, NULL,
744: ai_charge, 11, NULL,
745: ai_charge, 8, NULL,
746: ai_charge, 11, NULL,
747: ai_charge, 12, NULL,
748: ai_charge, 12, NULL,
749: ai_charge, 17, soldier_attack6_refire
750: };
751: mmove_t soldier_move_attack6 = {FRAME_runs01, FRAME_runs14, soldier_frames_attack6, soldier_run};
752:
753: void soldier_attack(edict_t *self)
754: {
755: if (self->s.skinnum < 4)
756: {
757: if (random() < 0.5)
758: self->monsterinfo.currentmove = &soldier_move_attack1;
759: else
760: self->monsterinfo.currentmove = &soldier_move_attack2;
761: }
762: else
763: {
764: self->monsterinfo.currentmove = &soldier_move_attack4;
765: }
766: }
767:
768:
769: //
770: // SIGHT
771: //
772:
773: void soldier_sight(edict_t *self, edict_t *other)
774: {
775: if (random() < 0.5)
776: gi.sound (self, CHAN_VOICE, sound_sight1, 1, ATTN_NORM, 0);
777: else
778: gi.sound (self, CHAN_VOICE, sound_sight2, 1, ATTN_NORM, 0);
779:
780: if ((skill->value > 0) && (range(self, self->enemy) >= RANGE_MID))
781: {
782: if (random() > 0.5)
783: self->monsterinfo.currentmove = &soldier_move_attack6;
784: }
785: }
786:
787: //
788: // DUCK
789: //
790:
791: void soldier_duck_hold (edict_t *self)
792: {
793: if (level.time >= self->monsterinfo.pausetime)
794: self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
795: else
796: self->monsterinfo.aiflags |= AI_HOLD_FRAME;
797: }
798:
799: mframe_t soldier_frames_duck [] =
800: {
801: ai_move, 5, soldier_duck_down,
802: ai_move, -1, soldier_duck_hold,
803: ai_move, 1, NULL,
804: ai_move, 0, soldier_duck_up,
805: ai_move, 5, NULL
806: };
807: mmove_t soldier_move_duck = {FRAME_duck01, FRAME_duck05, soldier_frames_duck, soldier_run};
808:
809: void soldier_dodge (edict_t *self, edict_t *attacker, float eta)
810: {
811: float r;
812:
813: r = random();
814: if (r > 0.25)
815: return;
816:
817: if (!self->enemy)
818: self->enemy = attacker;
819:
820: if (skill->value == 0)
821: {
822: self->monsterinfo.currentmove = &soldier_move_duck;
823: return;
824: }
825:
826: self->monsterinfo.pausetime = level.time + eta + 0.3;
827: r = random();
828:
829: if (skill->value == 1)
830: {
831: if (r > 0.33)
832: self->monsterinfo.currentmove = &soldier_move_duck;
833: else
834: self->monsterinfo.currentmove = &soldier_move_attack3;
835: return;
836: }
837:
838: if (skill->value >= 2)
839: {
840: if (r > 0.66)
841: self->monsterinfo.currentmove = &soldier_move_duck;
842: else
843: self->monsterinfo.currentmove = &soldier_move_attack3;
844: return;
845: }
846:
847: self->monsterinfo.currentmove = &soldier_move_attack3;
848: }
849:
850:
851: //
852: // DEATH
853: //
854:
855: void soldier_fire6 (edict_t *self)
856: {
857: soldier_fire (self, 5);
858: }
859:
860: void soldier_fire7 (edict_t *self)
861: {
862: soldier_fire (self, 6);
863: }
864:
865: void soldier_dead (edict_t *self)
866: {
867: VectorSet (self->mins, -16, -16, -24);
868: VectorSet (self->maxs, 16, 16, -8);
869: self->movetype = MOVETYPE_TOSS;
870: self->svflags |= SVF_DEADMONSTER;
871: self->nextthink = 0;
872: gi.linkentity (self);
873: }
874:
875: mframe_t soldier_frames_death1 [] =
876: {
877: ai_move, 0, NULL,
878: ai_move, -10, NULL,
879: ai_move, -10, NULL,
880: ai_move, -10, NULL,
881: ai_move, -5, NULL,
882: ai_move, 0, NULL,
883: ai_move, 0, NULL,
884: ai_move, 0, NULL,
885: ai_move, 0, NULL,
886: ai_move, 0, NULL,
887:
888: ai_move, 0, NULL,
889: ai_move, 0, NULL,
890: ai_move, 0, NULL,
891: ai_move, 0, NULL,
892: ai_move, 0, NULL,
893: ai_move, 0, NULL,
894: ai_move, 0, NULL,
895: ai_move, 0, NULL,
896: ai_move, 0, NULL,
897: ai_move, 0, NULL,
898:
899: ai_move, 0, NULL,
900: ai_move, 0, soldier_fire6,
901: ai_move, 0, NULL,
902: ai_move, 0, NULL,
903: ai_move, 0, soldier_fire7,
904: ai_move, 0, NULL,
905: ai_move, 0, NULL,
906: ai_move, 0, NULL,
907: ai_move, 0, NULL,
908: ai_move, 0, NULL,
909:
910: ai_move, 0, NULL,
911: ai_move, 0, NULL,
912: ai_move, 0, NULL,
913: ai_move, 0, NULL,
914: ai_move, 0, NULL,
915: ai_move, 0, NULL
916: };
917: mmove_t soldier_move_death1 = {FRAME_death101, FRAME_death136, soldier_frames_death1, soldier_dead};
918:
919: mframe_t soldier_frames_death2 [] =
920: {
921: ai_move, -5, NULL,
922: ai_move, -5, NULL,
923: ai_move, -5, NULL,
924: ai_move, 0, NULL,
925: ai_move, 0, NULL,
926: ai_move, 0, NULL,
927: ai_move, 0, NULL,
928: ai_move, 0, NULL,
929: ai_move, 0, NULL,
930: ai_move, 0, NULL,
931:
932: ai_move, 0, NULL,
933: ai_move, 0, NULL,
934: ai_move, 0, NULL,
935: ai_move, 0, NULL,
936: ai_move, 0, NULL,
937: ai_move, 0, NULL,
938: ai_move, 0, NULL,
939: ai_move, 0, NULL,
940: ai_move, 0, NULL,
941: ai_move, 0, NULL,
942:
943: ai_move, 0, NULL,
944: ai_move, 0, NULL,
945: ai_move, 0, NULL,
946: ai_move, 0, NULL,
947: ai_move, 0, NULL,
948: ai_move, 0, NULL,
949: ai_move, 0, NULL,
950: ai_move, 0, NULL,
951: ai_move, 0, NULL,
952: ai_move, 0, NULL,
953:
954: ai_move, 0, NULL,
955: ai_move, 0, NULL,
956: ai_move, 0, NULL,
957: ai_move, 0, NULL,
958: ai_move, 0, NULL
959: };
960: mmove_t soldier_move_death2 = {FRAME_death201, FRAME_death235, soldier_frames_death2, soldier_dead};
961:
962: mframe_t soldier_frames_death3 [] =
963: {
964: ai_move, -5, NULL,
965: ai_move, -5, NULL,
966: ai_move, -5, NULL,
967: ai_move, 0, NULL,
968: ai_move, 0, NULL,
969: ai_move, 0, NULL,
970: ai_move, 0, NULL,
971: ai_move, 0, NULL,
972: ai_move, 0, NULL,
973: ai_move, 0, NULL,
974:
975: ai_move, 0, NULL,
976: ai_move, 0, NULL,
977: ai_move, 0, NULL,
978: ai_move, 0, NULL,
979: ai_move, 0, NULL,
980: ai_move, 0, NULL,
981: ai_move, 0, NULL,
982: ai_move, 0, NULL,
983: ai_move, 0, NULL,
984: ai_move, 0, NULL,
985:
986: ai_move, 0, NULL,
987: ai_move, 0, NULL,
988: ai_move, 0, NULL,
989: ai_move, 0, NULL,
990: ai_move, 0, NULL,
991: ai_move, 0, NULL,
992: ai_move, 0, NULL,
993: ai_move, 0, NULL,
994: ai_move, 0, NULL,
995: ai_move, 0, NULL,
996:
997: ai_move, 0, NULL,
998: ai_move, 0, NULL,
999: ai_move, 0, NULL,
1000: ai_move, 0, NULL,
1001: ai_move, 0, NULL,
1002: ai_move, 0, NULL,
1003: ai_move, 0, NULL,
1004: ai_move, 0, NULL,
1005: ai_move, 0, NULL,
1006: ai_move, 0, NULL,
1007:
1008: ai_move, 0, NULL,
1009: ai_move, 0, NULL,
1010: ai_move, 0, NULL,
1011: ai_move, 0, NULL,
1012: ai_move, 0, NULL,
1013: };
1014: mmove_t soldier_move_death3 = {FRAME_death301, FRAME_death345, soldier_frames_death3, soldier_dead};
1015:
1016: mframe_t soldier_frames_death4 [] =
1017: {
1018: ai_move, 0, NULL,
1019: ai_move, 0, NULL,
1020: ai_move, 0, NULL,
1021: ai_move, 0, NULL,
1022: ai_move, 0, NULL,
1023: ai_move, 0, NULL,
1024: ai_move, 0, NULL,
1025: ai_move, 0, NULL,
1026: ai_move, 0, NULL,
1027: ai_move, 0, NULL,
1028:
1029: ai_move, 0, NULL,
1030: ai_move, 0, NULL,
1031: ai_move, 0, NULL,
1032: ai_move, 0, NULL,
1033: ai_move, 0, NULL,
1034: ai_move, 0, NULL,
1035: ai_move, 0, NULL,
1036: ai_move, 0, NULL,
1037: ai_move, 0, NULL,
1038: ai_move, 0, NULL,
1039:
1040: ai_move, 0, NULL,
1041: ai_move, 0, NULL,
1042: ai_move, 0, NULL,
1043: ai_move, 0, NULL,
1044: ai_move, 0, NULL,
1045: ai_move, 0, NULL,
1046: ai_move, 0, NULL,
1047: ai_move, 0, NULL,
1048: ai_move, 0, NULL,
1049: ai_move, 0, NULL,
1050:
1051: ai_move, 0, NULL,
1052: ai_move, 0, NULL,
1053: ai_move, 0, NULL,
1054: ai_move, 0, NULL,
1055: ai_move, 0, NULL,
1056: ai_move, 0, NULL,
1057: ai_move, 0, NULL,
1058: ai_move, 0, NULL,
1059: ai_move, 0, NULL,
1060: ai_move, 0, NULL,
1061:
1062: ai_move, 0, NULL,
1063: ai_move, 0, NULL,
1064: ai_move, 0, NULL,
1065: ai_move, 0, NULL,
1066: ai_move, 0, NULL,
1067: ai_move, 0, NULL,
1068: ai_move, 0, NULL,
1069: ai_move, 0, NULL,
1070: ai_move, 0, NULL,
1071: ai_move, 0, NULL,
1072:
1073: ai_move, 0, NULL,
1074: ai_move, 0, NULL,
1075: ai_move, 0, NULL
1076: };
1077: mmove_t soldier_move_death4 = {FRAME_death401, FRAME_death453, soldier_frames_death4, soldier_dead};
1078:
1079: mframe_t soldier_frames_death5 [] =
1080: {
1081: ai_move, -5, NULL,
1082: ai_move, -5, NULL,
1083: ai_move, -5, NULL,
1084: ai_move, 0, NULL,
1085: ai_move, 0, NULL,
1086: ai_move, 0, NULL,
1087: ai_move, 0, NULL,
1088: ai_move, 0, NULL,
1089: ai_move, 0, NULL,
1090: ai_move, 0, NULL,
1091:
1092: ai_move, 0, NULL,
1093: ai_move, 0, NULL,
1094: ai_move, 0, NULL,
1095: ai_move, 0, NULL,
1096: ai_move, 0, NULL,
1097: ai_move, 0, NULL,
1098: ai_move, 0, NULL,
1099: ai_move, 0, NULL,
1100: ai_move, 0, NULL,
1101: ai_move, 0, NULL,
1102:
1103: ai_move, 0, NULL,
1104: ai_move, 0, NULL,
1105: ai_move, 0, NULL,
1106: ai_move, 0, NULL
1107: };
1108: mmove_t soldier_move_death5 = {FRAME_death501, FRAME_death524, soldier_frames_death5, soldier_dead};
1109:
1110: mframe_t soldier_frames_death6 [] =
1111: {
1112: ai_move, 0, NULL,
1113: ai_move, 0, NULL,
1114: ai_move, 0, NULL,
1115: ai_move, 0, NULL,
1116: ai_move, 0, NULL,
1117: ai_move, 0, NULL,
1118: ai_move, 0, NULL,
1119: ai_move, 0, NULL,
1120: ai_move, 0, NULL,
1121: ai_move, 0, NULL
1122: };
1123: mmove_t soldier_move_death6 = {FRAME_death601, FRAME_death610, soldier_frames_death6, soldier_dead};
1124:
1125: void soldier_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
1126: {
1127: int n;
1128:
1129: // check for gib
1130: if (self->health <= self->gib_health)
1131: {
1132: gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
1133: for (n= 0; n < 3; n++)
1134: ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
1135: ThrowGib (self, "models/objects/gibs/chest/tris.md2", damage, GIB_ORGANIC);
1136: ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
1137: self->deadflag = DEAD_DEAD;
1138: return;
1139: }
1140:
1141: if (self->deadflag == DEAD_DEAD)
1142: return;
1143:
1144: // regular death
1145: self->deadflag = DEAD_DEAD;
1146: self->takedamage = DAMAGE_YES;
1147: self->s.skinnum |= 1;
1148:
1149: if (self->s.skinnum == 1)
1150: gi.sound (self, CHAN_VOICE, sound_death_light, 1, ATTN_NORM, 0);
1151: else if (self->s.skinnum == 3)
1152: gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0);
1153: else // (self->s.skinnum == 5)
1154: gi.sound (self, CHAN_VOICE, sound_death_ss, 1, ATTN_NORM, 0);
1155:
1156: if (fabs((self->s.origin[2] + self->viewheight) - point[2]) <= 4)
1157: {
1158: // head shot
1159: self->monsterinfo.currentmove = &soldier_move_death3;
1160: return;
1161: }
1162:
1163: n = rand() % 5;
1164: if (n == 0)
1165: self->monsterinfo.currentmove = &soldier_move_death1;
1166: else if (n == 1)
1167: self->monsterinfo.currentmove = &soldier_move_death2;
1168: else if (n == 2)
1169: self->monsterinfo.currentmove = &soldier_move_death4;
1170: else if (n == 3)
1171: self->monsterinfo.currentmove = &soldier_move_death5;
1172: else
1173: self->monsterinfo.currentmove = &soldier_move_death6;
1174: }
1175:
1176:
1177: //
1178: // SPAWN
1179: //
1180:
1181: void SP_monster_soldier_x (edict_t *self)
1182: {
1183:
1184: self->s.modelindex = gi.modelindex ("models/monsters/soldier/tris.md2");
1185: self->monsterinfo.scale = MODEL_SCALE;
1186: VectorSet (self->mins, -16, -16, -24);
1187: VectorSet (self->maxs, 16, 16, 32);
1188: self->movetype = MOVETYPE_STEP;
1189: self->solid = SOLID_BBOX;
1190:
1191: sound_idle = gi.soundindex ("soldier/solidle1.wav");
1192: sound_sight1 = gi.soundindex ("soldier/solsght1.wav");
1193: sound_sight2 = gi.soundindex ("soldier/solsrch1.wav");
1194: sound_cock = gi.soundindex ("infantry/infatck3.wav");
1195:
1196: self->mass = 100;
1197:
1198: self->pain = soldier_pain;
1199: self->die = soldier_die;
1200:
1201: self->monsterinfo.stand = soldier_stand;
1202: self->monsterinfo.walk = soldier_walk;
1203: self->monsterinfo.run = soldier_run;
1204: self->monsterinfo.dodge = soldier_dodge;
1205: self->monsterinfo.attack = soldier_attack;
1206: self->monsterinfo.melee = NULL;
1207: self->monsterinfo.sight = soldier_sight;
1208:
1209: gi.linkentity (self);
1210:
1211: self->monsterinfo.stand (self);
1212:
1213: walkmonster_start (self);
1214: }
1215:
1216:
1217: /*QUAKED monster_soldier_light (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
1218: */
1219: void SP_monster_soldier_light (edict_t *self)
1220: {
1221: if (deathmatch->value)
1222: {
1223: G_FreeEdict (self);
1224: return;
1225: }
1226:
1227: SP_monster_soldier_x (self);
1228:
1229: sound_pain_light = gi.soundindex ("soldier/solpain2.wav");
1230: sound_death_light = gi.soundindex ("soldier/soldeth2.wav");
1231: gi.modelindex ("models/objects/laser/tris.md2");
1232: gi.soundindex ("misc/lasfly.wav");
1233: gi.soundindex ("soldier/solatck2.wav");
1234:
1235: self->s.skinnum = 0;
1236: self->health = 20;
1237: self->gib_health = -30;
1238: }
1239:
1240: /*QUAKED monster_soldier (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
1241: */
1242: void SP_monster_soldier (edict_t *self)
1243: {
1244: if (deathmatch->value)
1245: {
1246: G_FreeEdict (self);
1247: return;
1248: }
1249:
1250: SP_monster_soldier_x (self);
1251:
1252: sound_pain = gi.soundindex ("soldier/solpain1.wav");
1253: sound_death = gi.soundindex ("soldier/soldeth1.wav");
1254: gi.soundindex ("soldier/solatck1.wav");
1255:
1256: self->s.skinnum = 2;
1257: self->health = 30;
1258: self->gib_health = -30;
1259: }
1260:
1261: /*QUAKED monster_soldier_ss (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
1262: */
1263: void SP_monster_soldier_ss (edict_t *self)
1264: {
1265: if (deathmatch->value)
1266: {
1267: G_FreeEdict (self);
1268: return;
1269: }
1270:
1271: SP_monster_soldier_x (self);
1272:
1273: sound_pain_ss = gi.soundindex ("soldier/solpain3.wav");
1274: sound_death_ss = gi.soundindex ("soldier/soldeth3.wav");
1275: gi.soundindex ("soldier/solatck3.wav");
1276:
1277: self->s.skinnum = 4;
1278: self->health = 40;
1279: self->gib_health = -30;
1280: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.