Add regional temperature curve
This commit is contained in:
@@ -25,6 +25,16 @@ bool IsDayInRange(int32 DayOfYear, int32 StartDay, int32 EndDay, int32 DaysPerYe
|
||||
|
||||
return Day >= Start || Day <= End;
|
||||
}
|
||||
|
||||
float GetWrappedHourDelta(float FromHour, float ToHour)
|
||||
{
|
||||
float Delta = FMath::Fmod(ToHour - FromHour, 24.0f);
|
||||
if (Delta < 0.0f)
|
||||
{
|
||||
Delta += 24.0f;
|
||||
}
|
||||
return Delta;
|
||||
}
|
||||
}
|
||||
|
||||
AAgrarianGameState::AAgrarianGameState()
|
||||
@@ -82,6 +92,12 @@ void AAgrarianGameState::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& O
|
||||
DOREPLIFETIME(AAgrarianGameState, WorldHours);
|
||||
DOREPLIFETIME(AAgrarianGameState, Weather);
|
||||
DOREPLIFETIME(AAgrarianGameState, AmbientTemperatureC);
|
||||
DOREPLIFETIME(AAgrarianGameState, RegionalDailyLowTemperatureC);
|
||||
DOREPLIFETIME(AAgrarianGameState, RegionalDailyHighTemperatureC);
|
||||
DOREPLIFETIME(AAgrarianGameState, RegionalObservedTemperatureC);
|
||||
DOREPLIFETIME(AAgrarianGameState, ObservedTemperatureBlend);
|
||||
DOREPLIFETIME(AAgrarianGameState, bHasRegionalObservedTemperature);
|
||||
DOREPLIFETIME(AAgrarianGameState, RegionalWeatherSource);
|
||||
DOREPLIFETIME(AAgrarianGameState, DaysPerAgrarianYear);
|
||||
DOREPLIFETIME(AAgrarianGameState, ActiveSolarTileId);
|
||||
DOREPLIFETIME(AAgrarianGameState, ActiveTileLatitude);
|
||||
@@ -118,6 +134,56 @@ void AAgrarianGameState::SetWeather(EAgrarianWeatherType NewWeather)
|
||||
}
|
||||
}
|
||||
|
||||
void AAgrarianGameState::SetRegionalTemperatureProfile(float DailyLowTemperatureC, float DailyHighTemperatureC)
|
||||
{
|
||||
if (!HasAuthority())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RegionalDailyLowTemperatureC = FMath::Clamp(FMath::Min(DailyLowTemperatureC, DailyHighTemperatureC), -80.0f, 70.0f);
|
||||
RegionalDailyHighTemperatureC = FMath::Clamp(FMath::Max(DailyLowTemperatureC, DailyHighTemperatureC), -80.0f, 70.0f);
|
||||
UpdateAmbientTemperature();
|
||||
}
|
||||
|
||||
void AAgrarianGameState::SetRegionalObservedTemperature(float ObservedTemperatureC, float BlendWeight, const FString& WeatherSource)
|
||||
{
|
||||
if (!HasAuthority())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RegionalObservedTemperatureC = FMath::Clamp(ObservedTemperatureC, -80.0f, 70.0f);
|
||||
ObservedTemperatureBlend = FMath::Clamp(BlendWeight, 0.0f, 1.0f);
|
||||
bHasRegionalObservedTemperature = ObservedTemperatureBlend > 0.0f;
|
||||
RegionalWeatherSource = WeatherSource.IsEmpty() ? TEXT("server_weather_adapter") : WeatherSource;
|
||||
UpdateAmbientTemperature();
|
||||
}
|
||||
|
||||
float AAgrarianGameState::GetClearSkyTemperatureForHour(float HourOfDay) const
|
||||
{
|
||||
const float LowTemperature = FMath::Min(RegionalDailyLowTemperatureC, RegionalDailyHighTemperatureC);
|
||||
const float HighTemperature = FMath::Max(RegionalDailyLowTemperatureC, RegionalDailyHighTemperatureC);
|
||||
const float LowHour = bHasActiveTileSolarData ? SunriseHourLocal : 6.0f;
|
||||
const float HighHour = bHasActiveTileSolarData ? FMath::Fmod(SolarNoonHourLocal + 3.0f, 24.0f) : 14.0f;
|
||||
const float NormalizedHour = FMath::Fmod(HourOfDay, 24.0f) < 0.0f
|
||||
? FMath::Fmod(HourOfDay, 24.0f) + 24.0f
|
||||
: FMath::Fmod(HourOfDay, 24.0f);
|
||||
|
||||
const float RisingDuration = FMath::Max(0.1f, GetWrappedHourDelta(LowHour, HighHour));
|
||||
const float HoursSinceLow = GetWrappedHourDelta(LowHour, NormalizedHour);
|
||||
if (HoursSinceLow <= RisingDuration)
|
||||
{
|
||||
const float Alpha = 0.5f - (0.5f * FMath::Cos(PI * (HoursSinceLow / RisingDuration)));
|
||||
return FMath::Lerp(LowTemperature, HighTemperature, Alpha);
|
||||
}
|
||||
|
||||
const float CoolingDuration = FMath::Max(0.1f, 24.0f - RisingDuration);
|
||||
const float HoursSinceHigh = GetWrappedHourDelta(HighHour, NormalizedHour);
|
||||
const float Alpha = 0.5f - (0.5f * FMath::Cos(PI * (HoursSinceHigh / CoolingDuration)));
|
||||
return FMath::Lerp(HighTemperature, LowTemperature, Alpha);
|
||||
}
|
||||
|
||||
bool AAgrarianGameState::ConfigureActiveSolarTile(FName TileId, float Latitude, float Longitude, const FString& TimeZoneId, float UtcOffsetHours)
|
||||
{
|
||||
if (!HasAuthority() || TileId == NAME_None)
|
||||
@@ -380,14 +446,20 @@ void AAgrarianGameState::UpdateSolarTimes()
|
||||
|
||||
void AAgrarianGameState::UpdateAmbientTemperature()
|
||||
{
|
||||
const float WarmestHour = bHasActiveTileSolarData ? FMath::Fmod(SolarNoonHourLocal + 3.0f, 24.0f) : 14.0f;
|
||||
const float DayWarmth = FMath::Sin(((WorldHours - WarmestHour) / 24.0f) * 2.0f * PI + (PI * 0.5f)) * 8.0f;
|
||||
const float ClearSkyTemperatureC = GetClearSkyTemperatureForHour(WorldHours);
|
||||
const float DailyMeanTemperatureC = (RegionalDailyLowTemperatureC + RegionalDailyHighTemperatureC) * 0.5f;
|
||||
const float ObservedAnchoredTemperatureC = bHasRegionalObservedTemperature
|
||||
? RegionalObservedTemperatureC + (ClearSkyTemperatureC - DailyMeanTemperatureC)
|
||||
: ClearSkyTemperatureC;
|
||||
const float BaseTemperatureC = bHasRegionalObservedTemperature
|
||||
? FMath::Lerp(ClearSkyTemperatureC, ObservedAnchoredTemperatureC, ObservedTemperatureBlend)
|
||||
: ClearSkyTemperatureC;
|
||||
float WeatherModifier = 0.0f;
|
||||
|
||||
switch (Weather)
|
||||
{
|
||||
case EAgrarianWeatherType::Rain:
|
||||
WeatherModifier = -3.0f;
|
||||
WeatherModifier = -2.0f;
|
||||
break;
|
||||
case EAgrarianWeatherType::ColdWind:
|
||||
WeatherModifier = -8.0f;
|
||||
@@ -400,5 +472,5 @@ void AAgrarianGameState::UpdateAmbientTemperature()
|
||||
break;
|
||||
}
|
||||
|
||||
AmbientTemperatureC = 10.0f + DayWarmth + WeatherModifier;
|
||||
AmbientTemperatureC = FMath::Clamp(BaseTemperatureC + WeatherModifier, -80.0f, 70.0f);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,24 @@ public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World")
|
||||
float AmbientTemperatureC = 12.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Temperature")
|
||||
float RegionalDailyLowTemperatureC = 9.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Temperature")
|
||||
float RegionalDailyHighTemperatureC = 18.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Temperature")
|
||||
float RegionalObservedTemperatureC = 12.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Temperature", meta = (ClampMin = "0.0", ClampMax = "1.0"))
|
||||
float ObservedTemperatureBlend = 0.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Temperature")
|
||||
bool bHasRegionalObservedTemperature = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Temperature")
|
||||
FString RegionalWeatherSource = TEXT("deterministic_tile_curve");
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Replicated, Category = "Agrarian|World|Tile Solar")
|
||||
FName ActiveSolarTileId = TEXT("gz_us_ca_pacifica_utm10n_e544_n4160");
|
||||
|
||||
@@ -79,6 +97,15 @@ public:
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|World")
|
||||
void SetWeather(EAgrarianWeatherType NewWeather);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|World|Temperature")
|
||||
void SetRegionalTemperatureProfile(float DailyLowTemperatureC, float DailyHighTemperatureC);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|World|Temperature")
|
||||
void SetRegionalObservedTemperature(float ObservedTemperatureC, float BlendWeight, const FString& WeatherSource);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Agrarian|World|Temperature")
|
||||
float GetClearSkyTemperatureForHour(float HourOfDay) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|World|Tile Solar")
|
||||
bool ConfigureActiveSolarTile(FName TileId, float Latitude, float Longitude, const FString& TimeZoneId, float UtcOffsetHours);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user