Reworked Mapbase console groups to use script files and separate server/client commands instead of cvars and tier1 commands

This commit is contained in:
Blixibon 2021-04-22 11:12:29 -05:00
parent ebec14d2b6
commit 15d04c0b9b
4 changed files with 162 additions and 80 deletions

View File

@ -461,7 +461,7 @@ CAI_Expresser::~CAI_Expresser()
#ifdef DEBUG
g_nExpressers--;
if ( g_nExpressers == 0 && pSemaphore->GetOwner() )
DevMsg( 2, "Speech semaphore being held by non-talker entity\n" );
CGMsg( 2, CON_GROUP_SPEECH_AI, "Speech semaphore being held by non-talker entity\n" );
#endif
}
@ -826,7 +826,7 @@ bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t &concept, AI_Response *re
{
entityName = ToBasePlayer( GetOuter() )->GetPlayerName();
}
DevMsg( 2, "SpeakDispatchResponse: Entity ( %i/%s ) already speaking, forcing '%s'\n", GetOuter()->entindex(), entityName ? entityName : "UNKNOWN", (const char*)concept );
CGMsg( 2, CON_GROUP_SPEECH_AI, "SpeakDispatchResponse: Entity ( %i/%s ) already speaking, forcing '%s'\n", GetOuter()->entindex(), entityName ? entityName : "UNKNOWN", (const char*)concept );
// Tracker 15911: Can break the game if we stop an imported map placed lcs here, so only
// cancel actor out of instanced scripted scenes. ywb
@ -835,7 +835,7 @@ bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t &concept, AI_Response *re
if ( IsRunningScriptedScene( GetOuter() ) )
{
DevMsg( "SpeakDispatchResponse: Entity ( %i/%s ) refusing to speak due to scene entity, tossing '%s'\n", GetOuter()->entindex(), entityName ? entityName : "UNKNOWN", (const char*)concept );
CGMsg( 1, CON_GROUP_SPEECH_AI, "SpeakDispatchResponse: Entity ( %i/%s ) refusing to speak due to scene entity, tossing '%s'\n", GetOuter()->entindex(), entityName ? entityName : "UNKNOWN", (const char*)concept );
return false;
}
}
@ -858,7 +858,7 @@ bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t &concept, AI_Response *re
float speakTime = GetResponseDuration( result );
GetOuter()->EmitSound( response );
DevMsg( 2, "SpeakDispatchResponse: Entity ( %i/%s ) playing sound '%s'\n", GetOuter()->entindex(), STRING( GetOuter()->GetEntityName() ), response );
CGMsg( 2, CON_GROUP_SPEECH_AI, "SpeakDispatchResponse: Entity ( %i/%s ) playing sound '%s'\n", GetOuter()->entindex(), STRING( GetOuter()->GetEntityName() ), response );
NoteSpeaking( speakTime, delay );
spoke = true;
#ifdef MAPBASE
@ -1079,7 +1079,7 @@ bool CAI_Expresser::FireEntIOFromResponse( char *response, CBaseEntity *pInitiat
CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, pszEntname, pInitiator );
if ( !pTarget )
{
Msg( "Response rule targeted %s with entityio, but that doesn't exist.\n", pszEntname );
CGMsg( 0, CON_GROUP_SPEECH_AI, "Response rule targeted %s with entityio, but that doesn't exist.\n", pszEntname );
// but this is actually a legit use case, so return true (below).
}
else
@ -1528,7 +1528,7 @@ void CAI_Expresser::DumpHistories()
{
ConceptHistory_t *h = &m_ConceptHistories[ i ];
DevMsg( "%i: %s at %f\n", c++, m_ConceptHistories.GetElementName( i ), h->timeSpoken );
CGMsg( 1, CON_GROUP_SPEECH_AI, "%i: %s at %f\n", c++, m_ConceptHistories.GetElementName( i ), h->timeSpoken );
}
}
@ -1571,7 +1571,7 @@ void CAI_Expresser::SpeechMsg( CBaseEntity *pFlex, const char *pszFormat, ... )
}
else
{
DevMsg( CFmtStr( &pszFormat ) );
CGMsg( 1, CON_GROUP_SPEECH_AI, CFmtStr( &pszFormat ) );
}
UTIL_LogPrintf( (char *) ( (const char *) CFmtStr( &pszFormat ) ) );
}

View File

@ -9,6 +9,7 @@
#include "cbase.h"
#include "tier0/icommandline.h"
#include "tier1/mapbase_con_groups.h"
#include "igamesystem.h"
#include "filesystem.h"
#include <vgui_controls/Controls.h>
@ -151,6 +152,8 @@ public:
virtual bool Init()
{
InitConsoleGroups( g_pFullFileSystem );
// Checks gameinfo.txt for additional command line options
KeyValues *gameinfo = new KeyValues("GameInfo");
if (GetGameInfoKeyValues(gameinfo))
@ -626,3 +629,38 @@ BEGIN_DATADESC( CMapbaseManifestEntity )
END_DATADESC()
#endif
//-----------------------------------------------------------------------------
void CV_IncludeNameChanged( IConVar *pConVar, const char *pOldString, float flOldValue );
#ifdef CLIENT_DLL
ConVar con_group_include_name_client( "con_group_include_name_client", "0", FCVAR_NONE, "Includes groups when printing on the client.", CV_IncludeNameChanged );
void CV_IncludeNameChanged( IConVar *pConVar, const char *pOldString, float flOldValue )
{
SetConsoleGroupIncludeNames( con_group_include_name_client.GetBool() );
}
#else
ConVar con_group_include_name( "con_group_include_name", "0", FCVAR_NONE, "Includes groups when printing.", CV_IncludeNameChanged );
void CV_IncludeNameChanged( IConVar *pConVar, const char *pOldString, float flOldValue )
{
SetConsoleGroupIncludeNames( con_group_include_name.GetBool() );
}
#endif
CON_COMMAND_SHARED( con_group_reload, "Reloads all console groups." )
{
InitConsoleGroups( g_pFullFileSystem );
}
CON_COMMAND_SHARED( con_group_list, "Prints a list of all console groups." )
{
PrintAllConsoleGroups();
}
CON_COMMAND_SHARED( con_group_toggle, "Toggles a console group." )
{
ToggleConsoleGroups( args.Arg( 1 ) );
}

View File

@ -16,25 +16,48 @@
//static const Color CON_COLOR_DEV_VERBOSE( 192, 128, 192, 255 );
// General
#define CON_GROUP_MAPBASE_MISC 0 // "Mapbase Misc."
#define CON_GROUP_PHYSICS 1 // "Physics"
enum ConGroupID_t
{
// General
CON_GROUP_MAPBASE_MISC, // "Mapbase misc."
CON_GROUP_PHYSICS, // "Physics"
CON_GROUP_IO_SYSTEM, // "Entity I/O"
CON_GROUP_RESPONSE_SYSTEM, // "Response System"
// Server
#define CON_GROUP_IO_SYSTEM 2 // "Entity I/O"
#define CON_GROUP_NPC_AI 3 // "NPC AI"
#define CON_GROUP_NPC_SCRIPTS 4 // "NPC Scripts"
#define CON_GROUP_CHOREO 5 // "Choreo"
// Game
CON_GROUP_NPC_AI, // "NPC AI"
CON_GROUP_NPC_SCRIPTS, // "NPC scripts"
CON_GROUP_SPEECH_AI, // "Speech AI"
CON_GROUP_CHOREO, // "Choreo"
// VScript
#define CON_GROUP_VSCRIPT 6 // "VScript"
#define CON_GROUP_VSCRIPT_PRINT 7 // "VScript Print"
// VScript
CON_GROUP_VSCRIPT, // "VScript"
CON_GROUP_VSCRIPT_PRINT, // "VScript print"
#define CON_GROUP_MAX 8 // must always be at the end
//--------------------------
//
// Mod groups can be inserted here
//
//--------------------------
CON_GROUP_MAX, // Keep this at the end
};
// Mapbase console group message.
void CGMsg( int level, int nGroup, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 3, 4 );
void CGMsg( int level, ConGroupID_t nGroup, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 3, 4 );
#define CGWarning CGMsg
//-----------------------------------------------------------------------------
class IBaseFileSystem;
void InitConsoleGroups( IBaseFileSystem *filesystem );
void PrintAllConsoleGroups();
void ToggleConsoleGroups( const char *pszQuery );
void SetConsoleGroupIncludeNames( bool bToggle );
#endif

View File

@ -11,102 +11,116 @@
#include <stdlib.h>
#include <string.h>
#include "basetypes.h"
#include "tier1/tier1.h"
#include "tier1/utldict.h"
#include "tier1.h"
#include "utldict.h"
#include "Color.h"
#include "tier1/mapbase_con_groups.h"
void CV_ColorChanged( IConVar *pConVar, const char *pOldString, float flOldValue );
#include "mapbase_con_groups.h"
#include "KeyValues.h"
#include "filesystem.h"
#include "mapbase_matchers_base.h"
struct ConGroup_t
{
ConGroup_t( const char *_pszName, ConVar *pCvar )
ConGroup_t( const char *_pszName, const char *_pszDescription )
{
pszName = _pszName;
cvar = pCvar;
pszDescription = _pszDescription;
_clr.SetColor( 224, 224, 224, 255 ); // Default to a shade of gray
}
const Color &GetColor()
{
if (_clr.a() == 0)
{
// Read the cvar
int clr[3];
sscanf( cvar->GetString(), "%i %i %i", &clr[0], &clr[1], &clr[2] );
_clr.SetColor( clr[0], clr[1], clr[2], 255 );
}
return _clr;
}
const char *pszName;
const char *pszDescription;
Color _clr;
ConVar *cvar;
//bool bDisabled;
bool bDisabled;
};
//-----------------------------------------------------------------------------
// To define a console group,
//-----------------------------------------------------------------------------
#define DEFINE_CON_GROUP_CVAR(name, def, desc) static ConVar con_group_##name##_color( "con_group_" #name "_color", def, FCVAR_ARCHIVE | FCVAR_REPLICATED, desc, CV_ColorChanged )
DEFINE_CON_GROUP_CVAR( mapbase_misc, "192 128 224", "Messages from misc. Mapbase functions, like map-specific files." );
DEFINE_CON_GROUP_CVAR( physics, "159 209 159", "Messages from physics-related events." );
DEFINE_CON_GROUP_CVAR( inputoutput, "220 170 220", "Messages from I/O events. (these display in developer 2)" );
DEFINE_CON_GROUP_CVAR( npc_ai, "240 160 200", "Messages from NPC AI, etc. which display at various verbse levels." );
DEFINE_CON_GROUP_CVAR( npc_scripts, "255 115 215", "Messages from scripted_sequence, etc. (these display in developer 2)" );
DEFINE_CON_GROUP_CVAR( choreo, "240 224 180", "Messages from choreographed scenes and response expressers. (these display in developer 1, 2, etc.)" );
DEFINE_CON_GROUP_CVAR( vscript, "192 224 240", "Internal messages from VScript not produced by the user's scripts." );
DEFINE_CON_GROUP_CVAR( vscript_print, "80 186 255", "Messages from VScript's 'print' function." );
// TODO: Something more reliable?
static bool g_bIncludeConGroupNames = false;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#define DEFINE_CON_GROUP(id, name, codename) { name, &con_group_##codename##_color }
//#define DEFINE_CON_GROUP(id, name, codename) { name, &con_group_##codename##_color }
#define DEFINE_CON_GROUP(id, name, description) { name, description }
ConGroup_t g_ConGroups[CON_GROUP_MAX] = {
// General
DEFINE_CON_GROUP( CON_GROUP_MAPBASE_MISC, "Mapbase misc.", mapbase_misc ),
DEFINE_CON_GROUP( CON_GROUP_PHYSICS, "Physics", physics ),
DEFINE_CON_GROUP( CON_GROUP_MAPBASE_MISC, "Mapbase misc.", "Messages from misc. Mapbase functions, like map-specific files." ),
DEFINE_CON_GROUP( CON_GROUP_PHYSICS, "Physics", "Messages from physics-related events." ),
DEFINE_CON_GROUP( CON_GROUP_IO_SYSTEM, "Entity IO", "Messages from I/O events. (these display in developer 2)" ),
DEFINE_CON_GROUP( CON_GROUP_RESPONSE_SYSTEM, "Response System", "Messages from the Response System, a library primarily used for NPC speech." ),
// Server
DEFINE_CON_GROUP( CON_GROUP_IO_SYSTEM, "Entity IO", inputoutput ),
DEFINE_CON_GROUP( CON_GROUP_NPC_AI, "NPC AI", npc_ai ),
DEFINE_CON_GROUP( CON_GROUP_NPC_SCRIPTS, "NPC scripts", npc_scripts ),
DEFINE_CON_GROUP( CON_GROUP_CHOREO, "Choreo", choreo ),
// Game
DEFINE_CON_GROUP( CON_GROUP_NPC_AI, "NPC AI", "Messages from NPC AI, etc. which display at various verbose levels." ),
DEFINE_CON_GROUP( CON_GROUP_NPC_SCRIPTS, "NPC scripts", "Messages from scripted_sequence, etc. (these display in developer 2)" ),
DEFINE_CON_GROUP( CON_GROUP_SPEECH_AI, "Speech AI", "Messages from response expressers. (these display in developer 1, 2, etc.)" ),
DEFINE_CON_GROUP( CON_GROUP_CHOREO, "Choreo", "Messages from choreographed scenes. (these display in developer 1, 2, etc.)" ),
// VScript
DEFINE_CON_GROUP( CON_GROUP_VSCRIPT, "VScript", vscript ),
DEFINE_CON_GROUP( CON_GROUP_VSCRIPT_PRINT, "VScript print", vscript_print ),
DEFINE_CON_GROUP( CON_GROUP_VSCRIPT, "VScript", "Internal messages from VScript not produced by actual scripts." ),
DEFINE_CON_GROUP( CON_GROUP_VSCRIPT_PRINT, "VScript print", "Messages from VScript's 'print' function." ),
};
void CV_ColorChanged( IConVar *pConVar, const char *pOldString, float flOldValue )
int FindConGroup( const char *pszName )
{
for (int i = 0; i < CON_GROUP_MAX; i++)
{
// Reset the alpha to indicate it needs to be refreshed
g_ConGroups[i]._clr[3] = 0;
if (Q_stricmp( pszName, g_ConGroups[i].pszName ) == 0)
return i;
}
return -1;
}
//-----------------------------------------------------------------------------
// Loads console groups
//-----------------------------------------------------------------------------
void LoadConsoleGroupsFromFile( IBaseFileSystem *filesystem, const char *pszFileName, const char *pathID )
{
KeyValues *pGroupRoot = new KeyValues( "ConsoleGroups" );
ConVar con_group_include_name( "con_group_include_name", "0", FCVAR_NONE, "Includes groups when printing." );
pGroupRoot->LoadFromFile( filesystem, pszFileName, pathID );
CON_COMMAND( con_group_list, "Prints a list of all console groups." )
KeyValues *pGroup = NULL;
for ( pGroup = pGroupRoot->GetFirstTrueSubKey(); pGroup; pGroup = pGroup->GetNextTrueSubKey() )
{
int index = FindConGroup( pGroup->GetName() );
if (index != -1)
{
g_ConGroups[index]._clr = pGroup->GetColor( "MessageColor" );
//g_ConGroups[index].bDisabled = pGroup->GetBool( "Disabled", false );
}
else
{
Warning( "Invalid console group %s (new groups should be defined in the code)\n", pGroup->GetName() );
}
}
pGroupRoot->deleteThis();
}
void InitConsoleGroups( IBaseFileSystem *filesystem )
{
LoadConsoleGroupsFromFile( filesystem, "scripts/mapbase_con_groups.txt", "MOD" );
LoadConsoleGroupsFromFile( filesystem, "scripts/mod_con_groups.txt", "MOD" );
}
void PrintAllConsoleGroups()
{
Msg( "============================================================\n" );
for (int i = 0; i < CON_GROUP_MAX; i++)
{
Msg( " # " );
ConColorMsg( g_ConGroups[i].GetColor(), "%s", g_ConGroups[i].pszName );
Msg( " - %s ", g_ConGroups[i].cvar->GetHelpText() );
Msg( " - %s ", g_ConGroups[i].pszDescription );
//if (g_ConGroups[i].bDisabled)
// Msg("(DISABLED)");
@ -116,26 +130,33 @@ CON_COMMAND( con_group_list, "Prints a list of all console groups." )
Msg( "============================================================\n" );
}
// TODO: Figure out how this can be done without server/client disparity issues
/*
CON_COMMAND( con_group_toggle, "Toggles a console group." )
void ToggleConsoleGroups( const char *pszQuery )
{
const char *pszGroup = args.Arg( 1 );
bool bMatched = false;
for (int i = 0; i < ARRAYSIZE( g_ConGroups ); i++)
{
if (V_stricmp(pszGroup, g_ConGroups[i].pszName) == 0)
if (Matcher_NamesMatch( pszQuery, g_ConGroups[i].pszName ))
{
Msg( "%s is now %s\n", g_ConGroups[i].pszName, g_ConGroups[i].bDisabled ? "enabled" : "disabled" );
g_ConGroups[i].bDisabled = !g_ConGroups[i].bDisabled;
return;
bMatched = true;
}
}
Msg( "No group named \"%s\"\n", pszGroup );
if (!bMatched)
Msg( "No groups matching \"%s\"\n", pszQuery );
}
*/
void CGMsg( int level, int nGroup, const tchar* pMsg, ... )
void SetConsoleGroupIncludeNames( bool bToggle )
{
g_bIncludeConGroupNames = bToggle;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CGMsg( int level, ConGroupID_t nGroup, const tchar* pMsg, ... )
{
// Return early if we're not at this level
if (!IsSpewActive("developer", level))
@ -152,11 +173,11 @@ void CGMsg( int level, int nGroup, const tchar* pMsg, ... )
ConGroup_t *pGroup = &g_ConGroups[nGroup];
/*if (pGroup->bDisabled)
if (pGroup->bDisabled)
{
// Do nothing
// Do nothing
}
else*/ if (con_group_include_name.GetBool())
else if (g_bIncludeConGroupNames)
{
ConColorMsg(level, pGroup->GetColor(), "[%s] %s", pGroup->pszName, string);
}