diff --git a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs index 0e44e34c4..03455b283 100644 --- a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs @@ -630,13 +630,26 @@ namespace Barotrauma walkPos += movement.Length() * 0.15f; footPos = Collider.SimPosition - new Vector2((float)Math.Sin(-Collider.Rotation), (float)Math.Cos(-Collider.Rotation)) * 0.4f; - - var rightThigh = GetLimb(LimbType.RightThigh); - var leftThigh = GetLimb(LimbType.LeftThigh); - - rightThigh.body.SmoothRotate(torso.Rotation + (float)Math.Sin(walkPos) * 0.3f, 2.0f); - leftThigh.body.SmoothRotate(torso.Rotation - (float)Math.Sin(walkPos) * 0.3f, 2.0f); - + + for (int i = -1; i<2; i+=2) + { + var thigh = i == -1 ? GetLimb(LimbType.LeftThigh) : GetLimb(LimbType.RightThigh); + var leg = i == -1 ? GetLimb(LimbType.LeftLeg) : GetLimb(LimbType.RightLeg); + + float thighDiff = Math.Abs(MathUtils.GetShortestAngle(torso.Rotation, thigh.Rotation)); + if (thighDiff > MathHelper.PiOver2) + { + //thigh bent too close to the torso -> force the leg to extend + float thighTorque = thighDiff * thigh.Mass * Math.Sign(torso.Rotation - thigh.Rotation) * 10.0f; + thigh.body.ApplyTorque(thighTorque); + leg.body.ApplyTorque(thighTorque); + } + else + { + thigh.body.SmoothRotate(torso.Rotation + (float)Math.Sin(walkPos) * i * 0.3f, 2.0f); + } + } + Vector2 transformedFootPos = new Vector2((float)Math.Sin(walkPos) * 0.5f, 0.0f); transformedFootPos = Vector2.Transform( transformedFootPos, diff --git a/Subsurface/Source/Characters/CharacterHUD.cs b/Subsurface/Source/Characters/CharacterHUD.cs index 39a3156a3..ff2daa19c 100644 --- a/Subsurface/Source/Characters/CharacterHUD.cs +++ b/Subsurface/Source/Characters/CharacterHUD.cs @@ -252,7 +252,7 @@ namespace Barotrauma suicideButton.ToolTip = GameMain.NetworkMember == null ? "The character can no longer be revived if you give in." : - "Let go of your character and enter spectator mode (other players will now longer be able to revive you)"; + "Let go of your character and enter spectator mode (other players will no longer be able to revive you)"; suicideButton.OnClicked = (button, userData) => { diff --git a/Subsurface/Source/GUI/GUIListBox.cs b/Subsurface/Source/GUI/GUIListBox.cs index 684f48e92..e57051e4c 100644 --- a/Subsurface/Source/GUI/GUIListBox.cs +++ b/Subsurface/Source/GUI/GUIListBox.cs @@ -163,7 +163,7 @@ namespace Barotrauma scrollBar.BarScroll = 0.0f; } - + public void Select(object userData, bool force = false) { for (int i = 0; i < children.Count; i++) @@ -260,7 +260,34 @@ namespace Barotrauma public override void AddToGUIUpdateList() { - base.AddToGUIUpdateList(); + if (!Visible) return; + if (ComponentsToUpdate.Contains(this)) return; + ComponentsToUpdate.Add(this); + + try + { + List fixedChildren = new List(children); + int lastVisible = 0; + for (int i = 0; i < fixedChildren.Count; i++) + { + if (fixedChildren[i] == frame) continue; + + if (!IsChildVisible(fixedChildren[i])) + { + if (lastVisible > 0) break; + continue; + } + + lastVisible = i; + fixedChildren[i].AddToGUIUpdateList(); + } + } + catch (Exception e) + { + DebugConsole.NewMessage("Error in AddToGUIUpdateList! GUIComponent runtime type: " + this.GetType().ToString() + "; children count: " + children.Count.ToString(), Color.Red); + throw e; + } + if (scrollBarEnabled && !scrollBarHidden) scrollBar.AddToGUIUpdateList(); } @@ -352,19 +379,9 @@ namespace Barotrauma rect.Height += scrollBar.Rect.Height; else rect.Width += scrollBar.Rect.Width; - - //float oldScroll = scrollBar.BarScroll; - //float oldSize = scrollBar.BarSize; + UpdateScrollBarSize(); UpdateChildrenRect(0.0f); - - //if (oldSize == 1.0f && scrollBar.BarScroll == 0.0f) scrollBar.BarScroll = 1.0f; - - //if (scrollBar.BarSize < 1.0f && oldScroll == 1.0f) - //{ - // scrollBar.BarScroll = 1.0f; - //} - } public override void ClearChildren() @@ -385,43 +402,54 @@ namespace Barotrauma public override void Draw(SpriteBatch spriteBatch) { if (!Visible) return; - - //base.Draw(spriteBatch); - + frame.Draw(spriteBatch); if (!scrollBarHidden) scrollBar.Draw(spriteBatch); - + + int lastVisible = 0; for (int i = 0; i < children.Count; i++) { GUIComponent child = children[i]; - if (child == frame || !child.Visible) continue; - - if (scrollBar.IsHorizontal) - { - if (child.Rect.Right < rect.X) continue; - if (child.Rect.Right > rect.Right) break; + if (child == frame) continue; - if (child.Rect.X < rect.X && child.Rect.Right >= rect.X) - { - continue; - } - } - else + if (!IsChildVisible(child)) { - if (child.Rect.Y + child.Rect.Height < rect.Y) continue; - if (child.Rect.Y + child.Rect.Height > rect.Y + rect.Height) break; - - if (child.Rect.Y < rect.Y && child.Rect.Y + child.Rect.Height >= rect.Y) - { - continue; - } + if (lastVisible > 0) break; + continue; } - + + lastVisible = i; child.Draw(spriteBatch); } + } - //GUI.DrawRectangle(spriteBatch, rect, Color.Black, false); + private bool IsChildVisible(GUIComponent child) + { + if (child == null || !child.Visible) return false; + + if (scrollBar.IsHorizontal) + { + if (child.Rect.Right < rect.X) return false; + if (child.Rect.Right > rect.Right) return false; + + if (child.Rect.X < rect.X && child.Rect.Right >= rect.X) + { + return false; + } + } + else + { + if (child.Rect.Y + child.Rect.Height < rect.Y) return false; + if (child.Rect.Y + child.Rect.Height > rect.Y + rect.Height) return false; + + if (child.Rect.Y < rect.Y && child.Rect.Y + child.Rect.Height >= rect.Y) + { + return false; + } + } + + return true; } } } diff --git a/Subsurface/Source/Map/Lights/LightSource.cs b/Subsurface/Source/Map/Lights/LightSource.cs index 9daf95ace..bc2363e7c 100644 --- a/Subsurface/Source/Map/Lights/LightSource.cs +++ b/Subsurface/Source/Map/Lights/LightSource.cs @@ -40,6 +40,8 @@ namespace Barotrauma.Lights //when were the vertices of the light volume last calculated private float lastRecalculationTime; + private Dictionary diffToSub; + private DynamicVertexBuffer lightVolumeBuffer; private DynamicIndexBuffer lightVolumeIndexBuffer; private int vertexCount; @@ -122,7 +124,7 @@ namespace Barotrauma.Lights color = new Color(ToolBox.GetAttributeVector4(element, "color", Vector4.One)); CastShadows = ToolBox.GetAttributeBool(element, "castshadows", true); - + foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) @@ -150,7 +152,9 @@ namespace Barotrauma.Lights CastShadows = true; texture = LightTexture; - + + diffToSub = new Dictionary(); + GameMain.LightManager.AddLight(this); } @@ -269,20 +273,34 @@ namespace Barotrauma.Lights else { if (sub.DockedTo.Contains(ParentSub) && !NeedsHullCheck) continue; - + lightPos -= (sub.Position - ParentSub.Position); Rectangle subBorders = sub.Borders; subBorders.Location += sub.HiddenSubPosition.ToPoint() - new Point(0, sub.Borders.Height); - //only draw if the light overlaps with the sub + //don't draw any shadows if the light doesn't overlap with the borders of the sub if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders)) { if (chList.List.Count > 0) NeedsRecalculation = true; chList.List.Clear(); continue; } - + + //recalculate vertices if the subs have moved > 5 px relative to each other + Vector2 diff = ParentSub.WorldPosition - sub.WorldPosition; + Vector2 prevDiff; + if (!diffToSub.TryGetValue(sub, out prevDiff)) + { + diffToSub.Add(sub, diff); + NeedsRecalculation = true; + } + else if (Vector2.DistanceSquared(diff, prevDiff) > 5.0f*5.0f) + { + diffToSub[sub] = diff; + NeedsRecalculation = true; + } + RefreshConvexHullList(chList, lightPos, sub); } } diff --git a/Subsurface/Source/Map/MapEntity.cs b/Subsurface/Source/Map/MapEntity.cs index 97d97536c..d67cf2dcc 100644 --- a/Subsurface/Source/Map/MapEntity.cs +++ b/Subsurface/Source/Map/MapEntity.cs @@ -463,7 +463,11 @@ namespace Barotrauma Vector2 moveAmount = Submarine.VectorToWorldGrid(cam.WorldViewCenter - center); selectedList = new List(clones); - selectedList.ForEach(c => c.Move(moveAmount)); + foreach (MapEntity clone in selectedList) + { + clone.Move(moveAmount); + clone.Submarine = Submarine.MainSub; + } } } diff --git a/Subsurface/Source/Map/SubmarineBody.cs b/Subsurface/Source/Map/SubmarineBody.cs index f3aa70d17..d7120dace 100644 --- a/Subsurface/Source/Map/SubmarineBody.cs +++ b/Subsurface/Source/Map/SubmarineBody.cs @@ -160,17 +160,17 @@ namespace Barotrauma private List GenerateConvexHull() { - if (!Structure.WallList.Any()) + List subWalls = Structure.WallList.FindAll(wall => wall.Submarine == submarine); + + if (subWalls.Count == 0) { return new List { new Vector2(-1.0f, 1.0f), new Vector2(1.0f, 1.0f), new Vector2(0.0f, -1.0f) }; } List points = new List(); - foreach (Structure wall in Structure.WallList) + foreach (Structure wall in subWalls) { - if (wall.Submarine != submarine) continue; - points.Add(new Vector2(wall.Rect.X, wall.Rect.Y)); points.Add(new Vector2(wall.Rect.X + wall.Rect.Width, wall.Rect.Y)); points.Add(new Vector2(wall.Rect.X, wall.Rect.Y - wall.Rect.Height)); diff --git a/Subsurface/Source/Sounds/SoundPlayer.cs b/Subsurface/Source/Sounds/SoundPlayer.cs index 517da436b..e28e438b5 100644 --- a/Subsurface/Source/Sounds/SoundPlayer.cs +++ b/Subsurface/Source/Sounds/SoundPlayer.cs @@ -346,42 +346,51 @@ namespace Barotrauma private static List GetSuitableMusicClips() { - Task criticalTask = null; - if (GameMain.GameSession != null && GameMain.GameSession.TaskManager != null) + string musicType = "default"; + if (OverrideMusicType != null) { - foreach (Task task in GameMain.GameSession.TaskManager.Tasks) + musicType = OverrideMusicType; + } + else if (Character.Controlled != null && + Level.Loaded != null && Level.Loaded.Ruins != null && + Level.Loaded.Ruins.Any(r => r.Area.Contains(Character.Controlled.WorldPosition))) + { + musicType = "ruins"; + } + else if ((Character.Controlled != null && Character.Controlled.Submarine != null && Character.Controlled.Submarine.AtDamageDepth) || + (Screen.Selected == GameMain.GameScreen && GameMain.GameScreen.Cam.Position.Y < SubmarineBody.DamageDepth)) + { + musicType = "deep"; + } + else + { + Task criticalTask = null; + if (GameMain.GameSession != null && GameMain.GameSession.TaskManager != null) { - if (!task.IsStarted) continue; - if (criticalTask == null || task.Priority > criticalTask.Priority) + foreach (Task task in GameMain.GameSession.TaskManager.Tasks) { - criticalTask = task; + if (!task.IsStarted) continue; + if (criticalTask == null || task.Priority > criticalTask.Priority) + { + criticalTask = task; + } } } + + if (criticalTask != null) + { + var suitableClips = + musicClips.Where(music => + music != null && + music.type == criticalTask.MusicType && + music.priorityRange.X < criticalTask.Priority && + music.priorityRange.Y > criticalTask.Priority).ToList(); + + if (suitableClips.Count > 0) return suitableClips; + } } - if (OverrideMusicType != null) - { - return musicClips.Where(x => x != null && x.type == OverrideMusicType).ToList(); - } - else if (Character.Controlled != null && Level.Loaded != null && Level.Loaded.Ruins!=null && Level.Loaded.Ruins.Any(r => r.Area.Contains(Character.Controlled.WorldPosition))) - { - return musicClips.Where(x => x != null && x.type == "ruins").ToList(); - } - else if (Submarine.MainSub != null && Submarine.MainSub.AtDamageDepth) - { - return musicClips.Where(x => x != null && x.type == "deep").ToList(); - } - else if (criticalTask == null) - { - return musicClips.Where(x => x != null && x.type == "default").ToList(); - } - - return musicClips.Where(x => - x != null && - x.type == criticalTask.MusicType && - x.priorityRange.X < criticalTask.Priority && - x.priorityRange.Y > criticalTask.Priority).ToList(); - + return musicClips.Where(music => music != null && music.type == musicType).ToList(); } public static void PlaySplashSound(Vector2 worldPosition, float strength) diff --git a/Subsurface/Source/Utils/MathUtils.cs b/Subsurface/Source/Utils/MathUtils.cs index 0aa6b5760..62f11fab1 100644 --- a/Subsurface/Source/Utils/MathUtils.cs +++ b/Subsurface/Source/Utils/MathUtils.cs @@ -381,6 +381,8 @@ namespace Barotrauma public static List GiftWrap(List points) { + if (points.Count == 0) return points; + Vector2 leftMost = points[0]; foreach (Vector2 point in points) {