示例#1
0
        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);
        }
示例#2
0
 public static bool HasCitizensInside(this Building building, CitizenUnit.Flags flags, int maxRecurseAmount = 5)
 {
     return(building.AnyCitizenInside(flags, citizenId =>
     {
         return true;
     },
                                      maxRecurseAmount));
 }
示例#3
0
        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);
        }
示例#4
0
        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);
        }
示例#5
0
        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
示例#7
0
        /// <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;
            }
        }