public static void ProcessGabargeIncome(ref Building building, int amountDelta, TransferManager.TransferReason material)
        {
            if (building.Info.m_class.m_service == ItemClass.Service.Garbage)
            {
                float product_value;
                switch (material)
                {
                case TransferManager.TransferReason.Lumber:
                    product_value = -amountDelta *RealCityIndustryBuildingAI.GetResourcePrice(material);

                    Singleton <EconomyManager> .instance.AddResource(EconomyManager.Resource.ResourcePrice, (int)product_value, ItemClass.Service.PlayerIndustry, ItemClass.SubService.PlayerIndustryForestry, ItemClass.Level.Level1);

                    break;

                case TransferManager.TransferReason.Coal:
                    product_value = -amountDelta *RealCityIndustryBuildingAI.GetResourcePrice(material);

                    Singleton <EconomyManager> .instance.AddResource(EconomyManager.Resource.ResourcePrice, (int)product_value, ItemClass.Service.PlayerIndustry, ItemClass.SubService.PlayerIndustryOre, ItemClass.Level.Level1);

                    break;

                case TransferManager.TransferReason.Petrol:
                    product_value = -amountDelta *RealCityIndustryBuildingAI.GetResourcePrice(material);

                    Singleton <EconomyManager> .instance.AddResource(EconomyManager.Resource.ResourcePrice, (int)product_value, ItemClass.Service.PlayerIndustry, ItemClass.SubService.PlayerIndustryOil, ItemClass.Level.Level1);

                    break;

                default: DebugLog.LogToFileOnly($"Error: ProcessGabargeIncome find unknown gabarge transition {building.Info.m_class} transfer reason {material}"); break;
                }
            }
        }
        public static void RevertGabargeIncome(ref Building building, int amountDelta, TransferManager.TransferReason material)
        {
            building.m_customBuffer2 = (ushort)Mathf.Clamp(building.m_customBuffer2 + amountDelta, 0, 65535);
            float productValue;

            switch (material)
            {
            case TransferManager.TransferReason.Lumber:
                productValue = amountDelta * RealCityIndustryBuildingAI.GetResourcePrice(material);
                Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.ResourcePrice, (int)productValue, ItemClass.Service.PlayerIndustry, ItemClass.SubService.PlayerIndustryForestry, ItemClass.Level.Level1);

                break;

            case TransferManager.TransferReason.Coal:
                productValue = amountDelta * RealCityIndustryBuildingAI.GetResourcePrice(material);
                Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.ResourcePrice, (int)productValue, ItemClass.Service.PlayerIndustry, ItemClass.SubService.PlayerIndustryOre, ItemClass.Level.Level1);

                break;

            case TransferManager.TransferReason.Petrol:
                productValue = amountDelta * RealCityIndustryBuildingAI.GetResourcePrice(material);
                Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.ResourcePrice, (int)productValue, ItemClass.Service.PlayerIndustry, ItemClass.SubService.PlayerIndustryOil, ItemClass.Level.Level1);

                break;

            default: DebugLog.LogToFileOnly($"Error: RevertGabargeIncome find unknown gabarge transition {building.Info.m_class} transfer reason {material}"); break;
            }
        }
        public static void Postfix(ushort buildingID, ref Building data)
        {
            var   material           = TransferManager.TransferReason.Goods;
            float initialMaterialFee = data.m_customBuffer1 * RealCityIndustryBuildingAI.GetResourcePrice(material) + 10000;

            BuildingData.buildingMoney[buildingID] = -initialMaterialFee;
        }
 public static void ProcessIncoming(ushort buildingID, ref Building data, TransferManager.TransferReason material, ref int amountDelta)
 {
     if (amountDelta > 0)
     {
         float tradeIncome1 = amountDelta * RealCityIndustryBuildingAI.GetResourcePrice(material);
         BuildingData.buildingMoney[buildingID] = BuildingData.buildingMoney[buildingID] - tradeIncome1;
     }
 }
Beispiel #5
0
        public static void Postfix(ushort buildingID, ref Building data)
        {
            RealCityIndustrialBuildingAI.InitDelegate();
            var   material           = RealCityIndustrialBuildingAI.GetIncomingTransferReason((IndustrialBuildingAI)(data.Info.m_buildingAI), buildingID);
            float initialMaterialFee = data.m_customBuffer1 * RealCityIndustryBuildingAI.GetResourcePrice(material) + 10000;

            BuildingData.buildingMoney[buildingID] = -initialMaterialFee;
        }
        public static void CaculateTradeIncome(ushort buildingID, ref Building data, TransferManager.TransferReason material, ref int amountDelta)
        {
            if (amountDelta < 0)
            {
                float tradeIncome = amountDelta * RealCityIndustryBuildingAI.GetResourcePrice(material);
                float tradeTax    = -tradeIncome *RealCityPrivateBuildingAI.GetTaxRate(data) / 100f;

                Singleton <EconomyManager> .instance.AddPrivateIncome((int)tradeTax, ItemClass.Service.Commercial, data.Info.m_class.m_subService, data.Info.m_class.m_level, 111333);

                BuildingData.buildingMoney[buildingID] = (BuildingData.buildingMoney[buildingID] - (tradeIncome + tradeTax));
            }
        }
Beispiel #7
0
        public static void RevertTradeIncome(ushort buildingID, ref Building data, TransferManager.TransferReason material, ref int amountDelta)
        {
            if (amountDelta > 0)
            {
                //revert
                data.m_customBuffer2 = (ushort)Mathf.Clamp(data.m_customBuffer2 + amountDelta, 0, 65535);
                float tradeIncome = -amountDelta *RealCityIndustryBuildingAI.GetResourcePrice(material);

                float tradeTax = -tradeIncome *RealCityPrivateBuildingAI.GetTaxRate(data) / 100f;

                MainDataStore.unfinishedTransitionLost += (int)(tradeTax / 100f);
                Singleton <EconomyManager> .instance.FetchResource((EconomyManager.Resource) 17, (int)tradeTax, ItemClass.Service.Industrial, data.Info.m_class.m_subService, data.Info.m_class.m_level);

                BuildingData.buildingMoney[buildingID] = (BuildingData.buildingMoney[buildingID] + (tradeIncome + tradeTax));
            }
        }
Beispiel #8
0
        public static void ProcessResourceArriveAtTarget(ref Vehicle data, ref int transferSize)
        {
            BuildingManager instance = Singleton <BuildingManager> .instance;
            BuildingInfo    info     = instance.m_buildings.m_buffer[data.m_targetBuilding].Info;

            if ((data.m_flags & Vehicle.Flags.TransferToTarget) != 0)
            {
                if ((info.m_class.m_service == ItemClass.Service.Electricity) || (info.m_class.m_service == ItemClass.Service.Water) || (info.m_class.m_service == ItemClass.Service.Disaster))
                {
                    info.m_buildingAI.ModifyMaterialBuffer(data.m_targetBuilding, ref instance.m_buildings.m_buffer[data.m_targetBuilding], (TransferManager.TransferReason)data.m_transferType, ref transferSize);
                    float productValue;
                    switch ((TransferManager.TransferReason)data.m_transferType)
                    {
                    case TransferManager.TransferReason.Petrol:
                        productValue = transferSize * RealCityIndustryBuildingAI.GetResourcePrice((TransferManager.TransferReason)data.m_transferType);
                        Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.ResourcePrice, (int)productValue, ItemClass.Service.PlayerIndustry, ItemClass.SubService.PlayerIndustryOil, ItemClass.Level.Level1);

                        break;

                    case TransferManager.TransferReason.Coal:
                        productValue = transferSize * RealCityIndustryBuildingAI.GetResourcePrice((TransferManager.TransferReason)data.m_transferType);
                        Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.ResourcePrice, (int)productValue, ItemClass.Service.PlayerIndustry, ItemClass.SubService.PlayerIndustryOre, ItemClass.Level.Level1);

                        break;

                    case TransferManager.TransferReason.Goods:
                        productValue = transferSize * RealCityIndustryBuildingAI.GetResourcePrice((TransferManager.TransferReason)data.m_transferType);
                        Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.ResourcePrice, (int)productValue, ItemClass.Service.PlayerIndustry, ItemClass.SubService.None, ItemClass.Level.Level1);

                        break;

                    case (TransferManager.TransferReason) 124:
                    case (TransferManager.TransferReason) 125: break;

                    default: DebugLog.LogToFileOnly("Error: ProcessResourceArriveAtTarget find unknow play building transition" + info.m_class.ToString() + "transfer reason " + data.m_transferType.ToString()); break;
                    }
                    if ((data.m_flags & Vehicle.Flags.TransferToTarget) != 0)
                    {
                        data.m_transferSize = (ushort)Mathf.Clamp(data.m_transferSize - transferSize, 0, data.m_transferSize);
                    }
                }
            }
        }
Beispiel #9
0
        public static void Prefix(TransferManager.TransferReason material, ref int amountDelta)
        {
            switch (material)
            {
            case TransferManager.TransferReason.Oil:
            case TransferManager.TransferReason.Ore:
            case TransferManager.TransferReason.Coal:
            case TransferManager.TransferReason.Petrol:
            case TransferManager.TransferReason.Food:
            case TransferManager.TransferReason.Grain:
            case TransferManager.TransferReason.Lumber:
            case TransferManager.TransferReason.Fish:
            case TransferManager.TransferReason.Logs:
            case TransferManager.TransferReason.Goods:
            case TransferManager.TransferReason.LuxuryProducts:
            case TransferManager.TransferReason.AnimalProducts:
            case TransferManager.TransferReason.Flours:
            case TransferManager.TransferReason.Petroleum:
            case TransferManager.TransferReason.Plastics:
            case TransferManager.TransferReason.Metals:
            case TransferManager.TransferReason.Glass:
            case TransferManager.TransferReason.PlanedTimber:
            case TransferManager.TransferReason.Paper:
                if (amountDelta < 0)
                {
                    int transferSize = -amountDelta;
                    MainDataStore.outsideGovermentMoney += (transferSize * RealCityIndustryBuildingAI.GetResourcePrice(material) * MainDataStore.outsideGovermentProfitRatio);
                    MainDataStore.outsideTouristMoney   += (transferSize * RealCityIndustryBuildingAI.GetResourcePrice(material) * MainDataStore.outsideCompanyProfitRatio * MainDataStore.outsideTouristSalaryProfitRatio);
                    //DebugLog.LogToFileOnly($"OutsideConnectionAIModifyMaterialBufferPatch: Find {material} amount = {amountDelta}");
                }
                break;

            default:
                break;
            }
        }
        public static bool Prefix(TransferManager.TransferReason material, ref TransferManager.TransferOffer offer)
        {
            switch (material)
            {
            case TransferManager.TransferReason.Shopping:
            case TransferManager.TransferReason.ShoppingB:
            case TransferManager.TransferReason.ShoppingC:
            case TransferManager.TransferReason.ShoppingD:
            case TransferManager.TransferReason.ShoppingE:
            case TransferManager.TransferReason.ShoppingF:
            case TransferManager.TransferReason.ShoppingG:
            case TransferManager.TransferReason.ShoppingH:
            case TransferManager.TransferReason.Entertainment:
            case TransferManager.TransferReason.EntertainmentB:
            case TransferManager.TransferReason.EntertainmentC:
            case TransferManager.TransferReason.EntertainmentD:
            case TransferManager.TransferReason.TouristA:
            case TransferManager.TransferReason.TouristB:
            case TransferManager.TransferReason.TouristC:
            case TransferManager.TransferReason.TouristD:
                if (RealCity.realCityV10)
                {
                    if (MainDataStore.outsideTouristMoney < 0)
                    {
                        if (Singleton <BuildingManager> .instance.m_buildings.m_buffer[offer.Building].Info.m_buildingAI is OutsideConnectionAI)
                        {
                            return(false);
                        }
                    }
                }
                break;

            case TransferManager.TransferReason.Oil:
            case TransferManager.TransferReason.Ore:
            case TransferManager.TransferReason.Coal:
            case TransferManager.TransferReason.Petrol:
            case TransferManager.TransferReason.Food:
            case TransferManager.TransferReason.Grain:
            case TransferManager.TransferReason.Lumber:
            case TransferManager.TransferReason.Logs:
            case TransferManager.TransferReason.Goods:
            case TransferManager.TransferReason.LuxuryProducts:
            case TransferManager.TransferReason.AnimalProducts:
            case TransferManager.TransferReason.Flours:
            case TransferManager.TransferReason.Petroleum:
            case TransferManager.TransferReason.Plastics:
            case TransferManager.TransferReason.Metals:
            case TransferManager.TransferReason.Glass:
            case TransferManager.TransferReason.PlanedTimber:
            case TransferManager.TransferReason.Paper:
                break;

            default:
                return(true);
            }

            if (offer.Citizen != 0)
            {
                var    instance       = Singleton <CitizenManager> .instance;
                ushort homeBuilding   = instance.m_citizens.m_buffer[offer.Citizen].m_homeBuilding;
                uint   citizenUnit    = CitizenData.GetCitizenUnit(homeBuilding);
                uint   containingUnit = instance.m_citizens.m_buffer[offer.Citizen].GetContainingUnit((uint)offer.Citizen, citizenUnit, CitizenUnit.Flags.Home);

                if (!instance.m_citizens.m_buffer[offer.Citizen].m_flags.IsFlagSet(Citizen.Flags.Tourist))
                {
                    if (CitizenUnitData.familyMoney[containingUnit] < MainDataStore.maxGoodPurchase * RealCityIndustryBuildingAI.GetResourcePrice(TransferManager.TransferReason.Shopping))
                    {
                        //Reject poor citizen to building
                        return(false);
                    }
                }
            }
            else if (offer.Building != 0)
            {
                var instance     = Singleton <BuildingManager> .instance;
                var buildingID   = offer.Building;
                var buildingData = instance.m_buildings.m_buffer[buildingID];
                if (buildingData.Info.m_class.m_service == ItemClass.Service.Industrial)
                {
                    RealCityIndustrialBuildingAI.InitDelegate();
                    RealCityCommonBuildingAI.InitDelegate();
                    var industrialBuildingAI = buildingData.Info.m_buildingAI as IndustrialBuildingAI;
                    TransferManager.TransferReason incomingTransferReason          = RealCityIndustrialBuildingAI.GetIncomingTransferReason((IndustrialBuildingAI)(buildingData.Info.m_buildingAI), buildingID);
                    TransferManager.TransferReason secondaryIncomingTransferReason = RealCityIndustrialBuildingAI.GetSecondaryIncomingTransferReason((IndustrialBuildingAI)(buildingData.Info.m_buildingAI), buildingID);
                    int maxIncomingLoadSize = RealCityIndustrialBuildingAI.MaxIncomingLoadSize((IndustrialBuildingAI)(buildingData.Info.m_buildingAI));
                    int num  = 0;
                    int num1 = 0;
                    int incomingCargoCapacity = 0;
                    int value = 0;
                    if (incomingTransferReason != TransferManager.TransferReason.None)
                    {
                        if (secondaryIncomingTransferReason != TransferManager.TransferReason.None)
                        {
                            RealCityCommonBuildingAI.CalculateGuestVehicles1((IndustrialBuildingAI)(buildingData.Info.m_buildingAI), buildingID, ref buildingData, incomingTransferReason, secondaryIncomingTransferReason, ref num, ref num1, ref incomingCargoCapacity, ref value);
                        }
                        else
                        {
                            RealCityCommonBuildingAI.CalculateGuestVehicles((IndustrialBuildingAI)(buildingData.Info.m_buildingAI), buildingID, ref buildingData, incomingTransferReason, ref num, ref num1, ref incomingCargoCapacity, ref value);
                        }
                    }
                    int productionCapacity  = industrialBuildingAI.CalculateProductionCapacity((ItemClass.Level)buildingData.m_level, new Randomizer((int)buildingID), buildingData.m_width, buildingData.m_length);
                    int consumptionDivider  = RealCityIndustrialBuildingAI.GetConsumptionDivider((IndustrialBuildingAI)(buildingData.Info.m_buildingAI));
                    int fullCapacity        = Mathf.Max(productionCapacity * 500 / consumptionDivider, maxIncomingLoadSize * 4);
                    int incomingAmontNeeded = fullCapacity - (int)buildingData.m_customBuffer1 - incomingCargoCapacity;
                    incomingAmontNeeded -= 8000;

                    if (incomingAmontNeeded < 0)
                    {
                        return(false);
                    }
                    else
                    {
                        if (material == incomingTransferReason)
                        {
                            //first remove.
                            //game bug, will send 2 incomingTransferReason per period
                            TransferManager.TransferOffer offer1 = default;
                            offer1.Building = buildingID;
                            Singleton <TransferManager> .instance.RemoveIncomingOffer(incomingTransferReason, offer1);
                        }
                    }
                }
                else if (buildingData.Info.m_class.m_service == ItemClass.Service.Commercial)
                {
                    RealCityCommercialBuildingAI.InitDelegate();
                    RealCityCommonBuildingAI.InitDelegate();
                    var commercialBuildingAI = buildingData.Info.m_buildingAI as CommercialBuildingAI;
                    int maxIncomingLoadSize  = RealCityCommercialBuildingAI.MaxIncomingLoadSize((CommercialBuildingAI)(buildingData.Info.m_buildingAI));
                    int visitplaceCount      = commercialBuildingAI.CalculateVisitplaceCount((ItemClass.Level)buildingData.m_level, new Randomizer((int)buildingID), buildingData.m_width, buildingData.m_length);
                    int fullCapacity         = Mathf.Max(visitplaceCount * 500, maxIncomingLoadSize * 4);
                    int num  = 0;
                    int num1 = 0;
                    int incomingCargoCapacity = 0;
                    int value = 0;
                    TransferManager.TransferReason incomingTransferReason = RealCityCommercialBuildingAI.GetIncomingTransferReason((CommercialBuildingAI)(buildingData.Info.m_buildingAI));
                    if (incomingTransferReason != TransferManager.TransferReason.None)
                    {
                        if (incomingTransferReason == TransferManager.TransferReason.Goods || incomingTransferReason == TransferManager.TransferReason.Food)
                        {
                            RealCityCommonBuildingAI.CalculateGuestVehicles1((CommercialBuildingAI)(buildingData.Info.m_buildingAI), buildingID, ref buildingData, incomingTransferReason, TransferManager.TransferReason.LuxuryProducts, ref num, ref num1, ref incomingCargoCapacity, ref value);
                        }
                        else
                        {
                            RealCityCommonBuildingAI.CalculateGuestVehicles((CommercialBuildingAI)(buildingData.Info.m_buildingAI), buildingID, ref buildingData, incomingTransferReason, ref num, ref num1, ref incomingCargoCapacity, ref value);
                        }
                        buildingData.m_tempImport = (byte)Mathf.Clamp(value, (int)buildingData.m_tempImport, 255);
                    }
                    int incomingAmontNeeded = fullCapacity - (int)buildingData.m_customBuffer1 - incomingCargoCapacity;
                    incomingAmontNeeded -= 6000;
                    if (incomingAmontNeeded < 0)
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
        public static void Prefix(uint citizenID, ref Citizen data, ref ushort sourceBuilding, ref ushort targetBuilding)
        {
            if (data.m_workBuilding != targetBuilding)
            {
                var building = Singleton <BuildingManager> .instance.m_buildings.m_buffer[targetBuilding];
                if (building.Info.m_class.m_service == ItemClass.Service.Commercial)
                {
                    CitizenManager instance       = Singleton <CitizenManager> .instance;
                    ushort         homeBuilding   = data.m_homeBuilding;
                    uint           citizenUnit    = CitizenData.GetCitizenUnit(homeBuilding);
                    uint           containingUnit = data.GetContainingUnit((uint)citizenID, citizenUnit, CitizenUnit.Flags.Home);

                    Citizen.BehaviourData behaviour = default;
                    int aliveVisitCount             = 0;
                    int totalVisitCount             = 0;
                    RealCityCommercialBuildingAI.InitDelegate();
                    RealCityCommercialBuildingAI.GetVisitBehaviour((CommercialBuildingAI)(building.Info.m_buildingAI), targetBuilding, ref building, ref behaviour, ref aliveVisitCount, ref totalVisitCount);
                    var amount = building.m_customBuffer2 / MainDataStore.maxGoodPurchase - totalVisitCount + aliveVisitCount;
                    var CommercialBuildingAI = building.Info.m_buildingAI as CommercialBuildingAI;
                    var maxCount             = CommercialBuildingAI.CalculateVisitplaceCount((ItemClass.Level)building.m_level, new Randomizer(targetBuilding), building.m_width, building.m_length);
                    if ((amount <= 0) || (maxCount <= totalVisitCount))
                    {
                        //Close CommercialBuilding
                        //Reject citizen to building which lack of goods
                        sourceBuilding    = targetBuilding;
                        building.m_flags &= ~Building.Flags.Active;
                        return;
                    }

                    if (data.m_flags.IsFlagSet(Citizen.Flags.Tourist))
                    {
                        //DebugLog.LogToFileOnly("Find Tourist in HumanAIStartMovingPatch");
                    }
                    else
                    {
                        //DebugLog.LogToFileOnly("Find Resident in HumanAIStartMovingPatch");
                        if (CitizenUnitData.familyMoney[containingUnit] < MainDataStore.maxGoodPurchase * RealCityIndustryBuildingAI.GetResourcePrice(TransferManager.TransferReason.Shopping))
                        {
                            //Reject poor citizen to building
                            if (CitizenUnitData.familyGoods[containingUnit] > 1000)
                            {
                                //If a family is lacking goods very seriously, even they do not have enough money, they can buy goods.
                                //minimumLivingAllowance will cover this expense.
                                sourceBuilding = targetBuilding;
                                return;
                            }
                        }
                        else if (CitizenUnitData.familyGoods[containingUnit] > 2000)
                        {
                            //Reject citizen who already have enough goods to building
                            sourceBuilding = targetBuilding;
                            return;
                        }
                    }
                }
            }
        }
Beispiel #12
0
        public static bool Prefix(ushort buildingID, ref Building data, uint citizen)
        {
            CitizenManager citizenManager = Singleton <CitizenManager> .instance;
            BuildingInfo   buildingInfo   = data.Info;

            if ((citizenManager.m_citizens.m_buffer[citizen].m_flags & Citizen.Flags.Tourist) != Citizen.Flags.None)
            {
                int consumptionMoney = MainDataStore.govermentSalary << 4;
                if (citizenManager.m_citizens.m_buffer[citizen].WealthLevel == Citizen.Wealth.High)
                {
                    consumptionMoney <<= 2;
                }
                if (citizenManager.m_citizens.m_buffer[citizen].WealthLevel == Citizen.Wealth.Medium)
                {
                    consumptionMoney <<= 1;
                }

                consumptionMoney = -consumptionMoney;
                if (MainDataStore.outsideTouristMoney > 0)
                {
                    buildingInfo.m_buildingAI.ModifyMaterialBuffer(buildingID, ref data, TransferManager.TransferReason.Entertainment, ref consumptionMoney);
                    MainDataStore.outsideTouristMoney += (consumptionMoney);
                }
                consumptionMoney = -MainDataStore.maxGoodPurchase;
                buildingInfo.m_buildingAI.ModifyMaterialBuffer(buildingID, ref data, TransferManager.TransferReason.Shopping, ref consumptionMoney);
                int priceInt = 0;
                IndustryBuildingGetResourcePricePatch.Prefix(ref priceInt, TransferManager.TransferReason.Shopping, data.Info.m_class.m_service);
                var m_goodsSellPrice = priceInt / 100;
                MainDataStore.outsideTouristMoney += (consumptionMoney * m_goodsSellPrice);
            }
            else
            {
                ushort homeBuilding   = citizenManager.m_citizens.m_buffer[citizen].m_homeBuilding;
                uint   citizenUnit    = CitizenData.GetCitizenUnit(homeBuilding);
                uint   containingUnit = citizenManager.m_citizens.m_buffer[citizen].GetContainingUnit((uint)citizen, citizenUnit, CitizenUnit.Flags.Home);

                if (containingUnit != 0)
                {
                    //int goodAmount = (int)(-(CitizenUnitData.familyMoney[containingUnit]) / RealCityIndustryBuildingAI.GetResourcePrice(TransferManager.TransferReason.Shopping));
                    int goodAmount = -MainDataStore.maxGoodPurchase;

                    if (goodAmount < 0)
                    {
                        buildingInfo.m_buildingAI.ModifyMaterialBuffer(buildingID, ref data, TransferManager.TransferReason.Shopping, ref goodAmount);

                        if (goodAmount != 0)
                        {
                            CitizenUnitData.familyGoods[containingUnit] = (ushort)(CitizenUnitData.familyGoods[containingUnit] - (goodAmount * 10));
                            if (CitizenUnitData.familyGoods[containingUnit] > 2000)
                            {
                                citizenManager.m_citizens.m_buffer[citizen].m_flags &= ~Citizen.Flags.NeedGoods;
                            }
                        }
                    }
                    else
                    {
                        goodAmount = 0;
                    }

                    var familyMoney = (CitizenUnitData.familyMoney[containingUnit] + goodAmount * RealCityIndustryBuildingAI.GetResourcePrice(TransferManager.TransferReason.Shopping));

                    float consumptionIndex;
                    if (buildingInfo.m_class.m_subService == ItemClass.SubService.CommercialLeisure)
                    {
                        consumptionIndex = 0.25f;
                    }
                    else if ((buildingInfo.m_class.m_subService == ItemClass.SubService.CommercialTourist))
                    {
                        consumptionIndex = 0.2f;
                    }
                    else if ((buildingInfo.m_class.m_subService == ItemClass.SubService.CommercialEco))
                    {
                        consumptionIndex = 0.05f;
                    }
                    else if ((buildingInfo.m_class.m_subService == ItemClass.SubService.CommercialHigh))
                    {
                        consumptionIndex = 0.15f;
                    }
                    else
                    {
                        consumptionIndex = 0.1f;
                    }

                    int consumptionMoney = -(int)(consumptionIndex * familyMoney);

                    if (consumptionMoney < 0)
                    {
                        int money = consumptionMoney;
                        buildingInfo.m_buildingAI.ModifyMaterialBuffer(buildingID, ref data, TransferManager.TransferReason.Entertainment, ref money);
                    }
                    else
                    {
                        consumptionMoney = 0;
                    }

                    CitizenData.citizenMoney[citizen]           = (CitizenData.citizenMoney[citizen] + consumptionMoney + goodAmount * RealCityIndustryBuildingAI.GetResourcePrice(TransferManager.TransferReason.Shopping));
                    CitizenUnitData.familyMoney[containingUnit] = CitizenUnitData.familyMoney[containingUnit] + consumptionMoney + goodAmount * RealCityIndustryBuildingAI.GetResourcePrice(TransferManager.TransferReason.Shopping);
                }
            }

            Singleton <BuildingAI> .instance.VisitorEnter(buildingID, ref data, citizen);

            return(false);
        }
        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;
            }
        }
        public static void ProcessFamily(uint homeID, ref CitizenUnit data)
        {
            if (RealCityResidentAI.preCitizenId > homeID)
            {
                //DebugLog.LogToFileOnly("Another period started");
                MainDataStore.familyCount      = RealCityResidentAI.familyCount;
                MainDataStore.citizenCount     = RealCityResidentAI.citizenCount;
                MainDataStore.level2HighWealth = RealCityResidentAI.level2HighWealth;
                MainDataStore.level3HighWealth = RealCityResidentAI.level3HighWealth;
                MainDataStore.level1HighWealth = RealCityResidentAI.level1HighWealth;
                if (RealCityResidentAI.familyCount != 0)
                {
                    MainDataStore.citizenSalaryPerFamily  = ((RealCityResidentAI.citizenSalaryCount / RealCityResidentAI.familyCount));
                    MainDataStore.citizenExpensePerFamily = ((RealCityResidentAI.citizenExpenseCount / RealCityResidentAI.familyCount));
                }
                MainDataStore.citizenExpense        = RealCityResidentAI.citizenExpenseCount;
                MainDataStore.citizenSalaryTaxTotal = RealCityResidentAI.citizenSalaryTaxTotal;
                MainDataStore.citizenSalaryTotal    = RealCityResidentAI.citizenSalaryCount;
                if (MainDataStore.familyCount < MainDataStore.familyWeightStableHigh)
                {
                    MainDataStore.familyWeightStableHigh = (uint)MainDataStore.familyCount;
                }
                else
                {
                    MainDataStore.familyWeightStableHigh = RealCityResidentAI.familyWeightStableHigh;
                }
                if (MainDataStore.familyCount < MainDataStore.familyWeightStableLow)
                {
                    MainDataStore.familyWeightStableLow = (uint)MainDataStore.familyCount;
                }
                else
                {
                    MainDataStore.familyWeightStableLow = RealCityResidentAI.familyWeightStableLow;
                }

                RealCityPrivateBuildingAI.profitBuildingMoneyFinal = RealCityPrivateBuildingAI.profitBuildingMoney;

                RealCityResidentAI.level3HighWealth           = 0;
                RealCityResidentAI.level2HighWealth           = 0;
                RealCityResidentAI.level1HighWealth           = 0;
                RealCityResidentAI.familyCount                = 0;
                RealCityResidentAI.citizenCount               = 0;
                RealCityResidentAI.citizenSalaryCount         = 0;
                RealCityResidentAI.citizenExpenseCount        = 0;
                RealCityResidentAI.citizenSalaryTaxTotal      = 0;
                RealCityResidentAI.tempCitizenSalaryTaxTotal  = 0f;
                RealCityResidentAI.familyWeightStableHigh     = 0;
                RealCityResidentAI.familyWeightStableLow      = 0;
                RealCityPrivateBuildingAI.profitBuildingMoney = 0;
            }

            RealCityResidentAI.preCitizenId = homeID;
            RealCityResidentAI.familyCount++;

            if (homeID > 524288)
            {
                DebugLog.LogToFileOnly("Error: citizen ID greater than 524288");
            }

            //DebugLog.LogToFileOnly($"ProcessCitizen pre family {homeID} moneny {CitizenUnitData.familyMoney[homeID]}");
            //ProcessCitizen pre, gather all citizenMoney to familyMoney
            ProcessCitizen(homeID, ref data, true);
            //DebugLog.LogToFileOnly($"ProcessCitizen post family {homeID} moneny {CitizenUnitData.familyMoney[homeID]}");
            //1.We calculate citizen income
            int familySalaryCurrent = 0;

            familySalaryCurrent += RealCityResidentAI.ProcessCitizenSalary(data.m_citizen0, false);
            familySalaryCurrent += RealCityResidentAI.ProcessCitizenSalary(data.m_citizen1, false);
            familySalaryCurrent += RealCityResidentAI.ProcessCitizenSalary(data.m_citizen2, false);
            familySalaryCurrent += RealCityResidentAI.ProcessCitizenSalary(data.m_citizen3, false);
            familySalaryCurrent += RealCityResidentAI.ProcessCitizenSalary(data.m_citizen4, false);
            RealCityResidentAI.citizenSalaryCount = RealCityResidentAI.citizenSalaryCount + familySalaryCurrent;
            if (familySalaryCurrent < 0)
            {
                DebugLog.LogToFileOnly("familySalaryCurrent< 0 in ResidentAI");
                familySalaryCurrent = 0;
            }

            //2.We calculate salary tax
            float tax = (float)(Politics.residentTax << 1) * familySalaryCurrent / 100f;

            RealCityResidentAI.tempCitizenSalaryTaxTotal = RealCityResidentAI.tempCitizenSalaryTaxTotal + (int)tax;
            RealCityResidentAI.citizenSalaryTaxTotal     = (int)RealCityResidentAI.tempCitizenSalaryTaxTotal;
            ProcessCitizenIncomeTax(homeID, tax);

            //3. We calculate expense
            int            educationFee = 0;
            int            hospitalFee  = 0;
            int            expenseRate  = 0;
            CitizenManager instance     = Singleton <CitizenManager> .instance;
            int            tempEducationFee;
            int            tempHospitalFee;

            if (data.m_citizen4 != 0u && !instance.m_citizens.m_buffer[(int)((UIntPtr)data.m_citizen4)].Dead)
            {
                GetExpenseRate(data.m_citizen4, out expenseRate, out tempEducationFee, out tempHospitalFee);
                educationFee += tempEducationFee;
                hospitalFee  += tempHospitalFee;
            }
            if (data.m_citizen3 != 0u && !instance.m_citizens.m_buffer[(int)((UIntPtr)data.m_citizen3)].Dead)
            {
                GetExpenseRate(data.m_citizen3, out expenseRate, out tempEducationFee, out tempHospitalFee);
                educationFee += tempEducationFee;
                hospitalFee  += tempHospitalFee;
            }
            if (data.m_citizen2 != 0u && !instance.m_citizens.m_buffer[(int)((UIntPtr)data.m_citizen2)].Dead)
            {
                GetExpenseRate(data.m_citizen2, out expenseRate, out tempEducationFee, out tempHospitalFee);
                educationFee += tempEducationFee;
                hospitalFee  += tempHospitalFee;
            }
            if (data.m_citizen1 != 0u && !instance.m_citizens.m_buffer[(int)((UIntPtr)data.m_citizen1)].Dead)
            {
                GetExpenseRate(data.m_citizen1, out expenseRate, out tempEducationFee, out tempHospitalFee);
                educationFee += tempEducationFee;
                hospitalFee  += tempHospitalFee;
            }
            if (data.m_citizen0 != 0u && !instance.m_citizens.m_buffer[(int)((UIntPtr)data.m_citizen0)].Dead)
            {
                GetExpenseRate(data.m_citizen0, out expenseRate, out tempEducationFee, out tempHospitalFee);
                educationFee += tempEducationFee;
                hospitalFee  += tempHospitalFee;
            }
            ProcessCitizenHouseRent(homeID, expenseRate);
            //campus DLC added.
            expenseRate = UniqueFacultyAI.IncreaseByBonus(UniqueFacultyAI.FacultyBonus.Economics, expenseRate);
            RealCityResidentAI.citizenExpenseCount += (educationFee + expenseRate + hospitalFee);

            //4. income - expense
            float incomeMinusExpense = familySalaryCurrent - tax - educationFee - expenseRate;

            CitizenUnitData.familyMoney[homeID] += incomeMinusExpense;

            //5. Limit familyMoney
            if (CitizenUnitData.familyMoney[homeID] > 100000000f)
            {
                CitizenUnitData.familyMoney[homeID] = 100000000f;
            }

            if (CitizenUnitData.familyMoney[homeID] < -100000000f)
            {
                CitizenUnitData.familyMoney[homeID] = -100000000f;
            }

            //6. Caculate minimumLivingAllowance and benefitOffset
            if (CitizenUnitData.familyMoney[homeID] < (-(Politics.benefitOffset * MainDataStore.govermentSalary) / 100f))
            {
                int num = (int)(-CitizenUnitData.familyMoney[homeID]);
                CitizenUnitData.familyMoney[homeID]  += num;
                MainDataStore.minimumLivingAllowance += num;
                Singleton <EconomyManager> .instance.FetchResource((EconomyManager.Resource) 17, num, ItemClass.Service.Residential, ItemClass.SubService.None, ItemClass.Level.Level1);
            }
            else
            {
                if (Politics.benefitOffset > 0)
                {
                    CitizenUnitData.familyMoney[homeID]  += ((Politics.benefitOffset * MainDataStore.govermentSalary) / 100f);
                    MainDataStore.minimumLivingAllowance += (int)((Politics.benefitOffset * MainDataStore.govermentSalary) / 100f);
                    Singleton <EconomyManager> .instance.FetchResource((EconomyManager.Resource) 17, (int)((Politics.benefitOffset * MainDataStore.govermentSalary) / 100f), ItemClass.Service.Residential, ItemClass.SubService.None, ItemClass.Level.Level1);
                }
            }

            var canBuyGoodMoney        = MainDataStore.maxGoodPurchase * RealCityIndustryBuildingAI.GetResourcePrice(TransferManager.TransferReason.Shopping);
            var familySalaryCurrentTmp = (familySalaryCurrent > canBuyGoodMoney) ? canBuyGoodMoney : familySalaryCurrent;

            //7. Process citizen status
            if ((CitizenUnitData.familyMoney[homeID] / (canBuyGoodMoney + 1000f - familySalaryCurrentTmp)) >= 30)
            {
                RealCityResidentAI.level3HighWealth++;
            }
            else if ((CitizenUnitData.familyMoney[homeID] / (canBuyGoodMoney + 1000f - familySalaryCurrentTmp)) >= 20)
            {
                RealCityResidentAI.level2HighWealth++;
            }
            else if ((CitizenUnitData.familyMoney[homeID] / (canBuyGoodMoney + 1000f - familySalaryCurrentTmp)) >= 10)
            {
                RealCityResidentAI.level1HighWealth++;
            }

            //8 reduce goods
            float reducedGoods;

            if (CitizenUnitData.familyMoney[homeID] < canBuyGoodMoney)
            {
                reducedGoods = CitizenUnitData.familyGoods[homeID] / 100f;
            }
            else
            {
                reducedGoods = CitizenUnitData.familyGoods[homeID] / 50f;
            }

            CitizenUnitData.familyGoods[homeID] = (ushort)COMath.Clamp((int)(CitizenUnitData.familyGoods[homeID] - reducedGoods), 0, 60000);
            data.m_goods = (ushort)(CitizenUnitData.familyGoods[homeID] / 10f);

            //9 Buy good from outside and try move family
            if (data.m_goods == 0)
            {
                if ((CitizenUnitData.familyMoney[homeID] > canBuyGoodMoney) && (familySalaryCurrent > 1))
                {
                    uint citizenID  = 0u;
                    int  familySize = 0;
                    if (data.m_citizen4 != 0u && !instance.m_citizens.m_buffer[(int)((UIntPtr)data.m_citizen4)].Dead)
                    {
                        familySize++;
                        citizenID = data.m_citizen4;
                        instance.m_citizens.m_buffer[citizenID].m_flags &= ~Citizen.Flags.NeedGoods;
                    }
                    if (data.m_citizen3 != 0u && !instance.m_citizens.m_buffer[(int)((UIntPtr)data.m_citizen3)].Dead)
                    {
                        familySize++;
                        citizenID = data.m_citizen3;
                        instance.m_citizens.m_buffer[citizenID].m_flags &= ~Citizen.Flags.NeedGoods;
                    }
                    if (data.m_citizen2 != 0u && !instance.m_citizens.m_buffer[(int)((UIntPtr)data.m_citizen2)].Dead)
                    {
                        familySize++;
                        citizenID = data.m_citizen2;
                        instance.m_citizens.m_buffer[citizenID].m_flags &= ~Citizen.Flags.NeedGoods;
                    }
                    if (data.m_citizen1 != 0u && !instance.m_citizens.m_buffer[(int)((UIntPtr)data.m_citizen1)].Dead)
                    {
                        familySize++;
                        citizenID = data.m_citizen1;
                        instance.m_citizens.m_buffer[citizenID].m_flags &= ~Citizen.Flags.NeedGoods;
                    }
                    if (data.m_citizen0 != 0u && !instance.m_citizens.m_buffer[(int)((UIntPtr)data.m_citizen0)].Dead)
                    {
                        familySize++;
                        citizenID = data.m_citizen0;
                        instance.m_citizens.m_buffer[citizenID].m_flags &= ~Citizen.Flags.NeedGoods;
                    }

                    Singleton <ResidentAI> .instance.TryMoveFamily(citizenID, ref instance.m_citizens.m_buffer[citizenID], familySize);

                    CitizenUnitData.familyGoods[homeID] = 5000;
                    data.m_goods = (ushort)(CitizenUnitData.familyGoods[homeID] / 10f);
                    CitizenUnitData.familyMoney[homeID] -= canBuyGoodMoney;
                    MainDataStore.outsideGovermentMoney += (canBuyGoodMoney * MainDataStore.outsideGovermentProfitRatio);
                    MainDataStore.outsideTouristMoney   += (canBuyGoodMoney * MainDataStore.outsideCompanyProfitRatio * MainDataStore.outsideTouristSalaryProfitRatio);
                }
            }

            //ProcessCitizen post, split all familyMoney to CitizenMoney
            ProcessCitizen(homeID, ref data, false);
        }
Beispiel #15
0
        private void RefreshDisplayData()
        {
            if (refeshOnce || (BuildingData.lastBuildingID != WorldInfoPanel.GetCurrentInstanceID().Building))
            {
                if (isVisible)
                {
                    BuildingData.lastBuildingID = WorldInfoPanel.GetCurrentInstanceID().Building;
                    Building buildingData = Singleton <BuildingManager> .instance.m_buildings.m_buffer[BuildingData.lastBuildingID];
                    if (buildingData.Info.m_class.m_service == ItemClass.Service.Residential)
                    {
                        Hide();
                    }
                    else
                    {
                        float  averageEmployeeFee = CaculateEmployeeOutcome(buildingData, out int totalWorkerCount);
                        int    landRentFee        = CaculateLandFee(buildingData, BuildingData.lastBuildingID);
                        string incomeType         = RealCityPrivateBuildingAI.GetProductionType(false, BuildingData.lastBuildingID, buildingData);
                        string outgoingType       = RealCityPrivateBuildingAI.GetProductionType(true, BuildingData.lastBuildingID, buildingData);
                        float  incomePrice        = RealCityPrivateBuildingAI.GetPrice(false, BuildingData.lastBuildingID, buildingData);
                        float  outgoingPrice      = RealCityPrivateBuildingAI.GetPrice(true, BuildingData.lastBuildingID, buildingData);
                        buildingMoney.text          = string.Format(Localization.Get("BUILDING_MONEY") + " [{0}]", BuildingData.buildingMoney[BuildingData.lastBuildingID]);
                        buildingNetAsset.text       = string.Format(Localization.Get("BUILDING_NETASSET") + " [{0}]", (BuildingData.buildingMoney[BuildingData.lastBuildingID] + buildingData.m_customBuffer1 * RealCityIndustryBuildingAI.GetResourcePrice(RealCityPrivateBuildingAI.GetIncomingProductionType(BuildingData.lastBuildingID, buildingData))));
                        buildingIncomeBuffer.text   = string.Format(Localization.Get("MATERIAL_BUFFER") + " [{0}]" + " " + incomeType, buildingData.m_customBuffer1);
                        buildingOutgoingBuffer.text = string.Format(Localization.Get("PRODUCTION_BUFFER") + " [{0}]" + " " + outgoingType, buildingData.m_customBuffer2);
                        employFee.text = Localization.Get("AVERAGE_EMPLOYFEE") + " " + averageEmployeeFee.ToString() + " " + Localization.Get("PROFIT_SHARING");
                        landRent.text  = string.Format(Localization.Get("BUILDING_LANDRENT") + " [{0:N2}]", landRentFee);
                        buyPrice.text  = string.Format(Localization.Get("BUY_PRICE") + " " + incomeType + "[{0:N2}]", incomePrice);
                        sellPrice.text = string.Format(Localization.Get("SELL_PRICE") + " " + outgoingType + " [{0:N2}]", outgoingPrice);

                        float consumptionDivider = 0f;
                        if (buildingData.Info.m_class.m_subService == ItemClass.SubService.IndustrialGeneric)
                        {
                            consumptionDivider    = RealCityPrivateBuildingAI.GetComsumptionDivider(buildingData, BuildingData.lastBuildingID) * 4f;
                            comsuptionDivide.text = string.Format(Localization.Get("MATERIAL_DIV_PRODUCTION") + " [1:{0:N2}]", consumptionDivider);
                        }
                        else
                        {
                            if ((buildingData.Info.m_buildingAI is IndustrialExtractorAI) || buildingData.Info.m_class.m_service == ItemClass.Service.Office)
                            {
                                comsuptionDivide.text = string.Format(Localization.Get("MATERIAL_DIV_PRODUCTION") + " N/A");
                            }
                            else
                            {
                                consumptionDivider    = RealCityPrivateBuildingAI.GetComsumptionDivider(buildingData, BuildingData.lastBuildingID);
                                comsuptionDivide.text = string.Format(Localization.Get("MATERIAL_DIV_PRODUCTION") + " [1:{0:N2}]", consumptionDivider);
                            }
                        }

                        int m_sellTax = RealCityPrivateBuildingAI.GetTaxRate(buildingData);
                        sellTax.text = string.Format(Localization.Get("SELL_TAX") + " [{0}%]", m_sellTax);

                        if (consumptionDivider == 0f)
                        {
                            profit.text = string.Format(Localization.Get("PROFIT") + " N/A");
                        }
                        else
                        {
                            float profitRatio = (outgoingPrice * (1f - m_sellTax / 100f) - (incomePrice / consumptionDivider)) / outgoingPrice;
                            if (buildingData.Info.m_class.m_service == ItemClass.Service.Commercial)
                            {
                                profit.text = string.Format(Localization.Get("PROFIT") + " [{0}%]" + Localization.Get("EXCLUDE_VISIT_INCOME"), (int)(profitRatio * 100f));
                            }
                            else
                            {
                                profit.text = string.Format(Localization.Get("PROFIT") + " [{0}%]", (int)(profitRatio * 100f));
                            }
                        }

                        int usedCar = 0;
                        int num     = 0;
                        int num1    = 0;
                        int num2    = 0;
                        int car     = 0;
                        if (buildingData.Info.m_class.m_service == ItemClass.Service.Industrial)
                        {
                            TransferManager.TransferReason tempReason = default(TransferManager.TransferReason);
                            if (buildingData.Info.m_buildingAI is IndustrialExtractorAI)
                            {
                                RealCityIndustrialExtractorAI.InitDelegate();
                                var industrialExtractorAI = (IndustrialExtractorAI)buildingData.Info.m_buildingAI;
                                int productionCapacity    = industrialExtractorAI.CalculateProductionCapacity((ItemClass.Level)buildingData.m_level, new Randomizer(BuildingData.lastBuildingID), buildingData.m_width, buildingData.m_length);
                                car        = Mathf.Max(1, productionCapacity / 6);
                                tempReason = RealCityIndustrialExtractorAI.GetOutgoingTransferReason((IndustrialExtractorAI)buildingData.Info.m_buildingAI);
                                RealCityCommonBuildingAI.InitDelegate();
                                RealCityCommonBuildingAI.CalculateOwnVehicles((IndustrialExtractorAI)buildingData.Info.m_buildingAI, BuildingData.lastBuildingID, ref buildingData, tempReason, ref usedCar, ref num, ref num1, ref num2);
                            }
                            else
                            {
                                RealCityIndustrialBuildingAI.InitDelegate();
                                var industrialBuildingAI = (IndustrialBuildingAI)buildingData.Info.m_buildingAI;
                                int productionCapacity   = industrialBuildingAI.CalculateProductionCapacity((ItemClass.Level)buildingData.m_level, new Randomizer(BuildingData.lastBuildingID), buildingData.m_width, buildingData.m_length);
                                car        = Mathf.Max(1, productionCapacity / 6);
                                tempReason = RealCityIndustrialBuildingAI.GetOutgoingTransferReason((IndustrialBuildingAI)buildingData.Info.m_buildingAI);
                                RealCityCommonBuildingAI.InitDelegate();
                                RealCityCommonBuildingAI.CalculateOwnVehicles((IndustrialBuildingAI)buildingData.Info.m_buildingAI, BuildingData.lastBuildingID, ref buildingData, tempReason, ref usedCar, ref num, ref num1, ref num2);
                            }

                            usedcar.text = string.Format(Localization.Get("CAR_USED") + " [{0}/{1}]", usedCar, car);
                        }
                        else if (buildingData.Info.m_class.m_service == ItemClass.Service.Commercial)
                        {
                            Citizen.BehaviourData behaviour = default;
                            int aliveVisitCount             = 0;
                            int totalVisitCount             = 0;
                            RealCityCommercialBuildingAI.InitDelegate();
                            RealCityCommercialBuildingAI.GetVisitBehaviour((CommercialBuildingAI)(buildingData.Info.m_buildingAI), BuildingData.lastBuildingID, ref buildingData, ref behaviour, ref aliveVisitCount, ref totalVisitCount);
                            var amount = buildingData.m_customBuffer2 / MainDataStore.maxGoodPurchase - totalVisitCount + aliveVisitCount;
                            var commercialBuildingAI = buildingData.Info.m_buildingAI as CommercialBuildingAI;
                            var maxCount             = commercialBuildingAI.CalculateVisitplaceCount((ItemClass.Level)buildingData.m_level, new Randomizer(BuildingData.lastBuildingID), buildingData.m_width, buildingData.m_length);
                            usedcar.text = string.Format("FORDEBUG" + " [{0}/{1}/{2}/{3}]", aliveVisitCount, totalVisitCount, maxCount, amount);
                        }
                        else
                        {
                            usedcar.text = Localization.Get("CAR_USED") + " 0/0";
                        }

                        BringToFront();
                        refeshOnce = false;
                    }
                }
            }
        }