Unstable v0.1300.0.0 (February 19th 2021)

This commit is contained in:
Joonas Rikkonen
2021-02-25 13:44:23 +02:00
parent b772654326
commit 24cbef485a
441 changed files with 21343 additions and 8562 deletions
@@ -5,6 +5,8 @@ using System.Linq;
using System.Xml.Linq;
using Barotrauma.Items.Components;
using Barotrauma.Networking;
using Barotrauma.Particles;
using Barotrauma.Sounds;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework;
@@ -33,12 +35,19 @@ namespace Barotrauma.MapCreatures.Behavior
[Serialize(defaultValue: 0f, isSaveable: false)]
public float MaxVelocity { get; set; }
[Serialize(defaultValue: "255,255,255,255", isSaveable: false)]
public Color ColorMultiplier { get; set; }
private float RandRotation() => Rand.Range(MinRotation, MaxRotation);
private float RandVelocity() => Rand.Range(MinVelocity, MaxVelocity);
public void Emit(Vector2 pos)
{
GameMain.ParticleManager.CreateParticle(Identifier, pos, RandRotation(), RandVelocity());
Particle particle = GameMain.ParticleManager.CreateParticle(Identifier, pos, RandRotation(), RandVelocity());
if (particle != null)
{
particle.ColorMultiplier = ColorMultiplier.ToVector4();
}
}
public DamageParticle(XElement element)
@@ -54,6 +63,9 @@ namespace Barotrauma.MapCreatures.Behavior
public readonly List<Sprite> LeafSprites = new List<Sprite>(), DamagedLeafSprites = new List<Sprite>();
public readonly List<DamageParticle> DamageParticles = new List<DamageParticle>();
public readonly List<DamageParticle> DeathParticles = new List<DamageParticle>();
public static bool AlwaysShowBallastFloraSprite = false;
partial void LoadPrefab(XElement element)
{
@@ -97,6 +109,9 @@ namespace Barotrauma.MapCreatures.Behavior
case "damageparticle":
DamageParticles.Add(new DamageParticle(subElement));
break;
case "deathparticle":
DeathParticles.Add(new DamageParticle(subElement));
break;
case "targets":
LoadTargets(subElement);
break;
@@ -112,7 +127,7 @@ namespace Barotrauma.MapCreatures.Behavior
float particleAmount = Rand.Range(16, 32);
for (int i = 0; i < particleAmount; i++)
{
GameMain.ParticleManager.CreateParticle("shrapnel", pos, Rand.Vector(Rand.Range(-50f, 50.0f)));
GameMain.ParticleManager.CreateParticle("shrapnel", pos, Rand.Vector(Rand.Range(0f, 250.0f)), Rand.Range(0f, 360.0f));
}
}
@@ -129,11 +144,22 @@ namespace Barotrauma.MapCreatures.Behavior
}
}
private static readonly Color DarkColor = new Color(25, 25, 25);
private void CreateDeathParticle(BallastFloraBranch branch)
{
Vector2 pos = GetWorldPosition() + branch.Position;
int amount = (int)Math.Clamp(branch.MaxHealth / 10f, 1, 10);
for (int i = 0; i < amount; i++)
{
foreach (DamageParticle particle in DeathParticles)
{
particle.Emit(pos);
}
}
}
public void Draw(SpriteBatch spriteBatch)
{
const float zStep = 0.00001f;
const float zStep = 0.000001f;
float leafDepth = zStep;
float flowerDepth = zStep;
@@ -217,12 +243,12 @@ namespace Barotrauma.MapCreatures.Behavior
if (HasBrokenThrough)
{
if (branchAtlas != null)
if (branchAtlas != null && branchAtlas.Loaded)
{
spriteBatch.Draw(branchAtlas.Texture, pos + branch.offset, branchSprite.SourceRect, branchColor, 0f, branchSprite.AbsoluteOrigin, BaseBranchScale * branch.VineStep, SpriteEffects.None, layer2);
}
if (decayAtlas != null && isDamaged)
if (decayAtlas != null && isDamaged && decayAtlas.Loaded)
{
spriteBatch.Draw(decayAtlas.Texture, pos + branch.offset, branchSprite.SourceRect, branch.HealthColor, 0f, branchSprite.AbsoluteOrigin, BaseBranchScale * branch.VineStep, SpriteEffects.None, layer2 - zStep);
}
@@ -242,6 +268,10 @@ namespace Barotrauma.MapCreatures.Behavior
DamagedFlowerSprites[variant].Draw(spriteBatch, pos, branch.HealthColor, flowerSprite.Origin, scale: flowerScale, rotate: branch.FlowerConfig.Rotation, depth: layer1 - flowerDepth - zStep);
}
flowerDepth -= zStep;
if (flowerDepth > 0.01f)
{
flowerDepth = zStep;
}
}
if (branch.LeafConfig.Variant >= 0 && HasBrokenThrough)
@@ -254,6 +284,10 @@ namespace Barotrauma.MapCreatures.Behavior
DamagedLeafSprites[variant].Draw(spriteBatch, pos, branch.HealthColor, leafSprite.Origin, scale: BaseLeafScale * branch.LeafConfig.Scale * branch.FlowerStep, rotate: branch.LeafConfig.Rotation, depth: layer3 + leafDepth - zStep);
}
leafDepth += zStep;
if (leafDepth > 0.01f)
{
flowerDepth = zStep;
}
}
}
}
@@ -264,25 +298,42 @@ namespace Barotrauma.MapCreatures.Behavior
switch (header)
{
case NetworkHeader.Infect:
int infectBranch = -1;
ushort itemId = msg.ReadUInt16();
bool infect = msg.ReadBoolean();
if (Entity.FindEntityByID(itemId) is Item item)
if (infect)
{
infectBranch = msg.ReadInt32();
}
Entity? entity = Entity.FindEntityByID(itemId);
if (entity is Item item)
{
if (infect)
{
ClaimTarget(item, null);
ClaimTarget(item, Branches.FirstOrDefault(b => b.ID == infectBranch));
}
else
{
RemoveClaim(itemId);
}
}
else
{
DebugConsole.AddWarning($"Received Infect.{infect} Network Header with invalid item ID: {itemId}, which belongs to {entity?.ToString() ?? "null!"}");
}
break;
case NetworkHeader.BranchCreate:
int parentId = msg.ReadInt32();
BallastFloraBranch branch = ReadBranch(msg);
BallastFloraBranch? parent = Branches.FirstOrDefault(b => b.ID == parentId);
UpdateConnections(branch, Branches.FirstOrDefault(b => b.ID == parentId));
if (parent == null)
{
DebugConsole.AddWarning($"Received BranchCreate with an invalid parent ID: {parentId}, Maximum ID is {Branches.Max(b => b.ID)}");
}
UpdateConnections(branch, parent);
Branches.Add(branch);
OnBranchGrowthSuccess(branch);
break;
@@ -290,7 +341,15 @@ namespace Barotrauma.MapCreatures.Behavior
int removedBranchId = msg.ReadInt32();
BallastFloraBranch removedBranch = Branches.FirstOrDefault(b => b.ID == removedBranchId);
if (removedBranch != null) { RemoveBranch(removedBranch); }
if (removedBranch != null)
{
RemoveBranch(removedBranch);
}
else
{
DebugConsole.AddWarning($"Received BranchRemove for a branch that doesn't exist. ID: {removedBranchId}, Maximum ID is {Branches.Max(b => b.ID)}");
}
break;
case NetworkHeader.BranchDamage:
@@ -303,6 +362,10 @@ namespace Barotrauma.MapCreatures.Behavior
CreateDamageParticle(damagedBranch, damage);
damagedBranch.Health = health;
}
else
{
DebugConsole.AddWarning($"Received BranchDamage for a branch that doesn't exist. ID: {damageBranchId}, Maximum ID is {Branches.Max(b => b.ID)}");
}
break;
case NetworkHeader.Kill:
Kill();
@@ -326,6 +389,7 @@ namespace Barotrauma.MapCreatures.Behavior
return new BallastFloraBranch(this, pos, (VineTileType)type, FoliageConfig.Deserialize(flowerConfig), FoliageConfig.Deserialize(leafConfig))
{
ID = id,
MaxHealth = maxHealth,
Sides = (TileSide) sides
};
}
@@ -22,47 +22,47 @@ namespace Barotrauma
var underwaterExplosion = GameMain.ParticleManager.CreateParticle("underwaterexplosion", worldPosition, Vector2.Zero, 0.0f, hull);
if (underwaterExplosion != null)
{
underwaterExplosion.Size *= MathHelper.Clamp(attack.Range / 150.0f, 0.5f, 10.0f);
underwaterExplosion.Size *= MathHelper.Clamp(Attack.Range / 150.0f, 0.5f, 10.0f);
underwaterExplosion.StartDelay = 0.0f;
}
}
for (int i = 0; i < attack.Range * 0.1f; i++)
for (int i = 0; i < Attack.Range * 0.1f; i++)
{
if (!underwater)
{
float particleSpeed = Rand.Range(0.0f, 1.0f);
particleSpeed = particleSpeed * particleSpeed * attack.Range;
particleSpeed = particleSpeed * particleSpeed * Attack.Range;
if (flames)
{
float particleScale = MathHelper.Clamp(attack.Range * 0.0025f, 0.5f, 2.0f);
float particleScale = MathHelper.Clamp(Attack.Range * 0.0025f, 0.5f, 2.0f);
var flameParticle = GameMain.ParticleManager.CreateParticle("explosionfire",
ClampParticlePos(worldPosition + Rand.Vector((float)System.Math.Sqrt(Rand.Range(0.0f, attack.Range))), hull),
ClampParticlePos(worldPosition + Rand.Vector((float)System.Math.Sqrt(Rand.Range(0.0f, Attack.Range))), hull),
Rand.Vector(Rand.Range(0.0f, particleSpeed)), 0.0f, hull);
if (flameParticle != null) flameParticle.Size *= particleScale;
}
if (smoke)
{
GameMain.ParticleManager.CreateParticle(Rand.Range(0.0f, 1.0f) < 0.5f ? "explosionsmoke" : "smoke",
ClampParticlePos(worldPosition + Rand.Vector((float)System.Math.Sqrt(Rand.Range(0.0f, attack.Range))), hull),
ClampParticlePos(worldPosition + Rand.Vector((float)System.Math.Sqrt(Rand.Range(0.0f, Attack.Range))), hull),
Rand.Vector(Rand.Range(0.0f, particleSpeed)), 0.0f, hull);
}
}
else if (underwaterBubble)
{
Vector2 bubblePos = Rand.Vector(Rand.Range(0.0f, attack.Range * 0.5f));
Vector2 bubblePos = Rand.Vector(Rand.Range(0.0f, Attack.Range * 0.5f));
GameMain.ParticleManager.CreateParticle("risingbubbles", worldPosition + bubblePos,
Vector2.Zero, 0.0f, hull);
if (i < attack.Range * 0.02f)
if (i < Attack.Range * 0.02f)
{
var underwaterExplosion = GameMain.ParticleManager.CreateParticle("underwaterexplosion", worldPosition + bubblePos,
Vector2.Zero, 0.0f, hull);
if (underwaterExplosion != null)
{
underwaterExplosion.Size *= MathHelper.Clamp(attack.Range / 300.0f, 0.5f, 2.0f) * Rand.Range(0.8f, 1.2f);
underwaterExplosion.Size *= MathHelper.Clamp(Attack.Range / 300.0f, 0.5f, 2.0f) * Rand.Range(0.8f, 1.2f);
}
}
@@ -77,7 +77,7 @@ namespace Barotrauma
if (flash)
{
float displayRange = flashRange.HasValue ? flashRange.Value : attack.Range;
float displayRange = flashRange.HasValue ? flashRange.Value : Attack.Range;
if (displayRange < 0.1f) { return; }
var light = new LightSource(worldPosition, displayRange, Color.LightYellow, null);
CoroutineManager.StartCoroutine(DimLight(light));
@@ -336,6 +336,7 @@ namespace Barotrauma
public void DrawSectionColors(SpriteBatch spriteBatch)
{
if (BackgroundSections == null || BackgroundSections.Count == 0) { return; }
Vector2 drawOffset = Submarine == null ? Vector2.Zero : Submarine.DrawPosition;
Point sectionSize = BackgroundSections[0].Rect.Size;
Vector2 drawPos = drawOffset + new Vector2(rect.Location.X + sectionSize.X / 2, rect.Location.Y - sectionSize.Y / 2);
@@ -31,11 +31,20 @@ namespace Barotrauma
List<VertexPositionTexture> vertices = new List<VertexPositionTexture>();
foreach (VoronoiCell cell in cells)
{
Vector2 minVert = cell.Edges[0].Point1;
Vector2 maxVert = cell.Edges[0].Point1;
float circumference = 0.0f;
foreach (GraphEdge edge in cell.Edges)
{
circumference += Vector2.Distance(edge.Point1, edge.Point2);
minVert = new Vector2(
Math.Min(minVert.X, edge.Point1.X),
Math.Min(minVert.Y, edge.Point1.Y));
maxVert = new Vector2(
Math.Max(maxVert.X, edge.Point1.X),
Math.Max(maxVert.Y, edge.Point1.Y));
}
Vector2 center = (minVert + maxVert) / 2;
foreach (GraphEdge edge in cell.Edges)
{
if (!edge.IsSolid) { continue; }
@@ -130,8 +139,8 @@ namespace Barotrauma
break;
}
float point1UV = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(edge.Point1 - cell.Center));
float point2UV = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(edge.Point2 - cell.Center));
float point1UV = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(edge.Point1 - center));
float point2UV = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(edge.Point2 - center));
//handle wrapping around 0/360
if (point1UV - point2UV > MathHelper.Pi)
{
@@ -43,10 +43,10 @@ namespace Barotrauma
}
}
public void DrawFront(SpriteBatch spriteBatch, Camera cam)
public void DrawDebugOverlay(SpriteBatch spriteBatch, Camera cam)
{
if (renderer == null) { return; }
renderer.Draw(spriteBatch, cam);
renderer.DrawDebugOverlay(spriteBatch, cam);
if (GameMain.DebugDraw && Screen.Selected.Cam.Zoom > 0.1f)
{
@@ -114,10 +114,13 @@ namespace Barotrauma
graphics.Clear(BackgroundColor);
if (renderer == null) return;
renderer.DrawBackground(spriteBatch, cam, LevelObjectManager, backgroundCreatureManager);
renderer?.DrawBackground(spriteBatch, cam, LevelObjectManager, backgroundCreatureManager);
}
public void DrawFront(SpriteBatch spriteBatch, Camera cam)
{
renderer?.DrawForeground(spriteBatch, cam, LevelObjectManager);
}
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
bool isGlobalUpdate = msg.ReadBoolean();
@@ -3,9 +3,11 @@ using Barotrauma.Networking;
using Barotrauma.Particles;
using Barotrauma.Sounds;
using Barotrauma.SpriteDeformations;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma
@@ -72,6 +74,18 @@ namespace Barotrauma
private set;
}
public bool VisibleOnSonar
{
get;
private set;
}
public float SonarRadius
{
get;
private set;
}
partial void InitProjSpecific()
{
Sprite?.EnsureLazyLoaded();
@@ -135,6 +149,13 @@ namespace Barotrauma
}
}
}
VisibleOnSonar = Prefab.SonarDisruption > 0.0f || Prefab.OverrideProperties.Any(p => p != null && p.SonarDisruption > 0.0f) ||
(Triggers != null && Triggers.Any(t => !MathUtils.NearlyEqual(t.Force, Vector2.Zero) && t.ForceMode != LevelTrigger.TriggerForceMode.LimitVelocity || !string.IsNullOrWhiteSpace(t.InfectIdentifier)));
if (VisibleOnSonar && Triggers.Any())
{
SonarRadius = Triggers.Select(t => t.ColliderRadius * 1.5f).Max();
}
}
public void Update(float deltaTime)
@@ -220,6 +241,7 @@ namespace Barotrauma
private void UpdateDeformations(float deltaTime)
{
if (ActivePrefab.DeformableSprite == null) { return; }
foreach (SpriteDeformation deformation in spriteDeformations)
{
if (deformation is PositionalDeformation positionalDeformation)
@@ -10,6 +10,7 @@ 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>();
private double NextRefreshTime;
@@ -26,6 +27,10 @@ namespace Barotrauma
{
obj.Update(deltaTime);
}
foreach (LevelObject obj in visibleObjectsMid)
{
obj.Update(deltaTime);
}
foreach (LevelObject obj in visibleObjectsFront)
{
obj.Update(deltaTime);
@@ -34,7 +39,7 @@ namespace Barotrauma
public IEnumerable<LevelObject> GetVisibleObjects()
{
return visibleObjectsBack.Union(visibleObjectsFront);
return visibleObjectsBack.Union(visibleObjectsMid).Union(visibleObjectsFront);
}
/// <summary>
@@ -43,6 +48,7 @@ namespace Barotrauma
private void RefreshVisibleObjects(Rectangle currentIndices, float zoom)
{
visibleObjectsBack.Clear();
visibleObjectsMid.Clear();
visibleObjectsFront.Clear();
float minSizeToDraw = MathHelper.Lerp(10.0f, 5.0f, Math.Min(zoom * 20.0f, 1.0f));
@@ -70,7 +76,10 @@ namespace Barotrauma
}
}
var objectList = obj.Position.Z >= 0 ? visibleObjectsBack : visibleObjectsFront;
var objectList =
obj.Position.Z >= 0 ?
visibleObjectsBack :
(obj.Position.Z < -1 ? visibleObjectsFront : visibleObjectsMid);
int drawOrderIndex = 0;
for (int i = 0; i < objectList.Count; i++)
{
@@ -102,8 +111,31 @@ namespace Barotrauma
currentGridIndices = currentIndices;
}
/// <summary>
/// Draw the objects behind the level walls
/// </summary>
public void DrawObjectsBack(SpriteBatch spriteBatch, Camera cam)
{
DrawObjects(spriteBatch, cam, visibleObjectsBack);
}
public void DrawObjects(SpriteBatch spriteBatch, Camera cam, bool drawFront)
/// <summary>
/// Draw the objects in front of the level walls, but behind characters
/// </summary>
public void DrawObjectsMid(SpriteBatch spriteBatch, Camera cam)
{
DrawObjects(spriteBatch, cam, visibleObjectsMid);
}
/// <summary>
/// Draw the objects in front of the level walls and characters
/// </summary>
public void DrawObjectsFront(SpriteBatch spriteBatch, Camera cam)
{
DrawObjects(spriteBatch, cam, visibleObjectsFront);
}
private void DrawObjects(SpriteBatch spriteBatch, Camera cam, List<LevelObject> objectList)
{
Rectangle indices = Rectangle.Empty;
indices.X = (int)Math.Floor(cam.WorldView.X / (float)GridSize);
@@ -132,7 +164,6 @@ namespace Barotrauma
}
}
var objectList = drawFront ? visibleObjectsFront : visibleObjectsBack;
foreach (LevelObject obj in objectList)
{
Vector2 camDiff = new Vector2(obj.Position.X, obj.Position.Y) - cam.WorldViewCenter;
@@ -220,7 +220,7 @@ namespace Barotrauma
SamplerState.LinearWrap, DepthStencilState.DepthRead, null, null,
cam.Transform);
backgroundSpriteManager?.DrawObjects(spriteBatch, cam, drawFront: false);
backgroundSpriteManager?.DrawObjectsBack(spriteBatch, cam);
if (cam.Zoom > 0.05f)
{
backgroundCreatureManager?.Draw(spriteBatch, cam);
@@ -262,8 +262,6 @@ namespace Barotrauma
color: Color.White * alpha, textureScale: new Vector2(texScale));
}
}
spriteBatch.End();
RenderWalls(GameMain.Instance.GraphicsDevice, cam);
@@ -272,11 +270,21 @@ namespace Barotrauma
BlendState.NonPremultiplied,
SamplerState.LinearClamp, DepthStencilState.DepthRead, null, null,
cam.Transform);
if (backgroundSpriteManager != null) backgroundSpriteManager.DrawObjects(spriteBatch, cam, drawFront: true);
backgroundSpriteManager?.DrawObjectsMid(spriteBatch, cam);
spriteBatch.End();
}
public void Draw(SpriteBatch spriteBatch, Camera cam)
public void DrawForeground(SpriteBatch spriteBatch, Camera cam, LevelObjectManager backgroundSpriteManager = null)
{
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.NonPremultiplied,
SamplerState.LinearClamp, DepthStencilState.DepthRead, null, null,
cam.Transform);
backgroundSpriteManager?.DrawObjectsFront(spriteBatch, cam);
spriteBatch.End();
}
public void DrawDebugOverlay(SpriteBatch spriteBatch, Camera cam)
{
if (GameMain.DebugDraw && cam.Zoom > 0.1f)
{
@@ -294,7 +302,7 @@ namespace Barotrauma
{
GUI.DrawLine(spriteBatch, new Vector2(edge.Point1.X + cell.Translation.X, -(edge.Point1.Y + cell.Translation.Y)),
new Vector2(edge.Point2.X + cell.Translation.X, -(edge.Point2.Y + cell.Translation.Y)), edge.NextToCave ? Color.Red : (cell.Body == null ? Color.Cyan * 0.5f : (edge.IsSolid ? Color.White : Color.Gray)),
width: edge.NextToCave ? 8 :1);
width: edge.NextToCave ? 8 : 1);
}
foreach (Vector2 point in cell.BodyVertices)
@@ -314,6 +322,11 @@ namespace Barotrauma
}
}*/
foreach (var abyssIsland in level.AbyssIslands)
{
GUI.DrawRectangle(spriteBatch, new Vector2(abyssIsland.Area.X, -abyssIsland.Area.Y - abyssIsland.Area.Height), abyssIsland.Area.Size.ToVector2(), Color.Cyan, thickness: 5);
}
foreach (var ruin in level.Ruins)
{
ruin.DebugDraw(spriteBatch);
@@ -395,20 +408,20 @@ namespace Barotrauma
graphicsDevice.SetVertexBuffer(wall.WallBuffer);
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(wall.WallBuffer.VertexCount / 3.0f));
if (destructibleWall.Damage > 0.0f)
{
wallCenterEffect.Texture = level.GenerationParams.WallSpriteDestroyed.Texture;
wallCenterEffect.Alpha = MathHelper.Lerp(0.2f, 1.0f, destructibleWall.Damage / destructibleWall.MaxHealth) * wall.Alpha;
wallCenterEffect.CurrentTechnique.Passes[0].Apply();
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(wall.WallEdgeBuffer.VertexCount / 3.0f));
}
wallEdgeEffect.Texture = level.GenerationParams.DestructibleWallEdgeSprite?.Texture ?? level.GenerationParams.WallEdgeSprite.Texture;
wallEdgeEffect.World = wall.GetTransform() * transformMatrix;
wallEdgeEffect.Alpha = wall.Alpha;
wallEdgeEffect.CurrentTechnique.Passes[0].Apply();
graphicsDevice.SetVertexBuffer(wall.WallEdgeBuffer);
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(wall.WallEdgeBuffer.VertexCount / 3.0f));
if (destructibleWall.Damage <= 0.0f) { continue; }
wallEdgeEffect.Texture = level.GenerationParams.WallSpriteDestroyed.Texture;
wallEdgeEffect.Alpha = MathHelper.Lerp(0.2f, 1.0f, destructibleWall.Damage / destructibleWall.MaxHealth) * wall.Alpha;
wallEdgeEffect.World = wall.GetTransform() * transformMatrix;
wallEdgeEffect.CurrentTechnique.Passes[0].Apply();
graphicsDevice.SetVertexBuffer(wall.WallEdgeBuffer);
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(wall.WallEdgeBuffer.VertexCount / 3.0f));
}
}
@@ -132,7 +132,7 @@ namespace Barotrauma.Lights
public void AddLight(LightSource light)
{
if (!lights.Contains(light)) lights.Add(light);
if (!lights.Contains(light)) { lights.Add(light); }
}
public void RemoveLight(LightSource light)
@@ -153,7 +153,7 @@ namespace Barotrauma.Lights
public void Update(float deltaTime)
{
foreach (LightSource light in lights)
foreach (LightSource light in activeLights)
{
if (!light.Enabled) { continue; }
light.Update(deltaTime);
@@ -183,7 +183,7 @@ namespace Barotrauma.Lights
foreach (LightSource light in lights)
{
if (!light.Enabled) { continue; }
if ((light.Color.A < 1 || light.Range < 1.0f || light.CurrentBrightness <= 0.0f) && !light.LightSourceParams.OverrideLightSpriteAlpha.HasValue) { continue; }
if ((light.Color.A < 1 || light.Range < 1.0f) && !light.LightSourceParams.OverrideLightSpriteAlpha.HasValue) { continue; }
if (light.ParentBody != null)
{
light.Position = light.ParentBody.DrawPosition;
@@ -212,7 +212,7 @@ namespace Barotrauma.Lights
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, transformMatrix: spriteBatchTransform);
foreach (LightSource light in activeLights)
{
if (light.IsBackground) { continue; }
if (light.IsBackground || light.CurrentBrightness <= 0.0f) { continue; }
//draw limb lights at this point, because they were skipped over previously to prevent them from being obstructed
if (light.ParentBody?.UserData is Limb limb && !limb.Hide) { light.DrawSprite(spriteBatch, cam); }
}
@@ -227,7 +227,7 @@ namespace Barotrauma.Lights
Level.Loaded?.BackgroundCreatureManager?.DrawLights(spriteBatch, cam);
foreach (LightSource light in activeLights)
{
if (!light.IsBackground) { continue; }
if (!light.IsBackground || light.CurrentBrightness <= 0.0f) { continue; }
light.DrawSprite(spriteBatch, cam);
light.DrawLightVolume(spriteBatch, lightEffect, transform);
}
@@ -272,7 +272,7 @@ namespace Barotrauma.Lights
foreach (LightSource light in activeLights)
{
//don't draw limb lights at this point, they need to be drawn after lights have been obstructed by characters
if (light.IsBackground || light.ParentBody?.UserData is Limb) { continue; }
if (light.IsBackground || light.ParentBody?.UserData is Limb || light.CurrentBrightness <= 0.0f) { continue; }
light.DrawSprite(spriteBatch, cam);
}
spriteBatch.End();
@@ -337,7 +337,7 @@ namespace Barotrauma.Lights
foreach (LightSource light in activeLights)
{
if (light.IsBackground) { continue; }
if (light.IsBackground || light.CurrentBrightness <= 0.0f) { continue; }
light.DrawLightVolume(spriteBatch, lightEffect, transform);
}
@@ -391,7 +391,7 @@ namespace Barotrauma.Lights
if (GUI.DisableItemHighlights) { return false; }
highlightedEntities.Clear();
if (Character.Controlled != null && (!Character.Controlled.IsKeyDown(InputType.Aim) || Character.Controlled.SelectedItems.Any(it => it?.GetComponent<Sprayer>() == null)))
if (Character.Controlled != null && (!Character.Controlled.IsKeyDown(InputType.Aim) || Character.Controlled.HeldItems.Any(it => it.GetComponent<Sprayer>() == null)))
{
if (Character.Controlled.FocusedItem != null)
{
@@ -470,37 +470,29 @@ namespace Barotrauma.Lights
public void Update(float deltaTime)
{
float brightness = 1.0f;
if (lightSourceParams.BlinkFrequency > 0.0f)
{
blinkTimer = (blinkTimer + deltaTime * lightSourceParams.BlinkFrequency) % 1.0f;
if (blinkTimer > 0.5f)
{
CurrentBrightness = 0.0f;
return;
}
}
if (lightSourceParams.PulseFrequency > 0.0f)
if (lightSourceParams.PulseFrequency > 0.0f && lightSourceParams.PulseAmount > 0.0f)
{
pulseState = (pulseState + deltaTime * lightSourceParams.PulseFrequency) % 1.0f;
//oscillate between 0-1
brightness *= 1.0f - (float)(Math.Sin(pulseState * MathHelper.TwoPi) + 1.0f) / 2.0f * lightSourceParams.PulseAmount;
}
if (blinkTimer > 0.5f)
if (lightSourceParams.Flicker > 0.0f)
{
CurrentBrightness = 0.0f;
}
else
{
float flicker = 0.0f;
float pulse = 0.0f;
if (lightSourceParams.Flicker > 0.0f)
{
flickerState += deltaTime * lightSourceParams.FlickerSpeed;
flickerState %= 255;
flicker = PerlinNoise.GetPerlin(flickerState, flickerState * 0.5f) * lightSourceParams.Flicker;
}
if (lightSourceParams.PulseFrequency > 0.0f && lightSourceParams.PulseAmount > 0.0f)
{
//oscillate between 0-1
pulse = (float)(Math.Sin(pulseState * MathHelper.TwoPi) + 1.0f) / 2.0f * lightSourceParams.PulseAmount;
}
CurrentBrightness = (1.0f - flicker) * (1.0f - pulse);
flickerState += deltaTime * lightSourceParams.FlickerSpeed;
flickerState %= 255;
brightness *= 1.0f - PerlinNoise.GetPerlin(flickerState, flickerState * 0.5f) * lightSourceParams.Flicker;
}
CurrentBrightness = brightness;
}
/// <summary>
@@ -2,8 +2,8 @@
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Microsoft.Xna.Framework.Input;
namespace Barotrauma
{
@@ -63,6 +63,8 @@ namespace Barotrauma
private Sprite[,] mapTiles;
private bool[,] tileDiscovered;
private float connectionHighlightState;
private Pair<Rectangle, string> connectionTooltip;
#if DEBUG
@@ -120,7 +122,6 @@ namespace Barotrauma
DrawOffset = -CurrentLocation.MapPosition;
}
Vector2 tileSize = generationParams.MapTiles.Values.First().First().size * generationParams.MapTileScale;
int tilesX = (int)Math.Ceiling(Width / tileSize.X);
int tilesY = (int)Math.Ceiling(Height / tileSize.Y);
@@ -222,7 +223,7 @@ namespace Barotrauma
return !tileDiscovered[MathHelper.Clamp(x, 0, tileDiscovered.Length), MathHelper.Clamp(y, 0, tileDiscovered.Length)];
}
partial void ChangeLocationType(Location location, string prevName, LocationTypeChange change)
partial void ChangeLocationTypeProjSpecific(Location location, string prevName, LocationTypeChange change)
{
if (change.Messages.Any())
{
@@ -267,15 +268,37 @@ namespace Barotrauma
}
}
currLocationIndicatorPos = Vector2.Lerp(currLocationIndicatorPos, CurrentDisplayLocation.MapPosition, deltaTime);
Vector2 currentPosition = CurrentDisplayLocation.MapPosition;
if (Level.Loaded?.Type == LevelData.LevelType.LocationConnection && Level.Loaded.StartLocation != null && Level.Loaded.EndLocation != null)
{
Vector2 startPos = CurrentDisplayLocation == Level.Loaded.StartLocation ? Level.Loaded.StartLocation.MapPosition : Level.Loaded.EndLocation.MapPosition;
int moveDir = CurrentDisplayLocation == Level.Loaded.StartLocation ? 1 : -1;
Vector2 diff = Level.Loaded.EndLocation.MapPosition - Level.Loaded.StartLocation.MapPosition;
currentPosition = startPos +
Vector2.Normalize(diff) * Math.Min(100, diff.Length() * 0.2f) * moveDir;
}
else
{
currentPosition += Vector2.UnitY * 35;
}
currLocationIndicatorPos = Vector2.Lerp(currLocationIndicatorPos, currentPosition, deltaTime);
#if DEBUG
if (GameMain.DebugDraw)
{
if (editor == null) CreateEditor();
editor.AddToGUIUpdateList(order: 1);
}
if (PlayerInput.KeyHit(Keys.Space))
{
Radiation?.OnStep();
}
#endif
Radiation?.MapUpdate(deltaTime);
if (mapAnimQueue.Count > 0)
{
hudVisibility = Math.Max(hudVisibility - deltaTime, 0.0f);
@@ -324,6 +347,15 @@ namespace Barotrauma
}
}
if (SelectedConnection != null)
{
connectionHighlightState = Math.Min(connectionHighlightState + deltaTime, 1.0f);
}
else
{
connectionHighlightState = 0.0f;
}
if (GUI.KeyboardDispatcher.Subscriber == null)
{
float moveSpeed = 1000.0f;
@@ -336,7 +368,7 @@ namespace Barotrauma
}
targetZoom = MathHelper.Clamp(targetZoom, generationParams.MinZoom, generationParams.MaxZoom);
zoom = MathHelper.Lerp(zoom, targetZoom, 0.1f);
zoom = MathHelper.Lerp(zoom, targetZoom * GUI.Scale, 0.1f);
if (GUI.MouseOn == mapContainer)
{
@@ -351,6 +383,7 @@ namespace Barotrauma
//clients aren't allowed to select the location without a permission
if ((GameMain.GameSession?.GameMode as CampaignMode)?.AllowedToManageCampaign() ?? false)
{
connectionHighlightState = 0.0f;
SelectedConnection = connection;
SelectedLocation = HighlightedLocation;
@@ -383,12 +416,13 @@ namespace Barotrauma
Level.Loaded.DebugSetEndLocation(null);
CurrentLocation.Discovered = true;
CurrentLocation.CreateStore();
OnLocationChanged?.Invoke(prevLocation, CurrentLocation);
SelectLocation(-1);
if (GameMain.Client == null)
{
CurrentLocation.CreateStore();
ProgressWorld();
Radiation.OnStep(1);
}
else
{
@@ -483,6 +517,8 @@ namespace Barotrauma
float rawNoiseScale = 1.0f + PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1));
cameraNoiseStrength = PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1));
Radiation.Draw(spriteBatch, rect, zoom);
noiseOverlay.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(),
startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
color : Color.White * cameraNoiseStrength * 0.1f,
@@ -519,22 +555,6 @@ namespace Barotrauma
if (!rect.Intersects(drawRect)) { continue; }
if (location == CurrentDisplayLocation )
{
generationParams.CurrentLocationIndicator.Draw(spriteBatch,
rectCenter + (currLocationIndicatorPos + viewOffset) * zoom,
generationParams.IndicatorColor,
generationParams.CurrentLocationIndicator.Origin, 0, Vector2.One * (generationParams.LocationIconSize / generationParams.CurrentLocationIndicator.size.X) * 1.7f * zoom);
}
if (location == SelectedLocation)
{
generationParams.SelectedLocationIndicator.Draw(spriteBatch,
rectCenter + (location.MapPosition + viewOffset) * zoom,
generationParams.IndicatorColor,
generationParams.SelectedLocationIndicator.Origin, 0, Vector2.One * (generationParams.LocationIconSize / generationParams.SelectedLocationIndicator.size.X) * 1.7f * zoom);
}
Color color = location.Type.SpriteColor;
if (!location.Discovered) { color = Color.White; }
if (location.Connections.Find(c => c.Locations.Contains(CurrentDisplayLocation)) == null)
@@ -542,6 +562,12 @@ namespace Barotrauma
color *= 0.5f;
}
// TODO proper visualization of this
if (location.Type.HasOutpost && !location.HasOutpost())
{
color = GUI.Style.Red;
}
float iconScale = location == CurrentDisplayLocation ? 1.2f : 1.0f;
if (location == HighlightedLocation)
{
@@ -550,7 +576,35 @@ namespace Barotrauma
location.Type.Sprite.Draw(spriteBatch, pos, color,
scale: generationParams.LocationIconSize / location.Type.Sprite.size.X * iconScale * zoom);
if (location.TypeChangeTimer <= 0 && !string.IsNullOrEmpty(location.LastTypeChangeMessage) && generationParams.TypeChangeIcon != null)
if (location == CurrentDisplayLocation)
{
if (SelectedLocation != null)
{
Vector2 dir = Vector2.Normalize(SelectedLocation.MapPosition - currLocationIndicatorPos);
GUI.Arrow.Draw(spriteBatch,
rectCenter + (currLocationIndicatorPos + viewOffset) * zoom + dir * generationParams.LocationIconSize * 0.6f * zoom,
generationParams.IndicatorColor,
GUI.Arrow.Origin,
rotate: MathUtils.VectorToAngle(dir) + MathHelper.PiOver2,
new Vector2(0.5f, 1.0f) * zoom);
}
generationParams.CurrentLocationIndicator.Draw(spriteBatch,
rectCenter + (currLocationIndicatorPos + viewOffset) * zoom,
generationParams.IndicatorColor,
generationParams.CurrentLocationIndicator.Origin, 0, Vector2.One * (generationParams.LocationIconSize / generationParams.CurrentLocationIndicator.size.X) * 0.8f * zoom);
}
if (location == SelectedLocation)
{
generationParams.SelectedLocationIndicator.Draw(spriteBatch,
rectCenter + (location.MapPosition + viewOffset) * zoom,
generationParams.IndicatorColor,
generationParams.SelectedLocationIndicator.Origin, 0, Vector2.One * (generationParams.LocationIconSize / generationParams.SelectedLocationIndicator.size.X) * 1.7f * zoom);
}
if (location.TimeSinceLastTypeChange < 1 && !string.IsNullOrEmpty(location.LastTypeChangeMessage) && generationParams.TypeChangeIcon != null)
{
Vector2 typeChangeIconPos = pos + new Vector2(1.35f, -0.35f) * generationParams.LocationIconSize * 0.5f * zoom;
float typeChangeIconScale = 18.0f / generationParams.TypeChangeIcon.SourceRect.Width;
@@ -576,7 +630,7 @@ namespace Barotrauma
}
}
if (GameMain.DebugDraw && location == HighlightedLocation && (!location.Discovered || !location.Type.HasOutpost))
if (GameMain.DebugDraw && location == HighlightedLocation && (!location.Discovered || !location.HasOutpost()))
{
if (location.Reputation != null)
{
@@ -608,9 +662,9 @@ namespace Barotrauma
Vector2 pos = rectCenter + (HighlightedLocation.MapPosition + viewOffset) * zoom;
pos.X += 50 * zoom;
Vector2 nameSize = GUI.LargeFont.MeasureString(HighlightedLocation.Name);
Vector2 typeSize = GUI.Font.MeasureString(HighlightedLocation.Type.Name);
Vector2 typeSize = string.IsNullOrEmpty(HighlightedLocation.Type.Name) ? Vector2.Zero : GUI.Font.MeasureString(HighlightedLocation.Type.Name);
Vector2 size = new Vector2(Math.Max(nameSize.X, typeSize.X), nameSize.Y + typeSize.Y);
bool showReputation = HighlightedLocation.Discovered && HighlightedLocation.Type.HasOutpost && HighlightedLocation.Reputation != null;
bool showReputation = hudVisibility > 0.0f && HighlightedLocation.Discovered && HighlightedLocation.Type.HasOutpost && HighlightedLocation.Reputation != null;
string repLabelText = null, repValueText = null;
Vector2 repLabelSize = Vector2.Zero, repBarSize = Vector2.Zero;
if (showReputation)
@@ -674,19 +728,22 @@ namespace Barotrauma
int width = (int)(generationParams.LocationConnectionWidth * zoom);
//current level
if (Level.Loaded?.LevelData == connection.LevelData)
{
connectionColor = generationParams.HighlightedConnectionColor;
width = (int)(width * 1.5f);
}
//selected connection
if (SelectedLocation != CurrentDisplayLocation &&
(connection.Locations.Contains(SelectedLocation) && connection.Locations.Contains(CurrentDisplayLocation)))
connection.Locations.Contains(SelectedLocation) && connection.Locations.Contains(CurrentDisplayLocation))
{
connectionColor = generationParams.HighlightedConnectionColor;
width *= 2;
}
//highlighted connection
else if (HighlightedLocation != CurrentDisplayLocation &&
(connection.Locations.Contains(HighlightedLocation) && connection.Locations.Contains(CurrentDisplayLocation)))
connection.Locations.Contains(HighlightedLocation) && connection.Locations.Contains(CurrentDisplayLocation))
{
connectionColor = generationParams.HighlightedConnectionColor;
width *= 2;
@@ -741,47 +798,90 @@ namespace Barotrauma
}
float dist = Vector2.Distance(start, end);
var connectionSprite = connection.Passed ? generationParams.PassedConnectionSprite : generationParams.ConnectionSprite;
Color segmentColor = connectionColor;
int segmentWidth = width;
if (connection == SelectedConnection)
{
float t = (i - startIndex) / (float)(endIndex - startIndex - 1);
if (CurrentDisplayLocation == connection.Locations[1]) { t = 1.0f - t; }
if (t > connectionHighlightState)
{
segmentWidth /= 2;
segmentColor = connection.Passed ? generationParams.ConnectionColor : generationParams.UnvisitedConnectionColor;
}
else
{
}
}
spriteBatch.Draw(connectionSprite.Texture,
new Rectangle((int)start.X, (int)start.Y, (int)(dist - 1 * zoom), width),
connectionSprite.SourceRect, connectionColor * a, MathUtils.VectorToAngle(end - start),
new Rectangle((int)start.X, (int)start.Y, (int)(dist - 1 * zoom), segmentWidth),
connectionSprite.SourceRect, segmentColor * a,
MathUtils.VectorToAngle(end - start),
new Vector2(0, connectionSprite.size.Y / 2), SpriteEffects.None, 0.01f);
}
int iconCount = 0, iconIndex = 0;
if (connectionStart.HasValue && connectionEnd.HasValue)
{
GUIComponentStyle crushDepthWarningIconStyle = null;
{
if (connection.LevelData.HasBeaconStation) { iconCount++; }
if (connection.LevelData.HasHuntingGrounds) { iconCount++; }
string tooltip = null;
if (connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio > connection.LevelData.RealWorldCrushDepth)
var subCrushDepth = Submarine.MainSub?.RealWorldCrushDepth ?? Level.DefaultRealWorldCrushDepth;
if (GameMain.GameSession?.Campaign?.UpgradeManager != null)
{
crushDepthWarningIconStyle = GUI.Style.GetComponentStyle("CrushDepthWarningHighIcon");
var hullUpgradePrefab = UpgradePrefab.Find("increasewallhealth");
if (hullUpgradePrefab != null)
{
int pendingLevel = GameMain.GameSession.Campaign.UpgradeManager.GetUpgradeLevel(hullUpgradePrefab, hullUpgradePrefab.UpgradeCategories.First());
int currentLevel = GameMain.GameSession.Campaign.UpgradeManager.GetRealUpgradeLevel(hullUpgradePrefab, hullUpgradePrefab.UpgradeCategories.First());
if (pendingLevel > currentLevel)
{
string updateValueStr = hullUpgradePrefab.SourceElement?.Element("Structure")?.GetAttributeString("crushdepth", null);
if (!string.IsNullOrEmpty(updateValueStr))
{
subCrushDepth = PropertyReference.CalculateUpgrade(subCrushDepth, pendingLevel - currentLevel, updateValueStr);
}
}
}
}
string crushDepthWarningIconStyle = null;
if (connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio > subCrushDepth)
{
iconCount++;
crushDepthWarningIconStyle = "CrushDepthWarningHighIcon";
tooltip = "crushdepthwarninghigh";
}
else if ((connection.LevelData.InitialDepth + connection.LevelData.Size.Y) * Physics.DisplayToRealWorldRatio > connection.LevelData.RealWorldCrushDepth)
else if ((connection.LevelData.InitialDepth + connection.LevelData.Size.Y) * Physics.DisplayToRealWorldRatio > subCrushDepth)
{
crushDepthWarningIconStyle = GUI.Style.GetComponentStyle("CrushDepthWarningLowIcon");
iconCount++;
crushDepthWarningIconStyle = "CrushDepthWarningLowIcon";
tooltip = "crushdepthwarninglow";
}
if (connection.LevelData.HasBeaconStation)
{
var beaconStationIconStyle = connection.LevelData.IsBeaconActive ? "BeaconStationActive" : "BeaconStationInactive";
DrawIcon(beaconStationIconStyle, (int)(28 * zoom), TextManager.Get(connection.LevelData.IsBeaconActive ? "BeaconStationActiveTooltip" : "BeaconStationInactiveTooltip"));
}
if (connection.LevelData.HasHuntingGrounds)
{
DrawIcon("HuntingGrounds", (int)(28 * zoom), TextManager.Get("HuntingGroundsTooltip"));
}
if (crushDepthWarningIconStyle != null)
{
Vector2 iconPos = (connectionStart.Value + connectionEnd.Value) / 2;
float iconSize = 32.0f * GUI.Scale;
bool mouseOn = HighlightedLocation == null && Vector2.DistanceSquared(iconPos, PlayerInput.MousePosition) < iconSize * iconSize;
Sprite crushDepthWarningIcon = crushDepthWarningIconStyle.GetDefaultSprite();
crushDepthWarningIcon.Draw(spriteBatch, iconPos,
mouseOn ? crushDepthWarningIconStyle.HoverColor : crushDepthWarningIconStyle.Color,
scale: iconSize / crushDepthWarningIcon.size.X);
if (mouseOn)
{
connectionTooltip = new Pair<Rectangle, string>(
new Rectangle(iconPos.ToPoint(), new Point((int)iconSize)),
TextManager.Get(tooltip)
DrawIcon(crushDepthWarningIconStyle, (int)(32 * zoom),
TextManager.Get(tooltip)
.Replace("[initialdepth]", ((int)(connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio)).ToString())
.Replace("[submarinecrushdepth]", ((int)(Submarine.MainSub?.RealWorldCrushDepth ?? Level.DefaultRealWorldCrushDepth)).ToString()));
}
.Replace("[submarinecrushdepth]", ((int)subCrushDepth).ToString()));
}
}
if (GameMain.DebugDraw && zoom > 1.0f && generationParams.ShowLevelTypeNames)
if (GameMain.DebugDraw && zoom > (1.0f * GUI.Scale) && generationParams.ShowLevelTypeNames)
{
Vector2 center = rectCenter + (connection.CenterPos + viewOffset) * zoom;
if (viewArea.Contains(center) && connection.Biome != null)
@@ -789,6 +889,25 @@ namespace Barotrauma
GUI.DrawString(spriteBatch, center, connection.Biome.Identifier + " (" + connection.Difficulty + ")", Color.White);
}
}
void DrawIcon(string iconStyle, int iconSize, string tooltip)
{
Vector2 iconPos = (connectionStart.Value + connectionEnd.Value) / 2;
Vector2 iconDiff = Vector2.Normalize(connectionEnd.Value - connectionStart.Value) * iconSize;
iconPos += (iconDiff * -(iconCount - 1) / 2.0f) + iconDiff * iconIndex;
var style = GUI.Style.GetComponentStyle(iconStyle);
bool mouseOn = HighlightedLocation == null && Vector2.DistanceSquared(iconPos, PlayerInput.MousePosition) < iconSize * iconSize;
Sprite iconSprite = style.GetDefaultSprite();
iconSprite.Draw(spriteBatch, iconPos, (mouseOn ? style.HoverColor : style.Color) * 0.7f,
scale: iconSize / iconSprite.size.X);
if (mouseOn)
{
connectionTooltip = new Pair<Rectangle, string>(new Rectangle(iconPos.ToPoint(), new Point(iconSize)), tooltip);
}
iconIndex++;
}
}
private float hudVisibility;
@@ -819,8 +938,9 @@ namespace Barotrauma
return;
}
if (anim.StartZoom == null) { anim.StartZoom = MathUtils.InverseLerp(generationParams.MinZoom, generationParams.MaxZoom, zoom); }
if (anim.EndZoom == null) { anim.EndZoom = MathUtils.InverseLerp(generationParams.MinZoom, generationParams.MaxZoom, zoom); }
float unscaledZoom = zoom / GUI.Scale;
if (anim.StartZoom == null) { anim.StartZoom = MathUtils.InverseLerp(generationParams.MinZoom, generationParams.MaxZoom, unscaledZoom); }
if (anim.EndZoom == null) { anim.EndZoom = MathUtils.InverseLerp(generationParams.MinZoom, generationParams.MaxZoom, unscaledZoom); }
anim.StartPos = (anim.StartLocation == null) ? -DrawOffset : anim.StartLocation.MapPosition;
@@ -833,7 +953,8 @@ namespace Barotrauma
zoom =
MathHelper.Lerp(generationParams.MinZoom, generationParams.MaxZoom,
MathHelper.SmoothStep(anim.StartZoom.Value, anim.EndZoom.Value, t));
MathHelper.SmoothStep(anim.StartZoom.Value, anim.EndZoom.Value, t))
* GUI.Scale;
if (anim.Timer >= anim.Duration)
{
@@ -0,0 +1,38 @@
#nullable enable
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Barotrauma
{
internal partial class Radiation
{
public void Draw(SpriteBatch spriteBatch, Rectangle container, float zoom)
{
if (!Enabled) { return; }
UISprite uiSprite = GUI.Style.RadiationSprite;
var (offsetX, offsetY) = Map.DrawOffset * zoom;
var (centerX, centerY) = container.Center.ToVector2();
var (halfSizeX, halfSizeY) = new Vector2(container.Width / 2f, container.Height / 2f) * zoom;
float viewBottom = centerY + Map.Height * zoom;
Vector2 topLeft = new Vector2(centerX + offsetX - halfSizeX, centerY + offsetY - halfSizeY);
Vector2 size = new Vector2((Amount - increasedAmount) * zoom + halfSizeX, viewBottom - topLeft.Y);
if (size.X < 0) { return; }
uiSprite.Sprite.DrawTiled(spriteBatch, topLeft, size, GUI.Style.Red * 0.33f, Vector2.Zero, textureScale: new Vector2(zoom));
if (container.Contains(PlayerInput.MousePosition) && PlayerInput.MousePosition.X < topLeft.X + size.X)
{
// TODO tooltip?
}
}
public void MapUpdate(float deltaTime)
{
if (increasedAmount > 0)
{
increasedAmount -= (lastIncrease / Params.AnimationSpeed) * deltaTime;
}
}
}
}
@@ -114,6 +114,18 @@ namespace Barotrauma
public MapEntity ReplacedBy;
public virtual void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) { }
/// <summary>
/// A method that modifies the draw depth to prevent z-fighting between entities with the same sprite depth
/// </summary>
public float GetDrawDepth(float baseDepth, Sprite sprite)
{
float depth = baseDepth
//take texture into account to get entities with (roughly) the same base depth and texture to render consecutively to minimize texture swaps
+ (sprite?.Texture?.SortingKey ?? 0) % 100 * 0.00001f
+ ID % 100 * 0.000001f;
return Math.Min(depth, 1.0f);
}
/// <summary>
/// Update the selection logic in submarine editor
@@ -202,7 +214,7 @@ namespace Barotrauma
}
else if (PlayerInput.KeyHit(Keys.V))
{
Paste(cam.WorldViewCenter);
Paste(cam.ScreenToWorld(PlayerInput.MousePosition));
}
else if (PlayerInput.KeyHit(Keys.G))
{
@@ -267,31 +279,10 @@ namespace Barotrauma
if (GUI.KeyboardDispatcher.Subscriber == null)
{
int up = PlayerInput.KeyDown(Keys.Up) ? 1 : 0,
down = PlayerInput.KeyDown(Keys.Down) ? -1 : 0,
left = PlayerInput.KeyDown(Keys.Left) ? -1 : 0,
right = PlayerInput.KeyDown(Keys.Right) ? 1 : 0;
int xKeysDown = (left + right);
int yKeysDown = (up + down);
if (xKeysDown != 0 || yKeysDown != 0) { keyDelay += (float) Timing.Step; } else { keyDelay = 0; }
Vector2 nudgeAmount = Vector2.Zero;
if (keyDelay >= 0.5f)
Vector2 nudge = GetNudgeAmount();
if (nudge != Vector2.Zero)
{
nudgeAmount.Y = yKeysDown;
nudgeAmount.X = xKeysDown;
}
if (PlayerInput.KeyHit(Keys.Up)) nudgeAmount.Y = 1f;
if (PlayerInput.KeyHit(Keys.Down)) nudgeAmount.Y = -1f;
if (PlayerInput.KeyHit(Keys.Left)) nudgeAmount.X = -1f;
if (PlayerInput.KeyHit(Keys.Right)) nudgeAmount.X = 1f;
if (nudgeAmount != Vector2.Zero)
{
foreach (MapEntity entityToNudge in selectedList) { entityToNudge.Move(nudgeAmount); }
foreach (MapEntity entityToNudge in selectedList) { entityToNudge.Move(nudge); }
}
}
else
@@ -464,6 +455,8 @@ namespace Barotrauma
{
if (PlayerInput.PrimaryMouseButtonHeld() &&
PlayerInput.KeyUp(Keys.Space) &&
PlayerInput.KeyUp(Keys.LeftAlt) &&
PlayerInput.KeyUp(Keys.RightAlt) &&
(highlightedListBox == null || (GUI.MouseOn != highlightedListBox && !highlightedListBox.IsParentOf(GUI.MouseOn))))
{
//if clicking a selected entity, start moving it
@@ -479,6 +472,37 @@ namespace Barotrauma
}
}
public static Vector2 GetNudgeAmount(bool doHold = true)
{
Vector2 nudgeAmount = Vector2.Zero;
if (doHold)
{
int up = PlayerInput.KeyDown(Keys.Up) ? 1 : 0,
down = PlayerInput.KeyDown(Keys.Down) ? -1 : 0,
left = PlayerInput.KeyDown(Keys.Left) ? -1 : 0,
right = PlayerInput.KeyDown(Keys.Right) ? 1 : 0;
int xKeysDown = (left + right);
int yKeysDown = (up + down);
if (xKeysDown != 0 || yKeysDown != 0) { keyDelay += (float) Timing.Step; } else { keyDelay = 0; }
if (keyDelay >= 0.5f)
{
nudgeAmount.Y = yKeysDown;
nudgeAmount.X = xKeysDown;
}
}
if (PlayerInput.KeyHit(Keys.Up)) nudgeAmount.Y = 1f;
if (PlayerInput.KeyHit(Keys.Down)) nudgeAmount.Y = -1f;
if (PlayerInput.KeyHit(Keys.Left)) nudgeAmount.X = -1f;
if (PlayerInput.KeyHit(Keys.Right)) nudgeAmount.X = 1f;
return nudgeAmount;
}
public MapEntity GetReplacementOrThis()
{
return ReplacedBy?.GetReplacementOrThis() ?? this;
@@ -499,7 +523,7 @@ namespace Barotrauma
{
if (entities == null)
{
if (potentialContainer.OwnInventory != null && potentialContainer.ParentInventory == null && !potentialContainer.OwnInventory.IsFull())
if (potentialContainer.OwnInventory != null && potentialContainer.ParentInventory == null && !potentialContainer.OwnInventory.IsFull(takeStacksIntoAccount: true))
{
targetContainer = potentialContainer;
break;
@@ -45,7 +45,10 @@ namespace Barotrauma
{
CreateInstance(newRect);
placePosition = Vector2.Zero;
selected = null;
if (!PlayerInput.IsShiftDown())
{
selected = null;
}
}
newRect.Y = -newRect.Y;
@@ -24,7 +24,7 @@ namespace Barotrauma
{
get
{
if (!GameMain.SubEditorScreen.ShowThalamus && prefab.Category.HasFlag(MapEntityCategory.Thalamus))
if (GameMain.SubEditorScreen.IsSubcategoryHidden(prefab.Subcategory))
{
return false;
}
@@ -191,10 +191,11 @@ namespace Barotrauma
Vector2 max = new Vector2(worldRect.Right, worldRect.Y);
foreach (DecorativeSprite decorativeSprite in Prefab.DecorativeSprites)
{
min.X = Math.Min(worldPos.X - decorativeSprite.Sprite.size.X * decorativeSprite.Sprite.RelativeOrigin.X * decorativeSprite.Scale * Scale, min.X);
max.X = Math.Max(worldPos.X + decorativeSprite.Sprite.size.X * (1.0f - decorativeSprite.Sprite.RelativeOrigin.X) * decorativeSprite.Scale * Scale, max.X);
min.Y = Math.Min(worldPos.Y - decorativeSprite.Sprite.size.Y * (1.0f - decorativeSprite.Sprite.RelativeOrigin.Y) * decorativeSprite.Scale * Scale, min.Y);
max.Y = Math.Max(worldPos.Y + decorativeSprite.Sprite.size.Y * decorativeSprite.Sprite.RelativeOrigin.Y * decorativeSprite.Scale * Scale, max.Y);
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);
}
if (min.X > worldView.Right || max.X < worldView.X) { return false; }
@@ -220,11 +221,14 @@ namespace Barotrauma
Draw(spriteBatch, editing, false, damageEffect);
}
private float GetRealDepth()
{
return SpriteDepthOverrideIsSet ? SpriteOverrideDepth : prefab.sprite.Depth;
}
public float GetDrawDepth()
{
float depth = SpriteDepthOverrideIsSet ? SpriteOverrideDepth : prefab.sprite.Depth;
depth -= (ID % 255) * 0.000001f;
return depth;
return GetDrawDepth(GetRealDepth(), prefab.sprite);
}
private void Draw(SpriteBatch spriteBatch, bool editing, bool back = true, Effect damageEffect = null)
@@ -254,7 +258,7 @@ namespace Barotrauma
thickness: Math.Max(1, (int)(2 / Screen.Selected.Cam.Zoom)));
}
bool isWiringMode = editing && SubEditorScreen.IsWiringMode();
bool isWiringMode = editing && SubEditorScreen.TransparentWiringMode && SubEditorScreen.IsWiringMode();
if (isWiringMode) { color *= 0.15f; }
@@ -263,8 +267,8 @@ namespace Barotrauma
float depth = GetDrawDepth();
Vector2 textureOffset = this.textureOffset;
if (FlippedX) textureOffset.X = -textureOffset.X;
if (FlippedY) textureOffset.Y = -textureOffset.Y;
if (FlippedX) { textureOffset.X = -textureOffset.X; }
if (FlippedY) { textureOffset.Y = -textureOffset.Y; }
if (back && damageEffect == null && !isWiringMode)
{
@@ -304,7 +308,7 @@ namespace Barotrauma
color: Prefab.BackgroundSpriteColor,
textureScale: TextureScale * Scale,
startOffset: backGroundOffset,
depth: Math.Max(Prefab.BackgroundSprite.Depth + (ID % 255) * 0.000001f, depth + 0.000001f));
depth: Math.Max(GetDrawDepth(Prefab.BackgroundSprite.Depth, Prefab.BackgroundSprite), depth + 0.000001f));
if (UseDropShadow)
{
@@ -322,13 +326,14 @@ namespace Barotrauma
}
}
if (back == depth > 0.5f)
if (back == GetRealDepth() > 0.5f)
{
SpriteEffects oldEffects = prefab.sprite.effects;
prefab.sprite.effects ^= SpriteEffects;
for (int i = 0; i < Sections.Length; i++)
{
Rectangle drawSection = Sections[i].rect;
if (damageEffect != null)
{
float newCutoff = MathHelper.Lerp(0.0f, 0.65f, Sections[i].damage / MaxHealth);
@@ -345,21 +350,30 @@ namespace Barotrauma
Submarine.DamageEffectColor = color;
}
}
if (!HasDamage && i == 0)
{
drawSection = new Rectangle(
drawSection.X,
drawSection.Y,
Sections[Sections.Length -1 ].rect.Right - drawSection.X,
drawSection.Y - (Sections[Sections.Length - 1].rect.Y - Sections[Sections.Length - 1].rect.Height));
i = Sections.Length;
}
Vector2 sectionOffset = new Vector2(
Math.Abs(rect.Location.X - Sections[i].rect.Location.X),
Math.Abs(rect.Location.Y - Sections[i].rect.Location.Y));
Math.Abs(rect.Location.X - drawSection.Location.X),
Math.Abs(rect.Location.Y - drawSection.Location.Y));
if (FlippedX && IsHorizontal) sectionOffset.X = Sections[i].rect.Right - rect.Right;
if (FlippedY && !IsHorizontal) sectionOffset.Y = (rect.Y - rect.Height) - (Sections[i].rect.Y - Sections[i].rect.Height);
if (FlippedX && IsHorizontal) { sectionOffset.X = drawSection.Right - rect.Right; }
if (FlippedY && !IsHorizontal) { sectionOffset.Y = (rect.Y - rect.Height) - (drawSection.Y - drawSection.Height); }
sectionOffset.X += MathUtils.PositiveModulo((int)-textureOffset.X, prefab.sprite.SourceRect.Width);
sectionOffset.Y += MathUtils.PositiveModulo((int)-textureOffset.Y, prefab.sprite.SourceRect.Height);
prefab.sprite.DrawTiled(
spriteBatch,
new Vector2(Sections[i].rect.X + drawOffset.X, -(Sections[i].rect.Y + drawOffset.Y)),
new Vector2(Sections[i].rect.Width, Sections[i].rect.Height),
new Vector2(drawSection.X + drawOffset.X, -(drawSection.Y + drawOffset.Y)),
new Vector2(drawSection.Width, drawSection.Height),
color: color,
startOffset: sectionOffset,
depth: depth,
@@ -369,10 +383,10 @@ namespace Barotrauma
foreach (var decorativeSprite in Prefab.DecorativeSprites)
{
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState) * Scale;
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState, spriteAnimState[decorativeSprite].RandomRotationFactor);
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState, spriteAnimState[decorativeSprite].RandomOffsetMultiplier) * Scale;
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(DrawPosition.X + offset.X, -(DrawPosition.Y + offset.Y)), color,
rotation, decorativeSprite.Scale * Scale, prefab.sprite.effects,
rotation, decorativeSprite.GetScale(spriteAnimState[decorativeSprite].RandomScaleFactor) * Scale, prefab.sprite.effects,
depth: Math.Min(depth + (decorativeSprite.Sprite.Depth - prefab.sprite.Depth), 0.999f));
}
prefab.sprite.effects = oldEffects;
@@ -62,7 +62,11 @@ namespace Barotrauma
};
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(new List<MapEntity> { structure }, false));
selected = null;
placePosition = Vector2.Zero;
if (!PlayerInput.IsShiftDown())
{
selected = null;
}
return;
}
}
@@ -22,6 +22,8 @@ namespace Barotrauma
public readonly float Range;
public readonly Vector2 FrequencyMultiplierRange;
public readonly bool Stream;
public readonly bool IgnoreMuffling;
public string Filename
{
@@ -55,7 +57,7 @@ namespace Barotrauma
{
DebugConsole.ThrowError($"Loaded frequency range exceeds max value: {FrequencyMultiplierRange} (original string was \"{freqMultAttr}\")");
}
sound.IgnoreMuffling = element.GetAttributeBool("dontmuffle", false);
IgnoreMuffling = element.GetAttributeBool("dontmuffle", false);
}
public float GetRandomFrequencyMultiplier()
@@ -376,22 +378,19 @@ namespace Barotrauma
public static void DrawGrid(SpriteBatch spriteBatch, int gridCells, Vector2 gridCenter, Vector2 roundedGridCenter, float alpha = 1.0f)
{
var horizontalLine = GUI.Style.GetComponentStyle("HorizontalLine").GetDefaultSprite();
var verticalLine = GUI.Style.GetComponentStyle("VerticalLine").GetDefaultSprite();
Vector2 topLeft = roundedGridCenter - Vector2.One * GridSize * gridCells / 2;
Vector2 bottomRight = roundedGridCenter + Vector2.One * GridSize * gridCells / 2;
for (int i = 0; i < gridCells; i++)
{
float distFromGridX = (MathUtils.RoundTowardsClosest(gridCenter.X, GridSize.X) - gridCenter.X) / GridSize.X;
float distFromGridY = (MathUtils.RoundTowardsClosest(gridCenter.X, GridSize.Y) - gridCenter.X) / GridSize.Y;
float distFromGridY = (MathUtils.RoundTowardsClosest(gridCenter.Y, GridSize.Y) - gridCenter.Y) / GridSize.Y;
float normalizedDistX = Math.Abs(i + distFromGridX - gridCells / 2) / (gridCells / 2);
float normalizedDistY = Math.Abs(i - distFromGridY - gridCells / 2) / (gridCells / 2);
float expandX = MathHelper.Lerp(30.0f, 0.0f, normalizedDistX);
float expandY = MathHelper.Lerp(30.0f, 0.0f, normalizedDistY);
float expandX = MathHelper.Lerp(30.0f, 0.0f, normalizedDistY);
float expandY = MathHelper.Lerp(30.0f, 0.0f, normalizedDistX);
GUI.DrawLine(spriteBatch,
new Vector2(topLeft.X - expandX, -bottomRight.Y + i * GridSize.Y),
@@ -420,9 +419,10 @@ namespace Barotrauma
parent.RectTransform, Anchor.Center),
style: null);
var connectedSubs = GetConnectedSubs();
foreach (Hull hull in Hull.hullList)
{
if (hull.Submarine != this && !(DockedTo.Contains(hull.Submarine))) continue;
if (hull.Submarine != this && !connectedSubs.Contains(hull.Submarine)) { continue; }
if (ignoreOutpost && !IsEntityFoundOnThisSub(hull, true)) { continue; }
Vector2 relativeHullPos = new Vector2(
@@ -533,11 +533,11 @@ namespace Barotrauma
for (int i = 0; i < item.Connections.Count; i++)
{
int wireCount = item.Connections[i].Wires.Count(w => w != null);
if (doorLinks + wireCount > Connection.MaxLinked)
if (doorLinks + wireCount > item.Connections[i].MaxWires)
{
errorMsgs.Add(TextManager.GetWithVariables("InsufficientFreeConnectionsWarning",
new string[] { "[doorcount]", "[freeconnectioncount]" },
new string[] { doorLinks.ToString(), (Connection.MaxLinked - wireCount).ToString() }));
new string[] { doorLinks.ToString(), (item.Connections[i].MaxWires - wireCount).ToString() }));
break;
}
}
@@ -79,14 +79,22 @@ namespace Barotrauma
if (maxDamageStructure != null)
{
SoundPlayer.PlayDamageSound(
soundTag,
impact * 10.0f,
ConvertUnits.ToDisplayUnits(impactSimPos),
MathHelper.Lerp(2000.0f, 10000.0f, (impact - MinCollisionImpact) / 2.0f),
maxDamageStructure.Tags);
PlayDamageSound(impactSimPos, impact, soundTag, maxDamageStructure);
}
}
private void PlayDamageSound(Vector2 impactSimPos, float impact, string soundTag, Structure hitStructure = null)
{
if (impact < MinCollisionImpact) { return; }
SoundPlayer.PlayDamageSound(
soundTag,
impact * 10.0f,
ConvertUnits.ToDisplayUnits(impactSimPos),
MathHelper.Lerp(2000.0f, 10000.0f, (impact - MinCollisionImpact) / 2.0f),
hitStructure?.Tags);
}
}
}