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 #define BLASTER_DISTANCE 300
25 
soldier_idle(edict_t * self)26 void soldier_idle (edict_t *self)
27 {
28 	if (random() > 0.8)
29 		gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
30 }
31 
soldier_cock(edict_t * self)32 void soldier_cock (edict_t *self)
33 {
34 	if (self->s.frame == FRAME_stand322)
35 		gi.sound (self, CHAN_WEAPON, sound_cock, 1, ATTN_IDLE, 0);
36 	else
37 		gi.sound (self, CHAN_WEAPON, sound_cock, 1, ATTN_NORM, 0);
38 }
39 
40 
41 // STAND
42 
43 void soldier_stand (edict_t *self);
44 
45 mframe_t soldier_frames_stand1 [] =
46 {
47 	ai_stand, 0, soldier_idle,
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 	ai_stand, 0, NULL,
57 
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 	ai_stand, 0, NULL,
68 
69 	ai_stand, 0, NULL,
70 	ai_stand, 0, NULL,
71 	ai_stand, 0, NULL,
72 	ai_stand, 0, NULL,
73 	ai_stand, 0, NULL,
74 	ai_stand, 0, NULL,
75 	ai_stand, 0, NULL,
76 	ai_stand, 0, NULL,
77 	ai_stand, 0, NULL,
78 	ai_stand, 0, NULL
79 };
80 mmove_t soldier_move_stand1 = {FRAME_stand101, FRAME_stand130, soldier_frames_stand1, soldier_stand};
81 
82 mframe_t soldier_frames_stand3 [] =
83 {
84 	ai_stand, 0, NULL,
85 	ai_stand, 0, NULL,
86 	ai_stand, 0, NULL,
87 	ai_stand, 0, NULL,
88 	ai_stand, 0, NULL,
89 	ai_stand, 0, NULL,
90 	ai_stand, 0, NULL,
91 	ai_stand, 0, NULL,
92 	ai_stand, 0, NULL,
93 	ai_stand, 0, NULL,
94 
95 	ai_stand, 0, NULL,
96 	ai_stand, 0, NULL,
97 	ai_stand, 0, NULL,
98 	ai_stand, 0, NULL,
99 	ai_stand, 0, NULL,
100 	ai_stand, 0, NULL,
101 	ai_stand, 0, NULL,
102 	ai_stand, 0, NULL,
103 	ai_stand, 0, NULL,
104 	ai_stand, 0, NULL,
105 
106 	ai_stand, 0, NULL,
107 	ai_stand, 0, soldier_cock,
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 	ai_stand, 0, NULL,
116 
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 	ai_stand, 0, NULL
126 };
127 mmove_t soldier_move_stand3 = {FRAME_stand301, FRAME_stand339, soldier_frames_stand3, soldier_stand};
128 
129 #if 0
130 mframe_t soldier_frames_stand4 [] =
131 {
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 	ai_stand, 0, NULL,
142 
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 	ai_stand, 0, NULL,
153 
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 	ai_stand, 0, NULL,
164 
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 	ai_stand, 0, NULL,
175 
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, 0, NULL,
182 	ai_stand, 4, NULL,
183 	ai_stand, 1, NULL,
184 	ai_stand, -1, NULL,
185 	ai_stand, -2, NULL,
186 
187 	ai_stand, 0, NULL,
188 	ai_stand, 0, NULL
189 };
190 mmove_t soldier_move_stand4 = {FRAME_stand401, FRAME_stand452, soldier_frames_stand4, NULL};
191 #endif
192 
soldier_stand(edict_t * self)193 void soldier_stand (edict_t *self)
194 {
195 	if ((self->monsterinfo.currentmove == &soldier_move_stand3) || (random() < 0.8))
196 		self->monsterinfo.currentmove = &soldier_move_stand1;
197 	else
198 		self->monsterinfo.currentmove = &soldier_move_stand3;
199 }
200 
201 
202 //
203 // WALK
204 //
205 
soldier_walk1_random(edict_t * self)206 void soldier_walk1_random (edict_t *self)
207 {
208 	if (random() > 0.1)
209 		self->monsterinfo.nextframe = FRAME_walk101;
210 }
211 
212 mframe_t soldier_frames_walk1 [] =
213 {
214 	ai_walk, 3,  NULL,
215 	ai_walk, 6,  NULL,
216 	ai_walk, 2,  NULL,
217 	ai_walk, 2,  NULL,
218 	ai_walk, 2,  NULL,
219 	ai_walk, 1,  NULL,
220 	ai_walk, 6,  NULL,
221 	ai_walk, 5,  NULL,
222 	ai_walk, 3,  NULL,
223 	ai_walk, -1, soldier_walk1_random,
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 	ai_walk, 0,  NULL
247 };
248 mmove_t soldier_move_walk1 = {FRAME_walk101, FRAME_walk133, soldier_frames_walk1, NULL};
249 
250 mframe_t soldier_frames_walk2 [] =
251 {
252 	ai_walk, 4,  NULL,
253 	ai_walk, 4,  NULL,
254 	ai_walk, 9,  NULL,
255 	ai_walk, 8,  NULL,
256 	ai_walk, 5,  NULL,
257 	ai_walk, 1,  NULL,
258 	ai_walk, 3,  NULL,
259 	ai_walk, 7,  NULL,
260 	ai_walk, 6,  NULL,
261 	ai_walk, 7,  NULL
262 };
263 mmove_t soldier_move_walk2 = {FRAME_walk209, FRAME_walk218, soldier_frames_walk2, NULL};
264 
soldier_walk(edict_t * self)265 void soldier_walk (edict_t *self)
266 {
267 	if (random() < 0.5)
268 		self->monsterinfo.currentmove = &soldier_move_walk1;
269 	else
270 		self->monsterinfo.currentmove = &soldier_move_walk2;
271 }
272 
273 
274 //
275 // RUN
276 //
277 
278 void soldier_run (edict_t *self);
279 
280 mframe_t soldier_frames_start_run [] =
281 {
282 	ai_run, 7,  NULL,
283 	ai_run, 5,  NULL
284 };
285 mmove_t soldier_move_start_run = {FRAME_run01, FRAME_run02, soldier_frames_start_run, soldier_run};
286 
287 mframe_t soldier_frames_run [] =
288 {
289 	ai_run, 10, NULL,
290 	ai_run, 11, NULL,
291 	ai_run, 11, NULL,
292 	ai_run, 16, NULL,
293 	ai_run, 10, NULL,
294 	ai_run, 15, NULL
295 };
296 mmove_t soldier_move_run = {FRAME_run03, FRAME_run08, soldier_frames_run, NULL};
297 
soldier_run(edict_t * self)298 void soldier_run (edict_t *self)
299 {
300 	if (self->monsterinfo.aiflags & AI_STAND_GROUND)
301 	{
302 		self->monsterinfo.currentmove = &soldier_move_stand1;
303 		return;
304 	}
305 
306 	if (self->monsterinfo.currentmove == &soldier_move_walk1 ||
307 		self->monsterinfo.currentmove == &soldier_move_walk2 ||
308 		self->monsterinfo.currentmove == &soldier_move_start_run)
309 	{
310 		self->monsterinfo.currentmove = &soldier_move_run;
311 	}
312 	else
313 	{
314 		self->monsterinfo.currentmove = &soldier_move_start_run;
315 	}
316 }
317 
318 
319 //
320 // PAIN
321 //
322 
323 mframe_t soldier_frames_pain1 [] =
324 {
325 	ai_move, -3, NULL,
326 	ai_move, 4,  NULL,
327 	ai_move, 1,  NULL,
328 	ai_move, 1,  NULL,
329 	ai_move, 0,  NULL
330 };
331 mmove_t soldier_move_pain1 = {FRAME_pain101, FRAME_pain105, soldier_frames_pain1, soldier_run};
332 
333 mframe_t soldier_frames_pain2 [] =
334 {
335 	ai_move, -13, NULL,
336 	ai_move, -1,  NULL,
337 	ai_move, 2,   NULL,
338 	ai_move, 4,   NULL,
339 	ai_move, 2,   NULL,
340 	ai_move, 3,   NULL,
341 	ai_move, 2,   NULL
342 };
343 mmove_t soldier_move_pain2 = {FRAME_pain201, FRAME_pain207, soldier_frames_pain2, soldier_run};
344 
345 mframe_t soldier_frames_pain3 [] =
346 {
347 	ai_move, -8, NULL,
348 	ai_move, 10, NULL,
349 	ai_move, -4, NULL,
350 	ai_move, -1, NULL,
351 	ai_move, -3, NULL,
352 	ai_move, 0,  NULL,
353 	ai_move, 3,  NULL,
354 	ai_move, 0,  NULL,
355 	ai_move, 0,  NULL,
356 	ai_move, 0,  NULL,
357 	ai_move, 0,  NULL,
358 	ai_move, 1,  NULL,
359 	ai_move, 0,  NULL,
360 	ai_move, 1,  NULL,
361 	ai_move, 2,  NULL,
362 	ai_move, 4,  NULL,
363 	ai_move, 3,  NULL,
364 	ai_move, 2,  NULL
365 };
366 mmove_t soldier_move_pain3 = {FRAME_pain301, FRAME_pain318, soldier_frames_pain3, soldier_run};
367 
368 mframe_t soldier_frames_pain4 [] =
369 {
370 	ai_move, 0,   NULL,
371 	ai_move, 0,   NULL,
372 	ai_move, 0,   NULL,
373 	ai_move, -10, NULL,
374 	ai_move, -6,  NULL,
375 	ai_move, 8,   NULL,
376 	ai_move, 4,   NULL,
377 	ai_move, 1,   NULL,
378 	ai_move, 0,   NULL,
379 	ai_move, 2,   NULL,
380 	ai_move, 5,   NULL,
381 	ai_move, 2,   NULL,
382 	ai_move, -1,  NULL,
383 	ai_move, -1,  NULL,
384 	ai_move, 3,   NULL,
385 	ai_move, 2,   NULL,
386 	ai_move, 0,   NULL
387 };
388 mmove_t soldier_move_pain4 = {FRAME_pain401, FRAME_pain417, soldier_frames_pain4, soldier_run};
389 
390 
soldier_pain(edict_t * self,edict_t * other,float kick,int damage)391 void soldier_pain (edict_t *self, edict_t *other, float kick, int damage)
392 {
393 	float	r;
394 	int		n;
395 
396 	if (self->health < (self->max_health / 2))
397 			self->s.skinnum |= 1;
398 
399 	if (level.time < self->pain_debounce_time)
400 	{
401 		if ((self->velocity[2] > 100) && ( (self->monsterinfo.currentmove == &soldier_move_pain1) || (self->monsterinfo.currentmove == &soldier_move_pain2) || (self->monsterinfo.currentmove == &soldier_move_pain3)))
402 			self->monsterinfo.currentmove = &soldier_move_pain4;
403 		return;
404 	}
405 
406 	self->pain_debounce_time = level.time + 3;
407 
408 	n = self->s.skinnum | 1;
409 	if (n == 1)
410 		gi.sound (self, CHAN_VOICE, sound_pain_light, 1, ATTN_NORM, 0);
411 	else if (n == 3)
412 		gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
413 	else
414 		gi.sound (self, CHAN_VOICE, sound_pain_ss, 1, ATTN_NORM, 0);
415 
416 	if (self->velocity[2] > 100)
417 	{
418 		self->monsterinfo.currentmove = &soldier_move_pain4;
419 		return;
420 	}
421 
422 	if (skill->value == 3)
423 		return;		// no pain anims in nightmare
424 
425 	r = random();
426 
427 	if (r < 0.33)
428 		self->monsterinfo.currentmove = &soldier_move_pain1;
429 	else if (r < 0.66)
430 		self->monsterinfo.currentmove = &soldier_move_pain2;
431 	else
432 		self->monsterinfo.currentmove = &soldier_move_pain3;
433 }
434 
435 
436 //
437 // ATTACK
438 //
439 
440 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};
441 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};
442 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};
443 
soldier_fire(edict_t * self,int flash_number)444 void soldier_fire (edict_t *self, int flash_number)
445 {
446 	vec3_t	start;
447 	vec3_t	forward, right, up;
448 	vec3_t	aim;
449 	vec3_t	dir;
450 	vec3_t	end;
451 	float	r, u;
452 	int		flash_index, distance;
453 
454 	if (self->s.skinnum < 2)
455 		flash_index = blaster_flash[flash_number];
456 	else if (self->s.skinnum < 4)
457 		flash_index = shotgun_flash[flash_number];
458 	else
459 		flash_index = machinegun_flash[flash_number];
460 
461 	AngleVectors (self->s.angles, forward, right, NULL);
462 	G_ProjectSource (self->s.origin, monster_flash_offset[flash_index], forward, right, start);
463 
464 	VectorSubtract(self->s.origin, self->enemy->s.origin, aim);
465 	distance = VectorLength(aim);
466 
467 	if (flash_number == 5 || flash_number == 6)
468 	{
469 		VectorCopy (forward, aim);
470 	}
471 	else
472 	{
473 		VectorCopy (self->enemy->s.origin, end);
474 		end[2] += self->enemy->viewheight;
475 		VectorSubtract (end, start, aim);
476 		vectoangles (aim, dir);
477 		AngleVectors (dir, forward, right, up);
478 
479 		r = crandom()*1000;
480 		u = crandom()*500;
481 		VectorMA (start, 8192, forward, end);
482 		VectorMA (end, r, right, end);
483 		VectorMA (end, u, up, end);
484 
485 		VectorSubtract (end, start, aim);
486 		VectorNormalize (aim);
487 	}
488 
489 	if (self->s.skinnum <= 1)
490 	{
491 		if (distance>BLASTER_DISTANCE || true)
492 		{
493 			monster_fire_blaster (self, start, aim, 75, 600, flash_index, (sv_serversideonly->value)?EF_BLASTER:0);
494 		}
495 		else
496 		{
497 			aim[2]+=.1;
498 			monster_fire_plasma (self, start, aim, 1, 800, EF_BLASTER);
499 		}
500 
501 	}
502 	else if (self->s.skinnum <= 3)
503 	{
504 		monster_fire_shotgun (self, start, aim, 9, 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, flash_index);
505 	}
506 	else
507 	{
508 		if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME))
509 			self->monsterinfo.pausetime = level.time + (3 + rand() % 8) * FRAMETIME;
510 
511 		monster_fire_bullet (self, start, aim, 20, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_index);
512 
513 		if (level.time >= self->monsterinfo.pausetime)
514 			self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
515 		else
516 			self->monsterinfo.aiflags |= AI_HOLD_FRAME;
517 	}
518 }
519 
520 // ATTACK1 (blaster/shotgun)
521 
soldier_fire1(edict_t * self)522 void soldier_fire1 (edict_t *self)
523 {
524 	soldier_fire (self, 0);
525 }
526 
soldier_attack1_refire1(edict_t * self)527 void soldier_attack1_refire1 (edict_t *self)
528 {
529 	if (self->s.skinnum > 1)
530 		return;
531 
532 	if (self->enemy->health <= 0)
533 		return;
534 
535 	if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
536 		self->monsterinfo.nextframe = FRAME_attak102;
537 	else
538 		self->monsterinfo.nextframe = FRAME_attak110;
539 }
540 
soldier_attack1_refire2(edict_t * self)541 void soldier_attack1_refire2 (edict_t *self)
542 {
543 	if (self->s.skinnum < 2)
544 		return;
545 
546 	if (self->enemy->health <= 0)
547 		return;
548 
549 	if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
550 		self->monsterinfo.nextframe = FRAME_attak102;
551 }
552 
553 mframe_t soldier_frames_attack1 [] =
554 {
555 	ai_charge, 0,  NULL,
556 	ai_charge, 0,  NULL,
557 	ai_charge, 0,  soldier_fire1,
558 	ai_charge, 0,  NULL,
559 	ai_charge, 0,  NULL,
560 	ai_charge, 0,  soldier_attack1_refire1,
561 	ai_charge, 0,  NULL,
562 	ai_charge, 0,  soldier_cock,
563 	ai_charge, 0,  soldier_attack1_refire2,
564 	ai_charge, 0,  NULL,
565 	ai_charge, 0,  NULL,
566 	ai_charge, 0,  NULL
567 };
568 mmove_t soldier_move_attack1 = {FRAME_attak101, FRAME_attak112, soldier_frames_attack1, soldier_run};
569 
570 // ATTACK2 (blaster/shotgun)
571 
soldier_fire2(edict_t * self)572 void soldier_fire2 (edict_t *self)
573 {
574 	soldier_fire (self, 1);
575 }
576 
soldier_attack2_refire1(edict_t * self)577 void soldier_attack2_refire1 (edict_t *self)
578 {
579 	if (self->s.skinnum > 1)
580 		return;
581 
582 	if (self->enemy->health <= 0)
583 		return;
584 
585 	if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
586 		self->monsterinfo.nextframe = FRAME_attak204;
587 	else
588 		self->monsterinfo.nextframe = FRAME_attak216;
589 }
590 
soldier_attack2_refire2(edict_t * self)591 void soldier_attack2_refire2 (edict_t *self)
592 {
593 	if (self->s.skinnum < 2)
594 		return;
595 
596 	if (self->enemy->health <= 0)
597 		return;
598 
599 	if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
600 		self->monsterinfo.nextframe = FRAME_attak204;
601 }
602 
603 mframe_t soldier_frames_attack2 [] =
604 {
605 	ai_charge, 0, NULL,
606 	ai_charge, 0, NULL,
607 	ai_charge, 0, NULL,
608 	ai_charge, 0, NULL,
609 	ai_charge, 0, soldier_fire2,
610 	ai_charge, 0, NULL,
611 	ai_charge, 0, NULL,
612 	ai_charge, 0, soldier_attack2_refire1,
613 	ai_charge, 0, NULL,
614 	ai_charge, 0, NULL,
615 	ai_charge, 0, NULL,
616 	ai_charge, 0, NULL,
617 	ai_charge, 0, soldier_cock,
618 	ai_charge, 0, NULL,
619 	ai_charge, 0, soldier_attack2_refire2,
620 	ai_charge, 0, NULL,
621 	ai_charge, 0, NULL,
622 	ai_charge, 0, NULL
623 };
624 mmove_t soldier_move_attack2 = {FRAME_attak201, FRAME_attak218, soldier_frames_attack2, soldier_run};
625 
626 // ATTACK3 (duck and shoot)
627 
soldier_duck_down(edict_t * self)628 void soldier_duck_down (edict_t *self)
629 {
630 	if (self->monsterinfo.aiflags & AI_DUCKED)
631 		return;
632 	self->monsterinfo.aiflags |= AI_DUCKED;
633 	self->maxs[2] -= 32;
634 	self->takedamage = DAMAGE_YES;
635 	self->monsterinfo.pausetime = level.time + 1;
636 	gi.linkentity (self);
637 }
638 
soldier_duck_up(edict_t * self)639 void soldier_duck_up (edict_t *self)
640 {
641 	self->monsterinfo.aiflags &= ~AI_DUCKED;
642 	self->maxs[2] += 32;
643 	self->takedamage = DAMAGE_AIM;
644 	gi.linkentity (self);
645 }
646 
soldier_fire3(edict_t * self)647 void soldier_fire3 (edict_t *self)
648 {
649 	soldier_duck_down (self);
650 	soldier_fire (self, 2);
651 }
652 
soldier_attack3_refire(edict_t * self)653 void soldier_attack3_refire (edict_t *self)
654 {
655 	if ((level.time + 0.4) < self->monsterinfo.pausetime)
656 		self->monsterinfo.nextframe = FRAME_attak303;
657 }
658 
659 mframe_t soldier_frames_attack3 [] =
660 {
661 	ai_charge, 0, NULL,
662 	ai_charge, 0, NULL,
663 	ai_charge, 0, soldier_fire3,
664 	ai_charge, 0, NULL,
665 	ai_charge, 0, NULL,
666 	ai_charge, 0, soldier_attack3_refire,
667 	ai_charge, 0, soldier_duck_up,
668 	ai_charge, 0, NULL,
669 	ai_charge, 0, NULL
670 };
671 mmove_t soldier_move_attack3 = {FRAME_attak301, FRAME_attak309, soldier_frames_attack3, soldier_run};
672 
673 // ATTACK4 (machinegun)
674 
soldier_fire4(edict_t * self)675 void soldier_fire4 (edict_t *self)
676 {
677 	soldier_fire (self, 3);
678 //
679 //	if (self->enemy->health <= 0)
680 //		return;
681 //
682 //	if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
683 //		self->monsterinfo.nextframe = FRAME_attak402;
684 }
685 
686 mframe_t soldier_frames_attack4 [] =
687 {
688 	ai_charge, 0, NULL,
689 	ai_charge, 0, NULL,
690 	ai_charge, 0, soldier_fire4,
691 	ai_charge, 0, NULL,
692 	ai_charge, 0, NULL,
693 	ai_charge, 0, NULL
694 };
695 mmove_t soldier_move_attack4 = {FRAME_attak401, FRAME_attak406, soldier_frames_attack4, soldier_run};
696 
697 #if 0
698 // ATTACK5 (prone)
699 
700 void soldier_fire5 (edict_t *self)
701 {
702 	soldier_fire (self, 4);
703 }
704 
705 void soldier_attack5_refire (edict_t *self)
706 {
707 	if (self->enemy->health <= 0)
708 		return;
709 
710 	if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
711 		self->monsterinfo.nextframe = FRAME_attak505;
712 }
713 
714 mframe_t soldier_frames_attack5 [] =
715 {
716 	ai_charge, 8, NULL,
717 	ai_charge, 8, NULL,
718 	ai_charge, 0, NULL,
719 	ai_charge, 0, NULL,
720 	ai_charge, 0, soldier_fire5,
721 	ai_charge, 0, NULL,
722 	ai_charge, 0, NULL,
723 	ai_charge, 0, soldier_attack5_refire
724 };
725 mmove_t soldier_move_attack5 = {FRAME_attak501, FRAME_attak508, soldier_frames_attack5, soldier_run};
726 #endif
727 
728 // ATTACK6 (run & shoot)
729 
soldier_fire8(edict_t * self)730 void soldier_fire8 (edict_t *self)
731 {
732 	soldier_fire (self, 7);
733 }
734 
soldier_attack6_refire(edict_t * self)735 void soldier_attack6_refire (edict_t *self)
736 {
737 	if (self->enemy->health <= 0)
738 		return;
739 
740 	if (range(self, self->enemy) < RANGE_MID)
741 		return;
742 
743 	if (skill->value == 3)
744 		self->monsterinfo.nextframe = FRAME_runs03;
745 }
746 
747 mframe_t soldier_frames_attack6 [] =
748 {
749 	ai_charge, 10, NULL,
750 	ai_charge,  4, NULL,
751 	ai_charge, 12, NULL,
752 	ai_charge, 11, soldier_fire8,
753 	ai_charge, 13, NULL,
754 	ai_charge, 18, NULL,
755 	ai_charge, 15, NULL,
756 	ai_charge, 14, NULL,
757 	ai_charge, 11, NULL,
758 	ai_charge,  8, NULL,
759 	ai_charge, 11, NULL,
760 	ai_charge, 12, NULL,
761 	ai_charge, 12, NULL,
762 	ai_charge, 17, soldier_attack6_refire
763 };
764 mmove_t soldier_move_attack6 = {FRAME_runs01, FRAME_runs14, soldier_frames_attack6, soldier_run};
765 
soldier_attack(edict_t * self)766 void soldier_attack(edict_t *self)
767 {
768 	if (self->s.skinnum < 4)
769 	{
770 		if (random() < 0.5)
771 			self->monsterinfo.currentmove = &soldier_move_attack1;
772 		else
773 			self->monsterinfo.currentmove = &soldier_move_attack2;
774 	}
775 	else
776 	{
777 		self->monsterinfo.currentmove = &soldier_move_attack4;
778 	}
779 }
780 
781 
782 //
783 // SIGHT
784 //
785 
soldier_sight(edict_t * self,edict_t * other)786 void soldier_sight(edict_t *self, edict_t *other)
787 {
788 	if (random() < 0.5)
789 		gi.sound (self, CHAN_VOICE, sound_sight1, 1, ATTN_NORM, 0);
790 	else
791 		gi.sound (self, CHAN_VOICE, sound_sight2, 1, ATTN_NORM, 0);
792 
793 	if ((skill->value > 0) && (range(self, self->enemy) >= RANGE_MID))
794 	{
795 		if (random() > 0.5)
796 			self->monsterinfo.currentmove = &soldier_move_attack6;
797 	}
798 }
799 
800 //
801 // DUCK
802 //
803 
soldier_duck_hold(edict_t * self)804 void soldier_duck_hold (edict_t *self)
805 {
806 	if (level.time >= self->monsterinfo.pausetime)
807 		self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
808 	else
809 		self->monsterinfo.aiflags |= AI_HOLD_FRAME;
810 }
811 
812 mframe_t soldier_frames_duck [] =
813 {
814 	ai_move, 5, soldier_duck_down,
815 	ai_move, -1, soldier_duck_hold,
816 	ai_move, 1,  NULL,
817 	ai_move, 0,  soldier_duck_up,
818 	ai_move, 5,  NULL
819 };
820 mmove_t soldier_move_duck = {FRAME_duck01, FRAME_duck05, soldier_frames_duck, soldier_run};
821 
soldier_dodge(edict_t * self,edict_t * attacker,float eta)822 void soldier_dodge (edict_t *self, edict_t *attacker, float eta)
823 {
824 	float	r;
825 
826 	r = random();
827 	if (r > 0.25)
828 		return;
829 
830 	if (!self->enemy)
831 		self->enemy = attacker;
832 
833 	if (skill->value == 0)
834 	{
835 		self->monsterinfo.currentmove = &soldier_move_duck;
836 		return;
837 	}
838 
839 	self->monsterinfo.pausetime = level.time + eta + 0.3;
840 	r = random();
841 
842 	if (skill->value == 1)
843 	{
844 		if (r > 0.33)
845 			self->monsterinfo.currentmove = &soldier_move_duck;
846 		else
847 			self->monsterinfo.currentmove = &soldier_move_attack3;
848 		return;
849 	}
850 
851 	if (skill->value >= 2)
852 	{
853 		if (r > 0.66)
854 			self->monsterinfo.currentmove = &soldier_move_duck;
855 		else
856 			self->monsterinfo.currentmove = &soldier_move_attack3;
857 		return;
858 	}
859 
860 	self->monsterinfo.currentmove = &soldier_move_attack3;
861 }
862 
863 
864 //
865 // DEATH
866 //
867 
soldier_fire6(edict_t * self)868 void soldier_fire6 (edict_t *self)
869 {
870 	soldier_fire (self, 5);
871 }
872 
soldier_fire7(edict_t * self)873 void soldier_fire7 (edict_t *self)
874 {
875 	soldier_fire (self, 6);
876 }
877 
soldier_dead(edict_t * self)878 void soldier_dead (edict_t *self)
879 {
880 	VectorSet (self->mins, -16, -16, -24);
881 	VectorSet (self->maxs, 16, 16, -8);
882 	self->movetype = MOVETYPE_TOSS;
883 	self->svflags |= SVF_DEADMONSTER;
884 	self->nextthink = 0;
885 
886 	self->think=FadeDieSink;
887 	self->nextthink=level.time+FADETIME+random()*5;
888 	self->floater=1;
889 
890 	gi.linkentity (self);
891 }
892 
893 mframe_t soldier_frames_death1 [] =
894 {
895 	ai_move, 0,   NULL,
896 	ai_move, -10, NULL,
897 	ai_move, -10, NULL,
898 	ai_move, -10, NULL,
899 	ai_move, -5,  NULL,
900 	ai_move, 0,   NULL,
901 	ai_move, 0,   NULL,
902 	ai_move, 0,   NULL,
903 	ai_move, 0,   NULL,
904 	ai_move, 0,   NULL,
905 
906 	ai_move, 0,   NULL,
907 	ai_move, 0,   NULL,
908 	ai_move, 0,   NULL,
909 	ai_move, 0,   NULL,
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 	ai_move, 0,   NULL,
918 	ai_move, 0,   soldier_fire6,
919 	ai_move, 0,   NULL,
920 	ai_move, 0,   NULL,
921 	ai_move, 0,   soldier_fire7,
922 	ai_move, 0,   NULL,
923 	ai_move, 0,   NULL,
924 	ai_move, 0,   NULL,
925 	ai_move, 0,   NULL,
926 	ai_move, 0,   NULL,
927 
928 	ai_move, 0,   NULL,
929 	ai_move, 0,   NULL,
930 	ai_move, 0,   NULL,
931 	ai_move, 0,   NULL,
932 	ai_move, 0,   NULL,
933 	ai_move, 0,   NULL
934 };
935 mmove_t soldier_move_death1 = {FRAME_death101, FRAME_death136, soldier_frames_death1, soldier_dead};
936 
937 mframe_t soldier_frames_death2 [] =
938 {
939 	ai_move, -5,  NULL,
940 	ai_move, -5,  NULL,
941 	ai_move, -5,  NULL,
942 	ai_move, 0,   NULL,
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 
950 	ai_move, 0,   NULL,
951 	ai_move, 0,   NULL,
952 	ai_move, 0,   NULL,
953 	ai_move, 0,   NULL,
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 	ai_move, 0,   NULL,
960 
961 	ai_move, 0,   NULL,
962 	ai_move, 0,   NULL,
963 	ai_move, 0,   NULL,
964 	ai_move, 0,   NULL,
965 	ai_move, 0,   NULL,
966 	ai_move, 0,   NULL,
967 	ai_move, 0,   NULL,
968 	ai_move, 0,   NULL,
969 	ai_move, 0,   NULL,
970 	ai_move, 0,   NULL,
971 
972 	ai_move, 0,   NULL,
973 	ai_move, 0,   NULL,
974 	ai_move, 0,   NULL,
975 	ai_move, 0,   NULL,
976 	ai_move, 0,   NULL
977 };
978 mmove_t soldier_move_death2 = {FRAME_death201, FRAME_death235, soldier_frames_death2, soldier_dead};
979 
980 mframe_t soldier_frames_death3 [] =
981 {
982 	ai_move, -5,  NULL,
983 	ai_move, -5,  NULL,
984 	ai_move, -5,  NULL,
985 	ai_move, 0,   NULL,
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 
993 	ai_move, 0,   NULL,
994 	ai_move, 0,   NULL,
995 	ai_move, 0,   NULL,
996 	ai_move, 0,   NULL,
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 
1004 	ai_move, 0,   NULL,
1005 	ai_move, 0,   NULL,
1006 	ai_move, 0,   NULL,
1007 	ai_move, 0,   NULL,
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 	ai_move, 0,   NULL,
1014 
1015 	ai_move, 0,   NULL,
1016 	ai_move, 0,   NULL,
1017 	ai_move, 0,   NULL,
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 
1026 	ai_move, 0,   NULL,
1027 	ai_move, 0,   NULL,
1028 	ai_move, 0,   NULL,
1029 	ai_move, 0,   NULL,
1030 	ai_move, 0,   NULL,
1031 };
1032 mmove_t soldier_move_death3 = {FRAME_death301, FRAME_death345, soldier_frames_death3, soldier_dead};
1033 
1034 mframe_t soldier_frames_death4 [] =
1035 {
1036 	ai_move, 0,   NULL,
1037 	ai_move, 0,   NULL,
1038 	ai_move, 0,   NULL,
1039 	ai_move, 0,   NULL,
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 
1047 	ai_move, 0,   NULL,
1048 	ai_move, 0,   NULL,
1049 	ai_move, 0,   NULL,
1050 	ai_move, 0,   NULL,
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 
1058 	ai_move, 0,   NULL,
1059 	ai_move, 0,   NULL,
1060 	ai_move, 0,   NULL,
1061 	ai_move, 0,   NULL,
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 
1069 	ai_move, 0,   NULL,
1070 	ai_move, 0,   NULL,
1071 	ai_move, 0,   NULL,
1072 	ai_move, 0,   NULL,
1073 	ai_move, 0,   NULL,
1074 	ai_move, 0,   NULL,
1075 	ai_move, 0,   NULL,
1076 	ai_move, 0,   NULL,
1077 	ai_move, 0,   NULL,
1078 	ai_move, 0,   NULL,
1079 
1080 	ai_move, 0,   NULL,
1081 	ai_move, 0,   NULL,
1082 	ai_move, 0,   NULL,
1083 	ai_move, 0,   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 
1091 	ai_move, 0,   NULL,
1092 	ai_move, 0,   NULL,
1093 	ai_move, 0,   NULL
1094 };
1095 mmove_t soldier_move_death4 = {FRAME_death401, FRAME_death453, soldier_frames_death4, soldier_dead};
1096 
1097 mframe_t soldier_frames_death5 [] =
1098 {
1099 	ai_move, -5,  NULL,
1100 	ai_move, -5,  NULL,
1101 	ai_move, -5,  NULL,
1102 	ai_move, 0,   NULL,
1103 	ai_move, 0,   NULL,
1104 	ai_move, 0,   NULL,
1105 	ai_move, 0,   NULL,
1106 	ai_move, 0,   NULL,
1107 	ai_move, 0,   NULL,
1108 	ai_move, 0,   NULL,
1109 
1110 	ai_move, 0,   NULL,
1111 	ai_move, 0,   NULL,
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 
1121 	ai_move, 0,   NULL,
1122 	ai_move, 0,   NULL,
1123 	ai_move, 0,   NULL,
1124 	ai_move, 0,   NULL
1125 };
1126 mmove_t soldier_move_death5 = {FRAME_death501, FRAME_death524, soldier_frames_death5, soldier_dead};
1127 
1128 mframe_t soldier_frames_death6 [] =
1129 {
1130 	ai_move, 0,   NULL,
1131 	ai_move, 0,   NULL,
1132 	ai_move, 0,   NULL,
1133 	ai_move, 0,   NULL,
1134 	ai_move, 0,   NULL,
1135 	ai_move, 0,   NULL,
1136 	ai_move, 0,   NULL,
1137 	ai_move, 0,   NULL,
1138 	ai_move, 0,   NULL,
1139 	ai_move, 0,   NULL
1140 };
1141 mmove_t soldier_move_death6 = {FRAME_death601, FRAME_death610, soldier_frames_death6, soldier_dead};
1142 
soldier_die(edict_t * self,edict_t * inflictor,edict_t * attacker,int damage,vec3_t point)1143 void soldier_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
1144 {
1145 	int		n;
1146 
1147 	switch (meansOfDeath & ~MOD_FRIENDLY_FIRE)
1148 	{
1149 		case MOD_ROCKET:
1150 		case MOD_BFG_LASER:
1151 		case MOD_BFG_BLAST:
1152 		case MOD_HANDGRENADE:
1153 		case MOD_HELD_GRENADE:
1154 		case MOD_BOMB:
1155 		case MOD_C4:
1156 		case MOD_GAS_BOOM:
1157 			self->health = self->gib_health;
1158 			break;
1159 		case MOD_FLAME:
1160 		case MOD_DISCHARGE:
1161 		case MOD_LAVA:
1162 			self->health -= damage * 2;
1163 			break;
1164 		case MOD_HG_SPLASH:
1165 		case MOD_R_SPLASH:
1166 		case MOD_G_SPLASH:
1167 			self->health -= damage * 5;
1168 			break;
1169 		case MOD_R_BFG_SPLASH:
1170 			self->health -= damage * 10;
1171 			break;
1172 	}
1173 
1174 // check for gib
1175 	if (self->health <= self->gib_health)
1176 	{
1177 		gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
1178 		for (n= 0; n < 3; n++)
1179 			ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
1180 		ThrowGib (self, "models/objects/gibs/chest/tris.md2", damage, GIB_ORGANIC);
1181 		ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
1182 		self->deadflag = DEAD_DEAD;
1183 		return;
1184 	}
1185 
1186 	if (self->deadflag == DEAD_DEAD)
1187 		return;
1188 
1189 // regular death
1190 	self->deadflag = DEAD_DEAD;
1191 	self->takedamage = DAMAGE_YES;
1192 	self->s.skinnum |= 1;
1193 
1194 	if (self->s.skinnum == 1)
1195 		gi.sound (self, CHAN_VOICE, sound_death_light, 1, ATTN_NORM, 0);
1196 	else if (self->s.skinnum == 3)
1197 		gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0);
1198 	else // (self->s.skinnum == 5)
1199 		gi.sound (self, CHAN_VOICE, sound_death_ss, 1, ATTN_NORM, 0);
1200 
1201 	if (headShot)	//(fabs((self->s.origin[2] + self->viewheight) - point[2]) <= 4)
1202 	{
1203 		// head shot
1204 		self->monsterinfo.currentmove = &soldier_move_death3;
1205 		return;
1206 	}
1207 
1208 	n = rand() % 5;
1209 	if (n == 0)
1210 		self->monsterinfo.currentmove = &soldier_move_death1;
1211 	else if (n == 1)
1212 		self->monsterinfo.currentmove = &soldier_move_death2;
1213 	else if (n == 2)
1214 		self->monsterinfo.currentmove = &soldier_move_death4;
1215 	else if (n == 3)
1216 		self->monsterinfo.currentmove = &soldier_move_death5;
1217 	else
1218 		self->monsterinfo.currentmove = &soldier_move_death6;
1219 
1220 }
1221 
1222 
1223 //
1224 // SPAWN
1225 //
1226 
SP_monster_soldier_x(edict_t * self)1227 void SP_monster_soldier_x (edict_t *self)
1228 {
1229 
1230 	self->s.modelindex = gi.modelindex ("models/monsters/soldier/tris.md2");
1231 	self->monsterinfo.scale = MODEL_SCALE;
1232 	VectorSet (self->mins, -16, -16, -24);
1233 	VectorSet (self->maxs, 16, 16, 32);
1234 	self->movetype = MOVETYPE_STEP;
1235 	self->solid = SOLID_BBOX;
1236 
1237 	sound_idle =	gi.soundindex ("soldier/solidle1.wav");
1238 	sound_sight1 =	gi.soundindex ("soldier/solsght1.wav");
1239 	sound_sight2 =	gi.soundindex ("soldier/solsrch1.wav");
1240 	sound_cock =	gi.soundindex ("infantry/infatck3.wav");
1241 
1242 	self->mass = 100;
1243 
1244 	self->pain = soldier_pain;
1245 	self->die = soldier_die;
1246 
1247 	self->monsterinfo.stand = soldier_stand;
1248 	self->monsterinfo.walk = soldier_walk;
1249 	self->monsterinfo.run = soldier_run;
1250 	self->monsterinfo.dodge = soldier_dodge;
1251 	self->monsterinfo.attack = soldier_attack;
1252 	self->monsterinfo.melee = NULL;
1253 	self->monsterinfo.sight = soldier_sight;
1254 
1255 	gi.linkentity (self);
1256 
1257 	self->monsterinfo.stand (self);
1258 
1259 	walkmonster_start (self);
1260 }
1261 
1262 
1263 /*QUAKED monster_soldier_light (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
1264 */
SP_monster_soldier_light(edict_t * self)1265 void SP_monster_soldier_light (edict_t *self)
1266 {
1267 	if (deathmatch->value)
1268 	{
1269 		G_FreeEdict (self);
1270 		return;
1271 	}
1272 
1273 	SP_monster_soldier_x (self);
1274 
1275 	sound_pain_light = gi.soundindex ("soldier/solpain2.wav");
1276 	sound_death_light =	gi.soundindex ("soldier/soldeth2.wav");
1277 	gi.modelindex ("models/objects/laser/tris.md2");
1278 	gi.soundindex ("misc/lasfly.wav");
1279 	gi.soundindex ("soldier/solatck2.wav");
1280 
1281 	self->s.skinnum = 0;
1282 	self->health = 90;
1283 	self->gib_health = -500;
1284 
1285 	self->max_health = self->health;
1286 }
1287 
1288 /*QUAKED monster_soldier (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
1289 */
soldier_enemycheck(edict_t * ent,edict_t * other)1290 qboolean soldier_enemycheck (edict_t *ent, edict_t *other)
1291 {
1292 
1293 	if (!Q_stricmp (other->classname, "monster_soldier_light"))
1294 		return true;
1295 
1296 	return false;
1297 }
SP_monster_soldier(edict_t * self)1298 void SP_monster_soldier (edict_t *self)
1299 {
1300 	if (deathmatch->value)
1301 	{
1302 		G_FreeEdict (self);
1303 		return;
1304 	}
1305 
1306 	SP_monster_soldier_x (self);
1307 
1308 
1309 	self->monsterinfo.enemycheck = soldier_enemycheck;
1310 
1311 	sound_pain = gi.soundindex ("soldier/solpain1.wav");
1312 	sound_death = gi.soundindex ("soldier/soldeth1.wav");
1313 	gi.soundindex ("soldier/solatck1.wav");
1314 
1315 	self->s.skinnum = 2;
1316 	self->health = 90;
1317 	self->gib_health = -500;
1318 
1319 	self->max_health = self->health;
1320 }
1321 
1322 /*QUAKED monster_soldier_ss (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
1323 */
SP_monster_soldier_ss(edict_t * self)1324 void SP_monster_soldier_ss (edict_t *self)
1325 {
1326 	if (deathmatch->value)
1327 	{
1328 		G_FreeEdict (self);
1329 		return;
1330 	}
1331 
1332 	SP_monster_soldier_x (self);
1333 
1334 	sound_pain_ss = gi.soundindex ("soldier/solpain3.wav");
1335 	sound_death_ss = gi.soundindex ("soldier/soldeth3.wav");
1336 	gi.soundindex ("soldier/solatck3.wav");
1337 
1338 	self->s.skinnum = 4;
1339 	self->health = 90;
1340 	self->gib_health = -500;
1341 
1342 	self->max_health = self->health;
1343 }
1344