// ResidentAI
 public static void Postfix(uint homeID, ref CitizenUnit data)
 {
     if ((Singleton <BuildingManager> .instance.m_buildings.m_buffer[data.m_building].m_flags & (Building.Flags.Completed | Building.Flags.Upgrading)) != Building.Flags.None)
     {
         ProcessFamily(homeID, ref data);
     }
 }
Beispiel #2
0
        public void GetCitizenIncome(CitizenUnit citizenUnit, int level, ref int income, ref int tourists)
        {
            CitizenManager instance = Singleton <CitizenManager> .instance;

            if (citizenUnit.m_citizen0 != 0u)
            {
                GetCitizenIncome(instance.m_citizens.m_buffer[(int)((UIntPtr)citizenUnit.m_citizen0)], level, ref income, ref tourists);
            }
            if (citizenUnit.m_citizen1 != 0u)
            {
                GetCitizenIncome(instance.m_citizens.m_buffer[(int)((UIntPtr)citizenUnit.m_citizen1)], level, ref income, ref tourists);
            }
            if (citizenUnit.m_citizen2 != 0u)
            {
                GetCitizenIncome(instance.m_citizens.m_buffer[(int)((UIntPtr)citizenUnit.m_citizen2)], level, ref income, ref tourists);
            }
            if (citizenUnit.m_citizen3 != 0u)
            {
                GetCitizenIncome(instance.m_citizens.m_buffer[(int)((UIntPtr)citizenUnit.m_citizen3)], level, ref income, ref tourists);
            }
            if (citizenUnit.m_citizen4 != 0u)
            {
                GetCitizenIncome(instance.m_citizens.m_buffer[(int)((UIntPtr)citizenUnit.m_citizen4)], level, ref income, ref tourists);
            }
        }
        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;
                }
            }
        }
        /// <summary>
        /// Gets the driver from a vehicle.
        /// See PassengerCarAI.GetDriverInstance - almost stock code.
        /// </summary>
        /// <param name="vehicleId">Id of the vehicle.</param>
        /// <param name="data">Vehicle data of the vehicle.</param>
        /// <returns>CitizenInstanceId of the driver.</returns>
        public ushort GetDriverInstanceId(ushort vehicleId, ref Vehicle data)
        {
            CitizenManager citizenManager = Singleton <CitizenManager> .instance;
            uint           citizenUnitId  = data.m_citizenUnits;
            uint           maxUnitCount   = citizenManager.m_units.m_size;
            int            numIter        = 0;

            while (citizenUnitId != 0)
            {
                ref CitizenUnit citizenUnit = ref citizenUnitId.ToCitizenUnit();
                for (int i = 0; i < 5; i++)
                {
                    uint citizenId = citizenUnit.GetCitizen(i);

                    if (citizenId != 0)
                    {
                        ushort citizenInstanceId = citizenId.ToCitizen().m_instance;
                        if (citizenInstanceId != 0)
                        {
                            return(citizenInstanceId);
                        }
                    }
                }

                citizenUnitId = citizenUnit.m_nextUnit;
                if (++numIter > maxUnitCount)
                {
                    CODebugBase <LogChannel> .Error(
                        LogChannel.Core,
                        "Invalid list detected!\n" + Environment.StackTrace);

                    break;
                }
            }
        public static void ReleaseUnitImplementation(object instance, uint unit, ref CitizenUnit data)
        {
            string message = "ReleaseUnitImplementation reverse Harmony patch wasn't applied";

            Logging.Error(message, instance, unit, data);
            throw new NotImplementedException(message);
        }
        private static int GetTotalUnitGroups(uint unitID)
        {
            int count = 0;

            while (unitID != 0)
            {
                CitizenUnit unit = CitizenManager.instance.m_units.m_buffer[unitID];
                unitID = unit.m_nextUnit;
                count++;
            }
            return(count);
        }
Beispiel #7
0
        private static int GetTotalUnitGroups(uint unitID)
        {
            int num = 0;

            while (unitID != 0u)
            {
                CitizenUnit citizenUnit = Singleton <CitizenManager> .instance.m_units.m_buffer[(int)((UIntPtr)unitID)];
                unitID = citizenUnit.m_nextUnit;
                num++;
            }
            return(num);
        }
        private uint[] getFamilyWithStudentInternal(int numAttempts)
        {
            // Check to see if too many attempts already
            if (numAttempts <= 0)
            {
                return(null);
            }

            // Get a random senior citizen
            uint familyId = this.fetchRandomFamilyWithStudent();

            Logger.logInfo(LOG_SENIORS, "StudentManager.getFamilyWithStudentInternal -- Family Id: {0}", familyId);
            if (familyId == 0)
            {
                // No Family with Students to be located
                return(null);
            }


            // Validate all seniors in the family and build an array of family members
            CitizenUnit familyWithStudent = this._citizenManager.m_units.m_buffer[familyId];

            uint[] family        = new uint[5];
            bool   seniorPresent = false;

            for (int i = 0; i < 5; i++)
            {
                uint familyMember = familyWithStudent.GetCitizen(i);
                if (this.IsStudent(familyMember))
                {
                    if (!this.validateStudent(familyMember))
                    {
                        // This particular Student is no longer valid for some reason, call recursively with one less attempt
                        return(this.getFamilyWithStudentInternal(--numAttempts));
                    }
                    seniorPresent = true;
                }
                Logger.logInfo(LOG_SENIORS, "StudentManager.getFamilyWithStudentInternal -- Family Member: {0}", familyMember);
                family[i] = familyMember;
            }

            if (!seniorPresent)
            {
                // No Student was found in this family (which is a bit weird), try again
                return(this.getFamilyWithStudentInternal(--numAttempts));
            }

            return(family);
        }
 public static void Prefix(uint homeID, ref CitizenUnit data)
 {
     if (CitizenUnitData.familyGoods[homeID] == 65535)
     {
         //first time
         if (data.m_goods < 6000)
         {
             CitizenUnitData.familyGoods[homeID] = (ushort)(data.m_goods * 10);
         }
         else
         {
             CitizenUnitData.familyGoods[homeID] = 60000;
         }
     }
 }
Beispiel #10
0
        public static bool Prefix(ref bool __result,
                                  // Harmony magic END
                                  ushort vehicleID,
                                  ref Vehicle vehicleData,
                                  PathUnit.Position pathPos,
                                  uint nextPath,
                                  int nextPositionIndex,
                                  out byte segmentOffset)
        {
            CitizenManager citizenManager = Singleton <CitizenManager> .instance;
            uint           maxUnitCount   = citizenManager.m_units.m_size;

            uint   driverCitizenId         = 0u;
            ushort driverCitizenInstanceId = 0;
            ushort targetBuildingId        = 0; // NON-STOCK CODE
            uint   curCitizenUnitId        = vehicleData.m_citizenUnits;
            int    numIterations           = 0;

            while (curCitizenUnitId != 0u && driverCitizenId == 0u)
            {
                ref CitizenUnit currentCitizenUnit = ref curCitizenUnitId.ToCitizenUnit();
                for (int i = 0; i < 5; i++)
                {
                    uint citizenId = currentCitizenUnit.GetCitizen(i);
                    if (citizenId == 0u)
                    {
                        continue;
                    }

                    driverCitizenInstanceId = citizenId.ToCitizen().m_instance;
                    if (driverCitizenInstanceId == 0)
                    {
                        continue;
                    }

                    // NON-STOCK CODE START
                    ref CitizenInstance driverCitizenInstance = ref driverCitizenInstanceId.ToCitizenInstance();
                    driverCitizenId  = driverCitizenInstance.m_citizen;
                    targetBuildingId = driverCitizenInstance.m_targetBuilding;
                    // NON-STOCK CODE END

                    break;
                }
Beispiel #11
0
        private void ReleaseUnusedCitizenUnits()
        {
            Utils.Log((object)"Find and clear unused citizen units.");
            CitizenManager instance = Singleton <CitizenManager> .instance;
            int            num      = 0;

            for (int index = 0; index < instance.m_units.m_buffer.Length; ++index)
            {
                CitizenUnit citizenUnit = instance.m_units.m_buffer[index];
                if (citizenUnit.m_flags != CitizenUnit.Flags.None && (int)citizenUnit.m_building == 0 && ((int)citizenUnit.m_vehicle == 0 && (int)citizenUnit.m_goods == 0))
                {
                    ++num;
                    instance.m_units.m_buffer[index] = new CitizenUnit();
                    instance.m_units.ReleaseItem((uint)index);
                    Utils.LogToTxt((object)string.Format("CitizenUnit #{0} - Flags: {1} - Citizens: #{2} | #{3} | #{4} | #{5} | #{6}", (object)index, (object)citizenUnit.m_flags, (object)citizenUnit.m_citizen0, (object)citizenUnit.m_citizen1, (object)citizenUnit.m_citizen2, (object)citizenUnit.m_citizen3, (object)citizenUnit.m_citizen4));
                }
            }
            Utils.Log((object)("Cleared " + (object)num + " unused citizen units."));
        }
Beispiel #12
0
        public void TryMoveFamily(uint citizenID)
        {
            uint        temp       = citizenID;
            int         familySize = 0;
            CitizenUnit data       = Singleton <CitizenManager> .instance.m_units.m_buffer[citizenID];
            Citizen     cit        = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenID];

            if ((int)data.m_citizen4 != 0 && !Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen4].Dead)
            {
                ++familySize;
                citizenID = data.m_citizen4;
            }
            if ((int)data.m_citizen3 != 0 && !Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen3].Dead)
            {
                ++familySize;
                citizenID = data.m_citizen3;
            }
            if ((int)data.m_citizen2 != 0 && !Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen2].Dead)
            {
                ++familySize;
                citizenID = data.m_citizen2;
            }
            if ((int)data.m_citizen1 != 0 && !Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen1].Dead)
            {
                ++familySize;
                citizenID = data.m_citizen1;
            }
            if ((int)data.m_citizen0 != 0 && !Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen0].Dead)
            {
                ++familySize;
                citizenID = data.m_citizen0;
            }
            if ((int)citizenID == 0)
            {
                return;
            }
            ResidentAI ai = cit.GetCitizenInfo(citizenID).GetAI() as ResidentAI;

            citizenID = temp;   //TODO: Unsure if citizenID should be kept or changed below
            ai.TryMoveFamily(citizenID, ref cit, familySize);
        }
Beispiel #13
0
        // copied from original private function ugh...
        private void MoveFamily(uint homeID, ref CitizenUnit data, ushort targetBuilding)
        {
            BuildingManager instance1 = Singleton <BuildingManager> .instance;
            CitizenManager  instance2 = Singleton <CitizenManager> .instance;
            uint            unitID    = 0;

            if (targetBuilding != (ushort)0)
            {
                unitID = instance1.m_buildings.m_buffer[(int)targetBuilding].GetEmptyCitizenUnit(CitizenUnit.Flags.Home);
            }
            for (int index = 0; index < 5; ++index)
            {
                uint citizen = data.GetCitizen(index);
                if (citizen != 0U && !instance2.m_citizens.m_buffer[citizen].Dead)
                {
                    instance2.m_citizens.m_buffer[citizen].SetHome(citizen, (ushort)0, unitID);
                    if (instance2.m_citizens.m_buffer[citizen].m_homeBuilding == (ushort)0)
                    {
                        instance2.ReleaseCitizen(citizen);
                    }
                }
            }
        }
 public void GetCitizenIncome(CitizenUnit citizenUnit, int level, ref int income, ref int tourists)
 {
     CitizenManager instance = Singleton<CitizenManager>.instance;
     if (citizenUnit.m_citizen0 != 0u)
     {
         GetCitizenIncome(instance.m_citizens.m_buffer[(int)((UIntPtr)citizenUnit.m_citizen0)], level, ref income, ref tourists);
     }
     if (citizenUnit.m_citizen1 != 0u)
     {
         GetCitizenIncome(instance.m_citizens.m_buffer[(int)((UIntPtr)citizenUnit.m_citizen1)], level, ref income, ref tourists);
     }
     if (citizenUnit.m_citizen2 != 0u)
     {
         GetCitizenIncome(instance.m_citizens.m_buffer[(int)((UIntPtr)citizenUnit.m_citizen2)], level, ref income, ref tourists);
     }
     if (citizenUnit.m_citizen3 != 0u)
     {
         GetCitizenIncome(instance.m_citizens.m_buffer[(int)((UIntPtr)citizenUnit.m_citizen3)], level, ref income, ref tourists);
     }
     if (citizenUnit.m_citizen4 != 0u)
     {
         GetCitizenIncome(instance.m_citizens.m_buffer[(int)((UIntPtr)citizenUnit.m_citizen4)], level, ref income, ref tourists);
     }
 }
        /// <summary>
        /// Prefix to force settings reset on load (if enabled) for RICO buildings (resetting to current settings).
        /// </summary>
        /// <param name="__instance">Original object instance reference</param>
        /// <param name="buildingID">Building instance ID</param>
        /// <param name="data">Building data</param>
        /// <param name="version">Version</param>
        private static bool Prefix(PrivateBuildingAI __instance, ushort buildingID, ref Building data, uint version)
        {
            // Don't do anything if the flag isn't set.
            if (!ModSettings.resetOnLoad)
            {
                // Carry on to original method.
                return(true);
            }

            // Check to see if we've preloaded a local settings file.
            if (Loading.localRicoDef != null)
            {
                // Step through each definition from the local settings file, looking for a match.
                foreach (RICOBuilding building in Loading.localRicoDef.Buildings)
                {
                    if (building.ricoEnabled && __instance.m_info.name == building.name)
                    {
                        // m_level is one less than building.level.
                        byte newLevel = (byte)(building.level - 1);

                        if (data.m_level != newLevel)
                        {
                            Debugging.Message("found building '" + building.name + "' with level " + (data.m_level + 1) + ", overriding to level " + building.level);
                            data.m_level = newLevel;
                        }

                        // Basic game code processing to continue initialisation.
                        __instance.CalculateWorkplaceCount((ItemClass.Level)data.m_level, new Randomizer(buildingID), data.Width, data.Length, out int level, out int level2, out int level3, out int level4);
                        __instance.AdjustWorkplaceCount(buildingID, ref data, ref level, ref level2, ref level3, ref level4);

                        int workCount       = level + level2 + level3 + level4;
                        int targetHomeCount = 0;

                        // Update visitor count.
                        int visitCount = __instance.CalculateVisitplaceCount((ItemClass.Level)data.m_level, new Randomizer(buildingID), data.Width, data.Length);

                        // Check to see if rsidential building homecounts differ from settings.
                        if (building.service == "residential")
                        {
                            int currentHomeCount = 0;

                            // Count currently applied citizen units (households).
                            if (data.m_citizenUnits != 0)
                            {
                                // At least one household here; get the first.
                                CitizenUnit citizenUnit = Singleton <CitizenManager> .instance.m_units.m_buffer[data.m_citizenUnits];
                                currentHomeCount = 1;

                                // Step through all applied citizen units (linked via m_nextUnit), counting as we go,
                                while (citizenUnit.m_nextUnit != 0)
                                {
                                    citizenUnit = Singleton <CitizenManager> .instance.m_units.m_buffer[citizenUnit.m_nextUnit];
                                    currentHomeCount++;
                                }
                            }

                            // Determine target household count.
                            targetHomeCount = __instance.CalculateHomeCount((ItemClass.Level)data.m_level, new Randomizer(buildingID), data.Width, data.Length);

                            // If target household count is lower than the current household count, we need to perform a forced reset.
                            // The reverse case, targets greater than current, will be caught with the base-case call to EnsureCitizenUnits below.
                            if (targetHomeCount < currentHomeCount)
                            {
                                Debugging.Message("found Residential prefab " + building.name + " with target homecount " + targetHomeCount + " and citizen units " + currentHomeCount + "; forcing homecount reset");
                                RealisticCitizenUnits.EnsureCitizenUnits(ref __instance, buildingID, ref data, targetHomeCount, workCount, visitCount, 0);
                            }
                        }

                        // Update citizen units to match new totals.
                        EnsureCitizenUnitsRev(__instance, buildingID, ref data, targetHomeCount, workCount, visitCount, 0);

                        // Clear any problems (so we don't have any residual issues from changing service types, for example (new) residential buildings showing 'not enough goods'.
                        // Any 'genuine' problems will be quickly reapplied by the game.
                        data.m_problems = 0;

                        // We've set things up here for Ploppable RICO - don't fall through to game code.
                        return(false);
                    }
                }
            }

            // If we've hit this point, then no Ploppable RICO setup has occured - fall through to game code.
            return(true);
        }
 public void GetCommute(CitizenUnit unit, ref int commute, ref int count)
 {
     CitizenManager instance = Singleton<CitizenManager>.instance;
     if (unit.m_citizen0 != 0u)
     {
         GetCommute(unit.m_citizen0, instance.m_citizens.m_buffer[unit.m_citizen0], ref commute, ref count);
     }
     if (unit.m_citizen1 != 0u)
     {
         GetCommute(unit.m_citizen1, instance.m_citizens.m_buffer[unit.m_citizen1], ref commute, ref count);
     }
     if (unit.m_citizen2 != 0u)
     {
         GetCommute(unit.m_citizen2, instance.m_citizens.m_buffer[unit.m_citizen2], ref commute, ref count);
     }
     if (unit.m_citizen3 != 0u)
     {
         GetCommute(unit.m_citizen3, instance.m_citizens.m_buffer[unit.m_citizen3], ref commute, ref count);
     }
     if (unit.m_citizen4 != 0u)
     {
         GetCommute(unit.m_citizen4, instance.m_citizens.m_buffer[unit.m_citizen4], ref commute, ref count);
     }
 }
 public void GetCommute(CitizenUnit unit, ref int commute, ref int count)
 {
     //Logger.dbgLog(string.Concat("ref commute:", commute.ToString()," count:",count.ToString()," blding:",unit.m_building.ToString()," nUnit:",unit.m_nextUnit.ToString()));
     CitizenManager instance = Singleton<CitizenManager>.instance;
     if (unit.m_citizen0 != 0u)
     {
         GetCommute(unit.m_citizen0, instance.m_citizens.m_buffer[unit.m_citizen0], ref commute, ref count);
     }
     if (unit.m_citizen1 != 0u)
     {
         GetCommute(unit.m_citizen1, instance.m_citizens.m_buffer[unit.m_citizen1], ref commute, ref count);
     }
     if (unit.m_citizen2 != 0u)
     {
         GetCommute(unit.m_citizen2, instance.m_citizens.m_buffer[unit.m_citizen2], ref commute, ref count);
     }
     if (unit.m_citizen3 != 0u)
     {
         GetCommute(unit.m_citizen3, instance.m_citizens.m_buffer[unit.m_citizen3], ref commute, ref count);
     }
     if (unit.m_citizen4 != 0u)
     {
         GetCommute(unit.m_citizen4, instance.m_citizens.m_buffer[unit.m_citizen4], ref commute, ref count);
     }
 }
Beispiel #18
0
 /// <summary>
 /// Because CO uses struct refs in their code. This is ever so slightly faster than just replacing the structure at the given index in the m_units array.
 /// </summary>
 /// <param name="unit"></param>
 /// <param name="next"></param>
 void SetNextUnit(ref CitizenUnit unit, uint next)
 {
     unit.m_nextUnit = next;
 }
 private void MoveFamily(uint homeID, ref CitizenUnit data, ushort targetBuilding)
 {
     BuildingManager instance = Singleton<BuildingManager>.instance;
     CitizenManager instance2 = Singleton<CitizenManager>.instance;
     uint unitID = 0u;
     if (targetBuilding != 0)
     {
         unitID = instance.m_buildings.m_buffer[(int)targetBuilding].GetEmptyCitizenUnit(CitizenUnit.Flags.Home);
     }
     for (int i = 0; i < 5; i++)
     {
         uint citizen = data.GetCitizen(i);
         if (citizen != 0u && !instance2.m_citizens.m_buffer[(int)((UIntPtr)citizen)].Dead)
         {
             instance2.m_citizens.m_buffer[(int)((UIntPtr)citizen)].SetHome(citizen, 0, unitID);
             if (instance2.m_citizens.m_buffer[(int)((UIntPtr)citizen)].m_homeBuilding == 0)
             {
                 instance2.ReleaseCitizen(citizen);
             }
         }
     }
 }
        public static void ProcessCitizen(uint homeID, ref CitizenUnit data, bool isPre)
        {
            if (isPre)
            {
                CitizenUnitData.familyMoney[homeID] = 0;
                if (data.m_citizen0 != 0)
                {
                    Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen0];
                    if ((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None)
                    {
                        if (citizenData.Dead == false)
                        {
                            RealCityResidentAI.citizenCount++;
                            CitizenUnitData.familyMoney[homeID] += CitizenData.citizenMoney[data.m_citizen0];
                        }
                    }
                }
                if (data.m_citizen1 != 0)
                {
                    Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen1];
                    if ((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None)
                    {
                        if (citizenData.Dead == false)
                        {
                            RealCityResidentAI.citizenCount++;
                            CitizenUnitData.familyMoney[homeID] += CitizenData.citizenMoney[data.m_citizen1];
                        }
                    }
                }
                if (data.m_citizen2 != 0)
                {
                    Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen2];
                    if ((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None)
                    {
                        if (citizenData.Dead == false)
                        {
                            RealCityResidentAI.citizenCount++;
                            CitizenUnitData.familyMoney[homeID] += CitizenData.citizenMoney[data.m_citizen2];
                        }
                    }
                }
                if (data.m_citizen3 != 0)
                {
                    Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen3];
                    if ((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None)
                    {
                        if (citizenData.Dead == false)
                        {
                            RealCityResidentAI.citizenCount++;
                            CitizenUnitData.familyMoney[homeID] += CitizenData.citizenMoney[data.m_citizen3];
                        }
                    }
                }
                if (data.m_citizen4 != 0)
                {
                    Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen4];
                    if ((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None)
                    {
                        if (citizenData.Dead == false)
                        {
                            RealCityResidentAI.citizenCount++;
                            CitizenUnitData.familyMoney[homeID] += CitizenData.citizenMoney[data.m_citizen4];
                        }
                    }
                }
            }
            else
            {
                if (CitizenUnitData.familyMoney[homeID] < MainDataStore.lowWealth)
                {
                    RealCityResidentAI.familyWeightStableLow++;
                }
                else if (CitizenUnitData.familyMoney[homeID] >= MainDataStore.highWealth)
                {
                    RealCityResidentAI.familyWeightStableHigh++;
                }

                int temp = 0;
                if (data.m_citizen0 != 0)
                {
                    Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen0];
                    if (((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None) && (citizenData.Dead == false))
                    {
                        temp++;
#if FASTRUN
#else
                        GetVoteChance(data.m_citizen0, citizenData, homeID);
#endif
                    }
                }
                if (data.m_citizen1 != 0)
                {
                    Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen1];
                    if (((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None) && (citizenData.Dead == false))
                    {
#if FASTRUN
#else
                        GetVoteChance(data.m_citizen1, citizenData, homeID);
#endif
                        temp++;
                    }
                }
                if (data.m_citizen2 != 0)
                {
                    Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen2];
                    if (((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None) && (citizenData.Dead == false))
                    {
#if FASTRUN
#else
                        GetVoteChance(data.m_citizen2, citizenData, homeID);
#endif
                        temp++;
                    }
                }
                if (data.m_citizen3 != 0)
                {
                    Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen3];
                    if (((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None) && (citizenData.Dead == false))
                    {
#if FASTRUN
#else
                        GetVoteChance(data.m_citizen3, citizenData, homeID);
#endif
                        temp++;
                    }
                }
                if (data.m_citizen4 != 0)
                {
                    Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen4];
                    if (((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None) && (citizenData.Dead == false))
                    {
#if FASTRUN
#else
                        GetVoteChance(data.m_citizen4, citizenData, homeID);
#endif
                        temp++;
                    }
                }

                if (temp != 0)
                {
                    if (data.m_citizen0 != 0)
                    {
                        Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen0];
                        if (((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None) && (citizenData.Dead == false))
                        {
                            CitizenData.citizenMoney[data.m_citizen0] = CitizenUnitData.familyMoney[homeID] / temp;
                        }
                    }
                    if (data.m_citizen1 != 0)
                    {
                        Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen1];
                        if (((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None) && (citizenData.Dead == false))
                        {
                            CitizenData.citizenMoney[data.m_citizen1] = CitizenUnitData.familyMoney[homeID] / temp;
                        }
                    }
                    if (data.m_citizen2 != 0)
                    {
                        Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen2];
                        if (((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None) && (citizenData.Dead == false))
                        {
                            CitizenData.citizenMoney[data.m_citizen2] = CitizenUnitData.familyMoney[homeID] / temp;
                        }
                    }
                    if (data.m_citizen3 != 0)
                    {
                        Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen3];
                        if (((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None) && (citizenData.Dead == false))
                        {
                            CitizenData.citizenMoney[data.m_citizen3] = CitizenUnitData.familyMoney[homeID] / temp;
                        }
                    }
                    if (data.m_citizen4 != 0)
                    {
                        Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[data.m_citizen4];
                        if (((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None) && (citizenData.Dead == false))
                        {
                            CitizenData.citizenMoney[data.m_citizen4] = CitizenUnitData.familyMoney[homeID] / temp;
                        }
                    }
                }
            }
        }
Beispiel #21
0
        /// <summary>
        /// Updates the citizens.
        /// </summary>
        /// <param name="building">The building.</param>
        /// <exception cref="Exception">Loop counter too high.</exception>
        private void UpdateCitizens(ref Building building)
        {
            CitizenManager citizenManager = Singleton <CitizenManager> .instance;

            int  count      = 0;
            int  size       = 0;
            int  assigned   = 0;
            int  unassigned = 0;
            uint unitId     = building.m_citizenUnits;

            while (unitId != 0)
            {
                CitizenUnit unit = citizenManager.m_units.m_buffer[unitId];
                for (int i = 0; i < 5; i++)
                {
                    uint citizenId = unit.GetCitizen(i);
                    if (citizenId != 0)
                    {
                        Citizen citizen = citizenManager.m_citizens.m_buffer[citizenId];
                        if (((this.dispatcherType == Dispatcher.DispatcherTypes.HearseDispatcher && citizen.Dead) ||
                             (this.dispatcherType == Dispatcher.DispatcherTypes.AmbulanceDispatcher && citizen.Sick)) &&
                            citizen.GetBuildingByLocation() == this.BuildingId)
                        {
                            size++;

                            if (this.citizens != null)
                            {
                                TargetCitizenInfo citizenInfo;
                                if (this.citizens.TryGetValue(citizenId, out citizenInfo))
                                {
                                    citizenInfo.Update(ref citizen, this.dispatcherType);
                                    if (citizenInfo.VehicleId == 0)
                                    {
                                        unassigned++;
                                    }
                                    else
                                    {
                                        assigned++;
                                    }
                                }
                                else
                                {
                                    this.citizens[citizenId] = new TargetCitizenInfo(citizenId, ref citizen, this.dispatcherType);
                                    unassigned++;
                                }
                            }
                        }
                    }
                }

                count++;
                if (count > (int)ushort.MaxValue * 10)
                {
                    throw new Exception("Loop counter too high");
                }

                unitId = unit.m_nextUnit;
            }

            this.ProblemSize        = size;
            this.CitizensAssigned   = assigned;
            this.CitizensUnAssigned = unassigned;
        }
        //workers building history update
        public void UpdateWorkers(int resilient_index)
        {
            if (!Settings.inst.listResidentsAndWorkers)
            {
                return;
            }

            List <uint> current_workers_ids = new List <uint>();

            Building       build    = Singleton <BuildingManager> .instance.m_buildings.m_buffer[m_resilients[resilient_index].buildingID];
            CitizenManager instance = Singleton <CitizenManager> .instance;
            uint           num      = build.m_citizenUnits;
            int            num2     = 0;

            while (num != 0u)
            {
                if ((ushort)(instance.m_units.m_buffer[(int)((UIntPtr)num)].m_flags & CitizenUnit.Flags.Work) != 0)
                {
                    CitizenUnit work_unit = instance.m_units.m_buffer[(int)((UIntPtr)num)];
                    if (work_unit.m_citizen0 != 0u)
                    {
                        current_workers_ids.Add(work_unit.m_citizen0);
                    }
                    if (work_unit.m_citizen1 != 0u)
                    {
                        current_workers_ids.Add(work_unit.m_citizen1);
                    }
                    if (work_unit.m_citizen2 != 0u)
                    {
                        current_workers_ids.Add(work_unit.m_citizen2);
                    }
                    if (work_unit.m_citizen3 != 0u)
                    {
                        current_workers_ids.Add(work_unit.m_citizen3);
                    }
                    if (work_unit.m_citizen4 != 0u)
                    {
                        current_workers_ids.Add(work_unit.m_citizen4);
                    }
                    current_workers_ids.Add(num);
                }

                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;
                }
            }

            //update history family list with any new names
            for (int i = 0; i < current_workers_ids.Count; i++)
            {
//				if(!m_resilients[resilient_index].idsBuffer.Contains(current_workers_ids[i]))
//				{
//					m_resilients[resilient_index].idsBuffer.Add(current_workers_ids[i]);
//				}
                string name = Singleton <CitizenManager> .instance.GetCitizenName(current_workers_ids[i]);

                if (name == null || name.Length == 0)
                {
                    //CODebugBase<LogChannel>.Error(LogChannel.Modding, "empty citizen name for " + current_workers_ids[i]);
                }
                else
                if (!m_resilients[resilient_index].namesBuffer.Contains(name))
                {
                    m_resilients[resilient_index].namesBuffer.Add(name);
                }
            }
        }
        /*********** building updates *************/

        //residential building history updates
        public void UpdateResidentFamilies(int resilient_index)
        {
            if (!Settings.inst.listResidentsAndWorkers)
            {
                return;
            }

            List <uint> current_families_id = new List <uint>();

            Building       build          = Singleton <BuildingManager> .instance.m_buildings.m_buffer[m_resilients[resilient_index].buildingID];
            CitizenManager instance       = Singleton <CitizenManager> .instance;
            uint           num            = build.m_citizenUnits;
            int            num2           = 0;
            int            aliveHomeCount = 0;

            while (num != 0u)
            {
                uint nextUnit = instance.m_units.m_buffer[(int)((UIntPtr)num)].m_nextUnit;
                if ((ushort)(instance.m_units.m_buffer[(int)((UIntPtr)num)].m_flags & CitizenUnit.Flags.Home) != 0)
                {
                    current_families_id.Add(num);
                    aliveHomeCount++;
                }
                num = nextUnit;

                if (++num2 > 524288)
                {
                    CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                    break;
                }
            }

            //update history family list with any new names
            int index_families_before_now = Math.Max(m_resilients[resilient_index].namesBuffer.Count - aliveHomeCount, 0);

            for (int i = 0; i < current_families_id.Count; i++)
            {
//				if(!m_resilients[resilient_index].idsBuffer.Contains(current_families_id[i]))
//				{
//					m_resilients[resilient_index].idsBuffer.Add(current_families_id[i]);
//				}

                uint        valid_citizen = 0u;
                CitizenUnit cu            = Singleton <CitizenManager> .instance.m_units.m_buffer[current_families_id[i]];
                if (cu.m_citizen0 != 0u)
                {
                    valid_citizen = cu.m_citizen0;
                }
                else if (cu.m_citizen1 != 0u)
                {
                    valid_citizen = cu.m_citizen1;
                }
                else if (cu.m_citizen2 != 0u)
                {
                    valid_citizen = cu.m_citizen2;
                }
                else if (cu.m_citizen3 != 0u)
                {
                    valid_citizen = cu.m_citizen3;
                }
                else if (cu.m_citizen4 != 0u)
                {
                    valid_citizen = cu.m_citizen4;
                }

                if (valid_citizen != 0u)
                {
                    int        family      = Singleton <CitizenManager> .instance.m_citizens.m_buffer[valid_citizen].m_family;
                    Randomizer randomizer2 = new Randomizer(family);
                    string     name        = "NAME_FEMALE_LAST";
                    //					if (Citizen.GetGender(citizenID) == Citizen.Gender.Male)
                    //					{
                    //						text = "NAME_MALE_FIRST";
                    //						text2 = "NAME_MALE_LAST";
                    //					}
                    name = Locale.Get(name, randomizer2.Int32(Locale.Count(name)));
                    name = name.Substring(4);                                                                                                                            //remove placeholder in front

                    if (m_resilients[resilient_index].namesBuffer.Count == 0 || m_resilients[resilient_index].namesBuffer.LastIndexOf(name) < index_families_before_now) //-1 if family was never present, otherwise check if it is not currently in
                    {
                        m_resilients[resilient_index].namesBuffer.Add(name);
                    }
                }
            }
        }
Beispiel #24
0
        /// <summary>
        /// 处理市民
        /// </summary>
        /// <param name="homeID"></param>
        /// <param name="data"></param>
        /// <param name="isPre"></param>
        public static void ProcessCitizen(uint homeID, ref CitizenUnit data, bool isPre)
        {
            FieldInfo fieldInfo;

            if (isPre)
            {
                CitizenUnitData.familyMoney[homeID] = 0;
                for (int i = 0; i <= 4; i++)
                {
                    fieldInfo = data.GetType().GetField($"m_citizen{i}");
                    uint m_citizenI = (uint)fieldInfo.GetValue(data);
                    if (m_citizenI != 0)
                    {
                        Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[m_citizenI];
                        if ((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None)
                        {
                            if (citizenData.Dead == false)
                            {
                                RealCityResidentAI.citizenCount++;
                                CitizenUnitData.familyMoney[homeID] += CitizenData.citizenMoney[m_citizenI];
                            }
                        }
                    }
                }
            }
            else
            {
                // post-process
                if (CitizenUnitData.familyMoney[homeID] < MainDataStore.lowWealth)
                {
                    RealCityResidentAI.familyWeightStableLow++;
                }
                else if (CitizenUnitData.familyMoney[homeID] >= MainDataStore.highWealth)
                {
                    RealCityResidentAI.familyWeightStableHigh++;
                }

                int temp = 0;
                for (int i = 0; i <= 4; i++)
                {
                    fieldInfo = data.GetType().GetField($"m_citizen{i}");
                    uint m_citizenI = (uint)fieldInfo.GetValue(data);

                    if (m_citizenI != 0)
                    {
                        Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[m_citizenI];
                        if (((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None) && (citizenData.Dead == false))
                        {
                            ++temp;
#if FASTRUN
#else
                            //add a party.chancce by its citizen data
                            //GetVoteChance(m_citizenI, citizenData, homeID);
                            if (Politics.IsOnElection() && Politics.IsOverVotingAge(Citizen.GetAgeGroup(citizenData.m_age)))
                            {
                                ElectionVoter v = new ElectionVoter(m_citizenI, ref citizenData, homeID, Election.CurrentElectionInfo);
                                v.VoteTicket();
                            }
#endif
                        }
                    }
                }

                if (temp != 0)
                {
                    for (int i = 0; i <= 4; i++)
                    {
                        fieldInfo = data.GetType().GetField($"m_citizen{i}");
                        uint m_citizenI = (uint)fieldInfo.GetValue(data);

                        if (m_citizenI != 0)
                        {
                            Citizen citizenData = Singleton <CitizenManager> .instance.m_citizens.m_buffer[m_citizenI];
                            if (((citizenData.m_flags & Citizen.Flags.MovingIn) == Citizen.Flags.None) && (citizenData.Dead == false))
                            {
                                CitizenData.citizenMoney[m_citizenI] = CitizenUnitData.familyMoney[homeID] / temp;
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Collects building info for debug use.
        /// </summary>
        /// <param name="buildings">The buildings.</param>
        /// <param name="vehicles">The vehicles.</param>
        /// <param name="districtManager">The district manager.</param>
        /// <param name="citizenManager">The citizen manager.</param>
        /// <param name="buildingId">The building identifier.</param>
        /// <param name="serviceBuilding">The service building.</param>
        /// <param name="targetBuilding">The target building.</param>
        /// <param name="buildingStamp">The building stamp.</param>
        /// <param name="verbose">If set to <c>true</c> include more information.</param>
        /// <returns>The debug information.</returns>
        private static Log.InfoList DebugInfoMsg(
            Building[] buildings,
            Vehicle[] vehicles,
            DistrictManager districtManager,
            CitizenManager citizenManager,
            ushort buildingId,
            ServiceBuildingInfo serviceBuilding,
            TargetBuildingInfo targetBuilding,
            BuildingStamp buildingStamp,
            bool verbose = false)
        {
            Log.InfoList info = new Log.InfoList();

            info.Add("BuildingId", buildingId);

            if (buildingStamp != null)
            {
                info.Add("O", "BuildingStamp");
            }

            if (serviceBuilding != null)
            {
                info.Add("O", "ServiceBuilding");
            }

            if (targetBuilding != null)
            {
                info.Add("O", "TargetBuilding");
            }

            List <KeyValuePair <string, TargetBuildingInfo> >  targetBuildings  = null;
            List <KeyValuePair <string, ServiceBuildingInfo> > serviceBuildings = null;

            if (verbose && Global.Buildings != null)
            {
                //if (serviceBuilding == null)
                //{
                //    serviceBuilding = Global.Buildings.GetServiceBuilding(buildingId);
                //}

                //if (targetBuilding == null)
                //{
                //    targetBuilding = Global.Buildings.GetTargetBuilding(buildingId);
                //}

                targetBuildings  = new List <KeyValuePair <string, TargetBuildingInfo> >();
                serviceBuildings = new List <KeyValuePair <string, ServiceBuildingInfo> >();

                if (serviceBuilding == null)
                {
                    if (Global.Buildings.Garbage.ServiceBuildings != null && Global.Buildings.Garbage.ServiceBuildings.TryGetValue(buildingId, out serviceBuilding))
                    {
                        serviceBuildings.Add(new KeyValuePair <string, ServiceBuildingInfo>("GB", serviceBuilding));
                    }

                    if (Global.Buildings.DeathCare.ServiceBuildings != null && Global.Buildings.DeathCare.ServiceBuildings.TryGetValue(buildingId, out serviceBuilding))
                    {
                        serviceBuildings.Add(new KeyValuePair <string, ServiceBuildingInfo>("DCB", serviceBuilding));
                    }

                    if (Global.Buildings.HealthCare.ServiceBuildings != null && Global.Buildings.HealthCare.ServiceBuildings.TryGetValue(buildingId, out serviceBuilding))
                    {
                        serviceBuildings.Add(new KeyValuePair <string, ServiceBuildingInfo>("HCB", serviceBuilding));
                    }

                    serviceBuilding = null;
                }

                if (targetBuilding == null)
                {
                    if (Global.Buildings.DeathCare.TargetBuildings != null && Global.Buildings.DeathCare.TargetBuildings.TryGetValue(buildingId, out targetBuilding))
                    {
                        targetBuildings.Add(new KeyValuePair <string, TargetBuildingInfo>("DPB", targetBuilding));
                    }

                    if (Global.Buildings.Garbage.TargetBuildings != null && Global.Buildings.Garbage.TargetBuildings.TryGetValue(buildingId, out targetBuilding))
                    {
                        targetBuildings.Add(new KeyValuePair <string, TargetBuildingInfo>("DB", targetBuilding));
                    }

                    if (Global.Buildings.HealthCare.TargetBuildings != null && Global.Buildings.HealthCare.TargetBuildings.TryGetValue(buildingId, out targetBuilding))
                    {
                        targetBuildings.Add(new KeyValuePair <string, TargetBuildingInfo>("SPB", targetBuilding));
                    }

                    targetBuilding = null;
                }
            }

            try
            {
                info.Add("AI", buildings[buildingId].Info.m_buildingAI.GetType());
                info.Add("InfoName", buildings[buildingId].Info.name);

                string name = GetBuildingName(buildingId);
                if (!String.IsNullOrEmpty(name) && name != buildings[buildingId].Info.name)
                {
                    info.Add("BuildingName", name);
                }
            }
            catch
            {
                info.Add("Error", "Info");
            }

            try
            {
                byte district = districtManager.GetDistrict(buildings[buildingId].m_position);
                info.Add("District", district);
                info.Add("DistrictName", districtManager.GetDistrictName(district));
            }
            catch (Exception ex)
            {
                info.Add("Exception", "District", ex.GetType().ToString(), ex.Message);
            }

            if (buildingStamp != null)
            {
                info.Add("Source", buildingStamp.Source);
                info.Add("SimulationTimeStamp", buildingStamp.SimulationTimeStamp);
                info.Add("SimulationTimeDelta", buildingStamp.SimulationTimeDelta);
            }

            AddServiceBuildingInfoToDebugInfoMsg(info, buildings, serviceBuilding, "B");
            if (serviceBuildings != null)
            {
                foreach (KeyValuePair <string, ServiceBuildingInfo> building in serviceBuildings)
                {
                    AddServiceBuildingInfoToDebugInfoMsg(info, buildings, building.Value, building.Key);
                }
            }

            AddTargetBuildingInfoToDebugInfoMsg(info, targetBuilding, "B");
            if (targetBuildings != null)
            {
                foreach (KeyValuePair <string, TargetBuildingInfo> building in targetBuildings)
                {
                    AddTargetBuildingInfoToDebugInfoMsg(info, building.Value, building.Key);
                }
            }

            if (verbose && Global.Buildings != null)
            {
                info.Add("Categories", Global.Buildings.GetCategories(buildingId));
            }

            float radius = float.NaN;

            int materialMax         = 0;
            int materialAmount      = 0;
            int serviceVehicleCount = 0;

            try
            {
                if (GetCapacityAmount(buildingId, ref buildings[buildingId], out materialAmount, out materialMax, out serviceVehicleCount))
                {
                    info.Add("CapacityAmount", materialAmount);
                    info.Add("CapacityMax", materialMax);
                    info.Add("ServiceVehicleCount", serviceVehicleCount);
                }

                serviceVehicleCount = 0;

                if (buildings[buildingId].Info.m_buildingAI is CemeteryAI)
                {
                    radius = ((CemeteryAI)buildings[buildingId].Info.m_buildingAI).m_deathCareRadius;

                    info.Add("DeathCareRadius", ((CemeteryAI)buildings[buildingId].Info.m_buildingAI).m_deathCareRadius);
                    info.Add("CorpseCapacity", ((CemeteryAI)buildings[buildingId].Info.m_buildingAI).m_corpseCapacity);
                    info.Add("GraveCount", ((CemeteryAI)buildings[buildingId].Info.m_buildingAI).m_graveCount);
                    info.Add("CustomBuffer1", buildings[buildingId].m_customBuffer1);                                                                                    // GraveUsed?
                    info.Add("CustomBuffer2", buildings[buildingId].m_customBuffer2);
                    info.Add("PR_HC_Calc", ((buildings[buildingId].m_productionRate * ((CemeteryAI)buildings[buildingId].Info.m_buildingAI).m_hearseCount) + 99) / 100); // Hearse capacity?
                    info.Add("IsFull", buildings[buildingId].Info.m_buildingAI.IsFull(buildingId, ref buildings[buildingId]));

                    buildings[buildingId].Info.m_buildingAI.GetMaterialAmount(buildingId, ref buildings[buildingId], TransferManager.TransferReason.Dead, out materialAmount, out materialMax);
                }
                else if (buildings[buildingId].Info.m_buildingAI is LandfillSiteAI)
                {
                    radius = ((LandfillSiteAI)buildings[buildingId].Info.m_buildingAI).m_collectRadius;

                    info.Add("CollectRadius", ((LandfillSiteAI)buildings[buildingId].Info.m_buildingAI).m_collectRadius);
                    info.Add("GarbageAmount", ((LandfillSiteAI)buildings[buildingId].Info.m_buildingAI).GetGarbageAmount(buildingId, ref buildings[buildingId]));
                    info.Add("GarbageCapacity", ((LandfillSiteAI)buildings[buildingId].Info.m_buildingAI).m_garbageCapacity);
                    info.Add("GarbageBuffer", buildings[buildingId].m_garbageBuffer);
                    info.Add("CustomBuffer1", buildings[buildingId].m_customBuffer1); // Garbage?
                    info.Add("IsFull", buildings[buildingId].Info.m_buildingAI.IsFull(buildingId, ref buildings[buildingId]));

                    buildings[buildingId].Info.m_buildingAI.GetMaterialAmount(buildingId, ref buildings[buildingId], TransferManager.TransferReason.Garbage, out materialAmount, out materialMax);
                }
                else if (buildings[buildingId].Info.m_buildingAI is HospitalAI)
                {
                    radius = ((HospitalAI)buildings[buildingId].Info.m_buildingAI).m_healthCareRadius;

                    info.Add("HealthCareRadius", ((HospitalAI)buildings[buildingId].Info.m_buildingAI).m_healthCareRadius);
                    info.Add("PatientCapacity", ((HospitalAI)buildings[buildingId].Info.m_buildingAI).m_patientCapacity);
                    info.Add("IsFull", buildings[buildingId].Info.m_buildingAI.IsFull(buildingId, ref buildings[buildingId]));

                    buildings[buildingId].Info.m_buildingAI.GetMaterialAmount(buildingId, ref buildings[buildingId], TransferManager.TransferReason.Sick, out materialAmount, out materialMax);
                }

                info.Add("materialMax", materialMax);
                info.Add("materialAmount", materialAmount);
                info.Add("materialFree", materialMax - materialAmount);
            }
            catch
            {
                info.Add("Error", "Material");
            }

            ushort ownVehicleCount  = 0;
            ushort madeVehicleCount = 0;

            try
            {
                ushort vehicleId = buildings[buildingId].m_ownVehicles;
                while (vehicleId != 0 && ownVehicleCount < ushort.MaxValue)
                {
                    ownVehicleCount++;
                    try
                    {
                        if ((vehicles[vehicleId].m_transferType == (byte)TransferManager.TransferReason.Garbage || vehicles[vehicleId].m_transferType == (byte)TransferManager.TransferReason.Dead) &&
                            vehicles[vehicleId].Info != null &&
                            (vehicles[vehicleId].m_flags & Vehicle.Flags.Created) == Vehicle.Flags.Created &&
                            (vehicles[vehicleId].m_flags & VehicleHelper.VehicleExists) != ~VehicleHelper.VehicleAll)
                        {
                            madeVehicleCount++;
                        }
                    }
                    catch
                    {
                        info.Add("Error", "Vehicle");
                    }

                    vehicleId = vehicles[vehicleId].m_nextOwnVehicle;
                }
                info.Add("OwnVehicles", ownVehicleCount);
                info.Add("MadeVehicles", madeVehicleCount);
            }
            catch
            {
                info.Add("Error", "Vehicles");
            }

            int productionRate = buildings[buildingId].m_productionRate;

            info.Add("VehicleCount", serviceVehicleCount);
            info.Add("ProductionRate", productionRate);
            info.Add("VehicleCountNominal", ((productionRate * serviceVehicleCount) + 99) / 100);

            try
            {
                int budget = Singleton <EconomyManager> .instance.GetBudget(buildings[buildingId].Info.m_buildingAI.m_info.m_class);

                productionRate = PlayerBuildingAI.GetProductionRate(productionRate, budget);
                int productionRate100     = PlayerBuildingAI.GetProductionRate(100, budget);
                int actualVehicleCount    = ((productionRate * serviceVehicleCount) + 99) / 100;
                int actualVehicleCount100 = ((productionRate100 * serviceVehicleCount) + 99) / 100;

                if (!float.IsNaN(radius))
                {
                    info.Add("Radius", radius);
                }

                info.Add("Budget", budget);
                info.Add("ProductionRateActual", productionRate, productionRate100);
                info.Add("VehicleCountActual", actualVehicleCount, actualVehicleCount100);
                info.Add("SpareVehicles", actualVehicleCount - ownVehicleCount, actualVehicleCount100 - ownVehicleCount);

                if (!float.IsNaN(radius))
                {
                    info.Add("ProductionRange", (double)productionRate * (double)radius * 0.00999999977648258);
                }
            }
            catch
            {
                info.Add("Error", "Budget");
            }

            try
            {
                float range = buildings[buildingId].Info.m_buildingAI.GetCurrentRange(buildingId, ref buildings[buildingId]);
                range = range * range * Global.Settings.RangeModifier;
                if (range < Global.Settings.RangeMinimum)
                {
                    info.Add("Range", range, '<', Global.Settings.RangeMinimum);
                }
                else if (range > Global.Settings.RangeMaximum)
                {
                    info.Add("Range", range, '>', Global.Settings.RangeMaximum);
                }
                else
                {
                    info.Add("Range", range, ">=<");
                }
            }
            catch
            {
                info.Add("Error", "Range");
            }

            try
            {
                List <string> needs = new List <string>();

                if (buildings[buildingId].m_garbageBuffer >= Global.Settings.Garbage.MinimumAmountForDispatch)
                {
                    needs.Add("Filthy");
                }
                else if (buildings[buildingId].m_garbageBuffer >= Global.Settings.Garbage.MinimumAmountForPatrol)
                {
                    needs.Add("Dirty");
                }
                else if (buildings[buildingId].m_garbageBuffer > 0)
                {
                    needs.Add("Dusty");
                }

                if (buildings[buildingId].m_deathProblemTimer > 0)
                {
                    needs.Add("Dead");
                }

                if (buildings[buildingId].m_garbageBuffer * Dispatcher.ProblemBufferModifier >= Dispatcher.ProblemLimitForgotten ||
                    buildings[buildingId].m_deathProblemTimer * Dispatcher.ProblemTimerModifier >= Dispatcher.ProblemLimitForgotten)
                {
                    needs.Add("Forgotten");
                }

                info.Add("Needs", needs);
            }
            catch
            {
                info.Add("Error", "Needs");
            }

            info.Add("DeathProblemTimer", buildings[buildingId].m_deathProblemTimer);
            info.Add("HealthProblemTimer", buildings[buildingId].m_healthProblemTimer);
            info.Add("MajorProblemTimer", buildings[buildingId].m_majorProblemTimer);

            try
            {
                int  citizens = 0;
                int  count    = 0;
                uint unitId   = buildings[buildingId].m_citizenUnits;
                while (unitId != 0)
                {
                    CitizenUnit unit = citizenManager.m_units.m_buffer[unitId];

                    try
                    {
                        for (int i = 0; i < 5; i++)
                        {
                            uint citizenId = unit.GetCitizen(i);
                            if (citizenId != 0)
                            {
                                Citizen citizen = citizenManager.m_citizens.m_buffer[citizenId];
                                if (citizen.Dead && citizen.GetBuildingByLocation() == buildingId)
                                {
                                    citizens++;
                                }
                            }
                        }
                    }
                    catch
                    {
                        info.Add("Error", "Citizen");
                    }

                    count++;
                    if (count > (int)ushort.MaxValue * 10)
                    {
                        break;
                    }

                    unitId = unit.m_nextUnit;
                }
                info.Add("DeadCitizens", citizens);
            }
            catch
            {
                info.Add("Error", "Citizens");
            }

            try
            {
                info.Add("GarbageAmount", buildings[buildingId].Info.m_buildingAI.GetGarbageAmount(buildingId, ref buildings[buildingId]));
                info.Add("GarbageBuffer", buildings[buildingId].m_garbageBuffer);
            }
            catch
            {
                info.Add("Error", "Garbage");
            }

            try
            {
                string problems = buildings[buildingId].m_problems.ToString();
                if (problems.IndexOfAny(new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }) >= 0)
                {
                    foreach (Notification.Problem problem in Enum.GetValues(typeof(Notification.Problem)))
                    {
                        if (problem != Notification.Problem.None && (buildings[buildingId].m_problems & problem) == problem)
                        {
                            problems += ", " + problem.ToString();
                        }
                    }
                }
                info.Add("Problems", problems);
            }
            catch
            {
                info.Add("Error", "Problems");
            }

            info.Add("FireIntensoty", buildings[buildingId].m_fireIntensity);

            try
            {
                string flags = buildings[buildingId].m_flags.ToString();
                if (flags.IndexOfAny(new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }) >= 0)
                {
                    foreach (Building.Flags flag in Enum.GetValues(typeof(Building.Flags)))
                    {
                        if (flag != Building.Flags.None && (buildings[buildingId].m_flags & flag) == flag)
                        {
                            flags += ", " + flag.ToString();
                        }
                    }
                }
                info.Add("Flags", flags);
            }
            catch
            {
                info.Add("Error", "Flags");
            }

            try
            {
                string status = buildings[buildingId].Info.m_buildingAI.GetLocalizedStatus(buildingId, ref buildings[buildingId]);
                if (!String.IsNullOrEmpty(status))
                {
                    info.Add("Status", status);
                }
            }
            catch
            {
                info.Add("Error", "Status");
            }

            try
            {
                info.Add("AI", buildings[buildingId].Info.m_buildingAI.GetType().AssemblyQualifiedName);
            }
            catch
            {
                info.Add("Error", "AI");
            }

            return(info);
        }
        public override void LateUpdate()
        {
            if (FavCimsMainClass.UnLoading) {
                return;
            }

            if (this.execute || this.FirstRun) {

                if(this.isVisible) {

                    try
                    {
                        citizen = MyInstanceID.Citizen;

                        this.CitizenData = this.MyCitizen.m_citizens.m_buffer [citizen];

                        //Little Screen Labels
                        this.BubbleCitizenAge.text = FavCimsLang.text ("FavCimsAgeColText_text");
                        this.BubbleCitizenAgePhase.text = FavCimsLang.text ("FavCimsAgePhaseColText_text");
                        this.BubbleCitizenEducation.text = FavCimsLang.text ("FavCimsEduColText_text");
                        this.BubbleWealthSprite.tooltip = FavCimsLang.text("Wealth_Label");
                        this.FavCimsDistrictLabel.text = FavCimsLang.text("District_Label");

                        //Family Label
                        this.BubbleFamilyBarLabel.text = FavCimsLang.text ("Citizen_Family_unit");
                        this.NoChildsFButton.text = FavCimsLang.text ("Citizen_Details_No_Childs");
                        this.NoPartnerFButton.text = FavCimsLang.text ("Citizen_Details_No_Partner");

                        ///Citizen Family
                        this.MyCitizenUnit = this.CitizenData.GetContainingUnit (citizen, MyBuilding.m_buildings.m_buffer [CitizenData.m_homeBuilding].m_citizenUnits, CitizenUnit.Flags.Home);

                        if (this.MyCitizenUnit != 0) {

                            this.Family = this.MyCitizen.m_units.m_buffer [this.MyCitizenUnit];

                            //Selected Citizen Data

                            //Citizen Name
                            this.BubbleHeaderCitizenName.text = this.MyCitizen.GetCitizenName (citizen);

                            //Citizen Genre
                            if (Citizen.GetGender (citizen) == Citizen.Gender.Female) {
                                this.BubbleHeaderIconSprite.texture = TextureDB.BubbleHeaderIconSpriteTextureFemale;
                                this.BubbleHeaderCitizenName.textColor = new Color32 (255, 102, 204, 213); //r,g,b,a
                                this.BubbleHeaderCitizenName.hoveredTextColor = new Color32 (255, 102, 204, 213); //r,g,b,a
                                this.BubbleHeaderCitizenName.pressedTextColor = new Color32 (255, 102, 204, 213); //r,g,b,a
                                this.BubbleHeaderCitizenName.focusedTextColor = new Color32 (255, 102, 204, 213); //r,g,b,a
                            }else{
                                this.BubbleHeaderIconSprite.texture = TextureDB.BubbleHeaderIconSpriteTextureMale;
                                this.BubbleHeaderCitizenName.textColor = new Color32 (204, 204, 51, 40); //r,g,b,a
                                this.BubbleHeaderCitizenName.hoveredTextColor = new Color32 (204, 204, 51, 40); //r,g,b,a
                                this.BubbleHeaderCitizenName.pressedTextColor = new Color32 (204, 204, 51, 40); //r,g,b,a
                                this.BubbleHeaderCitizenName.focusedTextColor = new Color32 (204, 204, 51, 40); //r,g,b,a
                            }

                            //Citizen Health
                            int tmp_health = this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].m_health;
                            string healthIcon = GetHealthString(Citizen.GetHealthLevel (tmp_health));
                            this.BubbleHealthSprite.normalBgSprite = healthIcon;
                            this.BubbleHealthSprite.tooltip = Locale.Get("INFO_HEALTH_TITLE");
                            this.BubbleHealthValue.text = FavCimsLang.text("Health_Level_" + sHealthLevels[(int) Citizen.GetHealthLevel (tmp_health)] +
                                                                           "_" + Citizen.GetGender (citizen));

                            switch (Citizen.GetHealthLevel (tmp_health)) {

                            case Citizen.Health.ExcellentHealth:
                                BubbleHealthValue.textColor = new Color32 (0, 102, 51, 100); //r,g,b,a
                                break;

                            case Citizen.Health.VeryHealthy:
                                BubbleHealthValue.textColor = new Color32 (0, 102, 51, 100); //r,g,b,a
                                break;

                            case Citizen.Health.Healthy:
                                BubbleHealthValue.textColor = new Color32 (102, 204, 0, 60); //r,g,b,a
                                break;

                            case Citizen.Health.PoorHealth:
                                BubbleHealthValue.textColor = new Color32 (255, 204, 0, 32); //r,g,b,a
                                break;

                            case Citizen.Health.Sick:
                                BubbleHealthValue.textColor = new Color32 (153, 0, 0, 0); //r,g,b,a
                                break;

                            case Citizen.Health.VerySick:
                                BubbleHealthValue.textColor = new Color32 (255, 0, 0, 0); //r,g,b,a
                                break;
                            }

                            //Citizen Education
                            var tmp_education = this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].EducationLevel;
                            string education = tmp_education.ToString ();
                            this.BubbleRow1EducationTooltipArea.tooltip = FavCimsLang.text ("Education_" + education + "_" + Citizen.GetGender (citizen));

                            if (education == "ThreeSchools") {
                                this.BubbleEduLevel3.isEnabled = true;
                                this.BubbleEduLevel2.isEnabled = true;
                                this.BubbleEduLevel1.isEnabled = true;
                            } else if (education == "TwoSchools") {
                                this.BubbleEduLevel3.isEnabled = false;
                                this.BubbleEduLevel2.isEnabled = true;
                                this.BubbleEduLevel1.isEnabled = true;
                            } else if (education == "OneSchool") {
                                this.BubbleEduLevel3.isEnabled = false;
                                this.BubbleEduLevel2.isEnabled = false;
                                this.BubbleEduLevel1.isEnabled = true;
                            } else {
                                this.BubbleEduLevel3.isEnabled = false;
                                this.BubbleEduLevel2.isEnabled = false;
                                this.BubbleEduLevel1.isEnabled = false;
                            }

                            //Citizen Wellbeing
                            int tmp_wellbeing = this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].m_wellbeing;
                            //string wellbeing = Citizen.GetWellbeingLevel (tmp_education, tmp_wellbeing).ToString ();
                            string wellbeingIcon = GetHappinessString(Citizen.GetHappinessLevel (tmp_wellbeing));
                            this.BubbleRow2WellbeingIcon.normalBgSprite = wellbeingIcon;
                            this.BubbleRow2WellbeingIcon.tooltip = FavCimsLang.text("WellBeingLabel") + FavCimsLang.text (wellbeingIcon);

                            //Citizen Wealth
                            var tmp_wealth = this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].WealthLevel;

                            this.BubbleRow2WealthValueVal.tooltip = FavCimsLang.text("Wealth_Label");
                            if(tmp_wealth == Citizen.Wealth.Low) {
                                this.BubbleRow2WealthValueVal.text = FavCimsLang.text("Low_Wealth_" + Citizen.GetGender (citizen));
                                this.BubbleRow2WealthValueVal.textColor = new Color32 (153, 0, 0, 0); //r,g,b,a
                            }else if (tmp_wealth == Citizen.Wealth.Medium) {
                                this.BubbleRow2WealthValueVal.text = FavCimsLang.text("Mid_Wealth_" + Citizen.GetGender (citizen));
                                this.BubbleRow2WealthValueVal.textColor = new Color32 (255, 204, 0, 32);
                            }else {
                                this.BubbleRow2WealthValueVal.text = FavCimsLang.text("High_Wealth_" + Citizen.GetGender (citizen));
                                this.BubbleRow2WealthValueVal.textColor = new Color32 (102, 204, 0, 60); //r,g,b,a
                            }

                            //Citizen Happiness
                            int tmp_happiness = Citizen.GetHappiness (tmp_health, tmp_wellbeing);
                            //string Happiness = Citizen.GetHappinessLevel (tmp_happiness).ToString (); //Bad, Poor, Good, Excellent, Suberb
                            string HappinessIcon = GetHappinessString (Citizen.GetHappinessLevel (tmp_happiness));
                            this.BubbleRow1HappyIcon.normalBgSprite = HappinessIcon;
                            this.BubbleRow1HappyIcon.tooltip = FavCimsLang.text("HappinessLabel") + FavCimsLang.text (HappinessIcon);

                            //Age Group (Age Phase)
                            int tmp_age = this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].m_age;
                            string agegroup = Citizen.GetAgeGroup (tmp_age).ToString ();
                            this.BubbleCitizenAgePhaseVal.text = FavCimsLang.text ("AgePhase_" + agegroup + "_" + Citizen.GetGender (citizen));

                            //Real Age
                            this.RealAge = FavCimsCore.CalculateCitizenAge (tmp_age);

                            if (this.RealAge <= 12) { //CHILD
                                this.BubbleCitizenAgeVal.text = this.RealAge.ToString ();
                                this.BubbleCitizenAgeVal.textColor = new Color32 (83, 166, 0, 60); //r,g,b,a
                                this.BubbleCitizenAgePhaseVal.textColor = new Color32 (83, 166, 0, 60); //r,g,b,a
                            } else if (this.RealAge <= 19) { //TEEN
                                this.BubbleCitizenAgeVal.text = this.RealAge.ToString ();
                                this.BubbleCitizenAgeVal.textColor = new Color32 (0, 102, 51, 100); //r,g,b,a
                                this.BubbleCitizenAgePhaseVal.textColor = new Color32 (0, 102, 51, 100); //r,g,b,a
                            } else if (this.RealAge <= 25) { //YOUNG
                                this.BubbleCitizenAgeVal.text = this.RealAge.ToString ();
                                this.BubbleCitizenAgeVal.textColor = new Color32 (255, 204, 0, 32); //r,g,b,a
                                this.BubbleCitizenAgePhaseVal.textColor = new Color32 (255, 204, 0, 32); //r,g,b,a
                            } else if (this.RealAge <= 65) { //ADULT
                                this.BubbleCitizenAgeVal.text = this.RealAge.ToString ();
                                this.BubbleCitizenAgeVal.textColor = new Color32 (255, 102, 0, 16); //r,g,b,a
                                this.BubbleCitizenAgePhaseVal.textColor = new Color32 (255, 102, 0, 16); //r,g,b,a
                            } else if (this.RealAge <= 90) { //SENIOR
                                this.BubbleCitizenAgeVal.text = this.RealAge.ToString ();
                                this.BubbleCitizenAgeVal.textColor = new Color32 (153, 0, 0, 0); //r,g,b,a
                                this.BubbleCitizenAgePhaseVal.textColor = new Color32 (153, 0, 0, 0); //r,g,b,a
                            } else { //FINAL
                                this.BubbleCitizenAgeVal.text = this.RealAge.ToString ();
                                this.BubbleCitizenAgeVal.textColor = new Color32 (255, 0, 0, 0); //r,g,b,a
                                this.BubbleCitizenAgePhaseVal.textColor = new Color32 (255, 0, 0, 0); //r,g,b,a
                            }

                            //Working Place
                            this.WorkPlace = this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].m_workBuilding;
                            if (this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].GetCurrentSchoolLevel (citizen) != ItemClass.Level.None) {
                                this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = null;
                                this.FavCimsWorkingPlaceSprite.texture = TextureDB.FavCimsWorkingPlaceTextureStudent;
                                this.FavCimsCitizenWorkPlaceLevelSprite.texture = null;
                                //this.CitizenRowData ["workplace"] = "Student";
                                this.FavCimsWorkingPlace.tooltip = Locale.Get ("CITIZEN_SCHOOL_LEVEL", this.MyCitizen.m_citizens.m_buffer [MyInstanceID.Index].GetCurrentSchoolLevel (citizen).ToString ());
                            } else if (this.WorkPlace == 0) {
                                this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = null;

                                if (tmp_age >= 180) {
                                    //In Pensione
                                    this.FavCimsWorkingPlaceSprite.texture = TextureDB.FavCimsWorkingPlaceTextureRetired;
                                    //this.CitizenRowData ["workplace"] = "Retired";
                                    this.FavCimsWorkingPlace.text = FavCimsLang.text ("Citizen_Retired");
                                    this.FavCimsWorkingPlace.isEnabled = false;
                                    this.FavCimsWorkingPlace.tooltip = FavCimsLang.text ("Citizen_Retired_tooltip");
                                    this.FavCimsWorkingPlaceSprite.tooltip = null;
                                    this.FavCimsWorkingPlaceButtonGamDefImg.tooltip = null;
                                    this.FavCimsCitizenWorkPlaceLevelSprite.texture = null;
                                } else {
                                    this.FavCimsWorkingPlaceSprite.texture = TextureDB.FavCimsWorkingPlaceTexture; //unemployed
                                    //this.CitizenRowData ["workplace"] = "Unemployed";
                                    this.FavCimsWorkingPlace.text = Locale.Get ("CITIZEN_OCCUPATION_UNEMPLOYED");
                                    this.FavCimsWorkingPlace.isEnabled = false;
                                    this.FavCimsWorkingPlace.tooltip = FavCimsLang.text ("Unemployed_tooltip");
                                    this.FavCimsWorkingPlaceSprite.tooltip = null;
                                    this.FavCimsWorkingPlaceButtonGamDefImg.tooltip = null;
                                    this.FavCimsCitizenWorkPlaceLevelSprite.texture = null;
                                }
                            }

                            //Perchè l'edificio è presente sia che lavori sia che vada a scuola, se lo metto nell'else qui sopra se va a scuola non comparirebbe nulla o dovrei scriverlo 2 volte.
                            if (this.WorkPlace != 0) {
                                this.WorkPlaceID.Building = this.WorkPlace;
                                //this.CitizenRowData ["workplace"] = this.MyBuilding.GetBuildingName (this.WorkPlace, this.MyInstanceID);
                                this.FavCimsWorkingPlace.text = this.MyBuilding.GetBuildingName (this.WorkPlace, this.MyInstanceID);
                                this.FavCimsWorkingPlace.isEnabled = true;
                                this.WorkInfo = this.MyBuilding.m_buildings.m_buffer [WorkPlaceID.Index].Info;

                                if (this.WorkInfo.m_class.m_service == ItemClass.Service.Commercial) {
                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = null;
                                    if (this.WorkInfo.m_class.m_subService == ItemClass.SubService.CommercialHigh) {
                                        this.FavCimsWorkingPlace.textColor = new Color32 (0, 51, 153, 147); //r,g,b,a
                                        this.FavCimsWorkingPlaceSprite.texture = TextureDB.FavCimsCitizenCommercialHighTexture;
                                        this.FavCimsWorkingPlace.tooltip = Locale.Get ("ZONEDBUILDING_TITLE", ItemClass.SubService.CommercialHigh.ToString ());
                                    } else {
                                        this.FavCimsWorkingPlace.textColor = new Color32 (0, 153, 204, 130); //r,g,b,a
                                        this.FavCimsWorkingPlaceSprite.texture = TextureDB.FavCimsCitizenCommercialLowTexture;
                                        this.FavCimsWorkingPlace.tooltip = Locale.Get ("ZONEDBUILDING_TITLE", ItemClass.SubService.CommercialLow.ToString ());
                                    }

                                    switch (this.WorkInfo.m_class.m_level)
                                    {
                                        case ItemClass.Level.Level3:
                                            this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsIndustrialLevel [3];
                                            break;
                                        case ItemClass.Level.Level2:
                                            this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsCommercialLevel [2];
                                            break;
                                        default:
                                            this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsCommercialLevel [1];
                                            break;
                                    }

                                } else if (this.WorkInfo.m_class.m_service == ItemClass.Service.Industrial) {

                                    this.FavCimsWorkingPlace.textColor = new Color32 (255, 204, 0, 32); //r,g,b,a
                                    this.FavCimsWorkingPlace.tooltip = Locale.Get ("ZONEDBUILDING_TITLE", "Industrial");

                                    switch (this.WorkInfo.m_class.m_subService)
                                    {
                                    case ItemClass.SubService.IndustrialFarming:
                                        this.FavCimsWorkingPlaceSprite.texture = null;
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyFarming";
                                        break;
                                    case ItemClass.SubService.IndustrialForestry:
                                        this.FavCimsWorkingPlaceSprite.texture = null;
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "ResourceForestry";
                                        break;
                                    case ItemClass.SubService.IndustrialOil:
                                        this.FavCimsWorkingPlaceSprite.texture = null;
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyOil";
                                        break;
                                    case ItemClass.SubService.IndustrialOre:
                                        this.FavCimsWorkingPlaceSprite.texture = null;
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyOre";
                                        break;
                                    default:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = null;
                                        this.FavCimsWorkingPlaceSprite.texture = TextureDB.FavCimsCitizenIndustrialGenericTexture;
                                        break;
                                    }

                                    switch (this.WorkInfo.m_class.m_level)
                                    {
                                    case ItemClass.Level.Level3:
                                        this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsIndustrialLevel [3];
                                        break;
                                    case ItemClass.Level.Level2:
                                        this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsCommercialLevel [2];
                                        break;
                                    default:
                                        this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsCommercialLevel [1];
                                        break;
                                    }

                                } else if (this.WorkInfo.m_class.m_service == ItemClass.Service.Office) {
                                    this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = null;
                                    this.FavCimsWorkingPlace.textColor = new Color32 (0, 204, 255, 128); //r,g,b,a
                                    this.FavCimsWorkingPlaceSprite.texture = TextureDB.FavCimsCitizenOfficeTexture;
                                    this.FavCimsWorkingPlace.tooltip = Locale.Get ("ZONEDBUILDING_TITLE", "Office");

                                    switch (this.WorkInfo.m_class.m_level)
                                    {
                                    case ItemClass.Level.Level3:
                                        this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsIndustrialLevel [3];
                                        break;
                                    case ItemClass.Level.Level2:
                                        this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsCommercialLevel [2];
                                        break;
                                    default:
                                        this.FavCimsCitizenWorkPlaceLevelSprite.texture = TextureDB.FavCimsCommercialLevel [1];
                                        break;
                                    }

                                } else {
                                    this.FavCimsCitizenWorkPlaceLevelSprite.texture = null;
                                    this.FavCimsWorkingPlaceSprite.texture = null;
                                    this.FavCimsWorkingPlace.textColor = new Color32 (153, 102, 51, 20); //r,g,b,a

                                    switch (this.WorkInfo.m_class.m_service)
                                    {
                                    case ItemClass.Service.FireDepartment:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "InfoIconFireSafety";
                                        this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "FireDepartment");
                                        break;
                                    case ItemClass.Service.HealthCare:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "ToolbarIconHealthcareFocused";
                                        this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "Healthcare");
                                        break;
                                    case ItemClass.Service.PoliceDepartment:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "ToolbarIconPolice";
                                        this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "Police");
                                        break;
                                    case ItemClass.Service.Garbage:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyRecycling";
                                        this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "Garbage");
                                        break;
                                    case ItemClass.Service.Electricity:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyPowerSaving";
                                        this.FavCimsWorkingPlace.tooltip = FavCimsLang.text ("Electricity_job");
                                        break;
                                    case ItemClass.Service.Education:
                                        this.FavCimsWorkingPlace.textColor = new Color32 (0, 102, 51, 100); //r,g,b,a
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "InfoIconEducationPressed";
                                        break;
                                    case ItemClass.Service.Beautification:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "SubBarBeautificationParksnPlazas";
                                        this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "Beautification");
                                        break;
                                    case ItemClass.Service.Government:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "ToolbarIconGovernment";
                                        this.FavCimsWorkingPlace.tooltip = FavCimsLang.text ("Government_job");
                                        break;
                                    case ItemClass.Service.Water:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyWaterSaving";
                                        this.FavCimsWorkingPlace.tooltip = FavCimsLang.text ("Water_job");
                                        break;
                                    case ItemClass.Service.PublicTransport:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyFreePublicTransport";
                                        this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "PublicTransport");
                                        break;
                                    case ItemClass.Service.Monument:
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "FeatureMonumentLevel6";
                                        this.FavCimsWorkingPlace.tooltip = Locale.Get ("SERVICE_DESC", "Monuments");
                                        break;
                                    default:
                                        this.FavCimsWorkingPlace.textColor = new Color32 (255, 204, 0, 32); //r,g,b,a
                                        this.FavCimsWorkingPlaceButtonGamDefImg.normalBgSprite = "IconPolicyNone";
                                        this.FavCimsWorkingPlace.tooltip = null;
                                        break;
                                    }
                                }

                                //District
                                this.WorkDistrict = (int)MyDistrict.GetDistrict (this.MyBuilding.m_buildings.m_buffer [WorkPlaceID.Index].m_position);

                                if (this.WorkDistrict == 0) {
                                    this.FavCimsWorkingPlaceSprite.tooltip = FavCimsLang.text ("DistrictLabel") + FavCimsLang.text ("DistrictNameNoDistrict");
                                } else {
                                    this.FavCimsWorkingPlaceSprite.tooltip = FavCimsLang.text ("DistrictLabel") + MyDistrict.GetDistrictName (this.WorkDistrict);
                                }

                            }else{
                                this.FavCimsWorkingPlace.isEnabled = false;
                                this.FavCimsCitizenWorkPlaceLevelSprite.texture = null;
                                this.FavCimsWorkingPlaceButtonGamDefImg.tooltip = null;
                                this.FavCimsWorkingPlaceSprite.tooltip = null;
                            }

                            //Family House
                            this.CitizenHome = this.MyCitizen.m_citizens.m_buffer [this.MyInstanceID.Index].m_homeBuilding;
                            if (this.CitizenHome != 0) {
                                this.CitizenHomeID.Building = this.CitizenHome;

                                this.BubbleHomeName.text = this.MyBuilding.GetBuildingName (this.CitizenHome, this.MyInstanceID);
                                this.BubbleHomeName.isEnabled = true;
                                this.BubbleHomeIcon.texture = TextureDB.FavCimsCitizenHomeTexture;
                                this.HomeInfo = this.MyBuilding.m_buildings.m_buffer [CitizenHomeID.Index].Info;

                                if (this.HomeInfo.m_class.m_service == ItemClass.Service.Residential) {

                                    this.BubbleHomeName.tooltip = null;

                                    if (this.HomeInfo.m_class.m_subService == ItemClass.SubService.ResidentialHigh) {
                                        this.BubbleHomeName.textColor = new Color32 (0, 102, 51, 100); //r,g,b,a
                                        this.BubbleHomeIcon.texture = TextureDB.FavCimsCitizenHomeTextureHigh;
                                        this.BubbleHomeName.tooltip = Locale.Get ("ZONEDBUILDING_TITLE", ItemClass.SubService.ResidentialHigh.ToString ());
                                    } else if (this.HomeInfo.m_class.m_subService == ItemClass.SubService.ResidentialLow) {
                                        this.BubbleHomeName.textColor = new Color32 (0, 153, 0, 80); //r,g,b,a
                                        this.BubbleHomeIcon.texture = TextureDB.FavCimsCitizenHomeTexture;
                                        this.BubbleHomeName.tooltip = Locale.Get ("ZONEDBUILDING_TITLE", ItemClass.SubService.ResidentialLow.ToString ());
                                    }

                                    switch (this.HomeInfo.m_class.m_level)
                                    {
                                    case ItemClass.Level.Level5:
                                        this.BubbleHomeLevel.texture = TextureDB.FavCimsResidentialLevel [5];
                                        break;
                                    case ItemClass.Level.Level4:
                                        this.BubbleHomeLevel.texture = TextureDB.FavCimsResidentialLevel [4];
                                        break;
                                    case ItemClass.Level.Level3:
                                        this.BubbleHomeLevel.texture = TextureDB.FavCimsResidentialLevel [3];
                                        break;
                                    case ItemClass.Level.Level2:
                                        this.BubbleHomeLevel.texture = TextureDB.FavCimsResidentialLevel [2];
                                        break;
                                    default:
                                        this.BubbleHomeLevel.texture = TextureDB.FavCimsResidentialLevel [1];
                                        break;
                                    }

                                    //District
                                    this.HomeDistrict = (int)MyDistrict.GetDistrict (this.MyBuilding.m_buildings.m_buffer [this.CitizenHomeID.Index].m_position);

                                    if (this.HomeDistrict == 0) {
                                        this.BubbleHomeIcon.tooltip = FavCimsLang.text ("DistrictLabel") + FavCimsLang.text ("DistrictNameNoDistrict");
                                    } else {
                                        this.BubbleHomeIcon.tooltip = FavCimsLang.text ("DistrictLabel") + MyDistrict.GetDistrictName (this.HomeDistrict);
                                    }

                                    //Home Status Problems
                                    Notification.Problem HomeProblems = MyBuilding.m_buildings.m_buffer[this.CitizenHome].m_problems;

                                    if(HomeProblems != Notification.Problem.None) {
                                        this.BubbleDetailsBgSprite.texture = TextureDB.BubbleDetailsBgSpriteProblems;
                                    }else{
                                        this.BubbleDetailsBgSprite.texture = TextureDB.BubbleDetailsBgSprite;
                                    }

                                    if(HomeProblems.ToString().Contains(Notification.Problem.Electricity.ToString())) {
                                        this.BubbleDetailsElettricity.normalFgSprite = "TutorialGlow";
                                        this.BubbleDetailsElettricity.tooltip = Locale.Get("NOTIFICATION_TITLE","Electricity");
                                    }else{
                                        this.BubbleDetailsElettricity.normalFgSprite = null;
                                        this.BubbleDetailsElettricity.tooltip = Locale.Get("NOTIFICATION_NONE");
                                    }

                                    if(HomeProblems.ToString().Contains(Notification.Problem.Sewage.ToString())) {
                                        this.BubbleDetailsWater.normalFgSprite = "TutorialGlow";
                                        this.BubbleDetailsWater.tooltip = Locale.Get("NOTIFICATION_TITLE","Sewage");
                                    } else if(HomeProblems.ToString().Contains(Notification.Problem.DirtyWater.ToString())) {
                                        this.BubbleDetailsWater.normalFgSprite = "TutorialGlow";
                                        this.BubbleDetailsWater.tooltip = Locale.Get("NOTIFICATION_NORMAL","DirtyWater");
                                    } else if(HomeProblems.ToString().Contains(Notification.Problem.Water.ToString())) {
                                        this.BubbleDetailsWater.normalFgSprite = "TutorialGlow";
                                        this.BubbleDetailsWater.tooltip = Locale.Get("NOTIFICATION_TITLE","Water");
                                    }else if(HomeProblems.ToString().Contains(Notification.Problem.Flood.ToString())) {
                                        this.BubbleDetailsWater.normalFgSprite = "TutorialGlow";
                                        this.BubbleDetailsWater.tooltip = Locale.Get("NOTIFICATION_TITLE","Flood");
                                    }else{
                                        this.BubbleDetailsWater.normalFgSprite = null;
                                        this.BubbleDetailsWater.tooltip = Locale.Get("NOTIFICATION_NONE");
                                    }

                                    if(HomeProblems.ToString().Contains(Notification.Problem.Death.ToString())) {
                                        this.BubbleDetailsDeath.normalFgSprite = "TutorialGlow";
                                        this.BubbleDetailsDeath.tooltip = Locale.Get("NOTIFICATION_TITLE","Death");
                                    }else{
                                        this.BubbleDetailsDeath.normalFgSprite = null;
                                        this.BubbleDetailsDeath.tooltip = Locale.Get("NOTIFICATION_NONE");
                                    }

                                    if(HomeProblems.ToString().Contains(Notification.Problem.Fire.ToString())) {
                                        this.BubbleDetailsFire.normalFgSprite = "TutorialGlow";
                                        this.BubbleDetailsFire.tooltip = Locale.Get("NOTIFICATION_TITLE","Fire");
                                    }else{
                                        this.BubbleDetailsFire.normalFgSprite = null;
                                        this.BubbleDetailsFire.tooltip = Locale.Get("NOTIFICATION_NONE");
                                    }

                                    if(HomeProblems.ToString().Contains(Notification.Problem.Garbage.ToString())) {
                                        this.BubbleDetailsGarbage.normalFgSprite = "TutorialGlow";
                                        this.BubbleDetailsGarbage.tooltip = Locale.Get("NOTIFICATION_TITLE","Garbage");
                                    }else{
                                        this.BubbleDetailsGarbage.normalFgSprite = null;
                                        this.BubbleDetailsGarbage.tooltip = Locale.Get("NOTIFICATION_NONE");
                                    }

                                    if(HomeProblems.ToString().Contains(Notification.Problem.LandValueLow.ToString())) {
                                        this.BubbleDetailsLandValue.normalFgSprite = "TutorialGlow";
                                        this.BubbleDetailsLandValue.tooltip = Locale.Get("NOTIFICATION_TITLE","LandValueLow");
                                    }else if(HomeProblems.ToString().Contains(Notification.Problem.TooFewServices.ToString())) {
                                        this.BubbleDetailsLandValue.normalFgSprite = "TutorialGlow";
                                        this.BubbleDetailsLandValue.tooltip = Locale.Get("NOTIFICATION_TITLE","ToofewServices");
                                    }else if(HomeProblems.ToString().Contains(Notification.Problem.TaxesTooHigh.ToString())) {
                                        this.BubbleDetailsLandValue.normalFgSprite = "TutorialGlow";
                                        this.BubbleDetailsLandValue.tooltip = Locale.Get("NOTIFICATION_TITLE","TaxesTooHigh");
                                    }else{
                                        this.BubbleDetailsLandValue.normalFgSprite = null;
                                        this.BubbleDetailsLandValue.tooltip = Locale.Get("NOTIFICATION_NONE");
                                    }

                                    if(HomeProblems.ToString().Contains(Notification.Problem.Noise.ToString())) {
                                        this.BubbleDetailsNoise.normalFgSprite = "TutorialGlow";
                                        this.BubbleDetailsNoise.tooltip = Locale.Get("NOTIFICATION_NORMAL","Noise");
                                    }else{
                                        this.BubbleDetailsNoise.normalFgSprite = null;
                                        this.BubbleDetailsNoise.tooltip = Locale.Get("NOTIFICATION_NONE");
                                    }

                                    if(HomeProblems.ToString().Contains(Notification.Problem.Pollution.ToString())) {
                                        this.BubbleDetailsPollution.normalFgSprite = "TutorialGlow";
                                        this.BubbleDetailsPollution.tooltip = Locale.Get("NOTIFICATION_NORMAL","Pollution");
                                    }else{
                                        this.BubbleDetailsPollution.normalFgSprite = null;
                                        this.BubbleDetailsPollution.tooltip = Locale.Get("NOTIFICATION_NONE");
                                    }

                                    if(HomeProblems.ToString().Contains(Notification.Problem.Crime.ToString())) {
                                        this.BubbleDetailsCrime.normalFgSprite = "TutorialGlow";
                                        this.BubbleDetailsCrime.tooltip = Locale.Get("NOTIFICATION_TITLE","Crime");
                                    }else{
                                        this.BubbleDetailsCrime.normalFgSprite = null;
                                        this.BubbleDetailsCrime.tooltip = Locale.Get("NOTIFICATION_NONE");
                                    }
                                }
                            } else {
                                this.BubbleHomeName.text = FavCimsLang.text ("Citizen_HomeLess");
                                this.BubbleHomeName.isEnabled = false;
                                this.BubbleHomeIcon.texture = TextureDB.FavCimsCitizenHomeTextureHomeless;
                                this.BubbleHomeIcon.tooltip = FavCimsLang.text ("DistrictNameNoDistrict");
                                this.BubbleHomeName.tooltip = FavCimsLang.text ("Citizen_HomeLess_tooltip");
                            }

                            //Activity
                            Activity(citizen, this.FavCimsLastActivityVehicleButton, this.FavCimsLastActivity, out this.MyVehicleID, out this.MyTargetID);

                            //Now in this District
                            this.MainCitizenInstance = MyCitizen.m_citizens.m_buffer[citizen].m_instance;
                            this.CitizenDistrict = (int)MyDistrict.GetDistrict(MyCitizen.m_instances.m_buffer[this.MainCitizenInstance].GetSmoothPosition(this.MainCitizenInstance));

                            if (this.CitizenDistrict == 0) {
                                this.FavCimsDistrictValue.tooltip = FavCimsLang.text("District_Label_tooltip");
                                this.FavCimsDistrictValue.text = FavCimsLang.text ("DistrictNameNoDistrict");
                            } else {
                                this.FavCimsDistrictValue.tooltip = FavCimsLang.text("District_Label_tooltip");
                                this.FavCimsDistrictValue.text = MyDistrict.GetDistrictName (this.CitizenDistrict);
                            }

                            //Citizen Have a Car?
                            FamilyVehicle(citizen, BubblePersonalCarButton, out this.PersonalVehicleID);
                            //Family Have a Car?
                            FamilyVehicle(this.Family.m_citizen0, BubbleFamilyBarCarButton, out this.FamilyVehicleID);

                            bool isSon = false;
                            int Sons = 0;

                            //Partner
                            if (this.Family.m_citizen0 != 0 && citizen == this.Family.m_citizen1) { //&& this.Family.m_citizen0 != citizen
                                this.CitizenPartner = this.Family.m_citizen0;
                                this.BubblePartnerLove.normalBgSprite = "InfoIconHealth";
                                //Have Pet?
                                if(this.DogOwner != 0) {
                                    FamilyPet(this.DogOwner);
                                }else{
                                    FamilyPet(this.Family.m_citizen1);
                                }
                            } else {
                                if (this.Family.m_citizen1 != 0 && citizen == this.Family.m_citizen0) {
                                    this.CitizenPartner = this.Family.m_citizen1;
                                    this.BubblePartnerLove.normalBgSprite = "InfoIconHealth";
                                    //Have Pet?
                                    if(this.DogOwner != 0) {
                                        FamilyPet(this.DogOwner);
                                    }else{
                                        FamilyPet(this.Family.m_citizen0);
                                    }
                                }else if (citizen == this.Family.m_citizen0) {
                                    //Have Pet?
                                    if(this.DogOwner != 0) {
                                        FamilyPet(this.DogOwner);
                                    }else{
                                        FamilyPet(citizen);
                                    }
                                    this.CitizenPartner = 0;
                                } else {
                                    this.BubblePartnerLove.normalBgSprite = "InfoIconAge";
                                    this.CitizenPartner = this.Family.m_citizen0;
                                    isSon = true;
                                }
                            }

                            if (this.CitizenPartner != 0) {

                                this.PartnerID.Citizen = CitizenPartner;

                                int CitizenPartnerINT = (int)((UIntPtr)this.CitizenPartner);

                                this.BubblePartnerName.text = this.MyCitizen.GetCitizenName (CitizenPartner);
                                if (Citizen.GetGender (CitizenPartner) == Citizen.Gender.Female) {
                                    this.BubblePartnerName.textColor = new Color32 (255, 102, 204, 213); //r,g,b,a
                                } else {
                                    this.BubblePartnerName.textColor = new Color32 (204, 204, 51, 40); //r,g,b,a
                                }

                                if (this.PartnerID.IsEmpty) {
                                    this.BubblePartnerName.tooltip = null;
                                    this.BubblePartnerName.isEnabled = false;
                                } else {
                                    this.BubblePartnerName.tooltip = FavCimsLang.text("Right_click_to_swith_tooltip");
                                    this.BubblePartnerName.isEnabled = true;
                                }

                                if(this.DogOwner != 0) {
                                    FamilyPet(this.DogOwner);
                                }else{
                                    FamilyPet(this.CitizenPartner);
                                }

                                Activity(this.CitizenPartner, this.BubblePartnerVehicleButton, this.BubblePartnerDestination, out this.PartnerVehID, out this.PartnerTarget);

                                //Real Age
                                this.RealAge = FavCimsCore.CalculateCitizenAge (this.MyCitizen.m_citizens.m_buffer [CitizenPartner].m_age);

                                if (this.RealAge <= 12) { //CHILD
                                    this.BubbleParnerAgeButton.text = this.RealAge.ToString ();
                                    this.BubbleParnerAgeButton.textColor = new Color32 (83, 166, 0, 60); //r,g,b,a
                                } else if (this.RealAge <= 19) { //TEEN
                                    this.BubbleParnerAgeButton.text = this.RealAge.ToString ();
                                    this.BubbleParnerAgeButton.textColor = new Color32 (0, 102, 51, 100); //r,g,b,a
                                } else if (this.RealAge <= 25) { //YOUNG
                                    this.BubbleParnerAgeButton.text = this.RealAge.ToString ();
                                    this.BubbleParnerAgeButton.textColor = new Color32 (255, 204, 0, 32); //r,g,b,a
                                } else if (this.RealAge <= 65) { //ADULT
                                    this.BubbleParnerAgeButton.text = this.RealAge.ToString ();
                                    this.BubbleParnerAgeButton.textColor = new Color32 (255, 102, 0, 16); //r,g,b,a
                                } else if (this.RealAge <= 90) { //SENIOR
                                    this.BubbleParnerAgeButton.text = this.RealAge.ToString ();
                                    this.BubbleParnerAgeButton.textColor = new Color32 (153, 0, 0, 0); //r,g,b,a
                                } else { //FINAL
                                    this.BubbleParnerAgeButton.text = this.RealAge.ToString ();
                                    this.BubbleParnerAgeButton.textColor = new Color32 (255, 0, 0, 0); //r,g,b,a
                                }

                                //Partner is in favorites?
                                if (FavCimsCore.RowID.ContainsKey (CitizenPartnerINT)) {
                                    //Yes
                                    //this.BubblePartnerFollowToggler.texture = TextureDB.LittleStarGold;
                                    this.BubblePartnerFollowToggler.normalBgSprite = "icon_fav_subscribed";
                                } else {
                                    //No
                                    //this.BubblePartnerFollowToggler.texture = TextureDB.LittleStarGrey;
                                    this.BubblePartnerFollowToggler.normalBgSprite = "icon_fav_unsubscribed";
                                }
                                this.PartnerPanel.Show ();
                                if(!isSon)
                                    this.NoPartnerPanel.Hide();
                            } else {
                                this.PartnerPanel.Hide ();
                                if(!isSon)
                                    this.NoPartnerPanel.Show();
                            }

                            //Genitore 2
                            if (isSon) {

                                this.NoPartnerPanel.Hide();

                                if(this.Family.m_citizen1 != 0) {

                                    this.CitizenPartner = this.Family.m_citizen1;

                                    this.Parent1ID.Citizen = CitizenPartner;

                                    int CitizenPartnerINT = (int)((UIntPtr)this.CitizenPartner);

                                    this.BubbleParent1Name.text = this.MyCitizen.GetCitizenName (CitizenPartner);
                                    if (Citizen.GetGender (CitizenPartner) == Citizen.Gender.Female) {
                                        this.BubbleParent1Name.textColor = new Color32 (255, 102, 204, 213); //r,g,b,a
                                    } else {
                                        this.BubbleParent1Name.textColor = new Color32 (204, 204, 51, 40); //r,g,b,a
                                    }

                                    if (this.Parent1ID.IsEmpty) {
                                        this.BubbleParent1Name.isEnabled = false;
                                        this.BubbleParent1Name.tooltip = null;
                                    } else {
                                        this.BubbleParent1Name.isEnabled = true;
                                        this.BubbleParent1Name.tooltip = FavCimsLang.text("Right_click_to_swith_tooltip");
                                    }

                                    Activity(this.CitizenPartner, this.BubbleParent1VehicleButton, this.BubbleParent1Destination, out this.Parent1VehID, out this.Parent1Target);

                                    //Real Age
                                    this.RealAge = FavCimsCore.CalculateCitizenAge (this.MyCitizen.m_citizens.m_buffer [CitizenPartner].m_age);

                                    if (this.RealAge <= 12) { //CHILD
                                        this.BubbleParent1AgeButton.text = this.RealAge.ToString ();
                                        this.BubbleParent1AgeButton.textColor = new Color32 (83, 166, 0, 60); //r,g,b,a
                                    } else if (this.RealAge <= 19) { //TEEN
                                        this.BubbleParent1AgeButton.text = this.RealAge.ToString ();
                                        this.BubbleParent1AgeButton.textColor = new Color32 (0, 102, 51, 100); //r,g,b,a
                                    } else if (this.RealAge <= 25) { //YOUNG
                                        this.BubbleParent1AgeButton.text = this.RealAge.ToString ();
                                        this.BubbleParent1AgeButton.textColor = new Color32 (255, 204, 0, 32); //r,g,b,a
                                    } else if (this.RealAge <= 65) { //ADULT
                                        this.BubbleParent1AgeButton.text = this.RealAge.ToString ();
                                        this.BubbleParent1AgeButton.textColor = new Color32 (255, 102, 0, 16); //r,g,b,a
                                    } else if (this.RealAge <= 90) { //SENIOR
                                        this.BubbleParent1AgeButton.text = this.RealAge.ToString ();
                                        this.BubbleParent1AgeButton.textColor = new Color32 (153, 0, 0, 0); //r,g,b,a
                                    } else { //FINAL
                                        this.BubbleParent1AgeButton.text = this.RealAge.ToString ();
                                        this.BubbleParent1AgeButton.textColor = new Color32 (255, 0, 0, 0); //r,g,b,a
                                    }

                                    //Parent1 is in favorites?
                                    if (FavCimsCore.RowID.ContainsKey (CitizenPartnerINT)) {
                                        //Yes
                                        this.BubbleParent1FollowToggler.normalBgSprite = "icon_fav_subscribed";
                                    } else {
                                        //No
                                        this.BubbleParent1FollowToggler.normalBgSprite = "icon_fav_unsubscribed";
                                    }
                                    this.Parent1Panel.Show ();
                                }else{
                                    this.Parent1Panel.Hide ();
                                }
                            } else {
                                this.Parent1Panel.Hide ();
                            }

                            //Parent2
                            if (this.Family.m_citizen2 != 0 && this.Family.m_citizen2 != citizen) {
                                this.CitizenParent2 = this.Family.m_citizen2;

                                this.Parent2ID.Citizen = CitizenParent2;

                                int CitizenParent2INT = (int)((UIntPtr)this.CitizenParent2);

                                this.BubbleFamilyMember2Name.text = this.MyCitizen.GetCitizenName (CitizenParent2);
                                if (Citizen.GetGender (CitizenParent2) == Citizen.Gender.Female) {
                                    this.BubbleFamilyMember2Name.textColor = new Color32 (255, 102, 204, 213); //r,g,b,a
                                    this.BubbleFamilyMember2IconSprite.texture = TextureDB.BubbleHeaderIconSpriteTextureFemale;
                                } else {
                                    this.BubbleFamilyMember2Name.textColor = new Color32 (204, 204, 51, 40); //r,g,b,a
                                    this.BubbleFamilyMember2IconSprite.texture = TextureDB.BubbleHeaderIconSpriteTextureMale;
                                }

                                if (this.Parent2ID.IsEmpty) {
                                    this.BubbleFamilyMember2Name.isEnabled = false;
                                    this.BubbleFamilyMember2Name.tooltip = null;
                                } else {
                                    this.BubbleFamilyMember2Name.isEnabled = true;
                                    this.BubbleFamilyMember2Name.tooltip = FavCimsLang.text("Right_click_to_swith_tooltip");
                                }

                                //Have Pet?
                                if(this.DogOwner != 0) {
                                    FamilyPet(this.DogOwner);
                                }else{
                                    FamilyPet(this.Family.m_citizen2);
                                }

                                Activity(this.CitizenParent2, this.BubbleFamilyMember2ActivityVehicleButton, this.BubbleFamilyMember2ActivityDestination, out this.Parent2VehID, out this.Parent2Target);

                                //Real Age
                                this.RealAge = FavCimsCore.CalculateCitizenAge (this.MyCitizen.m_citizens.m_buffer [CitizenParent2].m_age);

                                if (this.RealAge <= 12) { //CHILD
                                    this.BubbleFamilyMember2AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember2AgeButton.textColor = new Color32 (83, 166, 0, 60); //r,g,b,a
                                } else if (this.RealAge <= 19) { //TEEN
                                    this.BubbleFamilyMember2AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember2AgeButton.textColor = new Color32 (0, 102, 51, 100); //r,g,b,a
                                } else if (this.RealAge <= 25) { //YOUNG
                                    this.BubbleFamilyMember2AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember2AgeButton.textColor = new Color32 (255, 204, 0, 32); //r,g,b,a
                                } else if (this.RealAge <= 65) { //ADULT
                                    this.BubbleFamilyMember2AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember2AgeButton.textColor = new Color32 (255, 102, 0, 16); //r,g,b,a
                                } else if (this.RealAge <= 90) { //SENIOR
                                    this.BubbleFamilyMember2AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember2AgeButton.textColor = new Color32 (153, 0, 0, 0); //r,g,b,a
                                } else { //FINAL
                                    this.BubbleFamilyMember2AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember2AgeButton.textColor = new Color32 (255, 0, 0, 0); //r,g,b,a
                                }

                                //Parent is in favorites?
                                if (FavCimsCore.RowID.ContainsKey (CitizenParent2INT)) {
                                    //Yes
                                    this.BubbleFamilyMember2FollowToggler.normalBgSprite = "icon_fav_subscribed";
                                } else {
                                    //No
                                    this.BubbleFamilyMember2FollowToggler.normalBgSprite = "icon_fav_unsubscribed";
                                }
                                this.FamilyMember2Panel.Show ();

                                if(!isSon)
                                    Sons++;
                            } else {

                                if(this.Family.m_citizen2 == citizen) {
                                    //Have Pet?
                                    if(this.DogOwner != 0) {
                                        FamilyPet(this.DogOwner);
                                    }else{
                                        FamilyPet(this.Family.m_citizen2);
                                    }
                                }

                                this.FamilyMember2Panel.Hide ();
                            }

                            //Parent3
                            if (this.Family.m_citizen3 != 0 && this.Family.m_citizen3 != citizen) {
                                this.CitizenParent3 = this.Family.m_citizen3;

                                this.Parent3ID.Citizen = CitizenParent3;

                                int CitizenParent3INT = (int)((UIntPtr)this.CitizenParent3);

                                this.BubbleFamilyMember3Name.text = this.MyCitizen.GetCitizenName (CitizenParent3);
                                if (Citizen.GetGender (CitizenParent3) == Citizen.Gender.Female) {
                                    this.BubbleFamilyMember3Name.textColor = new Color32 (255, 102, 204, 213); //r,g,b,a
                                    this.BubbleFamilyMember3IconSprite.texture = TextureDB.BubbleHeaderIconSpriteTextureFemale;
                                } else {
                                    this.BubbleFamilyMember3Name.textColor = new Color32 (204, 204, 51, 40); //r,g,b,a
                                    this.BubbleFamilyMember3IconSprite.texture = TextureDB.BubbleHeaderIconSpriteTextureMale;
                                }

                                if (this.Parent3ID.IsEmpty) {
                                    this.BubbleFamilyMember3Name.isEnabled = false;
                                    this.BubbleFamilyMember3Name.tooltip = null;
                                } else {
                                    this.BubbleFamilyMember3Name.isEnabled = true;
                                    this.BubbleFamilyMember3Name.tooltip = FavCimsLang.text("Right_click_to_swith_tooltip");
                                }

                                //Have Pet?
                                if(this.DogOwner != 0) {
                                    FamilyPet(this.DogOwner);
                                }else{
                                    FamilyPet(this.Family.m_citizen3);
                                }

                                Activity(this.CitizenParent3, this.BubbleFamilyMember3ActivityVehicleButton, this.BubbleFamilyMember3ActivityDestination, out this.Parent3VehID, out this.Parent3Target);

                                //Real Age
                                this.RealAge = FavCimsCore.CalculateCitizenAge (this.MyCitizen.m_citizens.m_buffer [CitizenParent3].m_age);

                                if (this.RealAge <= 12) { //CHILD
                                    this.BubbleFamilyMember3AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember3AgeButton.textColor = new Color32 (83, 166, 0, 60); //r,g,b,a
                                } else if (this.RealAge <= 19) { //TEEN
                                    this.BubbleFamilyMember3AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember3AgeButton.textColor = new Color32 (0, 102, 51, 100); //r,g,b,a
                                } else if (this.RealAge <= 25) { //YOUNG
                                    this.BubbleFamilyMember3AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember3AgeButton.textColor = new Color32 (255, 204, 0, 32); //r,g,b,a
                                } else if (this.RealAge <= 65) { //ADULT
                                    this.BubbleFamilyMember3AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember3AgeButton.textColor = new Color32 (255, 102, 0, 16); //r,g,b,a
                                } else if (this.RealAge <= 90) { //SENIOR
                                    this.BubbleFamilyMember3AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember3AgeButton.textColor = new Color32 (153, 0, 0, 0); //r,g,b,a
                                } else { //FINAL
                                    this.BubbleFamilyMember3AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember3AgeButton.textColor = new Color32 (255, 0, 0, 0); //r,g,b,a
                                }

                                //Parent is in favorites?
                                if (FavCimsCore.RowID.ContainsKey (CitizenParent3INT)) {
                                    //Yes
                                    this.BubbleFamilyMember3FollowToggler.normalBgSprite = "icon_fav_subscribed";
                                } else {
                                    //No
                                    this.BubbleFamilyMember3FollowToggler.normalBgSprite = "icon_fav_unsubscribed";
                                }
                                this.FamilyMember3Panel.Show ();

                                if(!isSon)
                                    Sons++;
                            } else {

                                if(this.Family.m_citizen3 == citizen) {
                                    //Have Pet?
                                    if(this.DogOwner != 0) {
                                        FamilyPet(this.DogOwner);
                                    }else{
                                        FamilyPet(this.Family.m_citizen3);
                                    }
                                }

                                this.FamilyMember3Panel.Hide ();
                            }

                            //Parent4
                            if (this.Family.m_citizen4 != 0 && this.Family.m_citizen4 != citizen) {
                                this.CitizenParent4 = this.Family.m_citizen4;

                                this.Parent4ID.Citizen = CitizenParent4;

                                int CitizenParent4INT = (int)((UIntPtr)this.CitizenParent4);

                                this.BubbleFamilyMember4Name.text = this.MyCitizen.GetCitizenName (CitizenParent4);
                                if (Citizen.GetGender (CitizenParent4) == Citizen.Gender.Female) {
                                    this.BubbleFamilyMember4Name.textColor = new Color32 (255, 102, 204, 213); //r,g,b,a
                                    this.BubbleFamilyMember4IconSprite.texture = TextureDB.BubbleHeaderIconSpriteTextureFemale;
                                } else {
                                    this.BubbleFamilyMember4Name.textColor = new Color32 (204, 204, 51, 40); //r,g,b,a
                                    this.BubbleFamilyMember4IconSprite.texture = TextureDB.BubbleHeaderIconSpriteTextureMale;
                                }

                                if (this.Parent4ID.IsEmpty) {
                                    this.BubbleFamilyMember4Name.isEnabled = false;
                                    this.BubbleFamilyMember4Name.tooltip = null;
                                } else {
                                    this.BubbleFamilyMember4Name.isEnabled = true;
                                    this.BubbleFamilyMember4Name.tooltip = FavCimsLang.text("Right_click_to_swith_tooltip");
                                }

                                //Have Pet?
                                if(this.DogOwner != 0) {
                                    FamilyPet(this.DogOwner);
                                }else{
                                    FamilyPet(this.Family.m_citizen4);
                                }

                                Activity(this.CitizenParent4, this.BubbleFamilyMember4ActivityVehicleButton, this.BubbleFamilyMember4ActivityDestination, out this.Parent4VehID, out this.Parent4Target);

                                //Real Age
                                this.RealAge = FavCimsCore.CalculateCitizenAge (this.MyCitizen.m_citizens.m_buffer [CitizenParent4].m_age);

                                if (this.RealAge <= 12) { //CHILD
                                    this.BubbleFamilyMember4AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember4AgeButton.textColor = new Color32 (83, 166, 0, 60); //r,g,b,a
                                } else if (this.RealAge <= 19) { //TEEN
                                    this.BubbleFamilyMember4AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember4AgeButton.textColor = new Color32 (0, 102, 51, 100); //r,g,b,a
                                } else if (this.RealAge <= 25) { //YOUNG
                                    this.BubbleFamilyMember4AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember4AgeButton.textColor = new Color32 (255, 204, 0, 32); //r,g,b,a
                                } else if (this.RealAge <= 65) { //ADULT
                                    this.BubbleFamilyMember4AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember4AgeButton.textColor = new Color32 (255, 102, 0, 16); //r,g,b,a
                                } else if (this.RealAge <= 90) { //SENIOR
                                    this.BubbleFamilyMember4AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember4AgeButton.textColor = new Color32 (153, 0, 0, 0); //r,g,b,a
                                } else { //FINAL
                                    this.BubbleFamilyMember4AgeButton.text = this.RealAge.ToString ();
                                    this.BubbleFamilyMember4AgeButton.textColor = new Color32 (255, 0, 0, 0); //r,g,b,a
                                }

                                //Parent is in favorites?
                                if (FavCimsCore.RowID.ContainsKey (CitizenParent4INT)) {
                                    //Yes
                                    this.BubbleFamilyMember4FollowToggler.normalBgSprite = "icon_fav_subscribed";
                                } else {
                                    //No
                                    this.BubbleFamilyMember4FollowToggler.normalBgSprite = "icon_fav_unsubscribed";
                                }
                                this.FamilyMember4Panel.Show ();

                                if(!isSon)
                                    Sons++;
                            } else {

                                if(this.Family.m_citizen4 == citizen) {
                                    //Have Pet?
                                    if(this.DogOwner != 0) {
                                        FamilyPet(this.DogOwner);
                                    }else{
                                        FamilyPet(this.Family.m_citizen4);
                                    }
                                }

                                this.FamilyMember4Panel.Hide ();
                            }

                            if(Sons == 0 && !isSon) {
                                NoChildsPanel.Show();
                            }else{
                                NoChildsPanel.Hide();
                            }

                        }else{
                            //GameObject.Destroy (this.gameObject);
                            this.Hide();
                            this.MyInstanceID = InstanceID.Empty;
                            return;
                        }

                        if(this.FirstRun)
                            this.FirstRun = false;

                    } catch /*(Exception e)*/ {
                        //Debug.Error("errore" + e.ToString());
                    }
                }
            }
        }
        public static bool Prefix(ref bool __result, ref ResidentAI __instance, uint citizenID, ref Citizen data)
        {
            // Method result.
            bool removed = false;

            if ((citizenID % DataStore.lifeSpanMultiplier) == Threading.counter)
            {
                // Local reference.
                CitizenManager citizenManager = Singleton <CitizenManager> .instance;

                if (citizenID == 575960)
                {
                    Logging.Message("foundTarget");
                }

                int num = data.Age + 1;

                if (num <= 45)
                {
                    if (num == 15 || num == 45)
                    {
                        FinishSchoolOrWorkRev(__instance, citizenID, ref data);
                    }
                }
                else if (num == 90 || num >= ModSettings.retirementAge)
                {
                    FinishSchoolOrWorkRev(__instance, citizenID, ref data);
                }
                else if ((data.m_flags & Citizen.Flags.Student) != Citizen.Flags.None && (num % 15 == 0))  // Workspeed multiplier?
                {
                    FinishSchoolOrWorkRev(__instance, citizenID, ref data);
                }

                if ((data.m_flags & Citizen.Flags.Original) != Citizen.Flags.None)
                {
                    if (citizenManager.m_tempOldestOriginalResident < num)
                    {
                        citizenManager.m_tempOldestOriginalResident = num;
                    }
                    if (num == 240)
                    {
                        Singleton <StatisticsManager> .instance.Acquire <StatisticInt32>(StatisticType.FullLifespans).Add(1);
                    }
                }

                data.Age = num;

                // Checking for death and sickness chances.
                // Citizens who are currently moving or currently in a vehicle aren't affected.
                if (data.CurrentLocation != Citizen.Location.Moving && data.m_vehicle == 0)
                {
                    // Local reference.
                    SimulationManager simulationManager = Singleton <SimulationManager> .instance;

                    bool died = false;

                    if (ModSettings.VanillaCalcs)
                    {
                        // Using vanilla lifecycle calculations.
                        int num2 = 240;
                        int num3 = 255;
                        int num4 = Mathf.Max(0, 145 - (100 - data.m_health) * 3);
                        if (num4 != 0)
                        {
                            num2 += num4 / 3;
                            num3 += num4;
                        }
                        if (num >= num2)
                        {
                            bool flag = simulationManager.m_randomizer.Int32(2000u) < 3;
                            died = (simulationManager.m_randomizer.Int32(num2 * 100, num3 * 100) / 100 <= num || flag);
                        }
                    }
                    else
                    {
                        // Using custom lifecycle calculations.
                        // Game defines years as being age divided by 3.5.  Hence, 35 age increments per decade.
                        // Legacy mod behaviour worked on 25 increments per decade.
                        // If older than the maximum index - lucky them, but keep going using that final index.
                        int index = Math.Min((int)(num * ModSettings.decadeFactor), 10);

                        // Calculate 90% - 110%; using 100,000 as 100% (for precision).
                        int modifier = 100000 + ((150 * data.m_health) + (50 * data.m_wellbeing) - 10000);

                        // Death chance is simply if a random number between 0 and the modifier calculated above is less than the survival probability calculation for that decade of life.
                        // Also set maximum age of 400 (~114 years) to be consistent with the base game.
                        died = (simulationManager.m_randomizer.Int32(0, modifier) < DataStore.survivalProbCalc[index]) || num > 400;

                        // Check for sickness chance if they haven't died.
                        if (!died && simulationManager.m_randomizer.Int32(0, modifier) < DataStore.sicknessProbCalc[index])
                        {
                            // Make people sick, if they're unlucky.
                            data.Sick = true;

                            if (Logging.UseSicknessLog)
                            {
                                Logging.WriteToLog(Logging.SicknessLogName, "Citizen became sick with chance factor ", DataStore.sicknessProbCalc[index].ToString());
                            }
                        }
                    }

                    // Handle citizen death.
                    if (died)
                    {
                        // Check if citizen is only remaining parent and there are children.
                        uint        unitID         = data.GetContainingUnit(citizenID, Singleton <BuildingManager> .instance.m_buildings.m_buffer[data.m_homeBuilding].m_citizenUnits, CitizenUnit.Flags.Home);
                        CitizenUnit containingUnit = citizenManager.m_units.m_buffer[unitID];

                        // Log if we're doing that.
                        if (Logging.UseDeathLog)
                        {
                            Logging.WriteToLog(Logging.DeathLogName, "Killed citzen ", citizenID.ToString(), " at age ", data.Age.ToString(), " (", ((int)(data.Age / 3.5)).ToString(), " years old) with family ", containingUnit.m_citizen0.ToString(), ", " + containingUnit.m_citizen1.ToString(), ", " + containingUnit.m_citizen2.ToString(), ", ", containingUnit.m_citizen3.ToString(), ", ", containingUnit.m_citizen4.ToString());
                        }

                        // Reverse redirect to access private method Die().
                        DieRev(__instance, citizenID, ref data);

                        // If there are no adults remaining in this CitizenUnit, remove the others, as orphan households end up in simulation purgatory.
                        bool isParent     = containingUnit.m_citizen0 == citizenID || containingUnit.m_citizen1 == citizenID;
                        bool singleParent = isParent && (containingUnit.m_citizen0 == 0 || containingUnit.m_citizen1 == 0);
                        bool hasChild     = containingUnit.m_citizen2 != 0 || containingUnit.m_citizen3 != 0 || containingUnit.m_citizen4 != 0;

                        if (singleParent && hasChild)
                        {
                            for (int i = 0; i < 2; ++i)
                            {
                                uint currentChild;
                                switch (i)
                                {
                                case 0:
                                    currentChild = containingUnit.m_citizen2;
                                    break;

                                case 1:
                                    currentChild = containingUnit.m_citizen3;
                                    break;

                                default:
                                    currentChild = containingUnit.m_citizen4;
                                    break;
                                }

                                if (currentChild != 0)
                                {
                                    if (Logging.UseDeathLog)
                                    {
                                        Logging.WriteToLog(Logging.DeathLogName, "Removed orphan ", currentChild.ToString());
                                        citizenManager.ReleaseCitizen(currentChild);
                                    }
                                }
                            }
                        }

                        // Chance for 'vanishing corpse' (no need for deathcare).
                        if (!AIUtils.KeepCorpse())
                        {
                            citizenManager.ReleaseCitizen(citizenID);
                            removed = true;
                        }
                    }
                }
            }

            // Original method return value.
            __result = removed;

            // Don't execute base method after this.
            return(false);
        }
        public static void ProcessFamily(uint homeID, ref CitizenUnit data)
        {
            if (RealCityResidentAI.preCitizenId > homeID)
            {
                //DebugLog.LogToFileOnly("Another period started");
                MainDataStore.familyCount      = RealCityResidentAI.familyCount;
                MainDataStore.citizenCount     = RealCityResidentAI.citizenCount;
                MainDataStore.level2HighWealth = RealCityResidentAI.level2HighWealth;
                MainDataStore.level3HighWealth = RealCityResidentAI.level3HighWealth;
                MainDataStore.level1HighWealth = RealCityResidentAI.level1HighWealth;
                if (RealCityResidentAI.familyCount != 0)
                {
                    MainDataStore.citizenSalaryPerFamily  = ((RealCityResidentAI.citizenSalaryCount / RealCityResidentAI.familyCount));
                    MainDataStore.citizenExpensePerFamily = ((RealCityResidentAI.citizenExpenseCount / RealCityResidentAI.familyCount));
                }
                MainDataStore.citizenExpense        = RealCityResidentAI.citizenExpenseCount;
                MainDataStore.citizenSalaryTaxTotal = RealCityResidentAI.citizenSalaryTaxTotal;
                MainDataStore.citizenSalaryTotal    = RealCityResidentAI.citizenSalaryCount;
                if (MainDataStore.familyCount < MainDataStore.familyWeightStableHigh)
                {
                    MainDataStore.familyWeightStableHigh = (uint)MainDataStore.familyCount;
                }
                else
                {
                    MainDataStore.familyWeightStableHigh = RealCityResidentAI.familyWeightStableHigh;
                }
                if (MainDataStore.familyCount < MainDataStore.familyWeightStableLow)
                {
                    MainDataStore.familyWeightStableLow = (uint)MainDataStore.familyCount;
                }
                else
                {
                    MainDataStore.familyWeightStableLow = RealCityResidentAI.familyWeightStableLow;
                }

                RealCityPrivateBuildingAI.profitBuildingMoneyFinal = RealCityPrivateBuildingAI.profitBuildingMoney;

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

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

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

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

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

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

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

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

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

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

            CitizenUnitData.familyMoney[homeID] += incomeMinusExpense;

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

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

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

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

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

            //8 reduce goods
            float reducedGoods;

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

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

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

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

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

            //ProcessCitizen post, split all familyMoney to CitizenMoney
            ProcessCitizen(homeID, ref data, false);
        }