Unstable 1.8.4.0

This commit is contained in:
Markus Isberg
2025-03-12 12:56:27 +00:00
parent a4c3e868e4
commit a4a3427e4e
627 changed files with 29860 additions and 10018 deletions
@@ -26,7 +26,7 @@ namespace Barotrauma
private Vector3 velocity;
private float depth;
public float Depth { get; private set; }
private float alpha = 1.0f;
@@ -42,6 +42,8 @@ namespace Barotrauma
Vector2 drawPosition;
private bool flippedHorizontally;
public Vector2[,] CurrentSpriteDeformation
{
get;
@@ -88,6 +90,8 @@ namespace Barotrauma
Rand.Range(-prefab.Speed, prefab.Speed, Rand.RandSync.ClientOnly),
Rand.Range(0.0f, prefab.WanderZAmount, Rand.RandSync.ClientOnly));
Depth = Rand.Range(prefab.MinDepth, prefab.MaxDepth, Rand.RandSync.ClientOnly);
checkWallsTimer = Rand.Range(0.0f, CheckWallsInterval, Rand.RandSync.ClientOnly);
foreach (var subElement in prefab.Config.Elements())
@@ -104,6 +108,7 @@ namespace Barotrauma
default:
continue;
}
int j = 0;
foreach (XElement animationElement in subElement.Elements())
{
SpriteDeformation deformation = null;
@@ -118,7 +123,21 @@ namespace Barotrauma
deformation = SpriteDeformation.Load(animationElement, prefab.Name);
if (deformation != null)
{
deformation.Params = Prefab.SpriteDeformations[j].Params;
uniqueSpriteDeformations.Add(deformation);
if (prefab.DeformableSprite != null)
{
if (deformation.Resolution.X > prefab.DeformableSprite.Subdivisions.X ||
deformation.Resolution.Y > prefab.DeformableSprite.Subdivisions.Y)
{
DebugConsole.AddWarning(
$"Potential error in background creature {Prefab.Identifier}: deformation {deformation.GetType()} has a larger resolution ({deformation.Resolution})"+
$" than the amount of subdivisions on the deformable sprite ({prefab.DeformableSprite.Subdivisions}). Should the sprite be subdivided further to make full use of the deformation?",
contentPackage: Prefab.ContentPackage);
}
}
j++;
}
}
if (deformation != null)
@@ -127,12 +146,14 @@ namespace Barotrauma
}
}
}
flashTimer = Rand.Range(0.0f, prefab.FlashInterval, Rand.RandSync.Unsynced);
}
public void Update(float deltaTime)
{
position += new Vector2(velocity.X, velocity.Y) * deltaTime;
depth = MathHelper.Clamp(depth + velocity.Z * deltaTime, Prefab.MinDepth, Prefab.MaxDepth * 10);
Depth = MathHelper.Clamp(Depth + velocity.Z * deltaTime, Prefab.MinDepth, Prefab.MaxDepth);
if (Prefab.FlashInterval > 0.0f)
{
@@ -144,7 +165,7 @@ namespace Barotrauma
else
{
//value goes from 0 to 1 and back to 0 during the flash
alpha = (float)Math.Sin(-flashTimer / Prefab.FlashDuration * MathHelper.Pi) * PerlinNoise.GetPerlin((float)Timing.TotalTime * 0.1f, (float)Timing.TotalTime * 0.2f);
alpha = (float)Math.Sin(-flashTimer / Prefab.FlashDuration * MathHelper.Pi) * PerlinNoise.GetPerlin((float)Timing.TotalTime, (float)Timing.TotalTime * 0.5f);
if (flashTimer < -Prefab.FlashDuration)
{
flashTimer = Prefab.FlashInterval;
@@ -228,7 +249,13 @@ namespace Barotrauma
velocity = Vector3.Lerp(velocity, new Vector3(Steering.X, Steering.Y, velocity.Z), deltaTime);
UpdateDeformations(deltaTime);
//only flip if there's some horizontal movement speed (10% of the creature's speed)
//otherwise a creature swimming roughly up/down can flip around very frequently when the horizontal speed fluctuates around 0
if (Math.Abs(velocity.X) > Prefab.Speed * 0.1f)
{
flippedHorizontally = !Prefab.DisableFlipping && velocity.X < 0.0f;
}
UpdateDeformations(deltaTime, flippedHorizontally);
}
public void DrawLightSprite(SpriteBatch spriteBatch, Camera cam)
@@ -238,12 +265,17 @@ namespace Barotrauma
public void Draw(SpriteBatch spriteBatch, Camera cam)
{
Draw(spriteBatch,
cam,
Prefab.Sprite,
Prefab.DeformableSprite,
CurrentSpriteDeformation,
Color.Lerp(Color.White, Level.Loaded.BackgroundColor, depth / Math.Max(MaxDepth, Prefab.MaxDepth)) * alpha);
Color color =
Prefab.FadeOut ?
Color.Lerp(Color.White, Level.Loaded.BackgroundColor, Depth / Prefab.FadeOutDepth) * alpha :
Color.White * alpha;
Draw(spriteBatch,
cam,
Prefab.Sprite,
Prefab.DeformableSprite,
CurrentSpriteDeformation,
color);
}
private void Draw(SpriteBatch spriteBatch, Camera cam, Sprite sprite, DeformableSprite deformableSprite, Vector2[,] currentSpriteDeformation, Color color)
@@ -255,7 +287,7 @@ namespace Barotrauma
if (!Prefab.DisableRotation)
{
rotation = MathUtils.VectorToAngle(new Vector2(velocity.X, -velocity.Y));
if (velocity.X < 0.0f) { rotation -= MathHelper.Pi; }
if (flippedHorizontally) { rotation -= MathHelper.Pi; }
}
drawPosition = GetDrawPosition(cam);
@@ -266,8 +298,8 @@ namespace Barotrauma
color,
rotation,
scale,
Prefab.DisableFlipping || velocity.X > 0.0f ? SpriteEffects.None : SpriteEffects.FlipHorizontally,
Math.Min(depth / MaxDepth, 1.0f));
flippedHorizontally ? SpriteEffects.FlipHorizontally : SpriteEffects.None,
Math.Min(Depth / MaxDepth, 1.0f));
if (deformableSprite != null)
{
@@ -280,29 +312,29 @@ namespace Barotrauma
deformableSprite.Reset();
}
deformableSprite?.Draw(cam,
new Vector3(drawPosition.X, drawPosition.Y, Math.Min(depth / 10000.0f, 1.0f)),
new Vector3(drawPosition.X, drawPosition.Y, Math.Min(Depth / 10000.0f, 1.0f)),
deformableSprite.Origin,
rotation,
Vector2.One * scale,
color,
mirror: Prefab.DisableFlipping || velocity.X <= 0.0f);
mirror: flippedHorizontally);
}
}
public Vector2 GetDrawPosition(Camera cam)
{
Vector2 drawPosition = WorldPosition;
if (depth >= 0)
if (Depth >= 0)
{
Vector2 camOffset = drawPosition - cam.WorldViewCenter;
drawPosition -= camOffset * depth / MaxDepth;
drawPosition -= camOffset * Depth / MaxDepth;
}
return drawPosition;
}
public float GetScale()
{
return Math.Max(1.0f - depth / MaxDepth, 0.05f) * Prefab.Scale;
return Math.Max(1.0f - Depth / MaxDepth, 0.05f) * Prefab.Scale;
}
public Rectangle GetExtents(Camera cam)
@@ -328,7 +360,7 @@ namespace Barotrauma
}
}
private void UpdateDeformations(float deltaTime)
private void UpdateDeformations(float deltaTime, bool flippedHorizontally)
{
foreach (SpriteDeformation deformation in uniqueSpriteDeformations)
{
@@ -336,11 +368,13 @@ namespace Barotrauma
}
if (spriteDeformations.Count > 0)
{
CurrentSpriteDeformation = SpriteDeformation.GetDeformation(spriteDeformations, Prefab.DeformableSprite.Size);
CurrentSpriteDeformation = SpriteDeformation.GetDeformation(spriteDeformations, Prefab.DeformableSprite.Size,
flippedHorizontally: flippedHorizontally);
}
if (lightSpriteDeformations.Count > 0)
{
CurrentLightSpriteDeformation = SpriteDeformation.GetDeformation(lightSpriteDeformations, Prefab.DeformableLightSprite.Size);
CurrentLightSpriteDeformation = SpriteDeformation.GetDeformation(lightSpriteDeformations, Prefab.DeformableLightSprite.Size,
flippedHorizontally: flippedHorizontally);
}
}
}
@@ -15,18 +15,19 @@ namespace Barotrauma
private float checkVisibleTimer;
private readonly List<BackgroundCreaturePrefab> prefabs = new List<BackgroundCreaturePrefab>();
private readonly List<BackgroundCreature> creatures = new List<BackgroundCreature>();
public BackgroundCreatureManager(IEnumerable<BackgroundCreaturePrefabsFile> files)
private readonly List<BackgroundCreature> visibleCreatures = new List<BackgroundCreature>();
public BackgroundCreatureManager()
{
foreach(var file in files)
/*foreach(var file in files)
{
LoadConfig(file.Path);
}
}*/
}
public BackgroundCreatureManager(string path)
/*public BackgroundCreatureManager(string path)
{
DebugConsole.AddWarning($"Couldn't find any BackgroundCreaturePrefabs files, falling back to {path}");
LoadConfig(ContentPath.FromRaw(null, path));
@@ -42,35 +43,34 @@ namespace Barotrauma
if (mainElement.IsOverride())
{
mainElement = mainElement.FirstElement();
prefabs.Clear();
Prefabs.Clear();
DebugConsole.NewMessage($"Overriding all background creatures with '{configPath}'", Color.MediumPurple);
}
else if (prefabs.Any())
else if (Prefabs.Any())
{
DebugConsole.NewMessage($"Loading additional background creatures from file '{configPath}'");
}
foreach (var element in mainElement.Elements())
{
prefabs.Add(new BackgroundCreaturePrefab(element));
Prefabs.Add(new BackgroundCreaturePrefab(element));
};
}
catch (Exception e)
{
DebugConsole.ThrowError(String.Format("Failed to load BackgroundCreatures from {0}", configPath), e);
}
}
}*/
public void SpawnCreatures(Level level, int count, Vector2? position = null)
{
creatures.Clear();
if (prefabs.Count == 0) { return; }
List<BackgroundCreaturePrefab> availablePrefabs = new List<BackgroundCreaturePrefab>(BackgroundCreaturePrefab.Prefabs.OrderBy(p => p.Identifier.Value));
if (availablePrefabs.Count == 0) { return; }
count = Math.Min(count, MaxCreatures);
List<BackgroundCreaturePrefab> availablePrefabs = new List<BackgroundCreaturePrefab>(prefabs);
for (int i = 0; i < count; i++)
{
Vector2 pos = Vector2.Zero;
@@ -93,7 +93,7 @@ namespace Barotrauma
pos = (Vector2)position;
}
var prefab = ToolBox.SelectWeightedRandom(availablePrefabs, availablePrefabs.Select(p => p.GetCommonness(level.GenerationParams)).ToList(), Rand.RandSync.ClientOnly);
var prefab = ToolBox.SelectWeightedRandom(availablePrefabs, availablePrefabs.Select(p => p.GetCommonness(level?.LevelData)).ToList(), Rand.RandSync.ClientOnly);
if (prefab == null) { break; }
int amount = Rand.Range(prefab.SwarmMin, prefab.SwarmMax + 1, Rand.RandSync.ClientOnly);
@@ -125,16 +125,27 @@ namespace Barotrauma
{
if (checkVisibleTimer < 0.0f)
{
visibleCreatures.Clear();
int margin = 500;
foreach (BackgroundCreature creature in creatures)
{
Rectangle extents = creature.GetExtents(cam);
bool wasVisible = creature.Visible;
creature.Visible =
extents.Right >= cam.WorldView.X - margin &&
extents.X <= cam.WorldView.Right + margin &&
extents.Bottom >= cam.WorldView.Y - cam.WorldView.Height - margin &&
extents.Y <= cam.WorldView.Y + margin;
if (creature.Visible)
{
//insertion sort according to depth
int i = 0;
while (i < visibleCreatures.Count)
{
if (visibleCreatures[i].Depth < creature.Depth) { break; }
i++;
}
visibleCreatures.Insert(i, creature);
}
}
checkVisibleTimer = VisibilityCheckInterval;
@@ -144,27 +155,24 @@ namespace Barotrauma
checkVisibleTimer -= deltaTime;
}
foreach (BackgroundCreature creature in creatures)
foreach (BackgroundCreature creature in visibleCreatures)
{
if (!creature.Visible) { continue; }
creature.Update(deltaTime);
}
}
public void Draw(SpriteBatch spriteBatch, Camera cam)
{
foreach (BackgroundCreature creature in creatures)
foreach (BackgroundCreature creature in visibleCreatures)
{
if (!creature.Visible) { continue; }
creature.Draw(spriteBatch, cam);
}
}
public void DrawLights(SpriteBatch spriteBatch, Camera cam)
{
foreach (BackgroundCreature creature in creatures)
foreach (BackgroundCreature creature in visibleCreatures)
{
if (!creature.Visible) { continue; }
creature.DrawLightSprite(spriteBatch, cam);
}
}
@@ -1,65 +1,91 @@
using System.Collections.Generic;
using Barotrauma.SpriteDeformations;
using System.Collections.Generic;
using System.Xml.Linq;
namespace Barotrauma
{
class BackgroundCreaturePrefab
class BackgroundCreaturePrefab : Prefab, ISerializableEntity
{
public readonly Sprite Sprite, LightSprite;
public readonly DeformableSprite DeformableSprite, DeformableLightSprite;
public readonly static PrefabCollection<BackgroundCreaturePrefab> Prefabs = new PrefabCollection<BackgroundCreaturePrefab>();
public readonly string Name;
public Sprite Sprite { get; private set; }
public Sprite LightSprite { get; private set; }
public DeformableSprite DeformableSprite { get; private set; }
public DeformableSprite DeformableLightSprite { get; private set; }
private readonly string name;
public readonly XElement Config;
[Serialize(1.0f, IsPropertySaveable.Yes)]
[Serialize(1.0f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0.0f, MaxValueFloat = 1000.0f)]
public float Speed { get; private set; }
[Serialize(0.0f, IsPropertySaveable.Yes)]
[Serialize(0.0f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0.0f, MaxValueFloat = 1000.0f, DecimalCount = 3)]
public float WanderAmount { get; private set; }
[Serialize(0.0f, IsPropertySaveable.Yes)]
[Serialize(0.0f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0.0f, MaxValueFloat = 100.0f, DecimalCount = 3)]
public float WanderZAmount { get; private set; }
[Serialize(1, IsPropertySaveable.Yes)]
[Serialize(1, IsPropertySaveable.Yes), Editable(MinValueInt = 0, MaxValueInt = 1000)]
public int SwarmMin { get; private set; }
[Serialize(1, IsPropertySaveable.Yes)]
[Serialize(1, IsPropertySaveable.Yes), Editable(MinValueInt = 0, MaxValueInt = 1000)]
public int SwarmMax { get; private set; }
[Serialize(200.0f, IsPropertySaveable.Yes)]
[Serialize(200.0f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0.0f, MaxValueFloat = 10000.0f)]
public float SwarmRadius { get; private set; }
[Serialize(0.2f, IsPropertySaveable.Yes)]
[Serialize(0.2f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0.0f, MaxValueFloat = 10.0f)]
public float SwarmCohesion { get; private set; }
[Serialize(10.0f, IsPropertySaveable.Yes)]
[Serialize(10.0f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0.0f, MaxValueFloat = 10000.0f)]
public float MinDepth { get; private set; }
[Serialize(1000.0f, IsPropertySaveable.Yes)]
[Serialize(1000.0f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0.0f, MaxValueFloat = 10000.0f)]
public float MaxDepth { get; private set; }
[Serialize(false, IsPropertySaveable.Yes)]
[Serialize(10000.0f, IsPropertySaveable.Yes, description: "Creatures fade out to the background color of the level the further they are from the camera. This value is the depth at which the object becomes \"maximally\" faded out."), Editable]
public float FadeOutDepth
{
get;
private set;
}
[Serialize(true, IsPropertySaveable.Yes), Editable]
public bool FadeOut { get; private set; }
[Serialize(false, IsPropertySaveable.Yes), Editable]
public bool DisableRotation { get; private set; }
[Serialize(false, IsPropertySaveable.Yes)]
[Serialize(false, IsPropertySaveable.Yes), Editable]
public bool DisableFlipping { get; private set; }
[Serialize(1.0f, IsPropertySaveable.Yes)]
[Serialize(1.0f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0.0f, MaxValueFloat = 100.0f)]
public float Scale { get; private set; }
[Serialize(1.0f, IsPropertySaveable.Yes)]
[Serialize(1.0f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0.0f, MaxValueFloat = 100.0f)]
public float Commonness { get; private set; }
[Serialize(1000, IsPropertySaveable.Yes)]
[Serialize(1000, IsPropertySaveable.Yes), Editable(MinValueInt = 0, MaxValueInt = 1000)]
public int MaxCount { get; private set; }
[Serialize(0.0f, IsPropertySaveable.Yes)]
[Serialize(0.0f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0.0f, MaxValueFloat = 1000.0f)]
public float FlashInterval { get; private set; }
[Serialize(0.0f, IsPropertySaveable.Yes)]
[Serialize(0.0f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0.0f, MaxValueFloat = 1000.0f)]
public float FlashDuration { get; private set; }
public string Name => name;
public Dictionary<Identifier, SerializableProperty> SerializableProperties { get; private set; }
/// <summary>
/// Only used for editing sprite deformation parameters. The actual LevelObjects use separate SpriteDeformation instances.
/// </summary>
public List<SpriteDeformation> SpriteDeformations
{
get;
private set;
} = new List<SpriteDeformation>();
/// <summary>
/// Overrides the commonness of the object in a specific level type.
@@ -67,13 +93,13 @@ namespace Barotrauma
/// </summary>
public Dictionary<Identifier, float> OverrideCommonness = new Dictionary<Identifier, float>();
public BackgroundCreaturePrefab(ContentXElement element)
public BackgroundCreaturePrefab(ContentXElement element, BackgroundCreaturePrefabsFile file) : base(file, ParseIdentifier(element))
{
Name = element.Name.ToString();
name = element.Name.ToString();
Config = element;
SerializableProperty.DeserializeProperties(this, element);
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
foreach (var subElement in element.Elements())
{
@@ -84,6 +110,14 @@ namespace Barotrauma
break;
case "deformablesprite":
DeformableSprite = new DeformableSprite(subElement, lazyLoad: true);
foreach (XElement deformElement in subElement.Elements())
{
var deformation = SpriteDeformation.Load(deformElement, Name);
if (deformation != null)
{
SpriteDeformations.Add(deformation);
}
}
break;
case "lightsprite":
LightSprite = new Sprite(subElement, lazyLoad: true);
@@ -102,17 +136,42 @@ namespace Barotrauma
}
}
public float GetCommonness(LevelGenerationParams generationParams)
public static Identifier ParseIdentifier(XElement element)
{
if (generationParams != null &&
!generationParams.Identifier.IsEmpty &&
(OverrideCommonness.TryGetValue(generationParams.Identifier, out float commonness) ||
(!generationParams.OldIdentifier.IsEmpty && OverrideCommonness.TryGetValue(generationParams.OldIdentifier, out commonness))))
Identifier identifier = element.GetAttributeIdentifier("identifier", "");
if (identifier.IsEmpty)
{
identifier = element.NameAsIdentifier();
}
return identifier;
}
public float GetCommonness(LevelData levelData)
{
if (levelData?.GenerationParams is not { } generationParams || generationParams.Identifier.IsEmpty)
{
return Commonness;
}
if (OverrideCommonness.TryGetValue(generationParams.Identifier, out float commonness) || (!generationParams.OldIdentifier.IsEmpty && OverrideCommonness.TryGetValue(generationParams.OldIdentifier, out commonness)) ||
OverrideCommonness.TryGetValue(levelData.Biome.Identifier, out commonness))
{
return commonness;
}
return Commonness;
}
public override void Dispose()
{
Sprite?.Remove();
Sprite = null;
LightSprite?.Remove();
LightSprite = null;
DeformableLightSprite?.Remove();
DeformableLightSprite = null;
DeformableSprite?.Remove();
DeformableSprite = null;
}
}
}