|
|
1.1 root 1: /*
2: ==============================================================================
3:
4: boss2
5:
6: ==============================================================================
7: */
8:
9: #include "g_local.h"
10: #include "m_boss2.h"
11:
12: void BossExplode (edict_t *self);
13:
14: qboolean infront (edict_t *self, edict_t *other);
15:
16: static int sound_pain1;
17: static int sound_pain2;
18: static int sound_pain3;
19: static int sound_death;
20: static int sound_search1;
21:
22: void boss2_search (edict_t *self)
23: {
24: if (random() < 0.5)
25: gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NONE, 0);
26: }
27:
28: void boss2_run (edict_t *self);
29: void boss2_stand (edict_t *self);
30: void boss2_dead (edict_t *self);
31: void boss2_attack (edict_t *self);
32: void boss2_attack_mg (edict_t *self);
33: void boss2_reattack_mg (edict_t *self);
34: void boss2_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point);
35:
36: #define BOSS2_ROCKET_SPEED 750
37:
38: void Boss2PredictiveRocket (edict_t *self)
39: {
40: vec3_t forward, right;
41: vec3_t start;
42: vec3_t dir;
43: vec3_t vec;
44: float time, dist;
45:
46: gi.dprintf("predictive fire\n");
47:
48: AngleVectors (self->s.angles, forward, right, NULL);
49:
50: //1
51: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_1], forward, right, start);
52: VectorSubtract(self->enemy->s.origin, start, dir);
53: // dir[2] += self->enemy->viewheight;
54: dist = VectorLength(dir);
55: time = dist / BOSS2_ROCKET_SPEED;
56: VectorMA(self->enemy->s.origin, time-0.3, self->enemy->velocity, vec);
57:
58: // VectorCopy (self->enemy->s.origin, vec);
59: // vec[2] += self->enemy->viewheight;
60: VectorSubtract (vec, start, dir);
61: VectorNormalize (dir);
62: monster_fire_rocket (self, start, dir, 50, BOSS2_ROCKET_SPEED, MZ2_BOSS2_ROCKET_1);
63:
64: //2
65: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_2], forward, right, start);
66: VectorSubtract(self->enemy->s.origin, start, dir);
67: // dir[2] += self->enemy->viewheight;
68: dist = VectorLength(dir);
69: time = dist / BOSS2_ROCKET_SPEED;
70: VectorMA(self->enemy->s.origin, time-0.15, self->enemy->velocity, vec);
71:
72: // VectorCopy (self->enemy->s.origin, vec);
73: // vec[2] += self->enemy->viewheight;
74: VectorSubtract (vec, start, dir);
75: VectorNormalize (dir);
76: monster_fire_rocket (self, start, dir, 50, BOSS2_ROCKET_SPEED, MZ2_BOSS2_ROCKET_2);
77:
78: //3
79: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_3], forward, right, start);
80: VectorSubtract(self->enemy->s.origin, start, dir);
81: // dir[2] += self->enemy->viewheight;
82: dist = VectorLength(dir);
83: time = dist / BOSS2_ROCKET_SPEED;
84: VectorMA(self->enemy->s.origin, time, self->enemy->velocity, vec);
85:
86: // VectorCopy (self->enemy->s.origin, vec);
87: // vec[2] += self->enemy->viewheight;
88: VectorSubtract (vec, start, dir);
89: VectorNormalize (dir);
90: monster_fire_rocket (self, start, dir, 50, BOSS2_ROCKET_SPEED, MZ2_BOSS2_ROCKET_3);
91:
92: //4
93: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_4], forward, right, start);
94: VectorSubtract(self->enemy->s.origin, start, dir);
95: // dir[2] += self->enemy->viewheight;
96: dist = VectorLength(dir);
97: time = dist / BOSS2_ROCKET_SPEED;
98: VectorMA(self->enemy->s.origin, time+0.15, self->enemy->velocity, vec);
99:
100: // VectorCopy (self->enemy->s.origin, vec);
101: // vec[2] += self->enemy->viewheight;
102: VectorSubtract (vec, start, dir);
103: VectorNormalize (dir);
104: monster_fire_rocket (self, start, dir, 50, BOSS2_ROCKET_SPEED, MZ2_BOSS2_ROCKET_4);
105: }
106:
107: void Boss2Rocket (edict_t *self)
108: {
109: vec3_t forward, right;
110: vec3_t start;
111: vec3_t dir;
112: vec3_t vec;
113:
114: if(self->enemy)
115: {
116: if(self->enemy->client && random() < 0.9)
117: {
118: Boss2PredictiveRocket(self);
119: return;
120: }
121: }
122:
123: AngleVectors (self->s.angles, forward, right, NULL);
124:
125: //1
126: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_1], forward, right, start);
127: VectorCopy (self->enemy->s.origin, vec);
128: // vec[2] += self->enemy->viewheight;
129: vec[2] -= 15;
130: VectorSubtract (vec, start, dir);
131: VectorNormalize (dir);
132: VectorMA (dir, 0.4, right, dir);
133: VectorNormalize (dir);
134: monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_1);
135:
136: //2
137: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_2], forward, right, start);
138: VectorCopy (self->enemy->s.origin, vec);
139: // vec[2] += self->enemy->viewheight;
140: VectorSubtract (vec, start, dir);
141: VectorNormalize (dir);
142: VectorMA (dir, 0.025, right, dir);
143: VectorNormalize (dir);
144: monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_2);
145:
146: //3
147: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_3], forward, right, start);
148: VectorCopy (self->enemy->s.origin, vec);
149: // vec[2] += self->enemy->viewheight;
150: VectorSubtract (vec, start, dir);
151: VectorNormalize (dir);
152: VectorMA (dir, -0.025, right, dir);
153: VectorNormalize (dir);
154: monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_3);
155:
156: //4
157: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_4], forward, right, start);
158: VectorCopy (self->enemy->s.origin, vec);
159: // vec[2] += self->enemy->viewheight;
160: vec[2] -= 15;
161: VectorSubtract (vec, start, dir);
162: VectorNormalize (dir);
163: VectorMA (dir, -0.4, right, dir);
164: VectorNormalize (dir);
165: monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_4);
166:
167: //5
168: // G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_4], forward, right, start);
169: // VectorCopy (self->enemy->s.origin, vec);
170: // vec[2] += self->enemy->viewheight;
171: // VectorSubtract (vec, start, dir);
172: // VectorNormalize (dir);
173: // monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_2);
174: }
175:
176: void boss2_firebullet_right (edict_t *self)
177: {
178: vec3_t forward, right, target;
179: vec3_t start;
180:
181: AngleVectors (self->s.angles, forward, right, NULL);
182: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_MACHINEGUN_R1], forward, right, start);
183:
184: // VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target);
185: VectorMA (self->enemy->s.origin, 0.2, self->enemy->velocity, target);
186: target[2] += self->enemy->viewheight;
187: VectorSubtract (target, start, forward);
188: VectorNormalize (forward);
189:
190: monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD*3, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_R1);
191: // monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_R1);
192: }
193:
194: void boss2_firebullet_left (edict_t *self)
195: {
196: vec3_t forward, right, target;
197: vec3_t start;
198:
199: AngleVectors (self->s.angles, forward, right, NULL);
200: G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_MACHINEGUN_L1], forward, right, start);
201:
202: // VectorMA (self->enemy->s.origin, 0.2, self->enemy->velocity, target);
203: VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target);
204:
205: target[2] += self->enemy->viewheight;
206: VectorSubtract (target, start, forward);
207: VectorNormalize (forward);
208:
209: monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD*3, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_L1);
210: // monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_L1);
211: }
212:
213: void Boss2MachineGun (edict_t *self)
214: {
215: /* vec3_t forward, right;
216: vec3_t start;
217: vec3_t dir;
218: vec3_t vec;
219: int flash_number;
220:
221: AngleVectors (self->s.angles, forward, right, NULL);
222:
223: flash_number = MZ2_BOSS2_MACHINEGUN_1 + (self->s.frame - FRAME_attack10);
224: G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
225:
226: VectorCopy (self->enemy->s.origin, vec);
227: vec[2] += self->enemy->viewheight;
228: VectorSubtract (vec, start, dir);
229: VectorNormalize (dir);
230: monster_fire_bullet (self, start, dir, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number);
231: */
232: boss2_firebullet_left(self);
233: boss2_firebullet_right(self);
234: }
235:
236:
237: mframe_t boss2_frames_stand [] =
238: {
239: ai_stand, 0, NULL,
240: ai_stand, 0, NULL,
241: ai_stand, 0, NULL,
242: ai_stand, 0, NULL,
243: ai_stand, 0, NULL,
244: ai_stand, 0, NULL,
245: ai_stand, 0, NULL,
246: ai_stand, 0, NULL,
247: ai_stand, 0, NULL,
248: ai_stand, 0, NULL,
249: ai_stand, 0, NULL,
250: ai_stand, 0, NULL,
251: ai_stand, 0, NULL,
252: ai_stand, 0, NULL,
253: ai_stand, 0, NULL,
254: ai_stand, 0, NULL,
255: ai_stand, 0, NULL,
256: ai_stand, 0, NULL,
257: ai_stand, 0, NULL,
258: ai_stand, 0, NULL,
259: ai_stand, 0, NULL
260: };
261: mmove_t boss2_move_stand = {FRAME_stand30, FRAME_stand50, boss2_frames_stand, NULL};
262:
263: mframe_t boss2_frames_fidget [] =
264: {
265: ai_stand, 0, NULL,
266: ai_stand, 0, NULL,
267: ai_stand, 0, NULL,
268: ai_stand, 0, NULL,
269: ai_stand, 0, NULL,
270: ai_stand, 0, NULL,
271: ai_stand, 0, NULL,
272: ai_stand, 0, NULL,
273: ai_stand, 0, NULL,
274: ai_stand, 0, NULL,
275: ai_stand, 0, NULL,
276: ai_stand, 0, NULL,
277: ai_stand, 0, NULL,
278: ai_stand, 0, NULL,
279: ai_stand, 0, NULL,
280: ai_stand, 0, NULL,
281: ai_stand, 0, NULL,
282: ai_stand, 0, NULL,
283: ai_stand, 0, NULL,
284: ai_stand, 0, NULL,
285: ai_stand, 0, NULL,
286: ai_stand, 0, NULL,
287: ai_stand, 0, NULL,
288: ai_stand, 0, NULL,
289: ai_stand, 0, NULL,
290: ai_stand, 0, NULL,
291: ai_stand, 0, NULL,
292: ai_stand, 0, NULL,
293: ai_stand, 0, NULL,
294: ai_stand, 0, NULL
295: };
296: mmove_t boss2_move_fidget = {FRAME_stand1, FRAME_stand30, boss2_frames_fidget, NULL};
297:
298: mframe_t boss2_frames_walk [] =
299: {
300: /* PMM - normally, this is all 8's .. I upped it */
301: ai_walk, 10, NULL,
302: ai_walk, 10, NULL,
303: ai_walk, 10, NULL,
304: ai_walk, 10, NULL,
305: ai_walk, 10, NULL,
306: ai_walk, 10, NULL,
307: ai_walk, 10, NULL,
308: ai_walk, 10, NULL,
309: ai_walk, 10, NULL,
310: ai_walk, 10, NULL,
311: ai_walk, 10, NULL,
312: ai_walk, 10, NULL,
313: ai_walk, 10, NULL,
314: ai_walk, 10, NULL,
315: ai_walk, 10, NULL,
316: ai_walk, 10, NULL,
317: ai_walk, 10, NULL,
318: ai_walk, 10, NULL,
319: ai_walk, 10, NULL,
320: ai_walk, 10, NULL
321: };
322: mmove_t boss2_move_walk = {FRAME_walk1, FRAME_walk20, boss2_frames_walk, NULL};
323:
324:
325: mframe_t boss2_frames_run [] =
326: {
327: /* PMM - normally, this is all 8's .. I upped it */
328: ai_run, 10, NULL,
329: ai_run, 10, NULL,
330: ai_run, 10, NULL,
331: ai_run, 10, NULL,
332: ai_run, 10, NULL,
333: ai_run, 10, NULL,
334: ai_run, 10, NULL,
335: ai_run, 10, NULL,
336: ai_run, 10, NULL,
337: ai_run, 10, NULL,
338: ai_run, 10, NULL,
339: ai_run, 10, NULL,
340: ai_run, 10, NULL,
341: ai_run, 10, NULL,
342: ai_run, 10, NULL,
343: ai_run, 10, NULL,
344: ai_run, 10, NULL,
345: ai_run, 10, NULL,
346: ai_run, 10, NULL,
347: ai_run, 10, NULL
348: };
349: mmove_t boss2_move_run = {FRAME_walk1, FRAME_walk20, boss2_frames_run, NULL};
350:
351: mframe_t boss2_frames_attack_pre_mg [] =
352: {
353: /* used to be all 1's .. what a slow guy */
354: ai_charge, 2, NULL,
355: ai_charge, 2, NULL,
356: ai_charge, 2, NULL,
357: ai_charge, 2, NULL,
358: ai_charge, 2, NULL,
359: ai_charge, 2, NULL,
360: ai_charge, 2, NULL,
361: ai_charge, 2, NULL,
362: ai_charge, 2, boss2_attack_mg
363: };
364: mmove_t boss2_move_attack_pre_mg = {FRAME_attack1, FRAME_attack9, boss2_frames_attack_pre_mg, NULL};
365:
366:
367: // Loop this
368: mframe_t boss2_frames_attack_mg [] =
369: {
370: /* used to be all 1's .. what a slow guy */
371: ai_charge, 2, Boss2MachineGun,
372: ai_charge, 2, Boss2MachineGun,
373: ai_charge, 2, Boss2MachineGun,
374: ai_charge, 2, Boss2MachineGun,
375: ai_charge, 2, Boss2MachineGun,
376: ai_charge, 2, boss2_reattack_mg
377: };
378: mmove_t boss2_move_attack_mg = {FRAME_attack10, FRAME_attack15, boss2_frames_attack_mg, NULL};
379:
380: mframe_t boss2_frames_attack_post_mg [] =
381: {
382: /* used to be all 1's .. what a slow guy */
383: ai_charge, 2, NULL,
384: ai_charge, 2, NULL,
385: ai_charge, 2, NULL,
386: ai_charge, 2, NULL
387: };
388: mmove_t boss2_move_attack_post_mg = {FRAME_attack16, FRAME_attack19, boss2_frames_attack_post_mg, boss2_run};
389:
390: mframe_t boss2_frames_attack_rocket [] =
391: {
392: /* used to be all 1's .. except the Boss2Rocket frame, which was -20(!) */
393: ai_charge, 2, NULL,
394: ai_charge, 2, NULL,
395: ai_charge, 2, NULL,
396: ai_charge, 2, NULL,
397: ai_charge, 2, NULL,
398: ai_charge, 2, NULL,
399: ai_charge, 2, NULL,
400: ai_charge, 2, NULL,
401: ai_charge, 2, NULL,
402: ai_charge, 2, NULL,
403: ai_charge, 2, NULL,
404: ai_charge, 2, NULL,
405: ai_move, -5, Boss2Rocket,
406: ai_charge, 2, NULL,
407: ai_charge, 2, NULL,
408: ai_charge, 2, NULL,
409: ai_charge, 2, NULL,
410: ai_charge, 2, NULL,
411: ai_charge, 2, NULL,
412: ai_charge, 2, NULL,
413: ai_charge, 2, NULL
414: };
415: mmove_t boss2_move_attack_rocket = {FRAME_attack20, FRAME_attack40, boss2_frames_attack_rocket, boss2_run};
416:
417: mframe_t boss2_frames_pain_heavy [] =
418: {
419: ai_move, 0, NULL,
420: ai_move, 0, NULL,
421: ai_move, 0, NULL,
422: ai_move, 0, NULL,
423: ai_move, 0, NULL,
424: ai_move, 0, NULL,
425: ai_move, 0, NULL,
426: ai_move, 0, NULL,
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: ai_move, 0, NULL
437: };
438: mmove_t boss2_move_pain_heavy = {FRAME_pain2, FRAME_pain19, boss2_frames_pain_heavy, boss2_run};
439:
440: mframe_t boss2_frames_pain_light [] =
441: {
442: ai_move, 0, NULL,
443: ai_move, 0, NULL,
444: ai_move, 0, NULL,
445: ai_move, 0, NULL
446: };
447: mmove_t boss2_move_pain_light = {FRAME_pain20, FRAME_pain23, boss2_frames_pain_light, boss2_run};
448:
449: mframe_t boss2_frames_death [] =
450: {
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: ai_move, 0, NULL,
459: ai_move, 0, NULL,
460: ai_move, 0, NULL,
461: ai_move, 0, NULL,
462: ai_move, 0, NULL,
463: ai_move, 0, NULL,
464: ai_move, 0, NULL,
465: ai_move, 0, NULL,
466: ai_move, 0, NULL,
467: ai_move, 0, NULL,
468: ai_move, 0, NULL,
469: ai_move, 0, NULL,
470: ai_move, 0, NULL,
471: ai_move, 0, NULL,
472: ai_move, 0, NULL,
473: ai_move, 0, NULL,
474: ai_move, 0, NULL,
475: ai_move, 0, NULL,
476: ai_move, 0, NULL,
477: ai_move, 0, NULL,
478: ai_move, 0, NULL,
479: ai_move, 0, NULL,
480: ai_move, 0, NULL,
481: ai_move, 0, NULL,
482: ai_move, 0, NULL,
483: ai_move, 0, NULL,
484: ai_move, 0, NULL,
485: ai_move, 0, NULL,
486: ai_move, 0, NULL,
487: ai_move, 0, NULL,
488: ai_move, 0, NULL,
489: ai_move, 0, NULL,
490: ai_move, 0, NULL,
491: ai_move, 0, NULL,
492: ai_move, 0, NULL,
493: ai_move, 0, NULL,
494: ai_move, 0, NULL,
495: ai_move, 0, NULL,
496: ai_move, 0, NULL,
497: ai_move, 0, NULL,
498: ai_move, 0, NULL,
499: ai_move, 0, BossExplode
500: };
501: mmove_t boss2_move_death = {FRAME_death2, FRAME_death50, boss2_frames_death, boss2_dead};
502:
503: void boss2_stand (edict_t *self)
504: {
505: self->monsterinfo.currentmove = &boss2_move_stand;
506: }
507:
508: void boss2_run (edict_t *self)
509: {
510: if (self->monsterinfo.aiflags & AI_STAND_GROUND)
511: self->monsterinfo.currentmove = &boss2_move_stand;
512: else
513: self->monsterinfo.currentmove = &boss2_move_run;
514: }
515:
516: void boss2_walk (edict_t *self)
517: {
518: self->monsterinfo.currentmove = &boss2_move_walk;
519: }
520:
521: void boss2_attack (edict_t *self)
522: {
523: vec3_t vec;
524: float range;
525:
526: VectorSubtract (self->enemy->s.origin, self->s.origin, vec);
527: range = VectorLength (vec);
528:
529: if (range <= 125)
530: {
531: self->monsterinfo.currentmove = &boss2_move_attack_pre_mg;
532: }
533: else
534: {
535: if (random() <= 0.6)
536: self->monsterinfo.currentmove = &boss2_move_attack_pre_mg;
537: else
538: self->monsterinfo.currentmove = &boss2_move_attack_rocket;
539: }
540: }
541:
542: void boss2_attack_mg (edict_t *self)
543: {
544: self->monsterinfo.currentmove = &boss2_move_attack_mg;
545: }
546:
547: void boss2_reattack_mg (edict_t *self)
548: {
549: if ( infront(self, self->enemy) )
550: if (random() <= 0.7)
551: self->monsterinfo.currentmove = &boss2_move_attack_mg;
552: else
553: self->monsterinfo.currentmove = &boss2_move_attack_post_mg;
554: else
555: self->monsterinfo.currentmove = &boss2_move_attack_post_mg;
556: }
557:
558:
559: void boss2_pain (edict_t *self, edict_t *other, float kick, int damage)
560: {
561: if (self->health < (self->max_health / 2))
562: self->s.skinnum = 1;
563:
564: if (level.time < self->pain_debounce_time)
565: return;
566:
567: self->pain_debounce_time = level.time + 3;
568: // American wanted these at no attenuation
569: if (damage < 10)
570: {
571: gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NONE, 0);
572: self->monsterinfo.currentmove = &boss2_move_pain_light;
573: }
574: else if (damage < 30)
575: {
576: gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NONE, 0);
577: self->monsterinfo.currentmove = &boss2_move_pain_light;
578: }
579: else
580: {
581: gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NONE, 0);
582: self->monsterinfo.currentmove = &boss2_move_pain_heavy;
583: }
584: }
585:
586: void boss2_dead (edict_t *self)
587: {
588: VectorSet (self->mins, -56, -56, 0);
589: VectorSet (self->maxs, 56, 56, 80);
590: self->movetype = MOVETYPE_TOSS;
591: self->svflags |= SVF_DEADMONSTER;
592: self->nextthink = 0;
593: gi.linkentity (self);
594: }
595:
596: void boss2_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
597: {
598: gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NONE, 0);
599: self->deadflag = DEAD_DEAD;
600: self->takedamage = DAMAGE_NO;
601: self->count = 0;
602: self->monsterinfo.currentmove = &boss2_move_death;
603: #if 0
604: int n;
605:
606: self->s.sound = 0;
607: // check for gib
608: if (self->health <= self->gib_health)
609: {
610: gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
611: for (n= 0; n < 2; n++)
612: ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
613: for (n= 0; n < 4; n++)
614: ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
615: ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
616: self->deadflag = DEAD_DEAD;
617: return;
618: }
619:
620: if (self->deadflag == DEAD_DEAD)
621: return;
622:
623: self->deadflag = DEAD_DEAD;
624: self->takedamage = DAMAGE_YES;
625: self->monsterinfo.currentmove = &boss2_move_death;
626: #endif
627: }
628:
629: qboolean Boss2_CheckAttack (edict_t *self)
630: {
631: vec3_t spot1, spot2;
632: vec3_t temp;
633: float chance;
634: trace_t tr;
635: qboolean enemy_infront;
636: int enemy_range;
637: float enemy_yaw;
638:
639: if (self->enemy->health > 0)
640: {
641: // see if any entities are in the way of the shot
642: VectorCopy (self->s.origin, spot1);
643: spot1[2] += self->viewheight;
644: VectorCopy (self->enemy->s.origin, spot2);
645: spot2[2] += self->enemy->viewheight;
646:
647: tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA);
648:
649: // do we have a clear shot?
650: if (tr.ent != self->enemy)
651: {
652: // PGM - we want them to go ahead and shoot at info_notnulls if they can.
653: if(self->enemy->solid != SOLID_NOT || tr.fraction < 1.0) //PGM
654: return false;
655: }
656: }
657:
658: enemy_infront = infront(self, self->enemy);
659: enemy_range = range(self, self->enemy);
660: VectorSubtract (self->enemy->s.origin, self->s.origin, temp);
661: enemy_yaw = vectoyaw(temp);
662:
663: self->ideal_yaw = enemy_yaw;
664:
665:
666: // melee attack
667: if (enemy_range == RANGE_MELEE)
668: {
669: if (self->monsterinfo.melee)
670: self->monsterinfo.attack_state = AS_MELEE;
671: else
672: self->monsterinfo.attack_state = AS_MISSILE;
673: return true;
674: }
675:
676: // missile attack
677: if (!self->monsterinfo.attack)
678: return false;
679:
680: if (level.time < self->monsterinfo.attack_finished)
681: return false;
682:
683: if (enemy_range == RANGE_FAR)
684: return false;
685:
686: if (self->monsterinfo.aiflags & AI_STAND_GROUND)
687: {
688: chance = 0.4;
689: }
690: else if (enemy_range == RANGE_MELEE)
691: {
692: chance = 0.8;
693: }
694: else if (enemy_range == RANGE_NEAR)
695: {
696: chance = 0.8;
697: }
698: else if (enemy_range == RANGE_MID)
699: {
700: chance = 0.8;
701: }
702: else
703: {
704: return false;
705: }
706:
707: // PGM - go ahead and shoot every time if it's a info_notnull
708: if ((random () < chance) || (self->enemy->solid == SOLID_NOT))
709: {
710: self->monsterinfo.attack_state = AS_MISSILE;
711: self->monsterinfo.attack_finished = level.time + 2*random();
712: return true;
713: }
714:
715: if (self->flags & FL_FLY)
716: {
717: if (random() < 0.3)
718: self->monsterinfo.attack_state = AS_SLIDING;
719: else
720: self->monsterinfo.attack_state = AS_STRAIGHT;
721: }
722:
723: return false;
724: }
725:
726:
727:
728: /*QUAKED monster_boss2 (1 .5 0) (-56 -56 0) (56 56 80) Ambush Trigger_Spawn Sight
729: */
730: void SP_monster_boss2 (edict_t *self)
731: {
732: if (deathmatch->value)
733: {
734: G_FreeEdict (self);
735: return;
736: }
737:
738: sound_pain1 = gi.soundindex ("bosshovr/bhvpain1.wav");
739: sound_pain2 = gi.soundindex ("bosshovr/bhvpain2.wav");
740: sound_pain3 = gi.soundindex ("bosshovr/bhvpain3.wav");
741: sound_death = gi.soundindex ("bosshovr/bhvdeth1.wav");
742: sound_search1 = gi.soundindex ("bosshovr/bhvunqv1.wav");
743:
744: self->s.sound = gi.soundindex ("bosshovr/bhvengn1.wav");
745:
746: self->movetype = MOVETYPE_STEP;
747: self->solid = SOLID_BBOX;
748: self->s.modelindex = gi.modelindex ("models/monsters/boss2/tris.md2");
749: VectorSet (self->mins, -56, -56, 0);
750: VectorSet (self->maxs, 56, 56, 80);
751:
752: self->health = 2000;
753: self->gib_health = -200;
754: self->mass = 1000;
755:
756: self->yaw_speed = 50;
757:
758: self->flags |= FL_IMMUNE_LASER;
759:
760: self->pain = boss2_pain;
761: self->die = boss2_die;
762:
763: self->monsterinfo.stand = boss2_stand;
764: self->monsterinfo.walk = boss2_walk;
765: self->monsterinfo.run = boss2_run;
766: self->monsterinfo.attack = boss2_attack;
767: self->monsterinfo.search = boss2_search;
768: self->monsterinfo.checkattack = Boss2_CheckAttack;
769: gi.linkentity (self);
770:
771: self->monsterinfo.currentmove = &boss2_move_stand;
772: self->monsterinfo.scale = MODEL_SCALE;
773:
774: flymonster_start (self);
775: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.