/// <summary> /// Render the preview image. /// </summary> private void RenderPreview() { // Don't do anything if there's no prefab to render. if (currentSelection == null) { return; } // Select pack to render; override if there is one, otherwise the selected floor pack. FloorDataPack renderFloorPack = overrideFloors ?? floorPack; // Are we going to render floors? bool doFloors = renderFloors && !hideFloors; // If the selected building has colour variations, temporarily set the colour to the default for rendering. if (currentSelection.m_useColorVariations && currentSelection.m_material != null) { Color originalColor = currentSelection.m_material.color; currentSelection.m_material.color = currentSelection.m_color0; previewRender.Render(doFloors, renderFloorPack); currentSelection.m_material.color = originalColor; } else { // No temporary colour change needed. previewRender.Render(doFloors, renderFloorPack); } }
/// <summary> /// Updates the floor summary text labels with data from the current floor. /// </summary> /// <param name="floorData">FloorData record to summarise</param> internal void UpdateFloorText(FloorDataPack floorData) { // Set textfield values. firstMinLabel.text = floorData.firstFloorMin.ToString(); firstExtraLabel.text = floorData.firstFloorExtra.ToString(); floorHeightLabel.text = floorData.floorHeight.ToString(); // Set checkbox. ignoreFirstCheckBox.isChecked = floorData.firstFloorEmpty; }
/// <summary> /// Populates the textfields with data from the selected calculation pack. /// </summary> /// <param name="index">Index number of calculation pack</param> private void PopulateTextFields(int index) { // Get local reference. FloorDataPack floorPack = (FloorDataPack)packList[index]; // Set name field. PackNameField.text = floorPack.displayName ?? floorPack.name; // Populate controls. floorHeightField.text = floorPack.floorHeight.ToString(); firstMinField.text = floorPack.firstFloorMin.ToString(); firstExtraField.text = floorPack.firstFloorExtra.ToString(); firstEmptyCheck.isChecked = floorPack.firstFloorEmpty; }
/// <summary> /// Adds a custom floor override to a building prefab, but does NOT update live prefab data or save the configuration file. /// Used to populate dictionary when the prefab isn't available (e.g. before loading is complete). /// </summary> /// <param name="building">Name of building prefab to add</param> /// <param name="overridePack">Override floor pack to set</param> internal void SetOverride(string buildingName, FloorDataPack overridePack) { // Check to see if we already have an entry for this building. if (!overrides.ContainsKey(buildingName)) { // No - create new entry. overrides.Add(buildingName, overridePack); } else { // An entry for this building already exists - update it. overrides[buildingName] = overridePack; } }
/// <summary> /// 'Add new pack' button event handler. /// </summary> /// <param name="control">Calling component (unused)</param> /// <param name="mouseEvent">Mouse event (unused)</param> protected override void AddPack(UIComponent control, UIMouseEventParameter mouseEvent) { // Default new pack name. string basePackName = Translations.Translate("RPR_OPT_NPK"); string newPackName = basePackName; // Integer suffix for when the above name already exists (starts with 2). int packNum = 2; // Starting with our default new pack name, check to see if we already have a pack with this name for the currently selected service. while (FloorData.instance.calcPacks.Find(pack => pack.name.Equals(newPackName)) != null) { // We already have a match for this name; append the current integer suffix to the base name and try again, incementing the integer suffix for the next attempt (if required). newPackName = "New pack " + packNum++; } // We now have a unique name; set the textfield. PackNameField.text = newPackName; // Add new pack with basic values (deails will be populated later). FloorDataPack newPack = new FloorDataPack { version = (int)DataVersion.customOne }; // Update pack with information from the panel. UpdatePack(newPack); // Add our new pack to our list of packs and update defaults panel menus. FloorData.instance.AddCalculationPack(newPack); CalculationsPanel.Instance.UpdateDefaultMenus(); // Update pack menu. packDropDown.items = PackList(); // Set pack selection by iterating through each pack in the menu and looking for a match. for (int i = 0; i < packDropDown.items.Length; ++i) { if (packDropDown.items[i].Equals(newPack.displayName)) { // Got a match; apply selected index and stop looping. packDropDown.selectedIndex = i; break; } } // Save configuration file. ConfigUtils.SaveSettings(); }
/// <summary> /// Sets a custom floor override override for the given building prefab, and saves the updated configuration; and also UPDATES live prefab data. /// Used to add an entry in-game after prefabs have loaded. /// </summary> /// <param name="prefab">Building prefab/param> /// <param name="overridePack">Override floor pack to set</param> internal void SetOverride(BuildingInfo prefab, FloorDataPack overridePack) { // Apply changes. SetOverride(prefab.name, overridePack); // Apply school changes if this is a school. if (prefab.GetService() == ItemClass.Service.Education) { SchoolData.instance.UpdateSchoolPrefab(prefab); } // Save updated configuration file. ConfigUtils.SaveSettings(); // Refresh the prefab's population settings to reflect changes. RefreshPrefab(prefab); }
/// <summary> /// Updates the floor calculation pack selection to the selected calculation pack. /// </summary> /// <param name="index">Index number (from menu) of selection pack</param> private void UpdateFloorSelection(int index) { // Update selected pack. currentFloorPack = (FloorDataPack)floorPacks[index]; // Update description. floorDescription.text = currentFloorPack.description; // Update panel with new calculations, assuming that we're not using legacy popultion calcs. volumetricPanel.UpdateFloorText(currentFloorPack); if (currentPopPack.version != (int)DataVersion.legacy) { volumetricPanel.CalculateVolumetric(currentBuilding, CurrentLevelData, currentFloorPack, currentSchoolPack, currentMult); } // Communicate change with to rest of panel. BuildingDetailsPanel.Panel.FloorDataPack = currentFloorPack; }
/// <summary> /// Load settings from XML file. /// </summary> internal static void LoadSettings() { try { // Check to see if configuration file exists. if (File.Exists(ConfigFileName)) { // Read it. using (StreamReader reader = new StreamReader(ConfigFileName)) { XmlSerializer xmlSerializer = new XmlSerializer(typeof(XMLConfigurationFile)); if (!(xmlSerializer.Deserialize(reader) is XMLConfigurationFile configFile)) { Logging.Error("couldn't deserialize configuration file"); } else { // Deserialise population calculation packs. foreach (PopPackXML xmlPack in configFile.popPacks) { // Convert to volumetric pack. VolumetricPopPack volPack = new VolumetricPopPack() { name = xmlPack.name, displayName = xmlPack.name, service = xmlPack.service, version = (int)DataVersion.customOne, levels = new LevelData[xmlPack.calculationLevels.Count] }; // Iterate through each level in the xml and add to our volumetric pack. foreach (PopLevel calculationLevel in xmlPack.calculationLevels) { volPack.levels[calculationLevel.level] = new LevelData() { //floorHeight = calculationLevel.floorHeight, emptyArea = calculationLevel.emptyArea, emptyPercent = calculationLevel.emptyPercent, areaPer = calculationLevel.areaPer, multiFloorUnits = calculationLevel.multiLevel }; } // Add new pack to our dictionary. PopData.instance.AddCalculationPack(volPack); } // Deserialise floor calculation packs. foreach (FloorPackXML xmlPack in configFile.floorPacks) { // Convert to floor pack. FloorDataPack floorPack = new FloorDataPack() { name = xmlPack.name, displayName = xmlPack.name, version = (int)DataVersion.customOne, floorHeight = xmlPack.floorHeight, firstFloorMin = xmlPack.firstMin, firstFloorExtra = xmlPack.firstExtra, firstFloorEmpty = xmlPack.firstEmpty }; // Add new pack to our dictionary. FloorData.instance.AddCalculationPack(floorPack); } // Deserialise consumption records. DataMapping mapper = new DataMapping(); foreach (ConsumptionRecord consumptionRecord in configFile.consumption) { // Get relevant DataStore array for this record. int[][] dataArray = mapper.GetArray(consumptionRecord.service, consumptionRecord.subService); // Iterate through each consumption line and populate relevant DataStore fields. foreach (ConsumptionLine consumptionLine in consumptionRecord.levels) { int level = (int)consumptionLine.level; dataArray[level][DataStore.POWER] = consumptionLine.power; dataArray[level][DataStore.WATER] = consumptionLine.water; dataArray[level][DataStore.SEWAGE] = consumptionLine.sewage; dataArray[level][DataStore.GARBAGE] = consumptionLine.garbage; dataArray[level][DataStore.GROUND_POLLUTION] = consumptionLine.pollution; dataArray[level][DataStore.NOISE_POLLUTION] = consumptionLine.noise; dataArray[level][DataStore.MAIL] = consumptionLine.mail; dataArray[level][DataStore.INCOME] = consumptionLine.income; } } // Deserialise default pack lists. PopData.instance.DeserializeDefaults(configFile.popDefaults); FloorData.instance.DeserializeDefaults(configFile.floorDefaults); // Deserialise building pack lists. PopData.instance.DeserializeBuildings(configFile.buildings); FloorData.instance.DeserializeBuildings(configFile.buildings); SchoolData.instance.DeserializeBuildings(configFile.buildings); Multipliers.instance.DeserializeBuildings(configFile.buildings); // Deserialise building population overrides. PopData.instance.DeserializeOverrides(configFile.popOverrides); // Deserialize floor overrides. foreach (FloorCalcOverride floorOverride in configFile.floors) { FloorData.instance.SetOverride(floorOverride.prefab, new FloorDataPack { firstFloorMin = floorOverride.firstHeight, floorHeight = floorOverride.floorHeight }); } // Deserialise visit modes. RealisticVisitplaceCount.DeserializeVisits(configFile.visitorModes); // Deserialise commercial sales multipliers. GoodsUtils.DeserializeSalesMults(configFile.salesMults); // Deserialise office production multipliers. RealisticOfficeProduction.DeserializeProdMults(configFile.offProdMults); // Deserialize industrial production calculation modes. RealisticIndustrialProduction.DeserializeProds(configFile.indProdModes); RealisticExtractorProduction.DeserializeProds(configFile.extProdModes); // Deserialise commercial inventory caps. GoodsUtils.DeserializeInvCaps(configFile.comIndCaps); } } }
/// <summary> /// Called whenever the currently selected building is changed to update the panel display. /// </summary> /// <param name="building">Newly selected building</param> internal void SelectionChanged(BuildingInfo building) { // Set current building. currentBuilding = building; // Safety first! if (currentBuilding != null) { string buildingName = building.name; // Get available calculation packs for this building. popPacks = PopData.instance.GetPacks(building); floorPacks = FloorData.instance.Packs; // Get current and default packs for this item. currentPopPack = (PopDataPack)PopData.instance.ActivePack(building); currentFloorPack = (FloorDataPack)FloorData.instance.ActivePack(building); PopDataPack defaultPopPack = (PopDataPack)PopData.instance.CurrentDefaultPack(building); FloorDataPack defaultFloorPack = (FloorDataPack)FloorData.instance.CurrentDefaultPack(building); // Update multiplier before we do any other calcs. multCheck.isChecked = Multipliers.instance.HasOverride(buildingName); currentMult = Multipliers.instance.ActiveMultiplier(building); // Build pop pack menu. popMenu.items = new string[popPacks.Length]; for (int i = 0; i < popMenu.items.Length; ++i) { popMenu.items[i] = popPacks[i].displayName; // Check for default name match, if (popPacks[i].name.Equals(defaultPopPack.name)) { popMenu.items[i] += Translations.Translate("RPR_PCK_DEF"); } // Set menu selection to current pack if it matches. if (popPacks[i].name.Equals(currentPopPack.name)) { popMenu.selectedIndex = i; } } // Set population pack to current pack. UpdatePopSelection(currentPopPack); // Build floor pack menu. floorMenu.items = new string[floorPacks.Length]; for (int i = 0; i < floorPacks.Length; ++i) { floorMenu.items[i] = floorPacks[i].displayName; // Check for default name match, if (floorPacks[i].name.Equals(defaultFloorPack.name)) { floorMenu.items[i] += Translations.Translate("RPR_PCK_DEF"); } // Set menu selection to current pack if it matches. if (floorPacks[i].name.Equals(currentFloorPack.name)) { floorMenu.selectedIndex = i; // Force pack selection update. UpdateFloorSelection(i); } } // Update legacy panel for private building AIs (volumetric panel is updated by menu selection change above). if (building.GetAI() is PrivateBuildingAI) { legacyPanel.SelectionChanged(building); } // Is this a school building (need to do school building after pop and floor packs are updated)? if (building.GetAI() is SchoolAI) { // Yes - school building. Set current pack. currentSchoolPack = (SchoolDataPack)SchoolData.instance.ActivePack(building); // Are we using custom school settings? if (ModSettings.enableSchoolProperties) { // Yes - extend panel height and show school panel. volumetricPanel.relativePosition = new Vector2(0f, SchoolCalcY); applyButton.relativePosition = new Vector2(ApplyX, SchoolSaveY); // Get available school packs for this building. schoolPacks = SchoolData.instance.GetPacks(building); // Get current and default packs for this item. currentSchoolPack = (SchoolDataPack)SchoolData.instance.ActivePack(building); SchoolDataPack defaultSchoolPack = (SchoolDataPack)SchoolData.instance.CurrentDefaultPack(building); // Build school pack menu. schoolMenu.items = new string[schoolPacks.Length]; for (int i = 0; i < schoolMenu.items.Length; ++i) { schoolMenu.items[i] = schoolPacks[i].displayName; // Check for default name match, if (schoolPacks[i].name.Equals(defaultSchoolPack.name)) { schoolMenu.items[i] += Translations.Translate("RPR_PCK_DEF"); } // Set menu selection to current pack if it matches. if (schoolPacks[i].name.Equals(currentSchoolPack.name)) { schoolMenu.selectedIndex = i; // Force pack selection update. UpdateSchoolSelection(i); } } // Set multiplier value. multSlider.value = currentMult; schoolPanel.Show(); } else { // It's a school, but we're not using custom school settings, so use the non-school layout. volumetricPanel.relativePosition = new Vector2(0f, BaseCalcY); applyButton.relativePosition = new Vector2(ApplyX, BaseSaveY); schoolPanel.Hide(); } } else { // Not a school building - use non-school layout. currentSchoolPack = null; volumetricPanel.relativePosition = new Vector2(0f, BaseCalcY); applyButton.relativePosition = new Vector2(ApplyX, BaseSaveY); schoolPanel.Hide(); } } }
/// <summary> /// Saves and applies settings - save button event handler. /// </summary> private void SaveAndApply() { // Hide message. messageLabel.isVisible = false; // Don't do anything with invalid entries. if (currentSelection == null || currentSelection.name == null) { return; } // Are we doing population overrides? if (popCheck.isChecked) { // Read total floor count textfield if possible; ignore zero values if (int.TryParse(homeJobsCount.textField.text, out int homesJobs) && homesJobs != 0) { // Minimum value of 1. if (homesJobs < 1) { // Print warning message in red. messageLabel.textColor = new Color32(255, 0, 0, 255); messageLabel.text = Translations.Translate("RPR_ERR_ZERO"); messageLabel.isVisible = true; } else { // Set overide. PopData.instance.SetOverride(currentSelection, homesJobs); // Update CitizenUnits for existing building instances. CitizenUnitUtils.UpdateCitizenUnits(currentSelection.name, ItemClass.Service.None, currentSelection.GetSubService(), false); // Repopulate field with parsed value. homeJobLabel.text = homesJobs.ToString(); } } else { // TryParse couldn't parse any data; print warning message in red. messageLabel.textColor = new Color32(255, 0, 0, 255); messageLabel.text = Translations.Translate("RPR_ERR_INV"); messageLabel.isVisible = true; } } else { // Population override checkbox wasn't checked; remove any custom settings. PopData.instance.DeleteOverride(currentSelection); // Remove any legacy file settings to avoid conflicts. OverrideUtils.RemoveResidential(currentSelection); OverrideUtils.RemoveWorker(currentSelection); } // Are we doing floor overrides? if (floorCheck.isChecked) { // Attempt to parse values into override floor pack. FloorDataPack overrideFloors = TryParseFloors(); // Were we successful?. if (overrideFloors != null) { // Successful parsing - add override. FloorData.instance.SetOverride(currentSelection, overrideFloors); // Save configuration. ConfigUtils.SaveSettings(); // Update panel override. BuildingDetailsPanel.Panel.OverrideFloors = overrideFloors; // Repopulate fields with parsed values. UpdateFloorTextFields(overrideFloors.firstFloorMin.ToString(), overrideFloors.floorHeight.ToString()); } else { // Couldn't parse values; print warning message in red. messageLabel.textColor = new Color32(255, 0, 0, 255); messageLabel.text = Translations.Translate("RPR_ERR_INV"); messageLabel.isVisible = true; } } else { // Floor override checkbox wasn't checked; remove any floor override. FloorData.instance.DeleteOverride(currentSelection); } // Refresh the display so that all panels reflect the updated settings. BuildingDetailsPanel.Panel.Refresh(); }
/// <summary> /// Called whenever the currently selected building is changed to update the panel display. /// </summary> /// <param name="building"></param> public void SelectionChanged(BuildingInfo building) { string buildingName = building.name; // Hide message. messageLabel.isVisible = false; // Set current selecion. currentSelection = building; // Blank all textfields and deselect checkboxes to start with. homeJobsCount.textField.text = string.Empty; UpdateFloorTextFields(string.Empty, string.Empty); popCheck.isChecked = false; floorCheck.isChecked = false; // Disable buttons and exit if no valid building is selected. if (building == null || building.name == null) { saveButton.Disable(); deleteButton.Disable(); return; } // Set label by building type. if (building.GetService() == ItemClass.Service.Residential) { // Residential building - homes. homeJobLabel.text = Translations.Translate("RPR_LBL_HOM"); } else if (building.GetService() == ItemClass.Service.Education) { // Schoool building - students. homeJobLabel.text = Translations.Translate("RPR_LBL_STU"); } else { // Workplace building - jobs. homeJobLabel.text = Translations.Translate("RPR_LBL_JOB"); } // Get any population override. int homesJobs = PopData.instance.GetOverride(buildingName); // If custom settings were found (return value was non-zero), then display the result, rename the save button, and enable the delete button. if (homesJobs != 0) { // Valid custom settings found; display the result, rename the save button, and enable the delete button. homeJobsCount.textField.text = homesJobs.ToString(); saveButton.text = Translations.Translate("RPR_CUS_UPD"); deleteButton.Enable(); // Select the 'has population override' check. popCheck.isChecked = true; } else { // No population override - check for custom floor override. FloorDataPack overridePack = FloorData.instance.HasOverride(buildingName); if (overridePack != null) { // Valid custom settings found; display the result, rename the save button, and enable the delete button. UpdateFloorTextFields(overridePack.firstFloorMin.ToString(), overridePack.floorHeight.ToString()); saveButton.text = Translations.Translate("RPR_CUS_UPD"); deleteButton.Enable(); // Select the 'has floor override' check. floorCheck.isChecked = true; } else { // No valid selection - rename the save button, and disable the delete button. saveButton.text = Translations.Translate("RPR_CUS_ADD"); deleteButton.Disable(); } // Communicate override to panel. BuildingDetailsPanel.Panel.OverrideFloors = overridePack; } // We've at least got a valid building, so enable the save button. saveButton.Enable(); }
/// <summary> /// Perform and display volumetric calculations for the currently selected building. /// </summary> /// <param name="building">Selected building prefab</param> /// <param name="levelData">Population (level) calculation data to apply to calculations</param> /// <param name="floorData">Floor calculation data to apply to calculations</param> /// <param name="schoolData">School calculation data to apply to calculations</param> /// <param name="schoolData">Multiplier to apply to calculations</param> internal void CalculateVolumetric(BuildingInfo building, LevelData levelData, FloorDataPack floorData, SchoolDataPack schoolData, float multiplier) { // Safety first! if (building == null) { return; } // Reset message label. messageLabel.text = string.Empty; // Perform calculations. // Get floors and allocate area an number of floor labels. SortedList <int, float> floors = PopData.instance.VolumetricFloors(building.m_generatedInfo, floorData, out float totalArea); floorAreaLabel.text = totalArea.ToString("N0", LocaleManager.cultureInfo); numFloorsLabel.text = floors.Count.ToString(); // Get total units. int totalUnits = PopData.instance.VolumetricPopulation(building.m_generatedInfo, levelData, floorData, multiplier, floors, totalArea); // Floor labels list. List <string> floorLabels = new List <string>(); // What we call our units for this building. string unitName; switch (building.GetService()) { case ItemClass.Service.Residential: // Residential - households. unitName = Translations.Translate("RPR_CAL_UNI_HOU"); break; case ItemClass.Service.Education: // Education - students. unitName = Translations.Translate("RPR_CAL_UNI_STU"); break; default: // Default - workplaces. unitName = Translations.Translate("RPR_CAL_UNI_WOR"); break; } // See if we're using area calculations for numbers of units, i.e. areaPer is at least one. if (levelData.areaPer > 0) { // Determine area percentage to use for calculations (inverse of empty area percentage). float areaPercent = 1 - (levelData.emptyPercent / 100f); // Create new floor area labels by iterating through each floor. for (int i = 0; i < floors.Count; ++i) { // StringBuilder, because we're doing a fair bit of manipulation here. StringBuilder floorString = new StringBuilder("Floor "); // Floor number floorString.Append(i + 1); floorString.Append(" " + Translations.Translate("RPR_CAL_VOL_ARA") + " "); floorString.Append(floors[i].ToString("N0")); // See if we're calculating units per individual floor. if (!levelData.multiFloorUnits) { // Number of units on this floor - always rounded down. int floorUnits = (int)((floors[i] * areaPercent) / levelData.areaPer); // Adjust by multiplier (after rounded calculation above). floorUnits = (int)(floorUnits * multiplier); // Add extra info to label. floorString.Append(" ("); floorString.Append(floorUnits.ToString("N0")); floorString.Append(" "); floorString.Append(unitName); floorString.Append(")"); } // Add new floor label item with results for this calculation. floorLabels.Add(floorString.ToString()); } } // Do we have a current school selection, and are we using school property overrides? if (schoolData != null && ModSettings.enableSchoolProperties) { // Yes - calculate and display school worker breakdown. int[] workers = SchoolData.instance.CalcWorkers(schoolData, totalUnits); schoolWorkerLabel.Show(); schoolWorkerLabel.text = workers[0] + " / " + workers[1] + " / " + workers[2] + " / " + workers[3]; // Calculate construction cost to display. int cost = SchoolData.instance.CalcCost(schoolData, totalUnits); ColossalFramework.Singleton <EconomyManager> .instance.m_EconomyWrapper.OnGetConstructionCost(ref cost, building.m_class.m_service, building.m_class.m_subService, building.m_class.m_level); // Calculate maintenance cost to display. int maintenance = SchoolData.instance.CalcMaint(schoolData, totalUnits) * 100; ColossalFramework.Singleton <EconomyManager> .instance.m_EconomyWrapper.OnGetMaintenanceCost(ref maintenance, building.m_class.m_service, building.m_class.m_subService, building.m_class.m_level); float displayMaint = Mathf.Abs(maintenance * 0.0016f); // And display school cost breakdown. costLabel.Show(); costLabel.text = cost.ToString((!(displayMaint >= 10f)) ? Settings.moneyFormat : Settings.moneyFormatNoCents, LocaleManager.cultureInfo) + " / " + displayMaint.ToString((!(displayMaint >= 10f)) ? Settings.moneyFormat : Settings.moneyFormatNoCents, LocaleManager.cultureInfo); // Enforce school floors list position. ResetFloorListPosition(); } else { // No - hide school worker breakdown and cost labels. schoolWorkerLabel.Hide(); costLabel.Hide(); // Enforce default floors list position. ResetFloorListPosition(); } // Allocate our new list of labels to the floors list (via an interim fastlist to avoid race conditions if we 'build' manually directly into floorsList). FastList <object> fastList = new FastList <object>() { m_buffer = floorLabels.ToArray(), m_size = floorLabels.Count }; floorsList.rowsData = fastList; // Display total unit calculation result. switch (building.GetService()) { case ItemClass.Service.Residential: // Residential building. totalJobsLabel.Hide(); totalStudentsLabel.Hide(); totalHomesLabel.Show(); totalHomesLabel.text = totalUnits.ToString("N0", LocaleManager.cultureInfo); break; case ItemClass.Service.Education: // School building. totalHomesLabel.Hide(); totalJobsLabel.Hide(); totalStudentsLabel.Show(); totalStudentsLabel.text = totalUnits.ToString("N0", LocaleManager.cultureInfo); break; default: // Workplace building. totalHomesLabel.Hide(); totalStudentsLabel.Hide(); totalJobsLabel.Show(); totalJobsLabel.text = totalUnits.ToString("N0", LocaleManager.cultureInfo); break; } // Display commercial visit count, or hide the label if not commercial. if (building.GetAI() is CommercialBuildingAI) { visitCountLabel.Show(); visitCountLabel.text = RealisticVisitplaceCount.PreviewVisitCount(building, totalUnits).ToString(); } else { visitCountLabel.Hide(); } // Display production count, or hide the label if not a production building. if (building.GetAI() is PrivateBuildingAI privateAI && (privateAI is OfficeBuildingAI || privateAI is IndustrialBuildingAI || privateAI is IndustrialExtractorAI)) { productionLabel.Show(); productionLabel.text = privateAI.CalculateProductionCapacity(building.GetClassLevel(), new ColossalFramework.Math.Randomizer(), building.GetWidth(), building.GetLength()).ToString(); }
/// <summary> /// Constructor - initializes inbuilt default calculation packs and performs other setup tasks. /// </summary> public FloorData() { // Default; standard 3m stories. FloorDataPack newPack = new FloorDataPack { name = "generic", displayName = Translations.Translate("RPR_PCK_FDF_NAM"), description = Translations.Translate("RPR_PCK_FDF_DES"), version = (int)DataVersion.one, floorHeight = 3f, firstFloorMin = 3f, firstFloorExtra = 0f, firstFloorEmpty = false }; calcPacks.Add(newPack); // Standalone houses. newPack = new FloorDataPack { name = "house", displayName = Translations.Translate("RPR_PCK_FHO_NAM"), description = Translations.Translate("RPR_PCK_FHO_DES"), version = (int)DataVersion.one, floorHeight = 3f, firstFloorMin = 3f, firstFloorExtra = 0f, firstFloorEmpty = false }; calcPacks.Add(newPack); // Buildings with lobbies. newPack = new FloorDataPack { name = "lobbies", displayName = Translations.Translate("RPR_PCK_FDL_NAM"), description = Translations.Translate("RPR_PCK_FDL_DES"), version = (int)DataVersion.one, floorHeight = 3f, firstFloorMin = 3f, firstFloorExtra = 1f, firstFloorEmpty = true }; calcPacks.Add(newPack); // Commercial buildings newPack = new FloorDataPack { name = "commercial", displayName = Translations.Translate("RPR_PCK_FCM_NAM"), description = Translations.Translate("RPR_PCK_FCM_DES"), version = (int)DataVersion.one, floorHeight = 4f, firstFloorMin = 3f, firstFloorExtra = 3f, firstFloorEmpty = false }; calcPacks.Add(newPack); // Warehouses (commercial and industrial) newPack = new FloorDataPack { name = "warehouse", displayName = Translations.Translate("RPR_PCK_FWH_NAM"), description = Translations.Translate("RPR_PCK_FWH_DES"), version = (int)DataVersion.one, floorHeight = 9f, firstFloorMin = 3f, firstFloorExtra = 6f, firstFloorEmpty = false }; calcPacks.Add(newPack); // High-bay warehouses (commercial and industrial) newPack = new FloorDataPack { name = "highbay", displayName = Translations.Translate("RPR_PCK_FHB_NAM"), description = Translations.Translate("RPR_PCK_FHB_DES"), version = (int)DataVersion.one, floorHeight = 12f, firstFloorMin = 3f, firstFloorExtra = 9f, firstFloorEmpty = false }; calcPacks.Add(newPack); // Extractors and processors newPack = new FloorDataPack { name = "extractor", displayName = Translations.Translate("RPR_PCK_FEX_NAM"), description = Translations.Translate("RPR_PCK_FEX_DES"), version = (int)DataVersion.one, floorHeight = 99f, firstFloorMin = 3f, firstFloorExtra = 9f, firstFloorEmpty = false }; calcPacks.Add(newPack); // Initialise overrides dictionary. overrides = new Dictionary <string, FloorDataPack>(); }