Add MVP ambient biome audio hook

This commit is contained in:
2026-05-19 12:01:24 -07:00
parent c37d8d930c
commit fb658baff0
5 changed files with 89 additions and 12 deletions
+1 -1
View File
@@ -833,7 +833,7 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe
## 0.1.P MVP Audio And Atmosphere ## 0.1.P MVP Audio And Atmosphere
- [ ] Add ambient biome audio. - [x] Add ambient biome audio. Extended the placed `AAgrarianWeatherAudioController` so its ambient component explicitly owns a Ground Zero coastal-scrub biome loop slot with separate day/night volume targets, keeping the current MVP silent until placeholder or final audio assets are assigned while giving the map a real ambient audio attachment point.
- [ ] Add footstep placeholders. - [ ] Add footstep placeholders.
- [ ] Add gathering sounds. - [ ] Add gathering sounds.
- [ ] Add fire sounds. - [ ] Add fire sounds.
+13 -9
View File
@@ -302,15 +302,19 @@ the represented local day/night cycle and current weather without hard-coded
static light settings. The Ground Zero map setup script places this controller static light settings. The Ground Zero map setup script places this controller
and removes the earlier static demo sun/skylight/fog actors. and removes the earlier static demo sun/skylight/fog actors.
First-pass weather audio uses `AAgrarianWeatherAudioController`. The controller First-pass biome and weather audio uses `AAgrarianWeatherAudioController`. The
owns ambient, rain, wind, and storm audio components with assignable loop sound controller owns ambient, rain, wind, and storm audio components with assignable
slots. It reads replicated weather state, provider wind speed, provider cloud loop sound slots. The ambient component is explicitly the Ground Zero
data, and local night/day state, then fades component volumes so rain, wind, and coastal-scrub biome bed through `BiomeAmbientLoopSound`, with separate day and
storm cues follow the same authoritative weather mapping used by temperature and night volume targets so the map can carry wind, surf, insects, distant birds, or
lighting. The current MVP can ship without final sound assets because the other realistic low-level biome texture before final authored assets are
controller is silent until loops are assigned; placeholder or final audio can be available. It reads replicated weather state, provider wind speed, provider
added by setting the exposed sound properties on the placed controller or a cloud data, and local night/day state, then fades component volumes so rain,
Blueprint child. wind, and storm cues follow the same authoritative weather mapping used by
temperature and lighting. The current MVP can ship without final sound assets
because the 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 Blueprint child.
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
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/env python3
"""Verify the MVP ambient biome audio attachment point is wired."""
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
AUDIO_H = ROOT / "Source" / "AgrarianGame" / "AgrarianWeatherAudioController.h"
AUDIO_CPP = ROOT / "Source" / "AgrarianGame" / "AgrarianWeatherAudioController.cpp"
MAP_SETUP = ROOT / "Scripts" / "setup_ground_zero_demo_map.py"
TDD = ROOT / "Docs" / "TechnicalDesignDocument.md"
ROADMAP = ROOT / "AGRARIAN_DEVELOPMENT_ROADMAP.md"
REQUIRED = {
AUDIO_H: [
"TObjectPtr<USoundBase> BiomeAmbientLoopSound;",
"float BiomeAmbientDayVolume",
"float BiomeAmbientNightVolume",
"TObjectPtr<UAudioComponent> AmbientAudio;",
],
AUDIO_CPP: [
"BiomeAmbientLoopSound",
"AmbientAudio->SetSound(BiomeAmbientLoopSound)",
"FMath::Max(AmbientDayVolume, BiomeAmbientDayVolume)",
"FMath::Max(AmbientNightVolume, BiomeAmbientNightVolume)",
],
MAP_SETUP: [
"AGR_DemoWeatherAudioController",
"unreal.AgrarianWeatherAudioController",
],
TDD: [
"coastal-scrub biome bed",
"`BiomeAmbientLoopSound`",
"separate day and\nnight volume targets",
],
ROADMAP: [
"[x] Add ambient biome audio.",
],
}
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: ambient biome audio is wired through the placed weather audio controller.")
if __name__ == "__main__":
main()
@@ -83,7 +83,9 @@ void AAgrarianWeatherAudioController::RefreshWeatherAudio(float DeltaSeconds)
break; break;
} }
const float TargetAmbientVolume = GameState->IsNight() ? AmbientNightVolume : AmbientDayVolume; const float DayAmbient = FMath::Max(AmbientDayVolume, BiomeAmbientDayVolume);
const float NightAmbient = FMath::Max(AmbientNightVolume, BiomeAmbientNightVolume);
const float TargetAmbientVolume = GameState->IsNight() ? NightAmbient : DayAmbient;
const float InterpSpeed = FMath::Max(0.1f, VolumeInterpSpeed); const float InterpSpeed = FMath::Max(0.1f, VolumeInterpSpeed);
CurrentAmbientVolume = FMath::FInterpTo(CurrentAmbientVolume, TargetAmbientVolume, DeltaSeconds, InterpSpeed); CurrentAmbientVolume = FMath::FInterpTo(CurrentAmbientVolume, TargetAmbientVolume, DeltaSeconds, InterpSpeed);
CurrentRainVolume = FMath::FInterpTo(CurrentRainVolume, TargetRainVolume, DeltaSeconds, InterpSpeed); CurrentRainVolume = FMath::FInterpTo(CurrentRainVolume, TargetRainVolume, DeltaSeconds, InterpSpeed);
@@ -106,7 +108,11 @@ void AAgrarianWeatherAudioController::RefreshWeatherAudio(float DeltaSeconds)
void AAgrarianWeatherAudioController::AssignConfiguredSounds() void AAgrarianWeatherAudioController::AssignConfiguredSounds()
{ {
if (AmbientAudio && ClearAmbientSound) if (AmbientAudio && BiomeAmbientLoopSound)
{
AmbientAudio->SetSound(BiomeAmbientLoopSound);
}
else if (AmbientAudio && ClearAmbientSound)
{ {
AmbientAudio->SetSound(ClearAmbientSound); AmbientAudio->SetSound(ClearAmbientSound);
} }
@@ -40,6 +40,9 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather Audio") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather Audio")
TObjectPtr<USoundBase> ClearAmbientSound; TObjectPtr<USoundBase> ClearAmbientSound;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather Audio|Biome")
TObjectPtr<USoundBase> BiomeAmbientLoopSound;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather Audio") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather Audio")
TObjectPtr<USoundBase> RainLoopSound; TObjectPtr<USoundBase> RainLoopSound;
@@ -58,6 +61,12 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather Audio", meta = (ClampMin = "0.0", ClampMax = "1.0")) UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather Audio", meta = (ClampMin = "0.0", ClampMax = "1.0"))
float AmbientNightVolume = 0.22f; float AmbientNightVolume = 0.22f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather Audio|Biome", meta = (ClampMin = "0.0", ClampMax = "1.0"))
float BiomeAmbientDayVolume = 0.35f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather Audio|Biome", meta = (ClampMin = "0.0", ClampMax = "1.0"))
float BiomeAmbientNightVolume = 0.22f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather Audio", meta = (ClampMin = "0.0", ClampMax = "1.0")) UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Weather Audio", meta = (ClampMin = "0.0", ClampMax = "1.0"))
float MaxRainVolume = 0.8f; float MaxRainVolume = 0.8f;