1 /*
2 ==============================================================================
3
4 hover
5
6 ==============================================================================
7 */
8
9 #include "g_local.h"
10 #include "m_hover.h"
11
12 qboolean visible (edict_t *self, edict_t *other);
13
14
15 static int sound_pain1;
16 static int sound_pain2;
17 static int sound_death1;
18 static int sound_death2;
19 static int sound_sight;
20 static int sound_search1;
21 static int sound_search2;
22
23
hover_sight(edict_t * self,edict_t * other)24 void hover_sight (edict_t *self, edict_t *other)
25 {
26 gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
27 }
28
hover_search(edict_t * self)29 void hover_search (edict_t *self)
30 {
31 if (random() < 0.5)
32 gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NORM, 0);
33 else
34 gi.sound (self, CHAN_VOICE, sound_search2, 1, ATTN_NORM, 0);
35 }
36
37
38 void hover_run (edict_t *self);
39 void hover_stand (edict_t *self);
40 void hover_dead (edict_t *self);
41 void hover_attack (edict_t *self);
42 void hover_reattack (edict_t *self);
43 void hover_fire_blaster (edict_t *self);
44 void hover_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point);
45
46 mframe_t hover_frames_stand [] =
47 {
48 ai_stand, 0, NULL,
49 ai_stand, 0, NULL,
50 ai_stand, 0, NULL,
51 ai_stand, 0, NULL,
52 ai_stand, 0, NULL,
53 ai_stand, 0, NULL,
54 ai_stand, 0, NULL,
55 ai_stand, 0, NULL,
56 ai_stand, 0, NULL,
57 ai_stand, 0, NULL,
58 ai_stand, 0, NULL,
59 ai_stand, 0, NULL,
60 ai_stand, 0, NULL,
61 ai_stand, 0, NULL,
62 ai_stand, 0, NULL,
63 ai_stand, 0, NULL,
64 ai_stand, 0, NULL,
65 ai_stand, 0, NULL,
66 ai_stand, 0, NULL,
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 };
79 mmove_t hover_move_stand = {FRAME_stand01, FRAME_stand30, hover_frames_stand, NULL};
80
81 mframe_t hover_frames_stop1 [] =
82 {
83 ai_move, 0, NULL,
84 ai_move, 0, NULL,
85 ai_move, 0, NULL,
86 ai_move, 0, NULL,
87 ai_move, 0, NULL,
88 ai_move, 0, NULL,
89 ai_move, 0, NULL,
90 ai_move, 0, NULL,
91 ai_move, 0, NULL
92 };
93 mmove_t hover_move_stop1 = {FRAME_stop101, FRAME_stop109, hover_frames_stop1, NULL};
94
95 mframe_t hover_frames_stop2 [] =
96 {
97 ai_move, 0, NULL,
98 ai_move, 0, NULL,
99 ai_move, 0, NULL,
100 ai_move, 0, NULL,
101 ai_move, 0, NULL,
102 ai_move, 0, NULL,
103 ai_move, 0, NULL,
104 ai_move, 0, NULL
105 };
106 mmove_t hover_move_stop2 = {FRAME_stop201, FRAME_stop208, hover_frames_stop2, NULL};
107
108 mframe_t hover_frames_takeoff [] =
109 {
110 ai_move, 0, NULL,
111 ai_move, -2, NULL,
112 ai_move, 5, NULL,
113 ai_move, -1, NULL,
114 ai_move, 1, NULL,
115 ai_move, 0, NULL,
116 ai_move, 0, NULL,
117 ai_move, -1, NULL,
118 ai_move, -1, NULL,
119 ai_move, -1, NULL,
120 ai_move, 0, NULL,
121 ai_move, 2, NULL,
122 ai_move, 2, NULL,
123 ai_move, 1, NULL,
124 ai_move, 1, NULL,
125 ai_move, -6, NULL,
126 ai_move, -9, NULL,
127 ai_move, 1, NULL,
128 ai_move, 0, NULL,
129 ai_move, 2, NULL,
130 ai_move, 2, NULL,
131 ai_move, 1, NULL,
132 ai_move, 1, NULL,
133 ai_move, 1, NULL,
134 ai_move, 2, NULL,
135 ai_move, 0, NULL,
136 ai_move, 2, NULL,
137 ai_move, 3, NULL,
138 ai_move, 2, NULL,
139 ai_move, 0, NULL
140 };
141 mmove_t hover_move_takeoff = {FRAME_takeof01, FRAME_takeof30, hover_frames_takeoff, NULL};
142
143 mframe_t hover_frames_pain3 [] =
144 {
145 ai_move, 0, NULL,
146 ai_move, 0, NULL,
147 ai_move, 0, NULL,
148 ai_move, 0, NULL,
149 ai_move, 0, NULL,
150 ai_move, 0, NULL,
151 ai_move, 0, NULL,
152 ai_move, 0, NULL,
153 ai_move, 0, NULL
154 };
155 mmove_t hover_move_pain3 = {FRAME_pain301, FRAME_pain309, hover_frames_pain3, hover_run};
156
157 mframe_t hover_frames_pain2 [] =
158 {
159 ai_move, 0, NULL,
160 ai_move, 0, NULL,
161 ai_move, 0, NULL,
162 ai_move, 0, NULL,
163 ai_move, 0, NULL,
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 };
172 mmove_t hover_move_pain2 = {FRAME_pain201, FRAME_pain212, hover_frames_pain2, hover_run};
173
174 mframe_t hover_frames_pain1 [] =
175 {
176 ai_move, 0, NULL,
177 ai_move, 0, NULL,
178 ai_move, 2, NULL,
179 ai_move, -8, NULL,
180 ai_move, -4, NULL,
181 ai_move, -6, NULL,
182 ai_move, -4, NULL,
183 ai_move, -3, NULL,
184 ai_move, 1, NULL,
185 ai_move, 0, NULL,
186 ai_move, 0, NULL,
187 ai_move, 0, NULL,
188 ai_move, 3, NULL,
189 ai_move, 1, NULL,
190 ai_move, 0, NULL,
191 ai_move, 2, NULL,
192 ai_move, 3, NULL,
193 ai_move, 2, NULL,
194 ai_move, 7, NULL,
195 ai_move, 1, NULL,
196 ai_move, 0, NULL,
197 ai_move, 0, NULL,
198 ai_move, 2, NULL,
199 ai_move, 0, NULL,
200 ai_move, 0, NULL,
201 ai_move, 5, NULL,
202 ai_move, 3, NULL,
203 ai_move, 4, NULL
204 };
205 mmove_t hover_move_pain1 = {FRAME_pain101, FRAME_pain128, hover_frames_pain1, hover_run};
206
207 mframe_t hover_frames_land [] =
208 {
209 ai_move, 0, NULL
210 };
211 mmove_t hover_move_land = {FRAME_land01, FRAME_land01, hover_frames_land, NULL};
212
213 mframe_t hover_frames_forward [] =
214 {
215 ai_move, 0, NULL,
216 ai_move, 0, NULL,
217 ai_move, 0, NULL,
218 ai_move, 0, NULL,
219 ai_move, 0, NULL,
220 ai_move, 0, NULL,
221 ai_move, 0, NULL,
222 ai_move, 0, NULL,
223 ai_move, 0, NULL,
224 ai_move, 0, NULL,
225 ai_move, 0, NULL,
226 ai_move, 0, NULL,
227 ai_move, 0, NULL,
228 ai_move, 0, NULL,
229 ai_move, 0, NULL,
230 ai_move, 0, NULL,
231 ai_move, 0, NULL,
232 ai_move, 0, NULL,
233 ai_move, 0, NULL,
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 };
251 mmove_t hover_move_forward = {FRAME_forwrd01, FRAME_forwrd35, hover_frames_forward, NULL};
252
253 mframe_t hover_frames_walk [] =
254 {
255 ai_walk, 4, NULL,
256 ai_walk, 4, NULL,
257 ai_walk, 4, NULL,
258 ai_walk, 4, NULL,
259 ai_walk, 4, NULL,
260 ai_walk, 4, NULL,
261 ai_walk, 4, NULL,
262 ai_walk, 4, NULL,
263 ai_walk, 4, NULL,
264 ai_walk, 4, NULL,
265 ai_walk, 4, NULL,
266 ai_walk, 4, NULL,
267 ai_walk, 4, NULL,
268 ai_walk, 4, NULL,
269 ai_walk, 4, NULL,
270 ai_walk, 4, NULL,
271 ai_walk, 4, NULL,
272 ai_walk, 4, NULL,
273 ai_walk, 4, NULL,
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 };
291 mmove_t hover_move_walk = {FRAME_forwrd01, FRAME_forwrd35, hover_frames_walk, NULL};
292
293 mframe_t hover_frames_run [] =
294 {
295 ai_run, 10, NULL,
296 ai_run, 10, NULL,
297 ai_run, 10, NULL,
298 ai_run, 10, NULL,
299 ai_run, 10, NULL,
300 ai_run, 10, NULL,
301 ai_run, 10, NULL,
302 ai_run, 10, NULL,
303 ai_run, 10, NULL,
304 ai_run, 10, NULL,
305 ai_run, 10, NULL,
306 ai_run, 10, NULL,
307 ai_run, 10, NULL,
308 ai_run, 10, NULL,
309 ai_run, 10, NULL,
310 ai_run, 10, NULL,
311 ai_run, 10, NULL,
312 ai_run, 10, NULL,
313 ai_run, 10, NULL,
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 };
331 mmove_t hover_move_run = {FRAME_forwrd01, FRAME_forwrd35, hover_frames_run, NULL};
332
333 mframe_t hover_frames_death1 [] =
334 {
335 ai_move, 0, NULL,
336 ai_move, 0, NULL,
337 ai_move, 0, NULL,
338 ai_move, 0, NULL,
339 ai_move, 0, NULL,
340 ai_move, 0, NULL,
341 ai_move, -10,NULL,
342 ai_move, 3, NULL,
343 ai_move, 5, NULL,
344 ai_move, 4, NULL,
345 ai_move, 7, NULL
346 };
347 mmove_t hover_move_death1 = {FRAME_death101, FRAME_death111, hover_frames_death1, hover_dead};
348
349 mframe_t hover_frames_backward [] =
350 {
351 ai_move, 0, NULL,
352 ai_move, 0, NULL,
353 ai_move, 0, NULL,
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, 0, NULL,
361 ai_move, 0, NULL,
362 ai_move, 0, NULL,
363 ai_move, 0, NULL,
364 ai_move, 0, NULL,
365 ai_move, 0, NULL,
366 ai_move, 0, NULL,
367 ai_move, 0, NULL,
368 ai_move, 0, NULL,
369 ai_move, 0, NULL,
370 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 };
376 mmove_t hover_move_backward = {FRAME_backwd01, FRAME_backwd24, hover_frames_backward, NULL};
377
378 mframe_t hover_frames_start_attack [] =
379 {
380 ai_charge, 1, NULL,
381 ai_charge, 1, NULL,
382 ai_charge, 1, NULL
383 };
384 mmove_t hover_move_start_attack = {FRAME_attak101, FRAME_attak103, hover_frames_start_attack, hover_attack};
385
386 mframe_t hover_frames_attack1 [] =
387 {
388 ai_charge, -10, hover_fire_blaster,
389 ai_charge, -10, hover_fire_blaster,
390 ai_charge, 0, hover_reattack,
391 };
392 mmove_t hover_move_attack1 = {FRAME_attak104, FRAME_attak106, hover_frames_attack1, NULL};
393
394
395 mframe_t hover_frames_end_attack [] =
396 {
397 ai_charge, 1, NULL,
398 ai_charge, 1, NULL
399 };
400 mmove_t hover_move_end_attack = {FRAME_attak107, FRAME_attak108, hover_frames_end_attack, hover_run};
401
hover_reattack(edict_t * self)402 void hover_reattack (edict_t *self)
403 {
404 if (self->enemy->health > 0 )
405 if (visible (self, self->enemy) )
406 if (random() <= 0.6)
407 {
408 self->monsterinfo.currentmove = &hover_move_attack1;
409 return;
410 }
411 self->monsterinfo.currentmove = &hover_move_end_attack;
412 }
413
414
hover_fire_blaster(edict_t * self)415 void hover_fire_blaster (edict_t *self)
416 {
417 vec3_t start;
418 vec3_t forward, right;
419 vec3_t end;
420 vec3_t dir;
421 int effect;
422
423 AngleVectors (self->s.angles, forward, right, NULL);
424 G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_HOVER_BLASTER_1], forward, right, start);
425
426 VectorCopy (self->enemy->s.origin, end);
427 end[2] += self->enemy->viewheight;
428 VectorSubtract (end, start, dir);
429
430 monster_fire_blaster (self, start, dir, 50, 1000, MZ2_HOVER_BLASTER_1, (sv_serversideonly->value)?EF_BLASTER:0);
431 }
432
433
hover_stand(edict_t * self)434 void hover_stand (edict_t *self)
435 {
436 self->monsterinfo.currentmove = &hover_move_stand;
437 }
438
hover_run(edict_t * self)439 void hover_run (edict_t *self)
440 {
441 if (self->monsterinfo.aiflags & AI_STAND_GROUND)
442 self->monsterinfo.currentmove = &hover_move_stand;
443 else
444 self->monsterinfo.currentmove = &hover_move_run;
445 }
446
hover_walk(edict_t * self)447 void hover_walk (edict_t *self)
448 {
449 self->monsterinfo.currentmove = &hover_move_walk;
450 }
451
hover_start_attack(edict_t * self)452 void hover_start_attack (edict_t *self)
453 {
454 self->monsterinfo.currentmove = &hover_move_start_attack;
455 }
456
hover_attack(edict_t * self)457 void hover_attack(edict_t *self)
458 {
459 self->monsterinfo.currentmove = &hover_move_attack1;
460 }
461
462
hover_pain(edict_t * self,edict_t * other,float kick,int damage)463 void hover_pain (edict_t *self, edict_t *other, float kick, int damage)
464 {
465 if (self->health < (self->max_health / 2))
466 self->s.skinnum = 1;
467
468 if (level.time < self->pain_debounce_time)
469 return;
470
471 self->pain_debounce_time = level.time + 3;
472
473 if (skill->value == 3)
474 return; // no pain anims in nightmare
475
476 if (damage <= 25)
477 {
478 if (random() < 0.5)
479 {
480 gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
481 self->monsterinfo.currentmove = &hover_move_pain3;
482 }
483 else
484 {
485 gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
486 self->monsterinfo.currentmove = &hover_move_pain2;
487 }
488 }
489 else
490 {
491 gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
492 self->monsterinfo.currentmove = &hover_move_pain1;
493 }
494 }
495
hover_deadthink(edict_t * self)496 void hover_deadthink (edict_t *self)
497 {
498 if (!self->groundentity && level.time < self->timestamp)
499 {
500 self->nextthink = level.time + FRAMETIME;
501 return;
502 }
503 BecomeExplosion1(self);
504 }
505
hover_dead(edict_t * self)506 void hover_dead (edict_t *self)
507 {
508 VectorSet (self->mins, -16, -16, -24);
509 VectorSet (self->maxs, 16, 16, -8);
510 self->movetype = MOVETYPE_TOSS;
511 self->think = hover_deadthink;
512 self->nextthink = level.time + FRAMETIME;
513 self->timestamp = level.time + 15;
514 gi.linkentity (self);
515 }
516
hover_die(edict_t * self,edict_t * inflictor,edict_t * attacker,int damage,vec3_t point)517 void hover_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
518 {
519 int n;
520
521 // check for gib
522 if (self->health <= self->gib_health)
523 {
524 gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
525 for (n= 0; n < 2; n++)
526 ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
527 for (n= 0; n < 2; n++)
528 ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
529 ThrowHead (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
530 self->deadflag = DEAD_DEAD;
531 return;
532 }
533
534 if (self->deadflag == DEAD_DEAD)
535 return;
536
537 // regular death
538 if (random() < 0.5)
539 gi.sound (self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0);
540 else
541 gi.sound (self, CHAN_VOICE, sound_death2, 1, ATTN_NORM, 0);
542 self->deadflag = DEAD_DEAD;
543 self->takedamage = DAMAGE_YES;
544 self->monsterinfo.currentmove = &hover_move_death1;
545 }
546
547 /*QUAKED monster_hover (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
548 */
SP_monster_hover(edict_t * self)549 void SP_monster_hover (edict_t *self)
550 {
551 if (deathmatch->value)
552 {
553 G_FreeEdict (self);
554 return;
555 }
556
557 sound_pain1 = gi.soundindex ("hover/hovpain1.wav");
558 sound_pain2 = gi.soundindex ("hover/hovpain2.wav");
559 sound_death1 = gi.soundindex ("hover/hovdeth1.wav");
560 sound_death2 = gi.soundindex ("hover/hovdeth2.wav");
561 sound_sight = gi.soundindex ("hover/hovsght1.wav");
562 sound_search1 = gi.soundindex ("hover/hovsrch1.wav");
563 sound_search2 = gi.soundindex ("hover/hovsrch2.wav");
564
565 gi.soundindex ("hover/hovatck1.wav");
566
567 self->s.sound = gi.soundindex ("hover/hovidle1.wav");
568
569 self->movetype = MOVETYPE_STEP;
570 self->solid = SOLID_BBOX;
571 self->s.modelindex = gi.modelindex("models/monsters/hover/tris.md2");
572 VectorSet (self->mins, -24, -24, -24);
573 VectorSet (self->maxs, 24, 24, 32);
574
575 self->health = 240;
576 self->gib_health = -100;
577 self->mass = 150;
578
579 self->max_health = self->health;
580
581 self->pain = hover_pain;
582 self->die = hover_die;
583
584 self->monsterinfo.stand = hover_stand;
585 self->monsterinfo.walk = hover_walk;
586 self->monsterinfo.run = hover_run;
587 // self->monsterinfo.dodge = hover_dodge;
588 self->monsterinfo.attack = hover_start_attack;
589 self->monsterinfo.sight = hover_sight;
590 self->monsterinfo.search = hover_search;
591
592 gi.linkentity (self);
593
594 self->monsterinfo.currentmove = &hover_move_stand;
595 self->monsterinfo.scale = MODEL_SCALE;
596
597 flymonster_start (self);
598 }
599