Merge branch 'dev'

# Conflicts:
#	Barotrauma/BarotraumaClient/ClientSource/Characters/Animation/Ragdoll.cs
#	Barotrauma/BarotraumaClient/ClientSource/Characters/Character.cs
#	Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs
#	Barotrauma/BarotraumaClient/ClientSource/Characters/Jobs/JobPrefab.cs
#	Barotrauma/BarotraumaClient/ClientSource/Characters/Limb.cs
#	Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs
#	Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs
#	Barotrauma/BarotraumaClient/ClientSource/GUI/TalentMenu.cs
#	Barotrauma/BarotraumaClient/ClientSource/GameSession/RoundSummary.cs
#	Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemComponent.cs
#	Barotrauma/BarotraumaClient/ClientSource/Items/Components/ItemContainer.cs
#	Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Wire.cs
#	Barotrauma/BarotraumaClient/ClientSource/Items/Item.cs
#	Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs
#	Barotrauma/BarotraumaClient/ClientSource/Map/Submarine.cs
#	Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs
#	Barotrauma/BarotraumaClient/ClientSource/Networking/Primitives/Peers/ClientPeer.cs
#	Barotrauma/BarotraumaClient/ClientSource/Networking/RespawnManager.cs
#	Barotrauma/BarotraumaClient/ClientSource/Particles/Particle.cs
#	Barotrauma/BarotraumaClient/ClientSource/Particles/ParticleEmitter.cs
#	Barotrauma/BarotraumaClient/ClientSource/Physics/PhysicsBody.cs
#	Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs
#	Barotrauma/BarotraumaClient/ClientSource/Screens/LevelEditorScreen.cs
#	Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen/MainMenuScreen.cs
#	Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs
#	Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs
#	Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs
#	Barotrauma/BarotraumaClient/ClientSource/Steam/WorkshopMenu/Mutable/InstalledTab.cs
#	Barotrauma/BarotraumaClient/LinuxClient.csproj
#	Barotrauma/BarotraumaClient/MacClient.csproj
#	Barotrauma/BarotraumaClient/WindowsClient.csproj
#	Barotrauma/BarotraumaServer/LinuxServer.csproj
#	Barotrauma/BarotraumaServer/MacServer.csproj
#	Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs
#	Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs
#	Barotrauma/BarotraumaServer/ServerSource/Events/EventActions/ConversationAction.cs
#	Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs
#	Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs
#	Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs
#	Barotrauma/BarotraumaServer/WindowsServer.csproj
#	Barotrauma/BarotraumaShared/LocalMods/[DebugOnlyTest]Character override and variant tests/README.txt
#	Barotrauma/BarotraumaShared/LocalMods/[DebugOnlyTest]Character override and variant tests/filelist.xml
#	Barotrauma/BarotraumaShared/SharedSource/AchievementManager.cs
#	Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs
#	Barotrauma/BarotraumaShared/SharedSource/Characters/AI/HumanAIController.cs
#	Barotrauma/BarotraumaShared/SharedSource/Characters/AI/IndoorsSteeringManager.cs
#	Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCombat.cs
#	Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveDeconstructItem.cs
#	Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveFindSafety.cs
#	Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGoTo.cs
#	Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveOperateItem.cs
#	Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveReturn.cs
#	Barotrauma/BarotraumaShared/SharedSource/Characters/AI/PetBehavior.cs
#	Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs
#	Barotrauma/BarotraumaShared/SharedSource/Characters/CharacterInfo.cs
#	Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionHusk.cs
#	Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionPrefab.cs
#	Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs
#	Barotrauma/BarotraumaShared/SharedSource/Characters/Params/CharacterParams.cs
#	Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackage/ContentPackage.cs
#	Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs
#	Barotrauma/BarotraumaShared/SharedSource/DisembarkPerks/DisembarkPerkPrefab.cs
#	Barotrauma/BarotraumaShared/SharedSource/Enums.cs
#	Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/ConversationAction.cs
#	Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCChangeTeamAction.cs
#	Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs
#	Barotrauma/BarotraumaShared/SharedSource/Events/Missions/AbandonedOutpostMission.cs
#	Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs
#	Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs
#	Barotrauma/BarotraumaShared/SharedSource/GameSession/AutoItemPlacer.cs
#	Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs
#	Barotrauma/BarotraumaShared/SharedSource/Items/Components/GeneticMaterial.cs
#	Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Holdable.cs
#	Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs
#	Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs
#	Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs
#	Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs
#	Barotrauma/BarotraumaShared/SharedSource/Map/Map/Location.cs
#	Barotrauma/BarotraumaShared/SharedSource/Map/Map/LocationType.cs
#	Barotrauma/BarotraumaShared/SharedSource/Map/Outposts/OutpostGenerator.cs
#	Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs
#	Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineInfo.cs
#	Barotrauma/BarotraumaShared/SharedSource/Map/WayPoint.cs
#	Barotrauma/BarotraumaShared/SharedSource/Networking/EntitySpawner.cs
#	Barotrauma/BarotraumaShared/SharedSource/Networking/NetworkMember.cs
#	Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs
#	Barotrauma/BarotraumaShared/SharedSource/PerformanceCounter.cs
#	Barotrauma/BarotraumaShared/SharedSource/Serialization/XMLExtensions.cs
#	Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs
#	Barotrauma/BarotraumaShared/SharedSource/Tags.cs
#	Barotrauma/BarotraumaShared/SharedSource/Text/TextManager.cs
#	Barotrauma/BarotraumaShared/changelog.txt
This commit is contained in:
Markus Isberg
2025-04-10 14:35:30 +03:00
294 changed files with 8418 additions and 2944 deletions
@@ -104,19 +104,22 @@ namespace Barotrauma.Sounds
public virtual SoundChannel Play(float gain, float range, Vector2 position, bool muffle = false)
{
LogWarningIfStillLoading();
return new SoundChannel(this, gain, new Vector3(position.X, position.Y, 0.0f), 1.0f, range * 0.4f, range, "default", muffle);
if (Owner.CountPlayingInstances(this) >= MaxSimultaneousInstances) { return null; }
return new SoundChannel(this, gain, new Vector3(position.X, position.Y, 0.0f), 1.0f, range * 0.4f, range, SoundManager.SoundCategoryDefault, muffle);
}
public virtual SoundChannel Play(float gain, float range, float freqMult, Vector2 position, bool muffle = false)
{
LogWarningIfStillLoading();
return new SoundChannel(this, gain, new Vector3(position.X, position.Y, 0.0f), freqMult, range * 0.4f, range, "default", muffle);
if (Owner.CountPlayingInstances(this) >= MaxSimultaneousInstances) { return null; }
return new SoundChannel(this, gain, new Vector3(position.X, position.Y, 0.0f), freqMult, range * 0.4f, range, SoundManager.SoundCategoryDefault, muffle);
}
public virtual SoundChannel Play(Vector3? position, float gain, float freqMult = 1.0f, bool muffle = false)
{
LogWarningIfStillLoading();
return new SoundChannel(this, gain, position, freqMult, BaseNear, BaseFar, "default", muffle);
if (Owner.CountPlayingInstances(this) >= MaxSimultaneousInstances) { return null; }
return new SoundChannel(this, gain, position, freqMult, BaseNear, BaseFar, SoundManager.SoundCategoryDefault, muffle);
}
public virtual SoundChannel Play(float gain)
@@ -129,7 +132,7 @@ namespace Barotrauma.Sounds
return Play(BaseGain);
}
public virtual SoundChannel Play(float? gain, string category)
public virtual SoundChannel Play(float? gain, Identifier category)
{
if (Owner.CountPlayingInstances(this) >= MaxSimultaneousInstances) { return null; }
return new SoundChannel(this, gain ?? BaseGain, null, 1.0f, BaseNear, BaseFar, category);
@@ -398,8 +398,8 @@ namespace Barotrauma.Sounds
}
}
private string category;
public string Category
private Identifier category;
public Identifier Category
{
get { return category; }
set
@@ -483,7 +483,7 @@ namespace Barotrauma.Sounds
}
}
public SoundChannel(Sound sound, float gain, Vector3? position, float freqMult, float near, float far, string category, bool muffle = false)
public SoundChannel(Sound sound, float gain, Vector3? position, float freqMult, float near, float far, Identifier category, bool muffle = false)
{
Sound = sound;
@@ -12,11 +12,11 @@ namespace Barotrauma.Sounds
class SoundManager : IDisposable
{
public const int SourceCount = 32;
public const string SoundCategoryDefault = "default";
public const string SoundCategoryUi = "ui";
public const string SoundCategoryWaterAmbience = "waterambience";
public const string SoundCategoryMusic = "music";
public const string SoundCategoryVoip = "voip";
public static readonly Identifier SoundCategoryDefault = "default".ToIdentifier();
public static readonly Identifier SoundCategoryUi = "ui".ToIdentifier();
public static readonly Identifier SoundCategoryWaterAmbience = "waterambience".ToIdentifier();
public static readonly Identifier SoundCategoryMusic = "music".ToIdentifier();
public static readonly Identifier SoundCategoryVoip = "voip".ToIdentifier();
public bool Disabled
{
@@ -201,7 +201,7 @@ namespace Barotrauma.Sounds
}
}
private readonly Dictionary<string, CategoryModifier> categoryModifiers = new Dictionary<string, CategoryModifier>();
private readonly Dictionary<Identifier, CategoryModifier> categoryModifiers = new Dictionary<Identifier, CategoryModifier>();
public SoundManager()
{
@@ -548,10 +548,9 @@ namespace Barotrauma.Sounds
}
}
public void SetCategoryGainMultiplier(string category, float gain, int index=0)
public void SetCategoryGainMultiplier(Identifier category, float gain, int index=0)
{
if (Disabled) { return; }
category = category.ToLower();
lock (categoryModifiers)
{
if (!categoryModifiers.ContainsKey(category))
@@ -579,10 +578,9 @@ namespace Barotrauma.Sounds
}
}
public float GetCategoryGainMultiplier(string category, int index = -1)
public float GetCategoryGainMultiplier(Identifier category, int index = -1)
{
if (Disabled) { return 0.0f; }
category = category.ToLower();
lock (categoryModifiers)
{
if (categoryModifiers == null || !categoryModifiers.TryGetValue(category, out CategoryModifier categoryModifier)) { return 1.0f; }
@@ -602,11 +600,10 @@ namespace Barotrauma.Sounds
}
}
public void SetCategoryMuffle(string category, bool muffle)
public void SetCategoryMuffle(Identifier category, bool muffle)
{
if (Disabled) { return; }
category = category.ToLower();
lock (categoryModifiers)
{
if (!categoryModifiers.ContainsKey(category))
@@ -627,18 +624,17 @@ namespace Barotrauma.Sounds
{
if (playingChannels[i][j] != null && playingChannels[i][j].IsPlaying)
{
if (playingChannels[i][j]?.Category.ToLower() == category) { playingChannels[i][j].Muffled = muffle; }
if (playingChannels[i][j]?.Category == category) { playingChannels[i][j].Muffled = muffle; }
}
}
}
}
}
public bool GetCategoryMuffle(string category)
public bool GetCategoryMuffle(Identifier category)
{
if (Disabled) { return false; }
category = category.ToLower();
lock (categoryModifiers)
{
if (categoryModifiers == null || !categoryModifiers.TryGetValue(category, out CategoryModifier categoryModifier)) { return false; }
@@ -191,9 +191,12 @@ namespace Barotrauma
{
if (volume < 0.01f) { return; }
if (chn is not null) { waterAmbienceChannels.Remove(chn); }
chn = sound.Play(volume, "waterambience");
chn.Looping = true;
waterAmbienceChannels.Add(chn);
chn = sound.Play(volume, SoundManager.SoundCategoryWaterAmbience);
if (chn != null)
{
chn.Looping = true;
waterAmbienceChannels.Add(chn);
}
}
else
{
@@ -307,6 +310,7 @@ namespace Barotrauma
if (flowSoundChannels[i] == null || !flowSoundChannels[i].IsPlaying)
{
flowSoundChannels[i] = FlowSounds[i].Sound.Play(1.0f, FlowSoundRange, soundPos);
if (flowSoundChannels[i] == null) { continue; }
flowSoundChannels[i].Looping = true;
}
flowSoundChannels[i].Gain = Math.Max(flowVolumeRight[i], flowVolumeLeft[i]);
@@ -687,7 +691,22 @@ namespace Barotrauma
}
LogCurrentMusic();
updateMusicTimer = UpdateMusicInterval;
updateMusicTimer = UpdateMusicInterval;
if (mainTrack != null)
{
updateMusicTimer += mainTrack.MinimumPlayDuration;
}
}
bool muteBackgroundMusic = false;
for (int i = 0; i < SoundManager.SourceCount; i++)
{
SoundChannel playingSoundChannel = GameMain.SoundManager.GetSoundChannelFromIndex(SoundManager.SourcePoolIndex.Default, i);
if (playingSoundChannel is { MuteBackgroundMusic: true, IsPlaying: true })
{
muteBackgroundMusic = true;
break;
}
}
bool muteBackgroundMusic = false;
@@ -734,7 +753,7 @@ namespace Barotrauma
DisposeMusicChannel(i);
currentMusic[i] = targetMusic[i];
musicChannel[i] = currentMusic[i].Sound.Play(0.0f, i == noiseLoopIndex ? "default" : "music");
musicChannel[i] = currentMusic[i].Sound.Play(0.0f, i == noiseLoopIndex ? SoundManager.SoundCategoryDefault : SoundManager.SoundCategoryMusic);
if (targetMusic[i].ContinueFromPreviousTime)
{
musicChannel[i].StreamSeekPos = targetMusic[i].PreviousTime;
@@ -753,7 +772,7 @@ namespace Barotrauma
if (musicChannel[i] == null || !musicChannel[i].IsPlaying)
{
musicChannel[i]?.Dispose();
musicChannel[i] = currentMusic[i].Sound.Play(0.0f, i == noiseLoopIndex ? "default" : "music");
musicChannel[i] = currentMusic[i].Sound.Play(0.0f, i == noiseLoopIndex ? SoundManager.SoundCategoryDefault : SoundManager.SoundCategoryMusic);
musicChannel[i].Looping = true;
}
float targetGain = targetMusic[i].Volume;
@@ -874,6 +893,51 @@ namespace Barotrauma
}
Submarine targetSubmarine = Character.Controlled?.Submarine;
float intensity = (GameMain.GameSession?.EventManager?.MusicIntensity ?? 0) * 100.0f;
float enemyDistThreshold = 5000.0f;
if (targetSubmarine != null)
{
enemyDistThreshold = Math.Max(enemyDistThreshold, Math.Max(targetSubmarine.Borders.Width, targetSubmarine.Borders.Height) * 2.0f);
}
List<Character> monsterMusicCharacters = new List<Character>();
foreach (Character character in Character.CharacterList)
{
if (character.IsDead || !character.Enabled) { continue; }
if (character.AIController is not EnemyAIController { Enabled: true } enemyAI) { continue; }
if (!enemyAI.AttackHumans && !enemyAI.AttackRooms) { continue; }
bool specificMonsterMusicAvailable =
musicClips.Any(m => IsSuitableMusicClip(m, character.Params.MusicType, intensity));
if (specificMonsterMusicAvailable)
{
float maxDistSqr = MathF.Pow(enemyDistThreshold * character.Params.MusicRangeMultiplier, 2);
if (targetSubmarine != null)
{
if (Vector2.DistanceSquared(character.WorldPosition, targetSubmarine.WorldPosition) < maxDistSqr)
{
monsterMusicCharacters.Add(character);
}
}
else if (Character.Controlled != null)
{
if (Vector2.DistanceSquared(character.WorldPosition, Character.Controlled.WorldPosition) < maxDistSqr)
{
monsterMusicCharacters.Add(character);
}
}
}
}
if (monsterMusicCharacters.Any())
{
Character chosenCharacter = monsterMusicCharacters.GetRandomByWeight(c => c.Params.MusicCommonness, Rand.RandSync.Unsynced);
return chosenCharacter.Params.MusicType;
}
if (targetSubmarine != null && targetSubmarine.AtDamageDepth)
{
return "deep".ToIdentifier();
@@ -898,41 +962,6 @@ namespace Barotrauma
if (totalArea > 0.0f && floodedArea / totalArea > 0.25f) { return "flooded".ToIdentifier(); }
}
float intensity = (GameMain.GameSession?.EventManager?.MusicIntensity ?? 0) * 100.0f;
bool anyMonsterMusicAvailable =
musicClips.Any(m => IsSuitableMusicClip(m, "monster".ToIdentifier(), intensity) || IsSuitableMusicClip(m, "monsterambience".ToIdentifier(), intensity));
if (anyMonsterMusicAvailable)
{
float enemyDistThreshold = 5000.0f;
if (targetSubmarine != null)
{
enemyDistThreshold = Math.Max(enemyDistThreshold, Math.Max(targetSubmarine.Borders.Width, targetSubmarine.Borders.Height) * 2.0f);
}
foreach (Character character in Character.CharacterList)
{
if (character.IsDead || !character.Enabled) { continue; }
if (character.AIController is not EnemyAIController { Enabled: true } enemyAI) { continue; }
if (!enemyAI.AttackHumans && !enemyAI.AttackRooms) { continue; }
if (targetSubmarine != null)
{
if (Vector2.DistanceSquared(character.WorldPosition, targetSubmarine.WorldPosition) < enemyDistThreshold * enemyDistThreshold)
{
return "monster".ToIdentifier();
}
}
else if (Character.Controlled != null)
{
if (Vector2.DistanceSquared(character.WorldPosition, Character.Controlled.WorldPosition) < enemyDistThreshold * enemyDistThreshold)
{
return "monster".ToIdentifier();
}
}
}
}
if (GameMain.GameSession != null)
{
if (Submarine.Loaded != null && Level.Loaded != null && Submarine.MainSub != null && Submarine.MainSub.AtEndExit)
@@ -1012,7 +1041,7 @@ namespace Barotrauma
{
GUISound.GUISoundPrefabs
.Where(s => s.Type == soundType)
.GetRandomUnsynced()?.Sound?.Play(null, "ui");
.GetRandomUnsynced()?.Sound?.Play(null, SoundManager.SoundCategoryUi);
}
public static void PlayUISound(GUISoundType? soundType)
@@ -248,6 +248,10 @@ namespace Barotrauma
public readonly bool StartFromRandomTime;
public readonly bool ContinueFromPreviousTime;
public int PreviousTime;
/// <summary>
/// The music is forced to play at least for this long when it triggers, even if the situation changes and makes the music no longer suitable.
/// </summary>
public readonly float MinimumPlayDuration;
public BackgroundMusic(ContentXElement element, SoundsFile file) : base(element, file, stream: true)
{
@@ -260,7 +264,8 @@ namespace Barotrauma
ForceIntensityTrack = element.GetAttributeFloat(nameof(ForceIntensityTrack), 0.0f);
}
StartFromRandomTime = element.GetAttributeBool(nameof(StartFromRandomTime), false);
ContinueFromPreviousTime = element.GetAttributeBool(nameof(ContinueFromPreviousTime), false);
ContinueFromPreviousTime = element.GetAttributeBool(nameof(ContinueFromPreviousTime), false);
MinimumPlayDuration = element.GetAttributeFloat(nameof(MinimumPlayDuration), 0.0f);
}
}
@@ -76,7 +76,7 @@ namespace Barotrauma.Sounds
soundChannel = null;
}
}
chn = new SoundChannel(this, gain, null, 1.0f, 1.0f, 3.0f, "video", false);
chn = new SoundChannel(this, gain, null, 1.0f, 1.0f, 3.0f, "video".ToIdentifier(), false);
lock (mutex)
{
soundChannel = chn;
@@ -81,7 +81,7 @@ namespace Barotrauma.Sounds
soundChannel = null;
SoundChannel chn = new SoundChannel(this, 1.0f, null, 1.0f, 0.4f, 1.0f, "voip", false);
SoundChannel chn = new SoundChannel(this, 1.0f, null, 1.0f, 0.4f, 1.0f, SoundManager.SoundCategoryVoip, false);
soundChannel = chn;
Gain = 1.0f;
}