Add campfire extinguish logic

This commit is contained in:
2026-05-17 18:33:00 -07:00
parent 70eb22d716
commit c61b226f47
5 changed files with 78 additions and 7 deletions
+3 -1
View File
@@ -582,7 +582,9 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe
- [x] Create fire actor. - [x] Create fire actor.
- [x] Add fuel amount. - [x] Add fuel amount.
- [x] Add ignition interaction. - [x] Add ignition interaction.
- [ ] Add extinguish logic. - [x] Add extinguish logic. Added native campfire extinguish support that
clears fuel, turns off replicated lit state, and reuses the fire visual
update path used by natural fuel depletion.
- [x] Add warmth radius. - [x] Add warmth radius.
- [x] Add light source. - [x] Add light source.
- [ ] Add cooking placeholder if needed. - [ ] Add cooking placeholder if needed.
+4
View File
@@ -288,6 +288,10 @@ controller is silent until loops are assigned; placeholder or final audio can be
added by setting the exposed sound properties on the placed controller or a added by setting the exposed sound properties on the placed controller or a
Blueprint child. Blueprint child.
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.
The first real-weather adapter is `UAgrarianWeatherProviderSubsystem`. It uses The first real-weather adapter is `UAgrarianWeatherProviderSubsystem`. It uses
Open-Meteo forecast requests keyed by tile center latitude/longitude, parses the Open-Meteo forecast requests keyed by tile center latitude/longitude, parses the
current temperature, daily low/high, precipitation, wind, humidity, cloud cover, current temperature, daily low/high, precipitation, wind, humidity, cloud cover,
+42
View File
@@ -0,0 +1,42 @@
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
EXPECTED = {
ROOT / "Source" / "AgrarianGame" / "AgrarianCampfire.h": [
"void Extinguish();",
"void SetLit(bool bNewLit);",
],
ROOT / "Source" / "AgrarianGame" / "AgrarianCampfire.cpp": [
"void AAgrarianCampfire::Extinguish()",
"FuelSeconds = 0.0f;",
"SetLit(false);",
"void AAgrarianCampfire::SetLit(bool bNewLit)",
"UpdateVisualState();",
],
ROOT / "Docs" / "TechnicalDesignDocument.md": [
"Campfires expose native extinguish logic",
],
ROOT / "AGRARIAN_DEVELOPMENT_ROADMAP.md": [
"- [x] Add extinguish logic.",
],
}
def main():
missing = []
for path, snippets in EXPECTED.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 RuntimeError("Fire extinguish verification failed: " + "; ".join(missing))
print("PASS: campfire extinguish logic is implemented and documented.")
if __name__ == "__main__":
main()
+24 -5
View File
@@ -33,8 +33,7 @@ void AAgrarianCampfire::Tick(float DeltaSeconds)
FuelSeconds = FMath::Max(0.0f, FuelSeconds - DeltaSeconds); FuelSeconds = FMath::Max(0.0f, FuelSeconds - DeltaSeconds);
if (FuelSeconds <= 0.0f) if (FuelSeconds <= 0.0f)
{ {
bLit = false; SetLit(false);
UpdateVisualState();
} }
WarmNearbyCharacters(DeltaSeconds); WarmNearbyCharacters(DeltaSeconds);
@@ -69,8 +68,6 @@ void AAgrarianCampfire::Interact_Implementation(AAgrarianGameCharacter* Interact
if (Inventory && Inventory->RemoveItem(TEXT("wood"), 1)) if (Inventory && Inventory->RemoveItem(TEXT("wood"), 1))
{ {
AddFuel(90.0f); AddFuel(90.0f);
bLit = true;
UpdateVisualState();
} }
} }
@@ -81,10 +78,22 @@ void AAgrarianCampfire::AddFuel(float Seconds)
FuelSeconds += FMath::Max(0.0f, Seconds); FuelSeconds += FMath::Max(0.0f, Seconds);
if (FuelSeconds > 0.0f) if (FuelSeconds > 0.0f)
{ {
bLit = true; SetLit(true);
} }
else
{
UpdateVisualState(); UpdateVisualState();
} }
}
}
void AAgrarianCampfire::Extinguish()
{
if (HasAuthority())
{
FuelSeconds = 0.0f;
SetLit(false);
}
} }
void AAgrarianCampfire::OnRep_FireState() void AAgrarianCampfire::OnRep_FireState()
@@ -92,6 +101,16 @@ void AAgrarianCampfire::OnRep_FireState()
UpdateVisualState(); UpdateVisualState();
} }
void AAgrarianCampfire::SetLit(bool bNewLit)
{
if (bLit != bNewLit)
{
bLit = bNewLit;
}
UpdateVisualState();
}
void AAgrarianCampfire::UpdateVisualState() void AAgrarianCampfire::UpdateVisualState()
{ {
if (FireLight) if (FireLight)
+4
View File
@@ -46,10 +46,14 @@ public:
UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire") UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire")
void AddFuel(float Seconds); void AddFuel(float Seconds);
UFUNCTION(BlueprintCallable, Category = "Agrarian|Fire")
void Extinguish();
protected: protected:
UFUNCTION() UFUNCTION()
void OnRep_FireState(); void OnRep_FireState();
void SetLit(bool bNewLit);
void UpdateVisualState(); void UpdateVisualState();
void WarmNearbyCharacters(float DeltaSeconds); void WarmNearbyCharacters(float DeltaSeconds);
}; };