/// <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;
        }
Exemplo n.º 4
0
 /// <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();
        }
Exemplo n.º 6
0
        /// <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;
        }
Exemplo n.º 8
0
        /// <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();
                }
            }
        }
Exemplo n.º 10
0
        /// <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();
        }
Exemplo n.º 11
0
        /// <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();
            }
Exemplo n.º 13
0
        /// <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>();
        }