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

  1. /*
  2. ==============================================================================
  3.  
  4. GUNNER
  5.  
  6. ==============================================================================
  7. */
  8.  
  9. #include "g_local.h"
  10. #include "m_gunner.h"
  11.  
  12.  
  13. static int    sound_pain;
  14. static int    sound_pain2;
  15. static int    sound_death;
  16. static int    sound_idle;
  17. static int    sound_open;
  18. static int    sound_search;
  19. static int    sound_sight;
  20.  
  21.  
  22. void gunner_idlesound (edict_t *self)
  23. {
  24.     gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
  25. }
  26.  
  27. void gunner_sight (edict_t *self, edict_t *other)
  28. {
  29.     gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
  30. }
  31.  
  32. void gunner_search (edict_t *self)
  33. {
  34.     gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0);
  35. }
  36.  
  37.  
  38. qboolean visible (edict_t *self, edict_t *other);
  39. void GunnerGrenade (edict_t *self);
  40. void GunnerFire (edict_t *self);
  41. void gunner_fire_chain(edict_t *self);
  42. void gunner_refire_chain(edict_t *self);
  43.  
  44.  
  45. void gunner_stand (edict_t *self);
  46.  
  47. mframe_t gunner_frames_fidget [] =
  48. {
  49.     ai_stand, 0, NULL,
  50.     ai_stand, 0, NULL,
  51.     ai_stand, 0, NULL,
  52.     ai_stand, 0, NULL,
  53.     ai_stand, 0, NULL,
  54.     ai_stand, 0, NULL,
  55.     ai_stand, 0, NULL,
  56.     ai_stand, 0, gunner_idlesound,
  57.     ai_stand, 0, NULL,
  58.  
  59.     ai_stand, 0, NULL,
  60.     ai_stand, 0, NULL,
  61.     ai_stand, 0, NULL,
  62.     ai_stand, 0, NULL,
  63.     ai_stand, 0, NULL,
  64.     ai_stand, 0, NULL,
  65.     ai_stand, 0, NULL,
  66.     ai_stand, 0, NULL,
  67.     ai_stand, 0, NULL,
  68.     ai_stand, 0, NULL,
  69.  
  70.     ai_stand, 0, NULL,
  71.     ai_stand, 0, NULL,
  72.     ai_stand, 0, NULL,
  73.     ai_stand, 0, NULL,
  74.     ai_stand, 0, NULL,
  75.     ai_stand, 0, NULL,
  76.     ai_stand, 0, NULL,
  77.     ai_stand, 0, NULL,
  78.     ai_stand, 0, NULL,
  79.     ai_stand, 0, NULL,
  80.  
  81.     ai_stand, 0, NULL,
  82.     ai_stand, 0, NULL,
  83.     ai_stand, 0, NULL,
  84.     ai_stand, 0, NULL,
  85.     ai_stand, 0, NULL,
  86.     ai_stand, 0, NULL,
  87.     ai_stand, 0, NULL,
  88.     ai_stand, 0, NULL,
  89.     ai_stand, 0, NULL,
  90.     ai_stand, 0, NULL,
  91.  
  92.     ai_stand, 0, NULL,
  93.     ai_stand, 0, NULL,
  94.     ai_stand, 0, NULL,
  95.     ai_stand, 0, NULL,
  96.     ai_stand, 0, NULL,
  97.     ai_stand, 0, NULL,
  98.     ai_stand, 0, NULL,
  99.     ai_stand, 0, NULL,
  100.     ai_stand, 0, NULL,
  101.     ai_stand, 0, NULL
  102. };
  103. mmove_t    gunner_move_fidget = {FRAME_stand31, FRAME_stand70, gunner_frames_fidget, gunner_stand};
  104.  
  105. void gunner_fidget (edict_t *self)
  106. {
  107.     if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  108.         return;
  109.     if (random() <= 0.05)
  110.         self->monsterinfo.currentmove = &gunner_move_fidget;
  111. }
  112.  
  113. mframe_t gunner_frames_stand [] =
  114. {
  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, gunner_fidget,
  125.  
  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,
  135.     ai_stand, 0, gunner_fidget,
  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, gunner_fidget
  147. };
  148. mmove_t    gunner_move_stand = {FRAME_stand01, FRAME_stand30, gunner_frames_stand, NULL};
  149.  
  150. void gunner_stand (edict_t *self)
  151. {
  152.         self->monsterinfo.currentmove = &gunner_move_stand;
  153. }
  154.  
  155.  
  156. mframe_t gunner_frames_walk [] =
  157. {
  158.     ai_walk, 0, NULL,
  159.     ai_walk, 3, NULL,
  160.     ai_walk, 4, NULL,
  161.     ai_walk, 5, NULL,
  162.     ai_walk, 7, NULL,
  163.     ai_walk, 2, NULL,
  164.     ai_walk, 6, NULL,
  165.     ai_walk, 4, NULL,
  166.     ai_walk, 2, NULL,
  167.     ai_walk, 7, NULL,
  168.     ai_walk, 5, NULL,
  169.     ai_walk, 7, NULL,
  170.     ai_walk, 4, NULL
  171. };
  172. mmove_t gunner_move_walk = {FRAME_walk07, FRAME_walk19, gunner_frames_walk, NULL};
  173.  
  174. void gunner_walk (edict_t *self)
  175. {
  176.     self->monsterinfo.currentmove = &gunner_move_walk;
  177. }
  178.  
  179. mframe_t gunner_frames_run [] =
  180. {
  181.     ai_run, 26, NULL,
  182.     ai_run, 9,  NULL,
  183.     ai_run, 9,  NULL,
  184.     ai_run, 9,  NULL,
  185.     ai_run, 15, NULL,
  186.     ai_run, 10, NULL,
  187.     ai_run, 13, NULL,
  188.     ai_run, 6,  NULL
  189. };
  190.  
  191. mmove_t gunner_move_run = {FRAME_run01, FRAME_run08, gunner_frames_run, NULL};
  192.  
  193. void gunner_run (edict_t *self)
  194. {
  195.     if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  196.         self->monsterinfo.currentmove = &gunner_move_stand;
  197.     else
  198.         self->monsterinfo.currentmove = &gunner_move_run;
  199. }
  200.  
  201. mframe_t gunner_frames_runandshoot [] =
  202. {
  203.     ai_run, 32, NULL,
  204.     ai_run, 15, NULL,
  205.     ai_run, 10, NULL,
  206.     ai_run, 18, NULL,
  207.     ai_run, 8,  NULL,
  208.     ai_run, 20, NULL
  209. };
  210.  
  211. mmove_t gunner_move_runandshoot = {FRAME_runs01, FRAME_runs06, gunner_frames_runandshoot, NULL};
  212.  
  213. void gunner_runandshoot (edict_t *self)
  214. {
  215.     self->monsterinfo.currentmove = &gunner_move_runandshoot;
  216. }
  217.  
  218. mframe_t gunner_frames_pain3 [] =
  219. {
  220.     ai_move, -3, NULL,
  221.     ai_move, 1,     NULL,
  222.     ai_move, 1,     NULL,
  223.     ai_move, 0,     NULL,
  224.     ai_move, 1,     NULL
  225. };
  226. mmove_t gunner_move_pain3 = {FRAME_pain301, FRAME_pain305, gunner_frames_pain3, gunner_run};
  227.  
  228. mframe_t gunner_frames_pain2 [] =
  229. {
  230.     ai_move, -2, NULL,
  231.     ai_move, 11, NULL,
  232.     ai_move, 6,     NULL,
  233.     ai_move, 2,     NULL,
  234.     ai_move, -1, NULL,
  235.     ai_move, -7, NULL,
  236.     ai_move, -2, NULL,
  237.     ai_move, -7, NULL
  238. };
  239. mmove_t gunner_move_pain2 = {FRAME_pain201, FRAME_pain208, gunner_frames_pain2, gunner_run};
  240.  
  241. mframe_t gunner_frames_pain1 [] =
  242. {
  243.     ai_move, 2,     NULL,
  244.     ai_move, 0,     NULL,
  245.     ai_move, -5, NULL,
  246.     ai_move, 3,     NULL,
  247.     ai_move, -1, NULL,
  248.     ai_move, 0,     NULL,
  249.     ai_move, 0,     NULL,
  250.     ai_move, 0,     NULL,
  251.     ai_move, 0,     NULL,
  252.     ai_move, 1,     NULL,
  253.     ai_move, 1,     NULL,
  254.     ai_move, 2,     NULL,
  255.     ai_move, 1,     NULL,
  256.     ai_move, 0,     NULL,
  257.     ai_move, -2, NULL,
  258.     ai_move, -2, NULL,
  259.     ai_move, 0,     NULL,
  260.     ai_move, 0,     NULL
  261. };
  262. mmove_t gunner_move_pain1 = {FRAME_pain101, FRAME_pain118, gunner_frames_pain1, gunner_run};
  263.  
  264. void gunner_pain (edict_t *self, edict_t *other, float kick, int damage)
  265. {
  266.     if (self->health < (self->max_health / 2))
  267.         self->s.skinnum = 1;
  268.  
  269.     if (level.time < self->pain_debounce_time)
  270.         return;
  271.  
  272.     self->pain_debounce_time = level.time + 3;
  273.  
  274.     if (rand()&1)
  275.         gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
  276.     else
  277.         gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
  278.  
  279.     if (damage <= 10)
  280.         self->monsterinfo.currentmove = &gunner_move_pain3;
  281.     else if (damage <= 25)
  282.         self->monsterinfo.currentmove = &gunner_move_pain2;
  283.     else
  284.         self->monsterinfo.currentmove = &gunner_move_pain1;
  285. }
  286.  
  287. void gunner_dead (edict_t *self)
  288. {
  289.     VectorSet (self->mins, -16, -16, -24);
  290.     VectorSet (self->maxs, 16, 16, -8);
  291.     self->movetype = MOVETYPE_TOSS;
  292.     self->nextthink = 0;
  293.     gi.linkentity (self);
  294. }
  295.  
  296. mframe_t gunner_frames_death [] =
  297. {
  298.     ai_move, 0,     NULL,
  299.     ai_move, 0,     NULL,
  300.     ai_move, 0,     NULL,
  301.     ai_move, -7, NULL,
  302.     ai_move, -3, NULL,
  303.     ai_move, -5, NULL,
  304.     ai_move, 8,     NULL,
  305.     ai_move, 6,     NULL,
  306.     ai_move, 0,     NULL,
  307.     ai_move, 0,     NULL,
  308.     ai_move, 0,     NULL
  309. };
  310. mmove_t gunner_move_death = {FRAME_death01, FRAME_death11, gunner_frames_death, gunner_dead};
  311.  
  312. void gunner_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
  313. {
  314.     int        n;
  315.  
  316. // check for gib
  317.     if (self->health <= self->gib_health)
  318.     {
  319.         gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
  320.         for (n= 0; n < 2; n++)
  321.             ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
  322.         for (n= 0; n < 4; n++)
  323.             ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
  324.         ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
  325.         self->deadflag = DEAD_DEAD;
  326.         return;
  327.     }
  328.  
  329.     if (self->deadflag == DEAD_DEAD)
  330.         return;
  331.  
  332. // regular death
  333.     gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0);
  334.     self->deadflag = DEAD_DEAD;
  335.     self->takedamage = DAMAGE_YES;
  336.     self->monsterinfo.currentmove = &gunner_move_death;
  337. }
  338.  
  339.  
  340. void gunner_duck_down (edict_t *self)
  341. {
  342.     if (self->monsterinfo.aiflags & AI_DUCKED)
  343.         return;
  344.     self->monsterinfo.aiflags |= AI_DUCKED;
  345.     if (skill->value >= 2)
  346.     {
  347.         if (random() > 0.5)
  348.             GunnerGrenade (self);
  349.     }
  350.  
  351.     self->maxs[2] -= 32;
  352.     self->takedamage = DAMAGE_YES;
  353.     self->monsterinfo.pausetime = level.time + 1;
  354.     gi.linkentity (self);
  355. }
  356.  
  357. void gunner_duck_hold (edict_t *self)
  358. {
  359.     if (level.time >= self->monsterinfo.pausetime)
  360.         self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
  361.     else
  362.         self->monsterinfo.aiflags |= AI_HOLD_FRAME;
  363. }
  364.  
  365. void gunner_duck_up (edict_t *self)
  366. {
  367.     self->monsterinfo.aiflags &= ~AI_DUCKED;
  368.     self->maxs[2] += 32;
  369.     self->takedamage = DAMAGE_AIM;
  370.     gi.linkentity (self);
  371. }
  372.  
  373. mframe_t gunner_frames_duck [] =
  374. {
  375.     ai_move, 1,  gunner_duck_down,
  376.     ai_move, 1,  NULL,
  377.     ai_move, 1,  gunner_duck_hold,
  378.     ai_move, 0,  NULL,
  379.     ai_move, -1, NULL,
  380.     ai_move, -1, NULL,
  381.     ai_move, 0,  gunner_duck_up,
  382.     ai_move, -1, NULL
  383. };
  384. mmove_t    gunner_move_duck = {FRAME_duck01, FRAME_duck08, gunner_frames_duck, gunner_run};
  385.  
  386. void gunner_dodge (edict_t *self, edict_t *attacker, float eta)
  387. {
  388.     if (random() > 0.25)
  389.         return;
  390.  
  391.     if (!self->enemy)
  392.         self->enemy = attacker;
  393.  
  394.     self->monsterinfo.currentmove = &gunner_move_duck;
  395. }
  396.  
  397.  
  398. void gunner_opengun (edict_t *self)
  399. {
  400.     gi.sound (self, CHAN_VOICE, sound_open, 1, ATTN_IDLE, 0);
  401. }
  402.  
  403. void GunnerFire (edict_t *self)
  404. {
  405.     vec3_t    start;
  406.     vec3_t    forward, right;
  407.     vec3_t    target;
  408.     vec3_t    aim;
  409.     int        flash_number;
  410.  
  411.     flash_number = MZ2_GUNNER_MACHINEGUN_1 + (self->s.frame - FRAME_attak216);
  412.  
  413.     AngleVectors (self->s.angles, forward, right, NULL);
  414.     G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
  415.  
  416.     // project enemy back a bit and target there
  417.     VectorCopy (self->enemy->s.origin, target);
  418.     VectorMA (target, -0.2, self->enemy->velocity, target);
  419.     target[2] += self->enemy->viewheight;
  420.  
  421.     VectorSubtract (target, start, aim);
  422.     VectorNormalize (aim);
  423.     monster_fire_bullet (self, start, aim, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number);
  424. }
  425.  
  426. void GunnerGrenade (edict_t *self)
  427. {
  428.     vec3_t    start;
  429.     vec3_t    forward, right;
  430.     vec3_t    aim;
  431.     int        flash_number;
  432.  
  433.     if (self->s.frame == FRAME_attak105)
  434.         flash_number = MZ2_GUNNER_GRENADE_1;
  435.     else if (self->s.frame == FRAME_attak108)
  436.         flash_number = MZ2_GUNNER_GRENADE_2;
  437.     else if (self->s.frame == FRAME_attak111)
  438.         flash_number = MZ2_GUNNER_GRENADE_3;
  439.     else // (self->s.frame == FRAME_attak114)
  440.         flash_number = MZ2_GUNNER_GRENADE_4;
  441.  
  442.     AngleVectors (self->s.angles, forward, right, NULL);
  443.     G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
  444.  
  445.     //FIXME : do a spread -225 -75 75 225 degrees around forward
  446.     VectorCopy (forward, aim);
  447.  
  448.     monster_fire_grenade (self, start, aim, 50, 600, flash_number);
  449. }
  450.  
  451. mframe_t gunner_frames_attack_chain [] =
  452. {
  453.     /*
  454.     ai_charge, 0, NULL,
  455.     ai_charge, 0, NULL,
  456.     ai_charge, 0, NULL,
  457.     ai_charge, 0, NULL,
  458.     ai_charge, 0, NULL,
  459.     ai_charge, 0, NULL,
  460.     ai_charge, 0, NULL,
  461.     ai_charge, 0, NULL,
  462.     */
  463.     ai_charge, 0, gunner_opengun,
  464.     ai_charge, 0, NULL,
  465.     ai_charge, 0, NULL,
  466.     ai_charge, 0, NULL,
  467.     ai_charge, 0, NULL,
  468.     ai_charge, 0, NULL,
  469.     ai_charge, 0, NULL
  470. };
  471. mmove_t gunner_move_attack_chain = {FRAME_attak209, FRAME_attak215, gunner_frames_attack_chain, gunner_fire_chain};
  472.  
  473. mframe_t gunner_frames_fire_chain [] =
  474. {
  475.     ai_charge,   0, GunnerFire,
  476.     ai_charge,   0, GunnerFire,
  477.     ai_charge,   0, GunnerFire,
  478.     ai_charge,   0, GunnerFire,
  479.     ai_charge,   0, GunnerFire,
  480.     ai_charge,   0, GunnerFire,
  481.     ai_charge,   0, GunnerFire,
  482.     ai_charge,   0, GunnerFire
  483. };
  484. mmove_t gunner_move_fire_chain = {FRAME_attak216, FRAME_attak223, gunner_frames_fire_chain, gunner_refire_chain};
  485.  
  486. mframe_t gunner_frames_endfire_chain [] =
  487. {
  488.     ai_charge, 0, NULL,
  489.     ai_charge, 0, NULL,
  490.     ai_charge, 0, NULL,
  491.     ai_charge, 0, NULL,
  492.     ai_charge, 0, NULL,
  493.     ai_charge, 0, NULL,
  494.     ai_charge, 0, NULL
  495. };
  496. mmove_t gunner_move_endfire_chain = {FRAME_attak224, FRAME_attak230, gunner_frames_endfire_chain, gunner_run};
  497.  
  498. mframe_t gunner_frames_attack_grenade [] =
  499. {
  500.     ai_charge, 0, NULL,
  501.     ai_charge, 0, NULL,
  502.     ai_charge, 0, NULL,
  503.     ai_charge, 0, NULL,
  504.     ai_charge, 0, GunnerGrenade,
  505.     ai_charge, 0, NULL,
  506.     ai_charge, 0, NULL,
  507.     ai_charge, 0, GunnerGrenade,
  508.     ai_charge, 0, NULL,
  509.     ai_charge, 0, NULL,
  510.     ai_charge, 0, GunnerGrenade,
  511.     ai_charge, 0, NULL,
  512.     ai_charge, 0, NULL,
  513.     ai_charge, 0, GunnerGrenade,
  514.     ai_charge, 0, NULL,
  515.     ai_charge, 0, NULL,
  516.     ai_charge, 0, NULL,
  517.     ai_charge, 0, NULL,
  518.     ai_charge, 0, NULL,
  519.     ai_charge, 0, NULL,
  520.     ai_charge, 0, NULL
  521. };
  522. mmove_t gunner_move_attack_grenade = {FRAME_attak101, FRAME_attak121, gunner_frames_attack_grenade, gunner_run};
  523.  
  524. void gunner_attack(edict_t *self)
  525. {
  526.     if (range (self, self->enemy) == RANGE_MELEE)
  527.     {
  528.         self->monsterinfo.currentmove = &gunner_move_attack_chain;
  529.     }
  530.     else
  531.     {
  532.         if (random() <= 0.5)
  533.             self->monsterinfo.currentmove = &gunner_move_attack_grenade;
  534.         else
  535.             self->monsterinfo.currentmove = &gunner_move_attack_chain;
  536.     }
  537. }
  538.  
  539. void gunner_fire_chain(edict_t *self)
  540. {
  541.     self->monsterinfo.currentmove = &gunner_move_fire_chain;
  542. }
  543.  
  544. void gunner_refire_chain(edict_t *self)
  545. {
  546.     if (self->enemy->health > 0)
  547.         if ( visible (self, self->enemy) )
  548.             if (random() <= 0.5)
  549.             {
  550.                 self->monsterinfo.currentmove = &gunner_move_fire_chain;
  551.                 return;
  552.             }
  553.     self->monsterinfo.currentmove = &gunner_move_endfire_chain;
  554. }
  555.  
  556. /*QUAKED monster_gunner (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
  557. */
  558. void SP_monster_gunner (edict_t *self)
  559. {
  560.     if (deathmatch->value)
  561.     {
  562.         G_FreeEdict (self);
  563.         return;
  564.     }
  565.  
  566.     sound_death = gi.soundindex ("gunner/death1.wav");    
  567.     sound_pain = gi.soundindex ("gunner/gunpain2.wav");    
  568.     sound_pain2 = gi.soundindex ("gunner/gunpain1.wav");    
  569.     sound_idle = gi.soundindex ("gunner/gunidle1.wav");    
  570.     sound_open = gi.soundindex ("gunner/gunatck1.wav");    
  571.     sound_search = gi.soundindex ("gunner/gunsrch1.wav");    
  572.     sound_sight = gi.soundindex ("gunner/sight1.wav");    
  573.  
  574.     gi.soundindex ("gunner/gunatck2.wav");
  575.     gi.soundindex ("gunner/gunatck3.wav");
  576.  
  577.     self->movetype = MOVETYPE_STEP;
  578.     self->solid = SOLID_BBOX;
  579.     self->s.modelindex = gi.modelindex ("models/monsters/gunner/tris.md2");
  580.     VectorSet (self->mins, -16, -16, -24);
  581.     VectorSet (self->maxs, 16, 16, 32);
  582.  
  583.     self->health = 175;
  584.     self->gib_health = -70;
  585.     self->mass = 200;
  586.  
  587.     self->pain = gunner_pain;
  588.     self->die = gunner_die;
  589.  
  590.     self->monsterinfo.stand = gunner_stand;
  591.     self->monsterinfo.walk = gunner_walk;
  592.     self->monsterinfo.run = gunner_run;
  593.     self->monsterinfo.dodge = gunner_dodge;
  594.     self->monsterinfo.attack = gunner_attack;
  595.     self->monsterinfo.melee = NULL;
  596.     self->monsterinfo.sight = gunner_sight;
  597.     self->monsterinfo.search = gunner_search;
  598.  
  599.     gi.linkentity (self);
  600.  
  601.     self->monsterinfo.currentmove = &gunner_move_stand;    
  602.     self->monsterinfo.scale = MODEL_SCALE;
  603.  
  604.     walkmonster_start (self);
  605. }
  606.