Half-Life: monster_zombie and monster_headcrab are attacking somewhat properly now and chase you around. Currently still working out the whole vision logic.
This commit is contained in:
parent
690d390e79
commit
b9f4da2494
4 changed files with 165 additions and 33 deletions
|
@ -24,8 +24,8 @@ typedef struct
|
|||
enum
|
||||
{
|
||||
MONSTER_IDLE,
|
||||
MONSTER_DRAWING,
|
||||
MONSTER_HOLSTERING,
|
||||
MONSTER_FOLLOWING,
|
||||
MONSTER_CHASING,
|
||||
MONSTER_AIMING,
|
||||
MONSTER_DEAD,
|
||||
MONSTER_GIBBED
|
||||
|
@ -107,12 +107,16 @@ class CBaseMonster:CBaseEntity
|
|||
virtual void(void) Gib;
|
||||
virtual void(string) Sound;
|
||||
|
||||
/* see/hear subsystem */
|
||||
float m_flSeeTime;
|
||||
virtual void(void) SeeThink;
|
||||
|
||||
/* attack system */
|
||||
virtual void(void) AttackDraw;
|
||||
virtual void(void) AttackHolster;
|
||||
virtual void(void) AttackThink;
|
||||
virtual void(void) AttackMelee;
|
||||
virtual void(void) AttackRanged;
|
||||
virtual int(void) AttackMelee;
|
||||
virtual int(void) AttackRanged;
|
||||
|
||||
/* sequences */
|
||||
virtual void(void) FreeState;
|
||||
|
@ -177,6 +181,39 @@ CBaseMonster::IdleNoise(void)
|
|||
|
||||
}
|
||||
|
||||
void
|
||||
CBaseMonster::SeeThink(void)
|
||||
{
|
||||
if (m_eEnemy)
|
||||
return;
|
||||
|
||||
if (m_flSeeTime > time)
|
||||
return;
|
||||
|
||||
m_flSeeTime = time + 0.25f;
|
||||
|
||||
for (entity w = world; (w = find(w, ::classname, "player"));) {
|
||||
|
||||
if (w.health <= 0)
|
||||
continue;
|
||||
|
||||
/* first, is the potential enemy in our field of view? */
|
||||
makevectors(angles);
|
||||
vector v = normalize(w.origin - origin);
|
||||
float flDot = v * v_forward;
|
||||
|
||||
if (flDot < 0.60)
|
||||
continue;
|
||||
|
||||
other = world;
|
||||
traceline(origin, w.origin, MOVE_OTHERONLY, this);
|
||||
|
||||
if (trace_fraction == 1.0f) {
|
||||
m_eEnemy = w;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
void
|
||||
CBaseMonster::AttackThink(void)
|
||||
{
|
||||
|
@ -184,12 +221,9 @@ CBaseMonster::AttackThink(void)
|
|||
return;
|
||||
}
|
||||
|
||||
/* don't have an enemy? let's look out for one */
|
||||
if (!m_eEnemy) {
|
||||
/* find code here */
|
||||
m_flAttackThink = time + 0.5f;
|
||||
return;
|
||||
}
|
||||
/* reset */
|
||||
if (m_eEnemy && m_eEnemy.health <= 0)
|
||||
m_eEnemy = __NULL__;
|
||||
|
||||
/* do we have a clear shot? */
|
||||
other = world;
|
||||
|
@ -197,7 +231,7 @@ CBaseMonster::AttackThink(void)
|
|||
|
||||
/* something is blocking us */
|
||||
if (trace_fraction < 1.0f) {
|
||||
m_iMState = MONSTER_HOLSTERING;
|
||||
m_iMState = MONSTER_IDLE;
|
||||
|
||||
/* FIXME: This is unreliable, but unlikely that a player ever is here */
|
||||
if (m_vecLKPos != [0,0,0]) {
|
||||
|
@ -206,41 +240,39 @@ CBaseMonster::AttackThink(void)
|
|||
m_vecLKPos = [0,0,0];
|
||||
}
|
||||
} else {
|
||||
if (m_iMState == MONSTER_IDLE) {
|
||||
m_iMState = MONSTER_DRAWING;
|
||||
} else if (m_iMState == MONSTER_DRAWING) {
|
||||
m_iMState = MONSTER_AIMING;
|
||||
}
|
||||
|
||||
/* make sure we remember the last known position. */
|
||||
m_vecLKPos = m_eEnemy.origin;
|
||||
}
|
||||
|
||||
if (m_iMState == MONSTER_AIMING) {
|
||||
int m;
|
||||
if (vlen(origin - m_eEnemy.origin) < 96)
|
||||
AttackMelee();
|
||||
else
|
||||
AttackRanged();
|
||||
} else if (m_iMState == MONSTER_DRAWING) {
|
||||
AttackDraw();
|
||||
} else if (m_iMState == MONSTER_HOLSTERING) {
|
||||
AttackHolster();
|
||||
m_iMState = MONSTER_IDLE;
|
||||
m = AttackMelee();
|
||||
else {
|
||||
m = AttackRanged();
|
||||
|
||||
/* if we don't have the desired attack mode, walk */
|
||||
if (m == FALSE)
|
||||
m_iMState = MONSTER_CHASING;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
CBaseMonster::AttackMelee(void)
|
||||
{
|
||||
dprint(sprintf("^1%s::AttackMelee: Not defined!\n", ::classname));
|
||||
m_flAttackThink = time + 0.5f;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
CBaseMonster::AttackRanged(void)
|
||||
{
|
||||
dprint(sprintf("^1%s::AttackRanged: Not defined!\n", ::classname));
|
||||
m_flAttackThink = time + 0.5f;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -380,6 +412,13 @@ CBaseMonster::WalkRoute(void)
|
|||
input_angles[1] = endangles[1];
|
||||
input_movevalues = [m_flSequenceSpeed, 0, 0];
|
||||
}
|
||||
|
||||
if (m_iMState == MONSTER_CHASING) {
|
||||
/* we've got 'em in our sights, just need to walk closer */
|
||||
endangles = vectoangles(m_eEnemy.origin - origin);
|
||||
input_movevalues = [140, 0, 0];
|
||||
input_angles[1] = endangles[1];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -423,6 +462,7 @@ CBaseMonster::Physics(void)
|
|||
input_angles = angles = v_angle = m_vecSequenceAngle;
|
||||
SetFrame(m_flSequenceEnd);
|
||||
} else if (movetype == MOVETYPE_WALK) {
|
||||
SeeThink();
|
||||
AttackThink();
|
||||
CheckRoute();
|
||||
WalkRoute();
|
||||
|
|
|
@ -58,8 +58,8 @@ class monster_barney:CBaseNPC
|
|||
|
||||
virtual void(void) AttackDraw;
|
||||
virtual void(void) AttackHolster;
|
||||
virtual void(void) AttackMelee;
|
||||
virtual void(void) AttackRanged;
|
||||
virtual int(void) AttackMelee;
|
||||
virtual int(void) AttackRanged;
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -94,13 +94,13 @@ monster_barney::AttackHolster(void)
|
|||
m_flAttackThink = m_flAnimTime;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
monster_barney::AttackMelee(void)
|
||||
{
|
||||
AttackRanged();
|
||||
return AttackRanged();
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
monster_barney::AttackRanged(void)
|
||||
{
|
||||
/* visual */
|
||||
|
@ -110,6 +110,7 @@ monster_barney::AttackRanged(void)
|
|||
/* functional */
|
||||
TraceAttack_FireBullets(1, origin + [0,0,16], 8, [0.01,0,01], 2);
|
||||
Sound_Play(this, CHAN_WEAPON, "weapon_glock.fire");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -61,6 +61,8 @@ class monster_headcrab:CBaseMonster
|
|||
virtual int(void) AnimIdle;
|
||||
virtual int(void) AnimWalk;
|
||||
virtual int(void) AnimRun;
|
||||
virtual int(void) AttackRanged;
|
||||
virtual void(void) touch;
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -81,6 +83,32 @@ monster_headcrab::AnimRun(void)
|
|||
return HC_RUN;
|
||||
}
|
||||
|
||||
int
|
||||
monster_headcrab::AttackRanged(void)
|
||||
{
|
||||
/* visual */
|
||||
if (random() < 0.5)
|
||||
AnimPlay(HC_JUMP);
|
||||
else
|
||||
AnimPlay(HC_JUMP_VARIATION1);
|
||||
|
||||
m_flAttackThink = m_flAnimTime;
|
||||
Sound_Play(this, CHAN_VOICE, "monster_headcrab.attack");
|
||||
|
||||
/* functional */
|
||||
makevectors(vectoangles(m_eEnemy.origin - origin));
|
||||
velocity = v_forward * 512 + [0,0,250];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
monster_headcrab::touch(void)
|
||||
{
|
||||
if (other.takedamage == DAMAGE_YES)
|
||||
if (frame == HC_JUMP || frame == HC_JUMP_VARIATION1)
|
||||
Damage_Apply(other, this, 500, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
monster_headcrab::Pain(int iHitBody)
|
||||
{
|
||||
|
@ -149,5 +177,6 @@ monster_headcrab::monster_headcrab(void)
|
|||
|
||||
base_mins = [-16,-16,0];
|
||||
base_maxs = [16,16,36];
|
||||
m_iAlliance = MAL_ALIEN;
|
||||
CBaseMonster::CBaseMonster();
|
||||
}
|
||||
|
|
|
@ -80,8 +80,69 @@ class monster_zombie:CBaseMonster
|
|||
virtual void(int) Death;
|
||||
virtual void(void) IdleNoise;
|
||||
virtual void(void) Respawn;
|
||||
|
||||
virtual int(void) AnimIdle;
|
||||
virtual int(void) AnimWalk;
|
||||
virtual int(void) AnimRun;
|
||||
|
||||
virtual int(void) AttackMelee;
|
||||
virtual void(void) AttackFlail;
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
monster_zombie::AnimIdle(void)
|
||||
{
|
||||
return ZO_IDLE;
|
||||
}
|
||||
|
||||
int
|
||||
monster_zombie::AnimWalk(void)
|
||||
{
|
||||
return ZO_WALK;
|
||||
}
|
||||
|
||||
int
|
||||
monster_zombie::AnimRun(void)
|
||||
{
|
||||
return ZO_WALK;
|
||||
}
|
||||
|
||||
int
|
||||
monster_zombie::AttackMelee(void)
|
||||
{
|
||||
/* visual */
|
||||
if (random() < 0.5)
|
||||
AnimPlay(ZO_ATTACK1);
|
||||
else
|
||||
AnimPlay(ZO_ATTACK2);
|
||||
|
||||
m_flAttackThink = m_flAnimTime;
|
||||
Sound_Play(this, CHAN_VOICE, "monster_zombie.attack");
|
||||
|
||||
/* functional */
|
||||
think = AttackFlail;
|
||||
nextthink = 0.25f;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
monster_zombie::AttackFlail(void)
|
||||
{
|
||||
traceline(origin, m_eEnemy.origin, FALSE, this);
|
||||
|
||||
if (trace_fraction >= 1.0 || trace_ent.takedamage != DAMAGE_YES) {
|
||||
Sound_Play(this, CHAN_WEAPON, "monster_zombie.attackmiss");
|
||||
return;
|
||||
}
|
||||
|
||||
Damage_Apply(trace_ent, this, 25, 0, 0);
|
||||
Sound_Play(this, CHAN_WEAPON, "monster_zombie.attackhit");
|
||||
|
||||
if (m_eEnemy.health <= 0)
|
||||
m_eEnemy = __NULL__;
|
||||
}
|
||||
|
||||
void
|
||||
monster_zombie::Pain(int iHitBody)
|
||||
{
|
||||
|
@ -160,5 +221,6 @@ monster_zombie::monster_zombie(void)
|
|||
base_health = Skill_GetValue("zombie_health");
|
||||
base_mins = [-16,-16,0];
|
||||
base_maxs = [16,16,72];
|
||||
m_iAlliance = MAL_ALIEN;
|
||||
CBaseMonster::CBaseMonster();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue