|
|
1.1 root 1: /*
2: ==============================================================================
3:
4: parasite
5:
6: ==============================================================================
7: */
8:
9: #include "g_local.h"
10: #include "m_parasite.h"
11:
12:
13: static int sound_pain1;
14: static int sound_pain2;
15: static int sound_die;
16: static int sound_launch;
17: static int sound_impact;
18: static int sound_suck;
19: static int sound_reelin;
20: static int sound_sight;
21: static int sound_tap;
22: static int sound_scratch;
23: static int sound_search;
24:
25:
26: void parasite_stand (edict_t *self);
27: void parasite_start_run (edict_t *self);
28: void parasite_run (edict_t *self);
29: void parasite_walk (edict_t *self);
30: void parasite_start_walk (edict_t *self);
31: void parasite_end_fidget (edict_t *self);
32: void parasite_do_fidget (edict_t *self);
33: void parasite_refidget (edict_t *self);
34:
35:
36: void parasite_launch (edict_t *self)
37: {
38: gi.sound (self, CHAN_WEAPON, sound_launch, 1, ATTN_NORM, 0);
39: }
40:
41: void parasite_reel_in (edict_t *self)
42: {
43: gi.sound (self, CHAN_WEAPON, sound_reelin, 1, ATTN_NORM, 0);
44: }
45:
46: void parasite_sight (edict_t *self, edict_t *other)
47: {
48: gi.sound (self, CHAN_WEAPON, sound_sight, 1, ATTN_NORM, 0);
49: }
50:
51: void parasite_tap (edict_t *self)
52: {
53: gi.sound (self, CHAN_WEAPON, sound_tap, 1, ATTN_IDLE, 0);
54: }
55:
56: void parasite_scratch (edict_t *self)
57: {
58: gi.sound (self, CHAN_WEAPON, sound_scratch, 1, ATTN_IDLE, 0);
59: }
60:
61: void parasite_search (edict_t *self)
62: {
63: gi.sound (self, CHAN_WEAPON, sound_search, 1, ATTN_IDLE, 0);
64: }
65:
66:
67: mframe_t parasite_frames_start_fidget [] =
68: {
69: ai_stand, 0, NULL,
70: ai_stand, 0, NULL,
71: ai_stand, 0, NULL,
72: ai_stand, 0, NULL
73: };
74: mmove_t parasite_move_start_fidget = {FRAME_stand18, FRAME_stand21, parasite_frames_start_fidget, parasite_do_fidget};
75:
76: mframe_t parasite_frames_fidget [] =
77: {
78: ai_stand, 0, parasite_scratch,
79: ai_stand, 0, NULL,
80: ai_stand, 0, NULL,
81: ai_stand, 0, parasite_scratch,
82: ai_stand, 0, NULL,
83: ai_stand, 0, NULL
84: };
85: mmove_t parasite_move_fidget = {FRAME_stand22, FRAME_stand27, parasite_frames_fidget, parasite_refidget};
86:
87: mframe_t parasite_frames_end_fidget [] =
88: {
89: ai_stand, 0, parasite_scratch,
90: ai_stand, 0, NULL,
91: ai_stand, 0, NULL,
92: ai_stand, 0, NULL,
93: ai_stand, 0, NULL,
94: ai_stand, 0, NULL,
95: ai_stand, 0, NULL,
96: ai_stand, 0, NULL
97: };
98: mmove_t parasite_move_end_fidget = {FRAME_stand28, FRAME_stand35, parasite_frames_end_fidget, parasite_stand};
99:
100: void parasite_end_fidget (edict_t *self)
101: {
102: self->monsterinfo.currentmove = ¶site_move_end_fidget;
103: }
104:
105: void parasite_do_fidget (edict_t *self)
106: {
107: self->monsterinfo.currentmove = ¶site_move_fidget;
108: }
109:
110: void parasite_refidget (edict_t *self)
111: {
112: if (random() <= 0.8)
113: self->monsterinfo.currentmove = ¶site_move_fidget;
114: else
115: self->monsterinfo.currentmove = ¶site_move_end_fidget;
116: }
117:
118: void parasite_idle (edict_t *self)
119: {
120: self->monsterinfo.currentmove = ¶site_move_start_fidget;
121: }
122:
123:
124: mframe_t parasite_frames_stand [] =
125: {
126: ai_stand, 0, NULL,
127: ai_stand, 0, NULL,
128: ai_stand, 0, parasite_tap,
129: ai_stand, 0, NULL,
130: ai_stand, 0, parasite_tap,
131: ai_stand, 0, NULL,
132: ai_stand, 0, NULL,
133: ai_stand, 0, NULL,
134: ai_stand, 0, parasite_tap,
135: ai_stand, 0, NULL,
136: ai_stand, 0, parasite_tap,
137: ai_stand, 0, NULL,
138: ai_stand, 0, NULL,
139: ai_stand, 0, NULL,
140: ai_stand, 0, parasite_tap,
141: ai_stand, 0, NULL,
142: ai_stand, 0, parasite_tap
143: };
144: mmove_t parasite_move_stand = {FRAME_stand01, FRAME_stand17, parasite_frames_stand, parasite_stand};
145:
146: void parasite_stand (edict_t *self)
147: {
148: self->monsterinfo.currentmove = ¶site_move_stand;
149: }
150:
151:
152: mframe_t parasite_frames_run [] =
153: {
154: ai_run, 30, NULL,
155: ai_run, 30, NULL,
156: ai_run, 22, NULL,
157: ai_run, 19, NULL,
158: ai_run, 24, NULL,
159: ai_run, 28, NULL,
160: ai_run, 25, NULL
161: };
162: mmove_t parasite_move_run = {FRAME_run03, FRAME_run09, parasite_frames_run, NULL};
163:
164: mframe_t parasite_frames_start_run [] =
165: {
166: ai_run, 0, NULL,
167: ai_run, 30, NULL,
168: };
169: mmove_t parasite_move_start_run = {FRAME_run01, FRAME_run02, parasite_frames_start_run, parasite_run};
170:
171: mframe_t parasite_frames_stop_run [] =
172: {
173: ai_run, 20, NULL,
174: ai_run, 20, NULL,
175: ai_run, 12, NULL,
176: ai_run, 10, NULL,
177: ai_run, 0, NULL,
178: ai_run, 0, NULL
179: };
180: mmove_t parasite_move_stop_run = {FRAME_run10, FRAME_run15, parasite_frames_stop_run, NULL};
181:
182: void parasite_start_run (edict_t *self)
183: {
184: if (self->monsterinfo.aiflags & AI_STAND_GROUND)
185: self->monsterinfo.currentmove = ¶site_move_stand;
186: else
187: self->monsterinfo.currentmove = ¶site_move_start_run;
188: }
189:
190: void parasite_run (edict_t *self)
191: {
192: if (self->monsterinfo.aiflags & AI_STAND_GROUND)
193: self->monsterinfo.currentmove = ¶site_move_stand;
194: else
195: self->monsterinfo.currentmove = ¶site_move_run;
196: }
197:
198:
199: mframe_t parasite_frames_walk [] =
200: {
201: ai_walk, 30, NULL,
202: ai_walk, 30, NULL,
203: ai_walk, 22, NULL,
204: ai_walk, 19, NULL,
205: ai_walk, 24, NULL,
206: ai_walk, 28, NULL,
207: ai_walk, 25, NULL
208: };
209: mmove_t parasite_move_walk = {FRAME_run03, FRAME_run09, parasite_frames_walk, parasite_walk};
210:
211: mframe_t parasite_frames_start_walk [] =
212: {
213: ai_walk, 0, NULL,
214: ai_walk, 30, parasite_walk
215: };
216: mmove_t parasite_move_start_walk = {FRAME_run01, FRAME_run02, parasite_frames_start_walk, NULL};
217:
218: mframe_t parasite_frames_stop_walk [] =
219: {
220: ai_walk, 20, NULL,
221: ai_walk, 20, NULL,
222: ai_walk, 12, NULL,
223: ai_walk, 10, NULL,
224: ai_walk, 0, NULL,
225: ai_walk, 0, NULL
226: };
227: mmove_t parasite_move_stop_walk = {FRAME_run10, FRAME_run15, parasite_frames_stop_walk, NULL};
228:
229: void parasite_start_walk (edict_t *self)
230: {
231: self->monsterinfo.currentmove = ¶site_move_start_walk;
232: }
233:
234: void parasite_walk (edict_t *self)
235: {
236: self->monsterinfo.currentmove = ¶site_move_walk;
237: }
238:
239:
240: mframe_t parasite_frames_pain1 [] =
241: {
242: ai_move, 0, NULL,
243: ai_move, 0, NULL,
244: ai_move, 0, NULL,
245: ai_move, 0, NULL,
246: ai_move, 0, NULL,
247: ai_move, 0, NULL,
248: ai_move, 6, NULL,
249: ai_move, 16, NULL,
250: ai_move, -6, NULL,
251: ai_move, -7, NULL,
252: ai_move, 0, NULL
253: };
254: mmove_t parasite_move_pain1 = {FRAME_pain101, FRAME_pain111, parasite_frames_pain1, parasite_start_run};
255:
256: void parasite_pain (edict_t *self, edict_t *other, float kick, int damage)
257: {
258: if (self->health < (self->max_health / 2))
259: self->s.skinnum = 1;
260:
261: if (level.time < self->pain_debounce_time)
262: return;
263:
264: self->pain_debounce_time = level.time + 3;
265:
266: if (skill->value == 3)
267: return; // no pain anims in nightmare
268:
269: if (random() < 0.5)
270: gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
271: else
272: gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
273:
274: self->monsterinfo.currentmove = ¶site_move_pain1;
275: }
276:
277:
278: static qboolean parasite_drain_attack_ok (vec3_t start, vec3_t end)
279: {
280: vec3_t dir, angles;
281:
282: // check for max distance
283: VectorSubtract (start, end, dir);
284: if (VectorLength(dir) > 256)
285: return false;
286:
287: // check for min/max pitch
288: vectoangles (dir, angles);
289: if (angles[0] < -180)
290: angles[0] += 360;
291: if (fabs(angles[0]) > 30)
292: return false;
293:
294: return true;
295: }
296:
297: void parasite_drain_attack (edict_t *self)
298: {
299: vec3_t offset, start, f, r, end, dir;
300: trace_t tr;
301: int damage;
302:
303: AngleVectors (self->s.angles, f, r, NULL);
304: VectorSet (offset, 24, 0, 6);
305: G_ProjectSource (self->s.origin, offset, f, r, start);
306:
307: VectorCopy (self->enemy->s.origin, end);
308: if (!parasite_drain_attack_ok(start, end))
309: {
310: end[2] = self->enemy->s.origin[2] + self->enemy->maxs[2] - 8;
311: if (!parasite_drain_attack_ok(start, end))
312: {
313: end[2] = self->enemy->s.origin[2] + self->enemy->mins[2] + 8;
314: if (!parasite_drain_attack_ok(start, end))
315: return;
316: }
317: }
318: VectorCopy (self->enemy->s.origin, end);
319:
320: tr = gi.trace (start, NULL, NULL, end, self, MASK_SHOT);
321: if (tr.ent != self->enemy)
322: return;
323:
324: if (self->s.frame == FRAME_drain03)
325: {
326: damage = 5;
327: gi.sound (self->enemy, CHAN_AUTO, sound_impact, 1, ATTN_NORM, 0);
328: }
329: else
330: {
331: if (self->s.frame == FRAME_drain04)
332: gi.sound (self, CHAN_WEAPON, sound_suck, 1, ATTN_NORM, 0);
333: damage = 2;
334: }
335:
336: gi.WriteByte (svc_temp_entity);
337: gi.WriteByte (TE_PARASITE_ATTACK);
338: gi.WriteShort (self - g_edicts);
339: gi.WritePosition (start);
340: gi.WritePosition (end);
341: gi.multicast (self->s.origin, MULTICAST_PVS);
342:
343: VectorSubtract (start, end, dir);
344: T_Damage (self->enemy, self, self, dir, self->enemy->s.origin, vec3_origin, damage, 0, DAMAGE_NO_KNOCKBACK, MOD_UNKNOWN);
345: }
346:
347: mframe_t parasite_frames_drain [] =
348: {
349: ai_charge, 0, parasite_launch,
350: ai_charge, 0, NULL,
351: ai_charge, 15, parasite_drain_attack, // Target hits
352: ai_charge, 0, parasite_drain_attack, // drain
353: ai_charge, 0, parasite_drain_attack, // drain
354: ai_charge, 0, parasite_drain_attack, // drain
355: ai_charge, 0, parasite_drain_attack, // drain
356: ai_charge, -2, parasite_drain_attack, // drain
357: ai_charge, -2, parasite_drain_attack, // drain
358: ai_charge, -3, parasite_drain_attack, // drain
359: ai_charge, -2, parasite_drain_attack, // drain
360: ai_charge, 0, parasite_drain_attack, // drain
361: ai_charge, -1, parasite_drain_attack, // drain
362: ai_charge, 0, parasite_reel_in, // let go
363: ai_charge, -2, NULL,
364: ai_charge, -2, NULL,
365: ai_charge, -3, NULL,
366: ai_charge, 0, NULL
367: };
368: mmove_t parasite_move_drain = {FRAME_drain01, FRAME_drain18, parasite_frames_drain, parasite_start_run};
369:
370:
371: mframe_t parasite_frames_break [] =
372: {
373: ai_charge, 0, NULL,
374: ai_charge, -3, NULL,
375: ai_charge, 1, NULL,
376: ai_charge, 2, NULL,
377: ai_charge, -3, NULL,
378: ai_charge, 1, NULL,
379: ai_charge, 1, NULL,
380: ai_charge, 3, NULL,
381: ai_charge, 0, NULL,
382: ai_charge, -18, NULL,
383: ai_charge, 3, NULL,
384: ai_charge, 9, NULL,
385: ai_charge, 6, NULL,
386: ai_charge, 0, NULL,
387: ai_charge, -18, NULL,
388: ai_charge, 0, NULL,
389: ai_charge, 8, NULL,
390: ai_charge, 9, NULL,
391: ai_charge, 0, NULL,
392: ai_charge, -18, NULL,
393: ai_charge, 0, NULL,
394: ai_charge, 0, NULL, // airborne
395: ai_charge, 0, NULL, // airborne
396: ai_charge, 0, NULL, // slides
397: ai_charge, 0, NULL, // slides
398: ai_charge, 0, NULL, // slides
399: ai_charge, 0, NULL, // slides
400: ai_charge, 4, NULL,
401: ai_charge, 11, NULL,
402: ai_charge, -2, NULL,
403: ai_charge, -5, NULL,
404: ai_charge, 1, NULL
405: };
406: mmove_t parasite_move_break = {FRAME_break01, FRAME_break32, parasite_frames_break, parasite_start_run};
407:
408: /*
409: ===
410: Break Stuff Ends
411: ===
412: */
413:
414: void parasite_attack (edict_t *self)
415: {
416: // if (random() <= 0.2)
417: // self->monsterinfo.currentmove = ¶site_move_break;
418: // else
419: self->monsterinfo.currentmove = ¶site_move_drain;
420: }
421:
422:
423: //================
424: //ROGUE
425: void parasite_jump_down (edict_t *self)
426: {
427: vec3_t forward,up;
428:
429: AngleVectors (self->s.angles, forward, NULL, up);
430: VectorMA(self->velocity, 100, forward, self->velocity);
431: VectorMA(self->velocity, 300, up, self->velocity);
432: }
433:
434: void parasite_jump_up (edict_t *self)
435: {
436: vec3_t forward,up;
437:
438: AngleVectors (self->s.angles, forward, NULL, up);
439: VectorMA(self->velocity, 200, forward, self->velocity);
440: VectorMA(self->velocity, 450, up, self->velocity);
441: }
442:
443: void parasite_jump_wait_land (edict_t *self)
444: {
445: if(self->groundentity == NULL)
446: self->monsterinfo.nextframe = self->s.frame;
447: else
448: self->monsterinfo.nextframe = self->s.frame + 1;
449: }
450:
451: mframe_t parasite_frames_jump_up [] =
452: {
453: ai_move, -8, NULL,
454: ai_move, -8, NULL,
455: ai_move, -8, NULL,
456: ai_move, -8, parasite_jump_up,
457: ai_move, 0, NULL,
458: ai_move, 0, NULL,
459: ai_move, 0, parasite_jump_wait_land,
460: ai_move, 0, NULL
461: };
462: mmove_t parasite_move_jump_up = { FRAME_jump01, FRAME_jump08, parasite_frames_jump_up, parasite_run };
463:
464: mframe_t parasite_frames_jump_down [] =
465: {
466: ai_move, 0, NULL,
467: ai_move, 0, NULL,
468: ai_move, 0, NULL,
469: ai_move, 0, parasite_jump_down,
470: ai_move, 0, NULL,
471: ai_move, 0, NULL,
472: ai_move, 0, parasite_jump_wait_land,
473: ai_move, 0, NULL
474: };
475: mmove_t parasite_move_jump_down = { FRAME_jump01, FRAME_jump08, parasite_frames_jump_down, parasite_run };
476:
477: void parasite_jump (edict_t *self)
478: {
479: if(!self->enemy)
480: return;
481:
482: if(self->enemy->s.origin[2] > self->s.origin[2])
483: self->monsterinfo.currentmove = ¶site_move_jump_up;
484: else
485: self->monsterinfo.currentmove = ¶site_move_jump_down;
486: }
487:
488: /*
489: ===
490: Blocked
491: ===
492: */
493: qboolean parasite_blocked (edict_t *self, float dist)
494: {
495: if(blocked_checkshot (self, 0.25 + (0.05 * skill->value) ))
496: return true;
497:
498: if(blocked_checkjump (self, dist, 256, 68))
499: {
500: parasite_jump (self);
501: return true;
502: }
503:
504: if(blocked_checkplat (self, dist))
505: return true;
506: }
507: //ROGUE
508: //================
509:
510:
511:
512: /*
513: ===
514: Death Stuff Starts
515: ===
516: */
517:
518: void parasite_dead (edict_t *self)
519: {
520: VectorSet (self->mins, -16, -16, -24);
521: VectorSet (self->maxs, 16, 16, -8);
522: self->movetype = MOVETYPE_TOSS;
523: self->svflags |= SVF_DEADMONSTER;
524: self->nextthink = 0;
525: gi.linkentity (self);
526: }
527:
528: mframe_t parasite_frames_death [] =
529: {
530: ai_move, 0, NULL,
531: ai_move, 0, NULL,
532: ai_move, 0, NULL,
533: ai_move, 0, NULL,
534: ai_move, 0, NULL,
535: ai_move, 0, NULL,
536: ai_move, 0, NULL
537: };
538: mmove_t parasite_move_death = {FRAME_death101, FRAME_death107, parasite_frames_death, parasite_dead};
539:
540: void parasite_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
541: {
542: int n;
543:
544: // check for gib
545: if (self->health <= self->gib_health)
546: {
547: gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
548: for (n= 0; n < 2; n++)
549: ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
550: for (n= 0; n < 4; n++)
551: ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
552: ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
553: self->deadflag = DEAD_DEAD;
554: return;
555: }
556:
557: if (self->deadflag == DEAD_DEAD)
558: return;
559:
560: // regular death
561: gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0);
562: self->deadflag = DEAD_DEAD;
563: self->takedamage = DAMAGE_YES;
564: self->monsterinfo.currentmove = ¶site_move_death;
565: }
566:
567: /*
568: ===
569: End Death Stuff
570: ===
571: */
572:
573: /*QUAKED monster_parasite (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
574: */
575: void SP_monster_parasite (edict_t *self)
576: {
577: if (deathmatch->value)
578: {
579: G_FreeEdict (self);
580: return;
581: }
582:
583: sound_pain1 = gi.soundindex ("parasite/parpain1.wav");
584: sound_pain2 = gi.soundindex ("parasite/parpain2.wav");
585: sound_die = gi.soundindex ("parasite/pardeth1.wav");
586: sound_launch = gi.soundindex("parasite/paratck1.wav");
587: sound_impact = gi.soundindex("parasite/paratck2.wav");
588: sound_suck = gi.soundindex("parasite/paratck3.wav");
589: sound_reelin = gi.soundindex("parasite/paratck4.wav");
590: sound_sight = gi.soundindex("parasite/parsght1.wav");
591: sound_tap = gi.soundindex("parasite/paridle1.wav");
592: sound_scratch = gi.soundindex("parasite/paridle2.wav");
593: sound_search = gi.soundindex("parasite/parsrch1.wav");
594:
595: self->s.modelindex = gi.modelindex ("models/monsters/parasite/tris.md2");
596: VectorSet (self->mins, -16, -16, -24);
597: VectorSet (self->maxs, 16, 16, 24);
598: self->movetype = MOVETYPE_STEP;
599: self->solid = SOLID_BBOX;
600:
601: self->health = 175;
602: self->gib_health = -50;
603: self->mass = 250;
604:
605: self->pain = parasite_pain;
606: self->die = parasite_die;
607:
608: self->monsterinfo.stand = parasite_stand;
609: self->monsterinfo.walk = parasite_start_walk;
610: self->monsterinfo.run = parasite_start_run;
611: self->monsterinfo.attack = parasite_attack;
612: self->monsterinfo.sight = parasite_sight;
613: self->monsterinfo.idle = parasite_idle;
614: self->monsterinfo.blocked = parasite_blocked; // PGM
615:
616: gi.linkentity (self);
617:
618: self->monsterinfo.currentmove = ¶site_move_stand;
619: self->monsterinfo.scale = MODEL_SCALE;
620:
621: walkmonster_start (self);
622: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.