public static List <uint> GetAllCitizens(this Building building, CitizenUnit.Flags flags) { var citizenUnitId = building.m_citizenUnits; var citizenManager = CitizenManager.instance; var citizens = new List <uint>(); while (citizenUnitId != 0) { var citizenUnit = CitizenManager.instance.m_units.m_buffer[citizenUnitId]; if ((citizenUnit.m_flags & flags) != CitizenUnit.Flags.None) { var citizenIds = new [] { citizenUnit.m_citizen0, citizenUnit.m_citizen1, citizenUnit.m_citizen2, citizenUnit.m_citizen3, citizenUnit.m_citizen4 }; foreach (var citizenId in citizenIds) { if (citizenId > 0) { citizens.Add(citizenId); } } } citizenUnitId = citizenUnit.m_nextUnit; } return(citizens); }
public static bool HasCitizensInside(this Building building, CitizenUnit.Flags flags, int maxRecurseAmount = 5) { return(building.AnyCitizenInside(flags, citizenId => { return true; }, maxRecurseAmount)); }
public static List <uint> GetAllCitizensInside(this Building building, CitizenUnit.Flags flags) { var citizens = building.GetAllCitizens(flags); var citizensInBuilding = new List <uint>(); foreach (var citizenId in citizens) { if (citizenId > 0) { var citizen = CitizenManager.instance.m_citizens.m_buffer[citizenId]; var citizenBuilding = citizen.GetBuilding(); if (building.Same(citizenBuilding)) { citizensInBuilding.Add(citizenId); } } } return(citizensInBuilding); }
public static bool AnyCitizenInside(this Building building, CitizenUnit.Flags flags, Func <uint, bool> checkFunction, int maxRecurseAmount = 5) { var citizenUnitId = building.m_citizenUnits; while (citizenUnitId != 0 && maxRecurseAmount-- > 0) { var citizenUnit = CitizenManager.instance.m_units.m_buffer[citizenUnitId]; if ((citizenUnit.m_flags & flags) != CitizenUnit.Flags.None) { var citizenIds = new[] { citizenUnit.m_citizen0, citizenUnit.m_citizen1, citizenUnit.m_citizen2, citizenUnit.m_citizen3, citizenUnit.m_citizen4 }; foreach (var citizenId in citizenIds) { if (citizenId > 0) { var citizen = CitizenManager.instance.m_citizens.m_buffer[citizenId]; var citizenBuilding = citizen.GetBuilding(); if (building.Same(citizenBuilding) && checkFunction.Invoke(citizenId)) { return(true); } } } } citizenUnitId = citizenUnit.m_nextUnit; } return(false); }
public void GetCitizenIncome(CitizenUnit.Flags flags, Building buildingData, ref int income, ref int tourists) { int level = 0; UnlockManager um = Singleton <UnlockManager> .instance; if (!um.Unlocked(ItemClass.SubService.PublicTransportMetro)) { level += 1; if (!um.Unlocked(ItemClass.Service.PublicTransport)) { level += 1; if (!um.Unlocked(ItemClass.Service.HealthCare)) { level += 1; } } } CitizenManager instance = Singleton <CitizenManager> .instance; uint num = buildingData.m_citizenUnits; int num2 = 0; while (num != 0u) { if ((ushort)(instance.m_units.m_buffer[(int)((UIntPtr)num)].m_flags & flags) != 0) { GetCitizenIncome(instance.m_units.m_buffer[(int)((UIntPtr)num)], level, ref income, ref tourists); } num = instance.m_units.m_buffer[(int)((UIntPtr)num)].m_nextUnit; if (++num2 > 524288) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } }
internal static void EnsureCitizenUnits(ref PrivateBuildingAI __instance, ushort buildingID, ref Building data, int homeCount, int workCount, int visitCount, int studentCount) { int totalWorkCount = (workCount + 4) / 5; int totalVisitCount = (visitCount + 4) / 5; int totalHomeCount = homeCount; int[] workersRequired = new int[] { 0, 0, 0, 0 }; if ((data.m_flags & (Building.Flags.Abandoned | Building.Flags.BurnedDown)) == Building.Flags.None) { Citizen.Wealth wealthLevel = Citizen.GetWealthLevel(__instance.m_info.m_class.m_level); uint num = 0u; uint num2 = data.m_citizenUnits; int num3 = 0; while (num2 != 0u) { CitizenUnit.Flags flags = citizenUnitArray[(int)((UIntPtr)num2)].m_flags; if ((ushort)(flags & CitizenUnit.Flags.Home) != 0) { citizenUnitArray[(int)((UIntPtr)num2)].SetWealthLevel(wealthLevel); homeCount--; } if ((ushort)(flags & CitizenUnit.Flags.Work) != 0) { workCount -= 5; for (int i = 0; i < 5; i++) { uint citizen = citizenUnitArray[(int)((UIntPtr)num2)].GetCitizen(i); if (citizen != 0u) { // Tick off education to see what is there workersRequired[(int)citizenArray[(int)((UIntPtr)citizen)].EducationLevel]--; } } } if ((ushort)(flags & CitizenUnit.Flags.Visit) != 0) { visitCount -= 5; } if ((ushort)(flags & CitizenUnit.Flags.Student) != 0) { studentCount -= 5; } num = num2; num2 = citizenUnitArray[(int)((UIntPtr)num2)].m_nextUnit; if (++num3 > 524288) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } // end while /* * homeCount = Mathf.Max(0, homeCount); * workCount = Mathf.Max(0, workCount); */ visitCount = Mathf.Max(0, visitCount); studentCount = Mathf.Max(0, studentCount); if (homeCount > 0 || workCount > 0 || visitCount > 0 || studentCount > 0) { uint num4 = 0u; if (citizenManager.CreateUnits(out num4, ref Singleton <SimulationManager> .instance.m_randomizer, buildingID, 0, homeCount, workCount, visitCount, 0, studentCount)) { if (num != 0u) { citizenUnitArray[(int)((UIntPtr)num)].m_nextUnit = num4; } else { data.m_citizenUnits = num4; } } } // Stop incoming offers to get HandleWorkers() to start fresh TransferManager.TransferOffer offer = default(TransferManager.TransferOffer); offer.Building = buildingID; Singleton <TransferManager> .instance.RemoveIncomingOffer(TransferManager.TransferReason.Worker0, offer); Singleton <TransferManager> .instance.RemoveIncomingOffer(TransferManager.TransferReason.Worker1, offer); Singleton <TransferManager> .instance.RemoveIncomingOffer(TransferManager.TransferReason.Worker2, offer); Singleton <TransferManager> .instance.RemoveIncomingOffer(TransferManager.TransferReason.Worker3, offer); int worker0 = 0; int worker1 = 0; int worker2 = 0; int worker3 = 0; ItemClass.Level level = ((PrivateBuildingAI)data.Info.GetAI()).m_info.m_class.m_level; ((PrivateBuildingAI)data.Info.GetAI()).CalculateWorkplaceCount(level, new Randomizer((int)buildingID), data.Width, data.Length, out worker0, out worker1, out worker2, out worker3); // Update the workers required once figuring out how many are needed by the new building workersRequired[0] += worker0; workersRequired[1] += worker1; workersRequired[2] += worker2; workersRequired[3] += worker3; if (workCount < 0) { RemoveWorkerBuilding(buildingID, ref data, totalWorkCount); } else if (homeCount < 0) { RemoveHouseHold(buildingID, ref data, totalHomeCount); } /* * if (visitCount < 0) * { * RemoveVisitorsBuilding(buildingID, ref data, totalVisitCount); * } */ PromoteWorkers(buildingID, ref data, ref workersRequired); // Do nothing for students } // end if good building } // end EnsureCitizenUnits
/// <summary>Gets the unit ID that contains the specified citizen.</summary> /// <param name="citizen">The citizen to get the unit ID for.</param> /// <param name="citizenId">The ID of the citizen to get the unit ID for.</param> /// <param name="unitId">The unit ID of the citizen's building specified by the <paramref name="flag"/>.</param> /// <param name="flag">The citizen unit mode.</param> /// <returns>An ID of the citizen unit that contains the specified citizen</returns> public uint GetContainingUnit(ref Citizen citizen, uint citizenId, uint unitId, CitizenUnit.Flags flag) { if (citizenId == 0 || unitId == 0 || flag == CitizenUnit.Flags.None) { return(0); } return(citizen.GetContainingUnit(citizenId, unitId, flag)); }
/// <summary> /// Removes CitizenUnits that are surplus to requirements from the specified building. /// </summary> /// <param name="building">Building reference</param> /// <param name="homeCount">Number of households to apply</param> /// <param name="workCount">Number of workplaces to apply</param> /// <param name="visitCount">Number of visitplaces to apply</param> /// <param name="studentCount">Number of student places to apply</param> internal static void RemoveCitizenUnits(ref Building building, int homeCount, int workCount, int visitCount, int studentCount) { // Local references. CitizenManager citizenManager = Singleton <CitizenManager> .instance; CitizenUnit[] citizenUnits = citizenManager.m_units.m_buffer; // Set starting unit references. uint previousUnit = 0; uint currentUnit = building.m_citizenUnits; // Keep looping through all CitizenUnits in this building until the end. while (currentUnit != 0) { // Get reference to next unit and flags of this unit. CitizenUnit.Flags unitFlags = citizenUnits[currentUnit].m_flags; uint nextUnit = citizenUnits[currentUnit].m_nextUnit; // Status flag. bool removingFlag = false; // Is this a residential unit? if ((ushort)(unitFlags & CitizenUnit.Flags.Home) != 0) { // Residential unit; are we still allocating homes, and if we're preserving occupied units, is it empty? if (homeCount <= 0 && (citizenUnits[currentUnit].m_citizen0 + citizenUnits[currentUnit].m_citizen1 + citizenUnits[currentUnit].m_citizen2 + citizenUnits[currentUnit].m_citizen3 + citizenUnits[currentUnit].m_citizen4 == 0)) { // Already have the maximum number of households, therefore this workplace unit is surplus to requirements - remove it. removingFlag = true; } else { // Still allocating - reduce unallocated homeCount by 1. --homeCount; } } // Is this a workplace unit? else if ((ushort)(unitFlags & CitizenUnit.Flags.Work) != 0) { // Workplace unit; are we still allocating to workplaces? if (workCount <= 0) { // Not allocating any more, therefore this workplace unit is surplus to requirements - remove it. removingFlag = true; } else { // Still allocating - reduce unallocated workCount by 5. workCount -= 5; } } else if ((ushort)(unitFlags & CitizenUnit.Flags.Visit) != 0) { // VisitPlace unit; are we still allocating to visitCount? if (visitCount <= 0) { // Not allocating any more, therefore this workplace unit is surplus to requirements - remove it. removingFlag = true; } else { // Still allocating - reduce unallocated visitCount by 5. visitCount -= 5; } } else if ((ushort)(unitFlags & CitizenUnit.Flags.Student) != 0) { // Student unit; are we still allocating to students? if (studentCount <= 0) { // Not allocating any more, therefore this workplace unit is surplus to requirements - remove it. // Student buildings are set as workplace. removingFlag = true; } else { // Still allocating - reduce unallocated visitCount by 5. studentCount -= 5; } } else { // Invalid unit; remove it. removingFlag = true; Logging.Message("found unit ", currentUnit, " with no valid flags"); } // Are we removing this unit? if (removingFlag) { Logging.Message("removing unit ", currentUnit); // Unlink this unit from building CitizenUnit list. if (previousUnit != 0) { citizenUnits[previousUnit].m_nextUnit = nextUnit; } else { // No previous unit - unlink from building record. building.m_citizenUnits = nextUnit; } // Release unit. citizenUnits[currentUnit] = default(CitizenUnit); ReleaseUnitImplementation(citizenManager, currentUnit, ref citizenUnits[currentUnit]); citizenManager.m_unitCount = (int)(citizenManager.m_units.ItemCount() - 1); } else { // Not removing - therefore previous unit reference needs to be updated. previousUnit = currentUnit; } // Move on to next unit. currentUnit = nextUnit; } }
/// <summary> /// Removes CitizenUnits that are surplus to requirements from the specified building. /// </summary> /// <param name="building">Building reference</param> /// <param name="homeCount">Number of households to apply</param> /// <param name="workCount">Number of workplaces to apply</param> /// <param name="visitCount">Number of visitplaces to apply</param> /// <param name="preserveOccupied">Preserve occupied residential households</param> internal static void RemoveCitizenUnits(ref Building building, int homeCount, int workCount, int visitCount, bool preserveOccupied) { // Local references. CitizenManager citizenManager = Singleton <CitizenManager> .instance; CitizenUnit[] citizenUnits = citizenManager.m_units.m_buffer; Citizen[] citizens = citizenManager.m_citizens.m_buffer; uint previousUnit = building.m_citizenUnits; uint currentUnit = building.m_citizenUnits; // Keep looping through all CitizenUnits in this building until the end. while (currentUnit != 0) { // Get reference to next unit and flags of this unit. CitizenUnit.Flags unitFlags = citizenUnits[currentUnit].m_flags; uint nextUnit = citizenUnits[currentUnit].m_nextUnit; // Status flag. int removingFlag = (int)RemovingType.NotRemoving; // Is this a residential unit? if ((ushort)(unitFlags & CitizenUnit.Flags.Home) != 0) { // Residential unit; are we still allocating homes, and if we're preserving occupied units, is it empty? if (homeCount <= 0 && (!preserveOccupied || (citizenUnits[currentUnit].m_citizen0 + citizenUnits[currentUnit].m_citizen1 + citizenUnits[currentUnit].m_citizen2 + citizenUnits[currentUnit].m_citizen3 + citizenUnits[currentUnit].m_citizen4 == 0))) { // Already have the maximum number of households, and iw. removingFlag = (int)RemovingType.Household; } else { // Still allocating - reduce unallocated homeCount by 1. --homeCount; } } // Is this a workplace unit? if ((ushort)(unitFlags & CitizenUnit.Flags.Work) != 0) { // Workplace unit; are we still allocating to workplaces? if (workCount <= 0) { // Not allocating any more, therefore this workplace unit is surplus to requirements - remove it. removingFlag = (int)RemovingType.Workplace; } else { // Still allocating - reduce unallocated workCount by 5. workCount -= 5; } } else if ((ushort)(unitFlags & CitizenUnit.Flags.Visit) != 0) { // VisitPlace unit; are we still allocating to visitCount? if (visitCount <= 0) { // Not allocating any more, therefore this workplace unit is surplus to requirements - remove it. removingFlag = (int)RemovingType.Visitplace; } else { // Still allocating - reduce unallocated visitCount by 5. visitCount -= 5; } } // Are we removing this unit? if (removingFlag != (int)RemovingType.NotRemoving) { // Yes - remove any occupying citizens. for (int i = 0; i < 5; ++i) { // Remove relevant citizen unit reference from citizen. uint citizen = citizenUnits[currentUnit].GetCitizen(i); switch (removingFlag) { case (int)RemovingType.Household: citizens[citizen].m_homeBuilding = 0; break; case (int)RemovingType.Workplace: citizens[citizen].m_workBuilding = 0; break; case (int)RemovingType.Visitplace: citizens[citizen].m_visitBuilding = 0; break; } } // Unlink this unit from building CitizenUnit list. citizenUnits[previousUnit].m_nextUnit = nextUnit; // Release unit. ReleaseUnitImplementation(citizenManager, currentUnit, ref citizenUnits[currentUnit]); citizenManager.m_unitCount = (int)(citizenManager.m_units.ItemCount() - 1); } else { // Not removing - therefore previous unit reference needs to be updated. previousUnit = currentUnit; } // Move on to next unit. currentUnit = nextUnit; } }