예제 #1
0
void CASW_Encounter::LoadFromKeyValues( KeyValues *pKeys )
{
	m_SpawnDefs.Purge();

	m_vecPosition.x = pKeys->GetFloat( "PosX" );
	m_vecPosition.y = pKeys->GetFloat( "PosY" );
	m_vecPosition.z = 0;
	m_flEncounterRadius = pKeys->GetFloat( "Radius" );
	for ( KeyValues *pKey = pKeys->GetFirstSubKey(); pKey; pKey = pKey->GetNextKey() )
	{
		if ( !Q_stricmp( pKey->GetName(), "SpawnDef" ) )
		{
			CASW_Spawn_Definition* pSpawnDef = SpawnSelection()->GetSpawnDefByID( pKey->GetInt() );
			if ( pSpawnDef )
			{
				m_SpawnDefs.AddToTail( pSpawnDef );
			}
			else
			{
				Msg( "Failed to load spawn def %d for encounter.\n", pKey->GetInt() );
			}
		}
	}
}
예제 #2
0
void CASWMissionChooserNPCs::InitFixedSpawns( CLayoutSystem *pLayoutSystem, CMapLayout *pLayout )
{
	// init the spawn set for this mission
	KeyValues *pGenerationOptions = pLayout->GetGenerationOptions();
	if ( !pGenerationOptions )
	{
		Warning( "Error placed fixed alien spawns, no generation options in this layout." );
		return;
	}

	bool bChosenSpawnSet = false;
	const char *szNamedSpawnSet = pGenerationOptions->GetString( "AlienSpawnSet" );
	if ( szNamedSpawnSet && szNamedSpawnSet[0] )
	{
		bChosenSpawnSet = SpawnSelection()->SetCurrentSpawnSet( szNamedSpawnSet );
	}

	if ( !bChosenSpawnSet )
	{
		SpawnSelection()->SetCurrentSpawnSet( pGenerationOptions->GetInt( "Difficulty", 5 ) );
	}

	// if we have any rooms with the alien encounter tag, then just use those for fixed spawn locations
	bool bAlienEncounterTag = false;
	int iRooms = pLayout->m_PlacedRooms.Count();
	for ( int i = 0; i < iRooms; i++ )
	{
		CRoom *pRoom = pLayout->m_PlacedRooms[i];
		if ( pRoom && pRoom->m_pRoomTemplate && pRoom->m_pRoomTemplate->HasTag( "AlienEncounter" ) )
		{
			bAlienEncounterTag = true;

			CASW_Encounter *pEncounter = new CASW_Encounter();

			// pick a random spot in this room
			Vector vecWorldMins, vecWorldMaxs;
			pRoom->GetWorldBounds( &vecWorldMins, &vecWorldMaxs );
			Vector vecPos = vecWorldMins + pLayoutSystem->GetRandomFloat( 0, 1 ) * ( vecWorldMaxs - vecWorldMins );
			vecPos.z = 0;
			pEncounter->SetEncounterPosition( vecPos );
			pEncounter->SetEncounterRadius( pLayoutSystem->GetRandomFloat( asw_encounter_radius_min.GetFloat(), asw_encounter_radius_max.GetFloat() ) );

			// add spawn defs
			// TODO: more spawns in bigger rooms? or rooms with higher weights?
			int iSpawnsPerEncounter = pLayoutSystem->GetRandomInt( CurrentSpawnSet()->GetMinSpawnsPerEncounter(), CurrentSpawnSet()->GetMaxSpawnsPerEncounter() );
			for ( int i = 0; i < iSpawnsPerEncounter; i++ )
			{
				CASW_Spawn_Definition* pSpawnDef = CurrentSpawnSet()->GetSpawnDef( ASW_NPC_SPAWN_TYPE_FIXED );
				if ( !pSpawnDef )
					continue;
				pEncounter->AddSpawnDef( pSpawnDef );
			}

			pLayout->m_Encounters.AddToTail( pEncounter );
		}
	}

	if ( bAlienEncounterTag )
	{
		pLayout->MarkEncounterRooms();
		return;
	}

	// find area of the mission
	int iTotalArea = 0;
	for ( int i = 0; i < iRooms; i++ )
	{
		CRoom *pRoom = pLayout->m_PlacedRooms[i];
		iTotalArea += ( pRoom->m_pRoomTemplate->GetTilesX() * ASW_TILE_SIZE ) * ( pRoom->m_pRoomTemplate->GetTilesY() * ASW_TILE_SIZE );
	}

	// decide how many encounters we want
	int iEncounters = pLayoutSystem->GetRandomInt( CurrentSpawnSet()->GetMinEncounters(), CurrentSpawnSet()->GetMaxEncounters() );

	// distance between encounters
	//float flMinDistance = asw_encounters_distance_min.GetFloat();

	// randomly pick rooms for the encounters to be in, using the room weights
	CUtlVector<CRoom*> candidates;
	float flTotalWeight = 0;
	for ( int i = 0; i < iRooms; i++ )
	{
		CRoom *pRoom = pLayout->m_PlacedRooms[i];
		if ( pRoom->GetSpawnWeight() > 0
				&& !pRoom->m_pRoomTemplate->IsEscapeRoom() 
				&& !pRoom->m_pRoomTemplate->IsStartRoom() 
				&& !pRoom->m_pRoomTemplate->IsBorderRoom() )
		{
			flTotalWeight += pRoom->GetSpawnWeight();
			candidates.AddToTail( pRoom );
		}
	}

	for ( int e = 0; e < iEncounters; e++ )
	{
		float flChosen = pLayoutSystem->GetRandomFloat( 0, flTotalWeight );
		CRoom *pChosenRoom = NULL;
		for ( int i = 0; i < candidates.Count(); i++ )
		{
			CRoom *pRoom = candidates[i];
			flChosen -= pRoom->GetSpawnWeight();
			if ( flChosen <= 0 )
			{
				pChosenRoom = pRoom;
				break;
			}
		}

		if ( !pChosenRoom )
			continue;

		CASW_Encounter *pEncounter = new CASW_Encounter();

		// pick a random spot in this room
		Vector vecWorldMins, vecWorldMaxs;
		pChosenRoom->GetWorldBounds( &vecWorldMins, &vecWorldMaxs );
		//Vector vecPos = vecWorldMins + pLayoutSystem->GetRandomFloat( 0, 1 ) * ( vecWorldMaxs - vecWorldMins );
		Vector vecPos = ( vecWorldMins + vecWorldMaxs ) * 0.5f; // center of the room
		vecPos.z = 0;
		pEncounter->SetEncounterPosition( vecPos );
		pEncounter->SetEncounterRadius( pLayoutSystem->GetRandomFloat( asw_encounter_radius_min.GetFloat(), asw_encounter_radius_max.GetFloat() ) );

		// add spawn defs
		// TODO: more spawns in bigger rooms? or rooms with higher weights?
		int iSpawnsPerEncounter = pLayoutSystem->GetRandomInt( CurrentSpawnSet()->GetMinSpawnsPerEncounter(), CurrentSpawnSet()->GetMaxSpawnsPerEncounter() );
		for ( int i = 0; i < iSpawnsPerEncounter; i++ )
		{
			CASW_Spawn_Definition* pSpawnDef = CurrentSpawnSet()->GetSpawnDef( ASW_NPC_SPAWN_TYPE_FIXED );
			if ( !pSpawnDef )
				continue;
			pEncounter->AddSpawnDef( pSpawnDef );
		}

		pLayout->m_Encounters.AddToTail( pEncounter );
	}

	PushEncountersApart( pLayout );
	pLayout->MarkEncounterRooms();
}