Skip to content

Commit

Permalink
Implement feature #1 - weather conditions
Browse files Browse the repository at this point in the history
- citizens stay at home on bad weather
- citizens return home on bad weather
- same behavior for significant disasters
  • Loading branch information
dymanoid committed Jul 6, 2018
1 parent d6597a3 commit 879caec
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 21 deletions.
2 changes: 2 additions & 0 deletions src/RealTime/Core/RealTimeCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ public static RealTimeCore Run(RealTimeConfig config, string rootPath, Localizat
SimulationHandler.DayTimeSimulation = new DayTimeSimulation(config);
SimulationHandler.EventManager = eventManager;
SimulationHandler.CommercialAI = new RealTimeCommercialBuildingAI(timeInfo, buildingManager);
SimulationHandler.WeatherInfo = weatherInfo;

RealTimeStorage.CurrentLevelStorage.GameSaving += result.GameSaving;
result.storageData.Add(eventManager);
Expand Down Expand Up @@ -161,6 +162,7 @@ public void Stop()
SimulationHandler.DayTimeSimulation = null;
SimulationHandler.CommercialAI = null;
SimulationHandler.TimeAdjustment = null;
SimulationHandler.WeatherInfo = null;

try
{
Expand Down
21 changes: 21 additions & 0 deletions src/RealTime/CustomAI/RealTimeHumanAIBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,27 @@ protected bool IsCitizenVirtual<TAI>(TAI humanAI, ref TCitizen citizen, Func<TAI
return !Random.ShouldOccur(virtualChance);
}

/// <summary>Determines whether the weather is currently so bad that the citizen would like to stay inside a building.</summary>
/// <param name="citizenId">The ID of the citizen to check the weather for.</param>
/// <returns>
/// <c>true</c> if the weather is bad; otherwise, <c>false</c>.</returns>
protected bool IsBadWeather(uint citizenId)
{
if (WeatherInfo.IsDisasterHazardActive)
{
Log.Debug($"Citizen {citizenId} is uncomfortable because of a disaster");
return true;
}

bool result = WeatherInfo.StayInsideChance != 0 && Random.ShouldOccur(WeatherInfo.StayInsideChance);
if (result)
{
Log.Debug($"Citizen {citizenId} is uncomfortable because of bad weather");
}

return result;
}

private bool CanAttendEvent(uint citizenId, ref TCitizen citizen, ICityEvent cityEvent)
{
Citizen.AgeGroup age = CitizenProxy.GetAge(ref citizen);
Expand Down
35 changes: 26 additions & 9 deletions src/RealTime/CustomAI/RealTimeResidentAI.Moving.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,37 @@ private void ProcessCitizenMoving(TAI instance, uint citizenId, ref TCitizen cit
return;
}

if (CitizenMgr.InstanceHasFlags(instanceId, CitizenInstance.Flags.WaitingTransport | CitizenInstance.Flags.WaitingTaxi))
bool returnHome = false;
ushort targetBuilding = CitizenMgr.GetTargetBuilding(instanceId);
if (targetBuilding != CitizenProxy.GetWorkBuilding(ref citizen))
{
ItemClass.Service targetService = BuildingMgr.GetBuildingService(targetBuilding);
if (targetService == ItemClass.Service.Beautification && IsBadWeather(citizenId))
{
Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, false)} cancels the trip to a park due to bad weather");
returnHome = true;
}
}

if (!returnHome && CitizenMgr.InstanceHasFlags(instanceId, CitizenInstance.Flags.WaitingTransport | CitizenInstance.Flags.WaitingTaxi))
{
if (mayCancel && CitizenMgr.GetInstanceWaitCounter(instanceId) == 255 && Random.ShouldOccur(AbandonTransportWaitChance))
{
ushort home = CitizenProxy.GetHomeBuilding(ref citizen);
if (home == 0)
{
return;
}

Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, false)} doesn't want to wait for transport anymore, goes back home");
residentAI.StartMoving(instance, citizenId, ref citizen, 0, home);
Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, false)} goes back home");
returnHome = true;
}
}

if (returnHome)
{
ushort home = CitizenProxy.GetHomeBuilding(ref citizen);
if (home == 0)
{
return;
}

residentAI.StartMoving(instance, citizenId, ref citizen, 0, home);
}
}
}
}
6 changes: 3 additions & 3 deletions src/RealTime/CustomAI/RealTimeResidentAI.SchoolWork.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ private void ProcessCitizenAtSchoolOrWork(TAI instance, uint citizenId, ref TCit
}

ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);
if (ShouldGoToLunch(CitizenProxy.GetAge(ref citizen)))
if (ShouldGoToLunch(CitizenProxy.GetAge(ref citizen), citizenId))
{
ushort lunchPlace = MoveToCommercialBuilding(instance, citizenId, ref citizen, LocalSearchDistance, isVirtual);
if (lunchPlace != 0)
Expand Down Expand Up @@ -367,7 +367,7 @@ private bool ShouldReturnFromSchoolOrWork(uint citizenId, ushort buildingId, Cit
return false;
}

private bool ShouldGoToLunch(Citizen.AgeGroup citizenAge)
private bool ShouldGoToLunch(Citizen.AgeGroup citizenAge, uint citizenId)
{
if (!Config.IsLunchtimeEnabled)
{
Expand All @@ -383,7 +383,7 @@ private bool ShouldGoToLunch(Citizen.AgeGroup citizenAge)
}

float currentHour = TimeInfo.CurrentHour;
if (currentHour >= Config.LunchBegin && currentHour <= Config.LunchEnd)
if (!IsBadWeather(citizenId) && currentHour >= Config.LunchBegin && currentHour <= Config.LunchEnd)
{
return Random.ShouldOccur(Config.LunchQuota);
}
Expand Down
15 changes: 9 additions & 6 deletions src/RealTime/CustomAI/RealTimeResidentAI.Visit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ private void ReturnFromVisit(

private bool CitizenGoesShopping(TAI instance, uint citizenId, ref TCitizen citizen, bool isVirtual)
{
if (!CitizenProxy.HasFlags(ref citizen, Citizen.Flags.NeedGoods))
if (!CitizenProxy.HasFlags(ref citizen, Citizen.Flags.NeedGoods) || IsBadWeather(citizenId))
{
return false;
}
Expand All @@ -181,8 +181,9 @@ private bool CitizenGoesShopping(TAI instance, uint citizenId, ref TCitizen citi
{
if (Random.ShouldOccur(GetGoOutChance(CitizenProxy.GetAge(ref citizen))))
{
Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, isVirtual)} wanna go shopping at night");
ushort localVisitPlace = MoveToCommercialBuilding(instance, citizenId, ref citizen, LocalSearchDistance, isVirtual);
Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, isVirtual)} wanna go shopping at night, trying local shop '{localVisitPlace}'");
Log.DebugIf(localVisitPlace != 0, $"Citizen {citizenId} is going shopping at night to a local shop {localVisitPlace}");
return localVisitPlace > 0;
}

Expand All @@ -196,8 +197,9 @@ private bool CitizenGoesShopping(TAI instance, uint citizenId, ref TCitizen citi

if (Random.ShouldOccur(Config.LocalBuildingSearchQuota))
{
Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, isVirtual)} wanna go shopping");
localVisitPlace = MoveToCommercialBuilding(instance, citizenId, ref citizen, LocalSearchDistance, isVirtual);
Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, isVirtual)} wanna go shopping, tries a local shop '{localVisitPlace}'");
Log.DebugIf(localVisitPlace != 0, $"Citizen {citizenId} is going shopping to a local shop {localVisitPlace}");
}

if (localVisitPlace == 0)
Expand All @@ -220,7 +222,7 @@ private bool CitizenGoesShopping(TAI instance, uint citizenId, ref TCitizen citi

private bool CitizenGoesToEvent(TAI instance, uint citizenId, ref TCitizen citizen, bool isVirtual)
{
if (!Random.ShouldOccur(GetGoOutChance(CitizenProxy.GetAge(ref citizen))))
if (!Random.ShouldOccur(GetGoOutChance(CitizenProxy.GetAge(ref citizen))) || IsBadWeather(citizenId))
{
return false;
}
Expand All @@ -237,7 +239,7 @@ private bool CitizenGoesToEvent(TAI instance, uint citizenId, ref TCitizen citiz
private bool CitizenGoesRelaxing(TAI instance, uint citizenId, ref TCitizen citizen, bool isVirtual)
{
Citizen.AgeGroup citizenAge = CitizenProxy.GetAge(ref citizen);
if (!Random.ShouldOccur(GetGoOutChance(citizenAge)))
if (!Random.ShouldOccur(GetGoOutChance(citizenAge)) || IsBadWeather(citizenId))
{
return false;
}
Expand All @@ -250,8 +252,9 @@ private bool CitizenGoesRelaxing(TAI instance, uint citizenId, ref TCitizen citi

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

Expand Down
17 changes: 14 additions & 3 deletions src/RealTime/CustomAI/RealTimeTouristAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,19 @@ private void ProcessMoving(TAI instance, uint citizenId, ref TCitizen citizen)
return;
}

bool badWeather = IsBadWeather(citizenId);
if (CitizenMgr.InstanceHasFlags(instanceId, CitizenInstance.Flags.TargetIsNode | CitizenInstance.Flags.OnTour, true))
{
Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen, false)} exits the guided tour.");
FindRandomVisitPlace(instance, citizenId, ref citizen, TouristDoNothingProbability, 0, false);
if (!badWeather)
{
FindRandomVisitPlace(instance, citizenId, ref citizen, TouristDoNothingProbability, 0, false);
}
}

if (badWeather)
{
FindHotel(instance, citizenId, ref citizen, false);
}
}

Expand Down Expand Up @@ -140,7 +149,9 @@ private void ProcessVisit(TAI instance, uint citizenId, ref TCitizen citizen, bo
return;
}

if (Random.ShouldOccur(TouristEventChance) && AttendUpcomingEvent(citizenId, ref citizen, out ushort eventBuilding))
if (Random.ShouldOccur(TouristEventChance)
&& !IsBadWeather(citizenId)
&& AttendUpcomingEvent(citizenId, ref citizen, out ushort eventBuilding))
{
StartMovingToVisitBuilding(instance, citizenId, ref citizen, CitizenProxy.GetCurrentBuilding(ref citizen), eventBuilding, isVirtual);
Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen, isVirtual)} attending an event at {eventBuilding}");
Expand Down Expand Up @@ -180,7 +191,7 @@ private void FindRandomVisitPlace(TAI instance, uint citizenId, ref TCitizen cit
return;
}

if (!Random.ShouldOccur(GetGoOutChance(CitizenProxy.GetAge(ref citizen))))
if (!Random.ShouldOccur(GetGoOutChance(CitizenProxy.GetAge(ref citizen))) || IsBadWeather(citizenId))
{
FindHotel(instance, citizenId, ref citizen, isVirtual);
return;
Expand Down
12 changes: 12 additions & 0 deletions src/RealTime/Simulation/SimulationHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ public sealed class SimulationHandler : ThreadingExtensionBase
/// <summary>Gets or sets the time adjustment simulation class instance.</summary>
internal static TimeAdjustment TimeAdjustment { get; set; }

/// <summary>Gets or sets the weather information class instance.</summary>
internal static WeatherInfo WeatherInfo { get; set; }

/// <summary>
/// Called before each game simulation tick. A tick contains multiple frames.
/// Performs the dispatching for this simulation phase.
/// </summary>
public override void OnBeforeSimulationTick()
{
WeatherInfo?.Update();
}

/// <summary>
/// Called after each game simulation tick. A tick contains multiple frames.
/// Performs the dispatching for this simulation phase.
Expand Down

0 comments on commit 879caec

Please sign in to comment.