diff --git a/src/shared/NSEntity.h b/src/shared/NSEntity.h index 73c1fbd0..8df3f07c 100644 --- a/src/shared/NSEntity.h +++ b/src/shared/NSEntity.h @@ -322,7 +322,7 @@ public: /** Returns if the entity is visible from a given position and a field of view of 90 degrees. */ nonvirtual bool VisibleVec(vector); /** Returns a normalized value of how far away the target is from the entity's view direction. 1 means dead-center. 0 means it's behind.*/ - nonvirtual bool DistanceFromYaw(entity); + nonvirtual bool DistanceFromYaw(vector); /** Returns if the entity has any spawnflags set. */ nonvirtual bool HasSpawnFlags(float); /** Returns if the entity is aligned to the ground. */ diff --git a/src/shared/NSEntity.qc b/src/shared/NSEntity.qc index fadb3513..60f67d4e 100644 --- a/src/shared/NSEntity.qc +++ b/src/shared/NSEntity.qc @@ -99,7 +99,7 @@ bool NSEntity::VisibleVec( vector org ) { bool NSEntity::Visible( entity ent ) { /* is it in our field of view? */ - if ( DistanceFromYaw(ent) > 0.3f ) { + if ( DistanceFromYaw(ent.origin) > 0.3f ) { traceline( origin, ent.origin, MOVE_NORMAL, this ); if ( trace_fraction == 1.0f || trace_ent == ent ) { print( sprintf( "%s can see %s\n", classname, ent.classname ) ); @@ -110,12 +110,12 @@ bool NSEntity::Visible( entity ent ) { return ( false ); } -bool NSEntity::DistanceFromYaw( entity ent ) { +bool NSEntity::DistanceFromYaw( vector targetPos ) { vector flDelta; float flFoV; makevectors( angles ); - flDelta = normalize( ent.origin - origin ); + flDelta = normalize( targetPos - origin ); return flDelta * v_forward; } diff --git a/src/shared/NSMonster.h b/src/shared/NSMonster.h index abad1c96..3ce56bfd 100644 --- a/src/shared/NSMonster.h +++ b/src/shared/NSMonster.h @@ -337,6 +337,10 @@ public: virtual int AnimWalk(void); /** Overridable: Called when we need to play a fresh running framegroup. */ virtual int AnimRun(void); + /** Overridable: Called when we need to play a left turning animation. */ + virtual int AnimTurnLeft(void); + /** Overridable: Called when we need to play a right turning animation. */ + virtual int AnimTurnRight(void); /** Call to play a single animation onto it, which cannot be interrupted by movement. */ virtual void AnimPlay(float); /** Internal use only. Run every frame to update animation parameters. */ @@ -417,8 +421,10 @@ private: /* caching variables, don't save these */ float m_actIdle; + bool m_bTurning; nonvirtual void _LerpTurnToEnemy(void); + nonvirtual void _LerpTurnToYaw(vector); virtual void _Alerted(void); #endif }; diff --git a/src/shared/NSMonster.qc b/src/shared/NSMonster.qc index 8b404662..11bdd71e 100644 --- a/src/shared/NSMonster.qc +++ b/src/shared/NSMonster.qc @@ -200,7 +200,20 @@ NSMonster::AnimWalk(void) int NSMonster::AnimRun(void) { - return frameforaction(modelindex, ACT_RUN); + float runAnim = frameforaction(modelindex, ACT_RUN); + return (runAnim == -1) ? AnimWalk() : runAnim; +} + +int +NSMonster::AnimTurnLeft(void) +{ + return frameforaction(modelindex, ACT_TURN_LEFT); +} + +int +NSMonster::AnimTurnRight(void) +{ + return frameforaction(modelindex, ACT_TURN_RIGHT); } void @@ -453,20 +466,27 @@ NSMonster::GetYawSpeed(void) } void -NSMonster::_LerpTurnToEnemy(void) +NSMonster::_LerpTurnToYaw(vector turnYaw) { - /* only continue if we're in one of the three states. */ - if (GetState() != MONSTER_AIMING) - if (GetState() != MONSTER_CHASING) - if (GetState() != MONSTER_FOLLOWING) - return; - - if (!m_eEnemy) - return; - float turnSpeed = GetYawSpeed(); - vector vecWishAngle = vectoangles(m_eEnemy.origin - origin); - float yawDiff = anglesub(vecWishAngle[1], v_angle[1]); + vector vecWishAngle = turnYaw; + float yawDiff = anglesub(turnYaw[1], v_angle[1]); + + if (fabs(yawDiff) > 90) { + velocity = g_vec_null; + input_movevalues = g_vec_null; + + if (m_bTurning == false) + if (yawDiff < 0) { + SetFrame(AnimTurnRight()); + } else { + SetFrame(AnimTurnLeft()); + } + + m_bTurning = true; + } else { + m_bTurning = false; + } /* min/max out the diff */ if (yawDiff > 0) { @@ -487,6 +507,29 @@ NSMonster::_LerpTurnToEnemy(void) angles[1] = input_angles[1] = v_angle[1] = vecWishAngle[1]; } +void +NSMonster::_LerpTurnToPos(vector turnPos) +{ + vector vecWishAngle = vectoangles(turnPos - origin); + _LerpTurnToYaw(vecWishAngle); +} + + +void +NSMonster::_LerpTurnToEnemy(void) +{ + /* only continue if we're in one of the three states. */ + if (GetState() != MONSTER_AIMING) + if (GetState() != MONSTER_CHASING) + if (GetState() != MONSTER_FOLLOWING) + return; + + if (!m_eEnemy) + return; + + _LerpTurnToPos(m_eEnemy.origin); +} + void NSMonster::AttackThink(void) { @@ -645,6 +688,8 @@ NSMonster::RouteEnded(void) void NSMonster::WalkRoute(void) { + vector wishAngles; + /* we're busy shooting at something, don't walk */ if (GetState() == MONSTER_AIMING && m_eEnemy) { input_angles = vectoangles(m_eEnemy.origin - origin); @@ -662,29 +707,7 @@ NSMonster::WalkRoute(void) return; /* yaw interpolation */ - { - float turnSpeed = GetYawSpeed(); - vector vecWishAngle = input_angles; - float yawDiff = anglesub(vecWishAngle[1], v_angle[1]); - - /* min/max out the diff */ - if (yawDiff > 0) { - v_angle[1] += turnSpeed * frametime; - - if (v_angle[1] > vecWishAngle[1]) - v_angle[1] = vecWishAngle[1]; - } else if (yawDiff < 0) { - v_angle[1] -= turnSpeed * frametime; - - if (v_angle[1] < vecWishAngle[1]) - v_angle[1] = vecWishAngle[1]; - } - - /* fix angles */ - makevectors(v_angle); - vecWishAngle = vectoangles( v_forward ); - angles[1] = input_angles[1] = v_angle[1] = vecWishAngle[1]; - } + _LerpTurnToYaw(input_angles); } void @@ -699,6 +722,9 @@ NSMonster::AnimationUpdate(void) if (GetState() == MONSTER_AIMING) return; + if (m_bTurning) + return; + float spvel = vlen(velocity); float midspeed = GetWalkSpeed() + ((GetRunSpeed() - GetWalkSpeed()) * 0.5f); @@ -813,6 +839,7 @@ NSMonster::Physics(void) input_buttons = 0; input_timelength = frametime; input_angles = angles; + m_bTurning = false; /* when stuck in a sequence, forget enemies, combat stance */ if (GetSequenceState() != SEQUENCESTATE_NONE) {