private bool CitzenReturnsFromShelter(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort visitBuilding = CitizenProxy.GetVisitBuilding(ref citizen);

            if (BuildingMgr.GetBuildingService(visitBuilding) != ItemClass.Service.Disaster)
            {
                return(true);
            }

            if (!BuildingMgr.BuildingHasFlags(visitBuilding, Building.Flags.Downgrading))
            {
                return(false);
            }

            ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen);

            if (homeBuilding == 0)
            {
                Log.Debug($"WARNING: {GetCitizenDesc(citizenId, ref citizen)} was in a shelter but seems to be homeless. Releasing the citizen.");
                CitizenMgr.ReleaseCitizen(citizenId);
                return(true);
            }

            Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} returning from evacuation place back home");
            ReturnFromVisit(instance, citizenId, ref citizen, homeBuilding);
            return(true);
        }
Example #2
0
        private void ProcessVisit(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort visitBuilding = CitizenProxy.GetVisitBuilding(ref citizen);

            if (visitBuilding == 0)
            {
                CitizenMgr.ReleaseCitizen(citizenId);
                return;
            }

            if (BuildingMgr.BuildingHasFlags(visitBuilding, Building.Flags.Evacuating))
            {
                touristAI.FindEvacuationPlace(instance, citizenId, visitBuilding, touristAI.GetEvacuationReason(instance, visitBuilding));
                return;
            }

            switch (BuildingMgr.GetBuildingService(visitBuilding))
            {
            case ItemClass.Service.Disaster:
                if (BuildingMgr.BuildingHasFlags(visitBuilding, Building.Flags.Downgrading))
                {
                    CitizenProxy.RemoveFlags(ref citizen, Citizen.Flags.Evacuating);
                    FindRandomVisitPlace(instance, citizenId, ref citizen, 0, visitBuilding);
                }

                return;

            // Tourist is sleeping in a hotel
            case ItemClass.Service.Commercial
                when BuildingMgr.GetBuildingSubService(visitBuilding) == ItemClass.SubService.CommercialTourist &&
                !Random.ShouldOccur(GetHotelLeaveChance()):
                return;
            }

            ICityEvent currentEvent = EventMgr.GetCityEvent(visitBuilding);

            if (currentEvent != null && currentEvent.StartTime < TimeInfo.Now)
            {
                if (Random.ShouldOccur(TouristShoppingChance))
                {
                    BuildingMgr.ModifyMaterialBuffer(visitBuilding, TransferManager.TransferReason.Shopping, -ShoppingGoodsAmount);
                }

                return;
            }

            if (Random.ShouldOccur(TouristEventChance) && !WeatherInfo.IsBadWeather)
            {
                ICityEvent cityEvent = GetUpcomingEventToAttend(citizenId, ref citizen);
                if (cityEvent != null &&
                    StartMovingToVisitBuilding(instance, citizenId, ref citizen, CitizenProxy.GetCurrentBuilding(ref citizen), cityEvent.BuildingId))
                {
                    Log.Debug(LogCategory.Events, TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} attending an event at {cityEvent.BuildingId}");
                    return;
                }
            }

            FindRandomVisitPlace(instance, citizenId, ref citizen, 0, visitBuilding);
        }
        private bool ProcessCitizenInShelter(ref CitizenSchedule schedule, ref TCitizen citizen)
        {
            ushort shelter = CitizenProxy.GetVisitBuilding(ref citizen);

            if (BuildingMgr.BuildingHasFlags(shelter, Building.Flags.Downgrading))
            {
                schedule.Schedule(ResidentState.Unknown, default);
                return(true);
            }

            return(false);
        }
        private bool ProcessCitizenInShelter(ref CitizenSchedule schedule, ref TCitizen citizen)
        {
            ushort shelter = CitizenProxy.GetVisitBuilding(ref citizen);

            if (BuildingMgr.BuildingHasFlags(shelter, Building.Flags.Downgrading) && schedule.ScheduledState == ResidentState.InShelter)
            {
                CitizenProxy.RemoveFlags(ref citizen, Citizen.Flags.Evacuating);
                schedule.Schedule(ResidentState.Unknown);
                return(true);
            }

            return(false);
        }
Example #5
0
        private bool ProcessCitizenSick(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            var currentLocation = CitizenProxy.GetLocation(ref citizen);

            if (currentLocation == Citizen.Location.Moving)
            {
                return(false);
            }

            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (currentLocation != Citizen.Location.Home && currentBuilding == 0)
            {
                Log.Debug(LogCategory.State, $"Teleporting {GetCitizenDesc(citizenId, ref citizen)} back home because they are sick but no building is specified");
                CitizenProxy.SetLocation(ref citizen, Citizen.Location.Home);
                return(true);
            }

            if (currentLocation != Citizen.Location.Home && CitizenProxy.GetVehicle(ref citizen) != 0)
            {
                return(true);
            }

            if (currentLocation == Citizen.Location.Visit)
            {
                ushort visitBuilding = CitizenProxy.GetVisitBuilding(ref citizen);
                switch (BuildingMgr.GetBuildingService(visitBuilding))
                {
                case ItemClass.Service.HealthCare:
                    UpdateSickStateOnVisitingHealthcare(citizenId, visitBuilding, ref citizen);
                    return(true);

                case ItemClass.Service.Disaster when !BuildingMgr.BuildingHasFlags(visitBuilding, Building.Flags.Downgrading):
                    return(true);
                }
            }

            Log.Debug(LogCategory.State, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is sick, trying to get to a hospital");
            residentAI.FindHospital(instance, citizenId, currentBuilding, TransferManager.TransferReason.Sick);
            return(true);
        }
Example #6
0
        private void ProcessVisit(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort visitBuilding = CitizenProxy.GetVisitBuilding(ref citizen);

            if (visitBuilding == 0)
            {
                CitizenMgr.ReleaseCitizen(citizenId);
                return;
            }

            if (BuildingMgr.BuildingHasFlags(visitBuilding, Building.Flags.Evacuating))
            {
                touristAI.FindEvacuationPlace(instance, citizenId, visitBuilding, touristAI.GetEvacuationReason(instance, visitBuilding));
                return;
            }

            switch (BuildingMgr.GetBuildingService(visitBuilding))
            {
            case ItemClass.Service.Disaster:
                if (BuildingMgr.BuildingHasFlags(visitBuilding, Building.Flags.Downgrading))
                {
                    FindRandomVisitPlace(instance, citizenId, ref citizen, 0, visitBuilding);
                }

                return;

            // Tourist is sleeping in a hotel
            case ItemClass.Service.Commercial
                when TimeInfo.IsNightTime && BuildingMgr.GetBuildingSubService(visitBuilding) == ItemClass.SubService.CommercialTourist:
                return;
            }

            if (Random.ShouldOccur(TouristEventChance) && !IsBadWeather())
            {
                ICityEvent cityEvent = GetUpcomingEventToAttend(citizenId, ref citizen);
                if (cityEvent != null)
                {
                    StartMovingToVisitBuilding(instance, citizenId, ref citizen, CitizenProxy.GetCurrentBuilding(ref citizen), cityEvent.BuildingId);
                    Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} attending an event at {cityEvent.BuildingId}");
                    return;
                }
            }

            int doNothingChance;

            switch (EventMgr.GetEventState(visitBuilding, DateTime.MaxValue))
            {
            case CityEventState.Ongoing:
                if (Random.ShouldOccur(TouristShoppingChance))
                {
                    BuildingMgr.ModifyMaterialBuffer(visitBuilding, TransferManager.TransferReason.Shopping, -ShoppingGoodsAmount);
                }

                return;

            case CityEventState.Finished:
                doNothingChance = 0;
                break;

            default:
                doNothingChance = TouristDoNothingProbability;
                break;
            }

            FindRandomVisitPlace(instance, citizenId, ref citizen, doNothingChance, visitBuilding);
        }
        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.CurrentState = ResidentState.Visiting;
                    schedule.Hint         = ScheduleHint.OnTour;
                    return(ScheduleAction.ProcessState);
                }

                return(ScheduleAction.ProcessTransition);
            }

            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

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

            ItemClass.Service buildingService = BuildingMgr.GetBuildingService(currentBuilding);
            if (BuildingMgr.BuildingHasFlags(currentBuilding, Building.Flags.Evacuating) &&
                buildingService != ItemClass.Service.Disaster)
            {
                schedule.CurrentState = ResidentState.Evacuation;
                schedule.Schedule(ResidentState.InShelter);
                return(ScheduleAction.ProcessState);
            }

            switch (location)
            {
            case Citizen.Location.Home:
                schedule.CurrentState = ResidentState.AtHome;
                return(ScheduleAction.ProcessState);

            case Citizen.Location.Work:
                if (buildingService == ItemClass.Service.Disaster && CitizenProxy.HasFlags(ref citizen, Citizen.Flags.Evacuating))
                {
                    schedule.CurrentState = ResidentState.InShelter;
                    return(ScheduleAction.ProcessState);
                }

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

                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 when CitizenProxy.HasFlags(ref citizen, Citizen.Flags.Evacuating):
                    schedule.CurrentState = ResidentState.InShelter;

                    return(ScheduleAction.ProcessState);
                }

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

            return(ScheduleAction.Ignore);
        }
Example #8
0
        private ResidentState GetResidentState(ref TCitizen citizen)
        {
            if (CitizenProxy.HasFlags(ref citizen, Citizen.Flags.DummyTraffic))
            {
                return(ResidentState.Ignored);
            }

            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            ItemClass.Service buildingService = BuildingMgr.GetBuildingService(currentBuilding);

            if (BuildingMgr.BuildingHasFlags(currentBuilding, Building.Flags.Evacuating) &&
                buildingService != ItemClass.Service.Disaster)
            {
                return(ResidentState.Evacuating);
            }

            switch (CitizenProxy.GetLocation(ref citizen))
            {
            case Citizen.Location.Home:
                return(currentBuilding != 0
                        ? ResidentState.AtHome
                        : ResidentState.Unknown);

            case Citizen.Location.Work:
                if (buildingService == ItemClass.Service.Disaster && CitizenProxy.HasFlags(ref citizen, Citizen.Flags.Evacuating))
                {
                    return(ResidentState.InShelter);
                }

                if (CitizenProxy.GetVisitBuilding(ref citizen) == currentBuilding)
                {
                    // A citizen may visit their own work building (e.g. shopping)
                    goto case Citizen.Location.Visit;
                }

                return(currentBuilding != 0
                        ? ResidentState.AtSchoolOrWork
                        : ResidentState.Unknown);

            case Citizen.Location.Visit:
                if (currentBuilding == 0)
                {
                    return(ResidentState.Unknown);
                }

                switch (buildingService)
                {
                case ItemClass.Service.Commercial:
                    if (CitizenProxy.GetWorkBuilding(ref citizen) != 0 && IsWorkDay &&
                        TimeInfo.CurrentHour > Config.LunchBegin && TimeInfo.CurrentHour < GetSpareTimeBeginHour(CitizenProxy.GetAge(ref citizen)))
                    {
                        return(ResidentState.AtLunch);
                    }

                    if (BuildingMgr.GetBuildingSubService(currentBuilding) == ItemClass.SubService.CommercialLeisure)
                    {
                        return(ResidentState.AtLeisureArea);
                    }

                    return(ResidentState.Shopping);

                case ItemClass.Service.Beautification:
                    return(ResidentState.AtLeisureArea);

                case ItemClass.Service.Disaster:
                    return(ResidentState.InShelter);
                }

                return(ResidentState.Visiting);

            case Citizen.Location.Moving:
                ushort instanceId = CitizenProxy.GetInstance(ref citizen);
                if (CitizenMgr.InstanceHasFlags(instanceId, CitizenInstance.Flags.OnTour | CitizenInstance.Flags.TargetIsNode, true))
                {
                    return(ResidentState.OnTour);
                }

                ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen);
                return(homeBuilding != 0 && CitizenMgr.GetTargetBuilding(instanceId) == homeBuilding
                        ? ResidentState.MovingHome
                        : ResidentState.MovingToTarget);

            default:
                return(ResidentState.Unknown);
            }
        }
Example #9
0
        private void ProcessVisit(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort visitBuilding = CitizenProxy.GetVisitBuilding(ref citizen);

            if (visitBuilding == 0)
            {
                CitizenMgr.ReleaseCitizen(citizenId);
                return;
            }

            if (BuildingMgr.BuildingHasFlags(visitBuilding, Building.Flags.Evacuating))
            {
                touristAI.FindEvacuationPlace(instance, citizenId, visitBuilding, touristAI.GetEvacuationReason(instance, visitBuilding));
                return;
            }

            switch (BuildingMgr.GetBuildingService(visitBuilding))
            {
            case ItemClass.Service.Disaster:
                if (BuildingMgr.BuildingHasFlags(visitBuilding, Building.Flags.Downgrading))
                {
                    FindRandomVisitPlace(instance, citizenId, ref citizen, 0, visitBuilding);
                }

                return;

            // Tourist is sleeping in a hotel
            case ItemClass.Service.Commercial
                when TimeInfo.IsNightTime && BuildingMgr.GetBuildingSubService(visitBuilding) == ItemClass.SubService.CommercialTourist:
                return;
            }

            if (IsChance(TouristEventChance) && AttendUpcomingEvent(citizenId, ref citizen, out ushort eventBuilding))
            {
                StartMovingToVisitBuilding(instance, citizenId, ref citizen, CitizenProxy.GetCurrentBuilding(ref citizen), eventBuilding);
                touristAI.AddTouristVisit(instance, citizenId, eventBuilding);
                Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} attending an event at {eventBuilding}");
                return;
            }

            bool doShopping;

            switch (EventMgr.GetEventState(visitBuilding, DateTime.MaxValue))
            {
            case CityEventState.Ongoing:
                doShopping = IsChance(TouristShoppingChance);
                break;

            case CityEventState.Finished:
                doShopping = !FindRandomVisitPlace(instance, citizenId, ref citizen, 0, visitBuilding);
                break;

            default:
                doShopping = false;
                break;
            }

            if (doShopping || !FindRandomVisitPlace(instance, citizenId, ref citizen, TouristDoNothingProbability, visitBuilding))
            {
                BuildingMgr.ModifyMaterialBuffer(visitBuilding, TransferManager.TransferReason.Shopping, -ShoppingGoodsAmount);
                touristAI.AddTouristVisit(instance, citizenId, visitBuilding);
            }
        }
        private ResidentState GetResidentState(ref TCitizen citizen)
        {
            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            ItemClass.Service buildingService = BuildingMgr.GetBuildingService(currentBuilding);

            if (BuildingMgr.BuildingHasFlags(currentBuilding, Building.Flags.Evacuating) &&
                buildingService != ItemClass.Service.Disaster)
            {
                return(ResidentState.Evacuating);
            }

            switch (CitizenProxy.GetLocation(ref citizen))
            {
            case Citizen.Location.Home:
                if (CitizenProxy.HasFlags(ref citizen, Citizen.Flags.MovingIn))
                {
                    return(ResidentState.LeftCity);
                }

                if (currentBuilding != 0)
                {
                    return(ResidentState.AtHome);
                }

                return(ResidentState.Unknown);

            case Citizen.Location.Work:
                if (buildingService == ItemClass.Service.Disaster && CitizenProxy.HasFlags(ref citizen, Citizen.Flags.Evacuating))
                {
                    return(ResidentState.InShelter);
                }

                return(currentBuilding != 0
                        ? ResidentState.AtSchoolOrWork
                        : ResidentState.Unknown);

            case Citizen.Location.Visit:
                if (currentBuilding == 0)
                {
                    return(ResidentState.Unknown);
                }

                switch (buildingService)
                {
                case ItemClass.Service.Commercial:
                    if (CitizenProxy.GetWorkBuilding(ref citizen) != 0 && IsWorkDay &&
                        TimeInfo.CurrentHour > Config.LunchBegin && TimeInfo.CurrentHour < GetSpareTimeBeginHour(CitizenProxy.GetAge(ref citizen)))
                    {
                        return(ResidentState.AtLunch);
                    }

                    if (BuildingMgr.GetBuildingSubService(currentBuilding) == ItemClass.SubService.CommercialLeisure)
                    {
                        return(ResidentState.AtLeisureArea);
                    }

                    return(ResidentState.Shopping);

                case ItemClass.Service.Beautification:
                    return(ResidentState.AtLeisureArea);

                case ItemClass.Service.Disaster:
                    return(ResidentState.InShelter);
                }

                return(ResidentState.Visiting);

            case Citizen.Location.Moving:
                ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen);
                return(homeBuilding != 0 && CitizenMgr.GetTargetBuilding(CitizenProxy.GetInstance(ref citizen)) == homeBuilding
                        ? ResidentState.MovingHome
                        : ResidentState.MovingToTarget);

            default:
                return(ResidentState.Unknown);
            }
        }