/// <summary>
        /// Sets the internal supply reserve.
        /// </summary>
        /// <param name="buildingId"></param>
        /// <param name="amount">Must bet between 0 and 100.</param>
        public static void SetInternalSupplyReserve(int buildingId, int amount)
        {
            var buildingName = TransferManagerInfo.GetBuildingName(buildingId);

            Logger.LogVerbose($"Constraints::SetInternalSupplyReserve: {buildingName} ({buildingId}) => {amount} ...");

            m_buildingToInternalSupplyBuffer[buildingId] = COMath.Clamp(amount, 0, 100);
        }
Пример #2
0
        public static void Save(ref byte[] saveData)
        {
            //58
            int i = 0;

            //30
            SaveAndRestore.SaveData(ref i, cPartyChance, ref saveData);
            SaveAndRestore.SaveData(ref i, gPartyChance, ref saveData);
            SaveAndRestore.SaveData(ref i, sPartyChance, ref saveData);
            SaveAndRestore.SaveData(ref i, lPartyChance, ref saveData);
            SaveAndRestore.SaveData(ref i, nPartyChance, ref saveData);

            SaveAndRestore.SaveData(ref i, cPartyTickets, ref saveData);
            SaveAndRestore.SaveData(ref i, gPartyTickets, ref saveData);
            SaveAndRestore.SaveData(ref i, sPartyTickets, ref saveData);
            SaveAndRestore.SaveData(ref i, lPartyTickets, ref saveData);
            SaveAndRestore.SaveData(ref i, nPartyTickets, ref saveData);

            SaveAndRestore.SaveData(ref i, cPartySeats, ref saveData);
            SaveAndRestore.SaveData(ref i, gPartySeats, ref saveData);
            SaveAndRestore.SaveData(ref i, sPartySeats, ref saveData);
            SaveAndRestore.SaveData(ref i, lPartySeats, ref saveData);
            SaveAndRestore.SaveData(ref i, nPartySeats, ref saveData);

            //14
            SaveAndRestore.SaveData(ref i, nextMeetingInterval, ref saveData);
            SaveAndRestore.SaveData(ref i, case1, ref saveData);
            SaveAndRestore.SaveData(ref i, case2, ref saveData);
            SaveAndRestore.SaveData(ref i, case3, ref saveData);
            SaveAndRestore.SaveData(ref i, case4, ref saveData);
            SaveAndRestore.SaveData(ref i, case5, ref saveData);
            SaveAndRestore.SaveData(ref i, case6, ref saveData);
            SaveAndRestore.SaveData(ref i, case7, ref saveData);
            SaveAndRestore.SaveData(ref i, case8, ref saveData);
            SaveAndRestore.SaveData(ref i, currentBillId, ref saveData);
            SaveAndRestore.SaveData(ref i, currentYes, ref saveData);
            SaveAndRestore.SaveData(ref i, currentNo, ref saveData);
            SaveAndRestore.SaveData(ref i, currentNoAttend, ref saveData);

            //14
            SaveAndRestore.SaveData(ref i, residentTax, ref saveData);
            SaveAndRestore.SaveData(ref i, commercialTax, ref saveData);
            SaveAndRestore.SaveData(ref i, industryTax, ref saveData);
            SaveAndRestore.SaveData(ref i, benefitOffset, ref saveData);

            residentTax   = COMath.Clamp((int)residentTax, 0, 20);
            commercialTax = COMath.Clamp((int)commercialTax, 0, 20);
            industryTax   = COMath.Clamp((int)industryTax, 0, 20);
            benefitOffset = (short)COMath.Clamp((int)benefitOffset, 0, 100);

            if (i != saveData.Length)
            {
                DebugLog.LogToFileOnly($"Politics Save Error: saveData.Length = {saveData.Length} + i = {i}");
            }
        }
 /// <summary>
 /// Set the max percentage of traffic that can be outside-to-outside traffic.
 /// </summary>
 /// <param name="amount"></param>
 public static void SetGlobalOutsideToOutsideMaxPerc(int amount)
 {
     Logger.LogVerbose($"Constraints::SetGlobalOutsideToOutsideMaxPerc: {amount} ...");
     m_globalOutsideToOutsideMaxPerc = COMath.Clamp(amount, 0, 100);
 }
 /// <summary>
 /// Set the global outside connection intensity.
 /// </summary>
 /// <param name="amount"></param>
 public static void SetGlobalOutsideConnectionIntensity(int amount)
 {
     Logger.LogVerbose($"Constraints::SetGlobalOutsideConnectionIntensity: {amount} ...");
     m_globalOutsideConnectionIntensity = COMath.Clamp(amount, 0, 1000);
 }
        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);
        }