bool HasMatchingResearch( AdvancedResearchDef other )
        {
            if( researchDefs.Count != other.researchDefs.Count )
            {
                return false;
            }

            SortResearch();
            other.SortResearch();

            for( int i = 0; i < researchDefs.Count; ++ i )
            {
                if( researchDefs[ i ] != other.researchDefs[ i ] )
                {
                    return false;
                }
            }
            return true;
        }
        static HelpDef HelpForAdvancedResearch( AdvancedResearchDef advancedResearchDef, HelpCategoryDef category )
        {
            var helpDef = new HelpDef();
            helpDef.defName = advancedResearchDef.defName + "_AdvancedResearchDef_Help";
            helpDef.keyDef = advancedResearchDef.defName;
            helpDef.label = advancedResearchDef.label;
            if( advancedResearchDef.helpCategoryDef == null )
            {
                advancedResearchDef.helpCategoryDef = category;
            }
            if( advancedResearchDef.IsHelpEnabled )
            {
                helpDef.category = advancedResearchDef.helpCategoryDef;
            }

            var s = new StringBuilder();

            s.AppendLine( advancedResearchDef.description );
            s.AppendLine();

            #region Base Stats

            s.AppendLine( "AutoHelpTotalCost".Translate( advancedResearchDef.TotalCost.ToString() ) );
            s.AppendLine();

            #endregion

            #region Research, Buildings, Recipes and SowTags

            // Add research required
            var researchDefs = advancedResearchDef.GetResearchRequirements();
            BuildDefDescription( s, "AutoHelpListResearchRequired".Translate(), researchDefs.ConvertAll<Def>( def =>(Def)def ) );

            // Add buildings it unlocks
            var thingDefs = advancedResearchDef.GetThingsUnlocked();
            BuildDefDescription( s, "AutoHelpListThingsUnlocked".Translate(), thingDefs.ConvertAll<Def>( def =>(Def)def ) );

            // Add recipes it unlocks
            var recipeDefs = advancedResearchDef.GetRecipesUnlocked( ref thingDefs );
            BuildDefWithDefDescription( s, "AutoHelpListRecipesUnlocked".Translate(), "AutoHelpListRecipesOnThings".Translate(), recipeDefs.ConvertAll<Def>( def =>(Def)def ), thingDefs.ConvertAll<Def>( def =>(Def)def ) );

            // Add plants and sow tags it unlocks
            var sowTags = advancedResearchDef.GetSowTagsUnlocked( ref thingDefs );
            BuildDefWithStringDescription( s, "AutoHelpListPlantsUnlocked".Translate(), "AutoHelpListPlantsIn".Translate(), thingDefs.ConvertAll<Def>( def =>(Def)def ), sowTags );

            #endregion

            #region Lockouts

            // Add buildings it locks
            thingDefs = advancedResearchDef.GetThingsLocked();
            BuildDefDescription( s, "AutoHelpListThingsLocked".Translate(), thingDefs.ConvertAll<Def>( def =>(Def)def ) );

            // Add recipes it locks
            recipeDefs = advancedResearchDef.GetRecipesLocked( ref thingDefs );
            BuildDefWithDefDescription( s, "Prevents recipes:", "AutoHelpListRecipesOnThings".Translate(), recipeDefs.ConvertAll<Def>( def =>(Def)def ), thingDefs.ConvertAll<Def>( def =>(Def)def ) );

            // Add plants and sow tags it locks
            sowTags = advancedResearchDef.GetSowTagsLocked( ref thingDefs );
            BuildDefWithStringDescription( s, "AutoHelpListPlantsLocked".Translate(), "AutoHelpListPlantsIn".Translate(), thingDefs.ConvertAll<Def>( def =>(Def)def ), sowTags );

            #endregion

            helpDef.description = s.ToString();
            advancedResearchDef.HelpDef = helpDef;
            return helpDef;
        }
        private void ProcessResearch( AdvancedResearchDef Advanced )
        {
            if( Advanced.toggleRecipes ){
                // Recipe toggle on buildings

                // Get each building associated with the advanced research
                for( int bIndex = 0, bCountTo = Advanced.buildingDefs.Count; bIndex < bCountTo; bIndex++ ){
                    ThingDef building = Advanced.buildingDefs[ bIndex ];

                    // Get each recipe associated with the advanced research
                    for( int rIndex = 0, rCountTo = Advanced.recipeDefs.Count; rIndex < rCountTo; rIndex++ ){
                        RecipeDef recipe = Advanced.recipeDefs[ rIndex ];

                        // Show or hide recipes?
                        if( !Advanced.HideDefs )
                        {
                            // Make sure recipe has user list
                            if( recipe.recipeUsers == null )
                                recipe.recipeUsers = new List<ThingDef>();

                            // Add building to recipe
                            recipe.recipeUsers.Add( building );
                        } else {
                            // Remove building from recipe
                            if( ( recipe.recipeUsers != null ) && ( recipe.recipeUsers.IndexOf( building ) >= 0 ) ){
                                recipe.recipeUsers.Remove( building );
                            }

                            // Remove recipe from building
                            if( ( building.recipes != null ) && ( building.recipes.IndexOf( recipe ) >= 0 ) ){
                                building.recipes.Remove( recipe );
                            }
                        }
                    }

                    // Add this building to the list to recache
                    buildingRecipeRecache.Add( building );
                }
            }
            if( Advanced.toggleBuildings ) {
                // Designator toggle on buildings
                for( int bIndex = 0, bCountTo = Advanced.buildingDefs.Count; bIndex < bCountTo; bIndex++ ){
                    ThingDef building = Advanced.buildingDefs[ bIndex ];

                    // Show/Hide as appropriate
                    if( !Advanced.HideDefs ){
                        // Show building
                        building.researchPrerequisite = Research.Unlocker;
                    } else {
                        building.researchPrerequisite = Research.Locker;
                    }
                }
            }
            // Cache any callbacks
            if( Advanced.doCallbacks )
                for( int mIndex = 0, mCountTo = Advanced.researchMods.Count; mIndex < mCountTo; mIndex++ )
                    actionCache.Add( Advanced.researchMods[ mIndex ] );

            // Flag it as enabled to skip it in later checks
            Advanced.isEnabled = true;
        }
 private bool IsRecipeToggle( AdvancedResearchDef Advanced )
 {
     // Determine if this def toggles recipes
     return ( Advanced.recipeDefs != null )&&( Advanced.recipeDefs.Count > 0 )&&
         ( Advanced.buildingDefs != null )&&( Advanced.buildingDefs.Count > 0 );
 }
 private bool HasCallbacks( AdvancedResearchDef Advanced )
 {
     // Determine if this def has callbacks
     return ( Advanced.researchMods != null )&&( Advanced.researchMods.Count > 0 );
 }
        static HelpDef HelpForAdvancedResearch( AdvancedResearchDef advancedResearchDef, HelpCategoryDef category )
        {
            var helpDef = new HelpDef();
            helpDef.defName = advancedResearchDef.defName + "_AdvancedResearchDef_Help";
            helpDef.keyDef = advancedResearchDef;
            helpDef.label = advancedResearchDef.label;
            helpDef.description = advancedResearchDef.description;

            if( advancedResearchDef.helpCategoryDef == null )
            {
                advancedResearchDef.helpCategoryDef = category;
            }
            if( advancedResearchDef.IsHelpEnabled )
            {
                helpDef.category = advancedResearchDef.helpCategoryDef;
            }

            #region Base Stats

            HelpDetailSection totalCost = new HelpDetailSection(
                null,
                new [] {"AutoHelpTotalCost".Translate( advancedResearchDef.TotalCost.ToString() )});

            helpDef.HelpDetailSections.Add( totalCost );

            #endregion

            #region Research, Buildings, Recipes and SowTags

            // Add research required
            var researchDefs = advancedResearchDef.GetResearchRequirements();
            if( !researchDefs.NullOrEmpty() )
            {
                HelpDetailSection researchRequired = new HelpDetailSection(
                    "AutoHelpListResearchRequired".Translate(),
                    researchDefs.ConvertAll<Def>( def =>(Def)def ) );

                helpDef.HelpDetailSections.Add( researchRequired );
            }

            // Add buildings it unlocks
            var thingDefs = advancedResearchDef.GetThingsUnlocked();
            if( !thingDefs.NullOrEmpty() )
            {
                HelpDetailSection thingsUnlocked = new HelpDetailSection(
                    "AutoHelpListThingsUnlocked".Translate(),
                    thingDefs.ConvertAll<Def>( def =>(Def)def ) );

                helpDef.HelpDetailSections.Add( thingsUnlocked );
            }

            // Add recipes it unlocks
            var recipeDefs = advancedResearchDef.GetRecipesUnlocked( ref thingDefs );
            if(
                (!recipeDefs.NullOrEmpty()) &&
                (!thingDefs.NullOrEmpty())
            )
            {
                HelpDetailSection recipesUnlocked = new HelpDetailSection(
                    "AutoHelpListRecipesUnlocked".Translate(),
                    recipeDefs.ConvertAll<Def>( def =>(Def)def ) );

                helpDef.HelpDetailSections.Add( recipesUnlocked );

                HelpDetailSection recipesOnThingsUnlocked = new HelpDetailSection(
                    "AutoHelpListRecipesOnThings".Translate(),
                    thingDefs.ConvertAll<Def>(def => (Def)def));

                helpDef.HelpDetailSections.Add( recipesOnThingsUnlocked );
            }

            // Add plants and sow tags it unlocks
            var sowTags = advancedResearchDef.GetSowTagsUnlocked( ref thingDefs );
            if(
                (!sowTags.NullOrEmpty()) &&
                (!thingDefs.NullOrEmpty())
            )
            {
                HelpDetailSection plantsUnlocked = new HelpDetailSection(
                    "AutoHelpListPlantsUnlocked".Translate(),
                    thingDefs.ConvertAll<Def>( def =>(Def)def ) );

                helpDef.HelpDetailSections.Add( plantsUnlocked );

                HelpDetailSection recipesOnThingsUnlocked = new HelpDetailSection(
                    "AutoHelpListPlantsIn".Translate(),
                    sowTags.ToArray() );

                helpDef.HelpDetailSections.Add( recipesOnThingsUnlocked );
            }

            #endregion

            #region Lockouts

            // Add buildings it locks
            thingDefs = advancedResearchDef.GetThingsLocked();
            if( !thingDefs.NullOrEmpty() )
            {
                HelpDetailSection thingsLocked = new HelpDetailSection(
                    "AutoHelpListThingsLocked".Translate(),
                    thingDefs.ConvertAll<Def>( def =>(Def)def ) );

                helpDef.HelpDetailSections.Add( thingsLocked );
            }

            // Add recipes it locks
            recipeDefs = advancedResearchDef.GetRecipesLocked( ref thingDefs );
            if(
                (!recipeDefs.NullOrEmpty()) &&
                (!thingDefs.NullOrEmpty())
            )
            {
                HelpDetailSection recipesLocked = new HelpDetailSection(
                    "AutoHelpListRecipesLocked".Translate(), recipeDefs.ConvertAll<Def>( def =>(Def)def ) );

                helpDef.HelpDetailSections.Add( recipesLocked );

                HelpDetailSection recipesOnThings = new HelpDetailSection(
                    "AutoHelpListRecipesOnThings".Translate(), thingDefs.ConvertAll<Def>( def =>(Def)def ) );

                helpDef.HelpDetailSections.Add( recipesOnThings );
            }

            // Add plants and sow tags it locks
            sowTags = advancedResearchDef.GetSowTagsLocked( ref thingDefs );
            if(
                (!sowTags.NullOrEmpty()) &&
                (!thingDefs.NullOrEmpty())
            )
            {
                HelpDetailSection plantsLocked = new HelpDetailSection(
                    "AutoHelpListPlantsLocked".Translate(),
                    thingDefs.ConvertAll<Def>( def =>(Def)def ) );

                helpDef.HelpDetailSections.Add( plantsLocked );

                HelpDetailSection plantsIn = new HelpDetailSection(
                    "AutoHelpListPlantsIn".Translate(),
                    sowTags.ToArray() );

                helpDef.HelpDetailSections.Add( plantsIn );
            }

            #endregion

            advancedResearchDef.HelpDef = helpDef;
            return helpDef;
        }