Add unattended campfire risk state
This commit is contained in:
@@ -140,6 +140,7 @@ void AAgrarianCampfire::Tick(float DeltaSeconds)
|
||||
CookingProgressSeconds = FMath::Min(CookingSecondsRequired, CookingProgressSeconds + DeltaSeconds);
|
||||
}
|
||||
|
||||
UpdateFireRisk(DeltaSeconds);
|
||||
WarmNearbyCharacters(DeltaSeconds);
|
||||
}
|
||||
}
|
||||
@@ -152,6 +153,11 @@ void AAgrarianCampfire::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& Ou
|
||||
DOREPLIFETIME(AAgrarianCampfire, bCookingPlaceholderEnabled);
|
||||
DOREPLIFETIME(AAgrarianCampfire, CookingSecondsRequired);
|
||||
DOREPLIFETIME(AAgrarianCampfire, CookingProgressSeconds);
|
||||
DOREPLIFETIME(AAgrarianCampfire, FireRiskScore);
|
||||
DOREPLIFETIME(AAgrarianCampfire, LitDurationSeconds);
|
||||
DOREPLIFETIME(AAgrarianCampfire, SecondsSinceMaintenance);
|
||||
DOREPLIFETIME(AAgrarianCampfire, bFireAreaCleared);
|
||||
DOREPLIFETIME(AAgrarianCampfire, bFireContained);
|
||||
}
|
||||
|
||||
FText AAgrarianCampfire::GetInteractionText_Implementation(const AAgrarianGameCharacter* Interactor) const
|
||||
@@ -190,6 +196,11 @@ void AAgrarianCampfire::CapturePersistentState_Implementation(UAgrarianPersisten
|
||||
PersistentComponent->NumberState.Add(TEXT("cooking_placeholder_enabled"), bCookingPlaceholderEnabled ? 1.0f : 0.0f);
|
||||
PersistentComponent->NumberState.Add(TEXT("cooking_seconds_required"), CookingSecondsRequired);
|
||||
PersistentComponent->NumberState.Add(TEXT("cooking_progress_seconds"), CookingProgressSeconds);
|
||||
PersistentComponent->NumberState.Add(TEXT("fire_risk_score"), FireRiskScore);
|
||||
PersistentComponent->NumberState.Add(TEXT("lit_duration_seconds"), LitDurationSeconds);
|
||||
PersistentComponent->NumberState.Add(TEXT("seconds_since_maintenance"), SecondsSinceMaintenance);
|
||||
PersistentComponent->NumberState.Add(TEXT("fire_area_cleared"), bFireAreaCleared ? 1.0f : 0.0f);
|
||||
PersistentComponent->NumberState.Add(TEXT("fire_contained"), bFireContained ? 1.0f : 0.0f);
|
||||
}
|
||||
|
||||
void AAgrarianCampfire::ApplyPersistentState_Implementation(UAgrarianPersistentActorComponent* PersistentComponent)
|
||||
@@ -204,6 +215,11 @@ void AAgrarianCampfire::ApplyPersistentState_Implementation(UAgrarianPersistentA
|
||||
const float* SavedCookingRequired = PersistentComponent->NumberState.Find(TEXT("cooking_seconds_required"));
|
||||
const float* SavedCookingProgress = PersistentComponent->NumberState.Find(TEXT("cooking_progress_seconds"));
|
||||
const float* SavedLit = PersistentComponent->NumberState.Find(TEXT("lit"));
|
||||
const float* SavedRiskScore = PersistentComponent->NumberState.Find(TEXT("fire_risk_score"));
|
||||
const float* SavedLitDuration = PersistentComponent->NumberState.Find(TEXT("lit_duration_seconds"));
|
||||
const float* SavedSecondsSinceMaintenance = PersistentComponent->NumberState.Find(TEXT("seconds_since_maintenance"));
|
||||
const float* SavedAreaCleared = PersistentComponent->NumberState.Find(TEXT("fire_area_cleared"));
|
||||
const float* SavedContained = PersistentComponent->NumberState.Find(TEXT("fire_contained"));
|
||||
|
||||
if (SavedFuelSeconds)
|
||||
{
|
||||
@@ -225,6 +241,31 @@ void AAgrarianCampfire::ApplyPersistentState_Implementation(UAgrarianPersistentA
|
||||
CookingProgressSeconds = FMath::Clamp(*SavedCookingProgress, 0.0f, CookingSecondsRequired);
|
||||
}
|
||||
|
||||
if (SavedRiskScore)
|
||||
{
|
||||
FireRiskScore = FMath::Clamp(*SavedRiskScore, 0.0f, 100.0f);
|
||||
}
|
||||
|
||||
if (SavedLitDuration)
|
||||
{
|
||||
LitDurationSeconds = FMath::Max(0.0f, *SavedLitDuration);
|
||||
}
|
||||
|
||||
if (SavedSecondsSinceMaintenance)
|
||||
{
|
||||
SecondsSinceMaintenance = FMath::Max(0.0f, *SavedSecondsSinceMaintenance);
|
||||
}
|
||||
|
||||
if (SavedAreaCleared)
|
||||
{
|
||||
bFireAreaCleared = *SavedAreaCleared > 0.5f;
|
||||
}
|
||||
|
||||
if (SavedContained)
|
||||
{
|
||||
bFireContained = *SavedContained > 0.5f;
|
||||
}
|
||||
|
||||
SetLit(SavedLit && *SavedLit > 0.5f && FuelSeconds > 0.0f);
|
||||
}
|
||||
|
||||
@@ -249,10 +290,39 @@ void AAgrarianCampfire::Extinguish()
|
||||
if (HasAuthority())
|
||||
{
|
||||
FuelSeconds = 0.0f;
|
||||
FireRiskScore = 0.0f;
|
||||
LitDurationSeconds = 0.0f;
|
||||
SecondsSinceMaintenance = 0.0f;
|
||||
SetLit(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AAgrarianCampfire::MaintainFire(bool bClearArea, bool bContainFire)
|
||||
{
|
||||
if (!HasAuthority())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SecondsSinceMaintenance = 0.0f;
|
||||
if (bClearArea)
|
||||
{
|
||||
bFireAreaCleared = true;
|
||||
}
|
||||
if (bContainFire)
|
||||
{
|
||||
bFireContained = true;
|
||||
}
|
||||
|
||||
const float RiskReduction = (bFireAreaCleared ? 12.0f : 4.0f) + (bFireContained ? 12.0f : 4.0f);
|
||||
FireRiskScore = FMath::Clamp(FireRiskScore - RiskReduction, 0.0f, 100.0f);
|
||||
}
|
||||
|
||||
float AAgrarianCampfire::GetFireRiskRatio() const
|
||||
{
|
||||
return FMath::Clamp(FireRiskScore / 100.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
bool AAgrarianCampfire::CanCook() const
|
||||
{
|
||||
return bLit && bCookingPlaceholderEnabled && CookingSecondsRequired > 0.0f;
|
||||
@@ -328,6 +398,10 @@ void AAgrarianCampfire::SetLit(bool bNewLit)
|
||||
if (bLit != bNewLit)
|
||||
{
|
||||
bLit = bNewLit;
|
||||
if (bLit)
|
||||
{
|
||||
SecondsSinceMaintenance = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (HasAuthority() && bChanged)
|
||||
@@ -397,3 +471,49 @@ void AAgrarianCampfire::WarmNearbyCharacters(float DeltaSeconds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AAgrarianCampfire::UpdateFireRisk(float DeltaSeconds)
|
||||
{
|
||||
if (!HasAuthority() || !bLit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LitDurationSeconds += DeltaSeconds;
|
||||
SecondsSinceMaintenance += DeltaSeconds;
|
||||
|
||||
const float RiskGrowth = GetFireRiskGrowthPerSecond();
|
||||
FireRiskScore = FMath::Clamp(FireRiskScore + (RiskGrowth * DeltaSeconds), 0.0f, 100.0f);
|
||||
}
|
||||
|
||||
float AAgrarianCampfire::GetFireRiskGrowthPerSecond() const
|
||||
{
|
||||
float RiskGrowth = 0.0f;
|
||||
|
||||
if (SecondsSinceMaintenance >= UnmaintainedRiskDelaySeconds)
|
||||
{
|
||||
RiskGrowth += PoorMaintenanceRiskPerSecond;
|
||||
}
|
||||
|
||||
if (FuelSeconds >= HighFuelRiskThresholdSeconds)
|
||||
{
|
||||
RiskGrowth += HighFuelRiskPerSecond;
|
||||
}
|
||||
|
||||
if (bFireAreaCleared)
|
||||
{
|
||||
RiskGrowth *= FMath::Clamp(ClearedAreaRiskMultiplier, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
if (bFireContained)
|
||||
{
|
||||
RiskGrowth *= FMath::Clamp(ContainedFireRiskMultiplier, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
if (IsWetWeatherActive())
|
||||
{
|
||||
RiskGrowth *= 0.25f;
|
||||
}
|
||||
|
||||
return FMath::Max(0.0f, RiskGrowth);
|
||||
}
|
||||
|
||||
@@ -81,6 +81,39 @@ public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Cooking", meta = (ClampMin = "0"))
|
||||
float CookingProgressSeconds = 0.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0", ClampMax = "100"))
|
||||
float FireRiskScore = 0.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0"))
|
||||
float LitDurationSeconds = 0.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0"))
|
||||
float SecondsSinceMaintenance = 0.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Risk")
|
||||
bool bFireAreaCleared = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Risk")
|
||||
bool bFireContained = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0"))
|
||||
float UnmaintainedRiskDelaySeconds = 120.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0"))
|
||||
float PoorMaintenanceRiskPerSecond = 0.055f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0"))
|
||||
float HighFuelRiskThresholdSeconds = 180.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0"))
|
||||
float HighFuelRiskPerSecond = 0.025f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0", ClampMax = "1"))
|
||||
float ClearedAreaRiskMultiplier = 0.4f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Risk", meta = (ClampMin = "0", ClampMax = "1"))
|
||||
float ContainedFireRiskMultiplier = 0.35f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Weather", meta = (ClampMin = "1"))
|
||||
float RainFuelDrainMultiplier = 1.5f;
|
||||
|
||||
@@ -114,6 +147,12 @@ public:
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire")
|
||||
void Extinguish();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire|Risk")
|
||||
void MaintainFire(bool bClearArea, bool bContainFire);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Agrarian|Fire|Risk")
|
||||
float GetFireRiskRatio() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Agrarian|Fire|Cooking")
|
||||
bool CanCook() const;
|
||||
|
||||
@@ -137,4 +176,6 @@ protected:
|
||||
void SetLit(bool bNewLit);
|
||||
void UpdateVisualState();
|
||||
void WarmNearbyCharacters(float DeltaSeconds);
|
||||
void UpdateFireRisk(float DeltaSeconds);
|
||||
float GetFireRiskGrowthPerSecond() const;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user