Ejemplo n.º 1
0
        private void DoScheduledHome(ref CitizenSchedule schedule, TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen);

            if (homeBuilding == 0)
            {
                Log.Debug(LogCategory.State, $"{GetCitizenDesc(citizenId, ref citizen)} is currently homeless. Cannot move home, waiting for the next opportunity");
                return;
            }

            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            CitizenProxy.RemoveFlags(ref citizen, Citizen.Flags.Evacuating);

#if DEBUG
            string logEntry = $"{GetCitizenDesc(citizenId, ref citizen)} is going from {currentBuilding} back home";
#else
            const string logEntry = null;
#endif

            if (residentAI.StartMoving(instance, citizenId, ref citizen, currentBuilding, homeBuilding))
            {
                CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);
                schedule.Schedule(ResidentState.Unknown);
                Log.Debug(LogCategory.Movement, TimeInfo.Now, logEntry);
            }
            else
            {
                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} wanted to go home from {currentBuilding} but can't, waiting for the next opportunity");
            }
        }
        private bool ProcessCitizenSick(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            Citizen.Location 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)
            {
                ItemClass.Service service = BuildingMgr.GetBuildingService(CitizenProxy.GetVisitBuilding(ref citizen));
                if (service == ItemClass.Service.HealthCare || service == ItemClass.Service.Disaster)
                {
                    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);
        }
Ejemplo n.º 3
0
        private void DoScheduledHome(ref CitizenSchedule schedule, TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen);

            if (homeBuilding == 0)
            {
                Log.Debug(LogCategory.State, $"WARNING: {GetCitizenDesc(citizenId, ref citizen)} is in corrupt state: want to go home with no home building. Releasing the poor citizen.");
                CitizenMgr.ReleaseCitizen(citizenId);
                schedule = default;
                return;
            }

            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            CitizenProxy.RemoveFlags(ref citizen, Citizen.Flags.Evacuating);

            if (residentAI.StartMoving(instance, citizenId, ref citizen, currentBuilding, homeBuilding))
            {
                CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);
                schedule.Schedule(ResidentState.Unknown);
                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is going from {currentBuilding} back home");
            }
            else
            {
                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} wanted to go home from {currentBuilding} but can't, waiting for the next opportunity");
            }
        }
Ejemplo n.º 4
0
        private bool CitizenGoesRelaxing(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            Citizen.AgeGroup citizenAge = CitizenProxy.GetAge(ref citizen);
            if (!IsChance(GetGoOutChance(citizenAge)))
            {
                return(false);
            }

            ushort buildingId = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (buildingId == 0)
            {
                return(false);
            }

            if (TimeInfo.IsNightTime)
            {
                ushort leisure = MoveToLeisure(instance, citizenId, ref citizen, buildingId);
                Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} wanna relax at night, trying leisure area '{leisure}'");
                return(leisure != 0);
            }

            if (CitizenProxy.GetWorkBuilding(ref citizen) != 0 && IsWorkDayMorning(citizenAge))
            {
                return(false);
            }

            Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} wanna relax, heading to an entertainment place");
            residentAI.FindVisitPlace(instance, citizenId, buildingId, residentAI.GetEntertainmentReason(instance));
            return(true);
        }
Ejemplo n.º 5
0
        private void DoScheduledShopping(ref CitizenSchedule schedule, TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (schedule.Hint == ScheduleHint.LocalShoppingOnly)
            {
                schedule.Schedule(ResidentState.Unknown, default);

                ushort shop = MoveToCommercialBuilding(instance, citizenId, ref citizen, LocalSearchDistance);
                if (shop == 0)
                {
                    Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} wanted go shopping, but didn't find a local shop");
                }
                else
                {
                    Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} goes shopping at a local shop {shop}");
                }
            }
            else
            {
                uint          moreShoppingChance = spareTimeBehavior.GetGoOutChance(CitizenProxy.GetAge(ref citizen));
                ResidentState nextState          = Random.ShouldOccur(moreShoppingChance)
                    ? ResidentState.Unknown
                    : ResidentState.Shopping;

                schedule.Schedule(nextState, default);

                if (schedule.CurrentState != ResidentState.Shopping)
                {
                    Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} in state {schedule.CurrentState} wanna go shopping and schedules {nextState}, heading to a random shop");
                    residentAI.FindVisitPlace(instance, citizenId, currentBuilding, residentAI.GetShoppingReason(instance));
                }
            }
        }
Ejemplo n.º 6
0
        private bool StartMovingToVisitBuilding(TAI instance, uint citizenId, ref TCitizen citizen, ushort visitBuilding)
        {
            if (visitBuilding == 0)
            {
                return(false);
            }

            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (currentBuilding == visitBuilding)
            {
                CitizenProxy.SetVisitPlace(ref citizen, citizenId, visitBuilding);
                CitizenProxy.SetLocation(ref citizen, Citizen.Location.Visit);
                return(true);
            }

            CitizenProxy.SetVisitPlace(ref citizen, citizenId, visitBuilding);
            if (CitizenProxy.GetVisitBuilding(ref citizen) == 0)
            {
                // Building is full and doesn't accept visitors anymore
                return(false);
            }

            if (!residentAI.StartMoving(instance, citizenId, ref citizen, currentBuilding, visitBuilding))
            {
                CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);
                return(false);
            }

            return(true);
        }
Ejemplo n.º 7
0
        private bool ScheduleRelaxing(ref CitizenSchedule schedule, uint citizenId, ref TCitizen citizen)
        {
            Citizen.AgeGroup citizenAge = CitizenProxy.GetAge(ref citizen);

            uint relaxChance = spareTimeBehavior.GetRelaxingChance(citizenAge, schedule.WorkShift, schedule.WorkStatus == WorkStatus.OnVacation);

            relaxChance = AdjustRelaxChance(relaxChance, ref citizen);

            if (!Random.ShouldOccur(relaxChance) || WeatherInfo.IsBadWeather)
            {
                return(false);
            }

            ICityEvent cityEvent = GetUpcomingEventToAttend(citizenId, ref citizen);

            if (cityEvent != null)
            {
                ushort   currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);
                DateTime departureTime   = cityEvent.StartTime.AddHours(-travelBehavior.GetEstimatedTravelTime(currentBuilding, cityEvent.BuildingId));
                schedule.Schedule(ResidentState.Relaxing, departureTime);
                schedule.EventBuilding = cityEvent.BuildingId;
                schedule.Hint          = ScheduleHint.AttendingEvent;
                return(true);
            }

            schedule.Schedule(ResidentState.Relaxing);
            schedule.Hint = TimeInfo.IsNightTime && Random.ShouldOccur(NightLeisureChance)
                ? ScheduleHint.RelaxAtLeisureBuilding
                : ScheduleHint.None;

            return(true);
        }
Ejemplo n.º 8
0
        private bool ScheduleRelaxing(ref CitizenSchedule schedule, uint citizenId, ref TCitizen citizen)
        {
            Citizen.AgeGroup citizenAge = CitizenProxy.GetAge(ref citizen);
            if (!Random.ShouldOccur(spareTimeBehavior.GetGoOutChance(citizenAge)) || IsBadWeather())
            {
                return(false);
            }

            ICityEvent cityEvent = GetUpcomingEventToAttend(citizenId, ref citizen);

            if (cityEvent != null)
            {
                ushort   currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);
                DateTime departureTime   = cityEvent.StartTime.AddHours(-GetEstimatedTravelTime(currentBuilding, cityEvent.BuildingId));
                schedule.Schedule(ResidentState.Relaxing, departureTime);
                schedule.EventBuilding = cityEvent.BuildingId;
                schedule.Hint          = ScheduleHint.AttendingEvent;
                return(true);
            }

            schedule.Schedule(ResidentState.Relaxing, default);
            schedule.Hint = TimeInfo.IsNightTime
                ? ScheduleHint.RelaxAtLeisureBuilding
                : ScheduleHint.None;

            return(true);
        }
Ejemplo n.º 9
0
        private void ReturnFromVisit(
            TAI instance,
            uint citizenId,
            ref TCitizen citizen,
            ushort targetBuilding,
            Citizen.Location targetLocation,
            bool isVirtual)
        {
            if (targetBuilding == 0 || targetLocation == Citizen.Location.Visit || CitizenProxy.GetVehicle(ref citizen) != 0)
            {
                return;
            }

            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            CitizenProxy.RemoveFlags(ref citizen, Citizen.Flags.Evacuating);
            CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);

            if (isVirtual || targetBuilding == currentBuilding)
            {
                CitizenProxy.SetLocation(ref citizen, targetLocation);
            }
            else
            {
                residentAI.StartMoving(instance, citizenId, ref citizen, currentBuilding, targetBuilding);
            }
        }
Ejemplo n.º 10
0
        private ushort MoveToCommercialBuilding(TAI instance, uint citizenId, ref TCitizen citizen, float distance, bool isVirtual)
        {
            ushort buildingId = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (buildingId == 0)
            {
                return(0);
            }

            ushort foundBuilding = BuildingMgr.FindActiveBuilding(buildingId, distance, ItemClass.Service.Commercial);

            if (IsBuildingNoiseRestricted(foundBuilding))
            {
                Log.Debug($"Citizen {citizenId} won't go to the commercial building {foundBuilding}, it has a NIMBY policy");
                return(0);
            }

            if (StartMovingToVisitBuilding(instance, citizenId, ref citizen, foundBuilding, isVirtual))
            {
                ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen);
                uint   homeUnit     = BuildingMgr.GetCitizenUnit(homeBuilding);
                uint   citizenUnit  = CitizenProxy.GetContainingUnit(ref citizen, citizenId, homeUnit, CitizenUnit.Flags.Home);
                if (citizenUnit != 0)
                {
                    CitizenMgr.ModifyUnitGoods(citizenUnit, ShoppingGoodsAmount);
                }
            }

            return(foundBuilding);
        }
Ejemplo n.º 11
0
        private void DoScheduledWork(ref CitizenSchedule schedule, TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            schedule.WorkStatus          = WorkStatus.Working;
            schedule.DepartureToWorkTime = default;

            if (currentBuilding == schedule.WorkBuilding && schedule.CurrentState != ResidentState.AtSchoolOrWork)
            {
                CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);
                CitizenProxy.SetLocation(ref citizen, Citizen.Location.Work);
            }
            else if (residentAI.StartMoving(instance, citizenId, ref citizen, currentBuilding, schedule.WorkBuilding) &&
                     schedule.CurrentState == ResidentState.AtHome)
            {
                schedule.DepartureToWorkTime = TimeInfo.Now;
            }

            Citizen.AgeGroup citizenAge = CitizenProxy.GetAge(ref citizen);
            if (workBehavior.ScheduleLunch(ref schedule, citizenAge))
            {
                Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is going from {currentBuilding} to school/work {schedule.WorkBuilding} and will go to lunch at {schedule.ScheduledStateTime}");
            }
            else
            {
                workBehavior.ScheduleReturnFromWork(ref schedule, citizenAge);
                Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is going from {currentBuilding} to school/work {schedule.WorkBuilding} and will leave work at {schedule.ScheduledStateTime}");
            }
        }
Ejemplo n.º 12
0
        private void ProcessMoving(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort instanceId = CitizenProxy.GetInstance(ref citizen);
            ushort vehicleId  = CitizenProxy.GetVehicle(ref citizen);

            if (instanceId == 0)
            {
                if (vehicleId == 0)
                {
                    CitizenMgr.ReleaseCitizen(citizenId);
                }

                return;
            }

            if (vehicleId == 0 && CitizenMgr.IsAreaEvacuating(instanceId) && !CitizenProxy.HasFlags(ref citizen, Citizen.Flags.Evacuating))
            {
                Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} was on the way, but the area evacuates. Leaving the city.");
                touristAI.FindVisitPlace(instance, citizenId, CitizenProxy.GetCurrentBuilding(ref citizen), touristAI.GetLeavingReason(instance, citizenId, ref citizen));
                return;
            }

            if (CitizenMgr.InstanceHasFlags(instanceId, CitizenInstance.Flags.TargetIsNode | CitizenInstance.Flags.OnTour, true))
            {
                FindRandomVisitPlace(instance, citizenId, ref citizen, TouristDoNothingProbability, 0);
            }
        }
Ejemplo n.º 13
0
        private bool StartMovingToVisitBuilding(TAI instance, uint citizenId, ref TCitizen citizen, ushort visitBuilding, bool isVirtual)
        {
            if (visitBuilding == 0)
            {
                return(false);
            }

            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (isVirtual || currentBuilding == visitBuilding)
            {
                CitizenProxy.SetVisitPlace(ref citizen, citizenId, visitBuilding);
                CitizenProxy.SetVisitBuilding(ref citizen, visitBuilding);
                CitizenProxy.SetLocation(ref citizen, Citizen.Location.Visit);
                return(true);
            }
            else if (residentAI.StartMoving(instance, citizenId, ref citizen, currentBuilding, visitBuilding))
            {
                CitizenProxy.SetVisitPlace(ref citizen, citizenId, visitBuilding);
                CitizenProxy.SetVisitBuilding(ref citizen, visitBuilding);
                return(true);
            }

            return(false);
        }
Ejemplo n.º 14
0
        private void FindHotel(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (!Random.ShouldOccur(FindHotelChance))
            {
                Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} didn't want to stay in a hotel, leaving the city");
                touristAI.FindVisitPlace(instance, citizenId, currentBuilding, touristAI.GetLeavingReason(instance, citizenId, ref citizen));
                return;
            }

            ushort hotel = BuildingMgr.FindActiveBuilding(
                currentBuilding,
                FullSearchDistance,
                ItemClass.Service.Commercial,
                ItemClass.SubService.CommercialTourist);

            if (hotel == 0)
            {
                Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} didn't find a hotel, leaving the city");
                touristAI.FindVisitPlace(instance, citizenId, currentBuilding, touristAI.GetLeavingReason(instance, citizenId, ref citizen));
                return;
            }

            StartMovingToVisitBuilding(instance, citizenId, ref citizen, currentBuilding, hotel);
            Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} stays in a hotel {hotel}");
        }
Ejemplo n.º 15
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);
        }
Ejemplo n.º 16
0
        private uint AdjustRelaxChance(uint relaxChance, ref TCitizen citizen)
        {
            ushort visitBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            return((BuildingMgr.GetBuildingSubService(visitBuilding) == ItemClass.SubService.BeautificationParks)
                ? relaxChance * 2
                : relaxChance);
        }
Ejemplo n.º 17
0
        private void ProcessCitizenEvacuation(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort building = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (building != 0)
            {
                Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, false)} is trying to find an evacuation place");
                residentAI.FindEvacuationPlace(instance, citizenId, building, residentAI.GetEvacuationReason(instance, building));
            }
        }
Ejemplo n.º 18
0
        private bool DoScheduledShopping(ref CitizenSchedule schedule, TAI instance, uint citizenId, ref TCitizen citizen)
        {
            // Shopping was already scheduled last time, but the citizen is still at school/work or in shelter.
            // This can occur when the game's transfer manager can't find any activity for the citizen.
            // In that case, move back home.
            if ((schedule.CurrentState == ResidentState.AtSchoolOrWork || schedule.CurrentState == ResidentState.InShelter) &&
                schedule.LastScheduledState == ResidentState.Shopping)
            {
                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} wanted go shopping but is still at work or in shelter. No shopping activity found. Now going home.");
                return(false);
            }

            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (schedule.Hint == ScheduleHint.LocalShoppingOnly)
            {
                schedule.Schedule(ResidentState.Unknown);

                ushort shop = MoveToCommercialBuilding(instance, citizenId, ref citizen, LocalSearchDistance);
                if (shop == 0)
                {
                    Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} wanted go shopping, but didn't find a local shop");
                    return(false);
                }

                if (TimeInfo.IsNightTime)
                {
                    schedule.Hint = ScheduleHint.NoShoppingAnyMore;
                }

                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} goes shopping at a local shop {shop}");
                return(true);
            }

            uint          moreShoppingChance = spareTimeBehavior.GetShoppingChance(CitizenProxy.GetAge(ref citizen));
            ResidentState nextState          = schedule.Hint != ScheduleHint.NoShoppingAnyMore && Random.ShouldOccur(moreShoppingChance)
                ? ResidentState.Shopping
                : ResidentState.Unknown;

            schedule.Schedule(nextState);

            if (schedule.CurrentState != ResidentState.Shopping || Random.ShouldOccur(FindAnotherShopOrEntertainmentChance))
            {
                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} in state {schedule.CurrentState} wanna go shopping and schedules {nextState}, heading to a random shop, hint = {schedule.Hint}");
                residentAI.FindVisitPlace(instance, citizenId, currentBuilding, residentAI.GetShoppingReason(instance));
            }
#if DEBUG
            else
            {
                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} continues shopping in the same building.");
            }
#endif

            return(true);
        }
Ejemplo n.º 19
0
        private void DoScheduledRelaxing(ref CitizenSchedule schedule, TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort buildingId = CitizenProxy.GetCurrentBuilding(ref citizen);

            switch (schedule.Hint)
            {
            case ScheduleHint.RelaxAtLeisureBuilding:
                schedule.Schedule(ResidentState.Unknown, default);

                ushort leisure = MoveToLeisureBuilding(instance, citizenId, ref citizen, buildingId);
                if (leisure == 0)
                {
                    Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} wanted relax but didn't found a leisure building");
                }
                else
                {
                    Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} heading to a leisure building {leisure}");
                }

                return;

            case ScheduleHint.AttendingEvent:
                DateTime   returnTime = default;
                ICityEvent cityEvent  = EventMgr.GetCityEvent(schedule.EventBuilding);
                if (cityEvent == null)
                {
                    Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} wanted attend an event at '{schedule.EventBuilding}', but there was no event there");
                }
                else if (StartMovingToVisitBuilding(instance, citizenId, ref citizen, schedule.EventBuilding))
                {
                    returnTime = cityEvent.EndTime;
                    Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} wanna attend an event at '{schedule.EventBuilding}', will return at {returnTime}");
                }

                schedule.Schedule(ResidentState.Unknown, returnTime);
                schedule.EventBuilding = 0;
                return;
            }

            uint          relaxChance = spareTimeBehavior.GetGoOutChance(CitizenProxy.GetAge(ref citizen));
            ResidentState nextState   = Random.ShouldOccur(relaxChance)
                    ? ResidentState.Unknown
                    : ResidentState.Relaxing;

            schedule.Schedule(nextState, default);

            if (schedule.CurrentState != ResidentState.Relaxing)
            {
                Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} in state {schedule.CurrentState} wanna relax and then schedules {nextState}, heading to an entertainment building.");
                residentAI.FindVisitPlace(instance, citizenId, buildingId, residentAI.GetEntertainmentReason(instance));
            }
        }
Ejemplo n.º 20
0
        private void ProcessCitizenAtSchoolOrWork(TAI instance, uint citizenId, ref TCitizen citizen, bool isVirtual)
        {
            ushort workBuilding = CitizenProxy.GetWorkBuilding(ref citizen);

            if (workBuilding == 0)
            {
                Log.Debug($"WARNING: {GetCitizenDesc(citizenId, ref citizen, isVirtual)} is in corrupt state: at school/work with no work building. Teleporting home.");
                CitizenProxy.SetLocation(ref citizen, Citizen.Location.Home);
                return;
            }

            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (ShouldGoToLunch(CitizenProxy.GetAge(ref citizen), citizenId))
            {
                ushort lunchPlace = MoveToCommercialBuilding(instance, citizenId, ref citizen, LocalSearchDistance, isVirtual);
                if (lunchPlace != 0)
                {
                    Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, isVirtual)} is going for lunch from {currentBuilding} to {lunchPlace}");
                }
                else
                {
                    Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, isVirtual)} wanted to go for lunch from {currentBuilding}, but there were no buildings close enough");
                }

                return;
            }

            if (!ShouldReturnFromSchoolOrWork(citizenId, currentBuilding, CitizenProxy.GetAge(ref citizen)))
            {
                return;
            }

            Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, isVirtual)} leaves their workplace {workBuilding}");

            if (CitizenGoesToEvent(instance, citizenId, ref citizen, isVirtual))
            {
                return;
            }

            if (!CitizenGoesShopping(instance, citizenId, ref citizen, isVirtual) && !CitizenGoesRelaxing(instance, citizenId, ref citizen, isVirtual))
            {
                if (isVirtual)
                {
                    CitizenProxy.SetLocation(ref citizen, Citizen.Location.Home);
                }
                else
                {
                    residentAI.StartMoving(instance, citizenId, ref citizen, workBuilding, CitizenProxy.GetHomeBuilding(ref citizen));
                }
            }
        }
Ejemplo n.º 21
0
        private bool StartMovingToVisitBuilding(TAI instance, uint citizenId, ref TCitizen citizen, ushort visitBuilding)
        {
            if (visitBuilding == 0)
            {
                return(false);
            }

            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            residentAI.StartMoving(instance, citizenId, ref citizen, currentBuilding, visitBuilding);
            CitizenProxy.SetVisitPlace(ref citizen, citizenId, visitBuilding);
            CitizenProxy.SetVisitBuilding(ref citizen, visitBuilding);

            return(true);
        }
Ejemplo n.º 22
0
        private bool CitizenGoesWorking(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort homeBuilding    = CitizenProxy.GetHomeBuilding(ref citizen);
            ushort workBuilding    = CitizenProxy.GetWorkBuilding(ref citizen);
            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (!ShouldMoveToSchoolOrWork(workBuilding, currentBuilding, CitizenProxy.GetAge(ref citizen)))
            {
                return(false);
            }

            Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is going from {currentBuilding} ({CitizenProxy.GetLocation(ref citizen)}) to school/work {workBuilding}");

            residentAI.StartMoving(instance, citizenId, ref citizen, homeBuilding, workBuilding);
            return(true);
        }
        private void DoScheduledEvacuation(ref CitizenSchedule schedule, TAI instance, uint citizenId, ref TCitizen citizen)
        {
            schedule.Schedule(ResidentState.Unknown);
            ushort building = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (building == 0)
            {
                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is trying to find a shelter from current position");
                TransferMgr.AddOutgoingOfferFromCurrentPosition(citizenId, residentAI.GetEvacuationReason(instance, 0));
            }
            else
            {
                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is trying to find a shelter from {building}");
                residentAI.FindEvacuationPlace(instance, citizenId, building, residentAI.GetEvacuationReason(instance, building));
            }
        }
        private void DoScheduledEvacuation(ref CitizenSchedule schedule, TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort building = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (building == 0)
            {
                schedule.Schedule(ResidentState.AtHome);
                return;
            }

            schedule.Schedule(ResidentState.InShelter);
            if (schedule.CurrentState != ResidentState.InShelter)
            {
                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is trying to find an evacuation place");
                residentAI.FindEvacuationPlace(instance, citizenId, building, residentAI.GetEvacuationReason(instance, building));
            }
        }
        private void ProcessCitizenDead(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            Citizen.Location currentLocation = CitizenProxy.GetLocation(ref citizen);
            switch (currentLocation)
            {
            case Citizen.Location.Home when currentBuilding != 0:
                CitizenProxy.SetWorkplace(ref citizen, citizenId, 0);
                CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);
                break;

            case Citizen.Location.Work when currentBuilding != 0:
                CitizenProxy.SetHome(ref citizen, citizenId, 0);
                CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);
                break;

            case Citizen.Location.Visit when currentBuilding != 0:
                CitizenProxy.SetHome(ref citizen, citizenId, 0);
                CitizenProxy.SetWorkplace(ref citizen, citizenId, 0);

                if (BuildingMgr.GetBuildingService(CitizenProxy.GetVisitBuilding(ref citizen)) == ItemClass.Service.HealthCare)
                {
                    return;
                }

                break;

            case Citizen.Location.Moving when CitizenProxy.GetVehicle(ref citizen) != 0:
                CitizenProxy.SetHome(ref citizen, citizenId, 0);

                CitizenProxy.SetWorkplace(ref citizen, citizenId, 0);
                CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);
                return;

            default:
                Log.Debug(LogCategory.State, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is released because of death");
                residentSchedules[citizenId] = default;
                CitizenMgr.ReleaseCitizen(citizenId);
                return;
            }

            residentAI.FindHospital(instance, citizenId, currentBuilding, TransferManager.TransferReason.Dead);
            Log.Debug(LogCategory.State, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is dead, body should get serviced");
        }
        private void DoScheduledWork(ref CitizenSchedule schedule, TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            schedule.WorkStatus = WorkStatus.Working;

            if (currentBuilding == schedule.WorkBuilding && schedule.CurrentState != ResidentState.AtSchoolOrWork)
            {
                CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);
                CitizenProxy.SetLocation(ref citizen, Citizen.Location.Work);
                return;
            }

#if DEBUG
            string citizenDesc = GetCitizenDesc(citizenId, ref citizen);
#else
            const string citizenDesc = null;
#endif

            if (residentAI.StartMoving(instance, citizenId, ref citizen, currentBuilding, schedule.WorkBuilding))
            {
                if (schedule.CurrentState != ResidentState.AtHome)
                {
                    // The start moving method will register a departure from any building to work,
                    // but we are only interested in the 'home->work' route.
                    schedule.DepartureTime = default;
                }

                Citizen.AgeGroup citizenAge = CitizenProxy.GetAge(ref citizen);
                if (workBehavior.ScheduleLunch(ref schedule, citizenAge))
                {
                    Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{citizenDesc} is going from {currentBuilding} to school/work {schedule.WorkBuilding} and will go to lunch at {schedule.ScheduledStateTime}");
                }
                else
                {
                    workBehavior.ScheduleReturnFromWork(ref schedule, citizenAge);
                    Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{citizenDesc} is going from {currentBuilding} to school/work {schedule.WorkBuilding} and will leave work at {schedule.ScheduledStateTime}");
                }
            }
            else
            {
                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} wanted to go to work from {currentBuilding} but can't, will try once again next time");
                schedule.Schedule(ResidentState.Unknown);
            }
        }
Ejemplo n.º 27
0
        private uint AdjustRelaxChance(uint relaxChance, ref TCitizen citizen)
        {
            ushort visitBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (BuildingMgr.GetBuildingSubService(visitBuilding) == ItemClass.SubService.BeautificationParks)
            {
                return(relaxChance * 2);
            }
            else if (CitizenProxy.GetAge(ref citizen) == Citizen.AgeGroup.Senior &&
                     BuildingMgr.IsBuildingServiceLevel(visitBuilding, ItemClass.Service.HealthCare, ItemClass.Level.Level3))
            {
                return(relaxChance * 4);
            }
            else
            {
                return(relaxChance);
            }
        }
        private bool ScheduleWork(ref CitizenSchedule schedule, ref TCitizen citizen)
        {
            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (!workBehavior.ScheduleGoToWork(ref schedule, currentBuilding, simulationCycle))
            {
                return(false);
            }

            Log.Debug($"  - Schedule work at {schedule.ScheduledStateTime}");

            float timeLeft = (float)(schedule.ScheduledStateTime - TimeInfo.Now).TotalHours;

            if (timeLeft <= PrepareToWorkHours)
            {
                // Just sit at home if the work time will come soon
                Log.Debug($"  - Work time in {timeLeft} hours, preparing for departure");
                return(true);
            }

            if (timeLeft <= MaxTravelTime)
            {
                if (schedule.CurrentState != ResidentState.AtHome)
                {
                    Log.Debug($"  - Work time in {timeLeft} hours, returning home");
                    schedule.Schedule(ResidentState.AtHome, default);
                    return(true);
                }

                // If we have some time, try to shop locally.
                if (ScheduleShopping(ref schedule, ref citizen, true))
                {
                    Log.Debug($"  - Work time in {timeLeft} hours, trying local shop");
                }
                else
                {
                    Log.Debug($"  - Work time in {timeLeft} hours, doing nothing");
                }

                return(true);
            }

            return(false);
        }
Ejemplo n.º 29
0
        private ushort MoveToCommercialBuilding(TAI instance, uint citizenId, ref TCitizen citizen, float distance)
        {
            ushort buildingId = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (buildingId == 0)
            {
                return(0);
            }

            ushort foundBuilding = BuildingMgr.FindActiveBuilding(buildingId, distance, ItemClass.Service.Commercial);

            if (foundBuilding == CitizenProxy.GetWorkBuilding(ref citizen))
            {
                return(0);
            }

            StartMovingToVisitBuilding(instance, citizenId, ref citizen, foundBuilding);
            return(foundBuilding);
        }
        private void ProcessCitizenDead(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            Citizen.Location currentLocation = CitizenProxy.GetLocation(ref citizen);

            if (currentBuilding == 0 || (currentLocation == Citizen.Location.Moving && CitizenProxy.GetVehicle(ref citizen) == 0))
            {
                Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is released");
                residentSchedules[citizenId] = default;
                CitizenMgr.ReleaseCitizen(citizenId);
                return;
            }

            if (currentLocation != Citizen.Location.Home && CitizenProxy.GetHomeBuilding(ref citizen) != 0)
            {
                CitizenProxy.SetHome(ref citizen, citizenId, 0);
            }

            if (currentLocation != Citizen.Location.Work && CitizenProxy.GetWorkBuilding(ref citizen) != 0)
            {
                CitizenProxy.SetWorkplace(ref citizen, citizenId, 0);
            }

            if (currentLocation != Citizen.Location.Visit && CitizenProxy.GetVisitBuilding(ref citizen) != 0)
            {
                CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);
            }

            if (currentLocation == Citizen.Location.Moving || CitizenProxy.GetVehicle(ref citizen) != 0)
            {
                return;
            }

            if (currentLocation == Citizen.Location.Visit &&
                BuildingMgr.GetBuildingService(CitizenProxy.GetVisitBuilding(ref citizen)) == ItemClass.Service.HealthCare)
            {
                return;
            }

            residentAI.FindHospital(instance, citizenId, currentBuilding, TransferManager.TransferReason.Dead);
            Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is dead, body should get serviced");
        }