Some basic Attack functions for CBaseMonster. monster_barney in Half-Life will draw, holster his weapon against targets and shoot. Shows there's some use in our pathfinding already.
This commit is contained in:
parent
da7c5a27e2
commit
73597af3c0
5 changed files with 187 additions and 13 deletions
|
@ -279,6 +279,7 @@ void CBaseEntity::ReadEntity(float flChanged)
|
|||
}
|
||||
if (flChanged & BASEFL_CHANGED_FRAME) {
|
||||
frame1time = 0.0;
|
||||
frame2time = 0.0f;
|
||||
frame = readbyte();
|
||||
}
|
||||
if (flChanged & BASEFL_CHANGED_SKIN) {
|
||||
|
|
|
@ -20,15 +20,18 @@ typedef struct
|
|||
int m_iFlags;
|
||||
} nodeslist_t;
|
||||
|
||||
/* movement states */
|
||||
enum
|
||||
{
|
||||
MONSTER_IDLE,
|
||||
MONSTER_WALK,
|
||||
MONSTER_RUN,
|
||||
MONSTER_DRAWING,
|
||||
MONSTER_HOLSTERING,
|
||||
MONSTER_AIMING,
|
||||
MONSTER_DEAD,
|
||||
MONSTER_GIBBED,
|
||||
MONSTER_GIBBED
|
||||
};
|
||||
|
||||
/* scripted sequence states */
|
||||
enum
|
||||
{
|
||||
SEQUENCESTATE_NONE,
|
||||
|
@ -36,6 +39,7 @@ enum
|
|||
SEQUENCESTATE_ENDING
|
||||
};
|
||||
|
||||
/* monster flags */
|
||||
enumflags
|
||||
{
|
||||
MSF_WAITTILLSEEN,
|
||||
|
@ -51,6 +55,15 @@ enumflags
|
|||
MSF_MULTIPLAYER
|
||||
};
|
||||
|
||||
/* alliance state */
|
||||
enum
|
||||
{
|
||||
MAL_FRIEND, /* friendly towards the player */
|
||||
MAL_ENEMY, /* unfriendly towards the player */
|
||||
MAL_ALIEN, /* unfriendly towards anyone but themselves */
|
||||
MAL_ROGUE /* no allies, not even amongst themselves */
|
||||
};
|
||||
|
||||
class CBaseMonster:CBaseEntity
|
||||
{
|
||||
vector oldnet_velocity;
|
||||
|
@ -60,23 +73,29 @@ class CBaseMonster:CBaseEntity
|
|||
vector base_maxs;
|
||||
int base_health;
|
||||
|
||||
/* sequences */
|
||||
string m_strRouteEnded;
|
||||
int m_iSequenceRemove;
|
||||
int m_iSequenceState;
|
||||
float m_flSequenceEnd;
|
||||
float m_flSequenceSpeed;
|
||||
vector m_vecSequenceAngle;
|
||||
|
||||
/* attack/alliance system */
|
||||
entity m_eEnemy;
|
||||
float m_flFOV;
|
||||
float m_flAttackThink;
|
||||
int m_iAlliance;
|
||||
int m_iMState;
|
||||
vector m_vecLKPos; /* last-known pos */
|
||||
|
||||
/* pathfinding */
|
||||
int m_iNodes;
|
||||
int m_iCurNode;
|
||||
nodeslist_t *m_pRoute;
|
||||
vector m_vecLastNode;
|
||||
|
||||
/* sequences */
|
||||
string m_strRouteEnded;
|
||||
|
||||
void(void) CBaseMonster;
|
||||
|
||||
virtual void(void) touch;
|
||||
virtual void(void) Hide;
|
||||
virtual void(void) Respawn;
|
||||
|
@ -88,9 +107,15 @@ class CBaseMonster:CBaseEntity
|
|||
virtual void(void) Gib;
|
||||
virtual void(string) Sound;
|
||||
|
||||
/* attack system */
|
||||
virtual void(void) AttackDraw;
|
||||
virtual void(void) AttackHolster;
|
||||
virtual void(void) AttackThink;
|
||||
virtual void(void) AttackMelee;
|
||||
virtual void(void) AttackRanged;
|
||||
|
||||
/* sequences */
|
||||
virtual void(void) FreeState;
|
||||
|
||||
virtual void(void) ClearRoute;
|
||||
virtual void(void) CheckRoute;
|
||||
virtual void(void) WalkRoute;
|
||||
|
@ -101,6 +126,7 @@ class CBaseMonster:CBaseEntity
|
|||
virtual int(void) AnimIdle;
|
||||
virtual int(void) AnimWalk;
|
||||
virtual int(void) AnimRun;
|
||||
virtual void(float) AnimPlay;
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -121,6 +147,16 @@ CBaseMonster::AnimRun(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
CBaseMonster::AnimPlay(float seq)
|
||||
{
|
||||
/* forces a client-side update */
|
||||
SendFlags |= BASEFL_CHANGED_FRAME;
|
||||
|
||||
SetFrame(seq);
|
||||
m_flAnimTime = time + frameduration(modelindex, frame);
|
||||
}
|
||||
|
||||
void
|
||||
CBaseMonster::Sound(string msg)
|
||||
{
|
||||
|
@ -141,6 +177,86 @@ CBaseMonster::IdleNoise(void)
|
|||
|
||||
}
|
||||
|
||||
void
|
||||
CBaseMonster::AttackThink(void)
|
||||
{
|
||||
if (m_flAttackThink > time) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* don't have an enemy? let's look out for one */
|
||||
if (!m_eEnemy) {
|
||||
/* find code here */
|
||||
m_flAttackThink = time + 0.5f;
|
||||
return;
|
||||
}
|
||||
|
||||
/* do we have a clear shot? */
|
||||
other = world;
|
||||
traceline(origin, m_eEnemy.origin, MOVE_OTHERONLY, this);
|
||||
|
||||
/* something is blocking us */
|
||||
if (trace_fraction < 1.0f) {
|
||||
m_iMState = MONSTER_HOLSTERING;
|
||||
|
||||
/* FIXME: This is unreliable, but unlikely that a player ever is here */
|
||||
if (m_vecLKPos != [0,0,0]) {
|
||||
NewRoute(m_vecLKPos);
|
||||
m_flSequenceSpeed = 140;
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CBaseMonster::AttackMelee(void)
|
||||
{
|
||||
dprint(sprintf("^1%s::AttackMelee: Not defined!\n", ::classname));
|
||||
m_flAttackThink = time + 0.5f;
|
||||
}
|
||||
|
||||
void
|
||||
CBaseMonster::AttackRanged(void)
|
||||
{
|
||||
dprint(sprintf("^1%s::AttackRanged: Not defined!\n", ::classname));
|
||||
m_flAttackThink = time + 0.5f;
|
||||
}
|
||||
|
||||
void
|
||||
CBaseMonster::AttackDraw(void)
|
||||
{
|
||||
dprint(sprintf("^1%s::AttackDraw: Not defined!\n", ::classname));
|
||||
m_flAttackThink = time + 0.5f;
|
||||
}
|
||||
|
||||
void
|
||||
CBaseMonster::AttackHolster(void)
|
||||
{
|
||||
dprint(sprintf("^1%s::AttackHolster: Not defined!\n", ::classname));
|
||||
m_flAttackThink = time + 0.5f;
|
||||
}
|
||||
|
||||
void
|
||||
CBaseMonster::ClearRoute(void)
|
||||
{
|
||||
|
@ -203,7 +319,7 @@ CBaseMonster::CheckRoute(void)
|
|||
m_iCurNode--;
|
||||
velocity = [0,0,0]; /* clamp friction */
|
||||
}
|
||||
|
||||
|
||||
if (m_iCurNode < -1) {
|
||||
ClearRoute();
|
||||
dprint(sprintf("^2CBaseMonster::^3CheckRoute^7: %s reached end\n", this.m_strTargetName));
|
||||
|
@ -243,8 +359,18 @@ CBaseMonster::CheckRoute(void)
|
|||
void
|
||||
CBaseMonster::WalkRoute(void)
|
||||
{
|
||||
if (m_iNodes) {
|
||||
vector endangles;
|
||||
vector endangles;
|
||||
|
||||
/* we're busy shooting at something, don't walk */
|
||||
if (m_iMState == MONSTER_AIMING) {
|
||||
endangles = vectoangles(m_eEnemy.origin - origin);
|
||||
|
||||
/* TODO: lerp */
|
||||
input_angles[1] = endangles[1];
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_iNodes && m_iMState == MONSTER_IDLE) {
|
||||
/* we're on our last node */
|
||||
if (m_iCurNode < 0) {
|
||||
endangles = vectoangles(m_vecLastNode - origin);
|
||||
|
@ -297,6 +423,7 @@ CBaseMonster::Physics(void)
|
|||
input_angles = angles = v_angle = m_vecSequenceAngle;
|
||||
SetFrame(m_flSequenceEnd);
|
||||
} else if (movetype == MOVETYPE_WALK) {
|
||||
AttackThink();
|
||||
CheckRoute();
|
||||
WalkRoute();
|
||||
runstandardplayerphysics(this);
|
||||
|
@ -350,7 +477,8 @@ CBaseMonster::PlayerUse(void)
|
|||
void
|
||||
CBaseMonster::Pain(int iHitBody)
|
||||
{
|
||||
|
||||
if (!m_eEnemy)
|
||||
m_eEnemy = g_dmg_eAttacker;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -427,4 +555,8 @@ CBaseMonster::CBaseMonster(void)
|
|||
}
|
||||
|
||||
CBaseEntity::CBaseEntity();
|
||||
|
||||
/* give us a 65 degree view cone */
|
||||
m_flFOV = 1.0 / 65;
|
||||
m_iAlliance = MAL_ROGUE;
|
||||
}
|
||||
|
|
|
@ -451,6 +451,7 @@ CBaseNPC::Physics(void)
|
|||
SetFrame(m_flSequenceEnd);
|
||||
} else {
|
||||
if (style != MONSTER_DEAD) {
|
||||
AttackThink();
|
||||
TalkPlayerGreet();
|
||||
FollowChain();
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@ Skill_Init(void)
|
|||
readcmd(sprintf("exec skill_%s.cfg\n", cvar_string("game")));
|
||||
}
|
||||
|
||||
float Skill_GetValue(string variable)
|
||||
float
|
||||
Skill_GetValue(string variable)
|
||||
{
|
||||
float skill = cvar("skill");
|
||||
return cvar(sprintf("sk_%s%d", variable, skill));
|
||||
|
|
|
@ -55,6 +55,11 @@ class monster_barney:CBaseNPC
|
|||
virtual int(void) AnimIdle;
|
||||
virtual int(void) AnimWalk;
|
||||
virtual int(void) AnimRun;
|
||||
|
||||
virtual void(void) AttackDraw;
|
||||
virtual void(void) AttackHolster;
|
||||
virtual void(void) AttackMelee;
|
||||
virtual void(void) AttackRanged;
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -75,6 +80,38 @@ monster_barney::AnimRun(void)
|
|||
return BA_RUN;
|
||||
}
|
||||
|
||||
void
|
||||
monster_barney::AttackDraw(void)
|
||||
{
|
||||
AnimPlay(BA_DRAW);
|
||||
m_flAttackThink = m_flAnimTime;
|
||||
}
|
||||
|
||||
void
|
||||
monster_barney::AttackHolster(void)
|
||||
{
|
||||
AnimPlay(BA_HOLSTER);
|
||||
m_flAttackThink = m_flAnimTime;
|
||||
}
|
||||
|
||||
void
|
||||
monster_barney::AttackMelee(void)
|
||||
{
|
||||
AttackRanged();
|
||||
}
|
||||
|
||||
void
|
||||
monster_barney::AttackRanged(void)
|
||||
{
|
||||
/* visual */
|
||||
AnimPlay(BA_SHOOT1);
|
||||
m_flAttackThink = time + 0.4f;
|
||||
|
||||
/* functional */
|
||||
TraceAttack_FireBullets(1, origin + [0,0,16], 8, [0.01,0,01], 2);
|
||||
Sound_Play(this, CHAN_WEAPON, "weapon_glock.fire");
|
||||
}
|
||||
|
||||
void
|
||||
monster_barney::PlayerUse(void)
|
||||
{
|
||||
|
@ -89,6 +126,8 @@ monster_barney::PlayerUse(void)
|
|||
void
|
||||
monster_barney::Pain(int iHitBody)
|
||||
{
|
||||
CBaseNPC::Pain(iHitBody);
|
||||
|
||||
WarnAllies();
|
||||
|
||||
if (m_flAnimTime > time) {
|
||||
|
|
Loading…
Reference in a new issue