Unstable 1.8.4.0
This commit is contained in:
@@ -20,7 +20,8 @@ namespace Barotrauma
|
||||
|
||||
public override bool IsVisible(Rectangle worldView)
|
||||
{
|
||||
return Screen.Selected == GameMain.SubEditorScreen || GameMain.DebugDraw;
|
||||
if (Screen.Selected != GameMain.SubEditorScreen && !GameMain.DebugDraw) { return false; }
|
||||
return base.IsVisible(worldView);
|
||||
}
|
||||
|
||||
public override void Draw(SpriteBatch sb, bool editing, bool back = true)
|
||||
@@ -95,9 +96,13 @@ namespace Barotrauma
|
||||
new Vector2(Math.Sign(targetHull.Rect.Center.X - rect.Center.X), 0.0f)
|
||||
: new Vector2(0.0f, Math.Sign((rect.Y - rect.Height / 2.0f) - (targetHull.Rect.Y - targetHull.Rect.Height / 2.0f)));
|
||||
|
||||
Vector2 arrowPos = new Vector2(WorldRect.Center.X, -(WorldRect.Y - WorldRect.Height / 2));
|
||||
Vector2 arrowPos = new Vector2(WorldRect.Center.X, WorldRect.Y - WorldRect.Height / 2);
|
||||
if (Submarine != null)
|
||||
{
|
||||
arrowPos += (Submarine.DrawPosition - Submarine.Position);
|
||||
}
|
||||
arrowPos.Y = -arrowPos.Y;
|
||||
arrowPos += new Vector2(dir.X * (WorldRect.Width / 2), dir.Y * (WorldRect.Height / 2));
|
||||
|
||||
bool invalidDir = false;
|
||||
if (dir == Vector2.Zero)
|
||||
{
|
||||
|
||||
@@ -81,16 +81,12 @@ namespace Barotrauma
|
||||
public override bool IsVisible(Rectangle worldView)
|
||||
{
|
||||
if (BallastFlora != null) { return true; }
|
||||
|
||||
if (Screen.Selected != GameMain.SubEditorScreen && !GameMain.DebugDraw)
|
||||
{
|
||||
if (decals.Count == 0 && paintAmount < minimumPaintAmountToDraw) { return false; }
|
||||
|
||||
Rectangle worldRect = WorldRect;
|
||||
if (worldRect.X > worldView.Right || worldRect.Right < worldView.X) { return false; }
|
||||
if (worldRect.Y < worldView.Y - worldView.Height || worldRect.Y - worldRect.Height > worldView.Y) { return false; }
|
||||
}
|
||||
return true;
|
||||
return base.IsVisible(worldView);
|
||||
}
|
||||
|
||||
public override bool IsMouseOn(Vector2 position)
|
||||
@@ -103,12 +99,31 @@ namespace Barotrauma
|
||||
|
||||
private GUIComponent CreateEditingHUD(bool inGame = false)
|
||||
{
|
||||
int heightScaled = GUI.IntScale(20);
|
||||
editingHUD = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GUI.Canvas, Anchor.CenterRight) { MinSize = new Point(400, 0) }) { UserData = this };
|
||||
GUIListBox listBox = new GUIListBox(new RectTransform(new Vector2(0.95f, 0.8f), editingHUD.RectTransform, Anchor.Center), style: null)
|
||||
{
|
||||
CanTakeKeyBoardFocus = false
|
||||
};
|
||||
new SerializableEntityEditor(listBox.Content.RectTransform, this, inGame, showName: true, titleFont: GUIStyle.LargeFont);
|
||||
var hullEditor = new SerializableEntityEditor(listBox.Content.RectTransform, this, inGame, showName: true, titleFont: GUIStyle.LargeFont);
|
||||
|
||||
if (!inGame)
|
||||
{
|
||||
if (Linkable)
|
||||
{
|
||||
var linkText = new GUITextBlock(new RectTransform(new Point(editingHUD.Rect.Width, heightScaled), isFixedSize: true), TextManager.Get("HoldToLink"), font: GUIStyle.SmallFont);
|
||||
var hullLinkText = new GUITextBlock(new RectTransform(new Point(editingHUD.Rect.Width, heightScaled), isFixedSize: true), TextManager.Get("hulllinkinfo"), font: GUIStyle.SmallFont);
|
||||
var itemsText = new GUITextBlock(new RectTransform(new Point(editingHUD.Rect.Width, heightScaled), isFixedSize: true), TextManager.Get("AllowedLinks"), font: GUIStyle.SmallFont);
|
||||
LocalizedString allowedItems = AllowedLinks.None() ? TextManager.Get("None") : string.Join(", ", AllowedLinks);
|
||||
itemsText.Text = TextManager.AddPunctuation(':', itemsText.Text, allowedItems);
|
||||
hullEditor.AddCustomContent(linkText, 1);
|
||||
hullEditor.AddCustomContent(hullLinkText, 2);
|
||||
hullEditor.AddCustomContent(itemsText, 3);
|
||||
linkText.TextColor = GUIStyle.Orange;
|
||||
hullLinkText.TextColor = GUIStyle.Orange;
|
||||
itemsText.TextColor = GUIStyle.Orange;
|
||||
}
|
||||
}
|
||||
|
||||
PositionEditingHUD();
|
||||
|
||||
@@ -389,8 +404,8 @@ namespace Barotrauma
|
||||
//GUI.DrawRectangle(spriteBatch, new Rectangle((int)fs.LastExtinguishPos.X, (int)-fs.LastExtinguishPos.Y, 5,5), Color.Yellow, true);
|
||||
}
|
||||
|
||||
|
||||
GUI.DrawLine(spriteBatch, new Vector2(drawRect.X, -WorldSurface), new Vector2(drawRect.Right, -WorldSurface), Color.Cyan * 0.5f);
|
||||
float worldSurface = surface + Submarine.DrawPosition.Y;
|
||||
GUI.DrawLine(spriteBatch, new Vector2(drawRect.X, -worldSurface), new Vector2(drawRect.Right, -worldSurface), Color.Cyan * 0.5f);
|
||||
for (int i = 0; i < waveY.Length - 1; i++)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch,
|
||||
@@ -563,8 +578,7 @@ namespace Barotrauma
|
||||
corners[4] = new Vector3(x, bottom, 0.0f);
|
||||
//bottom right
|
||||
corners[5] = new Vector3(x + width, bottom, 0.0f);
|
||||
|
||||
Vector2[] uvCoords = new Vector2[4];
|
||||
|
||||
for (int n = 0; n < 4; n++)
|
||||
{
|
||||
uvCoords[n] = Vector2.Transform(new Vector2(corners[n].X, -corners[n].Y), transform);
|
||||
|
||||
+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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -13,6 +12,7 @@ namespace Barotrauma.Lights
|
||||
|
||||
public readonly Submarine Submarine;
|
||||
public HashSet<ConvexHull> IsHidden = new HashSet<ConvexHull>();
|
||||
public HashSet<ConvexHull> HasBeenVisible = new HashSet<ConvexHull>();
|
||||
public readonly List<ConvexHull> List = new List<ConvexHull>();
|
||||
|
||||
public ConvexHullList(Submarine submarine)
|
||||
@@ -443,10 +443,10 @@ namespace Barotrauma.Lights
|
||||
|
||||
public bool Intersects(Rectangle rect)
|
||||
{
|
||||
if (!Enabled) return false;
|
||||
if (!Enabled) { return false; }
|
||||
|
||||
Rectangle transformedBounds = BoundingBox;
|
||||
if (ParentEntity != null && ParentEntity.Submarine != null)
|
||||
if (ParentEntity is { Submarine: not null })
|
||||
{
|
||||
transformedBounds.X += (int)ParentEntity.Submarine.Position.X;
|
||||
transformedBounds.Y += (int)ParentEntity.Submarine.Position.Y;
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
|
||||
private readonly List<LightSource> activeLights = new List<LightSource>(capacity: 100);
|
||||
private readonly List<LightSource> activeLightsWithLightVolume = new List<LightSource>(capacity: 100);
|
||||
private readonly List<LightSource> activeShadowCastingLights = new List<LightSource>(capacity: 100);
|
||||
|
||||
public static int ActiveLightCount { get; private set; }
|
||||
|
||||
@@ -243,6 +243,7 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
}
|
||||
|
||||
/// <param name="backgroundObstructor">A render target that contains the structures that should obstruct lights in the background. If not given, damageable walls and hulls are rendered to obstruct the background lights.</param>
|
||||
public void RenderLightMap(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam, RenderTarget2D backgroundObstructor = null)
|
||||
{
|
||||
if (!LightingEnabled) { return; }
|
||||
@@ -273,13 +274,13 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
light.ParentBody.UpdateDrawPosition();
|
||||
|
||||
Vector2 pos = light.ParentBody.DrawPosition;
|
||||
Vector2 pos = light.ParentBody.DrawPosition + light.OffsetFromBody;
|
||||
if (light.ParentSub != null) { pos -= light.ParentSub.DrawPosition; }
|
||||
light.Position = pos;
|
||||
}
|
||||
|
||||
//above the top boundary of the level (in an inactive respawn shuttle?)
|
||||
if (Level.Loaded != null && light.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
|
||||
if (Level.IsPositionAboveLevel(light.WorldPosition)) { continue; }
|
||||
|
||||
float range = light.LightSourceParams.TextureRange;
|
||||
if (light.LightSprite != null)
|
||||
@@ -315,19 +316,20 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
|
||||
//find the lights with an active light volume
|
||||
activeLightsWithLightVolume.Clear();
|
||||
activeShadowCastingLights.Clear();
|
||||
foreach (var activeLight in activeLights)
|
||||
{
|
||||
if (!activeLight.CastShadows) { continue; }
|
||||
if (activeLight.Range < 1.0f || activeLight.Color.A < 1 || activeLight.CurrentBrightness <= 0.0f) { continue; }
|
||||
activeLightsWithLightVolume.Add(activeLight);
|
||||
activeShadowCastingLights.Add(activeLight);
|
||||
}
|
||||
|
||||
//remove some lights with a light volume if there's too many of them
|
||||
if (activeLightsWithLightVolume.Count > GameSettings.CurrentConfig.Graphics.VisibleLightLimit && Screen.Selected is { IsEditor: false })
|
||||
if (activeShadowCastingLights.Count > GameSettings.CurrentConfig.Graphics.VisibleLightLimit && Screen.Selected is { IsEditor: false })
|
||||
{
|
||||
for (int i = GameSettings.CurrentConfig.Graphics.VisibleLightLimit; i < activeLightsWithLightVolume.Count; i++)
|
||||
for (int i = GameSettings.CurrentConfig.Graphics.VisibleLightLimit; i < activeShadowCastingLights.Count; i++)
|
||||
{
|
||||
activeLights.Remove(activeLightsWithLightVolume[i]);
|
||||
activeLights.Remove(activeShadowCastingLights[i]);
|
||||
}
|
||||
}
|
||||
activeLights.Sort((l1, l2) => l1.LastRecalculationTime.CompareTo(l2.LastRecalculationTime));
|
||||
@@ -410,11 +412,21 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
spriteBatch.End();
|
||||
|
||||
GameMain.GameScreen.DamageEffect.CurrentTechnique = GameMain.GameScreen.DamageEffect.Techniques["StencilShaderSolidColor"];
|
||||
GameMain.GameScreen.DamageEffect.Parameters["solidColor"].SetValue(Color.Black.ToVector4());
|
||||
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied, SamplerState.LinearWrap, transformMatrix: spriteBatchTransform, effect: GameMain.GameScreen.DamageEffect);
|
||||
Submarine.DrawDamageable(spriteBatch, GameMain.GameScreen.DamageEffect);
|
||||
spriteBatch.End();
|
||||
if (backgroundObstructor != null)
|
||||
{
|
||||
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied, SamplerState.LinearWrap, transformMatrix: Matrix.Identity, effect: GameMain.GameScreen.DamageEffect);
|
||||
spriteBatch.Draw(backgroundObstructor, new Rectangle(0, 0,
|
||||
(int)(GameMain.GraphicsWidth * currLightMapScale), (int)(GameMain.GraphicsHeight * currLightMapScale)), Color.Black);
|
||||
spriteBatch.End();
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.GameScreen.DamageEffect.CurrentTechnique = GameMain.GameScreen.DamageEffect.Techniques["StencilShaderSolidColor"];
|
||||
GameMain.GameScreen.DamageEffect.Parameters["solidColor"].SetValue(Color.Black.ToVector4());
|
||||
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied, SamplerState.LinearWrap, transformMatrix: spriteBatchTransform, effect: GameMain.GameScreen.DamageEffect);
|
||||
Submarine.DrawDamageable(spriteBatch, GameMain.GameScreen.DamageEffect);
|
||||
spriteBatch.End();
|
||||
}
|
||||
|
||||
graphics.BlendState = BlendState.Additive;
|
||||
|
||||
@@ -679,11 +691,14 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
return visibleHulls;
|
||||
}
|
||||
|
||||
private static readonly List<VertexPositionColor> ShadowVertices = new List<VertexPositionColor>(500);
|
||||
private static readonly List<VertexPositionTexture> PenumbraVertices = new List<VertexPositionTexture>(500);
|
||||
|
||||
public void UpdateObstructVision(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam, Vector2 lookAtPosition)
|
||||
{
|
||||
if ((!LosEnabled || LosMode == LosMode.None) && ObstructVisionAmount <= 0.0f) { return; }
|
||||
if (ViewTarget == null) return;
|
||||
if (ViewTarget == null) { return; }
|
||||
|
||||
graphics.SetRenderTarget(LosTexture);
|
||||
|
||||
@@ -766,11 +781,11 @@ namespace Barotrauma.Lights
|
||||
|
||||
if (convexHulls != null)
|
||||
{
|
||||
List<VertexPositionColor> shadowVerts = new List<VertexPositionColor>();
|
||||
List<VertexPositionTexture> penumbraVerts = new List<VertexPositionTexture>();
|
||||
ShadowVertices.Clear();
|
||||
PenumbraVertices.Clear();
|
||||
foreach (ConvexHull convexHull in convexHulls)
|
||||
{
|
||||
if (!convexHull.Enabled || !convexHull.Intersects(camView)) { continue; }
|
||||
if (!convexHull.Intersects(camView)) { continue; }
|
||||
|
||||
Vector2 relativeViewPos = pos;
|
||||
if (convexHull.ParentEntity?.Submarine != null)
|
||||
@@ -782,26 +797,26 @@ namespace Barotrauma.Lights
|
||||
|
||||
for (int i = 0; i < convexHull.ShadowVertexCount; i++)
|
||||
{
|
||||
shadowVerts.Add(convexHull.ShadowVertices[i]);
|
||||
ShadowVertices.Add(convexHull.ShadowVertices[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < convexHull.PenumbraVertexCount; i++)
|
||||
{
|
||||
penumbraVerts.Add(convexHull.PenumbraVertices[i]);
|
||||
PenumbraVertices.Add(convexHull.PenumbraVertices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (shadowVerts.Count > 0)
|
||||
if (ShadowVertices.Count > 0)
|
||||
{
|
||||
ConvexHull.shadowEffect.World = shadowTransform;
|
||||
ConvexHull.shadowEffect.CurrentTechnique.Passes[0].Apply();
|
||||
graphics.DrawUserPrimitives(PrimitiveType.TriangleList, shadowVerts.ToArray(), 0, shadowVerts.Count / 3, VertexPositionColor.VertexDeclaration);
|
||||
graphics.DrawUserPrimitives(PrimitiveType.TriangleList, ShadowVertices.ToArray(), 0, ShadowVertices.Count / 3, VertexPositionColor.VertexDeclaration);
|
||||
|
||||
if (penumbraVerts.Count > 0)
|
||||
if (PenumbraVertices.Count > 0)
|
||||
{
|
||||
ConvexHull.penumbraEffect.World = shadowTransform;
|
||||
ConvexHull.penumbraEffect.CurrentTechnique.Passes[0].Apply();
|
||||
graphics.DrawUserPrimitives(PrimitiveType.TriangleList, penumbraVerts.ToArray(), 0, penumbraVerts.Count / 3, VertexPositionTexture.VertexDeclaration);
|
||||
graphics.DrawUserPrimitives(PrimitiveType.TriangleList, PenumbraVertices.ToArray(), 0, PenumbraVertices.Count / 3, VertexPositionTexture.VertexDeclaration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -827,7 +842,7 @@ namespace Barotrauma.Lights
|
||||
public void ClearLights()
|
||||
{
|
||||
activeLights.Clear();
|
||||
activeLightsWithLightVolume.Clear();
|
||||
activeShadowCastingLights.Clear();
|
||||
lights.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
@@ -245,7 +245,7 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!needsRecalculation && value)
|
||||
if (value)
|
||||
{
|
||||
foreach (ConvexHullList chList in convexHullsInRange)
|
||||
{
|
||||
@@ -450,6 +450,8 @@ namespace Barotrauma.Lights
|
||||
set;
|
||||
}
|
||||
|
||||
public Vector2 OffsetFromBody;
|
||||
|
||||
public DeformableSprite DeformableLightSprite
|
||||
{
|
||||
get;
|
||||
@@ -550,7 +552,6 @@ namespace Barotrauma.Lights
|
||||
chList.List.Clear();
|
||||
foreach (var convexHull in fullChList.List)
|
||||
{
|
||||
if (!convexHull.Enabled) { continue; }
|
||||
if (!MathUtils.CircleIntersectsRectangle(lightPos, TextureRange, convexHull.BoundingBox)) { continue; }
|
||||
if (lightSourceParams.Directional)
|
||||
{
|
||||
@@ -562,9 +563,9 @@ namespace Barotrauma.Lights
|
||||
// center is in the opposite direction from the ray (cheapest check first)
|
||||
if (Vector2.Dot(ray, convexHull.BoundingBox.Center.ToVector2() - lightPos) <= 0 &&
|
||||
/*ray doesn't hit the convex hull*/
|
||||
!MathUtils.GetLineRectangleIntersection(lightPos, lightPos + ray, bounds, out _) &&
|
||||
!MathUtils.GetLineWorldRectangleIntersection(lightPos, lightPos + ray, bounds, out _) &&
|
||||
/*normal vectors of the ray don't hit the convex hull */
|
||||
!MathUtils.GetLineRectangleIntersection(lightPos + normal, lightPos - normal, bounds, out _))
|
||||
!MathUtils.GetLineWorldRectangleIntersection(lightPos + normal, lightPos - normal, bounds, out _))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -572,6 +573,7 @@ namespace Barotrauma.Lights
|
||||
chList.List.Add(convexHull);
|
||||
}
|
||||
chList.IsHidden.RemoveWhere(ch => !chList.List.Contains(ch));
|
||||
chList.HasBeenVisible.RemoveWhere(ch => !chList.List.Contains(ch));
|
||||
HullsUpToDate.Add(sub);
|
||||
}
|
||||
|
||||
@@ -592,7 +594,17 @@ namespace Barotrauma.Lights
|
||||
private void CheckHullsInRange(Submarine sub)
|
||||
{
|
||||
//find the list of convexhulls that belong to the sub
|
||||
ConvexHullList chList = convexHullsInRange.FirstOrDefault(chList => chList.Submarine == sub);
|
||||
|
||||
// Performance-sensitive code, hence implemented without Linq.
|
||||
ConvexHullList chList = null;
|
||||
foreach (var chl in convexHullsInRange)
|
||||
{
|
||||
if (chl.Submarine == sub)
|
||||
{
|
||||
chList = chl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//not found -> create one
|
||||
if (chList == null)
|
||||
@@ -604,7 +616,8 @@ namespace Barotrauma.Lights
|
||||
|
||||
foreach (var ch in chList.List)
|
||||
{
|
||||
if (ch.LastVertexChangeTime > LastRecalculationTime && !chList.IsHidden.Contains(ch))
|
||||
if (ch.LastVertexChangeTime > LastRecalculationTime &&
|
||||
(!chList.IsHidden.Contains(ch) || chList.HasBeenVisible.Contains(ch)))
|
||||
{
|
||||
NeedsRecalculation = true;
|
||||
break;
|
||||
@@ -712,8 +725,8 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
foreach (ConvexHull hull in chList.List)
|
||||
{
|
||||
if (hull.IsInvalid) { continue; }
|
||||
if (!chList.IsHidden.Contains(hull))
|
||||
if (hull.IsInvalid || !hull.Enabled) { continue; }
|
||||
if (!chList.IsHidden.Contains(hull) || chList.HasBeenVisible.Contains(hull))
|
||||
{
|
||||
//find convexhull segments that are close enough and facing towards the light source
|
||||
lock (mutex)
|
||||
@@ -732,7 +745,17 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
foreach (ConvexHull hull in chList.List)
|
||||
{
|
||||
chList.IsHidden.Add(hull);
|
||||
if (!hull.Enabled)
|
||||
{
|
||||
//if the hull is not enabled, we cannot determine if it's visible or hidden from the point of view of the light source
|
||||
//so let's not mark it as hidden, but instead consider it as something that has been visible, so we know to recalculate if/when it becomes enabled again
|
||||
chList.IsHidden.Remove(hull);
|
||||
chList.HasBeenVisible.Add(hull);
|
||||
continue;
|
||||
}
|
||||
|
||||
//mark convex hulls as hidden at this point, they're removed if we find any of the segments to be visible
|
||||
chList.IsHidden.Add(hull);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1411,14 +1434,7 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
if (conditionals.None()) { return; }
|
||||
if (conditionalTarget == null) { return; }
|
||||
if (logicalOperator == PropertyConditional.LogicalOperatorType.And)
|
||||
{
|
||||
Enabled = conditionals.All(c => c.Matches(conditionalTarget));
|
||||
}
|
||||
else
|
||||
{
|
||||
Enabled = conditionals.Any(c => c.Matches(conditionalTarget));
|
||||
}
|
||||
Enabled = PropertyConditional.CheckConditionals(conditionalTarget, conditionals, logicalOperator);
|
||||
}
|
||||
|
||||
public void DebugDrawVertices(SpriteBatch spriteBatch)
|
||||
@@ -1501,6 +1517,7 @@ namespace Barotrauma.Lights
|
||||
foreach (var convexHullList in convexHullsInRange)
|
||||
{
|
||||
convexHullList.IsHidden.Remove(visibleConvexHull);
|
||||
convexHullList.HasBeenVisible.Add(visibleConvexHull);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -378,17 +378,24 @@ namespace Barotrauma
|
||||
|
||||
bool showReputation = hudVisibility > 0.0f && location.Type.HasOutpost && location.Reputation != null;
|
||||
|
||||
LocationType locationTypeToDisplay = location.GetLocationTypeToDisplay(out Identifier overrideDescriptionIdentifier);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), location.DisplayName, font: GUIStyle.LargeFont) { Padding = Vector4.Zero };
|
||||
if (!location.Type.Name.IsNullOrEmpty())
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), location.Type.Name, font: GUIStyle.SubHeadingFont) { Padding = Vector4.Zero };
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), locationTypeToDisplay.Name, font: GUIStyle.SubHeadingFont) { Padding = Vector4.Zero };
|
||||
}
|
||||
|
||||
CreateSpacing(10);
|
||||
|
||||
if (!location.Type.Description.IsNullOrEmpty())
|
||||
var description = locationTypeToDisplay.Description;
|
||||
if (!overrideDescriptionIdentifier.IsEmpty)
|
||||
{
|
||||
CreateTextWithIcon(location.Type.Description, location.Type.Sprite);
|
||||
description = TextManager.Get(overrideDescriptionIdentifier);
|
||||
}
|
||||
if (!description.IsNullOrEmpty())
|
||||
{
|
||||
CreateTextWithIcon(description, locationTypeToDisplay.Sprite);
|
||||
}
|
||||
|
||||
int highestSubTier = location.HighestSubmarineTierAvailable();
|
||||
@@ -699,6 +706,7 @@ namespace Barotrauma
|
||||
CurrentLocation.CreateStores();
|
||||
ProgressWorld(campaign);
|
||||
Radiation?.OnStep(1);
|
||||
mapAnimQueue.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -828,7 +836,7 @@ namespace Barotrauma
|
||||
|
||||
if (!rect.Intersects(drawRect)) { continue; }
|
||||
|
||||
Color color = location.Type.SpriteColor;
|
||||
Color color = location.OverrideIconColor ?? location.Type.SpriteColor;
|
||||
if (!location.Visited) { color = Color.White; }
|
||||
if (location.Connections.Find(c => c.Locations.Contains(currentDisplayLocation)) == null)
|
||||
{
|
||||
@@ -850,6 +858,27 @@ namespace Barotrauma
|
||||
iconScale *= notificationPulseAmount;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
if (generationParams.ShowStoreInfo)
|
||||
{
|
||||
if (location.Stores == null || location.Stores.None())
|
||||
{
|
||||
color = Color.DarkBlue;
|
||||
}
|
||||
//stores created, but nothing in stock
|
||||
else if (location.Stores.Values.None(s => s.Stock.Any()))
|
||||
{
|
||||
color = Color.Yellow;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = Color.Green;
|
||||
}
|
||||
|
||||
GUI.DrawString(spriteBatch, pos + Vector2.One * 20, "Time since visited: " +location.WorldStepsSinceVisited, Color.Yellow);
|
||||
}
|
||||
#endif
|
||||
|
||||
locationSprite.Draw(spriteBatch, pos, color,
|
||||
scale: generationParams.LocationIconSize / locationSprite.size.X * iconScale * zoom);
|
||||
|
||||
@@ -923,31 +952,32 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
Vector2 dPos = pos;
|
||||
//move the debug texts upwards so they don't go under the info panel that appears when highlighted
|
||||
Vector2 dPos = pos + new Vector2(15, -100);
|
||||
if (location == HighlightedLocation)
|
||||
{
|
||||
dPos.Y -= 80;
|
||||
GUI.DrawString(spriteBatch, dPos + new Vector2(15, 32), "Faction: " + (location.Faction?.Prefab.Name ?? "none"), Color.White, Color.Black, font: GUIStyle.SubHeadingFont);
|
||||
GUI.DrawString(spriteBatch, dPos + new Vector2(15, 50), "Secondary Faction: " + (location.SecondaryFaction?.Prefab.Name ?? "none"), Color.White, Color.Black, font: GUIStyle.SubHeadingFont);
|
||||
dPos.Y += 48;
|
||||
GUI.DrawString(spriteBatch, dPos, "Faction: " + (location.Faction?.Prefab.Name ?? "none"), Color.White, Color.Black, font: GUIStyle.SubHeadingFont);
|
||||
GUI.DrawString(spriteBatch, dPos + new Vector2(0, 18), "Secondary Faction: " + (location.SecondaryFaction?.Prefab.Name ?? "none"), Color.White, Color.Black, font: GUIStyle.SubHeadingFont);
|
||||
dPos.Y += 50;
|
||||
|
||||
if (PlayerInput.KeyDown(Keys.LeftShift))
|
||||
{
|
||||
GUI.DrawString(spriteBatch, new Vector2(150,150), "Dist: " +
|
||||
GUI.DrawString(spriteBatch, new Vector2(150, 150), "Dist: " +
|
||||
GetDistanceToClosestLocationOrConnection(CurrentLocation, int.MaxValue, loc => loc == location), Color.White, Color.Black, font: GUIStyle.SubHeadingFont);
|
||||
|
||||
}
|
||||
GUI.DrawString(spriteBatch, dPos, $"Difficulty: {location.LevelData.Difficulty.FormatSingleDecimal()}",
|
||||
ToolBox.GradientLerp(location.LevelData.Difficulty / 100.0f, GUIStyle.Blue, GUIStyle.Yellow, GUIStyle.Red), Color.Black * 0.8f, 4, font: GUIStyle.SmallFont);
|
||||
|
||||
dPos.Y += 25;
|
||||
GUI.DrawString(spriteBatch, dPos, $"Biome: {location.LevelData.Biome.DisplayName} ({location.LevelData.GenerationParams.Identifier})", Color.White, Color.Black, font: GUIStyle.SmallFont);
|
||||
}
|
||||
dPos.Y += 48;
|
||||
GUI.DrawString(spriteBatch, dPos, $"Difficulty: {location.LevelData.Difficulty.FormatSingleDecimal()}", Color.White, Color.Black * 0.8f, 4, font: GUIStyle.SmallFont);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DrawDecorativeHUD(spriteBatch, rect);
|
||||
|
||||
bool drawRadiationTooltip = true;
|
||||
|
||||
bool drawRadiationTooltip = HighlightedLocation == null;
|
||||
if (tooltip != null)
|
||||
{
|
||||
GUIComponent.DrawToolTip(spriteBatch, tooltip.Value.tip, tooltip.Value.targetArea);
|
||||
@@ -1056,7 +1086,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MathUtils.GetLineRectangleIntersection(start, end, new Rectangle(viewArea.X, viewArea.Y + viewArea.Height, viewArea.Width, viewArea.Height), out Vector2 intersection))
|
||||
if (MathUtils.GetLineWorldRectangleIntersection(start, end, new Rectangle(viewArea.X, viewArea.Y + viewArea.Height, viewArea.Width, viewArea.Height), out Vector2 intersection))
|
||||
{
|
||||
if (!viewArea.Contains(start))
|
||||
{
|
||||
@@ -1196,7 +1226,9 @@ namespace Barotrauma
|
||||
Vector2 center = rectCenter + (connection.CenterPos + viewOffset) * zoom;
|
||||
if (viewArea.Contains(center) && connection.Biome != null)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, center, (connection.LevelData?.GenerationParams?.Identifier ?? connection.Biome.Identifier) + " (" + connection.Difficulty.FormatSingleDecimal() + ")", Color.White);
|
||||
GUI.DrawString(spriteBatch, center - Vector2.UnitX * 50,
|
||||
$"{(connection.LevelData?.GenerationParams?.Identifier ?? connection.Biome.Identifier)} ({connection.Difficulty.FormatSingleDecimal()})",
|
||||
ToolBox.GradientLerp(connection.Difficulty / 100.0f, GUIStyle.Blue, GUIStyle.Yellow, GUIStyle.Red), backgroundColor: Color.Black * 0.7f, font: GUIStyle.SmallFont);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,18 +7,18 @@ namespace Barotrauma
|
||||
{
|
||||
internal partial class Radiation
|
||||
{
|
||||
private static readonly LocalizedString radiationTooltip = TextManager.Get("RadiationTooltip");
|
||||
private int? radiationMultiplier;
|
||||
private static float spriteIndex;
|
||||
private readonly SpriteSheet? sheet = GUIStyle.RadiationAnimSpriteSheet;
|
||||
private int maxFrames => (sheet?.FrameCount ?? 0) + 1;
|
||||
private readonly SpriteSheet? radiationEdgeAnimSheet = GUIStyle.RadiationAnimSpriteSheet;
|
||||
private int maxFrames => (radiationEdgeAnimSheet?.FrameCount ?? 0) + 1;
|
||||
|
||||
private bool isHovingOver;
|
||||
private bool isHoveringOver;
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, Rectangle container, float zoom)
|
||||
{
|
||||
if (!Enabled) { return; }
|
||||
|
||||
UISprite? uiSprite = GUIStyle.Radiation;
|
||||
UISprite? radiationMainSprite = GUIStyle.Radiation;
|
||||
var (offsetX, offsetY) = Map.DrawOffset * zoom;
|
||||
var (centerX, centerY) = container.Center.ToVector2();
|
||||
var (halfSizeX, halfSizeY) = new Vector2(container.Width / 2f, container.Height / 2f) * zoom;
|
||||
@@ -29,31 +29,41 @@ namespace Barotrauma
|
||||
|
||||
Vector2 spriteScale = new Vector2(zoom);
|
||||
|
||||
uiSprite?.Sprite.DrawTiled(spriteBatch, topLeft, size, color: Params.RadiationAreaColor, startOffset: Vector2.Zero, textureScale: spriteScale);
|
||||
radiationMainSprite?.Sprite.DrawTiled(spriteBatch, topLeft, size, color: Params.RadiationAreaColor, startOffset: Vector2.Zero, textureScale: spriteScale);
|
||||
|
||||
Vector2 topRight = topLeft + Vector2.UnitX * size.X;
|
||||
|
||||
int index = 0;
|
||||
if (sheet != null)
|
||||
if (radiationEdgeAnimSheet != null)
|
||||
{
|
||||
for (float i = 0; i <= size.Y; i += sheet.FrameSize.Y / 2f * zoom)
|
||||
for (float i = 0; i <= size.Y; i += radiationEdgeAnimSheet.FrameSize.Y / 2f * zoom)
|
||||
{
|
||||
bool isEven = ++index % 2 == 0;
|
||||
Vector2 origin = new Vector2(0.5f, 0) * sheet.FrameSize.X;
|
||||
Vector2 origin = new Vector2(0.5f, 0) * radiationEdgeAnimSheet.FrameSize.X;
|
||||
// every other sprite's animation is reversed to make it seem more chaotic
|
||||
int sprite = (int) MathF.Floor(isEven ? spriteIndex : maxFrames - spriteIndex);
|
||||
sheet.Draw(spriteBatch, sprite, topRight + new Vector2(0, i), Params.RadiationBorderTint, origin, 0f, spriteScale);
|
||||
radiationEdgeAnimSheet.Draw(spriteBatch, sprite, topRight + new Vector2(0, i), Params.RadiationBorderTint, origin, 0f, spriteScale);
|
||||
}
|
||||
}
|
||||
|
||||
isHovingOver = container.Contains(PlayerInput.MousePosition) && PlayerInput.MousePosition.X < topLeft.X + size.X;
|
||||
radiationMultiplier = null;
|
||||
if (container.Contains(PlayerInput.MousePosition))
|
||||
{
|
||||
float rightEdge = topLeft.X + size.X;
|
||||
float distanceFromRight = rightEdge - PlayerInput.MousePosition.X;
|
||||
if (distanceFromRight >= 0)
|
||||
{
|
||||
radiationMultiplier = Math.Min(4, (int)(distanceFromRight / (Params.RadiationEffectMultipliedPerPixelDistance * zoom)) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawFront(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (isHovingOver)
|
||||
if (radiationMultiplier is int multiplier)
|
||||
{
|
||||
GUIComponent.DrawToolTip(spriteBatch, radiationTooltip, PlayerInput.MousePosition + new Vector2(18 * GUI.Scale));
|
||||
var tooltip = TextManager.GetWithVariable("RadiationTooltip", "[jovianmultiplier]", multiplier.ToString());
|
||||
GUIComponent.DrawToolTip(spriteBatch, tooltip, PlayerInput.MousePosition + new Vector2(18 * GUI.Scale));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,16 @@ namespace Barotrauma
|
||||
|
||||
public virtual bool IsVisible(Rectangle worldView)
|
||||
{
|
||||
Rectangle worldRect = WorldRect;
|
||||
if (worldRect.X > worldView.Right || worldRect.Right < worldView.X) { return false; }
|
||||
if (worldRect.Y < worldView.Y - worldView.Height || worldRect.Y - worldRect.Height > worldView.Y) { return false; }
|
||||
//zoomed extremely far out -> no need to render
|
||||
if (Screen.Selected.Cam.Zoom < 0.05f) { return false; }
|
||||
if (worldRect.Width * Screen.Selected.Cam.Zoom < 1.0f ||
|
||||
worldRect.Height * Screen.Selected.Cam.Zoom < 1.0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -91,6 +101,8 @@ namespace Barotrauma
|
||||
|
||||
public virtual void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) { }
|
||||
|
||||
public virtual float GetDrawDepth() { return 0.0f; }
|
||||
|
||||
/// <summary>
|
||||
/// A method that modifies the draw depth to prevent z-fighting between entities with the same sprite depth
|
||||
/// </summary>
|
||||
@@ -305,6 +317,15 @@ namespace Barotrauma
|
||||
if (PlayerInput.IsCtrlDown())
|
||||
{
|
||||
HashSet<MapEntity> clones = Clone(SelectedList.ToList()).Where(c => c != null).ToHashSet();
|
||||
|
||||
if (clones.Count == 1)
|
||||
{
|
||||
if (clones.First() is WayPoint wayPoint && SelectedList.First() is WayPoint originalWaypoint && originalWaypoint.SpawnType == SpawnType.Path)
|
||||
{
|
||||
originalWaypoint.ConnectTo(wayPoint);
|
||||
}
|
||||
}
|
||||
|
||||
SelectedList = clones;
|
||||
SelectedList.ForEach(c => c.Move(moveAmount));
|
||||
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List<MapEntity>(clones), false));
|
||||
@@ -1068,6 +1089,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(clones, false, handleInventoryBehavior: false));
|
||||
if (Screen.Selected is SubEditorScreen subEditor) { subEditor.ReconstructLayers(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -16,6 +16,8 @@ namespace Barotrauma
|
||||
public readonly bool Stream;
|
||||
public readonly bool IgnoreMuffling;
|
||||
|
||||
public readonly bool MuteBackgroundMusic;
|
||||
|
||||
public readonly string? Filename;
|
||||
|
||||
private RoundSound(ContentXElement element, Sound sound)
|
||||
@@ -26,6 +28,7 @@ namespace Barotrauma
|
||||
Range = element.GetAttributeFloat("range", 1000.0f);
|
||||
Volume = element.GetAttributeFloat("volume", 1.0f);
|
||||
IgnoreMuffling = element.GetAttributeBool("dontmuffle", false);
|
||||
MuteBackgroundMusic = element.GetAttributeBool("MuteBackgroundMusic", false);
|
||||
|
||||
FrequencyMultiplierRange = new Vector2(1.0f);
|
||||
string freqMultAttr = element.GetAttributeString("frequencymultiplier", element.GetAttributeString("frequency", "1.0"));
|
||||
@@ -73,9 +76,16 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
Sound? existingSound = null;
|
||||
if (roundSoundByPath.TryGetValue(filename.FullPath, out RoundSound? rs) && rs.Sound is { Disposed: false })
|
||||
if (roundSoundByPath.TryGetValue(filename.FullPath, out RoundSound? rs))
|
||||
{
|
||||
existingSound = rs.Sound;
|
||||
if (rs.Sound is { Disposed: false })
|
||||
{
|
||||
existingSound = rs.Sound;
|
||||
}
|
||||
else
|
||||
{
|
||||
roundSoundByPath.Remove(filename.FullPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (existingSound is null)
|
||||
|
||||
@@ -328,11 +328,11 @@ namespace Barotrauma
|
||||
Vector2 max = new Vector2(worldRect.Right, worldRect.Y + worldRect.Height);
|
||||
foreach (DecorativeSprite decorativeSprite in Prefab.DecorativeSprites)
|
||||
{
|
||||
float scale = decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale;
|
||||
min.X = Math.Min(worldPos.X - decorativeSprite.Sprite.size.X * decorativeSprite.Sprite.RelativeOrigin.X * scale, min.X);
|
||||
max.X = Math.Max(worldPos.X + decorativeSprite.Sprite.size.X * (1.0f - decorativeSprite.Sprite.RelativeOrigin.X) * scale, max.X);
|
||||
min.Y = Math.Min(worldPos.Y - decorativeSprite.Sprite.size.Y * (1.0f - decorativeSprite.Sprite.RelativeOrigin.Y) * scale, min.Y);
|
||||
max.Y = Math.Max(worldPos.Y + decorativeSprite.Sprite.size.Y * decorativeSprite.Sprite.RelativeOrigin.Y * scale, max.Y);
|
||||
Vector2 scale = decorativeSprite.GetScale(ref spriteAnimState[decorativeSprite].ScaleState, spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale;
|
||||
min.X = Math.Min(worldPos.X - decorativeSprite.Sprite.size.X * decorativeSprite.Sprite.RelativeOrigin.X * scale.X, min.X);
|
||||
max.X = Math.Max(worldPos.X + decorativeSprite.Sprite.size.X * (1.0f - decorativeSprite.Sprite.RelativeOrigin.X) * scale.X, max.X);
|
||||
min.Y = Math.Min(worldPos.Y - decorativeSprite.Sprite.size.Y * (1.0f - decorativeSprite.Sprite.RelativeOrigin.Y) * scale.Y, min.Y);
|
||||
max.Y = Math.Max(worldPos.Y + decorativeSprite.Sprite.size.Y * decorativeSprite.Sprite.RelativeOrigin.Y * scale.Y, max.Y);
|
||||
}
|
||||
Vector2 offset = GetCollapseEffectOffset();
|
||||
min += offset;
|
||||
@@ -341,6 +341,9 @@ namespace Barotrauma
|
||||
if (min.X > worldView.Right || max.X < worldView.X) { return false; }
|
||||
if (min.Y > worldView.Y || max.Y < worldView.Y - worldView.Height) { return false; }
|
||||
|
||||
Vector2 extents = max - min;
|
||||
if (extents.X * Screen.Selected.Cam.Zoom < 1.0f) { return false; }
|
||||
if (extents.Y * Screen.Selected.Cam.Zoom < 1.0f) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -368,7 +371,7 @@ namespace Barotrauma
|
||||
return SpriteDepthOverrideIsSet ? SpriteOverrideDepth : Prefab.Sprite.Depth;
|
||||
}
|
||||
|
||||
public float GetDrawDepth()
|
||||
public override float GetDrawDepth()
|
||||
{
|
||||
return GetDrawDepth(GetRealDepth(), Prefab.Sprite);
|
||||
}
|
||||
@@ -448,7 +451,7 @@ namespace Barotrauma
|
||||
MathUtils.PositiveModulo(-textureOffset.X, Prefab.BackgroundSprite.SourceRect.Width * TextureScale.X * Scale),
|
||||
MathUtils.PositiveModulo(-textureOffset.Y, Prefab.BackgroundSprite.SourceRect.Height * TextureScale.Y * Scale));
|
||||
|
||||
float rotationRad = rotationForSprite(this.rotationRad, Prefab.BackgroundSprite);
|
||||
float rotationRad = GetRotationForSprite(this.rotationRad, Prefab.BackgroundSprite);
|
||||
|
||||
Prefab.BackgroundSprite.DrawTiled(
|
||||
spriteBatch,
|
||||
@@ -489,7 +492,7 @@ namespace Barotrauma
|
||||
advanceY = advanceY.FlipX();
|
||||
}
|
||||
|
||||
float sectionSpriteRotationRad = rotationForSprite(this.rotationRad, Prefab.Sprite);
|
||||
float sectionSpriteRotationRad = GetRotationForSprite(this.rotationRad, Prefab.Sprite);
|
||||
|
||||
for (int i = 0; i < Sections.Length; i++)
|
||||
{
|
||||
@@ -498,16 +501,19 @@ namespace Barotrauma
|
||||
{
|
||||
float newCutoff = MathHelper.Lerp(0.0f, 0.65f, Sections[i].damage / MaxHealth);
|
||||
|
||||
if (Math.Abs(newCutoff - Submarine.DamageEffectCutoff) > 0.01f || color != Submarine.DamageEffectColor)
|
||||
if (Math.Abs(newCutoff - Submarine.DamageEffectCutoff) > 0.05f)
|
||||
{
|
||||
spriteBatch.End();
|
||||
spriteBatch.Begin(SpriteSortMode.BackToFront,
|
||||
BlendState.NonPremultiplied, SamplerState.LinearWrap,
|
||||
null, null,
|
||||
damageEffect,
|
||||
Screen.Selected.Cam.Transform);
|
||||
|
||||
damageEffect.Parameters["aCutoff"].SetValue(newCutoff);
|
||||
damageEffect.Parameters["cCutoff"].SetValue(newCutoff * 1.2f);
|
||||
damageEffect.Parameters["inColor"].SetValue(color.ToVector4());
|
||||
|
||||
damageEffect.CurrentTechnique.Passes[0].Apply();
|
||||
|
||||
Submarine.DamageEffectCutoff = newCutoff;
|
||||
Submarine.DamageEffectColor = color;
|
||||
}
|
||||
}
|
||||
if (!HasDamage && i == 0)
|
||||
@@ -560,15 +566,20 @@ namespace Barotrauma
|
||||
pos: drawPos.FlipY(),
|
||||
color: color,
|
||||
rotate: rotation,
|
||||
scale: decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale,
|
||||
origin: decorativeSprite.Sprite.Origin,
|
||||
scale: decorativeSprite.GetScale(ref spriteAnimState[decorativeSprite].ScaleState, spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale,
|
||||
spriteEffect: Prefab.Sprite.effects ^ SpriteEffects,
|
||||
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - Prefab.Sprite.Depth), 0.999f));
|
||||
}
|
||||
}
|
||||
|
||||
static float rotationForSprite(float rotationRad, Sprite sprite)
|
||||
static float GetRotationForSprite(float rotationRad, Sprite sprite)
|
||||
{
|
||||
if (sprite.effects.HasFlag(SpriteEffects.FlipHorizontally) != sprite.effects.HasFlag(SpriteEffects.FlipVertically))
|
||||
// Use bitwise operations instead of HasFlag to avoid boxing, as this is performance-sensitive code.
|
||||
bool flipHorizontally = (sprite.effects & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally;
|
||||
bool flipVertically = (sprite.effects & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically;
|
||||
|
||||
if (flipHorizontally != flipVertically)
|
||||
{
|
||||
rotationRad = -rotationRad;
|
||||
}
|
||||
@@ -600,6 +611,10 @@ namespace Barotrauma
|
||||
if (GetSection(i).damage > 0)
|
||||
{
|
||||
var textPos = SectionPosition(i, true);
|
||||
if (Submarine != null)
|
||||
{
|
||||
textPos += (Submarine.DrawPosition - Submarine.Position);
|
||||
}
|
||||
textPos.Y = -textPos.Y;
|
||||
GUI.DrawString(spriteBatch, textPos, "Damage: " + (int)((GetSection(i).damage / MaxHealth) * 100f) + "%", Color.Yellow);
|
||||
}
|
||||
|
||||
@@ -89,9 +89,13 @@ namespace Barotrauma
|
||||
newRect = Submarine.AbsRect(placePosition, placeSize);
|
||||
}
|
||||
|
||||
Sprite.DrawTiled(spriteBatch, new Vector2(newRect.X, -newRect.Y), new Vector2(newRect.Width, newRect.Height), textureScale: TextureScale * Scale);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(newRect.X - GameMain.GraphicsWidth, -newRect.Y, newRect.Width + GameMain.GraphicsWidth * 2, newRect.Height), Color.White);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(newRect.X, -newRect.Y - GameMain.GraphicsHeight, newRect.Width, newRect.Height + GameMain.GraphicsHeight * 2), Color.White);
|
||||
Sprite.DrawTiled(spriteBatch, new Vector2(newRect.X, -newRect.Y), new Vector2(newRect.Width, newRect.Height), textureScale: TextureScale * Scale, color: SpriteColor);
|
||||
|
||||
float thickness = Math.Max(1.0f / cam.Zoom, 1.0f);
|
||||
int zoomInvariantWidth = (int)(GameMain.GraphicsWidth / cam.Zoom);
|
||||
int zoomInvariantHeight = (int)(GameMain.GraphicsHeight / cam.Zoom);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(newRect.X - zoomInvariantWidth, -newRect.Y, newRect.Width + zoomInvariantWidth * 2, newRect.Height), Color.White, thickness: thickness);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(newRect.X, -newRect.Y - zoomInvariantHeight, newRect.Width, newRect.Height + zoomInvariantHeight * 2), Color.White, thickness: thickness);
|
||||
}
|
||||
|
||||
public override void DrawPlacing(SpriteBatch spriteBatch, Rectangle placeRect, float scale = 1.0f, float rotation = 0.0f, SpriteEffects spriteEffects = SpriteEffects.None)
|
||||
@@ -103,7 +107,7 @@ namespace Barotrauma
|
||||
spriteBatch,
|
||||
position,
|
||||
placeRect.Size.ToVector2(),
|
||||
color: Color.White * 0.8f,
|
||||
color: SpriteColor * 0.8f,
|
||||
origin: placeRect.Size.ToVector2() * 0.5f,
|
||||
rotation: rotation,
|
||||
textureScale: TextureScale * scale,
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace Barotrauma
|
||||
foreach (Submarine sub in Loaded)
|
||||
{
|
||||
Rectangle worldBorders = sub.Borders;
|
||||
worldBorders.Location += sub.WorldPosition.ToPoint();
|
||||
worldBorders.Location += (sub.DrawPosition + sub.HiddenSubPosition).ToPoint();
|
||||
worldBorders.Y = -worldBorders.Y;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, worldBorders, Color.White, false, 0, 5);
|
||||
@@ -159,46 +159,38 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public static float DamageEffectCutoff;
|
||||
public static Color DamageEffectColor;
|
||||
|
||||
private static readonly List<Structure> depthSortedDamageable = new List<Structure>();
|
||||
public static void DrawDamageable(SpriteBatch spriteBatch, Effect damageEffect, bool editing = false, Predicate<MapEntity> predicate = null)
|
||||
{
|
||||
var entitiesToRender = !editing && visibleEntities != null ? visibleEntities : MapEntity.MapEntityList;
|
||||
|
||||
depthSortedDamageable.Clear();
|
||||
|
||||
//insertion sort according to draw depth
|
||||
foreach (MapEntity e in entitiesToRender)
|
||||
if (!editing && visibleEntities != null)
|
||||
{
|
||||
if (e is Structure structure && structure.DrawDamageEffect)
|
||||
foreach (MapEntity e in visibleEntities)
|
||||
{
|
||||
if (predicate != null)
|
||||
if (e is Structure structure && structure.DrawDamageEffect)
|
||||
{
|
||||
if (!predicate(e)) { continue; }
|
||||
if (predicate != null)
|
||||
{
|
||||
if (!predicate(structure)) { continue; }
|
||||
}
|
||||
structure.DrawDamage(spriteBatch, damageEffect, editing);
|
||||
}
|
||||
float drawDepth = structure.GetDrawDepth();
|
||||
int i = 0;
|
||||
while (i < depthSortedDamageable.Count)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (Structure structure in Structure.WallList)
|
||||
{
|
||||
if (structure.DrawDamageEffect)
|
||||
{
|
||||
float otherDrawDepth = depthSortedDamageable[i].GetDrawDepth();
|
||||
if (otherDrawDepth < drawDepth) { break; }
|
||||
i++;
|
||||
if (predicate != null)
|
||||
{
|
||||
if (!predicate(structure)) { continue; }
|
||||
}
|
||||
structure.DrawDamage(spriteBatch, damageEffect, editing);
|
||||
}
|
||||
depthSortedDamageable.Insert(i, structure);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Structure s in depthSortedDamageable)
|
||||
{
|
||||
s.DrawDamage(spriteBatch, damageEffect, editing);
|
||||
}
|
||||
if (damageEffect != null)
|
||||
{
|
||||
damageEffect.Parameters["aCutoff"].SetValue(0.0f);
|
||||
damageEffect.Parameters["cCutoff"].SetValue(0.0f);
|
||||
DamageEffectCutoff = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawPaintedColors(SpriteBatch spriteBatch, bool editing = false, Predicate<MapEntity> predicate = null)
|
||||
@@ -506,6 +498,16 @@ namespace Barotrauma
|
||||
warnings.Add(SubEditorScreen.WarningType.WaterInHulls);
|
||||
Hull.ShowHulls = true;
|
||||
}
|
||||
|
||||
if (Info.IsWreck)
|
||||
{
|
||||
Point vanillaBrainSize = new Point(204, 204);
|
||||
if (WreckAI.GetPotentialBrainRooms(this, WreckAIConfig.GetRandom(), minSize: vanillaBrainSize).None())
|
||||
{
|
||||
errorMsgs.Add(TextManager.Get("NoSuitableBrainRoomsWarning").Value);
|
||||
warnings.Add(SubEditorScreen.WarningType.NoSuitableBrainRooms);
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsWarningSuppressed(SubEditorScreen.WarningType.NotEnoughContainers))
|
||||
{
|
||||
@@ -656,6 +658,7 @@ namespace Barotrauma
|
||||
errorMsgs.Add(TextManager.GetWithVariables("InsufficientFreeConnectionsWarning",
|
||||
("[doorcount]", doorLinks.ToString()),
|
||||
("[freeconnectioncount]", (item.Connections[i].MaxWires - wireCount).ToString())).Value);
|
||||
warnings.Add(SubEditorScreen.WarningType.InsufficientFreeConnectionsWarning);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -836,7 +839,7 @@ namespace Barotrauma
|
||||
subBody.PositionBuffer.Insert(index, posInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||
{
|
||||
Identifier layerIdentifier = msg.ReadIdentifier();
|
||||
|
||||
@@ -572,8 +572,9 @@ namespace Barotrauma
|
||||
Vector2 offset = decorativeSprite.GetOffset(ref offsetState, Vector2.Zero) * scale;
|
||||
if (flippedX) { offset.X = -offset.X; }
|
||||
if (flippedY) { offset.Y = -offset.Y; }
|
||||
decorativeSprite.Sprite.Draw(spriteRecorder, new Vector2(spritePos.X + offset.X, -(spritePos.Y + offset.Y)), color,
|
||||
rotationRad + rot, decorativeSprite.GetScale(0f) * scale, prefab.Sprite.effects,
|
||||
float throwAway = 0.0f;
|
||||
decorativeSprite.Sprite.Draw(spriteRecorder, new Vector2(spritePos.X + offset.X, -(spritePos.Y + offset.Y)), color, decorativeSprite.Sprite.Origin,
|
||||
rotationRad + rot, decorativeSprite.GetScale(ref throwAway, 0f) * scale, prefab.Sprite.effects,
|
||||
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - prefab.Sprite.Depth), 0.999f));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ namespace Barotrauma
|
||||
|
||||
public override bool IsVisible(Rectangle worldView)
|
||||
{
|
||||
return Screen.Selected == GameMain.SubEditorScreen || GameMain.DebugDraw;
|
||||
if (Screen.Selected != GameMain.SubEditorScreen && !GameMain.DebugDraw) { return false; }
|
||||
return base.IsVisible(worldView);
|
||||
}
|
||||
|
||||
public override bool SelectableInEditor
|
||||
@@ -45,6 +46,10 @@ namespace Barotrauma
|
||||
}
|
||||
if (IsHighlighted || IsHighlighted) { clr = Color.Lerp(clr, Color.White, 0.8f); }
|
||||
|
||||
if (Stairs is { Removed: true }) { Stairs = null; }
|
||||
if (Ladders is { Item.Removed: true }) { Ladders = null; }
|
||||
if (ConnectedGap is { Removed: true }) { ConnectedGap = null; }
|
||||
|
||||
int iconSize = spawnType == SpawnType.Path ? WaypointSize : SpawnPointSize;
|
||||
if (ConnectedDoor != null || Ladders != null || Stairs != null || SpawnType != SpawnType.Path)
|
||||
{
|
||||
@@ -92,6 +97,11 @@ namespace Barotrauma
|
||||
if (sprite != null)
|
||||
{
|
||||
float spriteScale = iconSize / (float)sprite.SourceRect.Width;
|
||||
if (Ladders == null && ConnectedDoor == null && ConnectedGap != null)
|
||||
{
|
||||
clr = Color.White;
|
||||
spriteScale *= 1.5f;
|
||||
}
|
||||
sprite.Draw(spriteBatch, drawPos, clr, origin: sprite.size / 2, scale: spriteScale, depth: 0.001f);
|
||||
sprite2?.Draw(spriteBatch, drawPos + sprite.size * spriteScale * 0.5f, clr, origin: sprite2.size / 2, scale: spriteScale, depth: 0.001f);
|
||||
}
|
||||
@@ -100,27 +110,39 @@ namespace Barotrauma
|
||||
{
|
||||
AssignedJob.Icon.Draw(spriteBatch, drawPos, AssignedJob.UIColor, scale: iconSize / (float)AssignedJob.Icon.SourceRect.Width * 0.8f, depth: 0.0f);
|
||||
}
|
||||
|
||||
foreach (MapEntity e in linkedTo)
|
||||
|
||||
// alternate line drawing for when cloning the waypoint: line goes from current position to original position, where moving started
|
||||
if (StartMovingPos != Vector2.Zero && SelectedList.Contains(this) && PlayerInput.IsCtrlDown())
|
||||
{
|
||||
GUI.DrawLine(spriteBatch,
|
||||
drawPos,
|
||||
new Vector2(e.DrawPosition.X, -e.DrawPosition.Y),
|
||||
new Vector2(StartMovingPos.X, -StartMovingPos.Y),
|
||||
(IsTraversable ? GUIStyle.Green : Color.Gray) * 0.7f, width: 5, depth: 0.002f);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (MapEntity e in linkedTo)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch,
|
||||
drawPos,
|
||||
new Vector2(e.DrawPosition.X, -e.DrawPosition.Y),
|
||||
(IsTraversable ? GUIStyle.Green : Color.Gray) * 0.7f, width: 5, depth: 0.002f);
|
||||
}
|
||||
}
|
||||
|
||||
if (ConnectedGap != null)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch,
|
||||
drawPos,
|
||||
new Vector2(ConnectedGap.DrawPosition.X, -ConnectedGap.DrawPosition.Y),
|
||||
GUIStyle.Green * 0.5f, width: 1);
|
||||
Color.White, width: 1);
|
||||
}
|
||||
if (Ladders != null)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch,
|
||||
drawPos,
|
||||
new Vector2(Ladders.Item.DrawPosition.X, -Ladders.Item.DrawPosition.Y),
|
||||
GUIStyle.Green * 0.5f, width: 1);
|
||||
Color.White, width: 1);
|
||||
}
|
||||
|
||||
var color = Color.WhiteSmoke;
|
||||
@@ -419,6 +441,7 @@ namespace Barotrauma
|
||||
jobDropDown.AddItem(TextManager.Get("Any"), null);
|
||||
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs)
|
||||
{
|
||||
if (jobPrefab.Name.IsNullOrWhiteSpace()) { continue; }
|
||||
jobDropDown.AddItem(jobPrefab.Name, jobPrefab);
|
||||
}
|
||||
jobDropDown.SelectItem(AssignedJob);
|
||||
@@ -432,7 +455,7 @@ namespace Barotrauma
|
||||
};
|
||||
propertyBox.OnTextChanged += (textBox, text) =>
|
||||
{
|
||||
tags = text.Split(',').ToIdentifiers().ToHashSet();
|
||||
tags = text.ToIdentifiers().ToHashSet();
|
||||
return true;
|
||||
};
|
||||
propertyBox.OnEnterPressed += (textBox, text) =>
|
||||
|
||||
Reference in New Issue
Block a user