|
|
1.1 root 1: /*
2: ==============================================================================
3:
4: flyer
5:
6: ==============================================================================
7: */
8:
9: #include "g_local.h"
10: #include "m_flyer.h"
11:
12: qboolean visible (edict_t *self, edict_t *other);
13:
14: static int nextmove; // Used for start/stop frames
15:
16: static int sound_sight;
17: static int sound_idle;
18: static int sound_pain1;
19: static int sound_pain2;
20: static int sound_slash;
21: static int sound_sproing;
22: static int sound_die;
23:
24:
25: void flyer_check_melee(edict_t *self);
26: void flyer_loop_melee (edict_t *self);
27: void flyer_melee (edict_t *self);
28: void flyer_setstart (edict_t *self);
29: void flyer_stand (edict_t *self);
30: void flyer_nextmove (edict_t *self);
31:
32: // ROGUE - kamikaze stuff
33: void flyer_kamikaze (edict_t *self);
34: void flyer_kamikaze_check (edict_t *self);
35: void flyer_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point);
36:
37: void showme1 (edict_t *self)
38: {
39: if (!self->dmg)
40: {
41: gi.dprintf ("straight - %d\n", self->monsterinfo.lefty);
42: self->dmg = 1;
43: }
44: }
45:
46: void showme2 (edict_t *self)
47: {
48: if (!self->dmg)
49: {
50: gi.dprintf ("strafe - %d\n", self->monsterinfo.lefty);
51: self->dmg = 1;
52: }
53: }
54:
55:
56: void flyer_sight (edict_t *self, edict_t *other)
57: {
58: gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
59: }
60:
61: void flyer_idle (edict_t *self)
62: {
63: gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
64: }
65:
66: void flyer_pop_blades (edict_t *self)
67: {
68: gi.sound (self, CHAN_VOICE, sound_sproing, 1, ATTN_NORM, 0);
69: }
70:
71:
72: mframe_t flyer_frames_stand [] =
73: {
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: ai_stand, 0, NULL,
81: ai_stand, 0, NULL,
82: ai_stand, 0, NULL,
83: ai_stand, 0, NULL,
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: 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: };
120: mmove_t flyer_move_stand = {FRAME_stand01, FRAME_stand45, flyer_frames_stand, NULL};
121:
122:
123: mframe_t flyer_frames_walk [] =
124: {
125: ai_walk, 5, NULL,
126: ai_walk, 5, NULL,
127: ai_walk, 5, NULL,
128: ai_walk, 5, NULL,
129: ai_walk, 5, NULL,
130: ai_walk, 5, NULL,
131: ai_walk, 5, NULL,
132: ai_walk, 5, NULL,
133: ai_walk, 5, NULL,
134: ai_walk, 5, NULL,
135: ai_walk, 5, NULL,
136: ai_walk, 5, NULL,
137: ai_walk, 5, NULL,
138: ai_walk, 5, NULL,
139: ai_walk, 5, NULL,
140: ai_walk, 5, NULL,
141: ai_walk, 5, NULL,
142: ai_walk, 5, NULL,
143: ai_walk, 5, NULL,
144: ai_walk, 5, NULL,
145: ai_walk, 5, NULL,
146: ai_walk, 5, NULL,
147: ai_walk, 5, NULL,
148: ai_walk, 5, NULL,
149: ai_walk, 5, NULL,
150: ai_walk, 5, NULL,
151: ai_walk, 5, NULL,
152: ai_walk, 5, NULL,
153: ai_walk, 5, NULL,
154: ai_walk, 5, NULL,
155: ai_walk, 5, NULL,
156: ai_walk, 5, NULL,
157: ai_walk, 5, NULL,
158: ai_walk, 5, NULL,
159: ai_walk, 5, NULL,
160: ai_walk, 5, NULL,
161: ai_walk, 5, NULL,
162: ai_walk, 5, NULL,
163: ai_walk, 5, NULL,
164: ai_walk, 5, NULL,
165: ai_walk, 5, NULL,
166: ai_walk, 5, NULL,
167: ai_walk, 5, NULL,
168: ai_walk, 5, NULL,
169: ai_walk, 5, NULL
170: };
171: mmove_t flyer_move_walk = {FRAME_stand01, FRAME_stand45, flyer_frames_walk, NULL};
172:
173: mframe_t flyer_frames_run [] =
174: {
175: ai_run, 10, NULL,
176: ai_run, 10, NULL,
177: ai_run, 10, NULL,
178: ai_run, 10, NULL,
179: ai_run, 10, NULL,
180: ai_run, 10, NULL,
181: ai_run, 10, NULL,
182: ai_run, 10, NULL,
183: ai_run, 10, NULL,
184: ai_run, 10, NULL,
185: ai_run, 10, NULL,
186: ai_run, 10, NULL,
187: ai_run, 10, NULL,
188: ai_run, 10, NULL,
189: ai_run, 10, NULL,
190: ai_run, 10, NULL,
191: ai_run, 10, NULL,
192: ai_run, 10, NULL,
193: ai_run, 10, NULL,
194: ai_run, 10, NULL,
195: ai_run, 10, NULL,
196: ai_run, 10, NULL,
197: ai_run, 10, NULL,
198: ai_run, 10, NULL,
199: ai_run, 10, NULL,
200: ai_run, 10, NULL,
201: ai_run, 10, NULL,
202: ai_run, 10, NULL,
203: ai_run, 10, NULL,
204: ai_run, 10, NULL,
205: ai_run, 10, NULL,
206: ai_run, 10, NULL,
207: ai_run, 10, NULL,
208: ai_run, 10, NULL,
209: ai_run, 10, NULL,
210: ai_run, 10, NULL,
211: ai_run, 10, NULL,
212: ai_run, 10, NULL,
213: ai_run, 10, NULL,
214: ai_run, 10, NULL,
215: ai_run, 10, NULL,
216: ai_run, 10, NULL,
217: ai_run, 10, NULL,
218: ai_run, 10, NULL,
219: ai_run, 10, NULL
220: };
221: mmove_t flyer_move_run = {FRAME_stand01, FRAME_stand45, flyer_frames_run, NULL};
222:
223: mframe_t flyer_frames_kamizake [] =
224: {
225: ai_charge, 40, flyer_kamikaze_check,
226: ai_charge, 40, flyer_kamikaze_check,
227: ai_charge, 40, flyer_kamikaze_check,
228: ai_charge, 40, flyer_kamikaze_check,
229: ai_charge, 40, flyer_kamikaze_check
230: };
231: mmove_t flyer_move_kamikaze = {FRAME_rollr02, FRAME_rollr06, flyer_frames_kamizake, flyer_kamikaze};
232:
233: void flyer_run (edict_t *self)
234: {
235: if (self->mass > 50)
236: self->monsterinfo.currentmove = &flyer_move_kamikaze;
237: else
238: if (self->monsterinfo.aiflags & AI_STAND_GROUND)
239: self->monsterinfo.currentmove = &flyer_move_stand;
240: else
241: self->monsterinfo.currentmove = &flyer_move_run;
242: }
243:
244: void flyer_walk (edict_t *self)
245: {
246: if (self->mass > 50)
247: flyer_run (self);
248: else
249: self->monsterinfo.currentmove = &flyer_move_walk;
250: }
251:
252: void flyer_stand (edict_t *self)
253: {
254: if (self->mass > 50)
255: flyer_run (self);
256: else
257: self->monsterinfo.currentmove = &flyer_move_stand;
258: }
259:
260: // ROGUE - kamikaze stuff
261:
262: void flyer_kamikaze_explode (edict_t *self)
263: {
264: vec3_t dir;
265:
266: if (self->monsterinfo.commander && self->monsterinfo.commander->inuse &&
267: !strcmp(self->monsterinfo.commander->classname, "monster_carrier"))
268: {
269: self->monsterinfo.commander->monsterinfo.monster_slots++;
270: if ((g_showlogic) && (g_showlogic->value))
271: gi.dprintf ("suicide hit!. %d slots left\n", self->monsterinfo.commander->monsterinfo.monster_slots);
272: }
273:
274: // gi.dprintf ("boom!\n");
275: // T_RadiusDamage(self, self->owner, 125, self, self->dmg_radius, MOD_NUKE);
276: // T_RadiusDamage(self, self->owner, 125, self, 150, MOD_NUKE);
277: if (self->enemy)
278: {
279: VectorSubtract (self->enemy->s.origin, self->s.origin, dir);
280: //void T_Damage (edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir, vec3_t point,
281: // vec3_t normal, int damage, int knockback, int dflags, int mod)
282: T_Damage (self->enemy, self, self, dir, self->s.origin, vec3_origin, (int)50, (int)50, DAMAGE_RADIUS, MOD_UNKNOWN);
283: }
284:
285: flyer_die (self, NULL, NULL, 0, dir);
286: /* VectorMA (self->s.origin, -0.02, self->velocity, origin);
287: gi.WriteByte (svc_temp_entity);
288: gi.WriteByte (TE_ROCKET_EXPLOSION);
289: gi.WritePosition (origin);
290: gi.multicast (self->s.origin, MULTICAST_PHS);
291:
292: G_FreeEdict (self);
293: */
294: }
295:
296: void flyer_kamikaze (edict_t *self)
297: {
298: self->monsterinfo.currentmove = &flyer_move_kamikaze;
299: }
300:
301: void flyer_kamikaze_check (edict_t *self)
302: {
303: float dist;
304:
305: // PMM - this needed because we could have gone away before we get here (blocked code)
306: if (!self->inuse)
307: return;
308:
309: if ((!self->enemy) || (!self->enemy->inuse))
310: {
311: flyer_kamikaze_explode (self);
312: return;
313: }
314:
315: self->goalentity = self->enemy;
316:
317: dist = realrange (self, self->enemy);
318:
319: if (dist < 90)
320: flyer_kamikaze_explode (self);
321: }
322:
323: // rogue - kamikaze
324:
325: mframe_t flyer_frames_start [] =
326: {
327: ai_move, 0, NULL,
328: ai_move, 0, NULL,
329: ai_move, 0, NULL,
330: ai_move, 0, NULL,
331: ai_move, 0, NULL,
332: ai_move, 0, flyer_nextmove
333: };
334: mmove_t flyer_move_start = {FRAME_start01, FRAME_start06, flyer_frames_start, NULL};
335:
336: mframe_t flyer_frames_stop [] =
337: {
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: ai_move, 0, NULL,
344: ai_move, 0, flyer_nextmove
345: };
346: mmove_t flyer_move_stop = {FRAME_stop01, FRAME_stop07, flyer_frames_stop, NULL};
347:
348: void flyer_stop (edict_t *self)
349: {
350: self->monsterinfo.currentmove = &flyer_move_stop;
351: }
352:
353: void flyer_start (edict_t *self)
354: {
355: self->monsterinfo.currentmove = &flyer_move_start;
356: }
357:
358:
359: mframe_t flyer_frames_rollright [] =
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: };
371: mmove_t flyer_move_rollright = {FRAME_rollr01, FRAME_rollr09, flyer_frames_rollright, NULL};
372:
373: mframe_t flyer_frames_rollleft [] =
374: {
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: };
385: mmove_t flyer_move_rollleft = {FRAME_rollf01, FRAME_rollf09, flyer_frames_rollleft, NULL};
386:
387: mframe_t flyer_frames_pain3 [] =
388: {
389: ai_move, 0, NULL,
390: ai_move, 0, NULL,
391: ai_move, 0, NULL,
392: ai_move, 0, NULL
393: };
394: mmove_t flyer_move_pain3 = {FRAME_pain301, FRAME_pain304, flyer_frames_pain3, flyer_run};
395:
396: mframe_t flyer_frames_pain2 [] =
397: {
398: ai_move, 0, NULL,
399: ai_move, 0, NULL,
400: ai_move, 0, NULL,
401: ai_move, 0, NULL
402: };
403: mmove_t flyer_move_pain2 = {FRAME_pain201, FRAME_pain204, flyer_frames_pain2, flyer_run};
404:
405: mframe_t flyer_frames_pain1 [] =
406: {
407: ai_move, 0, NULL,
408: ai_move, 0, NULL,
409: ai_move, 0, NULL,
410: ai_move, 0, NULL,
411: ai_move, 0, NULL,
412: ai_move, 0, NULL,
413: ai_move, 0, NULL,
414: ai_move, 0, NULL,
415: ai_move, 0, NULL
416: };
417: mmove_t flyer_move_pain1 = {FRAME_pain101, FRAME_pain109, flyer_frames_pain1, flyer_run};
418:
419: mframe_t flyer_frames_defense [] =
420: {
421: ai_move, 0, NULL,
422: ai_move, 0, NULL,
423: ai_move, 0, NULL, // Hold this frame
424: ai_move, 0, NULL,
425: ai_move, 0, NULL,
426: ai_move, 0, NULL
427: };
428: mmove_t flyer_move_defense = {FRAME_defens01, FRAME_defens06, flyer_frames_defense, NULL};
429:
430: mframe_t flyer_frames_bankright [] =
431: {
432: ai_move, 0, NULL,
433: ai_move, 0, NULL,
434: ai_move, 0, NULL,
435: ai_move, 0, NULL,
436: ai_move, 0, NULL,
437: ai_move, 0, NULL,
438: ai_move, 0, NULL
439: };
440: mmove_t flyer_move_bankright = {FRAME_bankr01, FRAME_bankr07, flyer_frames_bankright, NULL};
441:
442: mframe_t flyer_frames_bankleft [] =
443: {
444: ai_move, 0, NULL,
445: ai_move, 0, NULL,
446: ai_move, 0, NULL,
447: ai_move, 0, NULL,
448: ai_move, 0, NULL,
449: ai_move, 0, NULL,
450: ai_move, 0, NULL
451: };
452: mmove_t flyer_move_bankleft = {FRAME_bankl01, FRAME_bankl07, flyer_frames_bankleft, NULL};
453:
454:
455: void flyer_fire (edict_t *self, int flash_number)
456: {
457: vec3_t start;
458: vec3_t forward, right;
459: vec3_t end;
460: vec3_t dir;
461: int effect;
462:
463: if(!self->enemy || !self->enemy->inuse) //PGM
464: return; //PGM
465:
466: if ((self->s.frame == FRAME_attak204) || (self->s.frame == FRAME_attak207) || (self->s.frame == FRAME_attak210))
467: effect = EF_HYPERBLASTER;
468: else
469: effect = 0;
470: AngleVectors (self->s.angles, forward, right, NULL);
471: G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
472:
473: VectorCopy (self->enemy->s.origin, end);
474: end[2] += self->enemy->viewheight;
475: VectorSubtract (end, start, dir);
476:
477: monster_fire_blaster (self, start, dir, 1, 1000, flash_number, effect);
478: }
479:
480: void flyer_fireleft (edict_t *self)
481: {
482: flyer_fire (self, MZ2_FLYER_BLASTER_1);
483: }
484:
485: void flyer_fireright (edict_t *self)
486: {
487: flyer_fire (self, MZ2_FLYER_BLASTER_2);
488: }
489:
490:
491: mframe_t flyer_frames_attack2 [] =
492: {
493: ai_charge, 0, NULL,
494: ai_charge, 0, NULL,
495: ai_charge, 0, NULL,
496: ai_charge, -10, flyer_fireleft, // left gun
497: ai_charge, -10, flyer_fireright, // right gun
498: ai_charge, -10, flyer_fireleft, // left gun
499: ai_charge, -10, flyer_fireright, // right gun
500: ai_charge, -10, flyer_fireleft, // left gun
501: ai_charge, -10, flyer_fireright, // right gun
502: ai_charge, -10, flyer_fireleft, // left gun
503: ai_charge, -10, flyer_fireright, // right gun
504: ai_charge, 0, NULL,
505: ai_charge, 0, NULL,
506: ai_charge, 0, NULL,
507: ai_charge, 0, NULL,
508: ai_charge, 0, NULL,
509: ai_charge, 0, NULL
510: };
511: mmove_t flyer_move_attack2 = {FRAME_attak201, FRAME_attak217, flyer_frames_attack2, flyer_run};
512:
513: // PMM
514: // circle strafe frames
515:
516: mframe_t flyer_frames_attack3 [] =
517: {
518: ai_charge, 10, NULL,
519: ai_charge, 10, NULL,
520: ai_charge, 10, NULL,
521: ai_charge, 10, flyer_fireleft, // left gun
522: ai_charge, 10, flyer_fireright, // right gun
523: ai_charge, 10, flyer_fireleft, // left gun
524: ai_charge, 10, flyer_fireright, // right gun
525: ai_charge, 10, flyer_fireleft, // left gun
526: ai_charge, 10, flyer_fireright, // right gun
527: ai_charge, 10, flyer_fireleft, // left gun
528: ai_charge, 10, flyer_fireright, // right gun
529: ai_charge, 10, NULL,
530: ai_charge, 10, NULL,
531: ai_charge, 10, NULL,
532: ai_charge, 10, NULL,
533: ai_charge, 10, NULL,
534: ai_charge, 10, NULL
535: };
536: mmove_t flyer_move_attack3 = {FRAME_attak201, FRAME_attak217, flyer_frames_attack3, flyer_run};
537: // pmm
538:
539: void flyer_slash_left (edict_t *self)
540: {
541: vec3_t aim;
542:
543: VectorSet (aim, MELEE_DISTANCE, self->mins[0], 0);
544: fire_hit (self, aim, 5, 0);
545: gi.sound (self, CHAN_WEAPON, sound_slash, 1, ATTN_NORM, 0);
546: }
547:
548: void flyer_slash_right (edict_t *self)
549: {
550: vec3_t aim;
551:
552: VectorSet (aim, MELEE_DISTANCE, self->maxs[0], 0);
553: fire_hit (self, aim, 5, 0);
554: gi.sound (self, CHAN_WEAPON, sound_slash, 1, ATTN_NORM, 0);
555: }
556:
557: mframe_t flyer_frames_start_melee [] =
558: {
559: ai_charge, 0, flyer_pop_blades,
560: ai_charge, 0, NULL,
561: ai_charge, 0, NULL,
562: ai_charge, 0, NULL,
563: ai_charge, 0, NULL,
564: ai_charge, 0, NULL
565: };
566: mmove_t flyer_move_start_melee = {FRAME_attak101, FRAME_attak106, flyer_frames_start_melee, flyer_loop_melee};
567:
568: mframe_t flyer_frames_end_melee [] =
569: {
570: ai_charge, 0, NULL,
571: ai_charge, 0, NULL,
572: ai_charge, 0, NULL
573: };
574: mmove_t flyer_move_end_melee = {FRAME_attak119, FRAME_attak121, flyer_frames_end_melee, flyer_run};
575:
576:
577: mframe_t flyer_frames_loop_melee [] =
578: {
579: ai_charge, 0, NULL, // Loop Start
580: ai_charge, 0, NULL,
581: ai_charge, 0, flyer_slash_left, // Left Wing Strike
582: ai_charge, 0, NULL,
583: ai_charge, 0, NULL,
584: ai_charge, 0, NULL,
585: ai_charge, 0, NULL,
586: ai_charge, 0, flyer_slash_right, // Right Wing Strike
587: ai_charge, 0, NULL,
588: ai_charge, 0, NULL,
589: ai_charge, 0, NULL,
590: ai_charge, 0, NULL // Loop Ends
591:
592: };
593: mmove_t flyer_move_loop_melee = {FRAME_attak107, FRAME_attak118, flyer_frames_loop_melee, flyer_check_melee};
594:
595: void flyer_loop_melee (edict_t *self)
596: {
597: /* if (random() <= 0.5)
598: self->monsterinfo.currentmove = &flyer_move_attack1;
599: else */
600: self->monsterinfo.currentmove = &flyer_move_loop_melee;
601: }
602:
603:
604:
605: void flyer_attack (edict_t *self)
606: {
607: float chance;
608: /* if (random() <= 0.5)
609: self->monsterinfo.currentmove = &flyer_move_attack1;
610: else */
611: // 0% chance of circle in easy
612: // 50% chance in normal
613: // 75% chance in hard
614: // 86.67% chance in nightmare
615:
616: if (self->mass > 50)
617: {
618: flyer_run (self);
619: return;
620: }
621:
622: if (!skill->value)
623: chance = 0;
624: else
625: chance = 1.0 - (0.5/(float)(skill->value));
626:
627: if (random() > chance)
628: {
629: self->monsterinfo.attack_state = AS_STRAIGHT;
630: self->monsterinfo.currentmove = &flyer_move_attack2;
631: }
632: else // circle strafe
633: {
634: if (random () <= 0.5) // switch directions
635: self->monsterinfo.lefty = 1 - self->monsterinfo.lefty;
636: self->monsterinfo.attack_state = AS_SLIDING;
637: self->monsterinfo.currentmove = &flyer_move_attack3;
638: }
639: }
640:
641: void flyer_setstart (edict_t *self)
642: {
643: nextmove = ACTION_run;
644: self->monsterinfo.currentmove = &flyer_move_start;
645: }
646:
647: void flyer_nextmove (edict_t *self)
648: {
649: if (nextmove == ACTION_attack1)
650: self->monsterinfo.currentmove = &flyer_move_start_melee;
651: else if (nextmove == ACTION_attack2)
652: self->monsterinfo.currentmove = &flyer_move_attack2;
653: else if (nextmove == ACTION_run)
654: self->monsterinfo.currentmove = &flyer_move_run;
655: }
656:
657: void flyer_melee (edict_t *self)
658: {
659: // flyer.nextmove = ACTION_attack1;
660: // self->monsterinfo.currentmove = &flyer_move_stop;
661: if (self->mass > 50)
662: flyer_run (self);
663: else
664: self->monsterinfo.currentmove = &flyer_move_start_melee;
665: }
666:
667: void flyer_check_melee(edict_t *self)
668: {
669: if (range (self, self->enemy) == RANGE_MELEE)
670: if (random() <= 0.8)
671: self->monsterinfo.currentmove = &flyer_move_loop_melee;
672: else
673: self->monsterinfo.currentmove = &flyer_move_end_melee;
674: else
675: self->monsterinfo.currentmove = &flyer_move_end_melee;
676: }
677:
678: void flyer_pain (edict_t *self, edict_t *other, float kick, int damage)
679: {
680: int n;
681:
682: // pmm - kamikaze's don't feel pain
683: if (self->mass != 50)
684: return;
685: // pmm
686:
687: if (self->health < (self->max_health / 2))
688: self->s.skinnum = 1;
689:
690: if (level.time < self->pain_debounce_time)
691: return;
692:
693: self->pain_debounce_time = level.time + 3;
694: if (skill->value == 3)
695: return; // no pain anims in nightmare
696:
697: n = rand() % 3;
698: if (n == 0)
699: {
700: gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
701: self->monsterinfo.currentmove = &flyer_move_pain1;
702: }
703: else if (n == 1)
704: {
705: gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
706: self->monsterinfo.currentmove = &flyer_move_pain2;
707: }
708: else
709: {
710: gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
711: self->monsterinfo.currentmove = &flyer_move_pain3;
712: }
713: }
714:
715:
716: void flyer_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
717: {
718: gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0);
719: BecomeExplosion1(self);
720: }
721:
722: // PMM - kamikaze code .. blow up if blocked
723: int flyer_blocked (edict_t *self, float dist)
724: {
725: vec3_t origin;
726:
727: // kamikaze = 100, normal = 50
728: if (self->mass == 100)
729: {
730: flyer_kamikaze_check(self);
731:
732: // if the above didn't blow us up (i.e. I got blocked by the player)
733: if (self->inuse)
734: {
735: if (self->monsterinfo.commander && self->monsterinfo.commander->inuse &&
736: !strcmp(self->monsterinfo.commander->classname, "monster_carrier"))
737: {
738: self->monsterinfo.commander->monsterinfo.monster_slots++;
739: if ((g_showlogic) && (g_showlogic->value))
740: gi.dprintf ("suicide blocked, exploding. %d slots left\n", self->monsterinfo.commander->monsterinfo.monster_slots);
741: }
742:
743: VectorMA (self->s.origin, -0.02, self->velocity, origin);
744: gi.WriteByte (svc_temp_entity);
745: gi.WriteByte (TE_ROCKET_EXPLOSION);
746: gi.WritePosition (origin);
747: gi.multicast (self->s.origin, MULTICAST_PHS);
748:
749: G_FreeEdict (self);
750: }
751: return true;
752: }
753: // we're a normal flyer
754: if(blocked_checkshot (self, 0.25 + (0.05 * skill->value) ))
755: return true;
756:
757: return false;
758: }
759:
760: /*QUAKED monster_flyer (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
761: */
762: void SP_monster_flyer (edict_t *self)
763: {
764: if (deathmatch->value)
765: {
766: G_FreeEdict (self);
767: return;
768: }
769:
770: // fix a map bug in jail5.bsp
771: if (!Q_stricmp(level.mapname, "jail5") && (self->s.origin[2] == -104))
772: {
773: self->targetname = self->target;
774: self->target = NULL;
775: }
776:
777: sound_sight = gi.soundindex ("flyer/flysght1.wav");
778: sound_idle = gi.soundindex ("flyer/flysrch1.wav");
779: sound_pain1 = gi.soundindex ("flyer/flypain1.wav");
780: sound_pain2 = gi.soundindex ("flyer/flypain2.wav");
781: sound_slash = gi.soundindex ("flyer/flyatck2.wav");
782: sound_sproing = gi.soundindex ("flyer/flyatck1.wav");
783: sound_die = gi.soundindex ("flyer/flydeth1.wav");
784:
785: gi.soundindex ("flyer/flyatck3.wav");
786:
787: self->s.modelindex = gi.modelindex ("models/monsters/flyer/tris.md2");
788: VectorSet (self->mins, -16, -16, -24);
789: // PMM - shortened to 16 from 32
790: VectorSet (self->maxs, 16, 16, 16);
791: self->movetype = MOVETYPE_STEP;
792: self->solid = SOLID_BBOX;
793:
794: self->s.sound = gi.soundindex ("flyer/flyidle1.wav");
795:
796: self->health = 50;
797: self->mass = 50;
798:
799: self->pain = flyer_pain;
800: self->die = flyer_die;
801:
802: self->monsterinfo.stand = flyer_stand;
803: self->monsterinfo.walk = flyer_walk;
804: self->monsterinfo.run = flyer_run;
805: self->monsterinfo.attack = flyer_attack;
806: self->monsterinfo.melee = flyer_melee;
807: self->monsterinfo.sight = flyer_sight;
808: self->monsterinfo.idle = flyer_idle;
809: self->monsterinfo.blocked = flyer_blocked;
810:
811: gi.linkentity (self);
812:
813: self->monsterinfo.currentmove = &flyer_move_stand;
814: self->monsterinfo.scale = MODEL_SCALE;
815:
816: flymonster_start (self);
817: }
818:
819: // PMM - suicide fliers
820: void SP_monster_kamikaze (edict_t *self)
821: {
822: if (deathmatch->value)
823: {
824: G_FreeEdict (self);
825: return;
826: }
827:
828: sound_sight = gi.soundindex ("flyer/flysght1.wav");
829: sound_idle = gi.soundindex ("flyer/flysrch1.wav");
830: sound_pain1 = gi.soundindex ("flyer/flypain1.wav");
831: sound_pain2 = gi.soundindex ("flyer/flypain2.wav");
832: sound_slash = gi.soundindex ("flyer/flyatck2.wav");
833: sound_sproing = gi.soundindex ("flyer/flyatck1.wav");
834: sound_die = gi.soundindex ("flyer/flydeth1.wav");
835:
836: gi.soundindex ("flyer/flyatck3.wav");
837:
838: self->s.modelindex = gi.modelindex ("models/monsters/flyer/tris.md2");
839: VectorSet (self->mins, -16, -16, -24);
840: // used to be 32 tall .. was WAY too big
841: VectorSet (self->maxs, 16, 16, 16);
842: self->movetype = MOVETYPE_STEP;
843: self->solid = SOLID_BBOX;
844:
845: self->s.sound = gi.soundindex ("flyer/flyidle1.wav");
846:
847: self->s.effects |= EF_ROCKET;
848:
849: self->health = 50;
850: // PMM - normal flyer has mass of 50
851: self->mass = 100;
852:
853: self->pain = flyer_pain;
854: self->die = flyer_die;
855:
856: self->monsterinfo.stand = flyer_stand;
857: self->monsterinfo.walk = flyer_walk;
858: self->monsterinfo.run = flyer_run;
859: self->monsterinfo.attack = flyer_attack;
860: self->monsterinfo.melee = flyer_melee;
861: self->monsterinfo.sight = flyer_sight;
862: self->monsterinfo.idle = flyer_idle;
863:
864: self->monsterinfo.blocked = flyer_blocked;
865:
866: gi.linkentity (self);
867:
868: self->monsterinfo.currentmove = &flyer_move_stand;
869: self->monsterinfo.scale = MODEL_SCALE;
870:
871: flymonster_start (self);
872: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.