diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj index 03b92baa8..98c44895a 100644 --- a/Subsurface/Barotrauma.csproj +++ b/Subsurface/Barotrauma.csproj @@ -817,6 +817,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Subsurface/Content/Particles/ParticlePrefabs.xml b/Subsurface/Content/Particles/ParticlePrefabs.xml index d2be342c8..7182505bc 100644 --- a/Subsurface/Content/Particles/ParticlePrefabs.xml +++ b/Subsurface/Content/Particles/ParticlePrefabs.xml @@ -234,4 +234,68 @@ velocitychange="0.0, 1.0"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Subsurface/Content/Particles/shrapnel.png b/Subsurface/Content/Particles/shrapnel.png new file mode 100644 index 000000000..ad42c6eeb Binary files /dev/null and b/Subsurface/Content/Particles/shrapnel.png differ diff --git a/Subsurface/Source/Map/Gap.cs b/Subsurface/Source/Map/Gap.cs index b976b4ebd..1f25e71b5 100644 --- a/Subsurface/Source/Map/Gap.cs +++ b/Subsurface/Source/Map/Gap.cs @@ -163,6 +163,8 @@ namespace Barotrauma hulls[1] = temp; } + flowTargetHull = hulls[0]; + for (int i = 0 ; i <2; i++) { if (hulls[i]==null) continue; diff --git a/Subsurface/Source/Map/Structure.cs b/Subsurface/Source/Map/Structure.cs index a2fb24ee6..5eddba372 100644 --- a/Subsurface/Source/Map/Structure.cs +++ b/Subsurface/Source/Map/Structure.cs @@ -537,8 +537,22 @@ namespace Barotrauma if (sectionIndex < 0 || sectionIndex > sections.Length - 1) return; - if (GameMain.Client == null) SetDamage(sectionIndex, sections[sectionIndex].damage + damage); + var section = sections[sectionIndex]; + int particleAmount = (int)(Math.Min(Health - section.damage, damage) * Rand.Range(0.1f, 1.0f)); + for (int i = 0; i < particleAmount; i++) + { + Vector2 particlePos = new Vector2( + Rand.Range(section.rect.X, section.rect.Right), + Rand.Range(section.rect.Y - section.rect.Height, section.rect.Y)); + + if (Submarine != null) particlePos += Submarine.DrawPosition; + + var particle = GameMain.ParticleManager.CreateParticle("shrapnel", particlePos, Rand.Vector(Rand.Range(1.0f, 50.0f))); + if (particle == null) break; + } + + if (GameMain.Client == null) SetDamage(sectionIndex, section.damage + damage); } public int FindSectionIndex(Vector2 displayPos) diff --git a/Subsurface/Source/Map/SubmarineBody.cs b/Subsurface/Source/Map/SubmarineBody.cs index 2d633ee98..4742058f2 100644 --- a/Subsurface/Source/Map/SubmarineBody.cs +++ b/Subsurface/Source/Map/SubmarineBody.cs @@ -444,6 +444,18 @@ namespace Barotrauma float wallImpact = Vector2.Dot(Velocity, -collisionNormal); ApplyImpact(wallImpact, -collisionNormal, contact); + + Vector2 n; + FixedArray2 particlePos; + contact.GetWorldManifold(out n, out particlePos); + + int particleAmount = (int)(wallImpact*10.0f); + for (int i = 0; i < particleAmount; i++) + { + var particle = GameMain.ParticleManager.CreateParticle("iceshards", + ConvertUnits.ToDisplayUnits(particlePos[0]) + Rand.Vector(Rand.Range(1.0f, 50.0f)), + Rand.Vector(Rand.Range(50.0f,500.0f)) + Velocity); + } return true; } diff --git a/Subsurface/Source/Particles/Particle.cs b/Subsurface/Source/Particles/Particle.cs index df76d43c8..4d9f87429 100644 --- a/Subsurface/Source/Particles/Particle.cs +++ b/Subsurface/Source/Particles/Particle.cs @@ -37,6 +37,7 @@ namespace Barotrauma.Particles private Vector2 velocityChange; private Vector2 drawPosition; + private float drawRotation; //private float checkCollisionTimer; @@ -65,6 +66,12 @@ namespace Barotrauma.Particles get { return velocityChange; } set { velocityChange = value; } } + + public Vector2 Velocity + { + get { return velocity; } + set { velocity = value; } + } public void Init(ParticlePrefab prefab, Vector2 position, Vector2 speed, float rotation, Hull hullGuess = null) { @@ -74,26 +81,19 @@ namespace Barotrauma.Particles spriteIndex = Rand.Int(prefab.Sprites.Count); currentHull = Hull.FindHull(position, hullGuess); - //if (currentHull != null && currentHull.Submarine != null) - //{ - // Vector2 subVel = ConvertUnits.ToDisplayUnits(currentHull.Submarine.Velocity); - // //subVel.Y = -subVel.Y; - // speed += subVel; - //} - //else - //{ - // int a = 1; - //} - //if (currentHull == null) position = Submarine.Loaded == null ? position : position + Submarine.Loaded.Position; this.position = position; prevPosition = position; - + drawPosition = position; - velocity = MathUtils.IsValid(speed) ? speed : Vector2.Zero; + if (currentHull != null && currentHull.Submarine != null) + { + velocity += ConvertUnits.ToDisplayUnits(currentHull.Submarine.Velocity); + } + this.rotation = rotation + Rand.Range(prefab.StartRotationMin, prefab.StartRotationMax); prevRotation = rotation; @@ -142,12 +142,12 @@ namespace Barotrauma.Particles public bool Update(float deltaTime) { - - Vector2 subVel = currentHull ==null || currentHull.Submarine==null ? Vector2.Zero : ConvertUnits.ToDisplayUnits(currentHull.Submarine.Velocity); + prevPosition = position; + prevRotation = rotation; //over 3 times faster than position += velocity * deltatime - position.X += (velocity.X+subVel.X) * deltaTime; - position.Y += (velocity.Y+subVel.Y) * deltaTime; + position.X += velocity.X * deltaTime; + position.Y += velocity.Y * deltaTime; if (prefab.RotateToDirection) { @@ -161,6 +161,16 @@ namespace Barotrauma.Particles rotation += angularVelocity * deltaTime; } + if (prefab.WaterDrag > 0.0f && + (currentHull == null || (currentHull.Submarine != null && position.Y - currentHull.Submarine.DrawPosition.Y < currentHull.Surface))) + { + ApplyDrag(prefab.WaterDrag, deltaTime); + } + else if (prefab.Drag > 0.0f) + { + ApplyDrag(prefab.Drag, deltaTime); + } + velocity.X += velocityChange.X * deltaTime; velocity.Y += velocityChange.Y * deltaTime; @@ -174,11 +184,20 @@ namespace Barotrauma.Particles color.G / 255.0f + prefab.ColorChange.Y * deltaTime, color.B / 255.0f + prefab.ColorChange.Z * deltaTime); - if ((prefab.DeleteOnCollision || prefab.CollidesWithWalls) && currentHull!=null) + if (prefab.DeleteOnCollision || prefab.CollidesWithWalls) { Vector2 edgePos = position + prefab.CollisionRadius * Vector2.Normalize(velocity) * size.X; - - if (!Submarine.RectContains(currentHull.WorldRect, edgePos)) + + if (currentHull == null) + { + var collidedHull = Hull.FindHullOld(edgePos); + if (collidedHull != null) + { + if (prefab.DeleteOnCollision) return false; + OnWallCollisionOutside(collidedHull); + } + } + else if (!Submarine.RectContains(currentHull.WorldRect, edgePos)) { if (prefab.DeleteOnCollision) return false; @@ -196,15 +215,13 @@ namespace Barotrauma.Particles if (Math.Sign(velocity.X) != Math.Sign(gap.WorldRect.Center.X - currentHull.WorldRect.Center.X)) continue; } - //Rectangle enlargedRect = new Rectangle(gap.Rect.X - 10, gap.Rect.Y + 10, gap.Rect.Width + 20, gap.Rect.Height + 20); - //if (!Submarine.RectContains(enlargedRect, position)) continue; gapFound = true; } if (!gapFound) { - OnWallCollision(currentHull, edgePos); + OnWallCollisionInside(currentHull, edgePos); } else { @@ -212,21 +229,9 @@ namespace Barotrauma.Particles hullGaps = currentHull == null ? new List() : currentHull.ConnectedGaps; if (OnChangeHull != null) OnChangeHull(edgePos, currentHull); - - } - - //Hull prevHull = Hull.FindHull(prevPosition, hullLimits, currentHull); - - //if (prevHull == null) return false; - + } } - - //if (position.Y < currentHull.Rect.Y-currentHull.Rect.Height) - //{ - // position.Y = currentHull.Rect.Y - currentHull.Rect.Height; - // velocity.Y *= -0.2f; - //} - //if (!Submarine.RectContains(currentHull.Rect, position)) return false; + } lifeTime -= deltaTime; @@ -236,10 +241,22 @@ namespace Barotrauma.Particles return true; } - private void OnWallCollision(Hull prevHull, Vector2 position) + private void ApplyDrag(float dragCoefficient, float deltaTime) + { + if (velocity == Vector2.Zero) return; + + float speed = velocity.Length(); + velocity -= (velocity / speed) * Math.Min(speed * speed * prefab.WaterDrag * deltaTime, 1.0f); + } + + private void OnWallCollisionInside(Hull prevHull, Vector2 position) { Rectangle prevHullRect = prevHull.WorldRect; + Vector2 subVel = ConvertUnits.ToDisplayUnits(prevHull.Submarine.Velocity); + + velocity -= subVel; + if (position.Y < prevHullRect.Y - prevHullRect.Height) { position.Y = prevHullRect.Y - prevHullRect.Height + 1.0f; @@ -264,30 +281,64 @@ namespace Barotrauma.Particles } velocity *= prefab.Restitution; + + velocity += subVel; } - - public void Draw(SpriteBatch spriteBatch) + + + private void OnWallCollisionOutside(Hull collisionHull) { - drawPosition = Physics.Interpolate(prevPosition, position); - float drawRotation = Physics.Interpolate(prevRotation, rotation); - - //drawPosition = ConvertUnits.ToDisplayUnits(drawPosition); - - Vector2 drawSize = size; - - if (prefab.GrowTime>0.0f && totalLifeTime-lifeTime < prefab.GrowTime) + Rectangle hullRect = collisionHull.WorldRect; + + if (position.Y < hullRect.Y - hullRect.Height) { - drawSize *= ((totalLifeTime - lifeTime) / prefab.GrowTime); + position.Y = hullRect.Y - hullRect.Height - 1.0f; + velocity.Y = -velocity.Y; + } + else if (position.Y > hullRect.Y) + { + position.Y = hullRect.Y + 1.0f; + velocity.X = Math.Abs(velocity.Y) * Math.Sign(velocity.X); + velocity.Y = -velocity.Y; } - prefab.Sprites[spriteIndex].Draw(spriteBatch, - new Vector2(drawPosition.X, -drawPosition.Y), - color * alpha, - prefab.Sprites[spriteIndex].Origin, drawRotation, - drawSize, SpriteEffects.None, prefab.Sprites[spriteIndex].Depth); + if (position.X < hullRect.X) + { + position.X = hullRect.X - 1.0f; + velocity.X = -velocity.X; + } + else if (position.X > hullRect.X + hullRect.Width) + { + position.X = hullRect.X + hullRect.Width + 1.0f; + velocity.X = -velocity.X; + } + + velocity *= prefab.Restitution; + } + + public void UpdateDrawPos() + { + drawPosition = Physics.Interpolate(prevPosition, position); + drawRotation = Physics.Interpolate(prevRotation, rotation); prevPosition = position; prevRotation = rotation; } + + public void Draw(SpriteBatch spriteBatch) + { + Vector2 drawSize = size; + + if (prefab.GrowTime > 0.0f && totalLifeTime - lifeTime < prefab.GrowTime) + { + drawSize *= ((totalLifeTime - lifeTime) / prefab.GrowTime); + } + + prefab.Sprites[spriteIndex].Draw(spriteBatch, + new Vector2(drawPosition.X, -drawPosition.Y), + color * alpha, + prefab.Sprites[spriteIndex].Origin, drawRotation, + drawSize, SpriteEffects.None, prefab.Sprites[spriteIndex].Depth); + } } } diff --git a/Subsurface/Source/Particles/ParticleManager.cs b/Subsurface/Source/Particles/ParticleManager.cs index 9759587c1..cf522d8d1 100644 --- a/Subsurface/Source/Particles/ParticleManager.cs +++ b/Subsurface/Source/Particles/ParticleManager.cs @@ -113,6 +113,14 @@ namespace Barotrauma.Particles } } + public void UpdateTransforms() + { + for (int i = 0; i < particleCount; i++) + { + particles[i].UpdateDrawPos(); + } + } + public void Draw(SpriteBatch spriteBatch, bool inWater, ParticleBlendState blendState) { ParticlePrefab.DrawTargetType drawTarget = inWater ? ParticlePrefab.DrawTargetType.Water : ParticlePrefab.DrawTargetType.Air; diff --git a/Subsurface/Source/Particles/ParticlePrefab.cs b/Subsurface/Source/Particles/ParticlePrefab.cs index 54efa74fa..c0af6a518 100644 --- a/Subsurface/Source/Particles/ParticlePrefab.cs +++ b/Subsurface/Source/Particles/ParticlePrefab.cs @@ -20,6 +20,8 @@ namespace Barotrauma.Particles public readonly Vector2 StartSizeMin, StartSizeMax; public readonly Vector2 SizeChangeMin, SizeChangeMax; + public readonly float Drag, WaterDrag; + public readonly Color StartColor; public readonly float StartAlpha; @@ -89,6 +91,9 @@ namespace Barotrauma.Particles SizeChangeMax = SizeChangeMin; } + Drag = ToolBox.GetAttributeFloat(element, "drag", 0.0f); + WaterDrag = ToolBox.GetAttributeFloat(element, "waterdrag", 0.0f); + Restitution = ToolBox.GetAttributeFloat(element, "restitution", 0.5f); switch (ToolBox.GetAttributeString(element, "blendstate", "alphablend")) diff --git a/Subsurface/Source/Screens/GameScreen.cs b/Subsurface/Source/Screens/GameScreen.cs index bb95df021..6fae5ad43 100644 --- a/Subsurface/Source/Screens/GameScreen.cs +++ b/Subsurface/Source/Screens/GameScreen.cs @@ -109,23 +109,24 @@ namespace Barotrauma } #endif - if (GameMain.GameSession!=null) GameMain.GameSession.Update((float)deltaTime); - //EventManager.Update(gameTime); - - if (Level.Loaded != null) Level.Loaded.Update((float)deltaTime); - - Character.UpdateAll(cam, (float)deltaTime); - - BackgroundCreatureManager.Update(cam, (float)deltaTime); - - GameMain.ParticleManager.Update((float)deltaTime); - - StatusEffect.UpdateAll((float)deltaTime); - Physics.accumulator = Math.Min(Physics.accumulator, Physics.step * 6); //Physics.accumulator = Physics.step; while (Physics.accumulator >= Physics.step) { + + if (GameMain.GameSession != null) GameMain.GameSession.Update((float)Physics.step); + //EventManager.Update(gameTime); + + if (Level.Loaded != null) Level.Loaded.Update((float)Physics.step); + + Character.UpdateAll(cam, (float)Physics.step); + + BackgroundCreatureManager.Update(cam, (float)Physics.step); + + GameMain.ParticleManager.Update((float)Physics.step); + + StatusEffect.UpdateAll((float)Physics.step); + if (Character.Controlled != null && Lights.LightManager.ViewTarget != null) { cam.TargetPos = Lights.LightManager.ViewTarget.WorldPosition; @@ -210,6 +211,8 @@ namespace Barotrauma sub.UpdateTransform(); } + GameMain.ParticleManager.UpdateTransforms(); + GameMain.LightManager.ObstructVision = Character.Controlled != null && Character.Controlled.ObstructVision; GameMain.LightManager.UpdateLightMap(graphics, spriteBatch, cam);