mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2025-09-19 20:16:10 +08:00
Added original SDK code for Alien Swarm.
This commit is contained in:
382
game/server/ai_basenpc_physicsflyer.cpp
Normal file
382
game/server/ai_basenpc_physicsflyer.cpp
Normal file
@ -0,0 +1,382 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Base class for many flying NPCs
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "ai_basenpc_physicsflyer.h"
|
||||
#include "ai_route.h"
|
||||
#include "ai_navigator.h"
|
||||
#include "ai_motor.h"
|
||||
#include "physics_saverestore.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
BEGIN_DATADESC( CAI_BasePhysicsFlyingBot )
|
||||
|
||||
DEFINE_FIELD( m_vCurrentVelocity, FIELD_VECTOR),
|
||||
DEFINE_FIELD( m_vCurrentBanking, FIELD_VECTOR),
|
||||
DEFINE_FIELD( m_vNoiseMod, FIELD_VECTOR),
|
||||
DEFINE_FIELD( m_fHeadYaw, FIELD_FLOAT),
|
||||
DEFINE_FIELD( m_vLastPatrolDir, FIELD_VECTOR),
|
||||
|
||||
DEFINE_PHYSPTR( m_pMotionController ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Override to return correct velocity
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
void CAI_BasePhysicsFlyingBot::GetVelocity(Vector *vVelocity, AngularImpulse *vAngVelocity)
|
||||
{
|
||||
Assert( GetMoveType() == MOVETYPE_VPHYSICS );
|
||||
if ( VPhysicsGetObject() )
|
||||
{
|
||||
VPhysicsGetObject()->GetVelocity( vVelocity, vAngVelocity );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( vVelocity )
|
||||
{
|
||||
vVelocity->Init();
|
||||
}
|
||||
if ( vAngVelocity )
|
||||
{
|
||||
vAngVelocity->Init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Turn head yaw into facing direction
|
||||
// Input :
|
||||
// Output :
|
||||
//-----------------------------------------------------------------------------
|
||||
QAngle CAI_BasePhysicsFlyingBot::BodyAngles()
|
||||
{
|
||||
return QAngle(0,m_fHeadYaw,0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input :
|
||||
// Output :
|
||||
//-----------------------------------------------------------------------------
|
||||
void CAI_BasePhysicsFlyingBot::TurnHeadToTarget(float flInterval, const Vector &MoveTarget )
|
||||
{
|
||||
float desYaw = UTIL_AngleDiff(VecToYaw(MoveTarget - GetLocalOrigin()), 0 );
|
||||
|
||||
m_fHeadYaw = desYaw;
|
||||
|
||||
return;
|
||||
|
||||
// If I've flipped completely around, reverse angles
|
||||
float fYawDiff = m_fHeadYaw - desYaw;
|
||||
if (fYawDiff > 180)
|
||||
{
|
||||
m_fHeadYaw -= 360;
|
||||
}
|
||||
else if (fYawDiff < -180)
|
||||
{
|
||||
m_fHeadYaw += 360;
|
||||
}
|
||||
|
||||
// RIGHT NOW, this affects every flying bot. This rate should be member data that individuals
|
||||
// can manipulate. THIS change for MANHACKS E3 2003 (sjb)
|
||||
float iRate = 0.8;
|
||||
|
||||
// Make frame rate independent
|
||||
float timeToUse = flInterval;
|
||||
while (timeToUse > 0)
|
||||
{
|
||||
m_fHeadYaw = (iRate * m_fHeadYaw) + (1-iRate)*desYaw;
|
||||
timeToUse -= 0.1;
|
||||
}
|
||||
|
||||
while( m_fHeadYaw > 360 )
|
||||
{
|
||||
m_fHeadYaw -= 360.0f;
|
||||
}
|
||||
|
||||
while( m_fHeadYaw < 0 )
|
||||
{
|
||||
m_fHeadYaw += 360.f;
|
||||
}
|
||||
|
||||
// SetBoneController( 0, m_fHeadYaw );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
float CAI_BasePhysicsFlyingBot::MinGroundDist(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
Vector CAI_BasePhysicsFlyingBot::VelocityToAvoidObstacles(float flInterval)
|
||||
{
|
||||
// --------------------------------
|
||||
// Avoid banging into stuff
|
||||
// --------------------------------
|
||||
trace_t tr;
|
||||
Vector vTravelDir = m_vCurrentVelocity*flInterval;
|
||||
Vector endPos = GetAbsOrigin() + vTravelDir;
|
||||
AI_TraceEntity( this, GetAbsOrigin(), endPos, GetAITraceMask()|CONTENTS_WATER, &tr);
|
||||
if (tr.fraction != 1.0)
|
||||
{
|
||||
// Bounce off in normal
|
||||
Vector vBounce = tr.plane.normal * 0.5 * m_vCurrentVelocity.Length();
|
||||
return (vBounce);
|
||||
}
|
||||
|
||||
// --------------------------------
|
||||
// Try to remain above the ground.
|
||||
// --------------------------------
|
||||
float flMinGroundDist = MinGroundDist();
|
||||
AI_TraceLine(GetAbsOrigin(), GetAbsOrigin() + Vector(0, 0, -flMinGroundDist),
|
||||
GetAITraceMask_BrushOnly()|CONTENTS_WATER, this, COLLISION_GROUP_NONE, &tr);
|
||||
if (tr.fraction < 1)
|
||||
{
|
||||
// Clamp veloctiy
|
||||
if (tr.fraction < 0.1)
|
||||
{
|
||||
tr.fraction = 0.1;
|
||||
}
|
||||
|
||||
return Vector(0, 0, 50/tr.fraction);
|
||||
}
|
||||
return vec3_origin;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
void CAI_BasePhysicsFlyingBot::StartTask( const Task_t *pTask )
|
||||
{
|
||||
switch (pTask->iTask)
|
||||
{
|
||||
// Skip as done via bone controller
|
||||
case TASK_FACE_ENEMY:
|
||||
{
|
||||
TaskComplete();
|
||||
break;
|
||||
}
|
||||
// Activity is just idle (have no run)
|
||||
case TASK_RUN_PATH:
|
||||
{
|
||||
GetNavigator()->SetMovementActivity(ACT_IDLE);
|
||||
TaskComplete();
|
||||
break;
|
||||
}
|
||||
// Don't check for run/walk activity
|
||||
case TASK_SCRIPT_RUN_TO_TARGET:
|
||||
case TASK_SCRIPT_WALK_TO_TARGET:
|
||||
{
|
||||
if (GetTarget() == NULL)
|
||||
{
|
||||
TaskFail(FAIL_NO_TARGET);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!GetNavigator()->SetGoal( GOALTYPE_TARGETENT ) )
|
||||
{
|
||||
TaskFail(FAIL_NO_ROUTE);
|
||||
GetNavigator()->ClearGoal();
|
||||
}
|
||||
}
|
||||
TaskComplete();
|
||||
break;
|
||||
}
|
||||
// Override to get more to get a directional path
|
||||
case TASK_GET_PATH_TO_RANDOM_NODE:
|
||||
{
|
||||
if ( GetNavigator()->SetRandomGoal( pTask->flTaskData, m_vLastPatrolDir ) )
|
||||
TaskComplete();
|
||||
else
|
||||
TaskFail(FAIL_NO_REACHABLE_NODE);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
BaseClass::StartTask(pTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void CAI_BasePhysicsFlyingBot::MoveToTarget(float flInterval, const Vector &MoveTarget)
|
||||
{
|
||||
Assert(0); // This must be overridden in the leaf classes
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
AI_NavPathProgress_t CAI_BasePhysicsFlyingBot::ProgressFlyPath(
|
||||
float flInterval,
|
||||
const CBaseEntity *pNewTarget,
|
||||
unsigned collisionMask,
|
||||
bool bNewTrySimplify,
|
||||
float strictPointTolerance)
|
||||
{
|
||||
AI_ProgressFlyPathParams_t params( collisionMask );
|
||||
params.strictPointTolerance = strictPointTolerance;
|
||||
params.SetCurrent( pNewTarget, bNewTrySimplify );
|
||||
|
||||
AI_NavPathProgress_t progress = GetNavigator()->ProgressFlyPath( params );
|
||||
|
||||
switch ( progress )
|
||||
{
|
||||
case AINPP_NO_CHANGE:
|
||||
case AINPP_ADVANCED:
|
||||
{
|
||||
MoveToTarget(flInterval, GetNavigator()->GetCurWaypointPos());
|
||||
break;
|
||||
}
|
||||
|
||||
case AINPP_COMPLETE:
|
||||
{
|
||||
TaskMovementComplete();
|
||||
break;
|
||||
}
|
||||
|
||||
case AINPP_BLOCKED: // function is not supposed to test blocking, just simple path progression
|
||||
default:
|
||||
{
|
||||
AssertMsg( 0, ( "Unexpected result" ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
CAI_BasePhysicsFlyingBot::CAI_BasePhysicsFlyingBot()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
m_vCurrentVelocity.Init();
|
||||
m_vCurrentBanking.Init();
|
||||
m_vLastPatrolDir.Init();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
CAI_BasePhysicsFlyingBot::~CAI_BasePhysicsFlyingBot( void )
|
||||
{
|
||||
physenv->DestroyMotionController( m_pMotionController );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_BasePhysicsFlyingBot::CreateVPhysics( void )
|
||||
{
|
||||
// Create the object in the physics system
|
||||
IPhysicsObject *pPhysicsObject = VPhysicsInitNormal( SOLID_BBOX, FSOLID_NOT_STANDABLE, false );
|
||||
|
||||
m_pMotionController = physenv->CreateMotionController( this );
|
||||
m_pMotionController->AttachObject( pPhysicsObject, true );
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pTarget -
|
||||
// &chasePosition -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CAI_BasePhysicsFlyingBot::TranslateNavGoal( CBaseEntity *pTarget, Vector &chasePosition )
|
||||
{
|
||||
Assert( pTarget != NULL );
|
||||
|
||||
if ( pTarget == NULL )
|
||||
{
|
||||
chasePosition = vec3_origin;
|
||||
return;
|
||||
}
|
||||
|
||||
// Chase their eyes
|
||||
chasePosition = pTarget->GetAbsOrigin() + pTarget->GetViewOffset();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pController -
|
||||
// *pObject -
|
||||
// deltaTime -
|
||||
// &linear -
|
||||
// &angular -
|
||||
// Output : IMotionEvent::simresult_e
|
||||
//-----------------------------------------------------------------------------
|
||||
IMotionEvent::simresult_e CAI_BasePhysicsFlyingBot::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular )
|
||||
{
|
||||
static int count;
|
||||
|
||||
IPhysicsObject *pPhysicsObject = VPhysicsGetObject();
|
||||
// Assert( pPhysicsObject );
|
||||
if (!pPhysicsObject)
|
||||
return SIM_NOTHING;
|
||||
|
||||
// move
|
||||
Vector actualVelocity;
|
||||
AngularImpulse actualAngularVelocity;
|
||||
pPhysicsObject->GetVelocity( &actualVelocity, &actualAngularVelocity );
|
||||
linear = (m_vCurrentVelocity - actualVelocity) * (0.1 / deltaTime) * 10.0;
|
||||
|
||||
/*
|
||||
DevMsg("Sim %d : %5.1f %5.1f %5.1f\n", count++,
|
||||
m_vCurrentVelocity.x - actualVelocity.x,
|
||||
m_vCurrentVelocity.y - actualVelocity.y,
|
||||
m_vCurrentVelocity.z - actualVelocity.z );
|
||||
*/
|
||||
|
||||
// do angles.
|
||||
Vector actualPosition;
|
||||
QAngle actualAngles;
|
||||
pPhysicsObject->GetPosition( &actualPosition, &actualAngles );
|
||||
|
||||
// FIXME: banking currently disabled, forces simple upright posture
|
||||
angular.x = (UTIL_AngleDiff( m_vCurrentBanking.z, actualAngles.z ) - actualAngularVelocity.x) * (1 / deltaTime);
|
||||
angular.y = (UTIL_AngleDiff( m_vCurrentBanking.x, actualAngles.x ) - actualAngularVelocity.y) * (1 / deltaTime);
|
||||
|
||||
// turn toward target
|
||||
angular.z = UTIL_AngleDiff( m_fHeadYaw, actualAngles.y + actualAngularVelocity.z * 0.1 ) * (1 / deltaTime);
|
||||
|
||||
// angular = m_vCurrentAngularVelocity - actualAngularVelocity;
|
||||
|
||||
// DevMsg("Sim %d : %.1f %.1f %.1f (%.1f)\n", count++, actualAngles.x, actualAngles.y, actualAngles.z, m_fHeadYaw );
|
||||
|
||||
// FIXME: remove the stuff from MoveExecute();
|
||||
// FIXME: check MOVE?
|
||||
|
||||
ClampMotorForces( linear, angular );
|
||||
|
||||
return SIM_GLOBAL_ACCELERATION; // on my local axis. SIM_GLOBAL_ACCELERATION
|
||||
}
|
||||
|
Reference in New Issue
Block a user