Release 1.10.5.0 - Autumn Update 2025

This commit is contained in:
Regalis11
2025-09-17 13:44:21 +03:00
parent d13836ce87
commit caa0326cf8
120 changed files with 2584 additions and 635 deletions
@@ -2,6 +2,7 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Xml.Linq;
@@ -23,10 +24,12 @@ namespace Barotrauma
private bool swarmSpawned;
private readonly List<MonsterSet> monsterSets = new List<MonsterSet>();
private readonly LocalizedString sonarLabel;
private readonly ImmutableArray<Identifier> beaconTags;
public BeaconMission(MissionPrefab prefab, Location[] locations, Submarine sub) : base(prefab, locations, sub)
{
swarmSpawned = false;
beaconTags = prefab.ConfigElement.GetAttributeIdentifierArray("beacontags", []).ToImmutableArray();
foreach (var monsterElement in prefab.ConfigElement.GetChildElements("monster"))
{
@@ -185,6 +188,29 @@ namespace Barotrauma
{
levelData.HasBeaconStation = true;
levelData.IsBeaconActive = false;
if (beaconTags.Length > 0)
{
var selectedBeacon = GetRandomBeaconByTags(beaconTags, levelData);
if (selectedBeacon != null)
{
levelData.ForceBeaconStation = selectedBeacon;
}
else
{
DebugConsole.ThrowError($"Beacon mission \"{Prefab.Identifier}\" could not find a suitable beacon station with beacontags \"{string.Join(", ", beaconTags)}\" for level difficulty {levelData.Difficulty:F1}.",
contentPackage: Prefab.ContentPackage);
}
}
}
private static SubmarineInfo GetRandomBeaconByTags(ImmutableArray<Identifier> tags, LevelData levelData)
{
return GetRandomSubmarineByTagsAndDifficulty(
tags,
levelData,
s => s.IsBeacon,
"beacon station");
}
}
}
@@ -48,7 +48,7 @@ namespace Barotrauma
protected static bool IsClient => GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient;
private readonly CheckDataAction completeCheckDataAction;
protected readonly CheckDataAction completeCheckDataAction;
public readonly ImmutableArray<LocalizedString> Headers;
public readonly ImmutableArray<LocalizedString> Messages;
@@ -110,9 +110,11 @@ namespace Barotrauma
public bool Failed
{
get { return failed; }
get { return failed || ForceFailure; }
}
public bool ForceFailure;
public virtual bool AllowRespawning
{
get { return true; }
@@ -541,9 +543,10 @@ namespace Barotrauma
{
if (GameMain.NetworkMember is not { IsClient: true })
{
completed =
completed =
!ForceFailure &&
DetermineCompleted() &&
(completeCheckDataAction == null ||completeCheckDataAction.GetSuccess());
(completeCheckDataAction == null || completeCheckDataAction.GetSuccess());
}
if (completed)
{
@@ -569,6 +572,10 @@ namespace Barotrauma
TimesAttempted++;
EndMissionSpecific(completed);
if (ForceFailure)
{
failed = true;
}
}
protected abstract bool DetermineCompleted();
@@ -829,6 +836,51 @@ namespace Barotrauma
cargoSpawnPos.Position.X + Rand.Range(-20.0f, 20.0f, Rand.RandSync.ServerAndClient),
cargoRoom.Rect.Y - cargoRoom.Rect.Height + itemPrefab.Size.Y / 2);
}
/// <summary>
/// Gets a random submarine by tags, filtered by difficulty. Used by missions that force specific submarines (wrecks, beacons, etc.)
/// </summary>
/// <param name="tags">Mission tags to match against</param>
/// <param name="seed">Random seed for selection</param>
/// <param name="submarineSelector">Function to filter submarines by type (e.g., s => s.IsWreck)</param>
/// <param name="submarineTypeName">Name of submarine type for error messages (e.g., "wreck", "beacon station")</param>
/// <returns>Selected submarine, or null if none found</returns>
protected static SubmarineInfo GetRandomSubmarineByTagsAndDifficulty(
IEnumerable<Identifier> tags,
LevelData levelData,
Func<SubmarineInfo, bool> submarineSelector,
string submarineTypeName)
{
var rand = new MTRandom(ToolBox.StringToInt(levelData.Seed));
float levelDifficulty = levelData.Difficulty;
var submarinesWithTags = SubmarineInfo.SavedSubmarines
.Where(submarineSelector)
.Where(s =>
{
return s.GetExtraSubmarineInfo is { } extraInfo && (tags.None() || tags.Any(t => extraInfo.MissionTags.Contains(t)));
})
.ToList();
var matchingSubmarines = submarinesWithTags
.Where(s =>
{
return s.GetExtraSubmarineInfo is { } extraInfo &&
levelDifficulty >= extraInfo.MinLevelDifficulty &&
levelDifficulty <= extraInfo.MaxLevelDifficulty;
})
.ToList();
if (matchingSubmarines.Count == 0)
{
if (submarinesWithTags.Count > 0)
{
DebugConsole.ThrowError($"Found {submarinesWithTags.Count} {submarineTypeName}(s) with matching tags \"{string.Join(", ", tags)}\", but none are suitable for level difficulty {levelDifficulty:F1}.");
}
return null;
}
return matchingSubmarines[rand.Next(matchingSubmarines.Count)];
}
}
class AbilityMissionMoneyGainMultiplier : AbilityObject, IAbilityValue, IAbilityMission
@@ -4,6 +4,7 @@ using FarseerPhysics;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
namespace Barotrauma
@@ -240,6 +241,8 @@ namespace Barotrauma
/// </summary>
private readonly float requiredDeliveryAmount;
private readonly ImmutableArray<Identifier> wreckTags;
private LocalizedString pickedUpMessage;
/// <summary>
@@ -311,12 +314,13 @@ namespace Barotrauma
: base(prefab, locations, sub)
{
requiredDeliveryAmount = prefab.ConfigElement.GetAttributeFloat(nameof(requiredDeliveryAmount), 0.98f);
//LevelData may not be instantiated at this point, in that case use the name identifier of the location
rng = new MTRandom(ToolBox.StringToInt(
locations[0].LevelData?.Seed ?? locations[0].NameIdentifier.Value +
locations[1].LevelData?.Seed ?? locations[1].NameIdentifier.Value));
wreckTags = prefab.ConfigElement.GetAttributeIdentifierArray("wrecktags", []).ToImmutableArray();
partiallyRetrievedMessage = GetMessage(nameof(partiallyRetrievedMessage));
allRetrievedMessage = GetMessage(nameof(allRetrievedMessage));
pickedUpMessage = GetMessage(nameof(pickedUpMessage));
@@ -756,5 +760,31 @@ namespace Barotrauma
target.Reset();
}
}
public override void AdjustLevelData(LevelData levelData)
{
if (wreckTags.Length > 0)
{
var selectedWreck = GetRandomWreckByTags(wreckTags, levelData);
if (selectedWreck != null)
{
levelData.ForceWreck = selectedWreck;
}
else
{
DebugConsole.ThrowError($"Salvage mission \"{Prefab.Identifier}\" could not find a suitable wreck with wrecktags \"{string.Join(", ", wreckTags)}\" for level difficulty {levelData.Difficulty:F1}.",
contentPackage: Prefab.ContentPackage);
}
}
}
private static SubmarineInfo GetRandomWreckByTags(ImmutableArray<Identifier> tags, LevelData levelData)
{
return GetRandomSubmarineByTagsAndDifficulty(
tags,
levelData,
s => s.IsWreck,
"wreck");
}
}
}