diff --git a/.gitignore b/.gitignore index 6c59afd3c..2dcf45db7 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ bld/ #performance reports & sessions *.vsp -*.psess \ No newline at end of file +*.psess +/packages/MonoGame.Framework.WindowsDX.3.4.0.459/lib/net40 diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj index 562d70328..cc4923d8d 100644 --- a/Subsurface/Barotrauma.csproj +++ b/Subsurface/Barotrauma.csproj @@ -278,8 +278,9 @@ - - $(MSBuildProgramFiles32)\MonoGame\v3.0\Assemblies\Windows\MonoGame.Framework.dll + + False + ..\..\MonoGame\MonoGame.Framework\bin\Windows\AnyCPU\Debug\MonoGame.Framework.dll .\NVorbis.dll diff --git a/Subsurface/Content/Items/Weapons/weapons.xml b/Subsurface/Content/Items/Weapons/weapons.xml index e0dbb95e0..d11fb4a13 100644 --- a/Subsurface/Content/Items/Weapons/weapons.xml +++ b/Subsurface/Content/Items/Weapons/weapons.xml @@ -36,7 +36,7 @@ - + diff --git a/Subsurface/Source/Items/Components/Door.cs b/Subsurface/Source/Items/Components/Door.cs index c9f0e7f4b..59367e2c1 100644 --- a/Subsurface/Source/Items/Components/Door.cs +++ b/Subsurface/Source/Items/Components/Door.cs @@ -213,7 +213,7 @@ namespace Barotrauma.Items.Components if (convexHull == null) return; - if (rect.Height == 0) + if (rect.Height == 0 || rect.Width == 0) { convexHull.Enabled = false; } diff --git a/Subsurface/Source/Items/Item.cs b/Subsurface/Source/Items/Item.cs index 8d38540e3..846f53cc2 100644 --- a/Subsurface/Source/Items/Item.cs +++ b/Subsurface/Source/Items/Item.cs @@ -642,7 +642,7 @@ namespace Barotrauma body.ResetDynamics(); } body.ApplyForce(buoyancy - body.LinearVelocity * volume); - + CurrentHull.HandleItems(deltaTime, this); //apply simple angular drag body.ApplyTorque(body.AngularVelocity * volume * -0.05f); } diff --git a/Subsurface/Source/Map/Hull.cs b/Subsurface/Source/Map/Hull.cs index c65d22791..12e7fc672 100644 --- a/Subsurface/Source/Map/Hull.cs +++ b/Subsurface/Source/Map/Hull.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using System.Linq; using System.Xml.Linq; using FarseerPhysics; +using FarseerPhysics.Dynamics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Lidgren.Network; @@ -392,7 +393,7 @@ namespace Barotrauma float maxDelta = Math.Max(Math.Abs(rightDelta[i]), Math.Abs(leftDelta[i])); if (maxDelta > Rand.Range(1.0f,10.0f)) { - Vector2 particlePos = new Vector2(rect.X + WaveWidth * i, surface + waveY[i]); + var particlePos = new Vector2(rect.X + WaveWidth * i, surface + waveY[i]); if (Submarine != null) particlePos += Submarine.Position; GameMain.ParticleManager.CreateParticle("mist", @@ -452,6 +453,31 @@ namespace Barotrauma } } + public void HandleItems(float deltaTime, Item body) + { + if (!body.InWater || body.body == null || body.Container != null) + return; + float floor = rect.Y - rect.Height; + float waterLevel = (floor + Volume/rect.Width); + + + var actionPoint = new Vector2(body.Rect.X, body.Rect.Y); + var forceFactor = 1f - ((actionPoint.Y - waterLevel)/Math.Max(body.body.Density - 10, 1)); + + if (!(forceFactor > 0f)) return; + + var uplift = -GameMain.World.Gravity*(forceFactor - body.body.LinearVelocity.Y*5); + body.body.FarseerBody.ApplyForce(uplift*deltaTime); + + var gap = + ConnectedGaps.Where(i => i.Open > 0).OrderBy(i => Vector2.Distance(body.Position, i.Position)).FirstOrDefault(); + if (gap == null || gap.LerpedFlowForce.Length() < 0) + return; + var pos = gap.Position - body.Position; + pos.Normalize(); + body.body.ApplyForce((pos*gap.LerpedFlowForce)*deltaTime); + } + public void Extinquish(float deltaTime, float amount, Vector2 position) { for (int i = fireSources.Count - 1; i >= 0; i-- ) diff --git a/Subsurface/Source/Map/Lights/ConvexHull.cs b/Subsurface/Source/Map/Lights/ConvexHull.cs index fe8b0692e..b20520ad0 100644 --- a/Subsurface/Source/Map/Lights/ConvexHull.cs +++ b/Subsurface/Source/Map/Lights/ConvexHull.cs @@ -175,13 +175,14 @@ namespace Barotrauma.Lights public bool Intersects(Rectangle rect) { + if (!Enabled) + return false; Rectangle transformedBounds = boundingBox; if (parentEntity != null && parentEntity.Submarine != null) { transformedBounds.X += (int)parentEntity.Submarine.Position.X; transformedBounds.Y += (int)parentEntity.Submarine.Position.Y; } - return transformedBounds.Intersects(rect); } diff --git a/Subsurface/Source/Map/Structure.cs b/Subsurface/Source/Map/Structure.cs index 541cea00c..3064762ac 100644 --- a/Subsurface/Source/Map/Structure.cs +++ b/Subsurface/Source/Map/Structure.cs @@ -26,7 +26,8 @@ namespace Barotrauma public float lastSentDamage; public bool isHighLighted; - + public ConvexHull hull; + public WallSection(Rectangle rect) { this.rect = rect; @@ -45,7 +46,7 @@ namespace Barotrauma public static int wallSectionSize = 100; public static List WallList = new List(); - ConvexHull convexHull; + List _convexHulls; StructurePrefab prefab; @@ -125,9 +126,9 @@ namespace Barotrauma } } - if (convexHull!=null) + if (_convexHulls!=null) { - convexHull.Move(amount); + _convexHulls.ForEach(x => x.Move(amount)); } //if (gaps != null) //{ @@ -258,19 +259,73 @@ namespace Barotrauma if (prefab.CastShadow) { - - Vector2[] corners = new Vector2[4]; - corners[0] = new Vector2(rect.X, rect.Y - rect.Height); - corners[1] = new Vector2(rect.X, rect.Y); - corners[2] = new Vector2(rect.Right, rect.Y); - corners[3] = new Vector2(rect.Right, rect.Y - rect.Height); - - convexHull = new ConvexHull(corners, Color.Black, this); + GeneateConvexHull(); } InsertToList(); } + private void GeneateConvexHull() + { + // If not null and not empty , remove the hulls from the system + if(_convexHulls != null && _convexHulls.Any()) + _convexHulls.ForEach(x => x.Remove()); + + // list all of hulls for this structure + _convexHulls = new List(); + + // merged sections + // TODO: merge damaged sections + var mergedSections = new List(); + foreach (var section in sections) + { + + // if there is a gap and we have sections to merge, do it. + if (section.gap != null) + GenerateMergedHull(mergedSections); + else + mergedSections.Add(section); + } + + // take care of any leftover pieces + if (mergedSections.Count > 0) + { + GenerateMergedHull(mergedSections); + } + } + + private void GenerateMergedHull(List mergedSections) + { + if (!mergedSections.Any()) return; + Rectangle mergedRect; + + + if (isHorizontal) + mergedRect = new Rectangle(mergedSections.Min(x => x.rect.Left), mergedSections.Max(x => x.rect.Top), + mergedSections.Sum(x => x.rect.Width), mergedSections.First().rect.Height); + else + { + mergedRect = new Rectangle(mergedSections.Min(x => x.rect.Left), mergedSections.Max(x => x.rect.Top), + mergedSections.First().rect.Width, mergedSections.Sum(x => x.rect.Height)); + } + + + var h = new ConvexHull(CalculateExtremes(mergedRect), Color.Black, this); + mergedSections.ForEach(x => x.hull = h); + _convexHulls.Add(h); + mergedSections.Clear(); + } + + private static Vector2[] CalculateExtremes(Rectangle sectionRect) + { + Vector2[] corners = new Vector2[4]; + corners[0] = new Vector2(sectionRect.X, sectionRect.Y - sectionRect.Height); + corners[1] = new Vector2(sectionRect.X, sectionRect.Y); + corners[2] = new Vector2(sectionRect.Right, sectionRect.Y); + corners[3] = new Vector2(sectionRect.Right, sectionRect.Y - sectionRect.Height); + return corners; + } + public override bool IsMouseOn(Vector2 position) { if (StairDirection == Direction.None) @@ -304,7 +359,7 @@ namespace Barotrauma GameMain.World.RemoveBody(b); } - if (convexHull != null) convexHull.Remove(); + if (_convexHulls != null) _convexHulls.ForEach(x => x.Remove()); } @@ -317,7 +372,7 @@ namespace Barotrauma Vector2 drawOffset = Submarine == null ? Vector2.Zero : Submarine.DrawPosition; prefab.sprite.DrawTiled(spriteBatch, new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)), new Vector2(rect.Width, rect.Height), Vector2.Zero, color); - + foreach (WallSection s in sections) { @@ -329,14 +384,23 @@ namespace Barotrauma } s.isHighLighted = false; - + if (s.damage < 0.01f) continue; GUI.DrawRectangle(spriteBatch, new Vector2(s.rect.X + drawOffset.X, -(s.rect.Y + drawOffset.Y)), new Vector2(s.rect.Width, s.rect.Height), Color.Black * (s.damage / prefab.MaxHealth), true); } - + /* + if(_convexHulls == null) return; + var rand = new Random(32434324); + foreach (var hull in _convexHulls) + { + if (sections.Count(x => x.hull == hull) <= 1) + continue; + var col = new Color((int) (255 * rand.NextDouble()), (int)(255 * rand.NextDouble()), (int)(255 * rand.NextDouble()), 255); + GUI.DrawRectangle(spriteBatch,new Vector2 (hull.BoundingBox.X + drawOffset.X, -(hull.BoundingBox.Y + drawOffset.Y)), new Vector2(hull.BoundingBox.Width, hull.BoundingBox.Height),col,true ); + }*/ } private bool OnWallCollision(Fixture f1, Fixture f2, Contact contact) @@ -477,6 +541,7 @@ namespace Barotrauma private void SetDamage(int sectionIndex, float damage) { + if (Submarine.Loaded != null && Submarine.Loaded.GodMode) return; if (!prefab.HasBody) return; @@ -495,6 +560,8 @@ namespace Barotrauma //remove existing gap if damage is below 50% sections[sectionIndex].gap.Remove(); sections[sectionIndex].gap = null; + if(CastShadow) + GeneateConvexHull(); } } else @@ -507,6 +574,8 @@ namespace Barotrauma gapRect.Width += 20; gapRect.Height += 20; sections[sectionIndex].gap = new Gap(gapRect, !isHorizontal, Submarine); + if(CastShadow) + GeneateConvexHull(); } } @@ -518,12 +587,9 @@ namespace Barotrauma bool hasHole = SectionHasHole(sectionIndex); - if (hadHole != hasHole) - { - if (hasHole) Explosion.ApplyExplosionForces(sections[sectionIndex].gap.WorldPosition, 500.0f, 5.0f, 0.0f, 0.0f); - UpdateSections(); - } - + if (hadHole == hasHole) return; + if (hasHole) Explosion.ApplyExplosionForces(sections[sectionIndex].gap.WorldPosition, 500.0f, 5.0f, 0.0f, 0.0f); + UpdateSections(); } private void UpdateSections() @@ -533,53 +599,41 @@ namespace Barotrauma GameMain.World.RemoveBody(b); } bodies.Clear(); - - int x = sections[0].rect.X; - int y = sections[0].rect.Y; - int width = sections[0].rect.Width; - int height = sections[0].rect.Height; - - bool hasHoles = false; - - for (int i = 1; i < sections.Length; i++) + var mergedSections = new List(); + foreach (var section in sections) { - bool hasHole = SectionHasHole(i); - if (hasHole) hasHoles = true; - if (hasHole || i == sections.Length - 1) - { - if (width > 0 && height > 0) - { - CreateRectBody(new Rectangle(x, y, width, height)); - } - if (isHorizontal) - { - x = sections[i].rect.X+ sections[i].rect.Width; - width = 0; - } - else - { - y = sections[i].rect.Y - sections[i].rect.Height; - height = 0; - } - } + if(section.gap == null) + mergedSections.Add(section); + if (section.gap == null || mergedSections.Count <= 0) continue; + Rectangle mergedRect; + if (isHorizontal) + mergedRect = new Rectangle(mergedSections.Min(x => x.rect.Left), mergedSections.Max(x => x.rect.Top), + mergedSections.Sum(x => x.rect.Width), mergedSections.First().rect.Height); else { - if (isHorizontal) - { - width += sections[i].rect.Width; - } - else - { - height += sections[i].rect.Height; - } + mergedRect = new Rectangle(mergedSections.Min(x => x.rect.Left), mergedSections.Max(x => x.rect.Top), + mergedSections.First().rect.Width, mergedSections.Sum(x => x.rect.Height)); } + CreateRectBody(mergedRect); + } + if (mergedSections.Count > 0) + { + Rectangle mergedRect; + if (isHorizontal) + mergedRect = new Rectangle(mergedSections.Min(x => x.rect.Left), mergedSections.Max(x => x.rect.Top), + mergedSections.Sum(x => x.rect.Width), mergedSections.First().rect.Height); + else + { + mergedRect = new Rectangle(mergedSections.Min(x => x.rect.Left), mergedSections.Max(x => x.rect.Top), + mergedSections.First().rect.Width, mergedSections.Sum(x => x.rect.Height)); + } + CreateRectBody(mergedRect); } - if (hasHoles) + if (sections.Any(x => x.gap != null)) { CreateRectBody(rect).IsSensor = true; } - } private Body CreateRectBody(Rectangle rect)