public static void ProcessLandFeeNoOffice(Building building, ushort buildingID)
        {
            DistrictManager instance = Singleton <DistrictManager> .instance;
            byte            district = instance.GetDistrict(building.m_position);

            DistrictPolicies.Services servicePolicies  = instance.m_districts.m_buffer[district].m_servicePolicies;
            DistrictPolicies.Taxation taxationPolicies = instance.m_districts.m_buffer[district].m_taxationPolicies;

            int landFee;

            GetLandRentNoOffice(out landFee, building, buildingID);
            int taxRate;

            taxRate = Singleton <EconomyManager> .instance.GetTaxRate(building.Info.m_class, taxationPolicies);

            if (((taxationPolicies & DistrictPolicies.Taxation.DontTaxLeisure) != DistrictPolicies.Taxation.None) && (building.Info.m_class.m_subService == ItemClass.SubService.CommercialLeisure))
            {
                landFee = 0;
            }

            if (instance.IsPolicyLoaded(DistrictPolicies.Policies.ExtraInsulation))
            {
                if ((servicePolicies & DistrictPolicies.Services.ExtraInsulation) != DistrictPolicies.Services.None)
                {
                    landFee = landFee * 95 / 100;
                }
            }
            if ((servicePolicies & DistrictPolicies.Services.Recycling) != DistrictPolicies.Services.None)
            {
                landFee = landFee * 95 / 100;
            }

            if (BuildingData.buildingMoney[buildingID] <= ((landFee * taxRate) / 100f))
            {
                landFee = 0;
            }
            else
            {
                RealCityPrivateBuildingAI.profitBuildingCount++;
            }

            if (RealCityEconomyExtension.Can16timesUpdate(buildingID))
            {
                Singleton <EconomyManager> .instance.AddPrivateIncome(landFee, building.Info.m_class.m_service, building.Info.m_class.m_subService, building.Info.m_class.m_level, taxRate * 100);

                if ((building.Info.m_class.m_service == ItemClass.Service.Commercial) || (building.Info.m_class.m_service == ItemClass.Service.Industrial))
                {
                    BuildingData.buildingMoney[buildingID] = (BuildingData.buildingMoney[buildingID] - (float)(landFee * taxRate) / 100);
                }
            }
        }
        static int TakeExam(uint citizenIndex)
        {
            SimulationManager simulationManager = Singleton <SimulationManager> .instance;
            CitizenManager    citizenManager    = Singleton <CitizenManager> .instance;
            DistrictManager   districtManager   = Singleton <DistrictManager> .instance;
            BuildingManager   buildingManager   = Singleton <BuildingManager> .instance;
            Vector3           position          = buildingManager.m_buildings.m_buffer[citizenManager.m_citizens.m_buffer[citizenIndex].m_homeBuilding].m_position;
            byte district = districtManager.GetDistrict(position);

            DistrictPolicies.Services servicePolicies = districtManager.m_districts.m_buffer[(int)district].m_servicePolicies;
            int grade = simulationManager.m_randomizer.Int32(100);

            if ((servicePolicies & DistrictPolicies.Services.EducationBoost) != 0)
            {
                grade += 20;
            }
            return(grade);
        }
        private static int ticketPriceForPrefix(ushort vehicleID, ref Vehicle vehicleData)
        {
            var def = TransportSystemDefinition.from(vehicleData.Info.m_class.m_subService, vehicleData.Info.m_vehicleType);

            if (def == default(TransportSystemDefinition))
            {
                if (TransportLinesManagerMod.instance != null && TransportLinesManagerMod.debugMode)
                {
                    TLMUtils.doLog("NULL TSysDef! {0}+{1}+{2}", vehicleData.Info.GetAI().GetType(), vehicleData.Info.m_class.m_subService, vehicleData.Info.m_vehicleType);
                }
                return(100);
            }
            if (def.vehicleType == VehicleInfo.VehicleType.Ferry)
            {
                DistrictManager           instance        = Singleton <DistrictManager> .instance;
                byte                      district        = instance.GetDistrict(vehicleData.m_targetPos3);
                DistrictPolicies.Services servicePolicies = instance.m_districts.m_buffer[(int)district].m_servicePolicies;
                if ((servicePolicies & DistrictPolicies.Services.PreferFerries) != DistrictPolicies.Services.None)
                {
                    District[] expr_6E_cp_0 = instance.m_districts.m_buffer;
                    byte       expr_6E_cp_1 = district;
                    expr_6E_cp_0[(int)expr_6E_cp_1].m_servicePoliciesEffect = (expr_6E_cp_0[(int)expr_6E_cp_1].m_servicePoliciesEffect | DistrictPolicies.Services.PreferFerries);
                    return(0);
                }
            }
            if (vehicleData.m_transportLine == 0)
            {
                var value = (int)BasicTransportExtensionSingleton.instance(def).getDefaultTicketPrice();
                return(value);
            }
            else
            {
                var value = (int)(BasicTransportExtensionSingleton.instance(def).getTicketPrice((uint)vehicleData.m_transportLine));

                return(value);
            }
        }
        public int GetTicketPrice(ushort vehicleID, ref Vehicle vehicleData)
        {
            if (vehicleData.m_transportLine == 0)
            {
                return(ticketPriceForPrefix(vehicleID, ref vehicleData));
            }
            DistrictManager instance = Singleton <DistrictManager> .instance;
            byte            district = instance.GetDistrict(vehicleData.m_targetPos3);

            DistrictPolicies.Services servicePolicies = instance.m_districts.m_buffer[(int)district].m_servicePolicies;
            DistrictPolicies.Event    @event          = instance.m_districts.m_buffer[(int)district].m_eventPolicies & Singleton <EventManager> .instance.GetEventPolicyMask();

            if ((servicePolicies & DistrictPolicies.Services.FreeTransport) != DistrictPolicies.Services.None)
            {
                District[] expr_80_cp_0 = instance.m_districts.m_buffer;
                byte       expr_80_cp_1 = district;
                expr_80_cp_0[(int)expr_80_cp_1].m_servicePoliciesEffect = (expr_80_cp_0[(int)expr_80_cp_1].m_servicePoliciesEffect | DistrictPolicies.Services.FreeTransport);
                return(0);
            }
            if ((@event & DistrictPolicies.Event.ComeOneComeAll) != DistrictPolicies.Event.None)
            {
                District[] expr_AC_cp_0 = instance.m_districts.m_buffer;
                byte       expr_AC_cp_1 = district;
                expr_AC_cp_0[(int)expr_AC_cp_1].m_eventPoliciesEffect = (expr_AC_cp_0[(int)expr_AC_cp_1].m_eventPoliciesEffect | DistrictPolicies.Event.ComeOneComeAll);
                return(0);
            }
            if ((servicePolicies & DistrictPolicies.Services.HighTicketPrices) != DistrictPolicies.Services.None)
            {
                District[] expr_D8_cp_0 = instance.m_districts.m_buffer;
                byte       expr_D8_cp_1 = district;
                expr_D8_cp_0[(int)expr_D8_cp_1].m_servicePoliciesEffect = (expr_D8_cp_0[(int)expr_D8_cp_1].m_servicePoliciesEffect | DistrictPolicies.Services.HighTicketPrices);
                return((int)ticketPriceForPrefix(vehicleID, ref vehicleData) * 5 / 4);
            }

            return(ticketPriceForPrefix(vehicleID, ref vehicleData));
        }
Exemple #5
0
 public static void HandleFire(CommercialBuildingAI thisAI, ushort buildingID, ref Building data, ref Building.Frame frameData, DistrictPolicies.Services policies)
 {
     Debug.LogWarning("HandleFire is not overridden!");
 }
Exemple #6
0
 public static int HandleCommonConsumption(CommercialBuildingAI thisAI, ushort buildingID, ref Building data, ref Building.Frame frameData, ref int electricityConsumption, ref int heatingConsumption, ref int waterConsumption, ref int sewageAccumulation, ref int garbageAccumulation, DistrictPolicies.Services policies)
 {
     Debug.LogWarning("HandleCommonConsumption is not overridden!");
     return(0);
 }
Exemple #7
0
        public static void SimulationStepActive(CommercialBuildingAI thisAI, ushort buildingID, ref Building buildingData, ref Building.Frame frameData)
        {
            //This is a mess because I pulled it directly from the decompiled code and patched it up slightly.
            //It works though, and that's all I'm bothered about for now.

            if (thisAI)
            {
                DistrictManager               instance1            = Singleton <DistrictManager> .instance;
                byte                          district             = instance1.GetDistrict(buildingData.m_position);
                DistrictPolicies.Services     policies             = instance1.m_districts.m_buffer[(int)district].m_servicePolicies;
                DistrictPolicies.Taxation     taxationPolicies     = instance1.m_districts.m_buffer[(int)district].m_taxationPolicies;
                DistrictPolicies.CityPlanning cityPlanningPolicies = instance1.m_districts.m_buffer[(int)district].m_cityPlanningPolicies;
                instance1.m_districts.m_buffer[(int)district].m_servicePoliciesEffect |= policies & (DistrictPolicies.Services.PowerSaving | DistrictPolicies.Services.WaterSaving | DistrictPolicies.Services.SmokeDetectors | DistrictPolicies.Services.Recycling | DistrictPolicies.Services.RecreationalUse | DistrictPolicies.Services.ExtraInsulation | DistrictPolicies.Services.NoElectricity | DistrictPolicies.Services.OnlyElectricity | DistrictPolicies.Services.RecyclePlastic);
                switch (thisAI.m_info.m_class.m_subService)
                {
                case ItemClass.SubService.CommercialLow:
                    if ((taxationPolicies & (DistrictPolicies.Taxation.TaxRaiseComLow | DistrictPolicies.Taxation.TaxLowerComLow)) != (DistrictPolicies.Taxation.TaxRaiseComLow | DistrictPolicies.Taxation.TaxLowerComLow))
                    {
                        instance1.m_districts.m_buffer[(int)district].m_taxationPoliciesEffect |= taxationPolicies & (DistrictPolicies.Taxation.TaxRaiseComLow | DistrictPolicies.Taxation.TaxLowerComLow);
                    }
                    instance1.m_districts.m_buffer[(int)district].m_cityPlanningPoliciesEffect |= cityPlanningPolicies & DistrictPolicies.CityPlanning.SmallBusiness;
                    break;

                case ItemClass.SubService.CommercialHigh:
                    if ((taxationPolicies & (DistrictPolicies.Taxation.TaxRaiseComHigh | DistrictPolicies.Taxation.TaxLowerComHigh)) != (DistrictPolicies.Taxation.TaxRaiseComHigh | DistrictPolicies.Taxation.TaxLowerComHigh))
                    {
                        instance1.m_districts.m_buffer[(int)district].m_taxationPoliciesEffect |= taxationPolicies & (DistrictPolicies.Taxation.TaxRaiseComHigh | DistrictPolicies.Taxation.TaxLowerComHigh);
                    }
                    instance1.m_districts.m_buffer[(int)district].m_cityPlanningPoliciesEffect |= cityPlanningPolicies & DistrictPolicies.CityPlanning.BigBusiness;
                    break;

                case ItemClass.SubService.CommercialLeisure:
                    instance1.m_districts.m_buffer[(int)district].m_taxationPoliciesEffect     |= taxationPolicies & DistrictPolicies.Taxation.DontTaxLeisure;
                    instance1.m_districts.m_buffer[(int)district].m_cityPlanningPoliciesEffect |= cityPlanningPolicies & DistrictPolicies.CityPlanning.NoLoudNoises;
                    break;

                case ItemClass.SubService.CommercialTourist:
                    instance1.m_districts.m_buffer[(int)district].m_cityPlanningPoliciesEffect |= cityPlanningPolicies & DistrictPolicies.CityPlanning.LightningRods;
                    break;

                case ItemClass.SubService.CommercialEco:
                    instance1.m_districts.m_buffer[(int)district].m_cityPlanningPoliciesEffect |= cityPlanningPolicies;
                    break;
                }
                Citizen.BehaviourData behaviour = new Citizen.BehaviourData();
                int aliveWorkerCount            = 0;
                int totalWorkerCount            = 0;
                int workPlaceCount = 0;
                int num1           = NewPrivateBuildingAI.HandleWorkers(thisAI, buildingID, ref buildingData, ref behaviour, ref aliveWorkerCount, ref totalWorkerCount, ref workPlaceCount);

                if ((buildingData.m_flags & Building.Flags.Evacuating) != Building.Flags.None)
                {
                    num1 = 0;
                }

                int width      = buildingData.Width;
                int length     = buildingData.Length;
                int num2       = MaxIncomingLoadSize(thisAI);
                int aliveCount = 0;
                int totalCount = 0;
                GetVisitBehaviour(thisAI, buildingID, ref buildingData, ref behaviour, ref aliveCount, ref totalCount);
                int visitCount = thisAI.CalculateVisitplaceCount(new Randomizer((int)buildingID), width, length);
                int num3       = Mathf.Max(0, visitCount - totalCount);
                int a1         = visitCount * 500;
                int num4       = Mathf.Max(a1, num2 * 4);
                TransferManager.TransferReason incomingTransferReason = GetIncomingTransferReason(thisAI);
                TransferManager.TransferReason outgoingTransferReason = GetOutgoingTransferReason(thisAI, buildingID);
                if (num1 != 0)
                {
                    int num5 = num4;
                    if (incomingTransferReason != TransferManager.TransferReason.None)
                    {
                        num5 = Mathf.Min(num5, (int)buildingData.m_customBuffer1);
                    }
                    if (outgoingTransferReason != TransferManager.TransferReason.None)
                    {
                        num5 = Mathf.Min(num5, num4 - (int)buildingData.m_customBuffer2);
                    }
                    int num6 = Mathf.Max(0, Mathf.Min(num1, (num5 * 200 + num4 - 1) / num4));
                    int a2   = (visitCount * num6 + 9) / 10;
                    if (Singleton <SimulationManager> .instance.m_isNightTime)
                    {
                        a2 = a2 + 1 >> 1;
                    }
                    int num7 = Mathf.Max(0, Mathf.Min(a2, num5));
                    if (incomingTransferReason != TransferManager.TransferReason.None)
                    {
                        buildingData.m_customBuffer1 -= (ushort)num7;
                    }
                    if (outgoingTransferReason != TransferManager.TransferReason.None)
                    {
                        buildingData.m_customBuffer2 += (ushort)num7;
                    }
                    num1 = (num7 + 9) / 10;
                }
                int electricityConsumption;
                int waterConsumption;
                int sewageAccumulation;
                int garbageAccumulation;
                int incomeAccumulation;
                thisAI.GetConsumptionRates(new Randomizer((int)buildingID), num1, out electricityConsumption, out waterConsumption, out sewageAccumulation, out garbageAccumulation, out incomeAccumulation);
                int heatingConsumption = 0;
                if (electricityConsumption != 0 && instance1.IsPolicyLoaded(DistrictPolicies.Policies.ExtraInsulation))
                {
                    if ((policies & DistrictPolicies.Services.ExtraInsulation) != DistrictPolicies.Services.None)
                    {
                        heatingConsumption = Mathf.Max(1, electricityConsumption * 3 + 8 >> 4);
                        incomeAccumulation = incomeAccumulation * 95 / 100;
                    }
                    else
                    {
                        heatingConsumption = Mathf.Max(1, electricityConsumption + 2 >> 2);
                    }
                }
                if (garbageAccumulation != 0 && (policies & DistrictPolicies.Services.Recycling) != DistrictPolicies.Services.None)
                {
                    garbageAccumulation = Mathf.Max(1, garbageAccumulation * 85 / 100);
                    incomeAccumulation  = incomeAccumulation * 95 / 100;
                }
                int taxRate;
                switch (thisAI.m_info.m_class.m_subService)
                {
                case ItemClass.SubService.CommercialLeisure:
                    taxRate = (buildingData.m_flags & Building.Flags.HighDensity) == Building.Flags.None ? Singleton <EconomyManager> .instance.GetTaxRate(ItemClass.Service.Commercial, ItemClass.SubService.CommercialLow, thisAI.m_info.m_class.m_level, taxationPolicies) : Singleton <EconomyManager> .instance.GetTaxRate(ItemClass.Service.Commercial, ItemClass.SubService.CommercialHigh, thisAI.m_info.m_class.m_level, taxationPolicies);

                    if ((taxationPolicies & DistrictPolicies.Taxation.DontTaxLeisure) != DistrictPolicies.Taxation.None)
                    {
                        taxRate = 0;
                    }
                    if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.NoLoudNoises) != DistrictPolicies.CityPlanning.None && Singleton <SimulationManager> .instance.m_isNightTime)
                    {
                        electricityConsumption = electricityConsumption + 1 >> 1;
                        waterConsumption       = waterConsumption + 1 >> 1;
                        sewageAccumulation     = sewageAccumulation + 1 >> 1;
                        garbageAccumulation    = garbageAccumulation + 1 >> 1;
                        incomeAccumulation     = 0;
                        break;
                    }
                    break;

                case ItemClass.SubService.CommercialTourist:
                    taxRate = (buildingData.m_flags & Building.Flags.HighDensity) == Building.Flags.None ? Singleton <EconomyManager> .instance.GetTaxRate(ItemClass.Service.Commercial, ItemClass.SubService.CommercialLow, thisAI.m_info.m_class.m_level, taxationPolicies) : Singleton <EconomyManager> .instance.GetTaxRate(ItemClass.Service.Commercial, ItemClass.SubService.CommercialHigh, thisAI.m_info.m_class.m_level, taxationPolicies);

                    break;

                default:
                    taxRate = Singleton <EconomyManager> .instance.GetTaxRate(thisAI.m_info.m_class, taxationPolicies);

                    break;
                }
                if (num1 != 0)
                {
                    int num5 = HandleCommonConsumption(thisAI, buildingID, ref buildingData, ref frameData, ref electricityConsumption, ref heatingConsumption, ref waterConsumption, ref sewageAccumulation, ref garbageAccumulation, policies);
                    num1 = (num1 * num5 + 99) / 100;
                    if (num1 != 0)
                    {
                        int amount1 = incomeAccumulation;
                        if (amount1 != 0)
                        {
                            if (thisAI.m_info.m_class.m_subService == ItemClass.SubService.CommercialLow)
                            {
                                if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.SmallBusiness) != DistrictPolicies.CityPlanning.None)
                                {
                                    Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.PolicyCost, 12, thisAI.m_info.m_class);

                                    amount1 *= 2;
                                }
                            }
                            else if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.BigBusiness) != DistrictPolicies.CityPlanning.None)
                            {
                                Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.PolicyCost, 25, thisAI.m_info.m_class);

                                amount1 *= 3;
                            }
                            if ((policies & DistrictPolicies.Services.RecreationalUse) != DistrictPolicies.Services.None)
                            {
                                amount1 = (amount1 * 105 + 99) / 100;
                            }
                            int num6 = Singleton <EconomyManager> .instance.AddPrivateIncome(amount1, ItemClass.Service.Commercial, thisAI.m_info.m_class.m_subService, thisAI.m_info.m_class.m_level, taxRate);

                            int amount2 = (behaviour.m_touristCount * num6 + (aliveCount >> 1)) / Mathf.Max(1, aliveCount);
                            int amount3 = Mathf.Max(0, num6 - amount2);
                            if (amount3 != 0)
                            {
                                Singleton <EconomyManager> .instance.AddResource(EconomyManager.Resource.CitizenIncome, amount3, thisAI.m_info.m_class);
                            }
                            if (amount2 != 0)
                            {
                                Singleton <EconomyManager> .instance.AddResource(EconomyManager.Resource.TourismIncome, amount2, thisAI.m_info.m_class);
                            }
                        }
                        int groundPollution;
                        int noisePollution;
                        thisAI.GetPollutionRates(num1, cityPlanningPolicies, out groundPollution, out noisePollution);
                        if (groundPollution != 0 && Singleton <SimulationManager> .instance.m_randomizer.Int32(3U) == 0)
                        {
                            Singleton <NaturalResourceManager> .instance.TryDumpResource(NaturalResourceManager.Resource.Pollution, groundPollution, groundPollution, buildingData.m_position, 60f);
                        }
                        if (noisePollution != 0)
                        {
                            Singleton <ImmaterialResourceManager> .instance.AddResource(ImmaterialResourceManager.Resource.NoisePollution, noisePollution, buildingData.m_position, 60f);
                        }
                        if (num5 < 100)
                        {
                            buildingData.m_flags |= Building.Flags.RateReduced;
                        }
                        else
                        {
                            buildingData.m_flags &= ~Building.Flags.RateReduced;
                        }
                        buildingData.m_flags |= Building.Flags.Active;
                    }
                    else
                    {
                        buildingData.m_flags &= ~(Building.Flags.RateReduced | Building.Flags.Active);
                    }
                }
                else
                {
                    electricityConsumption  = 0;
                    heatingConsumption      = 0;
                    waterConsumption        = 0;
                    sewageAccumulation      = 0;
                    garbageAccumulation     = 0;
                    buildingData.m_problems = Notification.RemoveProblems(buildingData.m_problems, Notification.Problem.Electricity | Notification.Problem.Water | Notification.Problem.Sewage | Notification.Problem.Flood | Notification.Problem.Heating);
                    buildingData.m_flags   &= ~(Building.Flags.RateReduced | Building.Flags.Active);
                }
                int   health    = 0;
                int   wellbeing = 0;
                float radius    = (float)(buildingData.Width + buildingData.Length) * 2.5f;
                if (behaviour.m_healthAccumulation != 0)
                {
                    if (aliveWorkerCount + aliveCount != 0)
                    {
                        health = (behaviour.m_healthAccumulation + (aliveWorkerCount + aliveCount >> 1)) / (aliveWorkerCount + aliveCount);
                    }
                    Singleton <ImmaterialResourceManager> .instance.AddResource(ImmaterialResourceManager.Resource.Health, behaviour.m_healthAccumulation, buildingData.m_position, radius);
                }
                if (behaviour.m_wellbeingAccumulation != 0)
                {
                    if (aliveWorkerCount + aliveCount != 0)
                    {
                        wellbeing = (behaviour.m_wellbeingAccumulation + (aliveWorkerCount + aliveCount >> 1)) / (aliveWorkerCount + aliveCount);
                    }
                    Singleton <ImmaterialResourceManager> .instance.AddResource(ImmaterialResourceManager.Resource.Wellbeing, behaviour.m_wellbeingAccumulation, buildingData.m_position, radius);
                }
                int num8 = Citizen.GetHappiness(health, wellbeing) * 15 / 100;
                int a3   = aliveWorkerCount * 20 / workPlaceCount;
                if ((buildingData.m_problems & Notification.Problem.MajorProblem) == Notification.Problem.None)
                {
                    num8 += 20;
                }
                if (buildingData.m_problems == Notification.Problem.None)
                {
                    num8 += 25;
                }
                int num9  = num8 + Mathf.Min(a3, (int)buildingData.m_customBuffer1 * a3 / num4) + (a3 - Mathf.Min(a3, (int)buildingData.m_customBuffer2 * a3 / num4));
                int num10 = (int)(8 - thisAI.m_info.m_class.m_level);
                int num11 = (int)(11 - thisAI.m_info.m_class.m_level);
                if (thisAI.m_info.m_class.m_subService == ItemClass.SubService.CommercialHigh)
                {
                    ++num10;
                    ++num11;
                }
                if (taxRate < num10)
                {
                    num9 += num10 - taxRate;
                }
                if (taxRate > num11)
                {
                    num9 -= taxRate - num11;
                }
                if (taxRate >= num11 + 4)
                {
                    if ((int)buildingData.m_taxProblemTimer != 0 || Singleton <SimulationManager> .instance.m_randomizer.Int32(32U) == 0)
                    {
                        int num5 = taxRate - num11 >> 2;
                        buildingData.m_taxProblemTimer = (byte)Mathf.Min((int)byte.MaxValue, (int)buildingData.m_taxProblemTimer + num5);
                        if ((int)buildingData.m_taxProblemTimer >= 96)
                        {
                            buildingData.m_problems = Notification.AddProblems(buildingData.m_problems, Notification.Problem.TaxesTooHigh | Notification.Problem.MajorProblem);
                        }
                        else if ((int)buildingData.m_taxProblemTimer >= 32)
                        {
                            buildingData.m_problems = Notification.AddProblems(buildingData.m_problems, Notification.Problem.TaxesTooHigh);
                        }
                    }
                }
                else
                {
                    buildingData.m_taxProblemTimer = (byte)Mathf.Max(0, (int)buildingData.m_taxProblemTimer - 1);
                    buildingData.m_problems        = Notification.RemoveProblems(buildingData.m_problems, Notification.Problem.TaxesTooHigh);
                }
                int entertainment;
                int attractiveness;
                GetAccumulation(thisAI, new Randomizer((int)buildingID), num1, taxRate, cityPlanningPolicies, taxationPolicies, out entertainment, out attractiveness);
                if (entertainment != 0)
                {
                    Singleton <ImmaterialResourceManager> .instance.AddResource(ImmaterialResourceManager.Resource.Entertainment, entertainment, buildingData.m_position, radius);
                }
                if (attractiveness != 0)
                {
                    Singleton <ImmaterialResourceManager> .instance.AddResource(ImmaterialResourceManager.Resource.Attractiveness, attractiveness);
                }
                int happiness = Mathf.Clamp(num9, 0, 100);
                buildingData.m_health       = (byte)health;
                buildingData.m_happiness    = (byte)happiness;
                buildingData.m_citizenCount = (byte)(aliveWorkerCount + aliveCount);
                HandleDead(thisAI, buildingID, ref buildingData, ref behaviour, totalWorkerCount + totalCount);
                int crimeAccumulation = behaviour.m_crimeAccumulation / 10;
                if (thisAI.m_info.m_class.m_subService == ItemClass.SubService.CommercialLeisure)
                {
                    crimeAccumulation = crimeAccumulation * 5 + 3 >> 2;
                }
                if ((policies & DistrictPolicies.Services.RecreationalUse) != DistrictPolicies.Services.None)
                {
                    crimeAccumulation = crimeAccumulation * 3 + 3 >> 2;
                }
                HandleCrime(thisAI, buildingID, ref buildingData, crimeAccumulation, (int)buildingData.m_citizenCount);
                int num12 = (int)buildingData.m_crimeBuffer;
                if (aliveWorkerCount != 0)
                {
                    Singleton <ImmaterialResourceManager> .instance.AddResource(ImmaterialResourceManager.Resource.Density, aliveWorkerCount, buildingData.m_position, radius);

                    int num5 = (behaviour.m_educated0Count * 100 + behaviour.m_educated1Count * 50 + behaviour.m_educated2Count * 30) / aliveWorkerCount + 50;
                    buildingData.m_fireHazard = (byte)num5;
                }
                else
                {
                    buildingData.m_fireHazard = (byte)0;
                }
                int crimeRate = (int)buildingData.m_citizenCount == 0 ? 0 : (num12 + ((int)buildingData.m_citizenCount >> 1)) / (int)buildingData.m_citizenCount;
                int count     = 0;
                int cargo     = 0;
                int capacity  = 0;
                int outside   = 0;
                if (incomingTransferReason != TransferManager.TransferReason.None)
                {
                    CalculateGuestVehicles(thisAI, buildingID, ref buildingData, incomingTransferReason, ref count, ref cargo, ref capacity, ref outside);
                    buildingData.m_tempImport = (byte)Mathf.Clamp(outside, (int)buildingData.m_tempImport, (int)byte.MaxValue);
                }
                buildingData.m_tempExport = (byte)Mathf.Clamp(behaviour.m_touristCount, (int)buildingData.m_tempExport, (int)byte.MaxValue);
                SimulationManager _simulationManager = Singleton <SimulationManager> .instance;
                if ((long)((_simulationManager.m_currentFrameIndex & 3840U) >> 8) == (long)((int)buildingID & 15) && (thisAI.m_info.m_class.m_subService == ItemClass.SubService.CommercialLow || thisAI.m_info.m_class.m_subService == ItemClass.SubService.CommercialHigh) && ((int)Singleton <ZoneManager> .instance.m_lastBuildIndex == (int)_simulationManager.m_currentBuildIndex && (buildingData.m_flags & Building.Flags.Upgrading) == Building.Flags.None))
                {
                    CheckBuildingLevel(thisAI, buildingID, ref buildingData, ref frameData, ref behaviour, aliveCount);
                }
                if ((buildingData.m_flags & (Building.Flags.Completed | Building.Flags.Upgrading)) == Building.Flags.None)
                {
                    return;
                }
                Notification.Problem problems1 = Notification.RemoveProblems(buildingData.m_problems, Notification.Problem.NoCustomers | Notification.Problem.NoGoods);

                //Begin edited section

                if ((int)buildingData.m_customBuffer2 > num4 - (a1 >> 1) && aliveCount <= visitCount >> 1)
                {
                    if (_simulationManager.m_currentDayTimeHour > 19 && _simulationManager.m_currentDayTimeHour < 20)
                    {
                        buildingData.m_outgoingProblemTimer = (byte)Mathf.Min(byte.MaxValue, buildingData.m_outgoingProblemTimer + 1);

                        if (buildingData.m_outgoingProblemTimer >= 192)
                        {
                            problems1 = Notification.AddProblems(problems1, Notification.Problem.NoCustomers | Notification.Problem.MajorProblem);
                        }
                        else if (buildingData.m_outgoingProblemTimer >= 128)
                        {
                            problems1 = Notification.AddProblems(problems1, Notification.Problem.NoCustomers);
                        }
                    }
                    else
                    {
                        buildingData.m_outgoingProblemTimer = 0;
                    }
                }
                else
                {
                    buildingData.m_outgoingProblemTimer = (byte)0;
                }

                if (!CityEventManager.instance.EventStartsWithin(3D) && !CityEventManager.instance.EventTakingPlace() && !CityEventManager.instance.EventJustEnded())
                {
                    if ((int)buildingData.m_customBuffer1 == 0)
                    {
                        buildingData.m_incomingProblemTimer = (byte)Mathf.Min((int)byte.MaxValue, (int)buildingData.m_incomingProblemTimer + 1);
                        problems1 = (int)buildingData.m_incomingProblemTimer >= 64 ? Notification.AddProblems(problems1, Notification.Problem.NoGoods | Notification.Problem.MajorProblem) : Notification.AddProblems(problems1, Notification.Problem.NoGoods);
                    }
                    else
                    {
                        buildingData.m_incomingProblemTimer = (byte)0;
                    }

                    float currentHour = _simulationManager.m_currentDayTimeHour;

                    //Artifically shop at night to keep industry happy. Will give the effect of industry stocking up commercial over night.
                    //Note: ModifyMaterialBuffer is expensive, so if there's any performance impact with the mod now, it'll most likely be this.
                    if ((currentHour > 20f || currentHour < 4f))
                    {
                        if (_simulationManager.m_randomizer.Int32(80) < 2)
                        {
                            //Simulate 2 people buying things
                            int amount = -200;
                            thisAI.ModifyMaterialBuffer(buildingID, ref buildingData, TransferManager.TransferReason.Shopping, ref amount);
                        }
                    }
                    else if (Experiments.ExperimentsToggle.AllowActiveCommercialFix && _simulationManager.m_randomizer.Int32(40) < 5) //Added in as a potential fix to random inactive buildings. Lack of customers still shuts down commercial.
                    {
                        int amount = -50;
                        thisAI.ModifyMaterialBuffer(buildingID, ref buildingData, TransferManager.TransferReason.Shopping, ref amount);
                    }
                }
                else
                {
                    buildingData.m_incomingProblemTimer = 0;
                }

                //End edited section

                buildingData.m_problems = problems1;
                instance1.m_districts.m_buffer[(int)district].AddCommercialData(ref behaviour, health, happiness, crimeRate, workPlaceCount, aliveWorkerCount, Mathf.Max(0, workPlaceCount - totalWorkerCount), visitCount, aliveCount, num3, (int)thisAI.m_info.m_class.m_level, electricityConsumption, heatingConsumption, waterConsumption, sewageAccumulation, garbageAccumulation, incomeAccumulation, Mathf.Min(100, (int)buildingData.m_garbageBuffer / 50), (int)buildingData.m_waterPollution * 100 / (int)byte.MaxValue, (int)buildingData.m_finalImport, (int)buildingData.m_finalExport, thisAI.m_info.m_class.m_subService);
                if ((int)buildingData.m_fireIntensity == 0 && incomingTransferReason != TransferManager.TransferReason.None)
                {
                    int num5 = num4 - (int)buildingData.m_customBuffer1 - capacity - (num2 >> 1);
                    if (num5 >= 0)
                    {
                        Singleton <TransferManager> .instance.AddIncomingOffer(incomingTransferReason, new TransferManager.TransferOffer()
                        {
                            Priority = num5 * 8 / num2,
                            Building = buildingID,
                            Position = buildingData.m_position,
                            Amount   = 1,
                            Active   = false
                        });
                    }
                }
                if ((int)buildingData.m_fireIntensity == 0 && outgoingTransferReason != TransferManager.TransferReason.None)
                {
                    int num5 = (int)buildingData.m_customBuffer2 - aliveCount * 100;
                    if (num5 >= 100 && num3 > 0)
                    {
                        Singleton <TransferManager> .instance.AddOutgoingOffer(outgoingTransferReason, new TransferManager.TransferOffer()
                        {
                            Priority = Mathf.Max(1, num5 * 8 / num4),
                            Building = buildingID,
                            Position = buildingData.m_position,
                            Amount   = Mathf.Min(num5 / 100, num3),
                            Active   = false
                        });
                    }
                }

                PrivateBuildingAI baseAI = thisAI as PrivateBuildingAI; //Because we don't have access to base here.

                if (baseAI != null)
                {
                    NewPrivateBuildingAI.SimulationStepActive(baseAI, buildingID, ref buildingData, ref frameData);
                }

                HandleFire(thisAI, buildingID, ref buildingData, ref frameData, policies);
            }
            else
            {
                Debug.LogError("Commercial building " + buildingID + " has no AI! This could have been bad.");
            }
        }
        private static bool ticketPriceForPrefix(ushort vehicleID, ref Vehicle vehicleData, ref int __result)
        {
            var def = TransportSystemDefinition.from(vehicleData.Info);

            if (def == default(TransportSystemDefinition))
            {
                return(true);
            }

            DistrictManager instance = Singleton <DistrictManager> .instance;
            byte            district = instance.GetDistrict(vehicleData.m_targetPos3);

            DistrictPolicies.Services servicePolicies = instance.m_districts.m_buffer[(int)district].m_servicePolicies;
            DistrictPolicies.Event    @event          = instance.m_districts.m_buffer[(int)district].m_eventPolicies & Singleton <EventManager> .instance.GetEventPolicyMask();

            float multiplier;

            if (vehicleData.Info.m_class.m_subService == ItemClass.SubService.PublicTransportTours)
            {
                multiplier = 1;
            }
            else
            {
                if ((servicePolicies & DistrictPolicies.Services.FreeTransport) != DistrictPolicies.Services.None)
                {
                    __result = 0;
                    return(false);
                }
                if ((@event & DistrictPolicies.Event.ComeOneComeAll) != DistrictPolicies.Event.None)
                {
                    __result = 0;
                    return(false);
                }
                if ((servicePolicies & DistrictPolicies.Services.HighTicketPrices) != DistrictPolicies.Services.None)
                {
                    District[] expr_114_cp_0 = instance.m_districts.m_buffer;
                    byte       expr_114_cp_1 = district;
                    expr_114_cp_0[(int)expr_114_cp_1].m_servicePoliciesEffect = (expr_114_cp_0[(int)expr_114_cp_1].m_servicePoliciesEffect | DistrictPolicies.Services.HighTicketPrices);
                    multiplier = 5f / 4f;
                }
                else
                {
                    multiplier = 1;
                }
            }
            if (vehicleData.m_transportLine == 0)
            {
                __result = (int)(def.GetTransportExtension().GetDefaultTicketPrice(0) * multiplier);
                return(false);
            }
            else
            {
                if (TLMTransportLineExtension.instance.IsUsingCustomConfig(vehicleData.m_transportLine))
                {
                    __result = (int)(TLMTransportLineExtension.instance.GetTicketPrice(vehicleData.m_transportLine) * multiplier);
                }
                else
                {
                    __result = (int)(def.GetTransportExtension().GetTicketPrice(TLMLineUtils.getPrefix(vehicleData.m_transportLine)) * multiplier);
                }
                return(false);
            }
        }
        new int HandleCommonConsumption(ushort buildingID, ref Building data, ref int electricityConsumption, ref int heatingConsumption, ref int waterConsumption, ref int sewageAccumulation, ref int garbageAccumulation, DistrictPolicies.Services policies)
        {
            int             num      = 100;
            DistrictManager instance = Singleton <DistrictManager> .instance;

            Notification.Problem problem = Notification.RemoveProblems(data.m_problems, Notification.Problem.Electricity | Notification.Problem.Water | Notification.Problem.Sewage | Notification.Problem.Flood | Notification.Problem.Heating);
            bool flag             = data.m_electricityProblemTimer != 0;
            bool flag2            = false;
            bool flag3            = false;
            int  electricityUsage = 0;
            int  heatingUsage     = 0;
            int  waterUsage       = 0;
            int  sewageUsage      = 0;

            if (electricityConsumption != 0)
            {
                int num2 = Mathf.RoundToInt((20f - Singleton <WeatherManager> .instance.SampleTemperature(data.m_position, false)) * 8f);
                num2 = Mathf.Clamp(num2, 0, 400);
                int num3 = heatingConsumption;
                heatingConsumption = (num3 * num2 + Singleton <SimulationManager> .instance.m_randomizer.Int32(100u)) / 100;
                if ((policies & DistrictPolicies.Services.PowerSaving) != DistrictPolicies.Services.None)
                {
                    electricityConsumption = Mathf.Max(1, electricityConsumption * 90 / 100);
                    Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.PolicyCost, 32, this.m_info.m_class);
                }
                bool flag4 = false;
                int  num4  = heatingConsumption * 2 - (int)data.m_heatingBuffer;
                if (num4 > 0 && (policies & DistrictPolicies.Services.OnlyElectricity) == DistrictPolicies.Services.None)
                {
                    int num5 = Singleton <WaterManager> .instance.TryFetchHeating(data.m_position, heatingConsumption, num4, out flag4);

                    data.m_heatingBuffer += (ushort)num5;
                }
                if ((int)data.m_heatingBuffer < heatingConsumption)
                {
                    if ((policies & DistrictPolicies.Services.NoElectricity) != DistrictPolicies.Services.None)
                    {
                        flag3 = true;
                        data.m_heatingProblemTimer = (byte)Mathf.Min(255, (int)(data.m_heatingProblemTimer + 1));
                        if (data.m_heatingProblemTimer >= 65)
                        {
                            num     = 0;
                            problem = Notification.AddProblems(problem, Notification.Problem.Heating | Notification.Problem.MajorProblem);
                        }
                        else if (data.m_heatingProblemTimer >= 3)
                        {
                            num    /= 2;
                            problem = Notification.AddProblems(problem, Notification.Problem.Heating);
                        }
                    }
                    else
                    {
                        num2 = ((num2 + 50) * (heatingConsumption - (int)data.m_heatingBuffer) + heatingConsumption - 1) / heatingConsumption;
                        electricityConsumption += (num3 * num2 + Singleton <SimulationManager> .instance.m_randomizer.Int32(100u)) / 100;
                        if (flag4)
                        {
                            flag3 = true;
                            data.m_heatingProblemTimer = (byte)Mathf.Min(255, (int)(data.m_heatingProblemTimer + 1));
                            if (data.m_heatingProblemTimer >= 3)
                            {
                                problem = Notification.AddProblems(problem, Notification.Problem.Heating);
                            }
                        }
                    }
                    heatingUsage         = (int)data.m_heatingBuffer;
                    data.m_heatingBuffer = 0;
                }
                else
                {
                    heatingUsage          = heatingConsumption;
                    data.m_heatingBuffer -= (ushort)heatingConsumption;
                }
                num4 = electricityConsumption * 2 - (int)data.m_electricityBuffer;
                if (num4 > 0)
                {
                    int num6 = Singleton <ElectricityManager> .instance.TryFetchElectricity(data.m_position, electricityConsumption, num4);

                    data.m_electricityBuffer += (ushort)num6;
                }
                if ((int)data.m_electricityBuffer < electricityConsumption)
                {
                    flag2 = true;
                    data.m_electricityProblemTimer = (byte)Mathf.Min(255, (int)(data.m_electricityProblemTimer + 1));
                    if (data.m_electricityProblemTimer >= 65)
                    {
                        num     = 0;
                        problem = Notification.AddProblems(problem, Notification.Problem.Electricity | Notification.Problem.MajorProblem);
                    }
                    else if (data.m_electricityProblemTimer >= 3)
                    {
                        num    /= 2;
                        problem = Notification.AddProblems(problem, Notification.Problem.Electricity);
                    }
                    electricityUsage         = (int)data.m_electricityBuffer;
                    data.m_electricityBuffer = 0;
                    if (Singleton <UnlockManager> .instance.Unlocked(ItemClass.Service.Electricity))
                    {
                        GuideController properties = Singleton <GuideManager> .instance.m_properties;
                        if (properties != null)
                        {
                            int publicServiceIndex      = ItemClass.GetPublicServiceIndex(ItemClass.Service.Electricity);
                            int electricityCapacity     = instance.m_districts.m_buffer[0].GetElectricityCapacity();
                            int electricityConsumption2 = instance.m_districts.m_buffer[0].GetElectricityConsumption();
                            if (electricityCapacity >= electricityConsumption2)
                            {
                                Singleton <GuideManager> .instance.m_serviceNeeded[publicServiceIndex].Activate(properties.m_serviceNeeded2, ItemClass.Service.Electricity);
                            }
                            else
                            {
                                Singleton <GuideManager> .instance.m_serviceNeeded[publicServiceIndex].Activate(properties.m_serviceNeeded, ItemClass.Service.Electricity);
                            }
                        }
                    }
                }
                else
                {
                    electricityUsage          = electricityConsumption;
                    data.m_electricityBuffer -= (ushort)electricityConsumption;
                }
            }
            else
            {
                heatingConsumption = 0;
            }
            if (!flag2)
            {
                data.m_electricityProblemTimer = 0;
            }
            if (flag != flag2)
            {
                Singleton <BuildingManager> .instance.UpdateBuildingColors(buildingID);
            }
            if (!flag3)
            {
                data.m_heatingProblemTimer = 0;
            }
            bool flag5 = false;
            int  num7  = sewageAccumulation;

            if (waterConsumption != 0)
            {
                if ((policies & DistrictPolicies.Services.WaterSaving) != DistrictPolicies.Services.None)
                {
                    waterConsumption = Mathf.Max(1, waterConsumption * 85 / 100);
                    if (sewageAccumulation != 0)
                    {
                        sewageAccumulation = Mathf.Max(1, sewageAccumulation * 85 / 100);
                    }
                    Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.PolicyCost, 32, this.m_info.m_class);
                }
                int num8 = waterConsumption * 2 - (int)data.m_waterBuffer;
                if (num8 > 0)
                {
                    int num9 = Singleton <WaterManager> .instance.TryFetchWater(data.m_position, waterConsumption, num8, ref data.m_waterPollution);

                    data.m_waterBuffer += (ushort)num9;
                }
                if ((int)data.m_waterBuffer < waterConsumption)
                {
                    flag5 = true;
                    data.m_waterProblemTimer = (byte)Mathf.Min(255, (int)(data.m_waterProblemTimer + 1));
                    if (data.m_waterProblemTimer >= 65)
                    {
                        num     = 0;
                        problem = Notification.AddProblems(problem, Notification.Problem.Water | Notification.Problem.MajorProblem);
                    }
                    else if (data.m_waterProblemTimer >= 3)
                    {
                        num    /= 2;
                        problem = Notification.AddProblems(problem, Notification.Problem.Water);
                    }
                    num7               = sewageAccumulation * (waterConsumption + (int)data.m_waterBuffer) / (waterConsumption << 1);
                    waterUsage         = (int)data.m_waterBuffer;
                    data.m_waterBuffer = 0;
                    if (Singleton <UnlockManager> .instance.Unlocked(ItemClass.Service.Water))
                    {
                        GuideController properties2 = Singleton <GuideManager> .instance.m_properties;
                        if (properties2 != null)
                        {
                            int publicServiceIndex2 = ItemClass.GetPublicServiceIndex(ItemClass.Service.Water);
                            int waterCapacity       = instance.m_districts.m_buffer[0].GetWaterCapacity();
                            int waterConsumption2   = instance.m_districts.m_buffer[0].GetWaterConsumption();
                            if (waterCapacity >= waterConsumption2)
                            {
                                Singleton <GuideManager> .instance.m_serviceNeeded[publicServiceIndex2].Activate(properties2.m_serviceNeeded2, ItemClass.Service.Water);
                            }
                            else
                            {
                                Singleton <GuideManager> .instance.m_serviceNeeded[publicServiceIndex2].Activate(properties2.m_serviceNeeded, ItemClass.Service.Water);
                            }
                        }
                    }
                }
                else
                {
                    num7                = sewageAccumulation;
                    waterUsage          = waterConsumption;
                    data.m_waterBuffer -= (ushort)waterConsumption;
                }
            }
            if (num7 != 0)
            {
                int num10 = num7 * 2 - (int)data.m_sewageBuffer;
                if (num10 < num7)
                {
                    if (!flag5 && (data.m_problems & Notification.Problem.Water) == Notification.Problem.None)
                    {
                        flag5 = true;
                        data.m_waterProblemTimer = (byte)Mathf.Min(255, (int)(data.m_waterProblemTimer + 1));
                        if (data.m_waterProblemTimer >= 65)
                        {
                            num     = 0;
                            problem = Notification.AddProblems(problem, Notification.Problem.Sewage | Notification.Problem.MajorProblem);
                        }
                        else if (data.m_waterProblemTimer >= 3)
                        {
                            num    /= 2;
                            problem = Notification.AddProblems(problem, Notification.Problem.Sewage);
                        }
                    }
                    sewageUsage         = num10;
                    data.m_sewageBuffer = (ushort)(num7 * 2);
                }
                else
                {
                    sewageUsage          = num7;
                    data.m_sewageBuffer += (ushort)num7;
                }
            }
            if (!flag5)
            {
                data.m_waterProblemTimer = 0;
            }
            if (garbageAccumulation != 0)
            {
                int num11 = (int)(65535 - data.m_garbageBuffer);
                if (num11 < garbageAccumulation)
                {
                    num = 0;
                    data.m_garbageBuffer = (ushort)num11;
                }
                else
                {
                    //start edit
                    StormDrainAI stormDrainAI = data.Info.m_buildingAI as StormDrainAI;
                    if (stormDrainAI == null)
                    {
                        data.m_garbageBuffer += (ushort)garbageAccumulation;
                    }
                    else if (stormDrainAI.m_filter == false)
                    {
                        data.m_garbageBuffer += (ushort)garbageAccumulation;
                    }
                    else
                    {
                        int pollutantAccumulation = Hydraulics.removePollutants(buildingID, Hydraulics.getPollutants(buildingID));
                        data.m_garbageBuffer += (ushort)pollutantAccumulation;
                        //Debug.Log("[RF]CommonBuildingAI.handleCommonConsumption garbagebuffer = " + data.m_garbageBuffer.ToString());
                    }
                    //end edit
                }
            }
            if (num7 != 0)
            {
                int num12 = Mathf.Min(num7 * 2, (int)data.m_sewageBuffer);
                if (num12 > 0)
                {
                    int num13 = Singleton <WaterManager> .instance.TryDumpSewage(data.m_position, num7 * 2, num12);

                    data.m_sewageBuffer -= (ushort)num13;
                }
            }
            if (garbageAccumulation != 0)
            {
                int num14 = (int)data.m_garbageBuffer;
                if (num14 >= 200 && Singleton <SimulationManager> .instance.m_randomizer.Int32(5u) == 0 && Singleton <UnlockManager> .instance.Unlocked(ItemClass.Service.Garbage))
                {
                    int num15 = 0;
                    int num16 = 0;
                    int num17 = 0;
                    int num18 = 0;
                    this.CalculateGuestVehicles(buildingID, ref data, TransferManager.TransferReason.Garbage, ref num15, ref num16, ref num17, ref num18);
                    num14 -= num17 - num16;
                    if (num14 >= 200)
                    {
                        TransferManager.TransferOffer offer = default(TransferManager.TransferOffer);
                        offer.Priority = num14 / 1000;
                        offer.Building = buildingID;
                        offer.Position = data.m_position;
                        offer.Amount   = 1;
                        Singleton <TransferManager> .instance.AddOutgoingOffer(TransferManager.TransferReason.Garbage, offer);
                    }
                }
            }
            if (this.CanSufferFromFlood())
            {
                float num19 = Singleton <TerrainManager> .instance.WaterLevel(VectorUtils.XZ(data.m_position));

                if (num19 > data.m_position.y)
                {
                    if (num19 > data.m_position.y + (float)ModSettings.BuildingFloodedTolerance / 100f)
                    {
                        //Debug.Log("[RF].CBAId Detoured Flooded Notification");
                        num     = 0;
                        problem = Notification.AddProblems(problem, Notification.Problem.Flood | Notification.Problem.MajorProblem);
                    }
                    else if (num19 > data.m_position.y + (float)ModSettings.BuildingFloodingTolerance / 100f)
                    {
                        //Debug.Log("[RF].CBAId Detoured Flooding Notification");
                        num    /= 2;
                        problem = Notification.AddProblems(problem, Notification.Problem.Flood);
                        GuideController properties3 = Singleton <GuideManager> .instance.m_properties;
                        if (properties3 != null)
                        {
                            Singleton <BuildingManager> .instance.m_buildingFlooded.Activate(properties3.m_buildingFlooded, buildingID);
                        }
                    }
                }
                //Debug.Log("[RF].CBAId Detouring was sucessful!");
            }

            byte district = instance.GetDistrict(data.m_position);

            instance.m_districts.m_buffer[(int)district].AddUsageData(electricityUsage, heatingUsage, waterUsage, sewageUsage);
            data.m_problems = problem;
            return(num);
        }
        // CitizenAI
        public bool CustomStartPathFind(ushort instanceID, ref CitizenInstance citizenData, Vector3 startPos, Vector3 endPos, VehicleInfo vehicleInfo)
        {
            NetInfo.LaneType        laneType    = NetInfo.LaneType.Pedestrian;
            VehicleInfo.VehicleType vehicleType = VehicleInfo.VehicleType.None;
            if (vehicleInfo != null)
            {
                if (vehicleInfo.m_class.m_subService == ItemClass.SubService.PublicTransportTaxi)
                {
                    if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTaxi) == CitizenInstance.Flags.None && Singleton <DistrictManager> .instance.m_districts.m_buffer[0].m_productionData.m_finalTaxiCapacity != 0u)
                    {
                        SimulationManager instance = Singleton <SimulationManager> .instance;
                        if (instance.m_isNightTime || instance.m_randomizer.Int32(2u) == 0)
                        {
                            laneType    |= (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
                            vehicleType |= vehicleInfo.m_vehicleType;
                        }
                    }
                }
                else
                {
                    laneType    |= NetInfo.LaneType.Vehicle;
                    vehicleType |= vehicleInfo.m_vehicleType;
                }
            }
            PathUnit.Position vehiclePosition = default(PathUnit.Position);
            ushort            parkedVehicle   = Singleton <CitizenManager> .instance.m_citizens.m_buffer[(int)((UIntPtr)citizenData.m_citizen)].m_parkedVehicle;

            if (parkedVehicle != 0)
            {
                Vector3 position = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[(int)parkedVehicle].m_position;
                PathManager.FindPathPosition(position, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, false, false, 32f, out vehiclePosition);
            }
            bool allowUnderground = (citizenData.m_flags & (CitizenInstance.Flags.Underground | CitizenInstance.Flags.Transition)) != CitizenInstance.Flags.None;

            PathUnit.Position startPosA;
            PathUnit.Position endPosA;
            if (this.FindPathPosition(instanceID, ref citizenData, startPos, laneType, vehicleType, allowUnderground, out startPosA) &&
                this.FindPathPosition(instanceID, ref citizenData, endPos, laneType, vehicleType, false, out endPosA))
            {
                // NON-STOCK CODE START //
                Citizen.Wealth wealthLevel = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].WealthLevel;

                byte districtId = Singleton <DistrictManager> .instance.GetDistrict(startPos);

                DistrictPolicies.Services servicePolicies = Singleton <DistrictManager> .instance.m_districts.m_buffer[(int)districtId].m_servicePolicies;
                int transportUsageProb = (servicePolicies & DistrictPolicies.Services.FreeTransport) != DistrictPolicies.Services.None ? FREE_TRANSPORT_USAGE_PROBABILITY[(int)wealthLevel] : TRANSPORT_USAGE_PROBABILITY[(int)wealthLevel];

                //bool mayUseTransport = false;
                if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None)                   // STOCK CODE
                {
                    if (vehicleInfo == null || (instanceID % 100) + 1 <= transportUsageProb)
                    {
                        laneType |= NetInfo.LaneType.PublicTransport;                         // STOCK CODE
                        //mayUseTransport = true;
                        //Log._Debug($"CustomCitizenAI: citizen {instanceID} can use public transport");
                    }
                }
                // NON-STOCK CODE END //
                PathUnit.Position position2 = default(PathUnit.Position);
                uint path;
                // NON-STOCK CODE START //
                ExtVehicleType?extVehicleType = null;
                if (vehicleInfo != null)
                {
                    extVehicleType = CustomVehicleAI.DetermineVehicleTypeFromVehicleInfo(vehicleInfo);
                }
                //Log._Debug($"CustomCitizenAI: citizen instance {instanceID}, id {citizenData.m_citizen}. {vehicleType} {extVehicleType} mayUseTransport={mayUseTransport} wealthLevel={wealthLevel}");
                bool res = false;
                if (Options.disableSomething5 || extVehicleType == null)
                {
                    // NON-STOCK CODE END //
                    res = Singleton <CustomPathManager> .instance.CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, position2, endPosA, position2, vehiclePosition, laneType, vehicleType, 20000f, false, false, false, false, false);
                }
                // NON-STOCK CODE START //
                else
                {
                    res = Singleton <CustomPathManager> .instance.CreatePath((ExtVehicleType)extVehicleType, out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, position2, endPosA, position2, vehiclePosition, laneType, vehicleType, 20000f, false, false, false, false);
                }
                // NON-STOCK CODE END //
                if (res)
                {
                    if (citizenData.m_path != 0u)
                    {
                        Singleton <PathManager> .instance.ReleasePath(citizenData.m_path);
                    }
                    citizenData.m_path   = path;
                    citizenData.m_flags |= CitizenInstance.Flags.WaitingPath;
                    return(true);
                }
            }
            return(false);
        }
        new protected int HandleCommonConsumption(ushort buildingID, ref Building data, ref Building.Frame frameData, ref int electricityConsumption, ref int heatingConsumption, ref int waterConsumption, ref int sewageAccumulation, ref int garbageAccumulation, DistrictPolicies.Services policies)
        {
            int             num      = 100;
            DistrictManager instance = Singleton <DistrictManager> .instance;

            Notification.Problem problem = Notification.RemoveProblems(data.m_problems, Notification.Problem.Electricity | Notification.Problem.Water | Notification.Problem.Sewage | Notification.Problem.Flood | Notification.Problem.Heating);
            bool flag             = data.m_electricityProblemTimer != 0;
            bool flag2            = false;
            bool flag3            = false;
            int  electricityUsage = 0;
            int  heatingUsage     = 0;
            int  waterUsage       = 0;
            int  sewageUsage      = 0;

            if (electricityConsumption != 0)
            {
                int num2 = Mathf.RoundToInt((20f - Singleton <WeatherManager> .instance.SampleTemperature(data.m_position, false)) * 8f);
                num2 = Mathf.Clamp(num2, 0, 400);
                int num3 = heatingConsumption;
                heatingConsumption = (num3 * num2 + Singleton <SimulationManager> .instance.m_randomizer.Int32(100u)) / 100;
                if ((policies & DistrictPolicies.Services.PowerSaving) != DistrictPolicies.Services.None)
                {
                    electricityConsumption = Mathf.Max(1, electricityConsumption * 90 / 100);
                    Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.PolicyCost, 32, this.m_info.m_class);
                }
                bool flag4 = false;
                int  num4  = heatingConsumption * 2 - (int)data.m_heatingBuffer;
                if (num4 > 0 && (policies & DistrictPolicies.Services.OnlyElectricity) == DistrictPolicies.Services.None)
                {
                    int num5 = Singleton <WaterManager> .instance.TryFetchHeating(data.m_position, heatingConsumption, num4, out flag4);

                    data.m_heatingBuffer += (ushort)num5;
                }
                if ((int)data.m_heatingBuffer < heatingConsumption)
                {
                    if ((policies & DistrictPolicies.Services.NoElectricity) != DistrictPolicies.Services.None)
                    {
                        flag3 = true;
                        data.m_heatingProblemTimer = (byte)Mathf.Min(255, (int)(data.m_heatingProblemTimer + 1));
                        if (data.m_heatingProblemTimer >= 65)
                        {
                            num     = 0;
                            problem = Notification.AddProblems(problem, Notification.Problem.Heating | Notification.Problem.MajorProblem);
                        }
                        else if (data.m_heatingProblemTimer >= 3)
                        {
                            num    /= 2;
                            problem = Notification.AddProblems(problem, Notification.Problem.Heating);
                        }
                    }
                    else
                    {
                        num2 = ((num2 + 50) * (heatingConsumption - (int)data.m_heatingBuffer) + heatingConsumption - 1) / heatingConsumption;
                        electricityConsumption += (num3 * num2 + Singleton <SimulationManager> .instance.m_randomizer.Int32(100u)) / 100;
                        if (flag4)
                        {
                            flag3 = true;
                            data.m_heatingProblemTimer = (byte)Mathf.Min(255, (int)(data.m_heatingProblemTimer + 1));
                            if (data.m_heatingProblemTimer >= 3)
                            {
                                problem = Notification.AddProblems(problem, Notification.Problem.Heating);
                            }
                        }
                    }
                    heatingUsage         = (int)data.m_heatingBuffer;
                    data.m_heatingBuffer = 0;
                }
                else
                {
                    heatingUsage          = heatingConsumption;
                    data.m_heatingBuffer -= (ushort)heatingConsumption;
                }
                int num6;
                int a;
                if (this.CanStockpileElectricity(buildingID, ref data, out num6, out a))
                {
                    num4 = num6 + electricityConsumption * 2 - (int)data.m_electricityBuffer;
                    if (num4 > 0)
                    {
                        int num7 = electricityConsumption;
                        if ((int)data.m_electricityBuffer < num6)
                        {
                            num7 += Mathf.Min(a, num6 - (int)data.m_electricityBuffer);
                        }
                        int num8 = Singleton <ElectricityManager> .instance.TryFetchElectricity(data.m_position, num7, num4);

                        data.m_electricityBuffer += (ushort)num8;
                        if (num8 < num4 && num8 < num7)
                        {
                            flag2   = true;
                            problem = Notification.AddProblems(problem, Notification.Problem.Electricity);
                            if (data.m_electricityProblemTimer < 64)
                            {
                                data.m_electricityProblemTimer = 64;
                            }
                        }
                    }
                }
                else
                {
                    num4 = electricityConsumption * 2 - (int)data.m_electricityBuffer;
                    if (num4 > 0)
                    {
                        int num9 = Singleton <ElectricityManager> .instance.TryFetchElectricity(data.m_position, electricityConsumption, num4);

                        data.m_electricityBuffer += (ushort)num9;
                    }
                }
                if ((int)data.m_electricityBuffer < electricityConsumption)
                {
                    flag2 = true;
                    data.m_electricityProblemTimer = (byte)Mathf.Min(255, (int)(data.m_electricityProblemTimer + 1));
                    if (data.m_electricityProblemTimer >= 65)
                    {
                        num     = 0;
                        problem = Notification.AddProblems(problem, Notification.Problem.Electricity | Notification.Problem.MajorProblem);
                    }
                    else if (data.m_electricityProblemTimer >= 3)
                    {
                        num    /= 2;
                        problem = Notification.AddProblems(problem, Notification.Problem.Electricity);
                    }
                    electricityUsage         = (int)data.m_electricityBuffer;
                    data.m_electricityBuffer = 0;
                    if (Singleton <UnlockManager> .instance.Unlocked(ItemClass.Service.Electricity))
                    {
                        GuideController properties = Singleton <GuideManager> .instance.m_properties;
                        if (properties != null)
                        {
                            int publicServiceIndex      = ItemClass.GetPublicServiceIndex(ItemClass.Service.Electricity);
                            int electricityCapacity     = instance.m_districts.m_buffer[0].GetElectricityCapacity();
                            int electricityConsumption2 = instance.m_districts.m_buffer[0].GetElectricityConsumption();
                            if (electricityCapacity >= electricityConsumption2)
                            {
                                Singleton <GuideManager> .instance.m_serviceNeeded[publicServiceIndex].Activate(properties.m_serviceNeeded2, ItemClass.Service.Electricity);
                            }
                            else
                            {
                                Singleton <GuideManager> .instance.m_serviceNeeded[publicServiceIndex].Activate(properties.m_serviceNeeded, ItemClass.Service.Electricity);
                            }
                        }
                    }
                }
                else
                {
                    electricityUsage          = electricityConsumption;
                    data.m_electricityBuffer -= (ushort)electricityConsumption;
                }
            }
            else
            {
                heatingConsumption = 0;
            }
            if (!flag2)
            {
                data.m_electricityProblemTimer = 0;
            }
            if (flag != flag2)
            {
                Singleton <BuildingManager> .instance.UpdateBuildingColors(buildingID);
            }
            if (!flag3)
            {
                data.m_heatingProblemTimer = 0;
            }
            bool flag5 = false;
            int  num10 = sewageAccumulation;

            if (waterConsumption != 0)
            {
                if ((policies & DistrictPolicies.Services.WaterSaving) != DistrictPolicies.Services.None)
                {
                    waterConsumption = Mathf.Max(1, waterConsumption * 85 / 100);
                    if (sewageAccumulation != 0)
                    {
                        sewageAccumulation = Mathf.Max(1, sewageAccumulation * 85 / 100);
                    }
                    Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.PolicyCost, 32, this.m_info.m_class);
                }
                int num11;
                int a2;
                if (this.CanStockpileWater(buildingID, ref data, out num11, out a2))
                {
                    int num12 = num11 + waterConsumption * 2 - (int)data.m_waterBuffer;
                    if (num12 > 0)
                    {
                        int num13 = waterConsumption;
                        if ((int)data.m_waterBuffer < num11)
                        {
                            num13 += Mathf.Min(a2, num11 - (int)data.m_waterBuffer);
                        }
                        int num14 = Singleton <WaterManager> .instance.TryFetchWater(data.m_position, num13, num12, ref data.m_waterPollution);

                        data.m_waterBuffer += (ushort)num14;
                        if (num14 < num12 && num14 < num13)
                        {
                            flag5   = true;
                            problem = Notification.AddProblems(problem, Notification.Problem.Water);
                            if (data.m_waterProblemTimer < 64)
                            {
                                data.m_waterProblemTimer = 64;
                            }
                        }
                    }
                }
                else
                {
                    int num15 = waterConsumption * 2 - (int)data.m_waterBuffer;
                    if (num15 > 0)
                    {
                        int num16 = Singleton <WaterManager> .instance.TryFetchWater(data.m_position, waterConsumption, num15, ref data.m_waterPollution);

                        data.m_waterBuffer += (ushort)num16;
                    }
                }
                if ((int)data.m_waterBuffer < waterConsumption)
                {
                    flag5 = true;
                    data.m_waterProblemTimer = (byte)Mathf.Min(255, (int)(data.m_waterProblemTimer + 1));
                    if (data.m_waterProblemTimer >= 65)
                    {
                        num     = 0;
                        problem = Notification.AddProblems(problem, Notification.Problem.Water | Notification.Problem.MajorProblem);
                    }
                    else if (data.m_waterProblemTimer >= 3)
                    {
                        num    /= 2;
                        problem = Notification.AddProblems(problem, Notification.Problem.Water);
                    }
                    num10              = sewageAccumulation * (waterConsumption + (int)data.m_waterBuffer) / (waterConsumption << 1);
                    waterUsage         = (int)data.m_waterBuffer;
                    data.m_waterBuffer = 0;
                    if (Singleton <UnlockManager> .instance.Unlocked(ItemClass.Service.Water))
                    {
                        GuideController properties2 = Singleton <GuideManager> .instance.m_properties;
                        if (properties2 != null)
                        {
                            int publicServiceIndex2 = ItemClass.GetPublicServiceIndex(ItemClass.Service.Water);
                            int waterCapacity       = instance.m_districts.m_buffer[0].GetWaterCapacity();
                            int waterConsumption2   = instance.m_districts.m_buffer[0].GetWaterConsumption();
                            if (waterCapacity >= waterConsumption2)
                            {
                                Singleton <GuideManager> .instance.m_serviceNeeded[publicServiceIndex2].Activate(properties2.m_serviceNeeded2, ItemClass.Service.Water);
                            }
                            else
                            {
                                Singleton <GuideManager> .instance.m_serviceNeeded[publicServiceIndex2].Activate(properties2.m_serviceNeeded, ItemClass.Service.Water);
                            }
                        }
                    }
                }
                else
                {
                    num10               = sewageAccumulation;
                    waterUsage          = waterConsumption;
                    data.m_waterBuffer -= (ushort)waterConsumption;
                }
            }
            int num17;
            int b;

            if (this.CanStockpileWater(buildingID, ref data, out num17, out b))
            {
                int num18 = Mathf.Max(0, num17 + num10 * 2 - (int)data.m_sewageBuffer);
                if (num18 < num10)
                {
                    if (!flag5 && (data.m_problems & Notification.Problem.Water) == Notification.Problem.None)
                    {
                        flag5 = true;
                        data.m_waterProblemTimer = (byte)Mathf.Min(255, (int)(data.m_waterProblemTimer + 1));
                        if (data.m_waterProblemTimer >= 65)
                        {
                            num     = 0;
                            problem = Notification.AddProblems(problem, Notification.Problem.Sewage | Notification.Problem.MajorProblem);
                        }
                        else if (data.m_waterProblemTimer >= 3)
                        {
                            num    /= 2;
                            problem = Notification.AddProblems(problem, Notification.Problem.Sewage);
                        }
                    }
                    sewageUsage         = num18;
                    data.m_sewageBuffer = (ushort)(num17 + num10 * 2);
                }
                else
                {
                    sewageUsage          = num10;
                    data.m_sewageBuffer += (ushort)num10;
                }
                int num19 = num10 + Mathf.Max(num10, b);
                num18 = Mathf.Min(num19, (int)data.m_sewageBuffer);
                if (num18 > 0)
                {
                    int num20 = Singleton <WaterManager> .instance.TryDumpSewage(data.m_position, num19, num18);

                    data.m_sewageBuffer -= (ushort)num20;
                    if (num20 < num19 && num20 < num18 && !flag5 && (data.m_problems & Notification.Problem.Water) == Notification.Problem.None)
                    {
                        flag5   = true;
                        problem = Notification.AddProblems(problem, Notification.Problem.Sewage);
                        if (data.m_waterProblemTimer < 64)
                        {
                            data.m_waterProblemTimer = 64;
                        }
                    }
                }
            }
            else if (num10 != 0)
            {
                int num21 = Mathf.Max(0, num10 * 2 - (int)data.m_sewageBuffer);
                if (num21 < num10)
                {
                    if (!flag5 && (data.m_problems & Notification.Problem.Water) == Notification.Problem.None)
                    {
                        flag5 = true;
                        data.m_waterProblemTimer = (byte)Mathf.Min(255, (int)(data.m_waterProblemTimer + 1));
                        if (data.m_waterProblemTimer >= 65)
                        {
                            num     = 0;
                            problem = Notification.AddProblems(problem, Notification.Problem.Sewage | Notification.Problem.MajorProblem);
                        }
                        else if (data.m_waterProblemTimer >= 3)
                        {
                            num    /= 2;
                            problem = Notification.AddProblems(problem, Notification.Problem.Sewage);
                        }
                    }
                    sewageUsage         = num21;
                    data.m_sewageBuffer = (ushort)(num10 * 2);
                }
                else
                {
                    sewageUsage          = num10;
                    data.m_sewageBuffer += (ushort)num10;
                }
                num21 = Mathf.Min(num10 * 2, (int)data.m_sewageBuffer);
                if (num21 > 0)
                {
                    int num22 = Singleton <WaterManager> .instance.TryDumpSewage(data.m_position, num10 * 2, num21);

                    data.m_sewageBuffer -= (ushort)num22;
                }
            }
            if (!flag5)
            {
                data.m_waterProblemTimer = 0;
            }
            if (garbageAccumulation != 0)
            {
                int num23 = (int)(65535 - data.m_garbageBuffer);
                if (num23 < garbageAccumulation)
                {
                    num = 0;
                    data.m_garbageBuffer = (ushort)num23;
                }
                else
                {
                    //start edit
                    StormDrainAI stormDrainAI = data.Info.m_buildingAI as StormDrainAI;
                    if (stormDrainAI == null)
                    {
                        data.m_garbageBuffer += (ushort)garbageAccumulation;
                    }
                    else if (stormDrainAI.m_filter == false)
                    {
                        data.m_garbageBuffer += (ushort)garbageAccumulation;
                    }
                    else
                    {
                        int pollutantAccumulation = Hydraulics.removePollutants(buildingID, Hydraulics.getPollutants(buildingID));
                        data.m_garbageBuffer += (ushort)pollutantAccumulation;
                        //Debug.Log("[RF]CommonBuildingAI.handleCommonConsumption garbagebuffer = " + data.m_garbageBuffer.ToString());
                    }
                    //end edit
                }
            }
            if (garbageAccumulation != 0)
            {
                int num24 = (int)data.m_garbageBuffer;
                if (num24 >= 200 && Singleton <SimulationManager> .instance.m_randomizer.Int32(5u) == 0 && Singleton <UnlockManager> .instance.Unlocked(ItemClass.Service.Garbage))
                {
                    int num25 = 0;
                    int num26 = 0;
                    int num27 = 0;
                    int num28 = 0;
                    this.CalculateGuestVehicles(buildingID, ref data, TransferManager.TransferReason.Garbage, ref num25, ref num26, ref num27, ref num28);
                    num24 -= num27 - num26;
                    if (num24 >= 200)
                    {
                        TransferManager.TransferOffer offer = default(TransferManager.TransferOffer);
                        offer.Priority = num24 / 1000;
                        offer.Building = buildingID;
                        offer.Position = data.m_position;
                        offer.Amount   = 1;
                        Singleton <TransferManager> .instance.AddOutgoingOffer(TransferManager.TransferReason.Garbage, offer);
                    }
                }
            }
            bool flag6;

            if (this.CanSufferFromFlood(out flag6))
            {
                float num29 = Singleton <TerrainManager> .instance.WaterLevel(VectorUtils.XZ(data.m_position));

                if (num29 > data.m_position.y)
                {
                    bool flag7 = num29 > data.m_position.y + Mathf.Max(4f, this.m_info.m_collisionHeight);
                    if ((!flag6 || flag7) && (data.m_flags & Building.Flags.Flooded) == Building.Flags.None && data.m_fireIntensity == 0)
                    {
                        DisasterManager instance2 = Singleton <DisasterManager> .instance;
                        ushort          num30     = instance2.FindDisaster <FloodBaseAI>(data.m_position);
                        if (num30 == 0)
                        {
                            DisasterInfo disasterInfo = DisasterManager.FindDisasterInfo <GenericFloodAI>();
                            if (disasterInfo != null && instance2.CreateDisaster(out num30, disasterInfo))
                            {
                                instance2.m_disasters.m_buffer[(int)num30].m_intensity      = 10;
                                instance2.m_disasters.m_buffer[(int)num30].m_targetPosition = data.m_position;
                                disasterInfo.m_disasterAI.StartNow(num30, ref instance2.m_disasters.m_buffer[(int)num30]);
                            }
                        }
                        if (num30 != 0)
                        {
                            InstanceID srcID = default(InstanceID);
                            InstanceID dstID = default(InstanceID);
                            srcID.Disaster = num30;
                            dstID.Building = buildingID;
                            Singleton <InstanceManager> .instance.CopyGroup(srcID, dstID);

                            DisasterInfo info = instance2.m_disasters.m_buffer[(int)num30].Info;
                            info.m_disasterAI.ActivateNow(num30, ref instance2.m_disasters.m_buffer[(int)num30]);
                            if ((instance2.m_disasters.m_buffer[(int)num30].m_flags & DisasterData.Flags.Significant) != DisasterData.Flags.None)
                            {
                                instance2.DetectDisaster(num30, false);
                                instance2.FollowDisaster(num30);
                            }
                        }
                        data.m_flags |= Building.Flags.Flooded;
                    }
                    if (flag7)
                    {
                        frameData.m_constructState = (byte)Mathf.Max(0, (int)frameData.m_constructState - 1088 / this.GetCollapseTime());
                        data.SetFrameData(Singleton <SimulationManager> .instance.m_currentFrameIndex, frameData);
                        InstanceID id = default(InstanceID);
                        id.Building = buildingID;
                        InstanceManager.Group group = Singleton <InstanceManager> .instance.GetGroup(id);

                        if (group != null)
                        {
                            ushort disaster = group.m_ownerInstance.Disaster;
                            if (disaster != 0)
                            {
                                DisasterData[] expr_D18_cp_0 = Singleton <DisasterManager> .instance.m_disasters.m_buffer;
                                ushort         expr_D18_cp_1 = disaster;
                                expr_D18_cp_0[(int)expr_D18_cp_1].m_collapsedCount = (ushort)(expr_D18_cp_0[(int)expr_D18_cp_1].m_collapsedCount + 1);
                            }
                        }
                        if (frameData.m_constructState == 0)
                        {
                            Singleton <InstanceManager> .instance.SetGroup(id, null);
                        }
                        data.m_levelUpProgress = 0;
                        data.m_fireIntensity   = 0;
                        data.m_garbageBuffer   = 0;
                        data.m_flags          |= Building.Flags.Collapsed;
                        num = 0;
                        this.RemovePeople(buildingID, ref data, 90);
                        this.BuildingDeactivated(buildingID, ref data);
                        if (this.m_info.m_hasParkingSpaces != VehicleInfo.VehicleType.None)
                        {
                            Singleton <BuildingManager> .instance.UpdateParkingSpaces(buildingID, ref data);
                        }
                        Singleton <BuildingManager> .instance.UpdateBuildingRenderer(buildingID, true);

                        Singleton <BuildingManager> .instance.UpdateBuildingColors(buildingID);

                        GuideController properties3 = Singleton <GuideManager> .instance.m_properties;
                        if (properties3 != null)
                        {
                            Singleton <BuildingManager> .instance.m_buildingFlooded.Deactivate(buildingID, false);

                            Singleton <BuildingManager> .instance.m_buildingFlooded2.Deactivate(buildingID, false);
                        }
                    }
                    else if (!flag6)
                    {
                        if ((data.m_flags & Building.Flags.RoadAccessFailed) == Building.Flags.None)
                        {
                            int num31 = 0;
                            int num32 = 0;
                            int num33 = 0;
                            int num34 = 0;
                            this.CalculateGuestVehicles(buildingID, ref data, TransferManager.TransferReason.FloodWater, ref num31, ref num32, ref num33, ref num34);
                            if (num31 == 0)
                            {
                                TransferManager.TransferOffer offer2 = default(TransferManager.TransferOffer);
                                offer2.Priority = 5;
                                offer2.Building = buildingID;
                                offer2.Position = data.m_position;
                                offer2.Amount   = 1;
                                Singleton <TransferManager> .instance.AddOutgoingOffer(TransferManager.TransferReason.FloodWater, offer2);
                            }
                        }
                        if (num29 > data.m_position.y + (float)ModSettings.BuildingFloodedTolerance / 100f)
                        {
                            num     = 0;
                            problem = Notification.AddProblems(problem, Notification.Problem.Flood | Notification.Problem.MajorProblem);
                        }
                        else if (num29 > data.m_position.y + (float)ModSettings.BuildingFloodingTolerance / 100f)
                        {
                            num    /= 2;
                            problem = Notification.AddProblems(problem, Notification.Problem.Flood);
                        }
                        GuideController properties4 = Singleton <GuideManager> .instance.m_properties;
                        if (properties4 != null)
                        {
                            if (Singleton <LoadingManager> .instance.SupportsExpansion(Expansion.NaturalDisasters) && Singleton <UnlockManager> .instance.Unlocked(UnlockManager.Feature.WaterPumping))
                            {
                                Singleton <BuildingManager> .instance.m_buildingFlooded2.Activate(properties4.m_buildingFlooded2, buildingID);
                            }
                            else
                            {
                                Singleton <BuildingManager> .instance.m_buildingFlooded.Activate(properties4.m_buildingFlooded, buildingID);
                            }
                        }
                    }
                }
                else if ((data.m_flags & Building.Flags.Flooded) != Building.Flags.None)
                {
                    InstanceID id2 = default(InstanceID);
                    id2.Building = buildingID;
                    Singleton <InstanceManager> .instance.SetGroup(id2, null);

                    data.m_flags &= ~Building.Flags.Flooded;
                }
            }
            byte district = instance.GetDistrict(data.m_position);

            instance.m_districts.m_buffer[(int)district].AddUsageData(electricityUsage, heatingUsage, waterUsage, sewageUsage);
            data.m_problems = problem;
            return(num);
        }
Exemple #12
0
        protected override void ProduceGoods(ushort buildingID, ref Building buildingData, ref Building.Frame frameData, int productionRate, int finalProductionRate, ref Citizen.BehaviourData behaviour, int aliveWorkerCount, int totalWorkerCount, int workPlaceCount, int aliveVisitorCount, int totalVisitorCount, int visitPlaceCount)
        {
            DistrictManager instance = Singleton <DistrictManager> .instance;
            byte            district = instance.GetDistrict(buildingData.m_position);

            DistrictPolicies.Services servicePolicies = instance.m_districts.m_buffer[(int)district].m_servicePolicies;
            Notification.Problem      problem         = Notification.RemoveProblems(buildingData.m_problems, Notification.Problem.WaterNotConnected | Notification.Problem.NoResources | Notification.Problem.NoNaturalResources | Notification.Problem.FishFarmWaterDirty | Notification.Problem.NoPlaceForFishingGoods);
            int num  = 0;
            int num2 = 0;
            int num3 = 0;

            if (this.m_extractionPositions != null && this.m_extractionPositions.Length > 0)
            {
                for (int i = 0; i < this.m_extractionPositions.Length; i++)
                {
                    Vector3 position = buildingData.CalculatePosition(this.m_extractionPositions[i]);
                    int     b;
                    int     num4;
                    int     value;
                    Singleton <TerrainManager> .instance.CountWaterCoverage(position, 20f, out b, out num4, out value);

                    num += Mathf.Clamp(value, 0, 128);
                    num3 = Mathf.Max(num3, b);
                }
                if (this.m_info.name == "Algae Tank")
                {
                    this.m_info.m_placementMode = BuildingInfo.PlacementMode.Roadside;
                    num2 = 0;
                    num3 = 1;
                }
                else
                {
                    num2 = num / this.m_extractionPositions.Length;
                }
            }
            else
            {
                finalProductionRate = 0;
            }
            if (num2 > 32)
            {
                GuideController properties = Singleton <GuideManager> .instance.m_properties;
                if (properties != null)
                {
                    Singleton <BuildingManager> .instance.m_fishingPollutionDetected.Activate(properties.m_fishingPollutionDetected, buildingID);
                }
            }
            if (num3 == 0)
            {
                finalProductionRate = 0;
            }
            if (finalProductionRate != 0)
            {
                int num5 = finalProductionRate;
                if (num2 > 96)
                {
                    problem = (Notification.Problem.FishFarmWaterDirty | Notification.Problem.FatalProblem);
                }
                else if (num2 > 64)
                {
                    problem = Notification.AddProblems(problem, Notification.Problem.FishFarmWaterDirty | Notification.Problem.MajorProblem);
                }
                else if (num2 > 32)
                {
                    problem = Notification.AddProblems(problem, Notification.Problem.FishFarmWaterDirty);
                }
                finalProductionRate = finalProductionRate * Mathf.Clamp(255 - num2 * 2, 0, 255) / 255;
                int num6 = finalProductionRate * this.m_noiseAccumulation / 100;
                if (num6 != 0)
                {
                    Singleton <ImmaterialResourceManager> .instance.AddResource(ImmaterialResourceManager.Resource.NoisePollution, num6, buildingData.m_position, this.m_noiseRadius);
                }
                base.HandleDead(buildingID, ref buildingData, ref behaviour, totalWorkerCount);
                int num7 = 0;
                int num8 = 0;
                if (this.m_outputResource != TransferManager.TransferReason.None)
                {
                    int num9 = (this.m_productionRate * finalProductionRate + 99) / 100;
                    if (this.m_info.m_class.m_level == ItemClass.Level.Level3 && (servicePolicies & DistrictPolicies.Services.AlgaeBasedWaterFiltering) != DistrictPolicies.Services.None)
                    {
                        District[] buffer = instance.m_districts.m_buffer;
                        byte       b2     = district;
                        buffer[(int)b2].m_servicePoliciesEffect = (buffer[(int)b2].m_servicePoliciesEffect | DistrictPolicies.Services.AlgaeBasedWaterFiltering);
                        num9 = (num9 * 50 + 49) / 100;
                    }
                    int cycleBufferSize = this.GetCycleBufferSize(buildingID, ref buildingData);
                    int num10           = (int)buildingData.m_customBuffer1;
                    num7 = this.GetStorageBufferSize(buildingID, ref buildingData);
                    num8 = (int)(buildingData.m_customBuffer2 * 100);
                    if (num9 >= cycleBufferSize - num10)
                    {
                        if (cycleBufferSize > num7 - num8)
                        {
                            num9    = cycleBufferSize - num10;
                            num10   = cycleBufferSize;
                            problem = Notification.AddProblems(problem, Notification.Problem.NoPlaceForFishingGoods);
                        }
                        else
                        {
                            num10 = num10 + num9 - cycleBufferSize;
                            num8 += cycleBufferSize;
                        }
                    }
                    else
                    {
                        num10 += num9;
                    }
                    Singleton <StatisticsManager> .instance.Acquire <StatisticInt64>(StatisticType.FishFarmed).Add(num9);

                    buildingData.m_customBuffer1 = (ushort)num10;
                    buildingData.m_customBuffer2 = (ushort)(num8 / 100);
                }
                if (this.m_outputResource != TransferManager.TransferReason.None)
                {
                    int num11  = (num5 * this.m_outputVehicleCount + 99) / 100;
                    int num12  = 0;
                    int num13  = 0;
                    int num14  = 0;
                    int value2 = 0;
                    base.CalculateOwnVehicles(buildingID, ref buildingData, this.m_outputResource, ref num12, ref num13, ref num14, ref value2);
                    buildingData.m_tempExport = (byte)Mathf.Clamp(value2, (int)buildingData.m_tempExport, 255);
                    if (buildingData.m_finalExport != 0)
                    {
                        District[] buffer2 = instance.m_districts.m_buffer;
                        byte       b3      = district;
                        buffer2[(int)b3].m_playerConsumption.m_finalExportAmount = buffer2[(int)b3].m_playerConsumption.m_finalExportAmount + (uint)buildingData.m_finalExport;
                    }
                    int num15 = num8;
                    if (num15 >= 8000 && num12 < num11)
                    {
                        TransferManager.TransferOffer offer = default(TransferManager.TransferOffer);
                        offer.Priority = Mathf.Max(1, num15 * 8 / num7);
                        offer.Building = buildingID;
                        offer.Position = buildingData.m_position;
                        offer.Amount   = 1;
                        offer.Active   = true;
                        Singleton <TransferManager> .instance.AddOutgoingOffer(this.m_outputResource, offer);
                    }
                }
            }
            buildingData.m_problems   = problem;
            buildingData.m_education3 = (byte)Mathf.Clamp(finalProductionRate * this.m_productionRate / Mathf.Max(1, this.m_productionRate), 0, 255);
            base.ProduceGoods(buildingID, ref buildingData, ref frameData, productionRate, finalProductionRate, ref behaviour, aliveWorkerCount, totalWorkerCount, workPlaceCount, aliveVisitorCount, totalVisitorCount, visitPlaceCount);
        }
        // CitizenAI
        public bool CustomStartPathFind(ushort instanceID, ref CitizenInstance citizenData, Vector3 startPos, Vector3 endPos, VehicleInfo vehicleInfo)
        {
            CitizenManager citMan = Singleton <CitizenManager> .instance;

            if (citMan.m_citizens.m_buffer[citizenData.m_citizen].CurrentLocation == Citizen.Location.Home)
            {
                currentTransportMode[instanceID] = TransportMode.None;                 // reset currently used transport mode at home
            }
            SimulationManager simManager = Singleton <SimulationManager> .instance;

            Citizen.Wealth wealthLevel  = citMan.m_citizens.m_buffer[citizenData.m_citizen].WealthLevel;
            bool           couldUseTaxi = false;   // could cim use a taxi if it was not forbidden because of randomization?
            bool           couldUseCar  = false;
            bool           couldUseBike = false;
            bool           wouldAffordTaxiVoluntarily = false;

            bool randomParking = false;

            if (vehicleInfo != null)
            {
                if (vehicleInfo.m_class.m_subService == ItemClass.SubService.PublicTransportTaxi)
                {
                    if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTaxi) == CitizenInstance.Flags.None &&
                        Singleton <DistrictManager> .instance.m_districts.m_buffer[0].m_productionData.m_finalTaxiCapacity != 0u)
                    {
                        couldUseTaxi = true;

                        if (currentTransportMode[instanceID] == TransportMode.Taxi || (currentTransportMode[instanceID] == TransportMode.None &&
                                                                                       ((simManager.m_isNightTime && simManager.m_randomizer.Int32(100) < NIGHT_TAXI_USAGE_PROBABILITY[(int)wealthLevel]) ||
                                                                                        (!simManager.m_isNightTime && simManager.m_randomizer.Int32(100) < DAY_TAXI_USAGE_PROBABILITY[(int)wealthLevel]))))
                        {
                            wouldAffordTaxiVoluntarily = true;                             // NON-STOCK CODE
                        }
                    }
                }
                else
                {
                    // NON-STOCK CODE START
                    if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Bicycle)
                    {
                        couldUseBike = true;
                    }
                    else if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Car)
                    {
                        couldUseCar = true;
                    }
                    // NON-STOCK CODE END

                    if (citizenData.m_targetBuilding != 0 && Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)citizenData.m_targetBuilding].Info.m_class.m_service > ItemClass.Service.Office)
                    {
                        randomParking = true;
                    }
                }
            }

            byte districtId = Singleton <DistrictManager> .instance.GetDistrict(startPos);

            DistrictPolicies.Services servicePolicies = Singleton <DistrictManager> .instance.m_districts.m_buffer[(int)districtId].m_servicePolicies;
            int transportUsageProb = (servicePolicies & DistrictPolicies.Services.FreeTransport) != DistrictPolicies.Services.None ? FREE_TRANSPORT_USAGE_PROBABILITY[(int)wealthLevel] : TRANSPORT_USAGE_PROBABILITY[(int)wealthLevel];

            bool useTaxi            = false;
            bool useBike            = false;
            bool useCar             = false;
            bool usePublicTransport = false;

            if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None)               // STOCK CODE
            {
                if (currentTransportMode[instanceID] == TransportMode.PublicTransport || useTaxi ||
                    (currentTransportMode[instanceID] == TransportMode.None && simManager.m_randomizer.Int32(100) < transportUsageProb))
                {
                    usePublicTransport = true;
                }
            }

            ushort parkedVehicle     = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].m_parkedVehicle;
            bool   couldUseParkedCar = false;           // cims are not allowed to use pocket cars (unless we have no choice)

            PathUnit.Position vehiclePosition = default(PathUnit.Position);
            if (parkedVehicle != 0)
            {
                Vector3 position = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[(int)parkedVehicle].m_position;
                if (PathManager.FindPathPosition(position, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, false, false, 32f, out vehiclePosition))
                {
                    couldUseParkedCar = true;
                }
            }

            if (couldUseBike)
            {
                // everyone who has a bike may use it
                useBike = true;
            }

            if (!usePublicTransport)
            {
                if (couldUseParkedCar && currentTransportMode[instanceID] == TransportMode.Car)
                {
                    useCar = true;
                }
                else if ((wouldAffordTaxiVoluntarily && currentTransportMode[instanceID] == TransportMode.Taxi) || couldUseTaxi)
                {
                    useTaxi = true;
                }
                else if (couldUseCar)
                {
                    // pocket car fallback
                    useCar = true;
                }
            }

            ExtVehicleType extVehicleType = ExtVehicleType.None;

            NetInfo.LaneType        laneType    = NetInfo.LaneType.Pedestrian;
            VehicleInfo.VehicleType vehicleType = VehicleInfo.VehicleType.None;

            if (usePublicTransport)
            {
                currentTransportMode[instanceID] = TransportMode.PublicTransport;
                laneType       |= NetInfo.LaneType.PublicTransport;
                extVehicleType |= ExtVehicleType.PublicTransport;
            }

            if (useBike && vehicleInfo != null)
            {
                laneType       |= NetInfo.LaneType.Vehicle;
                vehicleType    |= vehicleInfo.m_vehicleType;
                extVehicleType |= ExtVehicleType.Bicycle;
            }

            if (useTaxi && vehicleInfo != null)
            {
                currentTransportMode[instanceID] = TransportMode.Taxi;
                laneType       |= (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
                vehicleType    |= vehicleInfo.m_vehicleType;
                extVehicleType |= ExtVehicleType.Taxi;
            }

            if (useCar && vehicleInfo != null)
            {
                currentTransportMode[instanceID] = TransportMode.Car;
                laneType       |= NetInfo.LaneType.Vehicle;
                vehicleType    |= vehicleInfo.m_vehicleType;
                extVehicleType |= ExtVehicleType.PassengerCar;
            }

            //Log._Debug($"Citizen {instanceID}: usePublicTransport={usePublicTransport} useCar={useCar} useTaxi={useTaxi} useBike={useBike} vehicleInfo.vehicleType={vehicleInfo?.m_vehicleType} laneType={laneType} vehicleType={vehicleType} extVehicleType={extVehicleType}");

            bool allowUnderground = (citizenData.m_flags & (CitizenInstance.Flags.Underground | CitizenInstance.Flags.Transition)) != CitizenInstance.Flags.None;

            PathUnit.Position startPosA;
            PathUnit.Position endPosA;
            if (this.FindPathPosition(instanceID, ref citizenData, startPos, laneType, vehicleType, allowUnderground, out startPosA) &&
                this.FindPathPosition(instanceID, ref citizenData, endPos, laneType, vehicleType, false, out endPosA))
            {
                PathUnit.Position position2 = default(PathUnit.Position);
                uint path;
#if DEBUG
                //Log._Debug($"CustomCitizenAI: citizen instance {instanceID}, id {citizenData.m_citizen}. vehicleType={vehicleType} laneType={laneType} extVehicleType={extVehicleType} usePublicTransport={usePublicTransport} useTaxi={useTaxi} useBike={useBike} useCar={useCar} wealthLevel={wealthLevel}");
#endif
                // NON-STOCK CODE END //
                if (Singleton <CustomPathManager> .instance.CreatePath(false, (ExtVehicleType)extVehicleType, null, out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, position2, endPosA, position2, vehiclePosition, laneType, vehicleType, 20000f, false, false, false, false, randomParking))
                {
                    if (citizenData.m_path != 0u)
                    {
                        Singleton <PathManager> .instance.ReleasePath(citizenData.m_path);
                    }
                    citizenData.m_path   = path;
                    citizenData.m_flags |= CitizenInstance.Flags.WaitingPath;
                    return(true);
                }
            }
            return(false);
        }
Exemple #14
0
        internal void GetIncome(ushort buildingID, Building buildingData, ref int income, ref int tourists)
        {
            DistrictManager instance = Singleton <DistrictManager> .instance;
            byte            district = instance.GetDistrict(buildingData.m_position);

            DistrictPolicies.Services servicePolicies = instance.m_districts.m_buffer[(int)district].m_servicePolicies;
            ItemClass.Zone            zone            = buildingData.Info.m_class.GetZone();

            int baseIncome = 0;// GetBaseIncome(buildingData.Info.m_class.m_level, zone);

            if ((servicePolicies & DistrictPolicies.Services.Recycling) != DistrictPolicies.Services.None)
            {
                baseIncome = baseIncome * 95 / 100;
            }

            int percentage = 100;

            if (zone == ItemClass.Zone.ResidentialHigh || zone == ItemClass.Zone.ResidentialLow)
            {
                GetCitizenIncome(CitizenUnit.Flags.Home, buildingData, ref income, ref tourists);
            }
            else if (zone == ItemClass.Zone.CommercialHigh || zone == ItemClass.Zone.CommercialLow)
            {
                GetCitizenIncome(CitizenUnit.Flags.Visit, buildingData, ref income, ref tourists);

                DistrictPolicies.CityPlanning cityPlanningPolicies = instance.m_districts.m_buffer[(int)district].m_cityPlanningPolicies;
                if (buildingData.Info.m_class.m_subService == ItemClass.SubService.CommercialLow)
                {
                    if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.SmallBusiness) != DistrictPolicies.CityPlanning.None)
                    {
                        baseIncome += 20;
                    }
                }
                else if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.BigBusiness) != DistrictPolicies.CityPlanning.None)
                {
                    baseIncome += 20;
                }
                if ((servicePolicies & DistrictPolicies.Services.RecreationalUse) != DistrictPolicies.Services.None)
                {
                    baseIncome = (baseIncome * 105 + 99) / 100;
                }
                if (buildingData.m_outgoingProblemTimer >= 128 || buildingData.m_customBuffer1 == 0)
                {
                    percentage = 0;
                }
            }
            else if (zone == ItemClass.Zone.Industrial)
            {
                GetCitizenIncome(CitizenUnit.Flags.Work, buildingData, ref income, ref tourists);

                if (buildingData.m_outgoingProblemTimer >= 128 || buildingData.m_customBuffer1 == 0)
                {
                    percentage = 0;
                }
            }
            else if (zone == ItemClass.Zone.Office)
            {
                GetCitizenIncome(CitizenUnit.Flags.Work, buildingData, ref income, ref tourists);
            }


            income   = (income * baseIncome + 99) / 100;
            tourists = (tourists * baseIncome + 99) / 100;
            if (buildingData.m_electricityProblemTimer >= 1 || buildingData.m_waterProblemTimer >= 1 || buildingData.m_waterProblemTimer >= 1 || buildingData.m_garbageBuffer > 60000)
            {
                percentage = 0;
            }
            float num18 = Singleton <TerrainManager> .instance.WaterLevel(VectorUtils.XZ(buildingData.m_position));

            if (num18 > buildingData.m_position.y)
            {
                percentage = 0;
            }
            income   = (income * percentage + 99) / 100;
            tourists = (tourists * percentage * 2 + 99) / 100;
        }