home *** CD-ROM | disk | FTP | other *** search
/ Gambler 19 / GAMBLERCD19.BIN / UTILS / 3D / BRONIE / DUAL_LAU.ZIP / src / m_boss31.c < prev    next >
C/C++ Source or Header  |  1998-01-13  |  18KB  |  729 lines

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