mirror of
https://github.com/celisej567/source-engine.git
synced 2026-01-03 05:49:41 +03:00
upload "kind" alien swarm
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: The system for handling director's commentary style production info in-game.
|
||||
//
|
||||
@@ -11,9 +11,9 @@
|
||||
#include "tier0/icommandline.h"
|
||||
#include "igamesystem.h"
|
||||
#include "filesystem.h"
|
||||
#include <KeyValues.h>
|
||||
#include <keyvalues.h>
|
||||
#include "in_buttons.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
#include "engine/ienginesound.h"
|
||||
#include "soundenvelope.h"
|
||||
#include "utldict.h"
|
||||
#include "isaverestore.h"
|
||||
@@ -21,7 +21,9 @@
|
||||
#include "saverestore_utlvector.h"
|
||||
#include "gamestats.h"
|
||||
#include "ai_basenpc.h"
|
||||
#include "Sprite.h"
|
||||
#include "sprite.h"
|
||||
#include "point_template.h"
|
||||
#include "mapentities.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
@@ -33,6 +35,7 @@ static const char *s_pCommentaryUpdateViewThink = "CommentaryUpdateViewThink";
|
||||
|
||||
extern ConVar commentary;
|
||||
ConVar commentary_available("commentary_available", "0", FCVAR_NONE, "Automatically set by the game when a commentary file is available for the current map." );
|
||||
extern ConVar rr_remarkables_enabled;
|
||||
|
||||
enum teleport_stages_t
|
||||
{
|
||||
@@ -59,6 +62,10 @@ bool IsInCommentaryMode( void )
|
||||
return g_bInCommentaryMode;
|
||||
}
|
||||
|
||||
PRECACHE_REGISTER_BEGIN( GLOBAL, PrecachePointCommentaryNode )
|
||||
PRECACHE( MODEL, "models/extras/info_speech.mdl" )
|
||||
PRECACHE_REGISTER_END()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: An entity that marks a spot for a piece of commentary
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -255,6 +262,7 @@ public:
|
||||
CCommentarySystem() : CAutoGameSystemPerFrame( "CCommentarySystem" )
|
||||
{
|
||||
m_iCommentaryNodeCount = 0;
|
||||
m_pkvSavedModifications = NULL;
|
||||
}
|
||||
|
||||
virtual void LevelInitPreEntity()
|
||||
@@ -283,6 +291,7 @@ public:
|
||||
{
|
||||
g_bInCommentaryMode = true;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -341,7 +350,10 @@ public:
|
||||
|
||||
virtual void LevelInitPostEntity( void )
|
||||
{
|
||||
if ( !IsInCommentaryMode() )
|
||||
// Previously, we would bail out immediately. However if info_remarkables are enabled,
|
||||
// there is the possiblity that they are defined in the commentary file, because it was a
|
||||
// more convenient markup tool for the writers than Hammer. Therefore we must load it.
|
||||
if ( !IsInCommentaryMode() && !rr_remarkables_enabled.GetBool() )
|
||||
return;
|
||||
|
||||
// Don't spawn commentary entities when loading a savegame
|
||||
@@ -351,8 +363,11 @@ public:
|
||||
m_bCommentaryEnabledMidGame = false;
|
||||
InitCommentary();
|
||||
|
||||
IGameEvent *event = gameeventmanager->CreateEvent( "playing_commentary" );
|
||||
gameeventmanager->FireEventClientSide( event );
|
||||
if ( IsInCommentaryMode() )
|
||||
{
|
||||
IGameEvent *event = gameeventmanager->CreateEvent( "playing_commentary" );
|
||||
gameeventmanager->FireEventClientSide( event );
|
||||
}
|
||||
}
|
||||
|
||||
CPointCommentaryNode *GetNodeUnderCrosshair()
|
||||
@@ -591,11 +606,19 @@ public:
|
||||
return;
|
||||
|
||||
// Spawn the commentary semaphore entity
|
||||
CBaseEntity *pSemaphore = CreateEntityByName( "info_target" );
|
||||
pSemaphore->SetName( MAKE_STRING(COMMENTARY_SPAWNED_SEMAPHORE) );
|
||||
static CGameString infoTargetStr( "info_target" );
|
||||
static CGameString commentarySpawnedSemaphoreName( COMMENTARY_SPAWNED_SEMAPHORE );
|
||||
CBaseEntity *pSemaphore = CreateEntityByName( infoTargetStr );
|
||||
pSemaphore->SetName( commentarySpawnedSemaphoreName );
|
||||
|
||||
bool oldLock = engine->LockNetworkStringTables( false );
|
||||
|
||||
if ( m_pkvSavedModifications != NULL )
|
||||
{
|
||||
m_pkvSavedModifications->deleteThis();
|
||||
m_pkvSavedModifications = NULL;
|
||||
}
|
||||
|
||||
// Find the commentary file
|
||||
char szFullName[512];
|
||||
Q_snprintf(szFullName,sizeof(szFullName), "maps/%s_commentary.txt", STRING( gpGlobals->mapname ));
|
||||
@@ -604,6 +627,20 @@ public:
|
||||
{
|
||||
Msg( "Commentary: Loading commentary data from %s. \n", szFullName );
|
||||
|
||||
unsigned int iFileSize = filesystem->Size( szFullName, "MOD" );
|
||||
Assert( iFileSize > 0 );
|
||||
|
||||
CPointTemplate *PointTemplates[MAX_EDICTS];
|
||||
int iPointTemplateCount = 0;
|
||||
HierarchicalSpawnMapData_t SpawnData[MAX_EDICTS]; //for point templates
|
||||
|
||||
//to avoid rewriting a bunch of code, I'm leaving the keyvalue parsing as is. But to get point_templates to work, I need the keyvalues as strings. So we go file->KeyValues->String.
|
||||
char *pKVToStringBuffer = (char *)stackalloc( sizeof(char *) * iFileSize );
|
||||
char TempKeyBuffer[20 * 1024];
|
||||
CUtlBuffer SpawnKeyValuesBackToString( TempKeyBuffer, 20 * 1024 );
|
||||
int iKVStringBufferIndex = 0;
|
||||
|
||||
|
||||
// Load each commentary block, and spawn the entities
|
||||
KeyValues *pkvNode = pkvFile->GetFirstSubKey();
|
||||
while ( pkvNode )
|
||||
@@ -625,16 +662,71 @@ public:
|
||||
pNodeName = pClassname->GetString();
|
||||
}
|
||||
|
||||
if ( rr_remarkables_enabled.GetBool() )
|
||||
{
|
||||
bool bModifyBlock = !Q_strcmp( pkvNode->GetName(), "modify_entity" );
|
||||
|
||||
// in L4D, we hijack the commentary system to create
|
||||
// info_remarkable nodes. If we are here with commentary
|
||||
// disabled, load only those nodes.
|
||||
// We also hijack it for map updates (exploits/etc.) on 360
|
||||
|
||||
KeyValues *pUpdateFlag = pkvNode->FindKey( "mapupdate", false );
|
||||
if ( !IsInCommentaryMode() &&
|
||||
( Q_strncmp( pNodeName, "info_remarkable", sizeof("info_remarkable")) != 0 ) &&
|
||||
!pUpdateFlag && !bModifyBlock )
|
||||
{
|
||||
// Move to next entity
|
||||
pkvNode = pkvNode->GetNextKey();
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( bModifyBlock )
|
||||
{
|
||||
if ( m_pkvSavedModifications == NULL )
|
||||
{
|
||||
m_pkvSavedModifications = new KeyValues("Entities");
|
||||
}
|
||||
m_pkvSavedModifications->AddSubKey( pkvNode->MakeCopy() );
|
||||
}
|
||||
}
|
||||
|
||||
// Spawn the commentary entity
|
||||
CBaseEntity *pNode = CreateEntityByName( pNodeName );
|
||||
if ( pNode )
|
||||
{
|
||||
ParseEntKVBlock( pNode, pkvNode );
|
||||
DispatchSpawn( pNode );
|
||||
|
||||
EHANDLE hHandle;
|
||||
hHandle = pNode;
|
||||
m_hSpawnedEntities.AddToTail( hHandle );
|
||||
int iAddIndex = m_hSpawnedEntities.AddToTail( hHandle );
|
||||
|
||||
SpawnKeyValuesBackToString.SeekPut( CUtlBuffer::SEEK_HEAD, 0 );
|
||||
pkvNode->RecursiveSaveToFile( SpawnKeyValuesBackToString, 0 );
|
||||
int iLength = SpawnKeyValuesBackToString.TellPut() - 1;
|
||||
|
||||
//trim off the start and end that we don't care about
|
||||
while( TempKeyBuffer[iLength] != '}' )
|
||||
{
|
||||
--iLength;
|
||||
}
|
||||
--iLength;
|
||||
|
||||
char *pStart = TempKeyBuffer;
|
||||
while( *pStart != '{' )
|
||||
{
|
||||
++pStart;
|
||||
}
|
||||
pStart += 2; //RecursiveSaveToFile saves "name"\n{\n. We're skipping past that final \n
|
||||
iLength -= (pStart - TempKeyBuffer);
|
||||
|
||||
//don't need to null terminate or space at all
|
||||
memcpy( &pKVToStringBuffer[iKVStringBufferIndex], pStart, iLength );
|
||||
|
||||
SpawnData[iAddIndex].m_pMapData = &pKVToStringBuffer[iKVStringBufferIndex];
|
||||
SpawnData[iAddIndex].m_iMapDataLength = iLength;
|
||||
|
||||
iKVStringBufferIndex += iLength;
|
||||
|
||||
CPointCommentaryNode *pCommNode = dynamic_cast<CPointCommentaryNode*>(pNode);
|
||||
if ( pCommNode )
|
||||
@@ -642,6 +734,13 @@ public:
|
||||
m_iCommentaryNodeCount++;
|
||||
pCommNode->SetNodeNumber( m_iCommentaryNodeCount );
|
||||
}
|
||||
|
||||
CPointTemplate *pPointTemplate = dynamic_cast<CPointTemplate*>(pNode);
|
||||
if ( pPointTemplate )
|
||||
{
|
||||
PointTemplates[iPointTemplateCount] = pPointTemplate;
|
||||
++iPointTemplateCount;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -652,6 +751,39 @@ public:
|
||||
pkvNode = pkvNode->GetNextKey();
|
||||
}
|
||||
|
||||
ApplyCommentaryModifications();
|
||||
|
||||
if( iPointTemplateCount != 0 )
|
||||
{
|
||||
CBaseEntity **pSpawnedEntities = NULL;
|
||||
int iSpawnedEntityCount = m_hSpawnedEntities.Count();
|
||||
if( iSpawnedEntityCount != 0 )
|
||||
{
|
||||
pSpawnedEntities = (CBaseEntity **)stackalloc( sizeof(CBaseEntity *) * m_hSpawnedEntities.Count() );
|
||||
|
||||
for( int i = 0; i != iSpawnedEntityCount; ++i )
|
||||
{
|
||||
pSpawnedEntities[i] = m_hSpawnedEntities[i].Get();
|
||||
}
|
||||
}
|
||||
|
||||
MapEntity_ParseAllEntites_SpawnTemplates( PointTemplates, iPointTemplateCount, pSpawnedEntities, SpawnData, iSpawnedEntityCount );
|
||||
|
||||
for( int i = iSpawnedEntityCount; --i >= 0; )
|
||||
{
|
||||
//remove any entities that were nullified in the point template parsing process
|
||||
if( pSpawnedEntities[i] == NULL )
|
||||
m_hSpawnedEntities.Remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
for( int i = 0; i != m_hSpawnedEntities.Count(); ++i )
|
||||
{
|
||||
DispatchSpawn( m_hSpawnedEntities[i] );
|
||||
}
|
||||
|
||||
PrecachePointTemplates();
|
||||
|
||||
// Then activate all the entities
|
||||
for ( int i = 0; i < m_hSpawnedEntities.Count(); i++ )
|
||||
{
|
||||
@@ -666,6 +798,56 @@ public:
|
||||
engine->LockNetworkStringTables( oldLock );
|
||||
}
|
||||
|
||||
void ApplyCommentaryModifications()
|
||||
{
|
||||
KeyValues *pkvNode = m_pkvSavedModifications ? m_pkvSavedModifications->GetFirstSubKey() : NULL;
|
||||
while ( pkvNode )
|
||||
{
|
||||
KeyValues *pModifyBlock = pkvNode->FindKey( "modify" );
|
||||
if ( pModifyBlock )
|
||||
{
|
||||
// find entities with model name
|
||||
KeyValues *pFindByModelname = pkvNode->FindKey( "find_by_modelname" );
|
||||
if ( pFindByModelname )
|
||||
{
|
||||
CBaseEntity *pEnt = gEntList.FindEntityByModel( NULL, pFindByModelname->GetString() );
|
||||
while ( pEnt )
|
||||
{
|
||||
KeyValues *pKey = pModifyBlock->GetFirstSubKey();
|
||||
while( pKey )
|
||||
{
|
||||
pEnt->KeyValue( pKey->GetName(), pKey->GetString() );
|
||||
pKey = pKey->GetNextKey();
|
||||
}
|
||||
|
||||
pEnt = gEntList.FindEntityByModel( pEnt, pFindByModelname->GetString() );
|
||||
}
|
||||
}
|
||||
|
||||
KeyValues *pFindByTargetname = pkvNode->FindKey( "find_by_targetname" );
|
||||
if ( pFindByTargetname )
|
||||
{
|
||||
CBaseEntity *pTarget = gEntList.FindEntityByTarget( NULL, pFindByTargetname->GetString() );
|
||||
|
||||
while ( pTarget )
|
||||
{
|
||||
KeyValues *pKey = pModifyBlock->GetFirstSubKey();
|
||||
while( pKey )
|
||||
{
|
||||
pTarget->KeyValue( pKey->GetName(), pKey->GetString() );
|
||||
pKey = pKey->GetNextKey();
|
||||
}
|
||||
|
||||
pTarget = gEntList.FindEntityByTarget( pTarget, pFindByTargetname->GetString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move to next entity
|
||||
pkvNode = pkvNode->GetNextKey();
|
||||
}
|
||||
}
|
||||
|
||||
void ShutDownCommentary( void )
|
||||
{
|
||||
if ( GetActiveNode() )
|
||||
@@ -705,6 +887,12 @@ public:
|
||||
}
|
||||
m_ModifiedConvars.Purge();
|
||||
|
||||
if ( m_pkvSavedModifications )
|
||||
{
|
||||
m_pkvSavedModifications->deleteThis();
|
||||
}
|
||||
m_pkvSavedModifications = NULL;
|
||||
|
||||
m_hCurrentNode = NULL;
|
||||
m_hActiveCommentaryNode = NULL;
|
||||
m_hLastCommentaryNode = NULL;
|
||||
@@ -790,15 +978,48 @@ private:
|
||||
float m_flNextTeleportTime;
|
||||
int m_iTeleportStage;
|
||||
|
||||
KeyValues *m_pkvSavedModifications;
|
||||
|
||||
CUtlVector< modifiedconvars_t > m_ModifiedConvars;
|
||||
CUtlVector<EHANDLE> m_hSpawnedEntities;
|
||||
CHandle<CPointCommentaryNode> m_hCurrentNode;
|
||||
CHandle<CPointCommentaryNode> m_hActiveCommentaryNode;
|
||||
CHandle<CPointCommentaryNode> m_hLastCommentaryNode;
|
||||
|
||||
friend bool Commentary_IsCommentaryEntity( CBaseEntity *pEntity );
|
||||
};
|
||||
|
||||
CCommentarySystem g_CommentarySystem;
|
||||
|
||||
void ApplyCommentaryModifications()
|
||||
{
|
||||
g_CommentarySystem.ApplyCommentaryModifications();
|
||||
}
|
||||
|
||||
bool Commentary_IsCommentaryEntity( CBaseEntity *pEntity )
|
||||
{
|
||||
for( int i = 0; i != g_CommentarySystem.m_hSpawnedEntities.Count(); ++i )
|
||||
{
|
||||
if( pEntity == g_CommentarySystem.m_hSpawnedEntities[i].Get() )
|
||||
return true;
|
||||
}
|
||||
|
||||
if( pEntity->GetEntityName() == MAKE_STRING( COMMENTARY_SPAWNED_SEMAPHORE ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Commentary_AbortCurrentNode( void )
|
||||
{
|
||||
if ( g_CommentarySystem.GetActiveNode() )
|
||||
{
|
||||
g_CommentarySystem.GetActiveNode()->AbortPlaying();
|
||||
}
|
||||
}
|
||||
|
||||
void CommentarySystem_PePlayerRunCommand( CBasePlayer *player, CUserCmd *ucmd )
|
||||
{
|
||||
g_CommentarySystem.PrePlayerRunCommand( player, ucmd );
|
||||
@@ -1244,7 +1465,7 @@ void CPointCommentaryNode::UpdateViewThink( void )
|
||||
|
||||
// Blend to the target position over time.
|
||||
float flCurTime = (gpGlobals->curtime - m_flStartTime);
|
||||
float flBlendPerc = clamp( flCurTime * 0.5f, 0.f, 1.f );
|
||||
float flBlendPerc = clamp( flCurTime / 2.0, 0, 1 );
|
||||
|
||||
// Figure out the current view position
|
||||
Vector vecCurEye;
|
||||
@@ -1269,7 +1490,7 @@ void CPointCommentaryNode::UpdateViewPostThink( void )
|
||||
// Blend back to the player's position over time.
|
||||
float flCurTime = (gpGlobals->curtime - m_flFinishedTime);
|
||||
float flTimeToBlend = MIN( 2.0, m_flFinishedTime - m_flStartTime );
|
||||
float flBlendPerc = 1.0f - clamp( flCurTime / flTimeToBlend, 0.f, 1.f );
|
||||
float flBlendPerc = 1.0 - clamp( flCurTime / flTimeToBlend, 0, 1 );
|
||||
|
||||
//Msg("OUT: CurTime %.2f, BlendTime: %.2f, Blend: %.3f\n", flCurTime, flTimeToBlend, flBlendPerc );
|
||||
|
||||
|
||||
Reference in New Issue
Block a user