diff --git a/sp/src/game/shared/ai_responsesystem_new.cpp b/sp/src/game/shared/ai_responsesystem_new.cpp index 80cbcca6..efa6d27c 100644 --- a/sp/src/game/shared/ai_responsesystem_new.cpp +++ b/sp/src/game/shared/ai_responsesystem_new.cpp @@ -46,6 +46,12 @@ extern ConVar rr_debugrule; // ( "rr_debugrule", "", FCVAR_NONE, "If set to the extern ConVar rr_dumpresponses; // ( "rr_dumpresponses", "0", FCVAR_NONE, "Dump all response_rules.txt and rules (requires restart)" ); extern ConVar rr_debugresponseconcept; // ( "rr_debugresponseconcept", "", FCVAR_NONE, "If set, rr_debugresponses will print only responses testing for the specified concept" ); +static void CC_RR_DumpHashInfo( const CCommand &args ); + +#ifdef MAPBASE +ConVar rr_enhanced_saverestore( "rr_enhanced_saverestore", "0", FCVAR_NONE, "Enables enhanced save/restore capabilities for the Response System." ); +#endif + extern ISceneFileCache *scenefilecache; extern INetworkStringTable *g_pStringTableClientSideChoreoScenes; @@ -622,6 +628,9 @@ public: Precache(); } +#ifdef MAPBASE + if (!rr_enhanced_saverestore.GetBool() || gpGlobals->eLoadType != MapLoad_Transition) +#endif ResetResponseGroups(); } @@ -736,6 +745,14 @@ CON_COMMAND( rr_reloadresponsesystems, "Reload all response system scripts." ) defaultresponsesytem.ReloadAllResponseSystems(); } +#if RR_DUMPHASHINFO_ENABLED +static void CC_RR_DumpHashInfo( const CCommand &args ) +{ + defaultresponsesytem.m_RulePartitions.PrintBucketInfo( &defaultresponsesytem ); +} +static ConCommand rr_dumphashinfo( "rr_dumphashinfo", CC_RR_DumpHashInfo, "Statistics on primary hash bucketing of response rule partitions"); +#endif + #ifdef MAPBASE // Designed for extern magic, this gives the <, >, etc. of response system criteria to the outside world. // Mostly just used for Matcher_Match in matchers.h. @@ -1021,6 +1038,37 @@ public: pSave->EndBlock(); } + +#ifdef MAPBASE + // Enhanced Response System save/restore + int count2 = 0; + if (rr_enhanced_saverestore.GetBool()) + { + // Rule state save/load + count2 = rs.m_RulePartitions.Count(); + pSave->WriteInt( &count2 ); + for ( ResponseRulePartition::tIndex idx = rs.m_RulePartitions.First() ; + rs.m_RulePartitions.IsValid(idx) ; + idx = rs.m_RulePartitions.Next(idx) ) + { + pSave->StartBlock( "Rule" ); + + pSave->WriteString( rs.m_RulePartitions.GetElementName( idx ) ); + const Rule &rule = rs.m_RulePartitions[ idx ]; + + bool bEnabled = rule.m_bEnabled; + Msg( "%s: %i\n", rs.m_RulePartitions.GetElementName( idx ), idx ); + pSave->WriteBool( &bEnabled ); + + pSave->EndBlock(); + } + } + else + { + // Indicate this isn't using enhanced save/restore + pSave->WriteInt( &count2 ); + } +#endif } void Restore( IRestore *pRestore, bool createPlayers ) @@ -1084,6 +1132,36 @@ public: pRestore->EndBlock(); } + +#ifdef MAPBASE + // Enhanced Response System save/restore + count = pRestore->ReadInt(); + for ( int i = 0; i < count; ++i ) + { + char szRuleBlockName[SIZE_BLOCK_NAME_BUF]; + pRestore->StartBlock( szRuleBlockName ); + if ( !Q_stricmp( szRuleBlockName, "Rule" ) ) + { + char groupname[ 256 ]; + pRestore->ReadString( groupname, sizeof( groupname ), 0 ); + + // Try and find it + Rule *rule = rs.m_RulePartitions.FindByName( groupname ); + if ( rule ) + { + bool bEnabled; + pRestore->ReadBool( &bEnabled ); + rule->m_bEnabled = bEnabled; + } + else + { + Warning("Warning: Can't find rule %s\n", groupname); + } + } + + pRestore->EndBlock(); + } +#endif } private: diff --git a/sp/src/responserules/runtime/response_system.cpp b/sp/src/responserules/runtime/response_system.cpp index 94660c58..37d5f0d9 100644 --- a/sp/src/responserules/runtime/response_system.cpp +++ b/sp/src/responserules/runtime/response_system.cpp @@ -21,7 +21,6 @@ using namespace ResponseRules; static void CC_RR_Debug_ResponseConcept_Exclude( const CCommand &args ); static ConCommand rr_debug_responseconcept_exclude( "rr_debugresponseconcept_exclude", CC_RR_Debug_ResponseConcept_Exclude, "Set a list of concepts to exclude from rr_debugresponseconcept. Separate multiple concepts with spaces. Call with no arguments to see current list. Call 'rr_debug_responseconcept_exclude !' to reset."); -static void CC_RR_DumpHashInfo( const CCommand &args ); namespace ResponseRules { @@ -2809,12 +2808,6 @@ static void CC_RR_Debug_ResponseConcept_Exclude( const CCommand &args ) } } #if RR_DUMPHASHINFO_ENABLED -static void CC_RR_DumpHashInfo( const CCommand &args ) -{ - defaultresponsesytem.m_InstancedSystems[0]->m_RulePartitions.PrintBucketInfo( defaultresponsesytem.m_InstancedSystems[0] ); -} -static ConCommand rr_dumphashinfo( "rr_dumphashinfo", CC_RR_DumpHashInfo, "Statistics on primary hash bucketing of response rule partitions"); - void ResponseRulePartition::PrintBucketInfo( CResponseSystem *pSys ) { struct bucktuple_t diff --git a/sp/src/responserules/runtime/response_types_internal.cpp b/sp/src/responserules/runtime/response_types_internal.cpp index 2d11bdd2..72e7eca5 100644 --- a/sp/src/responserules/runtime/response_types_internal.cpp +++ b/sp/src/responserules/runtime/response_types_internal.cpp @@ -47,6 +47,24 @@ char const *ResponseRulePartition::GetElementName( const tIndex &i ) const } +Rule *ResponseRulePartition::FindByName( char const *name ) const +{ + int count; + + for ( int bukkit = 0 ; bukkit < N_RESPONSE_PARTITIONS ; ++bukkit ) + { + count = m_RuleParts[bukkit].Count(); + for ( int i = 0; i < count; ++i ) + { + if (V_strncmp( m_RuleParts[bukkit].GetElementName(i), name, CRR_Response::MAX_RULE_NAME ) == 0) + return m_RuleParts[bukkit][i]; + } + } + + return NULL; +} + + int ResponseRulePartition::Count( void ) { int count = 0 ; diff --git a/sp/src/responserules/runtime/response_types_internal.h b/sp/src/responserules/runtime/response_types_internal.h index 99e766fe..5222c80d 100644 --- a/sp/src/responserules/runtime/response_types_internal.h +++ b/sp/src/responserules/runtime/response_types_internal.h @@ -436,6 +436,7 @@ namespace ResponseRules inline Rule &operator[]( tIndex idx ); int Count( void ); // number of elements inside, but you can't iterate from 0 to this char const *GetElementName( const tIndex &i ) const; + Rule *FindByName( char const *name ) const; /// given a dictionary and an element number inside that dict, /// return a tIndex