//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: Precaches and defs for entities and other data that must always be available. // //=========================================================================== #include "cbase.h" #include "soundent.h" #include "client.h" #include "decals.h" #include "editor_sendcommand.h" #include "EnvMessage.h" #include "player.h" #include "gamerules.h" #include "teamplay_gamerules.h" #include "physics.h" #include "isaverestore.h" #include "activitylist.h" #include "eventlist.h" #include "eventqueue.h" #include "ai_network.h" #include "ai_schedule.h" #include "ai_networkmanager.h" #include "ai_utils.h" #include "basetempentity.h" #include "world.h" #include "mempool.h" #include "igamesystem.h" #include "engine/IEngineSound.h" #include "globals.h" #include "engine/IStaticPropMgr.h" #include "particle_parse.h" #include "globalstate.h" #include "cvisibilitymonitor.h" #include "model_types.h" #include "vscript/ivscript.h" #include "vscript_server.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" extern CBaseEntity *g_pLastSpawn; void InitBodyQue(void); extern void W_Precache(void); extern void ActivityList_Free( void ); extern CUtlMemoryPool g_EntityListPool; #define SF_DECAL_NOTINDEATHMATCH 2048 #if !defined( CLIENT_DLL ) #define SF_GAME_EVENT_PROXY_AUTO_VISIBILITY 1 //========================================================= // Allows level designers to generate certain game events // from entity i/o. //========================================================= class CInfoGameEventProxy : public CPointEntity { private: string_t m_iszEventName; float m_flRange; public: DECLARE_CLASS( CInfoGameEventProxy, CPointEntity ); void Spawn(); int UpdateTransmitState(); void InputGenerateGameEvent( inputdata_t &inputdata ); static bool GameEventProxyCallback( CBaseEntity *pProxy, CBasePlayer *pViewingPlayer ); DECLARE_DATADESC(); }; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CInfoGameEventProxy::Spawn() { BaseClass::Spawn(); m_flRange *= 12.0f; // Convert feet to inches if( GetSpawnFlags() & SF_GAME_EVENT_PROXY_AUTO_VISIBILITY ) { VisibilityMonitor_AddEntity( this, m_flRange, &CInfoGameEventProxy::GameEventProxyCallback, NULL ); } } //----------------------------------------------------------------------------- // Purpose: Always transmitted to clients //----------------------------------------------------------------------------- int CInfoGameEventProxy::UpdateTransmitState() { return SetTransmitState( FL_EDICT_ALWAYS ); } //--------------------------------------------------------- //--------------------------------------------------------- void CInfoGameEventProxy::InputGenerateGameEvent( inputdata_t &inputdata ) { CBasePlayer *pActivator = ToBasePlayer( inputdata.pActivator ); IGameEvent *event = gameeventmanager->CreateEvent( m_iszEventName.ToCStr() ); if ( event ) { if ( pActivator ) { event->SetInt( "userid", pActivator->GetUserID() ); } event->SetInt( "subject", entindex() ); gameeventmanager->FireEvent( event ); } } //--------------------------------------------------------- // Callback for the visibility monitor. //--------------------------------------------------------- bool CInfoGameEventProxy::GameEventProxyCallback( CBaseEntity *pProxy, CBasePlayer *pViewingPlayer ) { CInfoGameEventProxy *pProxyPtr = dynamic_cast (pProxy); if( !pProxyPtr ) return true; IGameEvent * event = gameeventmanager->CreateEvent( pProxyPtr->m_iszEventName.ToCStr() ); if ( event ) { event->SetInt( "userid", pViewingPlayer->GetUserID() ); event->SetInt( "subject", pProxyPtr->entindex() ); gameeventmanager->FireEvent( event ); } return false; } LINK_ENTITY_TO_CLASS( info_game_event_proxy, CInfoGameEventProxy ); BEGIN_DATADESC( CInfoGameEventProxy ) DEFINE_KEYFIELD( m_iszEventName, FIELD_STRING, "event_name" ), DEFINE_KEYFIELD( m_flRange, FIELD_FLOAT, "range" ), DEFINE_INPUTFUNC( FIELD_STRING, "GenerateGameEvent", InputGenerateGameEvent ), END_DATADESC() #endif class CDecal : public CPointEntity { public: DECLARE_CLASS( CDecal, CPointEntity ); void Spawn( void ); bool KeyValue( const char *szKeyName, const char *szValue ); // Need to apply static decals here to get them into the signon buffer for the server appropriately virtual void Activate(); void TriggerDecal( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); // Input handlers. void InputActivate( inputdata_t &inputdata ); CBaseEntity *GetDecalEntityAndPosition( Vector *pPosition, bool bStatic ); DECLARE_DATADESC(); public: int m_nTexture; bool m_bLowPriority; string_t m_entityName; private: void StaticDecal( void ); }; BEGIN_DATADESC( CDecal ) DEFINE_FIELD( m_nTexture, FIELD_INTEGER ), DEFINE_KEYFIELD( m_bLowPriority, FIELD_BOOLEAN, "LowPriority" ), // Don't mark as FDECAL_PERMANENT so not save/restored and will be reused on the client preferentially DEFINE_KEYFIELD( m_entityName, FIELD_STRING, "ApplyEntity" ), // Force apply to this entity instead of tracing // Function pointers DEFINE_FUNCTION( StaticDecal ), DEFINE_FUNCTION( TriggerDecal ), DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ), END_DATADESC() LINK_ENTITY_TO_CLASS( infodecal, CDecal ); // UNDONE: These won't get sent to joining players in multi-player void CDecal::Spawn( void ) { if ( m_nTexture < 0 || (gpGlobals->deathmatch && HasSpawnFlags( SF_DECAL_NOTINDEATHMATCH )) ) { UTIL_Remove( this ); return; } } void CDecal::Activate() { BaseClass::Activate(); if ( !GetEntityName() ) { StaticDecal(); } else { // if there IS a targetname, the decal sprays itself on when it is triggered. SetThink ( &CDecal::SUB_DoNothing ); SetUse(&CDecal::TriggerDecal); } } class CTraceFilterValidForDecal : public CTraceFilterSimple { public: CTraceFilterValidForDecal(const IHandleEntity *passentity, int collisionGroup ) : CTraceFilterSimple( passentity, collisionGroup ) { } virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) { static const char *ppszIgnoredClasses[] = { "weapon_*", "item_*", "prop_ragdoll", "prop_dynamic", "prop_static", "prop_physics", "npc_bullseye", // Tracker 15335 }; CBaseEntity *pEntity = EntityFromEntityHandle( pServerEntity ); // Tracker 15335: Never impact decals against entities which are not rendering, either. if ( pEntity->IsEffectActive( EF_NODRAW ) ) return false; for ( int i = 0; i < ARRAYSIZE(ppszIgnoredClasses); i++ ) { if ( pEntity->ClassMatches( ppszIgnoredClasses[i] ) ) return false; } if ( modelinfo->GetModelType( pEntity->GetModel() ) != mod_brush ) return false; return CTraceFilterSimple::ShouldHitEntity( pServerEntity, contentsMask ); } }; CBaseEntity *CDecal::GetDecalEntityAndPosition( Vector *pPosition, bool bStatic ) { CBaseEntity *pEntity = NULL; if ( !m_entityName ) { trace_t trace; Vector start = GetAbsOrigin(); Vector direction(1,1,1); if ( GetAbsAngles() == vec3_angle ) { start -= direction * 5; } else { GetVectors( &direction, NULL, NULL ); } Vector end = start + direction * 10; if ( bStatic ) { CTraceFilterValidForDecal traceFilter( this, COLLISION_GROUP_NONE ); UTIL_TraceLine( start, end, MASK_SOLID, &traceFilter, &trace ); } else { UTIL_TraceLine( start, end, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trace ); } if ( trace.DidHitNonWorldEntity() ) { *pPosition = trace.endpos; return trace.m_pEnt; } } else { pEntity = gEntList.FindEntityByName( NULL, m_entityName ); } *pPosition = GetAbsOrigin(); return pEntity; } void CDecal::TriggerDecal ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { // this is set up as a USE function for info_decals that have targetnames, so that the // decal doesn't get applied until it is fired. (usually by a scripted sequence) trace_t trace; int entityIndex; Vector position; CBaseEntity *pEntity = GetDecalEntityAndPosition(&position, false); entityIndex = pEntity ? pEntity->entindex() : 0; CBroadcastRecipientFilter filter; te->BSPDecal( filter, 0.0, &position, entityIndex, m_nTexture ); SetThink( &CDecal::SUB_Remove ); SetNextThink( gpGlobals->curtime + 0.1f ); } void CDecal::InputActivate( inputdata_t &inputdata ) { TriggerDecal( inputdata.pActivator, inputdata.pCaller, USE_ON, 0 ); } void CDecal::StaticDecal( void ) { Vector position; CBaseEntity *pEntity = GetDecalEntityAndPosition(&position, true); int entityIndex = 0; int modelIndex = 0; if ( pEntity ) { entityIndex = pEntity->entindex(); modelIndex = pEntity->GetModelIndex(); Vector worldspace = position; VectorITransform( worldspace, pEntity->EntityToWorldTransform(), position ); } else { position = GetAbsOrigin(); } engine->StaticDecal( position, m_nTexture, entityIndex, modelIndex, m_bLowPriority ); SUB_Remove(); } bool CDecal::KeyValue( const char *szKeyName, const char *szValue ) { if (FStrEq(szKeyName, "texture")) { // FIXME: should decals all be preloaded? m_nTexture = UTIL_PrecacheDecal( szValue, true ); // Found if (m_nTexture >= 0 ) return true; Warning( "Can't find decal %s\n", szValue ); } else { return BaseClass::KeyValue( szKeyName, szValue ); } return true; } //----------------------------------------------------------------------------- // Purpose: Projects a decal against a prop //----------------------------------------------------------------------------- class CProjectedDecal : public CPointEntity { public: DECLARE_CLASS( CProjectedDecal, CPointEntity ); void Spawn( void ); bool KeyValue( const char *szKeyName, const char *szValue ); // Need to apply static decals here to get them into the signon buffer for the server appropriately virtual void Activate(); void TriggerDecal( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); // Input handlers. void InputActivate( inputdata_t &inputdata ); DECLARE_DATADESC(); public: int m_nTexture; float m_flDistance; private: void ProjectDecal( CRecipientFilter& filter ); void StaticDecal( void ); }; BEGIN_DATADESC( CProjectedDecal ) DEFINE_FIELD( m_nTexture, FIELD_INTEGER ), DEFINE_KEYFIELD( m_flDistance, FIELD_FLOAT, "Distance" ), // Function pointers DEFINE_FUNCTION( StaticDecal ), DEFINE_FUNCTION( TriggerDecal ), DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ), END_DATADESC() LINK_ENTITY_TO_CLASS( info_projecteddecal, CProjectedDecal ); // UNDONE: These won't get sent to joining players in multi-player void CProjectedDecal::Spawn( void ) { if ( m_nTexture < 0 || (gpGlobals->deathmatch && HasSpawnFlags( SF_DECAL_NOTINDEATHMATCH )) ) { UTIL_Remove( this ); return; } } void CProjectedDecal::Activate() { BaseClass::Activate(); if ( !GetEntityName() ) { StaticDecal(); } else { // if there IS a targetname, the decal sprays itself on when it is triggered. SetThink ( &CProjectedDecal::SUB_DoNothing ); SetUse(&CProjectedDecal::TriggerDecal); } } void CProjectedDecal::InputActivate( inputdata_t &inputdata ) { TriggerDecal( inputdata.pActivator, inputdata.pCaller, USE_ON, 0 ); } void CProjectedDecal::ProjectDecal( CRecipientFilter& filter ) { te->ProjectDecal( filter, 0.0, &GetAbsOrigin(), &GetAbsAngles(), m_flDistance, m_nTexture ); } void CProjectedDecal::TriggerDecal ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { CBroadcastRecipientFilter filter; ProjectDecal( filter ); SetThink( &CProjectedDecal::SUB_Remove ); SetNextThink( gpGlobals->curtime + 0.1f ); } void CProjectedDecal::StaticDecal( void ) { CBroadcastRecipientFilter initFilter; initFilter.MakeInitMessage(); ProjectDecal( initFilter ); SUB_Remove(); } bool CProjectedDecal::KeyValue( const char *szKeyName, const char *szValue ) { if (FStrEq(szKeyName, "texture")) { // FIXME: should decals all be preloaded? m_nTexture = UTIL_PrecacheDecal( szValue, true ); // Found if (m_nTexture >= 0 ) return true; Warning( "Can't find decal %s\n", szValue ); } else { return BaseClass::KeyValue( szKeyName, szValue ); } return true; } //======================= // CWorld // // This spawns first when each level begins. //======================= LINK_ENTITY_TO_CLASS( worldspawn, CWorld ); BEGIN_DATADESC( CWorld ) DEFINE_FIELD( m_flWaveHeight, FIELD_FLOAT ), // keyvalues are parsed from map, but not saved/loaded DEFINE_KEYFIELD( m_iszChapterTitle, FIELD_STRING, "chaptertitle" ), DEFINE_KEYFIELD( m_bStartDark, FIELD_BOOLEAN, "startdark" ), DEFINE_KEYFIELD( m_bDisplayTitle, FIELD_BOOLEAN, "gametitle" ), DEFINE_FIELD( m_WorldMins, FIELD_VECTOR ), DEFINE_FIELD( m_WorldMaxs, FIELD_VECTOR ), // DEFINE_FIELD( m_flMaxOccludeeArea, FIELD_CLASSCHECK_IGNORE ) // do this or else we get a warning about multiply-defined fields // DEFINE_FIELD( m_flMinOccluderArea, FIELD_CLASSCHECK_IGNORE ) // do this or else we get a warning about multiply-defined fields #ifdef _X360 DEFINE_KEYFIELD( m_flMaxOccludeeArea, FIELD_FLOAT, "maxoccludeearea_x360" ), DEFINE_KEYFIELD( m_flMinOccluderArea, FIELD_FLOAT, "minoccluderarea_x360" ), #else DEFINE_KEYFIELD( m_flMaxOccludeeArea, FIELD_FLOAT, "maxoccludeearea" ), DEFINE_KEYFIELD( m_flMinOccluderArea, FIELD_FLOAT, "minoccluderarea" ), #endif DEFINE_KEYFIELD( m_flMaxPropScreenSpaceWidth, FIELD_FLOAT, "maxpropscreenwidth" ), DEFINE_KEYFIELD( m_flMinPropScreenSpaceWidth, FIELD_FLOAT, "minpropscreenwidth" ), DEFINE_KEYFIELD( m_iszDetailSpriteMaterial, FIELD_STRING, "detailmaterial" ), DEFINE_KEYFIELD( m_bColdWorld, FIELD_BOOLEAN, "coldworld" ), END_DATADESC() // SendTable stuff. IMPLEMENT_SERVERCLASS_ST(CWorld, DT_WORLD) SendPropFloat (SENDINFO(m_flWaveHeight), 8, SPROP_ROUNDUP, 0.0f, 8.0f), SendPropVector (SENDINFO(m_WorldMins), -1, SPROP_COORD), SendPropVector (SENDINFO(m_WorldMaxs), -1, SPROP_COORD), SendPropInt (SENDINFO(m_bStartDark), 1, SPROP_UNSIGNED ), SendPropFloat (SENDINFO(m_flMaxOccludeeArea), 0, SPROP_NOSCALE ), SendPropFloat (SENDINFO(m_flMinOccluderArea), 0, SPROP_NOSCALE ), SendPropFloat (SENDINFO(m_flMaxPropScreenSpaceWidth), 0, SPROP_NOSCALE ), SendPropFloat (SENDINFO(m_flMinPropScreenSpaceWidth), 0, SPROP_NOSCALE ), SendPropStringT (SENDINFO(m_iszDetailSpriteMaterial) ), SendPropInt (SENDINFO(m_bColdWorld), 1, SPROP_UNSIGNED ), END_SEND_TABLE() // // Just to ignore the "wad" field. // bool CWorld::KeyValue( const char *szKeyName, const char *szValue ) { if ( FStrEq(szKeyName, "skyname") ) { // Sent over net now. ConVarRef skyname( "sv_skyname" ); skyname.SetValue( szValue ); } else if ( FStrEq(szKeyName, "newunit") ) { // Single player only. Clear save directory if set if ( atoi(szValue) ) { extern void Game_SetOneWayTransition(); Game_SetOneWayTransition(); } } else if ( FStrEq(szKeyName, "world_mins") ) { Vector vec; sscanf( szValue, "%f %f %f", &vec.x, &vec.y, &vec.z ); m_WorldMins = vec; } else if ( FStrEq(szKeyName, "world_maxs") ) { Vector vec; sscanf( szValue, "%f %f %f", &vec.x, &vec.y, &vec.z ); m_WorldMaxs = vec; } else if ( FStrEq(szKeyName, "timeofday" ) ) { SetTimeOfDay( atoi( szValue ) ); } else return BaseClass::KeyValue( szKeyName, szValue ); return true; } extern bool g_fGameOver; CWorld *g_WorldEntity = NULL; CWorld* GetWorldEntity() { return g_WorldEntity; } CWorld::CWorld( ) { AddEFlags( EFL_NO_AUTO_EDICT_ATTACH | EFL_KEEP_ON_RECREATE_ENTITIES ); NetworkProp()->AttachEdict( INDEXENT(RequiredEdictIndex()) ); ActivityList_Init(); EventList_Init(); SetSolid( SOLID_BSP ); SetMoveType( MOVETYPE_NONE ); m_bColdWorld = false; // Set this in the constructor for legacy maps (sjb) m_iTimeOfDay = TIME_MIDNIGHT; } CWorld::~CWorld() { // If in edit mode tell Hammer I'm ending my session. This re-enables // the Hammer UI so they can continue editing the map. #ifdef _WIN32 Editor_EndSession(false); #endif EventList_Free(); ActivityList_Free(); if ( g_pGameRules ) { g_pGameRules->LevelShutdown(); delete g_pGameRules; g_pGameRules = NULL; } g_WorldEntity = NULL; } //------------------------------------------------------------------------------ // Add a decal to the world //------------------------------------------------------------------------------ void CWorld::DecalTrace( trace_t *pTrace, char const *decalName) { int index = decalsystem->GetDecalIndexForName( decalName ); if ( index < 0 ) return; CBroadcastRecipientFilter filter; if ( pTrace->hitbox != 0 ) { te->Decal( filter, 0.0f, &pTrace->endpos, &pTrace->startpos, 0, pTrace->hitbox, index ); } else { te->WorldDecal( filter, 0.0, &pTrace->endpos, index ); } } void CWorld::RegisterSharedActivities( void ) { ActivityList_RegisterSharedActivities(); } void CWorld::RegisterSharedEvents( void ) { EventList_RegisterSharedEvents(); } void CWorld::Spawn( void ) { SetLocalOrigin( vec3_origin ); SetLocalAngles( vec3_angle ); // NOTE: SHOULD NEVER BE ANYTHING OTHER THAN 1!!! SetModelIndex( 1 ); // world model SetModelName( AllocPooledString( modelinfo->GetModelName( GetModel() ) ) ); AddFlag( FL_WORLDBRUSH ); g_EventQueue.Init(); Precache( ); GlobalEntity_Add( "is_console", STRING(gpGlobals->mapname), ( IsConsole() ) ? GLOBAL_ON : GLOBAL_OFF ); GlobalEntity_Add( "is_pc", STRING(gpGlobals->mapname), ( !IsConsole() ) ? GLOBAL_ON : GLOBAL_OFF ); } static const char *g_DefaultLightstyles[] = { // 0 normal "m", // 1 FLICKER (first variety) "mmnmmommommnonmmonqnmmo", // 2 SLOW STRONG PULSE "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba", // 3 CANDLE (first variety) "mmmmmaaaaammmmmaaaaaabcdefgabcdefg", // 4 FAST STROBE "mamamamamama", // 5 GENTLE PULSE 1 "jklmnopqrstuvwxyzyxwvutsrqponmlkj", // 6 FLICKER (second variety) "nmonqnmomnmomomno", // 7 CANDLE (second variety) "mmmaaaabcdefgmmmmaaaammmaamm", // 8 CANDLE (third variety) "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa", // 9 SLOW STROBE (fourth variety) "aaaaaaaazzzzzzzz", // 10 FLUORESCENT FLICKER "mmamammmmammamamaaamammma", // 11 SLOW PULSE NOT FADE TO BLACK "abcdefghijklmnopqrrqponmlkjihgfedcba", // 12 UNDERWATER LIGHT MUTATION // this light only distorts the lightmap - no contribution // is made to the brightness of affected surfaces "mmnnmmnnnmmnn", }; const char *GetDefaultLightstyleString( int styleIndex ) { if ( styleIndex < ARRAYSIZE(g_DefaultLightstyles) ) { return g_DefaultLightstyles[styleIndex]; } return "m"; } //----------------------------------------------------------------------------- string_t g_iszFuncBrushClassname = NULL_STRING; void CWorld::Precache( void ) { COM_TimestampedLog( "CWorld::Precache - Start" ); g_WorldEntity = this; g_fGameOver = false; g_pLastSpawn = NULL; g_Language.SetValue( LANGUAGE_ENGLISH ); // TODO use VGUI to get current language #ifndef INFESTED_DLL ConVarRef stepsize( "sv_stepsize" ); stepsize.SetValue( 18 ); #endif ConVarRef roomtype( "room_type" ); roomtype.SetValue( 0 ); // Set up game rules Assert( !g_pGameRules ); if (g_pGameRules) { delete g_pGameRules; } InstallGameRules(); Assert( g_pGameRules ); g_pGameRules->Init(); CSoundEnt::InitSoundEnt(); // UNDONE: Make most of these things server systems or precache_registers // ================================================= // Activities // ================================================= ActivityList_Free(); RegisterSharedActivities(); EventList_Free(); RegisterSharedEvents(); // Only allow precaching between LevelInitPreEntity and PostEntity CBaseEntity::SetAllowPrecache( true ); COM_TimestampedLog( "IGameSystem::LevelInitPreEntityAllSystems" ); IGameSystem::LevelInitPreEntityAllSystems( STRING( GetModelName() ) ); COM_TimestampedLog( "g_pGameRules->CreateStandardEntities()" ); // Create the player resource g_pGameRules->CreateStandardEntities(); COM_TimestampedLog( "InitBodyQue()" ); InitBodyQue(); COM_TimestampedLog( "SENTENCEG_Init()" ); // init sentence group playback stuff from sentences.txt. // ok to call this multiple times, calls after first are ignored. SENTENCEG_Init(); COM_TimestampedLog( "PrecacheStandardParticleSystems()" ); // Precache standard particle systems PrecacheStandardParticleSystems( ); // the area based ambient sounds MUST be the first precache_sounds COM_TimestampedLog( "W_Precache()" ); // player precaches W_Precache (); // get weapon precaches COM_TimestampedLog( "ClientPrecache()" ); ClientPrecache(); COM_TimestampedLog( "PrecacheTempEnts()" ); // precache all temp ent stuff CBaseTempEntity::PrecacheTempEnts(); COM_TimestampedLog( "LightStyles" ); // // Setup light animation tables. 'a' is total darkness, 'z' is maxbright. // for ( int i = 0; i < ARRAYSIZE(g_DefaultLightstyles); i++ ) { engine->LightStyle( i, GetDefaultLightstyleString(i) ); } // styles 32-62 are assigned by the light program for switchable lights // 63 testing engine->LightStyle(63, "a"); COM_TimestampedLog( "InitializeAINetworks" ); // ================================================= // Load and Init AI Networks // ================================================= CAI_NetworkManager::InitializeAINetworks(); // ================================================= // Load and Init AI Schedules // ================================================= COM_TimestampedLog( "LoadAllSchedules" ); g_AI_SchedulesManager.LoadAllSchedules(); // ================================================= // Initialize NPC Relationships // ================================================= COM_TimestampedLog( "InitDefaultAIRelationships" ); g_pGameRules->InitDefaultAIRelationships(); COM_TimestampedLog( "InitInteractionSystem" ); CBaseCombatCharacter::InitInteractionSystem(); COM_TimestampedLog( "g_pGameRules->Precache" ); // Call the gamerules precache after the AI precache so that games can precache NPCs that are always loaded g_pGameRules->Precache(); if ( m_iszChapterTitle != NULL_STRING ) { DevMsg( 2, "Chapter title: %s\n", STRING(m_iszChapterTitle) ); CMessage *pMessage = (CMessage *)CBaseEntity::Create( "env_message", vec3_origin, vec3_angle, NULL ); if ( pMessage ) { pMessage->SetMessage( m_iszChapterTitle ); m_iszChapterTitle = NULL_STRING; // send the message entity a play message command, delayed by 1 second pMessage->AddSpawnFlags( SF_MESSAGE_ONCE ); pMessage->SetThink( &CMessage::SUB_CallUseToggle ); pMessage->SetNextThink( gpGlobals->curtime + 1.0f ); } } g_iszFuncBrushClassname = AllocPooledString("func_brush"); if ( m_iszDetailSpriteMaterial.Get() != NULL_STRING ) { PrecacheMaterial( STRING( m_iszDetailSpriteMaterial.Get() ) ); } COM_TimestampedLog( "CWorld::Precache - Finish" ); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CWorld::UpdateOnRemove( void ) { BaseClass::UpdateOnRemove(); } //----------------------------------------------------------------------------- // Purpose: // Output : float //----------------------------------------------------------------------------- float GetRealTime() { return Plat_FloatTime(); } bool CWorld::GetDisplayTitle() const { return m_bDisplayTitle; } bool CWorld::GetStartDark() const { return m_bStartDark; } void CWorld::SetDisplayTitle( bool display ) { m_bDisplayTitle = display; } void CWorld::SetStartDark( bool startdark ) { m_bStartDark = startdark; } bool CWorld::IsColdWorld( void ) { return m_bColdWorld; } int CWorld::GetTimeOfDay() const { return m_iTimeOfDay; } void CWorld::SetTimeOfDay( int iTimeOfDay ) { m_iTimeOfDay = iTimeOfDay; }