using System; using System.Collections.Generic; using Cysharp.Threading.Tasks; using Unity.Mathematics; using Time = UnityEngine.Time; namespace DanieleMarotta.RiversongCodeShowcase { public class PlaySoundOnEventSystem : GameSystem, IInitializable, IDisposable { [InjectService] private ISoundPlayer _soundPlayer; [InjectService] private ISignalBus _signalBus; [InjectService] private IGameDatabase _gameDatabase; [InjectService] private ITileSpace _tileSpace; private Dictionary _soundPlayedTimestamps = new(); public PlaySoundOnEventSystem(IServiceLocator serviceLocator) : base(serviceLocator) { } public UniTask InitializeAsync() { _signalBus.Subscribe(OnBuildingPlacementAnimationCompleted); _signalBus.Subscribe(OnConstructionSiteDeleted); _signalBus.Subscribe(OnBuildingDeleted); _signalBus.Subscribe(OnBuildingUpgraded); _signalBus.Subscribe(OnRawResourcesRemoved); _signalBus.Subscribe(OnRoadTileUpdated); _signalBus.Subscribe(OnBuildMenuButtonUnlockAnimationStarted); return UniTask.CompletedTask; } public void Dispose() { _signalBus.Unsubscribe(OnBuildingPlacementAnimationCompleted); _signalBus.Unsubscribe(OnConstructionSiteDeleted); _signalBus.Unsubscribe(OnBuildingDeleted); _signalBus.Unsubscribe(OnBuildingUpgraded); _signalBus.Unsubscribe(OnRawResourcesRemoved); _signalBus.Unsubscribe(OnRoadTileUpdated); _signalBus.Unsubscribe(OnBuildMenuButtonUnlockAnimationStarted); } private bool UpdatePlayedTimestamp(int key) { var timestamp = _soundPlayedTimestamps.GetValueOrDefault(key); const float minInterval = 0.1f; if (Time.unscaledTime - timestamp < minInterval) return false; _soundPlayedTimestamps[key] = Time.unscaledTime; return true; } private void OnBuildingPlacementAnimationCompleted(BuildingPlacementAnimationCompletedSignal signal) { PlaySystemSound(SystemSoundId.BuildingPlaced); } private void OnConstructionSiteDeleted(ConstructionSiteDeletedSignal signal) { PlaySystemSound(SystemSoundId.BuildingDeleted); } private void OnBuildingDeleted(BuildingDeletedSignal signal) { if (signal.Options == DeleteBuildingOptions.Silent) return; PlaySystemSound(SystemSoundId.BuildingDeleted); } private void OnBuildingUpgraded(BuildingUpgradedSignal signal) { if (!signal.Building.Definition.IsHouse || !UpdatePlayedTimestamp((int)SystemSoundId.HouseUpgraded)) return; var position = (float3)_tileSpace.GetRectWorldCenter(signal.Building.Rect); _soundPlayer.PlayAt(SystemSoundId.HouseUpgraded, position); } private void OnRawResourcesRemoved(RawResourcesRemovedSignal signal) { foreach (var resourceNode in signal.ResourceNodes) { var definition = _gameDatabase.WithId(resourceNode.DefinitionId); if (!UpdatePlayedTimestamp(definition.RuntimeId)) continue; if (signal.Reason == RawResourcesRemovedSignal.RemovalReason.Harvested) _soundPlayer.PlayAt(definition.DeleteAudio, resourceNode.Tile); else _soundPlayer.Play(definition.DeleteAudio); } } private void OnRoadTileUpdated(RoadTileUpdatedSignal signal) { PlaySystemSound(signal.RoadTileAdded ? SystemSoundId.RoadTilePlaced : SystemSoundId.RoadTileDeleted); } private void OnBuildMenuButtonUnlockAnimationStarted(BuildMenuButtonUnlockAnimationStartedSignal signal) { PlaySystemSound(SystemSoundId.UnlockNotification); } private void PlaySystemSound(SystemSoundId soundId) { if (UpdatePlayedTimestamp((int)soundId)) _soundPlayer.Play(soundId); } } }