private ScheduleAction UpdateCitizenState(ref TCitizen citizen, ref CitizenSchedule schedule)
        {
            if (schedule.CurrentState == ResidentState.Ignored)
            {
                return(ScheduleAction.Ignore);
            }

            if (CitizenProxy.HasFlags(ref citizen, Citizen.Flags.DummyTraffic))
            {
                schedule.CurrentState = ResidentState.Ignored;
                return(ScheduleAction.Ignore);
            }

            Citizen.Location location = CitizenProxy.GetLocation(ref citizen);
            if (location == Citizen.Location.Moving)
            {
                if (CitizenMgr.InstanceHasFlags(
                        CitizenProxy.GetInstance(ref citizen),
                        CitizenInstance.Flags.OnTour | CitizenInstance.Flags.TargetIsNode,
                        true))
                {
                    // Guided tours are treated as visits
                    schedule.Hint = ScheduleHint.OnTour;
                }

                schedule.CurrentState = ResidentState.InTransition;
                return(ScheduleAction.ProcessTransition);
            }

            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (currentBuilding == 0)
            {
                schedule.CurrentState = ResidentState.Unknown;
                return(ScheduleAction.ProcessState);
            }

            if (BuildingMgr.BuildingHasFlags(currentBuilding, Building.Flags.Evacuating))
            {
                schedule.CurrentState = ResidentState.Evacuation;
                return(ScheduleAction.ProcessState);
            }

            ItemClass.Service buildingService = BuildingMgr.GetBuildingService(currentBuilding);
            switch (location)
            {
            case Citizen.Location.Home:
                schedule.CurrentState = ResidentState.AtHome;
                return(ScheduleAction.ProcessState);

            case Citizen.Location.Work:
                if (CitizenProxy.GetVisitBuilding(ref citizen) == currentBuilding && schedule.WorkStatus != WorkStatus.Working)
                {
                    // A citizen may visit their own work building (e.g. shopping),
                    // but the game sets the location to 'work' even if the citizen visits the building.
                    goto case Citizen.Location.Visit;
                }

                switch (buildingService)
                {
                case ItemClass.Service.Electricity:
                case ItemClass.Service.Water:
                case ItemClass.Service.HealthCare:
                case ItemClass.Service.PoliceDepartment:
                case ItemClass.Service.FireDepartment:
                case ItemClass.Service.Disaster:
                    if (BuildingMgr.IsAreaEvacuating(currentBuilding))
                    {
                        schedule.CurrentState = ResidentState.InShelter;
                        return(ScheduleAction.ProcessState);
                    }

                    break;
                }

                schedule.CurrentState = ResidentState.AtSchoolOrWork;
                return(ScheduleAction.ProcessState);

            case Citizen.Location.Visit:
                switch (buildingService)
                {
                case ItemClass.Service.Beautification:
                case ItemClass.Service.Monument:
                case ItemClass.Service.Tourism:
                case ItemClass.Service.Commercial
                    when BuildingMgr.GetBuildingSubService(currentBuilding) == ItemClass.SubService.CommercialLeisure &&
                    schedule.WorkStatus != WorkStatus.Working:

                    schedule.CurrentState = ResidentState.Relaxing;

                    return(ScheduleAction.ProcessState);

                case ItemClass.Service.Commercial:
                    schedule.CurrentState = ResidentState.Shopping;
                    return(ScheduleAction.ProcessState);

                case ItemClass.Service.Disaster:
                    schedule.CurrentState = ResidentState.InShelter;
                    return(ScheduleAction.ProcessState);
                }

                schedule.CurrentState = ResidentState.Visiting;
                return(ScheduleAction.ProcessState);
            }

            return(ScheduleAction.Ignore);
        }