Exemple #1
0
        /// <summary>
        /// Calculates the construction cost of a workplace, depending on current settings (overrides or default).
        /// </summary>
        /// <param name="thisAI">AI reference to calculate for</param>
        /// <returns>Final construction cost</returns>
        internal static int WorkplaceConstructionCost(PrivateBuildingAI thisAI, int fixedCost)
        {
            int baseCost;

            // Local references.
            BuildingInfo thisInfo = thisAI.m_info;

            ItemClass.Level thisLevel = thisInfo.GetClassLevel();

            // Are we overriding cost?
            if (ModSettings.overrideCost)
            {
                // Yes - calculate based on workplaces by level multiplied by appropriate cost-per-job setting.
                thisAI.CalculateWorkplaceCount(thisLevel, new Randomizer(), thisInfo.GetWidth(), thisInfo.GetLength(), out int jobs0, out int jobs1, out int jobs2, out int jobs3);
                baseCost = (ModSettings.costPerJob0 * jobs0) + (ModSettings.costPerJob1 * jobs1) + (ModSettings.costPerJob2 * jobs2) + (ModSettings.costPerJob3 * jobs3);
            }
            else
            {
                // No - just use the base cost provided.
                baseCost = fixedCost;
            }

            // Multiply base cost by 100 before feeding to EconomyManager for nomalization to game conditions prior to return.
            baseCost *= 100;
            Singleton <EconomyManager> .instance.m_EconomyWrapper.OnGetConstructionCost(ref baseCost, thisInfo.GetService(), thisInfo.GetSubService(), thisLevel);

            return(baseCost);
        }
        public static int HandleWorkers(PrivateBuildingAI thisAI, ushort buildingID, ref Building buildingData, ref Citizen.BehaviourData behaviour, ref int aliveWorkerCount, ref int totalWorkerCount, ref int workPlaceCount)
        {
            //Not messed with this code too much yet. Still requires cleaning up.

            int b = 0;
            int level0, level1, level2, level3;

            //Fix for crashing? Modification added for this statement
            if (thisAI != null)
            {
                GetWorkBehaviour(thisAI, buildingID, ref buildingData, ref behaviour, ref aliveWorkerCount, ref totalWorkerCount);
                thisAI.CalculateWorkplaceCount(new Randomizer((int)buildingID), buildingData.Width, buildingData.Length, out level0, out level1, out level2, out level3);
                workPlaceCount = level0 + level1 + level2 + level3;

                if ((int)buildingData.m_fireIntensity == 0)
                {
                    HandleWorkPlaces(thisAI, buildingID, ref buildingData, level0, level1, level2, level3, ref behaviour, aliveWorkerCount, totalWorkerCount);
                    if (aliveWorkerCount != 0 && workPlaceCount != 0)
                    {
                        int num = (behaviour.m_efficiencyAccumulation + aliveWorkerCount - 1) / aliveWorkerCount;
                        b = 2 * num - 200 * num / ((100 * aliveWorkerCount + workPlaceCount - 1) / workPlaceCount + 100);
                    }
                }

                Notification.Problem problems1 = Notification.RemoveProblems(buildingData.m_problems, Notification.Problem.NoWorkers | Notification.Problem.NoEducatedWorkers);
                int num1 = (level3 * 300 + level2 * 200 + level1 * 100) / (workPlaceCount + 1);
                int num2 = (behaviour.m_educated3Count * 300 + behaviour.m_educated2Count * 200 + behaviour.m_educated1Count * 100) / (aliveWorkerCount + 1);

                //Start of modification

                if (Chances.WorkHour())
                {
                    if (aliveWorkerCount < workPlaceCount >> 1)
                    {
                        buildingData.m_workerProblemTimer = (byte)Mathf.Min((int)byte.MaxValue, (int)buildingData.m_workerProblemTimer + 1);
                        if ((int)buildingData.m_workerProblemTimer >= 128)
                            problems1 = Notification.AddProblems(problems1, Notification.Problem.NoWorkers | Notification.Problem.MajorProblem);
                        else if ((int)buildingData.m_workerProblemTimer >= 64)
                            problems1 = Notification.AddProblems(problems1, Notification.Problem.NoWorkers);
                    }
                    else if (num2 < num1 - 50)
                    {
                        buildingData.m_workerProblemTimer = (byte)Mathf.Min((int)byte.MaxValue, (int)buildingData.m_workerProblemTimer + 1);
                        if ((int)buildingData.m_workerProblemTimer >= 128)
                            problems1 = Notification.AddProblems(problems1, Notification.Problem.NoEducatedWorkers | Notification.Problem.MajorProblem);
                        else if ((int)buildingData.m_workerProblemTimer >= 64)
                            problems1 = Notification.AddProblems(problems1, Notification.Problem.NoEducatedWorkers);
                    }
                    else
                        buildingData.m_workerProblemTimer = (byte)0;
                }

                //End of modification

                buildingData.m_problems = problems1;
            }
            return Mathf.Max(1, b);
        }
        /// <summary>
        /// Custom implementation of PrivateBuildingAI.BuildingUpgraded that takes into account that our levels can be upgraded OR downgraded; for use when current building level is below the set prefb leve.
        /// </summary>
        /// <param name="buildingAI">Building AI instance</param>
        /// <param name="buildingID">Building instance ID</param>
        /// <param name="data">Building data record</param>
        private static void CustomBuildingUpgraded(PrivateBuildingAI buildingAI, ushort buildingID, ref Building data)
        {
            buildingAI.CalculateWorkplaceCount((ItemClass.Level)data.m_level, new Randomizer(buildingID), data.Width, data.Length, out int level, out int level2, out int level3, out int level4);
            buildingAI.AdjustWorkplaceCount(buildingID, ref data, ref level, ref level2, ref level3, ref level4);
            int workCount  = level + level2 + level3 + level4;
            int homeCount  = buildingAI.CalculateHomeCount((ItemClass.Level)data.m_level, new Randomizer(buildingID), data.Width, data.Length);
            int visitCount = buildingAI.CalculateVisitplaceCount((ItemClass.Level)data.m_level, new Randomizer(buildingID), data.Width, data.Length);

            ReversePatches.EnsureCitizenUnits(buildingAI, buildingID, ref data, homeCount, workCount, visitCount, 0);
        }
        public static int HandleWorkers(PrivateBuildingAI thisAI, ushort buildingID, ref Building buildingData, ref Citizen.BehaviourData behaviour, ref int aliveWorkerCount, ref int totalWorkerCount, ref int workPlaceCount)
        {
            //Not messed with this code too much yet. Still requires cleaning up.

            int b = 0;
            int level0, level1, level2, level3;

            //Fix for crashing? Modification added for this statement
            if (thisAI != null)
            {
                GetWorkBehaviour(thisAI, buildingID, ref buildingData, ref behaviour, ref aliveWorkerCount, ref totalWorkerCount);
                thisAI.CalculateWorkplaceCount(new Randomizer((int)buildingID), buildingData.Width, buildingData.Length, out level0, out level1, out level2, out level3);
                workPlaceCount = level0 + level1 + level2 + level3;

                if ((int)buildingData.m_fireIntensity == 0)
                {
                    HandleWorkPlaces(thisAI, buildingID, ref buildingData, level0, level1, level2, level3, ref behaviour, aliveWorkerCount, totalWorkerCount);
                    if (aliveWorkerCount != 0 && workPlaceCount != 0)
                    {
                        int num = (behaviour.m_efficiencyAccumulation + aliveWorkerCount - 1) / aliveWorkerCount;
                        b = 2 * num - 200 * num / ((100 * aliveWorkerCount + workPlaceCount - 1) / workPlaceCount + 100);
                    }
                }

                Notification.Problem problems1 = Notification.RemoveProblems(buildingData.m_problems, Notification.Problem.NoWorkers | Notification.Problem.NoEducatedWorkers);
                int num1 = (level3 * 300 + level2 * 200 + level1 * 100) / (workPlaceCount + 1);
                int num2 = (behaviour.m_educated3Count * 300 + behaviour.m_educated2Count * 200 + behaviour.m_educated1Count * 100) / (aliveWorkerCount + 1);

                //Start of modification

                if (Chances.WorkHour())
                {
                    if (aliveWorkerCount < workPlaceCount >> 1)
                    {
                        buildingData.m_workerProblemTimer = (byte)Mathf.Min((int)byte.MaxValue, (int)buildingData.m_workerProblemTimer + 1);
                        if ((int)buildingData.m_workerProblemTimer >= 128)
                        {
                            problems1 = Notification.AddProblems(problems1, Notification.Problem.NoWorkers | Notification.Problem.MajorProblem);
                        }
                        else if ((int)buildingData.m_workerProblemTimer >= 64)
                        {
                            problems1 = Notification.AddProblems(problems1, Notification.Problem.NoWorkers);
                        }
                    }
                    else if (num2 < num1 - 50)
                    {
                        buildingData.m_workerProblemTimer = (byte)Mathf.Min((int)byte.MaxValue, (int)buildingData.m_workerProblemTimer + 1);
                        if ((int)buildingData.m_workerProblemTimer >= 128)
                        {
                            problems1 = Notification.AddProblems(problems1, Notification.Problem.NoEducatedWorkers | Notification.Problem.MajorProblem);
                        }
                        else if ((int)buildingData.m_workerProblemTimer >= 64)
                        {
                            problems1 = Notification.AddProblems(problems1, Notification.Problem.NoEducatedWorkers);
                        }
                    }
                }

                //End of modification

                buildingData.m_problems = problems1;
            }
            return(Mathf.Max(1, b));
        }
        /// <summary>
        /// Prefix to force settings reset on load (if enabled) for RICO buildings (resetting to current settings).
        /// </summary>
        /// <param name="__instance">Original object instance reference</param>
        /// <param name="buildingID">Building instance ID</param>
        /// <param name="data">Building data</param>
        /// <param name="version">Version</param>
        private static bool Prefix(PrivateBuildingAI __instance, ushort buildingID, ref Building data, uint version)
        {
            // Don't do anything if the flag isn't set.
            if (!ModSettings.resetOnLoad)
            {
                // Carry on to original method.
                return(true);
            }

            // Check to see if we've preloaded a local settings file.
            if (Loading.localRicoDef != null)
            {
                // Step through each definition from the local settings file, looking for a match.
                foreach (RICOBuilding building in Loading.localRicoDef.Buildings)
                {
                    if (building.ricoEnabled && __instance.m_info.name == building.name)
                    {
                        // m_level is one less than building.level.
                        byte newLevel = (byte)(building.level - 1);

                        if (data.m_level != newLevel)
                        {
                            Debugging.Message("found building '" + building.name + "' with level " + (data.m_level + 1) + ", overriding to level " + building.level);
                            data.m_level = newLevel;
                        }

                        // Basic game code processing to continue initialisation.
                        __instance.CalculateWorkplaceCount((ItemClass.Level)data.m_level, new Randomizer(buildingID), data.Width, data.Length, out int level, out int level2, out int level3, out int level4);
                        __instance.AdjustWorkplaceCount(buildingID, ref data, ref level, ref level2, ref level3, ref level4);

                        int workCount       = level + level2 + level3 + level4;
                        int targetHomeCount = 0;

                        // Update visitor count.
                        int visitCount = __instance.CalculateVisitplaceCount((ItemClass.Level)data.m_level, new Randomizer(buildingID), data.Width, data.Length);

                        // Check to see if rsidential building homecounts differ from settings.
                        if (building.service == "residential")
                        {
                            int currentHomeCount = 0;

                            // Count currently applied citizen units (households).
                            if (data.m_citizenUnits != 0)
                            {
                                // At least one household here; get the first.
                                CitizenUnit citizenUnit = Singleton <CitizenManager> .instance.m_units.m_buffer[data.m_citizenUnits];
                                currentHomeCount = 1;

                                // Step through all applied citizen units (linked via m_nextUnit), counting as we go,
                                while (citizenUnit.m_nextUnit != 0)
                                {
                                    citizenUnit = Singleton <CitizenManager> .instance.m_units.m_buffer[citizenUnit.m_nextUnit];
                                    currentHomeCount++;
                                }
                            }

                            // Determine target household count.
                            targetHomeCount = __instance.CalculateHomeCount((ItemClass.Level)data.m_level, new Randomizer(buildingID), data.Width, data.Length);

                            // If target household count is lower than the current household count, we need to perform a forced reset.
                            // The reverse case, targets greater than current, will be caught with the base-case call to EnsureCitizenUnits below.
                            if (targetHomeCount < currentHomeCount)
                            {
                                Debugging.Message("found Residential prefab " + building.name + " with target homecount " + targetHomeCount + " and citizen units " + currentHomeCount + "; forcing homecount reset");
                                RealisticCitizenUnits.EnsureCitizenUnits(ref __instance, buildingID, ref data, targetHomeCount, workCount, visitCount, 0);
                            }
                        }

                        // Update citizen units to match new totals.
                        EnsureCitizenUnitsRev(__instance, buildingID, ref data, targetHomeCount, workCount, visitCount, 0);

                        // Clear any problems (so we don't have any residual issues from changing service types, for example (new) residential buildings showing 'not enough goods'.
                        // Any 'genuine' problems will be quickly reapplied by the game.
                        data.m_problems = 0;

                        // We've set things up here for Ploppable RICO - don't fall through to game code.
                        return(false);
                    }
                }
            }

            // If we've hit this point, then no Ploppable RICO setup has occured - fall through to game code.
            return(true);
        }