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())