mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-01-12 23:07:55 +03:00
Added AI hint radius from the Alien Swarm SDK as well as an all-new "hint weight" keyvalue
This commit is contained in:
parent
ece1a612ce
commit
847db9c3e3
@ -35,6 +35,10 @@ CHintCriteria::CHintCriteria( void )
|
||||
m_strGroup = NULL_STRING;
|
||||
m_iFlags = 0;
|
||||
m_HintTypes.Purge();
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
m_pfnFilter = NULL;
|
||||
m_pFilterContext = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1117,10 +1121,10 @@ void CAI_Hint::NPCHandleStartNav( CAI_BaseNPC *pNPC, bool bDefaultFacing )
|
||||
|
||||
HintIgnoreFacing_t facing = GetIgnoreFacing();
|
||||
if (facing == HIF_DEFAULT)
|
||||
facing = bDefaultFacing ? HIF_YES : HIF_NO;
|
||||
facing = bDefaultFacing ? HIF_NO : HIF_YES;
|
||||
|
||||
if (facing == HIF_YES)
|
||||
pNPC->GetNavigator()->SetArrivalDirection(GetDirection());
|
||||
if (facing == HIF_NO)
|
||||
pNPC->GetNavigator()->SetArrivalDirection( GetDirection() );
|
||||
|
||||
if (HintActivityName() != NULL_STRING)
|
||||
{
|
||||
@ -1139,6 +1143,51 @@ void CAI_Hint::NPCHandleStartNav( CAI_BaseNPC *pNPC, bool bDefaultFacing )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns true if this hint should override a NPC's yaw even during regular AI.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_Hint::OverridesNPCYaw( CAI_BaseNPC *pNPC )
|
||||
{
|
||||
switch (HintType())
|
||||
{
|
||||
case HINT_TACTICAL_COVER_CUSTOM:
|
||||
case HINT_TACTICAL_COVER_MED:
|
||||
case HINT_TACTICAL_COVER_LOW:
|
||||
{
|
||||
if (pNPC->HasMemory( bits_MEMORY_INCOVER ))
|
||||
{
|
||||
// By default, don't override yaw on cover nodes unless they use custom activities.
|
||||
HintIgnoreFacing_t facing = GetIgnoreFacing();
|
||||
if (facing == HIF_DEFAULT)
|
||||
return ( HintActivityName() != NULL_STRING );
|
||||
|
||||
return facing == HIF_NO;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case HINT_PLAYER_ALLY_MOVE_AWAY_DEST:
|
||||
{
|
||||
Vector vHintPos;
|
||||
GetPosition( pNPC, &vHintPos );
|
||||
if (VectorsAreEqual( vHintPos, pNPC->GetAbsOrigin(), 0.1f ))
|
||||
{
|
||||
// By default, don't override yaw on move away destinations unless they use custom activities.
|
||||
HintIgnoreFacing_t facing = GetIgnoreFacing();
|
||||
if (facing == HIF_DEFAULT)
|
||||
return ( HintActivityName() != NULL_STRING );
|
||||
|
||||
return facing == HIF_NO;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1258,6 +1307,30 @@ bool CAI_Hint::HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hint
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Test against generic filter
|
||||
// (From Alien Swarm SDK)
|
||||
if ( !hintCriteria.PassesFilter( this ) )
|
||||
{
|
||||
REPORTFAILURE( "Failed filter test" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// (From Alien Swarm SDK)
|
||||
int nRadius = GetRadius();
|
||||
if ( nRadius != 0 )
|
||||
{
|
||||
// Calculate our distance
|
||||
float distance = (GetAbsOrigin() - position).LengthSqr();
|
||||
|
||||
if ( distance > nRadius * nRadius )
|
||||
{
|
||||
REPORTFAILURE( "NPC is not within the node's radius." );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( hintCriteria.HasFlag(bits_HINT_NPC_IN_NODE_FOV) )
|
||||
{
|
||||
if ( pNPC == NULL )
|
||||
@ -1377,10 +1450,18 @@ bool CAI_Hint::HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hint
|
||||
{
|
||||
trace_t tr;
|
||||
// Can my bounding box fit there?
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
Vector vStep( 0, 0, pNPC->StepHeight() );
|
||||
AI_TraceHull ( GetAbsOrigin() + vStep, GetAbsOrigin(), pNPC->WorldAlignMins(), pNPC->WorldAlignMaxs() - vStep,
|
||||
MASK_SOLID, pNPC, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
if ( tr.fraction < 0.95 )
|
||||
#else
|
||||
AI_TraceHull ( GetAbsOrigin(), GetAbsOrigin(), pNPC->WorldAlignMins(), pNPC->WorldAlignMaxs(),
|
||||
MASK_SOLID, pNPC, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
if ( tr.fraction != 1.0 )
|
||||
#endif
|
||||
{
|
||||
REPORTFAILURE( "Node isn't clear." );
|
||||
return false;
|
||||
@ -1396,6 +1477,15 @@ bool CAI_Hint::HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hint
|
||||
// Calculate our distance
|
||||
float distance = (GetAbsOrigin() - position).Length();
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Divide by hint weight
|
||||
float flWeight = GetHintWeight();
|
||||
if ( flWeight != 1.0f )
|
||||
{
|
||||
distance *= GetHintWeightInverse();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Must be closer than the current best
|
||||
if ( distance > *flNearestDistance )
|
||||
{
|
||||
@ -1576,6 +1666,14 @@ void CAI_Hint::OnRestore()
|
||||
m_NodeData.nNodeID = g_pAINetworkManager->GetEditOps()->GetNodeIdFromWCId( m_NodeData.nWCNodeID );
|
||||
FixupTargetNode();
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_NodeData.flWeight != 0.0f && m_NodeData.flWeight != 1.0f)
|
||||
{
|
||||
// Re-invert the weight
|
||||
m_NodeData.flWeightInverse = 1.0f / m_NodeData.flWeight;
|
||||
}
|
||||
#endif
|
||||
|
||||
CAI_Node *pNode = GetNode();
|
||||
|
||||
if ( !pNode )
|
||||
@ -1751,6 +1849,11 @@ void CC_ai_drop_hint( const CCommand &args )
|
||||
nodeData.fIgnoreFacing = HIF_DEFAULT;
|
||||
nodeData.minState = NPC_STATE_IDLE;
|
||||
nodeData.maxState = NPC_STATE_COMBAT;
|
||||
#ifdef MAPBASE
|
||||
nodeData.nRadius = 0; // From Alien Swarm SDK
|
||||
nodeData.flWeight = 1.0f;
|
||||
nodeData.flWeightInverse = 1.0f;
|
||||
#endif
|
||||
CAI_Hint *pHint = CAI_HintManager::CreateHint( &nodeData, NULL );
|
||||
if ( pHint )
|
||||
{
|
||||
|
@ -112,6 +112,13 @@ enum Hint_e
|
||||
|
||||
// CS port hints
|
||||
HINT_CSTRIKE_HOSTAGE_ESCAPE = 1100,
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Mapbase hints
|
||||
// (these start at a high number to avoid potential conflicts with mod hints)
|
||||
|
||||
HINT_TACTICAL_COVER_CUSTOM = 10000, // Cover node with a custom hint activity (NPCs can take cover and reload here while playing said activity)
|
||||
#endif
|
||||
};
|
||||
const char *GetHintTypeDescription( Hint_e iHintType );
|
||||
const char *GetHintTypeDescription( CAI_Hint *pHint );
|
||||
@ -120,6 +127,10 @@ const char *GetHintTypeDescription( CAI_Hint *pHint );
|
||||
// CHintCriteria
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
typedef bool (*HintSearchFilterFunc_t)( void *pContext, CAI_Hint *pCandidate );
|
||||
#endif
|
||||
|
||||
class CHintCriteria
|
||||
{
|
||||
public:
|
||||
@ -134,6 +145,11 @@ public:
|
||||
void SetGroup( string_t group );
|
||||
string_t GetGroup( void ) const { return m_strGroup; }
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
void SetFilterFunc( HintSearchFilterFunc_t pfnFilter, void *pContext = NULL ) { m_pfnFilter = pfnFilter; m_pFilterContext = pContext; }
|
||||
bool PassesFilter( CAI_Hint *pCandidate ) const { return (m_pfnFilter) ? (*m_pfnFilter)(m_pFilterContext, pCandidate) : true; }
|
||||
#endif
|
||||
|
||||
int GetFirstHintType( void ) const { return m_iFirstHintType; }
|
||||
int GetLastHintType( void ) const { return m_iLastHintType; }
|
||||
bool MatchesHintType( int hintType ) const;
|
||||
@ -176,6 +192,11 @@ private:
|
||||
|
||||
zoneList_t m_zoneInclude;
|
||||
zoneList_t m_zoneExclude;
|
||||
|
||||
#ifdef MAPBASE
|
||||
HintSearchFilterFunc_t m_pfnFilter;
|
||||
void * m_pFilterContext;
|
||||
#endif
|
||||
};
|
||||
|
||||
class CAI_Node;
|
||||
@ -310,11 +331,21 @@ public:
|
||||
int GetNodeId() { return m_NodeData.nNodeID; }
|
||||
int GetWCId() { return m_NodeData.nWCNodeID; }
|
||||
|
||||
#ifdef MAPBASE
|
||||
int GetRadius() const { return m_NodeData.nRadius; } // From Alien Swarm SDK
|
||||
|
||||
float GetHintWeight() const { return m_NodeData.flWeight; }
|
||||
float GetHintWeightInverse() const { return m_NodeData.flWeightInverse; } // Used to multiply distances
|
||||
#endif
|
||||
|
||||
bool HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria, const Vector &position, float *flNearestDistance, bool bIgnoreLock = false, bool bIgnoreHintType = false );
|
||||
bool IsInNodeFOV( CBaseEntity *pOther );
|
||||
|
||||
#ifdef MAPBASE
|
||||
void NPCHandleStartNav( CAI_BaseNPC *pNPC, bool bDefaultFacing );
|
||||
|
||||
// Returns true if this hint should override a NPC's yaw even during regular AI.
|
||||
bool OverridesNPCYaw( CAI_BaseNPC *pNPC );
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
|
@ -173,6 +173,10 @@ BEGIN_SIMPLE_DATADESC( HintNodeData )
|
||||
DEFINE_KEYFIELD( fIgnoreFacing, FIELD_INTEGER, "IgnoreFacing" ),
|
||||
DEFINE_KEYFIELD( minState, FIELD_INTEGER, "MinimumState" ),
|
||||
DEFINE_KEYFIELD( maxState, FIELD_INTEGER, "MaximumState" ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( nRadius, FIELD_INTEGER, "radius" ), // From Alien Swarm SDK
|
||||
DEFINE_KEYFIELD( flWeight, FIELD_FLOAT, "hintweight" ),
|
||||
#endif
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
@ -205,6 +209,17 @@ int CNodeEnt::Spawn( const char *pMapData )
|
||||
m_NodeData.minState = NPC_STATE_IDLE;
|
||||
if ( m_NodeData.maxState == NPC_STATE_NONE )
|
||||
m_NodeData.maxState = NPC_STATE_COMBAT;
|
||||
#ifdef MAPBASE
|
||||
if (m_NodeData.flWeight == 0.0f)
|
||||
{
|
||||
m_NodeData.flWeight = 1.0f;
|
||||
}
|
||||
else if (m_NodeData.flWeight != 1.0f)
|
||||
{
|
||||
// Invert the weight so that it could be used as a direct multiplier for distances, etc.
|
||||
m_NodeData.flWeightInverse = 1.0f / m_NodeData.flWeight;
|
||||
}
|
||||
#endif
|
||||
// ---------------------------------------------------------------------------------
|
||||
// If just a hint node (not used for navigation) just create a hint and bail
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
@ -42,6 +42,11 @@ struct HintNodeData
|
||||
HintIgnoreFacing_t fIgnoreFacing;
|
||||
NPC_STATE minState;
|
||||
NPC_STATE maxState;
|
||||
#ifdef MAPBASE
|
||||
int nRadius; // From Alien Swarm SDK
|
||||
float flWeight;
|
||||
float flWeightInverse; // Not saved
|
||||
#endif
|
||||
|
||||
int nWCNodeID; // Node ID assigned by worldcraft (not same as engine!)
|
||||
|
||||
|
@ -144,6 +144,31 @@ public:
|
||||
int m_capabilities; // cache this
|
||||
};
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-------------------------------------
|
||||
// Purpose: A version of CNodeFilter which allows hints to influence the result.
|
||||
//-------------------------------------
|
||||
class CNodeHintFilter : public CNodeFilter
|
||||
{
|
||||
public:
|
||||
CNodeHintFilter( CAI_BaseNPC *pNPC, const Vector &pos ) : CNodeFilter( pNPC, pos ) {}
|
||||
CNodeHintFilter( const Vector &pos ) : CNodeFilter( pos ) {}
|
||||
|
||||
virtual float NodeDistanceSqr( CAI_Node &node )
|
||||
{
|
||||
// Heavier hints are considered closer
|
||||
if (node.GetHint() && node.GetHint()->GetHintWeight() != 1.0f)
|
||||
{
|
||||
return CNodeFilter::NodeDistanceSqr( node ) * node.GetHint()->GetHintWeightInverse();
|
||||
}
|
||||
else
|
||||
{
|
||||
return CNodeFilter::NodeDistanceSqr( node );
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CAI_Network
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -351,7 +376,12 @@ int CAI_Network::NearestNodeToPoint( CAI_BaseNPC *pNPC, const Vector &vecOrigin,
|
||||
// First get nodes distances and eliminate those that are beyond
|
||||
// the maximum allowed distance for local movements
|
||||
// ---------------------------------------------------------------
|
||||
#ifdef MAPBASE
|
||||
// Allow hint weight to influence supposed distance
|
||||
CNodeHintFilter filter( pNPC, vecOrigin );
|
||||
#else
|
||||
CNodeFilter filter( pNPC, vecOrigin );
|
||||
#endif
|
||||
|
||||
#ifdef AI_PERF_MON
|
||||
m_nPerfStatNN++;
|
||||
@ -605,8 +635,13 @@ CAI_Node *CAI_Network::AddNode( const Vector &origin, float yaw )
|
||||
|
||||
CAI_Link *CAI_Network::CreateLink( int srcID, int destID, CAI_DynamicLink *pDynamicLink )
|
||||
{
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
CAI_Node *pSrcNode = GetNode( srcID );
|
||||
CAI_Node *pDestNode = GetNode( destID );
|
||||
#else
|
||||
CAI_Node *pSrcNode = g_pBigAINet->GetNode( srcID );
|
||||
CAI_Node *pDestNode = g_pBigAINet->GetNode( destID );
|
||||
#endif
|
||||
|
||||
Assert( pSrcNode && pDestNode && pSrcNode != pDestNode );
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user