From f56bb35301836e56582a575a75864392a0177875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Mon, 2 Dec 2013 19:31:46 -0800 Subject: Fix line endings. WHAMMY. --- mp/src/game/server/world.cpp | 1466 +++++++++++++++++++++--------------------- 1 file changed, 733 insertions(+), 733 deletions(-) (limited to 'mp/src/game/server/world.cpp') diff --git a/mp/src/game/server/world.cpp b/mp/src/game/server/world.cpp index 41abb291..55c1e7b5 100644 --- a/mp/src/game/server/world.cpp +++ b/mp/src/game/server/world.cpp @@ -1,733 +1,733 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// Purpose: Precaches and defs for entities and other data that must always be available. -// -// $NoKeywords: $ -//===========================================================================// - -#include "cbase.h" -#include "soundent.h" -#include "client.h" -#include "decals.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" - -// 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 - -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 ); - - DECLARE_DATADESC(); - -public: - int m_nTexture; - bool m_bLowPriority; - -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 - - // 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); - } -} - -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; - - UTIL_TraceLine( GetAbsOrigin() - Vector(5,5,5), GetAbsOrigin() + Vector(5,5,5), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trace ); - - entityIndex = trace.m_pEnt ? trace.m_pEnt->entindex() : 0; - - CBroadcastRecipientFilter filter; - - te->BSPDecal( filter, 0.0, - &GetAbsOrigin(), 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 ) -{ - 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; - } - - - return CTraceFilterSimple::ShouldHitEntity( pServerEntity, contentsMask ); - } - }; - - trace_t trace; - CTraceFilterValidForDecal traceFilter( this, COLLISION_GROUP_NONE ); - int entityIndex, modelIndex = 0; - - Vector position = GetAbsOrigin(); - UTIL_TraceLine( position - Vector(5,5,5), position + Vector(5,5,5), MASK_SOLID, &traceFilter, &trace ); - - bool canDraw = true; - - entityIndex = trace.m_pEnt ? (short)trace.m_pEnt->entindex() : 0; - if ( entityIndex ) - { - CBaseEntity *ent = trace.m_pEnt; - if ( ent ) - { - modelIndex = ent->GetModelIndex(); - VectorITransform( GetAbsOrigin(), ent->EntityToWorldTransform(), position ); - - canDraw = ( modelIndex != 0 ); - if ( !canDraw ) - { - Warning( "Suppressed StaticDecal which would have hit entity %i (class:%s, name:%s) with modelindex = 0\n", - ent->entindex(), - ent->GetClassname(), - STRING( ent->GetEntityName() ) ); - } - } - } - - if ( canDraw ) - { - 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 ), -#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 - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; -} - - -extern bool g_fGameOver; -static 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; -} - -CWorld::~CWorld( ) -{ - EventList_Free(); - ActivityList_Free(); - if ( g_pGameRules ) - { - g_pGameRules->LevelShutdown(); - delete g_pGameRules; - g_pGameRules = NULL; - } - g_WorldEntity = NULL; -} - - -//------------------------------------------------------------------------------ -// Purpose : Add a decal to the world -// Input : -// Output : -//------------------------------------------------------------------------------ -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"; -} - -void CWorld::Precache( void ) -{ - g_WorldEntity = this; - g_fGameOver = false; - g_pLastSpawn = NULL; - - ConVarRef stepsize( "sv_stepsize" ); - stepsize.SetValue( 18 ); - - 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(); - - // Only allow precaching between LevelInitPreEntity and PostEntity - CBaseEntity::SetAllowPrecache( true ); - IGameSystem::LevelInitPreEntityAllSystems( STRING( GetModelName() ) ); - - // Create the player resource - g_pGameRules->CreateStandardEntities(); - - // UNDONE: Make most of these things server systems or precache_registers - // ================================================= - // Activities - // ================================================= - ActivityList_Free(); - RegisterSharedActivities(); - - EventList_Free(); - RegisterSharedEvents(); - - InitBodyQue(); -// init sentence group playback stuff from sentences.txt. -// ok to call this multiple times, calls after first are ignored. - - SENTENCEG_Init(); - - // Precache standard particle systems - PrecacheStandardParticleSystems( ); - -// the area based ambient sounds MUST be the first precache_sounds - -// player precaches - W_Precache (); // get weapon precaches - ClientPrecache(); - g_pGameRules->Precache(); - // precache all temp ent stuff - CBaseTempEntity::PrecacheTempEnts(); - - g_Language.SetValue( LANGUAGE_ENGLISH ); // TODO use VGUI to get current language - - if ( g_Language.GetInt() == LANGUAGE_GERMAN ) - { - PrecacheModel( "models/germangibs.mdl" ); - } - else - { - PrecacheModel( "models/gibs/hgibs.mdl" ); - } - - PrecacheScriptSound( "BaseEntity.EnterWater" ); - PrecacheScriptSound( "BaseEntity.ExitWater" ); - -// -// 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"); - - // ================================================= - // Load and Init AI Networks - // ================================================= - CAI_NetworkManager::InitializeAINetworks(); - // ================================================= - // Load and Init AI Schedules - // ================================================= - g_AI_SchedulesManager.LoadAllSchedules(); - // ================================================= - // Initialize NPC Relationships - // ================================================= - g_pGameRules->InitDefaultAIRelationships(); - CBaseCombatCharacter::InitInteractionSystem(); - - // Call all registered precachers. - CPrecacheRegister::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"); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float GetRealTime() -{ - return engine->Time(); -} - - -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; -} +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Precaches and defs for entities and other data that must always be available. +// +// $NoKeywords: $ +//===========================================================================// + +#include "cbase.h" +#include "soundent.h" +#include "client.h" +#include "decals.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" + +// 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 + +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 ); + + DECLARE_DATADESC(); + +public: + int m_nTexture; + bool m_bLowPriority; + +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 + + // 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); + } +} + +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; + + UTIL_TraceLine( GetAbsOrigin() - Vector(5,5,5), GetAbsOrigin() + Vector(5,5,5), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trace ); + + entityIndex = trace.m_pEnt ? trace.m_pEnt->entindex() : 0; + + CBroadcastRecipientFilter filter; + + te->BSPDecal( filter, 0.0, + &GetAbsOrigin(), 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 ) +{ + 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; + } + + + return CTraceFilterSimple::ShouldHitEntity( pServerEntity, contentsMask ); + } + }; + + trace_t trace; + CTraceFilterValidForDecal traceFilter( this, COLLISION_GROUP_NONE ); + int entityIndex, modelIndex = 0; + + Vector position = GetAbsOrigin(); + UTIL_TraceLine( position - Vector(5,5,5), position + Vector(5,5,5), MASK_SOLID, &traceFilter, &trace ); + + bool canDraw = true; + + entityIndex = trace.m_pEnt ? (short)trace.m_pEnt->entindex() : 0; + if ( entityIndex ) + { + CBaseEntity *ent = trace.m_pEnt; + if ( ent ) + { + modelIndex = ent->GetModelIndex(); + VectorITransform( GetAbsOrigin(), ent->EntityToWorldTransform(), position ); + + canDraw = ( modelIndex != 0 ); + if ( !canDraw ) + { + Warning( "Suppressed StaticDecal which would have hit entity %i (class:%s, name:%s) with modelindex = 0\n", + ent->entindex(), + ent->GetClassname(), + STRING( ent->GetEntityName() ) ); + } + } + } + + if ( canDraw ) + { + 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 ), +#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 + return BaseClass::KeyValue( szKeyName, szValue ); + + return true; +} + + +extern bool g_fGameOver; +static 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; +} + +CWorld::~CWorld( ) +{ + EventList_Free(); + ActivityList_Free(); + if ( g_pGameRules ) + { + g_pGameRules->LevelShutdown(); + delete g_pGameRules; + g_pGameRules = NULL; + } + g_WorldEntity = NULL; +} + + +//------------------------------------------------------------------------------ +// Purpose : Add a decal to the world +// Input : +// Output : +//------------------------------------------------------------------------------ +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"; +} + +void CWorld::Precache( void ) +{ + g_WorldEntity = this; + g_fGameOver = false; + g_pLastSpawn = NULL; + + ConVarRef stepsize( "sv_stepsize" ); + stepsize.SetValue( 18 ); + + 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(); + + // Only allow precaching between LevelInitPreEntity and PostEntity + CBaseEntity::SetAllowPrecache( true ); + IGameSystem::LevelInitPreEntityAllSystems( STRING( GetModelName() ) ); + + // Create the player resource + g_pGameRules->CreateStandardEntities(); + + // UNDONE: Make most of these things server systems or precache_registers + // ================================================= + // Activities + // ================================================= + ActivityList_Free(); + RegisterSharedActivities(); + + EventList_Free(); + RegisterSharedEvents(); + + InitBodyQue(); +// init sentence group playback stuff from sentences.txt. +// ok to call this multiple times, calls after first are ignored. + + SENTENCEG_Init(); + + // Precache standard particle systems + PrecacheStandardParticleSystems( ); + +// the area based ambient sounds MUST be the first precache_sounds + +// player precaches + W_Precache (); // get weapon precaches + ClientPrecache(); + g_pGameRules->Precache(); + // precache all temp ent stuff + CBaseTempEntity::PrecacheTempEnts(); + + g_Language.SetValue( LANGUAGE_ENGLISH ); // TODO use VGUI to get current language + + if ( g_Language.GetInt() == LANGUAGE_GERMAN ) + { + PrecacheModel( "models/germangibs.mdl" ); + } + else + { + PrecacheModel( "models/gibs/hgibs.mdl" ); + } + + PrecacheScriptSound( "BaseEntity.EnterWater" ); + PrecacheScriptSound( "BaseEntity.ExitWater" ); + +// +// 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"); + + // ================================================= + // Load and Init AI Networks + // ================================================= + CAI_NetworkManager::InitializeAINetworks(); + // ================================================= + // Load and Init AI Schedules + // ================================================= + g_AI_SchedulesManager.LoadAllSchedules(); + // ================================================= + // Initialize NPC Relationships + // ================================================= + g_pGameRules->InitDefaultAIRelationships(); + CBaseCombatCharacter::InitInteractionSystem(); + + // Call all registered precachers. + CPrecacheRegister::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"); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : float +//----------------------------------------------------------------------------- +float GetRealTime() +{ + return engine->Time(); +} + + +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; +} -- cgit v1.2.3