📄 m_soldier.c
字号:
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
==============================================================================
SOLDIER
==============================================================================
*/
#include "g_local.h"
#include "m_soldier.h"
static int sound_idle;
static int sound_sight1;
static int sound_sight2;
static int sound_pain_light;
static int sound_pain;
static int sound_pain_ss;
static int sound_death_light;
static int sound_death;
static int sound_death_ss;
static int sound_cock;
void soldier_idle (edict_t *self)
{
if (random() > 0.8)
gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
}
void soldier_cock (edict_t *self)
{
if (self->s.frame == FRAME_stand322)
gi.sound (self, CHAN_WEAPON, sound_cock, 1, ATTN_IDLE, 0);
else
gi.sound (self, CHAN_WEAPON, sound_cock, 1, ATTN_NORM, 0);
}
// STAND
void soldier_stand (edict_t *self);
mframe_t soldier_frames_stand1 [] =
{
ai_stand, 0, soldier_idle,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL
};
mmove_t soldier_move_stand1 = {FRAME_stand101, FRAME_stand130, soldier_frames_stand1, soldier_stand};
mframe_t soldier_frames_stand3 [] =
{
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, soldier_cock,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL
};
mmove_t soldier_move_stand3 = {FRAME_stand301, FRAME_stand339, soldier_frames_stand3, soldier_stand};
#if 0
mframe_t soldier_frames_stand4 [] =
{
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL,
ai_stand, 4, NULL,
ai_stand, 1, NULL,
ai_stand, -1, NULL,
ai_stand, -2, NULL,
ai_stand, 0, NULL,
ai_stand, 0, NULL
};
mmove_t soldier_move_stand4 = {FRAME_stand401, FRAME_stand452, soldier_frames_stand4, NULL};
#endif
void soldier_stand (edict_t *self)
{
if ((self->monsterinfo.currentmove == &soldier_move_stand3) || (random() < 0.8))
self->monsterinfo.currentmove = &soldier_move_stand1;
else
self->monsterinfo.currentmove = &soldier_move_stand3;
}
//
// WALK
//
void soldier_walk1_random (edict_t *self)
{
if (random() > 0.1)
self->monsterinfo.nextframe = FRAME_walk101;
}
mframe_t soldier_frames_walk1 [] =
{
ai_walk, 3, NULL,
ai_walk, 6, NULL,
ai_walk, 2, NULL,
ai_walk, 2, NULL,
ai_walk, 2, NULL,
ai_walk, 1, NULL,
ai_walk, 6, NULL,
ai_walk, 5, NULL,
ai_walk, 3, NULL,
ai_walk, -1, soldier_walk1_random,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL,
ai_walk, 0, NULL
};
mmove_t soldier_move_walk1 = {FRAME_walk101, FRAME_walk133, soldier_frames_walk1, NULL};
mframe_t soldier_frames_walk2 [] =
{
ai_walk, 4, NULL,
ai_walk, 4, NULL,
ai_walk, 9, NULL,
ai_walk, 8, NULL,
ai_walk, 5, NULL,
ai_walk, 1, NULL,
ai_walk, 3, NULL,
ai_walk, 7, NULL,
ai_walk, 6, NULL,
ai_walk, 7, NULL
};
mmove_t soldier_move_walk2 = {FRAME_walk209, FRAME_walk218, soldier_frames_walk2, NULL};
void soldier_walk (edict_t *self)
{
if (random() < 0.5)
self->monsterinfo.currentmove = &soldier_move_walk1;
else
self->monsterinfo.currentmove = &soldier_move_walk2;
}
//
// RUN
//
void soldier_run (edict_t *self);
mframe_t soldier_frames_start_run [] =
{
ai_run, 7, NULL,
ai_run, 5, NULL
};
mmove_t soldier_move_start_run = {FRAME_run01, FRAME_run02, soldier_frames_start_run, soldier_run};
mframe_t soldier_frames_run [] =
{
ai_run, 10, NULL,
ai_run, 11, NULL,
ai_run, 11, NULL,
ai_run, 16, NULL,
ai_run, 10, NULL,
ai_run, 15, NULL
};
mmove_t soldier_move_run = {FRAME_run03, FRAME_run08, soldier_frames_run, NULL};
void soldier_run (edict_t *self)
{
if (self->monsterinfo.aiflags & AI_STAND_GROUND)
{
self->monsterinfo.currentmove = &soldier_move_stand1;
return;
}
if (self->monsterinfo.currentmove == &soldier_move_walk1 ||
self->monsterinfo.currentmove == &soldier_move_walk2 ||
self->monsterinfo.currentmove == &soldier_move_start_run)
{
self->monsterinfo.currentmove = &soldier_move_run;
}
else
{
self->monsterinfo.currentmove = &soldier_move_start_run;
}
}
//
// PAIN
//
mframe_t soldier_frames_pain1 [] =
{
ai_move, -3, NULL,
ai_move, 4, NULL,
ai_move, 1, NULL,
ai_move, 1, NULL,
ai_move, 0, NULL
};
mmove_t soldier_move_pain1 = {FRAME_pain101, FRAME_pain105, soldier_frames_pain1, soldier_run};
mframe_t soldier_frames_pain2 [] =
{
ai_move, -13, NULL,
ai_move, -1, NULL,
ai_move, 2, NULL,
ai_move, 4, NULL,
ai_move, 2, NULL,
ai_move, 3, NULL,
ai_move, 2, NULL
};
mmove_t soldier_move_pain2 = {FRAME_pain201, FRAME_pain207, soldier_frames_pain2, soldier_run};
mframe_t soldier_frames_pain3 [] =
{
ai_move, -8, NULL,
ai_move, 10, NULL,
ai_move, -4, NULL,
ai_move, -1, NULL,
ai_move, -3, NULL,
ai_move, 0, NULL,
ai_move, 3, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 1, NULL,
ai_move, 0, NULL,
ai_move, 1, NULL,
ai_move, 2, NULL,
ai_move, 4, NULL,
ai_move, 3, NULL,
ai_move, 2, NULL
};
mmove_t soldier_move_pain3 = {FRAME_pain301, FRAME_pain318, soldier_frames_pain3, soldier_run};
mframe_t soldier_frames_pain4 [] =
{
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, 0, NULL,
ai_move, -10, NULL,
ai_move, -6, NULL,
ai_move, 8, NULL,
ai_move, 4, NULL,
ai_move, 1, NULL,
ai_move, 0, NULL,
ai_move, 2, NULL,
ai_move, 5, NULL,
ai_move, 2, NULL,
ai_move, -1, NULL,
ai_move, -1, NULL,
ai_move, 3, NULL,
ai_move, 2, NULL,
ai_move, 0, NULL
};
mmove_t soldier_move_pain4 = {FRAME_pain401, FRAME_pain417, soldier_frames_pain4, soldier_run};
void soldier_pain (edict_t *self, edict_t *other, float kick, int damage)
{
float r;
int n;
if (self->health < (self->max_health / 2))
self->s.skinnum |= 1;
if (level.time < self->pain_debounce_time)
{
if ((self->velocity[2] > 100) && ( (self->monsterinfo.currentmove == &soldier_move_pain1) || (self->monsterinfo.currentmove == &soldier_move_pain2) || (self->monsterinfo.currentmove == &soldier_move_pain3)))
self->monsterinfo.currentmove = &soldier_move_pain4;
return;
}
self->pain_debounce_time = level.time + 3;
n = self->s.skinnum | 1;
if (n == 1)
gi.sound (self, CHAN_VOICE, sound_pain_light, 1, ATTN_NORM, 0);
else if (n == 3)
gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
else
gi.sound (self, CHAN_VOICE, sound_pain_ss, 1, ATTN_NORM, 0);
if (self->velocity[2] > 100)
{
self->monsterinfo.currentmove = &soldier_move_pain4;
return;
}
if (skill->value == 3)
return; // no pain anims in nightmare
r = random();
if (r < 0.33)
self->monsterinfo.currentmove = &soldier_move_pain1;
else if (r < 0.66)
self->monsterinfo.currentmove = &soldier_move_pain2;
else
self->monsterinfo.currentmove = &soldier_move_pain3;
}
//
// ATTACK
//
static int blaster_flash [] = {MZ2_SOLDIER_BLASTER_1, MZ2_SOLDIER_BLASTER_2, MZ2_SOLDIER_BLASTER_3, MZ2_SOLDIER_BLASTER_4, MZ2_SOLDIER_BLASTER_5, MZ2_SOLDIER_BLASTER_6, MZ2_SOLDIER_BLASTER_7, MZ2_SOLDIER_BLASTER_8};
static int shotgun_flash [] = {MZ2_SOLDIER_SHOTGUN_1, MZ2_SOLDIER_SHOTGUN_2, MZ2_SOLDIER_SHOTGUN_3, MZ2_SOLDIER_SHOTGUN_4, MZ2_SOLDIER_SHOTGUN_5, MZ2_SOLDIER_SHOTGUN_6, MZ2_SOLDIER_SHOTGUN_7, MZ2_SOLDIER_SHOTGUN_8};
static int machinegun_flash [] = {MZ2_SOLDIER_MACHINEGUN_1, MZ2_SOLDIER_MACHINEGUN_2, MZ2_SOLDIER_MACHINEGUN_3, MZ2_SOLDIER_MACHINEGUN_4, MZ2_SOLDIER_MACHINEGUN_5, MZ2_SOLDIER_MACHINEGUN_6, MZ2_SOLDIER_MACHINEGUN_7, MZ2_SOLDIER_MACHINEGUN_8};
void soldier_fire (edict_t *self, int flash_number)
{
vec3_t start;
vec3_t forward, right, up;
vec3_t aim;
vec3_t dir;
vec3_t end;
float r, u;
int flash_index;
if (self->s.skinnum < 2)
flash_index = blaster_flash[flash_number];
else if (self->s.skinnum < 4)
flash_index = shotgun_flash[flash_number];
else
flash_index = machinegun_flash[flash_number];
AngleVectors (self->s.angles, forward, right, NULL);
G_ProjectSource (self->s.origin, monster_flash_offset[flash_index], forward, right, start);
if (flash_number == 5 || flash_number == 6)
{
VectorCopy (forward, aim);
}
else
{
VectorCopy (self->enemy->s.origin, end);
end[2] += self->enemy->viewheight;
VectorSubtract (end, start, aim);
vectoangles (aim, dir);
AngleVectors (dir, forward, right, up);
r = crandom()*1000;
u = crandom()*500;
VectorMA (start, 8192, forward, end);
VectorMA (end, r, right, end);
VectorMA (end, u, up, end);
VectorSubtract (end, start, aim);
VectorNormalize (aim);
}
if (self->s.skinnum <= 1)
{
monster_fire_blaster (self, start, aim, 5, 600, flash_index, EF_BLASTER);
}
else if (self->s.skinnum <= 3)
{
monster_fire_shotgun (self, start, aim, 2, 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, flash_index);
}
else
{
if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME))
self->monsterinfo.pausetime = level.time + (3 + rand() % 8) * FRAMETIME;
monster_fire_bullet (self, start, aim, 2, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_index);
if (level.time >= self->monsterinfo.pausetime)
self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
else
self->monsterinfo.aiflags |= AI_HOLD_FRAME;
}
}
// ATTACK1 (blaster/shotgun)
void soldier_fire1 (edict_t *self)
{
soldier_fire (self, 0);
}
void soldier_attack1_refire1 (edict_t *self)
{
if (self->s.skinnum > 1)
return;
if (self->enemy->health <= 0)
return;
if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
self->monsterinfo.nextframe = FRAME_attak102;
else
self->monsterinfo.nextframe = FRAME_attak110;
}
void soldier_attack1_refire2 (edict_t *self)
{
if (self->s.skinnum < 2)
return;
if (self->enemy->health <= 0)
return;
if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
self->monsterinfo.nextframe = FRAME_attak102;
}
mframe_t soldier_frames_attack1 [] =
{
ai_charge, 0, NULL,
ai_charge, 0, NULL,
ai_charge, 0, soldier_fire1,
ai_charge, 0, NULL,
ai_charge, 0, NULL,
ai_charge, 0, soldier_attack1_refire1,
ai_charge, 0, NULL,
ai_charge, 0, soldier_cock,
ai_charge, 0, soldier_attack1_refire2,
ai_charge, 0, NULL,
ai_charge, 0, NULL,
ai_charge, 0, NULL
};
mmove_t soldier_move_attack1 = {FRAME_attak101, FRAME_attak112, soldier_frames_attack1, soldier_run};
// ATTACK2 (blaster/shotgun)
void soldier_fire2 (edict_t *self)
{
soldier_fire (self, 1);
}
void soldier_attack2_refire1 (edict_t *self)
{
if (self->s.skinnum > 1)
return;
if (self->enemy->health <= 0)
return;
if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
self->monsterinfo.nextframe = FRAME_attak204;
else
self->monsterinfo.nextframe = FRAME_attak216;
}
void soldier_attack2_refire2 (edict_t *self)
{
if (self->s.skinnum < 2)
return;
if (self->enemy->health <= 0)
return;
if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
self->monsterinfo.nextframe = FRAME_attak204;
}
mframe_t soldier_frames_attack2 [] =
{
ai_charge, 0, NULL,
ai_charge, 0, NULL,
ai_charge, 0, NULL,
ai_charge, 0, NULL,
ai_charge, 0, soldier_fire2,
ai_charge, 0, NULL,
ai_charge, 0, NULL,
ai_charge, 0, soldier_attack2_refire1,
ai_charge, 0, NULL,
ai_charge, 0, NULL,
ai_charge, 0, NULL,
ai_charge, 0, NULL,
ai_charge, 0, soldier_cock,
ai_charge, 0, NULL,
ai_charge, 0, soldier_attack2_refire2,
ai_charge, 0, NULL,
ai_charge, 0, NULL,
ai_charge, 0, NULL
};
mmove_t soldier_move_attack2 = {FRAME_attak201, FRAME_attak218, soldier_frames_attack2, soldier_run};
// ATTACK3 (duck and shoot)
void soldier_duck_down (edict_t *self)
{
if (self->monsterinfo.aiflags & AI_DUCKED)
return;
self->monsterinfo.aiflags |= AI_DUCKED;
self->maxs[2] -= 32;
self->takedamage = DAMAGE_YES;
self->monsterinfo.pausetime = level.time + 1;
gi.linkentity (self);
}
void soldier_duck_up (edict_t *self)
{
self->monsterinfo.aiflags &= ~AI_DUCKED;
self->maxs[2] += 32;
self->takedamage = DAMAGE_AIM;
gi.linkentity (self);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -