public static void ProcessLandFeeOffice(Building building, ushort buildingID, int totalWorkerCount)
        {
            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 = totalWorkerCount * 10;
            int taxRate;

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

            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] >= 0)
            {
                BuildingData.buildingMoney[buildingID] = (BuildingData.buildingMoney[buildingID] - (float)(landFee * taxRate) / 100);
                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);
            }
        }
コード例 #2
0
        public int CaculateLandFee(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;
            DistrictPolicies.CityPlanning cityPlanningPolicies = instance.m_districts.m_buffer[district].m_cityPlanningPolicies;

            GetLandRent(building, out int landFee);
            float taxRate;

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

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

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

            if (BuildingData.buildingMoney[buildingID] > 0)
            {
                if ((building.Info.m_class.m_service == ItemClass.Service.Commercial) || (building.Info.m_class.m_service == ItemClass.Service.Industrial))
                {
                    if (BuildingData.buildingMoney[buildingID] > (taxRate * landFee / 100f))
                    {
                        return((int)(taxRate * landFee / 100f));
                    }
                    else
                    {
                        return(0);
                    }
                }
                else if (building.Info.m_class.m_service == ItemClass.Service.Office)
                {
                    Citizen.BehaviourData behaviourData = default;
                    int aliveWorkerCount = 0;
                    int totalWorkerCount = 0;
                    RealCityCommonBuildingAI.InitDelegate();
                    RealCityCommonBuildingAI.GetWorkBehaviour((OfficeBuildingAI)building.Info.m_buildingAI, buildingID, ref building, ref behaviourData, ref aliveWorkerCount, ref totalWorkerCount);
                    return((int)(totalWorkerCount * taxRate / 10f));
                }
            }

            return(0);
        }
コード例 #3
0
ファイル: EconomyHandler.cs プロジェクト: qifengwei/Tango
        public static bool Prefix(Resource resource, int amount, ItemClass.Service service, ItemClass.SubService subService,
                                  ItemClass.Level level, DistrictPolicies.Taxation taxationPolicies, ref int __result, out bool __state)
        {
            __state = false;

            // Always ignore the private income handler if it's called from AddResource
            AddPrivateIncome.DontRunPatch = true;

            // Don't run patch when we are applying from the command handler
            if (DontRunPatch)
            {
                return(true);
            }

            // Flag to prevent adding resources when it's not possible in the respective command handler
            if (DontAddResource)
            {
                __result = amount;
                // Don't run actual method
                return(false);
            }

            if (amount == 0)
            {
                return(true);
            }

            // Check for resource types that only change in the simulation tick (ignore them in the client)
            if (MultiplayerManager.Instance.CurrentRole == MultiplayerRole.Client)
            {
                switch (resource)
                {
                case Resource.RewardAmount:
                case Resource.CitizenIncome:
                case Resource.PublicIncome:
                case Resource.TourismIncome:
                case Resource.ResourcePrice:
                    // Tell the method caller that the money was added successfully
                    __result = amount;
                    return(false);

                case Resource.PrivateIncome:
                    // Return the same amount as the real method would return (see EconomyManager::AddPrivateIncome)
                    int taxRate = EconomyManager.instance.GetTaxRate(service, subService, level, taxationPolicies);
                    taxRate = UniqueFacultyAI.IncreaseByBonus(UniqueFacultyAI.FacultyBonus.Economics, taxRate);
                    int taxMultiplier = ReflectionHelper.GetAttr <int>(EconomyManager.instance, "m_taxMultiplier");
                    __result = (int)((amount * taxRate * taxMultiplier + 999999L) / 1000000L);
                    return(false);
                }
            }

            __state = true;
            return(true);
        }
        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);
                }
            }
        }
コード例 #5
0
ファイル: EconomyHandler.cs プロジェクト: qifengwei/Tango
        public static void Postfix(Resource resource, ItemClass.Service service, ItemClass.SubService subService,
                                   ItemClass.Level level, DistrictPolicies.Taxation taxationPolicies, int amount, ref bool __state)
        {
            AddPrivateIncome.DontRunPatch = false;

            if (!__state)
            {
                return;
            }

            ResourceCommandHandler.Queue(new EconomyResourceCommand()
            {
                Action         = ResourceAction.ADD,
                ResourceType   = resource,
                ResourceAmount = amount,
                Service        = service,
                SubService     = subService,
                Level          = level,
                Taxation       = taxationPolicies
            });
        }
コード例 #6
0
        public static void GetAccumulation(CommercialBuildingAI thisAI, Randomizer r, int productionRate, int taxRate, DistrictPolicies.CityPlanning cityPlanningPolicies, DistrictPolicies.Taxation taxationPolicies, out int entertainment, out int attractiveness)
        {
            entertainment  = 0;
            attractiveness = 0;

            Debug.LogWarning("GetAccumulation is not overridden!");
        }
コード例 #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.");
            }
        }
        public static void CalculateBuildingMoneyAndSalary(Building building, ushort buildingID)
        {
            if (BuildingData.buildingMoney[buildingID] > MainDataStore.maxBuildingMoneyLimit)
            {
                BuildingData.buildingMoney[buildingID] = MainDataStore.maxBuildingMoneyLimit;
            }
            else if (BuildingData.buildingMoney[buildingID] < -MainDataStore.maxBuildingMoneyLimit)
            {
                BuildingData.buildingMoney[buildingID] = -MainDataStore.maxBuildingMoneyLimit;
            }


            if (building.Info.m_class.m_service == ItemClass.Service.Industrial || building.Info.m_class.m_service == ItemClass.Service.Commercial || building.Info.m_class.m_service == ItemClass.Service.Office)
            {
                Citizen.BehaviourData behaviourData = default;
                int aliveWorkerCount = 0;
                int totalWorkerCount = 0;
                RealCityCommonBuildingAI.InitDelegate();
                RealCityCommonBuildingAI.GetWorkBehaviour((CommonBuildingAI)building.Info.m_buildingAI, buildingID, ref building, ref behaviourData, ref aliveWorkerCount, ref totalWorkerCount);
                float bossTake       = 0;
                float investToOffice = 0;
                float profitShare    = 0;

                switch (building.Info.m_class.m_subService)
                {
                case ItemClass.SubService.OfficeGeneric:
                case ItemClass.SubService.OfficeHightech:
                    profitShare = 1f; break;

                case ItemClass.SubService.IndustrialFarming:
                case ItemClass.SubService.IndustrialForestry:
                    if (building.Info.m_buildingAI is IndustrialExtractorAI)
                    {
                        bossTake       = MainDataStore.bossRatioInduExtractor;
                        investToOffice = MainDataStore.investRatioInduExtractor;
                        profitShare    = MainDataStore.profitShareRatioInduExtractor;
                    }
                    else
                    {
                        bossTake       = MainDataStore.bossRatioInduOther;
                        investToOffice = MainDataStore.investRatioInduOther;
                        profitShare    = MainDataStore.profitShareRatioInduOther;
                    }
                    break;

                case ItemClass.SubService.IndustrialOil:
                case ItemClass.SubService.IndustrialOre:
                    bossTake       = MainDataStore.bossRatioInduOther;
                    investToOffice = MainDataStore.investRatioInduOther;
                    profitShare    = MainDataStore.profitShareRatioInduOther; break;

                case ItemClass.SubService.IndustrialGeneric:
                    if (building.Info.m_class.m_level == ItemClass.Level.Level1)
                    {
                        bossTake       = MainDataStore.bossRatioInduLevel1;
                        investToOffice = MainDataStore.investRatioInduLevel1;
                        profitShare    = MainDataStore.profitShareRatioInduLevel1;
                    }
                    else if (building.Info.m_class.m_level == ItemClass.Level.Level2)
                    {
                        bossTake       = MainDataStore.bossRatioInduLevel2;
                        investToOffice = MainDataStore.investRatioInduLevel2;
                        profitShare    = MainDataStore.profitShareRatioInduLevel2;
                    }
                    else
                    {
                        bossTake       = MainDataStore.bossRatioInduLevel3;
                        investToOffice = MainDataStore.investRatioInduLevel3;
                        profitShare    = MainDataStore.profitShareRatioInduLevel3;
                    }
                    break;

                case ItemClass.SubService.CommercialHigh:
                case ItemClass.SubService.CommercialLow:
                    if (building.Info.m_class.m_level == ItemClass.Level.Level1)
                    {
                        bossTake       = MainDataStore.bossRatioCommLevel1;
                        investToOffice = MainDataStore.investRatioCommLevel1;
                        profitShare    = MainDataStore.profitShareRatioCommLevel1;
                    }
                    else if (building.Info.m_class.m_level == ItemClass.Level.Level2)
                    {
                        bossTake       = MainDataStore.bossRatioCommLevel2;
                        investToOffice = MainDataStore.investRatioCommLevel2;
                        profitShare    = MainDataStore.profitShareRatioCommLevel2;
                    }
                    else
                    {
                        bossTake       = MainDataStore.bossRatioCommLevel3;
                        investToOffice = MainDataStore.investRatioCommLevel3;
                        profitShare    = MainDataStore.profitShareRatioCommLevel1;
                    }
                    break;

                case ItemClass.SubService.CommercialTourist:
                    bossTake       = MainDataStore.bossRatioCommTou;
                    investToOffice = MainDataStore.investRatioCommTou;
                    profitShare    = MainDataStore.profitShareRatioCommTou;
                    break;

                case ItemClass.SubService.CommercialLeisure:
                    bossTake       = MainDataStore.bossRatioCommOther;
                    investToOffice = MainDataStore.investRatioCommOther;
                    profitShare    = MainDataStore.profitShareRatioCommOther; break;

                case ItemClass.SubService.CommercialEco:
                    bossTake       = MainDataStore.bossRatioCommECO;
                    investToOffice = MainDataStore.investRatioCommECO;
                    profitShare    = MainDataStore.profitShareRatioCommECO; break;
                }
                // boss take and return to office
                if (BuildingData.buildingMoney[buildingID] > 0)
                {
                    //Reduce Boss fee
                    long investToOfficeFee = (long)(BuildingData.buildingMoney[buildingID] * investToOffice);
                    long bossTakeFee       = (long)(BuildingData.buildingMoney[buildingID] * bossTake);
                    if (building.Info.m_class.m_service == ItemClass.Service.Commercial)
                    {
                        //Commercial have help tourism
                        MainDataStore.outsideTouristMoney += ((bossTakeFee - investToOfficeFee) * MainDataStore.outsideCompanyProfitRatio * MainDataStore.outsideTouristSalaryProfitRatio);
                    }
                    RealCityPrivateBuildingAI.profitBuildingMoney += investToOfficeFee;
                    BuildingData.buildingMoney[buildingID]        -= bossTakeFee;
                }

                if (building.Info.m_class.m_service == ItemClass.Service.Office)
                {
                    float allOfficeWorker     = RealCityPrivateBuildingAI.allOfficeLevel1WorkCountFinal + RealCityPrivateBuildingAI.allOfficeLevel2WorkCountFinal + RealCityPrivateBuildingAI.allOfficeLevel3WorkCountFinal + RealCityPrivateBuildingAI.allOfficeHighTechWorkCountFinal;
                    float averageOfficeSalary = 0;
                    if (allOfficeWorker != 0)
                    {
                        averageOfficeSalary = (RealCityPrivateBuildingAI.profitBuildingMoneyFinal / allOfficeWorker);
                    }

                    if (building.Info.m_class.m_subService == ItemClass.SubService.OfficeGeneric)
                    {
                        if (building.Info.m_class.m_level == ItemClass.Level.Level1)
                        {
                            BuildingData.buildingMoney[buildingID] = averageOfficeSalary * totalWorkerCount * 0.6f;
                        }
                        else if (building.Info.m_class.m_level == ItemClass.Level.Level2)
                        {
                            BuildingData.buildingMoney[buildingID] = averageOfficeSalary * totalWorkerCount * 0.8f;
                        }
                        else if (building.Info.m_class.m_level == ItemClass.Level.Level3)
                        {
                            BuildingData.buildingMoney[buildingID] = averageOfficeSalary * totalWorkerCount * 1f;
                        }
                    }
                    else if (building.Info.m_class.m_subService == ItemClass.SubService.OfficeHightech)
                    {
                        BuildingData.buildingMoney[buildingID] = averageOfficeSalary * totalWorkerCount * 0.75f;
                    }

                    ProcessLandFeeOffice(building, buildingID, totalWorkerCount);
                }

                //Calculate building salary
                int buildingAsset = (int)(BuildingData.buildingMoney[buildingID] + building.m_customBuffer1 * RealCityIndustryBuildingAI.GetResourcePrice(RealCityPrivateBuildingAI.GetIncomingProductionType(buildingID, building)));
                int salary        = 0;
                if ((buildingAsset > 0) && (totalWorkerCount != 0))
                {
                    salary = (int)(buildingAsset * profitShare / totalWorkerCount);
                    switch (building.Info.m_class.m_subService)
                    {
                    case ItemClass.SubService.IndustrialFarming:
                    case ItemClass.SubService.IndustrialForestry:
                    case ItemClass.SubService.IndustrialOil:
                    case ItemClass.SubService.IndustrialOre:
                        salary = Math.Min(salary, MainDataStore.salaryInduOtherMax); break;

                    case ItemClass.SubService.IndustrialGeneric:
                        if (building.Info.m_class.m_level == ItemClass.Level.Level1)
                        {
                            salary = Math.Min(salary, MainDataStore.salaryInduLevel1Max);
                        }
                        else if (building.Info.m_class.m_level == ItemClass.Level.Level2)
                        {
                            salary = Math.Min(salary, MainDataStore.salaryInduLevel2Max);
                        }
                        else
                        {
                            salary = Math.Min(salary, MainDataStore.salaryInduLevel3Max);
                        }
                        break;

                    case ItemClass.SubService.CommercialHigh:
                    case ItemClass.SubService.CommercialLow:
                        if (building.Info.m_class.m_level == ItemClass.Level.Level1)
                        {
                            salary = Math.Min(salary, MainDataStore.salaryCommLevel1Max);
                        }
                        else if (building.Info.m_class.m_level == ItemClass.Level.Level2)
                        {
                            salary = Math.Min(salary, MainDataStore.salaryCommLevel2Max);
                        }
                        else
                        {
                            salary = Math.Min(salary, MainDataStore.salaryCommLevel3Max);
                        }
                        break;

                    case ItemClass.SubService.CommercialTourist:
                        salary = Math.Min(salary, MainDataStore.salaryCommTouMax); break;

                    case ItemClass.SubService.CommercialLeisure:
                        salary = Math.Min(salary, MainDataStore.salaryCommOtherMax); break;

                    case ItemClass.SubService.CommercialEco:
                        salary = Math.Min(salary, MainDataStore.salaryCommECOMax); break;
                    }
                }

                if (salary > 0)
                {
                    BuildingData.buildingWorkCount[buildingID] = salary;
                }
                else
                {
                    BuildingData.buildingWorkCount[buildingID] = 0;
                }
            }
            else
            {
                //resident building
                ItemClass                 @class             = building.Info.m_class;
                int                       incomeAccumulation = 0;
                DistrictManager           instance           = Singleton <DistrictManager> .instance;
                byte                      district           = instance.GetDistrict(building.m_position);
                DistrictPolicies.Taxation taxationPolicies   = instance.m_districts.m_buffer[district].m_taxationPolicies;
                if (@class.m_subService == ItemClass.SubService.ResidentialLow)
                {
                    switch (@class.m_level)
                    {
                    case ItemClass.Level.Level1:
                        incomeAccumulation = MainDataStore.residentLowLevel1Rent;
                        break;

                    case ItemClass.Level.Level2:
                        incomeAccumulation = MainDataStore.residentLowLevel2Rent;
                        break;

                    case ItemClass.Level.Level3:
                        incomeAccumulation = MainDataStore.residentLowLevel3Rent;
                        break;

                    case ItemClass.Level.Level4:
                        incomeAccumulation = MainDataStore.residentLowLevel4Rent;
                        break;

                    case ItemClass.Level.Level5:
                        incomeAccumulation = MainDataStore.residentLowLevel5Rent;
                        break;
                    }
                }
                else if (@class.m_subService == ItemClass.SubService.ResidentialLowEco)
                {
                    switch (@class.m_level)
                    {
                    case ItemClass.Level.Level1:
                        incomeAccumulation = MainDataStore.residentLowLevel1Rent;
                        break;

                    case ItemClass.Level.Level2:
                        incomeAccumulation = MainDataStore.residentLowLevel2Rent;
                        break;

                    case ItemClass.Level.Level3:
                        incomeAccumulation = MainDataStore.residentLowLevel3Rent;
                        break;

                    case ItemClass.Level.Level4:
                        incomeAccumulation = MainDataStore.residentLowLevel4Rent;
                        break;

                    case ItemClass.Level.Level5:
                        incomeAccumulation = MainDataStore.residentLowLevel5Rent;
                        break;
                    }
                }
                else if (@class.m_subService == ItemClass.SubService.ResidentialHigh)
                {
                    switch (@class.m_level)
                    {
                    case ItemClass.Level.Level1:
                        incomeAccumulation = MainDataStore.residentHighLevel1Rent;
                        break;

                    case ItemClass.Level.Level2:
                        incomeAccumulation = MainDataStore.residentHighLevel2Rent;
                        break;

                    case ItemClass.Level.Level3:
                        incomeAccumulation = MainDataStore.residentHighLevel3Rent;
                        break;

                    case ItemClass.Level.Level4:
                        incomeAccumulation = MainDataStore.residentHighLevel4Rent;
                        break;

                    case ItemClass.Level.Level5:
                        incomeAccumulation = MainDataStore.residentHighLevel5Rent;
                        break;
                    }
                }
                else
                {
                    switch (@class.m_level)
                    {
                    case ItemClass.Level.Level1:
                        incomeAccumulation = MainDataStore.residentHighLevel1Rent;
                        break;

                    case ItemClass.Level.Level2:
                        incomeAccumulation = MainDataStore.residentHighLevel2Rent;
                        break;

                    case ItemClass.Level.Level3:
                        incomeAccumulation = MainDataStore.residentHighLevel3Rent;
                        break;

                    case ItemClass.Level.Level4:
                        incomeAccumulation = MainDataStore.residentHighLevel4Rent;
                        break;

                    case ItemClass.Level.Level5:
                        incomeAccumulation = MainDataStore.residentHighLevel5Rent;
                        break;
                    }
                }
                int num2;
                num2 = Singleton <EconomyManager> .instance.GetTaxRate(@class, taxationPolicies);

                incomeAccumulation = (int)((num2 * incomeAccumulation) / 100f);
                BuildingData.buildingWorkCount[buildingID] = incomeAccumulation;
            }
        }