|
|
1.1 root 1: /*
2: ==============================================================================
3:
4: chick
5:
6: ==============================================================================
7: */
8:
9: #include "g_local.h"
10: #include "m_chick.h"
11:
12: // ROGUE
13: #define LEAD_TARGET 1
14: // ROGUE
15:
16: qboolean visible (edict_t *self, edict_t *other);
17:
18: void chick_stand (edict_t *self);
19: void chick_run (edict_t *self);
20: void chick_reslash(edict_t *self);
21: void chick_rerocket(edict_t *self);
22: void chick_attack1(edict_t *self);
23:
24: static int sound_missile_prelaunch;
25: static int sound_missile_launch;
26: static int sound_melee_swing;
27: static int sound_melee_hit;
28: static int sound_missile_reload;
29: static int sound_death1;
30: static int sound_death2;
31: static int sound_fall_down;
32: static int sound_idle1;
33: static int sound_idle2;
34: static int sound_pain1;
35: static int sound_pain2;
36: static int sound_pain3;
37: static int sound_sight;
38: static int sound_search;
39:
40: void ChickMoan (edict_t *self)
41: {
42: if (random() < 0.5)
43: gi.sound (self, CHAN_VOICE, sound_idle1, 1, ATTN_IDLE, 0);
44: else
45: gi.sound (self, CHAN_VOICE, sound_idle2, 1, ATTN_IDLE, 0);
46: }
47:
48: mframe_t chick_frames_fidget [] =
49: {
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: ai_stand, 0, NULL,
58: ai_stand, 0, ChickMoan,
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: ai_stand, 0, NULL,
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: ai_stand, 0, NULL
80: };
81: mmove_t chick_move_fidget = {FRAME_stand201, FRAME_stand230, chick_frames_fidget, chick_stand};
82:
83: void chick_fidget (edict_t *self)
84: {
85: if (self->monsterinfo.aiflags & AI_STAND_GROUND)
86: return;
87: if (random() <= 0.3)
88: self->monsterinfo.currentmove = &chick_move_fidget;
89: }
90:
91: mframe_t chick_frames_stand [] =
92: {
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, 0, NULL,
99: ai_stand, 0, NULL,
100: ai_stand, 0, NULL,
101: ai_stand, 0, NULL,
102: ai_stand, 0, NULL,
103: ai_stand, 0, NULL,
104: ai_stand, 0, NULL,
105: ai_stand, 0, NULL,
106: ai_stand, 0, NULL,
107: ai_stand, 0, NULL,
108: 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, chick_fidget,
123:
124: };
125: mmove_t chick_move_stand = {FRAME_stand101, FRAME_stand130, chick_frames_stand, NULL};
126:
127: void chick_stand (edict_t *self)
128: {
129: self->monsterinfo.currentmove = &chick_move_stand;
130: }
131:
132: mframe_t chick_frames_start_run [] =
133: {
134: ai_run, 1, NULL,
135: ai_run, 0, NULL,
136: ai_run, 0, NULL,
137: ai_run, -1, NULL,
138: ai_run, -1, NULL,
139: ai_run, 0, NULL,
140: ai_run, 1, NULL,
141: ai_run, 3, NULL,
142: ai_run, 6, NULL,
143: ai_run, 3, NULL
144: };
145: mmove_t chick_move_start_run = {FRAME_walk01, FRAME_walk10, chick_frames_start_run, chick_run};
146:
147: mframe_t chick_frames_run [] =
148: {
149: ai_run, 6, NULL,
150: ai_run, 8, NULL,
151: ai_run, 13, NULL,
152: ai_run, 5, monster_done_dodge, // make sure to clear dodge bit
153: ai_run, 7, NULL,
154: ai_run, 4, NULL,
155: ai_run, 11, NULL,
156: ai_run, 5, NULL,
157: ai_run, 9, NULL,
158: ai_run, 7, NULL
159: };
160:
161: mmove_t chick_move_run = {FRAME_walk11, FRAME_walk20, chick_frames_run, NULL};
162:
163: mframe_t chick_frames_walk [] =
164: {
165: ai_walk, 6, NULL,
166: ai_walk, 8, NULL,
167: ai_walk, 13, NULL,
168: ai_walk, 5, NULL,
169: ai_walk, 7, NULL,
170: ai_walk, 4, NULL,
171: ai_walk, 11, NULL,
172: ai_walk, 5, NULL,
173: ai_walk, 9, NULL,
174: ai_walk, 7, NULL
175: };
176:
177: mmove_t chick_move_walk = {FRAME_walk11, FRAME_walk20, chick_frames_walk, NULL};
178:
179: void chick_walk (edict_t *self)
180: {
181: self->monsterinfo.currentmove = &chick_move_walk;
182: }
183:
184: void chick_run (edict_t *self)
185: {
186: monster_done_dodge (self);
187:
188: if (self->monsterinfo.aiflags & AI_STAND_GROUND)
189: {
190: self->monsterinfo.currentmove = &chick_move_stand;
191: return;
192: }
193:
194: if (self->monsterinfo.currentmove == &chick_move_walk ||
195: self->monsterinfo.currentmove == &chick_move_start_run)
196: {
197: self->monsterinfo.currentmove = &chick_move_run;
198: }
199: else
200: {
201: self->monsterinfo.currentmove = &chick_move_start_run;
202: }
203: }
204:
205: mframe_t chick_frames_pain1 [] =
206: {
207: ai_move, 0, NULL,
208: ai_move, 0, NULL,
209: ai_move, 0, NULL,
210: ai_move, 0, NULL,
211: ai_move, 0, NULL
212: };
213: mmove_t chick_move_pain1 = {FRAME_pain101, FRAME_pain105, chick_frames_pain1, chick_run};
214:
215: mframe_t chick_frames_pain2 [] =
216: {
217: ai_move, 0, NULL,
218: ai_move, 0, NULL,
219: ai_move, 0, NULL,
220: ai_move, 0, NULL,
221: ai_move, 0, NULL
222: };
223: mmove_t chick_move_pain2 = {FRAME_pain201, FRAME_pain205, chick_frames_pain2, chick_run};
224:
225: mframe_t chick_frames_pain3 [] =
226: {
227: ai_move, 0, NULL,
228: ai_move, 0, NULL,
229: ai_move, -6, NULL,
230: ai_move, 3, NULL,
231: ai_move, 11, NULL,
232: ai_move, 3, NULL,
233: ai_move, 0, NULL,
234: ai_move, 0, NULL,
235: ai_move, 4, NULL,
236: ai_move, 1, NULL,
237: ai_move, 0, NULL,
238: ai_move, -3, NULL,
239: ai_move, -4, NULL,
240: ai_move, 5, NULL,
241: ai_move, 7, NULL,
242: ai_move, -2, NULL,
243: ai_move, 3, NULL,
244: ai_move, -5, NULL,
245: ai_move, -2, NULL,
246: ai_move, -8, NULL,
247: ai_move, 2, NULL
248: };
249: mmove_t chick_move_pain3 = {FRAME_pain301, FRAME_pain321, chick_frames_pain3, chick_run};
250:
251: void chick_pain (edict_t *self, edict_t *other, float kick, int damage)
252: {
253: float r;
254:
255: monster_done_dodge(self);
256:
257: if (self->health < (self->max_health / 2))
258: self->s.skinnum = 1;
259:
260: if (level.time < self->pain_debounce_time)
261: return;
262:
263: self->pain_debounce_time = level.time + 3;
264:
265: r = random();
266: if (r < 0.33)
267: gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
268: else if (r < 0.66)
269: gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
270: else
271: gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NORM, 0);
272:
273: if (skill->value == 3)
274: return; // no pain anims in nightmare
275:
276: // PMM - clear this from blindfire
277: self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING;
278:
279: if (damage <= 10)
280: self->monsterinfo.currentmove = &chick_move_pain1;
281: else if (damage <= 25)
282: self->monsterinfo.currentmove = &chick_move_pain2;
283: else
284: self->monsterinfo.currentmove = &chick_move_pain3;
285:
286: // PMM - clear duck flag
287: if (self->monsterinfo.aiflags & AI_DUCKED)
288: monster_duck_up(self);
289: }
290:
291: void chick_dead (edict_t *self)
292: {
293: VectorSet (self->mins, -16, -16, 0);
294: VectorSet (self->maxs, 16, 16, 16);
295: self->movetype = MOVETYPE_TOSS;
296: self->svflags |= SVF_DEADMONSTER;
297: self->nextthink = 0;
298: gi.linkentity (self);
299: }
300:
301: mframe_t chick_frames_death2 [] =
302: {
303: ai_move, -6, NULL,
304: ai_move, 0, NULL,
305: ai_move, -1, NULL,
306: ai_move, -5, NULL,
307: ai_move, 0, NULL,
308: ai_move, -1, NULL,
309: ai_move, -2, NULL,
310: ai_move, 1, NULL,
311: ai_move, 10, NULL,
312: ai_move, 2, NULL,
313: ai_move, 3, NULL,
314: ai_move, 1, NULL,
315: ai_move, 2, NULL,
316: ai_move, 0, NULL,
317: ai_move, 3, NULL,
318: ai_move, 3, NULL,
319: ai_move, 1, NULL,
320: ai_move, -3, NULL,
321: ai_move, -5, NULL,
322: ai_move, 4, NULL,
323: ai_move, 15, NULL,
324: ai_move, 14, NULL,
325: ai_move, 1, NULL
326: };
327: mmove_t chick_move_death2 = {FRAME_death201, FRAME_death223, chick_frames_death2, chick_dead};
328:
329: mframe_t chick_frames_death1 [] =
330: {
331: ai_move, 0, NULL,
332: ai_move, 0, NULL,
333: ai_move, -7, NULL,
334: ai_move, 4, NULL,
335: ai_move, 11, NULL,
336: ai_move, 0, NULL,
337: ai_move, 0, NULL,
338: ai_move, 0, NULL,
339: ai_move, 0, NULL,
340: ai_move, 0, NULL,
341: ai_move, 0, NULL,
342: ai_move, 0, NULL
343:
344: };
345: mmove_t chick_move_death1 = {FRAME_death101, FRAME_death112, chick_frames_death1, chick_dead};
346:
347: void chick_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
348: {
349: int n;
350:
351: // check for gib
352: if (self->health <= self->gib_health)
353: {
354: gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
355: for (n= 0; n < 2; n++)
356: ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
357: for (n= 0; n < 4; n++)
358: ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
359: ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
360: self->deadflag = DEAD_DEAD;
361: return;
362: }
363:
364: if (self->deadflag == DEAD_DEAD)
365: return;
366:
367: // regular death
368: self->deadflag = DEAD_DEAD;
369: self->takedamage = DAMAGE_YES;
370:
371: n = rand() % 2;
372: if (n == 0)
373: {
374: self->monsterinfo.currentmove = &chick_move_death1;
375: gi.sound (self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0);
376: }
377: else
378: {
379: self->monsterinfo.currentmove = &chick_move_death2;
380: gi.sound (self, CHAN_VOICE, sound_death2, 1, ATTN_NORM, 0);
381: }
382: }
383:
384: // PMM - changes to duck code for new dodge
385:
386: mframe_t chick_frames_duck [] =
387: {
388: ai_move, 0, monster_duck_down,
389: ai_move, 1, NULL,
390: ai_move, 4, monster_duck_hold,
391: ai_move, -4, NULL,
392: ai_move, -5, monster_duck_up,
393: ai_move, 3, NULL,
394: ai_move, 1, NULL
395: };
396: mmove_t chick_move_duck = {FRAME_duck01, FRAME_duck07, chick_frames_duck, chick_run};
397:
398: /*
399: void chick_dodge (edict_t *self, edict_t *attacker, float eta, trace_t *tr)
400: {
401: // begin orig code
402: if (random() > 0.25)
403: return;
404:
405: if (!self->enemy)
406: self->enemy = attacker;
407:
408: self->monsterinfo.currentmove = &chick_move_duck;
409: // end
410:
411: float r;
412: float height;
413: int shooting = 0;
414:
415: if (!self->enemy)
416: {
417: self->enemy = attacker;
418: FoundTarget (self);
419: }
420:
421: // PMM - don't bother if it's going to hit anyway; fix for weird in-your-face etas (I was
422: // seeing numbers like 13 and 14)
423: if ((eta < 0.1) || (eta > 5))
424: return;
425:
426: r = random();
427: if (r > (0.25*((skill->value)+1)))
428: return;
429:
430: if ((self->monsterinfo.currentmove == &chick_move_start_attack1) ||
431: (self->monsterinfo.currentmove == &chick_move_attack1))
432: {
433: shooting = 1;
434: }
435: if (self->monsterinfo.aiflags & AI_DODGING)
436: {
437: height = self->absmax[2];
438: }
439: else
440: {
441: height = self->absmax[2]-32-1; // the -1 is because the absmax is s.origin + maxs + 1
442: }
443:
444: // check to see if it makes sense to duck
445: if (tr->endpos[2] <= height)
446: {
447: vec3_t right, diff;
448: if (shooting)
449: {
450: self->monsterinfo.attack_state = AS_SLIDING;
451: return;
452: }
453: AngleVectors (self->s.angles, NULL, right, NULL);
454: VectorSubtract (tr->endpos, self->s.origin, diff);
455: if (DotProduct (right, diff) < 0)
456: {
457: self->monsterinfo.lefty = 1;
458: }
459: // if it doesn't sense to duck, try to strafe away
460: monster_done_dodge (self);
461: self->monsterinfo.currentmove = &chick_move_run;
462: self->monsterinfo.attack_state = AS_SLIDING;
463: return;
464: }
465:
466: if (skill->value == 0)
467: {
468: self->monsterinfo.currentmove = &chick_move_duck;
469: // PMM - stupid dodge
470: self->monsterinfo.duck_wait_time = level.time + eta + 1;
471: self->monsterinfo.aiflags |= AI_DODGING;
472: return;
473: }
474:
475: if (!shooting)
476: {
477: self->monsterinfo.currentmove = &chick_move_duck;
478: self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value));
479: self->monsterinfo.aiflags |= AI_DODGING;
480: }
481: return;
482:
483: }
484: */
485: void ChickSlash (edict_t *self)
486: {
487: vec3_t aim;
488:
489: VectorSet (aim, MELEE_DISTANCE, self->mins[0], 10);
490: gi.sound (self, CHAN_WEAPON, sound_melee_swing, 1, ATTN_NORM, 0);
491: fire_hit (self, aim, (10 + (rand() %6)), 100);
492: }
493:
494:
495: void ChickRocket (edict_t *self)
496: {
497: vec3_t forward, right;
498: vec3_t start;
499: vec3_t dir;
500: vec3_t vec;
501: trace_t trace; // PMM - check target
502: int rocketSpeed;
503: float dist;
504: // pmm - blindfire
505: vec3_t target;
506: qboolean blindfire = false;
507:
508: if (self->monsterinfo.aiflags & AI_MANUAL_STEERING)
509: blindfire = true;
510: else
511: blindfire = false;
512:
513: if(!self->enemy || !self->enemy->inuse) //PGM
514: return; //PGM
515:
516: AngleVectors (self->s.angles, forward, right, NULL);
517: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_CHICK_ROCKET_1], forward, right, start);
518:
519: rocketSpeed = 500 + (100 * skill->value); // PGM rock & roll.... :)
520:
521: // put a debug trail from start to endpoint, confirm that the start point is
522: // correct for the trace
523:
524: // PMM
525: if (blindfire)
526: VectorCopy (self->monsterinfo.blind_fire_target, target);
527: else
528: VectorCopy (self->enemy->s.origin, target);
529: // pmm
530: //PGM
531: // PMM - blindfire shooting
532: if (blindfire)
533: {
534: VectorCopy (target, vec);
535: VectorSubtract (vec, start, dir);
536: }
537: // pmm
538: // don't shoot at feet if they're above where i'm shooting from.
539: else if(random() < 0.33 || (start[2] < self->enemy->absmin[2]))
540: {
541: // gi.dprintf("normal shot\n");
542: VectorCopy (target, vec);
543: vec[2] += self->enemy->viewheight;
544: VectorSubtract (vec, start, dir);
545: }
546: else
547: {
548: // gi.dprintf("shooting at feet!\n");
549: VectorCopy (target, vec);
550: vec[2] = self->enemy->absmin[2];
551: VectorSubtract (vec, start, dir);
552: }
553: //PGM
554:
555: //======
556: //PMM - lead target (not when blindfiring)
557: // 20, 35, 50, 65 chance of leading
558: if((!blindfire) && ((random() < (0.2 + ((3 - skill->value) * 0.15)))))
559: {
560: float time;
561:
562: // gi.dprintf ("leading target\n");
563: dist = VectorLength (dir);
564: time = dist/rocketSpeed;
565: VectorMA(vec, time, self->enemy->velocity, vec);
566: VectorSubtract(vec, start, dir);
567: }
568: //PMM - lead target
569: //======
570:
571: VectorNormalize (dir);
572:
573: // pmm blindfire doesn't check target (done in checkattack)
574: // paranoia, make sure we're not shooting a target right next to us
575: trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT);
576: if (blindfire)
577: {
578: // blindfire has different fail criteria for the trace
579: if (!(trace.startsolid || trace.allsolid || (trace.fraction < 0.5)))
580: monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1);
581: else
582: {
583: // geez, this is bad. she's avoiding about 80% of her blindfires due to hitting things.
584: // hunt around for a good shot
585: // try shifting the target to the left a little (to help counter her large offset)
586: VectorCopy (target, vec);
587: VectorMA (vec, -10, right, vec);
588: VectorSubtract(vec, start, dir);
589: VectorNormalize (dir);
590: trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT);
591: if (!(trace.startsolid || trace.allsolid || (trace.fraction < 0.5)))
592: monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1);
593: else
594: {
595: // ok, that failed. try to the right
596: VectorCopy (target, vec);
597: VectorMA (vec, 10, right, vec);
598: VectorSubtract(vec, start, dir);
599: VectorNormalize (dir);
600: trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT);
601: if (!(trace.startsolid || trace.allsolid || (trace.fraction < 0.5)))
602: monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1);
603: else if ((g_showlogic) && (g_showlogic->value))
604: // ok, I give up
605: gi.dprintf ("chick avoiding blindfire shot\n");
606: }
607: }
608: }
609: else
610: {
611: trace = gi.trace(start, vec3_origin, vec3_origin, vec, self, MASK_SHOT);
612: if(trace.ent == self->enemy || trace.ent == world)
613: {
614: if(trace.fraction > 0.5 || (trace.ent && trace.ent->client))
615: monster_fire_rocket (self, start, dir, 50, rocketSpeed, MZ2_CHICK_ROCKET_1);
616: // else
617: // gi.dprintf("didn't make it halfway to target...aborting\n");
618: }
619: }
620: }
621:
622: void Chick_PreAttack1 (edict_t *self)
623: {
624: gi.sound (self, CHAN_VOICE, sound_missile_prelaunch, 1, ATTN_NORM, 0);
625: }
626:
627: void ChickReload (edict_t *self)
628: {
629: gi.sound (self, CHAN_VOICE, sound_missile_reload, 1, ATTN_NORM, 0);
630: }
631:
632:
633: mframe_t chick_frames_start_attack1 [] =
634: {
635: ai_charge, 0, Chick_PreAttack1,
636: ai_charge, 0, NULL,
637: ai_charge, 0, NULL,
638: ai_charge, 4, NULL,
639: ai_charge, 0, NULL,
640: ai_charge, -3, NULL,
641: ai_charge, 3, NULL,
642: ai_charge, 5, NULL,
643: ai_charge, 7, NULL,
644: ai_charge, 0, NULL,
645: ai_charge, 0, NULL,
646: ai_charge, 0, NULL,
647: ai_charge, 0, chick_attack1
648: };
649: mmove_t chick_move_start_attack1 = {FRAME_attak101, FRAME_attak113, chick_frames_start_attack1, NULL};
650:
651:
652: mframe_t chick_frames_attack1 [] =
653: {
654: ai_charge, 19, ChickRocket,
655: ai_charge, -6, NULL,
656: ai_charge, -5, NULL,
657: ai_charge, -2, NULL,
658: ai_charge, -7, NULL,
659: ai_charge, 0, NULL,
660: ai_charge, 1, NULL,
661: ai_charge, 10, ChickReload,
662: ai_charge, 4, NULL,
663: ai_charge, 5, NULL,
664: ai_charge, 6, NULL,
665: ai_charge, 6, NULL,
666: ai_charge, 4, NULL,
667: ai_charge, 3, chick_rerocket
668:
669: };
670: mmove_t chick_move_attack1 = {FRAME_attak114, FRAME_attak127, chick_frames_attack1, NULL};
671:
672: mframe_t chick_frames_end_attack1 [] =
673: {
674: ai_charge, -3, NULL,
675: ai_charge, 0, NULL,
676: ai_charge, -6, NULL,
677: ai_charge, -4, NULL,
678: ai_charge, -2, NULL
679: };
680: mmove_t chick_move_end_attack1 = {FRAME_attak128, FRAME_attak132, chick_frames_end_attack1, chick_run};
681:
682: void chick_rerocket(edict_t *self)
683: {
684: if (self->monsterinfo.aiflags & AI_MANUAL_STEERING)
685: {
686: self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING;
687: self->monsterinfo.currentmove = &chick_move_end_attack1;
688: return;
689: }
690: if (self->enemy->health > 0)
691: {
692: if (range (self, self->enemy) > RANGE_MELEE)
693: if ( visible (self, self->enemy) )
694: if (random() <= (0.6 + (0.05*((float)skill->value))))
695: {
696: self->monsterinfo.currentmove = &chick_move_attack1;
697: return;
698: }
699: }
700: self->monsterinfo.currentmove = &chick_move_end_attack1;
701: }
702:
703: void chick_attack1(edict_t *self)
704: {
705: self->monsterinfo.currentmove = &chick_move_attack1;
706: }
707:
708: mframe_t chick_frames_slash [] =
709: {
710: ai_charge, 1, NULL,
711: ai_charge, 7, ChickSlash,
712: ai_charge, -7, NULL,
713: ai_charge, 1, NULL,
714: ai_charge, -1, NULL,
715: ai_charge, 1, NULL,
716: ai_charge, 0, NULL,
717: ai_charge, 1, NULL,
718: ai_charge, -2, chick_reslash
719: };
720: mmove_t chick_move_slash = {FRAME_attak204, FRAME_attak212, chick_frames_slash, NULL};
721:
722: mframe_t chick_frames_end_slash [] =
723: {
724: ai_charge, -6, NULL,
725: ai_charge, -1, NULL,
726: ai_charge, -6, NULL,
727: ai_charge, 0, NULL
728: };
729: mmove_t chick_move_end_slash = {FRAME_attak213, FRAME_attak216, chick_frames_end_slash, chick_run};
730:
731:
732: void chick_reslash(edict_t *self)
733: {
734: if (self->enemy->health > 0)
735: {
736: if (range (self, self->enemy) == RANGE_MELEE)
737: if (random() <= 0.9)
738: {
739: self->monsterinfo.currentmove = &chick_move_slash;
740: return;
741: }
742: else
743: {
744: self->monsterinfo.currentmove = &chick_move_end_slash;
745: return;
746: }
747: }
748: self->monsterinfo.currentmove = &chick_move_end_slash;
749: }
750:
751: void chick_slash(edict_t *self)
752: {
753: self->monsterinfo.currentmove = &chick_move_slash;
754: }
755:
756:
757: mframe_t chick_frames_start_slash [] =
758: {
759: ai_charge, 1, NULL,
760: ai_charge, 8, NULL,
761: ai_charge, 3, NULL
762: };
763: mmove_t chick_move_start_slash = {FRAME_attak201, FRAME_attak203, chick_frames_start_slash, chick_slash};
764:
765:
766:
767: void chick_melee(edict_t *self)
768: {
769: self->monsterinfo.currentmove = &chick_move_start_slash;
770: }
771:
772:
773: void chick_attack(edict_t *self)
774: {
775: float r, chance;
776:
777: monster_done_dodge (self);
778:
779: // PMM
780: if (self->monsterinfo.attack_state == AS_BLIND)
781: {
782: // setup shot probabilities
783: if (self->monsterinfo.blind_fire_delay < 1.0)
784: chance = 1.0;
785: else if (self->monsterinfo.blind_fire_delay < 7.5)
786: chance = 0.4;
787: else
788: chance = 0.1;
789:
790: r = random();
791:
792: gi.dprintf ("chance = %2.2f, roll = %2.2f\n", chance, r);
793:
794: // minimum of 2 seconds, plus 0-3, after the shots are done
795: self->monsterinfo.blind_fire_delay += 4.0 + 1.5 + random();
796:
797: // don't shoot at the origin
798: if (VectorCompare (self->monsterinfo.blind_fire_target, vec3_origin))
799: return;
800:
801: // don't shoot if the dice say not to
802: if (r > chance)
803: {
804: if ((g_showlogic) && (g_showlogic->value))
805: gi.dprintf ("blindfire - NO SHOT\n");
806: return;
807: }
808:
809: // turn on manual steering to signal both manual steering and blindfire
810: self->monsterinfo.aiflags |= AI_MANUAL_STEERING;
811: self->monsterinfo.currentmove = &chick_move_start_attack1;
812: self->monsterinfo.attack_finished = level.time + 2*random();
813: return;
814: }
815: // pmm
816:
817: self->monsterinfo.currentmove = &chick_move_start_attack1;
818: }
819:
820: void chick_sight(edict_t *self, edict_t *other)
821: {
822: gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
823: }
824:
825: //===========
826: //PGM
827: qboolean chick_blocked (edict_t *self, float dist)
828: {
829: if(blocked_checkshot (self, 0.25 + (0.05 * skill->value) ))
830: return true;
831:
832: if(blocked_checkplat (self, dist))
833: return true;
834:
835: return false;
836: }
837: //PGM
838: //===========
839:
840: void chick_duck (edict_t *self, float eta)
841: {
842: if ((self->monsterinfo.currentmove == &chick_move_start_attack1) ||
843: (self->monsterinfo.currentmove == &chick_move_attack1))
844: {
845: // if we're shooting, and not on easy, don't dodge
846: if (skill->value)
847: {
848: self->monsterinfo.aiflags &= ~AI_DUCKED;
849: return;
850: }
851: }
852:
853: if (skill->value == 0)
854: // PMM - stupid dodge
855: self->monsterinfo.duck_wait_time = level.time + eta + 1;
856: else
857: self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value));
858:
859: // has to be done immediately otherwise she can get stuck
860: monster_duck_down(self);
861:
862: self->monsterinfo.nextframe = FRAME_duck01;
863: self->monsterinfo.currentmove = &chick_move_duck;
864: return;
865: }
866:
867: void chick_sidestep (edict_t *self)
868: {
869: if ((self->monsterinfo.currentmove == &chick_move_start_attack1) ||
870: (self->monsterinfo.currentmove == &chick_move_attack1))
871: {
872: // if we're shooting, and not on easy, don't dodge
873: if (skill->value)
874: {
875: self->monsterinfo.aiflags &= ~AI_DODGING;
876: return;
877: }
878: }
879:
880: if (self->monsterinfo.currentmove != &chick_move_run)
881: self->monsterinfo.currentmove = &chick_move_run;
882: }
883:
884: /*QUAKED monster_chick (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
885: */
886: void SP_monster_chick (edict_t *self)
887: {
888: if (deathmatch->value)
889: {
890: G_FreeEdict (self);
891: return;
892: }
893:
894: sound_missile_prelaunch = gi.soundindex ("chick/chkatck1.wav");
895: sound_missile_launch = gi.soundindex ("chick/chkatck2.wav");
896: sound_melee_swing = gi.soundindex ("chick/chkatck3.wav");
897: sound_melee_hit = gi.soundindex ("chick/chkatck4.wav");
898: sound_missile_reload = gi.soundindex ("chick/chkatck5.wav");
899: sound_death1 = gi.soundindex ("chick/chkdeth1.wav");
900: sound_death2 = gi.soundindex ("chick/chkdeth2.wav");
901: sound_fall_down = gi.soundindex ("chick/chkfall1.wav");
902: sound_idle1 = gi.soundindex ("chick/chkidle1.wav");
903: sound_idle2 = gi.soundindex ("chick/chkidle2.wav");
904: sound_pain1 = gi.soundindex ("chick/chkpain1.wav");
905: sound_pain2 = gi.soundindex ("chick/chkpain2.wav");
906: sound_pain3 = gi.soundindex ("chick/chkpain3.wav");
907: sound_sight = gi.soundindex ("chick/chksght1.wav");
908: sound_search = gi.soundindex ("chick/chksrch1.wav");
909:
910: self->movetype = MOVETYPE_STEP;
911: self->solid = SOLID_BBOX;
912: self->s.modelindex = gi.modelindex ("models/monsters/bitch2/tris.md2");
913: VectorSet (self->mins, -16, -16, 0);
914: VectorSet (self->maxs, 16, 16, 56);
915:
916: self->health = 175;
917: self->gib_health = -70;
918: self->mass = 200;
919:
920: self->pain = chick_pain;
921: self->die = chick_die;
922:
923: self->monsterinfo.stand = chick_stand;
924: self->monsterinfo.walk = chick_walk;
925: self->monsterinfo.run = chick_run;
926: // pmm
927: self->monsterinfo.dodge = M_MonsterDodge;
928: self->monsterinfo.duck = chick_duck;
929: self->monsterinfo.unduck = monster_duck_up;
930: self->monsterinfo.sidestep = chick_sidestep;
931: // self->monsterinfo.dodge = chick_dodge;
932: // pmm
933: self->monsterinfo.attack = chick_attack;
934: self->monsterinfo.melee = chick_melee;
935: self->monsterinfo.sight = chick_sight;
936: self->monsterinfo.blocked = chick_blocked; // PGM
937:
938: gi.linkentity (self);
939:
940: self->monsterinfo.currentmove = &chick_move_stand;
941: self->monsterinfo.scale = MODEL_SCALE;
942:
943: // PMM
944: self->monsterinfo.blindfire = true;
945: // pmm
946: walkmonster_start (self);
947: }
948:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.