mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-01-13 07:17:57 +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_strGroup = NULL_STRING;
|
||||||
m_iFlags = 0;
|
m_iFlags = 0;
|
||||||
m_HintTypes.Purge();
|
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();
|
HintIgnoreFacing_t facing = GetIgnoreFacing();
|
||||||
if (facing == HIF_DEFAULT)
|
if (facing == HIF_DEFAULT)
|
||||||
facing = bDefaultFacing ? HIF_YES : HIF_NO;
|
facing = bDefaultFacing ? HIF_NO : HIF_YES;
|
||||||
|
|
||||||
if (facing == HIF_YES)
|
if (facing == HIF_NO)
|
||||||
pNPC->GetNavigator()->SetArrivalDirection(GetDirection());
|
pNPC->GetNavigator()->SetArrivalDirection( GetDirection() );
|
||||||
|
|
||||||
if (HintActivityName() != NULL_STRING)
|
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
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -1258,6 +1307,30 @@ bool CAI_Hint::HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hint
|
|||||||
return false;
|
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 ( hintCriteria.HasFlag(bits_HINT_NPC_IN_NODE_FOV) )
|
||||||
{
|
{
|
||||||
if ( pNPC == NULL )
|
if ( pNPC == NULL )
|
||||||
@ -1377,10 +1450,18 @@ bool CAI_Hint::HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hint
|
|||||||
{
|
{
|
||||||
trace_t tr;
|
trace_t tr;
|
||||||
// Can my bounding box fit there?
|
// 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(),
|
AI_TraceHull ( GetAbsOrigin(), GetAbsOrigin(), pNPC->WorldAlignMins(), pNPC->WorldAlignMaxs(),
|
||||||
MASK_SOLID, pNPC, COLLISION_GROUP_NONE, &tr );
|
MASK_SOLID, pNPC, COLLISION_GROUP_NONE, &tr );
|
||||||
|
|
||||||
if ( tr.fraction != 1.0 )
|
if ( tr.fraction != 1.0 )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
REPORTFAILURE( "Node isn't clear." );
|
REPORTFAILURE( "Node isn't clear." );
|
||||||
return false;
|
return false;
|
||||||
@ -1396,6 +1477,15 @@ bool CAI_Hint::HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hint
|
|||||||
// Calculate our distance
|
// Calculate our distance
|
||||||
float distance = (GetAbsOrigin() - position).Length();
|
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
|
// Must be closer than the current best
|
||||||
if ( distance > *flNearestDistance )
|
if ( distance > *flNearestDistance )
|
||||||
{
|
{
|
||||||
@ -1576,6 +1666,14 @@ void CAI_Hint::OnRestore()
|
|||||||
m_NodeData.nNodeID = g_pAINetworkManager->GetEditOps()->GetNodeIdFromWCId( m_NodeData.nWCNodeID );
|
m_NodeData.nNodeID = g_pAINetworkManager->GetEditOps()->GetNodeIdFromWCId( m_NodeData.nWCNodeID );
|
||||||
FixupTargetNode();
|
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();
|
CAI_Node *pNode = GetNode();
|
||||||
|
|
||||||
if ( !pNode )
|
if ( !pNode )
|
||||||
@ -1751,6 +1849,11 @@ void CC_ai_drop_hint( const CCommand &args )
|
|||||||
nodeData.fIgnoreFacing = HIF_DEFAULT;
|
nodeData.fIgnoreFacing = HIF_DEFAULT;
|
||||||
nodeData.minState = NPC_STATE_IDLE;
|
nodeData.minState = NPC_STATE_IDLE;
|
||||||
nodeData.maxState = NPC_STATE_COMBAT;
|
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 );
|
CAI_Hint *pHint = CAI_HintManager::CreateHint( &nodeData, NULL );
|
||||||
if ( pHint )
|
if ( pHint )
|
||||||
{
|
{
|
||||||
|
@ -112,6 +112,13 @@ enum Hint_e
|
|||||||
|
|
||||||
// CS port hints
|
// CS port hints
|
||||||
HINT_CSTRIKE_HOSTAGE_ESCAPE = 1100,
|
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( Hint_e iHintType );
|
||||||
const char *GetHintTypeDescription( CAI_Hint *pHint );
|
const char *GetHintTypeDescription( CAI_Hint *pHint );
|
||||||
@ -120,6 +127,10 @@ const char *GetHintTypeDescription( CAI_Hint *pHint );
|
|||||||
// CHintCriteria
|
// CHintCriteria
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef MAPBASE // From Alien Swarm SDK
|
||||||
|
typedef bool (*HintSearchFilterFunc_t)( void *pContext, CAI_Hint *pCandidate );
|
||||||
|
#endif
|
||||||
|
|
||||||
class CHintCriteria
|
class CHintCriteria
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -134,6 +145,11 @@ public:
|
|||||||
void SetGroup( string_t group );
|
void SetGroup( string_t group );
|
||||||
string_t GetGroup( void ) const { return m_strGroup; }
|
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 GetFirstHintType( void ) const { return m_iFirstHintType; }
|
||||||
int GetLastHintType( void ) const { return m_iLastHintType; }
|
int GetLastHintType( void ) const { return m_iLastHintType; }
|
||||||
bool MatchesHintType( int hintType ) const;
|
bool MatchesHintType( int hintType ) const;
|
||||||
@ -176,6 +192,11 @@ private:
|
|||||||
|
|
||||||
zoneList_t m_zoneInclude;
|
zoneList_t m_zoneInclude;
|
||||||
zoneList_t m_zoneExclude;
|
zoneList_t m_zoneExclude;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
HintSearchFilterFunc_t m_pfnFilter;
|
||||||
|
void * m_pFilterContext;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class CAI_Node;
|
class CAI_Node;
|
||||||
@ -310,11 +331,21 @@ public:
|
|||||||
int GetNodeId() { return m_NodeData.nNodeID; }
|
int GetNodeId() { return m_NodeData.nNodeID; }
|
||||||
int GetWCId() { return m_NodeData.nWCNodeID; }
|
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 HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria, const Vector &position, float *flNearestDistance, bool bIgnoreLock = false, bool bIgnoreHintType = false );
|
||||||
bool IsInNodeFOV( CBaseEntity *pOther );
|
bool IsInNodeFOV( CBaseEntity *pOther );
|
||||||
|
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
void NPCHandleStartNav( CAI_BaseNPC *pNPC, bool bDefaultFacing );
|
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
|
#endif
|
||||||
|
|
||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
@ -173,6 +173,10 @@ BEGIN_SIMPLE_DATADESC( HintNodeData )
|
|||||||
DEFINE_KEYFIELD( fIgnoreFacing, FIELD_INTEGER, "IgnoreFacing" ),
|
DEFINE_KEYFIELD( fIgnoreFacing, FIELD_INTEGER, "IgnoreFacing" ),
|
||||||
DEFINE_KEYFIELD( minState, FIELD_INTEGER, "MinimumState" ),
|
DEFINE_KEYFIELD( minState, FIELD_INTEGER, "MinimumState" ),
|
||||||
DEFINE_KEYFIELD( maxState, FIELD_INTEGER, "MaximumState" ),
|
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()
|
END_DATADESC()
|
||||||
|
|
||||||
@ -205,6 +209,17 @@ int CNodeEnt::Spawn( const char *pMapData )
|
|||||||
m_NodeData.minState = NPC_STATE_IDLE;
|
m_NodeData.minState = NPC_STATE_IDLE;
|
||||||
if ( m_NodeData.maxState == NPC_STATE_NONE )
|
if ( m_NodeData.maxState == NPC_STATE_NONE )
|
||||||
m_NodeData.maxState = NPC_STATE_COMBAT;
|
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
|
// If just a hint node (not used for navigation) just create a hint and bail
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
@ -42,6 +42,11 @@ struct HintNodeData
|
|||||||
HintIgnoreFacing_t fIgnoreFacing;
|
HintIgnoreFacing_t fIgnoreFacing;
|
||||||
NPC_STATE minState;
|
NPC_STATE minState;
|
||||||
NPC_STATE maxState;
|
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!)
|
int nWCNodeID; // Node ID assigned by worldcraft (not same as engine!)
|
||||||
|
|
||||||
|
@ -144,6 +144,31 @@ public:
|
|||||||
int m_capabilities; // cache this
|
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
|
// 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
|
// First get nodes distances and eliminate those that are beyond
|
||||||
// the maximum allowed distance for local movements
|
// 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 );
|
CNodeFilter filter( pNPC, vecOrigin );
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef AI_PERF_MON
|
#ifdef AI_PERF_MON
|
||||||
m_nPerfStatNN++;
|
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 )
|
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 *pSrcNode = g_pBigAINet->GetNode( srcID );
|
||||||
CAI_Node *pDestNode = g_pBigAINet->GetNode( destID );
|
CAI_Node *pDestNode = g_pBigAINet->GetNode( destID );
|
||||||
|
#endif
|
||||||
|
|
||||||
Assert( pSrcNode && pDestNode && pSrcNode != pDestNode );
|
Assert( pSrcNode && pDestNode && pSrcNode != pDestNode );
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user