public static void ProcessLandFeeNoOffice(Building building, ushort buildingID) { DistrictManager instance = Singleton <DistrictManager> .instance; byte district = instance.GetDistrict(building.m_position); DistrictPolicies.Services servicePolicies = instance.m_districts.m_buffer[district].m_servicePolicies; DistrictPolicies.Taxation taxationPolicies = instance.m_districts.m_buffer[district].m_taxationPolicies; int landFee; GetLandRentNoOffice(out landFee, building, buildingID); int taxRate; taxRate = Singleton <EconomyManager> .instance.GetTaxRate(building.Info.m_class, taxationPolicies); if (((taxationPolicies & DistrictPolicies.Taxation.DontTaxLeisure) != DistrictPolicies.Taxation.None) && (building.Info.m_class.m_subService == ItemClass.SubService.CommercialLeisure)) { landFee = 0; } if (instance.IsPolicyLoaded(DistrictPolicies.Policies.ExtraInsulation)) { if ((servicePolicies & DistrictPolicies.Services.ExtraInsulation) != DistrictPolicies.Services.None) { landFee = landFee * 95 / 100; } } if ((servicePolicies & DistrictPolicies.Services.Recycling) != DistrictPolicies.Services.None) { landFee = landFee * 95 / 100; } if (BuildingData.buildingMoney[buildingID] <= ((landFee * taxRate) / 100f)) { landFee = 0; } else { RealCityPrivateBuildingAI.profitBuildingCount++; } if (RealCityEconomyExtension.Can16timesUpdate(buildingID)) { Singleton <EconomyManager> .instance.AddPrivateIncome(landFee, building.Info.m_class.m_service, building.Info.m_class.m_subService, building.Info.m_class.m_level, taxRate * 100); if ((building.Info.m_class.m_service == ItemClass.Service.Commercial) || (building.Info.m_class.m_service == ItemClass.Service.Industrial)) { BuildingData.buildingMoney[buildingID] = (BuildingData.buildingMoney[buildingID] - (float)(landFee * taxRate) / 100); } } }
static int TakeExam(uint citizenIndex) { SimulationManager simulationManager = Singleton <SimulationManager> .instance; CitizenManager citizenManager = Singleton <CitizenManager> .instance; DistrictManager districtManager = Singleton <DistrictManager> .instance; BuildingManager buildingManager = Singleton <BuildingManager> .instance; Vector3 position = buildingManager.m_buildings.m_buffer[citizenManager.m_citizens.m_buffer[citizenIndex].m_homeBuilding].m_position; byte district = districtManager.GetDistrict(position); DistrictPolicies.Services servicePolicies = districtManager.m_districts.m_buffer[(int)district].m_servicePolicies; int grade = simulationManager.m_randomizer.Int32(100); if ((servicePolicies & DistrictPolicies.Services.EducationBoost) != 0) { grade += 20; } return(grade); }
private static int ticketPriceForPrefix(ushort vehicleID, ref Vehicle vehicleData) { var def = TransportSystemDefinition.from(vehicleData.Info.m_class.m_subService, vehicleData.Info.m_vehicleType); if (def == default(TransportSystemDefinition)) { if (TransportLinesManagerMod.instance != null && TransportLinesManagerMod.debugMode) { TLMUtils.doLog("NULL TSysDef! {0}+{1}+{2}", vehicleData.Info.GetAI().GetType(), vehicleData.Info.m_class.m_subService, vehicleData.Info.m_vehicleType); } return(100); } if (def.vehicleType == VehicleInfo.VehicleType.Ferry) { DistrictManager instance = Singleton <DistrictManager> .instance; byte district = instance.GetDistrict(vehicleData.m_targetPos3); DistrictPolicies.Services servicePolicies = instance.m_districts.m_buffer[(int)district].m_servicePolicies; if ((servicePolicies & DistrictPolicies.Services.PreferFerries) != DistrictPolicies.Services.None) { District[] expr_6E_cp_0 = instance.m_districts.m_buffer; byte expr_6E_cp_1 = district; expr_6E_cp_0[(int)expr_6E_cp_1].m_servicePoliciesEffect = (expr_6E_cp_0[(int)expr_6E_cp_1].m_servicePoliciesEffect | DistrictPolicies.Services.PreferFerries); return(0); } } if (vehicleData.m_transportLine == 0) { var value = (int)BasicTransportExtensionSingleton.instance(def).getDefaultTicketPrice(); return(value); } else { var value = (int)(BasicTransportExtensionSingleton.instance(def).getTicketPrice((uint)vehicleData.m_transportLine)); return(value); } }
public int GetTicketPrice(ushort vehicleID, ref Vehicle vehicleData) { if (vehicleData.m_transportLine == 0) { return(ticketPriceForPrefix(vehicleID, ref vehicleData)); } DistrictManager instance = Singleton <DistrictManager> .instance; byte district = instance.GetDistrict(vehicleData.m_targetPos3); DistrictPolicies.Services servicePolicies = instance.m_districts.m_buffer[(int)district].m_servicePolicies; DistrictPolicies.Event @event = instance.m_districts.m_buffer[(int)district].m_eventPolicies & Singleton <EventManager> .instance.GetEventPolicyMask(); if ((servicePolicies & DistrictPolicies.Services.FreeTransport) != DistrictPolicies.Services.None) { District[] expr_80_cp_0 = instance.m_districts.m_buffer; byte expr_80_cp_1 = district; expr_80_cp_0[(int)expr_80_cp_1].m_servicePoliciesEffect = (expr_80_cp_0[(int)expr_80_cp_1].m_servicePoliciesEffect | DistrictPolicies.Services.FreeTransport); return(0); } if ((@event & DistrictPolicies.Event.ComeOneComeAll) != DistrictPolicies.Event.None) { District[] expr_AC_cp_0 = instance.m_districts.m_buffer; byte expr_AC_cp_1 = district; expr_AC_cp_0[(int)expr_AC_cp_1].m_eventPoliciesEffect = (expr_AC_cp_0[(int)expr_AC_cp_1].m_eventPoliciesEffect | DistrictPolicies.Event.ComeOneComeAll); return(0); } if ((servicePolicies & DistrictPolicies.Services.HighTicketPrices) != DistrictPolicies.Services.None) { District[] expr_D8_cp_0 = instance.m_districts.m_buffer; byte expr_D8_cp_1 = district; expr_D8_cp_0[(int)expr_D8_cp_1].m_servicePoliciesEffect = (expr_D8_cp_0[(int)expr_D8_cp_1].m_servicePoliciesEffect | DistrictPolicies.Services.HighTicketPrices); return((int)ticketPriceForPrefix(vehicleID, ref vehicleData) * 5 / 4); } return(ticketPriceForPrefix(vehicleID, ref vehicleData)); }
public static void HandleFire(CommercialBuildingAI thisAI, ushort buildingID, ref Building data, ref Building.Frame frameData, DistrictPolicies.Services policies) { Debug.LogWarning("HandleFire is not overridden!"); }
public static int HandleCommonConsumption(CommercialBuildingAI thisAI, ushort buildingID, ref Building data, ref Building.Frame frameData, ref int electricityConsumption, ref int heatingConsumption, ref int waterConsumption, ref int sewageAccumulation, ref int garbageAccumulation, DistrictPolicies.Services policies) { Debug.LogWarning("HandleCommonConsumption is not overridden!"); return(0); }
public static void SimulationStepActive(CommercialBuildingAI thisAI, ushort buildingID, ref Building buildingData, ref Building.Frame frameData) { //This is a mess because I pulled it directly from the decompiled code and patched it up slightly. //It works though, and that's all I'm bothered about for now. if (thisAI) { DistrictManager instance1 = Singleton <DistrictManager> .instance; byte district = instance1.GetDistrict(buildingData.m_position); DistrictPolicies.Services policies = instance1.m_districts.m_buffer[(int)district].m_servicePolicies; DistrictPolicies.Taxation taxationPolicies = instance1.m_districts.m_buffer[(int)district].m_taxationPolicies; DistrictPolicies.CityPlanning cityPlanningPolicies = instance1.m_districts.m_buffer[(int)district].m_cityPlanningPolicies; instance1.m_districts.m_buffer[(int)district].m_servicePoliciesEffect |= policies & (DistrictPolicies.Services.PowerSaving | DistrictPolicies.Services.WaterSaving | DistrictPolicies.Services.SmokeDetectors | DistrictPolicies.Services.Recycling | DistrictPolicies.Services.RecreationalUse | DistrictPolicies.Services.ExtraInsulation | DistrictPolicies.Services.NoElectricity | DistrictPolicies.Services.OnlyElectricity | DistrictPolicies.Services.RecyclePlastic); switch (thisAI.m_info.m_class.m_subService) { case ItemClass.SubService.CommercialLow: if ((taxationPolicies & (DistrictPolicies.Taxation.TaxRaiseComLow | DistrictPolicies.Taxation.TaxLowerComLow)) != (DistrictPolicies.Taxation.TaxRaiseComLow | DistrictPolicies.Taxation.TaxLowerComLow)) { instance1.m_districts.m_buffer[(int)district].m_taxationPoliciesEffect |= taxationPolicies & (DistrictPolicies.Taxation.TaxRaiseComLow | DistrictPolicies.Taxation.TaxLowerComLow); } instance1.m_districts.m_buffer[(int)district].m_cityPlanningPoliciesEffect |= cityPlanningPolicies & DistrictPolicies.CityPlanning.SmallBusiness; break; case ItemClass.SubService.CommercialHigh: if ((taxationPolicies & (DistrictPolicies.Taxation.TaxRaiseComHigh | DistrictPolicies.Taxation.TaxLowerComHigh)) != (DistrictPolicies.Taxation.TaxRaiseComHigh | DistrictPolicies.Taxation.TaxLowerComHigh)) { instance1.m_districts.m_buffer[(int)district].m_taxationPoliciesEffect |= taxationPolicies & (DistrictPolicies.Taxation.TaxRaiseComHigh | DistrictPolicies.Taxation.TaxLowerComHigh); } instance1.m_districts.m_buffer[(int)district].m_cityPlanningPoliciesEffect |= cityPlanningPolicies & DistrictPolicies.CityPlanning.BigBusiness; break; case ItemClass.SubService.CommercialLeisure: instance1.m_districts.m_buffer[(int)district].m_taxationPoliciesEffect |= taxationPolicies & DistrictPolicies.Taxation.DontTaxLeisure; instance1.m_districts.m_buffer[(int)district].m_cityPlanningPoliciesEffect |= cityPlanningPolicies & DistrictPolicies.CityPlanning.NoLoudNoises; break; case ItemClass.SubService.CommercialTourist: instance1.m_districts.m_buffer[(int)district].m_cityPlanningPoliciesEffect |= cityPlanningPolicies & DistrictPolicies.CityPlanning.LightningRods; break; case ItemClass.SubService.CommercialEco: instance1.m_districts.m_buffer[(int)district].m_cityPlanningPoliciesEffect |= cityPlanningPolicies; break; } Citizen.BehaviourData behaviour = new Citizen.BehaviourData(); int aliveWorkerCount = 0; int totalWorkerCount = 0; int workPlaceCount = 0; int num1 = NewPrivateBuildingAI.HandleWorkers(thisAI, buildingID, ref buildingData, ref behaviour, ref aliveWorkerCount, ref totalWorkerCount, ref workPlaceCount); if ((buildingData.m_flags & Building.Flags.Evacuating) != Building.Flags.None) { num1 = 0; } int width = buildingData.Width; int length = buildingData.Length; int num2 = MaxIncomingLoadSize(thisAI); int aliveCount = 0; int totalCount = 0; GetVisitBehaviour(thisAI, buildingID, ref buildingData, ref behaviour, ref aliveCount, ref totalCount); int visitCount = thisAI.CalculateVisitplaceCount(new Randomizer((int)buildingID), width, length); int num3 = Mathf.Max(0, visitCount - totalCount); int a1 = visitCount * 500; int num4 = Mathf.Max(a1, num2 * 4); TransferManager.TransferReason incomingTransferReason = GetIncomingTransferReason(thisAI); TransferManager.TransferReason outgoingTransferReason = GetOutgoingTransferReason(thisAI, buildingID); if (num1 != 0) { int num5 = num4; if (incomingTransferReason != TransferManager.TransferReason.None) { num5 = Mathf.Min(num5, (int)buildingData.m_customBuffer1); } if (outgoingTransferReason != TransferManager.TransferReason.None) { num5 = Mathf.Min(num5, num4 - (int)buildingData.m_customBuffer2); } int num6 = Mathf.Max(0, Mathf.Min(num1, (num5 * 200 + num4 - 1) / num4)); int a2 = (visitCount * num6 + 9) / 10; if (Singleton <SimulationManager> .instance.m_isNightTime) { a2 = a2 + 1 >> 1; } int num7 = Mathf.Max(0, Mathf.Min(a2, num5)); if (incomingTransferReason != TransferManager.TransferReason.None) { buildingData.m_customBuffer1 -= (ushort)num7; } if (outgoingTransferReason != TransferManager.TransferReason.None) { buildingData.m_customBuffer2 += (ushort)num7; } num1 = (num7 + 9) / 10; } int electricityConsumption; int waterConsumption; int sewageAccumulation; int garbageAccumulation; int incomeAccumulation; thisAI.GetConsumptionRates(new Randomizer((int)buildingID), num1, out electricityConsumption, out waterConsumption, out sewageAccumulation, out garbageAccumulation, out incomeAccumulation); int heatingConsumption = 0; if (electricityConsumption != 0 && instance1.IsPolicyLoaded(DistrictPolicies.Policies.ExtraInsulation)) { if ((policies & DistrictPolicies.Services.ExtraInsulation) != DistrictPolicies.Services.None) { heatingConsumption = Mathf.Max(1, electricityConsumption * 3 + 8 >> 4); incomeAccumulation = incomeAccumulation * 95 / 100; } else { heatingConsumption = Mathf.Max(1, electricityConsumption + 2 >> 2); } } if (garbageAccumulation != 0 && (policies & DistrictPolicies.Services.Recycling) != DistrictPolicies.Services.None) { garbageAccumulation = Mathf.Max(1, garbageAccumulation * 85 / 100); incomeAccumulation = incomeAccumulation * 95 / 100; } int taxRate; switch (thisAI.m_info.m_class.m_subService) { case ItemClass.SubService.CommercialLeisure: taxRate = (buildingData.m_flags & Building.Flags.HighDensity) == Building.Flags.None ? Singleton <EconomyManager> .instance.GetTaxRate(ItemClass.Service.Commercial, ItemClass.SubService.CommercialLow, thisAI.m_info.m_class.m_level, taxationPolicies) : Singleton <EconomyManager> .instance.GetTaxRate(ItemClass.Service.Commercial, ItemClass.SubService.CommercialHigh, thisAI.m_info.m_class.m_level, taxationPolicies); if ((taxationPolicies & DistrictPolicies.Taxation.DontTaxLeisure) != DistrictPolicies.Taxation.None) { taxRate = 0; } if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.NoLoudNoises) != DistrictPolicies.CityPlanning.None && Singleton <SimulationManager> .instance.m_isNightTime) { electricityConsumption = electricityConsumption + 1 >> 1; waterConsumption = waterConsumption + 1 >> 1; sewageAccumulation = sewageAccumulation + 1 >> 1; garbageAccumulation = garbageAccumulation + 1 >> 1; incomeAccumulation = 0; break; } break; case ItemClass.SubService.CommercialTourist: taxRate = (buildingData.m_flags & Building.Flags.HighDensity) == Building.Flags.None ? Singleton <EconomyManager> .instance.GetTaxRate(ItemClass.Service.Commercial, ItemClass.SubService.CommercialLow, thisAI.m_info.m_class.m_level, taxationPolicies) : Singleton <EconomyManager> .instance.GetTaxRate(ItemClass.Service.Commercial, ItemClass.SubService.CommercialHigh, thisAI.m_info.m_class.m_level, taxationPolicies); break; default: taxRate = Singleton <EconomyManager> .instance.GetTaxRate(thisAI.m_info.m_class, taxationPolicies); break; } if (num1 != 0) { int num5 = HandleCommonConsumption(thisAI, buildingID, ref buildingData, ref frameData, ref electricityConsumption, ref heatingConsumption, ref waterConsumption, ref sewageAccumulation, ref garbageAccumulation, policies); num1 = (num1 * num5 + 99) / 100; if (num1 != 0) { int amount1 = incomeAccumulation; if (amount1 != 0) { if (thisAI.m_info.m_class.m_subService == ItemClass.SubService.CommercialLow) { if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.SmallBusiness) != DistrictPolicies.CityPlanning.None) { Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.PolicyCost, 12, thisAI.m_info.m_class); amount1 *= 2; } } else if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.BigBusiness) != DistrictPolicies.CityPlanning.None) { Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.PolicyCost, 25, thisAI.m_info.m_class); amount1 *= 3; } if ((policies & DistrictPolicies.Services.RecreationalUse) != DistrictPolicies.Services.None) { amount1 = (amount1 * 105 + 99) / 100; } int num6 = Singleton <EconomyManager> .instance.AddPrivateIncome(amount1, ItemClass.Service.Commercial, thisAI.m_info.m_class.m_subService, thisAI.m_info.m_class.m_level, taxRate); int amount2 = (behaviour.m_touristCount * num6 + (aliveCount >> 1)) / Mathf.Max(1, aliveCount); int amount3 = Mathf.Max(0, num6 - amount2); if (amount3 != 0) { Singleton <EconomyManager> .instance.AddResource(EconomyManager.Resource.CitizenIncome, amount3, thisAI.m_info.m_class); } if (amount2 != 0) { Singleton <EconomyManager> .instance.AddResource(EconomyManager.Resource.TourismIncome, amount2, thisAI.m_info.m_class); } } int groundPollution; int noisePollution; thisAI.GetPollutionRates(num1, cityPlanningPolicies, out groundPollution, out noisePollution); if (groundPollution != 0 && Singleton <SimulationManager> .instance.m_randomizer.Int32(3U) == 0) { Singleton <NaturalResourceManager> .instance.TryDumpResource(NaturalResourceManager.Resource.Pollution, groundPollution, groundPollution, buildingData.m_position, 60f); } if (noisePollution != 0) { Singleton <ImmaterialResourceManager> .instance.AddResource(ImmaterialResourceManager.Resource.NoisePollution, noisePollution, buildingData.m_position, 60f); } if (num5 < 100) { buildingData.m_flags |= Building.Flags.RateReduced; } else { buildingData.m_flags &= ~Building.Flags.RateReduced; } buildingData.m_flags |= Building.Flags.Active; } else { buildingData.m_flags &= ~(Building.Flags.RateReduced | Building.Flags.Active); } } else { electricityConsumption = 0; heatingConsumption = 0; waterConsumption = 0; sewageAccumulation = 0; garbageAccumulation = 0; buildingData.m_problems = Notification.RemoveProblems(buildingData.m_problems, Notification.Problem.Electricity | Notification.Problem.Water | Notification.Problem.Sewage | Notification.Problem.Flood | Notification.Problem.Heating); buildingData.m_flags &= ~(Building.Flags.RateReduced | Building.Flags.Active); } int health = 0; int wellbeing = 0; float radius = (float)(buildingData.Width + buildingData.Length) * 2.5f; if (behaviour.m_healthAccumulation != 0) { if (aliveWorkerCount + aliveCount != 0) { health = (behaviour.m_healthAccumulation + (aliveWorkerCount + aliveCount >> 1)) / (aliveWorkerCount + aliveCount); } Singleton <ImmaterialResourceManager> .instance.AddResource(ImmaterialResourceManager.Resource.Health, behaviour.m_healthAccumulation, buildingData.m_position, radius); } if (behaviour.m_wellbeingAccumulation != 0) { if (aliveWorkerCount + aliveCount != 0) { wellbeing = (behaviour.m_wellbeingAccumulation + (aliveWorkerCount + aliveCount >> 1)) / (aliveWorkerCount + aliveCount); } Singleton <ImmaterialResourceManager> .instance.AddResource(ImmaterialResourceManager.Resource.Wellbeing, behaviour.m_wellbeingAccumulation, buildingData.m_position, radius); } int num8 = Citizen.GetHappiness(health, wellbeing) * 15 / 100; int a3 = aliveWorkerCount * 20 / workPlaceCount; if ((buildingData.m_problems & Notification.Problem.MajorProblem) == Notification.Problem.None) { num8 += 20; } if (buildingData.m_problems == Notification.Problem.None) { num8 += 25; } int num9 = num8 + Mathf.Min(a3, (int)buildingData.m_customBuffer1 * a3 / num4) + (a3 - Mathf.Min(a3, (int)buildingData.m_customBuffer2 * a3 / num4)); int num10 = (int)(8 - thisAI.m_info.m_class.m_level); int num11 = (int)(11 - thisAI.m_info.m_class.m_level); if (thisAI.m_info.m_class.m_subService == ItemClass.SubService.CommercialHigh) { ++num10; ++num11; } if (taxRate < num10) { num9 += num10 - taxRate; } if (taxRate > num11) { num9 -= taxRate - num11; } if (taxRate >= num11 + 4) { if ((int)buildingData.m_taxProblemTimer != 0 || Singleton <SimulationManager> .instance.m_randomizer.Int32(32U) == 0) { int num5 = taxRate - num11 >> 2; buildingData.m_taxProblemTimer = (byte)Mathf.Min((int)byte.MaxValue, (int)buildingData.m_taxProblemTimer + num5); if ((int)buildingData.m_taxProblemTimer >= 96) { buildingData.m_problems = Notification.AddProblems(buildingData.m_problems, Notification.Problem.TaxesTooHigh | Notification.Problem.MajorProblem); } else if ((int)buildingData.m_taxProblemTimer >= 32) { buildingData.m_problems = Notification.AddProblems(buildingData.m_problems, Notification.Problem.TaxesTooHigh); } } } else { buildingData.m_taxProblemTimer = (byte)Mathf.Max(0, (int)buildingData.m_taxProblemTimer - 1); buildingData.m_problems = Notification.RemoveProblems(buildingData.m_problems, Notification.Problem.TaxesTooHigh); } int entertainment; int attractiveness; GetAccumulation(thisAI, new Randomizer((int)buildingID), num1, taxRate, cityPlanningPolicies, taxationPolicies, out entertainment, out attractiveness); if (entertainment != 0) { Singleton <ImmaterialResourceManager> .instance.AddResource(ImmaterialResourceManager.Resource.Entertainment, entertainment, buildingData.m_position, radius); } if (attractiveness != 0) { Singleton <ImmaterialResourceManager> .instance.AddResource(ImmaterialResourceManager.Resource.Attractiveness, attractiveness); } int happiness = Mathf.Clamp(num9, 0, 100); buildingData.m_health = (byte)health; buildingData.m_happiness = (byte)happiness; buildingData.m_citizenCount = (byte)(aliveWorkerCount + aliveCount); HandleDead(thisAI, buildingID, ref buildingData, ref behaviour, totalWorkerCount + totalCount); int crimeAccumulation = behaviour.m_crimeAccumulation / 10; if (thisAI.m_info.m_class.m_subService == ItemClass.SubService.CommercialLeisure) { crimeAccumulation = crimeAccumulation * 5 + 3 >> 2; } if ((policies & DistrictPolicies.Services.RecreationalUse) != DistrictPolicies.Services.None) { crimeAccumulation = crimeAccumulation * 3 + 3 >> 2; } HandleCrime(thisAI, buildingID, ref buildingData, crimeAccumulation, (int)buildingData.m_citizenCount); int num12 = (int)buildingData.m_crimeBuffer; if (aliveWorkerCount != 0) { Singleton <ImmaterialResourceManager> .instance.AddResource(ImmaterialResourceManager.Resource.Density, aliveWorkerCount, buildingData.m_position, radius); int num5 = (behaviour.m_educated0Count * 100 + behaviour.m_educated1Count * 50 + behaviour.m_educated2Count * 30) / aliveWorkerCount + 50; buildingData.m_fireHazard = (byte)num5; } else { buildingData.m_fireHazard = (byte)0; } int crimeRate = (int)buildingData.m_citizenCount == 0 ? 0 : (num12 + ((int)buildingData.m_citizenCount >> 1)) / (int)buildingData.m_citizenCount; int count = 0; int cargo = 0; int capacity = 0; int outside = 0; if (incomingTransferReason != TransferManager.TransferReason.None) { CalculateGuestVehicles(thisAI, buildingID, ref buildingData, incomingTransferReason, ref count, ref cargo, ref capacity, ref outside); buildingData.m_tempImport = (byte)Mathf.Clamp(outside, (int)buildingData.m_tempImport, (int)byte.MaxValue); } buildingData.m_tempExport = (byte)Mathf.Clamp(behaviour.m_touristCount, (int)buildingData.m_tempExport, (int)byte.MaxValue); SimulationManager _simulationManager = Singleton <SimulationManager> .instance; if ((long)((_simulationManager.m_currentFrameIndex & 3840U) >> 8) == (long)((int)buildingID & 15) && (thisAI.m_info.m_class.m_subService == ItemClass.SubService.CommercialLow || thisAI.m_info.m_class.m_subService == ItemClass.SubService.CommercialHigh) && ((int)Singleton <ZoneManager> .instance.m_lastBuildIndex == (int)_simulationManager.m_currentBuildIndex && (buildingData.m_flags & Building.Flags.Upgrading) == Building.Flags.None)) { CheckBuildingLevel(thisAI, buildingID, ref buildingData, ref frameData, ref behaviour, aliveCount); } if ((buildingData.m_flags & (Building.Flags.Completed | Building.Flags.Upgrading)) == Building.Flags.None) { return; } Notification.Problem problems1 = Notification.RemoveProblems(buildingData.m_problems, Notification.Problem.NoCustomers | Notification.Problem.NoGoods); //Begin edited section if ((int)buildingData.m_customBuffer2 > num4 - (a1 >> 1) && aliveCount <= visitCount >> 1) { if (_simulationManager.m_currentDayTimeHour > 19 && _simulationManager.m_currentDayTimeHour < 20) { buildingData.m_outgoingProblemTimer = (byte)Mathf.Min(byte.MaxValue, buildingData.m_outgoingProblemTimer + 1); if (buildingData.m_outgoingProblemTimer >= 192) { problems1 = Notification.AddProblems(problems1, Notification.Problem.NoCustomers | Notification.Problem.MajorProblem); } else if (buildingData.m_outgoingProblemTimer >= 128) { problems1 = Notification.AddProblems(problems1, Notification.Problem.NoCustomers); } } else { buildingData.m_outgoingProblemTimer = 0; } } else { buildingData.m_outgoingProblemTimer = (byte)0; } if (!CityEventManager.instance.EventStartsWithin(3D) && !CityEventManager.instance.EventTakingPlace() && !CityEventManager.instance.EventJustEnded()) { if ((int)buildingData.m_customBuffer1 == 0) { buildingData.m_incomingProblemTimer = (byte)Mathf.Min((int)byte.MaxValue, (int)buildingData.m_incomingProblemTimer + 1); problems1 = (int)buildingData.m_incomingProblemTimer >= 64 ? Notification.AddProblems(problems1, Notification.Problem.NoGoods | Notification.Problem.MajorProblem) : Notification.AddProblems(problems1, Notification.Problem.NoGoods); } else { buildingData.m_incomingProblemTimer = (byte)0; } float currentHour = _simulationManager.m_currentDayTimeHour; //Artifically shop at night to keep industry happy. Will give the effect of industry stocking up commercial over night. //Note: ModifyMaterialBuffer is expensive, so if there's any performance impact with the mod now, it'll most likely be this. if ((currentHour > 20f || currentHour < 4f)) { if (_simulationManager.m_randomizer.Int32(80) < 2) { //Simulate 2 people buying things int amount = -200; thisAI.ModifyMaterialBuffer(buildingID, ref buildingData, TransferManager.TransferReason.Shopping, ref amount); } } else if (Experiments.ExperimentsToggle.AllowActiveCommercialFix && _simulationManager.m_randomizer.Int32(40) < 5) //Added in as a potential fix to random inactive buildings. Lack of customers still shuts down commercial. { int amount = -50; thisAI.ModifyMaterialBuffer(buildingID, ref buildingData, TransferManager.TransferReason.Shopping, ref amount); } } else { buildingData.m_incomingProblemTimer = 0; } //End edited section buildingData.m_problems = problems1; instance1.m_districts.m_buffer[(int)district].AddCommercialData(ref behaviour, health, happiness, crimeRate, workPlaceCount, aliveWorkerCount, Mathf.Max(0, workPlaceCount - totalWorkerCount), visitCount, aliveCount, num3, (int)thisAI.m_info.m_class.m_level, electricityConsumption, heatingConsumption, waterConsumption, sewageAccumulation, garbageAccumulation, incomeAccumulation, Mathf.Min(100, (int)buildingData.m_garbageBuffer / 50), (int)buildingData.m_waterPollution * 100 / (int)byte.MaxValue, (int)buildingData.m_finalImport, (int)buildingData.m_finalExport, thisAI.m_info.m_class.m_subService); if ((int)buildingData.m_fireIntensity == 0 && incomingTransferReason != TransferManager.TransferReason.None) { int num5 = num4 - (int)buildingData.m_customBuffer1 - capacity - (num2 >> 1); if (num5 >= 0) { Singleton <TransferManager> .instance.AddIncomingOffer(incomingTransferReason, new TransferManager.TransferOffer() { Priority = num5 * 8 / num2, Building = buildingID, Position = buildingData.m_position, Amount = 1, Active = false }); } } if ((int)buildingData.m_fireIntensity == 0 && outgoingTransferReason != TransferManager.TransferReason.None) { int num5 = (int)buildingData.m_customBuffer2 - aliveCount * 100; if (num5 >= 100 && num3 > 0) { Singleton <TransferManager> .instance.AddOutgoingOffer(outgoingTransferReason, new TransferManager.TransferOffer() { Priority = Mathf.Max(1, num5 * 8 / num4), Building = buildingID, Position = buildingData.m_position, Amount = Mathf.Min(num5 / 100, num3), Active = false }); } } PrivateBuildingAI baseAI = thisAI as PrivateBuildingAI; //Because we don't have access to base here. if (baseAI != null) { NewPrivateBuildingAI.SimulationStepActive(baseAI, buildingID, ref buildingData, ref frameData); } HandleFire(thisAI, buildingID, ref buildingData, ref frameData, policies); } else { Debug.LogError("Commercial building " + buildingID + " has no AI! This could have been bad."); } }
private static bool ticketPriceForPrefix(ushort vehicleID, ref Vehicle vehicleData, ref int __result) { var def = TransportSystemDefinition.from(vehicleData.Info); if (def == default(TransportSystemDefinition)) { return(true); } DistrictManager instance = Singleton <DistrictManager> .instance; byte district = instance.GetDistrict(vehicleData.m_targetPos3); DistrictPolicies.Services servicePolicies = instance.m_districts.m_buffer[(int)district].m_servicePolicies; DistrictPolicies.Event @event = instance.m_districts.m_buffer[(int)district].m_eventPolicies & Singleton <EventManager> .instance.GetEventPolicyMask(); float multiplier; if (vehicleData.Info.m_class.m_subService == ItemClass.SubService.PublicTransportTours) { multiplier = 1; } else { if ((servicePolicies & DistrictPolicies.Services.FreeTransport) != DistrictPolicies.Services.None) { __result = 0; return(false); } if ((@event & DistrictPolicies.Event.ComeOneComeAll) != DistrictPolicies.Event.None) { __result = 0; return(false); } if ((servicePolicies & DistrictPolicies.Services.HighTicketPrices) != DistrictPolicies.Services.None) { District[] expr_114_cp_0 = instance.m_districts.m_buffer; byte expr_114_cp_1 = district; expr_114_cp_0[(int)expr_114_cp_1].m_servicePoliciesEffect = (expr_114_cp_0[(int)expr_114_cp_1].m_servicePoliciesEffect | DistrictPolicies.Services.HighTicketPrices); multiplier = 5f / 4f; } else { multiplier = 1; } } if (vehicleData.m_transportLine == 0) { __result = (int)(def.GetTransportExtension().GetDefaultTicketPrice(0) * multiplier); return(false); } else { if (TLMTransportLineExtension.instance.IsUsingCustomConfig(vehicleData.m_transportLine)) { __result = (int)(TLMTransportLineExtension.instance.GetTicketPrice(vehicleData.m_transportLine) * multiplier); } else { __result = (int)(def.GetTransportExtension().GetTicketPrice(TLMLineUtils.getPrefix(vehicleData.m_transportLine)) * multiplier); } return(false); } }
new int HandleCommonConsumption(ushort buildingID, ref Building data, ref int electricityConsumption, ref int heatingConsumption, ref int waterConsumption, ref int sewageAccumulation, ref int garbageAccumulation, DistrictPolicies.Services policies) { int num = 100; DistrictManager instance = Singleton <DistrictManager> .instance; Notification.Problem problem = Notification.RemoveProblems(data.m_problems, Notification.Problem.Electricity | Notification.Problem.Water | Notification.Problem.Sewage | Notification.Problem.Flood | Notification.Problem.Heating); bool flag = data.m_electricityProblemTimer != 0; bool flag2 = false; bool flag3 = false; int electricityUsage = 0; int heatingUsage = 0; int waterUsage = 0; int sewageUsage = 0; if (electricityConsumption != 0) { int num2 = Mathf.RoundToInt((20f - Singleton <WeatherManager> .instance.SampleTemperature(data.m_position, false)) * 8f); num2 = Mathf.Clamp(num2, 0, 400); int num3 = heatingConsumption; heatingConsumption = (num3 * num2 + Singleton <SimulationManager> .instance.m_randomizer.Int32(100u)) / 100; if ((policies & DistrictPolicies.Services.PowerSaving) != DistrictPolicies.Services.None) { electricityConsumption = Mathf.Max(1, electricityConsumption * 90 / 100); Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.PolicyCost, 32, this.m_info.m_class); } bool flag4 = false; int num4 = heatingConsumption * 2 - (int)data.m_heatingBuffer; if (num4 > 0 && (policies & DistrictPolicies.Services.OnlyElectricity) == DistrictPolicies.Services.None) { int num5 = Singleton <WaterManager> .instance.TryFetchHeating(data.m_position, heatingConsumption, num4, out flag4); data.m_heatingBuffer += (ushort)num5; } if ((int)data.m_heatingBuffer < heatingConsumption) { if ((policies & DistrictPolicies.Services.NoElectricity) != DistrictPolicies.Services.None) { flag3 = true; data.m_heatingProblemTimer = (byte)Mathf.Min(255, (int)(data.m_heatingProblemTimer + 1)); if (data.m_heatingProblemTimer >= 65) { num = 0; problem = Notification.AddProblems(problem, Notification.Problem.Heating | Notification.Problem.MajorProblem); } else if (data.m_heatingProblemTimer >= 3) { num /= 2; problem = Notification.AddProblems(problem, Notification.Problem.Heating); } } else { num2 = ((num2 + 50) * (heatingConsumption - (int)data.m_heatingBuffer) + heatingConsumption - 1) / heatingConsumption; electricityConsumption += (num3 * num2 + Singleton <SimulationManager> .instance.m_randomizer.Int32(100u)) / 100; if (flag4) { flag3 = true; data.m_heatingProblemTimer = (byte)Mathf.Min(255, (int)(data.m_heatingProblemTimer + 1)); if (data.m_heatingProblemTimer >= 3) { problem = Notification.AddProblems(problem, Notification.Problem.Heating); } } } heatingUsage = (int)data.m_heatingBuffer; data.m_heatingBuffer = 0; } else { heatingUsage = heatingConsumption; data.m_heatingBuffer -= (ushort)heatingConsumption; } num4 = electricityConsumption * 2 - (int)data.m_electricityBuffer; if (num4 > 0) { int num6 = Singleton <ElectricityManager> .instance.TryFetchElectricity(data.m_position, electricityConsumption, num4); data.m_electricityBuffer += (ushort)num6; } if ((int)data.m_electricityBuffer < electricityConsumption) { flag2 = true; data.m_electricityProblemTimer = (byte)Mathf.Min(255, (int)(data.m_electricityProblemTimer + 1)); if (data.m_electricityProblemTimer >= 65) { num = 0; problem = Notification.AddProblems(problem, Notification.Problem.Electricity | Notification.Problem.MajorProblem); } else if (data.m_electricityProblemTimer >= 3) { num /= 2; problem = Notification.AddProblems(problem, Notification.Problem.Electricity); } electricityUsage = (int)data.m_electricityBuffer; data.m_electricityBuffer = 0; if (Singleton <UnlockManager> .instance.Unlocked(ItemClass.Service.Electricity)) { GuideController properties = Singleton <GuideManager> .instance.m_properties; if (properties != null) { int publicServiceIndex = ItemClass.GetPublicServiceIndex(ItemClass.Service.Electricity); int electricityCapacity = instance.m_districts.m_buffer[0].GetElectricityCapacity(); int electricityConsumption2 = instance.m_districts.m_buffer[0].GetElectricityConsumption(); if (electricityCapacity >= electricityConsumption2) { Singleton <GuideManager> .instance.m_serviceNeeded[publicServiceIndex].Activate(properties.m_serviceNeeded2, ItemClass.Service.Electricity); } else { Singleton <GuideManager> .instance.m_serviceNeeded[publicServiceIndex].Activate(properties.m_serviceNeeded, ItemClass.Service.Electricity); } } } } else { electricityUsage = electricityConsumption; data.m_electricityBuffer -= (ushort)electricityConsumption; } } else { heatingConsumption = 0; } if (!flag2) { data.m_electricityProblemTimer = 0; } if (flag != flag2) { Singleton <BuildingManager> .instance.UpdateBuildingColors(buildingID); } if (!flag3) { data.m_heatingProblemTimer = 0; } bool flag5 = false; int num7 = sewageAccumulation; if (waterConsumption != 0) { if ((policies & DistrictPolicies.Services.WaterSaving) != DistrictPolicies.Services.None) { waterConsumption = Mathf.Max(1, waterConsumption * 85 / 100); if (sewageAccumulation != 0) { sewageAccumulation = Mathf.Max(1, sewageAccumulation * 85 / 100); } Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.PolicyCost, 32, this.m_info.m_class); } int num8 = waterConsumption * 2 - (int)data.m_waterBuffer; if (num8 > 0) { int num9 = Singleton <WaterManager> .instance.TryFetchWater(data.m_position, waterConsumption, num8, ref data.m_waterPollution); data.m_waterBuffer += (ushort)num9; } if ((int)data.m_waterBuffer < waterConsumption) { flag5 = true; data.m_waterProblemTimer = (byte)Mathf.Min(255, (int)(data.m_waterProblemTimer + 1)); if (data.m_waterProblemTimer >= 65) { num = 0; problem = Notification.AddProblems(problem, Notification.Problem.Water | Notification.Problem.MajorProblem); } else if (data.m_waterProblemTimer >= 3) { num /= 2; problem = Notification.AddProblems(problem, Notification.Problem.Water); } num7 = sewageAccumulation * (waterConsumption + (int)data.m_waterBuffer) / (waterConsumption << 1); waterUsage = (int)data.m_waterBuffer; data.m_waterBuffer = 0; if (Singleton <UnlockManager> .instance.Unlocked(ItemClass.Service.Water)) { GuideController properties2 = Singleton <GuideManager> .instance.m_properties; if (properties2 != null) { int publicServiceIndex2 = ItemClass.GetPublicServiceIndex(ItemClass.Service.Water); int waterCapacity = instance.m_districts.m_buffer[0].GetWaterCapacity(); int waterConsumption2 = instance.m_districts.m_buffer[0].GetWaterConsumption(); if (waterCapacity >= waterConsumption2) { Singleton <GuideManager> .instance.m_serviceNeeded[publicServiceIndex2].Activate(properties2.m_serviceNeeded2, ItemClass.Service.Water); } else { Singleton <GuideManager> .instance.m_serviceNeeded[publicServiceIndex2].Activate(properties2.m_serviceNeeded, ItemClass.Service.Water); } } } } else { num7 = sewageAccumulation; waterUsage = waterConsumption; data.m_waterBuffer -= (ushort)waterConsumption; } } if (num7 != 0) { int num10 = num7 * 2 - (int)data.m_sewageBuffer; if (num10 < num7) { if (!flag5 && (data.m_problems & Notification.Problem.Water) == Notification.Problem.None) { flag5 = true; data.m_waterProblemTimer = (byte)Mathf.Min(255, (int)(data.m_waterProblemTimer + 1)); if (data.m_waterProblemTimer >= 65) { num = 0; problem = Notification.AddProblems(problem, Notification.Problem.Sewage | Notification.Problem.MajorProblem); } else if (data.m_waterProblemTimer >= 3) { num /= 2; problem = Notification.AddProblems(problem, Notification.Problem.Sewage); } } sewageUsage = num10; data.m_sewageBuffer = (ushort)(num7 * 2); } else { sewageUsage = num7; data.m_sewageBuffer += (ushort)num7; } } if (!flag5) { data.m_waterProblemTimer = 0; } if (garbageAccumulation != 0) { int num11 = (int)(65535 - data.m_garbageBuffer); if (num11 < garbageAccumulation) { num = 0; data.m_garbageBuffer = (ushort)num11; } else { //start edit StormDrainAI stormDrainAI = data.Info.m_buildingAI as StormDrainAI; if (stormDrainAI == null) { data.m_garbageBuffer += (ushort)garbageAccumulation; } else if (stormDrainAI.m_filter == false) { data.m_garbageBuffer += (ushort)garbageAccumulation; } else { int pollutantAccumulation = Hydraulics.removePollutants(buildingID, Hydraulics.getPollutants(buildingID)); data.m_garbageBuffer += (ushort)pollutantAccumulation; //Debug.Log("[RF]CommonBuildingAI.handleCommonConsumption garbagebuffer = " + data.m_garbageBuffer.ToString()); } //end edit } } if (num7 != 0) { int num12 = Mathf.Min(num7 * 2, (int)data.m_sewageBuffer); if (num12 > 0) { int num13 = Singleton <WaterManager> .instance.TryDumpSewage(data.m_position, num7 * 2, num12); data.m_sewageBuffer -= (ushort)num13; } } if (garbageAccumulation != 0) { int num14 = (int)data.m_garbageBuffer; if (num14 >= 200 && Singleton <SimulationManager> .instance.m_randomizer.Int32(5u) == 0 && Singleton <UnlockManager> .instance.Unlocked(ItemClass.Service.Garbage)) { int num15 = 0; int num16 = 0; int num17 = 0; int num18 = 0; this.CalculateGuestVehicles(buildingID, ref data, TransferManager.TransferReason.Garbage, ref num15, ref num16, ref num17, ref num18); num14 -= num17 - num16; if (num14 >= 200) { TransferManager.TransferOffer offer = default(TransferManager.TransferOffer); offer.Priority = num14 / 1000; offer.Building = buildingID; offer.Position = data.m_position; offer.Amount = 1; Singleton <TransferManager> .instance.AddOutgoingOffer(TransferManager.TransferReason.Garbage, offer); } } } if (this.CanSufferFromFlood()) { float num19 = Singleton <TerrainManager> .instance.WaterLevel(VectorUtils.XZ(data.m_position)); if (num19 > data.m_position.y) { if (num19 > data.m_position.y + (float)ModSettings.BuildingFloodedTolerance / 100f) { //Debug.Log("[RF].CBAId Detoured Flooded Notification"); num = 0; problem = Notification.AddProblems(problem, Notification.Problem.Flood | Notification.Problem.MajorProblem); } else if (num19 > data.m_position.y + (float)ModSettings.BuildingFloodingTolerance / 100f) { //Debug.Log("[RF].CBAId Detoured Flooding Notification"); num /= 2; problem = Notification.AddProblems(problem, Notification.Problem.Flood); GuideController properties3 = Singleton <GuideManager> .instance.m_properties; if (properties3 != null) { Singleton <BuildingManager> .instance.m_buildingFlooded.Activate(properties3.m_buildingFlooded, buildingID); } } } //Debug.Log("[RF].CBAId Detouring was sucessful!"); } byte district = instance.GetDistrict(data.m_position); instance.m_districts.m_buffer[(int)district].AddUsageData(electricityUsage, heatingUsage, waterUsage, sewageUsage); data.m_problems = problem; return(num); }
// CitizenAI public bool CustomStartPathFind(ushort instanceID, ref CitizenInstance citizenData, Vector3 startPos, Vector3 endPos, VehicleInfo vehicleInfo) { NetInfo.LaneType laneType = NetInfo.LaneType.Pedestrian; VehicleInfo.VehicleType vehicleType = VehicleInfo.VehicleType.None; if (vehicleInfo != null) { if (vehicleInfo.m_class.m_subService == ItemClass.SubService.PublicTransportTaxi) { if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTaxi) == CitizenInstance.Flags.None && Singleton <DistrictManager> .instance.m_districts.m_buffer[0].m_productionData.m_finalTaxiCapacity != 0u) { SimulationManager instance = Singleton <SimulationManager> .instance; if (instance.m_isNightTime || instance.m_randomizer.Int32(2u) == 0) { laneType |= (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle); vehicleType |= vehicleInfo.m_vehicleType; } } } else { laneType |= NetInfo.LaneType.Vehicle; vehicleType |= vehicleInfo.m_vehicleType; } } PathUnit.Position vehiclePosition = default(PathUnit.Position); ushort parkedVehicle = Singleton <CitizenManager> .instance.m_citizens.m_buffer[(int)((UIntPtr)citizenData.m_citizen)].m_parkedVehicle; if (parkedVehicle != 0) { Vector3 position = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[(int)parkedVehicle].m_position; PathManager.FindPathPosition(position, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, false, false, 32f, out vehiclePosition); } bool allowUnderground = (citizenData.m_flags & (CitizenInstance.Flags.Underground | CitizenInstance.Flags.Transition)) != CitizenInstance.Flags.None; PathUnit.Position startPosA; PathUnit.Position endPosA; if (this.FindPathPosition(instanceID, ref citizenData, startPos, laneType, vehicleType, allowUnderground, out startPosA) && this.FindPathPosition(instanceID, ref citizenData, endPos, laneType, vehicleType, false, out endPosA)) { // NON-STOCK CODE START // Citizen.Wealth wealthLevel = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].WealthLevel; byte districtId = Singleton <DistrictManager> .instance.GetDistrict(startPos); DistrictPolicies.Services servicePolicies = Singleton <DistrictManager> .instance.m_districts.m_buffer[(int)districtId].m_servicePolicies; int transportUsageProb = (servicePolicies & DistrictPolicies.Services.FreeTransport) != DistrictPolicies.Services.None ? FREE_TRANSPORT_USAGE_PROBABILITY[(int)wealthLevel] : TRANSPORT_USAGE_PROBABILITY[(int)wealthLevel]; //bool mayUseTransport = false; if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None) // STOCK CODE { if (vehicleInfo == null || (instanceID % 100) + 1 <= transportUsageProb) { laneType |= NetInfo.LaneType.PublicTransport; // STOCK CODE //mayUseTransport = true; //Log._Debug($"CustomCitizenAI: citizen {instanceID} can use public transport"); } } // NON-STOCK CODE END // PathUnit.Position position2 = default(PathUnit.Position); uint path; // NON-STOCK CODE START // ExtVehicleType?extVehicleType = null; if (vehicleInfo != null) { extVehicleType = CustomVehicleAI.DetermineVehicleTypeFromVehicleInfo(vehicleInfo); } //Log._Debug($"CustomCitizenAI: citizen instance {instanceID}, id {citizenData.m_citizen}. {vehicleType} {extVehicleType} mayUseTransport={mayUseTransport} wealthLevel={wealthLevel}"); bool res = false; if (Options.disableSomething5 || extVehicleType == null) { // NON-STOCK CODE END // res = Singleton <CustomPathManager> .instance.CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, position2, endPosA, position2, vehiclePosition, laneType, vehicleType, 20000f, false, false, false, false, false); } // NON-STOCK CODE START // else { res = Singleton <CustomPathManager> .instance.CreatePath((ExtVehicleType)extVehicleType, out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, position2, endPosA, position2, vehiclePosition, laneType, vehicleType, 20000f, false, false, false, false); } // NON-STOCK CODE END // if (res) { if (citizenData.m_path != 0u) { Singleton <PathManager> .instance.ReleasePath(citizenData.m_path); } citizenData.m_path = path; citizenData.m_flags |= CitizenInstance.Flags.WaitingPath; return(true); } } return(false); }
new protected int HandleCommonConsumption(ushort buildingID, ref Building data, ref Building.Frame frameData, ref int electricityConsumption, ref int heatingConsumption, ref int waterConsumption, ref int sewageAccumulation, ref int garbageAccumulation, DistrictPolicies.Services policies) { int num = 100; DistrictManager instance = Singleton <DistrictManager> .instance; Notification.Problem problem = Notification.RemoveProblems(data.m_problems, Notification.Problem.Electricity | Notification.Problem.Water | Notification.Problem.Sewage | Notification.Problem.Flood | Notification.Problem.Heating); bool flag = data.m_electricityProblemTimer != 0; bool flag2 = false; bool flag3 = false; int electricityUsage = 0; int heatingUsage = 0; int waterUsage = 0; int sewageUsage = 0; if (electricityConsumption != 0) { int num2 = Mathf.RoundToInt((20f - Singleton <WeatherManager> .instance.SampleTemperature(data.m_position, false)) * 8f); num2 = Mathf.Clamp(num2, 0, 400); int num3 = heatingConsumption; heatingConsumption = (num3 * num2 + Singleton <SimulationManager> .instance.m_randomizer.Int32(100u)) / 100; if ((policies & DistrictPolicies.Services.PowerSaving) != DistrictPolicies.Services.None) { electricityConsumption = Mathf.Max(1, electricityConsumption * 90 / 100); Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.PolicyCost, 32, this.m_info.m_class); } bool flag4 = false; int num4 = heatingConsumption * 2 - (int)data.m_heatingBuffer; if (num4 > 0 && (policies & DistrictPolicies.Services.OnlyElectricity) == DistrictPolicies.Services.None) { int num5 = Singleton <WaterManager> .instance.TryFetchHeating(data.m_position, heatingConsumption, num4, out flag4); data.m_heatingBuffer += (ushort)num5; } if ((int)data.m_heatingBuffer < heatingConsumption) { if ((policies & DistrictPolicies.Services.NoElectricity) != DistrictPolicies.Services.None) { flag3 = true; data.m_heatingProblemTimer = (byte)Mathf.Min(255, (int)(data.m_heatingProblemTimer + 1)); if (data.m_heatingProblemTimer >= 65) { num = 0; problem = Notification.AddProblems(problem, Notification.Problem.Heating | Notification.Problem.MajorProblem); } else if (data.m_heatingProblemTimer >= 3) { num /= 2; problem = Notification.AddProblems(problem, Notification.Problem.Heating); } } else { num2 = ((num2 + 50) * (heatingConsumption - (int)data.m_heatingBuffer) + heatingConsumption - 1) / heatingConsumption; electricityConsumption += (num3 * num2 + Singleton <SimulationManager> .instance.m_randomizer.Int32(100u)) / 100; if (flag4) { flag3 = true; data.m_heatingProblemTimer = (byte)Mathf.Min(255, (int)(data.m_heatingProblemTimer + 1)); if (data.m_heatingProblemTimer >= 3) { problem = Notification.AddProblems(problem, Notification.Problem.Heating); } } } heatingUsage = (int)data.m_heatingBuffer; data.m_heatingBuffer = 0; } else { heatingUsage = heatingConsumption; data.m_heatingBuffer -= (ushort)heatingConsumption; } int num6; int a; if (this.CanStockpileElectricity(buildingID, ref data, out num6, out a)) { num4 = num6 + electricityConsumption * 2 - (int)data.m_electricityBuffer; if (num4 > 0) { int num7 = electricityConsumption; if ((int)data.m_electricityBuffer < num6) { num7 += Mathf.Min(a, num6 - (int)data.m_electricityBuffer); } int num8 = Singleton <ElectricityManager> .instance.TryFetchElectricity(data.m_position, num7, num4); data.m_electricityBuffer += (ushort)num8; if (num8 < num4 && num8 < num7) { flag2 = true; problem = Notification.AddProblems(problem, Notification.Problem.Electricity); if (data.m_electricityProblemTimer < 64) { data.m_electricityProblemTimer = 64; } } } } else { num4 = electricityConsumption * 2 - (int)data.m_electricityBuffer; if (num4 > 0) { int num9 = Singleton <ElectricityManager> .instance.TryFetchElectricity(data.m_position, electricityConsumption, num4); data.m_electricityBuffer += (ushort)num9; } } if ((int)data.m_electricityBuffer < electricityConsumption) { flag2 = true; data.m_electricityProblemTimer = (byte)Mathf.Min(255, (int)(data.m_electricityProblemTimer + 1)); if (data.m_electricityProblemTimer >= 65) { num = 0; problem = Notification.AddProblems(problem, Notification.Problem.Electricity | Notification.Problem.MajorProblem); } else if (data.m_electricityProblemTimer >= 3) { num /= 2; problem = Notification.AddProblems(problem, Notification.Problem.Electricity); } electricityUsage = (int)data.m_electricityBuffer; data.m_electricityBuffer = 0; if (Singleton <UnlockManager> .instance.Unlocked(ItemClass.Service.Electricity)) { GuideController properties = Singleton <GuideManager> .instance.m_properties; if (properties != null) { int publicServiceIndex = ItemClass.GetPublicServiceIndex(ItemClass.Service.Electricity); int electricityCapacity = instance.m_districts.m_buffer[0].GetElectricityCapacity(); int electricityConsumption2 = instance.m_districts.m_buffer[0].GetElectricityConsumption(); if (electricityCapacity >= electricityConsumption2) { Singleton <GuideManager> .instance.m_serviceNeeded[publicServiceIndex].Activate(properties.m_serviceNeeded2, ItemClass.Service.Electricity); } else { Singleton <GuideManager> .instance.m_serviceNeeded[publicServiceIndex].Activate(properties.m_serviceNeeded, ItemClass.Service.Electricity); } } } } else { electricityUsage = electricityConsumption; data.m_electricityBuffer -= (ushort)electricityConsumption; } } else { heatingConsumption = 0; } if (!flag2) { data.m_electricityProblemTimer = 0; } if (flag != flag2) { Singleton <BuildingManager> .instance.UpdateBuildingColors(buildingID); } if (!flag3) { data.m_heatingProblemTimer = 0; } bool flag5 = false; int num10 = sewageAccumulation; if (waterConsumption != 0) { if ((policies & DistrictPolicies.Services.WaterSaving) != DistrictPolicies.Services.None) { waterConsumption = Mathf.Max(1, waterConsumption * 85 / 100); if (sewageAccumulation != 0) { sewageAccumulation = Mathf.Max(1, sewageAccumulation * 85 / 100); } Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.PolicyCost, 32, this.m_info.m_class); } int num11; int a2; if (this.CanStockpileWater(buildingID, ref data, out num11, out a2)) { int num12 = num11 + waterConsumption * 2 - (int)data.m_waterBuffer; if (num12 > 0) { int num13 = waterConsumption; if ((int)data.m_waterBuffer < num11) { num13 += Mathf.Min(a2, num11 - (int)data.m_waterBuffer); } int num14 = Singleton <WaterManager> .instance.TryFetchWater(data.m_position, num13, num12, ref data.m_waterPollution); data.m_waterBuffer += (ushort)num14; if (num14 < num12 && num14 < num13) { flag5 = true; problem = Notification.AddProblems(problem, Notification.Problem.Water); if (data.m_waterProblemTimer < 64) { data.m_waterProblemTimer = 64; } } } } else { int num15 = waterConsumption * 2 - (int)data.m_waterBuffer; if (num15 > 0) { int num16 = Singleton <WaterManager> .instance.TryFetchWater(data.m_position, waterConsumption, num15, ref data.m_waterPollution); data.m_waterBuffer += (ushort)num16; } } if ((int)data.m_waterBuffer < waterConsumption) { flag5 = true; data.m_waterProblemTimer = (byte)Mathf.Min(255, (int)(data.m_waterProblemTimer + 1)); if (data.m_waterProblemTimer >= 65) { num = 0; problem = Notification.AddProblems(problem, Notification.Problem.Water | Notification.Problem.MajorProblem); } else if (data.m_waterProblemTimer >= 3) { num /= 2; problem = Notification.AddProblems(problem, Notification.Problem.Water); } num10 = sewageAccumulation * (waterConsumption + (int)data.m_waterBuffer) / (waterConsumption << 1); waterUsage = (int)data.m_waterBuffer; data.m_waterBuffer = 0; if (Singleton <UnlockManager> .instance.Unlocked(ItemClass.Service.Water)) { GuideController properties2 = Singleton <GuideManager> .instance.m_properties; if (properties2 != null) { int publicServiceIndex2 = ItemClass.GetPublicServiceIndex(ItemClass.Service.Water); int waterCapacity = instance.m_districts.m_buffer[0].GetWaterCapacity(); int waterConsumption2 = instance.m_districts.m_buffer[0].GetWaterConsumption(); if (waterCapacity >= waterConsumption2) { Singleton <GuideManager> .instance.m_serviceNeeded[publicServiceIndex2].Activate(properties2.m_serviceNeeded2, ItemClass.Service.Water); } else { Singleton <GuideManager> .instance.m_serviceNeeded[publicServiceIndex2].Activate(properties2.m_serviceNeeded, ItemClass.Service.Water); } } } } else { num10 = sewageAccumulation; waterUsage = waterConsumption; data.m_waterBuffer -= (ushort)waterConsumption; } } int num17; int b; if (this.CanStockpileWater(buildingID, ref data, out num17, out b)) { int num18 = Mathf.Max(0, num17 + num10 * 2 - (int)data.m_sewageBuffer); if (num18 < num10) { if (!flag5 && (data.m_problems & Notification.Problem.Water) == Notification.Problem.None) { flag5 = true; data.m_waterProblemTimer = (byte)Mathf.Min(255, (int)(data.m_waterProblemTimer + 1)); if (data.m_waterProblemTimer >= 65) { num = 0; problem = Notification.AddProblems(problem, Notification.Problem.Sewage | Notification.Problem.MajorProblem); } else if (data.m_waterProblemTimer >= 3) { num /= 2; problem = Notification.AddProblems(problem, Notification.Problem.Sewage); } } sewageUsage = num18; data.m_sewageBuffer = (ushort)(num17 + num10 * 2); } else { sewageUsage = num10; data.m_sewageBuffer += (ushort)num10; } int num19 = num10 + Mathf.Max(num10, b); num18 = Mathf.Min(num19, (int)data.m_sewageBuffer); if (num18 > 0) { int num20 = Singleton <WaterManager> .instance.TryDumpSewage(data.m_position, num19, num18); data.m_sewageBuffer -= (ushort)num20; if (num20 < num19 && num20 < num18 && !flag5 && (data.m_problems & Notification.Problem.Water) == Notification.Problem.None) { flag5 = true; problem = Notification.AddProblems(problem, Notification.Problem.Sewage); if (data.m_waterProblemTimer < 64) { data.m_waterProblemTimer = 64; } } } } else if (num10 != 0) { int num21 = Mathf.Max(0, num10 * 2 - (int)data.m_sewageBuffer); if (num21 < num10) { if (!flag5 && (data.m_problems & Notification.Problem.Water) == Notification.Problem.None) { flag5 = true; data.m_waterProblemTimer = (byte)Mathf.Min(255, (int)(data.m_waterProblemTimer + 1)); if (data.m_waterProblemTimer >= 65) { num = 0; problem = Notification.AddProblems(problem, Notification.Problem.Sewage | Notification.Problem.MajorProblem); } else if (data.m_waterProblemTimer >= 3) { num /= 2; problem = Notification.AddProblems(problem, Notification.Problem.Sewage); } } sewageUsage = num21; data.m_sewageBuffer = (ushort)(num10 * 2); } else { sewageUsage = num10; data.m_sewageBuffer += (ushort)num10; } num21 = Mathf.Min(num10 * 2, (int)data.m_sewageBuffer); if (num21 > 0) { int num22 = Singleton <WaterManager> .instance.TryDumpSewage(data.m_position, num10 * 2, num21); data.m_sewageBuffer -= (ushort)num22; } } if (!flag5) { data.m_waterProblemTimer = 0; } if (garbageAccumulation != 0) { int num23 = (int)(65535 - data.m_garbageBuffer); if (num23 < garbageAccumulation) { num = 0; data.m_garbageBuffer = (ushort)num23; } else { //start edit StormDrainAI stormDrainAI = data.Info.m_buildingAI as StormDrainAI; if (stormDrainAI == null) { data.m_garbageBuffer += (ushort)garbageAccumulation; } else if (stormDrainAI.m_filter == false) { data.m_garbageBuffer += (ushort)garbageAccumulation; } else { int pollutantAccumulation = Hydraulics.removePollutants(buildingID, Hydraulics.getPollutants(buildingID)); data.m_garbageBuffer += (ushort)pollutantAccumulation; //Debug.Log("[RF]CommonBuildingAI.handleCommonConsumption garbagebuffer = " + data.m_garbageBuffer.ToString()); } //end edit } } if (garbageAccumulation != 0) { int num24 = (int)data.m_garbageBuffer; if (num24 >= 200 && Singleton <SimulationManager> .instance.m_randomizer.Int32(5u) == 0 && Singleton <UnlockManager> .instance.Unlocked(ItemClass.Service.Garbage)) { int num25 = 0; int num26 = 0; int num27 = 0; int num28 = 0; this.CalculateGuestVehicles(buildingID, ref data, TransferManager.TransferReason.Garbage, ref num25, ref num26, ref num27, ref num28); num24 -= num27 - num26; if (num24 >= 200) { TransferManager.TransferOffer offer = default(TransferManager.TransferOffer); offer.Priority = num24 / 1000; offer.Building = buildingID; offer.Position = data.m_position; offer.Amount = 1; Singleton <TransferManager> .instance.AddOutgoingOffer(TransferManager.TransferReason.Garbage, offer); } } } bool flag6; if (this.CanSufferFromFlood(out flag6)) { float num29 = Singleton <TerrainManager> .instance.WaterLevel(VectorUtils.XZ(data.m_position)); if (num29 > data.m_position.y) { bool flag7 = num29 > data.m_position.y + Mathf.Max(4f, this.m_info.m_collisionHeight); if ((!flag6 || flag7) && (data.m_flags & Building.Flags.Flooded) == Building.Flags.None && data.m_fireIntensity == 0) { DisasterManager instance2 = Singleton <DisasterManager> .instance; ushort num30 = instance2.FindDisaster <FloodBaseAI>(data.m_position); if (num30 == 0) { DisasterInfo disasterInfo = DisasterManager.FindDisasterInfo <GenericFloodAI>(); if (disasterInfo != null && instance2.CreateDisaster(out num30, disasterInfo)) { instance2.m_disasters.m_buffer[(int)num30].m_intensity = 10; instance2.m_disasters.m_buffer[(int)num30].m_targetPosition = data.m_position; disasterInfo.m_disasterAI.StartNow(num30, ref instance2.m_disasters.m_buffer[(int)num30]); } } if (num30 != 0) { InstanceID srcID = default(InstanceID); InstanceID dstID = default(InstanceID); srcID.Disaster = num30; dstID.Building = buildingID; Singleton <InstanceManager> .instance.CopyGroup(srcID, dstID); DisasterInfo info = instance2.m_disasters.m_buffer[(int)num30].Info; info.m_disasterAI.ActivateNow(num30, ref instance2.m_disasters.m_buffer[(int)num30]); if ((instance2.m_disasters.m_buffer[(int)num30].m_flags & DisasterData.Flags.Significant) != DisasterData.Flags.None) { instance2.DetectDisaster(num30, false); instance2.FollowDisaster(num30); } } data.m_flags |= Building.Flags.Flooded; } if (flag7) { frameData.m_constructState = (byte)Mathf.Max(0, (int)frameData.m_constructState - 1088 / this.GetCollapseTime()); data.SetFrameData(Singleton <SimulationManager> .instance.m_currentFrameIndex, frameData); InstanceID id = default(InstanceID); id.Building = buildingID; InstanceManager.Group group = Singleton <InstanceManager> .instance.GetGroup(id); if (group != null) { ushort disaster = group.m_ownerInstance.Disaster; if (disaster != 0) { DisasterData[] expr_D18_cp_0 = Singleton <DisasterManager> .instance.m_disasters.m_buffer; ushort expr_D18_cp_1 = disaster; expr_D18_cp_0[(int)expr_D18_cp_1].m_collapsedCount = (ushort)(expr_D18_cp_0[(int)expr_D18_cp_1].m_collapsedCount + 1); } } if (frameData.m_constructState == 0) { Singleton <InstanceManager> .instance.SetGroup(id, null); } data.m_levelUpProgress = 0; data.m_fireIntensity = 0; data.m_garbageBuffer = 0; data.m_flags |= Building.Flags.Collapsed; num = 0; this.RemovePeople(buildingID, ref data, 90); this.BuildingDeactivated(buildingID, ref data); if (this.m_info.m_hasParkingSpaces != VehicleInfo.VehicleType.None) { Singleton <BuildingManager> .instance.UpdateParkingSpaces(buildingID, ref data); } Singleton <BuildingManager> .instance.UpdateBuildingRenderer(buildingID, true); Singleton <BuildingManager> .instance.UpdateBuildingColors(buildingID); GuideController properties3 = Singleton <GuideManager> .instance.m_properties; if (properties3 != null) { Singleton <BuildingManager> .instance.m_buildingFlooded.Deactivate(buildingID, false); Singleton <BuildingManager> .instance.m_buildingFlooded2.Deactivate(buildingID, false); } } else if (!flag6) { if ((data.m_flags & Building.Flags.RoadAccessFailed) == Building.Flags.None) { int num31 = 0; int num32 = 0; int num33 = 0; int num34 = 0; this.CalculateGuestVehicles(buildingID, ref data, TransferManager.TransferReason.FloodWater, ref num31, ref num32, ref num33, ref num34); if (num31 == 0) { TransferManager.TransferOffer offer2 = default(TransferManager.TransferOffer); offer2.Priority = 5; offer2.Building = buildingID; offer2.Position = data.m_position; offer2.Amount = 1; Singleton <TransferManager> .instance.AddOutgoingOffer(TransferManager.TransferReason.FloodWater, offer2); } } if (num29 > data.m_position.y + (float)ModSettings.BuildingFloodedTolerance / 100f) { num = 0; problem = Notification.AddProblems(problem, Notification.Problem.Flood | Notification.Problem.MajorProblem); } else if (num29 > data.m_position.y + (float)ModSettings.BuildingFloodingTolerance / 100f) { num /= 2; problem = Notification.AddProblems(problem, Notification.Problem.Flood); } GuideController properties4 = Singleton <GuideManager> .instance.m_properties; if (properties4 != null) { if (Singleton <LoadingManager> .instance.SupportsExpansion(Expansion.NaturalDisasters) && Singleton <UnlockManager> .instance.Unlocked(UnlockManager.Feature.WaterPumping)) { Singleton <BuildingManager> .instance.m_buildingFlooded2.Activate(properties4.m_buildingFlooded2, buildingID); } else { Singleton <BuildingManager> .instance.m_buildingFlooded.Activate(properties4.m_buildingFlooded, buildingID); } } } } else if ((data.m_flags & Building.Flags.Flooded) != Building.Flags.None) { InstanceID id2 = default(InstanceID); id2.Building = buildingID; Singleton <InstanceManager> .instance.SetGroup(id2, null); data.m_flags &= ~Building.Flags.Flooded; } } byte district = instance.GetDistrict(data.m_position); instance.m_districts.m_buffer[(int)district].AddUsageData(electricityUsage, heatingUsage, waterUsage, sewageUsage); data.m_problems = problem; return(num); }
protected override void ProduceGoods(ushort buildingID, ref Building buildingData, ref Building.Frame frameData, int productionRate, int finalProductionRate, ref Citizen.BehaviourData behaviour, int aliveWorkerCount, int totalWorkerCount, int workPlaceCount, int aliveVisitorCount, int totalVisitorCount, int visitPlaceCount) { DistrictManager instance = Singleton <DistrictManager> .instance; byte district = instance.GetDistrict(buildingData.m_position); DistrictPolicies.Services servicePolicies = instance.m_districts.m_buffer[(int)district].m_servicePolicies; Notification.Problem problem = Notification.RemoveProblems(buildingData.m_problems, Notification.Problem.WaterNotConnected | Notification.Problem.NoResources | Notification.Problem.NoNaturalResources | Notification.Problem.FishFarmWaterDirty | Notification.Problem.NoPlaceForFishingGoods); int num = 0; int num2 = 0; int num3 = 0; if (this.m_extractionPositions != null && this.m_extractionPositions.Length > 0) { for (int i = 0; i < this.m_extractionPositions.Length; i++) { Vector3 position = buildingData.CalculatePosition(this.m_extractionPositions[i]); int b; int num4; int value; Singleton <TerrainManager> .instance.CountWaterCoverage(position, 20f, out b, out num4, out value); num += Mathf.Clamp(value, 0, 128); num3 = Mathf.Max(num3, b); } if (this.m_info.name == "Algae Tank") { this.m_info.m_placementMode = BuildingInfo.PlacementMode.Roadside; num2 = 0; num3 = 1; } else { num2 = num / this.m_extractionPositions.Length; } } else { finalProductionRate = 0; } if (num2 > 32) { GuideController properties = Singleton <GuideManager> .instance.m_properties; if (properties != null) { Singleton <BuildingManager> .instance.m_fishingPollutionDetected.Activate(properties.m_fishingPollutionDetected, buildingID); } } if (num3 == 0) { finalProductionRate = 0; } if (finalProductionRate != 0) { int num5 = finalProductionRate; if (num2 > 96) { problem = (Notification.Problem.FishFarmWaterDirty | Notification.Problem.FatalProblem); } else if (num2 > 64) { problem = Notification.AddProblems(problem, Notification.Problem.FishFarmWaterDirty | Notification.Problem.MajorProblem); } else if (num2 > 32) { problem = Notification.AddProblems(problem, Notification.Problem.FishFarmWaterDirty); } finalProductionRate = finalProductionRate * Mathf.Clamp(255 - num2 * 2, 0, 255) / 255; int num6 = finalProductionRate * this.m_noiseAccumulation / 100; if (num6 != 0) { Singleton <ImmaterialResourceManager> .instance.AddResource(ImmaterialResourceManager.Resource.NoisePollution, num6, buildingData.m_position, this.m_noiseRadius); } base.HandleDead(buildingID, ref buildingData, ref behaviour, totalWorkerCount); int num7 = 0; int num8 = 0; if (this.m_outputResource != TransferManager.TransferReason.None) { int num9 = (this.m_productionRate * finalProductionRate + 99) / 100; if (this.m_info.m_class.m_level == ItemClass.Level.Level3 && (servicePolicies & DistrictPolicies.Services.AlgaeBasedWaterFiltering) != DistrictPolicies.Services.None) { District[] buffer = instance.m_districts.m_buffer; byte b2 = district; buffer[(int)b2].m_servicePoliciesEffect = (buffer[(int)b2].m_servicePoliciesEffect | DistrictPolicies.Services.AlgaeBasedWaterFiltering); num9 = (num9 * 50 + 49) / 100; } int cycleBufferSize = this.GetCycleBufferSize(buildingID, ref buildingData); int num10 = (int)buildingData.m_customBuffer1; num7 = this.GetStorageBufferSize(buildingID, ref buildingData); num8 = (int)(buildingData.m_customBuffer2 * 100); if (num9 >= cycleBufferSize - num10) { if (cycleBufferSize > num7 - num8) { num9 = cycleBufferSize - num10; num10 = cycleBufferSize; problem = Notification.AddProblems(problem, Notification.Problem.NoPlaceForFishingGoods); } else { num10 = num10 + num9 - cycleBufferSize; num8 += cycleBufferSize; } } else { num10 += num9; } Singleton <StatisticsManager> .instance.Acquire <StatisticInt64>(StatisticType.FishFarmed).Add(num9); buildingData.m_customBuffer1 = (ushort)num10; buildingData.m_customBuffer2 = (ushort)(num8 / 100); } if (this.m_outputResource != TransferManager.TransferReason.None) { int num11 = (num5 * this.m_outputVehicleCount + 99) / 100; int num12 = 0; int num13 = 0; int num14 = 0; int value2 = 0; base.CalculateOwnVehicles(buildingID, ref buildingData, this.m_outputResource, ref num12, ref num13, ref num14, ref value2); buildingData.m_tempExport = (byte)Mathf.Clamp(value2, (int)buildingData.m_tempExport, 255); if (buildingData.m_finalExport != 0) { District[] buffer2 = instance.m_districts.m_buffer; byte b3 = district; buffer2[(int)b3].m_playerConsumption.m_finalExportAmount = buffer2[(int)b3].m_playerConsumption.m_finalExportAmount + (uint)buildingData.m_finalExport; } int num15 = num8; if (num15 >= 8000 && num12 < num11) { TransferManager.TransferOffer offer = default(TransferManager.TransferOffer); offer.Priority = Mathf.Max(1, num15 * 8 / num7); offer.Building = buildingID; offer.Position = buildingData.m_position; offer.Amount = 1; offer.Active = true; Singleton <TransferManager> .instance.AddOutgoingOffer(this.m_outputResource, offer); } } } buildingData.m_problems = problem; buildingData.m_education3 = (byte)Mathf.Clamp(finalProductionRate * this.m_productionRate / Mathf.Max(1, this.m_productionRate), 0, 255); base.ProduceGoods(buildingID, ref buildingData, ref frameData, productionRate, finalProductionRate, ref behaviour, aliveWorkerCount, totalWorkerCount, workPlaceCount, aliveVisitorCount, totalVisitorCount, visitPlaceCount); }
// CitizenAI public bool CustomStartPathFind(ushort instanceID, ref CitizenInstance citizenData, Vector3 startPos, Vector3 endPos, VehicleInfo vehicleInfo) { CitizenManager citMan = Singleton <CitizenManager> .instance; if (citMan.m_citizens.m_buffer[citizenData.m_citizen].CurrentLocation == Citizen.Location.Home) { currentTransportMode[instanceID] = TransportMode.None; // reset currently used transport mode at home } SimulationManager simManager = Singleton <SimulationManager> .instance; Citizen.Wealth wealthLevel = citMan.m_citizens.m_buffer[citizenData.m_citizen].WealthLevel; bool couldUseTaxi = false; // could cim use a taxi if it was not forbidden because of randomization? bool couldUseCar = false; bool couldUseBike = false; bool wouldAffordTaxiVoluntarily = false; bool randomParking = false; if (vehicleInfo != null) { if (vehicleInfo.m_class.m_subService == ItemClass.SubService.PublicTransportTaxi) { if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTaxi) == CitizenInstance.Flags.None && Singleton <DistrictManager> .instance.m_districts.m_buffer[0].m_productionData.m_finalTaxiCapacity != 0u) { couldUseTaxi = true; if (currentTransportMode[instanceID] == TransportMode.Taxi || (currentTransportMode[instanceID] == TransportMode.None && ((simManager.m_isNightTime && simManager.m_randomizer.Int32(100) < NIGHT_TAXI_USAGE_PROBABILITY[(int)wealthLevel]) || (!simManager.m_isNightTime && simManager.m_randomizer.Int32(100) < DAY_TAXI_USAGE_PROBABILITY[(int)wealthLevel])))) { wouldAffordTaxiVoluntarily = true; // NON-STOCK CODE } } } else { // NON-STOCK CODE START if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Bicycle) { couldUseBike = true; } else if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Car) { couldUseCar = true; } // NON-STOCK CODE END if (citizenData.m_targetBuilding != 0 && Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)citizenData.m_targetBuilding].Info.m_class.m_service > ItemClass.Service.Office) { randomParking = true; } } } byte districtId = Singleton <DistrictManager> .instance.GetDistrict(startPos); DistrictPolicies.Services servicePolicies = Singleton <DistrictManager> .instance.m_districts.m_buffer[(int)districtId].m_servicePolicies; int transportUsageProb = (servicePolicies & DistrictPolicies.Services.FreeTransport) != DistrictPolicies.Services.None ? FREE_TRANSPORT_USAGE_PROBABILITY[(int)wealthLevel] : TRANSPORT_USAGE_PROBABILITY[(int)wealthLevel]; bool useTaxi = false; bool useBike = false; bool useCar = false; bool usePublicTransport = false; if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None) // STOCK CODE { if (currentTransportMode[instanceID] == TransportMode.PublicTransport || useTaxi || (currentTransportMode[instanceID] == TransportMode.None && simManager.m_randomizer.Int32(100) < transportUsageProb)) { usePublicTransport = true; } } ushort parkedVehicle = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].m_parkedVehicle; bool couldUseParkedCar = false; // cims are not allowed to use pocket cars (unless we have no choice) PathUnit.Position vehiclePosition = default(PathUnit.Position); if (parkedVehicle != 0) { Vector3 position = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[(int)parkedVehicle].m_position; if (PathManager.FindPathPosition(position, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, false, false, 32f, out vehiclePosition)) { couldUseParkedCar = true; } } if (couldUseBike) { // everyone who has a bike may use it useBike = true; } if (!usePublicTransport) { if (couldUseParkedCar && currentTransportMode[instanceID] == TransportMode.Car) { useCar = true; } else if ((wouldAffordTaxiVoluntarily && currentTransportMode[instanceID] == TransportMode.Taxi) || couldUseTaxi) { useTaxi = true; } else if (couldUseCar) { // pocket car fallback useCar = true; } } ExtVehicleType extVehicleType = ExtVehicleType.None; NetInfo.LaneType laneType = NetInfo.LaneType.Pedestrian; VehicleInfo.VehicleType vehicleType = VehicleInfo.VehicleType.None; if (usePublicTransport) { currentTransportMode[instanceID] = TransportMode.PublicTransport; laneType |= NetInfo.LaneType.PublicTransport; extVehicleType |= ExtVehicleType.PublicTransport; } if (useBike && vehicleInfo != null) { laneType |= NetInfo.LaneType.Vehicle; vehicleType |= vehicleInfo.m_vehicleType; extVehicleType |= ExtVehicleType.Bicycle; } if (useTaxi && vehicleInfo != null) { currentTransportMode[instanceID] = TransportMode.Taxi; laneType |= (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle); vehicleType |= vehicleInfo.m_vehicleType; extVehicleType |= ExtVehicleType.Taxi; } if (useCar && vehicleInfo != null) { currentTransportMode[instanceID] = TransportMode.Car; laneType |= NetInfo.LaneType.Vehicle; vehicleType |= vehicleInfo.m_vehicleType; extVehicleType |= ExtVehicleType.PassengerCar; } //Log._Debug($"Citizen {instanceID}: usePublicTransport={usePublicTransport} useCar={useCar} useTaxi={useTaxi} useBike={useBike} vehicleInfo.vehicleType={vehicleInfo?.m_vehicleType} laneType={laneType} vehicleType={vehicleType} extVehicleType={extVehicleType}"); bool allowUnderground = (citizenData.m_flags & (CitizenInstance.Flags.Underground | CitizenInstance.Flags.Transition)) != CitizenInstance.Flags.None; PathUnit.Position startPosA; PathUnit.Position endPosA; if (this.FindPathPosition(instanceID, ref citizenData, startPos, laneType, vehicleType, allowUnderground, out startPosA) && this.FindPathPosition(instanceID, ref citizenData, endPos, laneType, vehicleType, false, out endPosA)) { PathUnit.Position position2 = default(PathUnit.Position); uint path; #if DEBUG //Log._Debug($"CustomCitizenAI: citizen instance {instanceID}, id {citizenData.m_citizen}. vehicleType={vehicleType} laneType={laneType} extVehicleType={extVehicleType} usePublicTransport={usePublicTransport} useTaxi={useTaxi} useBike={useBike} useCar={useCar} wealthLevel={wealthLevel}"); #endif // NON-STOCK CODE END // if (Singleton <CustomPathManager> .instance.CreatePath(false, (ExtVehicleType)extVehicleType, null, out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, position2, endPosA, position2, vehiclePosition, laneType, vehicleType, 20000f, false, false, false, false, randomParking)) { if (citizenData.m_path != 0u) { Singleton <PathManager> .instance.ReleasePath(citizenData.m_path); } citizenData.m_path = path; citizenData.m_flags |= CitizenInstance.Flags.WaitingPath; return(true); } } return(false); }
internal void GetIncome(ushort buildingID, Building buildingData, ref int income, ref int tourists) { DistrictManager instance = Singleton <DistrictManager> .instance; byte district = instance.GetDistrict(buildingData.m_position); DistrictPolicies.Services servicePolicies = instance.m_districts.m_buffer[(int)district].m_servicePolicies; ItemClass.Zone zone = buildingData.Info.m_class.GetZone(); int baseIncome = 0;// GetBaseIncome(buildingData.Info.m_class.m_level, zone); if ((servicePolicies & DistrictPolicies.Services.Recycling) != DistrictPolicies.Services.None) { baseIncome = baseIncome * 95 / 100; } int percentage = 100; if (zone == ItemClass.Zone.ResidentialHigh || zone == ItemClass.Zone.ResidentialLow) { GetCitizenIncome(CitizenUnit.Flags.Home, buildingData, ref income, ref tourists); } else if (zone == ItemClass.Zone.CommercialHigh || zone == ItemClass.Zone.CommercialLow) { GetCitizenIncome(CitizenUnit.Flags.Visit, buildingData, ref income, ref tourists); DistrictPolicies.CityPlanning cityPlanningPolicies = instance.m_districts.m_buffer[(int)district].m_cityPlanningPolicies; if (buildingData.Info.m_class.m_subService == ItemClass.SubService.CommercialLow) { if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.SmallBusiness) != DistrictPolicies.CityPlanning.None) { baseIncome += 20; } } else if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.BigBusiness) != DistrictPolicies.CityPlanning.None) { baseIncome += 20; } if ((servicePolicies & DistrictPolicies.Services.RecreationalUse) != DistrictPolicies.Services.None) { baseIncome = (baseIncome * 105 + 99) / 100; } if (buildingData.m_outgoingProblemTimer >= 128 || buildingData.m_customBuffer1 == 0) { percentage = 0; } } else if (zone == ItemClass.Zone.Industrial) { GetCitizenIncome(CitizenUnit.Flags.Work, buildingData, ref income, ref tourists); if (buildingData.m_outgoingProblemTimer >= 128 || buildingData.m_customBuffer1 == 0) { percentage = 0; } } else if (zone == ItemClass.Zone.Office) { GetCitizenIncome(CitizenUnit.Flags.Work, buildingData, ref income, ref tourists); } income = (income * baseIncome + 99) / 100; tourists = (tourists * baseIncome + 99) / 100; if (buildingData.m_electricityProblemTimer >= 1 || buildingData.m_waterProblemTimer >= 1 || buildingData.m_waterProblemTimer >= 1 || buildingData.m_garbageBuffer > 60000) { percentage = 0; } float num18 = Singleton <TerrainManager> .instance.WaterLevel(VectorUtils.XZ(buildingData.m_position)); if (num18 > buildingData.m_position.y) { percentage = 0; } income = (income * percentage + 99) / 100; tourists = (tourists * percentage * 2 + 99) / 100; }