Unstable 1.8.4.0
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using Barotrauma.Extensions;
|
||||
using FarseerPhysics;
|
||||
using FarseerPhysics.Common;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
@@ -10,7 +11,7 @@ namespace Barotrauma.Particles
|
||||
class Particle
|
||||
{
|
||||
private ParticlePrefab prefab;
|
||||
|
||||
|
||||
private string debugName = "Particle (uninitialized)";
|
||||
|
||||
public delegate void OnChangeHullHandler(Vector2 position, Hull currentHull);
|
||||
@@ -72,7 +73,7 @@ namespace Barotrauma.Particles
|
||||
|
||||
public float VelocityChangeMultiplier;
|
||||
|
||||
public bool DrawOnTop { get; private set; }
|
||||
public ParticleDrawOrder DrawOrder { get; private set; }
|
||||
|
||||
public ParticlePrefab.DrawTargetType DrawTarget
|
||||
{
|
||||
@@ -110,9 +111,12 @@ namespace Barotrauma.Particles
|
||||
{
|
||||
return debugName;
|
||||
}
|
||||
public void Init(ParticlePrefab prefab, Vector2 position, Vector2 speed, float rotation, Hull hullGuess = null, bool drawOnTop = false, float collisionIgnoreTimer = 0f, float lifeTimeMultiplier = 1f, Tuple<Vector2, Vector2> tracerPoints = null)
|
||||
public void Init(ParticlePrefab prefab, Vector2 spawnPosition, Vector2 speed, float spawnRotation, Hull hullGuess = null, ParticleDrawOrder drawOrder = ParticleDrawOrder.Default, float collisionIgnoreTimer = 0f, float lifeTimeMultiplier = 1f, Tuple<Vector2, Vector2> tracerPoints = null)
|
||||
{
|
||||
this.prefab = prefab;
|
||||
|
||||
System.Diagnostics.Debug.Assert(position.IsValid(), "Attempted to spawn a particle at an invalid position.");
|
||||
|
||||
#if DEBUG
|
||||
debugName = $"Particle ({prefab.Name})";
|
||||
#else
|
||||
@@ -124,14 +128,14 @@ namespace Barotrauma.Particles
|
||||
animState = 0;
|
||||
animFrame = 0;
|
||||
|
||||
currentHull = prefab.CanEnterSubs ? Hull.FindHull(position, hullGuess) : null;
|
||||
currentHull = prefab.CanEnterSubs ? Hull.FindHull(spawnPosition, hullGuess) : null;
|
||||
|
||||
size = prefab.StartSizeMin + (prefab.StartSizeMax - prefab.StartSizeMin) * Rand.Range(0.0f, 1.0f);
|
||||
|
||||
if (tracerPoints != null)
|
||||
{
|
||||
size = new Vector2(Vector2.Distance(tracerPoints.Item1, tracerPoints.Item2), size.Y);
|
||||
position = (tracerPoints.Item1 + tracerPoints.Item2) / 2;
|
||||
spawnPosition = (tracerPoints.Item1 + tracerPoints.Item2) / 2;
|
||||
}
|
||||
|
||||
RefreshColliderSize();
|
||||
@@ -139,23 +143,19 @@ namespace Barotrauma.Particles
|
||||
sizeChange = prefab.SizeChangeMin + (prefab.SizeChangeMax - prefab.SizeChangeMin) * Rand.Range(0.0f, 1.0f);
|
||||
changesSize = !sizeChange.NearlyEquals(Vector2.Zero);
|
||||
|
||||
this.position = position;
|
||||
prevPosition = position;
|
||||
|
||||
drawPosition = position;
|
||||
|
||||
velocity = MathUtils.IsValid(speed) ? speed : Vector2.Zero;
|
||||
|
||||
if (currentHull?.Submarine != null)
|
||||
{
|
||||
velocity += ConvertUnits.ToDisplayUnits(currentHull.Submarine.Velocity);
|
||||
//convert to the sub's coordinate space
|
||||
spawnPosition -= currentHull.Submarine.Position;
|
||||
}
|
||||
|
||||
position = prevPosition = drawPosition = spawnPosition;
|
||||
velocity = MathUtils.IsValid(speed) ? speed : Vector2.Zero;
|
||||
|
||||
this.rotation = rotation + Rand.Range(prefab.StartRotationMinRad, prefab.StartRotationMaxRad);
|
||||
prevRotation = rotation;
|
||||
rotation = spawnRotation + Rand.Range(prefab.StartRotationMinRad, prefab.StartRotationMaxRad);
|
||||
prevRotation = spawnRotation;
|
||||
|
||||
angularVelocity = Rand.Range(prefab.AngularVelocityMinRad, prefab.AngularVelocityMaxRad);
|
||||
|
||||
|
||||
if (prefab.LifeTimeMin <= 0.0f)
|
||||
{
|
||||
@@ -202,10 +202,10 @@ namespace Barotrauma.Particles
|
||||
{
|
||||
this.rotation = MathUtils.VectorToAngle(new Vector2(velocity.X, -velocity.Y));
|
||||
|
||||
prevRotation = rotation;
|
||||
prevRotation = spawnRotation;
|
||||
}
|
||||
|
||||
DrawOnTop = drawOnTop;
|
||||
DrawOrder = drawOrder;
|
||||
|
||||
this.collisionIgnoreTimer = collisionIgnoreTimer;
|
||||
}
|
||||
@@ -248,7 +248,7 @@ namespace Barotrauma.Particles
|
||||
rotation += angularVelocity * deltaTime;
|
||||
}
|
||||
|
||||
bool inWater = (currentHull == null || (currentHull.Submarine != null && position.Y - currentHull.Submarine.DrawPosition.Y < currentHull.Surface));
|
||||
bool inWater = (currentHull == null || (currentHull.Submarine != null && position.Y < currentHull.Surface));
|
||||
if (inWater)
|
||||
{
|
||||
velocity.X += velocityChangeWater.X * VelocityChangeMultiplier * deltaTime;
|
||||
@@ -323,7 +323,7 @@ namespace Barotrauma.Particles
|
||||
if (collisionIgnoreTimer > 0f)
|
||||
{
|
||||
collisionIgnoreTimer -= deltaTime;
|
||||
if (collisionIgnoreTimer <= 0f) { currentHull ??= Hull.FindHull(position); }
|
||||
if (collisionIgnoreTimer <= 0f) { currentHull ??= Hull.FindHull(position, guess: currentHull, useWorldCoordinates: false); }
|
||||
return UpdateResult.Normal;
|
||||
}
|
||||
if (!prefab.UseCollision) { return UpdateResult.Normal; }
|
||||
@@ -350,7 +350,7 @@ namespace Barotrauma.Particles
|
||||
{
|
||||
if (currentHull == null)
|
||||
{
|
||||
Hull collidedHull = Hull.FindHull(position);
|
||||
Hull collidedHull = Hull.FindHull(position, useWorldCoordinates: true);
|
||||
if (collidedHull != null)
|
||||
{
|
||||
if (prefab.DeleteOnCollision) { return UpdateResult.Delete; }
|
||||
@@ -359,7 +359,7 @@ namespace Barotrauma.Particles
|
||||
}
|
||||
else
|
||||
{
|
||||
Rectangle hullRect = currentHull.WorldRect;
|
||||
Rectangle hullRect = currentHull.Rect;
|
||||
Vector2 collisionNormal = Vector2.Zero;
|
||||
if (velocity.Y < 0.0f && position.Y - colliderRadius.Y < hullRect.Y - hullRect.Height)
|
||||
{
|
||||
@@ -377,9 +377,9 @@ namespace Barotrauma.Particles
|
||||
{
|
||||
if (gap.Open <= 0.9f || gap.IsHorizontal) { continue; }
|
||||
|
||||
if (gap.WorldRect.X > position.X || gap.WorldRect.Right < position.X) { continue; }
|
||||
float hullCenterY = currentHull.WorldRect.Y - currentHull.WorldRect.Height / 2;
|
||||
int gapDir = Math.Sign(gap.WorldRect.Y - hullCenterY);
|
||||
if (gap.Rect.X > position.X || gap.Rect.Right < position.X) { continue; }
|
||||
float hullCenterY = currentHull.Rect.Y - currentHull.Rect.Height / 2;
|
||||
int gapDir = Math.Sign(gap.Rect.Y - hullCenterY);
|
||||
if (Math.Sign(velocity.Y) != gapDir || Math.Sign(position.Y - hullCenterY) != gapDir) { continue; }
|
||||
|
||||
gapFound = true;
|
||||
@@ -411,9 +411,9 @@ namespace Barotrauma.Particles
|
||||
{
|
||||
if (gap.Open <= 0.9f || !gap.IsHorizontal) { continue; }
|
||||
|
||||
if (gap.WorldRect.Y < position.Y || gap.WorldRect.Y - gap.WorldRect.Height > position.Y) { continue; }
|
||||
int gapDir = Math.Sign(gap.WorldRect.Center.X - currentHull.WorldRect.Center.X);
|
||||
if (Math.Sign(velocity.X) != gapDir || Math.Sign(position.X - currentHull.WorldRect.Center.X) != gapDir) { continue; }
|
||||
if (gap.Rect.Y < position.Y || gap.WorldRect.Y - gap.Rect.Height > position.Y) { continue; }
|
||||
int gapDir = Math.Sign(gap.Rect.Center.X - currentHull.Rect.Center.X);
|
||||
if (Math.Sign(velocity.X) != gapDir || Math.Sign(position.X - currentHull.Rect.Center.X) != gapDir) { continue; }
|
||||
|
||||
gapFound = true;
|
||||
break;
|
||||
@@ -434,7 +434,7 @@ namespace Barotrauma.Particles
|
||||
}
|
||||
else
|
||||
{
|
||||
Hull newHull = Hull.FindHull(position, currentHull);
|
||||
Hull newHull = Hull.FindHull(position, currentHull, useWorldCoordinates: false);
|
||||
if (newHull != currentHull)
|
||||
{
|
||||
currentHull = newHull;
|
||||
@@ -457,32 +457,25 @@ namespace Barotrauma.Particles
|
||||
|
||||
private void ApplyDrag(float dragCoefficient, float deltaTime)
|
||||
{
|
||||
Vector2 relativeVel = velocity;
|
||||
if (currentHull?.Submarine != null)
|
||||
{
|
||||
relativeVel = velocity - ConvertUnits.ToDisplayUnits(currentHull.Submarine.Velocity);
|
||||
}
|
||||
Vector2 newVel = velocity;
|
||||
float speed = velocity.Length();
|
||||
|
||||
float speed = relativeVel.Length();
|
||||
|
||||
relativeVel /= speed;
|
||||
if (speed < 0.01f) { return; }
|
||||
|
||||
newVel /= speed;
|
||||
|
||||
float drag = speed * speed * dragCoefficient * 0.01f * deltaTime;
|
||||
if (drag > speed)
|
||||
{
|
||||
relativeVel = Vector2.Zero;
|
||||
newVel = Vector2.Zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
speed -= drag;
|
||||
relativeVel *= speed;
|
||||
newVel *= speed;
|
||||
}
|
||||
|
||||
velocity = relativeVel;
|
||||
if (currentHull?.Submarine != null)
|
||||
{
|
||||
velocity += ConvertUnits.ToDisplayUnits(currentHull.Submarine.Velocity);
|
||||
}
|
||||
velocity = newVel;
|
||||
}
|
||||
|
||||
|
||||
@@ -490,10 +483,7 @@ namespace Barotrauma.Particles
|
||||
{
|
||||
if (prevHull == null) { return; }
|
||||
|
||||
Rectangle prevHullRect = prevHull.WorldRect;
|
||||
|
||||
Vector2 subVel = prevHull?.Submarine != null ? ConvertUnits.ToDisplayUnits(prevHull.Submarine.Velocity) : Vector2.Zero;
|
||||
velocity -= subVel;
|
||||
Rectangle prevHullRect = prevHull.Rect;
|
||||
|
||||
if (Math.Abs(collisionNormal.X) > Math.Abs(collisionNormal.Y))
|
||||
{
|
||||
@@ -524,14 +514,12 @@ namespace Barotrauma.Particles
|
||||
}
|
||||
|
||||
OnCollision?.Invoke(position, currentHull);
|
||||
|
||||
velocity += subVel;
|
||||
}
|
||||
|
||||
|
||||
private void OnWallCollisionOutside(Hull collisionHull)
|
||||
{
|
||||
Rectangle hullRect = collisionHull.WorldRect;
|
||||
Rectangle hullRect = collisionHull.Rect;
|
||||
|
||||
Vector2 center = new Vector2(hullRect.X + hullRect.Width / 2, hullRect.Y - hullRect.Height / 2);
|
||||
|
||||
@@ -584,7 +572,13 @@ namespace Barotrauma.Particles
|
||||
|
||||
Color currColor = new Color(color.ToVector4() * ColorMultiplier);
|
||||
|
||||
Vector2 drawPos = new Vector2(drawPosition.X, -drawPosition.Y);
|
||||
Vector2 drawPos = drawPosition;
|
||||
if (currentHull?.Submarine is Submarine sub)
|
||||
{
|
||||
drawPos += sub.DrawPosition;
|
||||
}
|
||||
|
||||
drawPos = new Vector2(drawPos.X, -drawPos.Y);
|
||||
if (prefab.Sprites[spriteIndex] is SpriteSheet sheet)
|
||||
{
|
||||
sheet.Draw(
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Barotrauma.Particles
|
||||
{
|
||||
class ParticleEmitterProperties : ISerializableEntity
|
||||
{
|
||||
|
||||
private const float MinValue = int.MinValue,
|
||||
MaxValue = int.MaxValue;
|
||||
|
||||
@@ -98,8 +99,11 @@ namespace Barotrauma.Particles
|
||||
[Editable, Serialize(1f, IsPropertySaveable.Yes)]
|
||||
public float LifeTimeMultiplier { get; set; }
|
||||
|
||||
[Editable, Serialize(false, IsPropertySaveable.Yes)]
|
||||
public bool DrawOnTop { get; set; }
|
||||
[Editable, Serialize(false, IsPropertySaveable.Yes, description: "Should the particle be drawn as a tracer (a line from a weapon to the point it hit)? Only supported on hitscan projectiles and repair tools. Defaults to true on hitscan projectiles.")]
|
||||
public bool UseTracerPoints { get; set; }
|
||||
|
||||
[Editable, Serialize(ParticleDrawOrder.Default, IsPropertySaveable.Yes)]
|
||||
public ParticleDrawOrder DrawOrder { get; set; }
|
||||
|
||||
[Serialize(0f, IsPropertySaveable.Yes)]
|
||||
public float Angle
|
||||
@@ -127,6 +131,12 @@ namespace Barotrauma.Particles
|
||||
public ParticleEmitterProperties(XElement element)
|
||||
{
|
||||
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
|
||||
|
||||
//backwards compatibility
|
||||
if (element.GetAttributeBool("drawontop", false))
|
||||
{
|
||||
DrawOrder = ParticleDrawOrder.Foreground;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +225,9 @@ namespace Barotrauma.Particles
|
||||
position += dir * Rand.Range(Prefab.Properties.DistanceMin, Prefab.Properties.DistanceMax);
|
||||
}
|
||||
|
||||
var particle = GameMain.ParticleManager.CreateParticle(particlePrefab, position, velocity, particleRotation, hullGuess, particlePrefab.DrawOnTop || Prefab.DrawOnTop, lifeTimeMultiplier: Prefab.Properties.LifeTimeMultiplier, tracerPoints: tracerPoints);
|
||||
var particle = GameMain.ParticleManager.CreateParticle(particlePrefab, position, velocity, particleRotation, hullGuess,
|
||||
particlePrefab.DrawOrder != ParticleDrawOrder.Default ? particlePrefab.DrawOrder : Prefab.DrawOrder,
|
||||
lifeTimeMultiplier: Prefab.Properties.LifeTimeMultiplier, tracerPoints: Prefab.Properties.UseTracerPoints ? tracerPoints : null);
|
||||
|
||||
if (particle != null)
|
||||
{
|
||||
@@ -286,7 +298,9 @@ namespace Barotrauma.Particles
|
||||
|
||||
public readonly ContentPackage? ContentPackage;
|
||||
|
||||
public bool DrawOnTop => Properties.DrawOnTop || ParticlePrefab is { DrawOnTop: true };
|
||||
public ParticleDrawOrder DrawOrder => Properties.DrawOrder != ParticleDrawOrder.Default ?
|
||||
Properties.DrawOrder :
|
||||
(ParticlePrefab?.DrawOrder ?? ParticleDrawOrder.Default);
|
||||
|
||||
public ParticleEmitterPrefab(ContentXElement element)
|
||||
{
|
||||
|
||||
@@ -11,6 +11,13 @@ namespace Barotrauma.Particles
|
||||
AlphaBlend, Additive//, Distortion
|
||||
}
|
||||
|
||||
enum ParticleDrawOrder
|
||||
{
|
||||
Default,
|
||||
Foreground,
|
||||
Background
|
||||
}
|
||||
|
||||
class ParticleManager
|
||||
{
|
||||
private const int MaxOutOfViewDist = 500;
|
||||
@@ -91,11 +98,14 @@ namespace Barotrauma.Particles
|
||||
return CreateParticle(prefab, position, velocity, rotation, hullGuess, collisionIgnoreTimer: collisionIgnoreTimer, tracerPoints:tracerPoints);
|
||||
}
|
||||
|
||||
public Particle CreateParticle(ParticlePrefab prefab, Vector2 position, Vector2 velocity, float rotation = 0.0f, Hull hullGuess = null, bool drawOnTop = false, float collisionIgnoreTimer = 0f, float lifeTimeMultiplier = 1f, Tuple<Vector2, Vector2> tracerPoints = null)
|
||||
public Particle CreateParticle(ParticlePrefab prefab, Vector2 position, Vector2 velocity, float rotation = 0.0f, Hull hullGuess = null, ParticleDrawOrder drawOrder = ParticleDrawOrder.Default, float collisionIgnoreTimer = 0f, float lifeTimeMultiplier = 1f, Tuple<Vector2, Vector2> tracerPoints = null)
|
||||
{
|
||||
if (prefab == null || prefab.Sprites.Count == 0) { return null; }
|
||||
if (particleCount >= MaxParticles)
|
||||
{
|
||||
//maximum number of particles reached, and this is not a high-prio particle or something that should always draw
|
||||
// -> the particle won't be created, we can return early
|
||||
if (particleCount >= MaxParticles && prefab.Priority == 0 && !prefab.DrawAlways) { return null; }
|
||||
for (int i = 0; i < particleCount; i++)
|
||||
{
|
||||
if (particles[i].Prefab.Priority < prefab.Priority ||
|
||||
@@ -134,7 +144,7 @@ namespace Barotrauma.Particles
|
||||
if (particles[particleCount] == null) { particles[particleCount] = new Particle(); }
|
||||
Particle particle = particles[particleCount];
|
||||
|
||||
particle.Init(prefab, position, velocity, rotation, hullGuess, drawOnTop, collisionIgnoreTimer, lifeTimeMultiplier, tracerPoints: tracerPoints);
|
||||
particle.Init(prefab, position, velocity, rotation, hullGuess, drawOrder, collisionIgnoreTimer, lifeTimeMultiplier, tracerPoints: tracerPoints);
|
||||
particleCount++;
|
||||
particlesInCreationOrder.AddFirst(particle);
|
||||
|
||||
@@ -213,7 +223,7 @@ namespace Barotrauma.Particles
|
||||
return activeParticles;
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool inWater, bool? inSub, ParticleBlendState blendState)
|
||||
public void Draw(SpriteBatch spriteBatch, bool inWater, bool? inSub, ParticleBlendState blendState, bool? background = false)
|
||||
{
|
||||
ParticlePrefab.DrawTargetType drawTarget = inWater ? ParticlePrefab.DrawTargetType.Water : ParticlePrefab.DrawTargetType.Air;
|
||||
|
||||
@@ -225,12 +235,16 @@ namespace Barotrauma.Particles
|
||||
if (inSub.HasValue)
|
||||
{
|
||||
bool isOutside = particle.CurrentHull == null;
|
||||
if (!particle.DrawOnTop && isOutside == inSub.Value)
|
||||
if (particle.DrawOrder != ParticleDrawOrder.Foreground && isOutside == inSub.Value)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (background.HasValue)
|
||||
{
|
||||
bool isBackgroundParticle = particle.DrawOrder == ParticleDrawOrder.Background;
|
||||
if (background.Value != isBackgroundParticle) { continue; }
|
||||
}
|
||||
particle.Draw(spriteBatch);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Barotrauma.Particles
|
||||
{
|
||||
public static readonly PrefabCollection<ParticlePrefab> Prefabs = new PrefabCollection<ParticlePrefab>();
|
||||
|
||||
[Flags]
|
||||
public enum DrawTargetType { Air = 1, Water = 2, Both = 3 }
|
||||
|
||||
public readonly List<Sprite> Sprites;
|
||||
@@ -151,7 +152,7 @@ namespace Barotrauma.Particles
|
||||
public float Friction { get; private set; }
|
||||
|
||||
[Editable(0.0f, 1.0f)]
|
||||
[Serialize(0.5f, IsPropertySaveable.No, description: "How much of the particle's velocity is conserved when it collides with something, i.e. the \"bounciness\" of the particle. (1.0 = the particle stops completely).")]
|
||||
[Serialize(0.5f, IsPropertySaveable.No, description: "How much of the particle's velocity is conserved when it collides with something, i.e. the \"bounciness\" of the particle. (0.0 = the particle stops completely).")]
|
||||
public float Restitution { get; private set; }
|
||||
|
||||
//size -----------------------------------------
|
||||
@@ -188,8 +189,8 @@ namespace Barotrauma.Particles
|
||||
[Editable, Serialize(DrawTargetType.Air, IsPropertySaveable.No, description: "Should the particle be rendered in air, water or both.")]
|
||||
public DrawTargetType DrawTarget { get; private set; }
|
||||
|
||||
[Editable, Serialize(false, IsPropertySaveable.No, description: "Should the particle be always rendered on top of entities?")]
|
||||
public bool DrawOnTop { get; private set; }
|
||||
[Editable, Serialize(ParticleDrawOrder.Default, IsPropertySaveable.No, description: "Should the particle be always forced to render on top of entities or behind everything?")]
|
||||
public ParticleDrawOrder DrawOrder { get; private set; }
|
||||
|
||||
[Editable, Serialize(false, IsPropertySaveable.No, description: "Draw the particle even when it's calculated to be outside of view (the formula doesn't take scales into account). ")]
|
||||
public bool DrawAlways { get; private set; }
|
||||
@@ -226,6 +227,16 @@ namespace Barotrauma.Particles
|
||||
|
||||
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
|
||||
|
||||
//backwards compatibility
|
||||
if (element.GetAttributeBool("drawontop", false))
|
||||
{
|
||||
DrawOrder = ParticleDrawOrder.Foreground;
|
||||
}
|
||||
if (BlendState == ParticleBlendState.Additive && DrawOrder == ParticleDrawOrder.Background)
|
||||
{
|
||||
DebugConsole.AddWarning($"Error in particle prefab {Identifier}: additive particles cannot be rendered in the background.");
|
||||
}
|
||||
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
|
||||
Reference in New Issue
Block a user