//========= Copyright Valve Corporation, All rights reserved. ============// #include "cbase.h" #ifdef HL2_EPISODIC #include "hl2_gamerules.h" #include "ammodef.h" #include "hl2_shareddefs.h" #include "filesystem.h" #include #ifdef CLIENT_DLL #else #include "player.h" #include "game.h" #include "gamerules.h" #include "teamplay_gamerules.h" #include "hl2_player.h" #include "voice_gamemgr.h" #include "globalstate.h" #include "ai_basenpc.h" #include "weapon_physcannon.h" #include "ammodef.h" #endif #ifdef CLIENT_DLL #define CHalfLife2Survival C_HalfLife2Survival #define CHalfLife2SurvivalProxy C_HalfLife2SurvivalProxy #endif ConVar gamerules_survival( "gamerules_survival", "0", FCVAR_REPLICATED ); class CHalfLife2SurvivalProxy : public CGameRulesProxy { public: DECLARE_CLASS( CHalfLife2SurvivalProxy, CGameRulesProxy ); DECLARE_NETWORKCLASS(); }; class CSurvivalAmmo { public: char m_szAmmoName[256]; int m_iAmount; }; class CSurvivalSettings { public: CSurvivalSettings(); CUtlVector > m_Loadout; int m_iSpawnHealth; string_t m_szPickups; CUtlVector m_Ammo; }; CSurvivalSettings::CSurvivalSettings() { m_iSpawnHealth = 100; } class CHalfLife2Survival : public CHalfLife2 { public: DECLARE_CLASS( CHalfLife2Survival, CHalfLife2 ); #ifdef CLIENT_DLL DECLARE_CLIENTCLASS_NOBASE(); // This makes datatables able to access our private vars. #else DECLARE_SERVERCLASS_NOBASE(); // This makes datatables able to access our private vars. CHalfLife2Survival(); virtual ~CHalfLife2Survival() {} virtual void Think( void ); virtual void PlayerSpawn( CBasePlayer *pPlayer ); virtual bool IsAllowedToSpawn( CBaseEntity *pEntity ); virtual void CreateStandardEntities(); void ReadSurvivalScriptFile( void ); void ParseSurvivalSettings( KeyValues *pSubKey ); void ParseSurvivalAmmo( KeyValues *pSubKey ); private: bool m_bActive; CSurvivalSettings m_SurvivalSettings; #endif }; //----------------------------------------------------------------------------- // Gets us at the Half-Life 2 game rules //----------------------------------------------------------------------------- inline CHalfLife2Survival* HL2SurvivalGameRules() { return static_cast(g_pGameRules); } REGISTER_GAMERULES_CLASS( CHalfLife2Survival ); BEGIN_NETWORK_TABLE_NOBASE( CHalfLife2Survival, DT_HL2SurvivalGameRules ) END_NETWORK_TABLE() LINK_ENTITY_TO_CLASS( hl2_survival_gamerules, CHalfLife2SurvivalProxy ); IMPLEMENT_NETWORKCLASS_ALIASED( HalfLife2SurvivalProxy, DT_HalfLife2SurvivalProxy ) #ifdef CLIENT_DLL void RecvProxy_HL2SurvivalGameRules( const RecvProp *pProp, void **pOut, void *pData, int objectID ) { CHalfLife2Survival *pRules = HL2SurvivalGameRules(); Assert( pRules ); *pOut = pRules; } BEGIN_RECV_TABLE( CHalfLife2SurvivalProxy, DT_HalfLife2SurvivalProxy ) RecvPropDataTable( "hl2_survival_gamerules_data", 0, 0, &REFERENCE_RECV_TABLE( DT_HL2SurvivalGameRules ), RecvProxy_HL2SurvivalGameRules ) END_RECV_TABLE() #else void* SendProxy_HL2SurvivalGameRules( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID ) { CHalfLife2Survival *pRules = HL2SurvivalGameRules(); Assert( pRules ); pRecipients->SetAllRecipients(); return pRules; } BEGIN_SEND_TABLE( CHalfLife2SurvivalProxy, DT_HalfLife2SurvivalProxy ) SendPropDataTable( "hl2_survival_gamerules_data", 0, &REFERENCE_SEND_TABLE( DT_HL2SurvivalGameRules ), SendProxy_HL2SurvivalGameRules ) END_SEND_TABLE() #endif #ifndef CLIENT_DLL CHalfLife2Survival::CHalfLife2Survival() { m_bActive = false; } void CHalfLife2Survival::Think( void ) { } bool CHalfLife2Survival::IsAllowedToSpawn( CBaseEntity *pEntity ) { if ( !m_bActive ) return BaseClass::IsAllowedToSpawn( pEntity ); const char *pPickups = STRING( m_SurvivalSettings.m_szPickups ); if ( !pPickups ) return false; if ( Q_stristr( pPickups, "everything" ) ) return true; if ( Q_stristr( pPickups, pEntity->GetClassname() ) || Q_stristr( pPickups, STRING( pEntity->GetEntityName() ) ) ) return true; return false; } void CHalfLife2Survival::PlayerSpawn( CBasePlayer *pPlayer ) { BaseClass::PlayerSpawn( pPlayer ); if ( !m_bActive ) return; pPlayer->EquipSuit(); pPlayer->SetHealth( m_SurvivalSettings.m_iSpawnHealth ); for ( int i = 0; i < m_SurvivalSettings.m_Loadout.Count(); ++i ) { pPlayer->GiveNamedItem( m_SurvivalSettings.m_Loadout[i] ); } for ( int i = 0; i < m_SurvivalSettings.m_Ammo.Count(); ++i ) { pPlayer->CBasePlayer::GiveAmmo( m_SurvivalSettings.m_Ammo[i].m_iAmount , m_SurvivalSettings.m_Ammo[i].m_szAmmoName ); } } void CHalfLife2Survival::ParseSurvivalSettings( KeyValues *pSubKey ) { if ( pSubKey == NULL ) return; m_SurvivalSettings.m_szPickups = NULL_STRING; m_SurvivalSettings.m_iSpawnHealth = 100; KeyValues *pTestKey = pSubKey->GetFirstSubKey(); while ( pTestKey ) { if ( !stricmp( pTestKey->GetName(), "weapons" ) ) { const char *pLoadout = pTestKey->GetString(); Q_SplitString( pLoadout, ";", m_SurvivalSettings.m_Loadout ); } else if ( !stricmp( pTestKey->GetName(), "spawnhealth" ) ) { m_SurvivalSettings.m_iSpawnHealth = pTestKey->GetInt( NULL, 100 ); } else if ( !stricmp( pTestKey->GetName(), "allowedpickups" ) ) { m_SurvivalSettings.m_szPickups = MAKE_STRING( pTestKey->GetString() ); } pTestKey = pTestKey->GetNextKey(); } } void CHalfLife2Survival::ParseSurvivalAmmo( KeyValues *pSubKey ) { if ( pSubKey ) { KeyValues *pAmmoKey = pSubKey->GetFirstSubKey(); while ( pAmmoKey ) { CSurvivalAmmo ammo; Q_strcpy( ammo.m_szAmmoName, pAmmoKey->GetName() ); ammo.m_iAmount = pAmmoKey->GetInt(); m_SurvivalSettings.m_Ammo.AddToTail( ammo ); pAmmoKey = pAmmoKey->GetNextKey(); } } } void CHalfLife2Survival::ReadSurvivalScriptFile( void ) { char szFullName[512]; Q_snprintf( szFullName, sizeof( szFullName ), "maps/%s_survival.txt", STRING(gpGlobals->mapname) ); KeyValues *pkvFile = new KeyValues( "Survival" ); if ( pkvFile->LoadFromFile( filesystem, szFullName, "MOD" ) ) { ParseSurvivalSettings( pkvFile->FindKey( "settings" ) ); ParseSurvivalAmmo( pkvFile->FindKey( "ammo" ) ); CUtlVector entities; UTIL_LoadAndSpawnEntitiesFromScript( entities, szFullName, "Survival", true ); // It's important to turn on survival mode after we create all the entities // in the script, so that we don't remove them if they violate survival rules. // i.e. we want the player to start with a shotgun, but prevent all future shotguns from spawning. m_bActive = true; } else { m_bActive = false; } } void CHalfLife2Survival::CreateStandardEntities( void ) { ReadSurvivalScriptFile(); } #endif #endif