private static bool CheckInfoCompatibility(Vector3 pos, ItemClass.Service service, ItemClass.SubService subService, TransferManager.TransferReason[] allowedTypes, Building.Flags flagsRequired, Building.Flags flagsForbidden, BuildingManager bm, ref ushort result, ref float lastNearest, ushort buildingId, BuildingInfo info)
 {
     //doErrorLog($"CheckInfoCompatibility 0  {pos}, {service}, {subService}, {allowedTypes},  {flagsRequired},  {flagsForbidden}, {bm},  {result},  {lastNearest},  {buildingId}, {info}");
     if (info != null && (info.m_class.m_service == service || service == ItemClass.Service.None) && (info.m_class.m_subService == subService || subService == ItemClass.SubService.None))
     {
         //doErrorLog("CheckInfoCompatibility 1");
         Building.Flags flags = bm.m_buildings.m_buffer[buildingId].m_flags;
         //doErrorLog("CheckInfoCompatibility 2");
         if ((flags & (flagsRequired | flagsForbidden)) == flagsRequired)
         {
             //doErrorLog("CheckInfoCompatibility 3");
             if (allowedTypes == null ||
                 allowedTypes.Length == 0 ||
                 !(info.GetAI() is DepotAI depotAI) ||
                 (depotAI.m_transportInfo != null && allowedTypes.Contains(depotAI.m_transportInfo.m_vehicleReason)) ||
                 (depotAI.m_secondaryTransportInfo != null && allowedTypes.Contains(depotAI.m_secondaryTransportInfo.m_vehicleReason)))
             {
                 //doErrorLog("CheckInfoCompatibility 4");
                 float dist = Vector3.SqrMagnitude(pos - bm.m_buildings.m_buffer[buildingId].m_position);
                 //doErrorLog("CheckInfoCompatibility 5");
                 if (dist < lastNearest)
                 {
                     result      = buildingId;
                     lastNearest = dist;
                     return(true);
                 }
             }
         }
     }
     return(false);
 }
Beispiel #2
0
        public void closeDepotInfo(UIComponent component, UIMouseEventParameter eventParam)
        {
            BuildingInfo basicInfo = Singleton <BuildingManager> .instance.m_buildings.m_buffer[m_buildingIdSelecionado.Building].Info;
            DepotAI      basicAI   = basicInfo.GetAI() as DepotAI;

            Hide();

            TLMPublicTransportManagementPanel.instance?.OpenAt(UiCategoryTab.DepotListing, TransportSystemDefinition.from(basicAI));
        }
Beispiel #3
0
        public void closeDepotInfo(UIComponent component, UIMouseEventParameter eventParam)
        {
            BuildingInfo basicInfo = Singleton <BuildingManager> .instance.m_buildings.m_buffer[m_buildingIdSelecionado.Building].Info;
            DepotAI      basicAI   = basicInfo.GetAI() as DepotAI;

            Hide();
            m_controller.defaultListingLinesPanel.Show();
            TLMPublicTransportDetailPanel.instance.SetActiveTab(TLMPublicTransportDetailPanel.tabSystemOrder.Length + Array.IndexOf(TLMPublicTransportDetailPanel.tabSystemOrder, TLMCW.getConfigIndexForTransportInfo(basicAI.m_transportInfo)));
        }
Beispiel #4
0
        public static IBasicBuildingAIOverrides getBuildingOverrideExtension(BuildingInfo info)
        {
            PrefabAI targetAi     = info.GetAI();
            Type     targetTypeAi = targetAi.GetType();

            if (subtypes == null)
            {
                subtypes = new Dictionary <Type, Type>();
                var subclasses = SVMUtils.GetSubtypesRecursive(typeof(BasicBuildingAIOverrides <,>), typeof(SVMBuildingAIOverrideUtils));
                SVMUtils.doLog("GetOverride pré - subclasses:\r\n\t{0}", string.Join("\r\n\t", subclasses?.Select(x => x.ToString())?.ToArray() ?? new string[0]));
                foreach (Type t in subclasses)
                {
                    try
                    {
                        subtypes[t.BaseType.GetGenericArguments()[1]] = t;
                    }
                    catch (Exception e)
                    {
                        SVMUtils.doErrorLog("ERROR ADDING SUBTYPE {0}!\r\n{1}", t, subclasses);
                    }
                }
                SVMUtils.doLog("GetOverride - Classes:\r\n\t{0}", string.Join("\r\n\t", subtypes?.Select(x => x.Key.ToString() + "=>" + x.Value.ToString())?.ToArray() ?? new string[0]));
            }
            Type targetClass = null;
            IBasicBuildingAIOverrides value = null;

            if (!subtypes.ContainsKey(targetTypeAi))
            {
                foreach (var clazz in subtypes.Keys)
                {
                    if (clazz.IsAssignableFrom(targetTypeAi))
                    {
                        value = (IBasicBuildingAIOverrides)SVMUtils.GetPrivateStaticField("instance", subtypes[clazz]);
                        //SVMUtils.doLog("GetOverride - clazz = {0}; value = {1}", clazz, value);
                        if (value.AcceptsAI(targetAi))
                        {
                            targetClass = subtypes[clazz];
                            break;
                        }
                    }
                }
                SVMUtils.doLog("GetOverride - targetClass = {0} ({1})", targetClass, targetTypeAi);
                if (targetClass == null)
                {
                    return(null);
                }
            }
            else
            {
                targetClass = subtypes[targetTypeAi];
                value       = (IBasicBuildingAIOverrides)SVMUtils.GetPrivateStaticField("instance", targetClass);
            }
            //SVMUtils.doLog("GetOverride - value = {0}", value);
            return((IBasicBuildingAIOverrides)value);
        }
Beispiel #5
0
        /// <summary>
        /// Harmony Postfix patch to ZonedBuildingWorldInfoPanel.UpdateBindings to display visitor counts for commercial buildings.
        /// </summary>
        public static void Postfix()
        {
            // Currently selected building.
            ushort building = WorldInfoPanel.GetCurrentInstanceID().Building;

            // Create visit label if it isn't already set up.
            if (visitLabel == null)
            {
                // Get info panel.
                ZonedBuildingWorldInfoPanel infoPanel = UIView.library.Get <ZonedBuildingWorldInfoPanel>(typeof(ZonedBuildingWorldInfoPanel).Name);

                // Add current visitor count label.
                visitLabel           = UIControls.AddLabel(infoPanel.component, 65f, 280f, Translations.Translate("RPR_INF_VIS"), textScale: 0.75f);
                visitLabel.textColor = new Color32(185, 221, 254, 255);
                visitLabel.font      = Resources.FindObjectsOfTypeAll <UIFont>().FirstOrDefault((UIFont f) => f.name == "OpenSans-Regular");

                // Position under existing Highly Educated workers count row in line with total workplace count label.
                UIComponent situationLabel = infoPanel.Find("WorkSituation");
                UIComponent workerLabel    = infoPanel.Find("HighlyEducatedWorkers");
                if (situationLabel != null && workerLabel != null)
                {
                    visitLabel.absolutePosition = new Vector2(situationLabel.absolutePosition.x, workerLabel.absolutePosition.y + 25f);
                }
                else
                {
                    Logging.Error("couldn't find ZonedBuildingWorldInfoPanel components");
                }
            }

            // Local references.
            Building[]   buildingBuffer = Singleton <BuildingManager> .instance.m_buildings.m_buffer;
            BuildingInfo buildingInfo   = buildingBuffer[building].Info;

            // Is this a commercial building?
            CommercialBuildingAI commercialAI = buildingInfo.GetAI() as CommercialBuildingAI;

            if (commercialAI == null)
            {
                // Not a commercial building - hide the label.
                visitLabel.Hide();
            }
            else
            {
                // Commercial building - show the label.
                visitLabel.Show();

                // Get current visitor count.
                int aliveCount = 0, totalCount = 0;
                Citizen.BehaviourData behaviour = new Citizen.BehaviourData();
                GetVisitBehaviour(commercialAI, building, ref buildingBuffer[building], ref behaviour, ref aliveCount, ref totalCount);

                // Display visitor count.
                visitLabel.text = totalCount.ToString() + " / " + commercialAI.CalculateVisitplaceCount((ItemClass.Level)buildingBuffer[building].m_level, new ColossalFramework.Math.Randomizer(building), buildingBuffer[building].Width, buildingBuffer[building].Length).ToString() + " " + Translations.Translate("RPR_INF_VIS");
            }
        }
Beispiel #6
0
        /// <summary>
        /// Updates all school prefabs (e.g. when the global multiplier has changed).
        /// </summary>
        internal void UpdateSchools()
        {
            // Iterate through all loaded building prefabs.
            for (uint i = 0; i < PrefabCollection <BuildingInfo> .LoadedCount(); ++i)
            {
                BuildingInfo building = PrefabCollection <BuildingInfo> .GetLoaded(i);

                // Check for schools.
                if (building?.name != null && building.GetAI() is SchoolAI schoolAI && (building.GetClassLevel() == ItemClass.Level.Level1 || building.GetClassLevel() == ItemClass.Level.Level2))
                {
                    // Found a school; update school record and tooltip.
                    UpdateSchoolPrefab(building, schoolAI);
                }
            }
        }
 public bool isFromSystem(BuildingInfo info)
 {
     if (ServiceVehiclesManagerMod.debugMode)
     {
         SVMUtils.doLog($"[{info?.GetAI()?.GetType()}->{this}]" +
                        $" info.m_class.m_service == service = { info?.m_class?.m_service == service};" +
                        $" subService == info.m_class.m_subService = { subService == info?.m_class?.m_subService };" +
                        $" info?.GetAI() is OutsideConnectionAI == outsideConnection = {info?.GetAI() is OutsideConnectionAI == outsideConnection };" +
                        $" info.m_class.m_level == level = {info?.m_class?.m_level} == {level} = {info?.m_class?.m_level == level};" +
                        $" SVMBuildingAIOverrideUtils.getBuildingOverrideExtension(info).Count = {SVMBuildingAIOverrideUtils.getBuildingOverrideExtension(info)?.Count};" +
                        $" ExtraAllowedLevels = [{String.Join(",", SVMBuildingAIOverrideUtils.getBuildingOverrideExtension(info).SelectMany(x => x?.ExtraAllowedLevels() ?? new List<ItemClass.Level>()).Select(x => x.ToString() ?? "<NULL>")?.ToArray())}];" +
                        $" instance?.vehicleType ({this?.vehicleType}) ;" +
                        $" aiOverride?.AllowVehicleType(vehicleType) = {this?.vehicleType}) ;" +
                        $" SVMBuildingAIOverrideUtils.getBuildingOverrideExtension(info).Where = {ListAiOverrides(info).Count()} ");
     }
     return(ListAiOverrides(info).Count() > 0);
 }
Beispiel #8
0
        /// <summary>
        /// Harmony Postfix patch to skip 'gradual construction' for plopped RICO growables, and/or to apply the 'Make Historical' and/or 'Lock level' settings on building creation, accoriding to settings.
        /// </summary>
        /// <param name="__result">Original method result (unchanged)</param>
        /// <param name="info">BuildingInfo prefab for this building (unchanged)</param>
        /// <param name="position">Building position (ignored)</param>
        /// <param name="angle">Building rotation (ignored)</param>
        /// <param name="relocating">Building relocation (ignored)</param>
        /// <param name="needMoney">Is money needed (ignored)</param>
        /// <param name="fixedHeight">Fixed height (ignored)</param>
        internal static void Postfix(ref ushort __result, ref BuildingInfo info, Vector3 position, float angle, int relocating, bool needMoney, bool fixedHeight)
        {
            // Check that we have a valid building ID.
            if (__result == 0)
            {
                return;
            }

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

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

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

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

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

                // Enable ABLC level lock if option is set and ABLC is running.
                if (ModUtils.ablcLockBuildingLevel != null && ((ModSettings.lockLevelOther && !isRICO) || (ModSettings.lockLevelRico && isRICO)))
                {
                    ModUtils.ablcLockBuildingLevel.Invoke(null, new object[] { __result, Singleton <BuildingManager> .instance.m_buildings.m_buffer[__result].m_level });
                }
            }
        }
        /// <summary>
        /// Returns the workplace breakdowns and visitor count for the given building prefab and level.
        /// </summary>
        /// <param name="buildingPrefab">Building prefab record</param>
        /// <param name="level">Building level</param>
        /// <returns>Workplace breakdowns and visitor count </returns>
        public override int[] Workplaces(BuildingInfo buildingPrefab, int level)
        {
            int[] array;
            int   minWorkers;

            // Need to test if we're an extractor or not for this one.
            if (buildingPrefab.GetAI() is IndustrialExtractorAI)
            {
                array      = LegacyAIUtils.GetExtractorArray(buildingPrefab);
                minWorkers = 3;
            }
            else
            {
                array      = LegacyAIUtils.GetIndustryArray(buildingPrefab, level);
                minWorkers = 4;
            }

            LegacyAIUtils.CalculateprefabWorkerVisit(buildingPrefab.GetWidth(), buildingPrefab.GetLength(), ref buildingPrefab, minWorkers, ref array, out int[] output);

            return(output);
        }
Beispiel #10
0
        /// <summary>
        /// Applies a school data pack to a school prefab.
        /// </summary>
        /// <param name="prefab">School prefab to apply to</param>
        /// <param name="schoolPack">School data pack to apply</param>
        private void ApplyPack(BuildingInfo prefab, SchoolDataPack schoolPack)
        {
            // Null checks first.
            if (prefab?.name == null)
            {
                Logging.Error("No prefab found for SchoolPack ", schoolPack.name);
                return;
            }

            if (schoolPack == null)
            {
                Logging.Error("No SchoolPack found for prefab ", prefab.name);
            }

            // Apply settings to prefab.
            SchoolAI schoolAI = prefab.GetAI() as SchoolAI;

            if (prefab != null && schoolPack != null)
            {
                // Calculate workers and breakdowns.
                int[] workers = CalcWorkers(schoolPack, schoolAI.StudentCount);

                // Update prefab AI worker count with results (base + extras) per education level.
                schoolAI.m_workPlaceCount0 = workers[0];
                schoolAI.m_workPlaceCount1 = workers[1];
                schoolAI.m_workPlaceCount2 = workers[2];
                schoolAI.m_workPlaceCount3 = workers[3];

                // Calculate and update costs and maintenance.
                schoolAI.m_constructionCost = CalcCost(schoolPack, schoolAI.StudentCount);
                schoolAI.m_maintenanceCost  = CalcMaint(schoolPack, schoolAI.StudentCount);

                // Force update of m_studentCount.
                schoolAI.m_studentCount = schoolAI.StudentCount;

                // Update prefab and tooltip.
                UpdateSchoolPrefab(prefab, schoolAI);
            }
        }
Beispiel #11
0
        /// <summary>
        /// Performs task on completion of level loading - recording of school default properties and application of our settings.
        /// Should be called OnLevelLoaded, after prefabs have been loaded but before gameplay commences.
        /// </summary>
        internal void OnLoad()
        {
            // Initialise original properties dictionary.
            originalStats = new Dictionary <string, OriginalSchoolStats>();

            // Iterate through all loaded building prefabs.
            for (uint i = 0; i < PrefabCollection <BuildingInfo> .LoadedCount(); ++i)
            {
                BuildingInfo building = PrefabCollection <BuildingInfo> .GetLoaded(i);

                // Check for schools.
                if (building?.name != null && building.GetAI() is SchoolAI schoolAI && (building.GetClassLevel() == ItemClass.Level.Level1 || building.GetClassLevel() == ItemClass.Level.Level2))
                {
                    // Found a school; add it to our dictionary.
                    originalStats.Add(building.name, new OriginalSchoolStats
                    {
                        jobs0       = schoolAI.m_workPlaceCount0,
                        jobs1       = schoolAI.m_workPlaceCount1,
                        jobs2       = schoolAI.m_workPlaceCount2,
                        jobs3       = schoolAI.m_workPlaceCount3,
                        cost        = schoolAI.m_constructionCost,
                        maintenance = schoolAI.m_maintenanceCost
                    });

                    // If setting is set, get currently active pack and apply it.
                    if (ModSettings.enableSchoolProperties)
                    {
                        ApplyPack(building, ActivePack(building) as SchoolDataPack);

                        // ApplyPack includes a call to UpdateSchoolPrefab, so no need to do it again here.
                        continue;
                    }

                    // Update school record and tooltip.
                    UpdateSchoolPrefab(building, schoolAI);
                }
            }
        }
Beispiel #12
0
        internal IEnumerator <object> UpdateDo()
        {
            yield return(new WaitForSeconds(0.05f));

            ActionStatus.text = ActionQueue.instance.current == null ? "" : $"{ActionQueue.instance.current.GetType()}";
            ToolStatus.text   = $"{MoveItTool.ToolState} ({MoveItTool.MT_Tool}.{MoveItTool.AlignToolPhase}), POProc:{MoveItTool.POProcessing}";

            SelectedLarge.text = $"Objects Selected: {Action.selection.Count}";
            ushort[] types = new ushort[8];
            foreach (Instance instance in Action.selection)
            {
                if (instance is MoveableBuilding)
                {
                    types[0]++;
                }
                else if (instance is MoveableProp)
                {
                    PropInfo info = (PropInfo)PropLayer.Manager.GetInfo(instance.id).Prefab;
                    if (info.m_isDecal)
                    {
                        types[2]++;
                    }
                    else if (Filters.IsSurface(info))
                    {
                        types[3]++;
                    }
                    else
                    {
                        types[1]++;
                    }
                }
                else if (instance is MoveableTree)
                {
                    types[4]++;
                }
                else if (instance is MoveableProc)
                {
                    types[5]++;
                }
                else if (instance is MoveableNode)
                {
                    types[6]++;
                }
                else if (instance is MoveableSegment)
                {
                    types[7]++;
                }
                else
                {
                    throw new Exception($"Instance is invalid type (<{instance.GetType()}>)");
                }
            }
            SelectedSmall.text = $"B:{types[0]}, P:{types[1]}, D:{types[2]}, S:{types[3]}, T:{types[4]}, PO:{types[5]}, N:{types[6]}, S:{types[7]}\n ";

            // End with updating the hovered item
            if (id == null)
            {
                yield break;
            }
            if (id == InstanceID.Empty)
            {
                lastId = id;
                HoverLarge.textColor = new Color32(255, 255, 255, 255);
                yield break;
            }
            if (lastId == id)
            {
                yield break;
            }

            HoverLarge.textColor = new Color32(127, 217, 255, 255);
            HoverLarge.text      = "";
            HoverSmall.text      = "";

            if (id.Building > 0)
            {
                BuildingInfo info = BuildingManager.instance.m_buildings.m_buffer[id.Building].Info;
                HoverLarge.text    = $"B:{id.Building}  {info.name}";
                HoverLarge.tooltip = info.name;
                HoverSmall.text    = $"{info.GetType()} ({info.GetAI().GetType()})\n{info.m_class.name}\n({info.m_class.m_service}.{info.m_class.m_subService})";
            }
            else if (id.Prop > 0)
            {
                string   type = "P";
                PropInfo info = (PropInfo)PropLayer.Manager.GetInfo(id).Prefab;
                if (info.m_isDecal)
                {
                    type = "D";
                }
                HoverLarge.text    = $"{type}:{PropLayer.Manager.GetId(id)}  {info.name}";
                HoverLarge.tooltip = info.name;
                HoverSmall.text    = $"{info.GetType()}\n{info.m_class.name}";
            }
            else if (id.NetLane > 0)
            {
                IInfo info = MoveItTool.PO.GetProcObj(id.NetLane).Info;
                HoverLarge.text    = $"PO:{id.NetLane}  {info.Name}";
                HoverLarge.tooltip = info.Name;
                HoverSmall.text    = $"\n";
            }
            else if (id.Tree > 0)
            {
                TreeInfo info = TreeManager.instance.m_trees.m_buffer[id.Tree].Info;
                HoverLarge.text    = $"T:{id.Tree}  {info.name}";
                HoverLarge.tooltip = info.name;
                HoverSmall.text    = $"{info.GetType()}\n{info.m_class.name}";
            }
            else if (id.NetNode > 0)
            {
                NetInfo info = NetManager.instance.m_nodes.m_buffer[id.NetNode].Info;
                HoverLarge.text    = $"N:{id.NetNode}  {info.name}";
                HoverLarge.tooltip = info.name;
                HoverSmall.text    = $"{info.GetType()} ({info.GetAI().GetType()})\n{info.m_class.name}";
            }
            else if (id.NetSegment > 0)
            {
                NetInfo info = NetManager.instance.m_segments.m_buffer[id.NetSegment].Info;
                HoverLarge.text    = $"S:{id.NetSegment}  {info.name}";
                HoverLarge.tooltip = info.name;
                HoverSmall.text    = $"{info.GetType()} ({info.GetAI().GetType()})\n{info.m_class.name}";
            }

            lastId = id;
        }
        /// <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();
                }
            }
        }
Beispiel #14
0
        internal void LoadImpl(Package.Asset assetRef)
        {
            try
            {
                stack.Push(assetRef);
                LoadingManager.instance.m_loadingProfilerCustomAsset.BeginLoading(AssetName(assetRef.name));
                GameObject go = AssetDeserializer.Instantiate(assetRef) as GameObject;
                CustomAssetMetaData.Type type = GetMetaType(assetRef);
                string packageName            = assetRef.package.packageName;
                string fullName = type < CustomAssetMetaData.Type.RoadElevation ? packageName + "." + go.name : PillarOrElevationName(packageName, go.name);
                go.name = fullName;
                go.SetActive(false);
                PrefabInfo info = go.GetComponent <PrefabInfo>();
                info.m_isCustomContent = true;

                if (info.m_Atlas != null && !string.IsNullOrEmpty(info.m_InfoTooltipThumbnail) && info.m_Atlas[info.m_InfoTooltipThumbnail] != null)
                {
                    info.m_InfoTooltipAtlas = info.m_Atlas;
                }

                PropInfo pi = go.GetComponent <PropInfo>();

                if (pi != null)
                {
                    if (pi.m_lodObject != null)
                    {
                        pi.m_lodObject.SetActive(false);
                    }

                    Initialize(pi);
                    loadedProps.Add(fullName);
                }

                TreeInfo ti = go.GetComponent <TreeInfo>();

                if (ti != null)
                {
                    Initialize(ti);
                    loadedTrees.Add(fullName);
                }

                BuildingInfo bi = go.GetComponent <BuildingInfo>();

                if (bi != null)
                {
                    if (bi.m_lodObject != null)
                    {
                        bi.m_lodObject.SetActive(false);
                    }

                    bi.m_dontSpawnNormally = dontSpawnNormally.Remove(fullName);
                    Initialize(bi);
                    loadedBuildings.Add(fullName);

                    if (bi.GetAI() is IntersectionAI)
                    {
                        loadedIntersections.Add(fullName);
                    }
                }

                VehicleInfo vi = go.GetComponent <VehicleInfo>();

                if (vi != null)
                {
                    if (vi.m_lodObject != null)
                    {
                        vi.m_lodObject.SetActive(false);
                    }

                    Initialize(vi);
                    loadedVehicles.Add(fullName);
                }

                CitizenInfo ci = go.GetComponent <CitizenInfo>();

                if (ci != null)
                {
                    if (ci.m_lodObject != null)
                    {
                        ci.m_lodObject.SetActive(false);
                    }

                    if (ci.InitializeCustomPrefab(citizenMetaDatas[assetRef.fullName]))
                    {
                        citizenMetaDatas.Remove(assetRef.fullName);
                        ci.gameObject.SetActive(true);
                        Initialize(ci);
                        loadedCitizens.Add(fullName);
                    }
                    else
                    {
                        CODebugBase <LogChannel> .Warn(LogChannel.Modding, "Custom citizen [" + assetRef.fullName + "] template not available in selected theme. Asset not added in game.");
                    }
                }

                NetInfo ni = go.GetComponent <NetInfo>();

                if (ni != null)
                {
                    loadedNets.Add(fullName);
                    Initialize(ni);
                }
            }
            finally
            {
                stack.Pop();
                assetCount++;
                LoadingManager.instance.m_loadingProfilerCustomAsset.EndLoading();
            }
        }
Beispiel #15
0
        internal void Update()
        {
            if (!MoveItTool.showDebugPanel)
            {
                return;
            }

            ToolStatus.text = $"{MoveItTool.instance.ToolState} (align:{MoveItTool.instance.AlignMode}.{MoveItTool.instance.AlignToolPhase})";

            SelectedLarge.text = $"Objects Selected: {Action.selection.Count}";
            ushort[] types = new ushort[8];
            foreach (Instance instance in Action.selection)
            {
                if (instance is MoveableBuilding)
                {
                    types[0]++;
                }
                else if (instance is MoveableProp)
                {
                    PropInfo info = PropManager.instance.m_props.m_buffer[instance.id.Prop].Info;
                    if (info.m_isDecal)
                    {
                        types[2]++;
                    }
                    else if (Filters.IsSurface(info))
                    {
                        types[3]++;
                    }
                    else
                    {
                        types[1]++;
                    }
                }
                else if (instance is MoveableTree)
                {
                    types[4]++;
                }
                else if (instance is MoveableProc)
                {
                    types[5]++;
                }
                else if (instance is MoveableNode)
                {
                    types[6]++;
                }
                else if (instance is MoveableSegment)
                {
                    types[7]++;
                }
                else
                {
                    throw new Exception($"Instance is invalid type (<{instance.GetType()}>)");
                }
            }
            SelectedSmall.text = $"B:{types[0]}, P:{types[1]}, D:{types[2]}, S:{types[3]}, T:{types[4]}, PO:{types[5]}, N:{types[6]}, S:{types[7]}\n ";

            // End with updating the hovered item
            if (id == null)
            {
                return;
            }
            if (id == InstanceID.Empty)
            {
                lastId = id;
                HoverLarge.textColor = new Color32(255, 255, 255, 255);
                return;
            }
            if (lastId == id)
            {
                return;
            }

            HoverLarge.textColor = new Color32(127, 217, 255, 255);
            HoverLarge.text      = "";
            HoverSmall.text      = "";

            if (id.Building > 0)
            {
                BuildingInfo info = BuildingManager.instance.m_buildings.m_buffer[id.Building].Info;
                HoverLarge.text = $"B:{id.Building}  {info.name}";
                HoverSmall.text = $"{info.GetType()} ({info.GetAI().GetType()})\n{info.m_class.name}\n({info.m_class.m_service}.{info.m_class.m_subService})";
            }
            else if (id.Prop > 0)
            {
                string   type = "P";
                PropInfo info = PropManager.instance.m_props.m_buffer[id.Prop].Info;
                if (info.m_isDecal)
                {
                    type = "D";
                }
                HoverLarge.text = $"{type}:{id.Prop}  {info.name}";
                HoverSmall.text = $"{info.GetType()}\n{info.m_class.name}";
            }
            else if (id.NetLane > 0)
            {
                IInfo info = MoveItTool.PO.GetProcObj(id.NetLane).Info;
                HoverLarge.text = $"{id.NetLane}: {info.Name}";
                HoverSmall.text = $"\n";
            }
            else if (id.Tree > 0)
            {
                TreeInfo info = TreeManager.instance.m_trees.m_buffer[id.Tree].Info;
                HoverLarge.text = $"T:{id.Tree}  {info.name}";
                HoverSmall.text = $"{info.GetType()}\n{info.m_class.name}";
            }
            else if (id.NetNode > 0)
            {
                NetInfo info = NetManager.instance.m_nodes.m_buffer[id.NetNode].Info;
                HoverLarge.text = $"N:{id.NetNode}  {info.name}";
                HoverSmall.text = $"{info.GetType()} ({info.GetAI().GetType()})\n{info.m_class.name}";
            }
            else if (id.NetSegment > 0)
            {
                NetInfo info = NetManager.instance.m_segments.m_buffer[id.NetSegment].Info;
                HoverLarge.text = $"S:{id.NetSegment}  {info.name}";
                HoverSmall.text = $"{info.GetType()} ({info.GetAI().GetType()})\n{info.m_class.name}";
            }

            lastId = id;
        }
Beispiel #16
0
        internal void Update()
        {
            if (!MoveItTool.showDebugPanel)
            {
                return;
            }

            ToolStatus.text = $"{MoveItTool.instance.ToolState} (align:{MoveItTool.instance.AlignMode}.{MoveItTool.instance.AlignToolPhase})";

            // End with updating the hovered item
            if (id == null)
            {
                return;
            }
            if (id == InstanceID.Empty)
            {
                lastId = id;
                HoverLarge.textColor = new Color32(255, 255, 255, 255);
                return;
            }
            if (lastId == id)
            {
                return;
            }

            HoverLarge.textColor = new Color32(127, 217, 255, 255);
            HoverLarge.text      = "";
            HoverSmall.text      = "";

            if (id.Building > 0)
            {
                BuildingInfo info = BuildingManager.instance.m_buildings.m_buffer[id.Building].Info;
                HoverLarge.text = $"B:{id.Building}  {info.name}";
                HoverSmall.text = $"{info.GetType()} ({info.GetAI().GetType()})\n{info.m_class.name}\n({info.m_class.m_service}.{info.m_class.m_subService})";
                if (isModToolsEnabled())
                {
                    ModTools.Id = id;
                }
            }
            else if (id.Prop > 0)
            {
                string   type = "P";
                PropInfo info = PropManager.instance.m_props.m_buffer[id.Prop].Info;
                if (info.m_isDecal)
                {
                    type = "D";
                }
                HoverLarge.text = $"{type}:{id.Prop}  {info.name}";
                HoverSmall.text = $"{info.GetType()}\n{info.m_class.name}";
                if (isModToolsEnabled())
                {
                    ModTools.Id = id;
                }
            }
            else if (id.NetLane > 0)
            {
                IInfo info = MoveItTool.PO.GetProcObj(id.NetLane).Info;
                HoverLarge.text = $"{id.NetLane}: {info.Name}";
                HoverSmall.text = $"\n";
                if (isModToolsEnabled())
                {
                    ModTools.Id = id;
                }
            }
            else if (id.Tree > 0)
            {
                TreeInfo info = TreeManager.instance.m_trees.m_buffer[id.Tree].Info;
                HoverLarge.text = $"T:{id.Tree}  {info.name}";
                HoverSmall.text = $"{info.GetType()}\n{info.m_class.name}";
                if (isModToolsEnabled())
                {
                    ModTools.Id = id;
                }
            }
            else if (id.NetNode > 0)
            {
                NetInfo info = NetManager.instance.m_nodes.m_buffer[id.NetNode].Info;
                HoverLarge.text = $"N:{id.NetNode}  {info.name}";
                HoverSmall.text = $"{info.GetType()} ({info.GetAI().GetType()})\n{info.m_class.name}";
                if (isModToolsEnabled())
                {
                    ModTools.Id = id;
                }
            }
            else if (id.NetSegment > 0)
            {
                NetInfo info = NetManager.instance.m_segments.m_buffer[id.NetSegment].Info;
                HoverLarge.text = $"S:{id.NetSegment}  {info.name}";
                HoverSmall.text = $"{info.GetType()} ({info.GetAI().GetType()})\n{info.m_class.name}";
                if (isModToolsEnabled())
                {
                    ModTools.Id = id;
                }
            }

            lastId = id;
        }
Beispiel #17
0
        public static bool Filter(BuildingInfo info, bool isHover = false)
        {
            if (isHover)
            {
                // Select P&P on hover with Alt
                if (MITE.Settings.PillarsAsNotBuildings)
                {
                    //Debug.Log($"SINGLE-Pi m_class.name:{info.m_class.name}");
                    if (Array.Exists(PillarClassNames, s => s.Equals(info.m_class.name)))
                    {
                        if (Event.current.alt)
                        {
                            //Debug.Log("Alt");
                            return(true);
                        }
                        return(false);
                    }
                }
                if (MITE.Settings.PylonsAsNotBuildings)
                {
                    //Debug.Log($"SINGLE-Py AI type:{info.GetAI().GetType()}");
                    if (Array.Exists(PylonAITypes, s => s.Equals(info.GetAI().GetType())))
                    {
                        if (Event.current.alt)
                        {
                            //Debug.Log("Alt");
                            return(true);
                        }
                        return(false);
                    }
                }

                if (!MoveItTool.marqueeSelection)
                {
                    return(true);
                }
            }

            if (IsSurface(info))
            {
                if (MITE.filterSurfaces)
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            if (MoveItTool.filterBuildings)
            {
                // Filter pillars and pylons out of select
                if (MITE.Settings.PillarsAsNotBuildings)
                {
                    //Debug.Log($"MARQUEE m_class.name:{info.m_class.name}");
                    if (Array.Exists(PillarClassNames, s => s.Equals(info.m_class.name)))
                    {
                        return(false);
                    }
                }
                if (MITE.Settings.PylonsAsNotBuildings)
                {
                    if (Array.Exists(PylonAITypes, s => s.Equals(info.GetAI().GetType())))
                    {
                        return(false);
                    }
                }
                return(true);
            }
            return(false);
        }
 private static IEnumerable <IBasicBuildingAIOverrides> ListAiOverrides(BuildingInfo info, ServiceSystemDefinition instance)
 {
     if (SVMBuildingAIOverrideUtils.getBuildingOverrideExtension(info).Count == 0)
     {
         return(new List <IBasicBuildingAIOverrides>());
     }
     return(SVMBuildingAIOverrideUtils.getBuildingOverrideExtension(info).Where(aiOverride =>
                                                                                (info?.m_class?.m_service == instance?.service) &&
                                                                                instance?.subService == info?.m_class?.m_subService &&
                                                                                ((instance?.outsideConnection ?? false) || info?.m_class?.m_level == instance.level || (aiOverride?.ExtraAllowedLevels()?.Contains(instance.level) ?? false)) &&
                                                                                info?.GetAI() is OutsideConnectionAI == instance?.outsideConnection &&
                                                                                SVMUtils.logAndReturn(aiOverride?.AllowVehicleType(SVMUtils.logAndReturn(instance?.vehicleType ?? VehicleInfo.VehicleType.None, "EFF VEHICLE TYPE TESTED"), info?.GetAI()) ?? SVMUtils.logAndReturn(false, "AI OVERRIDE NULL!!!!!"), "AllowVehicleType")
                                                                                ));
 }
        /// <summary>
        /// Called whenever the currently selected building is changed to update the panel display.
        /// </summary>
        /// <param name="building"></param>
        public void SelectionChanged(BuildingInfo building)
        {
            if ((building == null) || (building.name == null))
            {
                // If no valid building selected, then hide the calculations panel.
                detailsPanel.height    = 0;
                detailsPanel.isVisible = false;
                return;
            }

            // Variables to compare actual counts vs. mod count, to see if there's another mod overriding counts.
            int appliedCount;
            int modCount;

            // Building model size, not plot size.
            Vector3 buildingSize = building.m_size;
            int     floorCount;

            // Array used for calculations depending on building service/subservice (via DataStore).
            int[] array;
            // Default minimum number of homes or jobs is one; different service types will override this.
            int minHomesJobs = 1;
            int customHomeJobs;

            // Check for valid building AI.
            if (!(building.GetAI() is PrivateBuildingAI buildingAI))
            {
                Debugging.Message("invalid building AI type in building details");
                return;
            }

            // Residential vs. workplace AI.
            if (buildingAI is ResidentialBuildingAI)
            {
                // Get appropriate calculation array.
                array = ResidentialBuildingAIMod.GetArray(building, (int)building.GetClassLevel());

                // Set calculated homes label.
                homesJobsCalcLabel.text = Translations.Translate("RPR_CAL_HOM_CALC");

                // Set customised homes label and get value (if any).
                homesJobsCustomLabel.text = Translations.Translate("RPR_CAL_HOM_CUST");
                customHomeJobs            = ExternalCalls.GetResidential(building);

                // Applied homes is what's actually being returned by the CaclulateHomeCount call to this building AI.
                // It differs from calculated homes if there's an override value for that building with this mod, or if another mod is overriding.
                appliedCount = buildingAI.CalculateHomeCount(building.GetClassLevel(), new Randomizer(0), building.GetWidth(), building.GetLength());
                homesJobsActualLabel.text = Translations.Translate("RPR_CAL_HOM_APPL") + appliedCount;
            }
            else
            {
                // Workplace AI.
                // Default minimum number of jobs is 4.
                minHomesJobs = 4;

                // Find the correct array for the relevant building AI.
                switch (building.GetService())
                {
                case ItemClass.Service.Commercial:
                    array = CommercialBuildingAIMod.GetArray(building, (int)building.GetClassLevel());
                    break;

                case ItemClass.Service.Office:
                    array = OfficeBuildingAIMod.GetArray(building, (int)building.GetClassLevel());
                    break;

                case ItemClass.Service.Industrial:
                    if (buildingAI is IndustrialExtractorAI)
                    {
                        array = IndustrialExtractorAIMod.GetArray(building, (int)building.GetClassLevel());
                    }
                    else
                    {
                        array = IndustrialBuildingAIMod.GetArray(building, (int)building.GetClassLevel());
                    }
                    break;

                default:
                    Debugging.Message("invalid building service in building details");
                    return;
                }

                // Set calculated jobs label.
                homesJobsCalcLabel.text = Translations.Translate("RPR_CAL_JOB_CALC") + " ";

                // Set customised jobs label and get value (if any).
                homesJobsCustomLabel.text = Translations.Translate("RPR_CAL_JOB_CUST") + " ";
                customHomeJobs            = ExternalCalls.GetWorker(building);

                // Applied jobs is what's actually being returned by the CalculateWorkplaceCount call to this building AI.
                // It differs from calculated jobs if there's an override value for that building with this mod, or if another mod is overriding.
                int[] jobs = new int[4];
                buildingAI.CalculateWorkplaceCount(building.GetClassLevel(), new Randomizer(0), building.GetWidth(), building.GetLength(), out jobs[0], out jobs[1], out jobs[2], out jobs[3]);
                appliedCount = jobs[0] + jobs[1] + jobs[2] + jobs[3];
                homesJobsActualLabel.text = Translations.Translate("RPR_CAL_JOB_APPL") + " " + appliedCount;
            }

            // Reproduce CalcBase calculations to get building area.
            int calcWidth  = building.GetWidth();
            int calcLength = building.GetLength();

            floorCount = Mathf.Max(1, Mathf.FloorToInt(buildingSize.y / array[DataStore.LEVEL_HEIGHT]));

            // If CALC_METHOD is zero, then calculations are based on building model size, not plot size.
            if (array[DataStore.CALC_METHOD] == 0)
            {
                // If asset has small x dimension, then use plot width in squares x 6m (75% of standard width) instead.
                if (buildingSize.x <= 1)
                {
                    calcWidth *= 6;
                }
                else
                {
                    calcWidth = (int)buildingSize.x;
                }

                // If asset has small z dimension, then use plot length in squares x 6m (75% of standard length) instead.
                if (buildingSize.z <= 1)
                {
                    calcLength *= 6;
                }
                else
                {
                    calcLength = (int)buildingSize.z;
                }
            }
            else
            {
                // If CALC_METHOD is nonzero, then caluclations are based on plot size, not building size.
                // Plot size is 8 metres per square.
                calcWidth  *= 8;
                calcLength *= 8;
            }

            // Display calculated (and retrieved) details.
            detailLabels[(int)Details.width].text       = Translations.Translate("RPR_CAL_BLD_X") + " " + calcWidth;
            detailLabels[(int)Details.length].text      = Translations.Translate("RPR_CAL_BLD_Z") + " " + calcLength;
            detailLabels[(int)Details.height].text      = Translations.Translate("RPR_CAL_BLD_Y") + " " + (int)buildingSize.y;
            detailLabels[(int)Details.personArea].text  = Translations.Translate("RPR_CAL_BLD_M2") + " " + array[DataStore.PEOPLE];
            detailLabels[(int)Details.floorHeight].text = Translations.Translate("RPR_CAL_FLR_Y") + " " + array[DataStore.LEVEL_HEIGHT];
            detailLabels[(int)Details.floors].text      = Translations.Translate("RPR_CAL_FLR") + " " + floorCount;

            // Area calculation - will need this later.
            int calculatedArea = calcWidth * calcLength;

            detailLabels[(int)Details.area].text = Translations.Translate("RPR_CAL_M2") + " " + calculatedArea;

            // Show or hide extra floor modifier as appropriate (hide for zero or less, otherwise show).
            if (array[DataStore.DENSIFICATION] > 0)
            {
                detailLabels[(int)Details.extraFloors].text      = Translations.Translate("RPR_CAL_FLR_M") + " " + array[DataStore.DENSIFICATION];
                detailLabels[(int)Details.extraFloors].isVisible = true;
            }
            else
            {
                detailLabels[(int)Details.extraFloors].isVisible = false;
            }

            // Set minimum residences for high density.
            if ((building.GetSubService() == ItemClass.SubService.ResidentialHigh) || (building.GetSubService() == ItemClass.SubService.ResidentialHighEco))
            {
                // Minimum of 2, or 90% number of floors, whichever is greater. This helps the 1x1 high density.
                minHomesJobs = Mathf.Max(2, Mathf.CeilToInt(0.9f * floorCount));
            }

            // Perform actual household or workplace calculation.
            modCount = Mathf.Max(minHomesJobs, (calculatedArea * (floorCount + Mathf.Max(0, array[DataStore.DENSIFICATION]))) / array[DataStore.PEOPLE]);
            homesJobsCalcLabel.text += modCount;

            // Set customised homes/jobs label (leave blank if no custom setting retrieved).
            if (customHomeJobs > 0)
            {
                homesJobsCustomLabel.text += customHomeJobs.ToString();

                // Update modCount to reflect the custom figures.
                modCount = customHomeJobs;
            }

            // Check to see if Ploppable RICO Revisited is controlling this building's population.
            if (ModUtils.CheckRICO(building))
            {
                messageLabel.text = Translations.Translate("RPR_CAL_RICO");
                messageLabel.Show();
            }
            else
            {
                // Hide message text by default.
                messageLabel.Hide();
            }

            // We've got a valid building and results, so show panel.
            detailsPanel.height    = 270;
            detailsPanel.isVisible = true;
        }
Beispiel #20
0
        bool RegisterPrefab(String fullName, Package.Asset asset, CustomAssetMetaData metaData, PrefabInfo info, GameObject go)
        {
            PropInfo pi = go.GetComponent <PropInfo>();

            if (pi != null)
            {
                if (pi.m_lodObject != null)
                {
                    pi.m_lodObject.SetActive(false);
                }

                if (StorePropName(fullName))
                {
                    PrefabCollection <PropInfo> .InitializePrefabs("Custom Assets", pi, null);

                    return(true);
                }
            }

            TreeInfo ti = go.GetComponent <TreeInfo>();

            if (ti != null && StoreTreeName(fullName))
            {
                PrefabCollection <TreeInfo> .InitializePrefabs("Custom Assets", ti, null);

                return(true);
            }

            BuildingInfo bi = go.GetComponent <BuildingInfo>();

            if (bi != null)
            {
                if (bi.m_lodObject != null)
                {
                    bi.m_lodObject.SetActive(false);
                }

                if (StoreBuildingName(fullName))
                {
                    PrefabCollection <BuildingInfo> .InitializePrefabs("Custom Assets", bi, null);

                    bi.m_dontSpawnNormally = !IsCommonBuilding(fullName, asset, metaData);

                    if (bi.GetAI() is IntersectionAI)
                    {
                        loadedIntersections.Add(fullName);
                    }

                    return(true);
                }
            }

            VehicleInfo vi = go.GetComponent <VehicleInfo>();

            if (vi != null)
            {
                if (vi.m_lodObject != null)
                {
                    vi.m_lodObject.SetActive(false);
                }

                if (StoreVehicleName(fullName))
                {
                    PrefabCollection <VehicleInfo> .InitializePrefabs("Custom Assets", vi, null);

                    return(true);
                }
            }

            return(false);
        }
 public Dictionary <TransferManager.TransferReason, Tuple <VehicleInfo.VehicleType, bool, bool> > GetManagedReasons(BuildingInfo info)
 {
     return(GetManagedReasons((U)info.GetAI(), default(TransferManager.TransferOffer)));
 }
 public Dictionary <TransferManager.TransferReason, StartTransferCallStructure> GetManagedReasons(BuildingInfo info)
 {
     return(GetManagedReasons((U)info.GetAI(), default(TransferManager.TransferOffer)));
 }
Beispiel #23
0
 /// <summary>
 /// Updates a school prefab record (and associated tooltip) with updated population.
 /// </summary>
 /// <param name="prefab">Prefab to update</param>
 internal void UpdateSchoolPrefab(BuildingInfo prefab) => UpdateSchoolPrefab(prefab, prefab.GetAI() as SchoolAI);
        /// <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();
            }
Beispiel #25
0
        public void Update(InstanceID instanceId)
        {
            id = instanceId;
            if (!MITE.Settings.ShowDebugPanel)
            {
                return;
            }

            if (id == null)
            {
                return;
            }
            if (id == InstanceID.Empty)
            {
                lastId = id;
                HoverLarge.textColor = new Color32(255, 255, 255, 255);
                return;
            }
            if (lastId == id)
            {
                return;
            }

            HoverLarge.textColor = new Color32(127, 217, 255, 255);
            HoverLarge.text      = "";
            HoverSmall.text      = "";

            if (id.Building > 0)
            {
                BuildingInfo info = BuildingManager.instance.m_buildings.m_buffer[id.Building].Info;
                HoverLarge.text = $"B:{id.Building}  {info.name}";
                HoverSmall.text = $"{info.GetType()} ({info.GetAI().GetType()})\n{info.m_class.name}\n({info.m_class.m_service}.{info.m_class.m_subService})";
                if (isModToolsEnabled())
                {
                    ModTools.Id = id;
                }
            }
            if (id.Prop > 0)
            {
                string   type = "P";
                PropInfo info = PropManager.instance.m_props.m_buffer[id.Prop].Info;
                if (info.m_isDecal)
                {
                    type = "D";
                }
                HoverLarge.text = $"{type}:{id.Prop}  {info.name}";
                HoverSmall.text = $"{info.GetType()}\n{info.m_class.name}";
                if (isModToolsEnabled())
                {
                    ModTools.Id = id;
                }
            }
            if (id.Tree > 0)
            {
                TreeInfo info = TreeManager.instance.m_trees.m_buffer[id.Tree].Info;
                HoverLarge.text = $"T:{id.Tree}  {info.name}";
                HoverSmall.text = $"{info.GetType()}\n{info.m_class.name}";
                if (isModToolsEnabled())
                {
                    ModTools.Id = id;
                }
            }
            if (id.NetNode > 0)
            {
                NetInfo info = NetManager.instance.m_nodes.m_buffer[id.NetNode].Info;
                HoverLarge.text = $"N:{id.NetNode}  {info.name}";
                HoverSmall.text = $"{info.GetType()} ({info.GetAI().GetType()})\n{info.m_class.name}";
                if (isModToolsEnabled())
                {
                    ModTools.Id = id;
                }
            }
            if (id.NetSegment > 0)
            {
                NetInfo info = NetManager.instance.m_segments.m_buffer[id.NetSegment].Info;
                HoverLarge.text = $"S:{id.NetSegment}  {info.name}";
                HoverSmall.text = $"{info.GetType()} ({info.GetAI().GetType()})\n{info.m_class.name}";
                if (isModToolsEnabled())
                {
                    ModTools.Id = id;
                }
            }

            lastId = id;
        }
 public static ServiceSystemDefinition from(BuildingInfo info, VehicleInfo.VehicleType type)
 {
     if (info == null)
     {
         return(default(ServiceSystemDefinition));
     }
     return(availableDefinitions.Keys.FirstOrDefault(x => x.service == info.m_class.m_service && x.subService == info.m_class.m_subService && (x.level == info.m_class.m_level || x.outsideConnection) && x.vehicleType == type && x.outsideConnection == info.GetAI() is OutsideConnectionAI));
 }
        /// <summary>
        /// Upgrades/downgrades the selected building to the given level, if possible.
        /// </summary>
        /// <param name="buildingID">Building instance ID</param>
        /// <param name="targetLevel">Level to upgrade/downgrade to</param>
        internal static void ForceLevel(ushort buildingID, byte targetLevel)
        {
            // BuildingInfo to change to, if this building isn't historical.
            BuildingInfo targetInfo = null;

            // References.
            BuildingManager buildingManager = Singleton <BuildingManager> .instance;

            Building[]        buildingBuffer = buildingManager.m_buildings.m_buffer;
            BuildingInfo      buildingInfo   = buildingBuffer[buildingID].Info;
            PrivateBuildingAI buildingAI     = buildingInfo?.GetAI() as PrivateBuildingAI;

            if (buildingInfo == null || buildingAI == null)
            {
                // If something went wrong, abort.
                Logging.Error("couldn't get existing building info");
                return;
            }

            // Check to see if this is historical or not, or is a RICO ploppable.
            bool isHistorical = buildingAI.IsHistorical(buildingID, ref Singleton <BuildingManager> .instance.m_buildings.m_buffer[buildingID], out bool _) || ModUtils.CheckRICOPloppable(buildingInfo);

            // Get target prefab (if needed, i.e. not historical or RICO ploppable).
            if (!isHistorical)
            {
                // Get upgrade/downgrade building target.
                targetInfo = GetTargetInfo(buildingID, targetLevel);
                if (targetInfo == null)
                {
                    // If we failed, don't do anything more.
                    return;
                }
            }

            // If we have a valid upgrade/downgrade target, proceed.
            if (isHistorical || targetInfo != null)
            {
                // Apply target level to our building and cancel all level-up progress.
                buildingBuffer[buildingID].m_level           = targetLevel;
                buildingBuffer[buildingID].m_levelUpProgress = 0;

                // Apply our upgrade/downgrade target if not historical
                if (!isHistorical)
                {
                    buildingManager.UpdateBuildingInfo(buildingID, targetInfo);
                }

                // Post-downgrade processing to update instance values - call game method if new level is equal to or greater than info base level, otherwise use custom method.
                BuildingInfo newInfo = targetInfo ?? buildingInfo;
                if (newInfo.GetAI() is PrivateBuildingAI newAI)
                {
                    if (targetLevel < (byte)newInfo.GetClassLevel())
                    {
                        // New level is less than info base level; call custom method.
                        CustomBuildingUpgraded(newAI, buildingID, ref buildingBuffer[buildingID]);
                    }
                    else
                    {
                        // New level is equal to or greater than info base level; call game method.
                        newAI.BuildingUpgraded(buildingID, ref buildingBuffer[buildingID]);
                    }
                }
            }
        }
        public static void CalculateAllWorkplaces()
        {
            if (!ShouldWeCount)
            {
                return;
            }

            WorkplacesEducated       = 0;
            WorkplacesHighlyEducated = 0;
            WorkplacesUneducated     = 0;
            WorkplacesWellEducated   = 0;

            for (var i = 0; i < comWorkplaces.Length; i++)
            {
                comWorkplaces[i] = 0;
                offWorkplaces[i] = 0;
                indWorkplaces[i] = 0;
            }

            BuildingManager buildingManager = Singleton <BuildingManager> .instance;

            if (buildingManager == null || buildingManager.m_buildings == null)
            {
                return;
            }

            // go through all buildings
            for (ushort buildingID = 0; buildingID < buildingManager.m_buildings.m_buffer.Length; buildingID++)
            {
                try
                {
                    Building building = buildingManager.m_buildings.m_buffer[buildingID];

                    BuildingInfo buildingInfo = building.Info;

                    // we have build info and created building
                    if (buildingInfo != null && (building.m_flags & Building.Flags.Created) != Building.Flags.None)
                    {
                        var privateBuildingAI = buildingInfo.GetAI() as PrivateBuildingAI;

                        // if it is zoned building (PlayerIndustry is for zoned special industry)
                        if (privateBuildingAI != null &&
                            (ItemClass.Service.Commercial == buildingInfo.GetService() ||
                             ItemClass.Service.Industrial == buildingInfo.GetService() ||
                             ItemClass.Service.PlayerIndustry == buildingInfo.GetService() ||
                             ItemClass.Service.Office == buildingInfo.GetService()))
                        {
                            int wp0, wp1, wp2, wp3;
                            privateBuildingAI.CalculateWorkplaceCount(
                                (ItemClass.Level)building.m_level,
                                new Randomizer(buildingID),
                                building.Width,
                                building.Length,
                                out wp0,
                                out wp1,
                                out wp2,
                                out wp3);

                            privateBuildingAI.AdjustWorkplaceCount(
                                buildingID,
                                ref building,
                                ref wp0,
                                ref wp1,
                                ref wp2,
                                ref wp3);

                            WorkplacesUneducated     += wp0;
                            WorkplacesEducated       += wp1;
                            WorkplacesWellEducated   += wp2;
                            WorkplacesHighlyEducated += wp3;

                            ItemClass.Service service = buildingInfo.GetService();
                            switch (service)
                            {
                            case ItemClass.Service.Commercial:
                                comWorkplaces[0] += wp0;
                                comWorkplaces[1] += wp1;
                                comWorkplaces[2] += wp2;
                                comWorkplaces[3] += wp3;
                                break;

                            case ItemClass.Service.Industrial:
                            case ItemClass.Service.PlayerIndustry:
                                indWorkplaces[0] += wp0;
                                indWorkplaces[1] += wp1;
                                indWorkplaces[2] += wp2;
                                indWorkplaces[3] += wp3;
                                break;

                            case ItemClass.Service.Office:
                                offWorkplaces[0] += wp0;
                                offWorkplaces[1] += wp1;
                                offWorkplaces[2] += wp2;
                                offWorkplaces[3] += wp3;
                                break;
                            }
                        } // if privateBuildingAI end
                        else
                        {
                            // this is for all other buildings - services, monuments, parks, INDUSTRY AREAS
                            if (buildingInfo.GetAI().GetType().IsSubclassOf(typeof(PlayerBuildingAI)))
                            {
                                var ai = buildingInfo.GetAI() as PlayerBuildingAI;
                                if (ai != null)
                                {
                                    int swp0, swp1, swp2, swp3;
                                    // Industry are buildings provide workplace info from this common method
                                    // But it does NOT work for raw material storages (they are like normal warehouses)
                                    ai.CountWorkPlaces(out swp0, out swp1, out swp2, out swp3); // works for industry areas

                                    // if it is sum of workplaces 0, it is another type of service building
                                    if (swp0 + swp1 + swp2 + swp3 == 0)
                                    {
                                        // we will try bit of reflection
                                        // we get Type of buildingAI
                                        var  serviceAI = buildingInfo.GetAI();
                                        Type aiType    = buildingInfo.GetAI().GetType();
                                        // we get all fields of that AI Type
                                        FieldInfo[] fieldInfos = aiType.GetFields();

                                        // we check if Types fields contains field m_workPlaceCount0
                                        if (fieldInfos.Length > 0 && serviceAI != null && aiType.GetField("m_workPlaceCount0") != null)
                                        {
                                            // and we count them
                                            swp0 = (int)(aiType.GetField("m_workPlaceCount0").GetValue(serviceAI) ?? 0);
                                            swp1 = (int)(aiType.GetField("m_workPlaceCount1").GetValue(serviceAI) ?? 0);
                                            swp2 = (int)(aiType.GetField("m_workPlaceCount2").GetValue(serviceAI) ?? 0);
                                            swp3 = (int)(aiType.GetField("m_workPlaceCount3").GetValue(serviceAI) ?? 0);
                                        }
                                    }

                                    WorkplacesUneducated     += swp0;
                                    WorkplacesEducated       += swp1;
                                    WorkplacesWellEducated   += swp2;
                                    WorkplacesHighlyEducated += swp3;
                                }
                            }
                        }
                    }
                }
                catch (NullReferenceException e)
                {
                    // This should not happen now...
                    Debug.Log("Demographics Mod: Trying to count building which does " +
                              "not have workplace information. We should not get here... " + e.Message);
                }
            }

            ShouldWeCount = false;
        }
Beispiel #29
0
        public static bool Filter(BuildingInfo info, bool isHover = false)
        {
            if (MoveItTool.filterPicker && info == Picker.Info)
            {
                return(true);
            }
            if (isHover)
            {
                //Select P&P on hover with Alt
                if (MoveItTool.altSelectNodeBuildings)
                {
                    if (Array.Exists(PillarClassNames, s => s.Equals(info.m_class.name)))
                    {
                        if (Event.current.alt)
                        {
                            return(true);
                        }
                        return(false);
                    }

                    if (Array.Exists(PylonAITypes, s => s.Equals(info.GetAI().GetType())))
                    {
                        if (Event.current.alt)
                        {
                            return(true);
                        }
                        return(false);
                    }
                }

                if (!MoveItTool.marqueeSelection)
                {
                    return(true);
                }
            }

            if (IsSurface(info))
            {
                if (MoveItTool.filterSurfaces)
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            if (MoveItTool.filterBuildings)
            {
                if (MoveItTool.altSelectNodeBuildings)
                {
                    if (Array.Exists(PillarClassNames, s => s.Equals(info.m_class.name)))
                    {
                        return(false);
                    }

                    if (Array.Exists(PylonAITypes, s => s.Equals(info.GetAI().GetType())))
                    {
                        return(false);
                    }
                }
                return(true);
            }
            return(false);
        }
Beispiel #30
0
        public void updateBidings()
        {
            BuildingInfo basicInfo = Singleton <BuildingManager> .instance.m_buildings.m_buffer[m_buildingIdSelecionado.Building].Info;
            DepotAI      basicAI   = basicInfo.GetAI() as DepotAI;

            if (basicAI == null)
            {
                closeDepotInfo(null, null);
                return;
            }

            TransportStationAI stationAI = basicInfo.GetAI() as TransportStationAI;
            HarborAI           harborAI  = basicInfo.GetAI() as HarborAI;


            vehiclesInUseLabel.text = LocaleFormatter.FormatGeneric("TRANSPORT_LINE_VEHICLECOUNT", new object[] { basicAI.GetVehicleCount(m_buildingIdSelecionado.Building, ref Singleton <BuildingManager> .instance.m_buildings.m_buffer[m_buildingIdSelecionado.Building]).ToString() });
            if (stationAI != null)
            {
                passengersLastWeek.isVisible = true;
                int passengerCount = stationAI.GetPassengerCount(m_buildingIdSelecionado.Building, ref Singleton <BuildingManager> .instance.m_buildings.m_buffer[m_buildingIdSelecionado.Building]);
                passengersLastWeek.text = LocaleFormatter.FormatGeneric("AIINFO_PASSENGERS_SERVICED", new object[] { passengerCount });
            }
            else
            {
                passengersLastWeek.isVisible = false;
            }

            upkeepCost.text = LocaleFormatter.FormatUpkeep(basicAI.GetResourceRate(m_buildingIdSelecionado.Building, ref Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)m_buildingIdSelecionado.Building], EconomyManager.Resource.Maintenance), false);

            uint num         = Singleton <BuildingManager> .instance.m_buildings.m_buffer[m_buildingIdSelecionado.Building].m_citizenUnits;
            int  num2        = 0;
            int  num3        = 0;
            int  unskill     = 0;
            int  oneSchool   = 0;
            int  twoSchool   = 0;
            int  threeSchool = 0;

            CitizenManager instance = Singleton <CitizenManager> .instance;

            while (num != 0u)
            {
                uint nextUnit = instance.m_units.m_buffer[(int)((UIntPtr)num)].m_nextUnit;
                if ((ushort)(instance.m_units.m_buffer[(int)((UIntPtr)num)].m_flags & CitizenUnit.Flags.Work) != 0)
                {
                    for (int i = 0; i < 5; i++)
                    {
                        uint citizen = instance.m_units.m_buffer[(int)((UIntPtr)num)].GetCitizen(i);
                        if (citizen != 0u && !instance.m_citizens.m_buffer[(int)((UIntPtr)citizen)].Dead && (instance.m_citizens.m_buffer[(int)((UIntPtr)citizen)].m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None)
                        {
                            num3++;
                            switch (instance.m_citizens.m_buffer[(int)((UIntPtr)citizen)].EducationLevel)
                            {
                            case Citizen.Education.Uneducated:
                                unskill++;
                                break;

                            case Citizen.Education.OneSchool:
                                oneSchool++;
                                break;

                            case Citizen.Education.TwoSchools:
                                twoSchool++;
                                break;

                            case Citizen.Education.ThreeSchools:
                                threeSchool++;
                                break;
                            }
                        }
                    }
                }
                num = nextUnit;
                if (++num2 > 524288)
                {
                    CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                    break;
                }
            }

            workerChart.SetValues(new int[] { unskill, oneSchool, twoSchool, threeSchool }, new int[] { basicAI.m_workPlaceCount0, basicAI.m_workPlaceCount1, basicAI.m_workPlaceCount2, basicAI.m_workPlaceCount3 });
        }