diff --git a/src/RealTime/CustomAI/Constants.cs b/src/RealTime/CustomAI/Constants.cs index cc006e68..2e7e321a 100644 --- a/src/RealTime/CustomAI/Constants.cs +++ b/src/RealTime/CustomAI/Constants.cs @@ -42,7 +42,7 @@ internal static class Constants public const float PrepareToWorkHours = 1f; /// An assumed maximum travel time to a target building. - public const float MaxTravelTime = 4f; + public const float MaxTravelTime = 2.5f; /// An assumed minimum travel to a target building. public const float MinTravelTime = 0.25f; @@ -54,6 +54,7 @@ internal static class Constants /// An assumed average speed of a citizen when moving to target (this is not just a walking speed, but also takes /// into account moving by car or public transport). /// + // TODO: calculate this dynamically depending on time speed public const float OnTheWayDistancePerHour = 500f; /// A chance in percent that a virtual citizen will not be realized in 'few virtual citizens' mode. diff --git a/src/RealTime/CustomAI/RealTimeResidentAI.Common.cs b/src/RealTime/CustomAI/RealTimeResidentAI.Common.cs index 74d9c714..5290d75d 100644 --- a/src/RealTime/CustomAI/RealTimeResidentAI.Common.cs +++ b/src/RealTime/CustomAI/RealTimeResidentAI.Common.cs @@ -321,7 +321,7 @@ private void ExecuteCitizenSchedule(ref CitizenSchedule schedule, TAI instance, { if (ProcessCurrentState(ref schedule, ref citizen) && schedule.ScheduledState == ResidentState.Unknown) { - Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} will be rescheduled now"); + Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} will be re-scheduled now"); // If the state processing changed the schedule, we need to update it UpdateCitizenSchedule(ref schedule, citizenId, ref citizen); @@ -371,6 +371,9 @@ private bool ProcessCurrentState(ref CitizenSchedule schedule, ref TCitizen citi { switch (schedule.CurrentState) { + case ResidentState.AtHome: + return RescheduleAtHome(ref schedule, ref citizen); + case ResidentState.Shopping: return ProcessCitizenShopping(ref schedule, ref citizen); diff --git a/src/RealTime/CustomAI/RealTimeResidentAI.Home.cs b/src/RealTime/CustomAI/RealTimeResidentAI.Home.cs index b3de2cbc..9ae24ab8 100644 --- a/src/RealTime/CustomAI/RealTimeResidentAI.Home.cs +++ b/src/RealTime/CustomAI/RealTimeResidentAI.Home.cs @@ -26,5 +26,35 @@ private void DoScheduledHome(ref CitizenSchedule schedule, TAI instance, uint ci schedule.Schedule(ResidentState.Unknown, default); Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is going from {currentBuilding} back home"); } + + private bool RescheduleAtHome(ref CitizenSchedule schedule, ref TCitizen citizen) + { + if (schedule.CurrentState != ResidentState.AtHome || TimeInfo.Now < schedule.ScheduledStateTime) + { + return false; + } + + if (schedule.ScheduledState != ResidentState.Relaxing && schedule.ScheduledState != ResidentState.Shopping) + { + return false; + } + + if (IsBadWeather()) + { + Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(0, ref citizen)} re-schedules an activity because of bad weather (see next line for citizen ID)"); + schedule.Schedule(ResidentState.Unknown, default); + return true; + } + + uint goOutChance = spareTimeBehavior.GetGoOutChance(CitizenProxy.GetAge(ref citizen)); + if (Random.ShouldOccur(goOutChance)) + { + return false; + } + + Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(0, ref citizen)} re-schedules an activity because of time (see next line for citizen ID)"); + schedule.Schedule(ResidentState.Unknown, default); + return true; + } } } diff --git a/src/RealTime/CustomAI/RealTimeResidentAI.Visit.cs b/src/RealTime/CustomAI/RealTimeResidentAI.Visit.cs index 7d12436e..66294f85 100644 --- a/src/RealTime/CustomAI/RealTimeResidentAI.Visit.cs +++ b/src/RealTime/CustomAI/RealTimeResidentAI.Visit.cs @@ -218,11 +218,15 @@ private bool IsBuildingNoiseRestricted(ushort targetBuilding, ushort currentBuil private bool RescheduleVisit(ref CitizenSchedule schedule, ref TCitizen citizen, ushort currentBuilding) { - if (schedule.ScheduledState != ResidentState.Relaxing - && schedule.ScheduledState != ResidentState.Shopping - && schedule.ScheduledState != ResidentState.Visiting) + switch (schedule.ScheduledState) { - return false; + case ResidentState.Shopping: + case ResidentState.Relaxing: + case ResidentState.Visiting: + break; + + default: + return false; } if (IsBadWeather())