/// <summary>
        /// Saves the current RICO settings to file and then applies them live in-game.
        /// </summary>
        private void SaveAndApply()
        {
            // Find current prefab instance.
            BuildingData currentBuildingData = Loading.xmlManager.prefabHash[currentSelection.prefab];

            // Save first.
            Save();

            // If we're converting a residential building to something else, then we first should clear out all households.
            if (currentBuildingData.prefab.GetService() == ItemClass.Service.Residential && !IsCurrentResidential())
            {
                // removeAll argument to true to remove all households.
                UpdateHouseholds(currentBuildingData.prefab.name, removeAll: true);
            }

            // Get the currently applied RICO settings (local, author, mod).
            RICOBuilding currentData = RICOUtils.CurrentRICOSetting(currentSelection);

            if (currentData != null)
            {
                // Convert the 'live' prefab (instance in PrefabCollection) and update household count and builidng level for all current instances.
                Loading.convertPrefabs.ConvertPrefab(currentData, PrefabCollection <BuildingInfo> .FindLoaded(currentBuildingData.prefab.name));
                UpdateHouseholds(currentBuildingData.prefab.name, currentData.level);
            }
            else
            {
                Debugging.Message("no current RICO settings to apply to prefab " + currentBuildingData);
            }

            // Force an update of all panels with current values.
            SettingsPanel.Panel.UpdateSelectedBuilding(currentSelection);
        }
        /// <summary>
        /// Saves the current RICO settings to file and then applies them live in-game.
        /// </summary>
        private void SaveAndApply()
        {
            // Find current prefab instance.
            BuildingData currentBuildingData = Loading.xmlManager.prefabHash[currentSelection.prefab];

            // Save first.
            Save();

            // Get the currently applied RICO settings (local, author, mod).
            RICOBuilding currentData = RICOUtils.CurrentRICOSetting(currentSelection);

            if (currentData != null)
            {
                // Convert the 'live' prefab (instance in PrefabCollection) and update household count and builidng level for all current instances.
                Loading.convertPrefabs.ConvertPrefab(currentData, PrefabCollection <BuildingInfo> .FindLoaded(currentBuildingData.prefab.name));
                CitizenUnitUtils.UpdateCitizenUnits(currentBuildingData.prefab.name);
            }
            else
            {
                Logging.Message("no current RICO settings to apply to prefab ", currentBuildingData.prefab.name);
            }

            // Force an update of all panels with current values.
            SettingsPanel.Panel.UpdateSelectedBuilding(currentSelection);
        }
        /// <summary>
        /// Checks to see if a building should be demolished if it's not in a district with the relevant specialisation.
        /// Called via Harmony Transpiler patches.
        /// </summary>
        /// <param name="buildingData">Building instance data</param>
        internal static void CheckSpecial(ref Building buildingData)
        {
            bool isRICO = RICOUtils.IsRICOAI(buildingData.Info.GetAI() as PrivateBuildingAI);

            // Check if the relevant 'ignore specialisation' setting is set.
            // If it is, we just don't do anything.  Otherwise, we mimic the base game's code for this ocurrence.
            if (!(ModSettings.noSpecOther && !isRICO) && !(ModSettings.noSpecRico && isRICO))
            {
                buildingData.m_flags |= Building.Flags.Demolishing;
                Singleton <SimulationManager> .instance.m_currentBuildIndex++;
            }
        }
        /// <summary>
        /// Harmony Postfix patch to force 'too few services' complaints off for all buildings.
        /// </summary>
        /// <param name="tooFewServices">If a 'too few services' complaint has been calculated</param>
        /// <param name="buildingID">Building instance ID</param>
        public static void Postfix(ref bool tooFewServices, ushort buildingID)
        {
            // Check if this building is RICO or not.
            bool isRICO = RICOUtils.IsRICOBuilding(buildingID);

            // Check if the relevant 'ignore too few services complaint' setting is set.
            if ((ModSettings.noServicesOther && !isRICO) || (ModSettings.noServicesRicoGrow && isRICO) || (ModSettings.noServicesRicoPlop && RICOUtils.IsRICOPloppable(buildingID)))
            {
                // It is - force too few services complaint off.
                tooFewServices = false;
            }
        }
        /// <summary>
        /// Harmony Postfix patch to force 'land value too low' complaints off for all buildings.
        /// </summary>
        /// <param name="landValueTooLow">If a 'land value too low' complaint has been calculated</param>
        /// <param name="buildingID">Building instance ID</param>
        public static void Postfix(ref bool landValueTooLow, ushort buildingID)
        {
            // Check if this building is RICO or not.
            bool isRICO = RICOUtils.IsRICOBuilding(buildingID);

            // Check if the relevant 'ignore low land value complaint' setting is set.
            if ((ModSettings.noValueOther && !isRICO) || (ModSettings.noValueRicoGrow && isRICO) || (ModSettings.noValueRicoPlop && RICOUtils.IsRICOPloppable(buildingID)))
            {
                // It is - force land value complaint off.
                landValueTooLow = false;
            }
        }
        /// <summary>
        /// Simple Prefix patch to toggle excecution of game method based on current settings.
        /// </summary>
        /// <param name="__instance">Harmony original instance reference</param>
        /// <returns>False if the base method shouldn't be called (collapse has been prevented), true otherwise</returns>
        public static bool Prefix(ref bool __result, CommonBuildingAI __instance)
        {
            if (ModSettings.noCollapse && RICOUtils.IsRICOPloppableAI(__instance as PrivateBuildingAI))
            {
                __result = false;

                // Don't call base method after this.
                return(false);
            }

            // Continue on to base method
            return(true);
        }
        /// <summary>
        /// Handles click events for Ploppable Tool panel tabs.
        /// </summary>
        /// <param name="panel">The Ploppable Tool panel for the selected tab</param>
        /// <param name="sprite">The sprite icon for the selected tab</param>
        public void TabClicked(int uiCategory, UISprite sprite)
        {
            // Clear the scroll panel.
            scrollPanel.Clear();

            // List of buildings in this category.
            List <BuildingData> buildingList = new List <BuildingData>();

            // Iterate through each prefab in our collection and see if it has RICO settings with a matching UI category.
            foreach (BuildingData buildingData in Loading.xmlManager.prefabHash.Values)
            {
                // Get the currently active RICO setting (if any) for this building.
                RICOBuilding ricoSetting = RICOUtils.CurrentRICOSetting(buildingData);

                // See if there's a valid RICO setting.
                if (ricoSetting != null)
                {
                    // Valid setting - if the UI category matches this one, add it to the list.
                    if (UICategoryIndex(ricoSetting.UiCategory) == uiCategory)
                    {
                        buildingList.Add(buildingData);
                    }
                }
            }

            // Set display FastList using our list of selected buildings, sorted alphabetically.
            scrollPanel.itemsData.m_buffer = buildingList.OrderBy(x => x.DisplayName).ToArray();
            scrollPanel.itemsData.m_size   = buildingList.Count;

            // Display the scroll panel.
            scrollPanel.DisplayAt(0);

            // Redraw all tab sprites in their base state (unfocused).
            for (int i = 0; i <= NumTypes; i++)
            {
                if (i <= 5)
                {
                    TabSprites[i].spriteName = "Zoning" + Names[i];
                }
                else
                {
                    TabSprites[i].spriteName = "IconPolicy" + Names[i];
                }
            }

            // Focus this sprite (no focused versions for AD or GC sprites so exclude those).
            if (sprite.spriteName != "IconPolicyLeisure" && sprite.spriteName != "IconPolicyTourist" && sprite.spriteName != "IconPolicyHightech" && sprite.spriteName != "IconPolicyOrganic" && sprite.spriteName != "IconPolicySelfsufficient")
            {
                sprite.spriteName += "Focused";
            }
        }
        public static bool NewZoneCheck(ref Building buildingData, ItemClass.Zone zone1, ItemClass.Zone zone2, bool allowCollapse)
        {
            // Check if this building is RICO or not.
            bool isRICO = RICOUtils.IsRICOAI(buildingData.Info.GetAI() as PrivateBuildingAI);

            // Check if the relevant 'ignore zoning' setting is set.
            if ((ModSettings.noZonesOther && !isRICO) || (ModSettings.noZonesRico && isRICO))
            {
                // It is - return true (tell the game we're in a valid zone).
                return(true);
            }

            // If we got here, this isn't a building covered by our settings: call original method and return its result.
            return(buildingData.CheckZoning(zone1, zone2, allowCollapse));
        }
Example #9
0
        /// <summary>
        /// Harmony Postfix patch to skip 'gradual construction' for plopped RICO growables, and/or to apply the 'Make Historical' and/or 'Lock level' settings on building creation, accoriding to settings.
        /// </summary>
        /// <param name="__result">Original method result (unchanged)</param>
        /// <param name="info">BuildingInfo prefab for this building (unchanged)</param>
        /// <param name="position">Building position (ignored)</param>
        /// <param name="angle">Building rotation (ignored)</param>
        /// <param name="relocating">Building relocation (ignored)</param>
        /// <param name="needMoney">Is money needed (ignored)</param>
        /// <param name="fixedHeight">Fixed height (ignored)</param>
        internal static void Postfix(ref ushort __result, ref BuildingInfo info, Vector3 position, float angle, int relocating, bool needMoney, bool fixedHeight)
        {
            // Check that we have a valid building ID.
            if (__result == 0)
            {
                return;
            }

            // Get building AI.
            PrivateBuildingAI buildingAI = info.GetAI() as PrivateBuildingAI;

            // Only interested in private building AI.
            if (buildingAI != null)
            {
                // Check if AI is a RICO custom AI type.
                bool isRICO = RICOUtils.IsRICOAI(buildingAI);

                // Check if it's a RICO custom AI type.
                // Enable 'ploppable growables' if option is set.
                if ((ModSettings.plopOther && !isRICO) || (ModSettings.plopRico && isRICO))
                {
                    // Check to see if construction time is greater than zero.
                    if (buildingAI.m_constructionTime > 0)
                    {
                        Singleton <BuildingManager> .instance.m_buildings.m_buffer[__result].m_frame0.m_constructState = byte.MaxValue;
                        BuildingCompletedRev(buildingAI, __result, ref Singleton <BuildingManager> .instance.m_buildings.m_buffer[__result]);

                        // Have to do this manually as CommonBuildingAI.BuildingCompleted won't if construction time isn't zero.
                        Singleton <BuildingManager> .instance.UpdateBuildingRenderer(__result, updateGroup : true);
                    }
                }

                // Enable 'Make Historical' if option is set.
                if ((ModSettings.historicalOther && !isRICO) || (ModSettings.historicalRico && isRICO))
                {
                    info.m_buildingAI.SetHistorical(__result, ref Singleton <BuildingManager> .instance.m_buildings.m_buffer[__result], historical: true);
                }

                // Enable ABLC level lock if option is set and ABLC is running.
                if (ModUtils.ablcLockBuildingLevel != null && ((ModSettings.lockLevelOther && !isRICO) || (ModSettings.lockLevelRico && isRICO)))
                {
                    ModUtils.ablcLockBuildingLevel.Invoke(null, new object[] { __result, Singleton <BuildingManager> .instance.m_buildings.m_buffer[__result].m_level });
                }
            }
        }
Example #10
0
        /// <summary>
        /// Called by other mods to determine whether or not Ploppable RICO Revisited is controlling the population of this prefab.
        /// </summary>
        /// <param name="prefab">Prefab reference</param>
        /// <returns>True if Ploppable RICO is controlling the population of this prefab, false otherwise.</returns>
        public static bool IsRICOPopManaged(BuildingInfo prefab)
        {
            // First, do we have a setting at all?
            if (prefab != null && Loading.xmlManager.prefabHash.ContainsKey(prefab))
            {
                // Get active RICO settings.
                RICOBuilding building = RICOUtils.CurrentRICOSetting(Loading.xmlManager.prefabHash[prefab]);

                // Check that it's enabled and isn't using reality.
                if (building != null && building.ricoEnabled && !building.UseReality)
                {
                    return(true);
                }
            }

            // If we got here, we don't have an active setting.
            return(false);
        }
Example #11
0
        /// <summary>
        /// Event handler for demolish warning checkbox.
        /// </summary>
        /// <param name="control">Calling UIComponent</param>
        /// <param name="isChecked">New isChecked state</param>
        private void DemolishWarnCheckChanged(UIComponent control, bool isChecked)
        {
            // Update mod settings.
            ModSettings.warnBulldoze = isChecked;

            // If we're in-game (dictionary has been initialized), iterate through dictionary, looking for RICO ploppable buildings and updating their auto-remove flags.
            if (Loading.xmlManager?.prefabHash != null)
            {
                foreach (BuildingInfo prefab in Loading.xmlManager.prefabHash.Keys)
                {
                    // Get active RICO settings.
                    RICOBuilding building = RICOUtils.CurrentRICOSetting(Loading.xmlManager.prefabHash[prefab]);

                    // Check that it's enabled and isn't growable.
                    if (building != null && building.ricoEnabled && !building.growable)
                    {
                        // Apply flag.
                        prefab.m_autoRemove = !isChecked;
                    }
                }
            }
        }
 /// <summary>
 /// Checks to see whether or not the specified building is a Ploppable RICO building.
 /// </summary>
 /// <param name="buildingID">Building instance ID</param>
 /// <returns>True if this is a Ploppable RICO building, false otherwise</returns>
 private bool IsRICOBuilding(ushort buildingID) => RICOUtils.IsRICOAI(Singleton <BuildingManager> .instance.m_buildings.m_buffer[buildingID].Info.GetAI() as PrivateBuildingAI);