Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

m_infantry.c (14651B)


      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 INFANTRY
     24 
     25 ==============================================================================
     26 */
     27 
     28 #include "g_local.h"
     29 #include "m_infantry.h"
     30 
     31 void InfantryMachineGun (edict_t *self);
     32 
     33 
     34 static int	sound_pain1;
     35 static int	sound_pain2;
     36 static int	sound_die1;
     37 static int	sound_die2;
     38 
     39 static int	sound_gunshot;
     40 static int	sound_weapon_cock;
     41 static int	sound_punch_swing;
     42 static int	sound_punch_hit;
     43 static int	sound_sight;
     44 static int	sound_search;
     45 static int	sound_idle;
     46 
     47 
     48 mframe_t infantry_frames_stand [] =
     49 {
     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, NULL,
     57 	ai_stand, 0, NULL,
     58 	ai_stand, 0, NULL,
     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 	ai_stand, 0, NULL,
     70 	ai_stand, 0, NULL,
     71 	ai_stand, 0, NULL
     72 };
     73 mmove_t infantry_move_stand = {FRAME_stand50, FRAME_stand71, infantry_frames_stand, NULL};
     74 
     75 void infantry_stand (edict_t *self)
     76 {
     77 	self->monsterinfo.currentmove = &infantry_move_stand;
     78 }
     79 
     80 
     81 mframe_t infantry_frames_fidget [] =
     82 {
     83 	ai_stand, 1,  NULL,
     84 	ai_stand, 0,  NULL,
     85 	ai_stand, 1,  NULL,
     86 	ai_stand, 3,  NULL,
     87 	ai_stand, 6,  NULL,
     88 	ai_stand, 3,  NULL,
     89 	ai_stand, 0,  NULL,
     90 	ai_stand, 0,  NULL,
     91 	ai_stand, 0,  NULL,
     92 	ai_stand, 0,  NULL,
     93 	ai_stand, 1,  NULL,
     94 	ai_stand, 0,  NULL,
     95 	ai_stand, 0,  NULL,
     96 	ai_stand, 0,  NULL,
     97 	ai_stand, 0,  NULL,
     98 	ai_stand, 1,  NULL,
     99 	ai_stand, 0,  NULL,
    100 	ai_stand, -1, NULL,
    101 	ai_stand, 0,  NULL,
    102 	ai_stand, 0,  NULL,
    103 	ai_stand, 1,  NULL,
    104 	ai_stand, 0,  NULL,
    105 	ai_stand, -2, NULL,
    106 	ai_stand, 1,  NULL,
    107 	ai_stand, 1,  NULL,
    108 	ai_stand, 1,  NULL,
    109 	ai_stand, -1, NULL,
    110 	ai_stand, 0,  NULL,
    111 	ai_stand, 0,  NULL,
    112 	ai_stand, -1, 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, -1, NULL,
    119 	ai_stand, 0,  NULL,
    120 	ai_stand, 0,  NULL,
    121 	ai_stand, 1,  NULL,
    122 	ai_stand, 0,  NULL,
    123 	ai_stand, 0,  NULL,
    124 	ai_stand, -1, NULL,
    125 	ai_stand, -1, NULL,
    126 	ai_stand, 0,  NULL,
    127 	ai_stand, -3, NULL,
    128 	ai_stand, -2, NULL,
    129 	ai_stand, -3, NULL,
    130 	ai_stand, -3, NULL,
    131 	ai_stand, -2, NULL
    132 };
    133 mmove_t infantry_move_fidget = {FRAME_stand01, FRAME_stand49, infantry_frames_fidget, infantry_stand};
    134 
    135 void infantry_fidget (edict_t *self)
    136 {
    137 	self->monsterinfo.currentmove = &infantry_move_fidget;
    138 	gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
    139 }
    140 
    141 mframe_t infantry_frames_walk [] =
    142 {
    143 	ai_walk, 5,  NULL,
    144 	ai_walk, 4,  NULL,
    145 	ai_walk, 4,  NULL,
    146 	ai_walk, 5,  NULL,
    147 	ai_walk, 4,  NULL,
    148 	ai_walk, 5,  NULL,
    149 	ai_walk, 6,  NULL,
    150 	ai_walk, 4,  NULL,
    151 	ai_walk, 4,  NULL,
    152 	ai_walk, 4,  NULL,
    153 	ai_walk, 4,  NULL,
    154 	ai_walk, 5,  NULL
    155 };
    156 mmove_t infantry_move_walk = {FRAME_walk03, FRAME_walk14, infantry_frames_walk, NULL};
    157 
    158 void infantry_walk (edict_t *self)
    159 {
    160 	self->monsterinfo.currentmove = &infantry_move_walk;
    161 }
    162 
    163 mframe_t infantry_frames_run [] =
    164 {
    165 	ai_run, 10, NULL,
    166 	ai_run, 20, NULL,
    167 	ai_run, 5,  NULL,
    168 	ai_run, 7,  NULL,
    169 	ai_run, 30, NULL,
    170 	ai_run, 35, NULL,
    171 	ai_run, 2,  NULL,
    172 	ai_run, 6,  NULL
    173 };
    174 mmove_t infantry_move_run = {FRAME_run01, FRAME_run08, infantry_frames_run, NULL};
    175 
    176 void infantry_run (edict_t *self)
    177 {
    178 	if (self->monsterinfo.aiflags & AI_STAND_GROUND)
    179 		self->monsterinfo.currentmove = &infantry_move_stand;
    180 	else
    181 		self->monsterinfo.currentmove = &infantry_move_run;
    182 }
    183 
    184 
    185 mframe_t infantry_frames_pain1 [] =
    186 {
    187 	ai_move, -3, NULL,
    188 	ai_move, -2, NULL,
    189 	ai_move, -1, NULL,
    190 	ai_move, -2, NULL,
    191 	ai_move, -1, NULL,
    192 	ai_move, 1,  NULL,
    193 	ai_move, -1, NULL,
    194 	ai_move, 1,  NULL,
    195 	ai_move, 6,  NULL,
    196 	ai_move, 2,  NULL
    197 };
    198 mmove_t infantry_move_pain1 = {FRAME_pain101, FRAME_pain110, infantry_frames_pain1, infantry_run};
    199 
    200 mframe_t infantry_frames_pain2 [] =
    201 {
    202 	ai_move, -3, NULL,
    203 	ai_move, -3, NULL,
    204 	ai_move, 0,  NULL,
    205 	ai_move, -1, NULL,
    206 	ai_move, -2, NULL,
    207 	ai_move, 0,  NULL,
    208 	ai_move, 0,  NULL,
    209 	ai_move, 2,  NULL,
    210 	ai_move, 5,  NULL,
    211 	ai_move, 2,  NULL
    212 };
    213 mmove_t infantry_move_pain2 = {FRAME_pain201, FRAME_pain210, infantry_frames_pain2, infantry_run};
    214 
    215 void infantry_pain (edict_t *self, edict_t *other, float kick, int damage)
    216 {
    217 	int		n;
    218 
    219 	if (self->health < (self->max_health / 2))
    220 		self->s.skinnum = 1;
    221 
    222 	if (level.time < self->pain_debounce_time)
    223 		return;
    224 
    225 	self->pain_debounce_time = level.time + 3;
    226 	
    227 	if (skill->value == 3)
    228 		return;		// no pain anims in nightmare
    229 
    230 	n = rand() % 2;
    231 	if (n == 0)
    232 	{
    233 		self->monsterinfo.currentmove = &infantry_move_pain1;
    234 		gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
    235 	}
    236 	else
    237 	{
    238 		self->monsterinfo.currentmove = &infantry_move_pain2;
    239 		gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
    240 	}
    241 }
    242 
    243 
    244 vec3_t	aimangles[] =
    245 {
    246 	0.0, 5.0, 0.0,
    247 	10.0, 15.0, 0.0,
    248 	20.0, 25.0, 0.0,
    249 	25.0, 35.0, 0.0,
    250 	30.0, 40.0, 0.0,
    251 	30.0, 45.0, 0.0,
    252 	25.0, 50.0, 0.0,
    253 	20.0, 40.0, 0.0,
    254 	15.0, 35.0, 0.0,
    255 	40.0, 35.0, 0.0,
    256 	70.0, 35.0, 0.0,
    257 	90.0, 35.0, 0.0
    258 };
    259 
    260 void InfantryMachineGun (edict_t *self)
    261 {
    262 	vec3_t	start, target;
    263 	vec3_t	forward, right;
    264 	vec3_t	vec;
    265 	int		flash_number;
    266 
    267 	if (self->s.frame == FRAME_attak111)
    268 	{
    269 		flash_number = MZ2_INFANTRY_MACHINEGUN_1;
    270 		AngleVectors (self->s.angles, forward, right, NULL);
    271 		G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
    272 
    273 		if (self->enemy)
    274 		{
    275 			VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target);
    276 			target[2] += self->enemy->viewheight;
    277 			VectorSubtract (target, start, forward);
    278 			VectorNormalize (forward);
    279 		}
    280 		else
    281 		{
    282 			AngleVectors (self->s.angles, forward, right, NULL);
    283 		}
    284 	}
    285 	else
    286 	{
    287 		flash_number = MZ2_INFANTRY_MACHINEGUN_2 + (self->s.frame - FRAME_death211);
    288 
    289 		AngleVectors (self->s.angles, forward, right, NULL);
    290 		G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
    291 
    292 		VectorSubtract (self->s.angles, aimangles[flash_number-MZ2_INFANTRY_MACHINEGUN_2], vec);
    293 		AngleVectors (vec, forward, NULL, NULL);
    294 	}
    295 
    296 	monster_fire_bullet (self, start, forward, 3, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_number);
    297 }
    298 
    299 void infantry_sight (edict_t *self, edict_t *other)
    300 {
    301 	gi.sound (self, CHAN_BODY, sound_sight, 1, ATTN_NORM, 0);
    302 }
    303 
    304 void infantry_dead (edict_t *self)
    305 {
    306 	VectorSet (self->mins, -16, -16, -24);
    307 	VectorSet (self->maxs, 16, 16, -8);
    308 	self->movetype = MOVETYPE_TOSS;
    309 	self->svflags |= SVF_DEADMONSTER;
    310 	gi.linkentity (self);
    311 
    312 	M_FlyCheck (self);
    313 }
    314 
    315 mframe_t infantry_frames_death1 [] =
    316 {
    317 	ai_move, -4, NULL,
    318 	ai_move, 0,  NULL,
    319 	ai_move, 0,  NULL,
    320 	ai_move, -1, NULL,
    321 	ai_move, -4, NULL,
    322 	ai_move, 0,  NULL,
    323 	ai_move, 0,  NULL,
    324 	ai_move, 0,  NULL,
    325 	ai_move, -1, NULL,
    326 	ai_move, 3,  NULL,
    327 	ai_move, 1,  NULL,
    328 	ai_move, 1,  NULL,
    329 	ai_move, -2, NULL,
    330 	ai_move, 2,  NULL,
    331 	ai_move, 2,  NULL,
    332 	ai_move, 9,  NULL,
    333 	ai_move, 9,  NULL,
    334 	ai_move, 5,  NULL,
    335 	ai_move, -3, NULL,
    336 	ai_move, -3, NULL
    337 };
    338 mmove_t infantry_move_death1 = {FRAME_death101, FRAME_death120, infantry_frames_death1, infantry_dead};
    339 
    340 // Off with his head
    341 mframe_t infantry_frames_death2 [] =
    342 {
    343 	ai_move, 0,   NULL,
    344 	ai_move, 1,   NULL,
    345 	ai_move, 5,   NULL,
    346 	ai_move, -1,  NULL,
    347 	ai_move, 0,   NULL,
    348 	ai_move, 1,   NULL,
    349 	ai_move, 1,   NULL,
    350 	ai_move, 4,   NULL,
    351 	ai_move, 3,   NULL,
    352 	ai_move, 0,   NULL,
    353 	ai_move, -2,  InfantryMachineGun,
    354 	ai_move, -2,  InfantryMachineGun,
    355 	ai_move, -3,  InfantryMachineGun,
    356 	ai_move, -1,  InfantryMachineGun,
    357 	ai_move, -2,  InfantryMachineGun,
    358 	ai_move, 0,   InfantryMachineGun,
    359 	ai_move, 2,   InfantryMachineGun,
    360 	ai_move, 2,   InfantryMachineGun,
    361 	ai_move, 3,   InfantryMachineGun,
    362 	ai_move, -10, InfantryMachineGun,
    363 	ai_move, -7,  InfantryMachineGun,
    364 	ai_move, -8,  InfantryMachineGun,
    365 	ai_move, -6,  NULL,
    366 	ai_move, 4,   NULL,
    367 	ai_move, 0,   NULL
    368 };
    369 mmove_t infantry_move_death2 = {FRAME_death201, FRAME_death225, infantry_frames_death2, infantry_dead};
    370 
    371 mframe_t infantry_frames_death3 [] =
    372 {
    373 	ai_move, 0,   NULL,
    374 	ai_move, 0,   NULL,
    375 	ai_move, 0,   NULL,
    376 	ai_move, -6,  NULL,
    377 	ai_move, -11, NULL,
    378 	ai_move, -3,  NULL,
    379 	ai_move, -11, NULL,
    380 	ai_move, 0,   NULL,
    381 	ai_move, 0,   NULL
    382 };
    383 mmove_t infantry_move_death3 = {FRAME_death301, FRAME_death309, infantry_frames_death3, infantry_dead};
    384 
    385 
    386 void infantry_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
    387 {
    388 	int		n;
    389 
    390 // check for gib
    391 	if (self->health <= self->gib_health)
    392 	{
    393 		gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
    394 		for (n= 0; n < 2; n++)
    395 			ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
    396 		for (n= 0; n < 4; n++)
    397 			ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
    398 		ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
    399 		self->deadflag = DEAD_DEAD;
    400 		return;
    401 	}
    402 
    403 	if (self->deadflag == DEAD_DEAD)
    404 		return;
    405 
    406 // regular death
    407 	self->deadflag = DEAD_DEAD;
    408 	self->takedamage = DAMAGE_YES;
    409 
    410 	n = rand() % 3;
    411 	if (n == 0)
    412 	{
    413 		self->monsterinfo.currentmove = &infantry_move_death1;
    414 		gi.sound (self, CHAN_VOICE, sound_die2, 1, ATTN_NORM, 0);
    415 	}
    416 	else if (n == 1)
    417 	{
    418 		self->monsterinfo.currentmove = &infantry_move_death2;
    419 		gi.sound (self, CHAN_VOICE, sound_die1, 1, ATTN_NORM, 0);
    420 	}
    421 	else
    422 	{
    423 		self->monsterinfo.currentmove = &infantry_move_death3;
    424 		gi.sound (self, CHAN_VOICE, sound_die2, 1, ATTN_NORM, 0);
    425 	}
    426 }
    427 
    428 
    429 void infantry_duck_down (edict_t *self)
    430 {
    431 	if (self->monsterinfo.aiflags & AI_DUCKED)
    432 		return;
    433 	self->monsterinfo.aiflags |= AI_DUCKED;
    434 	self->maxs[2] -= 32;
    435 	self->takedamage = DAMAGE_YES;
    436 	self->monsterinfo.pausetime = level.time + 1;
    437 	gi.linkentity (self);
    438 }
    439 
    440 void infantry_duck_hold (edict_t *self)
    441 {
    442 	if (level.time >= self->monsterinfo.pausetime)
    443 		self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
    444 	else
    445 		self->monsterinfo.aiflags |= AI_HOLD_FRAME;
    446 }
    447 
    448 void infantry_duck_up (edict_t *self)
    449 {
    450 	self->monsterinfo.aiflags &= ~AI_DUCKED;
    451 	self->maxs[2] += 32;
    452 	self->takedamage = DAMAGE_AIM;
    453 	gi.linkentity (self);
    454 }
    455 
    456 mframe_t infantry_frames_duck [] =
    457 {
    458 	ai_move, -2, infantry_duck_down,
    459 	ai_move, -5, infantry_duck_hold,
    460 	ai_move, 3,  NULL,
    461 	ai_move, 4,  infantry_duck_up,
    462 	ai_move, 0,  NULL
    463 };
    464 mmove_t infantry_move_duck = {FRAME_duck01, FRAME_duck05, infantry_frames_duck, infantry_run};
    465 
    466 void infantry_dodge (edict_t *self, edict_t *attacker, float eta)
    467 {
    468 	if (random() > 0.25)
    469 		return;
    470 
    471 	if (!self->enemy)
    472 		self->enemy = attacker;
    473 
    474 	self->monsterinfo.currentmove = &infantry_move_duck;
    475 }
    476 
    477 
    478 void infantry_cock_gun (edict_t *self)
    479 {
    480 	int		n;
    481 
    482 	gi.sound (self, CHAN_WEAPON, sound_weapon_cock, 1, ATTN_NORM, 0);
    483 	n = (rand() & 15) + 3 + 7;
    484 	self->monsterinfo.pausetime = level.time + n * FRAMETIME;
    485 }
    486 
    487 void infantry_fire (edict_t *self)
    488 {
    489 	InfantryMachineGun (self);
    490 
    491 	if (level.time >= self->monsterinfo.pausetime)
    492 		self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
    493 	else
    494 		self->monsterinfo.aiflags |= AI_HOLD_FRAME;
    495 }
    496 
    497 mframe_t infantry_frames_attack1 [] =
    498 {
    499 	ai_charge, 4,  NULL,
    500 	ai_charge, -1, NULL,
    501 	ai_charge, -1, NULL,
    502 	ai_charge, 0,  infantry_cock_gun,
    503 	ai_charge, -1, NULL,
    504 	ai_charge, 1,  NULL,
    505 	ai_charge, 1,  NULL,
    506 	ai_charge, 2,  NULL,
    507 	ai_charge, -2, NULL,
    508 	ai_charge, -3, NULL,
    509 	ai_charge, 1,  infantry_fire,
    510 	ai_charge, 5,  NULL,
    511 	ai_charge, -1, NULL,
    512 	ai_charge, -2, NULL,
    513 	ai_charge, -3, NULL
    514 };
    515 mmove_t infantry_move_attack1 = {FRAME_attak101, FRAME_attak115, infantry_frames_attack1, infantry_run};
    516 
    517 
    518 void infantry_swing (edict_t *self)
    519 {
    520 	gi.sound (self, CHAN_WEAPON, sound_punch_swing, 1, ATTN_NORM, 0);
    521 }
    522 
    523 void infantry_smack (edict_t *self)
    524 {
    525 	vec3_t	aim;
    526 
    527 	VectorSet (aim, MELEE_DISTANCE, 0, 0);
    528 	if (fire_hit (self, aim, (5 + (rand() % 5)), 50))
    529 		gi.sound (self, CHAN_WEAPON, sound_punch_hit, 1, ATTN_NORM, 0);
    530 }
    531 
    532 mframe_t infantry_frames_attack2 [] =
    533 {
    534 	ai_charge, 3, NULL,
    535 	ai_charge, 6, NULL,
    536 	ai_charge, 0, infantry_swing,
    537 	ai_charge, 8, NULL,
    538 	ai_charge, 5, NULL,
    539 	ai_charge, 8, infantry_smack,
    540 	ai_charge, 6, NULL,
    541 	ai_charge, 3, NULL,
    542 };
    543 mmove_t infantry_move_attack2 = {FRAME_attak201, FRAME_attak208, infantry_frames_attack2, infantry_run};
    544 
    545 void infantry_attack(edict_t *self)
    546 {
    547 	if (range (self, self->enemy) == RANGE_MELEE)
    548 		self->monsterinfo.currentmove = &infantry_move_attack2;
    549 	else
    550 		self->monsterinfo.currentmove = &infantry_move_attack1;
    551 }
    552 
    553 
    554 /*QUAKED monster_infantry (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
    555 */
    556 void SP_monster_infantry (edict_t *self)
    557 {
    558 	if (deathmatch->value)
    559 	{
    560 		G_FreeEdict (self);
    561 		return;
    562 	}
    563 
    564 	sound_pain1 = gi.soundindex ("infantry/infpain1.wav");
    565 	sound_pain2 = gi.soundindex ("infantry/infpain2.wav");
    566 	sound_die1 = gi.soundindex ("infantry/infdeth1.wav");
    567 	sound_die2 = gi.soundindex ("infantry/infdeth2.wav");
    568 
    569 	sound_gunshot = gi.soundindex ("infantry/infatck1.wav");
    570 	sound_weapon_cock = gi.soundindex ("infantry/infatck3.wav");
    571 	sound_punch_swing = gi.soundindex ("infantry/infatck2.wav");
    572 	sound_punch_hit = gi.soundindex ("infantry/melee2.wav");
    573 	
    574 	sound_sight = gi.soundindex ("infantry/infsght1.wav");
    575 	sound_search = gi.soundindex ("infantry/infsrch1.wav");
    576 	sound_idle = gi.soundindex ("infantry/infidle1.wav");
    577 	
    578 
    579 	self->movetype = MOVETYPE_STEP;
    580 	self->solid = SOLID_BBOX;
    581 	self->s.modelindex = gi.modelindex("models/monsters/infantry/tris.md2");
    582 	VectorSet (self->mins, -16, -16, -24);
    583 	VectorSet (self->maxs, 16, 16, 32);
    584 
    585 	self->health = 100;
    586 	self->gib_health = -40;
    587 	self->mass = 200;
    588 
    589 	self->pain = infantry_pain;
    590 	self->die = infantry_die;
    591 
    592 	self->monsterinfo.stand = infantry_stand;
    593 	self->monsterinfo.walk = infantry_walk;
    594 	self->monsterinfo.run = infantry_run;
    595 	self->monsterinfo.dodge = infantry_dodge;
    596 	self->monsterinfo.attack = infantry_attack;
    597 	self->monsterinfo.melee = NULL;
    598 	self->monsterinfo.sight = infantry_sight;
    599 	self->monsterinfo.idle = infantry_fidget;
    600 
    601 	gi.linkentity (self);
    602 
    603 	self->monsterinfo.currentmove = &infantry_move_stand;
    604 	self->monsterinfo.scale = MODEL_SCALE;
    605 
    606 	walkmonster_start (self);
    607 }