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