diff --git a/Content.Client/Audio/ContentAudioSystem.AmbientMusic.cs b/Content.Client/Audio/ContentAudioSystem.AmbientMusic.cs index d60c978ccf..dbebead171 100644 --- a/Content.Client/Audio/ContentAudioSystem.AmbientMusic.cs +++ b/Content.Client/Audio/ContentAudioSystem.AmbientMusic.cs @@ -117,6 +117,7 @@ public sealed partial class ContentAudioSystem private void OnRoundEndMessage(RoundEndMessageEvent ev) { + OnRoundEndMessageAmbientLoop(); //CP14 // If scoreboard shows then just stop the music _ambientMusicStream = _audio.Stop(_ambientMusicStream); _nextAudio = TimeSpan.FromMinutes(3); diff --git a/Content.Client/Audio/ContentAudioSystem.CP14AmbientLoop.cs b/Content.Client/Audio/ContentAudioSystem.CP14AmbientLoop.cs new file mode 100644 index 0000000000..e98aa10d6e --- /dev/null +++ b/Content.Client/Audio/ContentAudioSystem.CP14AmbientLoop.cs @@ -0,0 +1,122 @@ +using System.Linq; +using Content.Client.Gameplay; +using Content.Shared.Audio; +using Content.Shared.CCVar; +using Robust.Shared.Audio; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Player; + +namespace Content.Client.Audio; + +public sealed partial class ContentAudioSystem +{ + private const float AmbientLoopFadeInTime = 1f; + private const float AmbientLoopFadeOutTime = 4f; + + private Dictionary _loopStreams = new(); + + private TimeSpan _nextUpdateTime = TimeSpan.Zero; + private readonly TimeSpan _updateFrequency = TimeSpan.FromSeconds(1f); + + private void CP14InitializeAmbientLoops() + { + Subs.CVar(_configManager, CCVars.AmbientMusicVolume, AmbienceCVarChangedAmbientMusic, true); + } + + private void AmbienceCVarChangedAmbientMusic(float obj) + { + _volumeSlider = SharedAudioSystem.GainToVolume(obj); + + foreach (var loop in _loopStreams) + { + _audio.SetVolume(loop.Value, loop.Key.Sound.Params.Volume + _volumeSlider); + } + } + + private void OnRoundEndMessageAmbientLoop() + { + foreach (var loop in _loopStreams) + { + StopAmbientLoop(loop.Key); + } + } + + private void CP14UpdateAmbientLoops() + { + if (_timing.CurTime <= _nextUpdateTime) + return; + + _nextUpdateTime = _timing.CurTime + _updateFrequency; + + + if (_state.CurrentState is not GameplayState) + return; + + var requiredLoops = GetAmbientLoops(); + + foreach (var loop in _loopStreams) + { + if (!requiredLoops.Contains(loop.Key)) //If ambient is playing and it shouldn't, stop it. + StopAmbientLoop(loop.Key); + } + + foreach (var loop in requiredLoops) + { + if (!_loopStreams.ContainsKey(loop)) //If it's not playing, but should, run it + StartAmbientLoop(loop); + } + } + + private void StartAmbientLoop(CP14AmbientLoopPrototype proto) + { + if (_loopStreams.ContainsKey(proto)) + return; + + var newLoop = _audio.PlayGlobal( + proto.Sound, + Filter.Local(), + false, + AudioParams.Default + .WithLoop(true) + .WithVolume(proto.Sound.Params.Volume + _volumeSlider) + .WithPlayOffset(_random.NextFloat(0f, 100f))); + _loopStreams.Add(proto, newLoop.Value.Entity); + + FadeIn(newLoop.Value.Entity, newLoop.Value.Component, AmbientLoopFadeInTime); + } + + private void StopAmbientLoop(CP14AmbientLoopPrototype proto) + { + if (!_loopStreams.TryGetValue(proto, out var audioEntity)) + return; + + FadeOut(audioEntity, duration: AmbientLoopFadeOutTime); + _loopStreams.Remove(proto); + } + + /// + /// Checks the player's environment, and returns a list of all ambients that should currently be playing around the player + /// + /// + private List GetAmbientLoops() + { + List list = new(); + + var player = _player.LocalEntity; + + if (player == null) + return list; + + var ambientLoops = _proto.EnumeratePrototypes().ToList(); + + foreach (var loop in ambientLoops) + { + if (_rules.IsTrue(player.Value, _proto.Index(loop.Rules))) + { + list.Add(loop); + } + } + + return list; + } +} diff --git a/Content.Client/Audio/ContentAudioSystem.cs b/Content.Client/Audio/ContentAudioSystem.cs index f62b34b492..3fc77bb50a 100644 --- a/Content.Client/Audio/ContentAudioSystem.cs +++ b/Content.Client/Audio/ContentAudioSystem.cs @@ -29,13 +29,14 @@ public sealed partial class ContentAudioSystem : SharedContentAudioSystem public const float AmbientMusicMultiplier = 3f; public const float LobbyMultiplier = 3f; public const float InterfaceMultiplier = 2f; - + public override void Initialize() { base.Initialize(); UpdatesOutsidePrediction = true; InitializeAmbientMusic(); + CP14InitializeAmbientLoops(); //CP14 ambient loops InitializeLobbyMusic(); SubscribeNetworkEvent(OnRoundCleanup); } @@ -82,6 +83,7 @@ public sealed partial class ContentAudioSystem : SharedContentAudioSystem return; UpdateAmbientMusic(); + CP14UpdateAmbientLoops(); //CP14 UpdateLobbyMusic(); UpdateFades(frameTime); } diff --git a/Content.Shared/Audio/CP14AmbientLoopPrototype.cs b/Content.Shared/Audio/CP14AmbientLoopPrototype.cs new file mode 100644 index 0000000000..83f3a27509 --- /dev/null +++ b/Content.Shared/Audio/CP14AmbientLoopPrototype.cs @@ -0,0 +1,20 @@ +using Content.Shared.Random.Rules; +using Robust.Shared.Audio; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Audio; + +/// +/// Attaches a rules prototype to sound files to play ambience. +/// +[Prototype("ambientLoop")] +public sealed partial class CP14AmbientLoopPrototype : IPrototype +{ + [IdDataField] public string ID { get; } = string.Empty; + + [ViewVariables(VVAccess.ReadWrite), DataField("sound", required: true)] + public SoundSpecifier Sound = default!; + + [ViewVariables(VVAccess.ReadWrite), DataField("rules", required: true)] + public ProtoId Rules = string.Empty; +} diff --git a/Content.Shared/_CP14/Random/Rules/IsDaylight.cs b/Content.Shared/_CP14/Random/Rules/IsDaylight.cs new file mode 100644 index 0000000000..e694bd255f --- /dev/null +++ b/Content.Shared/_CP14/Random/Rules/IsDaylight.cs @@ -0,0 +1,19 @@ +using Content.Shared._CP14.DayCycle; +using Content.Shared.Random.Rules; + +namespace Content.Shared._CP14.Random.Rules; + +/// +/// Returns true if the attached entity is in space. +/// +public sealed partial class IsDaylight : RulesRule +{ + public override bool Check(EntityManager entManager, EntityUid uid) + { + var transform = entManager.System(); + var dayCycle = entManager.System(); + + //черт, нужны комиты из ветки фермерства + return !Inverted; + } +} diff --git a/Resources/Audio/_CP14/Ambience/Loops/attributions.yml b/Resources/Audio/_CP14/Ambience/Loops/attributions.yml new file mode 100644 index 0000000000..85ec50a7e3 --- /dev/null +++ b/Resources/Audio/_CP14/Ambience/Loops/attributions.yml @@ -0,0 +1,9 @@ +- files: ["grasslands.ogg"] + license: "CC-BY-NC-4.0" + copyright: 'by jgrzinich of Freesound.org.' + source: "https://freesound.org/people/jgrzinich/sounds/329805/" + +- files: ["water.ogg"] + license: "CC0-1.0" + copyright: 'by jackthemurray of Freesound.org.' + source: "https://freesound.org/people/jackthemurray/sounds/433589/" \ No newline at end of file diff --git a/Resources/Audio/_CP14/Ambience/Loops/grasslands.ogg b/Resources/Audio/_CP14/Ambience/Loops/grasslands.ogg new file mode 100644 index 0000000000..a8b4fbb94f Binary files /dev/null and b/Resources/Audio/_CP14/Ambience/Loops/grasslands.ogg differ diff --git a/Resources/Audio/_CP14/Ambience/Loops/water.ogg b/Resources/Audio/_CP14/Ambience/Loops/water.ogg new file mode 100644 index 0000000000..00a01f0b9c Binary files /dev/null and b/Resources/Audio/_CP14/Ambience/Loops/water.ogg differ diff --git a/Resources/Prototypes/_CP14/Entities/Structures/Flora/floorWater.yml b/Resources/Prototypes/_CP14/Entities/Structures/Flora/floorWater.yml index 720ac1105f..acd88141a3 100644 --- a/Resources/Prototypes/_CP14/Entities/Structures/Flora/floorWater.yml +++ b/Resources/Prototypes/_CP14/Entities/Structures/Flora/floorWater.yml @@ -65,4 +65,5 @@ deleteSpawnerAfterSpawn: false - type: Tag tags: - - HideContextMenu \ No newline at end of file + - HideContextMenu + - CP14AmbientWater \ No newline at end of file diff --git a/Resources/Prototypes/_CP14/audio_loops.yml b/Resources/Prototypes/_CP14/audio_loops.yml new file mode 100644 index 0000000000..715113d63a --- /dev/null +++ b/Resources/Prototypes/_CP14/audio_loops.yml @@ -0,0 +1,50 @@ + +- type: ambientLoop + id: Grasslands + sound: + params: + volume: -3 + collection: CP14LoopGrassland + rules: NearGrass + +- type: ambientLoop + id: Water + sound: + params: + volume: 18 + collection: CP14LoopWater + rules: NearWater + +# Sound collections +- type: soundCollection + id: CP14LoopGrassland + files: + - /Audio/_CP14/Ambience/Loops/grasslands.ogg + +- type: soundCollection + id: CP14LoopWater + files: + - /Audio/_CP14/Ambience/Loops/water.ogg + +# Rules +- type: rules + id: NearGrass + rules: + - !type:NearbyTilesPercentRule + ignoreAnchored: true + percent: 0.5 + tiles: + - CP14FloorGrass + - CP14FloorGrassLight + - CP14FloorGrassTall + range: 5 + +- type: rules + id: NearWater + rules: + - !type:NearbyEntitiesRule + count: 5 + whitelist: + tags: + - CP14AmbientWater + range: 4 \ No newline at end of file diff --git a/Resources/Prototypes/_CP14/audio_music.yml b/Resources/Prototypes/_CP14/audio_music.yml new file mode 100644 index 0000000000..f941c2ae69 --- /dev/null +++ b/Resources/Prototypes/_CP14/audio_music.yml @@ -0,0 +1,35 @@ +# 4 Priority - Special + +# 3 Priority - Departments + +# 2 Priority - General areas + +## Fallback if nothing else found +- type: ambientMusic + id: CP14Cave + sound: + params: + volume: -12 + collection: CP14AmbienceCave + rules: AlwaysTrue + +# Sound collections +- type: soundCollection + id: CP14AmbienceCave + files: + - /Audio/Ambience/ambilava1.ogg + - /Audio/Ambience/ambilava2.ogg + - /Audio/Ambience/ambimystery.ogg + - /Audio/Ambience/ambiruin.ogg + - /Audio/Ambience/ambiruin4.ogg + - /Audio/Ambience/maintambience.ogg + - /Audio/_CP14/Ambience/ambicave1.ogg + - /Audio/_CP14/Ambience/ambicreepy1.ogg + - /Audio/_CP14/Ambience/ambicreepy2.ogg + - /Audio/_CP14/Ambience/ambicreepy3.ogg + +# Rules +- type: rules + id: AlwaysTrue + rules: + - !type:AlwaysTrueRule \ No newline at end of file diff --git a/Resources/Prototypes/_CP14/tags.yml b/Resources/Prototypes/_CP14/tags.yml index 4ed2fc27ee..14b7b198d8 100644 --- a/Resources/Prototypes/_CP14/tags.yml +++ b/Resources/Prototypes/_CP14/tags.yml @@ -24,3 +24,6 @@ - type: Tag id: CP14Bottles + +- type: Tag + id: CP14AmbientWater diff --git a/Resources/Prototypes/audio.yml b/Resources/Prototypes/audio.yml index f941c2ae69..420764e544 100644 --- a/Resources/Prototypes/audio.yml +++ b/Resources/Prototypes/audio.yml @@ -1,35 +1 @@ -# 4 Priority - Special - -# 3 Priority - Departments - -# 2 Priority - General areas - -## Fallback if nothing else found -- type: ambientMusic - id: CP14Cave - sound: - params: - volume: -12 - collection: CP14AmbienceCave - rules: AlwaysTrue - -# Sound collections -- type: soundCollection - id: CP14AmbienceCave - files: - - /Audio/Ambience/ambilava1.ogg - - /Audio/Ambience/ambilava2.ogg - - /Audio/Ambience/ambimystery.ogg - - /Audio/Ambience/ambiruin.ogg - - /Audio/Ambience/ambiruin4.ogg - - /Audio/Ambience/maintambience.ogg - - /Audio/_CP14/Ambience/ambicave1.ogg - - /Audio/_CP14/Ambience/ambicreepy1.ogg - - /Audio/_CP14/Ambience/ambicreepy2.ogg - - /Audio/_CP14/Ambience/ambicreepy3.ogg - -# Rules -- type: rules - id: AlwaysTrue - rules: - - !type:AlwaysTrueRule \ No newline at end of file +# Not used in CP14 \ No newline at end of file