From 8053f2ec9ea5f19415103607e353d290111a9c19 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Sat, 30 Mar 2019 15:34:55 +0200 Subject: [PATCH] (c748c569a) Made looping StatusEffect sounds usable (previously they never stopped or updated their position), moved client-specific StatusEffect code to the client project --- .../BarotraumaClient/ClientCode.projitems | 1 + .../Source/StatusEffects/StatusEffect.cs | 144 ++++++++++++++++++ .../Source/StatusEffects/StatusEffect.cs | 124 +++------------ 3 files changed, 169 insertions(+), 100 deletions(-) create mode 100644 Barotrauma/BarotraumaClient/Source/StatusEffects/StatusEffect.cs diff --git a/Barotrauma/BarotraumaClient/ClientCode.projitems b/Barotrauma/BarotraumaClient/ClientCode.projitems index 489043880..1b79fd2eb 100644 --- a/Barotrauma/BarotraumaClient/ClientCode.projitems +++ b/Barotrauma/BarotraumaClient/ClientCode.projitems @@ -213,6 +213,7 @@ + Never diff --git a/Barotrauma/BarotraumaClient/Source/StatusEffects/StatusEffect.cs b/Barotrauma/BarotraumaClient/Source/StatusEffects/StatusEffect.cs new file mode 100644 index 000000000..778e11f82 --- /dev/null +++ b/Barotrauma/BarotraumaClient/Source/StatusEffects/StatusEffect.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Barotrauma.Particles; +using Barotrauma.Sounds; +using Microsoft.Xna.Framework; +using System.Xml.Linq; +using Barotrauma.Items.Components; + +namespace Barotrauma +{ + partial class StatusEffect + { + private List particleEmitters; + + private static HashSet ActiveLoopingSounds = new HashSet(); + private static double LastMuffleCheckTime; + private List sounds = new List(); + private SoundSelectionMode soundSelectionMode; + private SoundChannel soundChannel; + private Entity soundEmitter; + private double loopStartTime; + private bool loopSound; + + partial void InitProjSpecific(XElement element, string parentDebugName) + { + particleEmitters = new List(); + + foreach (XElement subElement in element.Elements()) + { + switch (subElement.Name.ToString().ToLowerInvariant()) + { + case "particleemitter": + particleEmitters.Add(new ParticleEmitter(subElement)); + break; + case "sound": + var sound = Submarine.LoadRoundSound(subElement); + if (sound != null) + { + loopSound = subElement.GetAttributeBool("loop", false); + if (subElement.Attribute("selectionmode") != null) + { + if (Enum.TryParse(subElement.GetAttributeString("selectionmode", "Random"), out SoundSelectionMode selectionMode)) + { + soundSelectionMode = selectionMode; + } + } + sounds.Add(sound); + } + break; + } + } + } + + partial void ApplyProjSpecific(float deltaTime, Entity entity, List targets, Hull hull) + { + if (entity != null && sounds.Count > 0) + { + if (soundChannel == null || !soundChannel.IsPlaying) + { + if (soundSelectionMode == SoundSelectionMode.All) + { + foreach (RoundSound sound in sounds) + { + soundChannel = SoundPlayer.PlaySound(sound.Sound, sound.Volume, sound.Range, entity.WorldPosition, hull); + if (soundChannel != null) soundChannel.Looping = loopSound; + } + } + else + { + int selectedSoundIndex = 0; + if (soundSelectionMode == SoundSelectionMode.ItemSpecific && entity is Item item) + { + selectedSoundIndex = item.ID % sounds.Count; + } + else if (soundSelectionMode == SoundSelectionMode.CharacterSpecific && entity is Character user) + { + selectedSoundIndex = user.ID % sounds.Count; + } + else + { + selectedSoundIndex = Rand.Int(sounds.Count); + } + var selectedSound = sounds[selectedSoundIndex]; + soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, selectedSound.Volume, selectedSound.Range, entity.WorldPosition, hull); + if (soundChannel != null) soundChannel.Looping = loopSound; + } + } + + if (soundChannel != null && soundChannel.Looping) + { + ActiveLoopingSounds.Add(this); + soundEmitter = entity; + loopStartTime = Timing.TotalTime; + } + } + + if (entity != null) + { + foreach (ParticleEmitter emitter in particleEmitters) + { + float angle = 0.0f; + if (emitter.Prefab.CopyEntityAngle) + { + if (entity is Item it) + { + angle = it.body == null ? 0.0f : it.body.Rotation; + } + } + + emitter.Emit(deltaTime, entity.WorldPosition, hull, angle); + } + } + } + + static partial void UpdateAllProjSpecific(float deltaTime) + { + bool doMuffleCheck = Timing.TotalTime > LastMuffleCheckTime + 0.2; + if (doMuffleCheck) { LastMuffleCheckTime = Timing.TotalTime; } + foreach (StatusEffect statusEffect in ActiveLoopingSounds) + { + if (statusEffect.soundChannel == null) { continue; } + + //stop looping sounds if the statuseffect hasn't been applied in 0.1 + //= keeping the sound looping requires continuously applying the statuseffect + if (Timing.TotalTime > statusEffect.loopStartTime + 0.1) + { + statusEffect.soundChannel.FadeOutAndDispose(); + statusEffect.soundChannel = null; + } + else + { + statusEffect.soundChannel.Position = new Vector3(statusEffect.soundEmitter.WorldPosition, 0.0f); + if (doMuffleCheck) + { + statusEffect.soundChannel.Muffled = SoundPlayer.ShouldMuffleSound( + Character.Controlled, statusEffect.soundEmitter.WorldPosition, statusEffect.soundChannel.Far, Character.Controlled?.CurrentHull); + } + } + } + ActiveLoopingSounds.RemoveWhere(s => s.soundChannel == null); + } + } +} diff --git a/Barotrauma/BarotraumaShared/Source/StatusEffects/StatusEffect.cs b/Barotrauma/BarotraumaShared/Source/StatusEffects/StatusEffect.cs index 072c260ab..42f846423 100644 --- a/Barotrauma/BarotraumaShared/Source/StatusEffects/StatusEffect.cs +++ b/Barotrauma/BarotraumaShared/Source/StatusEffects/StatusEffect.cs @@ -1,13 +1,9 @@ -using Microsoft.Xna.Framework; +using Barotrauma.Items.Components; +using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; -using Barotrauma.Items.Components; -#if CLIENT -using Barotrauma.Particles; -using Barotrauma.Sounds; -#endif namespace Barotrauma { @@ -90,20 +86,12 @@ namespace Barotrauma } } + private TargetType targetTypes; protected HashSet targetIdentifiers; private List requiredItems; - -#if CLIENT - private List particleEmitters; - - private List sounds = new List(); - private SoundSelectionMode soundSelectionMode; - private SoundChannel soundChannel; - private bool loopSound; -#endif - + public string[] propertyNames; private object[] propertyEffects; @@ -193,10 +181,6 @@ namespace Barotrauma Range = element.GetAttributeFloat("range", 0.0f); -#if CLIENT - particleEmitters = new List(); -#endif - IEnumerable attributes = element.Attributes(); List propertyAttributes = new List(); propertyConditionals = new List(); @@ -373,28 +357,16 @@ namespace Barotrauma var newSpawnItem = new ItemSpawnInfo(subElement, parentDebugName); if (newSpawnItem.ItemPrefab != null) spawnItems.Add(newSpawnItem); break; -#if CLIENT - case "particleemitter": - particleEmitters.Add(new ParticleEmitter(subElement)); - break; - case "sound": - var sound = Submarine.LoadRoundSound(subElement); - if (sound != null) - { - loopSound = subElement.GetAttributeBool("loop", false); - if (subElement.Attribute("selectionmode") != null) - { - if (Enum.TryParse(subElement.GetAttributeString("selectionmode", "Random"), out SoundSelectionMode selectionMode)) - { - soundSelectionMode = selectionMode; - } - } - sounds.Add(sound); - } - break; -#endif } } + InitProjSpecific(element, parentDebugName); + } + + partial void InitProjSpecific(XElement element, string parentDebugName); + + public bool HasTargetType(TargetType targetType) + { + return (targetTypes & targetType) != 0; } public bool HasTargetType(TargetType targetType) @@ -601,46 +573,10 @@ namespace Barotrauma { hull = ((Item)entity).CurrentHull; } -#if CLIENT - if (entity != null && sounds.Count > 0) - { - if (soundChannel == null || !soundChannel.IsPlaying) - { - if (soundSelectionMode == SoundSelectionMode.All) - { - foreach (RoundSound sound in sounds) - { - soundChannel = SoundPlayer.PlaySound(sound.Sound, sound.Volume, sound.Range, entity.WorldPosition, hull); - if (soundChannel != null) soundChannel.Looping = loopSound; - } - } - else - { - int selectedSoundIndex = 0; - if (soundSelectionMode == SoundSelectionMode.ItemSpecific && entity is Item item) - { - selectedSoundIndex = item.ID % sounds.Count; - } - else if (soundSelectionMode == SoundSelectionMode.CharacterSpecific && entity is Character user) - { - selectedSoundIndex = user.ID % sounds.Count; - } - else - { - selectedSoundIndex = Rand.Int(sounds.Count); - } - var selectedSound = sounds[selectedSoundIndex]; - soundChannel = SoundPlayer.PlaySound(selectedSound.Sound, selectedSound.Volume, selectedSound.Range, entity.WorldPosition, hull); - if (soundChannel != null) soundChannel.Looping = loopSound; - } - } - } -#endif foreach (ISerializableEntity serializableEntity in targets) { - Item item = serializableEntity as Item; - if (item == null) continue; + if (!(serializableEntity is Item item)) continue; Character targetCharacter = targets.FirstOrDefault(t => t is Character character && !character.Removed) as Character; if (targetCharacter == null) @@ -740,11 +676,7 @@ namespace Barotrauma fire.Size = new Vector2(FireSize, fire.Size.Y); } - bool isNotClient = true; -#if CLIENT - isNotClient = GameMain.Client == null; -#endif - + bool isNotClient = GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient; if (isNotClient && entity != null && Entity.Spawner != null) //clients are not allowed to spawn items { foreach (ItemSpawnInfo itemSpawnInfo in spawnItems) @@ -801,26 +733,11 @@ namespace Barotrauma } } -#if CLIENT - if (entity != null) - { - foreach (ParticleEmitter emitter in particleEmitters) - { - float angle = 0.0f; - if (emitter.Prefab.CopyEntityAngle) - { - if (entity is Item it) - { - angle = it.body == null ? 0.0f : it.body.Rotation; - } - } - - emitter.Emit(deltaTime, entity.WorldPosition, hull, angle); - } - } -#endif + ApplyProjSpecific(deltaTime, entity, targets, hull); } + partial void ApplyProjSpecific(float deltaTime, Entity entity, List targets, Hull currentHull); + private void ApplyToProperty(ISerializableEntity target, SerializableProperty property, object value, float deltaTime) { if (disableDeltaTime || setValue) deltaTime = 1.0f; @@ -857,6 +774,8 @@ namespace Barotrauma public static void UpdateAll(float deltaTime) { + UpdateAllProjSpecific(deltaTime); + DelayedEffect.Update(deltaTime); for (int i = DurationList.Count - 1; i >= 0; i--) { @@ -925,11 +844,16 @@ namespace Barotrauma } } + static partial void UpdateAllProjSpecific(float deltaTime); + public static void StopAll() { CoroutineManager.StopCoroutines("statuseffect"); DelayedEffect.DelayList.Clear(); DurationList.Clear(); +#if CLIENT + //ActiveLoopingSounds.Clear(); +#endif } public void AddTag(string tag)