|
|
1.1 root 1: /*
2: ==============================================================================
3:
4: MEDIC
5:
6: ==============================================================================
7: */
8:
9: #include "g_local.h"
10: #include "m_medic.h"
11:
12: qboolean visible (edict_t *self, edict_t *other);
13:
14:
15: static int sound_idle1;
16: static int sound_pain1;
17: static int sound_pain2;
18: static int sound_die;
19: static int sound_sight;
20: static int sound_search;
21: static int sound_hook_launch;
22: static int sound_hook_hit;
23: static int sound_hook_heal;
24: static int sound_hook_retract;
25:
26:
27: edict_t *medic_FindDeadMonster (edict_t *self)
28: {
29: edict_t *ent = NULL;
30: edict_t *best = NULL;
31:
32: while ((ent = findradius(ent, self->s.origin, 1024)) != NULL)
33: {
34: if (ent == self)
35: continue;
36: if (!(ent->svflags & SVF_MONSTER))
37: continue;
38: if (ent->monsterinfo.aiflags & AI_GOOD_GUY)
39: continue;
40: if (ent->owner)
41: continue;
42: if (ent->health > 0)
43: continue;
44: if (ent->nextthink)
45: continue;
46: if (!visible(self, ent))
47: continue;
48: if (!best)
49: {
50: best = ent;
51: continue;
52: }
53: if (ent->max_health <= best->max_health)
54: continue;
55: best = ent;
56: }
57:
58: return best;
59: }
60:
61: void medic_idle (edict_t *self)
62: {
63: edict_t *ent;
64:
65: gi.sound (self, CHAN_VOICE, sound_idle1, 1, ATTN_IDLE, 0);
66:
67: ent = medic_FindDeadMonster(self);
68: if (ent)
69: {
70: self->enemy = ent;
71: self->enemy->owner = self;
72: self->monsterinfo.aiflags |= AI_MEDIC;
73: FoundTarget (self);
74: }
75: }
76:
77: void medic_search (edict_t *self)
78: {
79: edict_t *ent;
80:
81: gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_IDLE, 0);
82:
83: if (!self->oldenemy)
84: {
85: ent = medic_FindDeadMonster(self);
86: if (ent)
87: {
88: self->oldenemy = self->enemy;
89: self->enemy = ent;
90: self->enemy->owner = self;
91: self->monsterinfo.aiflags |= AI_MEDIC;
92: FoundTarget (self);
93: }
94: }
95: }
96:
97: void medic_sight (edict_t *self, edict_t *other)
98: {
99: gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
100: }
101:
102:
103: mframe_t medic_frames_stand [] =
104: {
105: ai_stand, 0, medic_idle,
106: ai_stand, 0, NULL,
107: ai_stand, 0, NULL,
108: ai_stand, 0, NULL,
109: ai_stand, 0, NULL,
110: ai_stand, 0, NULL,
111: ai_stand, 0, NULL,
112: ai_stand, 0, NULL,
113: ai_stand, 0, NULL,
114: ai_stand, 0, NULL,
115: ai_stand, 0, NULL,
116: ai_stand, 0, NULL,
117: ai_stand, 0, NULL,
118: ai_stand, 0, NULL,
119: ai_stand, 0, NULL,
120: ai_stand, 0, NULL,
121: ai_stand, 0, NULL,
122: ai_stand, 0, NULL,
123: ai_stand, 0, NULL,
124: ai_stand, 0, NULL,
125: 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: ai_stand, 0, NULL,
131: ai_stand, 0, NULL,
132: ai_stand, 0, NULL,
133: ai_stand, 0, NULL,
134: ai_stand, 0, NULL,
135: ai_stand, 0, NULL,
136: ai_stand, 0, NULL,
137: ai_stand, 0, NULL,
138: ai_stand, 0, NULL,
139: ai_stand, 0, NULL,
140: ai_stand, 0, NULL,
141: ai_stand, 0, NULL,
142: ai_stand, 0, NULL,
143: ai_stand, 0, NULL,
144: ai_stand, 0, NULL,
145: ai_stand, 0, NULL,
146: ai_stand, 0, NULL,
147: ai_stand, 0, NULL,
148: ai_stand, 0, NULL,
149: ai_stand, 0, NULL,
150: ai_stand, 0, NULL,
151: ai_stand, 0, NULL,
152: ai_stand, 0, NULL,
153: ai_stand, 0, NULL,
154: ai_stand, 0, NULL,
155: ai_stand, 0, NULL,
156: ai_stand, 0, NULL,
157: ai_stand, 0, NULL,
158: ai_stand, 0, NULL,
159: ai_stand, 0, NULL,
160: ai_stand, 0, NULL,
161: ai_stand, 0, NULL,
162: ai_stand, 0, NULL,
163: ai_stand, 0, NULL,
164: ai_stand, 0, NULL,
165: ai_stand, 0, NULL,
166: ai_stand, 0, NULL,
167: ai_stand, 0, NULL,
168: ai_stand, 0, NULL,
169: ai_stand, 0, NULL,
170: ai_stand, 0, NULL,
171: ai_stand, 0, NULL,
172: ai_stand, 0, NULL,
173: ai_stand, 0, NULL,
174: ai_stand, 0, NULL,
175: ai_stand, 0, NULL,
176: ai_stand, 0, NULL,
177: ai_stand, 0, NULL,
178: ai_stand, 0, NULL,
179: ai_stand, 0, NULL,
180: ai_stand, 0, NULL,
181: ai_stand, 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: ai_stand, 0, NULL,
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:
196: };
197: mmove_t medic_move_stand = {FRAME_wait1, FRAME_wait90, medic_frames_stand, NULL};
198:
199: void medic_stand (edict_t *self)
200: {
201: self->monsterinfo.currentmove = &medic_move_stand;
202: }
203:
204:
205: mframe_t medic_frames_walk [] =
206: {
207: ai_walk, 6.2, NULL,
208: ai_walk, 18.1, NULL,
209: ai_walk, 1, NULL,
210: ai_walk, 9, NULL,
211: ai_walk, 10, NULL,
212: ai_walk, 9, NULL,
213: ai_walk, 11, NULL,
214: ai_walk, 11.6, NULL,
215: ai_walk, 2, NULL,
216: ai_walk, 9.9, NULL,
217: ai_walk, 14, NULL,
218: ai_walk, 9.3, NULL
219: };
220: mmove_t medic_move_walk = {FRAME_walk1, FRAME_walk12, medic_frames_walk, NULL};
221:
222: void medic_walk (edict_t *self)
223: {
224: self->monsterinfo.currentmove = &medic_move_walk;
225: }
226:
227:
228: mframe_t medic_frames_run [] =
229: {
230: ai_run, 18, NULL,
231: ai_run, 22.5, NULL,
232: ai_run, 25.4, NULL,
233: ai_run, 23.4, NULL,
234: ai_run, 24, NULL,
235: ai_run, 35.6, NULL
236:
237: };
238: mmove_t medic_move_run = {FRAME_run1, FRAME_run6, medic_frames_run, NULL};
239:
240: void medic_run (edict_t *self)
241: {
242: if (!(self->monsterinfo.aiflags & AI_MEDIC))
243: {
244: edict_t *ent;
245:
246: ent = medic_FindDeadMonster(self);
247: if (ent)
248: {
249: self->oldenemy = self->enemy;
250: self->enemy = ent;
251: self->enemy->owner = self;
252: self->monsterinfo.aiflags |= AI_MEDIC;
253: FoundTarget (self);
254: return;
255: }
256: }
257:
258: if (self->monsterinfo.aiflags & AI_STAND_GROUND)
259: self->monsterinfo.currentmove = &medic_move_stand;
260: else
261: self->monsterinfo.currentmove = &medic_move_run;
262: }
263:
264:
265: mframe_t medic_frames_pain1 [] =
266: {
267: ai_move, 0, NULL,
268: ai_move, 0, NULL,
269: ai_move, 0, NULL,
270: ai_move, 0, NULL,
271: ai_move, 0, NULL,
272: ai_move, 0, NULL,
273: ai_move, 0, NULL,
274: ai_move, 0, NULL
275: };
276: mmove_t medic_move_pain1 = {FRAME_paina1, FRAME_paina8, medic_frames_pain1, medic_run};
277:
278: mframe_t medic_frames_pain2 [] =
279: {
280: ai_move, 0, NULL,
281: ai_move, 0, NULL,
282: ai_move, 0, NULL,
283: ai_move, 0, NULL,
284: ai_move, 0, NULL,
285: ai_move, 0, NULL,
286: ai_move, 0, NULL,
287: ai_move, 0, NULL,
288: ai_move, 0, NULL,
289: ai_move, 0, NULL,
290: ai_move, 0, NULL,
291: ai_move, 0, NULL,
292: ai_move, 0, NULL,
293: ai_move, 0, NULL,
294: ai_move, 0, NULL
295: };
296: mmove_t medic_move_pain2 = {FRAME_painb1, FRAME_painb15, medic_frames_pain2, medic_run};
297:
298: void medic_pain (edict_t *self, edict_t *other, float kick, int damage)
299: {
300: if (self->health < (self->max_health / 2))
301: self->s.skinnum = 1;
302:
303: if (level.time < self->pain_debounce_time)
304: return;
305:
306: self->pain_debounce_time = level.time + 3;
307:
308: if (skill->value == 3)
309: return; // no pain anims in nightmare
310:
311: if (random() < 0.5)
312: {
313: self->monsterinfo.currentmove = &medic_move_pain1;
314: gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
315: }
316: else
317: {
318: self->monsterinfo.currentmove = &medic_move_pain2;
319: gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
320: }
321: }
322:
323: void medic_fire_blaster (edict_t *self)
324: {
325: vec3_t start;
326: vec3_t forward, right;
327: vec3_t end;
328: vec3_t dir;
329: int effect;
330:
331: if ((self->s.frame == FRAME_attack9) || (self->s.frame == FRAME_attack12))
332: effect = EF_BLASTER;
333: else if ((self->s.frame == FRAME_attack19) || (self->s.frame == FRAME_attack22) || (self->s.frame == FRAME_attack25) || (self->s.frame == FRAME_attack28))
334: effect = EF_HYPERBLASTER;
335: else
336: effect = 0;
337:
338: AngleVectors (self->s.angles, forward, right, NULL);
339: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_MEDIC_BLASTER_1], forward, right, start);
340:
341: VectorCopy (self->enemy->s.origin, end);
342: end[2] += self->enemy->viewheight;
343: VectorSubtract (end, start, dir);
344:
345: monster_fire_blaster (self, start, dir, 2, 1000, MZ2_MEDIC_BLASTER_1, effect);
346: }
347:
348:
349: void medic_dead (edict_t *self)
350: {
351: VectorSet (self->mins, -16, -16, -24);
352: VectorSet (self->maxs, 16, 16, -8);
353: self->movetype = MOVETYPE_TOSS;
354: self->svflags |= SVF_DEADMONSTER;
355: self->nextthink = 0;
356: gi.linkentity (self);
357: }
358:
359: mframe_t medic_frames_death [] =
360: {
361: ai_move, 0, NULL,
362: ai_move, 0, NULL,
363: ai_move, 0, NULL,
364: ai_move, 0, NULL,
365: ai_move, 0, NULL,
366: ai_move, 0, NULL,
367: ai_move, 0, NULL,
368: ai_move, 0, NULL,
369: ai_move, 0, NULL,
370: ai_move, 0, NULL,
371: ai_move, 0, NULL,
372: ai_move, 0, NULL,
373: ai_move, 0, NULL,
374: ai_move, 0, NULL,
375: ai_move, 0, NULL,
376: ai_move, 0, NULL,
377: ai_move, 0, NULL,
378: ai_move, 0, NULL,
379: ai_move, 0, NULL,
380: ai_move, 0, NULL,
381: ai_move, 0, NULL,
382: ai_move, 0, NULL,
383: ai_move, 0, NULL,
384: ai_move, 0, NULL,
385: ai_move, 0, NULL,
386: ai_move, 0, NULL,
387: ai_move, 0, NULL,
388: ai_move, 0, NULL,
389: ai_move, 0, NULL,
390: ai_move, 0, NULL
391: };
392: mmove_t medic_move_death = {FRAME_death1, FRAME_death30, medic_frames_death, medic_dead};
393:
394: void medic_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
395: {
396: int n;
397:
398: // if we had a pending patient, free him up for another medic
399: if ((self->enemy) && (self->enemy->owner == self))
400: self->enemy->owner = NULL;
401:
402: // check for gib
403: if (self->health <= self->gib_health)
404: {
405: gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
406: for (n= 0; n < 2; n++)
407: ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
408: for (n= 0; n < 4; n++)
409: ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
410: ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
411: self->deadflag = DEAD_DEAD;
412: return;
413: }
414:
415: if (self->deadflag == DEAD_DEAD)
416: return;
417:
418: // regular death
419: gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0);
420: self->deadflag = DEAD_DEAD;
421: self->takedamage = DAMAGE_YES;
422:
423: self->monsterinfo.currentmove = &medic_move_death;
424: }
425:
426:
427: void medic_duck_down (edict_t *self)
428: {
429: if (self->monsterinfo.aiflags & AI_DUCKED)
430: return;
431: self->monsterinfo.aiflags |= AI_DUCKED;
432: self->maxs[2] -= 32;
433: self->takedamage = DAMAGE_YES;
434: self->monsterinfo.pausetime = level.time + 1;
435: gi.linkentity (self);
436: }
437:
438: void medic_duck_hold (edict_t *self)
439: {
440: if (level.time >= self->monsterinfo.pausetime)
441: self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
442: else
443: self->monsterinfo.aiflags |= AI_HOLD_FRAME;
444: }
445:
446: void medic_duck_up (edict_t *self)
447: {
448: self->monsterinfo.aiflags &= ~AI_DUCKED;
449: self->maxs[2] += 32;
450: self->takedamage = DAMAGE_AIM;
451: gi.linkentity (self);
452: }
453:
454: mframe_t medic_frames_duck [] =
455: {
456: ai_move, -1, NULL,
457: ai_move, -1, NULL,
458: ai_move, -1, medic_duck_down,
459: ai_move, -1, medic_duck_hold,
460: ai_move, -1, NULL,
461: ai_move, -1, NULL,
462: ai_move, -1, medic_duck_up,
463: ai_move, -1, NULL,
464: ai_move, -1, NULL,
465: ai_move, -1, NULL,
466: ai_move, -1, NULL,
467: ai_move, -1, NULL,
468: ai_move, -1, NULL,
469: ai_move, -1, NULL,
470: ai_move, -1, NULL,
471: ai_move, -1, NULL
472: };
473: mmove_t medic_move_duck = {FRAME_duck1, FRAME_duck16, medic_frames_duck, medic_run};
474:
475: void medic_dodge (edict_t *self, edict_t *attacker, float eta)
476: {
477: if (random() > 0.25)
478: return;
479:
480: if (!self->enemy)
481: self->enemy = attacker;
482:
483: self->monsterinfo.currentmove = &medic_move_duck;
484: }
485:
486: mframe_t medic_frames_attackHyperBlaster [] =
487: {
488: ai_charge, 0, NULL,
489: ai_charge, 0, NULL,
490: ai_charge, 0, NULL,
491: ai_charge, 0, NULL,
492: ai_charge, 0, medic_fire_blaster,
493: ai_charge, 0, medic_fire_blaster,
494: ai_charge, 0, medic_fire_blaster,
495: ai_charge, 0, medic_fire_blaster,
496: ai_charge, 0, medic_fire_blaster,
497: ai_charge, 0, medic_fire_blaster,
498: ai_charge, 0, medic_fire_blaster,
499: ai_charge, 0, medic_fire_blaster,
500: ai_charge, 0, medic_fire_blaster,
501: ai_charge, 0, medic_fire_blaster,
502: ai_charge, 0, medic_fire_blaster,
503: ai_charge, 0, medic_fire_blaster
504: };
505: mmove_t medic_move_attackHyperBlaster = {FRAME_attack15, FRAME_attack30, medic_frames_attackHyperBlaster, medic_run};
506:
507:
508: void medic_continue (edict_t *self)
509: {
510: if (visible (self, self->enemy) )
511: if (random() <= 0.95)
512: self->monsterinfo.currentmove = &medic_move_attackHyperBlaster;
513: }
514:
515:
516: mframe_t medic_frames_attackBlaster [] =
517: {
518: ai_charge, 0, NULL,
519: ai_charge, 5, NULL,
520: ai_charge, 5, NULL,
521: ai_charge, 3, NULL,
522: ai_charge, 2, NULL,
523: ai_charge, 0, NULL,
524: ai_charge, 0, NULL,
525: ai_charge, 0, NULL,
526: ai_charge, 0, medic_fire_blaster,
527: ai_charge, 0, NULL,
528: ai_charge, 0, NULL,
529: ai_charge, 0, medic_fire_blaster,
530: ai_charge, 0, NULL,
531: ai_charge, 0, medic_continue // Change to medic_continue... Else, go to frame 32
532: };
533: mmove_t medic_move_attackBlaster = {FRAME_attack1, FRAME_attack14, medic_frames_attackBlaster, medic_run};
534:
535:
536: void medic_hook_launch (edict_t *self)
537: {
538: gi.sound (self, CHAN_WEAPON, sound_hook_launch, 1, ATTN_NORM, 0);
539: }
540:
541: void ED_CallSpawn (edict_t *ent);
542:
543: static vec3_t medic_cable_offsets[] =
544: {
545: 45.0, -9.2, 15.5,
546: 48.4, -9.7, 15.2,
547: 47.8, -9.8, 15.8,
548: 47.3, -9.3, 14.3,
549: 45.4, -10.1, 13.1,
550: 41.9, -12.7, 12.0,
551: 37.8, -15.8, 11.2,
552: 34.3, -18.4, 10.7,
553: 32.7, -19.7, 10.4,
554: 32.7, -19.7, 10.4
555: };
556:
557: void medic_cable_attack (edict_t *self)
558: {
559: vec3_t offset, start, end, f, r;
560: trace_t tr;
561: vec3_t dir, angles;
562: float distance;
563:
564: if (!self->enemy->inuse)
565: return;
566:
567: AngleVectors (self->s.angles, f, r, NULL);
568: VectorCopy (medic_cable_offsets[self->s.frame - FRAME_attack42], offset);
569: G_ProjectSource (self->s.origin, offset, f, r, start);
570:
571: // check for max distance
572: VectorSubtract (start, self->enemy->s.origin, dir);
573: distance = VectorLength(dir);
574: if (distance > 256)
575: return;
576:
577: // check for min/max pitch
578: vectoangles (dir, angles);
579: if (angles[0] < -180)
580: angles[0] += 360;
581: if (fabs(angles[0]) > 45)
582: return;
583:
584: tr = gi.trace (start, NULL, NULL, self->enemy->s.origin, self, MASK_SHOT);
585: if (tr.fraction != 1.0 && tr.ent != self->enemy)
586: return;
587:
588: if (self->s.frame == FRAME_attack43)
589: {
590: gi.sound (self->enemy, CHAN_AUTO, sound_hook_hit, 1, ATTN_NORM, 0);
591: self->enemy->monsterinfo.aiflags |= AI_RESURRECTING;
592: }
593: else if (self->s.frame == FRAME_attack50)
594: {
595: self->enemy->spawnflags = 0;
596: self->enemy->monsterinfo.aiflags = 0;
597: self->enemy->target = NULL;
598: self->enemy->targetname = NULL;
599: self->enemy->combattarget = NULL;
600: self->enemy->deathtarget = NULL;
601: self->enemy->owner = self;
602: ED_CallSpawn (self->enemy);
603: self->enemy->owner = NULL;
604: if (self->enemy->think)
605: {
606: self->enemy->nextthink = level.time;
607: self->enemy->think (self->enemy);
608: }
609: self->enemy->monsterinfo.aiflags |= AI_RESURRECTING;
610: if (self->oldenemy && self->oldenemy->client)
611: {
612: self->enemy->enemy = self->oldenemy;
613: FoundTarget (self->enemy);
614: }
615: }
616: else
617: {
618: if (self->s.frame == FRAME_attack44)
619: gi.sound (self, CHAN_WEAPON, sound_hook_heal, 1, ATTN_NORM, 0);
620: }
621:
622: // adjust start for beam origin being in middle of a segment
623: VectorMA (start, 8, f, start);
624:
625: // adjust end z for end spot since the monster is currently dead
626: VectorCopy (self->enemy->s.origin, end);
627: end[2] = self->enemy->absmin[2] + self->enemy->size[2] / 2;
628:
629: gi.WriteByte (svc_temp_entity);
630: gi.WriteByte (TE_MEDIC_CABLE_ATTACK);
631: gi.WriteShort (self - g_edicts);
632: gi.WritePosition (start);
633: gi.WritePosition (end);
634: gi.multicast (self->s.origin, MULTICAST_PVS);
635: }
636:
637: void medic_hook_retract (edict_t *self)
638: {
639: gi.sound (self, CHAN_WEAPON, sound_hook_retract, 1, ATTN_NORM, 0);
640: self->enemy->monsterinfo.aiflags &= ~AI_RESURRECTING;
641: }
642:
643: mframe_t medic_frames_attackCable [] =
644: {
645: ai_move, 2, NULL,
646: ai_move, 3, NULL,
647: ai_move, 5, NULL,
648: ai_move, 4.4, NULL,
649: ai_charge, 4.7, NULL,
650: ai_charge, 5, NULL,
651: ai_charge, 6, NULL,
652: ai_charge, 4, NULL,
653: ai_charge, 0, NULL,
654: ai_move, 0, medic_hook_launch,
655: ai_move, 0, medic_cable_attack,
656: ai_move, 0, medic_cable_attack,
657: ai_move, 0, medic_cable_attack,
658: ai_move, 0, medic_cable_attack,
659: ai_move, 0, medic_cable_attack,
660: ai_move, 0, medic_cable_attack,
661: ai_move, 0, medic_cable_attack,
662: ai_move, 0, medic_cable_attack,
663: ai_move, 0, medic_cable_attack,
664: ai_move, -15, medic_hook_retract,
665: ai_move, -1.5, NULL,
666: ai_move, -1.2, NULL,
667: ai_move, -3, NULL,
668: ai_move, -2, NULL,
669: ai_move, 0.3, NULL,
670: ai_move, 0.7, NULL,
671: ai_move, 1.2, NULL,
672: ai_move, 1.3, NULL
673: };
674: mmove_t medic_move_attackCable = {FRAME_attack33, FRAME_attack60, medic_frames_attackCable, medic_run};
675:
676:
677: void medic_attack(edict_t *self)
678: {
679: if (self->monsterinfo.aiflags & AI_MEDIC)
680: self->monsterinfo.currentmove = &medic_move_attackCable;
681: else
682: self->monsterinfo.currentmove = &medic_move_attackBlaster;
683: }
684:
685: qboolean medic_checkattack (edict_t *self)
686: {
687: if (self->monsterinfo.aiflags & AI_MEDIC)
688: {
689: medic_attack(self);
690: return true;
691: }
692:
693: return M_CheckAttack (self);
694: }
695:
696:
697: /*QUAKED monster_medic (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
698: */
699: void SP_monster_medic (edict_t *self)
700: {
701: if (deathmatch->value)
702: {
703: G_FreeEdict (self);
704: return;
705: }
706:
707: sound_idle1 = gi.soundindex ("medic/idle.wav");
708: sound_pain1 = gi.soundindex ("medic/medpain1.wav");
709: sound_pain2 = gi.soundindex ("medic/medpain2.wav");
710: sound_die = gi.soundindex ("medic/meddeth1.wav");
711: sound_sight = gi.soundindex ("medic/medsght1.wav");
712: sound_search = gi.soundindex ("medic/medsrch1.wav");
713: sound_hook_launch = gi.soundindex ("medic/medatck2.wav");
714: sound_hook_hit = gi.soundindex ("medic/medatck3.wav");
715: sound_hook_heal = gi.soundindex ("medic/medatck4.wav");
716: sound_hook_retract = gi.soundindex ("medic/medatck5.wav");
717:
718: gi.soundindex ("medic/medatck1.wav");
719:
720: self->movetype = MOVETYPE_STEP;
721: self->solid = SOLID_BBOX;
722: self->s.modelindex = gi.modelindex ("models/monsters/medic/tris.md2");
723: VectorSet (self->mins, -24, -24, -24);
724: VectorSet (self->maxs, 24, 24, 32);
725:
726: self->health = 300;
727: self->gib_health = -130;
728: self->mass = 400;
729:
730: self->pain = medic_pain;
731: self->die = medic_die;
732:
733: self->monsterinfo.stand = medic_stand;
734: self->monsterinfo.walk = medic_walk;
735: self->monsterinfo.run = medic_run;
736: self->monsterinfo.dodge = medic_dodge;
737: self->monsterinfo.attack = medic_attack;
738: self->monsterinfo.melee = NULL;
739: self->monsterinfo.sight = medic_sight;
740: self->monsterinfo.idle = medic_idle;
741: self->monsterinfo.search = medic_search;
742: self->monsterinfo.checkattack = medic_checkattack;
743:
744: gi.linkentity (self);
745:
746: self->monsterinfo.currentmove = &medic_move_stand;
747: self->monsterinfo.scale = MODEL_SCALE;
748:
749: walkmonster_start (self);
750: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.