1 #region Copyright & License Information
2 /*
3  * Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
4  * This file is part of OpenRA, which is free software. It is made
5  * available to you under the terms of the GNU General Public License
6  * as published by the Free Software Foundation, either version 3 of
7  * the License, or (at your option) any later version. For more
8  * information, see COPYING.
9  */
10 #endregion
11 
12 using System;
13 using System.Collections.Generic;
14 using System.Linq;
15 
16 namespace OpenRA.GameRules
17 {
18 	public class SoundInfo
19 	{
20 		public readonly Dictionary<string, string[]> Variants = new Dictionary<string, string[]>();
21 		public readonly Dictionary<string, string[]> Prefixes = new Dictionary<string, string[]>();
22 		public readonly Dictionary<string, string[]> Voices = new Dictionary<string, string[]>();
23 		public readonly Dictionary<string, string[]> Notifications = new Dictionary<string, string[]>();
24 		public readonly string DefaultVariant = ".aud";
25 		public readonly string DefaultPrefix = "";
26 		public readonly HashSet<string> DisableVariants = new HashSet<string>();
27 		public readonly HashSet<string> DisablePrefixes = new HashSet<string>();
28 
29 		public readonly Lazy<Dictionary<string, SoundPool>> VoicePools;
30 		public readonly Lazy<Dictionary<string, SoundPool>> NotificationsPools;
31 
SoundInfo(MiniYaml y)32 		public SoundInfo(MiniYaml y)
33 		{
34 			FieldLoader.Load(this, y);
35 
36 			VoicePools = Exts.Lazy(() => Voices.ToDictionary(a => a.Key, a => new SoundPool(1f, a.Value)));
37 			NotificationsPools = Exts.Lazy(() => ParseSoundPool(y, "Notifications"));
38 		}
39 
ParseSoundPool(MiniYaml y, string key)40 		Dictionary<string, SoundPool> ParseSoundPool(MiniYaml y, string key)
41 		{
42 			var ret = new Dictionary<string, SoundPool>();
43 			var classifiction = y.Nodes.First(x => x.Key == key);
44 			foreach (var t in classifiction.Value.Nodes)
45 			{
46 				var volumeModifier = 1f;
47 				var volumeModifierNode = t.Value.Nodes.FirstOrDefault(x => x.Key == "VolumeModifier");
48 				if (volumeModifierNode != null)
49 					volumeModifier = FieldLoader.GetValue<float>(volumeModifierNode.Key, volumeModifierNode.Value.Value);
50 
51 				var names = FieldLoader.GetValue<string[]>(t.Key, t.Value.Value);
52 				var sp = new SoundPool(volumeModifier, names);
53 				ret.Add(t.Key, sp);
54 			}
55 
56 			return ret;
57 		}
58 	}
59 
60 	public class SoundPool
61 	{
62 		public readonly float VolumeModifier;
63 		readonly string[] clips;
64 		readonly List<string> liveclips = new List<string>();
65 
SoundPool(float volumeModifier, params string[] clips)66 		public SoundPool(float volumeModifier, params string[] clips)
67 		{
68 			VolumeModifier = volumeModifier;
69 			this.clips = clips;
70 		}
71 
GetNext()72 		public string GetNext()
73 		{
74 			if (liveclips.Count == 0)
75 				liveclips.AddRange(clips);
76 
77 			// Avoid crashing if there's no clips at all
78 			if (liveclips.Count == 0)
79 				return null;
80 
81 			var i = Game.CosmeticRandom.Next(liveclips.Count);
82 			var s = liveclips[i];
83 			liveclips.RemoveAt(i);
84 			return s;
85 		}
86 	}
87 }
88