diff --git a/Subsurface/Content/Particles/ParticlePrefabs.xml b/Subsurface/Content/Particles/ParticlePrefabs.xml index da68c848f..f258b789b 100644 --- a/Subsurface/Content/Particles/ParticlePrefabs.xml +++ b/Subsurface/Content/Particles/ParticlePrefabs.xml @@ -9,6 +9,8 @@ lifetime="2" growtime ="0.2" collideswithwalls="true" + friction="0.01" + restitution="0.2" collisionradius="30.0" velocitychange="0.0, -9.8"> @@ -153,7 +155,8 @@ collisionradius="80.0" velocitychange="0.0, 2.5" animduration="4" - restitution="0.98" + friction="0.01" + restitution="0.01" loopanim="false"> @@ -222,6 +225,7 @@ growtime ="0.3" lifetime="3" collisionradius="30.0" + friction="0.01" restitution="0.1" velocitychange="0.0, -0.5"> @@ -250,7 +254,7 @@ lifetime="10.0" drawtarget="both" collideswithwalls="true" - collisionradius="10.0" + collisionradius="10.0" restitution="0.2" waterdrag="0.1" growtime ="0.0" diff --git a/Subsurface/Source/Map/FireSource.cs b/Subsurface/Source/Map/FireSource.cs index f9a016115..2401d8493 100644 --- a/Subsurface/Source/Map/FireSource.cs +++ b/Subsurface/Source/Map/FireSource.cs @@ -195,7 +195,7 @@ namespace Barotrauma if (Rand.Int(5) == 1) { var smokeParticle = GameMain.ParticleManager.CreateParticle("smoke", - particlePos, particleVel * 0.1f, 0.0f, hull); + particlePos, new Vector2(particleVel.X, particleVel.Y * 0.1f), 0.0f, hull); if (smokeParticle != null) { @@ -236,9 +236,10 @@ namespace Barotrauma { if (particleHull == hull || particleHull==null) return; - if (particleHull.FireSources.Find(fs => pos.X > fs.position.X-100.0f && pos.X < fs.position.X+fs.size.X+100.0f)!=null) return; + //hull already has a firesource roughly at the particles position -> don't create a new one + if (particleHull.FireSources.Find(fs => pos.X > fs.position.X - 100.0f && pos.X < fs.position.X + fs.size.X + 100.0f) != null) return; - new FireSource(new Vector2(pos.X, particleHull.WorldRect.Y-particleHull.Rect.Height + 5.0f)); + new FireSource(new Vector2(pos.X, particleHull.WorldRect.Y - particleHull.Rect.Height + 5.0f)); } private void DamageCharacters(float deltaTime) @@ -293,7 +294,7 @@ namespace Barotrauma { Vector2 spawnPos = new Vector2( WorldPosition.X + Rand.Range(0.0f, size.X), - Rand.Range(position.Y - size.Y, WorldPosition.Y) + 10.0f); + WorldPosition.Y + 10.0f); Vector2 speed = new Vector2((spawnPos.X - (WorldPosition.X + size.X / 2.0f)), (float)Math.Sqrt(size.X) * Rand.Range(20.0f, 25.0f)); diff --git a/Subsurface/Source/Map/Gap.cs b/Subsurface/Source/Map/Gap.cs index e2aa312f2..0724fae4e 100644 --- a/Subsurface/Source/Map/Gap.cs +++ b/Subsurface/Source/Map/Gap.cs @@ -266,7 +266,7 @@ namespace Barotrauma lerpedFlowForce = Vector2.Lerp(lerpedFlowForce, flowForce, deltaTime); - if (LerpedFlowForce.LengthSquared() > 10000.0f && flowTargetHull != null && flowTargetHull.Volume < flowTargetHull.FullVolume) + if (LerpedFlowForce.LengthSquared() > 20000.0f && flowTargetHull != null && flowTargetHull.Volume < flowTargetHull.FullVolume) { //UpdateFlowForce(); @@ -274,7 +274,7 @@ namespace Barotrauma if (isHorizontal) { pos.X += Math.Sign(flowForce.X); - pos.Y = MathHelper.Clamp((higherSurface + lowerSurface) / 2.0f, rect.Y - rect.Height, rect.Y); + pos.Y = MathHelper.Clamp((higherSurface + lowerSurface) / 2.0f, rect.Y - rect.Height, rect.Y) + 10; Vector2 velocity = new Vector2( MathHelper.Clamp(flowForce.X, -5000.0f, 5000.0f) * Rand.Range(0.5f, 0.7f), @@ -283,7 +283,7 @@ namespace Barotrauma var particle = GameMain.ParticleManager.CreateParticle( "watersplash", (Submarine == null ? pos : pos + Submarine.Position) - Vector2.UnitY * Rand.Range(0.0f, 10.0f), - velocity); + velocity, 0, flowTargetHull); if (particle != null) { @@ -298,7 +298,7 @@ namespace Barotrauma GameMain.ParticleManager.CreateParticle( "bubbles", Submarine == null ? pos : pos + Submarine.Position, - flowForce / 10.0f); + flowForce / 10.0f, 0, flowTargetHull); } } else diff --git a/Subsurface/Source/Particles/Particle.cs b/Subsurface/Source/Particles/Particle.cs index 1b8ffbd52..4102288cf 100644 --- a/Subsurface/Source/Particles/Particle.cs +++ b/Subsurface/Source/Particles/Particle.cs @@ -182,7 +182,7 @@ namespace Barotrauma.Particles if (prefab.DeleteOnCollision || prefab.CollidesWithWalls) { - Vector2 edgePos = position + prefab.CollisionRadius * Vector2.Normalize(velocity) * size.X; + //Vector2 edgePos = position + prefab.CollisionRadius * Vector2.Normalize(velocity) * size.X; if (currentHull == null) { @@ -194,38 +194,68 @@ namespace Barotrauma.Particles } } - else if (!Submarine.RectContains(currentHull.WorldRect, edgePos)) + else { - if (prefab.DeleteOnCollision) return false; - - bool gapFound = false; - foreach (Gap gap in hullGaps) + Vector2 collisionNormal = Vector2.Zero; + if (velocity.Y < 0.0f && position.Y - prefab.CollisionRadius * size.Y < currentHull.WorldRect.Y - currentHull.WorldRect.Height) { - if (!gap.isHorizontal) + if (prefab.DeleteOnCollision) return false; + collisionNormal = new Vector2(0.0f, 1.0f); + } + else if (velocity.Y > 0.0f && position.Y + prefab.CollisionRadius * size.Y > currentHull.WorldRect.Y) + { + if (prefab.DeleteOnCollision) return false; + collisionNormal = new Vector2(0.0f, -1.0f); + } + else if (velocity.X < 0.0f && position.X - prefab.CollisionRadius * size.X < currentHull.WorldRect.X) + { + if (prefab.DeleteOnCollision) return false; + collisionNormal = new Vector2(1.0f, 0.0f); + } + else if (velocity.X > 0.0f && position.X + prefab.CollisionRadius * size.X > currentHull.WorldRect.Right) + { + if (prefab.DeleteOnCollision) return false; + collisionNormal = new Vector2(-1.0f, 0.0f); + } + + if (collisionNormal != Vector2.Zero) + { + bool gapFound = false; + foreach (Gap gap in hullGaps) { - if (gap.WorldRect.X > position.X || gap.WorldRect.Right < position.X) continue; - if (Math.Sign(velocity.Y) != Math.Sign(gap.WorldRect.Y - (currentHull.WorldRect.Y - currentHull.WorldRect.Height))) continue; + if (gap.isHorizontal != (collisionNormal.X != 0.0f)) continue; + + if (gap.isHorizontal) + { + 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; + } + else + { + 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 (Math.Sign(velocity.Y) != gapDir || Math.Sign(position.Y - hullCenterY) != gapDir) continue; + } + + gapFound = true; + break; + } + + if (!gapFound) + { + OnWallCollisionInside(currentHull, collisionNormal); } else { - if (gap.WorldRect.Y < position.Y || gap.WorldRect.Y - gap.WorldRect.Height > position.Y) continue; - if (Math.Sign(velocity.X) != Math.Sign(gap.WorldRect.Center.X - currentHull.WorldRect.Center.X)) continue; + Hull newHull = Hull.FindHull(position); + if (newHull != currentHull) + { + hullGaps = currentHull == null ? new List() : currentHull.ConnectedGaps; + OnChangeHull?.Invoke(position, currentHull); + } } - - gapFound = true; - break; - } - - if (!gapFound) - { - OnWallCollisionInside(currentHull, edgePos); - } - else - { - currentHull = Hull.FindHull(position); - hullGaps = currentHull == null ? new List() : currentHull.ConnectedGaps; - - if (OnChangeHull != null) OnChangeHull(edgePos, currentHull); } } } @@ -242,41 +272,43 @@ namespace Barotrauma.Particles if (Math.Abs(velocity.X) < 0.0001f && Math.Abs(velocity.Y) < 0.0001f) return; float speed = velocity.Length(); - velocity -= (velocity / speed) * Math.Min(speed * speed * prefab.WaterDrag * deltaTime, 1.0f); + velocity -= (velocity / speed) * Math.Min(speed * speed * dragCoefficient * deltaTime, 1.0f); } - private void OnWallCollisionInside(Hull prevHull, Vector2 edgePos) + private void OnWallCollisionInside(Hull prevHull, Vector2 collisionNormal) { Rectangle prevHullRect = prevHull.WorldRect; Vector2 subVel = ConvertUnits.ToDisplayUnits(prevHull.Submarine.Velocity); - velocity -= subVel; - if (edgePos.Y < prevHullRect.Y - prevHullRect.Height) + if (Math.Abs(collisionNormal.X) > Math.Abs(collisionNormal.Y)) { - position.Y = prevHullRect.Y - prevHullRect.Height + prefab.CollisionRadius; - velocity.Y = -velocity.Y; + if (collisionNormal.X > 0.0f) + { + position.X = Math.Max(position.X, prevHullRect.X + prefab.CollisionRadius * size.X); + } + else + { + position.X = Math.Min(position.X, prevHullRect.Right - prefab.CollisionRadius * size.X); + } + velocity.X = Math.Sign(collisionNormal.X) * Math.Abs(velocity.X) * prefab.Restitution; + velocity.Y *= (1.0f - prefab.Friction); } - else if (edgePos.Y > prevHullRect.Y) + else { - position.Y = prevHullRect.Y - prefab.CollisionRadius; - velocity.X = Math.Abs(velocity.Y) * Math.Sign(velocity.X); - velocity.Y = -velocity.Y * 0.1f; - } + if (collisionNormal.Y > 0.0f) + { + position.Y = Math.Max(position.Y, prevHullRect.Y - prevHullRect.Height + prefab.CollisionRadius * size.Y); + } + else + { + position.Y = Math.Min(position.Y, prevHullRect.Y - prefab.CollisionRadius * size.Y); - if (edgePos.X < prevHullRect.X) - { - position.X = prevHullRect.X + prefab.CollisionRadius; - velocity.X = -velocity.X; + } + velocity.X *= (1.0f - prefab.Friction); + velocity.Y = Math.Sign(collisionNormal.Y) * Math.Abs(velocity.Y) * prefab.Restitution; } - else if (edgePos.X > prevHullRect.X + prevHullRect.Width) - { - position.X = prevHullRect.X + prevHullRect.Width - prefab.CollisionRadius; - velocity.X = -velocity.X; - } - - velocity *= prefab.Restitution; velocity += subVel; } @@ -347,8 +379,6 @@ namespace Barotrauma.Particles prefab.Sprites[spriteIndex].Origin, drawRotation, drawSize, SpriteEffects.None, prefab.Sprites[spriteIndex].Depth); } - - } } } diff --git a/Subsurface/Source/Particles/ParticlePrefab.cs b/Subsurface/Source/Particles/ParticlePrefab.cs index 47c9d29c5..0308c1fa1 100644 --- a/Subsurface/Source/Particles/ParticlePrefab.cs +++ b/Subsurface/Source/Particles/ParticlePrefab.cs @@ -38,6 +38,7 @@ namespace Barotrauma.Particles public readonly bool DeleteOnCollision; public readonly bool CollidesWithWalls; + public readonly float Friction; public readonly float Restitution; public readonly Vector2 VelocityChange; @@ -107,6 +108,7 @@ namespace Barotrauma.Particles Drag = ToolBox.GetAttributeFloat(element, "drag", 0.0f); WaterDrag = ToolBox.GetAttributeFloat(element, "waterdrag", 0.0f); + Friction = ToolBox.GetAttributeFloat(element, "friction", 0.5f); Restitution = ToolBox.GetAttributeFloat(element, "restitution", 0.5f); switch (ToolBox.GetAttributeString(element, "blendstate", "alphablend"))