File: game\m_boss32.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 Makron -- Final Boss
   24 
   25 ==============================================================================
   26 */
   27 
   28 #include "g_local.h"
   29 #include "m_boss32.h"
   30 
   31 qboolean visible (edict_t *self, edict_t *other);
   32 
   33 void MakronRailgun (edict_t *self);
   34 void MakronSaveloc (edict_t *self);
   35 void MakronHyperblaster (edict_t *self);
   36 void makron_step_left (edict_t *self);
   37 void makron_step_right (edict_t *self);
   38 void makronBFG (edict_t *self);
   39 void makron_dead (edict_t *self);
   40 
   41 static int      sound_pain4;
   42 static int      sound_pain5;
   43 static int      sound_pain6;
   44 static int      sound_death;
   45 static int      sound_step_left;
   46 static int      sound_step_right;
   47 static int      sound_attack_bfg;
   48 static int      sound_brainsplorch;
   49 static int      sound_prerailgun;
   50 static int      sound_popup;
   51 static int      sound_taunt1;
   52 static int      sound_taunt2;
   53 static int      sound_taunt3;
   54 static int      sound_hit;
   55 
   56 void makron_taunt (edict_t *self)
   57 {
   58         float r;
   59 
   60         r=random();
   61         if (r <= 0.3)
   62                 gi.sound (self, CHAN_AUTO, sound_taunt1, 1, ATTN_NONE, 0);
   63         else if (r <= 0.6)
   64                 gi.sound (self, CHAN_AUTO, sound_taunt2, 1, ATTN_NONE, 0);
   65         else
   66                 gi.sound (self, CHAN_AUTO, sound_taunt3, 1, ATTN_NONE, 0);
   67 }
   68 
   69 //
   70 // stand
   71 //
   72 
   73 mframe_t makron_frames_stand []=
   74 {
   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,              // 10
   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,              // 20
   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,              // 30
  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,              // 40
  115         ai_stand, 0, NULL,
  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,              // 50
  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               // 60
  135 };
  136 mmove_t makron_move_stand = {FRAME_stand201, FRAME_stand260, makron_frames_stand, NULL};
  137         
  138 void makron_stand (edict_t *self)
  139 {
  140         self->monsterinfo.currentmove = &makron_move_stand;
  141 }
  142 
  143 mframe_t makron_frames_run [] =
  144 {
  145         ai_run, 3,      makron_step_left,
  146         ai_run, 12,     NULL,
  147         ai_run, 8,      NULL,
  148         ai_run, 8,      NULL,
  149         ai_run, 8,      makron_step_right,
  150         ai_run, 6,      NULL,
  151         ai_run, 12,     NULL,
  152         ai_run, 9,      NULL,
  153         ai_run, 6,      NULL,
  154         ai_run, 12,     NULL
  155 };
  156 mmove_t makron_move_run = {FRAME_walk204, FRAME_walk213, makron_frames_run, NULL};
  157 
  158 void makron_hit (edict_t *self)
  159 {
  160         gi.sound (self, CHAN_AUTO, sound_hit, 1, ATTN_NONE,0);
  161 }
  162 
  163 void makron_popup (edict_t *self)
  164 {
  165         gi.sound (self, CHAN_BODY, sound_popup, 1, ATTN_NONE,0);
  166 }
  167 
  168 void makron_step_left (edict_t *self)
  169 {
  170         gi.sound (self, CHAN_BODY, sound_step_left, 1, ATTN_NORM,0);
  171 }
  172 
  173 void makron_step_right (edict_t *self)
  174 {
  175         gi.sound (self, CHAN_BODY, sound_step_right, 1, ATTN_NORM,0);
  176 }
  177 
  178 void makron_brainsplorch (edict_t *self)
  179 {
  180         gi.sound (self, CHAN_VOICE, sound_brainsplorch, 1, ATTN_NORM,0);
  181 }
  182 
  183 void makron_prerailgun (edict_t *self)
  184 {
  185         gi.sound (self, CHAN_WEAPON, sound_prerailgun, 1, ATTN_NORM,0);
  186 }
  187 
  188 
  189 mframe_t makron_frames_walk [] =
  190 {
  191         ai_walk, 3,     makron_step_left,
  192         ai_walk, 12,    NULL,
  193         ai_walk, 8,     NULL,
  194         ai_walk, 8,     NULL,
  195         ai_walk, 8,     makron_step_right,
  196         ai_walk, 6,     NULL,
  197         ai_walk, 12,    NULL,
  198         ai_walk, 9,     NULL,
  199         ai_walk, 6,     NULL,
  200         ai_walk, 12,    NULL
  201 };
  202 mmove_t makron_move_walk = {FRAME_walk204, FRAME_walk213, makron_frames_run, NULL};
  203 
  204 void makron_walk (edict_t *self)
  205 {
  206                 self->monsterinfo.currentmove = &makron_move_walk;
  207 }
  208 
  209 void makron_run (edict_t *self)
  210 {
  211         if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  212                 self->monsterinfo.currentmove = &makron_move_stand;
  213         else
  214                 self->monsterinfo.currentmove = &makron_move_run;
  215 }
  216 
  217 mframe_t makron_frames_pain6 [] =
  218 {
  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,           // 10
  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,      makron_popup,
  235         ai_move,        0,      NULL,
  236         ai_move,        0,      NULL,
  237         ai_move,        0,      NULL,
  238         ai_move,        0,      NULL,           // 20
  239         ai_move,        0,      NULL,
  240         ai_move,        0,      NULL,
  241         ai_move,        0,      NULL,
  242         ai_move,        0,      makron_taunt,
  243         ai_move,        0,      NULL,
  244         ai_move,        0,      NULL,
  245         ai_move,        0,      NULL
  246 };
  247 mmove_t makron_move_pain6 = {FRAME_pain601, FRAME_pain627, makron_frames_pain6, makron_run};
  248 
  249 mframe_t makron_frames_pain5 [] =
  250 {
  251         ai_move,        0,      NULL,
  252         ai_move,        0,      NULL,
  253         ai_move,        0,      NULL,
  254         ai_move,        0,      NULL
  255 };
  256 mmove_t makron_move_pain5 = {FRAME_pain501, FRAME_pain504, makron_frames_pain5, makron_run};
  257 
  258 mframe_t makron_frames_pain4 [] =
  259 {
  260         ai_move,        0,      NULL,
  261         ai_move,        0,      NULL,
  262         ai_move,        0,      NULL,
  263         ai_move,        0,      NULL
  264 };
  265 mmove_t makron_move_pain4 = {FRAME_pain401, FRAME_pain404, makron_frames_pain4, makron_run};
  266 
  267 mframe_t makron_frames_death2 [] =
  268 {
  269         ai_move,        -15,    NULL,
  270         ai_move,        3,      NULL,
  271         ai_move,        -12,    NULL,
  272         ai_move,        0,      makron_step_left,
  273         ai_move,        0,      NULL,
  274         ai_move,        0,      NULL,
  275         ai_move,        0,      NULL,
  276         ai_move,        0,      NULL,
  277         ai_move,        0,      NULL,
  278         ai_move,        0,      NULL,                   // 10
  279         ai_move,        0,      NULL,
  280         ai_move,        0,      NULL,
  281         ai_move,        0,      NULL,
  282         ai_move,        0,      NULL,
  283         ai_move,        0,      NULL,
  284         ai_move,        11,     NULL,
  285         ai_move,        12,     NULL,
  286         ai_move,        11,     makron_step_right,
  287         ai_move,        0,      NULL,
  288         ai_move,        0,      NULL,                   // 20
  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,        0,      NULL,
  298         ai_move,        0,      NULL,                   // 30
  299         ai_move,        0,      NULL,
  300         ai_move,        0,      NULL,
  301         ai_move,        0,      NULL,
  302         ai_move,        5,      NULL,
  303         ai_move,        7,      NULL,
  304         ai_move,        6,      makron_step_left,
  305         ai_move,        0,      NULL,
  306         ai_move,        0,      NULL,
  307         ai_move,        -1,     NULL,
  308         ai_move,        2,      NULL,                   // 40
  309         ai_move,        0,      NULL,                   
  310         ai_move,        0,      NULL,
  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,                   // 50
  319         ai_move,        0,      NULL,                   
  320         ai_move,        0,      NULL,
  321         ai_move,        0,      NULL,
  322         ai_move,        -6,     NULL,
  323         ai_move,        -4,     NULL,
  324         ai_move,        -6,     makron_step_right,
  325         ai_move,        -4,     NULL,
  326         ai_move,        -4,     makron_step_left,
  327         ai_move,        0,      NULL,
  328         ai_move,        0,      NULL,                   // 60
  329         ai_move,        0,      NULL,                   
  330         ai_move,        0,      NULL,
  331         ai_move,        -2,     NULL,
  332         ai_move,        -5,     NULL,
  333         ai_move,        -3,     makron_step_right,
  334         ai_move,        -8,     NULL,
  335         ai_move,        -3,     makron_step_left,
  336         ai_move,        -7,     NULL,
  337         ai_move,        -4,     NULL,
  338         ai_move,        -4,     makron_step_right,                      // 70
  339         ai_move,        -6,     NULL,                   
  340         ai_move,        -7,     NULL,
  341         ai_move,        0,      makron_step_left,
  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,                   // 80
  349         ai_move,        0,      NULL,                   
  350         ai_move,        0,      NULL,
  351         ai_move,        0,      NULL,
  352         ai_move,        0,      NULL,
  353         ai_move,        0,      NULL,
  354         ai_move,        -2,     NULL,
  355         ai_move,        0,      NULL,
  356         ai_move,        0,      NULL,
  357         ai_move,        2,      NULL,
  358         ai_move,        0,      NULL,                   // 90
  359         ai_move,        27,     makron_hit,                     
  360         ai_move,        26,     NULL,
  361         ai_move,        0,      makron_brainsplorch,
  362         ai_move,        0,      NULL,
  363         ai_move,        0,      NULL                    // 95
  364 };
  365 mmove_t makron_move_death2 = {FRAME_death201, FRAME_death295, makron_frames_death2, makron_dead};
  366 
  367 mframe_t makron_frames_death3 [] =
  368 {
  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         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 };
  390 mmove_t makron_move_death3 = {FRAME_death301, FRAME_death320, makron_frames_death3, NULL};
  391 
  392 mframe_t makron_frames_sight [] =
  393 {
  394         ai_move,        0,      NULL,
  395         ai_move,        0,      NULL,
  396         ai_move,        0,      NULL,
  397         ai_move,        0,      NULL,
  398         ai_move,        0,      NULL,
  399         ai_move,        0,      NULL,
  400         ai_move,        0,      NULL,
  401         ai_move,        0,      NULL,
  402         ai_move,        0,      NULL,
  403         ai_move,        0,      NULL,
  404         ai_move,        0,      NULL,
  405         ai_move,        0,      NULL,
  406         ai_move,        0,      NULL
  407 };
  408 mmove_t makron_move_sight= {FRAME_active01, FRAME_active13, makron_frames_sight, makron_run};
  409 
  410 void makronBFG (edict_t *self)
  411 {
  412         vec3_t  forward, right;
  413         vec3_t  start;
  414         vec3_t  dir;
  415         vec3_t  vec;
  416 
  417         AngleVectors (self->s.angles, forward, right, NULL);
  418         G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_MAKRON_BFG], forward, right, start);
  419 
  420         VectorCopy (self->enemy->s.origin, vec);
  421         vec[2] += self->enemy->viewheight;
  422         VectorSubtract (vec, start, dir);
  423         VectorNormalize (dir);
  424         gi.sound (self, CHAN_VOICE, sound_attack_bfg, 1, ATTN_NORM, 0);
  425         monster_fire_bfg (self, start, dir, 50, 300, 100, 300, MZ2_MAKRON_BFG);
  426 }       
  427 
  428 
  429 mframe_t makron_frames_attack3 []=
  430 {
  431         ai_charge,      0,      NULL,
  432         ai_charge,      0,      NULL,
  433         ai_charge,      0,      NULL,
  434         ai_charge,      0,      makronBFG,              // FIXME: BFG Attack here
  435         ai_move,        0,      NULL,
  436         ai_move,        0,      NULL,
  437         ai_move,        0,      NULL,
  438         ai_move,        0,      NULL
  439 };
  440 mmove_t makron_move_attack3 = {FRAME_attak301, FRAME_attak308, makron_frames_attack3, makron_run};
  441 
  442 mframe_t makron_frames_attack4[]=
  443 {
  444         ai_charge,      0,      NULL,
  445         ai_charge,      0,      NULL,
  446         ai_charge,      0,      NULL,
  447         ai_charge,      0,      NULL,
  448         ai_move,        0,      MakronHyperblaster,             // fire
  449         ai_move,        0,      MakronHyperblaster,             // fire
  450         ai_move,        0,      MakronHyperblaster,             // fire
  451         ai_move,        0,      MakronHyperblaster,             // fire
  452         ai_move,        0,      MakronHyperblaster,             // fire
  453         ai_move,        0,      MakronHyperblaster,             // fire
  454         ai_move,        0,      MakronHyperblaster,             // fire
  455         ai_move,        0,      MakronHyperblaster,             // fire
  456         ai_move,        0,      MakronHyperblaster,             // fire
  457         ai_move,        0,      MakronHyperblaster,             // fire
  458         ai_move,        0,      MakronHyperblaster,             // fire
  459         ai_move,        0,      MakronHyperblaster,             // fire
  460         ai_move,        0,      MakronHyperblaster,             // fire
  461         ai_move,        0,      MakronHyperblaster,             // fire
  462         ai_move,        0,      MakronHyperblaster,             // fire
  463         ai_move,        0,      MakronHyperblaster,             // fire
  464         ai_move,        0,      MakronHyperblaster,             // fire
  465         ai_move,        0,      NULL,
  466         ai_move,        0,      NULL,
  467         ai_move,        0,      NULL,
  468         ai_move,        0,      NULL,
  469         ai_move,        0,      NULL
  470 };
  471 mmove_t makron_move_attack4 = {FRAME_attak401, FRAME_attak426, makron_frames_attack4, makron_run};
  472 
  473 mframe_t makron_frames_attack5[]=
  474 {
  475         ai_charge,      0,      makron_prerailgun,
  476         ai_charge,      0,      NULL,
  477         ai_charge,      0,      NULL,
  478         ai_charge,      0,      NULL,
  479         ai_charge,      0,      NULL,
  480         ai_charge,      0,      NULL,
  481         ai_charge,      0,      NULL,
  482         ai_charge,      0,      MakronSaveloc,
  483         ai_move,        0,      MakronRailgun,          // Fire railgun
  484         ai_move,        0,      NULL,
  485         ai_move,        0,      NULL,
  486         ai_move,        0,      NULL,
  487         ai_move,        0,      NULL,
  488         ai_move,        0,      NULL,
  489         ai_move,        0,      NULL,
  490         ai_move,        0,      NULL
  491 };
  492 mmove_t makron_move_attack5 = {FRAME_attak501, FRAME_attak516, makron_frames_attack5, makron_run};
  493 
  494 void MakronSaveloc (edict_t *self)
  495 {
  496         VectorCopy (self->enemy->s.origin, self->pos1); //save for aiming the shot
  497         self->pos1[2] += self->enemy->viewheight;
  498 };
  499 
  500 // FIXME: He's not firing from the proper Z
  501 void MakronRailgun (edict_t *self)
  502 {
  503         vec3_t  start;
  504         vec3_t  dir;
  505         vec3_t  forward, right;
  506 
  507         AngleVectors (self->s.angles, forward, right, NULL);
  508         G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_MAKRON_RAILGUN_1], forward, right, start);
  509         
  510         // calc direction to where we targted
  511         VectorSubtract (self->pos1, start, dir);
  512         VectorNormalize (dir);
  513 
  514         monster_fire_railgun (self, start, dir, 50, 100, MZ2_MAKRON_RAILGUN_1);
  515 }
  516 
  517 // FIXME: This is all wrong. He's not firing at the proper angles.
  518 void MakronHyperblaster (edict_t *self)
  519 {
  520         vec3_t  dir;
  521         vec3_t  vec;
  522         vec3_t  start;
  523         vec3_t  forward, right;
  524         int             flash_number;
  525 
  526         flash_number = MZ2_MAKRON_BLASTER_1 + (self->s.frame - FRAME_attak405);
  527 
  528         AngleVectors (self->s.angles, forward, right, NULL);
  529         G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
  530 
  531         if (self->enemy)
  532         {
  533                 VectorCopy (self->enemy->s.origin, vec);
  534                 vec[2] += self->enemy->viewheight;
  535                 VectorSubtract (vec, start, vec);
  536                 vectoangles (vec, vec);
  537                 dir[0] = vec[0];
  538         }
  539         else
  540         {
  541                 dir[0] = 0;
  542         }
  543         if (self->s.frame <= FRAME_attak413)
  544                 dir[1] = self->s.angles[1] - 10 * (self->s.frame - FRAME_attak413);
  545         else
  546                 dir[1] = self->s.angles[1] + 10 * (self->s.frame - FRAME_attak421);
  547         dir[2] = 0;
  548 
  549         AngleVectors (dir, forward, NULL, NULL);
  550 
  551         monster_fire_blaster (self, start, forward, 15, 1000, MZ2_MAKRON_BLASTER_1, EF_BLASTER);
  552 }       
  553 
  554 
  555 void makron_pain (edict_t *self, edict_t *other, float kick, int damage)
  556 {
  557 
  558         if (self->health < (self->max_health / 2))
  559                         self->s.skinnum = 1;
  560 
  561         if (level.time < self->pain_debounce_time)
  562                         return;
  563 
  564         // Lessen the chance of him going into his pain frames
  565         if (damage <=25)
  566                 if (random()<0.2)
  567                         return;
  568 
  569         self->pain_debounce_time = level.time + 3;
  570         if (skill->value == 3)
  571                 return;         // no pain anims in nightmare
  572 
  573 
  574         if (damage <= 40)
  575         {
  576                 gi.sound (self, CHAN_VOICE, sound_pain4, 1, ATTN_NONE,0);
  577                 self->monsterinfo.currentmove = &makron_move_pain4;
  578         }
  579         else if (damage <= 110)
  580         {
  581                 gi.sound (self, CHAN_VOICE, sound_pain5, 1, ATTN_NONE,0);
  582                 self->monsterinfo.currentmove = &makron_move_pain5;
  583         }
  584         else
  585         {
  586                 if (damage <= 150)
  587                         if (random() <= 0.45)
  588                         {
  589                                 gi.sound (self, CHAN_VOICE, sound_pain6, 1, ATTN_NONE,0);
  590                                 self->monsterinfo.currentmove = &makron_move_pain6;
  591                         }
  592                 else
  593                         if (random() <= 0.35)
  594                         {
  595                                 gi.sound (self, CHAN_VOICE, sound_pain6, 1, ATTN_NONE,0);
  596                                 self->monsterinfo.currentmove = &makron_move_pain6;
  597                         }
  598         }
  599 };
  600 
  601 void makron_sight(edict_t *self, edict_t *other)
  602 {
  603         self->monsterinfo.currentmove = &makron_move_sight;
  604 };
  605 
  606 void makron_attack(edict_t *self)
  607 {
  608         vec3_t  vec;
  609         float   range;
  610         float   r;
  611 
  612         r = random();
  613 
  614         VectorSubtract (self->enemy->s.origin, self->s.origin, vec);
  615         range = VectorLength (vec);
  616 
  617 
  618         if (r <= 0.3)
  619                 self->monsterinfo.currentmove = &makron_move_attack3;
  620         else if (r <= 0.6)
  621                 self->monsterinfo.currentmove = &makron_move_attack4;
  622         else
  623                 self->monsterinfo.currentmove = &makron_move_attack5;
  624 }
  625 
  626 /*
  627 ---
  628 Makron Torso. This needs to be spawned in
  629 ---
  630 */
  631 
  632 void makron_torso_think (edict_t *self)
  633 {
  634         if (++self->s.frame < 365)
  635                 self->nextthink = level.time + FRAMETIME;
  636         else
  637         {               
  638                 self->s.frame = 346;
  639                 self->nextthink = level.time + FRAMETIME;
  640         }
  641 }
  642 
  643 void makron_torso (edict_t *ent)
  644 {
  645         ent->movetype = MOVETYPE_NONE;
  646         ent->solid = SOLID_NOT;
  647         VectorSet (ent->mins, -8, -8, 0);
  648         VectorSet (ent->maxs, 8, 8, 8);
  649         ent->s.frame = 346;
  650         ent->s.modelindex = gi.modelindex ("models/monsters/boss3/rider/tris.md2");
  651         ent->think = makron_torso_think;
  652         ent->nextthink = level.time + 2 * FRAMETIME;
  653         ent->s.sound = gi.soundindex ("makron/spine.wav");
  654         gi.linkentity (ent);
  655 }
  656 
  657 
  658 //
  659 // death
  660 //
  661 
  662 void makron_dead (edict_t *self)
  663 {
  664         VectorSet (self->mins, -60, -60, 0);
  665         VectorSet (self->maxs, 60, 60, 72);
  666         self->movetype = MOVETYPE_TOSS;
  667         self->svflags |= SVF_DEADMONSTER;
  668         self->nextthink = 0;
  669         gi.linkentity (self);
  670 }
  671 
  672 
  673 void makron_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
  674 {
  675         edict_t *tempent;
  676 
  677         int             n;
  678 
  679         self->s.sound = 0;
  680         // check for gib
  681         if (self->health <= self->gib_health)
  682         {
  683                 gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
  684                 for (n= 0; n < 1 /*4*/; n++)
  685                         ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
  686                 for (n= 0; n < 4; n++)
  687                         ThrowGib (self, "models/objects/gibs/sm_metal/tris.md2", damage, GIB_METALLIC);
  688                 ThrowHead (self, "models/objects/gibs/gear/tris.md2", damage, GIB_METALLIC);
  689                 self->deadflag = DEAD_DEAD;
  690                 return;
  691         }
  692 
  693         if (self->deadflag == DEAD_DEAD)
  694                 return;
  695 
  696 // regular death
  697         gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NONE, 0);
  698         self->deadflag = DEAD_DEAD;
  699         self->takedamage = DAMAGE_YES;
  700 
  701         tempent = G_Spawn();
  702         VectorCopy (self->s.origin, tempent->s.origin);
  703         VectorCopy (self->s.angles, tempent->s.angles);
  704         tempent->s.origin[1] -= 84;
  705         makron_torso (tempent);
  706 
  707         self->monsterinfo.currentmove = &makron_move_death2;
  708         
  709 }
  710 
  711 qboolean Makron_CheckAttack (edict_t *self)
  712 {
  713         vec3_t  spot1, spot2;
  714         vec3_t  temp;
  715         float   chance;
  716         trace_t tr;
  717         qboolean        enemy_infront;
  718         int                     enemy_range;
  719         float           enemy_yaw;
  720 
  721         if (self->enemy->health > 0)
  722         {
  723         // see if any entities are in the way of the shot
  724                 VectorCopy (self->s.origin, spot1);
  725                 spot1[2] += self->viewheight;
  726                 VectorCopy (self->enemy->s.origin, spot2);
  727                 spot2[2] += self->enemy->viewheight;
  728 
  729                 tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA);
  730 
  731                 // do we have a clear shot?
  732                 if (tr.ent != self->enemy)
  733                         return false;
  734         }
  735         
  736         enemy_infront = infront(self, self->enemy);
  737         enemy_range = range(self, self->enemy);
  738         VectorSubtract (self->enemy->s.origin, self->s.origin, temp);
  739         enemy_yaw = vectoyaw(temp);
  740 
  741         self->ideal_yaw = enemy_yaw;
  742 
  743 
  744         // melee attack
  745         if (enemy_range == RANGE_MELEE)
  746         {
  747                 if (self->monsterinfo.melee)
  748                         self->monsterinfo.attack_state = AS_MELEE;
  749                 else
  750                         self->monsterinfo.attack_state = AS_MISSILE;
  751                 return true;
  752         }
  753         
  754 // missile attack
  755         if (!self->monsterinfo.attack)
  756                 return false;
  757                 
  758         if (level.time < self->monsterinfo.attack_finished)
  759                 return false;
  760                 
  761         if (enemy_range == RANGE_FAR)
  762                 return false;
  763 
  764         if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  765         {
  766                 chance = 0.4;
  767         }
  768         else if (enemy_range == RANGE_MELEE)
  769         {
  770                 chance = 0.8;
  771         }
  772         else if (enemy_range == RANGE_NEAR)
  773         {
  774                 chance = 0.4;
  775         }
  776         else if (enemy_range == RANGE_MID)
  777         {
  778                 chance = 0.2;
  779         }
  780         else
  781         {
  782                 return false;
  783         }
  784 
  785         if (random () < chance)
  786         {
  787                 self->monsterinfo.attack_state = AS_MISSILE;
  788                 self->monsterinfo.attack_finished = level.time + 2*random();
  789                 return true;
  790         }
  791 
  792         if (self->flags & FL_FLY)
  793         {
  794                 if (random() < 0.3)
  795                         self->monsterinfo.attack_state = AS_SLIDING;
  796                 else
  797                         self->monsterinfo.attack_state = AS_STRAIGHT;
  798         }
  799 
  800         return false;
  801 }
  802 
  803 
  804 //
  805 // monster_makron
  806 //
  807 
  808 void MakronPrecache (void)
  809 {
  810         sound_pain4 = gi.soundindex ("makron/pain3.wav");
  811         sound_pain5 = gi.soundindex ("makron/pain2.wav");
  812         sound_pain6 = gi.soundindex ("makron/pain1.wav");
  813         sound_death = gi.soundindex ("makron/death.wav");
  814         sound_step_left = gi.soundindex ("makron/step1.wav");
  815         sound_step_right = gi.soundindex ("makron/step2.wav");
  816         sound_attack_bfg = gi.soundindex ("makron/bfg_fire.wav");
  817         sound_brainsplorch = gi.soundindex ("makron/brain1.wav");
  818         sound_prerailgun = gi.soundindex ("makron/rail_up.wav");
  819         sound_popup = gi.soundindex ("makron/popup.wav");
  820         sound_taunt1 = gi.soundindex ("makron/voice4.wav");
  821         sound_taunt2 = gi.soundindex ("makron/voice3.wav");
  822         sound_taunt3 = gi.soundindex ("makron/voice.wav");
  823         sound_hit = gi.soundindex ("makron/bhit.wav");
  824 
  825         gi.modelindex ("models/monsters/boss3/rider/tris.md2");
  826 }
  827 
  828 /*QUAKED monster_makron (1 .5 0) (-30 -30 0) (30 30 90) Ambush Trigger_Spawn Sight
  829 */
  830 void SP_monster_makron (edict_t *self)
  831 {
  832         if (deathmatch->value)
  833         {
  834                 G_FreeEdict (self);
  835                 return;
  836         }
  837 
  838         MakronPrecache ();
  839 
  840         self->movetype = MOVETYPE_STEP;
  841         self->solid = SOLID_BBOX;
  842         self->s.modelindex = gi.modelindex ("models/monsters/boss3/rider/tris.md2");
  843         VectorSet (self->mins, -30, -30, 0);
  844         VectorSet (self->maxs, 30, 30, 90);
  845 
  846         self->health = 3000;
  847         self->gib_health = -2000;
  848         self->mass = 500;
  849 
  850         self->pain = makron_pain;
  851         self->die = makron_die;
  852         self->monsterinfo.stand = makron_stand;
  853         self->monsterinfo.walk = makron_walk;
  854         self->monsterinfo.run = makron_run;
  855         self->monsterinfo.dodge = NULL;
  856         self->monsterinfo.attack = makron_attack;
  857         self->monsterinfo.melee = NULL;
  858         self->monsterinfo.sight = makron_sight;
  859         self->monsterinfo.checkattack = Makron_CheckAttack;
  860 
  861         gi.linkentity (self);
  862         
  863 //      self->monsterinfo.currentmove = &makron_move_stand;
  864         self->monsterinfo.currentmove = &makron_move_sight;
  865         self->monsterinfo.scale = MODEL_SCALE;
  866 
  867         walkmonster_start(self);
  868 }
  869 
  870 
  871 /*
  872 =================
  873 MakronSpawn
  874 
  875 =================
  876 */
  877 void MakronSpawn (edict_t *self)
  878 {
  879         vec3_t          vec;
  880         edict_t         *player;
  881 
  882         SP_monster_makron (self);
  883 
  884         // jump at player
  885         player = level.sight_client;
  886         if (!player)
  887                 return;
  888 
  889         VectorSubtract (player->s.origin, self->s.origin, vec);
  890         self->s.angles[YAW] = vectoyaw(vec);
  891         VectorNormalize (vec);
  892         VectorMA (vec3_origin, 400, vec, self->velocity);
  893         self->velocity[2] = 200;
  894         self->groundentity = NULL;
  895 }
  896 
  897 /*
  898 =================
  899 MakronToss
  900 
  901 Jorg is just about dead, so set up to launch Makron out
  902 =================
  903 */
  904 void MakronToss (edict_t *self)
  905 {
  906         edict_t *ent;
  907 
  908         ent = G_Spawn ();
  909         ent->nextthink = level.time + 0.8;
  910         ent->think = MakronSpawn;
  911         ent->target = self->target;
  912         VectorCopy (self->s.origin, ent->s.origin);
  913 }
  914