// Copyright Pacificao. All Rights Reserved. #include "AgrarianWeatherAudioController.h" #include "AgrarianGameState.h" #include "Components/AudioComponent.h" #include "Components/SceneComponent.h" #include "Engine/World.h" AAgrarianWeatherAudioController::AAgrarianWeatherAudioController() { PrimaryActorTick.bCanEverTick = true; bReplicates = false; SceneRoot = CreateDefaultSubobject(TEXT("SceneRoot")); RootComponent = SceneRoot; AmbientAudio = CreateDefaultSubobject(TEXT("AmbientAudio")); AmbientAudio->SetupAttachment(SceneRoot); AmbientAudio->bAutoActivate = false; RainAudio = CreateDefaultSubobject(TEXT("RainAudio")); RainAudio->SetupAttachment(SceneRoot); RainAudio->bAutoActivate = false; WindAudio = CreateDefaultSubobject(TEXT("WindAudio")); WindAudio->SetupAttachment(SceneRoot); WindAudio->bAutoActivate = false; StormAudio = CreateDefaultSubobject(TEXT("StormAudio")); StormAudio->SetupAttachment(SceneRoot); StormAudio->bAutoActivate = false; } void AAgrarianWeatherAudioController::BeginPlay() { Super::BeginPlay(); AssignConfiguredSounds(); RefreshWeatherAudio(0.0f); } void AAgrarianWeatherAudioController::Tick(float DeltaSeconds) { Super::Tick(DeltaSeconds); RefreshWeatherAudio(DeltaSeconds); } void AAgrarianWeatherAudioController::RefreshWeatherAudio(float DeltaSeconds) { const UWorld* World = GetWorld(); const AAgrarianGameState* GameState = World ? World->GetGameState() : nullptr; if (!GameState) { return; } CurrentWeather = GameState->Weather; const float WindAlpha = GetProviderWindAlpha(GameState->ActiveWeatherInputs.WindSpeedKmh, GameState->ActiveWeatherInputs.bHasProviderData); float TargetRainVolume = 0.0f; float TargetWindVolume = WindAlpha * MaxWindVolume; float TargetStormVolume = 0.0f; switch (GameState->Weather) { case EAgrarianWeatherType::Rain: TargetRainVolume = MaxRainVolume; TargetWindVolume = FMath::Max(TargetWindVolume, MaxWindVolume * 0.25f); break; case EAgrarianWeatherType::ColdWind: TargetWindVolume = FMath::Max(TargetWindVolume, MaxWindVolume * 0.7f); break; case EAgrarianWeatherType::Storm: TargetRainVolume = MaxRainVolume; TargetWindVolume = MaxWindVolume; TargetStormVolume = MaxStormVolume; break; default: break; } const float TargetAmbientVolume = GameState->IsNight() ? AmbientNightVolume : AmbientDayVolume; const float InterpSpeed = FMath::Max(0.1f, VolumeInterpSpeed); CurrentAmbientVolume = FMath::FInterpTo(CurrentAmbientVolume, TargetAmbientVolume, DeltaSeconds, InterpSpeed); CurrentRainVolume = FMath::FInterpTo(CurrentRainVolume, TargetRainVolume, DeltaSeconds, InterpSpeed); CurrentWindVolume = FMath::FInterpTo(CurrentWindVolume, TargetWindVolume, DeltaSeconds, InterpSpeed); CurrentStormVolume = FMath::FInterpTo(CurrentStormVolume, TargetStormVolume, DeltaSeconds, InterpSpeed); if (DeltaSeconds <= 0.0f) { CurrentAmbientVolume = TargetAmbientVolume; CurrentRainVolume = TargetRainVolume; CurrentWindVolume = TargetWindVolume; CurrentStormVolume = TargetStormVolume; } ApplyComponentVolume(AmbientAudio, CurrentAmbientVolume); ApplyComponentVolume(RainAudio, CurrentRainVolume); ApplyComponentVolume(WindAudio, CurrentWindVolume); ApplyComponentVolume(StormAudio, CurrentStormVolume); } void AAgrarianWeatherAudioController::AssignConfiguredSounds() { if (AmbientAudio && ClearAmbientSound) { AmbientAudio->SetSound(ClearAmbientSound); } if (RainAudio && RainLoopSound) { RainAudio->SetSound(RainLoopSound); } if (WindAudio && WindLoopSound) { WindAudio->SetSound(WindLoopSound); } if (StormAudio && StormLoopSound) { StormAudio->SetSound(StormLoopSound); } } void AAgrarianWeatherAudioController::ApplyComponentVolume(UAudioComponent* AudioComponent, float Volume) const { if (!AudioComponent) { return; } const float SafeVolume = FMath::Clamp(Volume, 0.0f, 1.0f); AudioComponent->SetVolumeMultiplier(SafeVolume); if (AudioComponent->Sound && SafeVolume > 0.01f && !AudioComponent->IsPlaying()) { AudioComponent->Play(); } else if (SafeVolume <= 0.01f && AudioComponent->IsPlaying()) { AudioComponent->Stop(); } } float AAgrarianWeatherAudioController::GetProviderWindAlpha(float WindSpeedKmh, bool bHasProviderData) const { if (!bHasProviderData) { return 0.0f; } return FMath::Clamp(WindSpeedKmh / 55.0f, 0.0f, 1.0f); }