Persist active fire spread state
This commit is contained in:
@@ -843,7 +843,7 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe
|
||||
- [x] Add server-authoritative fire spread rules for grass, brush, trees, shelters, and other burnable actors, including fuel, distance, wind, weather, and suppression hooks. Added replicated grass, forest, and structure fire intensities plus active spread radius that grow only on the server from nearby fuel, ignition distance, wind/weather, and a suppression-pressure hook for later rain, carried water, dirt/sand, firebreaks, and tools.
|
||||
- [x] Add fire maintenance gameplay so watched, cleared, contained, or extinguished fires are safe, while neglected fires can become dangerous. Updated lit campfire interaction to maintain the fire, added watch, clear-area, and contain-fire hooks, and made maintenance reduce campfire, vegetation, forest, and structure ignition risks while extinguishing resets active risk state.
|
||||
- [x] Add fire suppression hooks for rain, water carrying, dirt/sand, cleared firebreaks, and future firefighting tools. Added shared server-side suppression hooks plus water, dirt/sand, firebreak, and tool wrappers that raise suppression pressure, reduce ignition risks, reduce active fire intensity, shrink spread radius, and let rain/water drain fuel.
|
||||
- [ ] Persist active grass, forest, and structure fires across save/load without corrupting world state.
|
||||
- [x] Persist active grass, forest, and structure fires across save/load without corrupting world state. Extended campfire persistence coverage for ignition flags, ignition risk scores, active grass/forest/structure fire intensities, spread radius, and suppression pressure so save/load recovery preserves active and partially suppressed fire state.
|
||||
- [ ] Add QA coverage for safe campfires, unsafe campfires, vegetation spread, shelter ignition, suppression, and save/load recovery.
|
||||
- [ ] Add weather sounds.
|
||||
- [ ] Add wildlife sounds.
|
||||
|
||||
@@ -384,6 +384,13 @@ shrinks spread radius, and lets water/rain also drain fuel. Wet weather
|
||||
contributes passive suppression pressure so rain and storms naturally slow
|
||||
dangerous fires before later UI and inventory actions call the same hooks.
|
||||
|
||||
Active grass, forest, and structure fire state persists with campfires through
|
||||
the existing `UAgrarianPersistentActorComponent` provider path. Save records now
|
||||
carry ignition flags, ignition risk scores, fire intensities, spread radius, and
|
||||
suppression pressure so save/load recovery can restore active or partially
|
||||
suppressed fires without resetting the world to a safe state or corrupting the
|
||||
campfire's fuel, cooking, weather, and maintenance state.
|
||||
|
||||
Campfires expose native extinguish logic through `AAgrarianCampfire::Extinguish`.
|
||||
Extinguishing clears remaining fuel, turns off replicated lit state, and reuses
|
||||
the same visual update path as natural fuel depletion.
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Verify active grass, forest, and structure fire state persists."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
FIRE_CPP = ROOT / "Source" / "AgrarianGame" / "AgrarianCampfire.cpp"
|
||||
TDD = ROOT / "Docs" / "TechnicalDesignDocument.md"
|
||||
ROADMAP = ROOT / "AGRARIAN_DEVELOPMENT_ROADMAP.md"
|
||||
|
||||
PERSISTED_KEYS = [
|
||||
"grass_ignition_risk_score",
|
||||
"forest_ignition_risk_score",
|
||||
"structure_ignition_risk_score",
|
||||
"grass_or_brush_ignited",
|
||||
"forest_fuel_ignited",
|
||||
"structure_ignited",
|
||||
"grass_fire_intensity",
|
||||
"forest_fire_intensity",
|
||||
"structure_fire_intensity",
|
||||
"active_fire_spread_radius",
|
||||
"fire_suppression_pressure",
|
||||
]
|
||||
|
||||
|
||||
def require(condition: bool, message: str) -> None:
|
||||
if not condition:
|
||||
raise SystemExit(f"FAILED: {message}")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
fire_cpp = FIRE_CPP.read_text(encoding="utf-8")
|
||||
tdd = TDD.read_text(encoding="utf-8")
|
||||
roadmap = ROADMAP.read_text(encoding="utf-8")
|
||||
|
||||
for key in PERSISTED_KEYS:
|
||||
require(
|
||||
f'NumberState.Add(TEXT("{key}")' in fire_cpp,
|
||||
f"campfire capture missing persisted key {key}",
|
||||
)
|
||||
require(
|
||||
f'NumberState.Find(TEXT("{key}")' in fire_cpp,
|
||||
f"campfire apply missing persisted key {key}",
|
||||
)
|
||||
|
||||
for token in [
|
||||
"Active grass, forest, and structure fire state persists",
|
||||
"ignition flags",
|
||||
"fire intensities",
|
||||
"spread radius",
|
||||
"suppression pressure",
|
||||
]:
|
||||
require(token in tdd, f"technical design document missing {token!r}")
|
||||
|
||||
require(
|
||||
"[x] Persist active grass, forest, and structure fires across save/load" in roadmap,
|
||||
"roadmap item is not checked off",
|
||||
)
|
||||
|
||||
print("OK: active fire state persists across save/load.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -231,6 +231,7 @@ void AAgrarianCampfire::CapturePersistentState_Implementation(UAgrarianPersisten
|
||||
PersistentComponent->NumberState.Add(TEXT("forest_fire_intensity"), ForestFireIntensity);
|
||||
PersistentComponent->NumberState.Add(TEXT("structure_fire_intensity"), StructureFireIntensity);
|
||||
PersistentComponent->NumberState.Add(TEXT("active_fire_spread_radius"), ActiveFireSpreadRadius);
|
||||
PersistentComponent->NumberState.Add(TEXT("fire_suppression_pressure"), FireSuppressionPressure);
|
||||
}
|
||||
|
||||
void AAgrarianCampfire::ApplyPersistentState_Implementation(UAgrarianPersistentActorComponent* PersistentComponent)
|
||||
@@ -260,6 +261,7 @@ void AAgrarianCampfire::ApplyPersistentState_Implementation(UAgrarianPersistentA
|
||||
const float* SavedForestFireIntensity = PersistentComponent->NumberState.Find(TEXT("forest_fire_intensity"));
|
||||
const float* SavedStructureFireIntensity = PersistentComponent->NumberState.Find(TEXT("structure_fire_intensity"));
|
||||
const float* SavedActiveFireSpreadRadius = PersistentComponent->NumberState.Find(TEXT("active_fire_spread_radius"));
|
||||
const float* SavedFireSuppressionPressure = PersistentComponent->NumberState.Find(TEXT("fire_suppression_pressure"));
|
||||
|
||||
if (SavedFuelSeconds)
|
||||
{
|
||||
@@ -356,6 +358,11 @@ void AAgrarianCampfire::ApplyPersistentState_Implementation(UAgrarianPersistentA
|
||||
ActiveFireSpreadRadius = FMath::Clamp(*SavedActiveFireSpreadRadius, 0.0f, MaxFireSpreadRadius);
|
||||
}
|
||||
|
||||
if (SavedFireSuppressionPressure)
|
||||
{
|
||||
FireSuppressionPressure = FMath::Clamp(*SavedFireSuppressionPressure, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
SetLit(SavedLit && *SavedLit > 0.5f && FuelSeconds > 0.0f);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user