|
|
1.1 root 1: /*
2: ==============================================================================
3:
4: SOLDIER
5:
6: ==============================================================================
7: */
8:
9: #include "g_local.h"
10: #include "m_soldier.h"
11:
12: //ROGUE
13: #define RUN_SHOOT 1
14: #define CHECK_TARGET 1
15: //ROGUE
16:
17: static int sound_idle;
18: static int sound_sight1;
19: static int sound_sight2;
20: static int sound_pain_light;
21: static int sound_pain;
22: static int sound_pain_ss;
23: static int sound_death_light;
24: static int sound_death;
25: static int sound_death_ss;
26: static int sound_cock;
27:
28: void soldier_duck_up (edict_t *self);
29:
30: void soldier_start_charge (edict_t *self)
31: {
32: self->monsterinfo.aiflags |= AI_CHARGING;
33: }
34:
35: void soldier_stop_charge (edict_t *self)
36: {
37: self->monsterinfo.aiflags &= ~AI_CHARGING;
38: }
39:
40: void soldier_idle (edict_t *self)
41: {
42: if (random() > 0.8)
43: gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
44: }
45:
46: void soldier_cock (edict_t *self)
47: {
48: if (self->s.frame == FRAME_stand322)
49: gi.sound (self, CHAN_WEAPON, sound_cock, 1, ATTN_IDLE, 0);
50: else
51: gi.sound (self, CHAN_WEAPON, sound_cock, 1, ATTN_NORM, 0);
52: }
53:
54:
55: // STAND
56:
57: void soldier_stand (edict_t *self);
58:
59: mframe_t soldier_frames_stand1 [] =
60: {
61: ai_stand, 0, soldier_idle,
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: ai_stand, 0, NULL,
68: ai_stand, 0, NULL,
69: ai_stand, 0, NULL,
70: ai_stand, 0, NULL,
71:
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:
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 soldier_move_stand1 = {FRAME_stand101, FRAME_stand130, soldier_frames_stand1, soldier_stand};
95:
96: mframe_t soldier_frames_stand3 [] =
97: {
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:
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: ai_stand, 0, NULL,
116: ai_stand, 0, NULL,
117: ai_stand, 0, NULL,
118: ai_stand, 0, NULL,
119:
120: ai_stand, 0, NULL,
121: ai_stand, 0, soldier_cock,
122: ai_stand, 0, NULL,
123: ai_stand, 0, NULL,
124: ai_stand, 0, NULL,
125: ai_stand, 0, NULL,
126: ai_stand, 0, NULL,
127: ai_stand, 0, NULL,
128: ai_stand, 0, NULL,
129: ai_stand, 0, NULL,
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: };
141: mmove_t soldier_move_stand3 = {FRAME_stand301, FRAME_stand339, soldier_frames_stand3, soldier_stand};
142:
143: #if 0
144: mframe_t soldier_frames_stand4 [] =
145: {
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: ai_stand, 0, NULL,
153: ai_stand, 0, NULL,
154: ai_stand, 0, NULL,
155: ai_stand, 0, NULL,
156:
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: ai_stand, 0, NULL,
164: ai_stand, 0, NULL,
165: ai_stand, 0, NULL,
166: ai_stand, 0, NULL,
167:
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: ai_stand, 0, NULL,
175: ai_stand, 0, NULL,
176: ai_stand, 0, NULL,
177: ai_stand, 0, NULL,
178:
179: ai_stand, 0, NULL,
180: ai_stand, 0, NULL,
181: ai_stand, 0, NULL,
182: ai_stand, 0, NULL,
183: ai_stand, 0, NULL,
184: ai_stand, 0, NULL,
185: ai_stand, 0, NULL,
186: ai_stand, 0, NULL,
187: ai_stand, 0, NULL,
188: ai_stand, 0, NULL,
189:
190: ai_stand, 0, NULL,
191: ai_stand, 0, NULL,
192: ai_stand, 0, NULL,
193: ai_stand, 0, NULL,
194: ai_stand, 0, NULL,
195: ai_stand, 0, NULL,
196: ai_stand, 4, NULL,
197: ai_stand, 1, NULL,
198: ai_stand, -1, NULL,
199: ai_stand, -2, NULL,
200:
201: ai_stand, 0, NULL,
202: ai_stand, 0, NULL
203: };
204: mmove_t soldier_move_stand4 = {FRAME_stand401, FRAME_stand452, soldier_frames_stand4, NULL};
205: #endif
206:
207: void soldier_stand (edict_t *self)
208: {
209: if ((self->monsterinfo.currentmove == &soldier_move_stand3) || (random() < 0.8))
210: self->monsterinfo.currentmove = &soldier_move_stand1;
211: else
212: self->monsterinfo.currentmove = &soldier_move_stand3;
213: }
214:
215:
216: //
217: // WALK
218: //
219:
220: void soldier_walk1_random (edict_t *self)
221: {
222: if (random() > 0.1)
223: self->monsterinfo.nextframe = FRAME_walk101;
224: }
225:
226: mframe_t soldier_frames_walk1 [] =
227: {
228: ai_walk, 3, NULL,
229: ai_walk, 6, NULL,
230: ai_walk, 2, NULL,
231: ai_walk, 2, NULL,
232: ai_walk, 2, NULL,
233: ai_walk, 1, NULL,
234: ai_walk, 6, NULL,
235: ai_walk, 5, NULL,
236: ai_walk, 3, NULL,
237: ai_walk, -1, soldier_walk1_random,
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: ai_walk, 0, NULL,
247: ai_walk, 0, NULL,
248: ai_walk, 0, NULL,
249: ai_walk, 0, NULL,
250: ai_walk, 0, NULL,
251: ai_walk, 0, NULL,
252: ai_walk, 0, NULL,
253: ai_walk, 0, NULL,
254: ai_walk, 0, NULL,
255: ai_walk, 0, NULL,
256: ai_walk, 0, NULL,
257: ai_walk, 0, NULL,
258: ai_walk, 0, NULL,
259: ai_walk, 0, NULL,
260: ai_walk, 0, NULL
261: };
262: mmove_t soldier_move_walk1 = {FRAME_walk101, FRAME_walk133, soldier_frames_walk1, NULL};
263:
264: mframe_t soldier_frames_walk2 [] =
265: {
266: ai_walk, 4, NULL,
267: ai_walk, 4, NULL,
268: ai_walk, 9, NULL,
269: ai_walk, 8, NULL,
270: ai_walk, 5, NULL,
271: ai_walk, 1, NULL,
272: ai_walk, 3, NULL,
273: ai_walk, 7, NULL,
274: ai_walk, 6, NULL,
275: ai_walk, 7, NULL
276: };
277: mmove_t soldier_move_walk2 = {FRAME_walk209, FRAME_walk218, soldier_frames_walk2, NULL};
278:
279: void soldier_walk (edict_t *self)
280: {
281: if (random() < 0.5)
282: self->monsterinfo.currentmove = &soldier_move_walk1;
283: else
284: self->monsterinfo.currentmove = &soldier_move_walk2;
285: }
286:
287:
288: //
289: // RUN
290: //
291:
292: void soldier_run (edict_t *self);
293:
294: mframe_t soldier_frames_start_run [] =
295: {
296: ai_run, 7, NULL,
297: ai_run, 5, NULL
298: };
299: mmove_t soldier_move_start_run = {FRAME_run01, FRAME_run02, soldier_frames_start_run, soldier_run};
300:
301: #ifdef RUN_SHOOT
302: void soldier_fire (edict_t *self, int);
303:
304: void soldier_fire_run (edict_t *self) {
305: if ((self->s.skinnum <= 1) && (self->enemy) && visible(self, self->enemy)) {
306: soldier_fire(self, 0);
307: }
308: }
309: #endif
310:
311: mframe_t soldier_frames_run [] =
312: {
313: ai_run, 10, NULL,
314: ai_run, 11, monster_done_dodge,
315: ai_run, 11, NULL,
316: ai_run, 16, NULL,
317: ai_run, 10, NULL,
318: ai_run, 15, monster_done_dodge
319: };
320:
321: mmove_t soldier_move_run = {FRAME_run03, FRAME_run08, soldier_frames_run, NULL};
322:
323: void soldier_run (edict_t *self)
324: {
325: monster_done_dodge (self);
326:
327: if (self->monsterinfo.aiflags & AI_STAND_GROUND)
328: {
329: self->monsterinfo.currentmove = &soldier_move_stand1;
330: return;
331: }
332:
333: if (self->monsterinfo.currentmove == &soldier_move_walk1 ||
334: self->monsterinfo.currentmove == &soldier_move_walk2 ||
335: self->monsterinfo.currentmove == &soldier_move_start_run)
336: {
337: self->monsterinfo.currentmove = &soldier_move_run;
338: }
339: else
340: {
341: self->monsterinfo.currentmove = &soldier_move_start_run;
342: }
343: }
344:
345:
346: //
347: // PAIN
348: //
349:
350: mframe_t soldier_frames_pain1 [] =
351: {
352: ai_move, -3, NULL,
353: ai_move, 4, NULL,
354: ai_move, 1, NULL,
355: ai_move, 1, NULL,
356: ai_move, 0, NULL
357: };
358: mmove_t soldier_move_pain1 = {FRAME_pain101, FRAME_pain105, soldier_frames_pain1, soldier_run};
359:
360: mframe_t soldier_frames_pain2 [] =
361: {
362: ai_move, -13, NULL,
363: ai_move, -1, NULL,
364: ai_move, 2, NULL,
365: ai_move, 4, NULL,
366: ai_move, 2, NULL,
367: ai_move, 3, NULL,
368: ai_move, 2, NULL
369: };
370: mmove_t soldier_move_pain2 = {FRAME_pain201, FRAME_pain207, soldier_frames_pain2, soldier_run};
371:
372: mframe_t soldier_frames_pain3 [] =
373: {
374: ai_move, -8, NULL,
375: ai_move, 10, NULL,
376: ai_move, -4, NULL,
377: ai_move, -1, NULL,
378: ai_move, -3, NULL,
379: ai_move, 0, NULL,
380: ai_move, 3, NULL,
381: ai_move, 0, NULL,
382: ai_move, 0, NULL,
383: ai_move, 0, NULL,
384: ai_move, 0, NULL,
385: ai_move, 1, NULL,
386: ai_move, 0, NULL,
387: ai_move, 1, NULL,
388: ai_move, 2, NULL,
389: ai_move, 4, NULL,
390: ai_move, 3, NULL,
391: ai_move, 2, NULL
392: };
393: mmove_t soldier_move_pain3 = {FRAME_pain301, FRAME_pain318, soldier_frames_pain3, soldier_run};
394:
395: mframe_t soldier_frames_pain4 [] =
396: {
397: ai_move, 0, NULL,
398: ai_move, 0, NULL,
399: ai_move, 0, NULL,
400: ai_move, -10, NULL,
401: ai_move, -6, NULL,
402: ai_move, 8, NULL,
403: ai_move, 4, NULL,
404: ai_move, 1, NULL,
405: ai_move, 0, NULL,
406: ai_move, 2, NULL,
407: ai_move, 5, NULL,
408: ai_move, 2, NULL,
409: ai_move, -1, NULL,
410: ai_move, -1, NULL,
411: ai_move, 3, NULL,
412: ai_move, 2, NULL,
413: ai_move, 0, NULL
414: };
415: mmove_t soldier_move_pain4 = {FRAME_pain401, FRAME_pain417, soldier_frames_pain4, soldier_run};
416:
417:
418: void soldier_pain (edict_t *self, edict_t *other, float kick, int damage)
419: {
420: float r;
421: int n;
422:
423: if (self->health < (self->max_health / 2))
424: self->s.skinnum |= 1;
425:
426: monster_done_dodge (self);
427: soldier_stop_charge(self);
428:
429: // if we're blind firing, this needs to be turned off here
430: self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING;
431:
432: if (level.time < self->pain_debounce_time)
433: {
434: if ((self->velocity[2] > 100) && ( (self->monsterinfo.currentmove == &soldier_move_pain1) || (self->monsterinfo.currentmove == &soldier_move_pain2) || (self->monsterinfo.currentmove == &soldier_move_pain3)))
435: {
436: // PMM - clear duck flag
437: if (self->monsterinfo.aiflags & AI_DUCKED)
438: monster_duck_up(self);
439: self->monsterinfo.currentmove = &soldier_move_pain4;
440: }
441: return;
442: }
443:
444: self->pain_debounce_time = level.time + 3;
445:
446: n = self->s.skinnum | 1;
447: if (n == 1)
448: gi.sound (self, CHAN_VOICE, sound_pain_light, 1, ATTN_NORM, 0);
449: else if (n == 3)
450: gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
451: else
452: gi.sound (self, CHAN_VOICE, sound_pain_ss, 1, ATTN_NORM, 0);
453:
454: if (self->velocity[2] > 100)
455: {
456: // PMM - clear duck flag
457: if (self->monsterinfo.aiflags & AI_DUCKED)
458: monster_duck_up(self);
459: self->monsterinfo.currentmove = &soldier_move_pain4;
460: self->monsterinfo.pausetime = 0;
461: return;
462: }
463:
464: if (skill->value == 3)
465: return; // no pain anims in nightmare
466:
467: r = random();
468:
469: if (r < 0.33)
470: self->monsterinfo.currentmove = &soldier_move_pain1;
471: else if (r < 0.66)
472: self->monsterinfo.currentmove = &soldier_move_pain2;
473: else
474: self->monsterinfo.currentmove = &soldier_move_pain3;
475:
476: // PMM - clear duck flag
477: if (self->monsterinfo.aiflags & AI_DUCKED)
478: monster_duck_up(self);
479: self->monsterinfo.pausetime = 0;
480:
481: }
482:
483:
484: //
485: // ATTACK
486: //
487:
488: 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};
489: 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};
490: 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};
491:
492: //void soldier_fire (edict_t *self, int flash_number) PMM
493: void soldier_fire (edict_t *self, int in_flash_number)
494: {
495: vec3_t start;
496: vec3_t forward, right, up;
497: vec3_t aim;
498: vec3_t dir;
499: vec3_t end;
500: float r, u;
501: int flash_index;
502: int flash_number;
503: #ifdef RUN_SHOOT
504: vec3_t aim_norm;
505: float angle;
506: #endif
507: #ifdef CHECK_TARGET
508: trace_t tr;
509: vec3_t aim_good;
510: #endif
511:
512: if ((!self->enemy) || (!self->enemy->inuse))
513: return;
514:
515: if (in_flash_number < 0)
516: {
517: flash_number = -1 * in_flash_number;
518: }
519: else
520: flash_number = in_flash_number;
521:
522: if (self->s.skinnum < 2)
523: flash_index = blaster_flash[flash_number];
524: else if (self->s.skinnum < 4)
525: flash_index = shotgun_flash[flash_number];
526: else
527: flash_index = machinegun_flash[flash_number];
528:
529: AngleVectors (self->s.angles, forward, right, NULL);
530: G_ProjectSource (self->s.origin, monster_flash_offset[flash_index], forward, right, start);
531:
532: if (flash_number == 5 || flash_number == 6) // he's dead
533: {
534: VectorCopy (forward, aim);
535: }
536: else
537: {
538: VectorCopy (self->enemy->s.origin, end);
539: end[2] += self->enemy->viewheight;
540: VectorSubtract (end, start, aim);
541: #ifdef CHECK_TARGET
542: VectorCopy (end, aim_good);
543: #endif
544: #ifdef RUN_SHOOT
545: //PMM
546: if (in_flash_number < 0)
547: {
548: VectorCopy (aim, aim_norm);
549: VectorNormalize (aim_norm);
550: angle = DotProduct (aim_norm, forward);
551: //gi.dprintf ("Dot Product: %f", DotProduct (aim_norm, forward));
552: if (angle < 0.9) // ~25 degree angle
553: {
554: // if(g_showlogic && g_showlogic->value)
555: // gi.dprintf (" not firing due to bad dotprod %f\n", angle);
556: return;
557: } else {
558: // if(g_showlogic && g_showlogic->value)
559: // gi.dprintf (" firing: dotprod = %f\n", angle);
560: }
561: }
562: //-PMM
563: #endif
564: vectoangles (aim, dir);
565: AngleVectors (dir, forward, right, up);
566:
567: if (skill->value < 2)
568: {
569: r = crandom()*1000;
570: u = crandom()*500;
571: }
572: else
573: {
574: r = crandom()*500;
575: u = crandom()*250;
576: }
577: VectorMA (start, 8192, forward, end);
578: VectorMA (end, r, right, end);
579: VectorMA (end, u, up, end);
580:
581: VectorSubtract (end, start, aim);
582: VectorNormalize (aim);
583: }
584: #ifdef CHECK_TARGET
585: if (!(flash_number == 5 || flash_number == 6)) // he's dead
586: {
587: tr = gi.trace (start, NULL, NULL, aim_good, self, MASK_SHOT);
588: if ((tr.ent != self->enemy) && (tr.ent != world)) {
589: if(g_showlogic && g_showlogic->value)
590: gi.dprintf ("infantry shot aborted due to bad target\n");
591: return;
592: }
593: }
594: #endif
595: if (self->s.skinnum <= 1)
596: {
597: monster_fire_blaster (self, start, aim, 5, 600, flash_index, EF_BLASTER);
598: }
599: else if (self->s.skinnum <= 3)
600: {
601: monster_fire_shotgun (self, start, aim, 2, 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, flash_index);
602: }
603: else
604: {
605: // PMM - changed to wait from pausetime to not interfere with dodge code
606: if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME))
607: self->wait = level.time + (3 + rand() % 8) * FRAMETIME;
608:
609: monster_fire_bullet (self, start, aim, 2, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_index);
610:
611: if (level.time >= self->wait)
612: self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
613: else
614: self->monsterinfo.aiflags |= AI_HOLD_FRAME;
615: }
616: }
617:
618: // ATTACK1 (blaster/shotgun)
619:
620: void soldier_fire1 (edict_t *self)
621: {
622: soldier_fire (self, 0);
623: }
624:
625: void soldier_attack1_refire1 (edict_t *self)
626: {
627: // PMM - blindfire
628: if (self->monsterinfo.aiflags & AI_MANUAL_STEERING)
629: {
630: self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING;
631: return;
632: }
633: // pmm
634:
635: if (!self->enemy)
636: return;
637:
638: if (self->s.skinnum > 1)
639: return;
640:
641: if (self->enemy->health <= 0)
642: return;
643:
644: if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
645: self->monsterinfo.nextframe = FRAME_attak102;
646: else
647: self->monsterinfo.nextframe = FRAME_attak110;
648: }
649:
650: void soldier_attack1_refire2 (edict_t *self)
651: {
652: if (!self->enemy)
653: return;
654:
655: if (self->s.skinnum < 2)
656: return;
657:
658: if (self->enemy->health <= 0)
659: return;
660:
661: if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
662: self->monsterinfo.nextframe = FRAME_attak102;
663: }
664:
665: mframe_t soldier_frames_attack1 [] =
666: {
667: ai_charge, 0, NULL,
668: ai_charge, 0, NULL,
669: ai_charge, 0, soldier_fire1,
670: ai_charge, 0, NULL,
671: ai_charge, 0, NULL,
672: ai_charge, 0, soldier_attack1_refire1,
673: ai_charge, 0, NULL,
674: ai_charge, 0, soldier_cock,
675: ai_charge, 0, soldier_attack1_refire2,
676: ai_charge, 0, NULL,
677: ai_charge, 0, NULL,
678: ai_charge, 0, NULL
679: };
680: mmove_t soldier_move_attack1 = {FRAME_attak101, FRAME_attak112, soldier_frames_attack1, soldier_run};
681:
682: // ATTACK2 (blaster/shotgun)
683:
684: void soldier_fire2 (edict_t *self)
685: {
686: soldier_fire (self, 1);
687: }
688:
689: void soldier_attack2_refire1 (edict_t *self)
690: {
691: if (!self->enemy)
692: return;
693:
694: if (self->s.skinnum > 1)
695: return;
696:
697: if (self->enemy->health <= 0)
698: return;
699:
700: if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
701: self->monsterinfo.nextframe = FRAME_attak204;
702: else
703: self->monsterinfo.nextframe = FRAME_attak216;
704: }
705:
706: void soldier_attack2_refire2 (edict_t *self)
707: {
708: if (!self->enemy)
709: return;
710:
711: if (self->s.skinnum < 2)
712: return;
713:
714: if (self->enemy->health <= 0)
715: return;
716:
717: if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
718: self->monsterinfo.nextframe = FRAME_attak204;
719: }
720:
721: mframe_t soldier_frames_attack2 [] =
722: {
723: ai_charge, 0, NULL,
724: ai_charge, 0, NULL,
725: ai_charge, 0, NULL,
726: ai_charge, 0, NULL,
727: ai_charge, 0, soldier_fire2,
728: ai_charge, 0, NULL,
729: ai_charge, 0, NULL,
730: ai_charge, 0, soldier_attack2_refire1,
731: ai_charge, 0, NULL,
732: ai_charge, 0, NULL,
733: ai_charge, 0, NULL,
734: ai_charge, 0, NULL,
735: ai_charge, 0, soldier_cock,
736: ai_charge, 0, NULL,
737: ai_charge, 0, soldier_attack2_refire2,
738: ai_charge, 0, NULL,
739: ai_charge, 0, NULL,
740: ai_charge, 0, NULL
741: };
742: mmove_t soldier_move_attack2 = {FRAME_attak201, FRAME_attak218, soldier_frames_attack2, soldier_run};
743:
744: // ATTACK3 (duck and shoot)
745: /*
746: void soldier_duck_down (edict_t *self)
747: {
748: if ((g_showlogic) && (g_showlogic->value))
749: gi.dprintf ("duck down - %d!\n", self->s.frame);
750:
751: self->monsterinfo.aiflags |= AI_DUCKED;
752: // self->maxs[2] -= 32;
753: self->maxs[2] = self->monsterinfo.base_height - 32;
754: self->takedamage = DAMAGE_YES;
755: if (self->monsterinfo.duck_wait_time < level.time)
756: {
757: if ((g_showlogic) && (g_showlogic->value))
758: gi.dprintf ("soldier duck with no time!\n");
759: self->monsterinfo.duck_wait_time = level.time + 1;
760: }
761: gi.linkentity (self);
762: }
763:
764: void soldier_duck_up (edict_t *self)
765: {
766: if ((g_showlogic) && (g_showlogic->value))
767: gi.dprintf ("duck up - %d!\n", self->s.frame);
768: self->monsterinfo.aiflags &= ~AI_DUCKED;
769: // self->maxs[2] += 32;
770: self->maxs[2] = self->monsterinfo.base_height;
771: self->takedamage = DAMAGE_AIM;
772: gi.linkentity (self);
773: }
774: */
775: void soldier_fire3 (edict_t *self)
776: {
777: monster_duck_down (self);
778: soldier_fire (self, 2);
779: }
780:
781: void soldier_attack3_refire (edict_t *self)
782: {
783: if ((level.time + 0.4) < self->monsterinfo.duck_wait_time)
784: self->monsterinfo.nextframe = FRAME_attak303;
785: }
786:
787: mframe_t soldier_frames_attack3 [] =
788: {
789: ai_charge, 0, NULL,
790: ai_charge, 0, NULL,
791: ai_charge, 0, soldier_fire3,
792: ai_charge, 0, NULL,
793: ai_charge, 0, NULL,
794: ai_charge, 0, soldier_attack3_refire,
795: ai_charge, 0, monster_duck_up,
796: ai_charge, 0, NULL,
797: ai_charge, 0, NULL
798: };
799: mmove_t soldier_move_attack3 = {FRAME_attak301, FRAME_attak309, soldier_frames_attack3, soldier_run};
800:
801: // ATTACK4 (machinegun)
802:
803: void soldier_fire4 (edict_t *self)
804: {
805: soldier_fire (self, 3);
806: //
807: // if (self->enemy->health <= 0)
808: // return;
809: //
810: // if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
811: // self->monsterinfo.nextframe = FRAME_attak402;
812: }
813:
814: mframe_t soldier_frames_attack4 [] =
815: {
816: ai_charge, 0, NULL,
817: ai_charge, 0, NULL,
818: ai_charge, 0, soldier_fire4,
819: ai_charge, 0, NULL,
820: ai_charge, 0, NULL,
821: ai_charge, 0, NULL
822: };
823: mmove_t soldier_move_attack4 = {FRAME_attak401, FRAME_attak406, soldier_frames_attack4, soldier_run};
824:
825: #if 0
826: // ATTACK5 (prone)
827:
828: void soldier_fire5 (edict_t *self)
829: {
830: soldier_fire (self, 4);
831: }
832:
833: void soldier_attack5_refire (edict_t *self)
834: {
835: if (!self->enemy)
836: return;
837:
838: if (self->enemy->health <= 0)
839: return;
840:
841: if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
842: self->monsterinfo.nextframe = FRAME_attak505;
843: }
844:
845: mframe_t soldier_frames_attack5 [] =
846: {
847: ai_charge, 8, NULL,
848: ai_charge, 8, NULL,
849: ai_charge, 0, NULL,
850: ai_charge, 0, NULL,
851: ai_charge, 0, soldier_fire5,
852: ai_charge, 0, NULL,
853: ai_charge, 0, NULL,
854: ai_charge, 0, soldier_attack5_refire
855: };
856: mmove_t soldier_move_attack5 = {FRAME_attak501, FRAME_attak508, soldier_frames_attack5, soldier_run};
857: #endif
858:
859: // ATTACK6 (run & shoot)
860:
861: void soldier_fire8 (edict_t *self)
862: {
863: soldier_fire (self, -7);
864: // self->monsterinfo.aiflags |= AI_HOLD_FRAME;
865: // self->monsterinfo.pausetime = level.time + 1000000;
866: }
867:
868: void soldier_attack6_refire (edict_t *self)
869: {
870: // PMM - make sure dodge & charge bits are cleared
871: monster_done_dodge (self);
872: soldier_stop_charge (self);
873:
874: if (!self->enemy)
875: return;
876:
877: if (self->enemy->health <= 0)
878: return;
879:
880: // if (range(self, self->enemy) < RANGE_MID)
881: if (range(self, self->enemy) < RANGE_NEAR)
882: return;
883:
884: if ((skill->value == 3) || ((random() < (0.25*((float)skill->value)))))
885: self->monsterinfo.nextframe = FRAME_runs03;
886: }
887:
888: mframe_t soldier_frames_attack6 [] =
889: {
890: // PMM
891: // ai_run, 10, NULL,
892: ai_run, 10, soldier_start_charge,
893: ai_run, 4, NULL,
894: ai_run, 12, soldier_fire8,
895: ai_run, 11, NULL,
896: ai_run, 13, monster_done_dodge,
897: ai_run, 18, NULL,
898: ai_run, 15, NULL,
899: ai_run, 14, NULL,
900: ai_run, 11, NULL,
901: ai_run, 8, NULL,
902: ai_run, 11, NULL,
903: ai_run, 12, NULL,
904: ai_run, 12, NULL,
905: ai_run, 17, soldier_attack6_refire
906: };
907: mmove_t soldier_move_attack6 = {FRAME_runs01, FRAME_runs14, soldier_frames_attack6, soldier_run};
908:
909: void soldier_attack(edict_t *self)
910: {
911: float r, chance;
912:
913: monster_done_dodge (self);
914:
915: // PMM - blindfire!
916: if (self->monsterinfo.attack_state == AS_BLIND)
917: {
918: // setup shot probabilities
919: if (self->monsterinfo.blind_fire_delay < 1.0)
920: chance = 1.0;
921: else if (self->monsterinfo.blind_fire_delay < 7.5)
922: chance = 0.4;
923: else
924: chance = 0.1;
925:
926: r = random();
927:
928: // gi.dprintf ("chance = %2.2f, roll = %2.2f\n", chance, r);
929:
930: // minimum of 2 seconds, plus 0-3, after the shots are done
931: self->monsterinfo.blind_fire_delay += 2.1 + 2.0 + random()*3.0;
932:
933: // don't shoot at the origin
934: if (VectorCompare (self->monsterinfo.blind_fire_target, vec3_origin))
935: return;
936:
937: // don't shoot if the dice say not to
938: if (r > chance)
939: {
940: // if ((g_showlogic) && (g_showlogic->value))
941: // gi.dprintf ("blindfire - NO SHOT\n");
942: return;
943: }
944:
945: // turn on manual steering to signal both manual steering and blindfire
946: self->monsterinfo.aiflags |= AI_MANUAL_STEERING;
947: self->monsterinfo.currentmove = &soldier_move_attack1;
948: self->monsterinfo.attack_finished = level.time + 1.5 + random();
949: return;
950: }
951: // pmm
952:
953: // PMM - added this so the soldiers now run toward you and shoot instead of just stopping and shooting
954: // if ((range(self, self->enemy) >= RANGE_MID) && (r < (skill->value*0.25) && (self->s.skinnum <= 3)))
955:
956: r = random();
957:
958: if ((!(self->monsterinfo.aiflags & AI_BLOCKED)) && (range(self, self->enemy) >= RANGE_NEAR) && (r < (skill->value*0.25) && (self->s.skinnum <= 3)))
959: {
960: self->monsterinfo.currentmove = &soldier_move_attack6;
961: }
962: else
963: {
964: if (self->s.skinnum < 4)
965: {
966: if (random() < 0.5)
967: self->monsterinfo.currentmove = &soldier_move_attack1;
968: else
969: self->monsterinfo.currentmove = &soldier_move_attack2;
970: }
971: else
972: {
973: self->monsterinfo.currentmove = &soldier_move_attack4;
974: }
975: }
976: }
977:
978:
979: //
980: // SIGHT
981: //
982:
983: void soldier_sight(edict_t *self, edict_t *other)
984: {
985: if (random() < 0.5)
986: gi.sound (self, CHAN_VOICE, sound_sight1, 1, ATTN_NORM, 0);
987: else
988: gi.sound (self, CHAN_VOICE, sound_sight2, 1, ATTN_NORM, 0);
989:
990: // if ((skill->value > 0) && (self->enemy) && (range(self, self->enemy) >= RANGE_MID))
991: if ((skill->value > 0) && (self->enemy) && (range(self, self->enemy) >= RANGE_NEAR))
992: {
993: // PMM - don't let machinegunners run & shoot
994: if ((random() > 0.75) && (self->s.skinnum <= 3))
995: self->monsterinfo.currentmove = &soldier_move_attack6;
996: }
997: }
998:
999: //
1000: // DUCK
1001: //
1002: /*
1003: void soldier_duck_hold (edict_t *self)
1004: {
1005: if (level.time >= self->monsterinfo.duck_wait_time)
1006: self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
1007: else
1008: self->monsterinfo.aiflags |= AI_HOLD_FRAME;
1009: }
1010: */
1011: mframe_t soldier_frames_duck [] =
1012: {
1013: ai_move, 5, monster_duck_down,
1014: ai_move, -1, monster_duck_hold,
1015: ai_move, 1, NULL,
1016: ai_move, 0, monster_duck_up,
1017: ai_move, 5, NULL
1018: };
1019: mmove_t soldier_move_duck = {FRAME_duck01, FRAME_duck05, soldier_frames_duck, soldier_run};
1020:
1021: /*
1022: void soldier_dodge (edict_t *self, edict_t *attacker, float eta, trace_t *tr)
1023: {
1024: //===========
1025: //PMM - rogue rewrite of dodge code.
1026: // lots o' changes in here. Basically, they now check the tr and see if ducking would help,
1027: // and if it doesn't, they dodge like mad
1028: float r = random();
1029: float height;
1030:
1031: if ((g_showlogic) && (g_showlogic->value))
1032: {
1033: if (self->monsterinfo.aiflags & AI_DODGING)
1034: gi.dprintf ("dodging - ");
1035: if (self->monsterinfo.aiflags & AI_DUCKED)
1036: gi.dprintf ("ducked - ");
1037: }
1038: if (!self->enemy)
1039: {
1040: self->enemy = attacker;
1041: FoundTarget (self);
1042: }
1043:
1044: // PMM - don't bother if it's going to hit anyway; fix for weird in-your-face etas (I was
1045: // seeing numbers like 13 and 14)
1046: if ((eta < 0.1) || (eta > 5))
1047: {
1048: if ((g_showlogic) && (g_showlogic->value))
1049: gi.dprintf ("timeout\n");
1050: return;
1051: }
1052:
1053: // skill level determination..
1054: if (r > (0.25*((skill->value)+1)))
1055: {
1056: if ((g_showlogic) && (g_showlogic->value))
1057: gi.dprintf ("skillout\n");
1058: return;
1059: }
1060:
1061: // stop charging, since we're going to dodge (somehow) instead
1062: soldier_stop_charge (self);
1063:
1064: height = self->absmax[2]-32-1; // the -1 is because the absmax is s.origin + maxs + 1
1065:
1066: // if we're ducking already, or the shot is at our knees
1067: if ((tr->endpos[2] <= height) || (self->monsterinfo.aiflags & AI_DUCKED))
1068: {
1069: vec3_t right, diff;
1070:
1071: // if we're already dodging, just finish the sequence, i.e. don't do anything else
1072: if (self->monsterinfo.aiflags & AI_DODGING)
1073: {
1074: if ((g_showlogic) && (g_showlogic->value))
1075: gi.dprintf ("already dodging\n");
1076: return;
1077: }
1078:
1079: AngleVectors (self->s.angles, NULL, right, NULL);
1080: VectorSubtract (tr->endpos, self->s.origin, diff);
1081:
1082: if (DotProduct (right, diff) < 0)
1083: {
1084: self->monsterinfo.lefty = 1;
1085: // gi.dprintf ("left\n");
1086: } else {
1087: // gi.dprintf ("right\n");
1088: }
1089: // if it doesn't sense to duck, try to strafe and shoot
1090: // we don't want the machine gun guys running & shooting (looks bad)
1091:
1092: // if we are currently ducked, unduck
1093: if (self->monsterinfo.aiflags & AI_DUCKED)
1094: {
1095: if ((g_showlogic) && (g_showlogic->value))
1096: gi.dprintf ("unducking - ");
1097: soldier_duck_up(self);
1098: }
1099:
1100: self->monsterinfo.aiflags |= AI_DODGING;
1101: self->monsterinfo.attack_state = AS_SLIDING;
1102:
1103: if (self->s.skinnum <= 3)
1104: {
1105: if ((g_showlogic) && (g_showlogic->value))
1106: gi.dprintf ("shooting back!\n");
1107: self->monsterinfo.currentmove = &soldier_move_attack6;
1108: }
1109: else
1110: {
1111: if ((g_showlogic) && (g_showlogic->value))
1112: gi.dprintf ("strafing away!\n");
1113: self->monsterinfo.currentmove = &soldier_move_start_run;
1114: }
1115: return;
1116: }
1117:
1118: // if we're here, we're ducking, so clear the dodge bit if it's set
1119:
1120: if ((g_showlogic) && (g_showlogic->value))
1121: gi.dprintf ("ducking!\n");
1122: if (skill->value == 0)
1123: {
1124: // set this prematurely; it doesn't hurt, and prevents extra iterations
1125: self->monsterinfo.aiflags |= AI_DUCKED;
1126: monster_done_dodge (self);
1127: self->monsterinfo.currentmove = &soldier_move_duck;
1128: // PMM - stupid dodge
1129: self->monsterinfo.duck_wait_time = level.time + eta + 1;
1130: return;
1131: }
1132: // PMM - since we're only ducking some of the time, this needs to be moved down below
1133: // self->monsterinfo.duck_wait_time = level.time + eta + 0.3;
1134:
1135: r = random();
1136:
1137: // set this prematurely; it doesn't hurt, and prevents extra iterations
1138: self->monsterinfo.aiflags |= AI_DUCKED;
1139: monster_done_dodge (self);
1140:
1141: if (r > (skill->value * 0.33))
1142: {
1143: self->monsterinfo.currentmove = &soldier_move_duck;
1144: self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value));
1145: // has to be done immediately otherwise he can get stuck
1146: soldier_duck_down(self);
1147: }
1148: else
1149: {
1150: // has to be done immediately otherwise he can get stuck
1151: soldier_duck_down(self);
1152: self->monsterinfo.duck_wait_time = level.time + eta + 1;
1153: self->monsterinfo.currentmove = &soldier_move_attack3;
1154: self->monsterinfo.nextframe = FRAME_attak301;
1155: }
1156: return;
1157: //PMM
1158: //===========
1159:
1160: }
1161: */
1162: // pmm - blocking code
1163:
1164: qboolean soldier_blocked (edict_t *self, float dist)
1165: {
1166: // don't do anything if you're dodging
1167: if ((self->monsterinfo.aiflags & AI_DODGING) || (self->monsterinfo.aiflags & AI_DUCKED))
1168: return false;
1169:
1170: if(blocked_checkshot (self, 0.25 + (0.05 * skill->value) ))
1171: return true;
1172:
1173: // if(blocked_checkjump (self, dist, 192, 40))
1174: // {
1175: // soldier_jump(self);
1176: // return true;
1177: // }
1178:
1179: if(blocked_checkplat (self, dist))
1180: return true;
1181:
1182: return false;
1183: }
1184:
1185: //
1186: // DEATH
1187: //
1188:
1189: void soldier_fire6 (edict_t *self)
1190: {
1191: soldier_fire (self, 5);
1192: }
1193:
1194: void soldier_fire7 (edict_t *self)
1195: {
1196: soldier_fire (self, 6);
1197: }
1198:
1199: void soldier_dead (edict_t *self)
1200: {
1201: VectorSet (self->mins, -16, -16, -24);
1202: VectorSet (self->maxs, 16, 16, -8);
1203: self->movetype = MOVETYPE_TOSS;
1204: self->svflags |= SVF_DEADMONSTER;
1205: self->nextthink = 0;
1206: gi.linkentity (self);
1207: }
1208:
1209: // pmm - this quickie does a location trace to try to grow the bounding box
1210: //
1211: // this is because the frames are off; the origin is at the guy's feet.
1212: void soldier_dead2 (edict_t *self)
1213: {
1214: vec3_t tempmins, tempmaxs, temporg;
1215: trace_t tr;
1216:
1217: VectorCopy (self->s.origin, temporg);
1218: // this is because location traces done at the floor are guaranteed to hit the floor
1219: // (inside the sv_trace code it grows the bbox by 1 in all directions)
1220: temporg[2] += 1;
1221:
1222: VectorSet (tempmins, -32, -32, -24);
1223: VectorSet (tempmaxs, 32, 32, -8);
1224:
1225: tr = gi.trace (temporg, tempmins, tempmaxs, temporg, self, MASK_SOLID);
1226: if (tr.startsolid || tr.allsolid)
1227: {
1228: VectorSet (self->mins, -16, -16, -24);
1229: VectorSet (self->maxs, 16, 16, -8);
1230: }
1231: else
1232: {
1233: VectorCopy (tempmins, self->mins);
1234: VectorCopy (tempmaxs, self->maxs);
1235: }
1236: self->movetype = MOVETYPE_TOSS;
1237: self->svflags |= SVF_DEADMONSTER;
1238: self->nextthink = 0;
1239: gi.linkentity (self);
1240: }
1241:
1242: mframe_t soldier_frames_death1 [] =
1243: {
1244: ai_move, 0, NULL,
1245: ai_move, -10, NULL,
1246: ai_move, -10, NULL,
1247: ai_move, -10, NULL,
1248: ai_move, -5, NULL,
1249: ai_move, 0, NULL,
1250: ai_move, 0, NULL,
1251: ai_move, 0, NULL,
1252: ai_move, 0, NULL,
1253: ai_move, 0, NULL,
1254:
1255: ai_move, 0, NULL,
1256: ai_move, 0, NULL,
1257: ai_move, 0, NULL,
1258: ai_move, 0, NULL,
1259: ai_move, 0, NULL,
1260: ai_move, 0, NULL,
1261: ai_move, 0, NULL,
1262: ai_move, 0, NULL,
1263: ai_move, 0, NULL,
1264: ai_move, 0, NULL,
1265:
1266: ai_move, 0, NULL,
1267: ai_move, 0, soldier_fire6,
1268: ai_move, 0, NULL,
1269: ai_move, 0, NULL,
1270: ai_move, 0, soldier_fire7,
1271: ai_move, 0, NULL,
1272: ai_move, 0, NULL,
1273: ai_move, 0, NULL,
1274: ai_move, 0, NULL,
1275: ai_move, 0, NULL,
1276:
1277: ai_move, 0, NULL,
1278: ai_move, 0, NULL,
1279: ai_move, 0, NULL,
1280: ai_move, 0, NULL,
1281: ai_move, 0, NULL,
1282: ai_move, 0, NULL
1283: };
1284: mmove_t soldier_move_death1 = {FRAME_death101, FRAME_death136, soldier_frames_death1, soldier_dead};
1285:
1286: mframe_t soldier_frames_death2 [] =
1287: {
1288: ai_move, -5, NULL,
1289: ai_move, -5, NULL,
1290: ai_move, -5, NULL,
1291: ai_move, 0, NULL,
1292: ai_move, 0, NULL,
1293: ai_move, 0, NULL,
1294: ai_move, 0, NULL,
1295: ai_move, 0, NULL,
1296: ai_move, 0, NULL,
1297: ai_move, 0, NULL,
1298:
1299: ai_move, 0, NULL,
1300: ai_move, 0, NULL,
1301: ai_move, 0, NULL,
1302: ai_move, 0, NULL,
1303: ai_move, 0, NULL,
1304: ai_move, 0, NULL,
1305: ai_move, 0, NULL,
1306: ai_move, 0, NULL,
1307: ai_move, 0, NULL,
1308: ai_move, 0, NULL,
1309:
1310: ai_move, 0, NULL,
1311: ai_move, 0, NULL,
1312: ai_move, 0, NULL,
1313: ai_move, 0, NULL,
1314: ai_move, 0, NULL,
1315: ai_move, 0, NULL,
1316: ai_move, 0, NULL,
1317: ai_move, 0, NULL,
1318: ai_move, 0, NULL,
1319: ai_move, 0, NULL,
1320:
1321: ai_move, 0, NULL,
1322: ai_move, 0, NULL,
1323: ai_move, 0, NULL,
1324: ai_move, 0, NULL,
1325: ai_move, 0, NULL
1326: };
1327: mmove_t soldier_move_death2 = {FRAME_death201, FRAME_death235, soldier_frames_death2, soldier_dead};
1328:
1329: mframe_t soldier_frames_death3 [] =
1330: {
1331: ai_move, -5, NULL,
1332: ai_move, -5, NULL,
1333: ai_move, -5, NULL,
1334: ai_move, 0, NULL,
1335: ai_move, 0, NULL,
1336: ai_move, 0, NULL,
1337: ai_move, 0, NULL,
1338: ai_move, 0, NULL,
1339: ai_move, 0, NULL,
1340: ai_move, 0, NULL,
1341:
1342: ai_move, 0, NULL,
1343: ai_move, 0, NULL,
1344: ai_move, 0, NULL,
1345: ai_move, 0, NULL,
1346: ai_move, 0, NULL,
1347: ai_move, 0, NULL,
1348: ai_move, 0, NULL,
1349: ai_move, 0, NULL,
1350: ai_move, 0, NULL,
1351: ai_move, 0, NULL,
1352:
1353: ai_move, 0, NULL,
1354: ai_move, 0, NULL,
1355: ai_move, 0, NULL,
1356: ai_move, 0, NULL,
1357: ai_move, 0, NULL,
1358: ai_move, 0, NULL,
1359: ai_move, 0, NULL,
1360: ai_move, 0, NULL,
1361: ai_move, 0, NULL,
1362: ai_move, 0, NULL,
1363:
1364: ai_move, 0, NULL,
1365: ai_move, 0, NULL,
1366: ai_move, 0, NULL,
1367: ai_move, 0, NULL,
1368: ai_move, 0, NULL,
1369: ai_move, 0, NULL,
1370: ai_move, 0, NULL,
1371: ai_move, 0, NULL,
1372: ai_move, 0, NULL,
1373: ai_move, 0, NULL,
1374:
1375: ai_move, 0, NULL,
1376: ai_move, 0, NULL,
1377: ai_move, 0, NULL,
1378: ai_move, 0, NULL,
1379: ai_move, 0, NULL,
1380: };
1381: mmove_t soldier_move_death3 = {FRAME_death301, FRAME_death345, soldier_frames_death3, soldier_dead};
1382:
1383: mframe_t soldier_frames_death4 [] =
1384: {
1385: ai_move, 0, NULL,
1386: ai_move, 0, NULL,
1387: ai_move, 0, NULL,
1388: ai_move, 0, NULL,
1389: ai_move, 0, NULL,
1390: ai_move, 0, NULL,
1391: ai_move, 0, NULL,
1392: ai_move, 0, NULL,
1393: ai_move, 0, NULL,
1394: ai_move, 0, NULL,
1395:
1396: ai_move, 0, NULL,
1397: ai_move, 0, NULL,
1398: ai_move, 0, NULL,
1399: ai_move, 0, NULL,
1400: ai_move, 0, NULL,
1401: ai_move, 0, NULL,
1402: ai_move, 0, NULL,
1403: ai_move, 0, NULL,
1404: ai_move, 0, NULL,
1405: ai_move, 0, NULL,
1406:
1407: ai_move, 0, NULL,
1408: ai_move, 0, NULL,
1409: ai_move, 0, NULL,
1410: ai_move, 0, NULL,
1411: ai_move, 0, NULL,
1412: ai_move, 0, NULL,
1413: ai_move, 0, NULL,
1414: ai_move, 0, NULL,
1415: ai_move, 0, NULL,
1416: ai_move, 0, NULL,
1417:
1418: ai_move, 0, NULL,
1419: ai_move, 0, NULL,
1420: ai_move, 0, NULL,
1421: ai_move, 0, NULL,
1422: ai_move, 0, NULL,
1423: ai_move, 0, NULL,
1424: ai_move, 0, NULL,
1425: ai_move, 0, NULL,
1426: ai_move, 0, NULL,
1427: ai_move, 0, NULL,
1428:
1429: ai_move, 0, NULL,
1430: ai_move, 0, NULL,
1431: ai_move, 0, NULL,
1432: ai_move, 0, NULL,
1433: ai_move, 0, NULL,
1434: ai_move, 0, NULL,
1435: ai_move, 0, NULL,
1436: ai_move, 0, NULL,
1437: ai_move, 0, NULL,
1438: ai_move, 0, NULL,
1439:
1440: ai_move, 0, NULL,
1441: ai_move, 0, NULL,
1442: ai_move, 0, NULL
1443: };
1444: // PMM -changed to soldier_dead2 to get a larger bounding box
1445: mmove_t soldier_move_death4 = {FRAME_death401, FRAME_death453, soldier_frames_death4, soldier_dead2};
1446:
1447: mframe_t soldier_frames_death5 [] =
1448: {
1449: ai_move, -5, NULL,
1450: ai_move, -5, NULL,
1451: ai_move, -5, NULL,
1452: ai_move, 0, NULL,
1453: ai_move, 0, NULL,
1454: ai_move, 0, NULL,
1455: ai_move, 0, NULL,
1456: ai_move, 0, NULL,
1457: ai_move, 0, NULL,
1458: ai_move, 0, NULL,
1459:
1460: ai_move, 0, NULL,
1461: ai_move, 0, NULL,
1462: ai_move, 0, NULL,
1463: ai_move, 0, NULL,
1464: ai_move, 0, NULL,
1465: ai_move, 0, NULL,
1466: ai_move, 0, NULL,
1467: ai_move, 0, NULL,
1468: ai_move, 0, NULL,
1469: ai_move, 0, NULL,
1470:
1471: ai_move, 0, NULL,
1472: ai_move, 0, NULL,
1473: ai_move, 0, NULL,
1474: ai_move, 0, NULL
1475: };
1476: mmove_t soldier_move_death5 = {FRAME_death501, FRAME_death524, soldier_frames_death5, soldier_dead};
1477:
1478: mframe_t soldier_frames_death6 [] =
1479: {
1480: ai_move, 0, NULL,
1481: ai_move, 0, NULL,
1482: ai_move, 0, NULL,
1483: ai_move, 0, NULL,
1484: ai_move, 0, NULL,
1485: ai_move, 0, NULL,
1486: ai_move, 0, NULL,
1487: ai_move, 0, NULL,
1488: ai_move, 0, NULL,
1489: ai_move, 0, NULL
1490: };
1491: mmove_t soldier_move_death6 = {FRAME_death601, FRAME_death610, soldier_frames_death6, soldier_dead};
1492:
1493: void soldier_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
1494: {
1495: int n;
1496:
1497: // check for gib
1498: if (self->health <= self->gib_health)
1499: {
1500: gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
1501: for (n= 0; n < 3; n++)
1502: ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
1503: ThrowGib (self, "models/objects/gibs/chest/tris.md2", damage, GIB_ORGANIC);
1504: ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
1505: self->deadflag = DEAD_DEAD;
1506: return;
1507: }
1508:
1509: if (self->deadflag == DEAD_DEAD)
1510: return;
1511:
1512: // regular death
1513: self->deadflag = DEAD_DEAD;
1514: self->takedamage = DAMAGE_YES;
1515: self->s.skinnum |= 1;
1516:
1517: if (self->s.skinnum == 1)
1518: gi.sound (self, CHAN_VOICE, sound_death_light, 1, ATTN_NORM, 0);
1519: else if (self->s.skinnum == 3)
1520: gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0);
1521: else // (self->s.skinnum == 5)
1522: gi.sound (self, CHAN_VOICE, sound_death_ss, 1, ATTN_NORM, 0);
1523:
1524: if (fabs((self->s.origin[2] + self->viewheight) - point[2]) <= 4)
1525: {
1526: // head shot
1527: self->monsterinfo.currentmove = &soldier_move_death3;
1528: return;
1529: }
1530:
1531: n = rand() % 5;
1532: if (n == 0)
1533: self->monsterinfo.currentmove = &soldier_move_death1;
1534: else if (n == 1)
1535: self->monsterinfo.currentmove = &soldier_move_death2;
1536: else if (n == 2)
1537: self->monsterinfo.currentmove = &soldier_move_death4;
1538: else if (n == 3)
1539: self->monsterinfo.currentmove = &soldier_move_death5;
1540: else
1541: self->monsterinfo.currentmove = &soldier_move_death6;
1542: }
1543:
1544: //
1545: // NEW DODGE CODE
1546: //
1547:
1548: void soldier_sidestep (edict_t *self)
1549: {
1550: if (self->s.skinnum <= 3)
1551: {
1552: if ((g_showlogic) && (g_showlogic->value))
1553: gi.dprintf ("shooting back!\n");
1554: if (self->monsterinfo.currentmove != &soldier_move_attack6)
1555: self->monsterinfo.currentmove = &soldier_move_attack6;
1556: }
1557: else
1558: {
1559: if ((g_showlogic) && (g_showlogic->value))
1560: gi.dprintf ("strafing away!\n");
1561: if (self->monsterinfo.currentmove != &soldier_move_start_run)
1562: self->monsterinfo.currentmove = &soldier_move_start_run;
1563: }
1564: }
1565:
1566: void soldier_duck (edict_t *self, float eta)
1567: {
1568: float r;
1569:
1570: // has to be done immediately otherwise he can get stuck
1571: monster_duck_down(self);
1572:
1573: if (skill->value == 0)
1574: {
1575: // PMM - stupid dodge
1576: self->monsterinfo.nextframe = FRAME_duck01;
1577: self->monsterinfo.currentmove = &soldier_move_duck;
1578: self->monsterinfo.duck_wait_time = level.time + eta + 1;
1579: return;
1580: }
1581:
1582: r = random();
1583:
1584: if (r > (skill->value * 0.3))
1585: {
1586: self->monsterinfo.nextframe = FRAME_duck01;
1587: self->monsterinfo.currentmove = &soldier_move_duck;
1588: self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value));
1589: }
1590: else
1591: {
1592: self->monsterinfo.nextframe = FRAME_attak301;
1593: self->monsterinfo.currentmove = &soldier_move_attack3;
1594: self->monsterinfo.duck_wait_time = level.time + eta + 1;
1595: }
1596: return;
1597: }
1598:
1599: //=========
1600: //ROGUE
1601: void soldier_blind (edict_t *self);
1602:
1603: mframe_t soldier_frames_blind [] =
1604: {
1605: ai_move, 0, soldier_idle,
1606: ai_move, 0, NULL,
1607: ai_move, 0, NULL,
1608: ai_move, 0, NULL,
1609: ai_move, 0, NULL,
1610: ai_move, 0, NULL,
1611: ai_move, 0, NULL,
1612: ai_move, 0, NULL,
1613: ai_move, 0, NULL,
1614: ai_move, 0, NULL,
1615:
1616: ai_move, 0, NULL,
1617: ai_move, 0, NULL,
1618: ai_move, 0, NULL,
1619: ai_move, 0, NULL,
1620: ai_move, 0, NULL,
1621: ai_move, 0, NULL,
1622: ai_move, 0, NULL,
1623: ai_move, 0, NULL,
1624: ai_move, 0, NULL,
1625: ai_move, 0, NULL,
1626:
1627: ai_move, 0, NULL,
1628: ai_move, 0, NULL,
1629: ai_move, 0, NULL,
1630: ai_move, 0, NULL,
1631: ai_move, 0, NULL,
1632: ai_move, 0, NULL,
1633: ai_move, 0, NULL,
1634: ai_move, 0, NULL,
1635: ai_move, 0, NULL,
1636: ai_move, 0, NULL
1637: };
1638: mmove_t soldier_move_blind = {FRAME_stand101, FRAME_stand130, soldier_frames_blind, soldier_blind};
1639:
1640: void soldier_blind (edict_t *self)
1641: {
1642: self->monsterinfo.currentmove = &soldier_move_blind;
1643: }
1644: //ROGUE
1645: //=========
1646:
1647: //
1648: // SPAWN
1649: //
1650:
1651: void SP_monster_soldier_x (edict_t *self)
1652: {
1653:
1654: self->s.modelindex = gi.modelindex ("models/monsters/soldier/tris.md2");
1655: //PMM
1656: // self->s.effects |= EF_SPLATTER;
1657: //PMM
1658: self->monsterinfo.scale = MODEL_SCALE;
1659: VectorSet (self->mins, -16, -16, -24);
1660: VectorSet (self->maxs, 16, 16, 32);
1661: self->movetype = MOVETYPE_STEP;
1662: self->solid = SOLID_BBOX;
1663:
1664: sound_idle = gi.soundindex ("soldier/solidle1.wav");
1665: sound_sight1 = gi.soundindex ("soldier/solsght1.wav");
1666: sound_sight2 = gi.soundindex ("soldier/solsrch1.wav");
1667: sound_cock = gi.soundindex ("infantry/infatck3.wav");
1668:
1669: self->mass = 100;
1670:
1671: self->pain = soldier_pain;
1672: self->die = soldier_die;
1673:
1674: self->monsterinfo.stand = soldier_stand;
1675: self->monsterinfo.walk = soldier_walk;
1676: self->monsterinfo.run = soldier_run;
1677: self->monsterinfo.dodge = M_MonsterDodge;
1678: self->monsterinfo.attack = soldier_attack;
1679: self->monsterinfo.melee = NULL;
1680: self->monsterinfo.sight = soldier_sight;
1681:
1682: //=====
1683: //ROGUE
1684: self->monsterinfo.blocked = soldier_blocked;
1685: self->monsterinfo.duck = soldier_duck;
1686: self->monsterinfo.unduck = monster_duck_up;
1687: self->monsterinfo.sidestep = soldier_sidestep;
1688:
1689: if(self->spawnflags & 8) // blind
1690: self->monsterinfo.stand = soldier_blind;
1691: //ROGUE
1692: //=====
1693:
1694: gi.linkentity (self);
1695:
1696: self->monsterinfo.stand (self);
1697:
1698: walkmonster_start (self);
1699: }
1700:
1701:
1702: /*QUAKED monster_soldier_light (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight Blind
1703:
1704: Blind - monster will just stand there until triggered
1705: */
1706: void SP_monster_soldier_light (edict_t *self)
1707: {
1708: if (deathmatch->value)
1709: {
1710: G_FreeEdict (self);
1711: return;
1712: }
1713:
1714: SP_monster_soldier_x (self);
1715:
1716: sound_pain_light = gi.soundindex ("soldier/solpain2.wav");
1717: sound_death_light = gi.soundindex ("soldier/soldeth2.wav");
1718: gi.modelindex ("models/objects/laser/tris.md2");
1719: gi.soundindex ("misc/lasfly.wav");
1720: gi.soundindex ("soldier/solatck2.wav");
1721:
1722: self->s.skinnum = 0;
1723: self->health = 20;
1724: self->gib_health = -30;
1725:
1726: // PMM - blindfire
1727: self->monsterinfo.blindfire = true;
1728: }
1729:
1730: /*QUAKED monster_soldier (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight Blind
1731:
1732: Blind - monster will just stand there until triggered
1733: */
1734: void SP_monster_soldier (edict_t *self)
1735: {
1736: if (deathmatch->value)
1737: {
1738: G_FreeEdict (self);
1739: return;
1740: }
1741:
1742: SP_monster_soldier_x (self);
1743:
1744: sound_pain = gi.soundindex ("soldier/solpain1.wav");
1745: sound_death = gi.soundindex ("soldier/soldeth1.wav");
1746: gi.soundindex ("soldier/solatck1.wav");
1747:
1748: self->s.skinnum = 2;
1749: self->health = 30;
1750: self->gib_health = -30;
1751: }
1752:
1753: /*QUAKED monster_soldier_ss (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight Blind
1754:
1755: Blind - monster will just stand there until triggered
1756: */
1757: void SP_monster_soldier_ss (edict_t *self)
1758: {
1759: if (deathmatch->value)
1760: {
1761: G_FreeEdict (self);
1762: return;
1763: }
1764:
1765: SP_monster_soldier_x (self);
1766:
1767: sound_pain_ss = gi.soundindex ("soldier/solpain3.wav");
1768: sound_death_ss = gi.soundindex ("soldier/soldeth3.wav");
1769: gi.soundindex ("soldier/solatck3.wav");
1770:
1771: self->s.skinnum = 4;
1772: self->health = 40;
1773: self->gib_health = -30;
1774: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.