File: game\m_boss31.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 jorg
   24 
   25 ==============================================================================
   26 */
   27 
   28 #include "g_local.h"
   29 #include "m_boss31.h"
   30 
   31 extern SP_monster_makron (edict_t *self);
   32 qboolean visible (edict_t *self, edict_t *other);
   33 
   34 static int      sound_pain1;
   35 static int      sound_pain2;
   36 static int      sound_pain3;
   37 static int      sound_idle;
   38 static int      sound_death;
   39 static int      sound_search1;
   40 static int      sound_search2;
   41 static int      sound_search3;
   42 static int      sound_attack1;
   43 static int      sound_attack2;
   44 static int      sound_firegun;
   45 static int      sound_step_left;
   46 static int      sound_step_right;
   47 static int      sound_death_hit;
   48 
   49 void BossExplode (edict_t *self);
   50 void MakronToss (edict_t *self);
   51 
   52 
   53 void jorg_search (edict_t *self)
   54 {
   55         float r;
   56 
   57         r = random();
   58 
   59         if (r <= 0.3)
   60                 gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NORM, 0);
   61         else if (r <= 0.6)
   62                 gi.sound (self, CHAN_VOICE, sound_search2, 1, ATTN_NORM, 0);
   63         else
   64                 gi.sound (self, CHAN_VOICE, sound_search3, 1, ATTN_NORM, 0);
   65 }
   66 
   67 
   68 void jorg_dead (edict_t *self);
   69 void jorgBFG (edict_t *self);
   70 void jorgMachineGun (edict_t *self);
   71 void jorg_firebullet (edict_t *self);
   72 void jorg_reattack1(edict_t *self);
   73 void jorg_attack1(edict_t *self);
   74 void jorg_idle(edict_t *self);
   75 void jorg_step_left(edict_t *self);
   76 void jorg_step_right(edict_t *self);
   77 void jorg_death_hit(edict_t *self);
   78 
   79 //
   80 // stand
   81 //
   82 
   83 mframe_t jorg_frames_stand []=
   84 {
   85         ai_stand, 0, jorg_idle,
   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,              // 10
   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,              // 20
  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,              // 30
  115         ai_stand, 0, NULL,
  116         ai_stand, 0, NULL,
  117         ai_stand, 0, NULL,
  118         ai_stand, 19, NULL,
  119         ai_stand, 11, jorg_step_left,
  120         ai_stand, 0, NULL,
  121         ai_stand, 0, NULL,
  122         ai_stand, 6, NULL,
  123         ai_stand, 9, jorg_step_right,
  124         ai_stand, 0, NULL,              // 40
  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, -2, NULL,
  132         ai_stand, -17, jorg_step_left,
  133         ai_stand, 0, NULL,
  134         ai_stand, -12, NULL,            // 50
  135         ai_stand, -14, jorg_step_right  // 51
  136 };
  137 mmove_t jorg_move_stand = {FRAME_stand01, FRAME_stand51, jorg_frames_stand, NULL};
  138 
  139 void jorg_idle (edict_t *self)
  140 {
  141         gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_NORM,0);
  142 }
  143 
  144 void jorg_death_hit (edict_t *self)
  145 {
  146         gi.sound (self, CHAN_BODY, sound_death_hit, 1, ATTN_NORM,0);
  147 }
  148 
  149 
  150 void jorg_step_left (edict_t *self)
  151 {
  152         gi.sound (self, CHAN_BODY, sound_step_left, 1, ATTN_NORM,0);
  153 }
  154 
  155 void jorg_step_right (edict_t *self)
  156 {
  157         gi.sound (self, CHAN_BODY, sound_step_right, 1, ATTN_NORM,0);
  158 }
  159 
  160 
  161 void jorg_stand (edict_t *self)
  162 {
  163         self->monsterinfo.currentmove = &jorg_move_stand;
  164 }
  165 
  166 mframe_t jorg_frames_run [] =
  167 {
  168         ai_run, 17,     jorg_step_left,
  169         ai_run, 0,      NULL,
  170         ai_run, 0,      NULL,
  171         ai_run, 0,      NULL,
  172         ai_run, 12,     NULL,
  173         ai_run, 8,      NULL,
  174         ai_run, 10,     NULL,
  175         ai_run, 33,     jorg_step_right,
  176         ai_run, 0,      NULL,
  177         ai_run, 0,      NULL,
  178         ai_run, 0,      NULL,
  179         ai_run, 9,      NULL,
  180         ai_run, 9,      NULL,
  181         ai_run, 9,      NULL
  182 };
  183 mmove_t jorg_move_run = {FRAME_walk06, FRAME_walk19, jorg_frames_run, NULL};
  184 
  185 //
  186 // walk
  187 //
  188 
  189 mframe_t jorg_frames_start_walk [] =
  190 {
  191         ai_walk,        5,      NULL,
  192         ai_walk,        6,      NULL,
  193         ai_walk,        7,      NULL,
  194         ai_walk,        9,      NULL,
  195         ai_walk,        15,     NULL
  196 };
  197 mmove_t jorg_move_start_walk = {FRAME_walk01, FRAME_walk05, jorg_frames_start_walk, NULL};
  198 
  199 mframe_t jorg_frames_walk [] =
  200 {
  201         ai_walk, 17,    NULL,
  202         ai_walk, 0,     NULL,
  203         ai_walk, 0,     NULL,
  204         ai_walk, 0,     NULL,
  205         ai_walk, 12,    NULL,
  206         ai_walk, 8,     NULL,
  207         ai_walk, 10,    NULL,
  208         ai_walk, 33,    NULL,
  209         ai_walk, 0,     NULL,
  210         ai_walk, 0,     NULL,
  211         ai_walk, 0,     NULL,
  212         ai_walk, 9,     NULL,
  213         ai_walk, 9,     NULL,
  214         ai_walk, 9,     NULL
  215 };
  216 mmove_t jorg_move_walk = {FRAME_walk06, FRAME_walk19, jorg_frames_walk, NULL};
  217 
  218 mframe_t jorg_frames_end_walk [] =
  219 {
  220         ai_walk,        11,     NULL,
  221         ai_walk,        0,      NULL,
  222         ai_walk,        0,      NULL,
  223         ai_walk,        0,      NULL,
  224         ai_walk,        8,      NULL,
  225         ai_walk,        -8,     NULL
  226 };
  227 mmove_t jorg_move_end_walk = {FRAME_walk20, FRAME_walk25, jorg_frames_end_walk, NULL};
  228 
  229 void jorg_walk (edict_t *self)
  230 {
  231                 self->monsterinfo.currentmove = &jorg_move_walk;
  232 }
  233 
  234 void jorg_run (edict_t *self)
  235 {
  236         if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  237                 self->monsterinfo.currentmove = &jorg_move_stand;
  238         else
  239                 self->monsterinfo.currentmove = &jorg_move_run;
  240 }
  241 
  242 mframe_t jorg_frames_pain3 [] =
  243 {
  244         ai_move,        -28,    NULL,
  245         ai_move,        -6,     NULL,
  246         ai_move,        -3,     jorg_step_left,
  247         ai_move,        -9,     NULL,
  248         ai_move,        0,      jorg_step_right,
  249         ai_move,        0,      NULL,
  250         ai_move,        0,      NULL,
  251         ai_move,        0,      NULL,
  252         ai_move,        -7,     NULL,
  253         ai_move,        1,      NULL,
  254         ai_move,        -11,    NULL,
  255         ai_move,        -4,     NULL,
  256         ai_move,        0,      NULL,
  257         ai_move,        0,      NULL,
  258         ai_move,        10,     NULL,
  259         ai_move,        11,     NULL,
  260         ai_move,        0,      NULL,
  261         ai_move,        10,     NULL,
  262         ai_move,        3,      NULL,
  263         ai_move,        10,     NULL,
  264         ai_move,        7,      jorg_step_left,
  265         ai_move,        17,     NULL,
  266         ai_move,        0,      NULL,
  267         ai_move,        0,      NULL,
  268         ai_move,        0,      jorg_step_right
  269 };
  270 mmove_t jorg_move_pain3 = {FRAME_pain301, FRAME_pain325, jorg_frames_pain3, jorg_run};
  271 
  272 mframe_t jorg_frames_pain2 [] =
  273 {
  274         ai_move,        0,      NULL,
  275         ai_move,        0,      NULL,
  276         ai_move,        0,      NULL
  277 };
  278 mmove_t jorg_move_pain2 = {FRAME_pain201, FRAME_pain203, jorg_frames_pain2, jorg_run};
  279 
  280 mframe_t jorg_frames_pain1 [] =
  281 {
  282         ai_move,        0,      NULL,
  283         ai_move,        0,      NULL,
  284         ai_move,        0,      NULL
  285 };
  286 mmove_t jorg_move_pain1 = {FRAME_pain101, FRAME_pain103, jorg_frames_pain1, jorg_run};
  287 
  288 mframe_t jorg_frames_death1 [] =
  289 {
  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,
  299         ai_move,        0,      NULL,           // 10
  300         ai_move,        0,      NULL,
  301         ai_move,        0,      NULL,
  302         ai_move,        0,      NULL,
  303         ai_move,        0,      NULL,
  304         ai_move,        0,      NULL,
  305         ai_move,        0,      NULL,
  306         ai_move,        0,      NULL,
  307         ai_move,        0,      NULL,
  308         ai_move,        0,      NULL,
  309         ai_move,        0,      NULL,           // 20
  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,
  319         ai_move,        0,      NULL,           // 30
  320         ai_move,        0,      NULL,
  321         ai_move,        0,      NULL,
  322         ai_move,        0,      NULL,
  323         ai_move,        0,      NULL,
  324         ai_move,        0,      NULL,
  325         ai_move,        0,      NULL,
  326         ai_move,        0,      NULL,
  327         ai_move,        0,      NULL,
  328         ai_move,        0,      NULL,
  329         ai_move,        0,      NULL,           // 40
  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         ai_move,        0,      NULL,                   
  337         ai_move,        0,      NULL,
  338         ai_move,        0,      MakronToss,
  339         ai_move,        0,      BossExplode             // 50
  340 };
  341 mmove_t jorg_move_death = {FRAME_death01, FRAME_death50, jorg_frames_death1, jorg_dead};
  342 
  343 mframe_t jorg_frames_attack2 []=
  344 {
  345         ai_charge,      0,      NULL,
  346         ai_charge,      0,      NULL,
  347         ai_charge,      0,      NULL,
  348         ai_charge,      0,      NULL,
  349         ai_charge,      0,      NULL,
  350         ai_charge,      0,      NULL,
  351         ai_charge,      0,      jorgBFG,                
  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 };
  359 mmove_t jorg_move_attack2 = {FRAME_attak201, FRAME_attak213, jorg_frames_attack2, jorg_run};
  360 
  361 mframe_t jorg_frames_start_attack1 [] =
  362 {
  363         ai_charge,      0,      NULL,
  364         ai_charge,      0,      NULL,
  365         ai_charge,      0,      NULL,
  366         ai_charge,      0,      NULL,
  367         ai_charge,      0,      NULL,
  368         ai_charge,      0,      NULL,
  369         ai_charge,      0,      NULL,
  370         ai_charge,      0,      NULL
  371 };
  372 mmove_t jorg_move_start_attack1 = {FRAME_attak101, FRAME_attak108, jorg_frames_start_attack1, jorg_attack1};
  373 
  374 mframe_t jorg_frames_attack1[]=
  375 {
  376         ai_charge,      0,      jorg_firebullet,
  377         ai_charge,      0,      jorg_firebullet,
  378         ai_charge,      0,      jorg_firebullet,
  379         ai_charge,      0,      jorg_firebullet,
  380         ai_charge,      0,      jorg_firebullet,
  381         ai_charge,      0,      jorg_firebullet
  382 };
  383 mmove_t jorg_move_attack1 = {FRAME_attak109, FRAME_attak114, jorg_frames_attack1, jorg_reattack1};
  384 
  385 mframe_t jorg_frames_end_attack1[]=
  386 {
  387         ai_move,        0,      NULL,
  388         ai_move,        0,      NULL,
  389         ai_move,        0,      NULL,
  390         ai_move,        0,      NULL
  391 };
  392 mmove_t jorg_move_end_attack1 = {FRAME_attak115, FRAME_attak118, jorg_frames_end_attack1, jorg_run};
  393 
  394 void jorg_reattack1(edict_t *self)
  395 {
  396         if (visible(self, self->enemy))
  397                 if (random() < 0.9)
  398                         self->monsterinfo.currentmove = &jorg_move_attack1;
  399                 else
  400                 {
  401                         self->s.sound = 0;
  402                         self->monsterinfo.currentmove = &jorg_move_end_attack1; 
  403                 }
  404         else
  405         {
  406                 self->s.sound = 0;
  407                 self->monsterinfo.currentmove = &jorg_move_end_attack1; 
  408         }
  409 }
  410 
  411 void jorg_attack1(edict_t *self)
  412 {
  413         self->monsterinfo.currentmove = &jorg_move_attack1;
  414 }
  415 
  416 void jorg_pain (edict_t *self, edict_t *other, float kick, int damage)
  417 {
  418 
  419         if (self->health < (self->max_health / 2))
  420                         self->s.skinnum = 1;
  421         
  422         self->s.sound = 0;
  423 
  424         if (level.time < self->pain_debounce_time)
  425                         return;
  426 
  427         // Lessen the chance of him going into his pain frames if he takes little damage
  428         if (damage <= 40)
  429                 if (random()<=0.6)
  430                         return;
  431 
  432         /* 
  433         If he's entering his attack1 or using attack1, lessen the chance of him
  434         going into pain
  435         */
  436         
  437         if ( (self->s.frame >= FRAME_attak101) && (self->s.frame <= FRAME_attak108) )
  438                 if (random() <= 0.005)
  439                         return;
  440 
  441         if ( (self->s.frame >= FRAME_attak109) && (self->s.frame <= FRAME_attak114) )
  442                 if (random() <= 0.00005)
  443                         return;
  444 
  445 
  446         if ( (self->s.frame >= FRAME_attak201) && (self->s.frame <= FRAME_attak208) )
  447                 if (random() <= 0.005)
  448                         return;
  449 
  450 
  451         self->pain_debounce_time = level.time + 3;
  452         if (skill->value == 3)
  453                 return;         // no pain anims in nightmare
  454 
  455         if (damage <= 50)
  456         {
  457                 gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM,0);
  458                 self->monsterinfo.currentmove = &jorg_move_pain1;
  459         }
  460         else if (damage <= 100)
  461         {
  462                 gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM,0);
  463                 self->monsterinfo.currentmove = &jorg_move_pain2;
  464         }
  465         else
  466         {
  467                 if (random() <= 0.3)
  468                 {
  469                         gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NORM,0);
  470                         self->monsterinfo.currentmove = &jorg_move_pain3;
  471                 }
  472         }
  473 };
  474 
  475 void jorgBFG (edict_t *self)
  476 {
  477         vec3_t  forward, right;
  478         vec3_t  start;
  479         vec3_t  dir;
  480         vec3_t  vec;
  481 
  482         AngleVectors (self->s.angles, forward, right, NULL);
  483         G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_JORG_BFG_1], forward, right, start);
  484 
  485         VectorCopy (self->enemy->s.origin, vec);
  486         vec[2] += self->enemy->viewheight;
  487         VectorSubtract (vec, start, dir);
  488         VectorNormalize (dir);
  489         gi.sound (self, CHAN_VOICE, sound_attack2, 1, ATTN_NORM, 0);
  490         /*void monster_fire_bfg (edict_t *self, 
  491                                                          vec3_t start, 
  492                                                          vec3_t aimdir, 
  493                                                          int damage, 
  494                                                          int speed, 
  495                                                          int kick, 
  496                                                          float damage_radius, 
  497                                                          int flashtype)*/
  498         monster_fire_bfg (self, start, dir, 50, 300, 100, 200, MZ2_JORG_BFG_1);
  499 }       
  500 
  501 void jorg_firebullet_right (edict_t *self)
  502 {
  503         vec3_t  forward, right, target;
  504         vec3_t  start;
  505 
  506         AngleVectors (self->s.angles, forward, right, NULL);
  507         G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_JORG_MACHINEGUN_R1], forward, right, start);
  508 
  509         VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target);
  510         target[2] += self->enemy->viewheight;
  511         VectorSubtract (target, start, forward);
  512         VectorNormalize (forward);
  513 
  514         monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_JORG_MACHINEGUN_R1);
  515 }       
  516 
  517 void jorg_firebullet_left (edict_t *self)
  518 {
  519         vec3_t  forward, right, target;
  520         vec3_t  start;
  521 
  522         AngleVectors (self->s.angles, forward, right, NULL);
  523         G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_JORG_MACHINEGUN_L1], forward, right, start);
  524 
  525         VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target);
  526         target[2] += self->enemy->viewheight;
  527         VectorSubtract (target, start, forward);
  528         VectorNormalize (forward);
  529 
  530         monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_JORG_MACHINEGUN_L1);
  531 }       
  532 
  533 void jorg_firebullet (edict_t *self)
  534 {
  535         jorg_firebullet_left(self);
  536         jorg_firebullet_right(self);
  537 };
  538 
  539 void jorg_attack(edict_t *self)
  540 {
  541         vec3_t  vec;
  542         float   range;
  543         
  544         VectorSubtract (self->enemy->s.origin, self->s.origin, vec);
  545         range = VectorLength (vec);
  546 
  547         if (random() <= 0.75)
  548         {
  549                 gi.sound (self, CHAN_VOICE, sound_attack1, 1, ATTN_NORM,0);
  550                 self->s.sound = gi.soundindex ("boss3/w_loop.wav");
  551                 self->monsterinfo.currentmove = &jorg_move_start_attack1;
  552         }
  553         else
  554         {
  555                 gi.sound (self, CHAN_VOICE, sound_attack2, 1, ATTN_NORM,0);
  556                 self->monsterinfo.currentmove = &jorg_move_attack2;
  557         }
  558 }
  559 
  560 void jorg_dead (edict_t *self)
  561 {
  562 #if 0
563 edict_t *tempent; 564 /* 565 VectorSet (self->mins, -16, -16, -24); 566 VectorSet (self->maxs, 16, 16, -8); 567 */ 568 569 // Jorg is on modelindex2. Do not clear him. 570 VectorSet (self->mins, -60, -60, 0); 571 VectorSet (self->maxs, 60, 60, 72); 572 self->movetype = MOVETYPE_TOSS; 573 self->nextthink = 0; 574 gi.linkentity (self); 575 576 tempent = G_Spawn(); 577 VectorCopy (self->s.origin, tempent->s.origin); 578 VectorCopy (self->s.angles, tempent->s.angles); 579 tempent->killtarget = self->killtarget; 580 tempent->target = self->target; 581 tempent->activator = self->enemy; 582 self->killtarget = 0; 583 self->target = 0; 584 SP_monster_makron (tempent);
585 #endif 586 } 587 588 589 void jorg_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) 590 { 591 gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0); 592 self->deadflag = DEAD_DEAD; 593 self->takedamage = DAMAGE_NO; 594 self->s.sound = 0; 595 self->count = 0; 596 self->monsterinfo.currentmove = &jorg_move_death; 597 } 598 599 qboolean Jorg_CheckAttack (edict_t *self) 600 { 601 vec3_t spot1, spot2; 602 vec3_t temp; 603 float chance; 604 trace_t tr; 605 qboolean enemy_infront; 606 int enemy_range; 607 float enemy_yaw; 608 609 if (self->enemy->health > 0) 610 { 611 // see if any entities are in the way of the shot 612 VectorCopy (self->s.origin, spot1); 613 spot1[2] += self->viewheight; 614 VectorCopy (self->enemy->s.origin, spot2); 615 spot2[2] += self->enemy->viewheight; 616 617 tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA); 618 619 // do we have a clear shot? 620 if (tr.ent != self->enemy) 621 return false; 622 } 623 624 enemy_infront = infront(self, self->enemy); 625 enemy_range = range(self, self->enemy); 626 VectorSubtract (self->enemy->s.origin, self->s.origin, temp); 627 enemy_yaw = vectoyaw(temp); 628 629 self->ideal_yaw = enemy_yaw; 630 631 632 // melee attack 633 if (enemy_range == RANGE_MELEE) 634 { 635 if (self->monsterinfo.melee) 636 self->monsterinfo.attack_state = AS_MELEE; 637 else 638 self->monsterinfo.attack_state = AS_MISSILE; 639 return true; 640 } 641 642 // missile attack 643 if (!self->monsterinfo.attack) 644 return false; 645 646 if (level.time < self->monsterinfo.attack_finished) 647 return false; 648 649 if (enemy_range == RANGE_FAR) 650 return false; 651 652 if (self->monsterinfo.aiflags & AI_STAND_GROUND) 653 { 654 chance = 0.4; 655 } 656 else if (enemy_range == RANGE_MELEE) 657 { 658 chance = 0.8; 659 } 660 else if (enemy_range == RANGE_NEAR) 661 { 662 chance = 0.4; 663 } 664 else if (enemy_range == RANGE_MID) 665 { 666 chance = 0.2; 667 } 668 else 669 { 670 return false; 671 } 672 673 if (random () < chance) 674 { 675 self->monsterinfo.attack_state = AS_MISSILE; 676 self->monsterinfo.attack_finished = level.time + 2*random(); 677 return true; 678 } 679 680 if (self->flags & FL_FLY) 681 { 682 if (random() < 0.3) 683 self->monsterinfo.attack_state = AS_SLIDING; 684 else 685 self->monsterinfo.attack_state = AS_STRAIGHT; 686 } 687 688 return false; 689 } 690 691 692 void MakronPrecache (void); 693 694 /*QUAKED monster_jorg (1 .5 0) (-80 -80 0) (90 90 140) Ambush Trigger_Spawn Sight 695 */ 696 void SP_monster_jorg (edict_t *self) 697 { 698 if (deathmatch->value) 699 { 700 G_FreeEdict (self); 701 return; 702 } 703 704 sound_pain1 = gi.soundindex ("boss3/bs3pain1.wav"); 705 sound_pain2 = gi.soundindex ("boss3/bs3pain2.wav"); 706 sound_pain3 = gi.soundindex ("boss3/bs3pain3.wav"); 707 sound_death = gi.soundindex ("boss3/bs3deth1.wav"); 708 sound_attack1 = gi.soundindex ("boss3/bs3atck1.wav"); 709 sound_attack2 = gi.soundindex ("boss3/bs3atck2.wav"); 710 sound_search1 = gi.soundindex ("boss3/bs3srch1.wav"); 711 sound_search2 = gi.soundindex ("boss3/bs3srch2.wav"); 712 sound_search3 = gi.soundindex ("boss3/bs3srch3.wav"); 713 sound_idle = gi.soundindex ("boss3/bs3idle1.wav"); 714 sound_step_left = gi.soundindex ("boss3/step1.wav"); 715 sound_step_right = gi.soundindex ("boss3/step2.wav"); 716 sound_firegun = gi.soundindex ("boss3/xfire.wav"); 717 sound_death_hit = gi.soundindex ("boss3/d_hit.wav"); 718 719 MakronPrecache (); 720 721 self->movetype = MOVETYPE_STEP; 722 self->solid = SOLID_BBOX; 723 self->s.modelindex = gi.modelindex ("models/monsters/boss3/rider/tris.md2"); 724 self->s.modelindex2 = gi.modelindex ("models/monsters/boss3/jorg/tris.md2"); 725 VectorSet (self->mins, -80, -80, 0); 726 VectorSet (self->maxs, 80, 80, 140); 727 728 self->health = 3000; 729 self->gib_health = -2000; 730 self->mass = 1000; 731 732 self->pain = jorg_pain; 733 self->die = jorg_die; 734 self->monsterinfo.stand = jorg_stand; 735 self->monsterinfo.walk = jorg_walk; 736 self->monsterinfo.run = jorg_run; 737 self->monsterinfo.dodge = NULL; 738 self->monsterinfo.attack = jorg_attack; 739 self->monsterinfo.search = jorg_search; 740 self->monsterinfo.melee = NULL; 741 self->monsterinfo.sight = NULL; 742 self->monsterinfo.checkattack = Jorg_CheckAttack; 743 gi.linkentity (self); 744 745 self->monsterinfo.currentmove = &jorg_move_stand; 746 self->monsterinfo.scale = MODEL_SCALE; 747 748 walkmonster_start(self); 749 } 750