sqwarmed/sdk_src/game/missionchooser/asw_spawn_selection.cpp

369 lines
11 KiB
C++

//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
//
//
//===============================================================================
#include "asw_spawn_selection.h"
#include "filesystem.h"
#include "vstdlib/random.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
int g_nSpawnDefIDs = 0;
const char *g_SpawnTypes[] =
{
"ANY",
"FIXED",
"WANDERER",
"HORDE",
"BOSS",
"PROP",
"SPECIAL1",
"SPECIAL2"
};
int SpawnTypeFromString( const char *szText )
{
int nSpawnTypeCount = ( ( sizeof( g_SpawnTypes ) ) / sizeof( g_SpawnTypes[0] ) );
for ( int i = 0 ; i < nSpawnTypeCount; i++ )
{
if ( !V_stricmp( szText, g_SpawnTypes[i] ) )
return i;
}
return ASW_NPC_SPAWN_TYPE_INVALID;
}
// copies a string
char* ASW_AllocString( const char *szString )
{
if ( !szString )
return NULL;
int len = Q_strlen( szString ) + 1;
if ( len <= 1 )
return NULL;
char *text = new char[ len ];
Q_strncpy( text, szString, len );
return text;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CASW_Spawn_Definition::CASW_Spawn_Definition( int nID )
{
m_flSelectionWeight = 1.0f;
m_nID = nID;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CASW_Spawn_Definition::~CASW_Spawn_Definition()
{
m_Entries.PurgeAndDeleteElements();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CASW_Spawn_Definition::LoadFromKeyValues( KeyValues *pKeys )
{
m_flSelectionWeight = pKeys->GetFloat( "SelectionWeight" );
for ( KeyValues *pKey = pKeys->GetFirstSubKey(); pKey; pKey = pKey->GetNextKey() )
{
if ( !Q_stricmp( pKey->GetName(), "NPC" ) )
{
CASW_Entry *pEntry = new CASW_Entry();
pEntry->m_nMinPerSpawn = pKey->GetInt( "MinPerSpawn", 1 );
pEntry->m_nMaxPerSpawn = pKey->GetInt( "MaxPerSpawn", 1 );
pEntry->m_pszAlienClass = ASW_AllocString( pKey->GetString( "AlienClass" ) );
pEntry->m_bUseSpawners = pKey->GetBool( "UseSpawners" );
m_Entries.AddToTail( pEntry );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CASW_Spawn_Definition::ContainsAlienClass( const char *szAlienClass )
{
for ( int i = 0; i < m_Entries.Count(); i++ )
{
if ( !Q_stricmp( m_Entries[i]->m_pszAlienClass, szAlienClass ) )
return true;
}
return false;
}
void CASW_Spawn_Definition::ListSpawnDef()
{
Msg( "SpawnDef %d\n", GetID() );
for ( int i = 0; i < m_Entries.Count(); i++ )
{
Msg( " Entry %d class = %s min = %d max = %d\n", i, m_Entries[i]->m_pszAlienClass, m_Entries[i]->m_nMinPerSpawn, m_Entries[i]->m_nMaxPerSpawn );
}
}
// ==================================================================
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CASW_Spawn_Set::CASW_Spawn_Set()
{
for ( int i = 0; i < ASW_NPC_SPAWN_TYPE_COUNT; i++ )
{
m_flTotalWeight[i] = 0;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CASW_Spawn_Set::~CASW_Spawn_Set()
{
for ( int t = 0; t < ASW_NPC_SPAWN_TYPE_COUNT; t++ )
{
m_SpawnDefs[t].PurgeAndDeleteElements();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CASW_Spawn_Definition* CASW_Spawn_Set::GetSpawnDef( int nType )
{
int nCount = m_SpawnDefs[nType].Count();
float flChosen = RandomFloat( 0, m_flTotalWeight[nType] );
for ( int i = 0; i < nCount; i++ )
{
flChosen -= m_SpawnDefs[nType][i]->GetSelectionWeight();
if ( flChosen <= 0 )
{
return m_SpawnDefs[nType][i];
}
}
return NULL;
}
CASW_Spawn_Definition* CASW_Spawn_Set::GetSpawnDefByID( int nID )
{
for ( int t = 0; t < ASW_NPC_SPAWN_TYPE_COUNT; t++ )
{
for ( int i = 0; i < m_SpawnDefs[t].Count(); i++ )
{
if ( m_SpawnDefs[t][i]->GetID() == nID )
return m_SpawnDefs[t][i];
}
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CASW_Spawn_Set::LoadFromKeyValues( KeyValues *pKeys )
{
m_iMinDifficulty = pKeys->GetInt( "MinDifficulty" );
m_iMaxDifficulty = pKeys->GetInt( "MaxDifficulty" );
m_flFeederChance = pKeys->GetFloat( "FeederChance" );
m_iMinEncounters = pKeys->GetInt( "MinEncounters" );
m_iMaxEncounters = pKeys->GetInt( "MaxEncounters" );
m_iMinSpawnsPerEncounter = pKeys->GetInt( "MinSpawnsPerEncounter" );
m_iMaxSpawnsPerEncounter = pKeys->GetInt( "MaxSpawnsPerEncounter" );
m_pszSetName = ASW_AllocString( pKeys->GetString( "Name", "Unnamed" ) );
//Msg( "Loaded spawn set %s mindiff=%d maxdiff=%d\n", m_pszSetName, m_iMinDifficulty, m_iMaxDifficulty );
for ( KeyValues *pKey = pKeys->GetFirstSubKey(); pKey; pKey = pKey->GetNextKey() )
{
int nType = SpawnTypeFromString( pKey->GetName() );
if ( nType != ASW_NPC_SPAWN_TYPE_INVALID )
{
CASW_Spawn_Definition *pSpawnDef = new CASW_Spawn_Definition( g_nSpawnDefIDs++ );
pSpawnDef->LoadFromKeyValues( pKey );
m_SpawnDefs[nType].AddToTail( pSpawnDef );
m_flTotalWeight[nType] += pSpawnDef->GetSelectionWeight();
}
}
}
// ==================================================================
extern CASW_Spawn_Selection g_SpawnSelection;
CASW_Spawn_Set* CurrentSpawnSet()
{
return g_SpawnSelection.GetCurrentSpawnSet();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CASW_Spawn_Selection::CASW_Spawn_Selection()
{
m_pSpawnSetKeys = NULL;
m_pCurrentSpawnSet = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CASW_Spawn_Selection::~CASW_Spawn_Selection()
{
Reset();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CASW_Spawn_Selection::Init()
{
Reset();
LoadSpawnSets();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CASW_Spawn_Selection::SetCurrentSpawnSet( int iMissionDifficulty )
{
DevMsg( "[AS] Setting spawn set from mission difficulty %d\n", iMissionDifficulty );
// look through our spawn sets to find any that match the difficulty
CUtlVector<CASW_Spawn_Set*> candidates;
for ( int i = 0; i < m_SpawnSets.Count(); i++ )
{
if ( iMissionDifficulty >= m_SpawnSets[i]->GetMinDifficulty() && iMissionDifficulty <= m_SpawnSets[i]->GetMaxDifficulty() )
{
candidates.AddToTail( m_SpawnSets[i] );
}
}
if ( candidates.Count() <= 0 )
{
Warning( "Failed to SetCurrentSpawnSet by difficulty as couldn't find a default SpawnSelection block which covers this difficulty range. Requested difficulty=%d. Supported difficulties:\n", iMissionDifficulty );
for ( int i = 0; i < m_SpawnSets.Count(); i++ )
{
Msg( "%s Min=%d Max=%d\n", m_SpawnSets[i]->GetSetName(), m_SpawnSets[i]->GetMinDifficulty(), m_SpawnSets[i]->GetMaxDifficulty() );
}
return;
}
m_pCurrentSpawnSet = candidates[ RandomInt( 0, candidates.Count() - 1 ) ];
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CASW_Spawn_Selection::SetCurrentSpawnSet( const char *szSetName )
{
m_pCurrentSpawnSet = GetSpawnSet( szSetName );
return m_pCurrentSpawnSet != NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CASW_Spawn_Definition* CASW_Spawn_Selection::GetSpawnDefByID( int nID )
{
CASW_Spawn_Definition *pDef = NULL;
for ( int i = 0; i < m_SpawnSets.Count(); i++ )
{
pDef = m_SpawnSets[i]->GetSpawnDefByID( nID );
if ( pDef )
return pDef;
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CASW_Spawn_Selection::DumpCurrentSpawnSet()
{
if ( !m_pCurrentSpawnSet )
{
Msg( "No current spawn set!\n");
return;
}
Msg( "Current spawn set: %s Feeder chance: %f\n", m_pCurrentSpawnSet->GetSetName(), m_pCurrentSpawnSet->GetFeederChance() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CASW_Spawn_Set* CASW_Spawn_Selection::GetSpawnSet( const char *szSetName )
{
for ( int i = 0; i < m_SpawnSets.Count(); i++ )
{
if ( !Q_stricmp( m_SpawnSets[i]->GetSetName(), szSetName ) )
{
return m_SpawnSets[i];
}
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CASW_Spawn_Selection::LoadSpawnSets()
{
g_nSpawnDefIDs = 0;
m_pSpawnSetKeys = new KeyValues( "DefaultSpawnSets" );
//Msg( "LoadSpawnSets\n" );
if ( !m_pSpawnSetKeys->LoadFromFile( g_pFullFileSystem, "resource/alien_selection.txt", "GAME" ) )
{
Warning( "Error loading resource/alien_selections.txt\n" );
}
for ( KeyValues *pKey = m_pSpawnSetKeys; pKey; pKey = pKey->GetNextKey() )
{
if ( !Q_stricmp( pKey->GetName(), "SpawnSet" ) )
{
CASW_Spawn_Set *pSet = new CASW_Spawn_Set();
pSet->LoadFromKeyValues( pKey );
if ( !m_pCurrentSpawnSet )
{
m_pCurrentSpawnSet = pSet;
}
m_SpawnSets.AddToTail( pSet );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CASW_Spawn_Selection::Reset()
{
m_SpawnSets.PurgeAndDeleteElements();
if ( m_pSpawnSetKeys )
{
m_pSpawnSetKeys->deleteThis();
m_pSpawnSetKeys = NULL;
}
m_pCurrentSpawnSet = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *szName -
// Output : Returns true on success
//-----------------------------------------------------------------------------
bool CASW_Spawn_Selection::IsAvailableNPC( const char *szName )
{
return true;
}