Пример #1
0
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;
}
Пример #2
0
void CASW_Simple_Alien::FindNewEnemy()
{
	float dist;
	CBaseEntity *pNearest = UTIL_ASW_NearestMarine(GetAbsOrigin(), dist);
	if (CanSee(pNearest))
	{
		SetEnemy(pNearest);
	}
}
Пример #3
0
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;
}
Пример #4
0
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 );
            }
        }
    }
}
Пример #5
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;
}
Пример #6
0
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);
		}
	}
}
Пример #8
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;
}