|
|
1.1 root 1: /*
2: xatrix
3: gekk.c
4: */
5:
6: #include "g_local.h"
7: #include "m_gekk.h"
8:
9: static int sound_swing;
10: static int sound_hit;
11: static int sound_hit2;
12: static int sound_death;
13: static int sound_pain1;
14: static int sound_sight;
15: static int sound_search;
16: static int sound_step1;
17: static int sound_step2;
18: static int sound_step3;
19: static int sound_thud;
20: static int sound_chantlow;
21: static int sound_chantmid;
22: static int sound_chanthigh;
23:
24: void gekk_swim (edict_t *self);
25:
26: extern void gekk_jump_takeoff (edict_t *self);
27: extern void gekk_jump_takeoff2 (edict_t *self);
28: extern void gekk_check_landing (edict_t *self);
29: extern void gekk_check_landing2 (edict_t *self);
30: extern void gekk_stop_skid (edict_t *self);
31:
32: extern void water_to_land (edict_t *self);
33: extern void land_to_water (edict_t *self);
34:
35: extern void gekk_check_underwater (edict_t *self);
36: extern void gekk_bite (edict_t *self);
37:
38: extern void gekk_hit_left (edict_t *self);
39: extern void gekk_hit_right (edict_t *self);
40: extern void gekk_run_start (edict_t *self);
41:
42: extern mmove_t gekk_move_attack1;
43: extern mmove_t gekk_move_attack2;
44: extern mmove_t gekk_move_chant;
45: extern mmove_t gekk_move_swim_start;
46: extern mmove_t gekk_move_swim_loop;
47: extern mmove_t gekk_move_spit;
48: extern mmove_t gekk_move_run_start;
49:
50: extern qboolean gekk_check_jump (edict_t *self);
51:
52: //
53: // CHECKATTACK
54: //
55:
56: qboolean gekk_check_melee (edict_t *self)
57: {
58: if (!self->enemy && self->enemy->health <= 0)
59: return false;
60:
61: if (range (self, self->enemy) == RANGE_MELEE)
62: return true;
63: return false;
64: }
65:
66: qboolean gekk_check_jump (edict_t *self)
67: {
68: vec3_t v;
69: float distance;
70:
71: if (self->absmin[2] > (self->enemy->absmin[2] + 0.75 * self->enemy->size[2]))
72: return false;
73:
74: if (self->absmax[2] < (self->enemy->absmin[2] + 0.25 * self->enemy->size[2]))
75: return false;
76:
77: v[0] = self->s.origin[0] - self->enemy->s.origin[0];
78: v[1] = self->s.origin[1] - self->enemy->s.origin[1];
79: v[2] = 0;
80: distance = VectorLength(v);
81:
82: if (distance < 100)
83: {
84: return false;
85: }
86: if (distance > 100)
87: {
88: if (random() < 0.9)
89: return false;
90: }
91:
92: return true;
93: }
94:
95: qboolean gekk_check_jump_close (edict_t *self)
96: {
97: vec3_t v;
98: float distance;
99:
100: v[0] = self->s.origin[0] - self->enemy->s.origin[0];
101: v[1] = self->s.origin[1] - self->enemy->s.origin[1];
102: v[2] = 0;
103:
104: distance = VectorLength(v);
105:
106: if (distance < 100)
107: {
108: if (self->s.origin[2] < self->enemy->s.origin[2])
109: return true;
110: else
111: return false;
112: }
113:
114: return true;
115: }
116:
117:
118: qboolean gekk_checkattack (edict_t *self)
119: {
120: if (!self->enemy || self->enemy->health <= 0)
121: return false;
122:
123: if (gekk_check_melee(self))
124: {
125: self->monsterinfo.attack_state = AS_MELEE;
126: return true;
127: }
128:
129: if (gekk_check_jump(self))
130: {
131: self->monsterinfo.attack_state = AS_MISSILE;
132: return true;
133: }
134:
135: if (gekk_check_jump_close (self) && !self->waterlevel)
136: {
137: self->monsterinfo.attack_state = AS_MISSILE;
138: return true;
139: }
140:
141: return false;
142: }
143:
144:
145: //
146: // SOUNDS
147: //
148:
149: void gekk_step (edict_t *self)
150: {
151: int n;
152: n = (rand() + 1) % 3;
153: if (n == 0)
154: gi.sound (self, CHAN_VOICE, sound_step1, 1, ATTN_NORM, 0);
155: else if (n == 1)
156: gi.sound (self, CHAN_VOICE, sound_step2, 1, ATTN_NORM, 0);
157: else
158: gi.sound (self, CHAN_VOICE, sound_step3, 1, ATTN_NORM, 0);
159: }
160:
161: void gekk_sight (edict_t *self, edict_t *other)
162: {
163: gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
164: }
165:
166: void gekk_search (edict_t *self)
167: {
168: float r;
169:
170: if (self->spawnflags & 8)
171: {
172: r = random();
173: if (r < 0.33)
174: gi.sound (self, CHAN_VOICE, sound_chantlow, 1, ATTN_NORM, 0);
175: else if (r < 0.66)
176: gi.sound (self, CHAN_VOICE, sound_chantmid, 1, ATTN_NORM, 0);
177: else
178: gi.sound (self, CHAN_VOICE, sound_chanthigh, 1, ATTN_NORM, 0);
179: }
180: else
181: gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0);
182:
183:
184: self->health += 10 + (10 * random());
185: if (self->health > self->max_health)
186: self->health = self->max_health;
187:
188: if (self->health < (self->max_health /4))
189: self->s.skinnum = 2;
190: else if (self->health < (self->max_health / 2))
191: self->s.skinnum = 1;
192: else
193: self->s.skinnum = 0;
194: }
195:
196: void gekk_swing (edict_t *self)
197: {
198: gi.sound (self, CHAN_VOICE, sound_swing, 1, ATTN_NORM, 0);
199: }
200:
201: extern mmove_t gekk_move_run;
202: void gekk_face (edict_t *self)
203: {
204: self->monsterinfo.currentmove = &gekk_move_run;
205: }
206:
207: //
208: // STAND
209: //
210:
211: void ai_stand2 (edict_t *self, float dist)
212: {
213: if (self->spawnflags & 8)
214: {
215: ai_move (self, dist);
216: if (!(self->spawnflags & 1) && (self->monsterinfo.idle) && (level.time > self->monsterinfo.idle_time))
217: {
218: if (self->monsterinfo.idle_time)
219: {
220: self->monsterinfo.idle (self);
221: self->monsterinfo.idle_time = level.time + 15 + random() * 15;
222: }
223: else
224: {
225: self->monsterinfo.idle_time = level.time + random() * 15;
226: }
227: }
228: }
229: else
230: ai_stand (self, dist);
231: }
232:
233: mframe_t gekk_frames_stand [] =
234: {
235: ai_stand2, 0, NULL,
236: ai_stand2, 0, NULL,
237: ai_stand2, 0, NULL,
238: ai_stand2, 0, NULL,
239: ai_stand2, 0, NULL,
240: ai_stand2, 0, NULL,
241: ai_stand2, 0, NULL,
242: ai_stand2, 0, NULL,
243: ai_stand2, 0, NULL,
244: ai_stand2, 0, NULL, // 10
245:
246: ai_stand2, 0, NULL,
247: ai_stand2, 0, NULL,
248: ai_stand2, 0, NULL,
249: ai_stand2, 0, NULL,
250: ai_stand2, 0, NULL,
251: ai_stand2, 0, NULL,
252: ai_stand2, 0, NULL,
253: ai_stand2, 0, NULL,
254: ai_stand2, 0, NULL,
255: ai_stand2, 0, NULL, // 20
256:
257: ai_stand2, 0, NULL,
258: ai_stand2, 0, NULL,
259: ai_stand2, 0, NULL,
260: ai_stand2, 0, NULL,
261: ai_stand2, 0, NULL,
262: ai_stand2, 0, NULL,
263: ai_stand2, 0, NULL,
264: ai_stand2, 0, NULL,
265: ai_stand2, 0, NULL,
266: ai_stand2, 0, NULL, // 30
267:
268: ai_stand2, 0, NULL,
269: ai_stand2, 0, NULL,
270: ai_stand2, 0, NULL,
271: ai_stand2, 0, NULL,
272: ai_stand2, 0, NULL,
273: ai_stand2, 0, NULL,
274: ai_stand2, 0, NULL,
275: ai_stand2, 0, NULL,
276:
277: ai_stand2, 0, gekk_check_underwater,
278: };
279: mmove_t gekk_move_stand = {FRAME_stand_01, FRAME_stand_39, gekk_frames_stand, NULL};
280:
281: mframe_t gekk_frames_standunderwater[] =
282: {
283: ai_stand2, 0, NULL,
284: ai_stand2, 0, NULL,
285: ai_stand2, 0, NULL,
286:
287: ai_stand2, 0, gekk_check_underwater
288: };
289:
290: mmove_t gekk_move_standunderwater = {FRAME_amb_01, FRAME_amb_04, gekk_frames_standunderwater, NULL};
291:
292:
293: void gekk_swim_loop (edict_t *self)
294: {
295: self->flags |= FL_SWIM;
296: self->monsterinfo.currentmove = &gekk_move_swim_loop;
297: }
298:
299: mframe_t gekk_frames_swim [] =
300: {
301: ai_run, 16, NULL,
302: ai_run, 16, NULL,
303: ai_run, 16, NULL,
304:
305: ai_run, 16, gekk_swim
306: };
307: mmove_t gekk_move_swim_loop = {FRAME_amb_01, FRAME_amb_04, gekk_frames_swim, gekk_swim_loop};
308:
309: mframe_t gekk_frames_swim_start [] =
310: {
311: ai_run, 14, NULL,
312: ai_run, 14, NULL,
313: ai_run, 14, NULL,
314: ai_run, 14, NULL,
315: ai_run, 16, NULL,
316: ai_run, 16, NULL,
317: ai_run, 16, NULL,
318: ai_run, 18, NULL,
319: ai_run, 18, gekk_hit_left,
320: ai_run, 18, NULL,
321:
322: ai_run, 20, NULL,
323: ai_run, 20, NULL,
324: ai_run, 22, NULL,
325: ai_run, 22, NULL,
326: ai_run, 24, gekk_hit_right,
327: ai_run, 24, NULL,
328: ai_run, 26, NULL,
329: ai_run, 26, NULL,
330: ai_run, 24, NULL,
331: ai_run, 24, NULL,
332:
333: ai_run, 22, gekk_bite,
334: ai_run, 22, NULL,
335: ai_run, 22, NULL,
336: ai_run, 22, NULL,
337: ai_run, 22, NULL,
338: ai_run, 22, NULL,
339: ai_run, 22, NULL,
340: ai_run, 22, NULL,
341: ai_run, 18, NULL,
342: ai_run, 18, NULL,
343:
344: ai_run, 18, NULL,
345: ai_run, 18, NULL
346: };
347: mmove_t gekk_move_swim_start = {FRAME_swim_01, FRAME_swim_32, gekk_frames_swim_start, gekk_swim_loop};
348:
349: void gekk_swim (edict_t *self)
350: {
351:
352: if (gekk_checkattack)
353: if (!self->enemy->waterlevel && random() > 0.7)
354: water_to_land (self);
355: else
356: self->monsterinfo.currentmove = &gekk_move_swim_start;
357: }
358:
359:
360: void gekk_stand (edict_t *self)
361: {
362: if (self->waterlevel)
363: self->monsterinfo.currentmove = &gekk_move_standunderwater;
364: else
365: self->monsterinfo.currentmove = &gekk_move_stand;
366: }
367:
368: void gekk_chant (edict_t *self)
369: {
370: self->monsterinfo.currentmove = &gekk_move_chant;
371: }
372:
373: //
374: // IDLE
375: //
376:
377: void gekk_idle_loop (edict_t *self)
378: {
379: if (random() > 0.75 && self->health < self->max_health)
380: self->monsterinfo.nextframe = FRAME_idle_01;
381: }
382:
383: mframe_t gekk_frames_idle [] =
384: {
385: ai_stand2, 0, gekk_search,
386: ai_stand2, 0, NULL,
387: ai_stand2, 0, NULL,
388: ai_stand2, 0, NULL,
389: ai_stand2, 0, NULL,
390: ai_stand2, 0, NULL,
391: ai_stand2, 0, NULL,
392: ai_stand2, 0, NULL,
393: ai_stand2, 0, NULL,
394: ai_stand2, 0, NULL,
395:
396: ai_stand2, 0, NULL,
397: ai_stand2, 0, NULL,
398: ai_stand2, 0, NULL,
399: ai_stand2, 0, NULL,
400: ai_stand2, 0, NULL,
401: ai_stand2, 0, NULL,
402: ai_stand2, 0, NULL,
403: ai_stand2, 0, NULL,
404: ai_stand2, 0, NULL,
405: ai_stand2, 0, NULL,
406:
407: ai_stand2, 0, NULL,
408: ai_stand2, 0, NULL,
409: ai_stand2, 0, NULL,
410: ai_stand2, 0, NULL,
411: ai_stand2, 0, NULL,
412: ai_stand2, 0, NULL,
413: ai_stand2, 0, NULL,
414: ai_stand2, 0, NULL,
415: ai_stand2, 0, NULL,
416: ai_stand2, 0, NULL,
417:
418: ai_stand2, 0, NULL,
419: ai_stand2, 0, gekk_idle_loop
420: };
421: mmove_t gekk_move_idle = {FRAME_idle_01, FRAME_idle_32, gekk_frames_idle, gekk_stand};
422: mmove_t gekk_move_idle2 = {FRAME_idle_01, FRAME_idle_32, gekk_frames_idle, gekk_face};
423:
424: mframe_t gekk_frames_idle2 [] =
425: {
426: ai_move, 0, gekk_search,
427: ai_move, 0, NULL,
428: ai_move, 0, NULL,
429: ai_move, 0, NULL,
430: ai_move, 0, NULL,
431: ai_move, 0, NULL,
432: ai_move, 0, NULL,
433: ai_move, 0, NULL,
434: ai_move, 0, NULL,
435: ai_move, 0, NULL,
436:
437: ai_move, 0, NULL,
438: ai_move, 0, NULL,
439: ai_move, 0, NULL,
440: ai_move, 0, NULL,
441: ai_move, 0, NULL,
442: ai_move, 0, NULL,
443: ai_move, 0, NULL,
444: ai_move, 0, NULL,
445: ai_move, 0, NULL,
446: ai_move, 0, NULL,
447:
448: ai_move, 0, NULL,
449: ai_move, 0, NULL,
450: ai_move, 0, NULL,
451: ai_move, 0, NULL,
452: ai_move, 0, NULL,
453: ai_move, 0, NULL,
454: ai_move, 0, NULL,
455: ai_move, 0, NULL,
456: ai_move, 0, NULL,
457: ai_move, 0, NULL,
458:
459: ai_move, 0, NULL,
460: ai_move, 0, gekk_idle_loop
461: };
462: mmove_t gekk_move_chant = {FRAME_idle_01, FRAME_idle_32, gekk_frames_idle2, gekk_chant};
463:
464:
465: void gekk_idle (edict_t *self)
466: {
467: if (!self->waterlevel)
468: self->monsterinfo.currentmove = &gekk_move_idle;
469: else
470: self->monsterinfo.currentmove = &gekk_move_swim_start;
471: // gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
472: }
473:
474:
475: //
476: // WALK
477: //
478:
479: void gekk_walk (edict_t *self);
480: mframe_t gekk_frames_walk[] =
481: {
482: ai_walk, 3.849, gekk_check_underwater, // frame 0
483: ai_walk, 19.606, NULL, // frame 1
484: ai_walk, 25.583, NULL, // frame 2
485: ai_walk, 34.625, gekk_step, // frame 3
486: ai_walk, 27.365, NULL, // frame 4
487: ai_walk, 28.480, NULL, // frame 5
488: };
489:
490: mmove_t gekk_move_walk = {FRAME_run_01, FRAME_run_06, gekk_frames_walk, NULL};
491:
492: void gekk_walk (edict_t *self)
493: {
494: self->monsterinfo.currentmove = &gekk_move_walk;
495: }
496:
497:
498: //
499: // RUN
500: //
501:
502: void gekk_run_start (edict_t *self)
503: {
504: if (self->waterlevel)
505: {
506: self->monsterinfo.currentmove = &gekk_move_swim_start;
507: }
508: else
509: {
510: self->monsterinfo.currentmove = &gekk_move_run_start;
511: }
512: }
513:
514: void gekk_run (edict_t *self)
515: {
516:
517: if (self->waterlevel)
518: {
519: self->monsterinfo.currentmove = &gekk_move_swim_start;
520: return;
521: }
522: else
523: {
524: if (self->monsterinfo.aiflags & AI_STAND_GROUND)
525: self->monsterinfo.currentmove = &gekk_move_stand;
526: else
527: self->monsterinfo.currentmove = &gekk_move_run;
528: }
529:
530: }
531: mframe_t gekk_frames_run[] =
532: {
533: ai_run, 3.849, gekk_check_underwater, // frame 0
534: ai_run, 19.606, NULL, // frame 1
535: ai_run, 25.583, NULL, // frame 2
536: ai_run, 34.625, gekk_step, // frame 3
537: ai_run, 27.365, NULL, // frame 4
538: ai_run, 28.480, NULL, // frame 5
539: };
540: mmove_t gekk_move_run = {FRAME_run_01, FRAME_run_06, gekk_frames_run, NULL};
541:
542: mframe_t gekk_frames_run_st[] =
543: {
544: ai_run, 0.212, NULL, // frame 0
545: ai_run, 19.753, NULL, // frame 1
546: };
547: mmove_t gekk_move_run_start = {FRAME_stand_01, FRAME_stand_02, gekk_frames_run_st, gekk_run};
548:
549: //
550: // MELEE
551: //
552:
553: void gekk_hit_left (edict_t *self)
554: {
555: vec3_t aim;
556:
557: VectorSet (aim, MELEE_DISTANCE, self->mins[0], 8);
558: if (fire_hit (self, aim, (15 + (rand() %5)), 100))
559: gi.sound (self, CHAN_WEAPON, sound_hit, 1, ATTN_NORM, 0);
560: else
561: gi.sound (self, CHAN_WEAPON, sound_swing, 1, ATTN_NORM, 0);
562: }
563:
564: void gekk_hit_right (edict_t *self)
565: {
566: vec3_t aim;
567:
568: VectorSet (aim, MELEE_DISTANCE, self->maxs[0], 8);
569: if (fire_hit (self, aim, (15 + (rand() %5)), 100))
570: gi.sound (self, CHAN_WEAPON, sound_hit2, 1, ATTN_NORM, 0);
571: else
572: gi.sound (self, CHAN_WEAPON, sound_swing, 1, ATTN_NORM, 0);
573: }
574:
575: void gekk_check_refire (edict_t *self)
576: {
577: if (!self->enemy || !self->enemy->inuse || self->enemy->health <= 0)
578: return;
579:
580: if (random() < (skill->value * 0.1))
581: {
582: if (range (self, self->enemy) == RANGE_MELEE)
583: {
584: if (self->s.frame == FRAME_clawatk3_09)
585: self->monsterinfo.currentmove = &gekk_move_attack2;
586: else if (self->s.frame == FRAME_clawatk5_09)
587: self->monsterinfo.currentmove = &gekk_move_attack1;
588: }
589: }
590:
591: }
592:
593:
594: void loogie_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
595: {
596:
597: if (other == self->owner)
598: return;
599:
600: if (surf && (surf->flags & SURF_SKY))
601: {
602: G_FreeEdict (self);
603: return;
604: }
605:
606: if (self->owner->client)
607: PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT);
608:
609: if (other->takedamage)
610: T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, self->dmg, 1, DAMAGE_ENERGY, MOD_GEKK);
611:
612: G_FreeEdict (self);
613: };
614:
615:
616:
617: void fire_loogie (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed)
618: {
619: edict_t *loogie;
620: trace_t tr;
621:
622: VectorNormalize (dir);
623:
624: loogie = G_Spawn();
625: VectorCopy (start, loogie->s.origin);
626: VectorCopy (start, loogie->s.old_origin);
627: vectoangles (dir, loogie->s.angles);
628: VectorScale (dir, speed, loogie->velocity);
629: loogie->movetype = MOVETYPE_FLYMISSILE;
630: loogie->clipmask = MASK_SHOT;
631: loogie->solid = SOLID_BBOX;
632: loogie->s.effects |= RF_FULLBRIGHT;
633: VectorClear (loogie->mins);
634: VectorClear (loogie->maxs);
635:
636: loogie->s.modelindex = gi.modelindex ("models/objects/loogy/tris.md2");
637: loogie->owner = self;
638: loogie->touch = loogie_touch;
639: loogie->nextthink = level.time + 2;
640: loogie->think = G_FreeEdict;
641: loogie->dmg = damage;
642: gi.linkentity (loogie);
643:
644: tr = gi.trace (self->s.origin, NULL, NULL, loogie->s.origin, loogie, MASK_SHOT);
645: if (tr.fraction < 1.0)
646: {
647: VectorMA (loogie->s.origin, -10, dir, loogie->s.origin);
648: loogie->touch (loogie, tr.ent, NULL, NULL);
649: }
650:
651: }
652:
653: void loogie (edict_t *self)
654: {
655: vec3_t start;
656: vec3_t forward, right, up;
657: vec3_t end;
658: vec3_t dir;
659: vec3_t gekkoffset;
660:
661: VectorSet (gekkoffset, -18, -0.8, 24);
662:
663: if (!self->enemy || self->enemy->health <= 0)
664: return;
665:
666: AngleVectors (self->s.angles, forward, right, up);
667: G_ProjectSource (self->s.origin, gekkoffset, forward, right, start);
668:
669: VectorMA (start, 2, up, start);
670:
671: VectorCopy (self->enemy->s.origin, end);
672: end[2] += self->enemy->viewheight;
673: VectorSubtract (end, start, dir);
674:
675: fire_loogie (self, start, dir, 5, 550);
676:
677: }
678:
679: void reloogie (edict_t *self)
680: {
681: if (random() > 0.8 && self->health < self->max_health)
682: {
683: self->monsterinfo.currentmove = &gekk_move_idle2;
684: return;
685: }
686:
687: if (self->enemy->health >= 0)
688: if (random() > 0.7 && (range(self, self->enemy) == RANGE_NEAR))
689: self->monsterinfo.currentmove = &gekk_move_spit;
690: }
691:
692:
693: mframe_t gekk_frames_spit [] =
694: {
695: ai_charge, 0.000, NULL,
696: ai_charge, 0.000, NULL,
697: ai_charge, 0.000, NULL,
698: ai_charge, 0.000, NULL,
699: ai_charge, 0.000, NULL,
700:
701: ai_charge, 0.000, loogie,
702: ai_charge, 0.000, reloogie
703: };
704: mmove_t gekk_move_spit = {FRAME_spit_01, FRAME_spit_07, gekk_frames_spit, gekk_run_start};
705:
706:
707: mframe_t gekk_frames_attack1 [] =
708: {
709: ai_charge, 0, NULL,
710: ai_charge, 0, NULL,
711: ai_charge, 0, NULL,
712:
713: ai_charge, 0, gekk_hit_left,
714: ai_charge, 0, NULL,
715: ai_charge, 0, NULL,
716:
717: ai_charge, 0, NULL,
718: ai_charge, 0, NULL,
719: ai_charge, 0, gekk_check_refire
720:
721: };
722: mmove_t gekk_move_attack1 = {FRAME_clawatk3_01, FRAME_clawatk3_09, gekk_frames_attack1, gekk_run_start};
723:
724: mframe_t gekk_frames_attack2[] =
725: {
726: ai_charge, 0.000, NULL,
727: ai_charge, 0.000, NULL,
728: ai_charge, 0.000, gekk_hit_left,
729:
730: ai_charge, 0.000, NULL,
731: ai_charge, 0.000, NULL,
732: ai_charge, 0.000, gekk_hit_right,
733:
734: ai_charge, 0.000, NULL,
735: ai_charge, 0.000, NULL,
736: ai_charge, 0.000, gekk_check_refire
737:
738: };
739: mmove_t gekk_move_attack2 = {FRAME_clawatk5_01, FRAME_clawatk5_09, gekk_frames_attack2, gekk_run_start};
740:
741: void gekk_check_underwater (edict_t *self)
742: {
743: if (self->waterlevel)
744: {
745: land_to_water (self);
746: }
747: }
748:
749: mframe_t gekk_frames_leapatk[] =
750: {
751: ai_charge, 0.000, NULL, // frame 0
752: ai_charge, -0.387, NULL, // frame 1
753: ai_charge, -1.113, NULL, // frame 2
754: ai_charge, -0.237, NULL, // frame 3
755: ai_charge, 6.720, gekk_jump_takeoff, // frame 4 last frame on ground
756: ai_charge, 6.414, NULL, // frame 5 leaves ground
757: ai_charge, 0.163, NULL, // frame 6
758: ai_charge, 28.316, NULL, // frame 7
759: ai_charge, 24.198, NULL, // frame 8
760: ai_charge, 31.742, NULL, // frame 9
761: ai_charge, 35.977, gekk_check_landing, // frame 10 last frame in air
762: ai_charge, 12.303, gekk_stop_skid, // frame 11 feet back on ground
763: ai_charge, 20.122, gekk_stop_skid, // frame 12
764: ai_charge, -1.042, gekk_stop_skid, // frame 13
765: ai_charge, 2.556, gekk_stop_skid, // frame 14
766: ai_charge, 0.544, gekk_stop_skid, // frame 15
767: ai_charge, 1.862, gekk_stop_skid, // frame 16
768: ai_charge, 1.224, gekk_stop_skid, // frame 17
769:
770: ai_charge, -0.457, gekk_check_underwater, // frame 18
771: };
772: mmove_t gekk_move_leapatk = {FRAME_leapatk_01, FRAME_leapatk_19, gekk_frames_leapatk, gekk_run_start};
773:
774:
775: mframe_t gekk_frames_leapatk2[] =
776: {
777: ai_charge, 0.000, NULL, // frame 0
778: ai_charge, -0.387, NULL, // frame 1
779: ai_charge, -1.113, NULL, // frame 2
780: ai_charge, -0.237, NULL, // frame 3
781: ai_charge, 6.720, gekk_jump_takeoff2, // frame 4 last frame on ground
782: ai_charge, 6.414, NULL, // frame 5 leaves ground
783: ai_charge, 0.163, NULL, // frame 6
784: ai_charge, 28.316, NULL, // frame 7
785: ai_charge, 24.198, NULL, // frame 8
786: ai_charge, 31.742, NULL, // frame 9
787: ai_charge, 35.977, gekk_check_landing, // frame 10 last frame in air
788: ai_charge, 12.303, gekk_stop_skid, // frame 11 feet back on ground
789: ai_charge, 20.122, gekk_stop_skid, // frame 12
790: ai_charge, -1.042, gekk_stop_skid, // frame 13
791: ai_charge, 2.556, gekk_stop_skid, // frame 14
792: ai_charge, 0.544, gekk_stop_skid, // frame 15
793: ai_charge, 1.862, gekk_stop_skid, // frame 16
794: ai_charge, 1.224, gekk_stop_skid, // frame 17
795:
796: ai_charge, -0.457, gekk_check_underwater, // frame 18
797: };
798: mmove_t gekk_move_leapatk2 = {FRAME_leapatk_01, FRAME_leapatk_19, gekk_frames_leapatk2, gekk_run_start};
799:
800:
801: void gekk_bite (edict_t *self)
802: {
803: vec3_t aim;
804:
805: VectorSet (aim, MELEE_DISTANCE, 0, 0);
806: fire_hit (self, aim, 5, 0);
807: }
808:
809: void gekk_preattack (edict_t *self)
810: {
811: // underwater attack sound
812: // gi.sound (self, CHAN_WEAPON, something something underwater sound, 1, ATTN_NORM, 0);
813: return;
814: }
815:
816:
817: mframe_t gekk_frames_attack [] =
818: {
819: ai_charge, 16, gekk_preattack,
820: ai_charge, 16, NULL,
821: ai_charge, 16, NULL,
822: ai_charge, 16, NULL,
823: ai_charge, 16, gekk_bite,
824: ai_charge, 16, NULL,
825: ai_charge, 16, NULL,
826: ai_charge, 16, NULL,
827: ai_charge, 16, NULL,
828: ai_charge, 16, gekk_bite,
829:
830: ai_charge, 16, NULL,
831: ai_charge, 16, NULL,
832: ai_charge, 16, NULL,
833: ai_charge, 16, gekk_hit_left,
834: ai_charge, 16, NULL,
835: ai_charge, 16, NULL,
836: ai_charge, 16, NULL,
837: ai_charge, 16, NULL,
838: ai_charge, 16, gekk_hit_right,
839: ai_charge, 16, NULL,
840:
841: ai_charge, 16, NULL
842:
843: };
844: mmove_t gekk_move_attack = {FRAME_attack_01, FRAME_attack_21, gekk_frames_attack, gekk_run_start};
845:
846: void gekk_melee (edict_t *self)
847: {
848:
849: float r;
850:
851: if (self->waterlevel)
852: {
853: self->monsterinfo.currentmove = &gekk_move_attack;
854: }
855: else
856: {
857: r = random();
858:
859: if (r > 0.66)
860: self->monsterinfo.currentmove = &gekk_move_attack1;
861: else
862: self->monsterinfo.currentmove = &gekk_move_attack2;
863:
864: }
865:
866: }
867:
868:
869: //
870: // ATTACK
871: //
872:
873: void gekk_jump_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
874: {
875: if (self->health <= 0)
876: {
877: self->touch = NULL;
878: return;
879: }
880:
881: if (other->takedamage)
882: {
883: if (VectorLength(self->velocity) > 200)
884: {
885: vec3_t point;
886: vec3_t normal;
887: int damage;
888:
889: VectorCopy (self->velocity, normal);
890: VectorNormalize(normal);
891: VectorMA (self->s.origin, self->maxs[0], normal, point);
892: damage = 10 + 10 * random();
893: T_Damage (other, self, self, self->velocity, point, normal, damage, damage, 0, MOD_GEKK);
894: }
895: }
896:
897: if (!M_CheckBottom (self))
898: {
899: if (self->groundentity)
900: {
901: self->monsterinfo.nextframe = FRAME_leapatk_11;
902: self->touch = NULL;
903: }
904: return;
905: }
906:
907: self->touch = NULL;
908: }
909:
910: void gekk_jump_takeoff (edict_t *self)
911: {
912: vec3_t forward;
913:
914: gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
915: AngleVectors (self->s.angles, forward, NULL, NULL);
916: self->s.origin[2] += 1;
917:
918: // high jump
919: if (gekk_check_jump (self))
920: {
921: VectorScale (forward, 700, self->velocity);
922: self->velocity[2] = 250;
923: }
924: else
925: {
926: VectorScale (forward, 250, self->velocity);
927: self->velocity[2] = 400;
928: }
929:
930:
931: self->groundentity = NULL;
932: self->monsterinfo.aiflags |= AI_DUCKED;
933: self->monsterinfo.attack_finished = level.time + 3;
934: self->touch = gekk_jump_touch;
935: }
936:
937: void gekk_jump_takeoff2 (edict_t *self)
938: {
939: vec3_t forward;
940:
941: gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
942: AngleVectors (self->s.angles, forward, NULL, NULL);
943: self->s.origin[2] = self->enemy->s.origin[2];
944:
945: if (gekk_check_jump (self))
946: {
947: VectorScale (forward, 300, self->velocity);
948: self->velocity[2] = 250;
949: }
950: else
951: {
952: VectorScale (forward, 150, self->velocity);
953: self->velocity[2] = 300;
954: }
955:
956: self->groundentity = NULL;
957: self->monsterinfo.aiflags |= AI_DUCKED;
958: self->monsterinfo.attack_finished = level.time + 3;
959: self->touch = gekk_jump_touch;
960:
961: }
962:
963: void gekk_stop_skid (edict_t *self)
964: {
965: if (self->groundentity)
966: {
967: VectorClear (self->velocity);
968: }
969: }
970:
971: void gekk_check_landing (edict_t *self)
972: {
973: if (self->groundentity)
974: {
975: gi.sound (self, CHAN_WEAPON, sound_thud, 1, ATTN_NORM, 0);
976: self->monsterinfo.attack_finished = 0;
977: self->monsterinfo.aiflags &= ~AI_DUCKED;
978:
979: VectorClear (self->velocity);
980:
981: return;
982: }
983:
984: // note to self
985: // causing skid
986: if (level.time > self->monsterinfo.attack_finished)
987: self->monsterinfo.nextframe = FRAME_leapatk_11;
988: else
989: {
990: self->monsterinfo.nextframe = FRAME_leapatk_12;
991: }
992: }
993:
994: void gekk_jump (edict_t *self)
995: {
996:
997: if (self->flags & FL_SWIM || self->waterlevel)
998: {
999: return;
1000: }
1001: else
1002: {
1003: //if (random() > 0.8 && self->health < self->max_health)
1004: // self->monsterinfo.currentmove = &gekk_move_idle2;
1005: //else
1006: {
1007: if (random() > 0.5 && (range (self, self->enemy) >= RANGE_NEAR))
1008: self->monsterinfo.currentmove = &gekk_move_spit;
1009: else if (random() > 0.8)
1010: self->monsterinfo.currentmove = &gekk_move_spit;
1011: else
1012: self->monsterinfo.currentmove = &gekk_move_leapatk;
1013:
1014: }
1015: }
1016: }
1017:
1018: //
1019: // PAIN
1020: //
1021:
1022: mframe_t gekk_frames_pain[] =
1023: {
1024: ai_move, 0.000, NULL, // frame 0
1025: ai_move, 0.000, NULL, // frame 1
1026: ai_move, 0.000, NULL, // frame 2
1027: ai_move, 0.000, NULL, // frame 3
1028: ai_move, 0.000, NULL, // frame 4
1029: ai_move, 0.000, NULL, // frame 5
1030: };
1031: mmove_t gekk_move_pain = {FRAME_pain_01, FRAME_pain_06, gekk_frames_pain, gekk_run_start};
1032:
1033: mframe_t gekk_frames_pain1[] =
1034: {
1035: ai_move, 0.000, NULL, // frame 0
1036: ai_move, 0.000, NULL, // frame 1
1037: ai_move, 0.000, NULL, // frame 2
1038: ai_move, 0.000, NULL, // frame 3
1039: ai_move, 0.000, NULL, // frame 4
1040: ai_move, 0.000, NULL, // frame 5
1041: ai_move, 0.000, NULL, // frame 6
1042: ai_move, 0.000, NULL, // frame 7
1043: ai_move, 0.000, NULL, // frame 8
1044: ai_move, 0.000, NULL, // frame 9
1045:
1046: ai_move, 0.000, gekk_check_underwater
1047: };
1048: mmove_t gekk_move_pain1 = {FRAME_pain3_01, FRAME_pain3_11, gekk_frames_pain1, gekk_run_start};
1049:
1050: mframe_t gekk_frames_pain2[] =
1051: {
1052: ai_move, 0.000, NULL, // frame 0
1053: ai_move, 0.000, NULL, // frame 1
1054: ai_move, 0.000, NULL, // frame 2
1055: ai_move, 0.000, NULL, // frame 3
1056: ai_move, 0.000, NULL, // frame 4
1057: ai_move, 0.000, NULL, // frame 5
1058: ai_move, 0.000, NULL, // frame 6
1059: ai_move, 0.000, NULL, // frame 7
1060: ai_move, 0.000, NULL, // frame 8
1061: ai_move, 0.000, NULL, // frame 9
1062:
1063: ai_move, 0.000, NULL, // frame 10
1064: ai_move, 0.000, NULL, // frame 11
1065: ai_move, 0.000, gekk_check_underwater,
1066: };
1067: mmove_t gekk_move_pain2 = {FRAME_pain4_01, FRAME_pain4_13, gekk_frames_pain2, gekk_run_start};
1068:
1069: void gekk_pain (edict_t *self, edict_t *other, float kick, int damage)
1070: {
1071: float r;
1072:
1073: if (self->spawnflags & 8)
1074: {
1075: self->spawnflags &= ~8;
1076: return;
1077: }
1078:
1079: if (self->health < (self->max_health /4))
1080: self->s.skinnum = 2;
1081: else if (self->health < (self->max_health / 2))
1082: self->s.skinnum = 1;
1083:
1084: if (level.time < self->pain_debounce_time)
1085: return;
1086:
1087: self->pain_debounce_time = level.time + 3;
1088:
1089: gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
1090:
1091: if (self->waterlevel)
1092: {
1093: if (!self->flags & FL_SWIM)
1094: self->flags |= FL_SWIM;
1095:
1096: self->monsterinfo.currentmove = &gekk_move_pain;
1097: }
1098: else
1099: {
1100: r = random();
1101:
1102: if (r > 0.5)
1103: self->monsterinfo.currentmove = &gekk_move_pain1;
1104: else
1105: self->monsterinfo.currentmove = &gekk_move_pain2;
1106: }
1107: }
1108:
1109:
1110: //
1111: // DEATH
1112: //
1113:
1114: void gekk_dead (edict_t *self)
1115: {
1116: // fix this because of no blocking problem
1117: if (self->waterlevel)
1118: {
1119: return;
1120: }
1121: else
1122: {
1123: VectorSet (self->mins, -16, -16, -24);
1124: VectorSet (self->maxs, 16, 16, -8);
1125: self->movetype = MOVETYPE_TOSS;
1126: self->svflags |= SVF_DEADMONSTER;
1127: self->nextthink = 0;
1128: gi.linkentity (self);
1129: }
1130:
1131:
1132: }
1133:
1134: void gekk_gibfest (edict_t *self)
1135: {
1136:
1137: int damage = 20;
1138:
1139: gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
1140:
1141: ThrowGibACID (self, "models/objects/gekkgib/pelvis/tris.md2", damage, GIB_ORGANIC);
1142: ThrowGibACID (self, "models/objects/gekkgib/arm/tris.md2", damage, GIB_ORGANIC);
1143: ThrowGibACID (self, "models/objects/gekkgib/arm/tris.md2", damage, GIB_ORGANIC);
1144: ThrowGibACID (self, "models/objects/gekkgib/torso/tris.md2", damage, GIB_ORGANIC);
1145: ThrowGibACID (self, "models/objects/gekkgib/claw/tris.md2", damage, GIB_ORGANIC);
1146: ThrowGibACID (self, "models/objects/gekkgib/leg/tris.md2", damage, GIB_ORGANIC);
1147: ThrowGibACID (self, "models/objects/gekkgib/leg/tris.md2", damage, GIB_ORGANIC);
1148:
1149: ThrowHeadACID (self, "models/objects/gekkgib/head/tris.md2", damage, GIB_ORGANIC);
1150:
1151:
1152: self->deadflag = DEAD_DEAD;
1153:
1154: }
1155:
1156: void isgibfest (edict_t *self)
1157: {
1158: if (random() > 0.9)
1159: gekk_gibfest (self);
1160: }
1161:
1162: mframe_t gekk_frames_death1[] =
1163: {
1164:
1165: ai_move, -5.151, NULL, // frame 0
1166: ai_move, -12.223, NULL, // frame 1
1167: ai_move, -11.484, NULL, // frame 2
1168: ai_move, -17.952, NULL, // frame 3
1169: ai_move, -6.953, NULL, // frame 4
1170: ai_move, -7.393, NULL, // frame 5
1171: ai_move, -10.713, NULL, // frame 6
1172: ai_move, -17.464, NULL, // frame 7
1173: ai_move, -11.678, NULL, // frame 8
1174: ai_move, -11.678, NULL // frame 9
1175: };
1176: mmove_t gekk_move_death1 = {FRAME_death1_01, FRAME_death1_10, gekk_frames_death1, gekk_dead};
1177:
1178: mframe_t gekk_frames_death3[] =
1179: {
1180: ai_move, 0.000, NULL, // frame 0
1181: ai_move, 0.022, NULL, // frame 1
1182: ai_move, 0.169, NULL, // frame 2
1183: ai_move, -0.710, NULL, // frame 3
1184: ai_move, -13.446, NULL, // frame 4
1185: ai_move, -7.654, isgibfest, // frame 5
1186: ai_move, -31.951, NULL, // frame 6
1187:
1188: };
1189: mmove_t gekk_move_death3 = {FRAME_death3_01, FRAME_death3_07, gekk_frames_death3, gekk_dead};
1190:
1191: mframe_t gekk_frames_death4[] =
1192: {
1193: ai_move, 5.103, NULL, // frame 0
1194: ai_move, -4.808, NULL, // frame 1
1195: ai_move, -10.509, NULL, // frame 2
1196: ai_move, -9.899, NULL, // frame 3
1197: ai_move, 4.033, isgibfest, // frame 4
1198: ai_move, -5.197, NULL, // frame 5
1199: ai_move, -0.919, NULL, // frame 6
1200: ai_move, -8.821, NULL, // frame 7
1201: ai_move, -5.626, NULL, // frame 8
1202: ai_move, -8.865, isgibfest, // frame 9
1203: ai_move, -0.845, NULL, // frame 10
1204: ai_move, 1.986, NULL, // frame 11
1205: ai_move, 0.170, NULL, // frame 12
1206: ai_move, 1.339, isgibfest, // frame 13
1207: ai_move, -0.922, NULL, // frame 14
1208: ai_move, 0.818, NULL, // frame 15
1209: ai_move, -1.288, NULL, // frame 16
1210: ai_move, -1.408, isgibfest, // frame 17
1211: ai_move, -7.787, NULL, // frame 18
1212: ai_move, -3.995, NULL, // frame 19
1213: ai_move, -4.604, NULL, // frame 20
1214: ai_move, -1.715, isgibfest, // frame 21
1215: ai_move, -0.564, NULL, // frame 22
1216: ai_move, -0.597, NULL, // frame 23
1217: ai_move, 0.074, NULL, // frame 24
1218: ai_move, -0.309, isgibfest, // frame 25
1219: ai_move, -0.395, NULL, // frame 26
1220: ai_move, -0.501, NULL, // frame 27
1221: ai_move, -0.325, NULL, // frame 28
1222: ai_move, -0.931, isgibfest, // frame 29
1223: ai_move, -1.433, NULL, // frame 30
1224: ai_move, -1.626, NULL, // frame 31
1225: ai_move, 4.680, NULL, // frame 32
1226: ai_move, 0.560, NULL, // frame 33
1227: ai_move, -0.549, gekk_gibfest // frame 34
1228: };
1229: mmove_t gekk_move_death4 = {FRAME_death4_01, FRAME_death4_35, gekk_frames_death4, gekk_dead};
1230:
1231: mframe_t gekk_frames_wdeath[] =
1232: {
1233: ai_move, 0.000, NULL, // frame 0
1234: ai_move, 0.000, NULL, // frame 1
1235: ai_move, 0.000, NULL, // frame 2
1236: ai_move, 0.000, NULL, // frame 3
1237: ai_move, 0.000, NULL, // frame 4
1238: ai_move, 0.000, NULL, // frame 5
1239: ai_move, 0.000, NULL, // frame 6
1240: ai_move, 0.000, NULL, // frame 7
1241: ai_move, 0.000, NULL, // frame 8
1242: ai_move, 0.000, NULL, // frame 9
1243: ai_move, 0.000, NULL, // frame 10
1244: ai_move, 0.000, NULL, // frame 11
1245: ai_move, 0.000, NULL, // frame 12
1246: ai_move, 0.000, NULL, // frame 13
1247: ai_move, 0.000, NULL, // frame 14
1248: ai_move, 0.000, NULL, // frame 15
1249: ai_move, 0.000, NULL, // frame 16
1250: ai_move, 0.000, NULL, // frame 17
1251: ai_move, 0.000, NULL, // frame 18
1252: ai_move, 0.000, NULL, // frame 19
1253: ai_move, 0.000, NULL, // frame 20
1254: ai_move, 0.000, NULL, // frame 21
1255: ai_move, 0.000, NULL, // frame 22
1256: ai_move, 0.000, NULL, // frame 23
1257: ai_move, 0.000, NULL, // frame 24
1258: ai_move, 0.000, NULL, // frame 25
1259: ai_move, 0.000, NULL, // frame 26
1260: ai_move, 0.000, NULL, // frame 27
1261: ai_move, 0.000, NULL, // frame 28
1262: ai_move, 0.000, NULL, // frame 29
1263: ai_move, 0.000, NULL, // frame 30
1264: ai_move, 0.000, NULL, // frame 31
1265: ai_move, 0.000, NULL, // frame 32
1266: ai_move, 0.000, NULL, // frame 33
1267: ai_move, 0.000, NULL, // frame 34
1268: ai_move, 0.000, NULL, // frame 35
1269: ai_move, 0.000, NULL, // frame 36
1270: ai_move, 0.000, NULL, // frame 37
1271: ai_move, 0.000, NULL, // frame 38
1272: ai_move, 0.000, NULL, // frame 39
1273: ai_move, 0.000, NULL, // frame 40
1274: ai_move, 0.000, NULL, // frame 41
1275: ai_move, 0.000, NULL, // frame 42
1276: ai_move, 0.000, NULL, // frame 43
1277: ai_move, 0.000, NULL // frame 44
1278: };
1279: mmove_t gekk_move_wdeath = {FRAME_wdeath_01, FRAME_wdeath_45, gekk_frames_wdeath, gekk_dead};
1280:
1281: void gekk_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
1282: {
1283:
1284: float r;
1285:
1286: if (self->health <= self->gib_health)
1287: {
1288: gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
1289:
1290: ThrowGibACID (self, "models/objects/gekkgib/pelvis/tris.md2", damage, GIB_ORGANIC);
1291: ThrowGibACID (self, "models/objects/gekkgib/arm/tris.md2", damage, GIB_ORGANIC);
1292: ThrowGibACID (self, "models/objects/gekkgib/arm/tris.md2", damage, GIB_ORGANIC);
1293: ThrowGibACID (self, "models/objects/gekkgib/torso/tris.md2", damage, GIB_ORGANIC);
1294: ThrowGibACID (self, "models/objects/gekkgib/claw/tris.md2", damage, GIB_ORGANIC);
1295: ThrowGibACID (self, "models/objects/gekkgib/leg/tris.md2", damage, GIB_ORGANIC);
1296: ThrowGibACID (self, "models/objects/gekkgib/leg/tris.md2", damage, GIB_ORGANIC);
1297:
1298: ThrowHeadACID (self, "models/objects/gekkgib/head/tris.md2", damage, GIB_ORGANIC);
1299:
1300: self->deadflag = DEAD_DEAD;
1301: return;
1302: }
1303:
1304: if (self->deadflag == DEAD_DEAD)
1305: return;
1306:
1307: gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0);
1308: self->deadflag = DEAD_DEAD;
1309: self->takedamage = DAMAGE_YES;
1310: self->s.skinnum = 2;
1311:
1312: if (self->waterlevel)
1313: self->monsterinfo.currentmove = &gekk_move_wdeath;
1314: else
1315: {
1316: r = random();
1317: if (r > 0.66)
1318: self->monsterinfo.currentmove = &gekk_move_death1;
1319: else if (r > 0.33)
1320: self->monsterinfo.currentmove = &gekk_move_death3;
1321: else
1322: self->monsterinfo.currentmove = &gekk_move_death4;
1323:
1324: }
1325:
1326: }
1327:
1328:
1329: /*
1330: duck
1331: */
1332: void gekk_duck_down (edict_t *self)
1333: {
1334: if (self->monsterinfo.aiflags & AI_DUCKED)
1335: return;
1336: self->monsterinfo.aiflags |= AI_DUCKED;
1337: self->maxs[2] -= 32;
1338: self->takedamage = DAMAGE_YES;
1339: self->monsterinfo.pausetime = level.time + 1;
1340: gi.linkentity (self);
1341: }
1342:
1343: void gekk_duck_up (edict_t *self)
1344: {
1345: self->monsterinfo.aiflags &= ~AI_DUCKED;
1346: self->maxs[2] += 32;
1347: self->takedamage = DAMAGE_AIM;
1348: gi.linkentity (self);
1349: }
1350:
1351:
1352: void gekk_duck_hold (edict_t *self)
1353: {
1354: if (level.time >= self->monsterinfo.pausetime)
1355: self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
1356: else
1357: self->monsterinfo.aiflags |= AI_HOLD_FRAME;
1358: }
1359:
1360: mframe_t gekk_frames_lduck[] =
1361: {
1362: ai_move, 0.000, NULL, // frame 0
1363: ai_move, 0.000, NULL, // frame 1
1364: ai_move, 0.000, NULL, // frame 2
1365: ai_move, 0.000, NULL, // frame 3
1366: ai_move, 0.000, NULL, // frame 4
1367: ai_move, 0.000, NULL, // frame 5
1368: ai_move, 0.000, NULL, // frame 6
1369: ai_move, 0.000, NULL, // frame 7
1370: ai_move, 0.000, NULL, // frame 8
1371: ai_move, 0.000, NULL, // frame 9
1372:
1373: ai_move, 0.000, NULL, // frame 10
1374: ai_move, 0.000, NULL, // frame 11
1375: ai_move, 0.000, NULL // frame 12
1376:
1377: };
1378: mmove_t gekk_move_lduck = {FRAME_lduck_01, FRAME_lduck_13, gekk_frames_lduck, gekk_run_start};
1379:
1380: mframe_t gekk_frames_rduck[] =
1381: {
1382: ai_move, 0.000, NULL, // frame 0
1383: ai_move, 0.000, NULL, // frame 1
1384: ai_move, 0.000, NULL, // frame 2
1385: ai_move, 0.000, NULL, // frame 3
1386: ai_move, 0.000, NULL, // frame 4
1387: ai_move, 0.000, NULL, // frame 5
1388: ai_move, 0.000, NULL, // frame 6
1389: ai_move, 0.000, NULL, // frame 7
1390: ai_move, 0.000, NULL, // frame 8
1391: ai_move, 0.000, NULL, // frame 9
1392: ai_move, 0.000, NULL, // frame 10
1393: ai_move, 0.000, NULL, // frame 11
1394: ai_move, 0.000, NULL // frame 12
1395:
1396: };
1397: mmove_t gekk_move_rduck = {FRAME_rduck_01, FRAME_rduck_13, gekk_frames_rduck, gekk_run_start};
1398:
1399:
1400: void gekk_dodge (edict_t *self, edict_t *attacker, float eta)
1401: {
1402: float r;
1403:
1404: r = random();
1405: if (r > 0.25)
1406: return;
1407:
1408: if (!self->enemy)
1409: self->enemy = attacker;
1410:
1411: if (self->waterlevel)
1412: {
1413: self->monsterinfo.currentmove = &gekk_move_attack;
1414: return;
1415: }
1416:
1417: if (skill->value == 0)
1418: {
1419: r = random();
1420: if (r > 0.5)
1421: self->monsterinfo.currentmove = &gekk_move_lduck;
1422: else
1423: self->monsterinfo.currentmove = &gekk_move_rduck;
1424: return;
1425: }
1426:
1427: self->monsterinfo.pausetime = level.time + eta + 0.3;
1428: r = random();
1429:
1430: if (skill->value == 1)
1431: {
1432: if (r > 0.33)
1433: {
1434: r = random();
1435: if (r > 0.5)
1436: self->monsterinfo.currentmove = &gekk_move_lduck;
1437: else
1438: self->monsterinfo.currentmove = &gekk_move_rduck;
1439: }
1440: else
1441: {
1442: r = random();
1443: if (r > 0.66)
1444: self->monsterinfo.currentmove = &gekk_move_attack1;
1445: else
1446: self->monsterinfo.currentmove = &gekk_move_attack2;
1447:
1448: }
1449: return;
1450: }
1451:
1452: if (skill->value == 2)
1453: {
1454: if (r > 0.66)
1455: {
1456: r = random();
1457: if (r > 0.5)
1458: self->monsterinfo.currentmove = &gekk_move_lduck;
1459: else
1460: self->monsterinfo.currentmove = &gekk_move_rduck;
1461: }
1462: else
1463: {
1464: r = random();
1465: if (r > 0.66)
1466: self->monsterinfo.currentmove = &gekk_move_attack1;
1467: else
1468: self->monsterinfo.currentmove = &gekk_move_attack2;
1469: }
1470: return;
1471: }
1472:
1473: r = random();
1474: if (r > 0.66)
1475: self->monsterinfo.currentmove = &gekk_move_attack1;
1476: else
1477: self->monsterinfo.currentmove = &gekk_move_attack2;
1478:
1479:
1480: }
1481:
1482: //
1483: // SPAWN
1484: //
1485:
1486: /*QUAKED monster_gekk (1 .5 0) (-24 -24 -24) (24 24 24) Ambush Trigger_Spawn Sight Chant
1487: */
1488: void SP_monster_gekk (edict_t *self)
1489: {
1490: if (deathmatch->value)
1491: {
1492: G_FreeEdict (self);
1493: return;
1494: }
1495:
1496: sound_swing = gi.soundindex ("gek/gk_atck1.wav");
1497: sound_hit = gi.soundindex ("gek/gk_atck2.wav");
1498: sound_hit2 = gi.soundindex ("gek/gk_atck3.wav");
1499: sound_death = gi.soundindex ("gek/gk_deth1.wav");
1500: sound_pain1 = gi.soundindex ("gek/gk_pain1.wav");
1501: sound_sight = gi.soundindex ("gek/gk_sght1.wav");
1502: sound_search = gi.soundindex ("gek/gk_idle1.wav");
1503: sound_step1 = gi.soundindex ("gek/gk_step1.wav");
1504: sound_step2 = gi.soundindex ("gek/gk_step2.wav");
1505: sound_step3 = gi.soundindex ("gek/gk_step3.wav");
1506: sound_thud = gi.soundindex ("mutant/thud1.wav");
1507:
1508: sound_chantlow = gi.soundindex ("gek/gek_low.wav");
1509: sound_chantmid = gi.soundindex ("gek/gek_mid.wav");
1510: sound_chanthigh = gi.soundindex ("gek/gek_high.wav");
1511:
1512: self->movetype = MOVETYPE_STEP;
1513: self->solid = SOLID_BBOX;
1514: self->s.modelindex = gi.modelindex ("models/monsters/gekk/tris.md2");
1515: VectorSet (self->mins, -24, -24, -24);
1516: VectorSet (self->maxs, 24, 24, 24);
1517:
1518: gi.modelindex ("models/objects/gekkgib/pelvis/tris.md2");
1519: gi.modelindex ("models/objects/gekkgib/arm/tris.md2");
1520: gi.modelindex ("models/objects/gekkgib/torso/tris.md2");
1521: gi.modelindex ("models/objects/gekkgib/claw/tris.md2");
1522: gi.modelindex ("models/objects/gekkgib/leg/tris.md2");
1523: gi.modelindex ("models/objects/gekkgib/head/tris.md2");
1524:
1525: self->health = 125;
1526: self->gib_health = -30;
1527: self->mass = 300;
1528:
1529: self->pain = gekk_pain;
1530: self->die = gekk_die;
1531:
1532: self->monsterinfo.stand = gekk_stand;
1533:
1534: self->monsterinfo.walk = gekk_walk;
1535: self->monsterinfo.run = gekk_run_start;
1536: self->monsterinfo.dodge = gekk_dodge;
1537: self->monsterinfo.attack = gekk_jump;
1538: self->monsterinfo.melee = gekk_melee;
1539: self->monsterinfo.sight = gekk_sight;
1540:
1541: self->monsterinfo.search = gekk_search;
1542: self->monsterinfo.idle = gekk_idle;
1543: self->monsterinfo.checkattack = gekk_checkattack;
1544:
1545: gi.linkentity (self);
1546:
1547: self->monsterinfo.currentmove = &gekk_move_stand;
1548:
1549: self->monsterinfo.scale = MODEL_SCALE;
1550: walkmonster_start (self);
1551:
1552: if (self->spawnflags & 8)
1553: self->monsterinfo.currentmove = &gekk_move_chant;
1554:
1555: }
1556:
1557:
1558: void water_to_land (edict_t *self)
1559: {
1560: self->flags &= ~FL_SWIM;
1561: self->yaw_speed = 20;
1562: self->viewheight = 25;
1563:
1564: self->monsterinfo.currentmove = &gekk_move_leapatk2;
1565:
1566: VectorSet (self->mins, -24, -24, -24);
1567: VectorSet (self->maxs, 24, 24, 24);
1568: }
1569:
1570: void land_to_water (edict_t *self)
1571: {
1572: self->flags |= FL_SWIM;
1573: self->yaw_speed = 10;
1574: self->viewheight = 10;
1575:
1576: self->monsterinfo.currentmove = &gekk_move_swim_start;
1577:
1578: VectorSet (self->mins, -24, -24, -24);
1579: VectorSet (self->maxs, 24, 24, 16);
1580: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.