1 /*
2 ==============================================================================
3
4 floater
5
6 ==============================================================================
7 */
8
9 #include "g_local.h"
10 #include "m_float.h"
11
12
13 static int sound_attack2;
14 static int sound_attack3;
15 static int sound_death1;
16 static int sound_idle;
17 static int sound_pain1;
18 static int sound_pain2;
19 static int sound_sight;
20
21
floater_sight(edict_t * self,edict_t * other)22 void floater_sight (edict_t *self, edict_t *other)
23 {
24 gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
25 }
26
floater_idle(edict_t * self)27 void floater_idle (edict_t *self)
28 {
29 gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
30 }
31
32
33 //void floater_stand1 (edict_t *self);
34 void floater_dead (edict_t *self);
35 void floater_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point);
36 void floater_run (edict_t *self);
37 void floater_wham (edict_t *self);
38 void floater_zap (edict_t *self);
39
40
floater_fire_blaster(edict_t * self)41 void floater_fire_blaster (edict_t *self)
42 {
43 vec3_t start;
44 vec3_t forward, right;
45 vec3_t end;
46 vec3_t dir;
47 int effect;
48
49 if ((self->s.frame == FRAME_attak104) || (self->s.frame == FRAME_attak107))
50 effect = EF_HYPERBLASTER;
51 else
52 effect = 0;
53 AngleVectors (self->s.angles, forward, right, NULL);
54 G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_FLOAT_BLASTER_1], forward, right, start);
55
56 VectorCopy (self->enemy->s.origin, end);
57 end[2] += self->enemy->viewheight;
58 VectorSubtract (end, start, dir);
59
60 monster_fire_blaster (self, start, dir, 1, 1000, MZ2_FLOAT_BLASTER_1, effect);
61 }
62
63
64 mframe_t floater_frames_stand1 [] =
65 {
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 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 ai_stand, 0, NULL,
98 ai_stand, 0, NULL,
99 ai_stand, 0, NULL,
100 ai_stand, 0, NULL,
101 ai_stand, 0, NULL,
102 ai_stand, 0, NULL,
103 ai_stand, 0, NULL,
104 ai_stand, 0, NULL,
105 ai_stand, 0, NULL,
106 ai_stand, 0, NULL,
107 ai_stand, 0, NULL,
108 ai_stand, 0, NULL,
109 ai_stand, 0, NULL,
110 ai_stand, 0, NULL,
111 ai_stand, 0, NULL,
112 ai_stand, 0, NULL,
113 ai_stand, 0, NULL,
114 ai_stand, 0, NULL,
115 ai_stand, 0, NULL,
116 ai_stand, 0, NULL,
117 ai_stand, 0, NULL
118 };
119 mmove_t floater_move_stand1 = {FRAME_stand101, FRAME_stand152, floater_frames_stand1, NULL};
120
121 mframe_t floater_frames_stand2 [] =
122 {
123 ai_stand, 0, NULL,
124 ai_stand, 0, NULL,
125 ai_stand, 0, NULL,
126 ai_stand, 0, NULL,
127 ai_stand, 0, NULL,
128 ai_stand, 0, NULL,
129 ai_stand, 0, NULL,
130 ai_stand, 0, NULL,
131 ai_stand, 0, NULL,
132 ai_stand, 0, NULL,
133 ai_stand, 0, NULL,
134 ai_stand, 0, NULL,
135 ai_stand, 0, NULL,
136 ai_stand, 0, NULL,
137 ai_stand, 0, NULL,
138 ai_stand, 0, NULL,
139 ai_stand, 0, NULL,
140 ai_stand, 0, NULL,
141 ai_stand, 0, NULL,
142 ai_stand, 0, NULL,
143 ai_stand, 0, NULL,
144 ai_stand, 0, NULL,
145 ai_stand, 0, NULL,
146 ai_stand, 0, NULL,
147 ai_stand, 0, NULL,
148 ai_stand, 0, NULL,
149 ai_stand, 0, NULL,
150 ai_stand, 0, NULL,
151 ai_stand, 0, NULL,
152 ai_stand, 0, NULL,
153 ai_stand, 0, NULL,
154 ai_stand, 0, NULL,
155 ai_stand, 0, NULL,
156 ai_stand, 0, NULL,
157 ai_stand, 0, NULL,
158 ai_stand, 0, NULL,
159 ai_stand, 0, NULL,
160 ai_stand, 0, NULL,
161 ai_stand, 0, NULL,
162 ai_stand, 0, NULL,
163 ai_stand, 0, NULL,
164 ai_stand, 0, NULL,
165 ai_stand, 0, NULL,
166 ai_stand, 0, NULL,
167 ai_stand, 0, NULL,
168 ai_stand, 0, NULL,
169 ai_stand, 0, NULL,
170 ai_stand, 0, NULL,
171 ai_stand, 0, NULL,
172 ai_stand, 0, NULL,
173 ai_stand, 0, NULL,
174 ai_stand, 0, NULL
175 };
176 mmove_t floater_move_stand2 = {FRAME_stand201, FRAME_stand252, floater_frames_stand2, NULL};
177
floater_stand(edict_t * self)178 void floater_stand (edict_t *self)
179 {
180 if (random() <= 0.5)
181 self->monsterinfo.currentmove = &floater_move_stand1;
182 else
183 self->monsterinfo.currentmove = &floater_move_stand2;
184 }
185
186 mframe_t floater_frames_activate [] =
187 {
188 ai_move, 0, NULL,
189 ai_move, 0, NULL,
190 ai_move, 0, NULL,
191 ai_move, 0, NULL,
192 ai_move, 0, NULL,
193 ai_move, 0, NULL,
194 ai_move, 0, NULL,
195 ai_move, 0, NULL,
196 ai_move, 0, NULL,
197 ai_move, 0, NULL,
198 ai_move, 0, NULL,
199 ai_move, 0, NULL,
200 ai_move, 0, NULL,
201 ai_move, 0, NULL,
202 ai_move, 0, NULL,
203 ai_move, 0, NULL,
204 ai_move, 0, NULL,
205 ai_move, 0, NULL,
206 ai_move, 0, NULL,
207 ai_move, 0, NULL,
208 ai_move, 0, NULL,
209 ai_move, 0, NULL,
210 ai_move, 0, NULL,
211 ai_move, 0, NULL,
212 ai_move, 0, NULL,
213 ai_move, 0, NULL,
214 ai_move, 0, NULL,
215 ai_move, 0, NULL,
216 ai_move, 0, NULL,
217 ai_move, 0, NULL
218 };
219 mmove_t floater_move_activate = {FRAME_actvat01, FRAME_actvat31, floater_frames_activate, NULL};
220
221 mframe_t floater_frames_attack1 [] =
222 {
223 ai_charge, 0, NULL, // Blaster attack
224 ai_charge, 0, NULL,
225 ai_charge, 0, NULL,
226 ai_charge, 0, floater_fire_blaster, // BOOM (0, -25.8, 32.5) -- LOOP Starts
227 ai_charge, 0, floater_fire_blaster,
228 ai_charge, 0, floater_fire_blaster,
229 ai_charge, 0, floater_fire_blaster,
230 ai_charge, 0, floater_fire_blaster,
231 ai_charge, 0, floater_fire_blaster,
232 ai_charge, 0, floater_fire_blaster,
233 ai_charge, 0, NULL,
234 ai_charge, 0, NULL,
235 ai_charge, 0, NULL,
236 ai_charge, 0, NULL // -- LOOP Ends
237 };
238 mmove_t floater_move_attack1 = {FRAME_attak101, FRAME_attak114, floater_frames_attack1, floater_run};
239
240 mframe_t floater_frames_attack2 [] =
241 {
242 ai_charge, 0, NULL, // Claws
243 ai_charge, 0, NULL,
244 ai_charge, 0, NULL,
245 ai_charge, 0, NULL,
246 ai_charge, 0, NULL,
247 ai_charge, 0, NULL,
248 ai_charge, 0, NULL,
249 ai_charge, 0, NULL,
250 ai_charge, 0, NULL,
251 ai_charge, 0, NULL,
252 ai_charge, 0, NULL,
253 ai_charge, 0, floater_wham, // WHAM (0, -45, 29.6) -- LOOP Starts
254 ai_charge, 0, NULL,
255 ai_charge, 0, NULL,
256 ai_charge, 0, NULL,
257 ai_charge, 0, NULL,
258 ai_charge, 0, NULL,
259 ai_charge, 0, NULL,
260 ai_charge, 0, NULL, // -- LOOP Ends
261 ai_charge, 0, NULL,
262 ai_charge, 0, NULL,
263 ai_charge, 0, NULL,
264 ai_charge, 0, NULL,
265 ai_charge, 0, NULL,
266 ai_charge, 0, NULL
267 };
268 mmove_t floater_move_attack2 = {FRAME_attak201, FRAME_attak225, floater_frames_attack2, floater_run};
269
270 mframe_t floater_frames_attack3 [] =
271 {
272 ai_charge, 0, NULL,
273 ai_charge, 0, NULL,
274 ai_charge, 0, NULL,
275 ai_charge, 0, NULL,
276 ai_charge, 0, NULL,
277 ai_charge, 0, NULL,
278 ai_charge, 0, NULL,
279 ai_charge, 0, NULL,
280 ai_charge, 0, floater_zap, // -- LOOP Starts
281 ai_charge, 0, NULL,
282 ai_charge, 0, NULL,
283 ai_charge, 0, NULL,
284 ai_charge, 0, NULL,
285 ai_charge, 0, NULL,
286 ai_charge, 0, NULL,
287 ai_charge, 0, NULL,
288 ai_charge, 0, NULL,
289 ai_charge, 0, NULL,
290 ai_charge, 0, NULL,
291 ai_charge, 0, NULL,
292 ai_charge, 0, NULL,
293 ai_charge, 0, NULL,
294 ai_charge, 0, NULL,
295 ai_charge, 0, NULL,
296 ai_charge, 0, NULL,
297 ai_charge, 0, NULL,
298 ai_charge, 0, NULL,
299 ai_charge, 0, NULL,
300 ai_charge, 0, NULL, // -- LOOP Ends
301 ai_charge, 0, NULL,
302 ai_charge, 0, NULL,
303 ai_charge, 0, NULL,
304 ai_charge, 0, NULL,
305 ai_charge, 0, NULL
306 };
307 mmove_t floater_move_attack3 = {FRAME_attak301, FRAME_attak334, floater_frames_attack3, floater_run};
308
309 mframe_t floater_frames_death [] =
310 {
311 ai_move, 0, NULL,
312 ai_move, 0, NULL,
313 ai_move, 0, NULL,
314 ai_move, 0, NULL,
315 ai_move, 0, NULL,
316 ai_move, 0, NULL,
317 ai_move, 0, NULL,
318 ai_move, 0, NULL,
319 ai_move, 0, NULL,
320 ai_move, 0, NULL,
321 ai_move, 0, NULL,
322 ai_move, 0, NULL,
323 ai_move, 0, NULL
324 };
325 mmove_t floater_move_death = {FRAME_death01, FRAME_death13, floater_frames_death, floater_dead};
326
327 mframe_t floater_frames_pain1 [] =
328 {
329 ai_move, 0, NULL,
330 ai_move, 0, NULL,
331 ai_move, 0, NULL,
332 ai_move, 0, NULL,
333 ai_move, 0, NULL,
334 ai_move, 0, NULL,
335 ai_move, 0, NULL
336 };
337 mmove_t floater_move_pain1 = {FRAME_pain101, FRAME_pain107, floater_frames_pain1, floater_run};
338
339 mframe_t floater_frames_pain2 [] =
340 {
341 ai_move, 0, NULL,
342 ai_move, 0, NULL,
343 ai_move, 0, NULL,
344 ai_move, 0, NULL,
345 ai_move, 0, NULL,
346 ai_move, 0, NULL,
347 ai_move, 0, NULL,
348 ai_move, 0, NULL
349 };
350 mmove_t floater_move_pain2 = {FRAME_pain201, FRAME_pain208, floater_frames_pain2, floater_run};
351
352 mframe_t floater_frames_pain3 [] =
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, 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 };
367 mmove_t floater_move_pain3 = {FRAME_pain301, FRAME_pain312, floater_frames_pain3, floater_run};
368
369 mframe_t floater_frames_walk [] =
370 {
371 ai_walk, 5, NULL,
372 ai_walk, 5, NULL,
373 ai_walk, 5, NULL,
374 ai_walk, 5, NULL,
375 ai_walk, 5, NULL,
376 ai_walk, 5, NULL,
377 ai_walk, 5, NULL,
378 ai_walk, 5, NULL,
379 ai_walk, 5, NULL,
380 ai_walk, 5, NULL,
381 ai_walk, 5, NULL,
382 ai_walk, 5, NULL,
383 ai_walk, 5, NULL,
384 ai_walk, 5, NULL,
385 ai_walk, 5, NULL,
386 ai_walk, 5, NULL,
387 ai_walk, 5, NULL,
388 ai_walk, 5, NULL,
389 ai_walk, 5, NULL,
390 ai_walk, 5, NULL,
391 ai_walk, 5, NULL,
392 ai_walk, 5, NULL,
393 ai_walk, 5, NULL,
394 ai_walk, 5, NULL,
395 ai_walk, 5, NULL,
396 ai_walk, 5, NULL,
397 ai_walk, 5, NULL,
398 ai_walk, 5, NULL,
399 ai_walk, 5, NULL,
400 ai_walk, 5, NULL,
401 ai_walk, 5, NULL,
402 ai_walk, 5, NULL,
403 ai_walk, 5, NULL,
404 ai_walk, 5, NULL,
405 ai_walk, 5, NULL,
406 ai_walk, 5, NULL,
407 ai_walk, 5, NULL,
408 ai_walk, 5, NULL,
409 ai_walk, 5, NULL,
410 ai_walk, 5, NULL,
411 ai_walk, 5, NULL,
412 ai_walk, 5, NULL,
413 ai_walk, 5, NULL,
414 ai_walk, 5, NULL,
415 ai_walk, 5, NULL,
416 ai_walk, 5, NULL,
417 ai_walk, 5, NULL,
418 ai_walk, 5, NULL,
419 ai_walk, 5, NULL,
420 ai_walk, 5, NULL,
421 ai_walk, 5, NULL,
422 ai_walk, 5, NULL
423 };
424 mmove_t floater_move_walk = {FRAME_stand101, FRAME_stand152, floater_frames_walk, NULL};
425
426 mframe_t floater_frames_run [] =
427 {
428 ai_run, 13, NULL,
429 ai_run, 13, NULL,
430 ai_run, 13, NULL,
431 ai_run, 13, NULL,
432 ai_run, 13, NULL,
433 ai_run, 13, NULL,
434 ai_run, 13, NULL,
435 ai_run, 13, NULL,
436 ai_run, 13, NULL,
437 ai_run, 13, NULL,
438 ai_run, 13, NULL,
439 ai_run, 13, NULL,
440 ai_run, 13, NULL,
441 ai_run, 13, NULL,
442 ai_run, 13, NULL,
443 ai_run, 13, NULL,
444 ai_run, 13, NULL,
445 ai_run, 13, NULL,
446 ai_run, 13, NULL,
447 ai_run, 13, NULL,
448 ai_run, 13, NULL,
449 ai_run, 13, NULL,
450 ai_run, 13, NULL,
451 ai_run, 13, NULL,
452 ai_run, 13, NULL,
453 ai_run, 13, NULL,
454 ai_run, 13, NULL,
455 ai_run, 13, NULL,
456 ai_run, 13, NULL,
457 ai_run, 13, NULL,
458 ai_run, 13, NULL,
459 ai_run, 13, NULL,
460 ai_run, 13, NULL,
461 ai_run, 13, NULL,
462 ai_run, 13, NULL,
463 ai_run, 13, NULL,
464 ai_run, 13, NULL,
465 ai_run, 13, NULL,
466 ai_run, 13, NULL,
467 ai_run, 13, NULL,
468 ai_run, 13, NULL,
469 ai_run, 13, NULL,
470 ai_run, 13, NULL,
471 ai_run, 13, NULL,
472 ai_run, 13, NULL,
473 ai_run, 13, NULL,
474 ai_run, 13, NULL,
475 ai_run, 13, NULL,
476 ai_run, 13, NULL,
477 ai_run, 13, NULL,
478 ai_run, 13, NULL,
479 ai_run, 13, NULL
480 };
481 mmove_t floater_move_run = {FRAME_stand101, FRAME_stand152, floater_frames_run, NULL};
482
floater_run(edict_t * self)483 void floater_run (edict_t *self)
484 {
485 if (self->monsterinfo.aiflags & AI_STAND_GROUND)
486 self->monsterinfo.currentmove = &floater_move_stand1;
487 else
488 self->monsterinfo.currentmove = &floater_move_run;
489 }
490
floater_walk(edict_t * self)491 void floater_walk (edict_t *self)
492 {
493 self->monsterinfo.currentmove = &floater_move_walk;
494 }
495
floater_wham(edict_t * self)496 void floater_wham (edict_t *self)
497 {
498 static vec3_t aim = {MELEE_DISTANCE, 0, 0};
499 gi.sound (self, CHAN_WEAPON, sound_attack3, 1, ATTN_NORM, 0);
500 fire_hit (self, aim, 5 + rand() % 6, -50);
501 }
502
floater_zap(edict_t * self)503 void floater_zap (edict_t *self)
504 {
505 vec3_t forward, right;
506 vec3_t origin;
507 vec3_t dir;
508 vec3_t offset;
509
510 VectorSubtract (self->enemy->s.origin, self->s.origin, dir);
511
512 AngleVectors (self->s.angles, forward, right, NULL);
513 //FIXME use a flash and replace these two lines with the commented one
514 VectorSet (offset, 18.5, -0.9, 10);
515 G_ProjectSource (self->s.origin, offset, forward, right, origin);
516 // G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, origin);
517
518 gi.sound (self, CHAN_WEAPON, sound_attack2, 1, ATTN_NORM, 0);
519
520 //FIXME use the flash, Luke
521 gi.WriteByte (svc_temp_entity);
522 gi.WriteByte (TE_SPLASH);
523 gi.WriteByte (32);
524 gi.WritePosition (origin);
525 gi.WriteDir (dir);
526 gi.WriteByte (1); //sparks
527 gi.multicast (origin, MULTICAST_PVS);
528
529 T_Damage (self->enemy, self, self, dir, self->enemy->s.origin, vec3_origin, 5 + rand() % 6, -10, DAMAGE_ENERGY, MOD_UNKNOWN);
530 }
531
floater_attack(edict_t * self)532 void floater_attack(edict_t *self)
533 {
534 self->monsterinfo.currentmove = &floater_move_attack1;
535 }
536
537
floater_melee(edict_t * self)538 void floater_melee(edict_t *self)
539 {
540 if (random() < 0.5)
541 self->monsterinfo.currentmove = &floater_move_attack3;
542 else
543 self->monsterinfo.currentmove = &floater_move_attack2;
544 }
545
546
floater_pain(edict_t * self,edict_t * other,float kick,int damage)547 void floater_pain (edict_t *self, edict_t *other, float kick, int damage)
548 {
549 int n;
550
551 if (self->health < (self->max_health / 2))
552 self->s.skinnum = 1;
553
554 if (level.time < self->pain_debounce_time)
555 return;
556
557 self->pain_debounce_time = level.time + 3;
558 if (skill->value == 3)
559 return; // no pain anims in nightmare
560
561 n = (rand() + 1) % 3;
562 if (n == 0)
563 {
564 gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
565 self->monsterinfo.currentmove = &floater_move_pain1;
566 }
567 else
568 {
569 gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
570 self->monsterinfo.currentmove = &floater_move_pain2;
571 }
572 }
573
floater_dead(edict_t * self)574 void floater_dead (edict_t *self)
575 {
576 VectorSet (self->mins, -16, -16, -24);
577 VectorSet (self->maxs, 16, 16, -8);
578 self->movetype = MOVETYPE_TOSS;
579 self->svflags |= SVF_DEADMONSTER;
580 self->nextthink = 0;
581 gi.linkentity (self);
582 }
583
floater_die(edict_t * self,edict_t * inflictor,edict_t * attacker,int damage,vec3_t point)584 void floater_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
585 {
586 gi.sound (self, CHAN_VOICE, sound_death1, 1, ATTN_NORM, 0);
587 BecomeExplosion1(self);
588 }
589
590 /*QUAKED monster_floater (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
591 */
SP_monster_floater(edict_t * self)592 void SP_monster_floater (edict_t *self)
593 {
594 if (deathmatch->value)
595 {
596 G_FreeEdict (self);
597 return;
598 }
599
600 sound_attack2 = gi.soundindex ("floater/fltatck2.wav");
601 sound_attack3 = gi.soundindex ("floater/fltatck3.wav");
602 sound_death1 = gi.soundindex ("floater/fltdeth1.wav");
603 sound_idle = gi.soundindex ("floater/fltidle1.wav");
604 sound_pain1 = gi.soundindex ("floater/fltpain1.wav");
605 sound_pain2 = gi.soundindex ("floater/fltpain2.wav");
606 sound_sight = gi.soundindex ("floater/fltsght1.wav");
607
608 gi.soundindex ("floater/fltatck1.wav");
609
610 self->s.sound = gi.soundindex ("floater/fltsrch1.wav");
611
612 self->movetype = MOVETYPE_STEP;
613 self->solid = SOLID_BBOX;
614 self->s.modelindex = gi.modelindex ("models/monsters/float/tris.md2");
615 VectorSet (self->mins, -24, -24, -24);
616 VectorSet (self->maxs, 24, 24, 32);
617
618 self->health = 200;
619 self->gib_health = -80;
620 self->mass = 300;
621
622 self->pain = floater_pain;
623 self->die = floater_die;
624
625 self->monsterinfo.stand = floater_stand;
626 self->monsterinfo.walk = floater_walk;
627 self->monsterinfo.run = floater_run;
628 // self->monsterinfo.dodge = floater_dodge;
629 self->monsterinfo.attack = floater_attack;
630 self->monsterinfo.melee = floater_melee;
631 self->monsterinfo.sight = floater_sight;
632 self->monsterinfo.idle = floater_idle;
633
634 gi.linkentity (self);
635
636 if (random() <= 0.5)
637 self->monsterinfo.currentmove = &floater_move_stand1;
638 else
639 self->monsterinfo.currentmove = &floater_move_stand2;
640
641 self->monsterinfo.scale = MODEL_SCALE;
642
643 flymonster_start (self);
644 }
645