File: game\m_brain.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 brain
24
25 ==============================================================================
26 */
27
28 #include "g_local.h"
29 #include "m_brain.h"
30
31
32 static int sound_chest_open;
33 static int sound_tentacles_extend;
34 static int sound_tentacles_retract;
35 static int sound_death;
36 static int sound_idle1;
37 static int sound_idle2;
38 static int sound_idle3;
39 static int sound_pain1;
40 static int sound_pain2;
41 static int sound_sight;
42 static int sound_search;
43 static int sound_melee1;
44 static int sound_melee2;
45 static int sound_melee3;
46
47
48 void brain_sight (edict_t *self, edict_t *other)
49 {
50 gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
51 }
52
53 void brain_search (edict_t *self)
54 {
55 gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0);
56 }
57
58
59 void brain_run (edict_t *self);
60 void brain_dead (edict_t *self);
61
62
63 //
64 // STAND
65 //
66
67 mframe_t brain_frames_stand [] =
68 {
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
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
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 };
102 mmove_t brain_move_stand = {FRAME_stand01, FRAME_stand30, brain_frames_stand, NULL};
103
104 void brain_stand (edict_t *self)
105 {
106 self->monsterinfo.currentmove = &brain_move_stand;
107 }
108
109
110 //
111 // IDLE
112 //
113
114 mframe_t brain_frames_idle [] =
115 {
116 ai_stand, 0, NULL,
117 ai_stand, 0, NULL,
118 ai_stand, 0, NULL,
119 ai_stand, 0, NULL,
120 ai_stand, 0, NULL,
121 ai_stand, 0, NULL,
122 ai_stand, 0, NULL,
123 ai_stand, 0, NULL,
124 ai_stand, 0, NULL,
125 ai_stand, 0, NULL,
126
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
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 };
149 mmove_t brain_move_idle = {FRAME_stand31, FRAME_stand60, brain_frames_idle, brain_stand};
150
151 void brain_idle (edict_t *self)
152 {
153 gi.sound (self, CHAN_AUTO, sound_idle3, 1, ATTN_IDLE, 0);
154 self->monsterinfo.currentmove = &brain_move_idle;
155 }
156
157
158 //
159 // WALK
160 //
161 mframe_t brain_frames_walk1 [] =
162 {
163 ai_walk, 7, NULL,
164 ai_walk, 2, NULL,
165 ai_walk, 3, NULL,
166 ai_walk, 3, NULL,
167 ai_walk, 1, NULL,
168 ai_walk, 0, NULL,
169 ai_walk, 0, NULL,
170 ai_walk, 9, NULL,
171 ai_walk, -4, NULL,
172 ai_walk, -1, NULL,
173 ai_walk, 2, NULL
174 };
175 mmove_t brain_move_walk1 = {FRAME_walk101, FRAME_walk111, brain_frames_walk1, NULL};
176
177 // walk2 is FUBAR, do not use
178 #if 0
179 void brain_walk2_cycle (edict_t *self)
180 {
181 if (random() > 0.1)
182 self->monsterinfo.nextframe = FRAME_walk220;
183 }
184
185 mframe_t brain_frames_walk2 [] =
186 {
187 ai_walk, 3, NULL,
188 ai_walk, -2, NULL,
189 ai_walk, -4, NULL,
190 ai_walk, -3, NULL,
191 ai_walk, 0, NULL,
192 ai_walk, 1, NULL,
193 ai_walk, 12, NULL,
194 ai_walk, 0, NULL,
195 ai_walk, -3, NULL,
196 ai_walk, 0, NULL,
197
198 ai_walk, -2, NULL,
199 ai_walk, 0, NULL,
200 ai_walk, 0, NULL,
201 ai_walk, 1, NULL,
202 ai_walk, 0, NULL,
203 ai_walk, 0, NULL,
204 ai_walk, 0, NULL,
205 ai_walk, 0, NULL,
206 ai_walk, 0, NULL,
207 ai_walk, 10, NULL, // Cycle Start
208
209 ai_walk, -1, NULL,
210 ai_walk, 7, NULL,
211 ai_walk, 0, NULL,
212 ai_walk, 3, NULL,
213 ai_walk, -3, NULL,
214 ai_walk, 2, NULL,
215 ai_walk, 4, NULL,
216 ai_walk, -3, NULL,
217 ai_walk, 2, NULL,
218 ai_walk, 0, NULL,
219
220 ai_walk, 4, brain_walk2_cycle,
221 ai_walk, -1, NULL,
222 ai_walk, -1, NULL,
223 ai_walk, -8, NULL,
224 ai_walk, 0, NULL,
225 ai_walk, 1, NULL,
226 ai_walk, 5, NULL,
227 ai_walk, 2, NULL,
228 ai_walk, -1, NULL,
229 ai_walk, -5, NULL
230 };
231 mmove_t brain_move_walk2 = {FRAME_walk201, FRAME_walk240, brain_frames_walk2, NULL}; 232 #endif
233
234 void brain_walk (edict_t *self)
235 {
236 // if (random() <= 0.5)
237 self->monsterinfo.currentmove = &brain_move_walk1;
238 // else
239 // self->monsterinfo.currentmove = &brain_move_walk2;
240 }
241
242
243
244 mframe_t brain_frames_defense [] =
245 {
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 };
256 mmove_t brain_move_defense = {FRAME_defens01, FRAME_defens08, brain_frames_defense, NULL};
257
258 mframe_t brain_frames_pain3 [] =
259 {
260 ai_move, -2, NULL,
261 ai_move, 2, NULL,
262 ai_move, 1, NULL,
263 ai_move, 3, NULL,
264 ai_move, 0, NULL,
265 ai_move, -4, NULL
266 };
267 mmove_t brain_move_pain3 = {FRAME_pain301, FRAME_pain306, brain_frames_pain3, brain_run};
268
269 mframe_t brain_frames_pain2 [] =
270 {
271 ai_move, -2, NULL,
272 ai_move, 0, NULL,
273 ai_move, 0, NULL,
274 ai_move, 0, NULL,
275 ai_move, 0, NULL,
276 ai_move, 3, NULL,
277 ai_move, 1, NULL,
278 ai_move, -2, NULL
279 };
280 mmove_t brain_move_pain2 = {FRAME_pain201, FRAME_pain208, brain_frames_pain2, brain_run};
281
282 mframe_t brain_frames_pain1 [] =
283 {
284 ai_move, -6, NULL,
285 ai_move, -2, NULL,
286 ai_move, -6, NULL,
287 ai_move, 0, NULL,
288 ai_move, 0, NULL,
289 ai_move, 0, NULL,
290 ai_move, 0, NULL,
291 ai_move, 0, NULL,
292 ai_move, 0, NULL,
293 ai_move, 0, NULL,
294 ai_move, 0, NULL,
295 ai_move, 0, NULL,
296 ai_move, 0, NULL,
297 ai_move, 2, NULL,
298 ai_move, 0, NULL,
299 ai_move, 2, NULL,
300 ai_move, 1, NULL,
301 ai_move, 7, NULL,
302 ai_move, 0, NULL,
303 ai_move, 3, NULL,
304 ai_move, -1, NULL
305 };
306 mmove_t brain_move_pain1 = {FRAME_pain101, FRAME_pain121, brain_frames_pain1, brain_run};
307
308
309 //
310 // DUCK
311 //
312
313 void brain_duck_down (edict_t *self)
314 {
315 if (self->monsterinfo.aiflags & AI_DUCKED)
316 return;
317 self->monsterinfo.aiflags |= AI_DUCKED;
318 self->maxs[2] -= 32;
319 self->takedamage = DAMAGE_YES;
320 gi.linkentity (self);
321 }
322
323 void brain_duck_hold (edict_t *self)
324 {
325 if (level.time >= self->monsterinfo.pausetime)
326 self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
327 else
328 self->monsterinfo.aiflags |= AI_HOLD_FRAME;
329 }
330
331 void brain_duck_up (edict_t *self)
332 {
333 self->monsterinfo.aiflags &= ~AI_DUCKED;
334 self->maxs[2] += 32;
335 self->takedamage = DAMAGE_AIM;
336 gi.linkentity (self);
337 }
338
339 mframe_t brain_frames_duck [] =
340 {
341 ai_move, 0, NULL,
342 ai_move, -2, brain_duck_down,
343 ai_move, 17, brain_duck_hold,
344 ai_move, -3, NULL,
345 ai_move, -1, brain_duck_up,
346 ai_move, -5, NULL,
347 ai_move, -6, NULL,
348 ai_move, -6, NULL
349 };
350 mmove_t brain_move_duck = {FRAME_duck01, FRAME_duck08, brain_frames_duck, brain_run};
351
352 void brain_dodge (edict_t *self, edict_t *attacker, float eta)
353 {
354 if (random() > 0.25)
355 return;
356
357 if (!self->enemy)
358 self->enemy = attacker;
359
360 self->monsterinfo.pausetime = level.time + eta + 0.5;
361 self->monsterinfo.currentmove = &brain_move_duck;
362 }
363
364
365 mframe_t brain_frames_death2 [] =
366 {
367 ai_move, 0, NULL,
368 ai_move, 0, NULL,
369 ai_move, 0, NULL,
370 ai_move, 9, NULL,
371 ai_move, 0, NULL
372 };
373 mmove_t brain_move_death2 = {FRAME_death201, FRAME_death205, brain_frames_death2, brain_dead};
374
375 mframe_t brain_frames_death1 [] =
376 {
377 ai_move, 0, NULL,
378 ai_move, 0, NULL,
379 ai_move, -2, NULL,
380 ai_move, 9, 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 ai_move, 0, NULL
395 };
396 mmove_t brain_move_death1 = {FRAME_death101, FRAME_death118, brain_frames_death1, brain_dead};
397
398
399 //
400 // MELEE
401 //
402
403 void brain_swing_right (edict_t *self)
404 {
405 gi.sound (self, CHAN_BODY, sound_melee1, 1, ATTN_NORM, 0);
406 }
407
408 void brain_hit_right (edict_t *self)
409 {
410 vec3_t aim;
411
412 VectorSet (aim, MELEE_DISTANCE, self->maxs[0], 8);
413 if (fire_hit (self, aim, (15 + (rand() %5)), 40))
414 gi.sound (self, CHAN_WEAPON, sound_melee3, 1, ATTN_NORM, 0);
415 }
416
417 void brain_swing_left (edict_t *self)
418 {
419 gi.sound (self, CHAN_BODY, sound_melee2, 1, ATTN_NORM, 0);
420 }
421
422 void brain_hit_left (edict_t *self)
423 {
424 vec3_t aim;
425
426 VectorSet (aim, MELEE_DISTANCE, self->mins[0], 8);
427 if (fire_hit (self, aim, (15 + (rand() %5)), 40))
428 gi.sound (self, CHAN_WEAPON, sound_melee3, 1, ATTN_NORM, 0);
429 }
430
431 mframe_t brain_frames_attack1 [] =
432 {
433 ai_charge, 8, NULL,
434 ai_charge, 3, NULL,
435 ai_charge, 5, NULL,
436 ai_charge, 0, NULL,
437 ai_charge, -3, brain_swing_right,
438 ai_charge, 0, NULL,
439 ai_charge, -5, NULL,
440 ai_charge, -7, brain_hit_right,
441 ai_charge, 0, NULL,
442 ai_charge, 6, brain_swing_left,
443 ai_charge, 1, NULL,
444 ai_charge, 2, brain_hit_left,
445 ai_charge, -3, NULL,
446 ai_charge, 6, NULL,
447 ai_charge, -1, NULL,
448 ai_charge, -3, NULL,
449 ai_charge, 2, NULL,
450 ai_charge, -11,NULL
451 };
452 mmove_t brain_move_attack1 = {FRAME_attak101, FRAME_attak118, brain_frames_attack1, brain_run};
453
454 void brain_chest_open (edict_t *self)
455 {
456 self->spawnflags &= ~65536;
457 self->monsterinfo.power_armor_type = POWER_ARMOR_NONE;
458 gi.sound (self, CHAN_BODY, sound_chest_open, 1, ATTN_NORM, 0);
459 }
460
461 void brain_tentacle_attack (edict_t *self)
462 {
463 vec3_t aim;
464
465 VectorSet (aim, MELEE_DISTANCE, 0, 8);
466 if (fire_hit (self, aim, (10 + (rand() %5)), -600) && skill->value > 0)
467 self->spawnflags |= 65536;
468 gi.sound (self, CHAN_WEAPON, sound_tentacles_retract, 1, ATTN_NORM, 0);
469 }
470
471 void brain_chest_closed (edict_t *self)
472 {
473 self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN;
474 if (self->spawnflags & 65536)
475 {
476 self->spawnflags &= ~65536;
477 self->monsterinfo.currentmove = &brain_move_attack1;
478 }
479 }
480
481 mframe_t brain_frames_attack2 [] =
482 {
483 ai_charge, 5, NULL,
484 ai_charge, -4, NULL,
485 ai_charge, -4, NULL,
486 ai_charge, -3, NULL,
487 ai_charge, 0, brain_chest_open,
488 ai_charge, 0, NULL,
489 ai_charge, 13, brain_tentacle_attack,
490 ai_charge, 0, NULL,
491 ai_charge, 2, NULL,
492 ai_charge, 0, NULL,
493 ai_charge, -9, brain_chest_closed,
494 ai_charge, 0, NULL,
495 ai_charge, 4, NULL,
496 ai_charge, 3, NULL,
497 ai_charge, 2, NULL,
498 ai_charge, -3, NULL,
499 ai_charge, -6, NULL
500 };
501 mmove_t brain_move_attack2 = {FRAME_attak201, FRAME_attak217, brain_frames_attack2, brain_run};
502
503 void brain_melee(edict_t *self)
504 {
505 if (random() <= 0.5)
506 self->monsterinfo.currentmove = &brain_move_attack1;
507 else
508 self->monsterinfo.currentmove = &brain_move_attack2;
509 }
510
511
512 //
513 // RUN
514 //
515
516 mframe_t brain_frames_run [] =
517 {
518 ai_run, 9, NULL,
519 ai_run, 2, NULL,
520 ai_run, 3, NULL,
521 ai_run, 3, NULL,
522 ai_run, 1, NULL,
523 ai_run, 0, NULL,
524 ai_run, 0, NULL,
525 ai_run, 10, NULL,
526 ai_run, -4, NULL,
527 ai_run, -1, NULL,
528 ai_run, 2, NULL
529 };
530 mmove_t brain_move_run = {FRAME_walk101, FRAME_walk111, brain_frames_run, NULL};
531
532 void brain_run (edict_t *self)
533 {
534 self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN;
535 if (self->monsterinfo.aiflags & AI_STAND_GROUND)
536 self->monsterinfo.currentmove = &brain_move_stand;
537 else
538 self->monsterinfo.currentmove = &brain_move_run;
539 }
540
541
542 void brain_pain (edict_t *self, edict_t *other, float kick, int damage)
543 {
544 float r;
545
546 if (self->health < (self->max_health / 2))
547 self->s.skinnum = 1;
548
549 if (level.time < self->pain_debounce_time)
550 return;
551
552 self->pain_debounce_time = level.time + 3;
553 if (skill->value == 3)
554 return; // no pain anims in nightmare
555
556 r = random();
557 if (r < 0.33)
558 {
559 gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
560 self->monsterinfo.currentmove = &brain_move_pain1;
561 }
562 else if (r < 0.66)
563 {
564 gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
565 self->monsterinfo.currentmove = &brain_move_pain2;
566 }
567 else
568 {
569 gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
570 self->monsterinfo.currentmove = &brain_move_pain3;
571 }
572 }
573
574 void brain_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
584
585
586 void brain_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
587 {
588 int n;
589
590 self->s.effects = 0;
591 self->monsterinfo.power_armor_type = POWER_ARMOR_NONE;
592
593 // check for gib
594 if (self->health <= self->gib_health)
595 {
596 gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
597 for (n= 0; n < 2; n++)
598 ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
599 for (n= 0; n < 4; n++)
600 ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
601 ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
602 self->deadflag = DEAD_DEAD;
603 return;
604 }
605
606 if (self->deadflag == DEAD_DEAD)
607 return;
608
609 // regular death
610 gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0);
611 self->deadflag = DEAD_DEAD;
612 self->takedamage = DAMAGE_YES;
613 if (random() <= 0.5)
614 self->monsterinfo.currentmove = &brain_move_death1;
615 else
616 self->monsterinfo.currentmove = &brain_move_death2;
617 }
618
619 /*QUAKED monster_brain (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
620 */
621 void SP_monster_brain (edict_t *self)
622 {
623 if (deathmatch->value)
624 {
625 G_FreeEdict (self);
626 return;
627 }
628
629 sound_chest_open = gi.soundindex ("brain/brnatck1.wav");
630 sound_tentacles_extend = gi.soundindex ("brain/brnatck2.wav");
631 sound_tentacles_retract = gi.soundindex ("brain/brnatck3.wav");
632 sound_death = gi.soundindex ("brain/brndeth1.wav");
633 sound_idle1 = gi.soundindex ("brain/brnidle1.wav");
634 sound_idle2 = gi.soundindex ("brain/brnidle2.wav");
635 sound_idle3 = gi.soundindex ("brain/brnlens1.wav");
636 sound_pain1 = gi.soundindex ("brain/brnpain1.wav");
637 sound_pain2 = gi.soundindex ("brain/brnpain2.wav");
638 sound_sight = gi.soundindex ("brain/brnsght1.wav");
639 sound_search = gi.soundindex ("brain/brnsrch1.wav");
640 sound_melee1 = gi.soundindex ("brain/melee1.wav");
641 sound_melee2 = gi.soundindex ("brain/melee2.wav");
642 sound_melee3 = gi.soundindex ("brain/melee3.wav");
643
644 self->movetype = MOVETYPE_STEP;
645 self->solid = SOLID_BBOX;
646 self->s.modelindex = gi.modelindex ("models/monsters/brain/tris.md2");
647 VectorSet (self->mins, -16, -16, -24);
648 VectorSet (self->maxs, 16, 16, 32);
649
650 self->health = 300;
651 self->gib_health = -150;
652 self->mass = 400;
653
654 self->pain = brain_pain;
655 self->die = brain_die;
656
657 self->monsterinfo.stand = brain_stand;
658 self->monsterinfo.walk = brain_walk;
659 self->monsterinfo.run = brain_run;
660 self->monsterinfo.dodge = brain_dodge;
661 // self->monsterinfo.attack = brain_attack;
662 self->monsterinfo.melee = brain_melee;
663 self->monsterinfo.sight = brain_sight;
664 self->monsterinfo.search = brain_search;
665 self->monsterinfo.idle = brain_idle;
666
667 self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN;
668 self->monsterinfo.power_armor_power = 100;
669
670 gi.linkentity (self);
671
672 self->monsterinfo.currentmove = &brain_move_stand;
673 self->monsterinfo.scale = MODEL_SCALE;
674
675 walkmonster_start (self);
676 }
677