#include "cbase.h" #include "asw_spawn_manager.h" #include "asw_arena.h" #include "asw_gamerules.h" #include "asw_game_resource.h" #include "asw_marine_resource.h" #include "asw_marine.h" #include "asw_weapon.h" #include "ai_network.h" #include "ai_networkmanager.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" ConVar asw_arena( "asw_arena", "0", FCVAR_CHEAT, "Will spawn waves of enemies (requires appropriate test map)" ); ConVar asw_arena_quantity_scale( "asw_arena_quantity_scale", "1.0", FCVAR_CHEAT, "Scales number of aliens spawned in arena mode" ); ConVar asw_arena_shuffle_walls( "asw_arena_shuffle_walls", "3", FCVAR_CHEAT, "Shuffle walls after how many waves?" ); ConVar asw_arena_wall_density_min( "asw_arena_wall_density_min", "0.0", FCVAR_CHEAT, "Max density of random wall brushes in arena mode" ); ConVar asw_arena_wall_density_max( "asw_arena_wall_density_max", "0.7", FCVAR_CHEAT, "Max density of random wall brushes in arena mode" ); ConVar asw_arena_waves_per_difficulty( "asw_arena_waves_per_difficulty", "3", FCVAR_CHEAT, "How many waves before difficulty ramps up" ); CASW_Arena g_ASWArena; CASW_Arena* ASWArena() { return &g_ASWArena; } CASW_Arena::CASW_Arena( void ) : CAutoGameSystemPerFrame( "CASW_Arena" ) { InitArenaAlienTypes(); } CASW_Arena::~CASW_Arena() { m_ArenaAliens.PurgeAndDeleteElements(); } bool CASW_Arena::Init() { m_ArenaRestTimer.Invalidate(); m_ArenaCheckTimer.Invalidate(); m_ArenaShuffleWallsTimer.Invalidate(); m_bStartedArenaMode = false; m_iArenaWave = 0; return true; } void CASW_Arena::Shutdown() { } void CASW_Arena::LevelInitPreEntity() { asw_arena.SetValue( Q_strnicmp( STRING(gpGlobals->mapname), "aiarena", 7 ) ? "0" : "1" ); Init(); } void CASW_Arena::FrameUpdatePostEntityThink() { // only think when we're in-game if ( !ASWGameRules() || ASWGameRules()->GetGameState() != ASW_GS_INGAME ) return; if ( asw_arena.GetBool() ) { UpdateArena(); } } void CASW_Arena::InitArenaAlienTypes() { m_ArenaAliens.PurgeAndDeleteElements(); m_ArenaAliens.AddToTail( new CASW_ArenaAlien( "asw_drone", 5, 10 ) ); m_ArenaAliens.AddToTail( new CASW_ArenaAlien( "asw_drone_jumper", 5, 10 ) ); m_ArenaAliens.AddToTail( new CASW_ArenaAlien( "asw_shieldbug", 1, 3 ) ); m_ArenaAliens.AddToTail( new CASW_ArenaAlien( "asw_mortarbug", 1, 5 ) ); m_ArenaAliens.AddToTail( new CASW_ArenaAlien( "asw_parasite", 1, 5 ) ); m_ArenaAliens.AddToTail( new CASW_ArenaAlien( "asw_harvester", 1, 6 ) ); m_ArenaAliens.AddToTail( new CASW_ArenaAlien( "asw_buzzer", 3, 6 ) ); } void CASW_Arena::UpdateArena() { // has arena mode just been turned on? if ( !m_bStartedArenaMode ) { for ( int i=0; i< m_ArenaAliens.Count(); i++ ) { UTIL_PrecacheOther( m_ArenaAliens[i]->m_szAlienClass ); } m_bStartedArenaMode = true; m_ArenaRestTimer.Start( 3.0f ); } if ( m_ArenaShuffleWallsTimer.HasStarted() && m_ArenaShuffleWallsTimer.IsElapsed() ) { TeleportPlayersToSpawn(); ShuffleArenaWalls(); m_ArenaShuffleWallsTimer.Invalidate(); m_ArenaRestTimer.Start( 2.5f ); } if ( m_ArenaRestTimer.HasStarted() && m_ArenaRestTimer.IsElapsed() ) { SpawnArenaWave(); m_ArenaRestTimer.Invalidate(); } if ( m_ArenaCheckTimer.HasStarted() && m_ArenaCheckTimer.IsElapsed() ) { // count live aliens CBaseEntity* pEntity = NULL; int iAliens = 0; while ((pEntity = gEntList.NextEnt( pEntity )) != NULL) { if ( pEntity && pEntity->IsNPC() && pEntity->Classify() != CLASS_ASW_MARINE && pEntity->GetHealth() > 0 ) iAliens++; } if ( iAliens <= 0 && !m_ArenaRestTimer.HasStarted() && !m_ArenaShuffleWallsTimer.HasStarted() ) { RefillMarineAmmo(); if ( asw_arena_shuffle_walls.GetInt() > 0 && ( m_iArenaWave % asw_arena_shuffle_walls.GetInt() ) == 0 && ( m_iArenaWave != 0 ) ) { UTIL_CenterPrintAll( UTIL_VarArgs("Wave %d clear!\nThe arena is changing...", m_iArenaWave ) ); m_ArenaShuffleWallsTimer.Start( 5.0f ); } else { UTIL_CenterPrintAll( UTIL_VarArgs("Wave %d clear!", m_iArenaWave ) ); m_ArenaRestTimer.Start( RandomFloat( 8, 12 ) ); } m_ArenaCheckTimer.Invalidate(); } } } void CASW_Arena::RefillMarineAmmo() { CASW_Game_Resource *pGameResource = ASWGameResource(); for (int i=0;iGetMaxMarineResources();i++) { if (pGameResource->GetMarineResource(i) != NULL && pGameResource->GetMarineResource(i)->GetMarineEntity()) { CASW_Marine *pMarine = pGameResource->GetMarineResource(i)->GetMarineEntity(); for (int k=0;kGetASWWeapon(k); if (!pWeapon) continue; // refill bullets in the gun pWeapon->m_iClip1 = pWeapon->GetMaxClip1(); pWeapon->m_iClip2 = pWeapon->GetMaxClip2(); // give the marine a load of ammo of that type pMarine->GiveAmmo(10000, pWeapon->GetPrimaryAmmoType()); pMarine->GiveAmmo(10000, pWeapon->GetSecondaryAmmoType()); } } } } void CASW_Arena::SpawnArenaWave() { if ( !ASWSpawnManager() ) return; if ( ASWGameRules() ) { ASWGameRules()->BroadcastSound( "Spawner.Horde" ); } // find the 4 corridor spawn points CUtlVector arenaSpawns[4]; int arenaSpawnsUsed[4]; memset( arenaSpawnsUsed, 0, sizeof( arenaSpawnsUsed ) ); CBaseEntity* pEntity = NULL; while ((pEntity = gEntList.FindEntityByClassname( pEntity, "info_target" )) != NULL) { if ( !stricmp( STRING( pEntity->GetEntityName() ), "Spawn_Front" ) ) { arenaSpawns[0].AddToTail( pEntity ); } else if ( !stricmp( STRING( pEntity->GetEntityName() ), "Spawn_Right" ) ) { arenaSpawns[1].AddToTail( pEntity ); } else if ( !stricmp( STRING( pEntity->GetEntityName() ), "Spawn_Below" ) ) { arenaSpawns[2].AddToTail( pEntity ); } else if ( !stricmp( STRING( pEntity->GetEntityName() ), "Spawn_Left" ) ) { arenaSpawns[3].AddToTail( pEntity ); } } Msg( "Found arena spawns: N:%d E:%d S:%d W:%d\n", arenaSpawns[0].Count(), arenaSpawns[1].Count(), arenaSpawns[2].Count(), arenaSpawns[3].Count() ); // decide how many alien types we're going to spawn int iAlienTypes = 2; float fRandom = RandomFloat(); if ( fRandom < 0.1f ) { iAlienTypes = 4; } else if ( fRandom < 0.30f ) { iAlienTypes = 3; } for ( int i=0 ; im_iQuantityMin, m_ArenaAliens[iAlienType]->m_iQuantityMax ); int iArenaLevel = m_iArenaWave / asw_arena_waves_per_difficulty.GetInt(); iQuantity += iArenaLevel; for ( int k=0 ; k < iQuantity ; k++ ) { if ( arenaSpawnsUsed[iDirection] < arenaSpawns[iDirection].Count() ) { CBaseEntity *pSpawnPoint = arenaSpawns[iDirection][arenaSpawnsUsed[iDirection]]; if ( !pSpawnPoint ) continue; if ( ASWSpawnManager()->SpawnAlienAt( m_ArenaAliens[iAlienType]->m_szAlienClass, pSpawnPoint->GetAbsOrigin(), pSpawnPoint->GetAbsAngles() ) ) { arenaSpawnsUsed[iDirection]++; } } } } m_iArenaWave++; } void CASW_Arena::TeleportPlayersToSpawn() { if ( !ASWGameRules() ) return; CBaseEntity *pSpot = NULL; CASW_Game_Resource *pGameResource = ASWGameResource(); for (int i=0;iGetMaxMarineResources();i++) { if (pGameResource->GetMarineResource(i) != NULL && pGameResource->GetMarineResource(i)->GetMarineEntity()) { CASW_Marine *pMarine = pGameResource->GetMarineResource(i)->GetMarineEntity(); if ( pMarine->GetHealth() > 0 ) { pSpot = ASWGameRules()->GetMarineSpawnPoint( pSpot ); if ( pSpot ) { pMarine->Teleport( &pSpot->GetAbsOrigin(), &pSpot->GetAbsAngles(), &vec3_origin ); } } } } } void CASW_Arena::ShuffleArenaWalls() { CUtlVector walls; CBaseEntity* pEntity = NULL; while ((pEntity = gEntList.FindEntityByClassname( pEntity, "func_brush" )) != NULL) { walls.AddToTail(pEntity); } // decide on level density float flDensity = RandomFloat( asw_arena_wall_density_min.GetFloat(), asw_arena_wall_density_max.GetFloat() ); // turn on and off blocks variant_t emptyVariant; for (int i=0;iAcceptInput( "Enable", NULL, NULL, emptyVariant, 0 ); } else { walls[i]->AcceptInput( "Disable", NULL, NULL, emptyVariant, 0 ); } walls[i]->AddFlag( FL_WORLDBRUSH ); walls[i]->SetMoveType( MOVETYPE_NONE ); } g_pAINetworkManager->BuildNetworkGraph(); } void CASW_Arena::Event_AlienKilled( CBaseEntity *pAlien, const CTakeDamageInfo &info ) { if ( asw_arena.GetBool() ) { m_ArenaCheckTimer.Start( 2.0f ); } } void asw_arena_wave_f( const CCommand& args ) { ASWArena()->SpawnArenaWave(); } static ConCommand asw_arena_wave("asw_arena_wave", asw_arena_wave_f, "Creates a wave of aliens on the arena test map", FCVAR_GAMEDLL | FCVAR_CHEAT);