diff --git a/Launcher2/LauncherMain.cs b/Launcher2/LauncherMain.cs index 25525ebb5..b8d166735 100644 --- a/Launcher2/LauncherMain.cs +++ b/Launcher2/LauncherMain.cs @@ -196,7 +196,7 @@ namespace Launcher2 var messageBox = GUIMessageBox.MessageBoxes.Peek(); if (messageBox != null) { - GUIComponent.MouseOn = messageBox; + GUIComponent.ForceMouseOn(messageBox); messageBox.Update(deltaTime); return; } diff --git a/StyleCop.Cache b/StyleCop.Cache deleted file mode 100644 index 472d28838..000000000 --- a/StyleCop.Cache +++ /dev/null @@ -1,7 +0,0 @@ - - 12 - - - - - \ No newline at end of file diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj index 3bd07bd27..81cae3f08 100644 --- a/Subsurface/Barotrauma.csproj +++ b/Subsurface/Barotrauma.csproj @@ -525,6 +525,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest Designer @@ -1486,7 +1489,6 @@ PreserveNewest - diff --git a/Subsurface/Content/Characters/Human/human.xml b/Subsurface/Content/Characters/Human/human.xml index 6b70f9857..28b9914fe 100644 --- a/Subsurface/Content/Characters/Human/human.xml +++ b/Subsurface/Content/Characters/Human/human.xml @@ -3,7 +3,7 @@ - - + + diff --git a/Subsurface/Content/Characters/Human/humanhusk.xml b/Subsurface/Content/Characters/Human/humanhusk.xml index 73b9e9e13..52f0e389e 100644 --- a/Subsurface/Content/Characters/Human/humanhusk.xml +++ b/Subsurface/Content/Characters/Human/humanhusk.xml @@ -13,7 +13,8 @@ swimspeed="2.5" impacttolerance="7.5"> - + + diff --git a/Subsurface/Content/Characters/Husk/husk.xml b/Subsurface/Content/Characters/Husk/husk.xml index 177bd1407..0376a0262 100644 --- a/Subsurface/Content/Characters/Husk/husk.xml +++ b/Subsurface/Content/Characters/Husk/husk.xml @@ -14,7 +14,8 @@ walkspeed="1.2" swimspeed="2.5"> - + + diff --git a/Subsurface/Content/Characters/Mantis/mantis.xml b/Subsurface/Content/Characters/Mantis/mantis.xml index cfcd6f781..669325144 100644 --- a/Subsurface/Content/Characters/Mantis/mantis.xml +++ b/Subsurface/Content/Characters/Mantis/mantis.xml @@ -9,7 +9,7 @@ - + @@ -89,6 +89,6 @@ + attackcooldown="1.0"/> diff --git a/Subsurface/Content/Characters/TigerThresher/damagedtigerthresher.png b/Subsurface/Content/Characters/Tigerthresher/damagedtigerthresher.png similarity index 100% rename from Subsurface/Content/Characters/TigerThresher/damagedtigerthresher.png rename to Subsurface/Content/Characters/Tigerthresher/damagedtigerthresher.png diff --git a/Subsurface/Content/Characters/TigerThresher/tigerthresher.png b/Subsurface/Content/Characters/Tigerthresher/tigerthresher.png similarity index 100% rename from Subsurface/Content/Characters/TigerThresher/tigerthresher.png rename to Subsurface/Content/Characters/Tigerthresher/tigerthresher.png diff --git a/Subsurface/Content/Characters/TigerThresher/tigerthresher.xml b/Subsurface/Content/Characters/Tigerthresher/tigerthresher.xml similarity index 78% rename from Subsurface/Content/Characters/TigerThresher/tigerthresher.xml rename to Subsurface/Content/Characters/Tigerthresher/tigerthresher.xml index 30083658c..1c9f3935c 100644 --- a/Subsurface/Content/Characters/TigerThresher/tigerthresher.xml +++ b/Subsurface/Content/Characters/Tigerthresher/tigerthresher.xml @@ -11,45 +11,45 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/Subsurface/Content/Characters/Watcher/watcher.xml b/Subsurface/Content/Characters/Watcher/watcher.xml index c83554741..9cf6a49a4 100644 --- a/Subsurface/Content/Characters/Watcher/watcher.xml +++ b/Subsurface/Content/Characters/Watcher/watcher.xml @@ -14,7 +14,7 @@ - + diff --git a/Subsurface/Content/Items/Artifacts/artifactholder.png b/Subsurface/Content/Items/Artifacts/artifactholder.png new file mode 100644 index 000000000..bca7f24fe Binary files /dev/null and b/Subsurface/Content/Items/Artifacts/artifactholder.png differ diff --git a/Subsurface/Content/Items/Artifacts/artifacts.xml b/Subsurface/Content/Items/Artifacts/artifacts.xml index 3f11229ed..3a6b3ee62 100644 --- a/Subsurface/Content/Items/Artifacts/artifacts.xml +++ b/Subsurface/Content/Items/Artifacts/artifacts.xml @@ -3,6 +3,7 @@ @@ -24,6 +25,7 @@ @@ -46,6 +48,7 @@ @@ -66,7 +69,7 @@ name="Oxygenite Shard" category="Alien" pickdistance="150" - tags="smallitem" + tags="alien,smallitem" impacttolerance="8"> @@ -86,7 +89,7 @@ name="Sulphurite Shard" category="Alien" pickdistance="150" - tags="smallitem" + tags="alien,smallitem" impacttolerance="8" spritecolor="1.0,0.0,0.0,1.0"> @@ -109,7 +112,7 @@ @@ -147,6 +150,7 @@ @@ -169,6 +173,7 @@ name="Alien Door" category="Alien" linkable="true" + Tags="alien" pickdistance="150.0"> @@ -190,6 +195,7 @@ name="Alien Motion Sensor" linkable="true" category="Alien" + Tags="alien" pickdistance="150.0"> @@ -201,4 +207,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Subsurface/Content/Map/RuinConfig.xml b/Subsurface/Content/Map/RuinConfig.xml index f843d1829..6953c9539 100644 --- a/Subsurface/Content/Map/RuinConfig.xml +++ b/Subsurface/Content/Map/RuinConfig.xml @@ -27,4 +27,6 @@ + + \ No newline at end of file diff --git a/Subsurface/Source/Characters/AI/EnemyAIController.cs b/Subsurface/Source/Characters/AI/EnemyAIController.cs index a4a6eccd2..a614c921b 100644 --- a/Subsurface/Source/Characters/AI/EnemyAIController.cs +++ b/Subsurface/Source/Characters/AI/EnemyAIController.cs @@ -110,7 +110,21 @@ namespace Barotrauma { UpdateDistanceAccumulator(); - Character.AnimController.IgnorePlatforms = (-Character.AnimController.TargetMovement.Y > Math.Abs(Character.AnimController.TargetMovement.X)); + bool ignorePlatforms = (-Character.AnimController.TargetMovement.Y > Math.Abs(Character.AnimController.TargetMovement.X)); + + if (steeringManager is IndoorsSteeringManager) + { + var currPath = ((IndoorsSteeringManager)steeringManager).CurrentPath; + if (currPath != null && currPath.CurrentNode != null) + { + if (currPath.CurrentNode.SimPosition.Y < Character.AnimController.GetColliderBottom().Y) + { + ignorePlatforms = true; + } + } + } + + Character.AnimController.IgnorePlatforms = ignorePlatforms; if (Character.AnimController is HumanoidAnimController) { @@ -237,6 +251,16 @@ namespace Barotrauma if (attackLimb != null) { steeringManager.SteeringSeek(attackSimPosition - (attackLimb.SimPosition - SimPosition)); + + if (steeringManager is IndoorsSteeringManager) + { + var indoorsSteering = (IndoorsSteeringManager)steeringManager; + if (indoorsSteering.CurrentPath!=null && (indoorsSteering.CurrentPath.Finished || indoorsSteering.CurrentPath.Unreachable)) + { + steeringManager.SteeringManual(deltaTime, attackSimPosition - attackLimb.SimPosition); + } + } + if (attackingLimb != null) UpdateLimbAttack(deltaTime, attackingLimb, attackSimPosition); } } @@ -501,13 +525,42 @@ namespace Barotrauma } spriteBatch.DrawString(GUI.Font, targetValue.ToString(), pos - Vector2.UnitY*20.0f, Color.Red); + } + if (selectedAiTarget != null) + { + GUI.DrawLine(spriteBatch, + new Vector2(Character.DrawPosition.X, -Character.DrawPosition.Y), + new Vector2(selectedAiTarget.WorldPosition.X, -selectedAiTarget.WorldPosition.Y), Color.Red); } spriteBatch.DrawString(GUI.Font, targetValue.ToString(), pos - Vector2.UnitY * 80.0f, Color.Red); spriteBatch.DrawString(GUI.Font, "updatetargets: "+updateTargetsTimer, pos - Vector2.UnitY * 100.0f, Color.Red); spriteBatch.DrawString(GUI.Font, "cooldown: " + coolDownTimer, pos - Vector2.UnitY * 120.0f, Color.Red); + + + IndoorsSteeringManager pathSteering = steeringManager as IndoorsSteeringManager; + if (pathSteering == null || pathSteering.CurrentPath == null || pathSteering.CurrentPath.CurrentNode == null) return; + + GUI.DrawLine(spriteBatch, + new Vector2(Character.DrawPosition.X, -Character.DrawPosition.Y), + new Vector2(pathSteering.CurrentPath.CurrentNode.DrawPosition.X, -pathSteering.CurrentPath.CurrentNode.DrawPosition.Y), + Color.LightGreen); + + + for (int i = 1; i < pathSteering.CurrentPath.Nodes.Count; i++) + { + GUI.DrawLine(spriteBatch, + new Vector2(pathSteering.CurrentPath.Nodes[i].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i].DrawPosition.Y), + new Vector2(pathSteering.CurrentPath.Nodes[i - 1].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i - 1].DrawPosition.Y), + Color.LightGreen); + + spriteBatch.DrawString(GUI.SmallFont, + pathSteering.CurrentPath.Nodes[i].ID.ToString(), + new Vector2(pathSteering.CurrentPath.Nodes[i].DrawPosition.X, -pathSteering.CurrentPath.Nodes[i].DrawPosition.Y - 10), + Color.LightGreen); + } } } diff --git a/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs b/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs index d5c045ee8..462a7e617 100644 --- a/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs +++ b/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs @@ -97,7 +97,7 @@ namespace Barotrauma diff.Y = 0.0f; } - if (diff.Length() < 0.01) return -host.Steering; + if (diff.LengthSquared() < 0.001f) return -host.Steering; return Vector2.Normalize(diff) * speed; } @@ -146,11 +146,11 @@ namespace Barotrauma } var collider = character.AnimController.Collider; - Vector2 colliderBottom = character.AnimController.GetColliderBottom(); - if (Math.Abs(collider.SimPosition.X - currentPath.CurrentNode.SimPosition.X) < collider.radius*2 && - currentPath.CurrentNode.SimPosition.Y > colliderBottom.Y && - currentPath.CurrentNode.SimPosition.Y < colliderBottom.Y + collider.height + collider.radius*2) + + if (Math.Abs(collider.SimPosition.X - currentPath.CurrentNode.SimPosition.X) < collider.radius * 2 && + currentPath.CurrentNode.SimPosition.Y > colliderBottom.Y && + currentPath.CurrentNode.SimPosition.Y < colliderBottom.Y + 1.5f) { currentPath.SkipToNextNode(); } @@ -167,8 +167,7 @@ namespace Barotrauma diff.X = 0.0f; //at the same height as the waypoint - if (currentPath.CurrentNode.SimPosition.Y > colliderBottom.Y && - currentPath.CurrentNode.SimPosition.Y < colliderBottom.Y + collider.height + collider.radius * 2) + if (Math.Abs(collider.SimPosition.Y - currentPath.CurrentNode.SimPosition.Y) < collider.height / 2 + collider.radius) { float heightFromFloor = character.AnimController.GetColliderBottom().Y - character.AnimController.FloorY; diff --git a/Subsurface/Source/Characters/AI/PathFinder.cs b/Subsurface/Source/Characters/AI/PathFinder.cs index 7ddef2f11..78846b22c 100644 --- a/Subsurface/Source/Characters/AI/PathFinder.cs +++ b/Subsurface/Source/Characters/AI/PathFinder.cs @@ -61,6 +61,7 @@ namespace Barotrauma } var nodeList = nodes.Values.ToList(); + nodeList.RemoveAll(n => n.connections.Count == 0); foreach (PathNode node in nodeList) { node.distances = new List(); @@ -69,6 +70,7 @@ namespace Barotrauma node.distances.Add(Vector2.Distance(node.position, node.connections[i].position)); } } + return nodeList; } } @@ -198,12 +200,6 @@ namespace Barotrauma { Vector2 nodePos = node.Position; - //if node waypoint is one of submarine waypoints outside the sub, transform position - //if (node.Waypoint!=null && node.Waypoint.Submarine != null && node.Waypoint.CurrentHull==null) - //{ - // nodePos -= node.Waypoint.Submarine.Position; - //} - float dist = Vector2.Distance(end, nodePos); if (dist < closestDist || endNode == null) { diff --git a/Subsurface/Source/Characters/Animation/FishAnimController.cs b/Subsurface/Source/Characters/Animation/FishAnimController.cs index cb6a1c7ed..ee420f416 100644 --- a/Subsurface/Source/Characters/Animation/FishAnimController.cs +++ b/Subsurface/Source/Characters/Animation/FishAnimController.cs @@ -51,17 +51,17 @@ namespace Barotrauma if (character.IsDead || character.IsUnconscious || stunTimer > 0.0f) { - collider.FarseerBody.FixedRotation = false; + Collider.FarseerBody.FixedRotation = false; if (character.IsRemotePlayer) { - MainLimb.pullJoint.WorldAnchorB = collider.SimPosition; + MainLimb.pullJoint.WorldAnchorB = Collider.SimPosition; MainLimb.pullJoint.Enabled = true; } else { - collider.LinearVelocity = (MainLimb.SimPosition - collider.SimPosition) * 60.0f; - collider.SmoothRotate(MainLimb.Rotation); + Collider.LinearVelocity = (MainLimb.SimPosition - Collider.SimPosition) * 60.0f; + Collider.SmoothRotate(MainLimb.Rotation); } if (stunTimer > 0) @@ -73,16 +73,16 @@ namespace Barotrauma } //re-enable collider - if (!collider.FarseerBody.Enabled) + if (!Collider.FarseerBody.Enabled) { var lowestLimb = FindLowestLimb(); - collider.SetTransform(new Vector2( - collider.SimPosition.X, - Math.Max(lowestLimb.SimPosition.Y + (collider.radius + collider.height / 2), collider.SimPosition.Y)), + Collider.SetTransform(new Vector2( + Collider.SimPosition.X, + Math.Max(lowestLimb.SimPosition.Y + (Collider.radius + Collider.height / 2), Collider.SimPosition.Y)), 0.0f); - collider.FarseerBody.Enabled = true; + Collider.FarseerBody.Enabled = true; } ResetPullJoints(); @@ -96,20 +96,20 @@ namespace Barotrauma if (inWater) { - collider.FarseerBody.FixedRotation = false; + Collider.FarseerBody.FixedRotation = false; UpdateSineAnim(deltaTime); } else if (currentHull != null && CanEnterSubmarine) { - if (Math.Abs(MathUtils.GetShortestAngle(collider.Rotation, 0.0f)) > 0.001f) + if (Math.Abs(MathUtils.GetShortestAngle(Collider.Rotation, 0.0f)) > 0.001f) { //rotate collider back upright - collider.AngularVelocity = MathUtils.GetShortestAngle(collider.Rotation, 0.0f) * 60.0f; - collider.FarseerBody.FixedRotation = false; + Collider.AngularVelocity = MathUtils.GetShortestAngle(Collider.Rotation, 0.0f) * 60.0f; + Collider.FarseerBody.FixedRotation = false; } else { - collider.FarseerBody.FixedRotation = true; + Collider.FarseerBody.FixedRotation = true; } UpdateWalkAnim(deltaTime); @@ -172,7 +172,7 @@ namespace Barotrauma movement = TargetMovement*swimSpeed; MainLimb.pullJoint.Enabled = true; - MainLimb.pullJoint.WorldAnchorB = collider.SimPosition; + MainLimb.pullJoint.WorldAnchorB = Collider.SimPosition; if (movement.LengthSquared() < 0.00001f) return; @@ -180,12 +180,12 @@ namespace Barotrauma if (rotateTowardsMovement) { - collider.SmoothRotate(movementAngle, 25.0f); + Collider.SmoothRotate(movementAngle, 25.0f); MainLimb.body.SmoothRotate(movementAngle, 25.0f); } else { - collider.SmoothRotate(HeadAngle * Dir, 25.0f); + Collider.SmoothRotate(HeadAngle * Dir, 25.0f); MainLimb.body.SmoothRotate(HeadAngle * Dir, 25.0f); } @@ -216,7 +216,7 @@ namespace Barotrauma Limbs[i].body.ApplyForce(((limbPos - Limbs[i].SimPosition) * 3.0f - Limbs[i].LinearVelocity * 3.0f) * Limbs[i].Mass); } - collider.LinearVelocity = Vector2.Lerp(collider.LinearVelocity, movement, 0.5f); + Collider.LinearVelocity = Vector2.Lerp(Collider.LinearVelocity, movement, 0.5f); floorY = Limbs[0].SimPosition.Y; } @@ -225,9 +225,7 @@ namespace Barotrauma { movement = MathUtils.SmoothStep(movement, TargetMovement * walkSpeed, 0.2f); if (movement == Vector2.Zero) return; - - IgnorePlatforms = (TargetMovement.Y < -Math.Abs(TargetMovement.X)); - + float mainLimbHeight, mainLimbAngle; if (MainLimb.type == LimbType.Torso) { @@ -242,9 +240,9 @@ namespace Barotrauma MainLimb.body.SmoothRotate(mainLimbAngle * Dir, 50.0f); - collider.LinearVelocity = new Vector2( + Collider.LinearVelocity = new Vector2( movement.X, - collider.LinearVelocity.Y > 0.0f ? collider.LinearVelocity.Y * 0.5f : collider.LinearVelocity.Y); + Collider.LinearVelocity.Y > 0.0f ? Collider.LinearVelocity.Y * 0.5f : Collider.LinearVelocity.Y); MainLimb.MoveToPos(GetColliderBottom() + Vector2.UnitY * mainLimbHeight, 10.0f); diff --git a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs index 246a549f0..e2fdb3ab2 100644 --- a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs @@ -54,21 +54,26 @@ namespace Barotrauma public override void UpdateAnim(float deltaTime) { if (Frozen) return; - + + levitatingCollider = true; + ColliderIndex = Crouching ? 1 : 0; + if (!Crouching && ColliderIndex == 1) Crouching = true; + if (character.IsDead || character.IsUnconscious || stunTimer > 0.0f) { - collider.FarseerBody.FixedRotation = false; + levitatingCollider = false; + Collider.FarseerBody.FixedRotation = false; - if (character.IsRemotePlayer) + /*if (character.IsRemotePlayer) { - MainLimb.pullJoint.WorldAnchorB = collider.SimPosition; + MainLimb.pullJoint.WorldAnchorB = Collider.SimPosition; MainLimb.pullJoint.Enabled = true; } else - { - collider.LinearVelocity = (GetLimb(LimbType.Waist).SimPosition - collider.SimPosition) * 20.0f; - collider.SmoothRotate(GetLimb(LimbType.Torso).Rotation); - } + {*/ + Collider.LinearVelocity = (GetLimb(LimbType.Waist).SimPosition - Collider.SimPosition) * 20.0f; + Collider.SmoothRotate(GetLimb(LimbType.Torso).Rotation); + //} if (stunTimer > 0) { @@ -90,39 +95,39 @@ namespace Barotrauma if (!character.IsRemotePlayer || true) { //re-enable collider - if (!collider.FarseerBody.Enabled) + if (!Collider.FarseerBody.Enabled) { var lowestLimb = FindLowestLimb(); - collider.SetTransform(new Vector2( - collider.SimPosition.X, - Math.Max(lowestLimb.SimPosition.Y + (collider.radius + collider.height / 2), collider.SimPosition.Y)), - collider.Rotation); + Collider.SetTransform(new Vector2( + Collider.SimPosition.X, + Math.Max(lowestLimb.SimPosition.Y + (Collider.radius + Collider.height / 2), Collider.SimPosition.Y)), + Collider.Rotation); - collider.FarseerBody.Enabled = true; + Collider.FarseerBody.Enabled = true; } if (swimming) { - collider.FarseerBody.FixedRotation = false; + Collider.FarseerBody.FixedRotation = false; } - else if (!collider.FarseerBody.FixedRotation) + else if (!Collider.FarseerBody.FixedRotation) { - if (Math.Abs(MathUtils.GetShortestAngle(collider.Rotation, 0.0f)) > 0.001f) + if (Math.Abs(MathUtils.GetShortestAngle(Collider.Rotation, 0.0f)) > 0.001f) { //rotate collider back upright - collider.AngularVelocity = MathUtils.GetShortestAngle(collider.Rotation, 0.0f) * 10.0f; - collider.FarseerBody.FixedRotation = false; + Collider.AngularVelocity = MathUtils.GetShortestAngle(Collider.Rotation, 0.0f) * 10.0f; + Collider.FarseerBody.FixedRotation = false; } else { - collider.FarseerBody.FixedRotation = true; + Collider.FarseerBody.FixedRotation = true; } } } else { - collider.FarseerBody.Enabled = false; + Collider.FarseerBody.Enabled = false; } if (character.LockHands) @@ -165,6 +170,7 @@ namespace Barotrauma switch (Anim) { case Animation.Climbing: + levitatingCollider = false; UpdateClimbing(); break; case Animation.UsingConstruction: @@ -210,7 +216,7 @@ namespace Barotrauma } aiming = false; - if (character.IsRemotePlayer && GameMain.Server == null) collider.LinearVelocity = Vector2.Zero; + if (character.IsRemotePlayer && GameMain.Server == null) Collider.LinearVelocity = Vector2.Zero; } @@ -240,28 +246,26 @@ namespace Barotrauma { TargetMovement = new Vector2(MathHelper.Clamp(TargetMovement.X, -1.5f, 1.5f), TargetMovement.Y); - if ((TargetMovement.X > 0.0f && stairs.StairDirection == Direction.Right) || + /*if ((TargetMovement.X > 0.0f && stairs.StairDirection == Direction.Right) || TargetMovement.X < 0.0f && stairs.StairDirection == Direction.Left) { TargetMovement *= 1.7f; //walkCycleSpeed *= 1.0f; - } + }*/ } Vector2 colliderPos = GetColliderBottom(); if (Math.Abs(TargetMovement.X) > 1.0f) { - int limbsInWater = 0; - foreach (Limb limb in Limbs) + float slowdownAmount = 0.0f; + if (currentHull != null) { - if (limb.inWater) limbsInWater++; + //full slowdown (1.0f) when water is up to the torso + surfaceY = ConvertUnits.ToSimUnits(currentHull.Surface); + slowdownAmount = MathHelper.Clamp((surfaceY - colliderPos.Y) / torsoPosition, 0.0f, 1.0f); } - float slowdownFactor = (float)limbsInWater / (float)Limbs.Length; - - float maxSpeed = Math.Max(TargetMovement.Length() - slowdownFactor, 1.0f); - // if (character.SelectedCharacter!=null) maxSpeed = Math.Min(maxSpeed, 1.0f); - + float maxSpeed = Math.Max(TargetMovement.Length() - slowdownAmount, 1.0f); TargetMovement = Vector2.Normalize(TargetMovement) * maxSpeed; } @@ -308,24 +312,19 @@ namespace Barotrauma if (onGround && (!character.IsRemotePlayer || GameMain.Server != null)) { //move slower if collider isn't upright - float rotationFactor = (float)Math.Abs(Math.Cos(collider.Rotation)); + float rotationFactor = (float)Math.Abs(Math.Cos(Collider.Rotation)); - collider.LinearVelocity = new Vector2( + Collider.LinearVelocity = new Vector2( movement.X * rotationFactor, - collider.LinearVelocity.Y > 0.0f ? collider.LinearVelocity.Y * 0.5f : collider.LinearVelocity.Y); + Collider.LinearVelocity.Y > 0.0f ? Collider.LinearVelocity.Y * 0.5f : Collider.LinearVelocity.Y); } - ClimbOverObstacles(); - getUpSpeed = getUpSpeed * Math.Max(head.SimPosition.Y - colliderPos.Y, 0.5f); torso.pullJoint.Enabled = true; head.pullJoint.Enabled = true; waist.pullJoint.Enabled = true; - collider.FarseerBody.Friction = 0.05f; - collider.FarseerBody.Restitution = 0.05f; - if (stairs != null) { torso.pullJoint.WorldAnchorB = new Vector2( @@ -444,9 +443,19 @@ namespace Barotrauma for (int i = -1; i < 2; i += 2) { - Vector2 footPos = new Vector2( - Crouching ? waist.SimPosition.X + Math.Sign(stepSize.X * i) * Dir * 0.3f : GetCenterOfMass().X, - colliderPos.Y - 0.1f); + Vector2 footPos = colliderPos; + + if (Crouching) + { + footPos = new Vector2( + waist.SimPosition.X + Math.Sign(stepSize.X * i) * Dir * 0.3f, + colliderPos.Y - 0.1f); + } + else + { + footPos = new Vector2(GetCenterOfMass().X + stepSize.X * i * 0.2f, colliderPos.Y - 0.1f); + } + var foot = i == -1 ? rightFoot : leftFoot; @@ -486,11 +495,11 @@ namespace Barotrauma private void ClimbOverObstacles() { - if (collider.FarseerBody.ContactList == null || Math.Abs(movement.X) < 0.01f) return; + if (Collider.FarseerBody.ContactList == null || Math.Abs(movement.X) < 0.01f) return; //check if the collider is touching a suitable obstacle to climb over Vector2? handle = null; - FarseerPhysics.Dynamics.Contacts.ContactEdge ce = collider.FarseerBody.ContactList; + FarseerPhysics.Dynamics.Contacts.ContactEdge ce = Collider.FarseerBody.ContactList; while (ce != null && ce.Contact != null) { if (ce.Contact.Enabled && ce.Contact.IsTouching && ce.Contact.FixtureA.CollisionCategories.HasFlag(Physics.CollisionWall)) @@ -500,7 +509,7 @@ namespace Barotrauma ce.Contact.GetWorldManifold(out contactNormal, out contactPos); //only climb if moving towards the obstacle - if (Math.Sign(contactPos[0].X - collider.SimPosition.X) == Math.Sign(movement.X) && + if (Math.Sign(contactPos[0].X - Collider.SimPosition.X) == Math.Sign(movement.X) && (handle == null || contactPos[0].Y > ((Vector2)handle).Y)) { handle = contactPos[0]; @@ -516,7 +525,7 @@ namespace Barotrauma //the contact point should be higher than the bottom of the collider if (((Vector2)handle).Y < colliderBottomY + 0.01f || - ((Vector2)handle).Y > collider.SimPosition.Y) return; + ((Vector2)handle).Y > Collider.SimPosition.Y) return; //find the height of the floor below the torso //(if moving towards towards an obstacle that's low enough to climb over, the torso should be above it) @@ -525,7 +534,7 @@ namespace Barotrauma if (obstacleY > colliderBottomY) { //higher vertical velocity for taller obstacles - collider.LinearVelocity += Vector2.UnitY * (((Vector2)handle).Y - colliderBottomY + 0.01f) * 50; + Collider.LinearVelocity += Vector2.UnitY * (((Vector2)handle).Y - colliderBottomY + 0.01f) * 50; onGround = true; } } @@ -543,7 +552,7 @@ namespace Barotrauma if (currentHull != null && (currentHull.Rect.Y - currentHull.Surface > 50.0f)) { - surfaceLimiter = (ConvertUnits.ToDisplayUnits(collider.SimPosition.Y + 0.4f) - surfaceY); + surfaceLimiter = (ConvertUnits.ToDisplayUnits(Collider.SimPosition.Y + 0.4f) - surfaceY); surfaceLimiter = Math.Max(1.0f, surfaceLimiter); if (surfaceLimiter > 50.0f) return; } @@ -554,7 +563,7 @@ namespace Barotrauma Limb leftFoot = GetLimb(LimbType.LeftFoot); Limb rightFoot = GetLimb(LimbType.RightFoot); - float rotation = MathHelper.WrapAngle(collider.Rotation); + float rotation = MathHelper.WrapAngle(Collider.Rotation); rotation = MathHelper.ToDegrees(rotation); if (rotation < 0.0f) rotation += 360; @@ -574,7 +583,7 @@ namespace Barotrauma if (!aiming) { float newRotation = MathUtils.VectorToAngle(TargetMovement) - MathHelper.PiOver2; - collider.SmoothRotate(newRotation, 5.0f); + Collider.SmoothRotate(newRotation, 5.0f); //torso.body.SmoothRotate(newRotation); } @@ -589,12 +598,12 @@ namespace Barotrauma TargetMovement = new Vector2(0.0f, -0.1f); float newRotation = MathUtils.VectorToAngle(diff); - collider.SmoothRotate(newRotation, 5.0f); + Collider.SmoothRotate(newRotation, 5.0f); } } - torso.body.SmoothRotate(collider.Rotation); - torso.body.MoveToPos(collider.SimPosition + new Vector2((float)Math.Sin(-collider.Rotation), (float)Math.Cos(-collider.Rotation))*0.4f, 5.0f); + torso.body.SmoothRotate(Collider.Rotation); + torso.body.MoveToPos(Collider.SimPosition + new Vector2((float)Math.Sin(-Collider.Rotation), (float)Math.Cos(-Collider.Rotation))*0.4f, 5.0f); if (TargetMovement == Vector2.Zero) return; @@ -626,11 +635,11 @@ namespace Barotrauma if (!character.IsRemotePlayer || GameMain.Server != null) { - collider.LinearVelocity = Vector2.Lerp(collider.LinearVelocity, movement * swimSpeed, movementLerp); + Collider.LinearVelocity = Vector2.Lerp(Collider.LinearVelocity, movement * swimSpeed, movementLerp); } walkPos += movement.Length() * 0.15f; - footPos = collider.SimPosition - new Vector2((float)Math.Sin(-collider.Rotation), (float)Math.Cos(-collider.Rotation)) * 0.4f; + 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); @@ -641,7 +650,7 @@ namespace Barotrauma Vector2 transformedFootPos = new Vector2((float)Math.Sin(walkPos) * 0.5f, 0.0f); transformedFootPos = Vector2.Transform( transformedFootPos, - Matrix.CreateRotationZ(collider.Rotation)); + Matrix.CreateRotationZ(Collider.Rotation)); MoveLimb(rightFoot, footPos - transformedFootPos, 1.0f); MoveLimb(leftFoot, footPos + transformedFootPos, 1.0f); @@ -741,20 +750,20 @@ namespace Barotrauma { ladderSimPos += character.SelectedConstruction.Submarine.SimPosition - currentHull.Submarine.SimPosition; } - - MoveLimb(head, new Vector2(ladderSimPos.X - 0.27f * Dir, collider.SimPosition.Y + 0.7f), 10.5f); - MoveLimb(torso, new Vector2(ladderSimPos.X - 0.27f * Dir, collider.SimPosition.Y+0.5f), 10.5f); - MoveLimb(waist, new Vector2(ladderSimPos.X - 0.35f * Dir, collider.SimPosition.Y+0.4f), 10.5f); - collider.MoveToPos(new Vector2(ladderSimPos.X - 0.2f * Dir, collider.SimPosition.Y), 10.5f); + MoveLimb(head, new Vector2(ladderSimPos.X - 0.27f * Dir, Collider.SimPosition.Y + 0.7f - colliderHeightFromFloor), 10.5f); + MoveLimb(torso, new Vector2(ladderSimPos.X - 0.27f * Dir, Collider.SimPosition.Y + 0.5f - colliderHeightFromFloor), 10.5f); + MoveLimb(waist, new Vector2(ladderSimPos.X - 0.35f * Dir, Collider.SimPosition.Y + 0.4f - colliderHeightFromFloor), 10.5f); + + Collider.MoveToPos(new Vector2(ladderSimPos.X - 0.2f * Dir, Collider.SimPosition.Y), 10.5f); bool slide = targetMovement.Y < -1.1f; Vector2 handPos = new Vector2( ladderSimPos.X, - collider.SimPosition.Y + 0.6f + movement.Y * 0.1f - ladderSimPos.Y); + Collider.SimPosition.Y + 0.6f + movement.Y * 0.1f - ladderSimPos.Y); - handPos.Y = Math.Min(-0.5f, handPos.Y); + handPos.Y = Math.Min(-0.5f, handPos.Y) - colliderHeightFromFloor; MoveLimb(leftHand, new Vector2(handPos.X, @@ -771,7 +780,7 @@ namespace Barotrauma Vector2 footPos = new Vector2( handPos.X - Dir * 0.05f, - collider.SimPosition.Y + 0.7f - stepHeight * 2.7f - ladderSimPos.Y - 0.7f); + Collider.SimPosition.Y + 0.7f - colliderHeightFromFloor - stepHeight * 2.7f - ladderSimPos.Y - 0.7f); //if (movement.Y < 0) footPos.Y += 0.05f; @@ -802,7 +811,7 @@ namespace Barotrauma //if (climbForce.Y > 0.5f) climbForce.Y = Math.Max(climbForce.Y, 1.3f); //apply forces to the collider to move the Character up/down - collider.ApplyForce((climbForce * 20.0f + subSpeed * 50.0f) * collider.Mass); + Collider.ApplyForce((climbForce * 20.0f + subSpeed * 50.0f) * Collider.Mass); head.body.SmoothRotate(0.0f); if (!character.SelectedConstruction.Prefab.Triggers.Any()) @@ -904,10 +913,10 @@ namespace Barotrauma } } - float dist = Vector2.Distance(target.SimPosition, collider.SimPosition); + float dist = Vector2.Distance(target.SimPosition, Collider.SimPosition); //limit movement if moving away from the target - if (Vector2.Dot(target.SimPosition - collider.SimPosition, targetMovement)<0) + if (Vector2.Dot(target.SimPosition - Collider.SimPosition, targetMovement)<0) { targetMovement *= MathHelper.Clamp(2.0f - dist, 0.0f, 1.0f); } @@ -1145,8 +1154,8 @@ namespace Barotrauma float angle = flipAngle ? -limb.body.Rotation : limb.body.Rotation; if (wrapAngle) angle = MathUtils.WrapAnglePi(angle); - - TrySetLimbPosition(limb, collider.SimPosition, position); + + TrySetLimbPosition(limb, Collider.SimPosition, position); limb.body.SetTransform(limb.body.SimPosition, angle); } diff --git a/Subsurface/Source/Characters/Animation/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs index 486b072a9..39ee92af7 100644 --- a/Subsurface/Source/Characters/Animation/Ragdoll.cs +++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs @@ -35,7 +35,7 @@ namespace Barotrauma { l.body.PhysEnabled = !frozen; } - collider.PhysEnabled = !frozen; + Collider.PhysEnabled = !frozen; } } @@ -70,6 +70,8 @@ namespace Barotrauma protected bool inWater, headInWater; public bool onGround; private bool ignorePlatforms; + + protected float colliderHeightFromFloor; protected Structure stairs; @@ -77,13 +79,46 @@ namespace Barotrauma public Direction TargetDir; - protected PhysicsBody collider; - + protected List collider; + protected int colliderIndex = 0; + public PhysicsBody Collider { get { - return collider; + return collider[colliderIndex]; + } + } + + public int ColliderIndex + { + get + { + return colliderIndex; + } + set + { + if (value == colliderIndex) return; + if (value >= collider.Count) return; + if (collider[colliderIndex].height f.CollisionCategories.HasFlag(Physics.CollisionWall))) return; + } + collider[value].LinearVelocity = collider[colliderIndex].LinearVelocity; + collider[value].AngularVelocity = collider[colliderIndex].AngularVelocity; + Vector2 pos = collider[colliderIndex].SimPosition; + pos.Y -= collider[colliderIndex].height * 0.5f; + pos.Y += collider[value].height * 0.5f; + collider[value].SetTransform(pos, collider[colliderIndex].Rotation); + collider[value].PhysEnabled = !frozen; + collider[value].Enabled = !simplePhysicsEnabled; + collider[value].Submarine = collider[colliderIndex].Submarine; + collider[colliderIndex].PhysEnabled = false; + colliderIndex = value; } } @@ -109,8 +144,8 @@ namespace Barotrauma get { return character.Submarine == null ? - ConvertUnits.ToDisplayUnits(collider.SimPosition) : - ConvertUnits.ToDisplayUnits(collider.SimPosition) + character.Submarine.Position; + ConvertUnits.ToDisplayUnits(Collider.SimPosition) : + ConvertUnits.ToDisplayUnits(Collider.SimPosition) + character.Submarine.Position; } } @@ -137,7 +172,7 @@ namespace Barotrauma { foreach (Limb limb in Limbs) { - limb.body.SetTransform(collider.SimPosition, collider.Rotation); + limb.body.SetTransform(Collider.SimPosition, Collider.Rotation); } } } @@ -207,7 +242,7 @@ namespace Barotrauma { limb.body.Submarine = currSubmarine; } - collider.Submarine = currSubmarine; + Collider.Submarine = currSubmarine; } } @@ -266,7 +301,12 @@ namespace Barotrauma ImpactTolerance = ToolBox.GetAttributeFloat(element, "impacttolerance", 50.0f); CanEnterSubmarine = ToolBox.GetAttributeBool(element, "canentersubmarine", true); - + + colliderHeightFromFloor = ToolBox.GetAttributeFloat(element, "colliderheightfromfloor", 45.0f); + colliderHeightFromFloor = ConvertUnits.ToSimUnits(colliderHeightFromFloor); + + collider = new List(); + foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString()) @@ -287,24 +327,31 @@ namespace Barotrauma break; case "collider": - collider = new PhysicsBody(subElement, scale); - collider.FarseerBody.FixedRotation = true; + collider.Add(new PhysicsBody(subElement, scale)); + + collider[collider.Count - 1].FarseerBody.Friction = 0.05f; + collider[collider.Count - 1].FarseerBody.Restitution = 0.05f; + collider[collider.Count - 1].FarseerBody.FixedRotation = true; + collider[collider.Count - 1].CollisionCategories = Physics.CollisionCharacter; + collider[collider.Count - 1].FarseerBody.AngularDamping = 5.0f; + collider[collider.Count - 1].FarseerBody.FixedRotation = true; + collider[collider.Count - 1].FarseerBody.OnCollision += OnLimbCollision; + if (collider.Count > 1) collider[collider.Count - 1].PhysEnabled = false; break; } } - if (collider == null) + if (collider[0] == null) { - DebugConsole.ThrowError("No collider configured for ''"+character.Name+"''!"); - collider = new PhysicsBody(0.0f, 0.0f, 0.5f, 5.0f); - collider.BodyType = BodyType.Dynamic; + DebugConsole.ThrowError("No collider configured for \""+character.Name+"\"!"); + collider[0] = new PhysicsBody(0.0f, 0.0f, 0.5f, 5.0f); + collider[0].BodyType = BodyType.Dynamic; + collider[0].CollisionCategories = Physics.CollisionCharacter; + collider[0].FarseerBody.AngularDamping = 5.0f; + collider[0].FarseerBody.FixedRotation = true; + collider[0].FarseerBody.OnCollision += OnLimbCollision; } - collider.CollisionCategories = Physics.CollisionCharacter; - collider.FarseerBody.AngularDamping = 5.0f; - collider.FarseerBody.FixedRotation = true; - collider.FarseerBody.OnCollision += OnLimbCollision; - UpdateCollisionCategories(); foreach (var joint in limbJoints) @@ -431,7 +478,7 @@ namespace Barotrauma //4. contact points is above the bottom half of the collider Vector2 normal; FarseerPhysics.Common.FixedArray2 points; contact.GetWorldManifold(out normal, out points); - if (points[0].Y > collider.SimPosition.Y) return false; + if (points[0].Y > Collider.SimPosition.Y) return false; //5. in water if (inWater && targetMovement.Y < 0.5f) return false; @@ -475,14 +522,14 @@ namespace Barotrauma limb.HitSound.Play(volume, impact * 100.0f, limb.WorldPosition); } } - else if (f1.Body == collider.FarseerBody) + else if (f1.Body == Collider.FarseerBody) { if (!character.IsRemotePlayer || GameMain.Server != null) { if (impact > ImpactTolerance) { character.AddDamage(CauseOfDeath.Damage, impact - ImpactTolerance, null); - SoundPlayer.PlayDamageSound(DamageSoundType.LimbBlunt, strongestImpact, collider); + SoundPlayer.PlayDamageSound(DamageSoundType.LimbBlunt, strongestImpact, Collider); strongestImpact = Math.Max(strongestImpact, impact - ImpactTolerance); } } @@ -495,7 +542,7 @@ namespace Barotrauma { if (simplePhysicsEnabled) return; - collider.UpdateDrawPosition(); + Collider.UpdateDrawPosition(); foreach (Limb limb in Limbs) { @@ -522,7 +569,7 @@ namespace Barotrauma limb.body.DebugDraw(spriteBatch, inWater ? Color.Cyan : Color.White); } - collider.DebugDraw(spriteBatch, inWater ? Color.SkyBlue : Color.Gray); + Collider.DebugDraw(spriteBatch, inWater ? Color.SkyBlue : Color.Gray); foreach (RevoluteJoint joint in limbJoints) { @@ -568,8 +615,8 @@ namespace Barotrauma if (ignorePlatforms) { GUI.DrawLine(spriteBatch, - new Vector2(collider.DrawPosition.X, -collider.DrawPosition.Y), - new Vector2(collider.DrawPosition.X, -collider.DrawPosition.Y + 50), + new Vector2(Collider.DrawPosition.X, -Collider.DrawPosition.Y), + new Vector2(Collider.DrawPosition.X, -Collider.DrawPosition.Y + 50), Color.Orange, 0, 5); } } @@ -577,7 +624,7 @@ namespace Barotrauma public virtual void Flip() { dir = (dir == Direction.Left) ? Direction.Right : Direction.Left; - + for (int i = 0; i < limbJoints.Length; i++) { float lowerLimit = -limbJoints[i].UpperLimit; @@ -601,6 +648,11 @@ namespace Barotrauma Limbs[i].Dir = Dir; + if (Limbs[i].LightSource != null) + { + Limbs[i].LightSource.SpriteEffect = (dir == Direction.Left) ? SpriteEffects.FlipHorizontally : SpriteEffects.None; + } + if (Limbs[i].pullJoint == null) continue; Limbs[i].pullJoint.LocalAnchorA = @@ -718,7 +770,7 @@ namespace Barotrauma //character.Stun = 0.1f; character.DisableImpactDamageTimer = 0.25f; - SetPosition(collider.SimPosition + moveAmount); + SetPosition(Collider.SimPosition + moveAmount); character.CursorPosition += moveAmount; } @@ -732,7 +784,7 @@ namespace Barotrauma wall | Physics.CollisionProjectile | Physics.CollisionStairs : wall | Physics.CollisionProjectile | Physics.CollisionPlatform | Physics.CollisionStairs; - collider.CollidesWith = collisionCategory; + Collider.CollidesWith = collisionCategory; foreach (Limb limb in Limbs) { @@ -749,19 +801,21 @@ namespace Barotrauma } } + protected bool levitatingCollider = true; + public void Update(Camera cam, float deltaTime) { if (!character.Enabled || Frozen) return; UpdateNetPlayerPosition(deltaTime); CheckDistFromCollider(); - + Vector2 flowForce = Vector2.Zero; FindHull(); splashSoundTimer -= deltaTime; - + //ragdoll isn't in any room -> it's in the water if (currentHull == null) { @@ -779,41 +833,41 @@ namespace Barotrauma float floorY = GetFloorY(); - if (currentHull.Volume > currentHull.FullVolume * 0.95f || - (waterSurface - floorY > HeadPosition * 0.95f && collider.SimPosition.Y < waterSurface)) - inWater = true; + if (currentHull.Volume > currentHull.FullVolume * 0.95f || + (waterSurface - floorY > HeadPosition * 0.95f && Collider.SimPosition.Y < waterSurface)) + inWater = true; } if (flowForce.LengthSquared() > 0.001f) { - collider.ApplyForce(flowForce); + Collider.ApplyForce(flowForce); } - if (currentHull==null || - currentHull.Volume > currentHull.FullVolume * 0.95f || - ConvertUnits.ToSimUnits(currentHull.Surface) > collider.SimPosition.Y) + if (currentHull == null || + currentHull.Volume > currentHull.FullVolume * 0.95f || + ConvertUnits.ToSimUnits(currentHull.Surface) > Collider.SimPosition.Y) { - collider.ApplyWaterForces(); + Collider.ApplyWaterForces(); } - - + + foreach (Limb limb in Limbs) { //find the room which the limb is in //the room where the ragdoll is in is used as the "guess", meaning that it's checked first Hull limbHull = currentHull == null ? null : Hull.FindHull(limb.WorldPosition, currentHull); - + bool prevInWater = limb.inWater; limb.inWater = false; if (limbHull == null) - { + { //limb isn't in any room -> it's in the water limb.inWater = true; } else if (limbHull.Volume > 0.0f && Submarine.RectContains(limbHull.Rect, limb.Position)) { - if (limb.Position.Y < limbHull.Surface) + if (limb.Position.Y < limbHull.Surface) { limb.inWater = true; @@ -829,7 +883,7 @@ namespace Barotrauma headInWater = true; } } - //the limb has gone through the surface of the water + //the limb has gone through the surface of the water if (Math.Abs(limb.LinearVelocity.Y) > 5.0f && limb.inWater != prevInWater) { @@ -838,14 +892,14 @@ namespace Barotrauma new Vector2(limb.Position.X, limbHull.Surface) + limbHull.Submarine.Position, new Vector2(0.0f, Math.Abs(-limb.LinearVelocity.Y * 20.0f)), 0.0f, limbHull); - + GameMain.ParticleManager.CreateParticle("bubbles", - new Vector2(limb.Position.X, limbHull.Surface) + limbHull.Submarine.Position, - limb.LinearVelocity*0.001f, + new Vector2(limb.Position.X, limbHull.Surface) + limbHull.Submarine.Position, + limb.LinearVelocity * 0.001f, 0.0f, limbHull); //if the Character dropped into water, create a wave - if (limb.LinearVelocity.Y<0.0f) + if (limb.LinearVelocity.Y < 0.0f) { if (splashSoundTimer <= 0.0f) { @@ -864,15 +918,18 @@ namespace Barotrauma } } + if (limb.LightSource != null) + { + limb.LightSource.Rotation = limb.Rotation; + } limb.Update(deltaTime); } - - + bool onStairs = stairs != null; stairs = null; - var contacts = collider.FarseerBody.ContactList; - while (collider.FarseerBody.Enabled && contacts != null && contacts.Contact != null) + var contacts = Collider.FarseerBody.ContactList; + while (Collider.FarseerBody.Enabled && contacts != null && contacts.Contact != null) { if (contacts.Contact.Enabled && contacts.Contact.IsTouching) { @@ -907,7 +964,7 @@ namespace Barotrauma //} - if (points[0].Y < collider.SimPosition.Y) + if (points[0].Y < Collider.SimPosition.Y) { floorY = Math.Max(floorY, points[0].Y); @@ -931,12 +988,82 @@ namespace Barotrauma onFloorTimer -= deltaTime; } + Vector2 rayStart = Collider.SimPosition; + Vector2 rayEnd = rayStart; + rayEnd.Y -= Collider.height * 0.5f + Collider.radius + colliderHeightFromFloor*1.2f; + Vector2 colliderBottomDisplay = ConvertUnits.ToDisplayUnits(GetColliderBottom()); + if (!inWater && !character.IsDead && !character.IsUnconscious && levitatingCollider && Collider.LinearVelocity.Y>-ImpactTolerance) + { + float closestFraction = 1.0f; + Fixture closestFixture = null; + GameMain.World.RayCast((fixture, point, normal, fraction) => + { + switch (fixture.CollisionCategories) + { + case Physics.CollisionStairs: + Structure structure = fixture.Body.UserData as Structure; + if (colliderBottomDisplay.Y < structure.Rect.Y - structure.Rect.Height + 30 && TargetMovement.Y < 0.5f) return -1; + break; + case Physics.CollisionPlatform: + Structure platform = fixture.Body.UserData as Structure; + if (IgnorePlatforms || colliderBottomDisplay.Y < platform.Rect.Y - 16) return -1; + break; + case Physics.CollisionWall: + break; + default: + return -1; + } + + if (fraction < closestFraction) + { + closestFraction = fraction; + closestFixture = fixture; + } + + return closestFraction; + } + , rayStart, rayEnd); + + if (closestFraction < 1.0f && closestFixture!=null) + { + bool forceImmediate = false; + onGround = true; + + switch (closestFixture.CollisionCategories) + { + case Physics.CollisionStairs: + stairs = closestFixture.Body.UserData as Structure; + onStairs = true; + forceImmediate = true; + break; + } + + float tfloorY = rayStart.Y + (rayEnd.Y - rayStart.Y) * closestFraction; + float targetY = tfloorY + Collider.height * 0.5f + Collider.radius + colliderHeightFromFloor; + + if (Math.Abs(Collider.SimPosition.Y - targetY) > 0.01f && Collider.SimPosition.Y allowedDist) + if (Vector2.DistanceSquared(Collider.SimPosition, MainLimb.SimPosition) > allowedDist*allowedDist) { foreach (Limb limb in Limbs) { @@ -1053,7 +1180,7 @@ namespace Barotrauma else if (collisionsDisabled) { //set the position of the ragdoll to make sure limbs don't get stuck inside walls when re-enabling collisions - SetPosition(collider.SimPosition, true); + SetPosition(Collider.SimPosition, true); UpdateCollisionCategories(); collisionsDisabled = false; @@ -1082,11 +1209,11 @@ namespace Barotrauma if (errorMagnitude > 2.0f) { //predicted position was way off, reset completely - collider.SetTransform(serverPos.Position, collider.Rotation); + Collider.SetTransform(serverPos.Position, Collider.Rotation); //local positions are incorrect now -> just clear the list character.MemLocalPos.Clear(); } - else if (errorMagnitude > collider.LinearVelocity.Length()/10.0f + 0.02f) + else if (errorMagnitude > Collider.LinearVelocity.Length()/10.0f + 0.02f) { //our prediction differs from the server position //-> we need to move the saved local position and all the positions saved after it @@ -1101,7 +1228,7 @@ namespace Barotrauma character.MemLocalPos[i].Direction, character.MemLocalPos[i].ID); } - collider.SetTransform(character.MemLocalPos.Last().Position, collider.Rotation); + Collider.SetTransform(character.MemLocalPos.Last().Position, Collider.Rotation); } } @@ -1112,8 +1239,8 @@ namespace Barotrauma { if (character.MemPos.Count > 0) { - collider.LinearVelocity = Vector2.Zero; - collider.CorrectPosition(character.MemPos, deltaTime, out overrideTargetMovement); + Collider.LinearVelocity = Vector2.Zero; + Collider.CorrectPosition(character.MemPos, deltaTime, out overrideTargetMovement); } } } @@ -1149,10 +1276,12 @@ namespace Barotrauma public Vector2 GetColliderBottom() { - float halfHeight = collider.height / 2 + collider.radius; + float halfHeight = Collider.height * 0.5f + Collider.radius; - return collider.SimPosition + - new Vector2((float)Math.Sin(collider.Rotation), -(float)Math.Cos(collider.Rotation)) * halfHeight; + Vector2 offset = Vector2.Zero; + offset.Y = -colliderHeightFromFloor; + return Collider.SimPosition + offset + + new Vector2((float)Math.Sin(Collider.Rotation), -(float)Math.Cos(Collider.Rotation)) * halfHeight; } public Limb FindLowestLimb() @@ -1171,11 +1300,24 @@ namespace Barotrauma public void Remove() { - foreach (Limb l in Limbs) l.Remove(); + foreach (Limb l in Limbs) + { + l.Remove(); + } + Limbs = null; + + foreach (PhysicsBody b in collider) + { + b.Remove(); + } + foreach (RevoluteJoint joint in limbJoints) { GameMain.World.RemoveJoint(joint); } + limbJoints = null; + + list.Remove(this); } } diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index 25fa0895d..edc937335 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -932,7 +932,7 @@ namespace Barotrauma if (selectedCharacter!=null) { - if (Vector2.Distance(selectedCharacter.WorldPosition, WorldPosition) > 300.0f || !selectedCharacter.CanBeSelected) + if (Vector2.DistanceSquared(selectedCharacter.WorldPosition, WorldPosition) > 90000.0f || !selectedCharacter.CanBeSelected) { DeselectCharacter(); } @@ -1027,7 +1027,7 @@ namespace Barotrauma maxDist = 150.0f; } - if (Vector2.Distance(WorldPosition, item.WorldPosition) < maxDist || + if (Vector2.DistanceSquared(WorldPosition, item.WorldPosition) < maxDist*maxDist || item.IsInsideTrigger(WorldPosition)) { return true; @@ -1069,10 +1069,10 @@ namespace Barotrauma { if (c == this || !c.enabled) continue; - if (Vector2.Distance(SimPosition, c.SimPosition) > maxDist) continue; + if (Vector2.DistanceSquared(SimPosition, c.SimPosition) > maxDist*maxDist) continue; - float dist = Vector2.Distance(mouseSimPos, c.SimPosition); - if (dist < maxDist && (closestCharacter==null || dist 1.0f) + if (Lights.LightManager.ViewTarget == this && Vector2.DistanceSquared(AnimController.Limbs[0].SimPosition, mouseSimPos) > 1.0f) { Body body = Submarine.PickBody(AnimController.Limbs[0].SimPosition, mouseSimPos); Structure structure = null; @@ -1177,7 +1177,7 @@ namespace Barotrauma if (closestCharacter != null && closestItem != null) { - if (Vector2.Distance(closestCharacter.SimPosition, mouseSimPos) < ConvertUnits.ToSimUnits(closestItemDist)) + if (Vector2.DistanceSquared(closestCharacter.SimPosition, mouseSimPos) < ConvertUnits.ToSimUnits(closestItemDist)*ConvertUnits.ToSimUnits(closestItemDist)) { if (selectedConstruction != closestItem) closestItem = null; } @@ -1237,6 +1237,14 @@ namespace Barotrauma } } + public static void AddAllToGUIUpdateList() + { + for (int i = 0; i < CharacterList.Count; i++) + { + CharacterList[i].AddToGUIUpdateList(); + } + } + public static void UpdateAll(Camera cam, float deltaTime) { //if (NewCharacterQueue.Count>0) @@ -1250,6 +1258,14 @@ namespace Barotrauma } } + public virtual void AddToGUIUpdateList() + { + if (controlled == this) + { + CharacterHUD.AddToGUIUpdateList(this); + } + } + public virtual void Update(Camera cam, float deltaTime) { if (!Enabled) return; @@ -1540,9 +1556,7 @@ namespace Barotrauma { if (aiTarget == null) return; - aiTarget.SightRange = 0.0f; - - aiTarget.SightRange = Mass*10.0f + AnimController.Collider.LinearVelocity.Length()*500.0f; + aiTarget.SightRange = Mass*100.0f + AnimController.Collider.LinearVelocity.Length()*500.0f; } public void ShowSpeechBubble(float duration, Color color) @@ -1853,7 +1867,6 @@ namespace Barotrauma aiTarget = null; } - foreach (Limb limb in AnimController.Limbs) { if (limb.pullJoint == null) continue; @@ -1905,6 +1918,10 @@ namespace Barotrauma if (aiTarget != null) aiTarget.Remove(); if (AnimController != null) AnimController.Remove(); + + if (Lights.LightManager.ViewTarget == this) Lights.LightManager.ViewTarget = null; + + if (AnimController != null) AnimController.Remove(); } public virtual void ClientWrite(NetBuffer msg, object[] extraData = null) diff --git a/Subsurface/Source/Characters/CharacterHUD.cs b/Subsurface/Source/Characters/CharacterHUD.cs index 179d1fbea..442fc6341 100644 --- a/Subsurface/Source/Characters/CharacterHUD.cs +++ b/Subsurface/Source/Characters/CharacterHUD.cs @@ -32,6 +32,31 @@ namespace Barotrauma damageOverlayTimer = MathHelper.Clamp(amount * 0.1f, 0.2f, 5.0f); } + public static void AddToGUIUpdateList(Character character) + { + if (cprButton != null && cprButton.Visible) cprButton.AddToGUIUpdateList(); + + if (suicideButton != null && suicideButton.Visible) suicideButton.AddToGUIUpdateList(); + + if (!character.IsUnconscious && character.Stun <= 0.0f) + { + + if (character.Inventory != null) + { + for (int i = 0; i < character.Inventory.Items.Length - 1; i++) + { + var item = character.Inventory.Items[i]; + if (item == null || CharacterInventory.limbSlots[i] == InvSlotType.Any) continue; + + foreach (ItemComponent ic in item.components) + { + if (ic.DrawHudWhenEquipped) ic.AddToGUIUpdateList(); + } + } + } + } + } + public static void Update(float deltaTime, Character character) { if (drowningBar != null) @@ -226,7 +251,7 @@ namespace Barotrauma suicideButton.OnClicked = (button, userData) => { - GUIComponent.MouseOn = null; + GUIComponent.ForceMouseOn(null); if (Character.Controlled != null) { Character.Controlled.Kill(Character.Controlled.CauseOfDeath); diff --git a/Subsurface/Source/Characters/CharacterInfo.cs b/Subsurface/Source/Characters/CharacterInfo.cs index 39cdcdf3b..4eada1df1 100644 --- a/Subsurface/Source/Characters/CharacterInfo.cs +++ b/Subsurface/Source/Characters/CharacterInfo.cs @@ -183,7 +183,7 @@ namespace Barotrauma spritePath = spritePath.Replace("[GENDER]", (this.gender == Gender.Female) ? "f" : ""); spritePath = spritePath.Replace("[HEADID]", HeadSpriteId.ToString()); - + string fileName = Path.GetFileNameWithoutExtension(spritePath); //go through the files in the directory to find a matching sprite diff --git a/Subsurface/Source/Characters/Limb.cs b/Subsurface/Source/Characters/Limb.cs index 348c84739..95445a17f 100644 --- a/Subsurface/Source/Characters/Limb.cs +++ b/Subsurface/Source/Characters/Limb.cs @@ -557,12 +557,29 @@ namespace Barotrauma public void Remove() { sprite.Remove(); - if (LightSource != null) LightSource.Remove(); - if (damagedSprite != null) damagedSprite.Remove(); + sprite = null; - body.Remove(); + if (LightSource != null) + { + LightSource.Remove(); + } + if (damagedSprite != null) + { + damagedSprite.Remove(); + damagedSprite = null; + } - if (hitSound != null) hitSound.Remove(); + if (body != null) + { + body.Remove(); + body = null; + } + + if (hitSound != null) + { + hitSound.Remove(); + hitSound = null; + } } } } diff --git a/Subsurface/Source/DebugConsole.cs b/Subsurface/Source/DebugConsole.cs index c21c4158b..4328191d5 100644 --- a/Subsurface/Source/DebugConsole.cs +++ b/Subsurface/Source/DebugConsole.cs @@ -6,6 +6,7 @@ using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Barotrauma.Networking; using Barotrauma.Items.Components; +using System.Text; namespace Barotrauma { @@ -78,6 +79,14 @@ namespace Barotrauma } + public static void AddToGUIUpdateList() + { + if (isOpen) + { + frame.AddToGUIUpdateList(); + } + } + public static void Update(GameMain game, float deltaTime) { if (PlayerInput.KeyHit(Keys.F3)) @@ -89,7 +98,7 @@ namespace Barotrauma } else { - GUIComponent.MouseOn = null; + GUIComponent.ForceMouseOn(null); textBox.Deselect(); } @@ -115,7 +124,6 @@ namespace Barotrauma if (PlayerInput.KeyDown(Keys.Enter) && textBox.Text != "") { - NewMessage(textBox.Text, Color.White); ExecuteCommand(textBox.Text, game); textBox.Text = ""; @@ -157,6 +165,7 @@ namespace Barotrauma case "netstats": case "help": case "dumpids": + case "admin": return true; default: return false; @@ -167,7 +176,11 @@ namespace Barotrauma { if (string.IsNullOrWhiteSpace(command)) return; string[] commands = command.Split(' '); - + + if (!commands[0].ToLowerInvariant().Equals("admin")) + { + NewMessage(textBox.Text, Color.White); + } #if !DEBUG if (GameMain.Client != null && !IsCommandPermitted(commands[0].ToLowerInvariant(), GameMain.Client)) @@ -279,6 +292,8 @@ namespace Barotrauma spawnPoint = WayPoint.GetRandom(commands[1].ToLowerInvariant() == "human" ? SpawnType.Human : SpawnType.Enemy); } + if (string.IsNullOrWhiteSpace(commands[1])) return; + if (spawnPoint != null) spawnPosition = spawnPoint.WorldPosition; if (commands[1].ToLowerInvariant()=="human") @@ -298,7 +313,10 @@ namespace Barotrauma } else { - spawnedCharacter = Character.Create("Content/Characters/" + commands[1] + "/" + commands[1] + ".xml", spawnPosition); + spawnedCharacter = Character.Create( + "Content/Characters/" + + commands[1].First().ToString().ToUpper() + commands[1].Substring(1) + + "/" + commands[1].ToLower() + ".xml", spawnPosition); } if (spawnedCharacter != null && GameMain.Server != null) @@ -361,6 +379,19 @@ namespace Barotrauma case "enablecrewai": HumanAIController.DisableCrewAI = false; break; + /*case "admin": + if (commands.Length < 2) break; + + if (GameMain.Server != null) + { + GameMain.Server.AdminAuthPass = commands[1]; + + } + else if (GameMain.Client != null) + { + GameMain.Client.RequestAdminAuth(commands[1]); + } + break;*/ case "kick": if (GameMain.NetworkMember == null || commands.Length < 2) break; GameMain.NetworkMember.KickPlayer(string.Join(" ", commands.Skip(1)), false); @@ -621,7 +652,7 @@ namespace Barotrauma var wire = item.GetComponent(); if (wire == null) continue; - if (wire.Nodes.Any() && !wire.Connections.Any(c => c != null)) + if (wire.GetNodes().Count > 0 && !wire.Connections.Any(c => c != null)) { wire.Item.Drop(null); DebugConsole.NewMessage("Dropped wire (ID: "+wire.Item.ID+") - attached on wall but no connections found", Color.Orange); diff --git a/Subsurface/Source/EventInput/EventInput.cs b/Subsurface/Source/EventInput/EventInput.cs index 1e51273fa..7965109ad 100644 --- a/Subsurface/Source/EventInput/EventInput.cs +++ b/Subsurface/Source/EventInput/EventInput.cs @@ -6,7 +6,7 @@ using Microsoft.Xna.Framework.Input; namespace EventInput { - +#if WINDOWS public class KeyboardLayout { const uint KLF_ACTIVATE = 1; //activate the layout @@ -16,14 +16,14 @@ namespace EventInput [DllImport("user32.dll")] private static extern long LoadKeyboardLayout( - string pwszKLID, // input locale identifier - uint Flags // input locale identifier options - ); + string pwszKLID, // input locale identifier + uint Flags // input locale identifier options + ); [DllImport("user32.dll")] private static extern long GetKeyboardLayoutName( - StringBuilder pwszKLID //[out] string that receives the name of the locale identifier - ); + StringBuilder pwszKLID //[out] string that receives the name of the locale identifier + ); public static string getName() { @@ -32,6 +32,7 @@ namespace EventInput return name.ToString(); } } +#endif public class CharacterEventArgs : EventArgs { @@ -115,9 +116,12 @@ namespace EventInput /// public static event KeyEventHandler KeyUp; + static bool initialized; + +#if WINDOWS delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); - static bool initialized; + static IntPtr prevWndProc; static WndProc hookProcDelegate; static IntPtr hIMC; @@ -145,7 +149,7 @@ namespace EventInput [DllImport("user32.dll", CharSet = CharSet.Unicode)] static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); - +#endif /// /// Initialize the TextInput with the given GameWindow. @@ -157,15 +161,15 @@ namespace EventInput { return; } - //throw new InvalidOperationException("TextInput.Initialize can only be called once!"); - hookProcDelegate = HookProc; #if WINDOWS - prevWndProc = (IntPtr)SetWindowLong(window.Handle, GWL_WNDPROC, - (int)Marshal.GetFunctionPointerForDelegate(hookProcDelegate)); + hookProcDelegate = HookProc; - hIMC = ImmGetContext(window.Handle); -#elif LINUX + prevWndProc = (IntPtr)SetWindowLong(window.Handle, GWL_WNDPROC, + (int)Marshal.GetFunctionPointerForDelegate(hookProcDelegate)); + + hIMC = ImmGetContext(window.Handle); +#else window.TextInput += ReceiveInput; #endif @@ -181,50 +185,48 @@ namespace EventInput { if (CharEntered != null) CharEntered(null, new CharacterEventArgs(character, 0)); } - +#if WINDOWS static IntPtr HookProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) { - IntPtr returnCode = CallWindowProc(prevWndProc, hWnd, msg, wParam, lParam); + IntPtr returnCode = CallWindowProc(prevWndProc, hWnd, msg, wParam, lParam); - switch (msg) - { - case WM_GETDLGCODE: - returnCode = (IntPtr)(returnCode.ToInt32() | DLGC_WANTALLKEYS); - break; + switch (msg) + { + case WM_GETDLGCODE: + returnCode = (IntPtr)(returnCode.ToInt32() | DLGC_WANTALLKEYS); + break; - case WM_KEYDOWN: - if (KeyDown != null) - KeyDown(null, new KeyEventArgs((Keys)wParam)); + case WM_KEYDOWN: + if (KeyDown != null) + KeyDown(null, new KeyEventArgs((Keys)wParam)); - break; + break; - case WM_KEYUP: - if (KeyUp != null) - KeyUp(null, new KeyEventArgs((Keys)wParam)); - break; + case WM_KEYUP: + if (KeyUp != null) + KeyUp(null, new KeyEventArgs((Keys)wParam)); + break; - case WM_CHAR: - if (CharEntered != null) - CharEntered(null, new CharacterEventArgs((char)wParam, lParam.ToInt32())); - break; + case WM_CHAR: + if (CharEntered != null) + CharEntered(null, new CharacterEventArgs((char)wParam, lParam.ToInt32())); + break; - case WM_IME_SETCONTEXT: - if (wParam.ToInt32() == 1) - ImmAssociateContext(hWnd, hIMC); - break; - - case WM_INPUTLANGCHANGE: - ImmAssociateContext(hWnd, hIMC); - returnCode = (IntPtr)1; - break; - } - - - - return returnCode; + case WM_IME_SETCONTEXT: + if (wParam.ToInt32() == 1) + ImmAssociateContext(hWnd, hIMC); + break; + case WM_INPUTLANGCHANGE: + ImmAssociateContext(hWnd, hIMC); + returnCode = (IntPtr)1; + break; } + + return returnCode; + } + +#endif } - } \ No newline at end of file diff --git a/Subsurface/Source/Events/ArtifactEvent.cs b/Subsurface/Source/Events/ArtifactEvent.cs index 70767c0c5..3cbc2b822 100644 --- a/Subsurface/Source/Events/ArtifactEvent.cs +++ b/Subsurface/Source/Events/ArtifactEvent.cs @@ -1,4 +1,5 @@ using Microsoft.Xna.Framework; +using System; using System.Xml.Linq; namespace Barotrauma @@ -37,6 +38,21 @@ namespace Barotrauma item = new Item(itemPrefab, position, null); item.MoveWithLevel = true; item.body.FarseerBody.IsKinematic = true; + + //try to find a nearby artifact holder (or any alien itemcontainer) and place the artifact inside it + foreach (Item it in Item.ItemList) + { + if (it.Submarine != null || !it.HasTag("alien")) continue; + + if (Math.Abs(item.WorldPosition.X - it.WorldPosition.X) > 2000.0f) continue; + if (Math.Abs(item.WorldPosition.Y - it.WorldPosition.Y) > 2000.0f) continue; + + var itemContainer = it.GetComponent(); + if (itemContainer == null) continue; + + itemContainer.Combine(item); + break; + } } public override void Update(float deltaTime) diff --git a/Subsurface/Source/GUI/GUI.cs b/Subsurface/Source/GUI/GUI.cs index 6fe2dda61..ed3373261 100644 --- a/Subsurface/Source/GUI/GUI.cs +++ b/Subsurface/Source/GUI/GUI.cs @@ -200,6 +200,8 @@ namespace Barotrauma GameMain.NetworkMember = null; } + CoroutineManager.StopCoroutines("EndCinematic"); + GameMain.GameSession = null; GameMain.MainMenuScreen.Select(); @@ -272,16 +274,6 @@ namespace Barotrauma } } - public static void DrawRectangle(SpriteBatch sb, Rectangle rect, Color clr, int thickness, float depth = 0.0f) - { - DrawLine(sb, new Vector2(rect.X, rect.Y), new Vector2(rect.Right, rect.Y), clr, depth, thickness); - DrawLine(sb, new Vector2(rect.X, rect.Bottom-thickness), new Vector2(rect.Right, rect.Bottom-thickness), clr, depth, thickness); - - DrawLine(sb, new Vector2(rect.X+thickness, rect.Y+thickness), new Vector2(rect.X+thickness, rect.Bottom-thickness), clr, depth, thickness); - - DrawLine(sb, new Vector2(rect.Right, rect.Y + thickness), new Vector2(rect.Right, rect.Bottom - thickness), clr, depth, thickness); - } - public static void DrawProgressBar(SpriteBatch sb, Vector2 start, Vector2 size, float progress, Color clr, float depth = 0.0f) { DrawProgressBar(sb, start, size, progress, clr, new Color(0.5f, 0.57f, 0.6f, 1.0f), depth); @@ -428,27 +420,30 @@ namespace Barotrauma if (GameMain.DebugDraw) { - spriteBatch.DrawString(SmallFont, + DrawString(spriteBatch, new Vector2(10, 10), "FPS: " + (int)GameMain.FrameCounter.AverageFramesPerSecond, - new Vector2(10, 10), Color.White); + Color.White, Color.Black * 0.5f, 0, SmallFont); - spriteBatch.DrawString(SmallFont, + DrawString(spriteBatch, new Vector2(10, 20), "Physics: " + GameMain.World.UpdateTime, - new Vector2(10, 20), Color.White); + Color.White, Color.Black * 0.5f, 0, SmallFont); - spriteBatch.DrawString(SmallFont, + DrawString(spriteBatch, new Vector2(10, 30), "Bodies: " + GameMain.World.BodyList.Count + " (" + GameMain.World.BodyList.FindAll(b => b.Awake && b.Enabled).Count + " awake)", - new Vector2(10, 30), Color.White); + Color.White, Color.Black * 0.5f, 0, SmallFont); - spriteBatch.DrawString(SmallFont, - "Camera pos: " + GameMain.GameScreen.Cam.Position.ToPoint(), - new Vector2(10, 40), Color.White); + if (Screen.Selected.Cam != null) + { + DrawString(spriteBatch, new Vector2(10, 40), + "Camera pos: " + Screen.Selected.Cam.Position.ToPoint(), + Color.White, Color.Black * 0.5f, 0, SmallFont); + } if (Submarine.MainSub != null) { - spriteBatch.DrawString(SmallFont, + DrawString(spriteBatch, new Vector2(10, 50), "Sub pos: " + Submarine.MainSub.Position.ToPoint(), - new Vector2(10, 50), Color.White); + Color.White, Color.Black * 0.5f, 0, SmallFont); } for (int i = 1; i < Sounds.SoundManager.DefaultSourceCount; i++) @@ -506,6 +501,28 @@ namespace Barotrauma cursor.Draw(spriteBatch, PlayerInput.LatestMousePosition); } + public static void AddToGUIUpdateList() + { + if (pauseMenuOpen) + { + pauseMenu.AddToGUIUpdateList(); + } + + if (settingsMenuOpen) + { + GameMain.Config.SettingsFrame.AddToGUIUpdateList(); + } + + if (GUIMessageBox.MessageBoxes.Count > 0) + { + var messageBox = GUIMessageBox.MessageBoxes.Peek(); + if (messageBox != null) + { + messageBox.AddToGUIUpdateList(); + } + } + } + public static void Update(float deltaTime) { if (pauseMenuOpen) @@ -523,7 +540,6 @@ namespace Barotrauma var messageBox = GUIMessageBox.MessageBoxes.Peek(); if (messageBox != null) { - GUIComponent.MouseOn = messageBox; messageBox.Update(deltaTime); } } diff --git a/Subsurface/Source/GUI/GUIComponent.cs b/Subsurface/Source/GUI/GUIComponent.cs index f3cabe95b..dc8e9d7cc 100644 --- a/Subsurface/Source/GUI/GUIComponent.cs +++ b/Subsurface/Source/GUI/GUIComponent.cs @@ -10,9 +10,47 @@ namespace Barotrauma public abstract class GUIComponent { const float FlashDuration = 1.5f; - - public static GUIComponent MouseOn; + public static GUIComponent MouseOn + { + get; + private set; + } + public static void ForceMouseOn(GUIComponent c) + { + MouseOn = c; + } + + protected static List ComponentsToUpdate = new List(); + + public virtual void AddToGUIUpdateList() + { + if (!Visible) return; + if (ComponentsToUpdate.Contains(this)) return; + ComponentsToUpdate.Add(this); + children.ForEach(c => c.AddToGUIUpdateList()); + } + + public static void ClearUpdateList() + { + ComponentsToUpdate.Clear(); + } + + public static GUIComponent UpdateMouseOn() + { + MouseOn = null; + for (int i=ComponentsToUpdate.Count-1;i>=0;i--) + { + GUIComponent c = ComponentsToUpdate[i]; + if (c.MouseRect.Contains(PlayerInput.MousePosition)) + { + MouseOn = c; + break; + } + } + return MouseOn; + } + protected static KeyboardDispatcher keyboardDispatcher; public enum ComponentState { None, Hover, Selected}; @@ -97,6 +135,11 @@ namespace Barotrauma } } } + + public virtual Rectangle MouseRect + { + get { return CanBeFocused ? rect : Rectangle.Empty; } + } public List sprites; //public Alignment SpriteAlignment { get; set; } @@ -304,7 +347,7 @@ namespace Barotrauma if (flashTimer>0.0f) flashTimer -= deltaTime; - if (CanBeFocused) + /*if (CanBeFocused) { if (rect.Contains(PlayerInput.MousePosition)) { @@ -315,7 +358,7 @@ namespace Barotrauma if (MouseOn == this) MouseOn = null; } - } + }*/ //use a fixed list since children can change their order in the main children list //TODO: maybe find a more efficient way of handling changes in list order diff --git a/Subsurface/Source/GUI/GUIDropDown.cs b/Subsurface/Source/GUI/GUIDropDown.cs index b88afd7c9..a3fc5d5d3 100644 --- a/Subsurface/Source/GUI/GUIDropDown.cs +++ b/Subsurface/Source/GUI/GUIDropDown.cs @@ -166,6 +166,13 @@ namespace Barotrauma return true; } + public override void AddToGUIUpdateList() + { + base.AddToGUIUpdateList(); + button.AddToGUIUpdateList(); + if (Dropped) listBox.AddToGUIUpdateList(); + } + public override void Update(float deltaTime) { if (!Visible) return; diff --git a/Subsurface/Source/GUI/GUIFrame.cs b/Subsurface/Source/GUI/GUIFrame.cs index c3adb43db..bf15905f6 100644 --- a/Subsurface/Source/GUI/GUIFrame.cs +++ b/Subsurface/Source/GUI/GUIFrame.cs @@ -36,7 +36,7 @@ namespace Barotrauma //if (style != null) ApplyStyle(style); } - + public override void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch) { if (!Visible) return; diff --git a/Subsurface/Source/GUI/GUIListBox.cs b/Subsurface/Source/GUI/GUIListBox.cs index 2fa4ea438..1d235d7e9 100644 --- a/Subsurface/Source/GUI/GUIListBox.cs +++ b/Subsurface/Source/GUI/GUIListBox.cs @@ -264,6 +264,20 @@ namespace Barotrauma } } + public override void AddToGUIUpdateList() + { + base.AddToGUIUpdateList(); + if (scrollBarEnabled && !scrollBarHidden) scrollBar.AddToGUIUpdateList(); + } + + public override Rectangle MouseRect + { + get + { + return Rectangle.Empty; + } + } + public override void Update(float deltaTime) { if (!Visible) return; diff --git a/Subsurface/Source/GUI/GUIStyle.cs b/Subsurface/Source/GUI/GUIStyle.cs index ea137a4ab..5fdc59c7d 100644 --- a/Subsurface/Source/GUI/GUIStyle.cs +++ b/Subsurface/Source/GUI/GUIStyle.cs @@ -14,7 +14,11 @@ namespace Barotrauma componentStyles = new Dictionary(); XDocument doc; - try { doc = XDocument.Load(file); } + try + { + ToolBox.IsProperFilenameCase(file); + doc = XDocument.Load(file); + } catch (Exception e) { DebugConsole.ThrowError("Loading style \"" + file + "\" failed", e); diff --git a/Subsurface/Source/GUI/GUITickBox.cs b/Subsurface/Source/GUI/GUITickBox.cs index 4421ef9c9..8ed501baa 100644 --- a/Subsurface/Source/GUI/GUITickBox.cs +++ b/Subsurface/Source/GUI/GUITickBox.cs @@ -55,6 +55,11 @@ namespace Barotrauma } } + public override Rectangle MouseRect + { + get { return box.Rect; } + } + public GUITickBox(Rectangle rect, string label, Alignment alignment, GUIComponent parent) : this(rect, label, alignment, GUI.Font, parent) { @@ -69,6 +74,7 @@ namespace Barotrauma box = new GUIFrame(rect, Color.DarkGray, null, this); box.HoverColor = Color.Gray; box.SelectedColor = Color.DarkGray; + box.CanBeFocused = false; text = new GUITextBlock(new Rectangle(rect.Right + 10, rect.Y+2, 20, rect.Height), label, GUI.Style, this, font); @@ -76,19 +82,19 @@ namespace Barotrauma Enabled = true; } - + public override void Update(float deltaTime) { if (!Visible || !Enabled) return; - if (MouseOn != null && MouseOn != this && !MouseOn.IsParentOf(this)) return; + //if (MouseOn != null && MouseOn != this && !MouseOn.IsParentOf(this)) return; - if (text.Rect.Contains(PlayerInput.MousePosition)) MouseOn = this; + //if (text.Rect.Contains(PlayerInput.MousePosition)) MouseOn = this; - if (box.Rect.Contains(PlayerInput.MousePosition)) + if (MouseOn==this)//box.Rect.Contains(PlayerInput.MousePosition)) { //ToolTip = this.ToolTip; - MouseOn = this; + //MouseOn = this; box.State = ComponentState.Hover; diff --git a/Subsurface/Source/GameMain.cs b/Subsurface/Source/GameMain.cs index 558816a71..d0c7fc0a4 100644 --- a/Subsurface/Source/GameMain.cs +++ b/Subsurface/Source/GameMain.cs @@ -330,10 +330,26 @@ namespace Barotrauma if (PlayerInput.KeyHit(Keys.Escape)) GUI.TogglePauseMenu(); - DebugConsole.Update(this, (float)Timing.Step); + GUIComponent.ClearUpdateList(); + DebugConsole.AddToGUIUpdateList(); paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen) && (NetworkMember == null || !NetworkMember.GameStarted); + + if (!paused) + { + Screen.Selected.AddToGUIUpdateList(); + } + + if (NetworkMember != null) + { + NetworkMember.AddToGUIUpdateList(); + } + + GUI.AddToGUIUpdateList(); + GUIComponent.UpdateMouseOn(); + + DebugConsole.Update(this, (float)Timing.Step); if (!paused) { @@ -374,6 +390,14 @@ namespace Barotrauma { Screen.Selected.Draw(deltaTime, GraphicsDevice, spriteBatch); } + + if (!DebugDraw) return; + if (GUIComponent.MouseOn!=null) + { + spriteBatch.Begin(); + GUI.DrawRectangle(spriteBatch, GUIComponent.MouseOn.MouseRect, Color.Lime); + spriteBatch.End(); + } } static bool waitForKeyHit = true; diff --git a/Subsurface/Source/GameSession/CrewManager.cs b/Subsurface/Source/GameSession/CrewManager.cs index 8315d18e3..4d2024d0c 100644 --- a/Subsurface/Source/GameSession/CrewManager.cs +++ b/Subsurface/Source/GameSession/CrewManager.cs @@ -157,6 +157,13 @@ namespace Barotrauma //new GUIImage(new Rectangle(-10, -5, 0, 0), character.AnimController.Limbs[0].sprite, Alignment.Left, frame); } + public void AddToGUIUpdateList() + { + guiFrame.AddToGUIUpdateList(); + if (commander.Frame != null) commander.Frame.AddToGUIUpdateList(); + if (crewFrameOpen) crewFrame.AddToGUIUpdateList(); + } + public void Update(float deltaTime) { guiFrame.Update(deltaTime); diff --git a/Subsurface/Source/GameSession/GameModes/GameMode.cs b/Subsurface/Source/GameSession/GameModes/GameMode.cs index 34ca97f4d..ae25c4ef2 100644 --- a/Subsurface/Source/GameSession/GameModes/GameMode.cs +++ b/Subsurface/Source/GameSession/GameModes/GameMode.cs @@ -77,6 +77,8 @@ namespace Barotrauma public virtual void MsgBox() { } + public virtual void AddToGUIUpdateList() { } + public virtual void Update(float deltaTime) { //if (!isRunning) return; diff --git a/Subsurface/Source/GameSession/GameModes/SinglePlayerMode.cs b/Subsurface/Source/GameSession/GameModes/SinglePlayerMode.cs index a176b3ac3..5d26ecd4f 100644 --- a/Subsurface/Source/GameSession/GameModes/SinglePlayerMode.cs +++ b/Subsurface/Source/GameSession/GameModes/SinglePlayerMode.cs @@ -215,6 +215,17 @@ namespace Barotrauma endShiftButton.Draw(spriteBatch); } + public override void AddToGUIUpdateList() + { + if (!isRunning) return; + + base.AddToGUIUpdateList(); + + CrewManager.AddToGUIUpdateList(); + + endShiftButton.AddToGUIUpdateList(); + } + public override void Update(float deltaTime) { if (!isRunning) return; @@ -357,7 +368,7 @@ namespace Barotrauma SoundPlayer.OverrideMusicType = CrewManager.characters.Any(c => !c.IsDead) ? "endshift" : "crewdead"; - CoroutineManager.StartCoroutine(EndCinematic(cinematic)); + CoroutineManager.StartCoroutine(EndCinematic(cinematic),"EndCinematic"); return true; } diff --git a/Subsurface/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs b/Subsurface/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs index d48bb1f80..f4f5bfd89 100644 --- a/Subsurface/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs +++ b/Subsurface/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs @@ -289,7 +289,10 @@ namespace Barotrauma.Tutorials } yield return new WaitForSeconds(1.0f); - var moloch = Character.Create("Content/Characters/Moloch/moloch.xml", steering.Item.WorldPosition + Vector2.UnitX * 3000.0f); + var moloch = Character.Create( + "Content/Characters/Moloch/moloch.xml", + steering.Item.WorldPosition + new Vector2(3000.0f, -500.0f)); + moloch.PlaySound(AIController.AiState.Attack); yield return new WaitForSeconds(1.0f); @@ -304,21 +307,20 @@ namespace Barotrauma.Tutorials if (s.Rect.Right > steering.Item.CurrentHull.Rect.Right) windows.Add(s); } + float slowdownTimer = 1.0f; bool broken = false; do { - Submarine.MainSub.Velocity = Vector2.Zero; + steering.TargetVelocity = Vector2.Zero; + + slowdownTimer = Math.Max(0.0f, slowdownTimer - CoroutineManager.DeltaTime*0.3f); + Submarine.MainSub.Velocity *= slowdownTimer; moloch.AIController.SelectTarget(steering.Item.CurrentHull.AiTarget); Vector2 steeringDir = windows[0].WorldPosition - moloch.WorldPosition; if (steeringDir != Vector2.Zero) steeringDir = Vector2.Normalize(steeringDir); - //foreach (Limb limb in moloch.AnimController.Limbs) - //{ - // limb.body.LinearVelocity = new Vector2(limb.LinearVelocity.X*2.0f, limb.LinearVelocity.Y + steeringDir.Y*10.0f); - //} - - moloch.AIController.Steering = steeringDir; + moloch.AIController.SteeringManager.SteeringManual(CoroutineManager.DeltaTime, steeringDir*100.0f); foreach (Structure window in windows) { @@ -332,7 +334,7 @@ namespace Barotrauma.Tutorials } - yield return new WaitForSeconds(0.1f); + yield return CoroutineStatus.Running; } while (!broken); //fix everything except the command windows @@ -346,13 +348,13 @@ namespace Barotrauma.Tutorials if (isWindow) { - w.AddDamage(i, -w.SectionDamage(i) * 0.2f); + //decrease window damage to slow down the leaking + w.AddDamage(i, -w.SectionDamage(i) * 0.495f); } else { w.AddDamage(i, -100000.0f); } - } } @@ -368,11 +370,16 @@ namespace Barotrauma.Tutorials Door commandDoor2 = Item.ItemList.Find(i => i.HasTag("commanddoor2")).GetComponent(); Door commandDoor3 = Item.ItemList.Find(i => i.HasTag("commanddoor3")).GetComponent(); - while (commandDoor1.IsOpen || (commandDoor2.IsOpen || commandDoor3.IsOpen)) + //wait until the player is out of the room and the doors are closed + while (Character.Controlled.WorldPosition.X > commandDoor1.Item.WorldPosition.X || + (commandDoor1.IsOpen || (commandDoor2.IsOpen || commandDoor3.IsOpen))) { + //prevent the hull from filling up completely and crushing the player + steering.Item.CurrentHull.Volume = Math.Min(steering.Item.CurrentHull.Volume, steering.Item.CurrentHull.FullVolume * 0.9f); yield return CoroutineStatus.Running; } + infoBox = CreateInfoFrame("You should quickly find yourself a diving mask or a diving suit. " + "There are some in the room next to the airlock."); @@ -452,7 +459,7 @@ namespace Barotrauma.Tutorials yield return CoroutineStatus.Running; } - moloch.AnimController.SetPosition(ConvertUnits.ToSimUnits(Character.Controlled.WorldPosition + Vector2.UnitY * 1000.0f)); + moloch.AnimController.SetPosition(ConvertUnits.ToSimUnits(Character.Controlled.WorldPosition + Vector2.UnitY * 600.0f)); infoBox = CreateInfoFrame("Now we're ready to shoot! Select the railgun controller."); @@ -466,6 +473,7 @@ namespace Barotrauma.Tutorials while (!moloch.IsDead) { + moloch.AIController.SelectTarget(Character.Controlled.AiTarget); yield return CoroutineStatus.Running; } diff --git a/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialMode.cs b/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialMode.cs index 7e59a33a6..9828e2dd4 100644 --- a/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialMode.cs +++ b/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialMode.cs @@ -27,6 +27,11 @@ namespace Barotrauma } + public override void AddToGUIUpdateList() + { + tutorialType.AddToGUIUpdateList(); + } + public override void Update(float deltaTime) { base.Update(deltaTime); diff --git a/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialType.cs b/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialType.cs index d84ef4968..a46777f2a 100644 --- a/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialType.cs +++ b/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialType.cs @@ -75,6 +75,11 @@ namespace Barotrauma.Tutorials CoroutineManager.StartCoroutine(UpdateState()); } + public virtual void AddToGUIUpdateList() + { + if (infoBox != null) infoBox.AddToGUIUpdateList(); + } + public virtual void Update(float deltaTime) { if (character!=null) diff --git a/Subsurface/Source/GameSession/GameSession.cs b/Subsurface/Source/GameSession/GameSession.cs index bf5e06adc..6f4bf4cf9 100644 --- a/Subsurface/Source/GameSession/GameSession.cs +++ b/Subsurface/Source/GameSession/GameSession.cs @@ -161,7 +161,7 @@ namespace Barotrauma } } - public void StartShift(string levelSeed, bool loadSecondSub = true) + public void StartShift(string levelSeed, bool loadSecondSub = false) { Level level = Level.CreateRandom(levelSeed); @@ -362,6 +362,17 @@ namespace Barotrauma } + public void AddToGUIUpdateList() + { + if (CrewManager != null) CrewManager.AddToGUIUpdateList(); + + if (gameMode != null) gameMode.AddToGUIUpdateList(); + + infoButton.AddToGUIUpdateList(); + + if (infoFrame != null) infoFrame.AddToGUIUpdateList(); + } + public void Update(float deltaTime) { TaskManager.Update(deltaTime); diff --git a/Subsurface/Source/Items/Components/Door.cs b/Subsurface/Source/Items/Components/Door.cs index 99ea03b1c..fc2e60560 100644 --- a/Subsurface/Source/Items/Components/Door.cs +++ b/Subsurface/Source/Items/Components/Door.cs @@ -1,13 +1,15 @@ -using System; -using System.IO; -using System.Xml.Linq; +using Barotrauma.Lights; +using Barotrauma.Networking; using FarseerPhysics; using FarseerPhysics.Dynamics; -using FarseerPhysics.Factories; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; -using Barotrauma.Lights; -using Barotrauma.Networking; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; + namespace Barotrauma.Items.Components { @@ -410,50 +412,53 @@ namespace Barotrauma.Items.Components { int dir = isHorizontal ? Math.Sign(c.SimPosition.Y - item.SimPosition.Y) : Math.Sign(c.SimPosition.X - item.SimPosition.X); - foreach (Limb l in c.AnimController.Limbs) + List bodies = c.AnimController.Limbs.Select(l => l.body).ToList(); + bodies.Add(c.AnimController.Collider); + + foreach (PhysicsBody body in bodies) { float diff = 0.0f; if (isHorizontal) { - if (l.SimPosition.X < simPos.X || l.SimPosition.X > simPos.X + simSize.X) continue; + if (body.SimPosition.X < simPos.X || body.SimPosition.X > simPos.X + simSize.X) continue; - diff = l.SimPosition.Y - item.SimPosition.Y; + diff = body.SimPosition.Y - item.SimPosition.Y; } else { - if (l.SimPosition.Y > simPos.Y || l.SimPosition.Y < simPos.Y - simSize.Y) continue; + if (body.SimPosition.Y > simPos.Y || body.SimPosition.Y < simPos.Y - simSize.Y) continue; - diff = l.SimPosition.X - item.SimPosition.X; + diff = body.SimPosition.X - item.SimPosition.X; } if (Math.Sign(diff) != dir) { - SoundPlayer.PlayDamageSound(DamageSoundType.LimbBlunt, 1.0f, l.body); + SoundPlayer.PlayDamageSound(DamageSoundType.LimbBlunt, 1.0f, body); if (isHorizontal) { - l.body.SetTransform(new Vector2(l.SimPosition.X, item.SimPosition.Y + dir * simSize.Y * 2.0f), l.body.Rotation); - l.body.ApplyLinearImpulse(new Vector2(isOpen ? 0.0f : 1.0f, dir * 2.0f)); + body.SetTransform(new Vector2(body.SimPosition.X, item.SimPosition.Y + dir * simSize.Y * 2.0f), body.Rotation); + body.ApplyLinearImpulse(new Vector2(isOpen ? 0.0f : 1.0f, dir * 2.0f)); } else { - l.body.SetTransform(new Vector2(item.SimPosition.X + dir * simSize.X * 1.2f, l.SimPosition.Y), l.body.Rotation); - l.body.ApplyLinearImpulse(new Vector2(dir * 0.5f, isOpen ? 0.0f : -1.0f)); + body.SetTransform(new Vector2(item.SimPosition.X + dir * simSize.X * 1.2f, body.SimPosition.Y), body.Rotation); + body.ApplyLinearImpulse(new Vector2(dir * 0.5f, isOpen ? 0.0f : -1.0f)); } } if (isHorizontal) { - if (Math.Abs(l.SimPosition.Y - item.SimPosition.Y) > simSize.Y * 0.5f) continue; + if (Math.Abs(body.SimPosition.Y - item.SimPosition.Y) > simSize.Y * 0.5f) continue; - l.body.ApplyLinearImpulse(new Vector2(isOpen ? 0.0f : 1.0f, dir * 0.5f)); + body.ApplyLinearImpulse(new Vector2(isOpen ? 0.0f : 1.0f, dir * 0.5f)); } else { - if (Math.Abs(l.SimPosition.X - item.SimPosition.X) > simSize.X * 0.5f) continue; + if (Math.Abs(body.SimPosition.X - item.SimPosition.X) > simSize.X * 0.5f) continue; - l.body.ApplyLinearImpulse(new Vector2(dir * 0.5f, isOpen ? 0.0f : -1.0f)); + body.ApplyLinearImpulse(new Vector2(dir * 0.5f, isOpen ? 0.0f : -1.0f)); } c.StartStun(0.2f); diff --git a/Subsurface/Source/Items/Components/Holdable/Pickable.cs b/Subsurface/Source/Items/Components/Holdable/Pickable.cs index 4c3a0d16a..bb6575bc2 100644 --- a/Subsurface/Source/Items/Components/Holdable/Pickable.cs +++ b/Subsurface/Source/Items/Components/Holdable/Pickable.cs @@ -102,10 +102,8 @@ namespace Barotrauma.Items.Components var leftHand = picker.AnimController.GetLimb(LimbType.LeftHand); var rightHand = picker.AnimController.GetLimb(LimbType.RightHand); - Drawable = true; - pickTimer = 0.0f; - while (pickTimer < requiredTime) + while (pickTimer < requiredTime && Screen.Selected != GameMain.EditMapScreen) { if (picker.IsKeyDown(InputType.Aim) || !item.IsInPickRange(picker.WorldPosition) || @@ -115,7 +113,6 @@ namespace Barotrauma.Items.Components yield return CoroutineStatus.Success; } - picker.UpdateHUDProgressBar( this, item.WorldPosition, @@ -148,8 +145,6 @@ namespace Barotrauma.Items.Components private void StopPicking(Character picker) { - Drawable = false; - picker.AnimController.Anim = AnimController.Animation.None; pickTimer = 0.0f; } diff --git a/Subsurface/Source/Items/Components/ItemComponent.cs b/Subsurface/Source/Items/Components/ItemComponent.cs index 470915355..964c6edd6 100644 --- a/Subsurface/Source/Items/Components/ItemComponent.cs +++ b/Subsurface/Source/Items/Components/ItemComponent.cs @@ -123,17 +123,22 @@ namespace Barotrauma.Items.Components set { if (value == drawable) return; + if (!(this is IDrawableComponent)) + { + DebugConsole.ThrowError("Couldn't make \""+this+"\" drawable (the component doesn't implement the IDrawableComponent interface)"); + return; + } + drawable = value; if (drawable) { - if (!item.drawableComponents.Contains(this as IDrawableComponent)) - item.drawableComponents.Add(this as IDrawableComponent); + if (!item.drawableComponents.Contains((IDrawableComponent)this)) + item.drawableComponents.Add((IDrawableComponent)this); } else { - item.drawableComponents.Remove(this as IDrawableComponent); - } - + item.drawableComponents.Remove((IDrawableComponent)this); + } } } @@ -470,6 +475,8 @@ namespace Barotrauma.Items.Components public virtual void DrawHUD(SpriteBatch spriteBatch, Character character) { } + public virtual void AddToGUIUpdateList() { } + public virtual void UpdateHUD(Character character) { } /// true if the operation was completed diff --git a/Subsurface/Source/Items/Components/Machines/Deconstructor.cs b/Subsurface/Source/Items/Components/Machines/Deconstructor.cs index 44ac51a75..716dfe503 100644 --- a/Subsurface/Source/Items/Components/Machines/Deconstructor.cs +++ b/Subsurface/Source/Items/Components/Machines/Deconstructor.cs @@ -85,6 +85,11 @@ namespace Barotrauma.Items.Components GuiFrame.Draw(spriteBatch); } + public override void AddToGUIUpdateList() + { + GuiFrame.AddToGUIUpdateList(); + } + public override void UpdateHUD(Character character) { GuiFrame.Update((float)Timing.Step); diff --git a/Subsurface/Source/Items/Components/Machines/Engine.cs b/Subsurface/Source/Items/Components/Machines/Engine.cs index 2be57d639..337fa286c 100644 --- a/Subsurface/Source/Items/Components/Machines/Engine.cs +++ b/Subsurface/Source/Items/Components/Machines/Engine.cs @@ -114,7 +114,11 @@ namespace Barotrauma.Items.Components //GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black, true); spriteBatch.DrawString(GUI.Font, "Force: " + (int)(targetForce) + " %", new Vector2(GuiFrame.Rect.X + 30, GuiFrame.Rect.Y + 30), Color.White); - + } + + public override void AddToGUIUpdateList() + { + GuiFrame.AddToGUIUpdateList(); } public override void UpdateHUD(Character character) diff --git a/Subsurface/Source/Items/Components/Machines/Fabricator.cs b/Subsurface/Source/Items/Components/Machines/Fabricator.cs index 80d511023..b14ad084a 100644 --- a/Subsurface/Source/Items/Components/Machines/Fabricator.cs +++ b/Subsurface/Source/Items/Components/Machines/Fabricator.cs @@ -379,6 +379,11 @@ namespace Barotrauma.Items.Components GuiFrame.Draw(spriteBatch); } + public override void AddToGUIUpdateList() + { + GuiFrame.AddToGUIUpdateList(); + } + public override void UpdateHUD(Character character) { FabricableItem targetItem = itemList.SelectedData as FabricableItem; diff --git a/Subsurface/Source/Items/Components/Machines/MiniMap.cs b/Subsurface/Source/Items/Components/Machines/MiniMap.cs index 784d44f0b..c98f1e07d 100644 --- a/Subsurface/Source/Items/Components/Machines/MiniMap.cs +++ b/Subsurface/Source/Items/Components/Machines/MiniMap.cs @@ -190,7 +190,7 @@ namespace Barotrauma.Items.Components Color.Black * 0.5f, 2, GUI.SmallFont); } - GUI.DrawRectangle(spriteBatch, hullRect, borderColor, 2); + GUI.DrawRectangle(spriteBatch, hullRect, borderColor, false, 0.0f, 2); } } diff --git a/Subsurface/Source/Items/Components/Machines/Pump.cs b/Subsurface/Source/Items/Components/Machines/Pump.cs index 6c5448bcc..97911bfa5 100644 --- a/Subsurface/Source/Items/Components/Machines/Pump.cs +++ b/Subsurface/Source/Items/Components/Machines/Pump.cs @@ -185,6 +185,11 @@ namespace Barotrauma.Items.Components } + public override void AddToGUIUpdateList() + { + GuiFrame.AddToGUIUpdateList(); + } + public override void UpdateHUD(Character character) { GuiFrame.Update(1.0f / 60.0f); diff --git a/Subsurface/Source/Items/Components/Machines/Radar.cs b/Subsurface/Source/Items/Components/Machines/Radar.cs index 7e4ca4c6e..c1903dbc3 100644 --- a/Subsurface/Source/Items/Components/Machines/Radar.cs +++ b/Subsurface/Source/Items/Components/Machines/Radar.cs @@ -70,6 +70,7 @@ namespace Barotrauma.Items.Components return true; }; + GuiFrame.CanBeFocused = false; } public override void Update(float deltaTime, Camera cam) @@ -108,6 +109,11 @@ namespace Barotrauma.Items.Components return pingState > 1.0f; } + public override void AddToGUIUpdateList() + { + GuiFrame.AddToGUIUpdateList(); + } + public override void UpdateHUD(Character character) { GuiFrame.Update((float)Timing.Step); diff --git a/Subsurface/Source/Items/Components/Machines/Reactor.cs b/Subsurface/Source/Items/Components/Machines/Reactor.cs index 6af7a0514..fff852a7b 100644 --- a/Subsurface/Source/Items/Components/Machines/Reactor.cs +++ b/Subsurface/Source/Items/Components/Machines/Reactor.cs @@ -487,6 +487,11 @@ namespace Barotrauma.Items.Components //y = y - 260; } + public override void AddToGUIUpdateList() + { + GuiFrame.AddToGUIUpdateList(); + } + public override void UpdateHUD(Character character) { GuiFrame.Update(1.0f / 60.0f); diff --git a/Subsurface/Source/Items/Components/Machines/Steering.cs b/Subsurface/Source/Items/Components/Machines/Steering.cs index a3ea3d2f8..3b198e660 100644 --- a/Subsurface/Source/Items/Components/Machines/Steering.cs +++ b/Subsurface/Source/Items/Components/Machines/Steering.cs @@ -223,20 +223,28 @@ namespace Barotrauma.Items.Components if (Vector2.Distance(PlayerInput.MousePosition, new Vector2(velRect.Center.X, velRect.Center.Y)) < 200.0f) { GUI.DrawRectangle(spriteBatch, new Rectangle((int)targetVelPos.X -10, (int)targetVelPos.Y - 10, 20, 20), Color.Red); - - if (PlayerInput.LeftButtonHeld()) - { - TargetVelocity = PlayerInput.MousePosition - new Vector2(velRect.Center.X, velRect.Center.Y); - targetVelocity.Y = -targetVelocity.Y; - - unsentChanges = true; - } } } + public override void AddToGUIUpdateList() + { + GuiFrame.AddToGUIUpdateList(); + } + public override void UpdateHUD(Character character) { GuiFrame.Update(1.0f / 60.0f); + + if (Vector2.Distance(PlayerInput.MousePosition, new Vector2(GuiFrame.Rect.Center.X, GuiFrame.Rect.Center.Y)) < 200.0f) + { + if (PlayerInput.LeftButtonHeld()) + { + TargetVelocity = PlayerInput.MousePosition - new Vector2(GuiFrame.Rect.Center.X, GuiFrame.Rect.Center.Y); + targetVelocity.Y = -targetVelocity.Y; + + unsentChanges = true; + } + } } private void UpdateAutoPilot(float deltaTime) @@ -433,10 +441,10 @@ namespace Barotrauma.Items.Components maintainPosTickBox.Selected = false; posToMaintain = null; + tickBox.Selected = true; UpdatePath(); - tickBox.Selected = true; return true; } diff --git a/Subsurface/Source/Items/Components/Power/PowerContainer.cs b/Subsurface/Source/Items/Components/Power/PowerContainer.cs index cf0f62bba..0982f8982 100644 --- a/Subsurface/Source/Items/Components/Power/PowerContainer.cs +++ b/Subsurface/Source/Items/Components/Power/PowerContainer.cs @@ -82,21 +82,22 @@ namespace Barotrauma.Items.Components IsActive = true; - var button = new GUIButton(new Rectangle(160, 50, 30,30), "-", GUI.Style, GuiFrame); - button.OnClicked = (GUIButton btn, object obj) => + if (canBeSelected) { - RechargeSpeed = Math.Max(rechargeSpeed - maxRechargeSpeed * 0.1f, 0.0f); + var button = new GUIButton(new Rectangle(160, 50, 30,30), "-", GUI.Style, GuiFrame); + button.OnClicked = (GUIButton btn, object obj) => + { + RechargeSpeed = Math.Max(rechargeSpeed - maxRechargeSpeed * 0.1f, 0.0f); + return true; + }; - return true; - }; - - button = new GUIButton(new Rectangle(200, 50, 30, 30), "+", GUI.Style, GuiFrame); - button.OnClicked = (GUIButton btn, object obj) => - { - RechargeSpeed = Math.Max(rechargeSpeed + maxRechargeSpeed * 0.1f, 0.0f); - - return true; - }; + button = new GUIButton(new Rectangle(200, 50, 30, 30), "+", GUI.Style, GuiFrame); + button.OnClicked = (GUIButton btn, object obj) => + { + RechargeSpeed = Math.Max(rechargeSpeed + maxRechargeSpeed * 0.1f, 0.0f); + return true; + }; + } } public override bool Pick(Character picker) @@ -165,28 +166,18 @@ namespace Barotrauma.Items.Components return; } - //currPowerConsumption = MathHelper.Lerp( - // currPowerConsumption, - // -maxOutput * chargeRate, - // 0.1f); - if (gridPower < gridLoad) { - // CurrPowerOutput = MathHelper.Lerp( - //CurrPowerOutput, Math.Min(maxOutput * chargeRate, gridLoad), 0.05f); - CurrPowerOutput = MathHelper.Lerp( CurrPowerOutput, - Math.Min(maxOutput * chargeRatio, gridLoad - (gridLoad * outputVoltage)), - 0.05f); + Math.Min(maxOutput * chargeRatio, gridLoad), + deltaTime); } else { - CurrPowerOutput = MathHelper.Lerp(CurrPowerOutput, 0.0f, 0.05f); + CurrPowerOutput = MathHelper.Lerp(CurrPowerOutput, 0.0f, deltaTime); } - - //powerConsumption = Math.Min(powerConsumption, 0.0f); Charge -= CurrPowerOutput / 3600.0f; } @@ -244,6 +235,11 @@ namespace Barotrauma.Items.Components spriteBatch.DrawString(GUI.Font, "Recharge rate: " + (int)((rechargeSpeed / maxRechargeSpeed) * 100.0f) + " %", new Vector2(x + 30, y + 95), Color.White); } + public override void AddToGUIUpdateList() + { + GuiFrame.AddToGUIUpdateList(); + } + public override void UpdateHUD(Character character) { GuiFrame.Update(1.0f / 60.0f); diff --git a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs index d7257c601..e8bae85b8 100644 --- a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs +++ b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs @@ -54,10 +54,11 @@ namespace Barotrauma.Items.Components //by the constructions connected to the grid fullPower = 0.0f; fullLoad = 0.0f; - updateTimer = 0; + connectedList.Clear(); CheckJunctions(deltaTime); + updateTimer = 0; foreach (Powered p in connectedList) { @@ -180,6 +181,11 @@ namespace Barotrauma.Items.Components spriteBatch.DrawString(GUI.Font, "Load: " + (int)powerLoad + " kW", new Vector2(x + 30, y + 100), Color.White); } + public override void AddToGUIUpdateList() + { + GuiFrame.AddToGUIUpdateList(); + } + public override void UpdateHUD(Character character) { GuiFrame.Update(1.0f / 60.0f); diff --git a/Subsurface/Source/Items/Components/Signal/Connection.cs b/Subsurface/Source/Items/Components/Signal/Connection.cs index bd31e328a..1b9d048ac 100644 --- a/Subsurface/Source/Items/Components/Signal/Connection.cs +++ b/Subsurface/Source/Items/Components/Signal/Connection.cs @@ -24,7 +24,7 @@ namespace Barotrauma.Items.Components private Item item; public readonly bool IsOutput; - + private static Wire draggingConnected; private List effects; @@ -433,8 +433,7 @@ namespace Barotrauma.Items.Components { if (mouseOn) { - item.IsHighlighted = true; - wire.Item.IsHighlighted = true; + ConnectionPanel.HighlightedWire = wire; if (!wire.Locked) { diff --git a/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs b/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs index 51cc37bd2..7566f35ad 100644 --- a/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs +++ b/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs @@ -7,7 +7,9 @@ using System.Xml.Linq; namespace Barotrauma.Items.Components { class ConnectionPanel : ItemComponent - { + { + public static Wire HighlightedWire; + public List Connections; Character user; @@ -33,15 +35,29 @@ namespace Barotrauma.Items.Components IsActive = true; } - public override void DrawHUD(SpriteBatch spriteBatch, Character character) + public override void UpdateHUD(Character character) { if (character != Character.Controlled || character != user) return; if (Screen.Selected != GameMain.EditMapScreen && - character.IsKeyHit(InputType.Select) && - character.SelectedConstruction==this.item) character.SelectedConstruction = null; - + character.IsKeyHit(InputType.Select) && + character.SelectedConstruction == this.item) character.SelectedConstruction = null; + + if (HighlightedWire != null) + { + HighlightedWire.Item.IsHighlighted = true; + if (HighlightedWire.Connections[0] != null && HighlightedWire.Connections[0].Item != null) HighlightedWire.Connections[0].Item.IsHighlighted = true; + if (HighlightedWire.Connections[1] != null && HighlightedWire.Connections[1].Item != null) HighlightedWire.Connections[1].Item.IsHighlighted = true; + } + } + + public override void DrawHUD(SpriteBatch spriteBatch, Character character) + { + if (character != Character.Controlled || character != user) return; + + HighlightedWire = null; Connection.DrawConnections(spriteBatch, this, character); + } public override XElement Save(XElement parentElement) diff --git a/Subsurface/Source/Items/Components/Signal/Wire.cs b/Subsurface/Source/Items/Components/Signal/Wire.cs index 8681e2b01..75c674380 100644 --- a/Subsurface/Source/Items/Components/Signal/Wire.cs +++ b/Subsurface/Source/Items/Components/Signal/Wire.cs @@ -56,8 +56,7 @@ namespace Barotrauma.Items.Components static Sprite wireSprite; - public List Nodes; - + private List nodes; private List sections; Connection[] connections; @@ -83,7 +82,7 @@ namespace Barotrauma.Items.Components wireSprite.Depth = 0.85f; } - Nodes = new List(); + nodes = new List(); sections = new List(); connections = new Connection[2]; @@ -159,17 +158,17 @@ namespace Barotrauma.Items.Components if (newConnection.Item.Submarine == null) continue; - if (Nodes.Count > 0 && Nodes[0] == newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition) break; - if (Nodes.Count > 1 && Nodes[Nodes.Count-1] == newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition) break; + if (nodes.Count > 0 && nodes[0] == newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition) break; + if (nodes.Count > 1 && nodes[nodes.Count-1] == newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition) break; if (i == 0) { - Nodes.Insert(0, newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition); + nodes.Insert(0, newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition); } else { - Nodes.Add(newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition); + nodes.Add(newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition); } @@ -192,7 +191,7 @@ namespace Barotrauma.Items.Components CleanNodes(); } - Drawable = Nodes.Any(); + Drawable = nodes.Any(); UpdateSections(); return true; @@ -222,7 +221,7 @@ namespace Barotrauma.Items.Components public override void Update(float deltaTime, Camera cam) { - if (Nodes.Count == 0) return; + if (nodes.Count == 0) return; Submarine sub = null; if (connections[0] != null && connections[0].Item.Submarine != null) sub = connections[0].Item.Submarine; @@ -231,7 +230,6 @@ namespace Barotrauma.Items.Components if (item.Submarine != sub && Screen.Selected != GameMain.EditMapScreen) { ClearConnections(); - Nodes.Clear(); return; } @@ -242,9 +240,9 @@ namespace Barotrauma.Items.Components { if (character == Character.Controlled && character.SelectedConstruction != null) return false; - if (newNodePos!= Vector2.Zero && Nodes.Count>0 && Vector2.Distance(newNodePos, Nodes[Nodes.Count - 1]) > nodeDistance) + if (newNodePos!= Vector2.Zero && nodes.Count>0 && Vector2.Distance(newNodePos, nodes[nodes.Count - 1]) > nodeDistance) { - Nodes.Add(newNodePos); + nodes.Add(newNodePos); UpdateSections(); Drawable = true; @@ -256,13 +254,13 @@ namespace Barotrauma.Items.Components public override void SecondaryUse(float deltaTime, Character character = null) { - if (Nodes.Count > 1) + if (nodes.Count > 1) { - Nodes.RemoveAt(Nodes.Count - 1); + nodes.RemoveAt(nodes.Count - 1); UpdateSections(); } - Drawable = Nodes.Any(); + Drawable = sections.Count > 0; } public override bool Pick(Character picker) @@ -272,19 +270,45 @@ namespace Barotrauma.Items.Components return true; } + public override void Move(Vector2 amount) + { + if (item.IsSelected) MoveNodes(amount); + } + + public List GetNodes() + { + return new List(nodes); + } + + public void SetNodes(List nodes) + { + this.nodes = new List(nodes); + UpdateSections(); + } + + public void MoveNodes(Vector2 amount) + { + for (int i = 0; i < nodes.Count; i++) + { + nodes[i] += amount; + } + UpdateSections(); + } + public void UpdateSections() { sections.Clear(); - for (int i = 0; i < Nodes.Count-1; i++) + for (int i = 0; i < nodes.Count-1; i++) { - sections.Add(new WireSection(Nodes[i], Nodes[i + 1])); + sections.Add(new WireSection(nodes[i], nodes[i + 1])); } + Drawable = sections.Count > 0; } private void ClearConnections() { - Nodes.Clear(); + nodes.Clear(); sections.Clear(); for (int i = 0; i < 2; i++) @@ -298,7 +322,7 @@ namespace Barotrauma.Items.Components connections[i] = null; } - Drawable = false; + Drawable = sections.Count > 0; } private Vector2 RoundNode(Vector2 position, Hull hull) @@ -328,14 +352,14 @@ namespace Barotrauma.Items.Components private void CleanNodes() { - for (int i = Nodes.Count - 2; i > 0; i--) + for (int i = nodes.Count - 2; i > 0; i--) { - if ((Nodes[i - 1].X == Nodes[i].X || Nodes[i - 1].Y == Nodes[i].Y) && - (Nodes[i + 1].X == Nodes[i].X || Nodes[i + 1].Y == Nodes[i].Y)) + if ((nodes[i - 1].X == nodes[i].X || nodes[i - 1].Y == nodes[i].Y) && + (nodes[i + 1].X == nodes[i].X || nodes[i + 1].Y == nodes[i].Y)) { - if (Vector2.Distance(Nodes[i - 1], Nodes[i]) == Vector2.Distance(Nodes[i + 1], Nodes[i])) + if (Vector2.Distance(nodes[i - 1], nodes[i]) == Vector2.Distance(nodes[i + 1], nodes[i])) { - Nodes.RemoveAt(i); + nodes.RemoveAt(i); } } } @@ -344,12 +368,12 @@ namespace Barotrauma.Items.Components do { removed = false; - for (int i = Nodes.Count - 2; i > 0; i--) + for (int i = nodes.Count - 2; i > 0; i--) { - if ((Nodes[i - 1].X == Nodes[i].X && Nodes[i + 1].X == Nodes[i].X) - || (Nodes[i - 1].Y == Nodes[i].Y && Nodes[i + 1].Y == Nodes[i].Y)) + if ((nodes[i - 1].X == nodes[i].X && nodes[i + 1].X == nodes[i].X) + || (nodes[i - 1].Y == nodes[i].Y && nodes[i + 1].Y == nodes[i].Y)) { - Nodes.RemoveAt(i); + nodes.RemoveAt(i); removed = true; } } @@ -360,7 +384,7 @@ namespace Barotrauma.Items.Components public void Draw(SpriteBatch spriteBatch, bool editing) { - if (!Nodes.Any()) + if (sections.Count == 0) { Drawable = false; return; @@ -378,7 +402,14 @@ namespace Barotrauma.Items.Components { foreach (WireSection section in sections) { - section.Draw(spriteBatch, Color.Gold, drawOffset, depth, 0.5f); + section.Draw(spriteBatch, Color.Gold, drawOffset, depth + 0.00001f, 0.7f); + } + } + else if (item.IsSelected) + { + foreach (WireSection section in sections) + { + section.Draw(spriteBatch, Color.Red, drawOffset, depth + 0.00001f, 0.7f); } } @@ -387,11 +418,11 @@ namespace Barotrauma.Items.Components section.Draw(spriteBatch, item.Color, drawOffset, depth, 0.3f); } - if (IsActive && Vector2.Distance(newNodePos, Nodes[Nodes.Count - 1]) > nodeDistance) + if (IsActive && Vector2.Distance(newNodePos, nodes[nodes.Count - 1]) > nodeDistance) { WireSection.Draw( spriteBatch, - new Vector2(Nodes[Nodes.Count - 1].X, Nodes[Nodes.Count - 1].Y) + drawOffset, + new Vector2(nodes[nodes.Count - 1].X, nodes[nodes.Count - 1].Y) + drawOffset, new Vector2(newNodePos.X, newNodePos.Y) + drawOffset, item.Color * 0.5f, depth, @@ -401,9 +432,9 @@ namespace Barotrauma.Items.Components if (!editing || !PlayerInput.MouseInsideWindow || !GameMain.EditMapScreen.WiringMode) return; if (Character.Controlled != null && Character.Controlled.SelectedConstruction != null) return; - for (int i = 0; i < Nodes.Count; i++) + for (int i = 0; i < nodes.Count; i++) { - Vector2 worldPos = Nodes[i]; + Vector2 worldPos = nodes[i]; if (item.Submarine != null) worldPos += item.Submarine.Position + item.Submarine.HiddenSubPosition; worldPos.Y = -worldPos.Y; @@ -431,7 +462,7 @@ namespace Barotrauma.Items.Components } else if (PlayerInput.RightButtonClicked()) { - Nodes.RemoveAt(i); + nodes.RemoveAt(i); break; } } @@ -456,7 +487,8 @@ namespace Barotrauma.Items.Components //if (item.Submarine != null) nodeWorldPos += item.Submarine.Position; - Nodes[(int)selectedNodeIndex] = nodeWorldPos; + nodes[(int)selectedNodeIndex] = nodeWorldPos; + UpdateSections(); MapEntity.SelectEntity(item); } @@ -470,23 +502,24 @@ namespace Barotrauma.Items.Components public override void FlipX() { - for (int i = 0; i < Nodes.Count; i++) + for (int i = 0; i < nodes.Count; i++) { - Nodes[i] = new Vector2(-Nodes[i].X, Nodes[i].Y); - } + nodes[i] = new Vector2(-nodes[i].X, nodes[i].Y); + } + UpdateSections(); } public override XElement Save(XElement parentElement) { XElement componentElement = base.Save(parentElement); - if (Nodes == null || Nodes.Count == 0) return componentElement; + if (nodes == null || nodes.Count == 0) return componentElement; - string[] nodeCoords = new string[Nodes.Count * 2]; - for (int i = 0; i < Nodes.Count; i++) + string[] nodeCoords = new string[nodes.Count * 2]; + for (int i = 0; i < nodes.Count; i++) { - nodeCoords[i * 2] = Nodes[i].X.ToString(CultureInfo.InvariantCulture); - nodeCoords[i * 2 + 1] = Nodes[i].Y.ToString(CultureInfo.InvariantCulture); + nodeCoords[i * 2] = nodes[i].X.ToString(CultureInfo.InvariantCulture); + nodeCoords[i * 2 + 1] = nodes[i].Y.ToString(CultureInfo.InvariantCulture); } componentElement.Add(new XAttribute("nodes", string.Join(";", nodeCoords))); @@ -518,10 +551,10 @@ namespace Barotrauma.Items.Components } catch { y = 0.0f; } - Nodes.Add(new Vector2(x, y)); + nodes.Add(new Vector2(x, y)); } - Drawable = Nodes.Any(); + Drawable = nodes.Any(); } @@ -534,26 +567,27 @@ namespace Barotrauma.Items.Components public void ClientWrite(Lidgren.Network.NetBuffer msg, object[] extraData = null) { - msg.Write((byte)Math.Min(Nodes.Count, 255)); - for (int i = 0; i < Math.Min(Nodes.Count, 255); i++) + msg.Write((byte)Math.Min(nodes.Count, 255)); + for (int i = 0; i < Math.Min(nodes.Count, 255); i++) { - msg.Write(Nodes[i].X); - msg.Write(Nodes[i].Y); + msg.Write(nodes[i].X); + msg.Write(nodes[i].Y); } } public void ServerRead(Lidgren.Network.NetIncomingMessage msg, Barotrauma.Networking.Client c) { - Nodes.Clear(); + nodes.Clear(); int nodeCount = msg.ReadByte(); for (int i = 0; i < nodeCount; i++) { Vector2 newNode = new Vector2(msg.ReadFloat(), msg.ReadFloat()); - if (MathUtils.IsValid(newNode)) Nodes.Add(newNode); + if (MathUtils.IsValid(newNode)) nodes.Add(newNode); } - Drawable = Nodes.Any(); + UpdateSections(); + Drawable = nodes.Any(); } } diff --git a/Subsurface/Source/Items/FixRequirement.cs b/Subsurface/Source/Items/FixRequirement.cs index a31d70d5e..1c928a8d9 100644 --- a/Subsurface/Source/Items/FixRequirement.cs +++ b/Subsurface/Source/Items/FixRequirement.cs @@ -190,6 +190,13 @@ namespace Barotrauma frame.Draw(spriteBatch); } + public static void AddToGUIUpdateList() + { + if (frame == null) return; + + frame.AddToGUIUpdateList(); + } + public static void UpdateHud(Item item, Character character) { if (frame == null || frame.UserData != item) diff --git a/Subsurface/Source/Items/Item.cs b/Subsurface/Source/Items/Item.cs index 6ea723803..4ea7d2100 100644 --- a/Subsurface/Source/Items/Item.cs +++ b/Subsurface/Source/Items/Item.cs @@ -414,6 +414,33 @@ namespace Barotrauma ItemList.Add(this); } + public override MapEntity Clone() + { + Item clone = new Item(rect, prefab, Submarine); + foreach (KeyValuePair property in properties) + { + if (!property.Value.Attributes.OfType().Any()) continue; + clone.properties[property.Key].TrySetValue(property.Value.GetValue()); + } + for (int i = 0; i < components.Count; i++) + { + foreach (KeyValuePair property in components[i].properties) + { + if (!property.Value.Attributes.OfType().Any()) continue; + clone.components[i].properties[property.Key].TrySetValue(property.Value.GetValue()); + } + } + if (ContainedItems != null) + { + foreach (Item containedItem in ContainedItems) + { + var containedClone = containedItem.Clone(); + clone.ownInventory.TryPutItem(containedClone as Item); + } + } + return clone; + } + public T GetComponent() { foreach (ItemComponent ic in components) @@ -579,6 +606,8 @@ namespace Barotrauma contained.Submarine = Submarine; contained.CurrentHull = CurrentHull; + + contained.SetContainedItemPositions(); } } @@ -737,11 +766,15 @@ namespace Barotrauma inWater = IsInWater(); if (inWater) ApplyStatusEffects(ActionType.InWater, deltaTime); + + isHighlighted = false; isHighlighted = false; if (body == null || !body.Enabled) return; + System.Diagnostics.Debug.Assert(body.FarseerBody.FixtureList != null); + if (Math.Abs(body.LinearVelocity.X) > 0.01f || Math.Abs(body.LinearVelocity.Y) > 0.01f) { Submarine prevSub = Submarine; @@ -858,7 +891,7 @@ namespace Barotrauma public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) { if (!Visible) return; - Color color = (isSelected && editing) ? color = Color.Red : spriteColor; + Color color = (IsSelected && editing) ? color = Color.Red : spriteColor; if (isHighlighted) color = Color.Orange; SpriteEffects oldEffects = prefab.sprite.effects; @@ -919,7 +952,7 @@ namespace Barotrauma return; } - if (isSelected || isHighlighted) + if (IsSelected || isHighlighted) { GUI.DrawRectangle(spriteBatch, new Vector2(DrawPosition.X - rect.Width / 2, -(DrawPosition.Y+rect.Height/2)), new Vector2(rect.Width, rect.Height), Color.Green,false,0,(int)Math.Max((1.5f/GameScreen.Selected.Cam.Zoom),1.0f)); @@ -1108,6 +1141,24 @@ namespace Barotrauma } } + public override void AddToGUIUpdateList() + { + if (condition <= 0.0f) + { + FixRequirement.AddToGUIUpdateList(); + return; + } + if (HasInGameEditableProperties) + { + if (editingHUD != null) editingHUD.AddToGUIUpdateList(); + } + foreach (ItemComponent ic in components) + { + ic.AddToGUIUpdateList(); + } + if (Screen.Selected is EditMapScreen && editingHUD != null) editingHUD.AddToGUIUpdateList(); + } + public virtual void UpdateHUD(Camera cam, Character character) { if (condition <= 0.0f) @@ -1357,7 +1408,7 @@ namespace Barotrauma ic.ApplyStatusEffects(ActionType.OnPicked, 1.0f, picker); ic.PlaySound(ActionType.OnPicked, picker.WorldPosition); - if (picker==Character.Controlled) GUIComponent.MouseOn = null; + if (picker == Character.Controlled) GUIComponent.ForceMouseOn(null); if (ic.CanBeSelected) selected = true; } @@ -1851,8 +1902,24 @@ namespace Barotrauma GameMain.Client.CreateEntityEvent(this, new object[] { index }); } - - public override void Remove() + public override void ShallowRemove() + { + base.ShallowRemove(); + + Removed = true; + foreach (ItemComponent ic in components) + { + ic.Remove(); + } + ItemList.Remove(this); + if (body != null) + { + body.Remove(); + body = null; + } + } + + public override void Remove() { base.Remove(); @@ -1886,4 +1953,4 @@ namespace Barotrauma } } -} \ No newline at end of file +} diff --git a/Subsurface/Source/Map/Entity.cs b/Subsurface/Source/Map/Entity.cs index 021a1e73e..8ee834dc8 100644 --- a/Subsurface/Source/Map/Entity.cs +++ b/Subsurface/Source/Map/Entity.cs @@ -110,7 +110,14 @@ namespace Barotrauma List list = new List(dictionary.Values); foreach (Entity e in list) { - e.Remove(); + try + { + e.Remove(); + } + catch (Exception exception) + { + DebugConsole.ThrowError("Error while removing entity \"" + e.ToString() + "\"", exception); + } } dictionary.Clear(); } diff --git a/Subsurface/Source/Map/Gap.cs b/Subsurface/Source/Map/Gap.cs index 5790aec50..b99a83ddf 100644 --- a/Subsurface/Source/Map/Gap.cs +++ b/Subsurface/Source/Map/Gap.cs @@ -114,6 +114,11 @@ namespace Barotrauma InsertToList(); } + public override MapEntity Clone() + { + return new Gap(rect, isHorizontal, Submarine); + } + public override void Move(Vector2 amount) { base.Move(amount); @@ -210,7 +215,7 @@ namespace Barotrauma isHorizontal ? new Vector2(rect.Height / 16.0f, 1.0f) : new Vector2(rect.Width / 16.0f, 1.0f)); } - if (isSelected) + if (IsSelected) { GUI.DrawRectangle(sb, new Vector2(WorldRect.X - 5, -WorldRect.Y - 5), @@ -247,7 +252,7 @@ namespace Barotrauma lerpedFlowForce = Vector2.Lerp(lerpedFlowForce, flowForce, deltaTime); - if (LerpedFlowForce.Length() > 100.0f && flowTargetHull != null && flowTargetHull.Volume < flowTargetHull.FullVolume) + if (LerpedFlowForce.LengthSquared() > 10000.0f && flowTargetHull != null && flowTargetHull.Volume < flowTargetHull.FullVolume) { //UpdateFlowForce(); @@ -526,7 +531,7 @@ namespace Barotrauma //a variable affecting the water flow through the gap //the larger the gap is, the faster the water flows - float sizeModifier = size * open; + float sizeModifier = size * open * open; float delta = Hull.MaxCompress * sizeModifier * deltaTime; @@ -557,12 +562,10 @@ namespace Barotrauma if (hull1.Volume < hull1.FullVolume - Hull.MaxCompress && hull1.Surface < rect.Y) { - - if (rect.X > hull1.Rect.X + hull1.Rect.Width / 2.0f) { float vel = ((rect.Y - rect.Height / 2) - (hull1.Surface + hull1.WaveY[hull1.WaveY.Length - 1])) * 0.1f; - + vel *= Math.Min(Math.Abs(flowForce.X) / 200.0f, 1.0f); hull1.WaveVel[hull1.WaveY.Length - 1] += vel; hull1.WaveVel[hull1.WaveY.Length - 2] += vel; @@ -570,11 +573,11 @@ namespace Barotrauma else { float vel = ((rect.Y - rect.Height / 2) - (hull1.Surface + hull1.WaveY[0])) * 0.1f; - + vel *= Math.Min(Math.Abs(flowForce.X) / 200.0f, 1.0f); hull1.WaveVel[0] += vel; hull1.WaveVel[1] += vel; - } + } } else { diff --git a/Subsurface/Source/Map/Hull.cs b/Subsurface/Source/Map/Hull.cs index f81097179..7aa4533c8 100644 --- a/Subsurface/Source/Map/Hull.cs +++ b/Subsurface/Source/Map/Hull.cs @@ -261,6 +261,11 @@ namespace Barotrauma return rect; } + + public override MapEntity Clone() + { + return new Hull(MapEntityPrefab.list.Find(m => m.Name == "Hull"), rect, Submarine); + } public static EntityGrid GenerateEntityGrid(Submarine submarine) { @@ -330,7 +335,7 @@ namespace Barotrauma base.Remove(); hullList.Remove(this); - if (Submarine == null || !Submarine.Loading) + if (Submarine == null || (!Submarine.Loading && !Submarine.Unloading)) { Item.UpdateHulls(); Gap.UpdateHulls(); @@ -605,7 +610,7 @@ namespace Barotrauma } - if ((isSelected || isHighlighted) && editing) + if ((IsSelected || isHighlighted) && editing) { GUI.DrawRectangle(spriteBatch, new Vector2(drawRect.X + 5, -drawRect.Y + 5), diff --git a/Subsurface/Source/Map/Levels/Level.cs b/Subsurface/Source/Map/Levels/Level.cs index 0f2ff1a6c..a48a4ca3d 100644 --- a/Subsurface/Source/Map/Levels/Level.cs +++ b/Subsurface/Source/Map/Levels/Level.cs @@ -54,7 +54,7 @@ namespace Barotrauma public const int GridCellSize = 2000; private List[,] cellGrid; - private WrappingWall[,] wrappingWalls; + //private WrappingWall[,] wrappingWalls; //private float shaftHeight; @@ -97,10 +97,10 @@ namespace Barotrauma get { return ruins; } } - public WrappingWall[,] WrappingWalls - { - get { return wrappingWalls; } - } + //public WrappingWall[,] WrappingWalls + //{ + // get { return wrappingWalls; } + //} public string Seed { @@ -187,11 +187,11 @@ namespace Barotrauma minWidth = Math.Max(minWidth, 6500.0f); startPosition = new Vector2( - Rand.Range(minWidth * 2, minWidth * 4, false), + Rand.Range(minWidth, minWidth * 2, false), Rand.Range(borders.Height * 0.5f, borders.Height - minWidth * 2, false)); endPosition = new Vector2( - borders.Width - Rand.Range(minWidth * 2, minWidth * 4, false), + borders.Width - Rand.Range(minWidth, minWidth * 2, false), Rand.Range(borders.Height * 0.5f, borders.Height - minWidth * 2, false)); List pathNodes = new List(); @@ -211,8 +211,12 @@ namespace Barotrauma pathNodes.Add(new Vector2(endPosition.X, borders.Height)); - List> smallTunnels = new List>(); + if (pathNodes.Count <= 2) + { + pathNodes.Add((startPosition + endPosition) / 2); + } + List> smallTunnels = new List>(); for (int i = 0; i < generationParams.SmallTunnelCount; i++) { var tunnelStartPos = pathNodes[Rand.Range(2, pathNodes.Count - 2, false)]; @@ -421,7 +425,8 @@ namespace Barotrauma cellGrid[x, y].Add(cell); } - + + ruins = new List(); for (int i = 0; i(); ruins.Add(ruin); ruin.RuinShapes.Sort((shape1, shape2) => shape2.DistanceFromEntrance.CompareTo(shape1.DistanceFromEntrance)); @@ -809,10 +813,11 @@ namespace Barotrauma public void Update(float deltaTime) { + /* if (Submarine.MainSub != null) { WrappingWall.UpdateWallShift(Submarine.MainSub.WorldPosition, wrappingWalls); - } + }*/ if (Hull.renderer != null) { @@ -884,6 +889,7 @@ namespace Barotrauma } } + /* if (wrappingWalls == null) return cells; for (int side = 0; side < 2; side++) @@ -899,7 +905,7 @@ namespace Barotrauma cells.Add(cell); } } - } + }*/ return cells; } @@ -918,6 +924,7 @@ namespace Barotrauma ruins = null; } + /* if (wrappingWalls!=null) { for (int side = 0; side < 2; side++) @@ -929,7 +936,7 @@ namespace Barotrauma } wrappingWalls = null; - } + }*/ cells = null; diff --git a/Subsurface/Source/Map/Levels/LevelRenderer.cs b/Subsurface/Source/Map/Levels/LevelRenderer.cs index f1e5148c1..0910925c2 100644 --- a/Subsurface/Source/Map/Levels/LevelRenderer.cs +++ b/Subsurface/Source/Map/Levels/LevelRenderer.cs @@ -219,6 +219,7 @@ namespace Barotrauma graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(bodyVertices.VertexCount / 3.0f)); + /* for (int side = 0; side < 2; side++) { for (int i = 0; i < 2; i++) @@ -234,7 +235,7 @@ namespace Barotrauma PrimitiveType.TriangleList, 0, (int)Math.Floor(level.WrappingWalls[side, i].BodyVertices.VertexCount / 3.0f)); } - } + }*/ graphicsDevice.SetVertexBuffer(wallVertices); @@ -243,7 +244,7 @@ namespace Barotrauma basicEffect.CurrentTechnique = basicEffect.Techniques["BasicEffect_Texture"]; basicEffect.CurrentTechnique.Passes[0].Apply(); graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(wallVertices.VertexCount / 3.0f)); - + /* for (int side = 0; side < 2; side++) { for (int i = 0; i < 2; i++) @@ -260,7 +261,7 @@ namespace Barotrauma (int)Math.Floor(level.WrappingWalls[side, i].WallVertices.VertexCount / 3.0f)); } - } + }*/ } diff --git a/Subsurface/Source/Map/Lights/ConvexHull.cs b/Subsurface/Source/Map/Lights/ConvexHull.cs index 7ab0bc15d..c48285988 100644 --- a/Subsurface/Source/Map/Lights/ConvexHull.cs +++ b/Subsurface/Source/Map/Lights/ConvexHull.cs @@ -44,13 +44,24 @@ namespace Barotrauma.Lights class ConvexHullList { + private List list; + public readonly Submarine Submarine; - public List List; + public List List + { + get { return list; } + set + { + Debug.Assert(value != null); + Debug.Assert(!list.Contains(null)); + list = value; + } + } public ConvexHullList(Submarine submarine) { Submarine = submarine; - List = new List(); + list = new List(); } } diff --git a/Subsurface/Source/Map/Lights/LightSource.cs b/Subsurface/Source/Map/Lights/LightSource.cs index 931c9455f..770d25443 100644 --- a/Subsurface/Source/Map/Lights/LightSource.cs +++ b/Subsurface/Source/Map/Lights/LightSource.cs @@ -18,6 +18,8 @@ namespace Barotrauma.Lights private float range; + public SpriteEffects SpriteEffect = SpriteEffects.None; + private Texture2D texture; public Sprite LightSprite; @@ -164,15 +166,15 @@ namespace Barotrauma.Lights private List GetHullsInRange(Submarine sub) { + //find the current list of hulls in range var chList = hullsInRange.Find(x => x.Submarine == sub); + //not found -> create one if (chList == null) { chList = new ConvexHullList(sub); hullsInRange.Add(chList); } - List list = chList.List; - Vector2 lightPos = position; if (ParentSub == null) @@ -183,15 +185,12 @@ namespace Barotrauma.Lights if (NeedsHullUpdate) { var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub); - - list = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)); - chList.List = list; + chList.List = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)); } } //light is outside, convexhull inside a sub else { - //todo: check lightPos -= sub.Position; Rectangle subBorders = sub.Borders; @@ -201,7 +200,7 @@ namespace Barotrauma.Lights if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders)) return null; var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub); - list = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)); + chList.List = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)); } } else @@ -215,15 +214,13 @@ namespace Barotrauma.Lights if (NeedsHullUpdate) { var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub); - - list = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)); - chList.List = list; + chList.List = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)); } } //light and convexhull are inside different subs else { - if (sub.DockedTo.Contains(ParentSub) && !NeedsHullUpdate) return list; + if (sub.DockedTo.Contains(ParentSub) && !NeedsHullUpdate) return chList.List; lightPos -= (sub.Position - ParentSub.Position); @@ -234,12 +231,11 @@ namespace Barotrauma.Lights if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders)) return null; var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub); - list = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)); - chList.List = list; + chList.List = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)); } } - return list; + return chList.List; } public static List GetHullsInRange(Vector2 position, float range, Submarine ParentSub) @@ -318,13 +314,14 @@ namespace Barotrauma.Lights overrideLightTexture.Draw(spriteBatch, drawPos, color * (color.A / 255.0f), overrideLightTexture.Origin, -Rotation, - new Vector2(overrideLightTexture.size.X / overrideLightTexture.SourceRect.Width, overrideLightTexture.size.Y / overrideLightTexture.SourceRect.Height)); + new Vector2(overrideLightTexture.size.X / overrideLightTexture.SourceRect.Width, overrideLightTexture.size.Y / overrideLightTexture.SourceRect.Height), + SpriteEffect); } } if (LightSprite != null) { - LightSprite.Draw(spriteBatch, drawPos, Color, LightSprite.Origin); + LightSprite.Draw(spriteBatch, drawPos, Color, LightSprite.Origin, -Rotation, 1, SpriteEffect); } } diff --git a/Subsurface/Source/Map/LinkedSubmarine.cs b/Subsurface/Source/Map/LinkedSubmarine.cs index b17c76116..856a65f65 100644 --- a/Subsurface/Source/Map/LinkedSubmarine.cs +++ b/Subsurface/Source/Map/LinkedSubmarine.cs @@ -111,7 +111,7 @@ namespace Barotrauma if (!editing || wallVertices == null) return; Color color = (isHighlighted) ? Color.Orange : Color.Green; - if (isSelected) color = Color.Red; + if (IsSelected) color = Color.Red; Vector2 pos = Position; diff --git a/Subsurface/Source/Map/Map/Map.cs b/Subsurface/Source/Map/Map/Map.cs index 64eae3e71..f54bf631a 100644 --- a/Subsurface/Source/Map/Map/Map.cs +++ b/Subsurface/Source/Map/Map/Map.cs @@ -358,7 +358,7 @@ namespace Barotrauma } rect.Inflate(8, 8); - GUI.DrawRectangle(spriteBatch, rect, Color.Black, 8); + GUI.DrawRectangle(spriteBatch, rect, Color.Black, false, 0.0f, 8); GUI.DrawRectangle(spriteBatch, rect, Color.LightGray); for (int i = 0; i < locations.Count; i++) diff --git a/Subsurface/Source/Map/MapEntity.cs b/Subsurface/Source/Map/MapEntity.cs index 13ae6bd4d..0ad25bb11 100644 --- a/Subsurface/Source/Map/MapEntity.cs +++ b/Subsurface/Source/Map/MapEntity.cs @@ -1,24 +1,41 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Xml.Linq; using FarseerPhysics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using System.Collections.ObjectModel; +using Barotrauma.Items.Components; namespace Barotrauma { - class MapEntity : Entity + abstract class MapEntity : Entity { public static List mapEntityList = new List(); //which entities have been selected for editing - public static List selectedList = new List(); + private static List selectedList = new List(); + public static List SelectedList + { + get + { + return selectedList; + } + } + private static List copiedList = new List(); protected static GUIComponent editingHUD; - + public static GUIComponent EditingHUD + { + get + { + return editingHUD; + } + } + protected static Vector2 selectionPos = Vector2.Zero; protected static Vector2 selectionSize = Vector2.Zero; @@ -37,7 +54,7 @@ namespace Barotrauma //is the mouse inside the rect protected bool isHighlighted; - protected bool isSelected; + //protected bool isSelected; private static bool disableSelect; public static bool DisableSelect @@ -149,7 +166,11 @@ namespace Barotrauma if (aiTarget == null) return 0.0f; return aiTarget.SoundRange; } - set { aiTarget.SoundRange = value; } + set + { + if (aiTarget == null) return; + aiTarget.SoundRange = value; + } } public float SightRange @@ -169,8 +190,7 @@ namespace Barotrauma public bool IsSelected { - get { return isSelected; } - set { isSelected = value; } + get { return selectedList.Contains(this); } } protected bool ResizeHorizontal @@ -202,6 +222,68 @@ namespace Barotrauma { return (Submarine.RectContains(WorldRect, position)); } + + public virtual MapEntity Clone() + { + throw new NotImplementedException(); + } + + public static List Clone(List entitiesToClone) + { + List clones = new List(); + foreach (MapEntity e in entitiesToClone) + { + Debug.Assert(e != null); + clones.Add(e.Clone()); + Debug.Assert(clones.Last() != null); + } + + Debug.Assert(clones.Count == entitiesToClone.Count); + + //clone links between the entities + for (int i = 0; i < clones.Count; i++) + { + foreach (MapEntity linked in entitiesToClone[i].linkedTo) + { + if (!entitiesToClone.Contains(linked)) continue; + + clones[i].linkedTo.Add(clones[entitiesToClone.IndexOf(linked)]); + } + } + + //connect clone wires to the clone items + for (int i = 0; i < clones.Count; i++) + { + var cloneItem = clones[i] as Item; + if (cloneItem == null) continue; + + var cloneWire = cloneItem.GetComponent(); + if (cloneWire == null) continue; + + var originalWire = ((Item)entitiesToClone[i]).GetComponent(); + + cloneWire.SetNodes(originalWire.GetNodes()); + + for (int n = 0; n < 2; n++) + { + if (originalWire.Connections[n] == null) continue; + + var connectedItem = originalWire.Connections[n].Item; + if (connectedItem == null) continue; + + //index of the item the wire is connected to + int itemIndex = entitiesToClone.IndexOf(connectedItem); + //index of the connection in the connectionpanel of the target item + int connectionIndex = connectedItem.Connections.IndexOf(originalWire.Connections[n]); + + (clones[itemIndex] as Item).GetComponent().Connections[connectionIndex].TryAddLink(cloneWire); + cloneWire.Connect((clones[itemIndex] as Item).Connections[connectionIndex], false); + + } + } + + return clones; + } protected void InsertToList() { @@ -229,6 +311,18 @@ namespace Barotrauma public virtual void DrawDamage(SpriteBatch spriteBatch, Effect damageEffect) {} + /// + /// Remove the entity from the entity list without removing links to other entities + /// + public virtual void ShallowRemove() + { + base.Remove(); + + mapEntityList.Remove(this); + + if (aiTarget != null) aiTarget.Remove(); + } + public override void Remove() { base.Remove(); @@ -288,7 +382,6 @@ namespace Barotrauma foreach (MapEntity e in mapEntityList) { e.isHighlighted = false; - e.isSelected = false; } if (DisableSelect) @@ -308,10 +401,40 @@ namespace Barotrauma if (PlayerInput.KeyDown(Keys.Delete)) { - foreach (MapEntity e in selectedList) e.Remove(); + selectedList.ForEach(e => e.Remove()); selectedList.Clear(); } + if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl)) + { + if (PlayerInput.GetKeyboardState.IsKeyDown(Keys.C) && + PlayerInput.GetOldKeyboardState.IsKeyUp(Keys.C)) + { + CopyEntities(selectedList); + } + else if (PlayerInput.GetKeyboardState.IsKeyDown(Keys.X) && + PlayerInput.GetOldKeyboardState.IsKeyUp(Keys.X)) + { + CopyEntities(selectedList); + + selectedList.ForEach(e => e.Remove()); + selectedList.Clear(); + } + else if (copiedList.Count > 0 && + PlayerInput.GetKeyboardState.IsKeyDown(Keys.V) && + PlayerInput.GetOldKeyboardState.IsKeyUp(Keys.V)) + { + var clones = Clone(copiedList); + + Vector2 center = Vector2.Zero; + clones.ForEach(c => center += c.WorldPosition); + center /= clones.Count; + + selectedList = new List(clones); + selectedList.ForEach(c => c.Move(cam.WorldViewCenter - center)); + } + } + Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition); MapEntity highLightedEntity = null; @@ -327,21 +450,15 @@ namespace Barotrauma { if (e.IsMouseOn(position)) highLightedEntity = e; } - e.isSelected = false; } if (highLightedEntity != null) highLightedEntity.isHighlighted = true; } - - foreach (MapEntity e in selectedList) - { - e.isSelected = true; - } - + //started moving selected entities if (startMovingPos != Vector2.Zero) - { + { if (PlayerInput.LeftButtonReleased()) { //mouse released -> move the entities to the new position of the mouse @@ -351,11 +468,22 @@ namespace Barotrauma if (moveAmount != Vector2.Zero) { - foreach (MapEntity e in selectedList) e.Move(moveAmount); + //clone + if (PlayerInput.KeyDown(Keys.LeftControl) || PlayerInput.KeyDown(Keys.RightControl)) + { + var clones = Clone(selectedList); + selectedList = clones; + selectedList.ForEach(c => c.Move(moveAmount)); + } + else // move + { + foreach (MapEntity e in selectedList) e.Move(moveAmount); + } } - startMovingPos = Vector2.Zero; + startMovingPos = Vector2.Zero; } + } //started dragging a "selection rectangle" else if (selectionPos != Vector2.Zero) @@ -402,6 +530,25 @@ namespace Barotrauma { selectedList = newSelection; } + + //select wire if both items it's connected to are selected + var selectedItems = selectedList.Where(e => e is Item).Cast().ToList(); + foreach (Item item in selectedItems) + { + if (item.Connections == null) continue; + foreach (Connection c in item.Connections) + { + foreach (Wire w in c.Wires) + { + if (w == null || selectedList.Contains(w.Item)) continue; + + if (w.OtherConnection(c) != null && selectedList.Contains(w.OtherConnection(c).Item)) + { + selectedList.Add(w.Item); + } + } + } + } selectionPos = Vector2.Zero; selectionSize = Vector2.Zero; @@ -410,7 +557,6 @@ namespace Barotrauma //default, not doing anything specific yet else { - if (PlayerInput.LeftButtonHeld() && PlayerInput.KeyUp(Keys.Space)) { @@ -422,12 +568,10 @@ namespace Barotrauma selectionPos = position; } - - - } - + } } + /// /// Draw the "selection rectangle" and outlines of entities that are being dragged (if any) /// @@ -504,10 +648,6 @@ namespace Barotrauma public static void DeselectAll() { - foreach (MapEntity e in selectedList) - { - e.isSelected = false; - } selectedList.Clear(); } @@ -516,10 +656,27 @@ namespace Barotrauma { DeselectAll(); - entity.isSelected = true; selectedList.Add(entity); } + + /// + /// copies a list of entities to the "clipboard" (copiedList) + /// + private static void CopyEntities(List entities) + { + List prevEntities = new List(mapEntityList); + + copiedList = Clone(entities); + + //find all new entities created during cloning + var newEntities = mapEntityList.Except(prevEntities).ToList(); + + //do a "shallow remove" (removes the entities from the game without removing links between them) + // -> items will stay in their containers + newEntities.ForEach(e => e.ShallowRemove()); + } + public virtual void FlipX() { if (Submarine == null) @@ -533,6 +690,11 @@ namespace Barotrauma Move(-relative * 2.0f); } + + public virtual void AddToGUIUpdateList() + { + if (editingHUD != null) editingHUD.AddToGUIUpdateList(); + } public virtual void UpdateEditing(Camera cam) { } @@ -631,26 +793,7 @@ namespace Barotrauma } } } - - public static List FindMapEntities(Vector2 pos) - { - List foundEntities = new List(); - foreach (MapEntity e in mapEntityList) - { - if (Submarine.RectContains(e.rect, pos)) foundEntities.Add(e); - } - return foundEntities; - } - - public static MapEntity FindMapEntity(Vector2 pos) - { - foreach (MapEntity e in mapEntityList) - { - if (Submarine.RectContains(e.rect, pos)) return e; - } - return null; - } - + /// /// Find entities whose rect intersects with the "selection rect" /// diff --git a/Subsurface/Source/Map/Structure.cs b/Subsurface/Source/Map/Structure.cs index 785d34fcb..a07a9256e 100644 --- a/Subsurface/Source/Map/Structure.cs +++ b/Subsurface/Source/Map/Structure.cs @@ -258,7 +258,6 @@ namespace Barotrauma } } - if (prefab.CastShadow) { GenerateConvexHull(); @@ -267,6 +266,11 @@ namespace Barotrauma InsertToList(); } + public override MapEntity Clone() + { + return new Structure(rect, prefab, Submarine); + } + private void CreateStairBodies() { bodies = new List(); @@ -486,14 +490,13 @@ namespace Barotrauma Draw(spriteBatch, false, false, damageEffect); } - private static float prevCutoff; private void Draw(SpriteBatch spriteBatch, bool editing, bool back = true, Effect damageEffect = null) { if (prefab.sprite == null) return; Color color = (isHighlighted) ? Color.Orange : Color.White; - if (isSelected && editing) + if (IsSelected && editing) { color = Color.Red; @@ -525,14 +528,14 @@ namespace Barotrauma { float newCutoff = Math.Min((sections[i].damage / prefab.MaxHealth), 0.65f); - if (Math.Abs(newCutoff - prevCutoff) > 0.01f) + if (Math.Abs(newCutoff - Submarine.DamageEffectCutoff) > 0.01f) { damageEffect.Parameters["aCutoff"].SetValue(newCutoff); damageEffect.Parameters["cCutoff"].SetValue(newCutoff * 1.2f); damageEffect.CurrentTechnique.Passes[0].Apply(); - prevCutoff = newCutoff; + Submarine.DamageEffectCutoff = newCutoff; } } @@ -760,11 +763,10 @@ namespace Barotrauma if(CastShadow) GenerateConvexHull(); } + + sections[sectionIndex].gap.Open = (damage / prefab.MaxHealth - 0.5f) * 2.0f; } - - if (sections[sectionIndex].gap != null) - sections[sectionIndex].gap.Open = (damage/prefab.MaxHealth - 0.5f)*2; - + bool hadHole = SectionBodyDisabled(sectionIndex); sections[sectionIndex].damage = MathHelper.Clamp(damage, 0.0f, prefab.MaxHealth); diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index 10d3ed934..359043c35 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -362,7 +362,7 @@ namespace Barotrauma worldBorders.Location += sub.WorldPosition.ToPoint(); worldBorders.Y = -worldBorders.Y; - GUI.DrawRectangle(spriteBatch, worldBorders, Color.White, 5); + GUI.DrawRectangle(spriteBatch, worldBorders, Color.White, false, 0, 5); if (sub.subBody.MemPos.Count < 2) continue; @@ -383,6 +383,9 @@ namespace Barotrauma } } + + public static float DamageEffectCutoff; + public static void DrawDamageable(SpriteBatch spriteBatch, Effect damageEffect, bool editing = false) { var entitiesToRender = !editing && visibleEntities != null ? visibleEntities : MapEntity.mapEntityList; @@ -396,6 +399,8 @@ namespace Barotrauma { damageEffect.Parameters["aCutoff"].SetValue(0.0f); damageEffect.Parameters["cCutoff"].SetValue(0.0f); + + DamageEffectCutoff = 0.0f; } } @@ -929,6 +934,7 @@ namespace Barotrauma { try { + ToolBox.IsProperFilenameCase(file); doc = XDocument.Load(file); } @@ -1035,13 +1041,10 @@ namespace Barotrauma if (item.Submarine != this) continue; var wire = item.GetComponent(); - if (wire == null) continue; - - for (int i = 0; i < wire.Nodes.Count; i++) + if (wire != null) { - wire.Nodes[i] -= center; + wire.MoveNodes(-center); } - wire.UpdateSections(); } for (int i = 0; i < MapEntity.mapEntityList.Count; i++) diff --git a/Subsurface/Source/Map/SubmarineBody.cs b/Subsurface/Source/Map/SubmarineBody.cs index c17d6c302..c9c904ef9 100644 --- a/Subsurface/Source/Map/SubmarineBody.cs +++ b/Subsurface/Source/Map/SubmarineBody.cs @@ -243,6 +243,21 @@ namespace Barotrauma return; } + //if outside left or right edge of the level + if (Position.X < 0 || Position.X > Level.Loaded.Size.X) + { + Rectangle worldBorders = Borders; + worldBorders.Location += Position.ToPoint(); + + //push the sub back below the upper "barrier" of the level + if (worldBorders.Y > Level.Loaded.Size.Y) + { + Body.LinearVelocity = new Vector2( + Body.LinearVelocity.X, + Math.Min(Body.LinearVelocity.Y, ConvertUnits.ToSimUnits(Level.Loaded.Size.Y - worldBorders.Y))); + } + } + //------------------------- Vector2 totalForce = CalculateBuoyancy(); diff --git a/Subsurface/Source/Map/WayPoint.cs b/Subsurface/Source/Map/WayPoint.cs index dba83d407..769a655bd 100644 --- a/Subsurface/Source/Map/WayPoint.cs +++ b/Subsurface/Source/Map/WayPoint.cs @@ -113,6 +113,16 @@ namespace Barotrauma currentHull = Hull.FindHull(WorldPosition); } + public override MapEntity Clone() + { + var clone = new WayPoint(rect, Submarine); + clone.idCardTags = idCardTags; + clone.spawnType = spawnType; + clone.assignedJob = assignedJob; + + return clone; + } + public override bool IsMouseOn(Vector2 position) { if (IsHidden()) return false; @@ -134,7 +144,7 @@ namespace Barotrauma drawPos.Y = -drawPos.Y; Color clr = currentHull == null ? Color.Blue : Color.White; - if (isSelected) clr = Color.Red; + if (IsSelected) clr = Color.Red; if (isHighlighted) clr = Color.DarkRed; int iconX = iconIndices[(int)spawnType]*IconSize % iconTexture.Width; @@ -434,7 +444,7 @@ namespace Barotrauma foreach (Structure stairs in stairList) { - WayPoint[] stairPoints = new WayPoint[2]; + WayPoint[] stairPoints = new WayPoint[3]; stairPoints[0] = new WayPoint( new Vector2(stairs.Rect.X - 32.0f, @@ -453,8 +463,10 @@ namespace Barotrauma stairPoints[i].ConnectTo(closest); } } - - stairPoints[0].ConnectTo(stairPoints[1]); + + stairPoints[2] = new WayPoint((stairPoints[0].Position + stairPoints[1].Position)/2, SpawnType.Path, submarine); + stairPoints[0].ConnectTo(stairPoints[2]); + stairPoints[2].ConnectTo(stairPoints[1]); } foreach (Item item in Item.ItemList) diff --git a/Subsurface/Source/Networking/Client.cs b/Subsurface/Source/Networking/Client.cs index 0632d92f0..e8b94e8af 100644 --- a/Subsurface/Source/Networking/Client.cs +++ b/Subsurface/Source/Networking/Client.cs @@ -61,7 +61,7 @@ namespace Barotrauma.Networking public float deleteDisconnectedTimer; - public ClientPermissions Permissions; + public ClientPermissions Permissions = ClientPermissions.None; public void InitClientSync() { @@ -76,7 +76,7 @@ namespace Barotrauma.Networking { get { return kickVoters.Count; } } - + public Client(NetPeer server, string name, byte ID) : this(name, ID) { @@ -110,6 +110,7 @@ namespace Barotrauma.Networking public static string SanitizeName(string name) { + name = name.Trim(); if (name.Length > 20) { name = name.Substring(0, 20); @@ -138,17 +139,17 @@ namespace Barotrauma.Networking public void GivePermission(ClientPermissions permission) { - this.Permissions |= permission; + if (!this.Permissions.HasFlag(permission)) this.Permissions |= permission; } public void RemovePermission(ClientPermissions permission) { - this.Permissions &= ~permission; + if (this.Permissions.HasFlag(permission)) this.Permissions &= ~permission; } public bool HasPermission(ClientPermissions permission) { - return false; //Permissions.HasFlag(permission); + return this.Permissions.HasFlag(permission); } public T GetVote(VoteType voteType) diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index 5ccd254b3..5c5844c19 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -20,7 +20,7 @@ namespace Barotrauma.Networking private GUIButton endRoundButton; private GUITickBox endVoteTickBox; - private ClientPermissions permissions; + private ClientPermissions permissions = ClientPermissions.None; private bool connected; @@ -646,7 +646,7 @@ namespace Barotrauma.Networking { GameMain.NetLobbyScreen.LastUpdateID = inc.ReadUInt32(); GameMain.NetLobbyScreen.ServerName = inc.ReadString(); - GameMain.NetLobbyScreen.ServerMessage = inc.ReadString(); + GameMain.NetLobbyScreen.ServerMessage.Text = inc.ReadString(); UInt16 subListCount = inc.ReadUInt16(); if (subListCount > 0) @@ -824,7 +824,7 @@ namespace Barotrauma.Networking public bool HasPermission(ClientPermissions permission) { - return false;// permissions.HasFlag(permission); + return permissions.HasFlag(permission); } public override void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch) @@ -921,7 +921,7 @@ namespace Barotrauma.Networking return true; } - + public bool VoteForKick(GUIButton button, object userdata) { var votedClient = otherClients.Find(c => c.Character == userdata); diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index 7c8ce07d0..e05cca670 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -58,6 +58,8 @@ namespace Barotrauma.Networking name = name.Replace(":", ""); name = name.Replace(";", ""); + AdminAuthPass = ""; + this.name = name; this.password = ""; if (password.Length>0) @@ -193,8 +195,8 @@ namespace Barotrauma.Networking { restClient = new RestClient(NetConfig.MasterServerUrl); } - - var request = new RestRequest("masterserver2.php", Method.GET); + + var request = new RestRequest("masterserver3.php", Method.GET); request.AddParameter("action", "addserver"); request.AddParameter("servername", name); request.AddParameter("serverport", Port); @@ -229,7 +231,7 @@ namespace Barotrauma.Networking restClient = new RestClient(NetConfig.MasterServerUrl); } - var request = new RestRequest("masterserver2.php", Method.GET); + var request = new RestRequest("masterserver3.php", Method.GET); request.AddParameter("action", "refreshserver"); request.AddParameter("gamestarted", gameStarted ? 1 : 0); request.AddParameter("currplayers", connectedClients.Count); @@ -269,6 +271,14 @@ namespace Barotrauma.Networking { masterServerResponded = true; + if (response.Content=="Error: server not found") + { + Log("Not registered to master server, re-registering...", Color.Red); + + RegisterToMasterServer(); + return; + } + if (response.ErrorException != null) { DebugConsole.NewMessage("Error while registering to master server (" + response.ErrorException + ")", Color.Red); @@ -286,6 +296,14 @@ namespace Barotrauma.Networking Log("Master server responded", Color.Cyan); } + public override void AddToGUIUpdateList() + { + if (started) base.AddToGUIUpdateList(); + + if (settingsFrame != null) settingsFrame.AddToGUIUpdateList(); + if (log.LogFrame != null) log.LogFrame.AddToGUIUpdateList(); + } + public override void Update(float deltaTime) { if (ShowNetStats) netStats.Update(deltaTime); @@ -705,7 +723,7 @@ namespace Barotrauma.Networking outmsg.WritePadBits(); outmsg.Write(GameMain.NetLobbyScreen.LastUpdateID); outmsg.Write(GameMain.NetLobbyScreen.GetServerName()); - outmsg.Write(GameMain.NetLobbyScreen.ServerMessage); + outmsg.Write(GameMain.NetLobbyScreen.ServerMessage.Text); var subList = GameMain.NetLobbyScreen.GetSubList(); if (c.lastRecvGeneralUpdate < 1) { @@ -1051,7 +1069,7 @@ namespace Barotrauma.Networking } } - CoroutineManager.StartCoroutine(EndCinematic()); + CoroutineManager.StartCoroutine(EndCinematic(),"EndCinematic"); } public IEnumerable EndCinematic() @@ -1462,6 +1480,7 @@ namespace Barotrauma.Networking public override void Disconnect() { banList.Save(); + SaveSettings(); if (registeredToMaster && restClient != null) { diff --git a/Subsurface/Source/Networking/GameServerSettings.cs b/Subsurface/Source/Networking/GameServerSettings.cs index 5798268aa..ae14dd0bb 100644 --- a/Subsurface/Source/Networking/GameServerSettings.cs +++ b/Subsurface/Source/Networking/GameServerSettings.cs @@ -63,6 +63,20 @@ namespace Barotrauma.Networking private string password; + private string adminAuthPass = ""; + public string AdminAuthPass + { + set + { + DebugConsole.NewMessage("Admin auth pass changed!",Color.Yellow); + adminAuthPass = ""; + if (value.Length > 0) + { + adminAuthPass = Encoding.UTF8.GetString(Lidgren.Network.NetUtility.ComputeSHAHash(Encoding.UTF8.GetBytes(value))); + } + } + } + private GUIFrame settingsFrame; private GUIFrame[] settingsTabs; private int settingsTabIndex; @@ -189,7 +203,8 @@ namespace Barotrauma.Networking { get { return banList; } } - + + [HasDefaultValue(true, true)] public bool AllowVoteKick { get; @@ -219,6 +234,13 @@ namespace Barotrauma.Networking doc.Root.SetAttributeValue("SubSelection", subSelectionMode.ToString()); doc.Root.SetAttributeValue("ModeSelection", modeSelectionMode.ToString()); + doc.Root.SetAttributeValue("TraitorsEnabled", TraitorsEnabled.ToString()); + + if (GameMain.NetLobbyScreen != null && GameMain.NetLobbyScreen.ServerMessage != null) + { + doc.Root.SetAttributeValue("ServerMessage", GameMain.NetLobbyScreen.ServerMessage); + } + XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.NewLineOnAttributes = true; @@ -251,7 +273,17 @@ namespace Barotrauma.Networking modeSelectionMode = SelectionMode.Manual; Enum.TryParse(ToolBox.GetAttributeString(doc.Root, "ModeSelection", "Manual"), out modeSelectionMode); Voting.AllowModeVoting = modeSelectionMode == SelectionMode.Vote; + + var traitorsEnabled = TraitorsEnabled; + Enum.TryParse(ToolBox.GetAttributeString(doc.Root, "TraitorsEnabled", "No"), out traitorsEnabled); + TraitorsEnabled = traitorsEnabled; + GameMain.NetLobbyScreen.SetTraitorsEnabled(traitorsEnabled); + if (GameMain.NetLobbyScreen != null && GameMain.NetLobbyScreen.ServerMessage != null) + { + GameMain.NetLobbyScreen.ServerMessage.Text = ToolBox.GetAttributeString(doc.Root, "ServerMessage", ""); + } + showLogButton.Visible = SaveServerLogs; List monsterNames = Directory.GetDirectories("Content/Characters").ToList(); diff --git a/Subsurface/Source/Networking/NetworkMember.cs b/Subsurface/Source/Networking/NetworkMember.cs index f9bdf3edc..87752201c 100644 --- a/Subsurface/Source/Networking/NetworkMember.cs +++ b/Subsurface/Source/Networking/NetworkMember.cs @@ -282,6 +282,14 @@ namespace Barotrauma.Networking public virtual void KickPlayer(string kickedName, bool ban, bool range = false) { } + public virtual void AddToGUIUpdateList() + { + if (gameStarted && Screen.Selected == GameMain.GameScreen) + { + inGameHUD.AddToGUIUpdateList(); + } + } + public virtual void Update(float deltaTime) { if (gameStarted && Screen.Selected == GameMain.GameScreen) diff --git a/Subsurface/Source/Networking/RespawnManager.cs b/Subsurface/Source/Networking/RespawnManager.cs index 3ec9cd424..0d0178024 100644 --- a/Subsurface/Source/Networking/RespawnManager.cs +++ b/Subsurface/Source/Networking/RespawnManager.cs @@ -412,6 +412,7 @@ namespace Barotrauma.Networking bool myCharacter = i >= clients.Count; var character = Character.Create(characterInfos[i], shuttleSpawnPoints[i].WorldPosition, !myCharacter, false); + character.TeamID = 1; if (myCharacter) { diff --git a/Subsurface/Source/Particles/Particle.cs b/Subsurface/Source/Particles/Particle.cs index d2c65e0f8..9ac4d7b0c 100644 --- a/Subsurface/Source/Particles/Particle.cs +++ b/Subsurface/Source/Particles/Particle.cs @@ -226,9 +226,9 @@ namespace Barotrauma.Particles private void ApplyDrag(float dragCoefficient, float deltaTime) { - if (velocity == Vector2.Zero) return; - + 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); } diff --git a/Subsurface/Source/Particles/ParticleManager.cs b/Subsurface/Source/Particles/ParticleManager.cs index 6bec2ccc1..40adebd87 100644 --- a/Subsurface/Source/Particles/ParticleManager.cs +++ b/Subsurface/Source/Particles/ParticleManager.cs @@ -109,7 +109,18 @@ namespace Barotrauma.Particles { for (int i = 0; i < particleCount; i++) { - if (!particles[i].Update(deltaTime)) RemoveParticle(i); + bool remove = false; + try + { + remove = !particles[i].Update(deltaTime); + } + catch (Exception e) + { + DebugConsole.ThrowError("Particle update failed", e); + remove = true; + } + + if (remove) RemoveParticle(i); } } diff --git a/Subsurface/Source/Screens/EditMapScreen.cs b/Subsurface/Source/Screens/EditMapScreen.cs index dbbb7f982..7e341b409 100644 --- a/Subsurface/Source/Screens/EditMapScreen.cs +++ b/Subsurface/Source/Screens/EditMapScreen.cs @@ -25,6 +25,8 @@ namespace Barotrauma private GUITextBox nameBox; + private GUIFrame hullVolumeFrame; + const int PreviouslyUsedCount = 10; private GUIListBox previouslyUsedList; @@ -63,6 +65,41 @@ namespace Barotrauma return "Structures: " + (MapEntity.mapEntityList.Count - Item.ItemList.Count); } + private string GetTotalHullVolume() + { + float totalVol = 0.0f; + Hull.hullList.ForEach(h => { totalVol += h.FullVolume; }); + return "Total Hull Volume:\n" + totalVol; + } + + private string GetSelectedHullVolume() + { + float buoyancyVol = 0.0f; + float selectedVol = 0.0f; + float neutralPercentage = 0.07f; + Hull.hullList.ForEach(h => { + buoyancyVol += h.FullVolume; + if (h.IsSelected) + { + selectedVol += h.FullVolume; + } + }); + buoyancyVol *= neutralPercentage; + string retVal = "Selected Hull Volume:\n" + selectedVol; + if (selectedVol>0.0f && buoyancyVol>0.0f) + { + if (buoyancyVol / selectedVol < 1.0f) + { + retVal += " (optimal NeutralBallastLevel is " + (buoyancyVol / selectedVol).ToString("0.00") + ")"; + } + else + { + retVal += " (insufficient volume for buoyancy control)"; + } + } + return retVal; + } + private string GetPhysicsBodyCount() { return "Physics bodies: " + GameMain.World.BodyList.Count; @@ -89,6 +126,16 @@ namespace Barotrauma topPanel = new GUIFrame(new Rectangle(0, 0, 0, 31), GUI.Style); topPanel.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); + hullVolumeFrame = new GUIFrame(new Rectangle(145, 26, 280, 70), GUI.Style, topPanel); + hullVolumeFrame.Visible = false; + hullVolumeFrame.Padding = new Vector4(3.0f, 3.0f, 3.0f, 3.0f); + + GUITextBlock totalHullVolume = new GUITextBlock(new Rectangle(0, 0, 0, 20), "", GUI.Style, hullVolumeFrame, GUI.SmallFont); + totalHullVolume.TextGetter = GetTotalHullVolume; + + GUITextBlock selectedHullVolume = new GUITextBlock(new Rectangle(0, 30, 0, 20), "", GUI.Style, hullVolumeFrame, GUI.SmallFont); + selectedHullVolume.TextGetter = GetSelectedHullVolume; + var button = new GUIButton(new Rectangle(0, 0, 70, 20), "Open...", GUI.Style, topPanel); button.OnClicked = CreateLoadScreen; @@ -250,8 +297,8 @@ namespace Barotrauma public override void Select() { base.Select(); - - GUIComponent.MouseOn = null; + + GUIComponent.ForceMouseOn(null); characterMode = false; if (Submarine.MainSub != null) @@ -278,7 +325,7 @@ namespace Barotrauma { base.Deselect(); - GUIComponent.MouseOn = null; + GUIComponent.ForceMouseOn(null); MapEntityPrefab.Selected = null; @@ -298,7 +345,7 @@ namespace Barotrauma private void CreateDummyCharacter() { - if (dummyCharacter != null) dummyCharacter.Remove(); + if (dummyCharacter != null) RemoveDummyCharacter(); dummyCharacter = Character.Create(Character.HumanConfigFile, Vector2.Zero); @@ -588,7 +635,7 @@ namespace Barotrauma characterMode = !characterMode; //button.Color = (characterMode) ? Color.Gold : Color.White; - wiringMode = false; + wiringMode = false; if (characterMode) { @@ -602,7 +649,6 @@ namespace Barotrauma foreach (MapEntity me in MapEntity.mapEntityList) { me.IsHighlighted = false; - me.IsSelected = false; } return true; @@ -658,7 +704,7 @@ namespace Barotrauma private GUIFrame CreateWiringPanel() { - GUIFrame frame = new GUIFrame(new Rectangle(0,0,50,300), null, Alignment.Right | Alignment.CenterY, GUI.Style); + GUIFrame frame = new GUIFrame(new Rectangle(0,0,65,300), null, Alignment.Right | Alignment.CenterY, GUI.Style); frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); GUIListBox listBox = new GUIListBox(Rectangle.Empty, GUI.Style, frame); @@ -769,7 +815,7 @@ namespace Barotrauma MapEntityPrefab.SelectPrefab(obj); selectedTab = -1; - GUIComponent.MouseOn = null; + GUIComponent.ForceMouseOn(null); return false; } @@ -804,6 +850,43 @@ namespace Barotrauma previouslyUsedList.children.Insert(0, textBlock); } + public override void AddToGUIUpdateList() + { + if (tutorial != null) tutorial.AddToGUIUpdateList(); + + if (MapEntity.SelectedList.Count == 1) + { + MapEntity.SelectedList[0].AddToGUIUpdateList(); + } + + leftPanel.AddToGUIUpdateList(); + topPanel.AddToGUIUpdateList(); + + if (wiringMode) + { + wiringToolPanel.AddToGUIUpdateList(); + } + + if (loadFrame != null) + { + loadFrame.AddToGUIUpdateList(); + } + else if (saveFrame != null) + { + saveFrame.AddToGUIUpdateList(); + } + else if (selectedTab > -1) + { + GUItabs[selectedTab].AddToGUIUpdateList(); + } + + if ((characterMode || wiringMode) && dummyCharacter != null) + { + CharacterHUD.AddToGUIUpdateList(dummyCharacter); + } + + GUI.AddToGUIUpdateList(); + } /// /// Allows the game to run logic such as updating the world, @@ -814,15 +897,11 @@ namespace Barotrauma { if (tutorial != null) tutorial.Update((float)deltaTime); + hullVolumeFrame.Visible = MapEntity.SelectedList.Any(s => s is Hull); + if (GUIComponent.MouseOn == null) { - //if (nameBox.Selected && PlayerInput.LeftButtonClicked()) - //{ - // ChangeSubName(nameBox, nameBox.Text); - //} - cam.MoveCamera((float)deltaTime); - //cam.Zoom = MathHelper.Clamp(cam.Zoom + (PlayerInput.ScrollWheelSpeed / 1000.0f)*cam.Zoom, 0.1f, 2.0f); } if (characterMode || wiringMode) @@ -845,6 +924,7 @@ namespace Barotrauma { limb.body.SetTransform(mouseSimPos, 0.0f); } + dummyCharacter.AnimController.Collider.SetTransform(mouseSimPos, 0.0f); } dummyCharacter.ControlLocalPlayer((float)deltaTime, cam, false); @@ -853,22 +933,20 @@ namespace Barotrauma dummyCharacter.Submarine = Submarine.MainSub; cam.TargetPos = Vector2.Zero; - } } else { - MapEntity.UpdateSelecting(cam); } - GUIComponent.MouseOn = null; + //GUIComponent.ForceMouseOn(null); if (!characterMode && !wiringMode) { if (MapEntityPrefab.Selected != null) MapEntityPrefab.Selected.UpdatePlacing(cam); - - MapEntity.UpdateEditor(cam); + + MapEntity.UpdateEditor(cam); } leftPanel.Update((float)deltaTime); @@ -906,9 +984,10 @@ namespace Barotrauma foreach (Item item in dummyCharacter.SelectedItems) { if (item == null) continue; - item.SetTransform(dummyCharacter.SimPosition, 0.0f); + item.SetTransform(dummyCharacter.SimPosition, 0.0f); item.Update(cam, (float)deltaTime); + item.SetTransform(item.body.SimPosition, 0.0f); } if (dummyCharacter.SelectedConstruction != null) diff --git a/Subsurface/Source/Screens/GameScreen.cs b/Subsurface/Source/Screens/GameScreen.cs index 62dce6099..9a4f81cdb 100644 --- a/Subsurface/Source/Screens/GameScreen.cs +++ b/Subsurface/Source/Screens/GameScreen.cs @@ -90,7 +90,22 @@ namespace Barotrauma Sounds.SoundManager.LowPassHFGain = 1.0f; } - + + public override void AddToGUIUpdateList() + { + if (Character.Controlled != null && Character.Controlled.SelectedConstruction != null) + { + if (Character.Controlled.SelectedConstruction == Character.Controlled.ClosestItem) + { + Character.Controlled.SelectedConstruction.AddToGUIUpdateList(); + } + } + + if (GameMain.GameSession != null) GameMain.GameSession.AddToGUIUpdateList(); + + Character.AddAllToGUIUpdateList(); + } + /// /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. @@ -117,6 +132,11 @@ namespace Barotrauma } #endif + foreach (MapEntity e in MapEntity.mapEntityList) + { + e.IsHighlighted = false; + } + if (GameMain.GameSession != null) GameMain.GameSession.Update((float)deltaTime); if (Level.Loaded != null) Level.Loaded.Update((float)deltaTime); @@ -129,7 +149,7 @@ namespace Barotrauma } } Character.UpdateAll(cam, (float)deltaTime); - + BackgroundCreatureManager.Update(cam, (float)deltaTime); GameMain.ParticleManager.Update((float)deltaTime); @@ -220,22 +240,6 @@ namespace Barotrauma GameMain.LightManager.UpdateObstructVision(graphics, spriteBatch, cam, Character.Controlled.CursorWorldPosition); } - List visibleSubs = new List(); - foreach (Submarine sub in Submarine.Loaded) - { - Rectangle worldBorders = new Rectangle( - sub.Borders.X + (int)sub.WorldPosition.X - 500, - sub.Borders.Y + (int)sub.WorldPosition.Y + 500, - sub.Borders.Width + 1000, - sub.Borders.Height + 1000); - - - if (Submarine.RectsOverlap(worldBorders, cam.WorldView)) - { - visibleSubs.Add(sub); - } - } - //---------------------------------------------------------------------------------------- //1. draw the background, characters and the parts of the submarine that are behind them //---------------------------------------------------------------------------------------- diff --git a/Subsurface/Source/Screens/LobbyScreen.cs b/Subsurface/Source/Screens/LobbyScreen.cs index 6052ae1d8..50fb6747f 100644 --- a/Subsurface/Source/Screens/LobbyScreen.cs +++ b/Subsurface/Source/Screens/LobbyScreen.cs @@ -341,6 +341,14 @@ namespace Barotrauma return false; } + public override void AddToGUIUpdateList() + { + base.AddToGUIUpdateList(); + + topPanel.AddToGUIUpdateList(); + bottomPanel[selectedRightPanel].AddToGUIUpdateList(); + } + public override void Update(double deltaTime) { base.Update(deltaTime); diff --git a/Subsurface/Source/Screens/MainMenuScreen.cs b/Subsurface/Source/Screens/MainMenuScreen.cs index d3d5e36df..d94a3a92d 100644 --- a/Subsurface/Source/Screens/MainMenuScreen.cs +++ b/Subsurface/Source/Screens/MainMenuScreen.cs @@ -467,6 +467,12 @@ namespace Barotrauma menuTabs[(int)Tab.LoadGame].RemoveChild(prevFrame); } + public override void AddToGUIUpdateList() + { + buttonsTab.AddToGUIUpdateList(); + if (selectedTab > 0) menuTabs[selectedTab].AddToGUIUpdateList(); + } + public override void Update(double deltaTime) { //GameMain.TitleScreen.Update(); diff --git a/Subsurface/Source/Screens/NetLobbyScreen.cs b/Subsurface/Source/Screens/NetLobbyScreen.cs index 832087ea2..aaa241141 100644 --- a/Subsurface/Source/Screens/NetLobbyScreen.cs +++ b/Subsurface/Source/Screens/NetLobbyScreen.cs @@ -9,6 +9,8 @@ using FarseerPhysics.Dynamics; using System.IO; using System.Linq; using System.Collections.Generic; +using System.Reflection; +using System.ComponentModel; namespace Barotrauma { @@ -61,10 +63,15 @@ namespace Barotrauma private Sprite backgroundSprite; private GUITextBox serverMessage; - public string ServerMessage + //public string ServerMessage + //{ + // get { return serverMessage.Text; } + // set { if (GameMain.Server != null) return; serverMessage.Text = value; } + //} + + public GUITextBox ServerMessage { - get { return serverMessage.Text; } - set { if (GameMain.Server != null) return; serverMessage.Text = value; } + get { return serverMessage; } } public GUIListBox SubList @@ -793,12 +800,12 @@ namespace Barotrauma } } - playerFrame = new GUIFrame(new Rectangle(0, 0, 0, 0), Color.Black * 0.3f); + playerFrame = new GUIFrame(new Rectangle(0, 0, 0, 0), Color.Black * 0.6f); - var playerFrameInner = new GUIFrame(new Rectangle(0, 0, 300, 250), null, Alignment.Center, GUI.Style, playerFrame); + var playerFrameInner = new GUIFrame(new Rectangle(0, 0, 300, 280), null, Alignment.Center, GUI.Style, playerFrame); playerFrameInner.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f); - new GUITextBlock(new Rectangle(0,0,200,20), component.UserData.ToString(), + new GUITextBlock(new Rectangle(0, 0, 200, 20), component.UserData.ToString(), GUI.Style, Alignment.TopLeft, Alignment.TopLeft, playerFrameInner, false, GUI.LargeFont); @@ -808,50 +815,50 @@ namespace Barotrauma new GUITextBlock(new Rectangle(0, 25, 150, 15), selectedClient.Connection.RemoteEndPoint.Address.ToString(), GUI.Style, playerFrameInner); - //var permissionsBox = new GUIFrame(new Rectangle(0, 60, 0, 85), GUI.Style, playerFrameInner); - //permissionsBox.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); - //permissionsBox.UserData = selectedClient; + var permissionsBox = new GUIFrame(new Rectangle(0, 60, 0, 90), GUI.Style, playerFrameInner); + permissionsBox.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); + permissionsBox.UserData = selectedClient; - //new GUITextBlock(new Rectangle(0, 0, 0, 15), "Permissions:", GUI.Style, permissionsBox); - //int x = 0, y = 0; - //foreach (ClientPermissions permission in Enum.GetValues(typeof(ClientPermissions))) - //{ - // if (permission == ClientPermissions.None) continue; + new GUITextBlock(new Rectangle(0, 0, 0, 15), "Permissions:", GUI.Style, permissionsBox); + int x = 0, y = 0; + foreach (ClientPermissions permission in Enum.GetValues(typeof(ClientPermissions))) + { + if (permission == ClientPermissions.None) continue; - // FieldInfo fi = typeof(ClientPermissions).GetField(permission.ToString()); - // DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); + FieldInfo fi = typeof(ClientPermissions).GetField(permission.ToString()); + DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); - // string permissionStr = attributes.Length > 0 ? attributes[0].Description : permission.ToString(); - - // var permissionTick = new GUITickBox(new Rectangle(x,y+20,15,15), permissionStr, Alignment.TopLeft, GUI.SmallFont, permissionsBox); - // permissionTick.UserData = permission; - // permissionTick.Selected = selectedClient.HasPermission(permission); + string permissionStr = attributes.Length > 0 ? attributes[0].Description : permission.ToString(); - // permissionTick.OnSelected = (tickBox) => - // { - // var client = tickBox.Parent.UserData as Client; - // if (client == null) return false; + var permissionTick = new GUITickBox(new Rectangle(x, y + 20, 15, 15), permissionStr, Alignment.TopLeft, GUI.SmallFont, permissionsBox); + permissionTick.UserData = permission; + permissionTick.Selected = selectedClient.HasPermission(permission); - // var thisPermission = (ClientPermissions)tickBox.UserData; + permissionTick.OnSelected = (tickBox) => + { + var client = tickBox.Parent.UserData as Client; + if (client == null) return false; - // if (tickBox.Selected) - // client.GivePermission(thisPermission); - // else - // client.RemovePermission(thisPermission); + var thisPermission = (ClientPermissions)tickBox.UserData; - // GameMain.Server.UpdateClientPermissions(client); + if (tickBox.Selected) + client.GivePermission(thisPermission); + else + client.RemovePermission(thisPermission); - // return true; - // }; + GameMain.Server.UpdateClientPermissions(client); + + return true; + }; - // y += 20; - // if (y >= permissionsBox.Rect.Height -20) - // { - // y = 0; - // x += 100; - // } - //} + y += 20; + if (y >= permissionsBox.Rect.Height-40) + { + y = 0; + x += 100; + } + } } if (GameMain.Server != null || GameMain.Client.HasPermission(ClientPermissions.Kick)) @@ -941,6 +948,24 @@ namespace Barotrauma playerList.ClearChildren(); } + public override void AddToGUIUpdateList() + { + base.AddToGUIUpdateList(); + + if (jobInfoFrame != null) + { + jobInfoFrame.AddToGUIUpdateList(); + } + else if (playerFrame != null) + { + playerFrame.AddToGUIUpdateList(); + } + else + { + menu.AddToGUIUpdateList(); + } + } + public override void Update(double deltaTime) { base.Update(deltaTime); diff --git a/Subsurface/Source/Screens/Screen.cs b/Subsurface/Source/Screens/Screen.cs index 0f69e280d..a57a06007 100644 --- a/Subsurface/Source/Screens/Screen.cs +++ b/Subsurface/Source/Screens/Screen.cs @@ -33,6 +33,10 @@ namespace Barotrauma get { return null; } } + public virtual void AddToGUIUpdateList() + { + } + public virtual void Update(double deltaTime) { } diff --git a/Subsurface/Source/Screens/ServerListScreen.cs b/Subsurface/Source/Screens/ServerListScreen.cs index 1b3c88d5a..b9891b09e 100644 --- a/Subsurface/Source/Screens/ServerListScreen.cs +++ b/Subsurface/Source/Screens/ServerListScreen.cs @@ -334,6 +334,11 @@ namespace Barotrauma spriteBatch.End(); } + public override void AddToGUIUpdateList() + { + menu.AddToGUIUpdateList(); + } + public override void Update(double deltaTime) { //GameMain.TitleScreen.Update(); diff --git a/Subsurface/Source/Sounds/SoundPlayer.cs b/Subsurface/Source/Sounds/SoundPlayer.cs index 4fbe35629..9053d899e 100644 --- a/Subsurface/Source/Sounds/SoundPlayer.cs +++ b/Subsurface/Source/Sounds/SoundPlayer.cs @@ -314,7 +314,7 @@ namespace Barotrauma { return musicClips.Where(x => x != null && x.type == OverrideMusicType).ToList(); } - else if (Character.Controlled != null && Level.Loaded != null && Level.Loaded.Ruins.Any(r => r.Area.Contains(Character.Controlled.WorldPosition))) + 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(); } diff --git a/Subsurface/Source/Sprite.cs b/Subsurface/Source/Sprite.cs index b0b41696f..2f377e951 100644 --- a/Subsurface/Source/Sprite.cs +++ b/Subsurface/Source/Sprite.cs @@ -379,7 +379,11 @@ namespace Barotrauma } //if not, free the texture - texture.Dispose(); + if (texture != null) + { + texture.Dispose(); + texture = null; + } } } diff --git a/Subsurface/Source/Utils/ToolBox.cs b/Subsurface/Source/Utils/ToolBox.cs index 30cffdc35..decd88e39 100644 --- a/Subsurface/Source/Utils/ToolBox.cs +++ b/Subsurface/Source/Utils/ToolBox.cs @@ -27,11 +27,55 @@ namespace Barotrauma public static class ToolBox { + public static bool IsProperFilenameCase(string filename) + { + char[] delimiters = { '/','\\' }; + string[] subDirs = filename.Split(delimiters); + string originalFilename = filename; + filename = ""; + + for (int i=0;i s.Equals(filename + subDirs[i + 1], StringComparison.Ordinal))) + { + return true; + } + else if (filePaths.Any(s => s.Equals(filename + subDirs[i + 1], StringComparison.OrdinalIgnoreCase))) + { + DebugConsole.ThrowError(originalFilename + " has incorrect case!"); + return false; + } + } + + string[] dirPaths = Directory.GetDirectories(filename); + + if (!dirPaths.Any(s => s.Equals(filename+subDirs[i+1],StringComparison.Ordinal))) + { + if (dirPaths.Any(s => s.Equals(filename + subDirs[i + 1], StringComparison.OrdinalIgnoreCase))) + { + DebugConsole.ThrowError(originalFilename + " has incorrect case!"); + } + else + { + DebugConsole.ThrowError(originalFilename + " doesn't exist!"); + } + return false; + } + } + return true; + } + public static XDocument TryLoadXml(string filePath) { XDocument doc; try { + IsProperFilenameCase(filePath); doc = XDocument.Load(filePath); } catch (Exception e) @@ -276,7 +320,7 @@ namespace Barotrauma if (components.Length!=3) { if (!errorMessages) return vector; - DebugConsole.ThrowError("Failed to parse the string ''"+stringVector3+"'' to Vector3"); + DebugConsole.ThrowError("Failed to parse the string \""+stringVector3+"\" to Vector3"); return vector; } diff --git a/Subsurface/changelog.txt b/Subsurface/changelog.txt index 2493dfda0..b13ee2981 100644 --- a/Subsurface/changelog.txt +++ b/Subsurface/changelog.txt @@ -1,3 +1,59 @@ +--------------------------------------------------------------------------------------------------------- +v0.5.4.0 +--------------------------------------------------------------------------------------------------------- + +Submarine editor: + - copy, paste and cut functionality + - items/structures can be copied by holding ctrl while dragging + - it's possible to move a wire by moving both items it's connected to (without having to move each + individual point of the wire separately) + - "hull volume helper" which makes it easier to select a suitable ballast tank size and + NeutralBallastLevel setting in the navigation terminal + - equipped items are removed when switching from wiring mode to character mode or vice versa + - no need to wait when deattaching items from the walls with a wrench + + +Bugfixes: + - wires are now positioned correctly in mirrored subs + - UI elements (buttons, textboxes, etc) can't be clicked through each other anymore + - fixed a bug that caused crashes when deattaching items from walls + - fixed a game-crashing particle bug + - fixed respawned characters getting assigned to a different team than the rest of the characters + (causing them to be displayed separately in the crew menu) + - pathfinding/autopilot fixes + +Misc: + - server hosts can give players special privileges (kick, ban, end round) + - saving the contents of the server info box and the traitor setting + - changes to battery logic: they can now be used to cover the entire power consumption of the + electrical grid (assuming their maximum output is high enough) + - added "artifact holders" to alien ruins (which can also be used for turning artifacts into power + sources if installed in a sub) + - changes to character collider behavior: crouching changes the size of the collider and it's + easier to step over small obstacles + + +--------------------------------------------------------------------------------------------------------- +v0.5.3.4 +--------------------------------------------------------------------------------------------------------- + +- fixed screen turning black in the tutorial +- the moloch attack in the tutorial is now much easier to survive +- servers readd themselves to the master server if they have been removed from the server list +- fixed a bug that caused lights to flicker even if there's enough power +- fixed items disappearing when dropping them in the submarine editor + +--------------------------------------------------------------------------------------------------------- +v0.5.3.3 +--------------------------------------------------------------------------------------------------------- + +- fixed a bug that caused crashes after a husk-infected player died +- disabled the "zoom effect" when under pressure as a huskified human +- only a limited number of messages are kept in the debug console (prevents performance issues if large +amounts of messages are added) +- some item and electricity logic optimization +- fixed "sprite tigerthresher not found" errors in the Linux version + --------------------------------------------------------------------------------------------------------- v0.5.3.2 ---------------------------------------------------------------------------------------------------------