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