Unstable 1.8.4.0
This commit is contained in:
+55
-21
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+28
-20
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+88
-29
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,26 +9,56 @@ namespace Barotrauma
|
||||
{
|
||||
static partial class CaveGenerator
|
||||
{
|
||||
public static List<VertexPositionTexture> GenerateWallVertices(List<Vector2[]> triangles, LevelGenerationParams generationParams, float zCoord)
|
||||
public static List<VertexPositionColor> GenerateWallVertices(List<Vector2[]> triangles, Color color, float zCoord)
|
||||
{
|
||||
var vertices = new List<VertexPositionTexture>();
|
||||
var vertices = new List<VertexPositionColor>();
|
||||
for (int i = 0; i < triangles.Count; i++)
|
||||
{
|
||||
foreach (Vector2 vertex in triangles[i])
|
||||
{
|
||||
Vector2 uvCoords = vertex / generationParams.WallTextureSize;
|
||||
vertices.Add(new VertexPositionTexture(new Vector3(vertex, zCoord), uvCoords));
|
||||
vertices.Add(new VertexPositionColor(new Vector3(vertex, zCoord), color));
|
||||
}
|
||||
}
|
||||
|
||||
return vertices;
|
||||
}
|
||||
|
||||
public static List<VertexPositionTexture> GenerateWallEdgeVertices(List<VoronoiCell> cells, Level level, float zCoord)
|
||||
/// <summary>
|
||||
/// Generates texture coordinates for the vertices based on their positions
|
||||
/// </summary>
|
||||
public static VertexPositionColorTexture[] ConvertToTextured(VertexPositionColor[] verts, float textureSize)
|
||||
{
|
||||
float outWardThickness = level.GenerationParams.WallEdgeExpandOutwardsAmount;
|
||||
VertexPositionColorTexture[] texturedVerts = new VertexPositionColorTexture[verts.Length];
|
||||
for (int i = 0; i < verts.Length; i++)
|
||||
{
|
||||
VertexPositionColor vertex = verts[i];
|
||||
texturedVerts[i] = new VertexPositionColorTexture(vertex.Position, vertex.Color, textureCoordinate: Vector2.Zero);
|
||||
}
|
||||
GenerateTextureCoordinates(texturedVerts, textureSize);
|
||||
return texturedVerts;
|
||||
}
|
||||
|
||||
List<VertexPositionTexture> vertices = new List<VertexPositionTexture>();
|
||||
/// <summary>
|
||||
/// Generates texture coordinates for the vertices based on their positions
|
||||
/// </summary>
|
||||
public static void GenerateTextureCoordinates(VertexPositionColorTexture[] verts, float textureSize)
|
||||
{
|
||||
for (int i = 0; i < verts.Length; i++)
|
||||
{
|
||||
VertexPositionColorTexture vertex = verts[i];
|
||||
Vector2 uvCoords = new Vector2(vertex.Position.X, vertex.Position.Y) / textureSize;
|
||||
verts[i] = new VertexPositionColorTexture(verts[i].Position, verts[i].Color, uvCoords);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<VertexPositionColorTexture> GenerateWallEdgeVertices(
|
||||
List<VoronoiCell> cells,
|
||||
float expandOutwards, float expandInwards,
|
||||
Color outerColor, Color innerColor,
|
||||
Level level, float zCoord, bool preventExpandThroughCell = false)
|
||||
{
|
||||
float outWardThickness = expandOutwards;
|
||||
|
||||
List<VertexPositionColorTexture> vertices = new List<VertexPositionColorTexture>();
|
||||
foreach (VoronoiCell cell in cells)
|
||||
{
|
||||
Vector2 minVert = cell.Edges[0].Point1;
|
||||
@@ -49,7 +79,10 @@ namespace Barotrauma
|
||||
{
|
||||
if (!edge.IsSolid) { continue; }
|
||||
|
||||
GraphEdge leftEdge = cell.Edges.Find(e => e != edge && (edge.Point1.NearlyEquals(e.Point1) || edge.Point1.NearlyEquals(e.Point2)));
|
||||
//the left-side edge on this same cell
|
||||
GraphEdge myLeftEdge = cell.Edges.Find(e => e != edge && (edge.Point1.NearlyEquals(e.Point1) || edge.Point1.NearlyEquals(e.Point2)));
|
||||
//the left-side edge on either this cell, or the adjacent one if this is attached to another cell
|
||||
GraphEdge leftEdge = myLeftEdge;
|
||||
var leftAdjacentCell = leftEdge?.AdjacentCell(cell);
|
||||
if (leftAdjacentCell != null)
|
||||
{
|
||||
@@ -57,7 +90,10 @@ namespace Barotrauma
|
||||
if (adjEdge != null) { leftEdge = adjEdge; }
|
||||
}
|
||||
|
||||
GraphEdge rightEdge = cell.Edges.Find(e => e != edge && (edge.Point2.NearlyEquals(e.Point1) || edge.Point2.NearlyEquals(e.Point2)));
|
||||
//the right-side edge on this same cell
|
||||
GraphEdge myRightEdge = cell.Edges.Find(e => e != edge && (edge.Point2.NearlyEquals(e.Point1) || edge.Point2.NearlyEquals(e.Point2)));
|
||||
//the right-side edge on either this cell, or the adjacent one if this is attached to another cell
|
||||
GraphEdge rightEdge = myRightEdge;
|
||||
var rightAdjacentCell = rightEdge?.AdjacentCell(cell);
|
||||
if (rightAdjacentCell != null)
|
||||
{
|
||||
@@ -67,18 +103,25 @@ namespace Barotrauma
|
||||
|
||||
Vector2 leftNormal = Vector2.Zero, rightNormal = Vector2.Zero;
|
||||
|
||||
float inwardThickness1 = level.GenerationParams.WallEdgeExpandInwardsAmount;
|
||||
float inwardThickness2 = level.GenerationParams.WallEdgeExpandInwardsAmount;
|
||||
float inwardThickness1 = Math.Min(expandInwards, edge.Length);
|
||||
float inwardThickness2 = inwardThickness1;
|
||||
if (leftEdge != null && !leftEdge.IsSolid)
|
||||
{
|
||||
//the left-side edge is non-solid (an edge between two cells, not an actual solid wall edge)
|
||||
// -> expand in the direction of that edge
|
||||
leftNormal = edge.Point1.NearlyEquals(leftEdge.Point1) ?
|
||||
Vector2.Normalize(leftEdge.Point2 - leftEdge.Point1) :
|
||||
Vector2.Normalize(leftEdge.Point1 - leftEdge.Point2);
|
||||
//maximum expansion is half of the size of the edge (otherwise the expansions from different sides of the edge could overlap or even extend "through" the cell)
|
||||
inwardThickness1 = Math.Min(inwardThickness1, leftEdge.Length / 2);
|
||||
}
|
||||
else if (leftEdge != null)
|
||||
{
|
||||
//use the average of this edge's and the adjacent edge's normals
|
||||
leftNormal = -Vector2.Normalize(edge.GetNormal(cell) + leftEdge.GetNormal(leftAdjacentCell ?? cell));
|
||||
if (!MathUtils.IsValid(leftNormal)) { leftNormal = -edge.GetNormal(cell); }
|
||||
//maximum expansion is the length of the adjacent edge (more expansion causes the textures to distort)
|
||||
inwardThickness1 = Math.Min(Math.Min(inwardThickness1, leftEdge.Length), myLeftEdge.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -109,11 +152,13 @@ namespace Barotrauma
|
||||
rightNormal = edge.Point2.NearlyEquals(rightEdge.Point1) ?
|
||||
Vector2.Normalize(rightEdge.Point2 - rightEdge.Point1) :
|
||||
Vector2.Normalize(rightEdge.Point1 - rightEdge.Point2);
|
||||
inwardThickness2 = Math.Min(inwardThickness2, rightEdge.Length / 2);
|
||||
}
|
||||
else if (rightEdge != null)
|
||||
{
|
||||
rightNormal = -Vector2.Normalize(edge.GetNormal(cell) + rightEdge.GetNormal(rightAdjacentCell ?? cell));
|
||||
if (!MathUtils.IsValid(rightNormal)) { rightNormal = -edge.GetNormal(cell); }
|
||||
inwardThickness2 = Math.Min(Math.Min(inwardThickness2, rightEdge.Length), myRightEdge.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -150,10 +195,51 @@ namespace Barotrauma
|
||||
point1UV = point1UV / MathHelper.TwoPi * textureRepeatCount;
|
||||
point2UV = point2UV / MathHelper.TwoPi * textureRepeatCount;
|
||||
|
||||
//if calculating the UVs based on polar coordinates would result in stretching (using less than 10% of the texture for a wall the size of the texture)
|
||||
//just calculate the UVs based on the length of the wall
|
||||
//(this will mean the textures don't align at point2, but it doesn't seem that noticeable)
|
||||
if ((point2UV - point1UV) * level.GenerationParams.WallEdgeTextureWidth < edge.Length * 0.1f)
|
||||
{
|
||||
point2UV = point1UV + edge.Length / 2 / level.GenerationParams.WallEdgeTextureWidth;
|
||||
}
|
||||
|
||||
//"extruding" inwards, need to make sure we don't make the edge poke through the cell from the other side
|
||||
if (preventExpandThroughCell)
|
||||
{
|
||||
foreach (GraphEdge otherEdge in cell.Edges)
|
||||
{
|
||||
if (otherEdge == edge || Vector2.Dot(otherEdge.GetNormal(cell), edge.GetNormal(cell)) > 0) { continue; }
|
||||
if (otherEdge != leftEdge)
|
||||
{
|
||||
inwardThickness1 = ClampThickness(otherEdge, edge.Point1, leftNormal, inwardThickness1);
|
||||
}
|
||||
if (otherEdge != rightEdge)
|
||||
{
|
||||
inwardThickness2 = ClampThickness(otherEdge, edge.Point2, rightNormal, inwardThickness2);
|
||||
}
|
||||
}
|
||||
|
||||
static float ClampThickness(GraphEdge otherEdge, Vector2 thisPoint, Vector2 thisEdgeNormal, float currThickness)
|
||||
{
|
||||
if (MathUtils.GetLineIntersection(
|
||||
thisPoint, thisPoint + thisEdgeNormal * currThickness,
|
||||
otherEdge.Point1, otherEdge.Point2, areLinesInfinite: false, out Vector2 intersection1))
|
||||
{
|
||||
return Math.Min(currThickness, Vector2.Distance(thisPoint, intersection1));
|
||||
}
|
||||
return currThickness;
|
||||
}
|
||||
}
|
||||
|
||||
//there needs to be some minimum amount of inward thickness,
|
||||
//if the edge texture doesn't extend inside at all you can see through between the edge texture and the solid part of the cell
|
||||
inwardThickness1 = Math.Max(inwardThickness1, Math.Min(100.0f, expandInwards));
|
||||
inwardThickness2 = Math.Max(inwardThickness2, Math.Min(100.0f, expandInwards));
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Vector2[] verts = new Vector2[3];
|
||||
VertexPositionTexture[] vertPos = new VertexPositionTexture[3];
|
||||
VertexPositionColorTexture[] vertPos = new VertexPositionColorTexture[3];
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
@@ -161,9 +247,9 @@ namespace Barotrauma
|
||||
verts[1] = edge.Point2 - rightNormal * outWardThickness;
|
||||
verts[2] = edge.Point1 + leftNormal * inwardThickness1;
|
||||
|
||||
vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], zCoord), new Vector2(point1UV, 0.0f));
|
||||
vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], zCoord), new Vector2(point2UV, 0.0f));
|
||||
vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], zCoord), new Vector2(point1UV, 1.0f));
|
||||
vertPos[0] = new VertexPositionColorTexture(new Vector3(verts[0], zCoord), outerColor, new Vector2(point1UV, 0.0f));
|
||||
vertPos[1] = new VertexPositionColorTexture(new Vector3(verts[1], zCoord), outerColor, new Vector2(point2UV, 0.0f));
|
||||
vertPos[2] = new VertexPositionColorTexture(new Vector3(verts[2], zCoord), innerColor, new Vector2(point1UV, 1.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -172,9 +258,9 @@ namespace Barotrauma
|
||||
verts[1] = edge.Point2 - rightNormal * outWardThickness;
|
||||
verts[2] = edge.Point2 + rightNormal * inwardThickness2;
|
||||
|
||||
vertPos[0] = new VertexPositionTexture(new Vector3(verts[0], zCoord), new Vector2(point1UV, 1.0f));
|
||||
vertPos[1] = new VertexPositionTexture(new Vector3(verts[1], zCoord), new Vector2(point2UV, 0.0f));
|
||||
vertPos[2] = new VertexPositionTexture(new Vector3(verts[2], zCoord), new Vector2(point2UV, 1.0f));
|
||||
vertPos[0] = new VertexPositionColorTexture(new Vector3(verts[0], zCoord), innerColor, new Vector2(point1UV, 1.0f));
|
||||
vertPos[1] = new VertexPositionColorTexture(new Vector3(verts[1], zCoord), outerColor, new Vector2(point2UV, 0.0f));
|
||||
vertPos[2] = new VertexPositionColorTexture(new Vector3(verts[2], zCoord), innerColor, new Vector2(point2UV, 1.0f));
|
||||
}
|
||||
vertices.AddRange(vertPos);
|
||||
}
|
||||
|
||||
@@ -47,62 +47,75 @@ namespace Barotrauma
|
||||
if (renderer == null) { return; }
|
||||
renderer.DrawDebugOverlay(spriteBatch, cam);
|
||||
|
||||
if (GameMain.DebugDraw && Screen.Selected.Cam.Zoom > 0.1f)
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
foreach (InterestingPosition pos in PositionsOfInterest)
|
||||
if (Screen.Selected.Cam.Zoom > 0.1f)
|
||||
{
|
||||
Color color = Color.Yellow;
|
||||
if (pos.PositionType == PositionType.Cave || pos.PositionType == PositionType.AbyssCave)
|
||||
foreach (InterestingPosition pos in PositionsOfInterest)
|
||||
{
|
||||
color = Color.DarkOrange;
|
||||
}
|
||||
else if (pos.PositionType == PositionType.Ruin)
|
||||
{
|
||||
color = Color.LightGray;
|
||||
}
|
||||
if (!pos.IsValid)
|
||||
{
|
||||
color = Color.Red;
|
||||
}
|
||||
Color color = Color.Yellow;
|
||||
if (pos.PositionType == PositionType.Cave || pos.PositionType == PositionType.AbyssCave)
|
||||
{
|
||||
color = Color.DarkOrange;
|
||||
}
|
||||
else if (pos.PositionType == PositionType.Ruin)
|
||||
{
|
||||
color = Color.LightGray;
|
||||
}
|
||||
if (!pos.IsValid)
|
||||
{
|
||||
color = Color.Red;
|
||||
}
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Vector2(pos.Position.X - 15.0f, -pos.Position.Y - 15.0f), new Vector2(30.0f, 30.0f), color, true);
|
||||
GUI.DrawRectangle(spriteBatch, new Vector2(pos.Position.X - 15.0f, -pos.Position.Y - 15.0f), new Vector2(30.0f, 30.0f), color, true);
|
||||
}
|
||||
|
||||
foreach (RuinGeneration.Ruin ruin in Ruins)
|
||||
{
|
||||
Rectangle ruinArea = ruin.Area;
|
||||
ruinArea.Y = -ruinArea.Y - ruinArea.Height;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, ruinArea, Color.DarkSlateBlue, false, 0, 5);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (RuinGeneration.Ruin ruin in Ruins)
|
||||
{
|
||||
Rectangle ruinArea = ruin.Area;
|
||||
ruinArea.Y = -ruinArea.Y - ruinArea.Height;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, ruinArea, Color.DarkSlateBlue, false, 0, 5);
|
||||
}
|
||||
|
||||
foreach (var positions in wreckPositions.Values)
|
||||
|
||||
float zoomFactor = MathHelper.Lerp(20, 1, MathUtils.InverseLerp(Screen.Selected.Cam.MinZoom, Screen.Selected.Cam.DefaultZoom, Screen.Selected.Cam.Zoom));
|
||||
foreach ((string debugInfo, List<Vector2> positions) in positionHistory)
|
||||
{
|
||||
for (int i = 0; i < positions.Count; i++)
|
||||
{
|
||||
float t = (i + 1) / (float)positions.Count;
|
||||
float multiplier = MathHelper.Lerp(0, 1, t);
|
||||
float multiplier = MathHelper.Lerp(0.1f, 1, t);
|
||||
Color color = Color.Red * multiplier;
|
||||
var pos = positions[i];
|
||||
pos.Y = -pos.Y;
|
||||
var size = new Vector2(100);
|
||||
GUI.DrawRectangle(spriteBatch, pos - size / 2, size, color, thickness: 10);
|
||||
var size = new Vector2(200);
|
||||
if (i == 0)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, pos - size, size * 2, Color.Red, thickness: 2 * zoomFactor);
|
||||
GUI.DrawString(spriteBatch, pos - new Vector2(10, 20), debugInfo, Color.White, font: GUIStyle.LargeFont, forceUpperCase: ForceUpperCase.Yes);
|
||||
}
|
||||
if (i < positions.Count - 1)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, pos - size / 2, size, Color.Red, isFilled: true);
|
||||
}
|
||||
var nextPos = positions[i + 1];
|
||||
nextPos.Y = -nextPos.Y;
|
||||
GUI.DrawLine(spriteBatch, pos, nextPos, color, width: 10);
|
||||
GUI.DrawLine(spriteBatch, pos, nextPos, color, width: 4 * zoomFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var rects in blockedRects.Values)
|
||||
foreach ((Submarine sub, List<Rectangle> rects) in blockedRects)
|
||||
{
|
||||
foreach (var rect in rects)
|
||||
foreach (Rectangle t in rects)
|
||||
{
|
||||
Rectangle newRect = rect;
|
||||
Rectangle newRect = t;
|
||||
newRect.Y = -newRect.Y;
|
||||
GUI.DrawRectangle(spriteBatch, newRect, Color.Red, thickness: 5);
|
||||
GUI.DrawRectangle(spriteBatch, newRect, Color.Red * 0.1f, isFilled: true);
|
||||
GUI.DrawString(spriteBatch, newRect.Center.ToVector2(), $"{sub.Info.Name}", Color.White, font: GUIStyle.LargeFont, forceUpperCase: ForceUpperCase.Yes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ namespace Barotrauma
|
||||
Prefab.OverrideProperties.Any(p => p != null && (p.Sprites.Any() || p.DeformableSprite != null));
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
public void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
CurrentRotation = Rotation;
|
||||
if (ActivePrefab.SwingFrequency > 0.0f)
|
||||
@@ -190,20 +190,24 @@ namespace Barotrauma
|
||||
ScaleOscillateTimer += deltaTime * ActivePrefab.ScaleOscillationFrequency;
|
||||
ScaleOscillateTimer = ScaleOscillateTimer % MathHelper.TwoPi;
|
||||
CurrentScaleOscillation = Vector2.Lerp(CurrentScaleOscillation, ActivePrefab.ScaleOscillation, deltaTime * 10.0f);
|
||||
|
||||
|
||||
float sin = (float)Math.Sin(ScaleOscillateTimer);
|
||||
CurrentScale *= new Vector2(
|
||||
1.0f + sin * CurrentScaleOscillation.X,
|
||||
1.0f + sin * CurrentScaleOscillation.Y);
|
||||
1.0f + sin * CurrentScaleOscillation.Y);
|
||||
}
|
||||
|
||||
if (LightSources != null)
|
||||
{
|
||||
Vector2 position2D = new Vector2(Position.X, Position.Y);
|
||||
Vector2 camDiff = position2D - cam.WorldViewCenter;
|
||||
for (int i = 0; i < LightSources.Length; i++)
|
||||
{
|
||||
if (LightSourceTriggers[i] != null) LightSources[i].Enabled = LightSourceTriggers[i].IsTriggered;
|
||||
if (LightSourceTriggers[i] != null) { LightSources[i].Enabled = LightSourceTriggers[i].IsTriggered; }
|
||||
LightSources[i].Rotation = -CurrentRotation;
|
||||
LightSources[i].SpriteScale = CurrentScale;
|
||||
LightSources[i].Position =
|
||||
position2D - camDiff * Position.Z * LevelObjectManager.ParallaxStrength;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,7 +241,10 @@ namespace Barotrauma
|
||||
{
|
||||
SoundChannels[i] = roundSound.Sound.Play(roundSound.Volume, roundSound.Range, roundSound.GetRandomFrequencyMultiplier(), soundPos);
|
||||
}
|
||||
SoundChannels[i].Position = new Vector3(soundPos.X, soundPos.Y, 0.0f);
|
||||
if (SoundChannels[i] != null)
|
||||
{
|
||||
SoundChannels[i].Position = new Vector3(soundPos.X, soundPos.Y, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (SoundChannels[i] != null && SoundChannels[i].IsPlaying)
|
||||
@@ -259,7 +266,7 @@ namespace Barotrauma
|
||||
}
|
||||
deformation.Update(deltaTime);
|
||||
}
|
||||
CurrentSpriteDeformation = SpriteDeformation.GetDeformation(spriteDeformations, ActivePrefab.DeformableSprite.Size);
|
||||
CurrentSpriteDeformation = SpriteDeformation.GetDeformation(spriteDeformations, ActivePrefab.DeformableSprite.Size, flippedHorizontally: false);
|
||||
if (LightSources != null)
|
||||
{
|
||||
foreach (LightSource lightSource in LightSources)
|
||||
|
||||
+28
-10
@@ -10,9 +10,11 @@ namespace Barotrauma
|
||||
{
|
||||
partial class LevelObjectManager
|
||||
{
|
||||
private readonly List<LevelObject> visibleObjectsBack = new List<LevelObject>();
|
||||
private readonly List<LevelObject> visibleObjectsMid = new List<LevelObject>();
|
||||
private readonly List<LevelObject> visibleObjectsFront = new List<LevelObject>();
|
||||
// Pre-initialized to the max size, so that we don't have to resize the lists at runtime. TODO: Could the capacity (of some collections?) be lower?
|
||||
private readonly List<LevelObject> visibleObjectsBack = new List<LevelObject>(MaxVisibleObjects);
|
||||
private readonly List<LevelObject> visibleObjectsMid = new List<LevelObject>(MaxVisibleObjects);
|
||||
private readonly List<LevelObject> visibleObjectsFront = new List<LevelObject>(MaxVisibleObjects);
|
||||
private readonly HashSet<LevelObject> allVisibleObjects = new HashSet<LevelObject>(MaxVisibleObjects);
|
||||
|
||||
private double NextRefreshTime;
|
||||
|
||||
@@ -31,25 +33,41 @@ namespace Barotrauma
|
||||
visibleObjectsFront.Clear();
|
||||
}
|
||||
|
||||
partial void UpdateProjSpecific(float deltaTime)
|
||||
partial void UpdateProjSpecific(float deltaTime, Camera cam)
|
||||
{
|
||||
foreach (LevelObject obj in visibleObjectsBack)
|
||||
{
|
||||
obj.Update(deltaTime);
|
||||
obj.Update(deltaTime, cam);
|
||||
}
|
||||
foreach (LevelObject obj in visibleObjectsMid)
|
||||
{
|
||||
obj.Update(deltaTime);
|
||||
obj.Update(deltaTime, cam);
|
||||
}
|
||||
foreach (LevelObject obj in visibleObjectsFront)
|
||||
{
|
||||
obj.Update(deltaTime);
|
||||
obj.Update(deltaTime, cam);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<LevelObject> GetVisibleObjects()
|
||||
/// <summary>
|
||||
/// Returns all visible objects, but not in order, because internally uses a HashSet.
|
||||
/// </summary>
|
||||
public IEnumerable<LevelObject> GetAllVisibleObjects()
|
||||
{
|
||||
return visibleObjectsBack.Union(visibleObjectsMid).Union(visibleObjectsFront);
|
||||
allVisibleObjects.Clear();
|
||||
foreach (LevelObject obj in visibleObjectsBack)
|
||||
{
|
||||
allVisibleObjects.Add(obj);
|
||||
}
|
||||
foreach (LevelObject obj in visibleObjectsMid)
|
||||
{
|
||||
allVisibleObjects.Add(obj);
|
||||
}
|
||||
foreach (LevelObject obj in visibleObjectsFront)
|
||||
{
|
||||
allVisibleObjects.Add(obj);
|
||||
}
|
||||
return allVisibleObjects;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -207,7 +225,7 @@ namespace Barotrauma
|
||||
activeSprite?.Draw(
|
||||
spriteBatch,
|
||||
new Vector2(obj.Position.X, -obj.Position.Y) - camDiff * obj.Position.Z * ParallaxStrength,
|
||||
Color.Lerp(obj.Prefab.SpriteColor, obj.Prefab.SpriteColor.Multiply(Level.Loaded.BackgroundTextureColor), obj.Position.Z / 3000.0f),
|
||||
Color.Lerp(obj.Prefab.SpriteColor, obj.Prefab.SpriteColor.Multiply(Level.Loaded.BackgroundTextureColor), obj.Position.Z / obj.Prefab.FadeOutDepth),
|
||||
activeSprite.Origin,
|
||||
obj.CurrentRotation,
|
||||
obj.CurrentScale,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Particles;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
@@ -10,10 +11,25 @@ namespace Barotrauma
|
||||
{
|
||||
class LevelWallVertexBuffer : IDisposable
|
||||
{
|
||||
public VertexBuffer WallEdgeBuffer, WallBuffer;
|
||||
/// <summary>
|
||||
/// Buffer for the vertices of the "actual" wall texture.
|
||||
/// </summary>
|
||||
public VertexBuffer WallBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Buffer for the vertices of the repeating edge texture drawn at the edges of the walls.
|
||||
/// </summary>
|
||||
public VertexBuffer WallEdgeBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Buffer for the vertices of the inner, non-textured black part of the wall.
|
||||
/// </summary>
|
||||
public VertexBuffer WallInnerBuffer;
|
||||
|
||||
public readonly Texture2D WallTexture, EdgeTexture;
|
||||
private VertexPositionColorTexture[] wallVertices;
|
||||
private VertexPositionColorTexture[] wallEdgeVertices;
|
||||
private VertexPositionColor[] wallInnerVertices;
|
||||
|
||||
public bool IsDisposed
|
||||
{
|
||||
@@ -21,7 +37,7 @@ namespace Barotrauma
|
||||
private set;
|
||||
}
|
||||
|
||||
public LevelWallVertexBuffer(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Texture2D wallTexture, Texture2D edgeTexture, Color color)
|
||||
public LevelWallVertexBuffer(VertexPositionColorTexture[] wallVertices, VertexPositionColorTexture[] wallEdgeVertices, VertexPositionColor[] wallInnerVertices, Texture2D wallTexture, Texture2D edgeTexture)
|
||||
{
|
||||
if (wallVertices.Length == 0)
|
||||
{
|
||||
@@ -31,32 +47,41 @@ namespace Barotrauma
|
||||
{
|
||||
throw new ArgumentException("Failed to instantiate a LevelWallVertexBuffer (no wall edge vertices).");
|
||||
}
|
||||
this.wallVertices = LevelRenderer.GetColoredVertices(wallVertices, color);
|
||||
this.wallVertices = wallVertices;
|
||||
WallBuffer = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, wallVertices.Length, BufferUsage.WriteOnly);
|
||||
WallBuffer.SetData(this.wallVertices);
|
||||
WallTexture = wallTexture;
|
||||
|
||||
this.wallEdgeVertices = LevelRenderer.GetColoredVertices(wallEdgeVertices, color);
|
||||
this.wallEdgeVertices = wallEdgeVertices;
|
||||
WallEdgeBuffer = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, wallEdgeVertices.Length, BufferUsage.WriteOnly);
|
||||
WallEdgeBuffer.SetData(this.wallEdgeVertices);
|
||||
EdgeTexture = edgeTexture;
|
||||
|
||||
if (wallInnerVertices != null)
|
||||
{
|
||||
this.wallInnerVertices = wallInnerVertices;
|
||||
WallInnerBuffer = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColor.VertexDeclaration, wallInnerVertices.Length, BufferUsage.WriteOnly);
|
||||
WallInnerBuffer.SetData(this.wallInnerVertices);
|
||||
}
|
||||
}
|
||||
|
||||
public void Append(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Color color)
|
||||
public void Append(VertexPositionColorTexture[] newWallVertices, VertexPositionColorTexture[] newWallEdgeVertices, VertexPositionColor[] newWallInnerVertices)
|
||||
{
|
||||
WallBuffer.Dispose();
|
||||
WallBuffer = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, this.wallVertices.Length + wallVertices.Length, BufferUsage.WriteOnly);
|
||||
int originalWallVertexCount = this.wallVertices.Length;
|
||||
Array.Resize(ref this.wallVertices, originalWallVertexCount + wallVertices.Length);
|
||||
Array.Copy(LevelRenderer.GetColoredVertices(wallVertices, color), 0, this.wallVertices, originalWallVertexCount, wallVertices.Length);
|
||||
WallBuffer.SetData(this.wallVertices);
|
||||
WallBuffer = Append(WallBuffer, ref wallVertices, newWallVertices, VertexPositionColorTexture.VertexDeclaration);
|
||||
WallEdgeBuffer = Append(WallEdgeBuffer, ref wallEdgeVertices, newWallEdgeVertices, VertexPositionColorTexture.VertexDeclaration);
|
||||
WallInnerBuffer = Append(WallInnerBuffer, ref wallInnerVertices, newWallInnerVertices, VertexPositionColor.VertexDeclaration);
|
||||
|
||||
WallEdgeBuffer.Dispose();
|
||||
WallEdgeBuffer = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, this.wallEdgeVertices.Length + wallEdgeVertices.Length, BufferUsage.WriteOnly);
|
||||
int originalWallEdgeVertexCount = this.wallEdgeVertices.Length;
|
||||
Array.Resize(ref this.wallEdgeVertices, originalWallEdgeVertexCount + wallEdgeVertices.Length);
|
||||
Array.Copy(LevelRenderer.GetColoredVertices(wallEdgeVertices, color), 0, this.wallEdgeVertices, originalWallEdgeVertexCount, wallEdgeVertices.Length);
|
||||
WallEdgeBuffer.SetData(this.wallEdgeVertices);
|
||||
static VertexBuffer Append<T>(VertexBuffer buffer, ref T[] currentVertices, T[] newVertices, VertexDeclaration vertexDeclaration) where T : struct, IVertexType
|
||||
{
|
||||
buffer?.Dispose();
|
||||
int originalVertexCount = currentVertices.Length;
|
||||
int newBufferSize = originalVertexCount + newVertices.Length;
|
||||
buffer = new VertexBuffer(GameMain.Instance.GraphicsDevice, vertexDeclaration, newBufferSize, BufferUsage.WriteOnly);
|
||||
Array.Resize(ref currentVertices, newBufferSize);
|
||||
Array.Copy(newVertices, 0, currentVertices, originalVertexCount, newVertices.Length);
|
||||
buffer.SetData(currentVertices);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
@@ -69,7 +94,7 @@ namespace Barotrauma
|
||||
|
||||
class LevelRenderer : IDisposable
|
||||
{
|
||||
private static BasicEffect wallEdgeEffect, wallCenterEffect;
|
||||
private static BasicEffect wallEdgeEffect, wallCenterEffect, wallInnerEffect;
|
||||
|
||||
private Vector2 waterParticleOffset;
|
||||
private Vector2 waterParticleVelocity;
|
||||
@@ -128,7 +153,16 @@ namespace Barotrauma
|
||||
};
|
||||
wallCenterEffect.CurrentTechnique = wallCenterEffect.Techniques["BasicEffect_Texture"];
|
||||
}
|
||||
|
||||
|
||||
if (wallInnerEffect == null)
|
||||
{
|
||||
wallInnerEffect = new BasicEffect(GameMain.Instance.GraphicsDevice)
|
||||
{
|
||||
VertexColorEnabled = true,
|
||||
TextureEnabled = false
|
||||
};
|
||||
wallInnerEffect.CurrentTechnique = wallInnerEffect.Techniques["BasicEffect_Texture"];
|
||||
}
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
@@ -162,10 +196,7 @@ namespace Barotrauma
|
||||
if (flashCooldown <= 0.0f)
|
||||
{
|
||||
flashTimer = 1.0f;
|
||||
if (level.GenerationParams.FlashSound != null)
|
||||
{
|
||||
level.GenerationParams.FlashSound.Play(1.0f, "default");
|
||||
}
|
||||
level.GenerationParams.FlashSound?.Play(1.0f, Sounds.SoundManager.SoundCategoryDefault);
|
||||
flashCooldown = Rand.Range(level.GenerationParams.FlashInterval.X, level.GenerationParams.FlashInterval.Y, Rand.RandSync.Unsynced);
|
||||
}
|
||||
if (flashTimer > 0.0f)
|
||||
@@ -183,7 +214,7 @@ namespace Barotrauma
|
||||
//calculate the sum of the forces of nearby level triggers
|
||||
//and use it to move the water texture and water distortion effect
|
||||
Vector2 currentWaterParticleVel = level.GenerationParams.WaterParticleVelocity;
|
||||
foreach (LevelObject levelObject in level.LevelObjectManager.GetVisibleObjects())
|
||||
foreach (LevelObject levelObject in level.LevelObjectManager.GetAllVisibleObjects())
|
||||
{
|
||||
if (levelObject.Triggers == null) { continue; }
|
||||
//use the largest water flow velocity of all the triggers
|
||||
@@ -224,22 +255,23 @@ namespace Barotrauma
|
||||
return verts;
|
||||
}
|
||||
|
||||
public void SetVertices(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Texture2D wallTexture, Texture2D edgeTexture, Color color)
|
||||
public void SetVertices(VertexPositionColorTexture[] wallVertices, VertexPositionColorTexture[] wallEdgeVertices, VertexPositionColor[] wallInnerVertices, Texture2D wallTexture, Texture2D edgeTexture)
|
||||
{
|
||||
var existingBuffer = vertexBuffers.Find(vb => vb.WallTexture == wallTexture && vb.EdgeTexture == edgeTexture);
|
||||
if (existingBuffer != null)
|
||||
{
|
||||
existingBuffer.Append(wallVertices, wallEdgeVertices,color);
|
||||
existingBuffer.Append(wallVertices, wallEdgeVertices, wallInnerVertices);
|
||||
}
|
||||
else
|
||||
{
|
||||
vertexBuffers.Add(new LevelWallVertexBuffer(wallVertices, wallEdgeVertices, wallTexture, edgeTexture, color));
|
||||
vertexBuffers.Add(new LevelWallVertexBuffer(wallVertices, wallEdgeVertices, wallInnerVertices, wallTexture, edgeTexture));
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawBackground(SpriteBatch spriteBatch, Camera cam,
|
||||
LevelObjectManager backgroundSpriteManager = null,
|
||||
BackgroundCreatureManager backgroundCreatureManager = null)
|
||||
BackgroundCreatureManager backgroundCreatureManager = null,
|
||||
ParticleManager particleManager = null)
|
||||
{
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.LinearWrap);
|
||||
|
||||
@@ -277,7 +309,7 @@ namespace Barotrauma
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred,
|
||||
BlendState.NonPremultiplied,
|
||||
SamplerState.LinearWrap, DepthStencilState.DepthRead, null, null,
|
||||
cam.Transform);
|
||||
cam.Transform);
|
||||
|
||||
backgroundSpriteManager?.DrawObjectsBack(spriteBatch, cam);
|
||||
if (cam.Zoom > 0.05f)
|
||||
@@ -321,6 +353,9 @@ namespace Barotrauma
|
||||
color: level.GenerationParams.WaterParticleColor * alpha, textureScale: new Vector2(texScale));
|
||||
}
|
||||
}
|
||||
|
||||
GameMain.ParticleManager?.Draw(spriteBatch, inWater: true, inSub: false, ParticleBlendState.AlphaBlend, background: true);
|
||||
|
||||
spriteBatch.End();
|
||||
|
||||
RenderWalls(GameMain.Instance.GraphicsDevice, cam);
|
||||
@@ -465,7 +500,8 @@ namespace Barotrauma
|
||||
var wallList = i == 0 ? level.ExtraWalls : level.UnsyncedExtraWalls;
|
||||
foreach (LevelWall wall in wallList)
|
||||
{
|
||||
if (!(wall is DestructibleLevelWall destructibleWall) || destructibleWall.Destroyed) { continue; }
|
||||
if (wall is not DestructibleLevelWall destructibleWall || destructibleWall.Destroyed) { continue; }
|
||||
if (!wall.IsVisible(cam.WorldView)) { continue; }
|
||||
|
||||
wallCenterEffect.Texture = level.GenerationParams.DestructibleWallSprite?.Texture ?? level.GenerationParams.WallSprite.Texture;
|
||||
wallCenterEffect.World = wall.GetTransform() * transformMatrix;
|
||||
@@ -491,15 +527,16 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
wallEdgeEffect.Alpha = 1.0f;
|
||||
wallCenterEffect.Alpha = 1.0f;
|
||||
|
||||
wallCenterEffect.World = transformMatrix;
|
||||
wallEdgeEffect.World = transformMatrix;
|
||||
wallEdgeEffect.Alpha = wallInnerEffect.Alpha = wallCenterEffect.Alpha = 1.0f;
|
||||
wallCenterEffect.World = wallInnerEffect.World = wallEdgeEffect.World = transformMatrix;
|
||||
|
||||
//render static walls
|
||||
foreach (var vertexBuffer in vertexBuffers)
|
||||
{
|
||||
wallInnerEffect.CurrentTechnique.Passes[0].Apply();
|
||||
graphicsDevice.SetVertexBuffer(vertexBuffer.WallInnerBuffer);
|
||||
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(vertexBuffer.WallInnerBuffer.VertexCount / 3.0f));
|
||||
|
||||
wallCenterEffect.Texture = vertexBuffer.WallTexture;
|
||||
wallCenterEffect.CurrentTechnique.Passes[0].Apply();
|
||||
graphicsDevice.SetVertexBuffer(vertexBuffer.WallBuffer);
|
||||
@@ -521,6 +558,7 @@ namespace Barotrauma
|
||||
foreach (LevelWall wall in wallList)
|
||||
{
|
||||
if (wall is DestructibleLevelWall) { continue; }
|
||||
if (!wall.IsVisible(cam.WorldView)) { continue; }
|
||||
//TODO: use LevelWallVertexBuffers for extra walls as well
|
||||
wallCenterEffect.World = wall.GetTransform() * transformMatrix;
|
||||
wallCenterEffect.Alpha = wall.Alpha;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -24,22 +23,47 @@ namespace Barotrauma
|
||||
Matrix.CreateTranslation(new Vector3(ConvertUnits.ToDisplayUnits(Body.Position), 0.0f));
|
||||
}
|
||||
|
||||
public void SetWallVertices(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Texture2D wallTexture, Texture2D edgeTexture, Color color)
|
||||
public void SetWallVertices(
|
||||
VertexPositionColorTexture[] wallVertices, VertexPositionColorTexture[] wallEdgeVertices,
|
||||
Texture2D wallTexture, Texture2D edgeTexture)
|
||||
{
|
||||
if (VertexBuffer != null && !VertexBuffer.IsDisposed) { VertexBuffer.Dispose(); }
|
||||
VertexBuffer = new LevelWallVertexBuffer(wallVertices, wallEdgeVertices, wallTexture, edgeTexture, color);
|
||||
VertexBuffer = new LevelWallVertexBuffer(wallVertices, wallEdgeVertices, wallInnerVertices: null, wallTexture, edgeTexture);
|
||||
}
|
||||
|
||||
public void GenerateVertices()
|
||||
{
|
||||
float zCoord = this is DestructibleLevelWall ? Rand.Range(0.9f, 1.0f) : 0.9f;
|
||||
List<VertexPositionTexture> wallVertices = CaveGenerator.GenerateWallVertices(triangles, level.GenerationParams, zCoord);
|
||||
var nonTexturedWallVerts =
|
||||
CaveGenerator.GenerateWallVertices(triangles, color, zCoord: 0.9f).ToArray();
|
||||
var wallVerts = CaveGenerator.ConvertToTextured(nonTexturedWallVerts, level.GenerationParams.WallTextureSize);
|
||||
SetWallVertices(
|
||||
wallVertices.ToArray(),
|
||||
CaveGenerator.GenerateWallEdgeVertices(Cells, level, zCoord).ToArray(),
|
||||
wallVertices: wallVerts,
|
||||
wallEdgeVertices: CaveGenerator.GenerateWallEdgeVertices(Cells,
|
||||
level.GenerationParams.WallEdgeExpandOutwardsAmount, level.GenerationParams.WallEdgeExpandInwardsAmount,
|
||||
outerColor: color, innerColor: color,
|
||||
level, zCoord)
|
||||
.ToArray(),
|
||||
level.GenerationParams.WallSprite.Texture,
|
||||
level.GenerationParams.WallEdgeSprite.Texture,
|
||||
color);
|
||||
level.GenerationParams.WallEdgeSprite.Texture);
|
||||
}
|
||||
|
||||
public bool IsVisible(Rectangle worldView)
|
||||
{
|
||||
RectangleF worldViewInSimUnits = new RectangleF(
|
||||
ConvertUnits.ToSimUnits(worldView.Location.ToVector2()),
|
||||
ConvertUnits.ToSimUnits(worldView.Size.ToVector2()));
|
||||
|
||||
foreach (var fixture in Body.FixtureList)
|
||||
{
|
||||
fixture.GetAABB(out var aabb, 0);
|
||||
Vector2 lowerBound = aabb.LowerBound + Body.Position;
|
||||
if (lowerBound.X > worldViewInSimUnits.Right || lowerBound.Y > worldViewInSimUnits.Y) { continue; }
|
||||
Vector2 upperBound = aabb.UpperBound + Body.Position;
|
||||
if (upperBound.X < worldViewInSimUnits.X || upperBound.Y < worldViewInSimUnits.Y - worldViewInSimUnits.Height) { continue; }
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user