Beispiel #1
0
bool CASW_AI_Senses::SwarmSenseEntity( CBaseEntity *pSightEnt )
{
	IASW_Spawnable_NPC* pAlienOuter = dynamic_cast<IASW_Spawnable_NPC*>(GetOuter());
	if (!pAlienOuter)
		return false;

	pAlienOuter->OnSwarmSenseEntity( pSightEnt );

	// insert at the head of my sight list
	NoteSeenEntity( pSightEnt );

	return true;
}
CBaseEntity* CASW_Spawn_Manager::SpawnAlienAt(const char* szAlienClass, const Vector& vecPos, const QAngle &angle)
{	
	CBaseEntity	*pEntity = NULL;	
	pEntity = CreateEntityByName( szAlienClass );
	CAI_BaseNPC	*pNPC = dynamic_cast<CAI_BaseNPC*>(pEntity);

	if ( pNPC )
	{
		pNPC->AddSpawnFlags( SF_NPC_FALL_TO_GROUND );		
	}

	// Strip pitch and roll from the spawner's angles. Pass only yaw to the spawned NPC.
	QAngle angles = angle;
	angles.x = 0.0;
	angles.z = 0.0;	
	pEntity->SetAbsOrigin( vecPos );	
	pEntity->SetAbsAngles( angles );

	IASW_Spawnable_NPC* pSpawnable = dynamic_cast<IASW_Spawnable_NPC*>(pEntity);
	ASSERT(pSpawnable);	
	if ( !pSpawnable )
	{
		Warning("NULL Spawnable Ent in CASW_Spawn_Manager::SpawnAlienAt! AlienClass = %s\n", szAlienClass);
		UTIL_Remove(pEntity);
		return NULL;
	}

	// have drones unburrow by default, so we don't worry so much about them spawning onscreen
	if ( !Q_strcmp( szAlienClass, "asw_drone" ) )
	{			
		pSpawnable->StartBurrowed();
		pSpawnable->SetUnburrowIdleActivity( NULL_STRING );
		pSpawnable->SetUnburrowActivity( NULL_STRING );
	}

	DispatchSpawn( pEntity );	
	pEntity->Activate();	

	// give our aliens the orders
	pSpawnable->SetAlienOrders(AOT_MoveToNearestMarine, vec3_origin, NULL);

	// reactivedrop: fixed horde aliens falling through floor and stuck in walls
	// by moving this function call to the bottom of SpawnAlienAt()
	
	// riflemod: temporary comment to test whether parasites fall throught floor 
	//UTIL_DropToFloor(pEntity, MASK_SOLID);

	return pEntity;
}
Beispiel #3
0
void CASW_AI_Senses::SwarmSense(int iDistance)
{
	IASW_Spawnable_NPC* pAlienOuter = dynamic_cast<IASW_Spawnable_NPC*>(GetOuter());
	if (!pAlienOuter)
		return;

	if ( m_TimeLastSwarmSense != gpGlobals->curtime || m_LastSwarmSenseDist != iDistance )
	{		
		SwarmSenseMarines(iDistance);
				
		m_LastSwarmSenseDist = iDistance;
		m_TimeLastSwarmSense = gpGlobals->curtime;
	}
	
	pAlienOuter->OnSwarmSensed( iDistance );
}
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;
			}
		}
	}
}
bool CASW_Base_Spawner::CanSpawn( const Vector &vecHullMins, const Vector &vecHullMaxs )
{
	if ( !m_bEnabled )
		return false;

	// is a marine too near?
	if ( !m_bSpawnIfMarinesAreNear && m_flNearDistance > 0 )
	{		
		CASW_Game_Resource* pGameResource = ASWGameResource();
		float distance = 0.0f;
		for ( int i = 0; i < ASW_MAX_MARINE_RESOURCES; i++ )
		{
			CASW_Marine_Resource* pMR = pGameResource->GetMarineResource(i);
			if ( pMR && pMR->GetMarineEntity() && pMR->GetMarineEntity()->GetHealth() > 0 )
			{
				distance = pMR->GetMarineEntity()->GetAbsOrigin().DistTo( GetAbsOrigin() );
				if ( distance < m_flNearDistance )
				{
					if ( asw_debug_spawners.GetBool() )
						Msg("asw_spawner(%s): Alien can't spawn because a marine (%d) is %f away\n", GetEntityName(), i, distance);
					return false;
				}
			}
		}
	}

	Vector mins = GetAbsOrigin() - Vector( 23, 23, 0 );
	Vector maxs = GetAbsOrigin() + Vector( 23, 23, 0 );
	CBaseEntity *pList[128];
	int count = UTIL_EntitiesInBox( pList, 128, mins, maxs, FL_CLIENT|FL_NPC );
	if ( count )
	{
		//Iterate through the list and check the results
		for ( int i = 0; i < count; i++ )
		{
			//Don't build on top of another entity
			if ( pList[i] == NULL )
				continue;

			//If one of the entities is solid, then we may not be able to spawn now
			if ( ( pList[i]->GetSolidFlags() & FSOLID_NOT_SOLID ) == false )
			{
				// Since the outer method doesn't work well around striders on account of their huge bounding box.
				// Find the ground under me and see if a human hull would fit there.
				trace_t tr;
				UTIL_TraceHull( GetAbsOrigin() + Vector( 0, 0, 1 ),
								GetAbsOrigin() - Vector( 0, 0, 1 ),
								vecHullMins,
								vecHullMaxs,
								MASK_NPCSOLID,
								NULL,
								COLLISION_GROUP_NONE,
								&tr );

				if (tr.fraction < 1.0f && tr.DidHitNonWorldEntity())
				{
					// some non-world entity is blocking the spawn point, so don't spawn
					if (tr.m_pEnt)
					{
						if ( m_iMoveAsideCount < 6 )	// don't send 'move aside' commands more than 5 times in a row, else you'll stop blocked NPCs going to sleep.
						{
							IASW_Spawnable_NPC *pSpawnable = dynamic_cast<IASW_Spawnable_NPC*>(tr.m_pEnt);
							if (pSpawnable)
							{
								pSpawnable->MoveAside();		// try and make him move aside
								m_iMoveAsideCount++;
							}
						}
						if (asw_debug_spawners.GetBool())
							Msg("asw_spawner(%s): Alien can't spawn because a non-world entity is blocking the spawn point: %s\n", GetEntityName(), tr.m_pEnt->GetClassname());
					}
					else
					{
						if (asw_debug_spawners.GetBool())
							Msg("asw_spawner(%s): Alien can't spawn because a non-world entity is blocking the spawn point.\n", GetEntityName());
					}
						
					return false;
				}
			}
		}
	}

	// is there something blocking the spawn point?
	if ( m_bCheckSpawnIsClear )
	{
		if ( asw_debug_spawners.GetBool() )
		{
			Msg("Checking spawn is clear...\n");
		}

		trace_t tr;
		UTIL_TraceHull( GetAbsOrigin(),
					GetAbsOrigin() + Vector( 0, 0, 1 ),
					vecHullMins,
					vecHullMaxs,
					MASK_NPCSOLID,
					this,
					COLLISION_GROUP_NONE,
					&tr );

		if( tr.fraction != 1.0 )
		{
			if ( asw_debug_spawners.GetBool() )
				Msg("asw_spawner(%s): Alien can't spawn because he wouldn't fit in the spawn point.\n", GetEntityName());
			// TODO: If we were trying to spawn an uber, change to spawning a regular instead
			return false;
		}
	}

	m_iMoveAsideCount = 0;
	return true;
}
IASW_Spawnable_NPC* CASW_Base_Spawner::SpawnAlien( const char *szAlienClassName, const Vector &vecHullMins, const Vector &vecHullMaxs )
{
	if ( !IsValidOnThisSkillLevel() )
	{
		UTIL_Remove(this);		// delete ourself if this spawner isn't valid on this difficulty level
		return NULL;
	}

	if ( !CanSpawn( vecHullMins, vecHullMaxs ) )	// this may turn off m_bCurrentlySpawningUber if there's no room
		return NULL;

	CBaseEntity	*pEntity = CreateEntityByName( szAlienClassName );
	if ( !pEntity )
	{
		Msg( "Failed to spawn %s\n", szAlienClassName );
		return NULL;
	}

	CAI_BaseNPC	*pNPC = pEntity->MyNPCPointer();
	if ( pNPC )
	{
		pNPC->AddSpawnFlags( SF_NPC_FALL_TO_GROUND );		
	}

	// check if he can see far
	if ( m_bLongRangeNPC )
		pEntity->AddSpawnFlags( SF_NPC_LONG_RANGE );

	if ( HasSpawnFlags( ASW_SF_NEVER_SLEEP ) )
		pEntity->AddSpawnFlags( SF_NPC_ALWAYSTHINK );

	// Strip pitch and roll from the spawner's angles. Pass only yaw to the spawned NPC.
	QAngle angles = GetAbsAngles();
	angles.x = 0.0;
	angles.z = 0.0;	
	pEntity->SetAbsOrigin( GetAbsOrigin() );	
	pEntity->SetAbsAngles( angles );

	IASW_Spawnable_NPC* pSpawnable = dynamic_cast<IASW_Spawnable_NPC*>(pEntity);
	Assert( pSpawnable );	
	if ( !pSpawnable )
	{
		Warning( "NULL Spawnable Ent in asw_spawner! AlienClass = %s\n", szAlienClassName );
		UTIL_Remove( pEntity );
		return NULL;
	}
	m_flLastSpawnTime = gpGlobals->curtime;
	if ( m_bStartBurrowed )
	{
		pSpawnable->StartBurrowed();
	}

	if ( m_bStartBurrowed )
	{
		pSpawnable->SetUnburrowIdleActivity( m_UnburrowIdleActivity );
		pSpawnable->SetUnburrowActivity( m_UnburrowActivity );
	}

	DispatchSpawn( pEntity );	

	pEntity->SetOwnerEntity( this );
	pEntity->Activate();

	if ( m_AlienName != NULL_STRING )
	{
		pEntity->SetName( m_AlienName );
	}
	
	pSpawnable->SetSpawner( this );

	RemoveObstructingProps( pEntity );	
	
	// give our aliens the orders
	pSpawnable->SetAlienOrders( m_AlienOrders, vec3_origin, GetOrderTarget() );

	m_OnSpawned.FireOutput(pEntity, this);

	return pSpawnable;
}
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;
}
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;
}