mirror of
https://github.com/celisej567/source-sdk-2013.git
synced 2026-09-23 20:09:45 +03:00
Added new NPC climbing activities and improved climbing navigation AI
This commit is contained in:
@@ -235,18 +235,47 @@ void CAI_Motor::MoveClimbStart( const Vector &climbDest, const Vector &climbDir
|
||||
// > code are not reciprocal for all state, and furthermore, stomp
|
||||
// > other state?
|
||||
|
||||
bool bGoingUp = (climbDir.z > 0.01);
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
if ( bGoingUp && GetOuter()->HaveSequenceForActivity( ACT_CLIMB_MOUNT_BOTTOM ) )
|
||||
{
|
||||
SetActivity( ACT_CLIMB_MOUNT_BOTTOM );
|
||||
|
||||
// Steal m_vecDismount for this
|
||||
GetOuter()->GetSequenceLinearMotion( GetSequence(), &m_vecDismount );
|
||||
GetOuter()->SetCycle( GetOuter()->GetMovementFrame( m_vecDismount.z - climbDist ) );
|
||||
}
|
||||
else if ( !bGoingUp && GetOuter()->HaveSequenceForActivity( ACT_CLIMB_MOUNT_TOP ) )
|
||||
{
|
||||
SetActivity( ACT_CLIMB_MOUNT_TOP );
|
||||
|
||||
// Steal m_vecDismount for this
|
||||
GetOuter()->GetSequenceLinearMotion( GetSequence(), &m_vecDismount );
|
||||
GetOuter()->SetCycle( GetOuter()->GetMovementFrame( m_vecDismount.z - climbDist ) );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if ( fabsf( climbDir.z ) < .1 )
|
||||
{
|
||||
SetActivity( GetNavigator()->GetMovementActivity() );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetActivity( (climbDir.z > -0.01 ) ? ACT_CLIMB_UP : ACT_CLIMB_DOWN );
|
||||
SetActivity( bGoingUp ? ACT_CLIMB_UP : ACT_CLIMB_DOWN );
|
||||
}
|
||||
|
||||
m_nDismountSequence = SelectWeightedSequence( ACT_CLIMB_DISMOUNT );
|
||||
if (m_nDismountSequence != ACT_INVALID)
|
||||
{
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
if ( !bGoingUp )
|
||||
{
|
||||
int nBottomDismount = SelectWeightedSequence( ACT_CLIMB_DISMOUNT_BOTTOM );
|
||||
if (nBottomDismount != ACTIVITY_NOT_AVAILABLE)
|
||||
m_nDismountSequence = nBottomDismount;
|
||||
}
|
||||
#endif
|
||||
|
||||
GetOuter()->GetSequenceLinearMotion( m_nDismountSequence, &m_vecDismount );
|
||||
}
|
||||
else
|
||||
@@ -262,6 +291,76 @@ void CAI_Motor::MoveClimbStart( const Vector &climbDest, const Vector &climbDir
|
||||
|
||||
AIMoveResult_t CAI_Motor::MoveClimbExecute( const Vector &climbDest, const Vector &climbDir, float climbDist, float yaw, int climbNodesLeft )
|
||||
{
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
if ( (GetActivity() == ACT_CLIMB_MOUNT_TOP || GetActivity() == ACT_CLIMB_MOUNT_BOTTOM) )
|
||||
{
|
||||
if (!GetOuter()->IsActivityFinished())
|
||||
{
|
||||
// Wait for the mounting to finish
|
||||
SetGroundEntity( NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fix up our position if we have to
|
||||
Vector vecTeleportOrigin;
|
||||
if (MoveClimbShouldTeleportToSequenceEnd( vecTeleportOrigin ))
|
||||
{
|
||||
SetLocalOrigin( vecTeleportOrigin );
|
||||
}
|
||||
|
||||
// Reset activity and start from the beginning
|
||||
GetOuter()->ResetActivity();
|
||||
return MoveClimbExecute( climbDest, climbDir, climbDist, yaw, climbNodesLeft );
|
||||
}
|
||||
}
|
||||
else if ( fabsf( climbDir.z ) > .1 && (GetActivity() != ACT_CLIMB_DISMOUNT && GetActivity() != ACT_CLIMB_DISMOUNT_BOTTOM) )
|
||||
{
|
||||
bool bGoingUp = (climbDir.z > -0.01);
|
||||
if ( GetOuter()->HaveSequenceForActivity( ACT_CLIMB_ALL ) )
|
||||
{
|
||||
SetActivity( ACT_CLIMB_ALL );
|
||||
|
||||
// TODO: Use UTIL_VecToPitch() instead if move_yaw becomes a true climb yaw and not just an up-down scalar
|
||||
SetPoseParameter( GetOuter()->LookupPoseMoveYaw(), climbDir.z < 0 ? 180.0 : -180.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
Activity desiredActivity = bGoingUp ? ACT_CLIMB_UP : ACT_CLIMB_DOWN;
|
||||
if ( GetActivity() != desiredActivity )
|
||||
{
|
||||
SetActivity( desiredActivity );
|
||||
}
|
||||
}
|
||||
|
||||
if (m_nDismountSequence != ACT_INVALID)
|
||||
{
|
||||
if (climbNodesLeft <= 2 && climbDist < fabs( m_vecDismount.z ))
|
||||
{
|
||||
if (bGoingUp)
|
||||
{
|
||||
// fixme: No other way to force m_nIdealSequence?
|
||||
GetOuter()->SetActivity( ACT_CLIMB_DISMOUNT );
|
||||
GetOuter()->SetCycle( GetOuter()->GetMovementFrame( m_vecDismount.z - climbDist ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetSequence() != m_nDismountSequence && GetOuter()->GetSequenceActivity( m_nDismountSequence ) == ACT_CLIMB_DISMOUNT_BOTTOM)
|
||||
{
|
||||
SetActivity( ACT_CLIMB_DISMOUNT_BOTTOM );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( climbDir.Length() == 0 && GetOuter()->GetInstantaneousVelocity() <= 0.01 )
|
||||
{
|
||||
// The NPC is somehow stuck climbing with no direction or movement.
|
||||
// This can be caused by NPCs getting stuck in each other and/or being moved away from the ladder.
|
||||
// In these cases, the NPC has to be made unstuck, or else they may remain in an immobile climbing state forever.
|
||||
Warning( "%s had to abort climbing due to no direction or movement\n", GetOuter()->GetDebugName() );
|
||||
return AIMR_ILLEGAL;
|
||||
}
|
||||
#else
|
||||
if ( fabsf( climbDir.z ) > .1 )
|
||||
{
|
||||
if ( GetActivity() != ACT_CLIMB_DISMOUNT )
|
||||
@@ -292,13 +391,34 @@ AIMoveResult_t CAI_Motor::MoveClimbExecute( const Vector &climbDest, const Vecto
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
float climbSpeed = GetOuter()->GetInstantaneousVelocity();
|
||||
|
||||
if (m_nDismountSequence != ACT_INVALID)
|
||||
{
|
||||
// catch situations where the climb mount/dismount finished before reaching goal
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
if ((GetActivity() == ACT_CLIMB_DISMOUNT || GetActivity() == ACT_CLIMB_DISMOUNT_BOTTOM))
|
||||
{
|
||||
SetGroundEntity( NULL );
|
||||
|
||||
if (GetOuter()->IsActivityFinished())
|
||||
{
|
||||
// Fix up our position if we have to
|
||||
Vector vecTeleportOrigin;
|
||||
if (MoveClimbShouldTeleportToSequenceEnd( vecTeleportOrigin ))
|
||||
{
|
||||
// Just force it to complete
|
||||
climbDist = 0.0f;
|
||||
}
|
||||
|
||||
climbSpeed = 200.0f;
|
||||
}
|
||||
}
|
||||
#else
|
||||
climbSpeed = MAX( climbSpeed, 30.0 );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -314,7 +434,7 @@ AIMoveResult_t CAI_Motor::MoveClimbExecute( const Vector &climbDest, const Vecto
|
||||
climbDist = 0;
|
||||
|
||||
const float climbTime = climbDist / climbSpeed;
|
||||
|
||||
|
||||
SetMoveInterval( GetMoveInterval() - climbTime );
|
||||
SetLocalOrigin( climbDest );
|
||||
|
||||
@@ -340,11 +460,63 @@ void CAI_Motor::MoveClimbStop()
|
||||
else
|
||||
SetActivity( ACT_IDLE );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Unlock desired weapon state so NPCs can unholster their weapons again.
|
||||
GetOuter()->SetDesiredWeaponState( DESIREDWEAPONSTATE_IGNORE );
|
||||
|
||||
// Unlock yaw
|
||||
// TODO: Add yaw locking for when climbing is paused
|
||||
//SetYawLocked( false );
|
||||
#endif
|
||||
|
||||
GetOuter()->RemoveFlag( FL_FLY );
|
||||
SetSmoothedVelocity( vec3_origin );
|
||||
SetGravity( 1.0 );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
void CAI_Motor::MoveClimbPause()
|
||||
{
|
||||
if (GetActivity() != ACT_CLIMB_DISMOUNT
|
||||
#ifdef EXPANDED_NAVIGATION_ACTIVITIES
|
||||
&& GetActivity() != ACT_CLIMB_MOUNT_TOP && GetActivity() != ACT_CLIMB_MOUNT_BOTTOM
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if ( GetActivity() == ACT_CLIMB_ALL )
|
||||
{
|
||||
SetPoseParameter( GetOuter()->LookupPoseMoveYaw(), 0.0f );
|
||||
}
|
||||
|
||||
SetSmoothedVelocity( vec3_origin );
|
||||
}
|
||||
else
|
||||
{
|
||||
// If already dismounting, do nothing
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This is part of a hack needed in cases where ladder mount/dismount animations collide with the world and don't move properly.
|
||||
// It's based off of the same code as scripted_sequence's teleportation fixup, although this function only resolves the bone origin and
|
||||
// returns whether or not teleportation is necessary, as the teleportation is achieved in different ways for different uses of this code.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_Motor::MoveClimbShouldTeleportToSequenceEnd( Vector &teleportOrigin )
|
||||
{
|
||||
QAngle new_angle;
|
||||
GetOuter()->GetBonePosition( 0, teleportOrigin, new_angle );
|
||||
|
||||
// Ensure that there is actually a distance needed to teleport there
|
||||
if ((GetLocalOrigin() - teleportOrigin).Length2DSqr() > Square( 8.0 ))
|
||||
{
|
||||
teleportOrigin.z = GetLocalOrigin().z;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Motion for jumping
|
||||
// Input :
|
||||
|
||||
Reference in New Issue
Block a user