1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20 /*
21 ==============================================================================
22
23 hover
24
25 ==============================================================================
26 */
27
28 #include "g_local.h"
29 #include "m_hover.h"
30
31 qboolean visible (edict_t *self, edict_t *other);
32
33
34 static int sound_pain1;
35 static int sound_pain2;
36 static int sound_death1;
37 static int sound_death2;
38 static int sound_sight;
39 static int sound_search1;
40 static int sound_search2;
41
42
hover_sight(edict_t * self,edict_t * other)43 void hover_sight (edict_t *self, edict_t *other)
44 {
45 gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
46 }
47
hover_search(edict_t * self)48 void hover_search (edict_t *self)
49 {
50 if (random() < 0.5)
51 gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NORM, 0);
52 else
53 gi.sound (self, CHAN_VOICE, sound_search2, 1, ATTN_NORM, 0);
54 }
55
56
57 void hover_run (edict_t *self);
58 void hover_stand (edict_t *self);
59 void hover_dead (edict_t *self);
60 void hover_attack (edict_t *self);
61 void hover_reattack (edict_t *self);
62 void hover_fire_blaster (edict_t *self);
63 void hover_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point);
64
65 mframe_t hover_frames_stand [] =
66 {
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 {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 };
98 mmove_t hover_move_stand = {FRAME_stand01, FRAME_stand30, hover_frames_stand, NULL};
99
100 mframe_t hover_frames_stop1 [] =
101 {
102 {ai_move, 0, NULL},
103 {ai_move, 0, NULL},
104 {ai_move, 0, NULL},
105 {ai_move, 0, NULL},
106 {ai_move, 0, NULL},
107 {ai_move, 0, NULL},
108 {ai_move, 0, NULL},
109 {ai_move, 0, NULL},
110 {ai_move, 0, NULL}
111 };
112 mmove_t hover_move_stop1 = {FRAME_stop101, FRAME_stop109, hover_frames_stop1, NULL};
113
114 mframe_t hover_frames_stop2 [] =
115 {
116 {ai_move, 0, NULL},
117 {ai_move, 0, NULL},
118 {ai_move, 0, NULL},
119 {ai_move, 0, NULL},
120 {ai_move, 0, NULL},
121 {ai_move, 0, NULL},
122 {ai_move, 0, NULL},
123 {ai_move, 0, NULL}
124 };
125 mmove_t hover_move_stop2 = {FRAME_stop201, FRAME_stop208, hover_frames_stop2, NULL};
126
127 mframe_t hover_frames_takeoff [] =
128 {
129 {ai_move, 0, NULL},
130 {ai_move, -2, NULL},
131 {ai_move, 5, NULL},
132 {ai_move, -1, NULL},
133 {ai_move, 1, NULL},
134 {ai_move, 0, NULL},
135 {ai_move, 0, NULL},
136 {ai_move, -1, NULL},
137 {ai_move, -1, NULL},
138 {ai_move, -1, NULL},
139 {ai_move, 0, NULL},
140 {ai_move, 2, NULL},
141 {ai_move, 2, NULL},
142 {ai_move, 1, NULL},
143 {ai_move, 1, NULL},
144 {ai_move, -6, NULL},
145 {ai_move, -9, NULL},
146 {ai_move, 1, NULL},
147 {ai_move, 0, NULL},
148 {ai_move, 2, NULL},
149 {ai_move, 2, NULL},
150 {ai_move, 1, NULL},
151 {ai_move, 1, NULL},
152 {ai_move, 1, NULL},
153 {ai_move, 2, NULL},
154 {ai_move, 0, NULL},
155 {ai_move, 2, NULL},
156 {ai_move, 3, NULL},
157 {ai_move, 2, NULL},
158 {ai_move, 0, NULL}
159 };
160 mmove_t hover_move_takeoff = {FRAME_takeof01, FRAME_takeof30, hover_frames_takeoff, NULL};
161
162 mframe_t hover_frames_pain3 [] =
163 {
164 {ai_move, 0, NULL},
165 {ai_move, 0, NULL},
166 {ai_move, 0, NULL},
167 {ai_move, 0, NULL},
168 {ai_move, 0, NULL},
169 {ai_move, 0, NULL},
170 {ai_move, 0, NULL},
171 {ai_move, 0, NULL},
172 {ai_move, 0, NULL}
173 };
174 mmove_t hover_move_pain3 = {FRAME_pain301, FRAME_pain309, hover_frames_pain3, hover_run};
175
176 mframe_t hover_frames_pain2 [] =
177 {
178 {ai_move, 0, NULL},
179 {ai_move, 0, NULL},
180 {ai_move, 0, NULL},
181 {ai_move, 0, NULL},
182 {ai_move, 0, NULL},
183 {ai_move, 0, NULL},
184 {ai_move, 0, NULL},
185 {ai_move, 0, NULL},
186 {ai_move, 0, NULL},
187 {ai_move, 0, NULL},
188 {ai_move, 0, NULL},
189 {ai_move, 0, NULL}
190 };
191 mmove_t hover_move_pain2 = {FRAME_pain201, FRAME_pain212, hover_frames_pain2, hover_run};
192
193 mframe_t hover_frames_pain1 [] =
194 {
195 {ai_move, 0, NULL},
196 {ai_move, 0, NULL},
197 {ai_move, 2, NULL},
198 {ai_move, -8, NULL},
199 {ai_move, -4, NULL},
200 {ai_move, -6, NULL},
201 {ai_move, -4, NULL},
202 {ai_move, -3, NULL},
203 {ai_move, 1, NULL},
204 {ai_move, 0, NULL},
205 {ai_move, 0, NULL},
206 {ai_move, 0, NULL},
207 {ai_move, 3, NULL},
208 {ai_move, 1, NULL},
209 {ai_move, 0, NULL},
210 {ai_move, 2, NULL},
211 {ai_move, 3, NULL},
212 {ai_move, 2, NULL},
213 {ai_move, 7, NULL},
214 {ai_move, 1, NULL},
215 {ai_move, 0, NULL},
216 {ai_move, 0, NULL},
217 {ai_move, 2, NULL},
218 {ai_move, 0, NULL},
219 {ai_move, 0, NULL},
220 {ai_move, 5, NULL},
221 {ai_move, 3, NULL},
222 {ai_move, 4, NULL}
223 };
224 mmove_t hover_move_pain1 = {FRAME_pain101, FRAME_pain128, hover_frames_pain1, hover_run};
225
226 mframe_t hover_frames_land [] =
227 {
228 {ai_move, 0, NULL}
229 };
230 mmove_t hover_move_land = {FRAME_land01, FRAME_land01, hover_frames_land, NULL};
231
232 mframe_t hover_frames_forward [] =
233 {
234 {ai_move, 0, NULL},
235 {ai_move, 0, NULL},
236 {ai_move, 0, NULL},
237 {ai_move, 0, NULL},
238 {ai_move, 0, NULL},
239 {ai_move, 0, NULL},
240 {ai_move, 0, NULL},
241 {ai_move, 0, NULL},
242 {ai_move, 0, NULL},
243 {ai_move, 0, NULL},
244 {ai_move, 0, NULL},
245 {ai_move, 0, NULL},
246 {ai_move, 0, NULL},
247 {ai_move, 0, NULL},
248 {ai_move, 0, NULL},
249 {ai_move, 0, NULL},
250 {ai_move, 0, NULL},
251 {ai_move, 0, NULL},
252 {ai_move, 0, NULL},
253 {ai_move, 0, NULL},
254 {ai_move, 0, NULL},
255 {ai_move, 0, NULL},
256 {ai_move, 0, NULL},
257 {ai_move, 0, NULL},
258 {ai_move, 0, NULL},
259 {ai_move, 0, NULL},
260 {ai_move, 0, NULL},
261 {ai_move, 0, NULL},
262 {ai_move, 0, NULL},
263 {ai_move, 0, NULL},
264 {ai_move, 0, NULL},
265 {ai_move, 0, NULL},
266 {ai_move, 0, NULL},
267 {ai_move, 0, NULL},
268 {ai_move, 0, NULL}
269 };
270 mmove_t hover_move_forward = {FRAME_forwrd01, FRAME_forwrd35, hover_frames_forward, NULL};
271
272 mframe_t hover_frames_walk [] =
273 {
274 {ai_walk, 4, NULL},
275 {ai_walk, 4, NULL},
276 {ai_walk, 4, NULL},
277 {ai_walk, 4, NULL},
278 {ai_walk, 4, NULL},
279 {ai_walk, 4, NULL},
280 {ai_walk, 4, NULL},
281 {ai_walk, 4, NULL},
282 {ai_walk, 4, NULL},
283 {ai_walk, 4, NULL},
284 {ai_walk, 4, NULL},
285 {ai_walk, 4, NULL},
286 {ai_walk, 4, NULL},
287 {ai_walk, 4, NULL},
288 {ai_walk, 4, NULL},
289 {ai_walk, 4, NULL},
290 {ai_walk, 4, NULL},
291 {ai_walk, 4, NULL},
292 {ai_walk, 4, NULL},
293 {ai_walk, 4, NULL},
294 {ai_walk, 4, NULL},
295 {ai_walk, 4, NULL},
296 {ai_walk, 4, NULL},
297 {ai_walk, 4, NULL},
298 {ai_walk, 4, NULL},
299 {ai_walk, 4, NULL},
300 {ai_walk, 4, NULL},
301 {ai_walk, 4, NULL},
302 {ai_walk, 4, NULL},
303 {ai_walk, 4, NULL},
304 {ai_walk, 4, NULL},
305 {ai_walk, 4, NULL},
306 {ai_walk, 4, NULL},
307 {ai_walk, 4, NULL},
308 {ai_walk, 4, NULL}
309 };
310 mmove_t hover_move_walk = {FRAME_forwrd01, FRAME_forwrd35, hover_frames_walk, NULL};
311
312 mframe_t hover_frames_run [] =
313 {
314 {ai_run, 10, NULL},
315 {ai_run, 10, NULL},
316 {ai_run, 10, NULL},
317 {ai_run, 10, NULL},
318 {ai_run, 10, NULL},
319 {ai_run, 10, NULL},
320 {ai_run, 10, NULL},
321 {ai_run, 10, NULL},
322 {ai_run, 10, NULL},
323 {ai_run, 10, NULL},
324 {ai_run, 10, NULL},
325 {ai_run, 10, NULL},
326 {ai_run, 10, NULL},
327 {ai_run, 10, NULL},
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 {ai_run, 10, NULL}
349 };
350 mmove_t hover_move_run = {FRAME_forwrd01, FRAME_forwrd35, hover_frames_run, NULL};
351
352 mframe_t hover_frames_death1 [] =
353 {
354 {ai_move, 0, NULL},
355 {ai_move, 0, NULL},
356 {ai_move, 0, NULL},
357 {ai_move, 0, NULL},
358 {ai_move, 0, NULL},
359 {ai_move, 0, NULL},
360 {ai_move, -10,NULL},
361 {ai_move, 3, NULL},
362 {ai_move, 5, NULL},
363 {ai_move, 4, NULL},
364 {ai_move, 7, NULL}
365 };
366 mmove_t hover_move_death1 = {FRAME_death101, FRAME_death111, hover_frames_death1, hover_dead};
367
368 mframe_t hover_frames_backward [] =
369 {
370 {ai_move, 0, NULL},
371 {ai_move, 0, NULL},
372 {ai_move, 0, NULL},
373 {ai_move, 0, NULL},
374 {ai_move, 0, NULL},
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 {ai_move, 0, NULL},
385 {ai_move, 0, NULL},
386 {ai_move, 0, NULL},
387 {ai_move, 0, NULL},
388 {ai_move, 0, NULL},
389 {ai_move, 0, NULL},
390 {ai_move, 0, NULL},
391 {ai_move, 0, NULL},
392 {ai_move, 0, NULL},
393 {ai_move, 0, NULL}
394 };
395 mmove_t hover_move_backward = {FRAME_backwd01, FRAME_backwd24, hover_frames_backward, NULL};
396
397 mframe_t hover_frames_start_attack [] =
398 {
399 {ai_charge, 1, NULL},
400 {ai_charge, 1, NULL},
401 {ai_charge, 1, NULL}
402 };
403 mmove_t hover_move_start_attack = {FRAME_attak101, FRAME_attak103, hover_frames_start_attack, hover_attack};
404
405 mframe_t hover_frames_attack1 [] =
406 {
407 {ai_charge, -10, hover_fire_blaster},
408 {ai_charge, -10, hover_fire_blaster},
409 {ai_charge, 0, hover_reattack},
410 };
411 mmove_t hover_move_attack1 = {FRAME_attak104, FRAME_attak106, hover_frames_attack1, NULL};
412
413
414 mframe_t hover_frames_end_attack [] =
415 {
416 {ai_charge, 1, NULL},
417 {ai_charge, 1, NULL}
418 };
419 mmove_t hover_move_end_attack = {FRAME_attak107, FRAME_attak108, hover_frames_end_attack, hover_run};
420
hover_reattack(edict_t * self)421 void hover_reattack (edict_t *self)
422 {
423 if (self->enemy->health > 0 )
424 if (visible (self, self->enemy) )
425 if (random() <= 0.6)
426 {
427 self->monsterinfo.currentmove = &hover_move_attack1;
428 return;
429 }
430 self->monsterinfo.currentmove = &hover_move_end_attack;
431 }
432
433
hover_fire_blaster(edict_t * self)434 void hover_fire_blaster (edict_t *self)
435 {
436 vec3_t start;
437 vec3_t forward, right;
438 vec3_t end;
439 vec3_t dir;
440 int effect;
441
442 if (self->s.frame == FRAME_attak104)
443 effect = EF_HYPERBLASTER;
444 else
445 effect = 0;
446
447 AngleVectors (self->s.angles, forward, right, NULL);
448 G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_HOVER_BLASTER_1], forward, right, start);
449
450 VectorCopy (self->enemy->s.origin, end);
451 end[2] += self->enemy->viewheight;
452 VectorSubtract (end, start, dir);
453
454 monster_fire_blaster (self, start, dir, 1, 1000, MZ2_HOVER_BLASTER_1, effect);
455 }
456
457
hover_stand(edict_t * self)458 void hover_stand (edict_t *self)
459 {
460 self->monsterinfo.currentmove = &hover_move_stand;
461 }
462
hover_run(edict_t * self)463 void hover_run (edict_t *self)
464 {
465 if (self->monsterinfo.aiflags & AI_STAND_GROUND)
466 self->monsterinfo.currentmove = &hover_move_stand;
467 else
468 self->monsterinfo.currentmove = &hover_move_run;
469 }
470
hover_walk(edict_t * self)471 void hover_walk (edict_t *self)
472 {
473 self->monsterinfo.currentmove = &hover_move_walk;
474 }
475
hover_start_attack(edict_t * self)476 void hover_start_attack (edict_t *self)
477 {
478 self->monsterinfo.currentmove = &hover_move_start_attack;
479 }
480
hover_attack(edict_t * self)481 void hover_attack(edict_t *self)
482 {
483 self->monsterinfo.currentmove = &hover_move_attack1;
484 }
485
486
hover_pain(edict_t * self,edict_t * other,float kick,int damage)487 void hover_pain (edict_t *self, edict_t *other, float kick, int damage)
488 {
489 if (self->health < (self->max_health / 2))
490 self->s.skinnum = 1;
491
492 if (level.time < self->pain_debounce_time)
493 return;
494
495 self->pain_debounce_time = level.time + 3;
496
497 if (skill->value == 3)
498 return; // no pain anims in nightmare
499
500 if (damage <= 25)
501 {
502 if (random() < 0.5)
503 {
504 gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
505 self->monsterinfo.currentmove = &hover_move_pain3;
506 }
507 else
508 {
509 gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
510 self->monsterinfo.currentmove = &hover_move_pain2;
511 }
512 }
513 else
514 {
515 gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
516 self->monsterinfo.currentmove = &hover_move_pain1;
517 }
518 }
519
hover_deadthink(edict_t * self)520 void hover_deadthink (edict_t *self)
521 {
522 if (!self->groundentity && level.time < self->timestamp)
523 {
524 self->nextthink = level.time + FRAMETIME;
525 return;
526 }
527 BecomeExplosion1(self);
528 }
529
hover_dead(edict_t * self)530 void hover_dead (edict_t *self)
531 {
532 VectorSet (self->mins, -16, -16, -24);
533 VectorSet (self->maxs, 16, 16, -8);
534 self->movetype = MOVETYPE_TOSS;
535 self->think = hover_deadthink;
536 self->nextthink = level.time + FRAMETIME;
537 self->timestamp = level.time + 15;
538 gi.linkentity (self);
539 }
540
hover_die(edict_t * self,edict_t * inflictor,edict_t * attacker,int damage,vec3_t point)541 void hover_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
542 {
543 int n;
544
545 // check for gib
546 if (self->health <= self->gib_health)
547 {
548 gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
549 for (n= 0; n < 2; n++)
550 ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
551 for (n= 0; n < 2; n++)
552 ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
553 ThrowHead (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
554 self->deadflag = DEAD_DEAD;
555 return;
556 }
557
558 if (self->deadflag == DEAD_DEAD)
559 return;
560
561 // regular death
562 if (random() < 0.5)
563 gi.sound (self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0);
564 else
565 gi.sound (self, CHAN_VOICE, sound_death2, 1, ATTN_NORM, 0);
566 self->deadflag = DEAD_DEAD;
567 self->takedamage = DAMAGE_YES;
568 self->monsterinfo.currentmove = &hover_move_death1;
569 }
570
571 /*QUAKED monster_hover (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
572 */
SP_monster_hover(edict_t * self)573 void SP_monster_hover (edict_t *self)
574 {
575 if (deathmatch->value)
576 {
577 G_FreeEdict (self);
578 return;
579 }
580
581 sound_pain1 = gi.soundindex ("hover/hovpain1.wav");
582 sound_pain2 = gi.soundindex ("hover/hovpain2.wav");
583 sound_death1 = gi.soundindex ("hover/hovdeth1.wav");
584 sound_death2 = gi.soundindex ("hover/hovdeth2.wav");
585 sound_sight = gi.soundindex ("hover/hovsght1.wav");
586 sound_search1 = gi.soundindex ("hover/hovsrch1.wav");
587 sound_search2 = gi.soundindex ("hover/hovsrch2.wav");
588
589 gi.soundindex ("hover/hovatck1.wav");
590
591 self->s.sound = gi.soundindex ("hover/hovidle1.wav");
592
593 self->movetype = MOVETYPE_STEP;
594 self->solid = SOLID_BBOX;
595 self->s.modelindex = gi.modelindex("models/monsters/hover/tris.md2");
596 VectorSet (self->mins, -24, -24, -24);
597 VectorSet (self->maxs, 24, 24, 32);
598
599 self->health = 240;
600 self->gib_health = -100;
601 self->mass = 150;
602
603 self->pain = hover_pain;
604 self->die = hover_die;
605
606 self->monsterinfo.stand = hover_stand;
607 self->monsterinfo.walk = hover_walk;
608 self->monsterinfo.run = hover_run;
609 // self->monsterinfo.dodge = hover_dodge;
610 self->monsterinfo.attack = hover_start_attack;
611 self->monsterinfo.sight = hover_sight;
612 self->monsterinfo.search = hover_search;
613
614 gi.linkentity (self);
615
616 self->monsterinfo.currentmove = &hover_move_stand;
617 self->monsterinfo.scale = MODEL_SCALE;
618
619 flymonster_start (self);
620 }
621