home *** CD-ROM | disk | FTP | other *** search
/ Gambler 19 / GAMBLERCD19.BIN / UTILS / 3D / BRONIE / DUAL_LAU.ZIP / src / m_boss2.c < prev    next >
C/C++ Source or Header  |  1997-11-26  |  16KB  |  660 lines

  1. /*
  2. ==============================================================================
  3.  
  4. boss2
  5.  
  6. ==============================================================================
  7. */
  8.  
  9. #include "g_local.h"
  10. #include "m_boss2.h"
  11.  
  12. void BossExplode (edict_t *self);
  13.  
  14. qboolean infront (edict_t *self, edict_t *other);
  15.  
  16. static int    sound_pain1;
  17. static int    sound_pain2;
  18. static int    sound_pain3;
  19. static int    sound_death;
  20. static int    sound_search1;
  21.  
  22. void boss2_search (edict_t *self)
  23. {
  24.     if (random() < 0.5)
  25.         gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NONE, 0);
  26. }
  27.  
  28. void boss2_run (edict_t *self);
  29. void boss2_stand (edict_t *self);
  30. void boss2_dead (edict_t *self);
  31. void boss2_attack (edict_t *self);
  32. void boss2_attack_mg (edict_t *self);
  33. void boss2_reattack_mg (edict_t *self);
  34. void boss2_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point);
  35.  
  36. void Boss2Rocket (edict_t *self)
  37. {
  38.     vec3_t    forward, right;
  39.     vec3_t    start;
  40.     vec3_t    dir;
  41.     vec3_t    vec;
  42.  
  43.     AngleVectors (self->s.angles, forward, right, NULL);
  44.  
  45. //1
  46.     G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_1], forward, right, start);
  47.     VectorCopy (self->enemy->s.origin, vec);
  48.     vec[2] += self->enemy->viewheight;
  49.     VectorSubtract (vec, start, dir);
  50.     VectorNormalize (dir);
  51.     monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_1);
  52.  
  53. //2
  54.     G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_2], forward, right, start);
  55.     VectorCopy (self->enemy->s.origin, vec);
  56.     vec[2] += self->enemy->viewheight;
  57.     VectorSubtract (vec, start, dir);
  58.     VectorNormalize (dir);
  59.     monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_2);
  60.  
  61. //3
  62.     G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_3], forward, right, start);
  63.     VectorCopy (self->enemy->s.origin, vec);
  64.     vec[2] += self->enemy->viewheight;
  65.     VectorSubtract (vec, start, dir);
  66.     VectorNormalize (dir);
  67.     monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_3);
  68.  
  69. //4
  70.     G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_ROCKET_4], forward, right, start);
  71.     VectorCopy (self->enemy->s.origin, vec);
  72.     vec[2] += self->enemy->viewheight;
  73.     VectorSubtract (vec, start, dir);
  74.     VectorNormalize (dir);
  75.     monster_fire_rocket (self, start, dir, 50, 500, MZ2_BOSS2_ROCKET_4);
  76. }    
  77.  
  78. void boss2_firebullet_right (edict_t *self)
  79. {
  80.     vec3_t    forward, right, target;
  81.     vec3_t    start;
  82.  
  83.     AngleVectors (self->s.angles, forward, right, NULL);
  84.     G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_MACHINEGUN_R1], forward, right, start);
  85.  
  86.     VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target);
  87.     target[2] += self->enemy->viewheight;
  88.     VectorSubtract (target, start, forward);
  89.     VectorNormalize (forward);
  90.  
  91.     monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_R1);
  92. }    
  93.  
  94. void boss2_firebullet_left (edict_t *self)
  95. {
  96.     vec3_t    forward, right, target;
  97.     vec3_t    start;
  98.     
  99.     AngleVectors (self->s.angles, forward, right, NULL);
  100.     G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_BOSS2_MACHINEGUN_L1], forward, right, start);
  101.  
  102.     VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target);
  103.  
  104.     target[2] += self->enemy->viewheight;
  105.     VectorSubtract (target, start, forward);
  106.     VectorNormalize (forward);
  107.  
  108.     monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_BOSS2_MACHINEGUN_L1);
  109. }    
  110.  
  111. void Boss2MachineGun (edict_t *self)
  112. {
  113. /*    vec3_t    forward, right;
  114.     vec3_t    start;
  115.     vec3_t    dir;
  116.     vec3_t    vec;
  117.     int        flash_number;
  118.  
  119.     AngleVectors (self->s.angles, forward, right, NULL);
  120.  
  121.     flash_number = MZ2_BOSS2_MACHINEGUN_1 + (self->s.frame - FRAME_attack10);
  122.     G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
  123.  
  124.     VectorCopy (self->enemy->s.origin, vec);
  125.     vec[2] += self->enemy->viewheight;
  126.     VectorSubtract (vec, start, dir);
  127.     VectorNormalize (dir);
  128.     monster_fire_bullet (self, start, dir, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number);
  129. */
  130.     boss2_firebullet_left(self);
  131.     boss2_firebullet_right(self);
  132. }    
  133.  
  134.  
  135. mframe_t boss2_frames_stand [] =
  136. {
  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. };
  159. mmove_t    boss2_move_stand = {FRAME_stand30, FRAME_stand50, boss2_frames_stand, NULL};
  160.  
  161. mframe_t boss2_frames_fidget [] =
  162. {
  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.     ai_stand, 0, NULL,
  176.     ai_stand, 0, NULL,
  177.     ai_stand, 0, NULL,
  178.     ai_stand, 0, NULL,
  179.     ai_stand, 0, NULL,
  180.     ai_stand, 0, NULL,
  181.     ai_stand, 0, NULL,
  182.     ai_stand, 0, NULL,
  183.     ai_stand, 0, NULL,
  184.     ai_stand, 0, NULL,
  185.     ai_stand, 0, NULL,
  186.     ai_stand, 0, NULL,
  187.     ai_stand, 0, NULL,
  188.     ai_stand, 0, NULL,
  189.     ai_stand, 0, NULL,
  190.     ai_stand, 0, NULL,
  191.     ai_stand, 0, NULL,
  192.     ai_stand, 0, NULL
  193. };
  194. mmove_t boss2_move_fidget = {FRAME_stand1, FRAME_stand30, boss2_frames_fidget, NULL};
  195.  
  196. mframe_t boss2_frames_walk [] =
  197. {
  198.     ai_walk,    8,    NULL,
  199.     ai_walk,    8,    NULL,
  200.     ai_walk,    8,    NULL,
  201.     ai_walk,    8,    NULL,
  202.     ai_walk,    8,    NULL,
  203.     ai_walk,    8,    NULL,
  204.     ai_walk,    8,    NULL,
  205.     ai_walk,    8,    NULL,
  206.     ai_walk,    8,    NULL,
  207.     ai_walk,    8,    NULL,
  208.     ai_walk,    8,    NULL,
  209.     ai_walk,    8,    NULL,
  210.     ai_walk,    8,    NULL,
  211.     ai_walk,    8,    NULL,
  212.     ai_walk,    8,    NULL,
  213.     ai_walk,    8,    NULL,
  214.     ai_walk,    8,    NULL,
  215.     ai_walk,    8,    NULL,
  216.     ai_walk,    8,    NULL,
  217.     ai_walk,    8,    NULL
  218. };
  219. mmove_t boss2_move_walk = {FRAME_walk1, FRAME_walk20, boss2_frames_walk, NULL};
  220.  
  221.  
  222. mframe_t boss2_frames_run [] =
  223. {
  224.     ai_run,    8,    NULL,
  225.     ai_run,    8,    NULL,
  226.     ai_run,    8,    NULL,
  227.     ai_run,    8,    NULL,
  228.     ai_run,    8,    NULL,
  229.     ai_run,    8,    NULL,
  230.     ai_run,    8,    NULL,
  231.     ai_run,    8,    NULL,
  232.     ai_run,    8,    NULL,
  233.     ai_run,    8,    NULL,
  234.     ai_run,    8,    NULL,
  235.     ai_run,    8,    NULL,
  236.     ai_run,    8,    NULL,
  237.     ai_run,    8,    NULL,
  238.     ai_run,    8,    NULL,
  239.     ai_run,    8,    NULL,
  240.     ai_run,    8,    NULL,
  241.     ai_run,    8,    NULL,
  242.     ai_run,    8,    NULL,
  243.     ai_run,    8,    NULL
  244. };
  245. mmove_t boss2_move_run = {FRAME_walk1, FRAME_walk20, boss2_frames_run, NULL};
  246.  
  247. mframe_t boss2_frames_attack_pre_mg [] =
  248. {
  249.     ai_charge,    1,    NULL,
  250.     ai_charge,    1,    NULL,
  251.     ai_charge,    1,    NULL,
  252.     ai_charge,    1,    NULL,
  253.     ai_charge,    1,    NULL,
  254.     ai_charge,    1,    NULL,
  255.     ai_charge,    1,    NULL,
  256.     ai_charge,    1,    NULL,
  257.     ai_charge,    1,    boss2_attack_mg
  258. };
  259. mmove_t boss2_move_attack_pre_mg = {FRAME_attack1, FRAME_attack9, boss2_frames_attack_pre_mg, NULL};
  260.  
  261.  
  262. // Loop this
  263. mframe_t boss2_frames_attack_mg [] =
  264. {
  265.     ai_charge,    1,    Boss2MachineGun,
  266.     ai_charge,    1,    Boss2MachineGun,
  267.     ai_charge,    1,    Boss2MachineGun,
  268.     ai_charge,    1,    Boss2MachineGun,
  269.     ai_charge,    1,    Boss2MachineGun,
  270.     ai_charge,    1,    boss2_reattack_mg
  271. };
  272. mmove_t boss2_move_attack_mg = {FRAME_attack10, FRAME_attack15, boss2_frames_attack_mg, NULL};
  273.  
  274. mframe_t boss2_frames_attack_post_mg [] =
  275. {
  276.     ai_charge,    1,    NULL,
  277.     ai_charge,    1,    NULL,
  278.     ai_charge,    1,    NULL,
  279.     ai_charge,    1,    NULL
  280. };
  281. mmove_t boss2_move_attack_post_mg = {FRAME_attack16, FRAME_attack19, boss2_frames_attack_post_mg, boss2_run};
  282.  
  283. mframe_t boss2_frames_attack_rocket [] =
  284. {
  285.     ai_charge,    1,    NULL,
  286.     ai_charge,    1,    NULL,
  287.     ai_charge,    1,    NULL,
  288.     ai_charge,    1,    NULL,
  289.     ai_charge,    1,    NULL,
  290.     ai_charge,    1,    NULL,
  291.     ai_charge,    1,    NULL,
  292.     ai_charge,    1,    NULL,
  293.     ai_charge,    1,    NULL,
  294.     ai_charge,    1,    NULL,
  295.     ai_charge,    1,    NULL,
  296.     ai_charge,    1,    NULL,
  297.     ai_move,    -20,    Boss2Rocket,
  298.     ai_charge,    1,    NULL,
  299.     ai_charge,    1,    NULL,
  300.     ai_charge,    1,    NULL,
  301.     ai_charge,    1,    NULL,
  302.     ai_charge,    1,    NULL,
  303.     ai_charge,    1,    NULL,
  304.     ai_charge,    1,    NULL,
  305.     ai_charge,    1,    NULL
  306. };
  307. mmove_t boss2_move_attack_rocket = {FRAME_attack20, FRAME_attack40, boss2_frames_attack_rocket, boss2_run};
  308.  
  309. mframe_t boss2_frames_pain_heavy [] =
  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.     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. };
  330. mmove_t boss2_move_pain_heavy = {FRAME_pain2, FRAME_pain19, boss2_frames_pain_heavy, boss2_run};
  331.  
  332. mframe_t boss2_frames_pain_light [] =
  333. {
  334.     ai_move,    0,    NULL,
  335.     ai_move,    0,    NULL,
  336.     ai_move,    0,    NULL,
  337.     ai_move,    0,    NULL
  338. };
  339. mmove_t boss2_move_pain_light = {FRAME_pain20, FRAME_pain23, boss2_frames_pain_light, boss2_run};
  340.  
  341. mframe_t boss2_frames_death [] =
  342. {
  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.     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,    0,    NULL,
  355.     ai_move,    0,    NULL,
  356.     ai_move,    0,    NULL,
  357.     ai_move,    0,    NULL,
  358.     ai_move,    0,    NULL,
  359.     ai_move,    0,    NULL,
  360.     ai_move,    0,    NULL,
  361.     ai_move,    0,    NULL,
  362.     ai_move,    0,    NULL,
  363.     ai_move,    0,    NULL,
  364.     ai_move,    0,    NULL,
  365.     ai_move,    0,    NULL,
  366.     ai_move,    0,    NULL,
  367.     ai_move,    0,    NULL,
  368.     ai_move,    0,    NULL,
  369.     ai_move,    0,    NULL,
  370.     ai_move,    0,    NULL,
  371.     ai_move,    0,    NULL,
  372.     ai_move,    0,    NULL,
  373.     ai_move,    0,    NULL,
  374.     ai_move,    0,    NULL,
  375.     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.     ai_move,    0,    NULL,
  390.     ai_move,    0,    NULL,
  391.     ai_move,    0,    BossExplode
  392. };
  393. mmove_t boss2_move_death = {FRAME_death2, FRAME_death50, boss2_frames_death, boss2_dead};
  394.  
  395. void boss2_stand (edict_t *self)
  396. {
  397.         self->monsterinfo.currentmove = &boss2_move_stand;
  398. }
  399.  
  400. void boss2_run (edict_t *self)
  401. {
  402.     if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  403.         self->monsterinfo.currentmove = &boss2_move_stand;
  404.     else
  405.         self->monsterinfo.currentmove = &boss2_move_run;
  406. }
  407.  
  408. void boss2_walk (edict_t *self)
  409. {
  410.     self->monsterinfo.currentmove = &boss2_move_walk;
  411. }
  412.  
  413. void boss2_attack (edict_t *self)
  414. {
  415.     vec3_t    vec;
  416.     float    range;
  417.  
  418.     VectorSubtract (self->enemy->s.origin, self->s.origin, vec);
  419.     range = VectorLength (vec);
  420.     
  421.     if (range <= 125)
  422.     {
  423.         self->monsterinfo.currentmove = &boss2_move_attack_pre_mg;
  424.     }
  425.     else 
  426.     {
  427.         if (random() <= 0.6)
  428.             self->monsterinfo.currentmove = &boss2_move_attack_pre_mg;
  429.         else
  430.             self->monsterinfo.currentmove = &boss2_move_attack_rocket;
  431.     }
  432. }
  433.  
  434. void boss2_attack_mg (edict_t *self)
  435. {
  436.     self->monsterinfo.currentmove = &boss2_move_attack_mg;
  437. }
  438.  
  439. void boss2_reattack_mg (edict_t *self)
  440. {
  441.     if ( infront(self, self->enemy) )
  442.         if (random() <= 0.7)
  443.             self->monsterinfo.currentmove = &boss2_move_attack_mg;
  444.         else
  445.             self->monsterinfo.currentmove = &boss2_move_attack_post_mg;
  446.     else
  447.         self->monsterinfo.currentmove = &boss2_move_attack_post_mg;
  448. }
  449.  
  450.  
  451. void boss2_pain (edict_t *self, edict_t *other, float kick, int damage)
  452. {
  453.     if (self->health < (self->max_health / 2))
  454.         self->s.skinnum = 1;
  455.  
  456.     if (level.time < self->pain_debounce_time)
  457.         return;
  458.  
  459.     self->pain_debounce_time = level.time + 3;
  460. // American wanted these at no attenuation
  461.     if (damage < 10)
  462.     {
  463.         gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NONE, 0);
  464.         self->monsterinfo.currentmove = &boss2_move_pain_light;
  465.     }
  466.     else if (damage < 30)
  467.     {
  468.         gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NONE, 0);
  469.         self->monsterinfo.currentmove = &boss2_move_pain_light;
  470.     }
  471.     else 
  472.     {
  473.         gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NONE, 0);
  474.         self->monsterinfo.currentmove = &boss2_move_pain_heavy;
  475.     }
  476. }
  477.  
  478. void boss2_dead (edict_t *self)
  479. {
  480.     VectorSet (self->mins, -56, -56, 0);
  481.     VectorSet (self->maxs, 56, 56, 80);
  482.     self->movetype = MOVETYPE_TOSS;
  483.     self->nextthink = 0;
  484.     gi.linkentity (self);
  485. }
  486.  
  487. void boss2_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
  488. {
  489.     gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NONE, 0);
  490.     self->deadflag = DEAD_DEAD;
  491.     self->takedamage = DAMAGE_NO;
  492.     self->count = 0;
  493.     self->monsterinfo.currentmove = &boss2_move_death;
  494. #if 0
  495.     int        n;
  496.  
  497.     self->s.sound = 0;
  498.     // check for gib
  499.     if (self->health <= self->gib_health)
  500.     {
  501.         gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
  502.         for (n= 0; n < 2; n++)
  503.             ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
  504.         for (n= 0; n < 4; n++)
  505.             ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
  506.         ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
  507.         self->deadflag = DEAD_DEAD;
  508.         return;
  509.     }
  510.  
  511.     if (self->deadflag == DEAD_DEAD)
  512.         return;
  513.  
  514.     self->deadflag = DEAD_DEAD;
  515.     self->takedamage = DAMAGE_YES;
  516.     self->monsterinfo.currentmove = &boss2_move_death;
  517. #endif
  518. }
  519.  
  520. qboolean Boss2_CheckAttack (edict_t *self)
  521. {
  522.     vec3_t    spot1, spot2;
  523.     vec3_t    temp;
  524.     float    chance;
  525.     trace_t    tr;
  526.     qboolean    enemy_infront;
  527.     int            enemy_range;
  528.     float        enemy_yaw;
  529.  
  530.     if (self->enemy->health > 0)
  531.     {
  532.     // see if any entities are in the way of the shot
  533.         VectorCopy (self->s.origin, spot1);
  534.         spot1[2] += self->viewheight;
  535.         VectorCopy (self->enemy->s.origin, spot2);
  536.         spot2[2] += self->enemy->viewheight;
  537.  
  538.         tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA);
  539.  
  540.         // do we have a clear shot?
  541.         if (tr.ent != self->enemy)
  542.             return false;
  543.     }
  544.     
  545.     enemy_infront = infront(self, self->enemy);
  546.     enemy_range = range(self, self->enemy);
  547.     VectorSubtract (self->enemy->s.origin, self->s.origin, temp);
  548.     enemy_yaw = vectoyaw(temp);
  549.  
  550.     self->ideal_yaw = enemy_yaw;
  551.  
  552.  
  553.     // melee attack
  554.     if (enemy_range == RANGE_MELEE)
  555.     {
  556.         if (self->monsterinfo.melee)
  557.             self->monsterinfo.attack_state = AS_MELEE;
  558.         else
  559.             self->monsterinfo.attack_state = AS_MISSILE;
  560.         return true;
  561.     }
  562.     
  563. // missile attack
  564.     if (!self->monsterinfo.attack)
  565.         return false;
  566.         
  567.     if (level.time < self->monsterinfo.attack_finished)
  568.         return false;
  569.         
  570.     if (enemy_range == RANGE_FAR)
  571.         return false;
  572.  
  573.     if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  574.     {
  575.         chance = 0.4;
  576.     }
  577.     else if (enemy_range == RANGE_MELEE)
  578.     {
  579.         chance = 0.8;
  580.     }
  581.     else if (enemy_range == RANGE_NEAR)
  582.     {
  583.         chance = 0.8;
  584.     }
  585.     else if (enemy_range == RANGE_MID)
  586.     {
  587.         chance = 0.8;
  588.     }
  589.     else
  590.     {
  591.         return false;
  592.     }
  593.  
  594.     if (random () < chance)
  595.     {
  596.         self->monsterinfo.attack_state = AS_MISSILE;
  597.         self->monsterinfo.attack_finished = level.time + 2*random();
  598.         return true;
  599.     }
  600.  
  601.     if (self->flags & FL_FLY)
  602.     {
  603.         if (random() < 0.3)
  604.             self->monsterinfo.attack_state = AS_SLIDING;
  605.         else
  606.             self->monsterinfo.attack_state = AS_STRAIGHT;
  607.     }
  608.  
  609.     return false;
  610. }
  611.  
  612.  
  613.  
  614. /*QUAKED monster_boss2 (1 .5 0) (-56 -56 0) (56 56 80) Ambush Trigger_Spawn Sight
  615. */
  616. void SP_monster_boss2 (edict_t *self)
  617. {
  618.     if (deathmatch->value)
  619.     {
  620.         G_FreeEdict (self);
  621.         return;
  622.     }
  623.  
  624.     sound_pain1 = gi.soundindex ("bosshovr/bhvpain1.wav");
  625.     sound_pain2 = gi.soundindex ("bosshovr/bhvpain2.wav");
  626.     sound_pain3 = gi.soundindex ("bosshovr/bhvpain3.wav");
  627.     sound_death = gi.soundindex ("bosshovr/bhvdeth1.wav");
  628.     sound_search1 = gi.soundindex ("bosshovr/bhvunqv1.wav");
  629.  
  630.     self->s.sound = gi.soundindex ("bosshovr/bhvengn1.wav");
  631.  
  632.     self->movetype = MOVETYPE_STEP;
  633.     self->solid = SOLID_BBOX;
  634.     self->s.modelindex = gi.modelindex ("models/monsters/boss2/tris.md2");
  635.     VectorSet (self->mins, -56, -56, 0);
  636.     VectorSet (self->maxs, 56, 56, 80);
  637.  
  638.     self->health = 2000;
  639.     self->gib_health = -200;
  640.     self->mass = 1000;
  641.  
  642.     self->flags |= FL_IMMUNE_LASER;
  643.  
  644.     self->pain = boss2_pain;
  645.     self->die = boss2_die;
  646.  
  647.     self->monsterinfo.stand = boss2_stand;
  648.     self->monsterinfo.walk = boss2_walk;
  649.     self->monsterinfo.run = boss2_run;
  650.     self->monsterinfo.attack = boss2_attack;
  651.     self->monsterinfo.search = boss2_search;
  652.     self->monsterinfo.checkattack = Boss2_CheckAttack;
  653.     gi.linkentity (self);
  654.  
  655.     self->monsterinfo.currentmove = &boss2_move_stand;    
  656.     self->monsterinfo.scale = MODEL_SCALE;
  657.  
  658.     flymonster_start (self);
  659. }
  660.