Add unattended campfire risk state
This commit is contained in:
@@ -837,7 +837,7 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe
|
|||||||
- [x] Add footstep placeholders. Added native player-character footstep hooks with assignable walk, sprint, crouch, and prone sound slots plus movement-state cadence, keeping the MVP silent until placeholder or final surface-aware audio assets are assigned.
|
- [x] Add footstep placeholders. Added native player-character footstep hooks with assignable walk, sprint, crouch, and prone sound slots plus movement-state cadence, keeping the MVP silent until placeholder or final surface-aware audio assets are assigned.
|
||||||
- [x] Add gathering sounds. Added spatialized resource-node gathering audio hooks with assignable normal/depleted gathering cues and a server-authoritative multicast trigger after successful harvests, keeping multiplayer clients aligned while remaining silent until audio assets are assigned.
|
- [x] Add gathering sounds. Added spatialized resource-node gathering audio hooks with assignable normal/depleted gathering cues and a server-authoritative multicast trigger after successful harvests, keeping multiplayer clients aligned while remaining silent until audio assets are assigned.
|
||||||
- [x] Add fire sounds. Added campfire loop, ignition, and extinguish audio hooks with spatialized components, replicated lit-state loop control, and server-triggered multicast event cues so fire audio follows the authoritative campfire state once assets are assigned.
|
- [x] Add fire sounds. Added campfire loop, ignition, and extinguish audio hooks with spatialized components, replicated lit-state loop control, and server-triggered multicast event cues so fire audio follows the authoritative campfire state once assets are assigned.
|
||||||
- [ ] Add unattended and poorly maintained fire risk for campfires and other open-flame sources.
|
- [x] Add unattended and poorly maintained fire risk for campfires and other open-flame sources. Added server-side campfire risk state for lit duration, seconds since maintenance, cleared area, containment, high fuel, wet weather mitigation, and a replicated `FireRiskScore` that later ignition/spread systems can consume.
|
||||||
- [ ] Add grass and forest ignition checks from irresponsible fire placement, wind/weather, dry fuel, nearby vegetation, and burn duration.
|
- [ ] Add grass and forest ignition checks from irresponsible fire placement, wind/weather, dry fuel, nearby vegetation, and burn duration.
|
||||||
- [ ] Add shelter/structure ignition risk when fires are placed too close to primitive shelters, wood piles, flammable crafting stations, or settlement objects.
|
- [ ] Add shelter/structure ignition risk when fires are placed too close to primitive shelters, wood piles, flammable crafting stations, or settlement objects.
|
||||||
- [ ] Add server-authoritative fire spread rules for grass, brush, trees, shelters, and other burnable actors, including fuel, distance, wind, weather, and suppression hooks.
|
- [ ] Add server-authoritative fire spread rules for grass, brush, trees, shelters, and other burnable actors, including fuel, distance, wind, weather, and suppression hooks.
|
||||||
|
|||||||
@@ -337,6 +337,14 @@ or stop the loop on clients, while the authoritative server multicasts ignition
|
|||||||
and extinguish events so the audio follows the same state changes as light,
|
and extinguish events so the audio follows the same state changes as light,
|
||||||
smoke, warmth, fuel, and persistence.
|
smoke, warmth, fuel, and persistence.
|
||||||
|
|
||||||
|
Campfires now track unattended and poorly maintained fire risk on the server.
|
||||||
|
`AAgrarianCampfire` records lit duration, seconds since maintenance, whether the
|
||||||
|
area has been cleared, whether the fire is contained, and a replicated
|
||||||
|
`FireRiskScore`. Risk grows after a fire has been left unattended, grows faster
|
||||||
|
when excessive fuel is burning, and is reduced by maintenance, cleared area,
|
||||||
|
containment, and wet weather. This first risk layer does not yet ignite nearby
|
||||||
|
vegetation or structures; later 0.1.P items consume the replicated risk score.
|
||||||
|
|
||||||
Campfires expose native extinguish logic through `AAgrarianCampfire::Extinguish`.
|
Campfires expose native extinguish logic through `AAgrarianCampfire::Extinguish`.
|
||||||
Extinguishing clears remaining fuel, turns off replicated lit state, and reuses
|
Extinguishing clears remaining fuel, turns off replicated lit state, and reuses
|
||||||
the same visual update path as natural fuel depletion.
|
the same visual update path as natural fuel depletion.
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Verify unattended and poorly maintained campfire risk state exists."""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
FIRE_H = ROOT / "Source" / "AgrarianGame" / "AgrarianCampfire.h"
|
||||||
|
FIRE_CPP = ROOT / "Source" / "AgrarianGame" / "AgrarianCampfire.cpp"
|
||||||
|
TDD = ROOT / "Docs" / "TechnicalDesignDocument.md"
|
||||||
|
ROADMAP = ROOT / "AGRARIAN_DEVELOPMENT_ROADMAP.md"
|
||||||
|
|
||||||
|
REQUIRED = {
|
||||||
|
FIRE_H: [
|
||||||
|
"float FireRiskScore",
|
||||||
|
"float LitDurationSeconds",
|
||||||
|
"float SecondsSinceMaintenance",
|
||||||
|
"bool bFireAreaCleared",
|
||||||
|
"bool bFireContained",
|
||||||
|
"float UnmaintainedRiskDelaySeconds",
|
||||||
|
"float PoorMaintenanceRiskPerSecond",
|
||||||
|
"float HighFuelRiskThresholdSeconds",
|
||||||
|
"void MaintainFire(bool bClearArea, bool bContainFire);",
|
||||||
|
"float GetFireRiskRatio() const;",
|
||||||
|
"void UpdateFireRisk(float DeltaSeconds);",
|
||||||
|
"float GetFireRiskGrowthPerSecond() const;",
|
||||||
|
],
|
||||||
|
FIRE_CPP: [
|
||||||
|
"DOREPLIFETIME(AAgrarianCampfire, FireRiskScore)",
|
||||||
|
"DOREPLIFETIME(AAgrarianCampfire, LitDurationSeconds)",
|
||||||
|
"DOREPLIFETIME(AAgrarianCampfire, SecondsSinceMaintenance)",
|
||||||
|
"DOREPLIFETIME(AAgrarianCampfire, bFireAreaCleared)",
|
||||||
|
"DOREPLIFETIME(AAgrarianCampfire, bFireContained)",
|
||||||
|
"UpdateFireRisk(DeltaSeconds);",
|
||||||
|
"AAgrarianCampfire::MaintainFire",
|
||||||
|
"AAgrarianCampfire::GetFireRiskGrowthPerSecond",
|
||||||
|
"SecondsSinceMaintenance >= UnmaintainedRiskDelaySeconds",
|
||||||
|
"FuelSeconds >= HighFuelRiskThresholdSeconds",
|
||||||
|
"IsWetWeatherActive()",
|
||||||
|
"fire_risk_score",
|
||||||
|
"seconds_since_maintenance",
|
||||||
|
],
|
||||||
|
TDD: [
|
||||||
|
"unattended and poorly maintained fire risk",
|
||||||
|
"`FireRiskScore`",
|
||||||
|
"Risk grows after a fire has been left unattended",
|
||||||
|
],
|
||||||
|
ROADMAP: [
|
||||||
|
"[x] Add unattended and poorly maintained fire risk",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
missing = []
|
||||||
|
for path, snippets in REQUIRED.items():
|
||||||
|
text = path.read_text(encoding="utf-8")
|
||||||
|
for snippet in snippets:
|
||||||
|
if snippet not in text:
|
||||||
|
missing.append(f"{path.relative_to(ROOT)} missing {snippet!r}")
|
||||||
|
if missing:
|
||||||
|
raise SystemExit("FAILED: " + "; ".join(missing))
|
||||||
|
print("OK: unattended campfire risk state is implemented and replicated.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -140,6 +140,7 @@ void AAgrarianCampfire::Tick(float DeltaSeconds)
|
|||||||
CookingProgressSeconds = FMath::Min(CookingSecondsRequired, CookingProgressSeconds + DeltaSeconds);
|
CookingProgressSeconds = FMath::Min(CookingSecondsRequired, CookingProgressSeconds + DeltaSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateFireRisk(DeltaSeconds);
|
||||||
WarmNearbyCharacters(DeltaSeconds);
|
WarmNearbyCharacters(DeltaSeconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,6 +153,11 @@ void AAgrarianCampfire::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& Ou
|
|||||||
DOREPLIFETIME(AAgrarianCampfire, bCookingPlaceholderEnabled);
|
DOREPLIFETIME(AAgrarianCampfire, bCookingPlaceholderEnabled);
|
||||||
DOREPLIFETIME(AAgrarianCampfire, CookingSecondsRequired);
|
DOREPLIFETIME(AAgrarianCampfire, CookingSecondsRequired);
|
||||||
DOREPLIFETIME(AAgrarianCampfire, CookingProgressSeconds);
|
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
|
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_placeholder_enabled"), bCookingPlaceholderEnabled ? 1.0f : 0.0f);
|
||||||
PersistentComponent->NumberState.Add(TEXT("cooking_seconds_required"), CookingSecondsRequired);
|
PersistentComponent->NumberState.Add(TEXT("cooking_seconds_required"), CookingSecondsRequired);
|
||||||
PersistentComponent->NumberState.Add(TEXT("cooking_progress_seconds"), CookingProgressSeconds);
|
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)
|
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* SavedCookingRequired = PersistentComponent->NumberState.Find(TEXT("cooking_seconds_required"));
|
||||||
const float* SavedCookingProgress = PersistentComponent->NumberState.Find(TEXT("cooking_progress_seconds"));
|
const float* SavedCookingProgress = PersistentComponent->NumberState.Find(TEXT("cooking_progress_seconds"));
|
||||||
const float* SavedLit = PersistentComponent->NumberState.Find(TEXT("lit"));
|
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)
|
if (SavedFuelSeconds)
|
||||||
{
|
{
|
||||||
@@ -225,6 +241,31 @@ void AAgrarianCampfire::ApplyPersistentState_Implementation(UAgrarianPersistentA
|
|||||||
CookingProgressSeconds = FMath::Clamp(*SavedCookingProgress, 0.0f, CookingSecondsRequired);
|
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);
|
SetLit(SavedLit && *SavedLit > 0.5f && FuelSeconds > 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,10 +290,39 @@ void AAgrarianCampfire::Extinguish()
|
|||||||
if (HasAuthority())
|
if (HasAuthority())
|
||||||
{
|
{
|
||||||
FuelSeconds = 0.0f;
|
FuelSeconds = 0.0f;
|
||||||
|
FireRiskScore = 0.0f;
|
||||||
|
LitDurationSeconds = 0.0f;
|
||||||
|
SecondsSinceMaintenance = 0.0f;
|
||||||
SetLit(false);
|
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
|
bool AAgrarianCampfire::CanCook() const
|
||||||
{
|
{
|
||||||
return bLit && bCookingPlaceholderEnabled && CookingSecondsRequired > 0.0f;
|
return bLit && bCookingPlaceholderEnabled && CookingSecondsRequired > 0.0f;
|
||||||
@@ -328,6 +398,10 @@ void AAgrarianCampfire::SetLit(bool bNewLit)
|
|||||||
if (bLit != bNewLit)
|
if (bLit != bNewLit)
|
||||||
{
|
{
|
||||||
bLit = bNewLit;
|
bLit = bNewLit;
|
||||||
|
if (bLit)
|
||||||
|
{
|
||||||
|
SecondsSinceMaintenance = 0.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasAuthority() && bChanged)
|
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"))
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Agrarian|Fire|Cooking", meta = (ClampMin = "0"))
|
||||||
float CookingProgressSeconds = 0.0f;
|
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"))
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Fire|Weather", meta = (ClampMin = "1"))
|
||||||
float RainFuelDrainMultiplier = 1.5f;
|
float RainFuelDrainMultiplier = 1.5f;
|
||||||
|
|
||||||
@@ -114,6 +147,12 @@ public:
|
|||||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire")
|
UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire")
|
||||||
void Extinguish();
|
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")
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Agrarian|Fire|Cooking")
|
||||||
bool CanCook() const;
|
bool CanCook() const;
|
||||||
|
|
||||||
@@ -137,4 +176,6 @@ protected:
|
|||||||
void SetLit(bool bNewLit);
|
void SetLit(bool bNewLit);
|
||||||
void UpdateVisualState();
|
void UpdateVisualState();
|
||||||
void WarmNearbyCharacters(float DeltaSeconds);
|
void WarmNearbyCharacters(float DeltaSeconds);
|
||||||
|
void UpdateFireRisk(float DeltaSeconds);
|
||||||
|
float GetFireRiskGrowthPerSecond() const;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user