Ejemplo n.º 1
0
        /// <summary>removes the specified flags from a citizen.</summary>
        /// <param name="citizen">The citizen to remove flags from.</param>
        /// <param name="flags">The flags to remove.</param>
        /// <returns>
        /// The current citizen's flags after removing the specified flags.
        /// </returns>
        public Citizen.Flags RemoveFlags(ref Citizen citizen, Citizen.Flags flags)
        {
            var currentFlags = citizen.m_flags;

            currentFlags &= ~flags;
            return(citizen.m_flags = currentFlags);
        }
Ejemplo n.º 2
0
        /// <summary>Adds the specified flags to a citizen.</summary>
        /// <param name="citizen">The citizen to add flags to.</param>
        /// <param name="flags">The flags to add.</param>
        /// <returns>The current citizen's flags after adding the specified flags.</returns>
        public Citizen.Flags AddFlags(ref Citizen citizen, Citizen.Flags flags)
        {
            var currentFlags = citizen.m_flags;

            currentFlags |= flags;
            return(citizen.m_flags = currentFlags);
        }
Ejemplo n.º 3
0
        public bool CheckCitizenFlags(uint citizenId, Citizen.Flags flagMask, Citizen.Flags?expectedResult = default(Citizen.Flags?))
        {
            bool ret = false;

            ProcessCitizen(citizenId, delegate(uint cId, ref Citizen citizen) {
                ret = LogicUtil.CheckFlags((uint)citizen.m_flags, (uint)flagMask, (uint?)expectedResult);
                return(true);
            });
            return(ret);
        }
        /// <summary>
        /// Check citizen flags contain at least one of the flags in <paramref name="flagMask"/>.
        /// </summary>
        ///
        /// <param name="citizenId">The id of the citizen to inspect.</param>
        /// <param name="flagMask">The flags to test.</param>
        /// <param name="expectedResult">If specified, ensure only the expected flags are found.</param>
        ///
        /// <returns>Returns <c>true</c> if the test passes, otherwise <c>false</c>.</returns>
        public bool CheckCitizenFlags(uint citizenId,
                                      Citizen.Flags flagMask,
                                      Citizen.Flags?expectedResult = null)
        {
            Citizen.Flags result =
                Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenId].m_flags
                & flagMask;

            return(expectedResult == null ? result != 0 : result == expectedResult);
        }
Ejemplo n.º 5
0
        /// <summary>Reads the data set to the specified <see cref="Stream" />.</summary>
        /// <param name="target">A <see cref="Stream" /> to write the data set to.</param>
        void IStorageData.StoreData(Stream target)
        {
            byte[] buffer        = new byte[CitizenSchedule.DataRecordSize];
            long   referenceTime = timeInfo.Now.Date.Ticks;

            for (int i = 0; i < citizens.Length; ++i)
            {
                Citizen.Flags flags = citizens[i].m_flags;
                if ((flags & Citizen.Flags.Created) == 0 ||
                    (flags & Citizen.Flags.DummyTraffic) != 0)
                {
                    continue;
                }

                residentSchedules[i].Write(buffer, referenceTime);
                target.Write(buffer, 0, buffer.Length);
            }
        }
Ejemplo n.º 6
0
        public static void Citizens(
            QueryHandler <Citizen, uint> h,
            Citizen.Flags flags = Citizen.Flags.Created
            )
        {
            var mgr = Singleton <Cities::CitizenManager> .instance;

            for (int i = 0; i < mgr.m_citizens.m_size; ++i)
            {
                if ((mgr.m_citizens.m_buffer[i].m_flags & flags) == Citizen.Flags.None)
                {
                    continue;
                }

                if (!h.Invoke(ref mgr.m_citizens.m_buffer[i], (uint)i))
                {
                    return;
                }
            }
        }
Ejemplo n.º 7
0
        /// <summary>Reads the data set from the specified <see cref="Stream" />.</summary>
        /// <param name="source">A <see cref="Stream" /> to read the data set from.</param>
        void IStorageData.ReadData(Stream source)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            byte[] buffer        = new byte[CitizenSchedule.DataRecordSize];
            long   referenceTime = timeInfo.Now.Date.Ticks;

            for (int i = 0; i < citizens.Length; ++i)
            {
                Citizen.Flags flags = citizens[i].m_flags;
                if ((flags & Citizen.Flags.Created) == 0 ||
                    (flags & Citizen.Flags.DummyTraffic) != 0)
                {
                    continue;
                }

                source.Read(buffer, 0, buffer.Length);
                residentSchedules[i].Read(buffer, referenceTime);
            }
        }
Ejemplo n.º 8
0
 public bool HasFlags(ref Citizen citizen, Citizen.Flags flags)
 {
     return((citizen.m_flags & flags) != 0);
 }
Ejemplo n.º 9
0
 /// <summary>
 /// Determines whether the specified citizen has particular flags.
 /// </summary>
 /// <param name="citizen">The citizen to check flags of.</param>
 /// <param name="flags">The flags to check.</param>
 /// <returns>
 /// <c>true</c> if the citizen has any of the specified flags; otherwise, <c>false</c>.
 /// </returns>
 public bool HasFlags(ref Citizen citizen, Citizen.Flags flags) => (citizen.m_flags & flags) != 0;
 internal static bool IsFlagSet(this Citizen.Flags value, Citizen.Flags flag) => (value & flag) != 0;
Ejemplo n.º 11
0
        public void CustomSimulationStep(ushort instanceId,
                                         ref CitizenInstance instanceData,
                                         Vector3 physicsLodRefPos)
        {
#if DEBUG
            bool citizenDebug = (DebugSettings.CitizenInstanceId == 0 ||
                                 DebugSettings.CitizenInstanceId == instanceId) &&
                                (DebugSettings.CitizenId == 0 ||
                                 DebugSettings.CitizenId == instanceData.m_citizen) &&
                                (DebugSettings.SourceBuildingId == 0 ||
                                 DebugSettings.SourceBuildingId == instanceData.m_sourceBuilding) &&
                                (DebugSettings.TargetBuildingId == 0 ||
                                 DebugSettings.TargetBuildingId == instanceData.m_targetBuilding);
            bool logParkingAi = DebugSwitch.BasicParkingAILog.Get() && citizenDebug;
#else
            var logParkingAi = false;
#endif
            CitizenManager citizenManager = Singleton <CitizenManager> .instance;
            uint           citizenId      = instanceData.m_citizen;

            if ((instanceData.m_flags & (CitizenInstance.Flags.Blown
                                         | CitizenInstance.Flags.Floating)) != CitizenInstance.Flags.None &&
                (instanceData.m_flags & CitizenInstance.Flags.Character) == CitizenInstance.Flags.None)
            {
                citizenManager.ReleaseCitizenInstance(instanceId);
                if (citizenId != 0u)
                {
                    citizenManager.ReleaseCitizen(citizenId);
                }

                return;
            }

            Citizen[] citizensBuffer = citizenManager.m_citizens.m_buffer;
            if ((instanceData.m_flags & CitizenInstance.Flags.WaitingPath) != CitizenInstance.Flags.None)
            {
                PathManager pathManager   = Singleton <PathManager> .instance;
                byte        pathFindFlags = pathManager.m_pathUnits.m_buffer[instanceData.m_path].m_pathFindFlags;

                // NON-STOCK CODE START
                ExtPathState mainPathState = ExtPathState.Calculating;
                if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || instanceData.m_path == 0)
                {
                    mainPathState = ExtPathState.Failed;
                }
                else if ((pathFindFlags & PathUnit.FLAG_READY) != 0)
                {
                    mainPathState = ExtPathState.Ready;
                }

                if (logParkingAi)
                {
                    Log._Debug(
                        $"CustomHumanAI.CustomSimulationStep({instanceId}): " +
                        $"Path: {instanceData.m_path}, mainPathState={mainPathState}");
                }

                ExtSoftPathState finalPathState;
                using (var bm = Benchmark.MaybeCreateBenchmark(
                           null,
                           "ConvertPathStateToSoftPathState+UpdateCitizenPathState"))
                {
                    finalPathState = ExtCitizenInstance.ConvertPathStateToSoftPathState(mainPathState);

                    if (Options.parkingAI)
                    {
                        finalPathState = AdvancedParkingManager.Instance.UpdateCitizenPathState(
                            instanceId,
                            ref instanceData,
                            ref ExtCitizenInstanceManager
                            .Instance.ExtInstances[
                                instanceId],
                            ref ExtCitizenManager
                            .Instance.ExtCitizens[
                                citizenId],
                            ref citizensBuffer[
                                instanceData.m_citizen],
                            mainPathState);
                        if (logParkingAi)
                        {
                            Log._Debug(
                                $"CustomHumanAI.CustomSimulationStep({instanceId}): " +
                                $"Applied Parking AI logic. Path: {instanceData.m_path}, " +
                                $"mainPathState={mainPathState}, finalPathState={finalPathState}, " +
                                $"extCitizenInstance={ExtCitizenInstanceManager.Instance.ExtInstances[instanceId]}");
                        }
                    } // if Options.parkingAi
                }

                switch (finalPathState)
                {
                case ExtSoftPathState.Ready: {
                    if (logParkingAi)
                    {
                        Log._Debug(
                            $"CustomHumanAI.CustomSimulationStep({instanceId}): Path-finding " +
                            $"succeeded for citizen instance {instanceId} " +
                            $"(finalPathState={finalPathState}). Path: {instanceData.m_path} " +
                            "-- calling HumanAI.PathfindSuccess");
                    }

                    if (citizenId == 0 ||
                        citizensBuffer[instanceData.m_citizen].m_vehicle == 0)
                    {
                        Spawn(instanceId, ref instanceData);
                    }

                    instanceData.m_pathPositionIndex = 255;
                    instanceData.m_flags            &= ~CitizenInstance.Flags.WaitingPath;
                    instanceData.m_flags            &= ~(CitizenInstance.Flags.HangAround
                                                         | CitizenInstance.Flags.Panicking
                                                         | CitizenInstance.Flags.SittingDown
                                                         | CitizenInstance.Flags.Cheering);

                    // NON-STOCK CODE START (transferred from ResidentAI.PathfindSuccess)
                    const Citizen.Flags CTZ_MASK = Citizen.Flags.Tourist
                                                   | Citizen.Flags.MovingIn
                                                   | Citizen.Flags.DummyTraffic;
                    if (citizenId != 0 &&
                        (citizensBuffer[citizenId].m_flags & CTZ_MASK) == Citizen.Flags.MovingIn)
                    {
                        StatisticBase statisticBase = Singleton <StatisticsManager>
                                                      .instance.Acquire <StatisticInt32>(StatisticType.MoveRate);

                        statisticBase.Add(1);
                    }

                    // NON-STOCK CODE END
                    PathfindSuccess(instanceId, ref instanceData);
                    break;
                }

                case ExtSoftPathState.Ignore: {
                    if (logParkingAi)
                    {
                        Log._Debug(
                            $"CustomHumanAI.CustomSimulationStep({instanceId}): " +
                            "Path-finding result shall be ignored for citizen instance " +
                            $"{instanceId} (finalPathState={finalPathState}). " +
                            $"Path: {instanceData.m_path} -- ignoring");
                    }

                    return;
                }

                case ExtSoftPathState.Calculating:
                default: {
                    if (logParkingAi)
                    {
                        Log._Debug(
                            $"CustomHumanAI.CustomSimulationStep({instanceId}): " +
                            $"Path-finding result undetermined for citizen instance {instanceId} " +
                            $"(finalPathState={finalPathState}). " +
                            $"Path: {instanceData.m_path} -- continue");
                    }

                    break;
                }

                case ExtSoftPathState.FailedHard: {
                    if (logParkingAi)
                    {
                        Log._Debug(
                            $"CustomHumanAI.CustomSimulationStep({instanceId}): " +
                            $"HARD path-finding failure for citizen instance {instanceId} " +
                            $"(finalPathState={finalPathState}). Path: {instanceData.m_path} " +
                            "-- calling HumanAI.PathfindFailure");
                    }

                    instanceData.m_flags &= ~CitizenInstance.Flags.WaitingPath;
                    instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround
                                              | CitizenInstance.Flags.Panicking
                                              | CitizenInstance.Flags.SittingDown
                                              | CitizenInstance.Flags.Cheering);
                    Singleton <PathManager> .instance.ReleasePath(instanceData.m_path);

                    instanceData.m_path = 0u;
                    PathfindFailure(instanceId, ref instanceData);
                    return;
                }

                case ExtSoftPathState.FailedSoft: {
                    if (logParkingAi)
                    {
                        Log._Debug(
                            $"CustomHumanAI.CustomSimulationStep({instanceId}): " +
                            $"SOFT path-finding failure for citizen instance {instanceId} " +
                            $"(finalPathState={finalPathState}). Path: {instanceData.m_path} " +
                            "-- calling HumanAI.InvalidPath");
                    }

                    // path mode has been updated, repeat path-finding
                    instanceData.m_flags &= ~CitizenInstance.Flags.WaitingPath;
                    instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround
                                              | CitizenInstance.Flags.Panicking
                                              | CitizenInstance.Flags.SittingDown
                                              | CitizenInstance.Flags.Cheering);
                    InvalidPath(instanceId, ref instanceData);
                    break;
                }
                }

                // NON-STOCK CODE END
            }

            // NON-STOCK CODE START
            using (var bm = Benchmark.MaybeCreateBenchmark(null, "ExtSimulationStep")) {
                if (Options.parkingAI)
                {
                    if (ExtSimulationStep(
                            instanceId,
                            ref instanceData,
                            ref ExtCitizenInstanceManager.Instance.ExtInstances[instanceId],
                            physicsLodRefPos))
                    {
                        return;
                    }
                }
            }

            // NON-STOCK CODE END
            base.SimulationStep(instanceId, ref instanceData, physicsLodRefPos);

            VehicleManager vehicleManager = Singleton <VehicleManager> .instance;
            ushort         vehicleId      = 0;
            if (instanceData.m_citizen != 0u)
            {
                vehicleId = citizensBuffer[instanceData.m_citizen].m_vehicle;
            }

            if (vehicleId != 0)
            {
                Vehicle[]   vehiclesBuffer = vehicleManager.m_vehicles.m_buffer;
                VehicleInfo vehicleInfo    = vehiclesBuffer[vehicleId].Info;

                if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Bicycle)
                {
                    vehicleInfo.m_vehicleAI.SimulationStep(
                        vehicleId,
                        ref vehiclesBuffer[vehicleId],
                        vehicleId,
                        ref vehiclesBuffer[vehicleId],
                        0);
                    vehicleId = 0;
                }
            }

            if (vehicleId != 0 ||
                (instanceData.m_flags & (CitizenInstance.Flags.Character
                                         | CitizenInstance.Flags.WaitingPath
                                         | CitizenInstance.Flags.Blown
                                         | CitizenInstance.Flags.Floating)) !=
                CitizenInstance.Flags.None)
            {
                return;
            }

            instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround
                                      | CitizenInstance.Flags.Panicking
                                      | CitizenInstance.Flags.SittingDown);
            ArriveAtDestination(instanceId, ref instanceData, false);
            citizenManager.ReleaseCitizenInstance(instanceId);
        }
Ejemplo n.º 12
0
        public static int ProcessCitizenSalary(uint citizenId, bool checkOnly)
        {
            int salary = 0;

            if (citizenId != 0u)
            {
                Citizen.Flags citizenFlag = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenId].m_flags;
                if ((citizenFlag & Citizen.Flags.Student) != Citizen.Flags.None)
                {
                    return(salary);
                }
                ushort workBuilding = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenId].m_workBuilding;
                if (workBuilding != 0u)
                {
                    Building buildingData = Singleton <BuildingManager> .instance.m_buildings.m_buffer[workBuilding];
                    if (!IsGoverment(workBuilding))
                    {
                        salary = BuildingData.buildingWorkCount[workBuilding];
                        if (!checkOnly)
                        {
                            if (buildingData.Info.m_class.m_service != ItemClass.Service.Office)
                            {
                                BuildingData.buildingMoney[workBuilding] -= salary;
                            }
                        }
                    }
                    else
                    {
                        //Goverment
                        int aliveWorkCount = 0;
                        int totalWorkCount = 0;
                        Citizen.BehaviourData behaviour = default;
                        RealCityCommonBuildingAI.InitDelegate();
                        RealCityCommonBuildingAI.GetWorkBehaviour((CommonBuildingAI)buildingData.Info.m_buildingAI, workBuilding, ref buildingData, ref behaviour, ref aliveWorkCount, ref totalWorkCount);
                        int salaryMax = 0;
                        switch (Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenId].EducationLevel)
                        {
                        case Citizen.Education.Uneducated:
                            salaryMax = (int)(MainDataStore.govermentSalary * 0.5);
                            salary    = MainDataStore.govermentEducation0SalaryFixed; break;

                        case Citizen.Education.OneSchool:
                            salaryMax = (int)(MainDataStore.govermentSalary * 0.55);
                            salary    = MainDataStore.govermentEducation1SalaryFixed; break;

                        case Citizen.Education.TwoSchools:
                            salaryMax = (int)(MainDataStore.govermentSalary * 0.65);
                            salary    = MainDataStore.govermentEducation2SalaryFixed; break;

                        case Citizen.Education.ThreeSchools:
                            salaryMax = (int)(MainDataStore.govermentSalary * 0.8);
                            salary    = MainDataStore.govermentEducation3SalaryFixed; break;
                        }
                        int allWorkCount = 0;
                        //Update to see if there is building workplace change.
                        //If a building have 10 workers and have 100 workplacecount, we assume that the other 90 vitual workers are from outside
                        //Which will give addition cost
                        allWorkCount = TotalWorkCount(workBuilding, buildingData, false, false);
                        if (totalWorkCount > allWorkCount)
                        {
                            Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenId].SetWorkplace(citizenId, 0, 0u);
                        }
                        float vitualWorkersRatio = (totalWorkCount != 0) ? (allWorkCount / (float)totalWorkCount) : 1f;

                        //Budget offset for Salary
                        int budget = Singleton <EconomyManager> .instance.GetBudget(buildingData.Info.m_class);

                        salary = (int)(salary * budget / 100f);
                        salary = Math.Max(salary, salaryMax);
#if Debug
                        DebugLog.LogToFileOnly("DebugInfo: LandPrice offset for Salary is " + landPriceOffset.ToString());
#endif
                        salary = UniqueFacultyAI.IncreaseByBonus(UniqueFacultyAI.FacultyBonus.Science, salary);
                        if (!checkOnly)
                        {
                            var m_class = Singleton <BuildingManager> .instance.m_buildings.m_buffer[workBuilding].Info.m_class;
                            Singleton <EconomyManager> .instance.FetchResource((EconomyManager.Resource) 16, (int)(salary * vitualWorkersRatio), m_class);

                            MainDataStore.outsideTouristMoney += (salary * (vitualWorkersRatio - 1f) * MainDataStore.outsideTouristSalaryProfitRatio);
                        }
                    }
                }
            }

            return(salary);
        }        //public
        // Local reference.


        /// <summary>
        /// Harmony Prefix patch to CitizenManager.SimulationStepImpl, to detect and remove any citizens in the building that don't have the 'created' flag set.
        /// </summary>
        /// <param name="__instance">Instance reference</param>
        /// <param name="subStep">Simulation cycle substep.</param>
        public static void Prefix(CitizenManager __instance, int subStep)
        {
            // Don't do anything when subStep is zero.
            if (subStep != 0)
            {
                // Local references.
                Citizen[]     citizenBuffer = __instance.m_citizens.m_buffer;
                CitizenUnit[] citizenUnits  = __instance.m_units.m_buffer;

                // Get current framecount to align with parent method's frame, so we avoid unnecessary cache misses.
                uint frameCount   = Singleton <SimulationManager> .instance.m_currentFrameIndex & 0xFFF;
                uint currentFrame = frameCount * 128;
                uint baseUnit     = currentFrame + (stepCount * 8);
                uint endUnit      = baseUnit + 7;

                // Increment our step counter when frameCount wraps back to zero (evey 4096 increments).
                if (frameCount == 0)
                {
                    ++stepCount;

                    // If our step counter is greater than 15, wrap back to zero.
                    if (stepCount > 15)
                    {
                        stepCount = 0;
                    }
                }

                // Iterate through next 8 units in this frame.
                for (uint currentUnit = baseUnit; currentUnit <= endUnit; ++currentUnit)
                {
                    // Only interested in home units.
                    if ((citizenUnits[currentUnit].m_flags & CitizenUnit.Flags.Home) != 0 && citizenUnits[currentUnit].m_building != 0)
                    {
                        // Check for citizens with invalid flags in this household.
                        uint thisCitizen = citizenUnits[currentUnit].m_citizen0;
                        if (thisCitizen != 0)
                        {
                            Citizen.Flags citizenFlags = citizenBuffer[thisCitizen].m_flags;
                            if ((citizenFlags & Citizen.Flags.Created) == 0)
                            {
                                RemoveCitizen(__instance, ref citizenUnits[currentUnit].m_citizen0, currentUnit, citizenUnits[currentUnit].m_building, citizenFlags);
                            }
                        }
                        thisCitizen = citizenUnits[currentUnit].m_citizen1;
                        if (thisCitizen != 0)
                        {
                            Citizen.Flags citizenFlags = citizenBuffer[thisCitizen].m_flags;
                            if ((citizenFlags & Citizen.Flags.Created) == 0)
                            {
                                RemoveCitizen(__instance, ref citizenUnits[currentUnit].m_citizen1, currentUnit, citizenUnits[currentUnit].m_building, citizenFlags);
                            }
                        }
                        thisCitizen = citizenUnits[currentUnit].m_citizen2;
                        if (thisCitizen != 0)
                        {
                            Citizen.Flags citizenFlags = citizenBuffer[thisCitizen].m_flags;
                            if ((citizenFlags & Citizen.Flags.Created) == 0)
                            {
                                RemoveCitizen(__instance, ref citizenUnits[currentUnit].m_citizen2, currentUnit, citizenUnits[currentUnit].m_building, citizenFlags);
                            }
                        }
                        thisCitizen = citizenUnits[currentUnit].m_citizen3;
                        if (thisCitizen != 0)
                        {
                            Citizen.Flags citizenFlags = citizenBuffer[thisCitizen].m_flags;
                            if ((citizenFlags & Citizen.Flags.Created) == 0)
                            {
                                RemoveCitizen(__instance, ref citizenUnits[currentUnit].m_citizen3, currentUnit, citizenUnits[currentUnit].m_building, citizenFlags);
                            }
                        }
                        thisCitizen = citizenUnits[currentUnit].m_citizen4;
                        if (thisCitizen != 0)
                        {
                            Citizen.Flags citizenFlags = citizenBuffer[thisCitizen].m_flags;
                            if ((citizenFlags & Citizen.Flags.Created) == 0)
                            {
                                RemoveCitizen(__instance, ref citizenUnits[currentUnit].m_citizen4, currentUnit, citizenUnits[currentUnit].m_building, citizenFlags);
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Removes a citizen with invalid flags.
        /// </summary>
        /// <param name="citizenManager">CitizenManager instance reference</param>
        /// <param name="citizenID">Citizen ID to remove</param>
        /// <param name="citizenUnit">Owning CitizenUnit ID</param>
        /// <param name="buildingID">Home building ID</param>
        /// <param name="flags">Citizen flags</param>
        private static void RemoveCitizen(CitizenManager citizenManager, ref uint citizenID, uint citizenUnit, ushort buildingID, Citizen.Flags flags)
        {
            // Log messaged.
            Logging.Message("found citizen ", citizenID.ToString(), " in unit ", citizenUnit.ToString(), " of building ", buildingID.ToString(), " with invalid flags ", flags.ToString());

            // Remove citizen and reset reference in CitizenUnit.
            citizenManager.ReleaseCitizen(citizenID);
            citizenID = 0;
        }