You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
275 lines
10 KiB
275 lines
10 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
// NextBotGroundLocomotion.h
|
||
|
// Basic ground-based movement for NextBotCombatCharacters
|
||
|
// Author: Michael Booth, February 2009
|
||
|
// Note: This is a refactoring of ZombieBotLocomotion from L4D
|
||
|
|
||
|
#ifndef NEXT_BOT_GROUND_LOCOMOTION_H
|
||
|
#define NEXT_BOT_GROUND_LOCOMOTION_H
|
||
|
|
||
|
#include "NextBotLocomotionInterface.h"
|
||
|
#include "nav_mesh.h"
|
||
|
|
||
|
|
||
|
class NextBotCombatCharacter;
|
||
|
|
||
|
//----------------------------------------------------------------------------------------------------------------
|
||
|
/**
|
||
|
* Basic ground-based movement for NextBotCombatCharacters.
|
||
|
* This locomotor resolves collisions and assumes a ground-based bot under the influence of gravity.
|
||
|
*/
|
||
|
class NextBotGroundLocomotion : public ILocomotion
|
||
|
{
|
||
|
public:
|
||
|
DECLARE_CLASS( NextBotGroundLocomotion, ILocomotion );
|
||
|
|
||
|
NextBotGroundLocomotion( INextBot *bot );
|
||
|
virtual ~NextBotGroundLocomotion();
|
||
|
|
||
|
virtual void Reset( void ); // reset locomotor to initial state
|
||
|
virtual void Update( void ); // update internal state
|
||
|
|
||
|
virtual void Approach( const Vector &pos, float goalWeight = 1.0f ); // move directly towards the given position
|
||
|
virtual void DriveTo( const Vector &pos ); // Move the bot to the precise given position immediately,
|
||
|
|
||
|
virtual bool ClimbUpToLedge( const Vector &landingGoal, const Vector &landingForward, const CBaseEntity *obstacle ); // initiate a jump to an adjacent high ledge, return false if climb can't start
|
||
|
virtual void JumpAcrossGap( const Vector &landingGoal, const Vector &landingForward ); // initiate a jump across an empty volume of space to far side
|
||
|
virtual void Jump( void ); // initiate a simple undirected jump in the air
|
||
|
virtual bool IsClimbingOrJumping( void ) const; // is jumping in any form
|
||
|
virtual bool IsClimbingUpToLedge( void ) const; // is climbing up to a high ledge
|
||
|
virtual bool IsJumpingAcrossGap( void ) const; // is jumping across a gap to the far side
|
||
|
|
||
|
virtual void Run( void ); // set desired movement speed to running
|
||
|
virtual void Walk( void ); // set desired movement speed to walking
|
||
|
virtual void Stop( void ); // set desired movement speed to stopped
|
||
|
virtual bool IsRunning( void ) const;
|
||
|
virtual void SetDesiredSpeed( float speed ); // set desired speed for locomotor movement
|
||
|
virtual float GetDesiredSpeed( void ) const; // returns the current desired speed
|
||
|
|
||
|
virtual float GetSpeedLimit( void ) const; // get maximum speed bot can reach, regardless of desired speed
|
||
|
|
||
|
virtual bool IsOnGround( void ) const; // return true if standing on something
|
||
|
virtual void OnLeaveGround( CBaseEntity *ground ); // invoked when bot leaves ground for any reason
|
||
|
virtual void OnLandOnGround( CBaseEntity *ground ); // invoked when bot lands on the ground after being in the air
|
||
|
virtual CBaseEntity *GetGround( void ) const; // return the current ground entity or NULL if not on the ground
|
||
|
virtual const Vector &GetGroundNormal( void ) const;// surface normal of the ground we are in contact with
|
||
|
|
||
|
virtual void ClimbLadder( const CNavLadder *ladder, const CNavArea *dismountGoal ); // climb the given ladder to the top and dismount
|
||
|
virtual void DescendLadder( const CNavLadder *ladder, const CNavArea *dismountGoal ); // descend the given ladder to the bottom and dismount
|
||
|
virtual bool IsUsingLadder( void ) const;
|
||
|
virtual bool IsAscendingOrDescendingLadder( void ) const; // we are actually on the ladder right now, either climbing up or down
|
||
|
|
||
|
virtual void FaceTowards( const Vector &target ); // rotate body to face towards "target"
|
||
|
|
||
|
virtual void SetDesiredLean( const QAngle &lean );
|
||
|
virtual const QAngle &GetDesiredLean( void ) const;
|
||
|
|
||
|
virtual const Vector &GetFeet( void ) const; // return position of "feet" - the driving point where the bot contacts the ground
|
||
|
|
||
|
virtual float GetStepHeight( void ) const; // if delta Z is greater than this, we have to jump to get up
|
||
|
virtual float GetMaxJumpHeight( void ) const; // return maximum height of a jump
|
||
|
virtual float GetDeathDropHeight( void ) const; // distance at which we will die if we fall
|
||
|
|
||
|
virtual float GetRunSpeed( void ) const; // get maximum running speed
|
||
|
virtual float GetWalkSpeed( void ) const; // get maximum walking speed
|
||
|
|
||
|
virtual float GetMaxAcceleration( void ) const; // return maximum acceleration of locomotor
|
||
|
virtual float GetMaxDeceleration( void ) const; // return maximum deceleration of locomotor
|
||
|
|
||
|
virtual const Vector &GetAcceleration( void ) const; // return current world space acceleration
|
||
|
virtual void SetAcceleration( const Vector &accel ); // set world space acceleration
|
||
|
|
||
|
virtual const Vector &GetVelocity( void ) const; // return current world space velocity
|
||
|
virtual void SetVelocity( const Vector &vel ); // set world space velocity
|
||
|
|
||
|
virtual void OnMoveToSuccess( const Path *path ); // invoked when an bot reaches its MoveTo goal
|
||
|
virtual void OnMoveToFailure( const Path *path, MoveToFailureType reason ); // invoked when an bot fails to reach a MoveTo goal
|
||
|
|
||
|
private:
|
||
|
void UpdatePosition( const Vector &newPos ); // move to newPos, resolving any collisions along the way
|
||
|
void UpdateGroundConstraint( void ); // keep ground solid
|
||
|
Vector ResolveCollisionV0( Vector from, Vector to, int recursionLimit );
|
||
|
|
||
|
Vector ResolveZombieCollisions( const Vector &pos ); // push away zombies that are interpenetrating
|
||
|
Vector ResolveCollision( const Vector &from, const Vector &to, int recursionLimit ); // check for collisions along move
|
||
|
bool DetectCollision( trace_t *pTrace, int &nDestructionAllowed, const Vector &from, const Vector &to, const Vector &vecMins, const Vector &vecMaxs );
|
||
|
void ApplyAccumulatedApproach( void );
|
||
|
bool DidJustJump( void ) const; // return true if we just started a jump
|
||
|
bool TraverseLadder( void ); // return true if we are climbing a ladder
|
||
|
|
||
|
virtual float GetGravity( void ) const; // return gravity force acting on bot
|
||
|
virtual float GetFrictionForward( void ) const; // return magnitude of forward friction
|
||
|
virtual float GetFrictionSideways( void ) const; // return magnitude of lateral friction
|
||
|
virtual float GetMaxYawRate( void ) const; // return max rate of yaw rotation
|
||
|
|
||
|
|
||
|
private:
|
||
|
NextBotCombatCharacter *m_nextBot;
|
||
|
|
||
|
Vector m_priorPos; // last update's position
|
||
|
Vector m_lastValidPos; // last valid position (not interpenetrating)
|
||
|
|
||
|
Vector m_acceleration;
|
||
|
Vector m_velocity;
|
||
|
|
||
|
float m_desiredSpeed; // speed bot wants to be moving
|
||
|
float m_actualSpeed; // actual speed bot is moving
|
||
|
|
||
|
float m_maxRunSpeed;
|
||
|
|
||
|
float m_forwardLean;
|
||
|
float m_sideLean;
|
||
|
QAngle m_desiredLean;
|
||
|
|
||
|
bool m_isJumping; // if true, we have jumped and have not yet hit the ground
|
||
|
bool m_isJumpingAcrossGap; // if true, we have jumped across a gap and have not yet hit the ground
|
||
|
EHANDLE m_ground; // have to manage this ourselves, since MOVETYPE_CUSTOM always NULLs out GetGroundEntity()
|
||
|
Vector m_groundNormal; // surface normal of the ground we are in contact with
|
||
|
bool m_isClimbingUpToLedge; // true if we are jumping up to an adjacent ledge
|
||
|
Vector m_ledgeJumpGoalPos;
|
||
|
bool m_isUsingFullFeetTrace; // true if we're in the air and tracing the lowest StepHeight in ResolveCollision
|
||
|
|
||
|
const CNavLadder *m_ladder; // ladder we are currently climbing/descending
|
||
|
const CNavArea *m_ladderDismountGoal; // the area we enter when finished with our ladder move
|
||
|
bool m_isGoingUpLadder; // if false, we're going down
|
||
|
|
||
|
CountdownTimer m_inhibitObstacleAvoidanceTimer; // when active, turn off path following feelers
|
||
|
|
||
|
CountdownTimer m_wiggleTimer; // for wiggling
|
||
|
NavRelativeDirType m_wiggleDirection;
|
||
|
|
||
|
mutable Vector m_eyePos; // for use with GetEyes(), etc.
|
||
|
|
||
|
Vector m_moveVector; // the direction of our motion in XY plane
|
||
|
float m_moveYaw; // global yaw of movement direction
|
||
|
|
||
|
Vector m_accumApproachVectors; // weighted sum of Approach() calls since last update
|
||
|
float m_accumApproachWeights;
|
||
|
bool m_bRecomputePostureOnCollision;
|
||
|
|
||
|
CountdownTimer m_ignorePhysicsPropTimer; // if active, don't collide with physics props (because we got stuck in one)
|
||
|
EHANDLE m_ignorePhysicsProp; // which prop to ignore
|
||
|
};
|
||
|
|
||
|
|
||
|
inline float NextBotGroundLocomotion::GetGravity( void ) const
|
||
|
{
|
||
|
return 1000.0f;
|
||
|
}
|
||
|
|
||
|
inline float NextBotGroundLocomotion::GetFrictionForward( void ) const
|
||
|
{
|
||
|
return 0.0f;
|
||
|
}
|
||
|
|
||
|
inline float NextBotGroundLocomotion::GetFrictionSideways( void ) const
|
||
|
{
|
||
|
return 3.0f;
|
||
|
}
|
||
|
|
||
|
inline float NextBotGroundLocomotion::GetMaxYawRate( void ) const
|
||
|
{
|
||
|
return 250.0f;
|
||
|
}
|
||
|
|
||
|
inline CBaseEntity *NextBotGroundLocomotion::GetGround( void ) const
|
||
|
{
|
||
|
return m_ground;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline const Vector &NextBotGroundLocomotion::GetGroundNormal( void ) const
|
||
|
{
|
||
|
return m_groundNormal;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline void NextBotGroundLocomotion::SetDesiredLean( const QAngle &lean )
|
||
|
{
|
||
|
m_desiredLean = lean;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline const QAngle &NextBotGroundLocomotion::GetDesiredLean( void ) const
|
||
|
{
|
||
|
return m_desiredLean;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline void NextBotGroundLocomotion::SetDesiredSpeed( float speed )
|
||
|
{
|
||
|
m_desiredSpeed = speed;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline float NextBotGroundLocomotion::GetDesiredSpeed( void ) const
|
||
|
{
|
||
|
return m_desiredSpeed;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline bool NextBotGroundLocomotion::IsClimbingOrJumping( void ) const
|
||
|
{
|
||
|
return m_isJumping;
|
||
|
}
|
||
|
|
||
|
inline bool NextBotGroundLocomotion::IsClimbingUpToLedge( void ) const
|
||
|
{
|
||
|
return m_isClimbingUpToLedge;
|
||
|
}
|
||
|
|
||
|
inline bool NextBotGroundLocomotion::IsJumpingAcrossGap( void ) const
|
||
|
{
|
||
|
return m_isJumpingAcrossGap;
|
||
|
}
|
||
|
|
||
|
inline bool NextBotGroundLocomotion::IsRunning( void ) const
|
||
|
{
|
||
|
/// @todo Rethink interface to distinguish actual state vs desired state (do we want to be running, or are we actually at running speed right now)
|
||
|
return m_actualSpeed > 0.9f * GetRunSpeed();
|
||
|
}
|
||
|
|
||
|
|
||
|
inline float NextBotGroundLocomotion::GetStepHeight( void ) const
|
||
|
{
|
||
|
return 18.0f;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline float NextBotGroundLocomotion::GetMaxJumpHeight( void ) const
|
||
|
{
|
||
|
return 180.0f; // 120.0f; // 84.0f; // 58.0f;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline float NextBotGroundLocomotion::GetDeathDropHeight( void ) const
|
||
|
{
|
||
|
return 200.0f;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline float NextBotGroundLocomotion::GetRunSpeed( void ) const
|
||
|
{
|
||
|
return 150.0f;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline float NextBotGroundLocomotion::GetWalkSpeed( void ) const
|
||
|
{
|
||
|
return 75.0f;
|
||
|
}
|
||
|
|
||
|
inline float NextBotGroundLocomotion::GetMaxAcceleration( void ) const
|
||
|
{
|
||
|
return 500.0f;
|
||
|
}
|
||
|
|
||
|
inline float NextBotGroundLocomotion::GetMaxDeceleration( void ) const
|
||
|
{
|
||
|
return 500.0f;
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif // NEXT_BOT_GROUND_LOCOMOTION_H
|
||
|
|