コード例 #1
0
ファイル: ai_dynamiclink.cpp プロジェクト: paralin/hl2sdk
void CAI_DynamicLinkController::GenerateLinksFromVolume()
{
	Assert( m_ControlledLinks.Count() == 0 );

	int nNodes = g_pBigAINet->NumNodes();
	CAI_Node **ppNodes = g_pBigAINet->AccessNodes();

	const float MinDistCareSq = Square(MAX_NODE_LINK_DIST + 0.1);

	const Vector &origin = WorldSpaceCenter();
	Vector vAbsMins, vAbsMaxs;
	CollisionProp()->WorldSpaceAABB( &vAbsMins, &vAbsMaxs );
	vAbsMins -= Vector( 1, 1, 1 );
	vAbsMaxs += Vector( 1, 1, 1 );

	for ( int i = 0; i < nNodes; i++ )
	{
		CAI_Node *pNode = ppNodes[i];
		const Vector &nodeOrigin = pNode->GetOrigin();
		if ( origin.DistToSqr(nodeOrigin) < MinDistCareSq )
		{
			int nLinks = pNode->NumLinks();
			for ( int j = 0; j < nLinks; j++ )
			{
				CAI_Link *pLink = pNode->GetLinkByIndex( j );
				int iLinkDest = pLink->DestNodeID( i );
				if ( iLinkDest > i )
				{
					const Vector &originOther = ppNodes[iLinkDest]->GetOrigin();
					if ( origin.DistToSqr(originOther) < MinDistCareSq )
					{
						if ( IsBoxIntersectingRay( vAbsMins, vAbsMaxs, nodeOrigin, originOther - nodeOrigin ) )
						{
							Assert( IsBoxIntersectingRay( vAbsMins, vAbsMaxs, originOther, nodeOrigin - originOther ) );

							CAI_DynamicLink *pLink = (CAI_DynamicLink *)CreateEntityByName( "info_node_link" );
							pLink->m_nSrcID = i;
							pLink->m_nDestID = iLinkDest;
							pLink->m_nSrcEditID = g_pAINetworkManager->GetEditOps()->GetWCIdFromNodeId( pLink->m_nSrcID );
							pLink->m_nDestEditID = g_pAINetworkManager->GetEditOps()->GetWCIdFromNodeId( pLink->m_nDestID );
							pLink->m_nLinkState = m_nLinkState;
							pLink->m_strAllowUse = m_strAllowUse;
							pLink->m_bFixedUpIds = true;
							pLink->m_bNotSaved = true;

							pLink->Spawn();
							m_ControlledLinks.AddToTail( pLink );
						}
					}
				}
			}
		}
	}
}
コード例 #2
0
ファイル: ai_dynamiclink.cpp プロジェクト: BenLubar/riflemod
void CAI_RadialLinkController::ModifyNodeLinks( bool bMakeStale )
{
	int nNodes = g_pBigAINet->NumNodes();
	CAI_Node **ppNodes = g_pBigAINet->AccessNodes();

	VPROF_BUDGET("ModifyLinks", "ModifyLinks");

	const float MinDistCareSq = Square( ai_radial_max_link_dist.GetFloat() + 0.1 );

	for ( int i = 0; i < nNodes; i++ )
	{
		CAI_Node *pNode = ppNodes[i];
		const Vector &nodeOrigin = pNode->GetOrigin();
		if ( m_vecAtRestOrigin.DistToSqr(nodeOrigin) < MinDistCareSq )
		{
			int nLinks = pNode->NumLinks();
			for ( int j = 0; j < nLinks; j++ )
			{
				CAI_Link *pLink = pNode->GetLinkByIndex( j );
				int iLinkDest = pLink->DestNodeID( i );

				if ( iLinkDest > i )
				{
					bool bQualify = true;

					if( ( (pLink->m_iAcceptedMoveTypes[HULL_HUMAN]||pLink->m_iAcceptedMoveTypes[HULL_WIDE_HUMAN]) & bits_CAP_MOVE_GROUND) == 0 )
					{
						// Micro-optimization: Ignore any connection that's not a walking connection for humans.(sjb)
						bQualify = false;
					}

					const Vector &originOther = ppNodes[iLinkDest]->GetOrigin();
					if ( bQualify && m_vecAtRestOrigin.DistToSqr(originOther) < MinDistCareSq )
					{
						if ( IsRayIntersectingSphere(nodeOrigin, originOther - nodeOrigin, m_vecAtRestOrigin, m_flRadius) )
						{
							if( bMakeStale )
							{
								pLink->m_LinkInfo |= bits_LINK_STALE_SUGGESTED;
								pLink->m_timeStaleExpires = FLT_MAX;
							}
							else
							{
								pLink->m_LinkInfo &= ~bits_LINK_STALE_SUGGESTED;
							}
						}
					}
				}
			}
		}
	}
}
コード例 #3
0
ファイル: ai_hint.cpp プロジェクト: Bubbasacs/FinalProj
void CAI_Hint::OnRestore()
{
	BaseClass::OnRestore();

	m_NodeData.nNodeID = g_pAINetworkManager->GetEditOps()->GetNodeIdFromWCId( m_NodeData.nWCNodeID );
	FixupTargetNode();

	CAI_Node *pNode = GetNode();
	
	if ( !pNode )
	{
		if ( m_NodeData.nWCNodeID > 0 )
			DevMsg("Warning: AI hint has incorrect or no AI node\n");
	}
	else
	{
		m_NodeData.vecPosition = pNode->GetOrigin();
		Teleport( &m_NodeData.vecPosition, NULL, NULL );
		pNode->SetHint( this );
	}
}
コード例 #4
0
void CASW_Spawn_Manager::PrespawnAlienAtRandomNode(const char *szAlienClass, const int iNumAliens, const int iHull, const Vector &playerStartPos, const int iNumNodes)
{
	for (int i = 0; i < iNumAliens; ++i)
	{
		CAI_Node *pNode = NULL;
		for (int k = 0; k < 30; ++k)
		{
			int node_id = RandomInt(0, iNumNodes - 1);
			pNode = g_pBigAINet->GetNode(node_id);
			if (!pNode || pNode->GetType() != NODE_GROUND)
				continue;
			else if (pNode->GetOrigin().DistToSqr(playerStartPos) < 1000 * 1000)
			{
				continue;
			}

			if (ValidSpawnPoint(pNode->GetPosition(iHull), NAI_Hull::Mins(iHull), NAI_Hull::Maxs(iHull), true, false))
			{
				// Raise the end position a little up off the floor, place the npc and drop him down
				CBaseEntity *pAlien = SpawnAlienAt(szAlienClass, pNode->GetPosition(iHull) + Vector(0.f, 0.f, 12.f), RandomAngle(0, 360));
				IASW_Spawnable_NPC *pSpawnable = dynamic_cast<IASW_Spawnable_NPC*>(pAlien);
				if (pSpawnable)
				{
					pSpawnable->SetAlienOrders(AOT_SpreadThenHibernate, vec3_origin, NULL);
				}
				if (asw_director_debug.GetBool() && pAlien)
				{
					Msg("Spawned alien at %f %f %f\n", pAlien->GetAbsOrigin());
					NDebugOverlay::Cross3D(pAlien->GetAbsOrigin(), 8.0f, 255, 0, 0, true, 20.0f);
				}
				if (pAlien)
					break;
			}
		}
	}
}
コード例 #5
0
bool CASW_Weapon_Blink::SetBlinkDestination()
{
	CASW_Player *pPlayer = GetCommander();
	if ( !pPlayer )
		return false;

	CASW_Marine *pMarine = GetMarine();
	if ( !pMarine )
		return false;

	Vector vecStart = pPlayer->GetCrosshairTracePos() + Vector( 0, 0, 30 );
	Vector vecEnd = pPlayer->GetCrosshairTracePos() - Vector( 0, 0, 30 );
	trace_t tr;
	UTIL_TraceHull( vecStart, vecEnd, pMarine->WorldAlignMins(), pMarine->WorldAlignMaxs(), MASK_PLAYERSOLID_BRUSHONLY, pMarine, COLLISION_GROUP_PLAYER_MOVEMENT, &tr );
	if ( tr.startsolid || tr.allsolid )
	{
		m_vecInvalidDestination = vecStart;
		return false;
	}

	if ( pMarine->GetAbsOrigin().DistTo( tr.endpos ) > asw_blink_range.GetFloat() )
	{
		m_vecInvalidDestination = tr.endpos;
		return false;
	}

	Vector vecDest = tr.endpos;

	// now see if we can build an AI path from the marine to this spot
	bool bValidRoute = false;

	if ( !pMarine->GetPathfinder() )
	{
		m_vecInvalidDestination = vecDest;
		return false;
	}

	AI_Waypoint_t *pRoute = pMarine->GetPathfinder()->BuildRoute( pMarine->GetAbsOrigin(), vecDest, NULL, 30, NAV_GROUND, bits_BUILD_GROUND | bits_BUILD_IGNORE_NPCS );
	if ( pRoute && !UTIL_ASW_DoorBlockingRoute( pRoute, true ) )
	{
		if ( !UTIL_ASW_BrushBlockingRoute( pRoute, MASK_PLAYERSOLID_BRUSHONLY, COLLISION_GROUP_PLAYER_MOVEMENT ) )
		{
			// if end node of the route is too Z different, then abort, to stop people jumping on top of walls
			AI_Waypoint_t *pLast = pRoute->GetLast();
			if ( pLast )
			{
				AI_Waypoint_t *pNode = pLast->GetPrev();
				if ( !pNode || fabs( pNode->GetPos().z - pLast->GetPos().z ) < 80.0f )
				{
					bValidRoute = true;
				}
			}
		}
	}
	
	if ( !bValidRoute )
	{
		// find the closest node to the dest and try to path there instead
		CAI_Network *pNetwork = pMarine->GetNavigator() ? pMarine->GetNavigator()->GetNetwork() : NULL;
		if ( pNetwork )
		{
			int nNode = pNetwork->NearestNodeToPoint( vecDest, false );
			if ( nNode != NO_NODE )
			{
				CAI_Node *pNode = pNetwork->GetNode( nNode );
				if ( pNode && pNode->GetType() == NODE_GROUND )
				{
					vecDest = pNode->GetOrigin();
					if ( pRoute )
					{
						ASWPathUtils()->DeleteRoute( pRoute );
						pRoute = NULL;
					}
					pRoute = pMarine->GetPathfinder()->BuildRoute( pMarine->GetAbsOrigin(), vecDest, NULL, 30, NAV_GROUND, bits_BUILD_GROUND | bits_BUILD_IGNORE_NPCS );
					if ( pRoute && !UTIL_ASW_DoorBlockingRoute( pRoute, true ) )
					{
						if ( !UTIL_ASW_BrushBlockingRoute( pRoute, MASK_PLAYERSOLID_BRUSHONLY, COLLISION_GROUP_PLAYER_MOVEMENT ) )
						{
							bValidRoute = true;
						}
					}
					if ( !bValidRoute )
					{
						m_vecInvalidDestination = vecDest;
					}
				}
			}
		}
	}

	if ( !bValidRoute )
	{
		if ( pRoute )
		{
			ASWPathUtils()->DeleteRoute( pRoute );
			pRoute = NULL;
		}
		return false;
	}

	if ( asw_blink_debug.GetBool() )
	{
		ASWPathUtils()->DebugDrawRoute( pMarine->GetAbsOrigin(), pRoute );
	}

	m_vecAbilityDestination = vecDest;

	if ( pRoute )
	{
		ASWPathUtils()->DeleteRoute( pRoute );
		pRoute = NULL;
	}

	return true;
}
コード例 #6
0
bool CASW_Spawn_Manager::SpawnRandomShieldbug()
{
    int iNumNodes = g_pBigAINet->NumNodes();
    if ( iNumNodes < 6 )
        return false;

    int nHull = HULL_WIDE_SHORT;
    CUtlVector<CASW_Open_Area*> aAreas;
    for ( int i = 0; i < 6; i++ )
    {
        CAI_Node *pNode = NULL;
        int nTries = 0;
        while ( nTries < 5 && ( !pNode || pNode->GetType() != NODE_GROUND ) )
        {
            pNode = g_pBigAINet->GetNode( RandomInt( 0, iNumNodes ) );
            nTries++;
        }

        if ( pNode )
        {
            CASW_Open_Area *pArea = FindNearbyOpenArea( pNode->GetOrigin(), HULL_MEDIUMBIG );
            if ( pArea && pArea->m_nTotalLinks > 30 )
            {
                // test if there's room to spawn a shieldbug at that spot
                if ( ValidSpawnPoint( pArea->m_pNode->GetPosition( nHull ), NAI_Hull::Mins( nHull ), NAI_Hull::Maxs( nHull ), true, false ) )
                {
                    aAreas.AddToTail( pArea );
                }
                else
                {
                    delete pArea;
                }
            }
        }
        // stop searching once we have 3 acceptable candidates
        if ( aAreas.Count() >= 3 )
            break;
    }

    // find area with the highest connectivity
    CASW_Open_Area *pBestArea = NULL;
    for ( int i = 0; i < aAreas.Count(); i++ )
    {
        CASW_Open_Area *pArea = aAreas[i];
        if ( !pBestArea || pArea->m_nTotalLinks > pBestArea->m_nTotalLinks )
        {
            pBestArea = pArea;
        }
    }

    if ( pBestArea )
    {
        CBaseEntity *pAlien = SpawnAlienAt( "asw_shieldbug", pBestArea->m_pNode->GetPosition( nHull ), RandomAngle( 0, 360 ) );
        IASW_Spawnable_NPC *pSpawnable = dynamic_cast<IASW_Spawnable_NPC*>( pAlien );
        if ( pSpawnable )
        {
            pSpawnable->SetAlienOrders(AOT_SpreadThenHibernate, vec3_origin, NULL);
        }
        aAreas.PurgeAndDeleteElements();
        return true;
    }

    aAreas.PurgeAndDeleteElements();
    return false;
}
コード例 #7
0
bool CASW_Spawn_Manager::SpawnAlientAtRandomNode()
{
    if ( spawnRandomAlienTimer.HasStarted() && !spawnRandomAlienTimer.IsElapsed() )
        return false;
    spawnRandomAlienTimer.Start( MINIMUM_SPAWN_DELAY );

    UpdateCandidateNodes();

    // decide if the alien is going to come from behind or in front
    bool bNorth = RandomFloat() < 0.7f;
    if ( m_northCandidateNodes.Count() <= 0 )
    {
        bNorth = false;
    }
    else if ( m_southCandidateNodes.Count() <= 0 )
    {
        bNorth = true;
    }

    CUtlVector<int> &candidateNodes = bNorth ? m_northCandidateNodes : m_southCandidateNodes;

    if ( candidateNodes.Count() <= 0 )
        return false;

    const char *szAlienClass = wandererQueue[wandererQueueStart];

    Vector vecMins, vecMaxs;
    GetAlienBounds( szAlienClass, vecMins, vecMaxs );

    int alienHull = getAlienHull(szAlienClass);

    int iMaxTries = 3;

    for ( int i=0 ; i<iMaxTries ; i++ )
    {
        int iChosen = RandomInt( 0, candidateNodes.Count() - 1);
        CAI_Node *pNode = GetNetwork()->GetNode( candidateNodes[iChosen] );
        if ( !pNode )
            continue;

        float flDistance = 0;
        CASW_Marine *pMarine = dynamic_cast<CASW_Marine*>(UTIL_ASW_NearestMarine( pNode->GetPosition( alienHull ), flDistance ));
        if ( !pMarine )
            return false;

        // check if there's a route from this node to the marine(s)
        AI_Waypoint_t *pRoute = ASWPathUtils()->BuildRoute( pNode->GetPosition( alienHull ), pMarine->GetAbsOrigin(), NULL, 100 );
        if ( !pRoute )
        {
            if ( asw_director_debug.GetBool() )
            {
                NDebugOverlay::Cross3D( pNode->GetOrigin(), 10.0f, 255, 128, 0, true, 20.0f );
            }
            continue;
        }

        if ( bNorth && UTIL_ASW_DoorBlockingRoute( pRoute, true ) )
        {
            DeleteRoute( pRoute );
            continue;
        }

        Vector vecSpawnPos = pNode->GetPosition( alienHull ) + Vector( 0, 0, 32 );
        bool needsGround = Q_stricmp(szAlienClass, "asw_buzzer") != 0;
        if ( ValidSpawnPoint( vecSpawnPos, vecMins, vecMaxs, needsGround, MARINE_NEAR_DISTANCE ) ) {
            float extraClearanceFactor = 1;
            //the boomer's hull seems to be too small for some reason
            if (Q_stricmp(szAlienClass, "asw_boomer") == 0) {
                extraClearanceFactor = 2;
            }

            Vector shiftSpawnBy = shiftSpawnPosition(vecSpawnPos, vecMins, vecMaxs, extraClearanceFactor);
            if (shiftSpawnBy.z == -1 ) {
                DeleteRoute( pRoute );
                continue;
            }

            Vector shiftedSpawnPos = vecSpawnPos+shiftSpawnBy;



            Vector testShift = shiftSpawnPosition(shiftedSpawnPos, vecMins, vecMaxs, extraClearanceFactor);
            if (testShift.x != 0 || testShift.y != 0 || testShift.z != 0) {
                DeleteRoute( pRoute );
                continue;
            }

            if ( SpawnAlienAt( szAlienClass, shiftedSpawnPos, vec3_angle ) ) {
                wandererQueueStart++;
                wandererQueueStart %= WANDERER_QUEUE_SIZE;
                if ( asw_director_debug.GetBool() )	{
                    NDebugOverlay::Cross3D( vecSpawnPos, 25.0f, 255, 255, 255, true, 20.0f );
                    float flDist;
                    CASW_Marine *pMarine = UTIL_ASW_NearestMarine( vecSpawnPos, flDist );
                    if ( pMarine ) {
                        NDebugOverlay::Line( pMarine->GetAbsOrigin(), vecSpawnPos, 64, 64, 64, true, 60.0f );
                    }
                }
                DeleteRoute( pRoute );
                return true;
            }
        }
        else
        {
            if ( asw_director_debug.GetBool() )
            {
                NDebugOverlay::Cross3D( vecSpawnPos, 25.0f, 255, 0, 0, true, 20.0f );
            }
        }
        DeleteRoute( pRoute );
    }
    return false;
}
コード例 #8
0
// heuristic to find reasonably open space - searches for areas with high node connectivity
CASW_Open_Area* CASW_Spawn_Manager::FindNearbyOpenArea( const Vector &vecSearchOrigin, int nSearchHull )
{
    CBaseEntity *pStartEntity = gEntList.FindEntityByClassname( NULL, "info_player_start" );
    int iNumNodes = g_pBigAINet->NumNodes();
    CAI_Node *pHighestConnectivity = NULL;
    int nHighestLinks = 0;
    for ( int i=0 ; i<iNumNodes; i++ )
    {
        CAI_Node *pNode = g_pBigAINet->GetNode( i );
        if ( !pNode || pNode->GetType() != NODE_GROUND )
            continue;

        Vector vecPos = pNode->GetOrigin();
        float flDist = vecPos.DistTo( vecSearchOrigin );
        if ( flDist > 400.0f )
            continue;

        // discard if node is too near start location
        if ( pStartEntity && vecPos.DistTo( pStartEntity->GetAbsOrigin() ) < 1400.0f )  // NOTE: assumes all start points are clustered near one another
            continue;

        // discard if node is inside an escape area
        bool bInsideEscapeArea = false;
        for ( int d=0; d<m_EscapeTriggers.Count(); d++ )
        {
            if ( m_EscapeTriggers[d]->CollisionProp()->IsPointInBounds( vecPos ) )
            {
                bInsideEscapeArea = true;
                break;
            }
        }
        if ( bInsideEscapeArea )
            continue;

        // count links that drones could follow
        int nLinks = pNode->NumLinks();
        int nValidLinks = 0;
        for ( int k = 0; k < nLinks; k++ )
        {
            CAI_Link *pLink = pNode->GetLinkByIndex( k );
            if ( !pLink )
                continue;

            if ( !( pLink->m_iAcceptedMoveTypes[nSearchHull] & bits_CAP_MOVE_GROUND ) )
                continue;

            nValidLinks++;
        }
        if ( nValidLinks > nHighestLinks )
        {
            nHighestLinks = nValidLinks;
            pHighestConnectivity = pNode;
        }
        if ( asw_director_debug.GetBool() )
        {
            NDebugOverlay::Text( vecPos, UTIL_VarArgs( "%d", nValidLinks ), false, 10.0f );
        }
    }

    if ( !pHighestConnectivity )
        return NULL;

    // now, starting at the new node, find all nearby nodes with a minimum connectivity
    CASW_Open_Area *pArea = new CASW_Open_Area();
    pArea->m_vecOrigin = pHighestConnectivity->GetOrigin();
    pArea->m_pNode = pHighestConnectivity;
    int nMinLinks = nHighestLinks * 0.3f;
    nMinLinks = MAX( nMinLinks, 4 );

    pArea->m_aAreaNodes.AddToTail( pHighestConnectivity );
    if ( asw_director_debug.GetBool() )
    {
        Msg( "minLinks = %d\n", nMinLinks );
    }
    pArea->m_nTotalLinks = 0;
    for ( int i=0 ; i<iNumNodes; i++ )
    {
        CAI_Node *pNode = g_pBigAINet->GetNode( i );
        if ( !pNode || pNode->GetType() != NODE_GROUND )
            continue;

        Vector vecPos = pNode->GetOrigin();
        float flDist = vecPos.DistTo( pArea->m_vecOrigin );
        if ( flDist > 400.0f )
            continue;

        // discard if node is inside an escape area
        bool bInsideEscapeArea = false;
        for ( int d=0; d<m_EscapeTriggers.Count(); d++ )
        {
            if ( m_EscapeTriggers[d]->CollisionProp()->IsPointInBounds( vecPos ) )
            {
                bInsideEscapeArea = true;
                break;
            }
        }
        if ( bInsideEscapeArea )
            continue;

        // count links that drones could follow
        int nLinks = pNode->NumLinks();
        int nValidLinks = 0;
        for ( int k = 0; k < nLinks; k++ )
        {
            CAI_Link *pLink = pNode->GetLinkByIndex( k );
            if ( !pLink )
                continue;

            if ( !( pLink->m_iAcceptedMoveTypes[nSearchHull] & bits_CAP_MOVE_GROUND ) )
                continue;

            nValidLinks++;
        }
        if ( nValidLinks >= nMinLinks )
        {
            pArea->m_aAreaNodes.AddToTail( pNode );
            pArea->m_nTotalLinks += nValidLinks;
        }
    }
    // highlight and measure bounds
    Vector vecAreaMins = Vector( FLT_MAX, FLT_MAX, FLT_MAX );
    Vector vecAreaMaxs = Vector( -FLT_MAX, -FLT_MAX, -FLT_MAX );

    for ( int i = 0; i < pArea->m_aAreaNodes.Count(); i++ )
    {
        vecAreaMins = VectorMin( vecAreaMins, pArea->m_aAreaNodes[i]->GetOrigin() );
        vecAreaMaxs = VectorMax( vecAreaMaxs, pArea->m_aAreaNodes[i]->GetOrigin() );

        if ( asw_director_debug.GetBool() )
        {
            if ( i == 0 )
            {
                NDebugOverlay::Cross3D( pArea->m_aAreaNodes[i]->GetOrigin(), 20.0f, 255, 255, 64, true, 10.0f );
            }
            else
            {
                NDebugOverlay::Cross3D( pArea->m_aAreaNodes[i]->GetOrigin(), 10.0f, 255, 128, 0, true, 10.0f );
            }
        }
    }

    Vector vecArea = ( vecAreaMaxs - vecAreaMins );
    float flArea = vecArea.x * vecArea.y;

    if ( asw_director_debug.GetBool() )
    {
        Msg( "area mins = %f %f %f\n", VectorExpand( vecAreaMins ) );
        Msg( "area maxs = %f %f %f\n", VectorExpand( vecAreaMaxs ) );
        NDebugOverlay::Box( vec3_origin, vecAreaMins, vecAreaMaxs, 255, 128, 128, 10, 10.0f );
        Msg( "Total links = %d Area = %f\n", pArea->m_nTotalLinks, flArea );
    }

    return pArea;
}
コード例 #9
0
bool CASW_Spawn_Manager::SpawnRandomParasitePack( int nParasites )
{
	int iNumNodes = g_pBigAINet->NumNodes();
	if ( iNumNodes < 6 )
		return false;

	int nHull = HULL_TINY;
	CUtlVector<CASW_Open_Area*> aAreas;
	for ( int i = 0; i < 6; i++ )
	{
		CAI_Node *pNode = NULL;
		int nTries = 0;
		while ( nTries < 5 && ( !pNode || pNode->GetType() != NODE_GROUND ) )
		{
			pNode = g_pBigAINet->GetNode( RandomInt( 0, iNumNodes ) );
			nTries++;
		}

		if ( pNode )
		{
			CASW_Open_Area *pArea = FindNearbyOpenArea( pNode->GetOrigin(), HULL_MEDIUMBIG );
			if ( pArea && pArea->m_nTotalLinks > 30 )
			{
				// test if there's room to spawn a shieldbug at that spot
				if ( ValidSpawnPoint( pArea->m_pNode->GetPosition( nHull ), NAI_Hull::Mins( nHull ), NAI_Hull::Maxs( nHull ), true, false ) )
				{
					aAreas.AddToTail( pArea );
				}
				else
				{
					delete pArea;
				}
			}
		}
		// stop searching once we have 3 acceptable candidates
		if ( aAreas.Count() >= 3 )
			break;
	}

	// find area with the highest connectivity
	CASW_Open_Area *pBestArea = NULL;
	for ( int i = 0; i < aAreas.Count(); i++ )
	{
		CASW_Open_Area *pArea = aAreas[i];
		if ( !pBestArea || pArea->m_nTotalLinks > pBestArea->m_nTotalLinks )
		{
			pBestArea = pArea;
		}
	}

	if ( pBestArea )
	{
		for ( int i = 0; i < nParasites; i++ )
		{
			// raise the position by 12 units, a workaround for parasites
			// falling through displacements
			CBaseEntity *pAlien = SpawnAlienAt( "asw_parasite", pBestArea->m_pNode->GetPosition( nHull )  + Vector(0.f, 0.f, 12.f), RandomAngle( 0, 360 ) );
			IASW_Spawnable_NPC *pSpawnable = dynamic_cast<IASW_Spawnable_NPC*>( pAlien );
			if ( pSpawnable )
			{
				pSpawnable->SetAlienOrders(AOT_SpreadThenHibernate, vec3_origin, NULL);
			}
			if ( asw_director_debug.GetBool() && pAlien )
			{
				Msg( "Spawned parasite at %f %f %f\n", pAlien->GetAbsOrigin() );
				NDebugOverlay::Cross3D( pAlien->GetAbsOrigin(), 8.0f, 255, 0, 0, true, 20.0f );
			}
		}
		aAreas.PurgeAndDeleteElements();
		return true;
	}

	aAreas.PurgeAndDeleteElements();
	return false;
}
コード例 #10
0
bool CASW_Spawn_Manager::SpawnAlientAtRandomNode()
{
	UpdateCandidateNodes();

	// decide if the alien is going to come from behind or in front
	bool bNorth = RandomFloat() < 0.7f;
	if ( m_northCandidateNodes.Count() <= 0 )
	{
		bNorth = false;
	}
	else if ( m_southCandidateNodes.Count() <= 0 )
	{
		bNorth = true;
	}

	CUtlVector<int> &candidateNodes = bNorth ? m_northCandidateNodes : m_southCandidateNodes;

	if ( candidateNodes.Count() <= 0 )
		return false;

	const char *szAlienClass = "asw_drone";
	Vector vecMins, vecMaxs;
	GetAlienBounds( szAlienClass, vecMins, vecMaxs );

	int iMaxTries = 1;
	for ( int i=0 ; i<iMaxTries ; i++ )
	{
		int iChosen = RandomInt( 0, candidateNodes.Count() - 1);
		CAI_Node *pNode = GetNetwork()->GetNode( candidateNodes[iChosen] );
		if ( !pNode )
			continue;

		float flDistance = 0;
		CASW_Marine *pMarine = dynamic_cast<CASW_Marine*>(UTIL_ASW_NearestMarine( pNode->GetPosition( CANDIDATE_ALIEN_HULL ), flDistance ));
		if ( !pMarine )
			return false;

		// check if there's a route from this node to the marine(s)
		AI_Waypoint_t *pRoute = ASWPathUtils()->BuildRoute( pNode->GetPosition( CANDIDATE_ALIEN_HULL ), pMarine->GetAbsOrigin(), NULL, 100 );
		if ( !pRoute )
		{
			if ( asw_director_debug.GetBool() )
			{
				NDebugOverlay::Cross3D( pNode->GetOrigin(), 10.0f, 255, 128, 0, true, 20.0f );
			}
			continue;
		}

		if ( bNorth && UTIL_ASW_DoorBlockingRoute( pRoute, true ) )
		{
			DeleteRoute( pRoute );
			continue;
		}

		// riflemod: preventing wanderers from spawning behind closed airlocks
		if (UTIL_ASW_BrushBlockingRoute(pRoute, MASK_PLAYERSOLID_BRUSHONLY, COLLISION_GROUP_PLAYER_MOVEMENT))
		{
			DeleteRoute(pRoute);
			continue;
		}
		
		Vector vecSpawnPos = pNode->GetPosition( CANDIDATE_ALIEN_HULL ) + Vector( 0, 0, 32 );
		if ( ValidSpawnPoint( vecSpawnPos, vecMins, vecMaxs, true, MARINE_NEAR_DISTANCE ) )
		{
			if ( SpawnAlienAt( szAlienClass, vecSpawnPos, vec3_angle ) )
			{
				if ( asw_director_debug.GetBool() )
				{
					NDebugOverlay::Cross3D( vecSpawnPos, 25.0f, 255, 255, 255, true, 20.0f );
					float flDist;
					CASW_Marine *pMarine = UTIL_ASW_NearestMarine( vecSpawnPos, flDist );
					if ( pMarine )
					{
						NDebugOverlay::Line( pMarine->GetAbsOrigin(), vecSpawnPos, 64, 64, 64, true, 60.0f );
					}
				}
				DeleteRoute( pRoute );
				return true;
			}
		}
		else
		{
			if ( asw_director_debug.GetBool() )
			{
				NDebugOverlay::Cross3D( vecSpawnPos, 25.0f, 255, 0, 0, true, 20.0f );
			}
		}
		DeleteRoute( pRoute );
	}
	return false;
}