OBT/1.2.1(Summer update)

Sync with upstream
This commit is contained in:
NotAlwaysTrue
2026-06-16 22:17:29 +08:00
committed by GitHub
parent 59bc21973a
commit d109c8f827
85 changed files with 1377 additions and 497 deletions
@@ -2971,11 +2971,39 @@ namespace Barotrauma
string percentage = string.Format(CultureInfo.InvariantCulture, "{0:P2}", (float)spawnPointsContainingResources / PathPoints.Count);
DebugConsole.NewMessage($"Level resources spawned: {itemCount}\n" +
$" Spawn points containing resources: {spawnPointsContainingResources} ({percentage})\n" +
$" Total value: {PathPoints.Sum(p => p.ClusterLocations.Sum(c => c.Resources.Sum(r => r.Prefab.DefaultPrice?.Price ?? 0)))} mk");
$" Total value: {GetTotalLevelResourceValue()} mk");
if (AbyssResources.Count > 0)
{
DebugConsole.NewMessage($"Abyss resources spawned: {AbyssResources.Sum(a => a.Resources.Count)}\n" +
$" Total value: {AbyssResources.Sum(c => c.Resources.Sum(r => r.Prefab.DefaultPrice?.Price ?? 0))} mk");
$" Total value: {GetTotalAbyssResourceValue()} mk");
}
int GetTotalLevelResourceValue()
{
int value = 0;
foreach (var pathPoint in PathPoints)
{
foreach (var clusterLocation in pathPoint.ClusterLocations)
{
foreach (var resource in clusterLocation.Resources)
{
value += resource.Prefab.DefaultPrice?.Price ?? 0;
}
}
}
return value;
}
int GetTotalAbyssResourceValue()
{
int value = 0;
foreach (var clusterLocation in AbyssResources)
{
foreach (var resource in clusterLocation.Resources)
{
value += resource.Prefab.DefaultPrice?.Price ?? 0;
}
}
return value;
}
#endif
@@ -3204,7 +3232,6 @@ namespace Barotrauma
}
}
/// <param name="rotation">Used by clients to set the rotation for the resources</param>
public List<Item> GenerateMissionResources(ItemPrefab prefab, int requiredAmount, PositionType positionType, IEnumerable<Cave> targetCaves = null)
{
var allValidLocations = GetAllValidClusterLocations();
@@ -5150,6 +5177,7 @@ namespace Barotrauma
renderer.Dispose();
renderer = null;
}
backgroundCreatureManager?.Clear();
#endif
if (LevelObjectManager != null)
@@ -11,7 +11,7 @@ namespace Barotrauma
partial class LevelObject : ISpatialEntity, IDamageable, ISerializableEntity
{
public readonly LevelObjectPrefab Prefab;
public Vector3 Position;
public Vector3 Position { get; set; }
public float NetworkUpdateTimer;
@@ -457,7 +457,7 @@ namespace Barotrauma
if (newObject.NeedsUpdate) { updateableObjects.Add(newObject); }
//add some variance to the Z position to prevent z-fighting
//(based on the x and y position of the object, scaled to be visually insignificant)
newObject.Position.Z += (minX + minY) % 100.0f * 0.00001f;
newObject.Position += new Vector3(0, 0, (minX + minY) % 100.0f * 0.00001f);
int xStart = (int)Math.Floor(minX / GridSize);
int xEnd = (int)Math.Floor(maxX / GridSize);
@@ -348,11 +348,22 @@ namespace Barotrauma
{
price *= 1f - characters.Max(static c => c.GetStatValue(StatTypes.StoreBuyMultiplierAffiliated, includeSaved: false));
price *= 1f - characters.Max(static c => c.Info.GetSavedStatValue(StatTypes.StoreBuyMultiplierAffiliated, Tags.StatIdentifierTargetAll));
price *= 1f - characters.Max(c => item.Tags.Sum(tag => c.Info.GetSavedStatValue(StatTypes.StoreBuyMultiplierAffiliated, tag)));
price *= 1f - characters.Max(c => GetStatValuesForItem(c, item, StatTypes.StoreBuyMultiplierAffiliated));
}
price *= 1f - characters.Max(static c => c.GetStatValue(StatTypes.StoreBuyMultiplier, includeSaved: false));
price *= 1f - characters.Max(c => item.Tags.Sum(tag => c.Info.GetSavedStatValue(StatTypes.StoreBuyMultiplier, tag)));
price *= 1f - characters.Max(c => GetStatValuesForItem(c, item, StatTypes.StoreBuyMultiplier));
}
static float GetStatValuesForItem(Character character, ItemPrefab item, StatTypes statType)
{
float statValueSum = 0.0f;
foreach (Identifier itemTag in item.Tags)
{
statValueSum += character.Info.GetSavedStatValue(statType, itemTag);
}
return statValueSum;
}
// Price should never go below 1 mk
return Math.Max((int)price, 1);
}
@@ -487,7 +487,19 @@ namespace Barotrauma
var portrait = new Sprite(subElement, lazyLoad: true);
if (portrait != null)
{
#if CLIENT
if (!File.Exists(portrait.FilePath))
{
DebugConsole.ThrowError($"Error in location type \"{Identifier}\": cannot find the location portrait \"{portrait.FilePath}\".");
}
else
{
portraitsList.Add(portrait);
}
#elif SERVER
// Add without checking the path, since servers don't parse the file path of the sprite
portraitsList.Add(portrait);
#endif
}
break;
case "store":
@@ -261,15 +261,7 @@ namespace Barotrauma
}
}
foreach (var endLocation in EndLocations)
{
if (endLocation.Type?.ForceLocationName is { IsEmpty: false })
{
endLocation.ForceName(endLocation.Type.ForceLocationName);
}
}
AssignEndLocationLevelData();
AssignEndLocationLevelData(campaign);
//backwards compatibility: if locations go out of bounds (map saved with different generation parameters before width/height were included in the xml)
float maxX = Locations.Select(l => l.MapPosition.X).Max();
@@ -973,13 +965,43 @@ namespace Barotrauma
previousToEndLocation.Connections.Add(endConnection);
endLocation.Connections.Add(endConnection);
AssignEndLocationLevelData();
AssignEndLocationLevelData(campaign);
}
private void AssignEndLocationLevelData()
/// <summary>
/// Assigns the correct outpost generation parameters to the end locations. Also checks and ensures that all of them are correctly assigned to the end biome, and have a location type that can be generated in the end biome.
/// Strangely shaped custom maps may sometimes generate in a way that there aren't enough locations in the last biome to assign as the end locations, and we may end up choosing locations in the second-to-last biome instead - let's correct that here.
/// </summary>
/// <param name="campaign"></param>
/// <exception cref="InvalidOperationException"></exception>
private void AssignEndLocationLevelData(CampaignMode campaign)
{
Biome endBiome = Biome.Prefabs.OrderBy(p => p.UintIdentifier).FirstOrDefault(b => b.IsEndBiome) ?? throw new InvalidOperationException("Could not find an end biome to assign to the end locations.");
LocationType endLocationType =
LocationType.Prefabs
.OrderBy(p => p.UintIdentifier)
.FirstOrDefault(IsSuitableEndLocationType)
?? throw new InvalidOperationException("Could not find an a location type to assign to the end locations.");
bool IsSuitableEndLocationType(LocationType lt)
{
return lt.AreaSettings.Any(s =>
s.Commonness > 0 &&
(s.MatchesBiome(endBiome.Identifier) || s.MatchesZone(generationParams.DifficultyZones)));
}
for (int i = 0; i < endLocations.Count; i++)
{
if (endLocations[i].Biome != endBiome)
{
endLocations[i].Biome = endBiome;
endLocations[i].LevelData = new LevelData(endLocations[i], this, endLocations[i].LevelData.Difficulty);
}
endLocations[i].ChangeType(campaign: campaign, endLocationType);
if (endLocationType.ForceLocationName is { IsEmpty: false })
{
endLocations[i].ForceName(endLocationType.ForceLocationName);
}
endLocations[i].LevelData.ReassignGenerationParams(Seed);
var outpostParams = OutpostGenerationParams.OutpostParams.FirstOrDefault(p => p.ForceToEndLocationIndex == i);
if (outpostParams != null)
@@ -275,7 +275,7 @@ namespace Barotrauma
{
CreateStairBodies();
}
else if (HasBody)
else if (Prefab.Body)
{
CreateSections();
UpdateSections();
@@ -346,7 +346,7 @@ namespace Barotrauma
{
Rectangle oldRect = Rect;
base.Rect = value;
if (HasBody)
if (Prefab.Body)
{
CreateSections();
UpdateSections();
@@ -668,7 +668,7 @@ namespace Barotrauma
{
prevSections = Sections.ToArray();
}
if (!HasBody)
if (!Prefab.Body)
{
if (FlippedX && IsHorizontal)
{
@@ -685,7 +685,7 @@ namespace Barotrauma
xsections = 1;
ysections = 1;
}
Sections = new WallSection[xsections];
Sections = new WallSection[Math.Max(xsections, ysections)];
}
else
{
@@ -1635,7 +1635,7 @@ namespace Barotrauma
CreateStairBodies();
}
if (HasBody)
if (Prefab.Body)
{
CreateSections();
UpdateSections();
@@ -1663,7 +1663,7 @@ namespace Barotrauma
CreateStairBodies();
}
if (HasBody)
if (Prefab.Body)
{
CreateSections();
UpdateSections();
@@ -29,6 +29,31 @@ namespace Barotrauma
partial class SubmarineInfo : IDisposable
{
public static HashSet<string> SubmarinePathsWithRemoteStorage { get; set; } = [];
public bool SaveToRemoteStorage
{
get
{
if (FilePath == null) { return false; }
return SubmarinePathsWithRemoteStorage.Contains(FilePath.CleanUpPathCrossPlatform(correctFilenameCase: false));
}
set
{
if (FilePath == null) { return; }
if (value)
{
SubmarinePathsWithRemoteStorage.Add(FilePath.CleanUpPathCrossPlatform(correctFilenameCase: false));
}
else
{
SubmarinePathsWithRemoteStorage.Remove(FilePath.CleanUpPathCrossPlatform(correctFilenameCase: false));
}
}
}
private static List<SubmarineInfo> savedSubmarines = new List<SubmarineInfo>();
public static IEnumerable<SubmarineInfo> SavedSubmarines => savedSubmarines;
@@ -197,6 +222,8 @@ namespace Barotrauma
set;
}
public bool IsFromRemoteStorage;
/// <summary>
/// When enabled, the <see cref="SubmarineElement">XML element is not loaded</see> until it is accessed.
/// </summary>