1 /*
2 ==============================================================================
3
4 INFANTRY
5
6 ==============================================================================
7 */
8
9 #include "g_local.h"
10 #include "m_infantry.h"
11
12 void InfantryMachineGun (edict_t *self);
13
14
15 static int sound_pain1;
16 static int sound_pain2;
17 static int sound_die1;
18 static int sound_die2;
19
20 static int sound_gunshot;
21 static int sound_weapon_cock;
22 static int sound_punch_swing;
23 static int sound_punch_hit;
24 static int sound_sight;
25 static int sound_search;
26 static int sound_idle;
27
28 mframe_t infantry_frames_stand [] =
29 {
30 ai_stand, 0, NULL,
31 ai_stand, 0, NULL,
32 ai_stand, 0, NULL,
33 ai_stand, 0, NULL,
34 ai_stand, 0, NULL,
35 ai_stand, 0, NULL,
36 ai_stand, 0, NULL,
37 ai_stand, 0, NULL,
38 ai_stand, 0, NULL,
39 ai_stand, 0, NULL,
40 ai_stand, 0, NULL,
41 ai_stand, 0, NULL,
42 ai_stand, 0, NULL,
43 ai_stand, 0, NULL,
44 ai_stand, 0, NULL,
45 ai_stand, 0, NULL,
46 ai_stand, 0, NULL,
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 };
53 mmove_t infantry_move_stand = {FRAME_stand50, FRAME_stand71, infantry_frames_stand, NULL};
54
infantry_stand(edict_t * self)55 void infantry_stand (edict_t *self)
56 {
57 self->monsterinfo.currentmove = &infantry_move_stand;
58 }
59
60
61 mframe_t infantry_frames_fidget [] =
62 {
63 ai_stand, 1, NULL,
64 ai_stand, 0, NULL,
65 ai_stand, 1, NULL,
66 ai_stand, 3, NULL,
67 ai_stand, 6, NULL,
68 ai_stand, 3, NULL,
69 ai_stand, 0, NULL,
70 ai_stand, 0, NULL,
71 ai_stand, 0, NULL,
72 ai_stand, 0, NULL,
73 ai_stand, 1, NULL,
74 ai_stand, 0, NULL,
75 ai_stand, 0, NULL,
76 ai_stand, 0, NULL,
77 ai_stand, 0, NULL,
78 ai_stand, 1, NULL,
79 ai_stand, 0, NULL,
80 ai_stand, -1, NULL,
81 ai_stand, 0, NULL,
82 ai_stand, 0, NULL,
83 ai_stand, 1, NULL,
84 ai_stand, 0, NULL,
85 ai_stand, -2, NULL,
86 ai_stand, 1, NULL,
87 ai_stand, 1, NULL,
88 ai_stand, 1, NULL,
89 ai_stand, -1, NULL,
90 ai_stand, 0, NULL,
91 ai_stand, 0, NULL,
92 ai_stand, -1, NULL,
93 ai_stand, 0, NULL,
94 ai_stand, 0, NULL,
95 ai_stand, 0, NULL,
96 ai_stand, 0, NULL,
97 ai_stand, 0, NULL,
98 ai_stand, -1, NULL,
99 ai_stand, 0, NULL,
100 ai_stand, 0, NULL,
101 ai_stand, 1, NULL,
102 ai_stand, 0, NULL,
103 ai_stand, 0, NULL,
104 ai_stand, -1, NULL,
105 ai_stand, -1, NULL,
106 ai_stand, 0, NULL,
107 ai_stand, -3, NULL,
108 ai_stand, -2, NULL,
109 ai_stand, -3, NULL,
110 ai_stand, -3, NULL,
111 ai_stand, -2, NULL
112 };
113 mmove_t infantry_move_fidget = {FRAME_stand01, FRAME_stand49, infantry_frames_fidget, infantry_stand};
114
infantry_fidget(edict_t * self)115 void infantry_fidget (edict_t *self)
116 {
117 self->monsterinfo.currentmove = &infantry_move_fidget;
118 gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
119 }
120
121 mframe_t infantry_frames_walk [] =
122 {
123 ai_walk, 5, NULL,
124 ai_walk, 4, NULL,
125 ai_walk, 4, NULL,
126 ai_walk, 5, NULL,
127 ai_walk, 4, NULL,
128 ai_walk, 5, NULL,
129 ai_walk, 6, NULL,
130 ai_walk, 4, NULL,
131 ai_walk, 4, NULL,
132 ai_walk, 4, NULL,
133 ai_walk, 4, NULL,
134 ai_walk, 5, NULL
135 };
136 mmove_t infantry_move_walk = {FRAME_walk03, FRAME_walk14, infantry_frames_walk, NULL};
137
infantry_walk(edict_t * self)138 void infantry_walk (edict_t *self)
139 {
140 self->monsterinfo.currentmove = &infantry_move_walk;
141 }
142
143 mframe_t infantry_frames_run [] =
144 {
145 ai_run, 10, NULL,
146 ai_run, 20, NULL,
147 ai_run, 5, NULL,
148 ai_run, 7, monster_done_dodge,
149 ai_run, 30, NULL,
150 ai_run, 35, NULL,
151 ai_run, 2, NULL,
152 ai_run, 6, NULL
153 };
154 mmove_t infantry_move_run = {FRAME_run01, FRAME_run08, infantry_frames_run, NULL};
155
infantry_run(edict_t * self)156 void infantry_run (edict_t *self)
157 {
158 monster_done_dodge (self);
159
160 if (self->monsterinfo.aiflags & AI_STAND_GROUND)
161 self->monsterinfo.currentmove = &infantry_move_stand;
162 else
163 self->monsterinfo.currentmove = &infantry_move_run;
164 }
165
166
167 mframe_t infantry_frames_pain1 [] =
168 {
169 ai_move, -3, NULL,
170 ai_move, -2, NULL,
171 ai_move, -1, NULL,
172 ai_move, -2, NULL,
173 ai_move, -1, NULL,
174 ai_move, 1, NULL,
175 ai_move, -1, NULL,
176 ai_move, 1, NULL,
177 ai_move, 6, NULL,
178 ai_move, 2, NULL
179 };
180 mmove_t infantry_move_pain1 = {FRAME_pain101, FRAME_pain110, infantry_frames_pain1, infantry_run};
181
182 mframe_t infantry_frames_pain2 [] =
183 {
184 ai_move, -3, NULL,
185 ai_move, -3, NULL,
186 ai_move, 0, NULL,
187 ai_move, -1, NULL,
188 ai_move, -2, NULL,
189 ai_move, 0, NULL,
190 ai_move, 0, NULL,
191 ai_move, 2, NULL,
192 ai_move, 5, NULL,
193 ai_move, 2, NULL
194 };
195 mmove_t infantry_move_pain2 = {FRAME_pain201, FRAME_pain210, infantry_frames_pain2, infantry_run};
196
infantry_pain(edict_t * self,edict_t * other,float kick,int damage)197 void infantry_pain (edict_t *self, edict_t *other, float kick, int damage)
198 {
199 int n;
200
201 if (self->health < (self->max_health / 2))
202 self->s.skinnum = 1;
203
204 if (!self->groundentity)
205 {
206 // if ((g_showlogic) && (g_showlogic->value))
207 // gi.dprintf ("infantry: pain avoided due to no ground\n");
208 return;
209 }
210
211 monster_done_dodge (self);
212
213 if (level.time < self->pain_debounce_time)
214 return;
215
216 self->pain_debounce_time = level.time + 3;
217
218 if (skill->value == 3)
219 return; // no pain anims in nightmare
220
221 n = rand() % 2;
222 if (n == 0)
223 {
224 self->monsterinfo.currentmove = &infantry_move_pain1;
225 gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
226 }
227 else
228 {
229 self->monsterinfo.currentmove = &infantry_move_pain2;
230 gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
231 }
232
233 // PMM - clear duck flag
234 if (self->monsterinfo.aiflags & AI_DUCKED)
235 monster_duck_up(self);
236 }
237
238
239 vec3_t aimangles[] =
240 {
241 0.0, 5.0, 0.0,
242 10.0, 15.0, 0.0,
243 20.0, 25.0, 0.0,
244 25.0, 35.0, 0.0,
245 30.0, 40.0, 0.0,
246 30.0, 45.0, 0.0,
247 25.0, 50.0, 0.0,
248 20.0, 40.0, 0.0,
249 15.0, 35.0, 0.0,
250 40.0, 35.0, 0.0,
251 70.0, 35.0, 0.0,
252 90.0, 35.0, 0.0
253 };
254
InfantryMachineGun(edict_t * self)255 void InfantryMachineGun (edict_t *self)
256 {
257 vec3_t start, target;
258 vec3_t forward, right;
259 vec3_t vec;
260 int flash_number;
261
262 if(!self->enemy || !self->enemy->inuse) //PGM
263 return; //PGM
264
265 // pmm - new attack start frame
266 if (self->s.frame == FRAME_attak104)
267 {
268 flash_number = MZ2_INFANTRY_MACHINEGUN_1;
269 AngleVectors (self->s.angles, forward, right, NULL);
270 G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
271
272 if (self->enemy)
273 {
274 VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target);
275 target[2] += self->enemy->viewheight;
276 VectorSubtract (target, start, forward);
277 VectorNormalize (forward);
278 }
279 else
280 {
281 AngleVectors (self->s.angles, forward, right, NULL);
282 }
283 }
284 else
285 {
286 flash_number = MZ2_INFANTRY_MACHINEGUN_2 + (self->s.frame - FRAME_death211);
287
288 AngleVectors (self->s.angles, forward, right, NULL);
289 G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
290
291 VectorSubtract (self->s.angles, aimangles[flash_number-MZ2_INFANTRY_MACHINEGUN_2], vec);
292 AngleVectors (vec, forward, NULL, NULL);
293 }
294
295 monster_fire_bullet (self, start, forward, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number);
296 }
297
infantry_sight(edict_t * self,edict_t * other)298 void infantry_sight (edict_t *self, edict_t *other)
299 {
300 gi.sound (self, CHAN_BODY, sound_sight, 1, ATTN_NORM, 0);
301 }
302
infantry_dead(edict_t * self)303 void infantry_dead (edict_t *self)
304 {
305 VectorSet (self->mins, -16, -16, -24);
306 VectorSet (self->maxs, 16, 16, -8);
307 self->movetype = MOVETYPE_TOSS;
308 self->svflags |= SVF_DEADMONSTER;
309 gi.linkentity (self);
310
311 M_FlyCheck (self);
312 }
313
314 mframe_t infantry_frames_death1 [] =
315 {
316 ai_move, -4, NULL,
317 ai_move, 0, NULL,
318 ai_move, 0, NULL,
319 ai_move, -1, NULL,
320 ai_move, -4, NULL,
321 ai_move, 0, NULL,
322 ai_move, 0, NULL,
323 ai_move, 0, NULL,
324 ai_move, -1, NULL,
325 ai_move, 3, NULL,
326 ai_move, 1, NULL,
327 ai_move, 1, NULL,
328 ai_move, -2, NULL,
329 ai_move, 2, NULL,
330 ai_move, 2, NULL,
331 ai_move, 9, NULL,
332 ai_move, 9, NULL,
333 ai_move, 5, NULL,
334 ai_move, -3, NULL,
335 ai_move, -3, NULL
336 };
337 mmove_t infantry_move_death1 = {FRAME_death101, FRAME_death120, infantry_frames_death1, infantry_dead};
338
339 // Off with his head
340 mframe_t infantry_frames_death2 [] =
341 {
342 ai_move, 0, NULL,
343 ai_move, 1, NULL,
344 ai_move, 5, NULL,
345 ai_move, -1, NULL,
346 ai_move, 0, NULL,
347 ai_move, 1, NULL,
348 ai_move, 1, NULL,
349 ai_move, 4, NULL,
350 ai_move, 3, NULL,
351 ai_move, 0, NULL,
352 ai_move, -2, InfantryMachineGun,
353 ai_move, -2, InfantryMachineGun,
354 ai_move, -3, InfantryMachineGun,
355 ai_move, -1, InfantryMachineGun,
356 ai_move, -2, InfantryMachineGun,
357 ai_move, 0, InfantryMachineGun,
358 ai_move, 2, InfantryMachineGun,
359 ai_move, 2, InfantryMachineGun,
360 ai_move, 3, InfantryMachineGun,
361 ai_move, -10, InfantryMachineGun,
362 ai_move, -7, InfantryMachineGun,
363 ai_move, -8, InfantryMachineGun,
364 ai_move, -6, NULL,
365 ai_move, 4, NULL,
366 ai_move, 0, NULL
367 };
368 mmove_t infantry_move_death2 = {FRAME_death201, FRAME_death225, infantry_frames_death2, infantry_dead};
369
370 mframe_t infantry_frames_death3 [] =
371 {
372 ai_move, 0, NULL,
373 ai_move, 0, NULL,
374 ai_move, 0, NULL,
375 ai_move, -6, NULL,
376 ai_move, -11, NULL,
377 ai_move, -3, NULL,
378 ai_move, -11, NULL,
379 ai_move, 0, NULL,
380 ai_move, 0, NULL
381 };
382 mmove_t infantry_move_death3 = {FRAME_death301, FRAME_death309, infantry_frames_death3, infantry_dead};
383
384
infantry_die(edict_t * self,edict_t * inflictor,edict_t * attacker,int damage,vec3_t point)385 void infantry_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
386 {
387 int n;
388
389 // check for gib
390 if (self->health <= self->gib_health)
391 {
392 gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
393 for (n= 0; n < 2; n++)
394 ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
395 for (n= 0; n < 4; n++)
396 ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
397 ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
398 self->deadflag = DEAD_DEAD;
399 return;
400 }
401
402 if (self->deadflag == DEAD_DEAD)
403 return;
404
405 // regular death
406 self->deadflag = DEAD_DEAD;
407 self->takedamage = DAMAGE_YES;
408
409 n = rand() % 3;
410 if (n == 0)
411 {
412 self->monsterinfo.currentmove = &infantry_move_death1;
413 gi.sound (self, CHAN_VOICE, sound_die2, 1, ATTN_NORM, 0);
414 }
415 else if (n == 1)
416 {
417 self->monsterinfo.currentmove = &infantry_move_death2;
418 gi.sound (self, CHAN_VOICE, sound_die1, 1, ATTN_NORM, 0);
419 }
420 else
421 {
422 self->monsterinfo.currentmove = &infantry_move_death3;
423 gi.sound (self, CHAN_VOICE, sound_die2, 1, ATTN_NORM, 0);
424 }
425 }
426
427 mframe_t infantry_frames_duck [] =
428 {
429 ai_move, -2, monster_duck_down,
430 ai_move, -5, monster_duck_hold,
431 ai_move, 3, NULL,
432 ai_move, 4, monster_duck_up,
433 ai_move, 0, NULL
434 };
435 mmove_t infantry_move_duck = {FRAME_duck01, FRAME_duck05, infantry_frames_duck, infantry_run};
436
437 // PMM - dodge code moved below so I can see the attack frames
438
439
infantry_cock_gun(edict_t * self)440 void infantry_cock_gun (edict_t *self)
441 {
442 // pmm .. code that was here no longer needed
443 gi.sound (self, CHAN_WEAPON, sound_weapon_cock, 1, ATTN_NORM, 0);
444 }
445
infantry_fire(edict_t * self)446 void infantry_fire (edict_t *self)
447 {
448 InfantryMachineGun (self);
449 if (level.time >= self->monsterinfo.pausetime)
450 self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
451 else
452 self->monsterinfo.aiflags |= AI_HOLD_FRAME;
453 }
454
455 // this is here instead of cock_gun
456
infantry_fire_prep(edict_t * self)457 void infantry_fire_prep (edict_t *self)
458 {
459 int n;
460 n = (rand() & 15) + 3 + 1;
461 self->monsterinfo.pausetime = level.time + n*FRAMETIME;
462 }
463
464 // pmm
465 // frames reordered, tweaked for new frames
466
467 mframe_t infantry_frames_attack1 [] =
468 {
469 ai_charge, -3, NULL, //101
470 ai_charge, -2, NULL, //102
471 ai_charge, -1, infantry_fire_prep, //103
472 ai_charge, 5, infantry_fire, //104
473 ai_charge, 1, NULL, //105
474 ai_charge, -3, NULL, //106
475 ai_charge, -2, NULL, //107
476 ai_charge, 2, infantry_cock_gun, //108
477 ai_charge, 1, NULL, //109
478 ai_charge, 1, NULL, //110
479 ai_charge, -1, NULL, //111
480 ai_charge, 0, NULL, //112
481 ai_charge, -1, NULL, //113
482 ai_charge, -1, NULL, //114
483 ai_charge, 4, NULL //115
484 };
485 mmove_t infantry_move_attack1 = {FRAME_attak101, FRAME_attak115, infantry_frames_attack1, infantry_run};
486
487
infantry_swing(edict_t * self)488 void infantry_swing (edict_t *self)
489 {
490 gi.sound (self, CHAN_WEAPON, sound_punch_swing, 1, ATTN_NORM, 0);
491 }
492
infantry_smack(edict_t * self)493 void infantry_smack (edict_t *self)
494 {
495 vec3_t aim;
496
497 VectorSet (aim, MELEE_DISTANCE, 0, 0);
498 if (fire_hit (self, aim, (5 + (rand() % 5)), 50))
499 gi.sound (self, CHAN_WEAPON, sound_punch_hit, 1, ATTN_NORM, 0);
500 }
501
502 mframe_t infantry_frames_attack2 [] =
503 {
504 ai_charge, 3, NULL,
505 ai_charge, 6, NULL,
506 ai_charge, 0, infantry_swing,
507 ai_charge, 8, NULL,
508 ai_charge, 5, NULL,
509 ai_charge, 8, infantry_smack,
510 ai_charge, 6, NULL,
511 ai_charge, 3, NULL,
512 };
513 mmove_t infantry_move_attack2 = {FRAME_attak201, FRAME_attak208, infantry_frames_attack2, infantry_run};
514
infantry_attack(edict_t * self)515 void infantry_attack(edict_t *self)
516 {
517 monster_done_dodge (self);
518
519 if (range (self, self->enemy) == RANGE_MELEE)
520 self->monsterinfo.currentmove = &infantry_move_attack2;
521 else
522 self->monsterinfo.currentmove = &infantry_move_attack1;
523 }
524
525 //===========
526 //PGM
infantry_jump_now(edict_t * self)527 void infantry_jump_now (edict_t *self)
528 {
529 vec3_t forward,up;
530
531 monster_jump_start (self);
532
533 AngleVectors (self->s.angles, forward, NULL, up);
534 VectorMA(self->velocity, 100, forward, self->velocity);
535 VectorMA(self->velocity, 300, up, self->velocity);
536 }
537
infantry_jump2_now(edict_t * self)538 void infantry_jump2_now (edict_t *self)
539 {
540 vec3_t forward,up;
541
542 monster_jump_start (self);
543
544 AngleVectors (self->s.angles, forward, NULL, up);
545 VectorMA(self->velocity, 150, forward, self->velocity);
546 VectorMA(self->velocity, 400, up, self->velocity);
547 }
548
infantry_jump_wait_land(edict_t * self)549 void infantry_jump_wait_land (edict_t *self)
550 {
551 if(self->groundentity == NULL)
552 {
553 self->monsterinfo.nextframe = self->s.frame;
554
555 if(monster_jump_finished (self))
556 self->monsterinfo.nextframe = self->s.frame + 1;
557 }
558 else
559 self->monsterinfo.nextframe = self->s.frame + 1;
560 }
561
562 mframe_t infantry_frames_jump [] =
563 {
564 ai_move, 0, NULL,
565 ai_move, 0, NULL,
566 ai_move, 0, NULL,
567 ai_move, 0, infantry_jump_now,
568 ai_move, 0, NULL,
569 ai_move, 0, NULL,
570 ai_move, 0, NULL,
571 ai_move, 0, infantry_jump_wait_land,
572 ai_move, 0, NULL,
573 ai_move, 0, NULL
574 };
575 mmove_t infantry_move_jump = { FRAME_jump01, FRAME_jump10, infantry_frames_jump, infantry_run };
576
577 mframe_t infantry_frames_jump2 [] =
578 {
579 ai_move, -8, NULL,
580 ai_move, -4, NULL,
581 ai_move, -4, NULL,
582 ai_move, 0, infantry_jump_now,
583 ai_move, 0, NULL,
584 ai_move, 0, NULL,
585 ai_move, 0, NULL,
586 ai_move, 0, infantry_jump_wait_land,
587 ai_move, 0, NULL,
588 ai_move, 0, NULL
589 };
590 mmove_t infantry_move_jump2 = { FRAME_jump01, FRAME_jump10, infantry_frames_jump2, infantry_run };
591
infantry_jump(edict_t * self)592 void infantry_jump (edict_t *self)
593 {
594 if(!self->enemy)
595 return;
596
597 monster_done_dodge(self);
598
599 if(self->enemy->s.origin[2] > self->s.origin[2])
600 self->monsterinfo.currentmove = &infantry_move_jump2;
601 else
602 self->monsterinfo.currentmove = &infantry_move_jump;
603 }
604
infantry_blocked(edict_t * self,float dist)605 qboolean infantry_blocked (edict_t *self, float dist)
606 {
607 if(blocked_checkshot (self, 0.25 + (0.05 * skill->value) ))
608 return true;
609
610 if(blocked_checkjump (self, dist, 192, 40))
611 {
612 infantry_jump(self);
613 return true;
614 }
615
616 if(blocked_checkplat (self, dist))
617 return true;
618
619 return false;
620 }
621 //PGM
622 //===========
623 /*
624 void infantry_dodge (edict_t *self, edict_t *attacker, float eta, trace_t *tr)
625 {
626 //===========
627 //PMM - rogue rewrite of gunner dodge code.
628 float r;
629 float height;
630 int shooting = 0;
631
632 if (!self->enemy)
633 {
634 self->enemy = attacker;
635 FoundTarget (self);
636 }
637
638 // PMM - don't bother if it's going to hit anyway; fix for weird in-your-face etas (I was
639 // seeing numbers like 13 and 14)
640 if ((eta < 0.1) || (eta > 5))
641 return;
642
643 r = random();
644 if (r > (0.25*((skill->value)+1)))
645 return;
646
647 if ((self->monsterinfo.currentmove == &infantry_move_attack1) ||
648 (self->monsterinfo.currentmove == &infantry_move_attack2))
649 {
650 shooting = 1;
651 }
652 if (self->monsterinfo.aiflags & AI_DODGING)
653 {
654 height = self->absmax[2];
655 }
656 else
657 {
658 height = self->absmax[2]-32-1; // the -1 is because the absmax is s.origin + maxs + 1
659 }
660
661 // check to see if it makes sense to duck
662 if (tr->endpos[2] <= height)
663 {
664 vec3_t right,diff;
665
666 if (shooting)
667 {
668 self->monsterinfo.attack_state = AS_SLIDING;
669 return;
670 }
671 AngleVectors (self->s.angles, NULL, right, NULL);
672 VectorSubtract (tr->endpos, self->s.origin, diff);
673 if (DotProduct (right, diff) < 0)
674 {
675 self->monsterinfo.lefty = 1;
676 }
677 // if it doesn't sense to duck, try to strafe away
678 monster_done_dodge (self);
679 self->monsterinfo.currentmove = &infantry_move_run;
680 self->monsterinfo.attack_state = AS_SLIDING;
681 return;
682 }
683
684 if (skill->value == 0)
685 {
686 self->monsterinfo.currentmove = &infantry_move_duck;
687 // PMM - stupid dodge
688 self->monsterinfo.duck_wait_time = level.time + eta + 1;
689 self->monsterinfo.aiflags |= AI_DODGING;
690 return;
691 }
692
693 if (!shooting)
694 {
695 self->monsterinfo.currentmove = &infantry_move_duck;
696 self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value));
697 self->monsterinfo.aiflags |= AI_DODGING;
698 }
699 return;
700 //PMM
701 //===========
702 */
703
infantry_duck(edict_t * self,float eta)704 void infantry_duck (edict_t *self, float eta)
705 {
706 // if we're jumping, don't dodge
707 if ((self->monsterinfo.currentmove == &infantry_move_jump) ||
708 (self->monsterinfo.currentmove == &infantry_move_jump2))
709 {
710 return;
711 }
712
713 if ((self->monsterinfo.currentmove == &infantry_move_attack1) ||
714 (self->monsterinfo.currentmove == &infantry_move_attack2))
715 {
716 // if we're shooting, and not on easy, don't dodge
717 if (skill->value)
718 {
719 self->monsterinfo.aiflags &= ~AI_DUCKED;
720 return;
721 }
722 }
723
724 if (skill->value == 0)
725 // PMM - stupid dodge
726 self->monsterinfo.duck_wait_time = level.time + eta + 1;
727 else
728 self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value));
729
730 // has to be done immediately otherwise he can get stuck
731 monster_duck_down(self);
732
733 self->monsterinfo.nextframe = FRAME_duck01;
734 self->monsterinfo.currentmove = &infantry_move_duck;
735 return;
736 }
737
infantry_sidestep(edict_t * self)738 void infantry_sidestep (edict_t *self)
739 {
740 // if we're jumping, don't dodge
741 if ((self->monsterinfo.currentmove == &infantry_move_jump) ||
742 (self->monsterinfo.currentmove == &infantry_move_jump2))
743 {
744 return;
745 }
746
747 if ((self->monsterinfo.currentmove == &infantry_move_attack1) ||
748 (self->monsterinfo.currentmove == &infantry_move_attack2))
749 {
750 // if we're shooting, and not on easy, don't dodge
751 if (skill->value)
752 {
753 self->monsterinfo.aiflags &= ~AI_DODGING;
754 return;
755 }
756 }
757
758 if (self->monsterinfo.currentmove != &infantry_move_run)
759 self->monsterinfo.currentmove = &infantry_move_run;
760 }
761
762 /*QUAKED monster_infantry (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
763 */
SP_monster_infantry(edict_t * self)764 void SP_monster_infantry (edict_t *self)
765 {
766 if (deathmatch->value)
767 {
768 G_FreeEdict (self);
769 return;
770 }
771
772 sound_pain1 = gi.soundindex ("infantry/infpain1.wav");
773 sound_pain2 = gi.soundindex ("infantry/infpain2.wav");
774 sound_die1 = gi.soundindex ("infantry/infdeth1.wav");
775 sound_die2 = gi.soundindex ("infantry/infdeth2.wav");
776
777 sound_gunshot = gi.soundindex ("infantry/infatck1.wav");
778 sound_weapon_cock = gi.soundindex ("infantry/infatck3.wav");
779 sound_punch_swing = gi.soundindex ("infantry/infatck2.wav");
780 sound_punch_hit = gi.soundindex ("infantry/melee2.wav");
781
782 sound_sight = gi.soundindex ("infantry/infsght1.wav");
783 sound_search = gi.soundindex ("infantry/infsrch1.wav");
784 sound_idle = gi.soundindex ("infantry/infidle1.wav");
785
786
787 self->movetype = MOVETYPE_STEP;
788 self->solid = SOLID_BBOX;
789 self->s.modelindex = gi.modelindex("models/monsters/infantry/tris.md2");
790 VectorSet (self->mins, -16, -16, -24);
791 VectorSet (self->maxs, 16, 16, 32);
792
793 self->health = 100;
794 self->gib_health = -40;
795 self->mass = 200;
796
797 self->pain = infantry_pain;
798 self->die = infantry_die;
799
800 self->monsterinfo.stand = infantry_stand;
801 self->monsterinfo.walk = infantry_walk;
802 self->monsterinfo.run = infantry_run;
803 // pmm
804 self->monsterinfo.dodge = M_MonsterDodge;
805 self->monsterinfo.duck = infantry_duck;
806 self->monsterinfo.unduck = monster_duck_up;
807 self->monsterinfo.sidestep = infantry_sidestep;
808 // self->monsterinfo.dodge = infantry_dodge;
809 // pmm
810 self->monsterinfo.attack = infantry_attack;
811 self->monsterinfo.melee = NULL;
812 self->monsterinfo.sight = infantry_sight;
813 self->monsterinfo.idle = infantry_fidget;
814 self->monsterinfo.blocked = infantry_blocked;
815
816 gi.linkentity (self);
817
818 self->monsterinfo.currentmove = &infantry_move_stand;
819 self->monsterinfo.scale = MODEL_SCALE;
820
821 walkmonster_start (self);
822 }
823