bool CASW_Spawn_Manager::AddHorde( int iHordeSize ) { m_iHordeToSpawn = iHordeSize; if ( m_vecHordePosition == vec3_origin ) { if ( !FindHordePosition() ) { Msg("Error: Failed to find horde position\n"); return false; } else { if ( asw_director_debug.GetBool() ) { NDebugOverlay::Cross3D( m_vecHordePosition, 50.0f, 255, 128, 0, true, 60.0f ); float flDist; CASW_Marine *pMarine = UTIL_ASW_NearestMarine( m_vecHordePosition, flDist ); if ( pMarine ) { NDebugOverlay::Line( pMarine->GetAbsOrigin(), m_vecHordePosition, 255, 128, 0, true, 60.0f ); } } } } return true; }
void CASW_Simple_Alien::FindNewEnemy() { float dist; CBaseEntity *pNearest = UTIL_ASW_NearestMarine(GetAbsOrigin(), dist); if (CanSee(pNearest)) { SetEnemy(pNearest); } }
bool CASW_Spawn_Manager::FindHordePosition() { // need to find a suitable place from which to spawn a horde // this place should: // - be far enough away from the marines so the whole horde can spawn before the marines get there // - should have a clear path to the marines UpdateCandidateNodes(); // decide if the horde 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 ) { if ( asw_director_debug.GetBool() ) { Msg( " Failed to find horde pos as there are no candidate nodes\n" ); } return false; } 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( CANDIDATE_ALIEN_HULL ), flDistance )); if ( !pMarine ) { if ( asw_director_debug.GetBool() ) { Msg( " Failed to find horde pos as there is no nearest marine\n" ); } 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.GetInt() >= 2 ) { Msg( " Discarding horde node %d as there's no route.\n", iChosen ); } continue; } if ( bNorth && UTIL_ASW_DoorBlockingRoute( pRoute, true ) ) { if ( asw_director_debug.GetInt() >= 2 ) { Msg( " Discarding horde node %d as there's a door in the way.\n", iChosen ); } DeleteRoute( pRoute ); continue; } m_vecHordePosition = pNode->GetPosition( CANDIDATE_ALIEN_HULL ) + Vector( 0, 0, 32 ); // spawn facing the nearest marine Vector vecDir = pMarine->GetAbsOrigin() - m_vecHordePosition; vecDir.z = 0; vecDir.NormalizeInPlace(); VectorAngles( vecDir, m_angHordeAngle ); if ( asw_director_debug.GetInt() >= 2 ) { Msg( " Accepting horde node %d.\n", iChosen ); } DeleteRoute( pRoute ); return true; } if ( asw_director_debug.GetBool() ) { Msg( " Failed to find horde pos as we tried 3 times to build routes to possible locations, but failed\n" ); } return false; }
void CASW_Spawn_Manager::UpdateCandidateNodes() { // don't update too frequently if ( m_CandidateUpdateTimer.HasStarted() && !m_CandidateUpdateTimer.IsElapsed() ) return; m_CandidateUpdateTimer.Start( asw_candidate_interval.GetFloat() ); if ( !GetNetwork() || !GetNetwork()->NumNodes() ) { m_vecHordePosition = vec3_origin; if ( asw_director_debug.GetBool() ) Msg("Error: Can't spawn hordes as this map has no node network\n"); return; } CASW_Game_Resource *pGameResource = ASWGameResource(); if ( !pGameResource ) return; Vector vecSouthMarine = vec3_origin; Vector vecNorthMarine = vec3_origin; for ( int i=0; i<pGameResource->GetMaxMarineResources(); i++ ) { CASW_Marine_Resource *pMR = pGameResource->GetMarineResource(i); if ( !pMR ) continue; CASW_Marine *pMarine = pMR->GetMarineEntity(); if ( !pMarine || pMarine->GetHealth() <= 0 ) continue; if ( vecSouthMarine == vec3_origin || vecSouthMarine.y > pMarine->GetAbsOrigin().y ) { vecSouthMarine = pMarine->GetAbsOrigin(); } if ( vecNorthMarine == vec3_origin || vecNorthMarine.y < pMarine->GetAbsOrigin().y ) { vecNorthMarine = pMarine->GetAbsOrigin(); } } if ( vecSouthMarine == vec3_origin || vecNorthMarine == vec3_origin ) // no live marines return; int iNumNodes = GetNetwork()->NumNodes(); m_northCandidateNodes.Purge(); m_southCandidateNodes.Purge(); for ( int i=0 ; i<iNumNodes; i++ ) { CAI_Node *pNode = GetNetwork()->GetNode( i ); if ( !pNode || pNode->GetType() != NODE_GROUND ) continue; Vector vecPos = pNode->GetPosition( CANDIDATE_ALIEN_HULL ); // find the nearest marine to this node float flDistance = 0; CASW_Marine *pMarine = dynamic_cast<CASW_Marine*>(UTIL_ASW_NearestMarine( vecPos, flDistance )); if ( !pMarine ) return; if ( flDistance > asw_horde_max_distance.GetFloat() || flDistance < asw_horde_min_distance.GetFloat() ) continue; // check node isn't in an exit trigger 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; if ( vecPos.y >= vecSouthMarine.y ) { if ( asw_director_debug.GetInt() == 3 ) { NDebugOverlay::Box( vecPos, -Vector( 5, 5, 5 ), Vector( 5, 5, 5 ), 32, 32, 128, 10, 60.0f ); } m_northCandidateNodes.AddToTail( i ); } if ( vecPos.y <= vecNorthMarine.y ) { m_southCandidateNodes.AddToTail( i ); if ( asw_director_debug.GetInt() == 3 ) { NDebugOverlay::Box( vecPos, -Vector( 5, 5, 5 ), Vector( 5, 5, 5 ), 128, 32, 32, 10, 60.0f ); } } } }
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; }
void CASW_Button_Area::ActivateUseIcon( CASW_Marine* pMarine, int nHoldType ) { if ( nHoldType == ASW_USE_HOLD_START ) return; // player has used this item //Msg("Player has activated a button area\n"); if ( !HasPower() || !ASWGameResource() ) { // todo: launch a window on the client saying there's no power, or whatever message is desired //Msg("We don't have the power cap'n\n"); return; } if ( m_bIsLocked ) { if ( pMarine->GetMarineProfile()->CanHack() ) { // can hack, get the player to launch his hacking window if ( !m_bIsInUse ) { if ( pMarine->StartUsing(this) ) { if ( GetHackProgress() <= 0 && pMarine->GetMarineResource() ) { pMarine->GetMarineResource()->m_iDamageTakenDuringHack = 0; } m_iAliensKilledBeforeHack = ASWGameResource()->GetAliensKilledInThisMission(); m_OnButtonHackStarted.FireOutput( pMarine, this ); if ( !asw_simple_hacking.GetBool() && pMarine->IsInhabited() ) { if ( !GetCurrentHack() ) // if we haven't created a hack object for this computer yet, then create one { m_hDoorHack = (CASW_Hack_Wire_Tile*) CreateEntityByName( "asw_hack_wire_tile" ); } if ( GetCurrentHack() ) { GetCurrentHack()->InitHack( pMarine->GetCommander(), pMarine, this ); } } if ( m_iHackLevel > 20 ) { pMarine->GetMarineSpeech()->Chatter( CHATTER_HACK_LONG_STARTED ); } else { pMarine->GetMarineSpeech()->Chatter( CHATTER_HACK_STARTED ); } } } else { if ( pMarine->m_hUsingEntity.Get() == this ) { pMarine->StopUsing(); } //Msg("Panel already in use"); } //Msg("Unlocked button\n"); // test hack puzzle so far /* m_hDoorHack = (CASW_Hack_Door*) CreateEntityByName( "asw_hack_door" ); if (GetCurrentHack()) { //for (int i=0;i<10;i++) //{ GetCurrentHack()->InitHack(pPlayer, pMarine, this); GetCurrentHack()->BuildPuzzle(7); GetCurrentHack()->ShowPuzzleStatus(); //} } */ } else { // can't hack (play some access denied sound) //Msg("Access denied\n"); EmitSound("ASWComputer.AccessDenied"); // check for a nearby AI tech marine float flMarineDistance; CASW_Marine *pTech = UTIL_ASW_NearestMarine( WorldSpaceCenter(), flMarineDistance, MARINE_CLASS_TECH, true ); if ( pTech && flMarineDistance < asw_tech_order_hack_range.GetFloat() ) { //Msg( "Told tech to hack panel\n" ); pTech->OrderHackArea( this ); } return; } } else { if ( pMarine ) { pMarine->GetMarineSpeech()->Chatter(CHATTER_USE); } ActivateUnlockedButton( pMarine ); } }
//----------------------------------------------------------------------------- // Purpose: Touch function. Activates the trigger. // Input : pOther - The thing that touched us. //----------------------------------------------------------------------------- void CASW_Jump_Trigger::VolumeTouch(CBaseEntity *pOther) { CASW_Alien_Jumper *pJumper = dynamic_cast<CASW_Alien_Jumper*>(pOther); if (pJumper && ( pJumper->CapabilitiesGet() & bits_CAP_MOVE_JUMP ) && !pJumper->IsJumping() && ( pJumper->GetFlags() & FL_ONGROUND ) ) { bool bJumped = false; if ( m_bForceJump && m_fForceSpeed != 0 ) { Vector vecVelocity; AngleVectors( m_ForceAngle, &vecVelocity ); vecVelocity *= m_fForceSpeed; bJumped = pJumper->DoForcedJump( vecVelocity ); } else { // pick a jump dest int iChosen = random->RandomInt(0, m_iNumJumpDests-1); if (!ReasonableJump(pJumper, iChosen)) { // the dest was blocked, so we're going to just go and try all our dests iChosen = -1; for (int i=0;i<m_iNumJumpDests;i++) { if (ReasonableJump(pJumper, i)) { iChosen = i; break; } } if (iChosen == -1) // all dests blocked return; } // don't jump if a marine is too near us float marine_distance = 0; CASW_Marine *pMarine = UTIL_ASW_NearestMarine(pJumper->GetAbsOrigin(), marine_distance); if (pMarine && marine_distance < m_fMinMarineDistance) { return; } bJumped = pJumper->DoJumpTo(m_vecJumpDestination[iChosen]); if ( !bJumped ) { bool bHasOrders = ( pJumper->m_AlienOrders != AOT_None ); if ( m_bRetryFailedJumps && !bHasOrders ) // don't stop and wait for retry if we're still moving somewhere pJumper->WaitAndRetryJump( m_vecJumpDestination[iChosen] ); } } // start to jump pJumper->m_bTriggerJumped = true; // clear the jumpers previous orders if ( bJumped && m_bClearOrders ) { pJumper->SetAlienOrders(AOT_None, vec3_origin, NULL); } } }
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; }