File: game\m_hover.c
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
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
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
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
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
458 void hover_stand (edict_t *self)
459 {
460 self->monsterinfo.currentmove = &hover_move_stand;
461 }
462
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
471 void hover_walk (edict_t *self)
472 {
473 self->monsterinfo.currentmove = &hover_move_walk;
474 }
475
476 void hover_start_attack (edict_t *self)
477 {
478 self->monsterinfo.currentmove = &hover_move_start_attack;
479 }
480
481 void hover_attack(edict_t *self)
482 {
483 self->monsterinfo.currentmove = &hover_move_attack1;
484 }
485
486
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
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
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
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 */
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