/// <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); }