dymanoid / RealTime

A mod for the Cities: Skylines game. Adjusts the time flow and the citizens behavior to make them more real.
MIT License
98 stars 59 forks source link

Citizen not found! #209

Closed pcfantasy closed 5 years ago

pcfantasy commented 5 years ago

Describe the bug A lot of Citizen not found in output.log, if disable RealTime mod, all thing is fine. I debug this for a while, it seems RealTime and TMPE release citizen instance twice? You can use harmony to add blow codes to monitor this strange behaviour.

    public static void CitizenManagerReleaseCitizenInstanceImplementationPreFix(ushort instance, ref CitizenInstance data)
    {
            if (data.m_flags == CitizenInstance.Flags.None)
            {
                DebugLog.LogToFileOnly("Error: release a already released citizeninstance" + Environment.StackTrace);
                DebugLog.LogToFileOnly("m_sourcebuilding = " + data.m_sourceBuilding);
                DebugLog.LogToFileOnly("m_targetbuilding = " + data.m_targetBuilding);
            }                
 }

Additional mods You can get all the mods you needed in save file

Enabled Plugins:

Game log file See attachment

output_log.txt test5.zip

pcfantasy commented 5 years ago

@dymanoid I think I find the root cause.

You have a postfix to add ProcessWaitingForTransport() in ResidentAI.SimulationStep. In ProcessWaitingForTransport(), if a citizen is homeless, you will release this citizen. But after ResidentAI.SimulationStep, there are still other codes in HumanAI.SimulationStep to release citizens. Which will cause this issue.

I will modify this and test this fix, then give you a pull request for your review, thanks.

    private sealed class ResidentAI_SimulationStep : PatchBase
    {
        protected override MethodInfo GetMethod()
        {
            return typeof(ResidentAI).GetMethod("SimulationStep", BindingFlags.Instance | BindingFlags.Public, null, new Type[]
            {
                typeof(ushort),
                typeof(CitizenInstance).MakeByRefType(),
                typeof(CitizenInstance.Frame).MakeByRefType(),
                typeof(bool)
            }, new ParameterModifier[0]);
        }

        private static void Postfix(ushort instanceID, ref CitizenInstance citizenData, ResidentAI __instance)
        {
            if (ResidentAIPatch.RealTimeAI == null || instanceID == 0)
            {
                return;
            }
            if ((citizenData.m_flags & (CitizenInstance.Flags.WaitingTransport | CitizenInstance.Flags.WaitingTaxi)) != CitizenInstance.Flags.None)
            {
                ResidentAIPatch.RealTimeAI.ProcessWaitingForTransport(__instance, citizenData.m_citizen, instanceID);
            }
        }
dymanoid commented 5 years ago

It turns out that 'releasing' a (resident) citizen, when their home building is not set, is generally wrong. The game will e.g. try to find a new home for a citizen whose housing was demolished.

I completely remove the releasing code for that part.

The game must cope with those citizens (either provide a new home or 'release' them). According to my tests, there are no negative effects in removing of the releasing code.