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