diff --git a/Launcher2/LauncherMain.cs b/Launcher2/LauncherMain.cs index b8d166735..ea862f64d 100644 --- a/Launcher2/LauncherMain.cs +++ b/Launcher2/LauncherMain.cs @@ -202,6 +202,10 @@ namespace Launcher2 } } + GUIComponent.ClearUpdateList(); + guiRoot.AddToGUIUpdateList(); + GUIComponent.UpdateMouseOn(); + guiRoot.Update(deltaTime); } @@ -296,24 +300,30 @@ namespace Launcher2 { updateInfoBox.ClearChildren(); - //string wrappedText = ToolBox.WrapText(text, updateInfoBox.Rect.Width, GUI.SmallFont); - - //int lineHeight = (int)GUI.SmallFont.MeasureString(" ").Y; - string[] lines = text.Split('\n'); foreach (string line in lines) { - if (string.IsNullOrWhiteSpace(line)) continue; - + int indent = 10; + int heigth = 0; + if (!string.IsNullOrWhiteSpace(line)) + { + if (line[0] == '-') + indent = 20; + } + else + { + heigth = 5; + } + GUITextBlock textBlock = new GUITextBlock( - new Rectangle(0,0,0,0), + new Rectangle(indent, 0, 0, heigth), line, GUI.Style, Alignment.TopLeft, Alignment.TopLeft, updateInfoBox, true, GUI.SmallFont); + textBlock.Padding = new Vector4(indent, 0, 0, 0); + textBlock.TextColor = indent > 10 ? Color.LightGray : Color.White; textBlock.CanBeFocused = false; } - - } private bool CheckForUpdates() @@ -410,7 +420,7 @@ namespace Launcher2 if (currentVersion.CompareTo(latestVersion) >= 0) { - updateInfoText.Text = "Game is up to date!"; + updateInfoText.Text = "Your game is up to date!"; return false; } @@ -439,9 +449,14 @@ namespace Launcher2 string innerText = ToolBox.ElementInnerText(patchNote); innerText = innerText.Replace("\r\n", "\n"); - sb.Append(innerText+"\n"); + innerText = innerText.Replace("\t", ""); + + sb.AppendLine("================================"); + sb.AppendLine(patchNumber); + sb.AppendLine("================================\n"); + + sb.AppendLine(innerText); - sb.AppendLine("----------------------------\n"); } SetUpdateInfoBox(sb.ToString()); @@ -577,7 +592,7 @@ namespace Launcher2 private void Completed(object sender, AsyncCompletedEventArgs e) { - if (e.Error!=null) + if (e.Error != null) { string errorMsg = "Error while downloading: " + e.Error; diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj index 81cae3f08..f0091efe5 100644 --- a/Subsurface/Barotrauma.csproj +++ b/Subsurface/Barotrauma.csproj @@ -92,6 +92,7 @@ + @@ -367,6 +368,13 @@ PreserveNewest + + PreserveNewest + + + Designer + PreserveNewest + PreserveNewest @@ -1092,9 +1100,33 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -1116,6 +1148,12 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -1131,6 +1169,21 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -1152,6 +1205,33 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -1284,6 +1364,57 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -1332,6 +1463,24 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -1383,6 +1532,21 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest diff --git a/Subsurface/Content/Characters/Carrier/alarm1.ogg b/Subsurface/Content/Characters/Carrier/alarm1.ogg new file mode 100644 index 000000000..f0d9d3b4d Binary files /dev/null and b/Subsurface/Content/Characters/Carrier/alarm1.ogg differ diff --git a/Subsurface/Content/Characters/Carrier/carrier.png b/Subsurface/Content/Characters/Carrier/carrier.png new file mode 100644 index 000000000..78c957814 Binary files /dev/null and b/Subsurface/Content/Characters/Carrier/carrier.png differ diff --git a/Subsurface/Content/Characters/Carrier/carrier.xml b/Subsurface/Content/Characters/Carrier/carrier.xml new file mode 100644 index 000000000..4ff3312d2 --- /dev/null +++ b/Subsurface/Content/Characters/Carrier/carrier.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Subsurface/Content/Characters/Carrier/carrier1.ogg b/Subsurface/Content/Characters/Carrier/carrier1.ogg new file mode 100644 index 000000000..fb049225a Binary files /dev/null and b/Subsurface/Content/Characters/Carrier/carrier1.ogg differ diff --git a/Subsurface/Content/Characters/Carrier/carrier2.ogg b/Subsurface/Content/Characters/Carrier/carrier2.ogg new file mode 100644 index 000000000..990eadd5f Binary files /dev/null and b/Subsurface/Content/Characters/Carrier/carrier2.ogg differ diff --git a/Subsurface/Content/Characters/Carrier/carrier3.ogg b/Subsurface/Content/Characters/Carrier/carrier3.ogg new file mode 100644 index 000000000..71c5fc00c Binary files /dev/null and b/Subsurface/Content/Characters/Carrier/carrier3.ogg differ diff --git a/Subsurface/Content/Characters/Carrier/ping.ogg b/Subsurface/Content/Characters/Carrier/ping.ogg new file mode 100644 index 000000000..ce361a7aa Binary files /dev/null and b/Subsurface/Content/Characters/Carrier/ping.ogg differ diff --git a/Subsurface/Content/Characters/Coelanth/attack1.ogg b/Subsurface/Content/Characters/Coelanth/attack1.ogg new file mode 100644 index 000000000..8985861ab Binary files /dev/null and b/Subsurface/Content/Characters/Coelanth/attack1.ogg differ diff --git a/Subsurface/Content/Characters/Coelanth/coelanth.xml b/Subsurface/Content/Characters/Coelanth/coelanth.xml index 369627839..4e820b397 100644 --- a/Subsurface/Content/Characters/Coelanth/coelanth.xml +++ b/Subsurface/Content/Characters/Coelanth/coelanth.xml @@ -1,9 +1,9 @@  - - - + + + diff --git a/Subsurface/Content/Characters/Coelanth/idle1.ogg b/Subsurface/Content/Characters/Coelanth/idle1.ogg new file mode 100644 index 000000000..079231c03 Binary files /dev/null and b/Subsurface/Content/Characters/Coelanth/idle1.ogg differ diff --git a/Subsurface/Content/Characters/Coelanth/idle2.ogg b/Subsurface/Content/Characters/Coelanth/idle2.ogg new file mode 100644 index 000000000..998f7769b Binary files /dev/null and b/Subsurface/Content/Characters/Coelanth/idle2.ogg differ diff --git a/Subsurface/Content/Characters/Fractalguardian/Die1.ogg b/Subsurface/Content/Characters/Fractalguardian/Die1.ogg new file mode 100644 index 000000000..a3786d9bc Binary files /dev/null and b/Subsurface/Content/Characters/Fractalguardian/Die1.ogg differ diff --git a/Subsurface/Content/Characters/Fractalguardian/Die2.ogg b/Subsurface/Content/Characters/Fractalguardian/Die2.ogg new file mode 100644 index 000000000..4e24f4425 Binary files /dev/null and b/Subsurface/Content/Characters/Fractalguardian/Die2.ogg differ diff --git a/Subsurface/Content/Characters/Fractalguardian/fractalguardian.xml b/Subsurface/Content/Characters/Fractalguardian/fractalguardian.xml index 86c561a70..69ad89036 100644 --- a/Subsurface/Content/Characters/Fractalguardian/fractalguardian.xml +++ b/Subsurface/Content/Characters/Fractalguardian/fractalguardian.xml @@ -3,6 +3,8 @@ + + diff --git a/Subsurface/Content/Characters/Fractalguardian2/fractalguardian2.xml b/Subsurface/Content/Characters/Fractalguardian2/fractalguardian2.xml index e1d743557..9f45de877 100644 --- a/Subsurface/Content/Characters/Fractalguardian2/fractalguardian2.xml +++ b/Subsurface/Content/Characters/Fractalguardian2/fractalguardian2.xml @@ -3,6 +3,8 @@ + + diff --git a/Subsurface/Content/Characters/Mantis/attack1.ogg b/Subsurface/Content/Characters/Mantis/attack1.ogg new file mode 100644 index 000000000..46084f03a Binary files /dev/null and b/Subsurface/Content/Characters/Mantis/attack1.ogg differ diff --git a/Subsurface/Content/Characters/Mantis/attack2.ogg b/Subsurface/Content/Characters/Mantis/attack2.ogg new file mode 100644 index 000000000..72de2e2e7 Binary files /dev/null and b/Subsurface/Content/Characters/Mantis/attack2.ogg differ diff --git a/Subsurface/Content/Characters/Mantis/idle1.ogg b/Subsurface/Content/Characters/Mantis/idle1.ogg new file mode 100644 index 000000000..261360518 Binary files /dev/null and b/Subsurface/Content/Characters/Mantis/idle1.ogg differ diff --git a/Subsurface/Content/Characters/Mantis/idle2.ogg b/Subsurface/Content/Characters/Mantis/idle2.ogg new file mode 100644 index 000000000..d1f349935 Binary files /dev/null and b/Subsurface/Content/Characters/Mantis/idle2.ogg differ diff --git a/Subsurface/Content/Characters/Mantis/idle3.ogg b/Subsurface/Content/Characters/Mantis/idle3.ogg new file mode 100644 index 000000000..03d2bd9bc Binary files /dev/null and b/Subsurface/Content/Characters/Mantis/idle3.ogg differ diff --git a/Subsurface/Content/Characters/Mantis/mantis.xml b/Subsurface/Content/Characters/Mantis/mantis.xml index 669325144..298d4c9e6 100644 --- a/Subsurface/Content/Characters/Mantis/mantis.xml +++ b/Subsurface/Content/Characters/Mantis/mantis.xml @@ -1,12 +1,13 @@  - - - - - + + + + + + + + + + + + + + + + + diff --git a/Subsurface/Content/Items/Artifacts/artifacts.xml b/Subsurface/Content/Items/Artifacts/artifacts.xml index 3a6b3ee62..2d7145c9a 100644 --- a/Subsurface/Content/Items/Artifacts/artifacts.xml +++ b/Subsurface/Content/Items/Artifacts/artifacts.xml @@ -227,11 +227,9 @@ - + - - - + diff --git a/Subsurface/Content/Items/Button/button.xml b/Subsurface/Content/Items/Button/button.xml index 87a5401bd..35954a92c 100644 --- a/Subsurface/Content/Items/Button/button.xml +++ b/Subsurface/Content/Items/Button/button.xml @@ -15,7 +15,7 @@ - + diff --git a/Subsurface/Content/Items/Electricity/poweritems.xml b/Subsurface/Content/Items/Electricity/poweritems.xml index 744d114e0..3a63ab3ef 100644 --- a/Subsurface/Content/Items/Electricity/poweritems.xml +++ b/Subsurface/Content/Items/Electricity/poweritems.xml @@ -50,7 +50,7 @@ - + @@ -59,7 +59,7 @@ - + diff --git a/Subsurface/Content/Items/Reactor/reactor.xml b/Subsurface/Content/Items/Reactor/reactor.xml index 7561565af..5d2d99079 100644 --- a/Subsurface/Content/Items/Reactor/reactor.xml +++ b/Subsurface/Content/Items/Reactor/reactor.xml @@ -39,7 +39,7 @@ - + diff --git a/Subsurface/Content/Items/Weapons/depthcharge.xml b/Subsurface/Content/Items/Weapons/depthcharge.xml index 31e9a2016..c3c31176c 100644 --- a/Subsurface/Content/Items/Weapons/depthcharge.xml +++ b/Subsurface/Content/Items/Weapons/depthcharge.xml @@ -45,7 +45,7 @@ - + diff --git a/Subsurface/Content/Items/Weapons/explosives.xml b/Subsurface/Content/Items/Weapons/explosives.xml index 8fd7dc4dc..57c683c19 100644 --- a/Subsurface/Content/Items/Weapons/explosives.xml +++ b/Subsurface/Content/Items/Weapons/explosives.xml @@ -91,7 +91,7 @@ - + diff --git a/Subsurface/Content/Items/Weapons/railgun.ogg b/Subsurface/Content/Items/Weapons/railgun.ogg index ea3128b57..8ff5c558c 100644 Binary files a/Subsurface/Content/Items/Weapons/railgun.ogg and b/Subsurface/Content/Items/Weapons/railgun.ogg differ diff --git a/Subsurface/Content/Items/Weapons/railgun.xml b/Subsurface/Content/Items/Weapons/railgun.xml index 5d5922029..2a6ee0ab8 100644 --- a/Subsurface/Content/Items/Weapons/railgun.xml +++ b/Subsurface/Content/Items/Weapons/railgun.xml @@ -34,8 +34,9 @@ - + + @@ -74,7 +75,7 @@ - + @@ -106,7 +107,7 @@ - + diff --git a/Subsurface/Content/Items/warningSiren.ogg b/Subsurface/Content/Items/warningSiren.ogg index bd8cb29d3..7f89d7239 100644 Binary files a/Subsurface/Content/Items/warningSiren.ogg and b/Subsurface/Content/Items/warningSiren.ogg differ diff --git a/Subsurface/Content/Map/StructurePrefabs.xml b/Subsurface/Content/Map/StructurePrefabs.xml index 92442cdf6..02a982966 100644 --- a/Subsurface/Content/Map/StructurePrefabs.xml +++ b/Subsurface/Content/Map/StructurePrefabs.xml @@ -108,22 +108,22 @@ - + - + - + - + diff --git a/Subsurface/Content/Map/background.png b/Subsurface/Content/Map/background.png index 3a0044f6b..923b03581 100644 Binary files a/Subsurface/Content/Map/background.png and b/Subsurface/Content/Map/background.png differ diff --git a/Subsurface/Content/Map/background2.png b/Subsurface/Content/Map/background2.png index 71a7675c7..9a5d8f8e3 100644 Binary files a/Subsurface/Content/Map/background2.png and b/Subsurface/Content/Map/background2.png differ diff --git a/Subsurface/Content/Missions.xml b/Subsurface/Content/Missions.xml index 6a615bd06..26d82d1f0 100644 --- a/Subsurface/Content/Missions.xml +++ b/Subsurface/Content/Missions.xml @@ -68,6 +68,17 @@ successmessage="It turns out the signal was emitted by a Moloch. The researchers of [location1] have agreed to pay you the reward nevertheless for getting rid of the Moloch." monsterfile="Content/Characters/Moloch/moloch.xml"> + + + + - + + + + + + + + @@ -30,16 +37,38 @@ - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Subsurface/Source/Camera.cs b/Subsurface/Source/Camera.cs index 1dca560a4..6f6c7aa6d 100644 --- a/Subsurface/Source/Camera.cs +++ b/Subsurface/Source/Camera.cs @@ -165,7 +165,7 @@ namespace Barotrauma } } - public void MoveCamera(float deltaTime) + public void MoveCamera(float deltaTime, bool allowMove = true, bool allowZoom = true) { prevPosition = position; prevZoom = zoom; @@ -175,7 +175,7 @@ namespace Barotrauma Vector2 moveCam = Vector2.Zero; if (targetPos == Vector2.Zero) { - if (GUIComponent.KeyboardDispatcher.Subscriber == null) + if (allowMove && GUIComponent.KeyboardDispatcher.Subscriber == null) { if (PlayerInput.KeyDown(Keys.LeftShift)) moveSpeed *= 2.0f; if (PlayerInput.KeyDown(Keys.LeftControl)) moveSpeed *= 0.5f; @@ -197,11 +197,14 @@ namespace Barotrauma moveCam = moveCam * deltaTime * 60.0f; - Vector2 mouseInWorld = ScreenToWorld(PlayerInput.MousePosition); - Vector2 diffViewCenter; - diffViewCenter = ((mouseInWorld - Position) * Zoom); - Zoom = MathHelper.Clamp(zoom + (PlayerInput.ScrollWheelSpeed / 1000.0f) * zoom, GameMain.DebugDraw ? 0.01f : 0.1f, 2.0f); - if (!PlayerInput.KeyDown(Keys.F)) Position = mouseInWorld - (diffViewCenter / Zoom); + if (allowZoom) + { + Vector2 mouseInWorld = ScreenToWorld(PlayerInput.MousePosition); + Vector2 diffViewCenter; + diffViewCenter = ((mouseInWorld - Position) * Zoom); + Zoom = MathHelper.Clamp(zoom + (PlayerInput.ScrollWheelSpeed / 1000.0f) * zoom, GameMain.DebugDraw ? 0.01f : 0.1f, 2.0f); + if (!PlayerInput.KeyDown(Keys.F)) Position = mouseInWorld - (diffViewCenter / Zoom); + } } else { diff --git a/Subsurface/Source/Characters/AICharacter.cs b/Subsurface/Source/Characters/AICharacter.cs index 8cd751d30..f653789b8 100644 --- a/Subsurface/Source/Characters/AICharacter.cs +++ b/Subsurface/Source/Characters/AICharacter.cs @@ -57,7 +57,15 @@ namespace Barotrauma } else { - PlaySound((aiController == null) ? AIController.AiState.None : aiController.State); + switch (aiController.State) + { + case AIController.AiState.Attack: + PlaySound(CharacterSound.SoundType.Attack); + break; + default: + PlaySound(CharacterSound.SoundType.Idle); + break; + } soundTimer = soundInterval; } diff --git a/Subsurface/Source/Characters/Animation/FishAnimController.cs b/Subsurface/Source/Characters/Animation/FishAnimController.cs index ee420f416..543339e16 100644 --- a/Subsurface/Source/Characters/Animation/FishAnimController.cs +++ b/Subsurface/Source/Characters/Animation/FishAnimController.cs @@ -205,15 +205,15 @@ namespace Barotrauma if (Limbs[i].SteerForce <= 0.0f) continue; Vector2 pullPos = Limbs[i].pullJoint == null ? Limbs[i].SimPosition : Limbs[i].pullJoint.WorldAnchorA; - Limbs[i].body.ApplyForce(movement * Limbs[i].SteerForce * Limbs[i].Mass, pullPos); + Limbs[i].body.ApplyForce(movement * Limbs[i].SteerForce * Limbs[i].Mass, pullPos); - if (Limbs[i] == MainLimb) continue; + /*if (Limbs[i] == MainLimb) continue; float dist = (MainLimb.SimPosition - Limbs[i].SimPosition).Length(); Vector2 limbPos = MainLimb.SimPosition - Vector2.Normalize(movement) * dist; - Limbs[i].body.ApplyForce(((limbPos - Limbs[i].SimPosition) * 3.0f - Limbs[i].LinearVelocity * 3.0f) * Limbs[i].Mass); + 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); diff --git a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs index e2fdb3ab2..84a864c36 100644 --- a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs @@ -173,12 +173,10 @@ namespace Barotrauma levitatingCollider = false; UpdateClimbing(); break; - case Animation.UsingConstruction: - UpdateStanding(); - break; case Animation.CPR: UpdateCPR(deltaTime); break; + case Animation.UsingConstruction: default: if (character.SelectedCharacter != null) DragCharacter(character.SelectedCharacter); @@ -260,9 +258,9 @@ namespace Barotrauma float slowdownAmount = 0.0f; if (currentHull != null) { - //full slowdown (1.0f) when water is up to the torso + //full slowdown (1.5f) when water is up to the torso surfaceY = ConvertUnits.ToSimUnits(currentHull.Surface); - slowdownAmount = MathHelper.Clamp((surfaceY - colliderPos.Y) / torsoPosition, 0.0f, 1.0f); + slowdownAmount = MathHelper.Clamp((surfaceY - colliderPos.Y) / torsoPosition, 0.0f, 1.0f) * 1.5f; } float maxSpeed = Math.Max(TargetMovement.Length() - slowdownAmount, 1.0f); @@ -272,7 +270,7 @@ namespace Barotrauma float walkPosX = (float)Math.Cos(walkPos); float walkPosY = (float)Math.Sin(walkPos); float runningModifier = (float)Math.Max(Math.Min(Math.Abs(TargetMovement.X), 3.0f) / 1.5f, 1.0); - + Vector2 stepSize = new Vector2( this.stepSize.X * walkPosX * runningModifier, this.stepSize.Y * walkPosY * runningModifier * runningModifier); @@ -567,7 +565,7 @@ namespace Barotrauma rotation = MathHelper.ToDegrees(rotation); if (rotation < 0.0f) rotation += 360; - if (!character.IsRemotePlayer && !aiming) + if (!character.IsRemotePlayer && !aiming && Anim != Animation.UsingConstruction) { if (rotation > 20 && rotation < 170) TargetDir = Direction.Left; @@ -751,9 +749,9 @@ namespace Barotrauma ladderSimPos += character.SelectedConstruction.Submarine.SimPosition - currentHull.Submarine.SimPosition; } - 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); + MoveLimb(head, new Vector2(ladderSimPos.X - 0.27f * Dir, Collider.SimPosition.Y + 0.9f - colliderHeightFromFloor), 10.5f); + MoveLimb(torso, new Vector2(ladderSimPos.X - 0.27f * Dir, Collider.SimPosition.Y + 0.7f - colliderHeightFromFloor), 10.5f); + MoveLimb(waist, new Vector2(ladderSimPos.X - 0.35f * Dir, Collider.SimPosition.Y + 0.6f - colliderHeightFromFloor), 10.5f); Collider.MoveToPos(new Vector2(ladderSimPos.X - 0.2f * Dir, Collider.SimPosition.Y), 10.5f); @@ -761,9 +759,9 @@ namespace Barotrauma Vector2 handPos = new Vector2( ladderSimPos.X, - Collider.SimPosition.Y + 0.6f + movement.Y * 0.1f - ladderSimPos.Y); + Collider.SimPosition.Y + 0.8f + movement.Y * 0.1f - ladderSimPos.Y); - handPos.Y = Math.Min(-0.5f, handPos.Y) - colliderHeightFromFloor; + handPos.Y = Math.Min(-0.2f, handPos.Y) - colliderHeightFromFloor; MoveLimb(leftHand, new Vector2(handPos.X, @@ -780,7 +778,7 @@ namespace Barotrauma Vector2 footPos = new Vector2( handPos.X - Dir * 0.05f, - Collider.SimPosition.Y + 0.7f - colliderHeightFromFloor - stepHeight * 2.7f - ladderSimPos.Y - 0.7f); + Collider.SimPosition.Y + 0.9f - colliderHeightFromFloor - stepHeight * 2.7f - ladderSimPos.Y - 0.7f); //if (movement.Y < 0) footPos.Y += 0.05f; diff --git a/Subsurface/Source/Characters/Animation/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs index 39ee92af7..1edafad57 100644 --- a/Subsurface/Source/Characters/Animation/Ragdoll.cs +++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs @@ -372,7 +372,8 @@ namespace Barotrauma foreach (Limb limb in Limbs) { - limb.sprite.Depth = startDepth + limb.sprite.Depth * 0.0001f; + if (limb.sprite != null) + limb.sprite.Depth = startDepth + limb.sprite.Depth * 0.0001f; } Limb torso = GetLimb(LimbType.Torso); @@ -638,27 +639,31 @@ namespace Barotrauma } - for (int i = 0; i < Limbs.Length; i++) + foreach (Limb limb in Limbs) { - if (Limbs[i] == null) continue; + if (limb == null) continue; - Vector2 spriteOrigin = Limbs[i].sprite.Origin; - spriteOrigin.X = Limbs[i].sprite.SourceRect.Width - spriteOrigin.X; - Limbs[i].sprite.Origin = spriteOrigin; - - Limbs[i].Dir = Dir; - - if (Limbs[i].LightSource != null) + if (limb.sprite != null) { - Limbs[i].LightSource.SpriteEffect = (dir == Direction.Left) ? SpriteEffects.FlipHorizontally : SpriteEffects.None; + Vector2 spriteOrigin = limb.sprite.Origin; + spriteOrigin.X = limb.sprite.SourceRect.Width - spriteOrigin.X; + limb.sprite.Origin = spriteOrigin; } - if (Limbs[i].pullJoint == null) continue; + limb.Dir = Dir; - Limbs[i].pullJoint.LocalAnchorA = - new Vector2( - -Limbs[i].pullJoint.LocalAnchorA.X, - Limbs[i].pullJoint.LocalAnchorA.Y); + if (limb.LightSource != null) + { + limb.LightSource.FlipX(); + } + + if (limb.pullJoint != null) + { + limb.pullJoint.LocalAnchorA = + new Vector2( + -limb.pullJoint.LocalAnchorA.X, + limb.pullJoint.LocalAnchorA.Y); + } } } @@ -864,6 +869,7 @@ namespace Barotrauma { //limb isn't in any room -> it's in the water limb.inWater = true; + if (limb.type == LimbType.Head) headInWater = true; } else if (limbHull.Volume > 0.0f && Submarine.RectContains(limbHull.Rect, limb.Position)) { diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index 994dad171..ad4138a84 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -144,10 +144,7 @@ namespace Barotrauma private float bleeding; - private Sound[] sounds; - private float[] soundRange; - //which AIstate each sound is for - private AIController.AiState[] soundStates; + private List sounds; private float attackCoolDown; @@ -603,28 +600,13 @@ namespace Barotrauma soundInterval = ToolBox.GetAttributeFloat(doc.Root, "soundinterval", 10.0f); var soundElements = doc.Root.Elements("sound").ToList(); - if (soundElements.Any()) + + sounds = new List(); + foreach (XElement soundElement in soundElements) { - sounds = new Sound[soundElements.Count]; - soundStates = new AIController.AiState[soundElements.Count]; - soundRange = new float[soundElements.Count]; - int i = 0; - foreach (XElement soundElement in soundElements) - { - sounds[i] = Sound.Load(soundElement.Attribute("file").Value); - soundRange[i] = ToolBox.GetAttributeFloat(soundElement, "range", 1000.0f); - if (soundElement.Attribute("state") == null) - { - soundStates[i] = AIController.AiState.None; - } - else - { - soundStates[i] = (AIController.AiState)Enum.Parse( - typeof(AIController.AiState), soundElement.Attribute("state").Value, true); - } - i++; - } + sounds.Add(new CharacterSound(soundElement)); } + if (file == humanConfigFile) { @@ -1536,8 +1518,14 @@ namespace Barotrauma private void UpdateOxygen(float deltaTime) { + float prevOxygen = oxygen; Oxygen += deltaTime * (oxygenAvailable < 30.0f ? -5.0f : 10.0f); + if (prevOxygen > 0.0f && Oxygen <= 0.0f && controlled == this) + { + SoundPlayer.PlaySound("drown"); + } + PressureProtection -= deltaTime * 100.0f; float hullAvailableOxygen = 0.0f; @@ -1678,6 +1666,8 @@ namespace Barotrauma /// public HUDProgressBar UpdateHUDProgressBar(object linkedObject, Vector2 worldPosition, float progress, Color emptyColor, Color fullColor) { + if (controlled != this) return null; + HUDProgressBar progressBar = null; if (!hudProgressBars.TryGetValue(linkedObject, out progressBar)) { @@ -1692,24 +1682,15 @@ namespace Barotrauma return progressBar; } - public void PlaySound(AIController.AiState state) + public void PlaySound(CharacterSound.SoundType soundType) { - if (sounds == null || !sounds.Any()) return; - var matchingSoundStates = soundStates.Where(x => x == state).ToList(); + if (sounds == null || sounds.Count == 0) return; - int selectedSound = Rand.Int(matchingSoundStates.Count); + var matchingSounds = sounds.FindAll(s => s.Type == soundType); + if (matchingSounds.Count == 0) return; - int n = 0; - for (int i = 0; i < sounds.Length; i++) - { - if (soundStates[i] != state) continue; - if (n == selectedSound && sounds[i]!=null) - { - sounds[i].Play(1.0f, soundRange[i], AnimController.Limbs[0].WorldPosition); - return; - } - n++; - } + var selectedSound = matchingSounds[Rand.Int(matchingSounds.Count)]; + selectedSound.Sound.Play(1.0f, selectedSound.Range, AnimController.WorldPosition); } public virtual void AddDamage(CauseOfDeath causeOfDeath, float amount, IDamageable attacker) @@ -1810,7 +1791,7 @@ namespace Barotrauma // limb.Damage = 100.0f; } - SoundPlayer.PlayDamageSound(DamageSoundType.Implode, 50.0f, AnimController.Collider); + SoundPlayer.PlaySound("implode", 1.0f, 150.0f, WorldPosition); for (int i = 0; i < 10; i++) { @@ -1861,11 +1842,9 @@ namespace Barotrauma GameServer.Log(Name+" has died (Cause of death: "+causeOfDeath+")", Color.Red); if (OnDeath != null) OnDeath(this, causeOfDeath); - - //CoroutineManager.StartCoroutine(DeathAnim(GameMain.GameScreen.Cam)); - - //health = 0.0f; - + + PlaySound(CharacterSound.SoundType.Die); + isDead = true; this.causeOfDeath = causeOfDeath; AnimController.movement = Vector2.Zero; @@ -1876,7 +1855,7 @@ namespace Barotrauma if (selectedItems[i] != null) selectedItems[i].Drop(this); } - if (aiTarget!=null) + if (aiTarget != null) { aiTarget.Remove(); aiTarget = null; diff --git a/Subsurface/Source/Characters/CharacterHUD.cs b/Subsurface/Source/Characters/CharacterHUD.cs index 442fc6341..aa5c11ef8 100644 --- a/Subsurface/Source/Characters/CharacterHUD.cs +++ b/Subsurface/Source/Characters/CharacterHUD.cs @@ -138,6 +138,7 @@ namespace Barotrauma { if (character.Inventory != null && !character.LockHands && character.Stun >= -0.1f) { + character.Inventory.DrawOffset = Vector2.Zero; character.Inventory.DrawOwn(spriteBatch); } diff --git a/Subsurface/Source/Characters/CharacterSound.cs b/Subsurface/Source/Characters/CharacterSound.cs new file mode 100644 index 000000000..fac222550 --- /dev/null +++ b/Subsurface/Source/Characters/CharacterSound.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace Barotrauma +{ + class CharacterSound + { + public enum SoundType + { + Idle, Attack, Die + } + + public readonly Sound Sound; + + public readonly SoundType Type; + + public readonly float Range; + + public CharacterSound(XElement element) + { + Sound = Sound.Load(element.Attribute("file").Value); + Range = ToolBox.GetAttributeFloat(element, "range", 1000.0f); + + Enum.TryParse(ToolBox.GetAttributeString(element, "state", "Idle"), true, out Type); + } + } +} diff --git a/Subsurface/Source/Characters/Limb.cs b/Subsurface/Source/Characters/Limb.cs index 95445a17f..9116143dd 100644 --- a/Subsurface/Source/Characters/Limb.cs +++ b/Subsurface/Source/Characters/Limb.cs @@ -423,7 +423,6 @@ namespace Barotrauma if (LightSource != null) { LightSource.ParentSub = body.Submarine; - LightSource.Position = Position; } if (!character.IsDead) damage = Math.Max(0.0f, damage-deltaTime*0.1f); @@ -504,6 +503,12 @@ namespace Barotrauma body.UpdateDrawPosition(); } + if (LightSource != null) + { + LightSource.Position = body.DrawPosition; + LightSource.Rotation = body.DrawRotation; + } + foreach (WearableSprite wearable in wearingItems) { SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally; @@ -528,36 +533,37 @@ namespace Barotrauma -body.DrawRotation, scale, spriteEffect, depth); } - - if (damage>0.0f && damagedSprite!=null && !hideLimb) + + if (damage > 0.0f && damagedSprite != null && !hideLimb) { SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally; - + float depth = sprite.Depth - 0.0000015f; - + damagedSprite.Draw(spriteBatch, new Vector2(body.DrawPosition.X, -body.DrawPosition.Y), - color*Math.Min(damage/50.0f,1.0f), sprite.Origin, + color * Math.Min(damage / 50.0f, 1.0f), sprite.Origin, -body.DrawRotation, 1.0f, spriteEffect, depth); } - + if (!GameMain.DebugDraw) return; - if (pullJoint!=null) + if (pullJoint != null) { Vector2 pos = ConvertUnits.ToDisplayUnits(pullJoint.WorldAnchorB); GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), Color.Red, true); - } - - + } } public void Remove() { - sprite.Remove(); - sprite = null; + if (sprite != null) + { + sprite.Remove(); + sprite = null; + } if (LightSource != null) { diff --git a/Subsurface/Source/DebugConsole.cs b/Subsurface/Source/DebugConsole.cs index 4328191d5..2e5a022f0 100644 --- a/Subsurface/Source/DebugConsole.cs +++ b/Subsurface/Source/DebugConsole.cs @@ -95,6 +95,7 @@ namespace Barotrauma if (isOpen) { textBox.Select(); + AddToGUIUpdateList(); } else { @@ -426,6 +427,14 @@ namespace Barotrauma case "mainmenuscreen": case "mainmenu": case "menu": + GameMain.GameSession = null; + + List characters = new List(Character.CharacterList); + foreach (Character c in characters) + { + c.Remove(); + } + GameMain.MainMenuScreen.Select(); break; case "gamescreen": diff --git a/Subsurface/Source/Events/Missions/SalvageMission.cs b/Subsurface/Source/Events/Missions/SalvageMission.cs index 358f52cf9..f12232250 100644 --- a/Subsurface/Source/Events/Missions/SalvageMission.cs +++ b/Subsurface/Source/Events/Missions/SalvageMission.cs @@ -54,6 +54,24 @@ namespace Barotrauma item = new Item(itemPrefab, position, null); item.MoveWithLevel = true; item.body.FarseerBody.IsKinematic = true; + + if (item.HasTag("alien")) + { + //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/GUIComponent.cs b/Subsurface/Source/GUI/GUIComponent.cs index dc8e9d7cc..f48325221 100644 --- a/Subsurface/Source/GUI/GUIComponent.cs +++ b/Subsurface/Source/GUI/GUIComponent.cs @@ -33,6 +33,13 @@ namespace Barotrauma public static void ClearUpdateList() { + if (keyboardDispatcher != null && + KeyboardDispatcher.Subscriber is GUIComponent && + !ComponentsToUpdate.Contains((GUIComponent)KeyboardDispatcher.Subscriber)) + { + KeyboardDispatcher.Subscriber = null; + } + ComponentsToUpdate.Clear(); } diff --git a/Subsurface/Source/GUI/GUIDropDown.cs b/Subsurface/Source/GUI/GUIDropDown.cs index a3fc5d5d3..177616007 100644 --- a/Subsurface/Source/GUI/GUIDropDown.cs +++ b/Subsurface/Source/GUI/GUIDropDown.cs @@ -103,14 +103,11 @@ namespace Barotrauma { GUITextBlock textBlock = new GUITextBlock(new Rectangle(0,0,0,20), text, GUI.Style, listBox); textBlock.UserData = userData; + } - //int totalHeight = 0; - //foreach (GUIComponent child in listBox.children) - //{ - // totalHeight += child.Rect.Height; - //} - - //listBox.Rect = new Rectangle(listBox.Rect.X,listBox.Rect.Y,listBox.Rect.Width,totalHeight); + public override void ClearChildren() + { + listBox.ClearChildren(); } public List GetChildren() diff --git a/Subsurface/Source/GUI/GUIListBox.cs b/Subsurface/Source/GUI/GUIListBox.cs index 1d235d7e9..44f0fd17a 100644 --- a/Subsurface/Source/GUI/GUIListBox.cs +++ b/Subsurface/Source/GUI/GUIListBox.cs @@ -147,7 +147,8 @@ namespace Barotrauma scrollBar = new GUIScrollBar( new Rectangle(this.rect.Right - 20, this.rect.Y, 20, this.rect.Height), null, 1.0f, GUI.Style); } - + + scrollBar.IsHorizontal = isHorizontal; frame = new GUIFrame(Rectangle.Empty, style, this); if (style != null) style.Apply(frame, this); diff --git a/Subsurface/Source/GUI/GUIScrollBar.cs b/Subsurface/Source/GUI/GUIScrollBar.cs index 60bb9d1ed..4e21592df 100644 --- a/Subsurface/Source/GUI/GUIScrollBar.cs +++ b/Subsurface/Source/GUI/GUIScrollBar.cs @@ -25,6 +25,12 @@ namespace Barotrauma public bool IsHorizontal { get { return isHorizontal; } + set + { + if (isHorizontal == value) return; + isHorizontal = value; + UpdateRect(); + } } public bool Enabled diff --git a/Subsurface/Source/GameMain.cs b/Subsurface/Source/GameMain.cs index d0c7fc0a4..346f2cbbb 100644 --- a/Subsurface/Source/GameMain.cs +++ b/Subsurface/Source/GameMain.cs @@ -250,7 +250,7 @@ namespace Barotrauma GameModePreset.Init(); - Submarine.Preload(); + Submarine.RefreshSavedSubs(); TitleScreen.LoadState = 80.0f; yield return CoroutineStatus.Running; diff --git a/Subsurface/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs b/Subsurface/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs index f4f5bfd89..cbfe29e10 100644 --- a/Subsurface/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs +++ b/Subsurface/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs @@ -283,7 +283,7 @@ namespace Barotrauma.Tutorials infoBox = CreateInfoFrame("Steer the submarine downwards, heading further into the cavern."); - while (Submarine.MainSub.WorldPosition.Y > 36500.0f) + while (Submarine.MainSub.WorldPosition.Y > 40000.0f) { yield return CoroutineStatus.Running; } @@ -293,7 +293,7 @@ namespace Barotrauma.Tutorials "Content/Characters/Moloch/moloch.xml", steering.Item.WorldPosition + new Vector2(3000.0f, -500.0f)); - moloch.PlaySound(AIController.AiState.Attack); + moloch.PlaySound(CharacterSound.SoundType.Attack); yield return new WaitForSeconds(1.0f); @@ -349,7 +349,7 @@ namespace Barotrauma.Tutorials if (isWindow) { //decrease window damage to slow down the leaking - w.AddDamage(i, -w.SectionDamage(i) * 0.495f); + w.AddDamage(i, -w.SectionDamage(i) * 0.48f); } else { diff --git a/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialType.cs b/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialType.cs index a46777f2a..2cfe573aa 100644 --- a/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialType.cs +++ b/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialType.cs @@ -39,7 +39,7 @@ namespace Barotrauma.Tutorials GameMain.GameSession = new GameSession(Submarine.MainSub, "", GameModePreset.list.Find(gm => gm.Name.ToLowerInvariant() == "tutorial")); (GameMain.GameSession.gameMode as TutorialMode).tutorialType = this; - GameMain.GameSession.StartShift("tuto2"); + GameMain.GameSession.StartShift("tuto"); GameMain.GameSession.TaskManager.Tasks.Clear(); diff --git a/Subsurface/Source/GameSession/GameSession.cs b/Subsurface/Source/GameSession/GameSession.cs index 6f4bf4cf9..a78996803 100644 --- a/Subsurface/Source/GameSession/GameSession.cs +++ b/Subsurface/Source/GameSession/GameSession.cs @@ -202,7 +202,7 @@ namespace Barotrauma { level.Generate(); - submarine.SetPosition(level.StartPosition - new Vector2(0.0f, 2000.0f)); + submarine.SetPosition(submarine.FindSpawnPos(level.StartPosition - new Vector2(0.0f, 2000.0f))); //secondSub.SetPosition(level.EndPosition - new Vector2(0.0f, 2000.0f)); diff --git a/Subsurface/Source/Items/Components/DockingPort.cs b/Subsurface/Source/Items/Components/DockingPort.cs index 2e66fd529..1217cd4fa 100644 --- a/Subsurface/Source/Items/Components/DockingPort.cs +++ b/Subsurface/Source/Items/Components/DockingPort.cs @@ -44,6 +44,12 @@ namespace Barotrauma.Items.Components private bool docked; + public int DockingDir + { + get { return dockingDir; } + set { dockingDir = value; } + } + [HasDefaultValue("32.0,32.0", false)] public string DistanceTolerance { @@ -150,7 +156,8 @@ namespace Barotrauma.Items.Components if (target.item.Submarine == item.Submarine) { - DebugConsole.ThrowError("Error - tried to a submarine to itself"); + DebugConsole.ThrowError("Error - tried to dock a submarine to itself"); + dockingTarget = null; return; } @@ -176,8 +183,9 @@ namespace Barotrauma.Items.Components dockingDir = IsHorizontal ? Math.Sign(dockingTarget.item.WorldPosition.X - item.WorldPosition.X) : - Math.Sign(item.WorldPosition.Y - dockingTarget.item.WorldPosition.Y); + Math.Sign(dockingTarget.item.WorldPosition.Y - item.WorldPosition.Y); dockingTarget.dockingDir = -dockingDir; + foreach (WayPoint wp in WayPoint.WayPointList) { @@ -199,12 +207,46 @@ namespace Barotrauma.Items.Components CreateJoint(false); } + public void Lock() + { + if (dockingTarget==null) + { + DebugConsole.ThrowError("Error - attempted to lock a docking port that's not connected to anything"); + return; + } + else if (joint is WeldJoint) + { + DebugConsole.ThrowError("Error - attempted to lock a docking port that's already locked"); + return; + } + + dockingDir = IsHorizontal ? + Math.Sign(dockingTarget.item.WorldPosition.X - item.WorldPosition.X) : + Math.Sign(dockingTarget.item.WorldPosition.Y - item.WorldPosition.Y); + dockingTarget.dockingDir = -dockingDir; + + GameMain.World.RemoveJoint(joint); + + PlaySound(ActionType.OnSecondaryUse, item.WorldPosition); + + ConnectWireBetweenPorts(); + + CreateJoint(true); + + if (!item.linkedTo.Any(e => e is Hull) && !dockingTarget.item.linkedTo.Any(e => e is Hull)) + { + CreateHull(); + + //item.NewComponentEvent(this, false, true); + } + } + private void CreateJoint(bool useWeldJoint) { Vector2 offset = (IsHorizontal ? - Vector2.UnitX * Math.Sign(dockingTarget.item.WorldPosition.X - item.WorldPosition.X) : - Vector2.UnitY * Math.Sign(dockingTarget.item.WorldPosition.Y - item.WorldPosition.Y)); + Vector2.UnitX * dockingDir : + Vector2.UnitY * dockingDir); offset *= DockedDistance * 0.5f; Vector2 pos1 = item.WorldPosition + offset; @@ -491,28 +533,18 @@ namespace Barotrauma.Items.Components if (!docked) { Dock(dockingTarget); + if (dockingTarget == null) return; } if (joint is DistanceJoint) { item.SendSignal(0, "0", "state_out"); + dockingState = MathHelper.Lerp(dockingState, 0.5f, deltaTime * 10.0f); if (Vector2.Distance(joint.WorldAnchorA, joint.WorldAnchorB) < 0.05f) { - GameMain.World.RemoveJoint(joint); - - PlaySound(ActionType.OnSecondaryUse, item.WorldPosition); - - ConnectWireBetweenPorts(); - - CreateJoint(true); - - if (!item.linkedTo.Any(e => e is Hull) && !dockingTarget.item.linkedTo.Any(e => e is Hull)) - { - CreateHull(); - } + Lock(); } - dockingState = MathHelper.Lerp(dockingState, 0.5f, deltaTime * 10.0f); } else { @@ -606,12 +638,14 @@ namespace Barotrauma.Items.Components if (!item.linkedTo.Any()) return; - foreach (MapEntity entity in item.linkedTo) + List linked = new List(item.linkedTo); + foreach (MapEntity entity in linked) { var hull = entity as Hull; if (hull != null) { hull.Remove(); + item.linkedTo.Remove(hull); continue; } @@ -619,6 +653,7 @@ namespace Barotrauma.Items.Components if (gap != null) { gap.Remove(); + gap.linkedTo.Remove(hull); continue; } @@ -626,10 +661,11 @@ namespace Barotrauma.Items.Components if (linkedItem == null) continue; var dockingPort = linkedItem.GetComponent(); - if (dockingPort != null) dockingTarget = dockingPort; + if (dockingPort != null) + { + Dock(dockingPort); + } } - - item.linkedTo.Clear(); } public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power = 0.0f) diff --git a/Subsurface/Source/Items/Components/Holdable/RepairTool.cs b/Subsurface/Source/Items/Components/Holdable/RepairTool.cs index edb85ccd6..03bb4d26d 100644 --- a/Subsurface/Source/Items/Components/Holdable/RepairTool.cs +++ b/Subsurface/Source/Items/Components/Holdable/RepairTool.cs @@ -177,7 +177,7 @@ namespace Barotrauma.Items.Components Item targetItem; if ((targetStructure = (targetBody.UserData as Structure)) != null) { - if (!fixableEntities.Contains(targetStructure.Name)) return; + if (!fixableEntities.Contains("structure") && !fixableEntities.Contains(targetStructure.Name)) return; if (targetStructure.IsPlatform) return; int sectionIndex = targetStructure.FindSectionIndex(ConvertUnits.ToDisplayUnits(pickedPosition)); @@ -195,7 +195,7 @@ namespace Barotrauma.Items.Components 1.0f - targetStructure.SectionDamage(sectionIndex) / targetStructure.Health, Color.Red, Color.Green); - progressBar.Size = new Vector2(60.0f, 20.0f); + if (progressBar != null) progressBar.Size = new Vector2(60.0f, 20.0f); targetStructure.AddDamage(sectionIndex, -StructureFixAmount * degreeOfSuccess); diff --git a/Subsurface/Source/Items/Components/ItemComponent.cs b/Subsurface/Source/Items/Components/ItemComponent.cs index 964c6edd6..d3ba798bf 100644 --- a/Subsurface/Source/Items/Components/ItemComponent.cs +++ b/Subsurface/Source/Items/Components/ItemComponent.cs @@ -544,11 +544,28 @@ namespace Barotrauma.Items.Components RemoveComponentSpecific(); } - protected virtual void RemoveComponentSpecific() + /// + /// Remove the component so that it doesn't appear to exist in the game world (stop sounds, remove bodies etc) + /// but don't reset anything that's required for cloning the item + /// + public void ShallowRemove() { + if (loopingSound != null) + { + Sounds.SoundManager.Stop(loopingSoundIndex); + } + ShallowRemoveComponentSpecific(); } + protected virtual void ShallowRemoveComponentSpecific() + { + RemoveComponentSpecific(); + } + + protected virtual void RemoveComponentSpecific() + { } + public bool HasRequiredSkills(Character character) { Skill temp; diff --git a/Subsurface/Source/Items/Components/Machines/Controller.cs b/Subsurface/Source/Items/Components/Machines/Controller.cs index ae10f6b79..65a7530b0 100644 --- a/Subsurface/Source/Items/Components/Machines/Controller.cs +++ b/Subsurface/Source/Items/Components/Machines/Controller.cs @@ -26,15 +26,15 @@ namespace Barotrauma.Items.Components private Direction dir; - //the x-position where the user walks to when using the controller - private float userPos; + //the position where the user walks to when using the controller + //(relative to the position of the item) + private Vector2 userPos; private Camera cam; private Character character; - [HasDefaultValue(0.0f, false)] - public float UserPos + public Vector2 UserPos { get { return userPos; } set { userPos = value; } @@ -45,13 +45,16 @@ namespace Barotrauma.Items.Components { limbPositions = new List(); - dir = (Direction)Enum.Parse(typeof(Direction), ToolBox.GetAttributeString(element, "direction", "None"), true); + userPos = ToolBox.GetAttributeVector2(element, "UserPos", Vector2.Zero); + Enum.TryParse(ToolBox.GetAttributeString(element, "direction", "None"), out dir); + foreach (XElement el in element.Elements()) { if (el.Name != "limbposition") continue; LimbPos lp = new LimbPos(); + try { lp.limbType = (LimbType)Enum.Parse(typeof(LimbType), el.Attribute("limb").Value, true); @@ -90,23 +93,34 @@ namespace Barotrauma.Items.Components character.AnimController.Anim = AnimController.Animation.UsingConstruction; - if (userPos != 0.0f) + if (userPos != Vector2.Zero) { float torsoX = character.Position.X; - Vector2 diff = new Vector2(item.Rect.X + UserPos - torsoX, 0.0f); + Vector2 diff = (item.WorldPosition + userPos) - character.WorldPosition; - if (diff!= Vector2.Zero && diff.Length() > 10.0f) + if (character.AnimController.InWater) { - //character.AnimController.Anim = AnimController.Animation.None; - - character.AnimController.TargetMovement = new Vector2(Math.Sign(diff.X), 0.0f); - character.AnimController.TargetDir = (Math.Sign(diff.X) == 1) ? Direction.Right : Direction.Left; - return; + if (diff.Length() > 30.0f) + { + character.AnimController.TargetMovement = Vector2.Clamp(diff*0.01f, -Vector2.One, Vector2.One); + character.AnimController.TargetDir = diff.X > 0.0f ? Direction.Right : Direction.Left; + } + else + { + character.AnimController.TargetMovement = Vector2.Zero; + } } else { - character.AnimController.TargetMovement = Vector2.Zero; + diff.Y = 0.0f; + if (diff != Vector2.Zero && diff.Length() > 10.0f) + { + character.AnimController.TargetMovement = Vector2.Normalize(diff); + character.AnimController.TargetDir = diff.X > 0.0f ? Direction.Right : Direction.Left; + return; + } + character.AnimController.TargetMovement = Vector2.Zero; } } @@ -115,6 +129,7 @@ namespace Barotrauma.Items.Components if (limbPositions.Count == 0) return; character.AnimController.Anim = AnimController.Animation.UsingConstruction; + character.AnimController.ResetPullJoints(); if (dir != 0) character.AnimController.TargetDir = dir; @@ -256,10 +271,10 @@ namespace Barotrauma.Items.Components dir = dir == Direction.Left ? Direction.Right : Direction.Left; } - if (userPos != 0.0f) + if (userPos.X != 0.0f) { - float diff = (item.Rect.X + UserPos) - item.Rect.Center.X; - userPos = item.Rect.Center.X - diff - item.Rect.X; + float diff = (item.Rect.X + UserPos.X) - item.Rect.Center.X; + userPos.X = item.Rect.Center.X - diff - item.Rect.X; } for (int i = 0; i < limbPositions.Count; i++) diff --git a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs index e8bae85b8..9fa4d9b2c 100644 --- a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs +++ b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs @@ -125,6 +125,8 @@ namespace Barotrauma.Items.Components Item it = recipient.Item; if (it == null) continue; + if (it.Condition <= 0.0f) continue; + Powered powered = it.GetComponent(); if (powered == null || !powered.IsActive) continue; diff --git a/Subsurface/Source/Items/Components/Signal/Connection.cs b/Subsurface/Source/Items/Components/Signal/Connection.cs index 1b9d048ac..c259ba04b 100644 --- a/Subsurface/Source/Items/Components/Signal/Connection.cs +++ b/Subsurface/Source/Items/Components/Signal/Connection.cs @@ -21,7 +21,7 @@ namespace Barotrauma.Items.Components public Wire[] Wires; - private Item item; + private Item item; public readonly bool IsOutput; @@ -30,7 +30,7 @@ namespace Barotrauma.Items.Components private List effects; public readonly ushort[] wireId; - + public bool IsPower { get; @@ -64,17 +64,17 @@ namespace Barotrauma.Items.Components { panelTexture = Sprite.LoadTexture("Content/Items/connectionpanel.png"); - connector = new Sprite(panelTexture, new Rectangle(470, 102, 19,43), Vector2.Zero, 0.0f); + connector = new Sprite(panelTexture, new Rectangle(470, 102, 19, 43), Vector2.Zero, 0.0f); connector.Origin = new Vector2(9.5f, 10.0f); - wireVertical = new Sprite(panelTexture, new Rectangle(408, 1, 11, 102), Vector2.Zero, 0.0f); + wireVertical = new Sprite(panelTexture, new Rectangle(408, 1, 11, 102), Vector2.Zero, 0.0f); } this.item = item; //recipient = new Connection[MaxLinked]; Wires = new Wire[MaxLinked]; - + IsOutput = (element.Name.ToString() == "output"); Name = ToolBox.GetAttributeString(element, "name", (IsOutput) ? "output" : "input"); @@ -92,12 +92,12 @@ namespace Barotrauma.Items.Components int index = -1; for (int i = 0; i < MaxLinked; i++) { - if (wireId[i]<1) index = i; + if (wireId[i] < 1) index = i; } if (index == -1) break; int id = ToolBox.GetAttributeInt(subElement, "w", 0); - if (id<0) id = 0; + if (id < 0) id = 0; wireId[index] = (ushort)id; break; @@ -113,7 +113,7 @@ namespace Barotrauma.Items.Components { for (int i = 0; i < MaxLinked; i++) { - if (Wires[i]==null) return i; + if (Wires[i] == null) return i; } return -1; } @@ -150,7 +150,7 @@ namespace Barotrauma.Items.Components } } } - + public void AddLink(int index, Wire wire) { Wires[index] = wire; @@ -164,9 +164,9 @@ namespace Barotrauma.Items.Components public void SendSignal(int stepsTaken, string signal, Item sender, float power) { - for (int i = 0; i-1) + if (linkIndex > -1) { Inventory.draggingItem = c.Wires[linkIndex].Item; } @@ -257,21 +257,21 @@ namespace Barotrauma.Items.Components //outputs are drawn at the right side of the panel, inputs at the left if (c.IsOutput) { - c.Draw(spriteBatch, panel.Item, rightPos, - new Vector2(rightPos.X - GUI.SmallFont.MeasureString(c.Name).X - 20, rightPos.Y+3), - rightWirePos, - mouseInRect, equippedWire != null, + c.Draw(spriteBatch, panel.Item, rightPos, + new Vector2(rightPos.X - GUI.SmallFont.MeasureString(c.Name).X - 20, rightPos.Y + 3), + rightWirePos, + mouseInRect, equippedWire, wireInterval); rightPos.Y += 30; - rightWirePos.Y += c.Wires.Count(w => w!=null) * wireInterval; + rightWirePos.Y += c.Wires.Count(w => w != null) * wireInterval; } else { c.Draw(spriteBatch, panel.Item, leftPos, - new Vector2(leftPos.X + 20, leftPos.Y-12), - leftWirePos, - mouseInRect, equippedWire != null, + new Vector2(leftPos.X + 20, leftPos.Y - 12), + leftWirePos, + mouseInRect, equippedWire, wireInterval); leftPos.Y += 30; @@ -279,14 +279,14 @@ namespace Barotrauma.Items.Components //leftWireX -= wireInterval; } } - + if (draggingConnected != null) { - DrawWire(spriteBatch, draggingConnected, draggingConnected.Item, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height), mouseInRect, false); + DrawWire(spriteBatch, draggingConnected, draggingConnected.Item, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height), mouseInRect, null); if (!PlayerInput.LeftButtonHeld()) { - //panel.Item.CreateServerEvent(panel, true, true); + //panel.Item.NewComponentEvent(panel, true, true); //draggingConnected.Drop(Character); draggingConnected = null; } @@ -294,61 +294,49 @@ namespace Barotrauma.Items.Components //if the Character using the panel has a wire item equipped //and the wire hasn't been connected yet, draw it on the panel - if (equippedWire!=null) + if (equippedWire != null) { if (panel.Connections.Find(c => c.Wires.Contains(equippedWire)) == null) { DrawWire(spriteBatch, equippedWire, equippedWire.Item, new Vector2(x + width / 2, y + height - 100), - new Vector2(x + width / 2, y + height), mouseInRect, false); + new Vector2(x + width / 2, y + height), mouseInRect, null); if (draggingConnected == equippedWire) Inventory.draggingItem = equippedWire.Item; - - //break; } } //stop dragging a wire item if cursor is outside the panel if (mouseInRect) Inventory.draggingItem = null; - if (draggingConnected != null) - { - DrawWire(spriteBatch, draggingConnected, draggingConnected.Item, PlayerInput.MousePosition, new Vector2(x + width / 2, y + height), mouseInRect, false); - - if (!PlayerInput.LeftButtonHeld()) - { - //draggingConnected.Drop(Character); - draggingConnected = null; - } - } spriteBatch.Draw(panelTexture, panelRect, new Rectangle(0, 0, width, height), Color.White); } - private void Draw(SpriteBatch spriteBatch, Item item, Vector2 position, Vector2 labelPos, Vector2 wirePosition, bool mouseIn, bool wireEquipped, float wireInterval) + private void Draw(SpriteBatch spriteBatch, Item item, Vector2 position, Vector2 labelPos, Vector2 wirePosition, bool mouseIn, Wire equippedWire, float wireInterval) { //spriteBatch.DrawString(GUI.SmallFont, Name, new Vector2(labelPos.X, labelPos.Y-10), Color.White); - GUI.DrawString(spriteBatch, labelPos, Name, IsPower ? Color.Red : Color.White, Color.Black,0, GUI.SmallFont); + GUI.DrawString(spriteBatch, labelPos, Name, IsPower ? Color.Red : Color.White, Color.Black, 0, GUI.SmallFont); - GUI.DrawRectangle(spriteBatch, new Rectangle((int)position.X-10, (int)position.Y-10, 20, 20), Color.White); + GUI.DrawRectangle(spriteBatch, new Rectangle((int)position.X - 10, (int)position.Y - 10, 20, 20), Color.White); spriteBatch.Draw(panelTexture, position - new Vector2(16.0f, 16.0f), new Rectangle(64, 256, 32, 32), Color.White); - - for (int i = 0; i w != null && w != draggingConnected)) { - spriteBatch.Draw(panelTexture, position - new Vector2(16.0f, 16.0f), new Rectangle(screwIndex*32, 256, 32, 32), Color.White); + spriteBatch.Draw(panelTexture, position - new Vector2(16.0f, 16.0f), new Rectangle(screwIndex * 32, 256, 32, 32), Color.White); } - + } - private static void DrawWire(SpriteBatch spriteBatch, Wire wire, Item item, Vector2 end, Vector2 start, bool mouseIn, bool wireEquipped) + private static void DrawWire(SpriteBatch spriteBatch, Wire wire, Item item, Vector2 end, Vector2 start, bool mouseIn, Wire equippedWire) { if (draggingConnected == wire) { if (!mouseIn) return; end = PlayerInput.MousePosition; - start.X = (start.X+end.X)/2.0f; + start.X = (start.X + end.X) / 2.0f; } int textX = (int)start.X; @@ -389,28 +377,30 @@ namespace Barotrauma.Items.Components else textX += 10; - float alpha = wireEquipped ? 0.5f : 1.0f; + bool canDrag = equippedWire == null || equippedWire == wire; - bool mouseOn = - !wireEquipped && + float alpha = canDrag ? 1.0f : 0.5f; + + bool mouseOn = + canDrag && ((PlayerInput.MousePosition.X > Math.Min(start.X, end.X) && PlayerInput.MousePosition.X < Math.Max(start.X, end.X) && MathUtils.LineToPointDistance(start, end, PlayerInput.MousePosition) < 6) || - Vector2.Distance(end, PlayerInput.MousePosition)<20.0f || - new Rectangle((start.X < end.X) ? textX-100 : textX, (int)start.Y-5, 100, 14).Contains(PlayerInput.MousePosition)); + Vector2.Distance(end, PlayerInput.MousePosition) < 20.0f || + new Rectangle((start.X < end.X) ? textX - 100 : textX, (int)start.Y - 5, 100, 14).Contains(PlayerInput.MousePosition)); - string label = wire.Locked ? item.Name +"\n(Locked)" : item.Name; + string label = wire.Locked ? item.Name + "\n(Locked)" : item.Name; - GUI.DrawString(spriteBatch, - new Vector2(start.X < end.X ? textX-GUI.SmallFont.MeasureString(label).X : textX,start.Y -5.0f), - label, - (mouseOn ? Color.Gold : Color.White) * (wire.Locked ? 0.6f : 1.0f), Color.Black * 0.8f, + GUI.DrawString(spriteBatch, + new Vector2(start.X < end.X ? textX - GUI.SmallFont.MeasureString(label).X : textX, start.Y - 5.0f), + label, + (mouseOn ? Color.Gold : Color.White) * (wire.Locked ? 0.6f : 1.0f), Color.Black * 0.8f, 3, GUI.SmallFont); var wireEnd = end + Vector2.Normalize(start - end) * 30.0f; float dist = Vector2.Distance(start, wireEnd); - + if (mouseOn) { spriteBatch.Draw(wireVertical.Texture, new Rectangle(wireEnd.ToPoint(), new Point(18, (int)dist)), wireVertical.SourceRect, @@ -427,9 +417,9 @@ namespace Barotrauma.Items.Components SpriteEffects.None, 0.0f); - connector.Draw(spriteBatch, end, Color.White, new Vector2(10.0f, 10.0f), MathUtils.VectorToAngle(end - start)+MathHelper.PiOver2); + connector.Draw(spriteBatch, end, Color.White, new Vector2(10.0f, 10.0f), MathUtils.VectorToAngle(end - start) + MathHelper.PiOver2); - if (draggingConnected == null && !wireEquipped) + if (draggingConnected == null && canDrag) { if (mouseOn) { @@ -438,9 +428,8 @@ namespace Barotrauma.Items.Components if (!wire.Locked) { //start dragging the wire - if (PlayerInput.LeftButtonHeld()) draggingConnected = wire; + if (PlayerInput.LeftButtonHeld()) draggingConnected = wire; } - } } } @@ -449,25 +438,25 @@ namespace Barotrauma.Items.Components { XElement newElement = new XElement(IsOutput ? "output" : "input", new XAttribute("name", Name)); - Array.Sort(Wires, delegate(Wire wire1, Wire wire2) + Array.Sort(Wires, delegate(Wire wire1, Wire wire2) { if (wire1 == null) return 1; if (wire2 == null) return -1; - return wire1.Item.ID.CompareTo(wire2.Item.ID); + return wire1.Item.ID.CompareTo(wire2.Item.ID); }); - for (int i = 0; i < MaxLinked; i++ ) + for (int i = 0; i < MaxLinked; i++) { if (Wires[i] == null) continue; - + //Connection recipient = wires[i].OtherConnection(this); //int connectionIndex = recipient.item.Connections.FindIndex(x => x == recipient); - newElement.Add(new XElement("link", - new XAttribute("w", Wires[i].Item.ID.ToString()))); + newElement.Add(new XElement("link", + new XAttribute("w", Wires[i].Item.ID.ToString()))); } - - parentElement.Add(newElement); + + parentElement.Add(newElement); } @@ -486,7 +475,7 @@ namespace Barotrauma.Items.Components if (wireItem == null) continue; Wires[i] = wireItem.GetComponent(); - if (Wires[i]!=null) + if (Wires[i] != null) { if (Wires[i].Item.body != null) Wires[i].Item.body.Enabled = false; Wires[i].Connect(this, false, true); @@ -499,4 +488,4 @@ namespace Barotrauma.Items.Components } } -} +} \ No newline at end of file diff --git a/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs b/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs index 7566f35ad..9ca463b7e 100644 --- a/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs +++ b/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs @@ -156,6 +156,10 @@ namespace Barotrauma.Items.Components } } } + + protected override void ShallowRemoveComponentSpecific() + { + } } } diff --git a/Subsurface/Source/Items/Components/Signal/Wire.cs b/Subsurface/Source/Items/Components/Signal/Wire.cs index 75c674380..37a8d7b5c 100644 --- a/Subsurface/Source/Items/Components/Signal/Wire.cs +++ b/Subsurface/Source/Items/Components/Signal/Wire.cs @@ -1,5 +1,6 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; using System; using System.Collections.Generic; using System.Globalization; @@ -63,8 +64,11 @@ namespace Barotrauma.Items.Components private Vector2 newNodePos; + + private static Wire draggingWire; private static int? selectedNodeIndex; + private static int? highlightedNodeIndex; public bool Hidden, Locked; @@ -89,7 +93,7 @@ namespace Barotrauma.Items.Components IsActive = false; } - + public Connection OtherConnection(Connection connection) { if (connection == null) return null; @@ -191,7 +195,14 @@ namespace Barotrauma.Items.Components CleanNodes(); } - Drawable = nodes.Any(); + if (!loading) + { + //Item.NewComponentEvent(this, true, true); + //the wire is active if only one end has been connected + IsActive = connections[0] == null ^ connections[1] == null; + } + + Drawable = IsActive || nodes.Any(); UpdateSections(); return true; @@ -202,7 +213,6 @@ namespace Barotrauma.Items.Components ClearConnections(); IsActive = true; - //Drawable = true; } public override void Unequip(Character character) @@ -227,7 +237,7 @@ namespace Barotrauma.Items.Components if (connections[0] != null && connections[0].Item.Submarine != null) sub = connections[0].Item.Submarine; if (connections[1] != null && connections[1].Item.Submarine != null) sub = connections[1].Item.Submarine; - if (item.Submarine != sub && Screen.Selected != GameMain.EditMapScreen) + if ((item.Submarine != sub || sub == null) && Screen.Selected != GameMain.EditMapScreen) { ClearConnections(); return; @@ -260,7 +270,7 @@ namespace Barotrauma.Items.Components UpdateSections(); } - Drawable = sections.Count > 0; + Drawable = IsActive || sections.Count > 0; } public override bool Pick(Character picker) @@ -303,7 +313,7 @@ namespace Barotrauma.Items.Components { sections.Add(new WireSection(nodes[i], nodes[i + 1])); } - Drawable = sections.Count > 0; + Drawable = IsActive || sections.Count > 0; } private void ClearConnections() @@ -384,7 +394,7 @@ namespace Barotrauma.Items.Components public void Draw(SpriteBatch spriteBatch, bool editing) { - if (sections.Count == 0) + if (sections.Count == 0 && !IsActive) { Drawable = false; return; @@ -396,7 +406,7 @@ namespace Barotrauma.Items.Components drawOffset = item.Submarine.DrawPosition + item.Submarine.HiddenSubPosition; } - float depth = wireSprite.Depth + ((item.ID % 100) * 0.00001f); + float depth = item.IsSelected ? 0.0f : wireSprite.Depth + ((item.ID % 100) * 0.00001f); if (item.IsHighlighted) { @@ -417,8 +427,8 @@ 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 && nodes.Count > 0 && Vector2.Distance(newNodePos, nodes[nodes.Count - 1]) > nodeDistance) { WireSection.Draw( spriteBatch, @@ -428,78 +438,198 @@ namespace Barotrauma.Items.Components depth, 0.3f); } - - if (!editing || !PlayerInput.MouseInsideWindow || !GameMain.EditMapScreen.WiringMode) return; - if (Character.Controlled != null && Character.Controlled.SelectedConstruction != null) return; + + if (!editing || !GameMain.EditMapScreen.WiringMode) return; for (int i = 0; i < nodes.Count; i++) { - Vector2 worldPos = nodes[i]; - if (item.Submarine != null) worldPos += item.Submarine.Position + item.Submarine.HiddenSubPosition; - worldPos.Y = -worldPos.Y; + Vector2 drawPos = nodes[i]; + if (item.Submarine != null) drawPos += item.Submarine.Position + item.Submarine.HiddenSubPosition; + drawPos.Y = -drawPos.Y; - GUI.DrawRectangle(spriteBatch, worldPos + new Vector2(-3, -3), new Vector2(6, 6), item.Color, true, 0.0f); - - if (IsActive) continue; - - if (GUIComponent.MouseOn != null || - Vector2.Distance(GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), new Vector2(worldPos.X, -worldPos.Y)) > 10.0f) + if (item.IsSelected) { - continue; + GUI.DrawRectangle(spriteBatch, drawPos + new Vector2(-5, -5), new Vector2(10, 10), item.Color, true, 0.0f); + + if (highlightedNodeIndex == i) + { + GUI.DrawRectangle(spriteBatch, drawPos + new Vector2(-10, -10), new Vector2(20, 20), Color.Red, false, 0.0f); + } } - - GUI.DrawRectangle(spriteBatch, worldPos + new Vector2(-10, -10), new Vector2(20, 20), Color.Red, false, 0.0f); - - if (selectedNodeIndex == null && draggingWire == null)// && !MapEntity.SelectedAny) + else { - if (PlayerInput.LeftButtonDown()) - { - MapEntity.DisableSelect = true; - MapEntity.SelectEntity(item); - draggingWire = this; - selectedNodeIndex = i; - break; - } - else if (PlayerInput.RightButtonClicked()) - { - nodes.RemoveAt(i); - break; - } + GUI.DrawRectangle(spriteBatch, drawPos + new Vector2(-3, -3), new Vector2(6, 6), item.Color, true, 0.0f); } } + } - if (PlayerInput.LeftButtonHeld()) + public static void UpdateEditing(List wires) + { + //dragging a node of some wire + if (draggingWire != null) { - if (selectedNodeIndex != null && draggingWire == this) + //cancel dragging + if (!PlayerInput.LeftButtonHeld()) + { + draggingWire = null; + selectedNodeIndex = null; + } + //update dragging + else { MapEntity.DisableSelect = true; - //Nodes[(int)selectedNodeIndex] = GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition)-Submarine.HiddenSubPosition+Submarine.Loaded.Position; - Submarine sub = null; - if (connections[0] != null && connections[0].Item.Submarine != null) sub = connections[0].Item.Submarine; - if (connections[1] != null && connections[1].Item.Submarine != null) sub = connections[1].Item.Submarine; + if (draggingWire.connections[0] != null && draggingWire.connections[0].Item.Submarine != null) sub = draggingWire.connections[0].Item.Submarine; + if (draggingWire.connections[1] != null && draggingWire.connections[1].Item.Submarine != null) sub = draggingWire.connections[1].Item.Submarine; Vector2 nodeWorldPos = GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition) - sub.HiddenSubPosition - sub.Position;// Nodes[(int)selectedNodeIndex]; nodeWorldPos.X = MathUtils.Round(nodeWorldPos.X, Submarine.GridSize.X / 2.0f); nodeWorldPos.Y = MathUtils.Round(nodeWorldPos.Y, Submarine.GridSize.Y / 2.0f); - //if (item.Submarine != null) nodeWorldPos += item.Submarine.Position; + draggingWire.nodes[(int)selectedNodeIndex] = nodeWorldPos; + draggingWire.UpdateSections(); - nodes[(int)selectedNodeIndex] = nodeWorldPos; - UpdateSections(); + MapEntity.SelectEntity(draggingWire.item); + } - MapEntity.SelectEntity(item); + return; + } + + //a wire has been selected -> check if we should start dragging one of the nodes + float nodeSelectDist = 10, sectionSelectDist = 5; + highlightedNodeIndex = null; + if (MapEntity.SelectedList.Count == 1 && MapEntity.SelectedList[0] is Item) + { + Wire selectedWire = ((Item)MapEntity.SelectedList[0]).GetComponent(); + + if (selectedWire != null) + { + Vector2 mousePos = GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition); + if (selectedWire.item.Submarine != null) mousePos -= (selectedWire.item.Submarine.Position + selectedWire.item.Submarine.HiddenSubPosition); + + //left click while holding ctrl -> check if the cursor is on a wire section, + //and add a new node if it is + if (PlayerInput.KeyDown(Keys.RightControl) || PlayerInput.KeyDown(Keys.LeftControl)) + { + if (PlayerInput.LeftButtonClicked()) + { + float temp = 0.0f; + int closestSectionIndex = selectedWire.GetClosestSectionIndex(mousePos, sectionSelectDist, out temp); + + if (closestSectionIndex > -1) + { + selectedWire.nodes.Insert(closestSectionIndex + 1, mousePos); + selectedWire.UpdateSections(); + } + } + } + else + { + //check if close enough to a node + float temp = 0.0f; + int closestIndex = selectedWire.GetClosestNodeIndex(mousePos, nodeSelectDist, out temp); + if (closestIndex > -1) + { + highlightedNodeIndex = closestIndex; + //start dragging the node + if (PlayerInput.LeftButtonHeld()) + { + draggingWire = selectedWire; + selectedNodeIndex = closestIndex; + } + //remove the node + else if (PlayerInput.RightButtonClicked() && closestIndex > 0 && closestIndex < selectedWire.nodes.Count - 1) + { + selectedWire.nodes.RemoveAt(closestIndex); + selectedWire.UpdateSections(); + } + } + } } } - else + + //check which wire is highlighted with the cursor + Wire highlighted = null; + float closestDist = 0.0f; + foreach (Wire w in wires) { - selectedNodeIndex = null; - draggingWire = null; + Vector2 mousePos = GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition); + if (w.item.Submarine != null) mousePos -= (w.item.Submarine.Position + w.item.Submarine.HiddenSubPosition); + + float dist = 0.0f; + if (w.GetClosestNodeIndex(mousePos, highlighted == null ? nodeSelectDist : closestDist, out dist) > -1) + { + highlighted = w; + closestDist = dist; + } + + if (w.GetClosestSectionIndex(mousePos, highlighted == null ? sectionSelectDist : closestDist, out dist) > -1) + { + highlighted = w; + closestDist = dist; + } + + } + + + if (highlighted != null) + { + highlighted.item.IsHighlighted = true; + + if (PlayerInput.LeftButtonClicked()) + { + MapEntity.DisableSelect = true; + MapEntity.SelectEntity(highlighted.item); + } } } + private int GetClosestNodeIndex(Vector2 pos, float maxDist, out float closestDist) + { + closestDist = 0.0f; + int closestIndex = -1; + + for (int i = 0; i < nodes.Count; i++) + { + float dist = Vector2.Distance(nodes[i], pos); + if (dist > maxDist) continue; + + if (closestIndex == -1 || dist < closestDist) + { + closestIndex = i; + closestDist = dist; + } + } + + return closestIndex; + } + + private int GetClosestSectionIndex(Vector2 mousePos, float maxDist, out float closestDist) + { + closestDist = 0.0f; + int closestIndex = -1; + + for (int i = 0; i < nodes.Count-1; i++) + { + if ((Math.Abs(nodes[i].X - nodes[i + 1].X)<5 || Math.Sign(mousePos.X - nodes[i].X) != Math.Sign(mousePos.X - nodes[i + 1].X)) && + (Math.Abs(nodes[i].Y - nodes[i + 1].Y)<5 || Math.Sign(mousePos.Y - nodes[i].Y) != Math.Sign(mousePos.Y - nodes[i + 1].Y))) + { + float dist = MathUtils.LineToPointDistance(nodes[i], nodes[i + 1], mousePos); + if (dist > maxDist) continue; + + if (closestIndex == -1 || dist < closestDist) + { + closestIndex = i; + closestDist = dist; + } + } + } + + return closestIndex; + } + public override void FlipX() { for (int i = 0; i < nodes.Count; i++) @@ -555,7 +685,20 @@ namespace Barotrauma.Items.Components } Drawable = nodes.Any(); + } + protected override void ShallowRemoveComponentSpecific() + { + for (int i = 0; i < 2; i++) + { + if (connections[i] == null) continue; + int wireIndex = connections[i].FindWireIndex(item); + + if (wireIndex > -1) + { + connections[i].AddLink(wireIndex, null); + } + } } protected override void RemoveComponentSpecific() diff --git a/Subsurface/Source/Items/Item.cs b/Subsurface/Source/Items/Item.cs index 1742e6832..0967c652e 100644 --- a/Subsurface/Source/Items/Item.cs +++ b/Subsurface/Source/Items/Item.cs @@ -888,6 +888,11 @@ namespace Barotrauma } } + public override bool IsVisible(Rectangle worldView) + { + return drawableComponents.Count > 0 || body == null || body.Enabled; + } + public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) { if (!Visible) return; @@ -1137,28 +1142,40 @@ namespace Barotrauma foreach (ItemComponent ic in components) { - ic.DrawHUD(spriteBatch, character); + if (ic.CanBeSelected) ic.DrawHUD(spriteBatch, character); } } public override void AddToGUIUpdateList() { - if (condition <= 0.0f) - { - FixRequirement.AddToGUIUpdateList(); - return; - } - if (HasInGameEditableProperties) + if (Screen.Selected is EditMapScreen) { if (editingHUD != null) editingHUD.AddToGUIUpdateList(); } - foreach (ItemComponent ic in components) + else { - ic.AddToGUIUpdateList(); + if (HasInGameEditableProperties) + { + if (editingHUD != null) editingHUD.AddToGUIUpdateList(); + } + } + + if (Character.Controlled != null && Character.Controlled.SelectedConstruction == this) + { + if (condition <= 0.0f) + { + FixRequirement.AddToGUIUpdateList(); + return; + } + + foreach (ItemComponent ic in components) + { + if (ic.CanBeSelected) ic.AddToGUIUpdateList(); + } } - if (Screen.Selected is EditMapScreen && editingHUD != null) editingHUD.AddToGUIUpdateList(); } + public virtual void UpdateHUD(Camera cam, Character character) { if (condition <= 0.0f) @@ -1949,16 +1966,22 @@ namespace Barotrauma GameMain.Client.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.ComponentState, index }); } + /// + /// Remove the item so that it doesn't appear to exist in the game world (stop sounds, remove bodies etc) + /// but don't reset anything that's required for cloning the item + /// public override void ShallowRemove() { base.ShallowRemove(); Removed = true; + foreach (ItemComponent ic in components) { - ic.Remove(); + ic.ShallowRemove(); } ItemList.Remove(this); + if (body != null) { body.Remove(); @@ -2000,4 +2023,4 @@ namespace Barotrauma } } -} +} \ No newline at end of file diff --git a/Subsurface/Source/Map/Explosion.cs b/Subsurface/Source/Map/Explosion.cs index de65641be..ba3a750f3 100644 --- a/Subsurface/Source/Map/Explosion.cs +++ b/Subsurface/Source/Map/Explosion.cs @@ -119,15 +119,21 @@ namespace Barotrauma foreach (Limb limb in c.AnimController.Limbs) { float dist = Vector2.Distance(limb.WorldPosition, worldPosition); + + //calculate distance from the "outer surface" of the physics body + //doesn't take the rotation of the limb into account, but should be accurate enough for this purpose + float limbRadius = Math.Max(Math.Max(limb.body.width * 0.5f, limb.body.height * 0.5f), limb.body.radius); + dist = Math.Max(0.0f, dist - FarseerPhysics.ConvertUnits.ToDisplayUnits(limbRadius)); if (dist > range) continue; float distFactor = 1.0f - dist / range; - if (limb.WorldPosition == worldPosition) continue; - c.AddDamage(limb.WorldPosition, DamageType.None, damage / c.AnimController.Limbs.Length * distFactor, 0.0f, stun * distFactor, false); + + if (limb.WorldPosition == worldPosition) continue; + if (force > 0.0f) { limb.body.ApplyLinearImpulse(Vector2.Normalize(limb.WorldPosition - worldPosition) * distFactor * force); @@ -136,11 +142,12 @@ namespace Barotrauma } } - public static void RangedStructureDamage(Vector2 worldPosition, float worldRange, float damage) + /// + /// Returns a dictionary where the keys are the structures that took damage and the values are the amount of damage taken + /// + public static Dictionary RangedStructureDamage(Vector2 worldPosition, float worldRange, float damage) { - List structureList = new List(); - - + List structureList = new List(); float dist = 600.0f; foreach (MapEntity entity in MapEntity.mapEntityList) { @@ -155,14 +162,28 @@ namespace Barotrauma } } + Dictionary damagedStructures = new Dictionary(); foreach (Structure structure in structureList) { for (int i = 0; i < structure.SectionCount; i++) { float distFactor = 1.0f - (Vector2.Distance(structure.SectionPosition(i, true), worldPosition) / worldRange); - if (distFactor > 0.0f) structure.AddDamage(i, damage * distFactor); - } + if (distFactor <= 0.0f) continue; + + structure.AddDamage(i, damage * distFactor); + + if (damagedStructures.ContainsKey(structure)) + { + damagedStructures[structure] += damage * distFactor; + } + else + { + damagedStructures.Add(structure, damage * distFactor); + } + } } + + return damagedStructures; } } } diff --git a/Subsurface/Source/Map/Gap.cs b/Subsurface/Source/Map/Gap.cs index b99a83ddf..f7b23a11b 100644 --- a/Subsurface/Source/Map/Gap.cs +++ b/Subsurface/Source/Map/Gap.cs @@ -80,6 +80,14 @@ namespace Barotrauma } } + public override string Name + { + get + { + return "Gap"; + } + } + public override bool SelectableInEditor { get @@ -197,7 +205,13 @@ namespace Barotrauma Color clr = (open == 0.0f) ? Color.Red : Color.Cyan; if (isHighlighted) clr = Color.Gold; - GUI.DrawRectangle(sb, new Rectangle(WorldRect.X, -WorldRect.Y, rect.Width, rect.Height), clr * 0.5f, true,0, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f)); + float depth = (ID % 255) * 0.000001f; + + GUI.DrawRectangle( + sb, new Rectangle(WorldRect.X, -WorldRect.Y, rect.Width, rect.Height), + clr * 0.5f, true, + depth, + (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f)); for (int i = 0; i < linkedTo.Count; i++) { @@ -209,10 +223,10 @@ namespace Barotrauma arrowPos += new Vector2(dir.X * (WorldRect.Width / 2 + 10), dir.Y * (WorldRect.Height / 2 + 10)); GUI.Arrow.Draw(sb, - arrowPos, - clr * 0.8f, + arrowPos, clr * 0.8f, GUI.Arrow.Origin, MathUtils.VectorToAngle(dir) + MathHelper.PiOver2, - isHorizontal ? new Vector2(rect.Height / 16.0f, 1.0f) : new Vector2(rect.Width / 16.0f, 1.0f)); + isHorizontal ? new Vector2(rect.Height / 16.0f, 1.0f) : new Vector2(rect.Width / 16.0f, 1.0f), + SpriteEffects.None, depth); } if (IsSelected) @@ -222,7 +236,7 @@ namespace Barotrauma new Vector2(rect.Width + 10, rect.Height + 10), Color.Red, false, - 0, + depth, (int)Math.Max((1.5f / GameScreen.Selected.Cam.Zoom), 1.0f)); } } diff --git a/Subsurface/Source/Map/Hull.cs b/Subsurface/Source/Map/Hull.cs index d68135eaf..95a1bf639 100644 --- a/Subsurface/Source/Map/Hull.cs +++ b/Subsurface/Source/Map/Hull.cs @@ -596,7 +596,7 @@ namespace Barotrauma GUI.DrawRectangle(spriteBatch, new Vector2(drawRect.X, -drawRect.Y), new Vector2(rect.Width, rect.Height), - Color.Blue, false, 0, (int)Math.Max((1.5f / Screen.Selected.Cam.Zoom), 1.0f)); + Color.Blue, false, (ID % 255) * 0.000001f, (int)Math.Max((1.5f / Screen.Selected.Cam.Zoom), 1.0f)); GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.X, -drawRect.Y, rect.Width, rect.Height), @@ -607,7 +607,6 @@ namespace Barotrauma spriteBatch.DrawString(GUI.SmallFont, "Pressure: " + ((int)pressure - rect.Y).ToString() + " - Oxygen: " + ((int)OxygenPercentage), new Vector2(drawRect.X + 5, -drawRect.Y + 5), Color.White); spriteBatch.DrawString(GUI.SmallFont, volume + " / " + FullVolume, new Vector2(drawRect.X + 5, -drawRect.Y + 20), Color.White); - } if ((IsSelected || isHighlighted) && editing) diff --git a/Subsurface/Source/Map/Levels/CaveGenerator.cs b/Subsurface/Source/Map/Levels/CaveGenerator.cs index 539cb595c..542ba571c 100644 --- a/Subsurface/Source/Map/Levels/CaveGenerator.cs +++ b/Subsurface/Source/Map/Levels/CaveGenerator.cs @@ -348,9 +348,9 @@ namespace Barotrauma return pathCells; } - public static List GeneratePolygons(List cells, out List verticeList, bool setSolid=true) + public static List GeneratePolygons(List cells, out List verticeList, bool setSolid=true) { - verticeList = new List(); + verticeList = new List(); var bodies = new List(); List tempVertices = new List(); @@ -388,7 +388,12 @@ namespace Barotrauma { foreach (Vector2 vertex in triangles[i]) { - verticeList.Add(new VertexPositionColor(new Vector3(vertex, 0.0f), Color.Black)); + //shift the coordinates around a bit to make the texture repetition less obvious + Vector2 uvCoords = new Vector2( + vertex.X / 2000.0f + (float)Math.Sin(vertex.X / 500.0f) * 0.15f, + vertex.Y / 2000.0f + (float)Math.Sin(vertex.Y / 700.0f) * 0.15f); + + verticeList.Add(new VertexPositionTexture(new Vector3(vertex, 1.0f), uvCoords)); } } diff --git a/Subsurface/Source/Map/Levels/Level.cs b/Subsurface/Source/Map/Levels/Level.cs index a48a4ca3d..03496ccdc 100644 --- a/Subsurface/Source/Map/Levels/Level.cs +++ b/Subsurface/Source/Map/Levels/Level.cs @@ -183,8 +183,12 @@ namespace Barotrauma float avgValue = (backgroundColor.R + backgroundColor.G + backgroundColor.G) / 3; GameMain.LightManager.AmbientLight = new Color(backgroundColor * (10.0f / avgValue), 1.0f); - float minWidth = Submarine.MainSub == null ? 0.0f : Math.Max(Submarine.MainSub.Borders.Width, Submarine.MainSub.Borders.Height); - minWidth = Math.Max(minWidth, 6500.0f); + float minWidth = 6500.0f; + if (Submarine.MainSub != null) + { + Rectangle dockedSubBorders = Submarine.MainSub.GetDockedBorders(); + minWidth = Math.Max(minWidth, Math.Max(dockedSubBorders.Width, dockedSubBorders.Height)); + } startPosition = new Vector2( Rand.Range(minWidth, minWidth * 2, false), @@ -437,7 +441,7 @@ namespace Barotrauma List cellsWithBody = new List(cells); - List bodyVertices; + List bodyVertices; bodies = CaveGenerator.GeneratePolygons(cellsWithBody, out bodyVertices); renderer.SetBodyVertices(bodyVertices.ToArray()); @@ -692,6 +696,8 @@ namespace Barotrauma int iter = 0; + ruinPos.Y = Math.Min(borders.Y + borders.Height - ruinSize.Y/2, ruinPos.Y); + while (mainPath.Any(p => Vector2.Distance(ruinPos, p.Center) < ruinRadius * 2.0f)) { Vector2 weighedPathPos = ruinPos; @@ -711,6 +717,7 @@ namespace Barotrauma //} weighedPathPos += moveAmount; + weighedPathPos.Y = Math.Min(borders.Y + borders.Height - ruinSize.Y / 2, weighedPathPos.Y); } ruinPos = weighedPathPos; @@ -743,10 +750,18 @@ namespace Barotrauma { var tooClose = GetTooCloseCells(ruinShape.Rect.Center.ToVector2(), Math.Max(ruinShape.Rect.Width, ruinShape.Rect.Height)); - tooClose.ForEach(c => + foreach (VoronoiCell cell in tooClose) { - if (c.edges.Any(e => ruinShape.Rect.Contains(e.point1) || ruinShape.Rect.Contains(e.point2))) c.CellType = CellType.Empty; - }); + if (cell.CellType == CellType.Empty) continue; + foreach (GraphEdge e in cell.edges) + { + if (MathUtils.GetLineRectangleIntersection(e.point1, e.point2, ruinShape.Rect) != null) + { + cell.CellType = CellType.Empty; + break; + } + } + } } } diff --git a/Subsurface/Source/Map/Levels/LevelRenderer.cs b/Subsurface/Source/Map/Levels/LevelRenderer.cs index 0910925c2..3c1cb824a 100644 --- a/Subsurface/Source/Map/Levels/LevelRenderer.cs +++ b/Subsurface/Source/Map/Levels/LevelRenderer.cs @@ -11,7 +11,7 @@ namespace Barotrauma { class LevelRenderer : IDisposable { - private static BasicEffect basicEffect; + private static BasicEffect wallEdgeEffect, wallCenterEffect; private static Sprite background, backgroundTop; private static Sprite dustParticles; @@ -39,14 +39,29 @@ namespace Barotrauma dustParticles = new Sprite("Content/Map/dustparticles.png", Vector2.Zero); } - if (basicEffect == null) + if (wallEdgeEffect == null) { - basicEffect = new BasicEffect(GameMain.CurrGraphicsDevice); - basicEffect.VertexColorEnabled = false; - - basicEffect.TextureEnabled = true; - basicEffect.Texture = TextureLoader.FromFile("Content/Map/iceWall.png"); + wallEdgeEffect = new BasicEffect(GameMain.CurrGraphicsDevice) + { + DiffuseColor = new Vector3(0.8f, 0.8f, 0.8f), + VertexColorEnabled = false, + TextureEnabled = true, + Texture = shaftTexture + }; + wallEdgeEffect.CurrentTechnique = wallEdgeEffect.Techniques["BasicEffect_Texture"]; } + + if (wallCenterEffect == null) + { + wallCenterEffect = new BasicEffect(GameMain.CurrGraphicsDevice) + { + VertexColorEnabled = false, + TextureEnabled = true, + Texture = backgroundTop.Texture + }; + wallCenterEffect.CurrentTechnique = wallCenterEffect.Techniques["BasicEffect_Texture"]; + } + if (backgroundSpriteManager==null) { @@ -79,9 +94,9 @@ namespace Barotrauma wallVertices.SetData(vertices); } - public void SetBodyVertices(VertexPositionColor[] vertices) + public void SetBodyVertices(VertexPositionTexture[] vertices) { - bodyVertices = new VertexBuffer(GameMain.CurrGraphicsDevice, VertexPositionColor.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly); + bodyVertices = new VertexBuffer(GameMain.CurrGraphicsDevice, VertexPositionTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly); bodyVertices.SetData(vertices); } @@ -96,21 +111,20 @@ namespace Barotrauma if (backgroundPos.Y < 1024) { - if (backgroundPos.Y > -1024) - { - background.SourceRect = new Rectangle((int)backgroundPos.X, (int)Math.Max(backgroundPos.Y, 0), 1024, 1024); - background.DrawTiled(spriteBatch, - (backgroundPos.Y < 0) ? new Vector2(0.0f, -backgroundPos.Y) : Vector2.Zero, - new Vector2(GameMain.GraphicsWidth, 1024 - backgroundPos.Y), - Vector2.Zero, level.BackgroundColor); - } - if (backgroundPos.Y < 0) { backgroundTop.SourceRect = new Rectangle((int)backgroundPos.X, (int)backgroundPos.Y, 1024, (int)Math.Min(-backgroundPos.Y, 1024)); backgroundTop.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(GameMain.GraphicsWidth, Math.Min(-backgroundPos.Y, GameMain.GraphicsHeight)), Vector2.Zero, level.BackgroundColor); } + if (backgroundPos.Y > -1024) + { + background.SourceRect = new Rectangle((int)backgroundPos.X, (int)Math.Max(backgroundPos.Y, 0), 1024, 1024); + background.DrawTiled(spriteBatch, + (backgroundPos.Y < 0) ? new Vector2(0.0f, (int)-backgroundPos.Y) : Vector2.Zero, + new Vector2(GameMain.GraphicsWidth, (int)Math.Ceiling(1024 - backgroundPos.Y)), + Vector2.Zero, level.BackgroundColor); + } } spriteBatch.End(); @@ -165,12 +179,12 @@ namespace Barotrauma GUI.DrawLine(spriteBatch, new Vector2(cell.edges[0].point1.X, -cell.edges[0].point1.Y), new Vector2(cell.Center.X, -cell.Center.Y), - Color.White); + Color.Blue*0.5f); foreach (GraphEdge edge in cell.edges) { GUI.DrawLine(spriteBatch, new Vector2(edge.point1.X, -edge.point1.Y), - new Vector2(edge.point2.X, -edge.point2.Y), cell.body==null ? Color.Gray : Color.White); + new Vector2(edge.point2.X, -edge.point2.Y), cell.body==null ? Color.Cyan*0.5f : Color.White); } foreach (Vector2 point in cell.bodyVertices) @@ -205,64 +219,21 @@ namespace Barotrauma { if (wallVertices == null) return; - basicEffect.World = cam.ShaderTransform - * Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f; + wallEdgeEffect.World = cam.ShaderTransform + * Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 100) * 0.5f; + wallCenterEffect.World = wallEdgeEffect.World; + //render the solid center of the wall cells graphicsDevice.SamplerStates[0] = SamplerState.LinearWrap; - graphicsDevice.BlendState = BlendState.AlphaBlend; graphicsDevice.SetVertexBuffer(bodyVertices); - - basicEffect.VertexColorEnabled = true; - basicEffect.TextureEnabled = false; - basicEffect.CurrentTechnique = basicEffect.Techniques["BasicEffect_VertexColor"]; - basicEffect.CurrentTechnique.Passes[0].Apply(); + wallCenterEffect.CurrentTechnique.Passes[0].Apply(); 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++) - { - basicEffect.World = Matrix.CreateTranslation(new Vector3(level.WrappingWalls[side, i].Offset, 0.0f)) * cam.ShaderTransform - * Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f; - basicEffect.CurrentTechnique.Passes[0].Apply(); - - - graphicsDevice.SetVertexBuffer(level.WrappingWalls[side, i].BodyVertices); - - graphicsDevice.DrawPrimitives( - PrimitiveType.TriangleList, 0, - (int)Math.Floor(level.WrappingWalls[side, i].BodyVertices.VertexCount / 3.0f)); - } - }*/ - - - graphicsDevice.SetVertexBuffer(wallVertices); - basicEffect.VertexColorEnabled = false; - basicEffect.TextureEnabled = true; - 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++) - { - - basicEffect.World = Matrix.CreateTranslation(new Vector3(level.WrappingWalls[side,i].Offset, 0.0f)) * cam.ShaderTransform - * Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f; - basicEffect.CurrentTechnique.Passes[0].Apply(); - - graphicsDevice.SetVertexBuffer(level.WrappingWalls[side, i].WallVertices); - - graphicsDevice.DrawPrimitives( - PrimitiveType.TriangleList, 0, - (int)Math.Floor(level.WrappingWalls[side, i].WallVertices.VertexCount / 3.0f)); - - } - }*/ + //render the edges of the wall cells + graphicsDevice.SetVertexBuffer(wallVertices); + wallEdgeEffect.CurrentTechnique.Passes[0].Apply(); + graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (int)Math.Floor(wallVertices.VertexCount / 3.0f)); } public void Dispose() diff --git a/Subsurface/Source/Map/Lights/LightSource.cs b/Subsurface/Source/Map/Lights/LightSource.cs index 770d25443..f6d21525d 100644 --- a/Subsurface/Source/Map/Lights/LightSource.cs +++ b/Subsurface/Source/Map/Lights/LightSource.cs @@ -185,7 +185,8 @@ namespace Barotrauma.Lights if (NeedsHullUpdate) { var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub); - chList.List = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)); + if (fullChList != null) + chList.List = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)); } } //light is outside, convexhull inside a sub @@ -299,7 +300,7 @@ namespace Barotrauma.Lights if (ParentSub != null) drawPos += ParentSub.DrawPosition; drawPos.Y = -drawPos.Y; - + if (range > 1.0f) { if (overrideLightTexture == null) @@ -326,6 +327,24 @@ namespace Barotrauma.Lights } } + public void FlipX() + { + SpriteEffect = SpriteEffect == SpriteEffects.None ? SpriteEffects.FlipHorizontally : SpriteEffects.None; + if (LightSprite != null) + { + Vector2 lightOrigin = LightSprite.Origin; + lightOrigin.X = LightSprite.SourceRect.Width - lightOrigin.X; + LightSprite.Origin = lightOrigin; + } + + if (overrideLightTexture != null) + { + Vector2 lightOrigin = overrideLightTexture.Origin; + lightOrigin.X = overrideLightTexture.SourceRect.Width - lightOrigin.X; + overrideLightTexture.Origin = lightOrigin; + } + } + public void Remove() { if (LightSprite != null) LightSprite.Remove(); diff --git a/Subsurface/Source/Map/LinkedSubmarine.cs b/Subsurface/Source/Map/LinkedSubmarine.cs index 856a65f65..631f76248 100644 --- a/Subsurface/Source/Map/LinkedSubmarine.cs +++ b/Subsurface/Source/Map/LinkedSubmarine.cs @@ -405,19 +405,29 @@ namespace Barotrauma } else { - sub.SetPosition(WorldPosition - Submarine.WorldPosition); - sub.Submarine = Submarine; + sub.SetPosition(WorldPosition); } - - var linkedItem = linkedTo.FirstOrDefault(lt => (lt is Item) && ((Item)lt).GetComponent() != null); - if (linkedItem == null) return; - - var linkedPort = ((Item)linkedItem).GetComponent(); + DockingPort linkedPort = null; DockingPort myPort = null; - float closestDistance = 0.0f; + + MapEntity linkedItem = linkedTo.FirstOrDefault(lt => (lt is Item) && ((Item)lt).GetComponent() != null); + if (linkedItem == null) + { + linkedPort = DockingPort.list.Find(dp => dp.DockingTarget != null && dp.DockingTarget.Item.Submarine == sub); + } + else + { + linkedPort = ((Item)linkedItem).GetComponent(); + } + if (linkedPort == null) + { + return; + } + + float closestDistance = 0.0f; foreach (DockingPort port in DockingPort.list) { if (port.Item.Submarine != sub || port.IsHorizontal != linkedPort.IsHorizontal) continue; @@ -432,8 +442,23 @@ namespace Barotrauma if (myPort != null) { - myPort.DockingTarget = linkedPort; - } + Vector2 portDiff = myPort.Item.WorldPosition - sub.WorldPosition; + Vector2 offset = (myPort.IsHorizontal ? + Vector2.UnitX * Math.Sign(linkedPort.Item.WorldPosition.X - myPort.Item.WorldPosition.X) : + Vector2.UnitY * Math.Sign(linkedPort.Item.WorldPosition.Y - myPort.Item.WorldPosition.Y)); + offset *= myPort.DockedDistance; + + sub.SetPosition( + (linkedPort.Item.WorldPosition - portDiff) + - offset); + + + myPort.Dock(linkedPort); + myPort.Lock(); + } + + sub.SetPosition(sub.WorldPosition - Submarine.WorldPosition); + sub.Submarine = Submarine; } } } diff --git a/Subsurface/Source/Map/MapEntity.cs b/Subsurface/Source/Map/MapEntity.cs index 0ad25bb11..97d97536c 100644 --- a/Subsurface/Source/Map/MapEntity.cs +++ b/Subsurface/Source/Map/MapEntity.cs @@ -26,7 +26,18 @@ namespace Barotrauma } } private static List copiedList = new List(); - + + private static List highlightedList = new List(); + + private static float highlightTimer; + + private static GUIListBox highlightedListBox; + public static GUIListBox HighlightedListBox + { + get { return highlightedListBox; } + } + + protected static GUIComponent editingHUD; public static GUIComponent EditingHUD { @@ -243,6 +254,7 @@ namespace Barotrauma //clone links between the entities for (int i = 0; i < clones.Count; i++) { + if (entitiesToClone[i].linkedTo == null) continue; foreach (MapEntity linked in entitiesToClone[i].linkedTo) { if (!entitiesToClone.Contains(linked)) continue; @@ -307,6 +319,11 @@ namespace Barotrauma mapEntityList.Insert(i, this); } + public virtual bool IsVisible(Rectangle worldView) + { + return true; + } + public virtual void Draw(SpriteBatch spriteBatch, bool editing, bool back=true) {} public virtual void DrawDamage(SpriteBatch spriteBatch, Effect damageEffect) {} @@ -329,6 +346,11 @@ namespace Barotrauma mapEntityList.Remove(this); + if (selectedList.Contains(this)) + { + selectedList = selectedList.FindAll(e => e != this); + } + if (aiTarget != null) aiTarget.Remove(); if (linkedTo != null) @@ -369,7 +391,7 @@ namespace Barotrauma public virtual void Update(Camera cam, float deltaTime) { } /// - /// Update the selection logic in editmap-screen + /// Update the selection logic in submarine editor /// public static void UpdateSelecting(Camera cam) { @@ -390,7 +412,15 @@ namespace Barotrauma return; } - if (GUIComponent.MouseOn != null || !PlayerInput.MouseInsideWindow) return; + if (GUIComponent.MouseOn != null || !PlayerInput.MouseInsideWindow) + { + if (highlightedListBox == null || + (GUIComponent.MouseOn != highlightedListBox && !highlightedListBox.IsParentOf(GUIComponent.MouseOn))) + { + UpdateHighlightedListBox(null); + return; + } + } if (MapEntityPrefab.Selected != null) { @@ -428,10 +458,12 @@ namespace Barotrauma Vector2 center = Vector2.Zero; clones.ForEach(c => center += c.WorldPosition); - center /= clones.Count; + center = Submarine.VectorToWorldGrid(center / clones.Count); + + Vector2 moveAmount = Submarine.VectorToWorldGrid(cam.WorldViewCenter - center); selectedList = new List(clones); - selectedList.ForEach(c => c.Move(cam.WorldViewCenter - center)); + selectedList.ForEach(c => c.Move(moveAmount)); } } @@ -441,19 +473,62 @@ namespace Barotrauma if (startMovingPos == Vector2.Zero) { - foreach (MapEntity e in mapEntityList) + List highlightedEntities = new List(); + if (highlightedListBox != null && highlightedListBox.IsParentOf(GUIComponent.MouseOn)) { - if (!e.SelectableInEditor) continue; - - if (highLightedEntity == null || e.Sprite == null || - (highLightedEntity.Sprite != null && e.Sprite.Depth < highLightedEntity.Sprite.Depth)) + highLightedEntity = GUIComponent.MouseOn.UserData as MapEntity; + } + else + { + foreach (MapEntity e in mapEntityList) { - if (e.IsMouseOn(position)) highLightedEntity = e; + if (!e.SelectableInEditor) continue; + + if (e.IsMouseOn(position)) + { + int i = 0; + while (i < highlightedEntities.Count && + e.Sprite != null && + (highlightedEntities[i].Sprite == null || highlightedEntities[i].Sprite.Depth < e.Sprite.Depth)) + { + i++; + } + + highlightedEntities.Insert(i, e); + + if (i == 0) highLightedEntity = e; + } + } + + if (PlayerInput.MouseSpeed.LengthSquared() > 10) + { + highlightTimer = 0.0f; + } + else + { + bool mouseNearHighlightBox = false; + + if (highlightedListBox != null) + { + Rectangle expandedRect = highlightedListBox.Rect; + expandedRect.Inflate(20, 20); + mouseNearHighlightBox = expandedRect.Contains(PlayerInput.MousePosition); + if (!mouseNearHighlightBox) highlightedListBox = null; + } + + highlightTimer += (float)Timing.Step; + if (highlightTimer > 1.0f) + { + if (!mouseNearHighlightBox) + { + UpdateHighlightedListBox(highlightedEntities); + highlightTimer = 0.0f; + } + } } } if (highLightedEntity != null) highLightedEntity.isHighlighted = true; - } //started moving selected entities @@ -501,11 +576,6 @@ namespace Barotrauma if (highLightedEntity != null) newSelection.Add(highLightedEntity); } - foreach (MapEntity e in newSelection) - { - e.isHighlighted = true; - } - if (PlayerInput.LeftButtonReleased()) { if (PlayerInput.KeyDown(Keys.LeftControl) || @@ -513,14 +583,7 @@ namespace Barotrauma { foreach (MapEntity e in newSelection) { - bool alreadySelected = false; - - foreach (MapEntity e2 in selectedList) - { - if (e.ID == e2.ID) alreadySelected = true; - } - - if (alreadySelected) + if (selectedList.Contains(e)) selectedList.Remove(e); else selectedList.Add(e); @@ -558,7 +621,8 @@ namespace Barotrauma else { if (PlayerInput.LeftButtonHeld() && - PlayerInput.KeyUp(Keys.Space)) + PlayerInput.KeyUp(Keys.Space) && + (highlightedListBox == null || (GUIComponent.MouseOn != highlightedListBox && !highlightedListBox.IsParentOf(GUIComponent.MouseOn)))) { //if clicking a selected entity, start moving it foreach (MapEntity e in selectedList) @@ -571,6 +635,57 @@ namespace Barotrauma } } + private static void UpdateHighlightedListBox(List highlightedEntities) + { + if (highlightedEntities == null || highlightedEntities.Count < 2) + { + highlightedListBox = null; + return; + } + if (highlightedListBox != null) + { + if (GUIComponent.MouseOn == highlightedListBox || highlightedListBox.IsParentOf(GUIComponent.MouseOn)) return; + if (highlightedEntities.SequenceEqual(highlightedList)) return; + } + + highlightedList = highlightedEntities; + + highlightedListBox = new GUIListBox( + new Rectangle((int)PlayerInput.MousePosition.X+15, (int)PlayerInput.MousePosition.Y+15, 150, highlightedEntities.Count * 15), + null, Alignment.TopLeft, GUI.Style, null, false); + + highlightedListBox.Color = Color.Black * 0.6f; + + foreach (MapEntity entity in highlightedEntities) + { + var textBlock = new GUITextBlock( + new Rectangle(0,0,0,15), + ToolBox.LimitString(entity.Name, GUI.SmallFont, 140), GUI.Style, highlightedListBox, GUI.SmallFont); + + textBlock.UserData = entity; + } + + highlightedListBox.OnSelected = (GUIComponent component, object obj) => + { + MapEntity entity = obj as MapEntity; + + if (PlayerInput.KeyDown(Keys.LeftControl) || + PlayerInput.KeyDown(Keys.RightControl)) + { + if (selectedList.Contains(entity)) + selectedList.Remove(entity); + else + selectedList.Add(entity); + } + else + { + SelectEntity(entity); + } + + return true; + }; + } + /// /// Draw the "selection rectangle" and outlines of entities that are being dragged (if any) @@ -608,6 +723,8 @@ namespace Barotrauma public static void UpdateEditor(Camera cam) { + if (highlightedListBox != null) highlightedListBox.Update((float)Timing.Step); + if (selectedList.Count == 1) { selectedList[0].UpdateEditing(cam); @@ -617,19 +734,21 @@ namespace Barotrauma selectedList[0].UpdateResizing(cam); } } - else + + if (editingHUD != null) { - if (editingHUD == null) return; - - foreach (GUIComponent component in editingHUD.children) + if (selectedList.Count == 0 || editingHUD.UserData != selectedList[0]) { - var textBox = component as GUITextBox; - if (textBox == null) continue; + foreach (GUIComponent component in editingHUD.children) + { + var textBox = component as GUITextBox; + if (textBox == null) continue; - textBox.Deselect(); + textBox.Deselect(); + } + + editingHUD = null; } - - editingHUD = null; } } @@ -644,6 +763,11 @@ namespace Barotrauma selectedList[0].DrawResizing(spriteBatch, cam); } } + + if (highlightedListBox != null) + { + highlightedListBox.Draw(spriteBatch); + } } public static void DeselectAll() @@ -658,8 +782,7 @@ namespace Barotrauma selectedList.Add(entity); } - - + /// /// copies a list of entities to the "clipboard" (copiedList) /// @@ -693,7 +816,7 @@ namespace Barotrauma public virtual void AddToGUIUpdateList() { - if (editingHUD != null) editingHUD.AddToGUIUpdateList(); + if (editingHUD != null && editingHUD.UserData == this) editingHUD.AddToGUIUpdateList(); } public virtual void UpdateEditing(Camera cam) { } diff --git a/Subsurface/Source/Map/Structure.cs b/Subsurface/Source/Map/Structure.cs index 8f35e98ab..775b66e72 100644 --- a/Subsurface/Source/Map/Structure.cs +++ b/Subsurface/Source/Map/Structure.cs @@ -101,7 +101,7 @@ namespace Barotrauma public override string Name { - get { return "structure"; } + get { return prefab.Name; } } public bool HasBody @@ -153,6 +153,11 @@ namespace Barotrauma } } + public List Tags + { + get { return prefab.tags; } + } + public override Rectangle Rect { get @@ -477,6 +482,15 @@ namespace Barotrauma if (convexHulls != null) convexHulls.ForEach(x => x.Remove()); } + public override bool IsVisible(Rectangle WorldView) + { + Rectangle worldRect = WorldRect; + + if (worldRect.X > WorldView.Right || worldRect.Right < WorldView.X) return false; + if (worldRect.Y < WorldView.Y - WorldView.Height || worldRect.Y - worldRect.Height > WorldView.Y) return false; + + return true; + } public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) { @@ -505,6 +519,9 @@ namespace Barotrauma Vector2 drawOffset = Submarine == null ? Vector2.Zero : Submarine.DrawPosition; + float depth = prefab.sprite.Depth; + depth -= (ID % 255) * 0.000001f; + if (back && damageEffect == null) { if (prefab.BackgroundSprite != null) @@ -513,7 +530,7 @@ namespace Barotrauma spriteBatch, new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)), new Vector2(rect.Width, rect.Height), - Vector2.Zero, color, Point.Zero); + color, Point.Zero); } } @@ -552,8 +569,8 @@ namespace Barotrauma spriteBatch, new Vector2(sections[i].rect.X + drawOffset.X, -(sections[i].rect.Y + drawOffset.Y)), new Vector2(sections[i].rect.Width, sections[i].rect.Height), - Vector2.Zero, color, - textureOffset); + color, + textureOffset, depth); } } diff --git a/Subsurface/Source/Map/StructurePrefab.cs b/Subsurface/Source/Map/StructurePrefab.cs index 3492fad31..b99087775 100644 --- a/Subsurface/Source/Map/StructurePrefab.cs +++ b/Subsurface/Source/Map/StructurePrefab.cs @@ -85,22 +85,9 @@ namespace Barotrauma { StructurePrefab sp = new StructurePrefab(); sp.name = element.Name.ToString(); - - //Vector4 sourceVector = ToolBox.GetAttributeVector4(element, "sourcerect", new Vector4(0,0,1,1)); - //Rectangle sourceRect = new Rectangle( - // (int)sourceVector.X, - // (int)sourceVector.Y, - // (int)sourceVector.Z, - // (int)sourceVector.W); - - //if (element.Attribute("sprite") != null) - //{ - // sp.sprite = new Sprite(element.Attribute("sprite").Value, sourceRect, Vector2.Zero); - - // sp.sprite.Depth = ToolBox.GetAttributeFloat(element, "depth", 0.0f); - - //} + sp.tags = new List(); + sp.tags.AddRange(ToolBox.GetAttributeString(element, "tags", "").Split(',')); foreach (XElement subElement in element.Elements()) { diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index 213c30924..e48cb5169 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -12,6 +12,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Xml.Linq; +using Voronoi2; namespace Barotrauma { @@ -298,11 +299,96 @@ namespace Barotrauma tags &= ~tag; } - //drawing ---------------------------------------------------- + /// + /// Returns a rect that contains the borders of this sub and all subs docked to it + /// + public Rectangle GetDockedBorders() + { + Rectangle dockedBorders = Borders; + dockedBorders.Y -= dockedBorders.Height; + + foreach (Submarine dockedSub in DockedTo) + { + Vector2 diff = dockedSub.Submarine == this ? dockedSub.WorldPosition : dockedSub.WorldPosition - WorldPosition; + + + Rectangle dockedSubBorders = dockedSub.Borders; + dockedSubBorders.Y -= dockedSubBorders.Height; + dockedSubBorders.Location += diff.ToPoint(); + + dockedBorders = Rectangle.Union(dockedBorders, dockedSubBorders); + } + + dockedBorders.Y += dockedBorders.Height; + return dockedBorders; + } + + public Vector2 FindSpawnPos(Vector2 spawnPos) + { + Rectangle dockedBorders = GetDockedBorders(); + + int iterations = 0; + bool wallTooClose = false; + do + { + Rectangle worldBorders = new Rectangle( + dockedBorders.X + (int)spawnPos.X, + dockedBorders.Y + (int)spawnPos.Y, + dockedBorders.Width, + dockedBorders.Height); + + wallTooClose = false; + + var nearbyCells = Level.Loaded.GetCells( + spawnPos, (int)Math.Ceiling(Math.Max(dockedBorders.Width, dockedBorders.Height) / (float)Level.GridCellSize)); + + foreach (VoronoiCell cell in nearbyCells) + { + if (cell.CellType == CellType.Empty) continue; + + foreach (GraphEdge e in cell.edges) + { + List intersections = MathUtils.GetLineRectangleIntersections(e.point1, e.point2, worldBorders); + foreach (Vector2 intersection in intersections) + { + wallTooClose = true; + + if (intersection.X < spawnPos.X) + { + spawnPos.X += intersection.X - worldBorders.X; + } + else + { + spawnPos.X += intersection.X - worldBorders.Right; + } + + if (intersection.Y < spawnPos.Y) + { + spawnPos.Y += intersection.Y - (worldBorders.Y - worldBorders.Height); + } + else + { + spawnPos.Y += intersection.Y - worldBorders.Y; + } + + spawnPos.Y = Math.Min(spawnPos.Y, Level.Loaded.Size.Y - dockedBorders.Height / 2); + } + } + } + + iterations++; + } while (wallTooClose && iterations < 10); + + return spawnPos; + + } + + //drawing ---------------------------------------------------- + public static void CullEntities(Camera cam) { - List visibleSubs = new List(); + HashSet visibleSubs = new HashSet(); foreach (Submarine sub in Submarine.Loaded) { Rectangle worldBorders = new Rectangle( @@ -311,19 +397,20 @@ namespace Barotrauma sub.Borders.Width + 1000, sub.Borders.Height + 1000); - if (Submarine.RectsOverlap(worldBorders, cam.WorldView)) { visibleSubs.Add(sub); } } + Rectangle worldView = cam.WorldView; + visibleEntities = new List(); foreach (MapEntity me in MapEntity.mapEntityList) { if (me.Submarine == null || visibleSubs.Contains(me.Submarine)) { - visibleEntities.Add(me); + if (me.IsVisible(worldView)) visibleEntities.Add(me); } } } @@ -827,11 +914,8 @@ namespace Barotrauma } } - public static void Preload() + public static void RefreshSavedSubs() { - - //string[] mapFilePaths; - //Unload(); SavedSubmarines.Clear(); if (!Directory.Exists(SavePath)) diff --git a/Subsurface/Source/Map/SubmarineBody.cs b/Subsurface/Source/Map/SubmarineBody.cs index 6a0f6906b..b882e5865 100644 --- a/Subsurface/Source/Map/SubmarineBody.cs +++ b/Subsurface/Source/Map/SubmarineBody.cs @@ -484,8 +484,6 @@ namespace Barotrauma Vector2 lastContactPoint = worldPoints[0]; - SoundPlayer.PlayDamageSound(DamageSoundType.StructureBlunt, impact * 10.0f, ConvertUnits.ToDisplayUnits(lastContactPoint)); - if (Character.Controlled != null && Character.Controlled.Submarine == submarine) { GameMain.GameScreen.Cam.Shake = impact * 2.0f; @@ -518,7 +516,29 @@ namespace Barotrauma item.body.ApplyLinearImpulse(item.body.Mass * impulse); } - Explosion.RangedStructureDamage(ConvertUnits.ToDisplayUnits(lastContactPoint), impact * 50.0f, impact * DamageMultiplier); + var damagedStructures = Explosion.RangedStructureDamage(ConvertUnits.ToDisplayUnits(lastContactPoint), impact * 50.0f, impact * DamageMultiplier); + + //play a damage sound for the structure that took the most damage + float maxDamage = 0.0f; + Structure maxDamageStructure = null; + foreach (KeyValuePair structureDamage in damagedStructures) + { + if (maxDamageStructure == null || structureDamage.Value > maxDamage) + { + maxDamage = structureDamage.Value; + maxDamageStructure = structureDamage.Key; + } + } + + if (maxDamageStructure != null) + { + SoundPlayer.PlayDamageSound( + DamageSoundType.StructureBlunt, + impact * 10.0f, + ConvertUnits.ToDisplayUnits(lastContactPoint), + MathHelper.Clamp(maxDamage * 4.0f, 1000.0f, 4000.0f), + maxDamageStructure.Tags); + } } } diff --git a/Subsurface/Source/Map/WayPoint.cs b/Subsurface/Source/Map/WayPoint.cs index 769a655bd..6575a5ff0 100644 --- a/Subsurface/Source/Map/WayPoint.cs +++ b/Subsurface/Source/Map/WayPoint.cs @@ -54,13 +54,13 @@ namespace Barotrauma set { spawnType = value; } } - //public override string Name - //{ - // get - // { - // return spawnType == SpawnType.Path ? "WayPoint" : "SpawnPoint"; - // } - //} + public override string Name + { + get + { + return spawnType == SpawnType.Path ? "WayPoint" : "SpawnPoint"; + } + } public string[] IdCardTags { diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index 06e419976..7bb5526dd 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -901,6 +901,8 @@ namespace Barotrauma.Networking if (autoRestart) AutoRestartTimer = Math.Max(AutoRestartInterval, 5.0f); GameMain.NetLobbyScreen.StartButton.Enabled = true; + UpdateNetLobby(null, null); + couldNotStart = true; } diff --git a/Subsurface/Source/Physics/PhysicsBody.cs b/Subsurface/Source/Physics/PhysicsBody.cs index 495b12425..037a62454 100644 --- a/Subsurface/Source/Physics/PhysicsBody.cs +++ b/Subsurface/Source/Physics/PhysicsBody.cs @@ -384,24 +384,16 @@ namespace Barotrauma //buoyancy Vector2 buoyancy = new Vector2(0, Mass * 9.6f); - //drag - Vector2 velDir = Vector2.Normalize(LinearVelocity); - - Vector2 line = new Vector2((float)Math.Cos(body.Rotation), (float)Math.Sin(body.Rotation)); - line *= Math.Max(height + radius*2, height); - - Vector2 normal = new Vector2(-line.Y, line.X); - normal = Vector2.Normalize(-normal); - - float dragDot = Math.Abs(Vector2.Dot(normal, velDir)); Vector2 dragForce = Vector2.Zero; - if (dragDot > 0) + + if (LinearVelocity.LengthSquared() > 0.00001f) { + //drag + Vector2 velDir = Vector2.Normalize(LinearVelocity); + float vel = LinearVelocity.Length() * 2.0f; - float drag = dragDot * vel * vel - * Math.Max(height + radius * 2, height); - dragForce = Math.Min(drag, Mass * 1000.0f) * -velDir; - //if (dragForce.Length() > 100.0f) { } + float drag = vel * vel * Math.Max(height + radius * 2, height); + dragForce = Math.Min(drag, Mass * 500.0f) * -velDir; } body.ApplyForce(dragForce + buoyancy); @@ -435,6 +427,8 @@ namespace Barotrauma UpdateDrawPosition(); + if (sprite == null) return; + SpriteEffects spriteEffect = (dir == 1.0f) ? SpriteEffects.None : SpriteEffects.FlipHorizontally; if (GameMain.DebugDraw && !body.Awake) diff --git a/Subsurface/Source/Program.cs b/Subsurface/Source/Program.cs index ebda383c2..201d399c6 100644 --- a/Subsurface/Source/Program.cs +++ b/Subsurface/Source/Program.cs @@ -53,6 +53,7 @@ namespace Barotrauma else { CrashDump(game, "crashreport.txt", e); + attemptRestart = false; } } diff --git a/Subsurface/Source/Screens/EditCharacterScreen.cs b/Subsurface/Source/Screens/EditCharacterScreen.cs index 3ef825e77..64e309ed3 100644 --- a/Subsurface/Source/Screens/EditCharacterScreen.cs +++ b/Subsurface/Source/Screens/EditCharacterScreen.cs @@ -85,7 +85,7 @@ namespace Barotrauma texturePaths = new List(); foreach (Limb limb in editingCharacter.AnimController.Limbs) { - if (texturePaths.Contains(limb.sprite.FilePath)) continue; + if (limb.sprite==null || texturePaths.Contains(limb.sprite.FilePath)) continue; textures.Add(limb.sprite.Texture); texturePaths.Add(limb.sprite.FilePath); } @@ -160,7 +160,7 @@ namespace Barotrauma foreach (Limb limb in editingCharacter.AnimController.Limbs) { - if (limb.sprite.FilePath != texturePaths[i]) continue; + if (limb.sprite == null || limb.sprite.FilePath != texturePaths[i]) continue; Rectangle rect = limb.sprite.SourceRect; rect.X += x; rect.Y += y; diff --git a/Subsurface/Source/Screens/EditMapScreen.cs b/Subsurface/Source/Screens/EditMapScreen.cs index 7e341b409..f3d687559 100644 --- a/Subsurface/Source/Screens/EditMapScreen.cs +++ b/Subsurface/Source/Screens/EditMapScreen.cs @@ -1,4 +1,5 @@ -using Microsoft.Xna.Framework; +using Barotrauma.Items.Components; +using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using System; @@ -30,6 +31,8 @@ namespace Barotrauma const int PreviouslyUsedCount = 10; private GUIListBox previouslyUsedList; + GUIDropDown linkedSubBox; + //a Character used for picking up and manipulating items private Character dummyCharacter; @@ -150,7 +153,7 @@ namespace Barotrauma var nameLabel = new GUITextBlock(new Rectangle(170, -4, 150, 20), "", GUI.Style, topPanel, GUI.LargeFont); nameLabel.TextGetter = GetSubName; - var linkedSubBox = new GUIDropDown(new Rectangle(750,0,200,20), "Add submarine", GUI.Style, topPanel); + linkedSubBox = new GUIDropDown(new Rectangle(750,0,200,20), "Add submarine", GUI.Style, topPanel); linkedSubBox.ToolTip = "Places another submarine into the current submarine file. "+ "Can be used for adding things such as smaller vessels, "+ @@ -191,7 +194,6 @@ namespace Barotrauma GUITextBox searchBox = new GUITextBox(new Rectangle(-20, 0, 180, 15), Alignment.TopRight, GUI.Style, GUItabs[i]); searchBox.Font = GUI.SmallFont; searchBox.OnTextChanged = FilterMessages; - GUIComponent.KeyboardDispatcher.Subscriber = searchBox; var clearButton = new GUIButton(new Rectangle(0, 0, 15, 15), "x", Alignment.TopRight, GUI.Style, GUItabs[i]); clearButton.OnClicked = ClearFilter; @@ -304,19 +306,25 @@ namespace Barotrauma if (Submarine.MainSub != null) { cam.Position = Submarine.MainSub.Position + Submarine.MainSub.HiddenSubPosition; - //nameBox.Text = Submarine.MainSub.Name; - //descriptionBox.Text = ToolBox.LimitString(Submarine.MainSub.Description, 15); } else { cam.Position = Submarine.HiddenSubStartPosition; - //if (nameBox != null) nameBox.Text = ""; - //descriptionBox.Text = ""; Submarine.MainSub = new Submarine(Path.Combine(Submarine.SavePath, "Unnamed.sub"), "", false); } - //nameBox.Deselect(); + SoundPlayer.OverrideMusicType = "none"; + for (int i = 0; i < Sounds.SoundManager.DefaultSourceCount; i++) + { + Sounds.SoundManager.Pause(i); + } + + linkedSubBox.ClearChildren(); + foreach (Submarine sub in Submarine.SavedSubmarines) + { + linkedSubBox.AddItem(sub.Name, sub); + } cam.UpdateTransform(); } @@ -335,6 +343,12 @@ namespace Barotrauma if (wiringMode) ToggleWiringMode(); + SoundPlayer.OverrideMusicType = null; + for (int i = 0; i < Sounds.SoundManager.DefaultSourceCount; i++) + { + Sounds.SoundManager.Resume(i); + } + if (dummyCharacter != null) { dummyCharacter.Remove(); @@ -391,6 +405,13 @@ namespace Barotrauma GUI.AddMessage("Submarine saved to " + Submarine.MainSub.FilePath, Color.Green, 3.0f); + Submarine.RefreshSavedSubs(); + linkedSubBox.ClearChildren(); + foreach (Submarine sub in Submarine.SavedSubmarines) + { + linkedSubBox.AddItem(sub.Name, sub); + } + saveFrame = null; return false; @@ -482,7 +503,7 @@ namespace Barotrauma private bool CreateLoadScreen(GUIButton button, object obj) { - Submarine.Preload(); + Submarine.RefreshSavedSubs(); int width = 300, height = 400; loadFrame = new GUIFrame(new Rectangle(GameMain.GraphicsWidth / 2 - width / 2, GameMain.GraphicsHeight / 2 - height / 2, width, height), GUI.Style, null); @@ -579,9 +600,11 @@ namespace Barotrauma { selectedTab = (int)obj; - ClearFilter(GUItabs[selectedTab].GetChild(), null); - - GUIComponent.KeyboardDispatcher.Subscriber = GUItabs[selectedTab].GetChild(); + var searchBox = GUItabs[selectedTab].GetChild(); + ClearFilter(searchBox, null); + + searchBox.AddToGUIUpdateList(); + searchBox.Select(); return true; } @@ -650,6 +673,8 @@ namespace Barotrauma { me.IsHighlighted = false; } + + MapEntity.DeselectAll(); return true; } @@ -665,7 +690,6 @@ namespace Barotrauma characterMode = false; - if (wiringMode) { CreateDummyCharacter(); @@ -682,6 +706,8 @@ namespace Barotrauma { RemoveDummyCharacter(); } + + MapEntity.DeselectAll(); return true; } @@ -843,7 +869,11 @@ namespace Barotrauma string name = ToolBox.LimitString(mapEntityPrefab.Name,15); - var textBlock = new GUITextBlock(new Rectangle(0,0,0,15), name, GUI.Style, previouslyUsedList); + var textBlock = new GUITextBlock( + new Rectangle(0,0,0,10), + ToolBox.LimitString(name, GUI.SmallFont, previouslyUsedList.Rect.Width), + GUI.Style, previouslyUsedList, GUI.SmallFont); + textBlock.UserData = mapEntityPrefab; previouslyUsedList.RemoveChild(textBlock); @@ -858,6 +888,10 @@ namespace Barotrauma { MapEntity.SelectedList[0].AddToGUIUpdateList(); } + if (MapEntity.HighlightedListBox != null) + { + MapEntity.HighlightedListBox.AddToGUIUpdateList(); + } leftPanel.AddToGUIUpdateList(); topPanel.AddToGUIUpdateList(); @@ -899,10 +933,7 @@ namespace Barotrauma hullVolumeFrame.Visible = MapEntity.SelectedList.Any(s => s is Hull); - if (GUIComponent.MouseOn == null) - { - cam.MoveCamera((float)deltaTime); - } + cam.MoveCamera((float)deltaTime, true, GUIComponent.MouseOn == null); if (characterMode || wiringMode) { @@ -917,6 +948,17 @@ namespace Barotrauma me.IsHighlighted = false; } + if (wiringMode && dummyCharacter.SelectedConstruction==null) + { + List wires = new List(); + foreach (Item item in Item.ItemList) + { + var wire = item.GetComponent(); + if (wire != null) wires.Add(wire); + } + Wire.UpdateEditing(wires); + } + if (dummyCharacter.SelectedConstruction==null) { Vector2 mouseSimPos = FarseerPhysics.ConvertUnits.ToSimUnits(dummyCharacter.CursorPosition); diff --git a/Subsurface/Source/Screens/MainMenuScreen.cs b/Subsurface/Source/Screens/MainMenuScreen.cs index d94a3a92d..740eb7935 100644 --- a/Subsurface/Source/Screens/MainMenuScreen.cs +++ b/Subsurface/Source/Screens/MainMenuScreen.cs @@ -92,30 +92,7 @@ namespace Barotrauma new GUITextBlock(new Rectangle(0, 0, 0, 30), "Selected submarine:", null, null, Alignment.Left, GUI.Style, menuTabs[(int)Tab.NewGame]); subList = new GUIListBox(new Rectangle(0, 30, 230, panelRect.Height-100), GUI.Style, menuTabs[(int)Tab.NewGame]); - var subsToShow = Submarine.SavedSubmarines.Where(s => !s.HasTag(SubmarineTag.HideInMenus)); - - foreach (Submarine sub in subsToShow) - { - var textBlock = new GUITextBlock( - new Rectangle(0, 0, 0, 25), - ToolBox.LimitString(sub.Name, GUI.Font, subList.Rect.Width-65), GUI.Style, - Alignment.Left, Alignment.Left, subList) - { - Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f), - ToolTip = sub.Description, - UserData = sub - }; - - if (sub.HasTag(SubmarineTag.Shuttle)) - { - textBlock.TextColor = textBlock.TextColor * 0.85f; - - var shuttleText = new GUITextBlock(new Rectangle(0, 0, 0, 25), "Shuttle", GUI.Style, Alignment.Left, Alignment.CenterY | Alignment.Right, textBlock, false, GUI.SmallFont); - shuttleText.TextColor = textBlock.TextColor * 0.8f; - shuttleText.ToolTip = textBlock.ToolTip; - } - } - if (Submarine.SavedSubmarines.Count > 0) subList.Select(Submarine.SavedSubmarines[0]); + UpdateSubList(); new GUITextBlock(new Rectangle((int)(subList.Rect.Width + 20), 0, 100, 20), "Save name: ", GUI.Style, Alignment.Left, Alignment.Left, menuTabs[(int)Tab.NewGame]); @@ -218,9 +195,41 @@ namespace Barotrauma Submarine.Unload(); + UpdateSubList(); + SelectTab(null, 0); //selectedTab = 0; } + + private void UpdateSubList() + { + var subsToShow = Submarine.SavedSubmarines.Where(s => !s.HasTag(SubmarineTag.HideInMenus)); + + subList.ClearChildren(); + + foreach (Submarine sub in subsToShow) + { + var textBlock = new GUITextBlock( + new Rectangle(0, 0, 0, 25), + ToolBox.LimitString(sub.Name, GUI.Font, subList.Rect.Width - 65), GUI.Style, + Alignment.Left, Alignment.Left, subList) + { + Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f), + ToolTip = sub.Description, + UserData = sub + }; + + if (sub.HasTag(SubmarineTag.Shuttle)) + { + textBlock.TextColor = textBlock.TextColor * 0.85f; + + var shuttleText = new GUITextBlock(new Rectangle(0, 0, 0, 25), "Shuttle", GUI.Style, Alignment.Left, Alignment.CenterY | Alignment.Right, textBlock, false, GUI.SmallFont); + shuttleText.TextColor = textBlock.TextColor * 0.8f; + shuttleText.ToolTip = textBlock.ToolTip; + } + } + if (Submarine.SavedSubmarines.Count > 0) subList.Select(Submarine.SavedSubmarines[0]); + } public bool SelectTab(GUIButton button, object obj) { diff --git a/Subsurface/Source/Sounds/OggStream.cs b/Subsurface/Source/Sounds/OggStream.cs index d2c9a5a7a..d877cc14f 100644 --- a/Subsurface/Source/Sounds/OggStream.cs +++ b/Subsurface/Source/Sounds/OggStream.cs @@ -47,14 +47,15 @@ namespace Barotrauma.Sounds public static void Check() { -#if !DEBUG - return; -#endif - ALError error; if ((error = AL.GetError()) != ALError.NoError) { - DebugConsole.ThrowError("OpenAL error: "+AL.GetErrorString(error)); +#if DEBUG + DebugConsole.ThrowError("OpenAL error: " + AL.GetErrorString(error)); +#else + + DebugConsole.NewMessage("OpenAL error: "+AL.GetErrorString(error), Microsoft.Xna.Framework.Color.Red); +#endif } } } diff --git a/Subsurface/Source/Sounds/Sound.cs b/Subsurface/Source/Sounds/Sound.cs index 5cfb62e89..867ae39f4 100644 --- a/Subsurface/Source/Sounds/Sound.cs +++ b/Subsurface/Source/Sounds/Sound.cs @@ -247,7 +247,8 @@ namespace Barotrauma loadedSounds.Remove(this); - if (alSourceId>0 && SoundManager.IsPlaying(alSourceId)) + if (alSourceId > 0 && + (SoundManager.IsPlaying(alSourceId) || SoundManager.IsPaused(alSourceId))) { SoundManager.Stop(alSourceId); ALHelper.Check(); @@ -258,10 +259,10 @@ namespace Barotrauma if (s.oggSound == oggSound) return; } - //System.Diagnostics.Debug.WriteLine("Removing sound " + filePath + " (buffer id" + AlBufferId + ")"); - SoundManager.ClearAlSource(AlBufferId); - if (oggSound!=null) oggSound.Dispose(); + ALHelper.Check(); + + if (oggSound != null) oggSound.Dispose(); } diff --git a/Subsurface/Source/Sounds/SoundManager.cs b/Subsurface/Source/Sounds/SoundManager.cs index 3c28bc280..86607bc00 100644 --- a/Subsurface/Source/Sounds/SoundManager.cs +++ b/Subsurface/Source/Sounds/SoundManager.cs @@ -149,12 +149,18 @@ namespace Barotrauma.Sounds return soundsPlaying[sourceIndex]; } - public static bool IsPlaying(int sourceIndex) { if (sourceIndex < 1 || sourceIndex>alSources.Count-1) return false; - var state = AL.GetSourceState(alSources[sourceIndex]); - return (state == ALSourceState.Playing); + + return AL.GetSourceState(alSources[sourceIndex]) == ALSourceState.Playing; + } + + public static bool IsPaused(int sourceIndex) + { + if (sourceIndex < 1 || sourceIndex > alSources.Count - 1) return false; + + return AL.GetSourceState(alSources[sourceIndex]) == ALSourceState.Paused; } public static bool IsLooping(int sourceIndex) diff --git a/Subsurface/Source/Sounds/SoundPlayer.cs b/Subsurface/Source/Sounds/SoundPlayer.cs index 9053d899e..a25b40c00 100644 --- a/Subsurface/Source/Sounds/SoundPlayer.cs +++ b/Subsurface/Source/Sounds/SoundPlayer.cs @@ -15,8 +15,7 @@ namespace Barotrauma { None, StructureBlunt, StructureSlash, - LimbBlunt, LimbSlash, LimbArmor, - Implode, Pressure + LimbBlunt, LimbSlash, LimbArmor } public struct DamageSound @@ -29,11 +28,15 @@ namespace Barotrauma public readonly Sound sound; - public DamageSound(Sound sound, Vector2 damageRange, DamageSoundType damageType) + public readonly string requiredTag; + + public DamageSound(Sound sound, Vector2 damageRange, DamageSoundType damageType, string requiredTag = "") { this.sound = sound; this.damageRange = damageRange; this.damageType = damageType; + + this.requiredTag = requiredTag; } } @@ -54,25 +57,30 @@ namespace Barotrauma static class SoundPlayer { - public static Sound[] flowSounds = new Sound[3]; - - public static Sound[] SplashSounds = new Sound[10]; + private static ILookup miscSounds; + //music public static float MusicVolume = 1.0f; - private const float MusicLerpSpeed = 0.1f; - private static Sound[] waterAmbiences = new Sound[2]; - private static int[] waterAmbienceIndexes = new int[2]; - - - private static DamageSound[] damageSounds; - private static BackgroundMusic currentMusic; private static BackgroundMusic targetMusic; private static BackgroundMusic[] musicClips; private static float currMusicVolume; + //ambience + private static Sound[] waterAmbiences = new Sound[2]; + private static int[] waterAmbienceIndexes = new int[2]; + + private static float ambientSoundTimer; + private static Vector2 ambientSoundInterval = new Vector2(20.0f, 40.0f); //x = min, y = max + + //misc + public static Sound[] flowSounds = new Sound[3]; + public static Sound[] SplashSounds = new Sound[10]; + + private static List damageSounds; + private static Sound startDrone; public static bool Initialized; @@ -133,39 +141,46 @@ namespace Barotrauma i++; } } + + List> miscSoundList = new List>(); + damageSounds = new List(); - var xDamageSounds = doc.Root.Elements("damagesound").ToList(); - - if (xDamageSounds.Any()) + foreach (XElement subElement in doc.Root.Elements()) { - damageSounds = new DamageSound[xDamageSounds.Count]; - int i = 0; - foreach (XElement element in xDamageSounds) + yield return CoroutineStatus.Running; + + switch (subElement.Name.ToString().ToLowerInvariant()) { - yield return CoroutineStatus.Running; - - Sound sound = Sound.Load(ToolBox.GetAttributeString(element, "file", ""), false); - if (sound == null) continue; + case "music": + continue; + case "damagesound": + Sound damageSound = Sound.Load(ToolBox.GetAttributeString(subElement, "file", ""), false); + if (damageSound == null) continue; - DamageSoundType damageSoundType = DamageSoundType.None; + DamageSoundType damageSoundType = DamageSoundType.None; + Enum.TryParse(ToolBox.GetAttributeString(subElement, "damagesoundtype", "None"), false, out damageSoundType); - try - { - damageSoundType = (DamageSoundType)Enum.Parse(typeof(DamageSoundType), - ToolBox.GetAttributeString(element, "damagesoundtype", "None")); - } - catch - { - damageSoundType = DamageSoundType.None; - } + damageSounds.Add(new DamageSound( + damageSound, + ToolBox.GetAttributeVector2(subElement, "damagerange", new Vector2(0.0f, 100.0f)), + damageSoundType, + ToolBox.GetAttributeString(subElement, "requiredtag", ""))); + break; + default: + Sound sound = Sound.Load(ToolBox.GetAttributeString(subElement, "file", ""), false); + if (sound != null) + { + miscSoundList.Add(new KeyValuePair(subElement.Name.ToString().ToLowerInvariant(), sound)); + } - damageSounds[i] = new DamageSound( - sound, ToolBox.GetAttributeVector2(element, "damagerange", new Vector2(0.0f,100.0f)), damageSoundType); - i++; + break; } } + miscSounds = miscSoundList.ToLookup(kvp => kvp.Key, kvp => kvp.Value); + + Initialized = true; yield return CoroutineStatus.Success; @@ -177,7 +192,7 @@ namespace Barotrauma { UpdateMusic(); - if (startDrone!=null && !startDrone.IsPlaying) + if (startDrone != null && !startDrone.IsPlaying) { startDrone.Remove(); startDrone = null; @@ -229,11 +244,20 @@ namespace Barotrauma movementSoundVolume = Math.Max(movementSoundVolume, movementFactor); } - //if (Submarine.MainSub != null) - //{ - // movementFactor = (Submarine.MainSub.Velocity == Vector2.Zero) ? 0.0f : Submarine.MainSub.Velocity.Length() / 5.0f; - // movementFactor = MathHelper.Clamp(movementFactor, 0.0f, 1.0f); - //} + if (ambientSoundTimer > 0.0f) + { + ambientSoundTimer -= (float)Timing.Step; + } + else + { + PlaySound( + "ambient", + Rand.Range(0.5f, 1.0f), + 1000.0f, + new Vector2(Sound.CameraPos.X, Sound.CameraPos.Y) + Rand.Vector(100.0f)); + + ambientSoundTimer = Rand.Range(ambientSoundInterval.X, ambientSoundInterval.Y); + } SoundManager.LowPassHFGain = lowpassHFGain; waterAmbienceIndexes[0] = waterAmbiences[0].Loop(waterAmbienceIndexes[0], ambienceVolume * (1.0f - movementSoundVolume)); @@ -241,13 +265,37 @@ namespace Barotrauma } + public static Sound GetSound(string soundTag) + { + var matchingSounds = miscSounds[soundTag].ToList(); + if (matchingSounds.Count == 0) return null; + + return matchingSounds[Rand.Int(matchingSounds.Count)]; + } + + public static void PlaySound(string soundTag, float volume = 1.0f) + { + var sound = GetSound(soundTag); + if (sound != null) sound.Play(volume); + } + + public static void PlaySound(string soundTag, float volume, float range, Vector2 position) + { + var sound = GetSound(soundTag); + if (sound != null) sound.Play(volume, range, position); + } + private static void UpdateMusic() { if (musicClips == null) return; List suitableMusic = GetSuitableMusicClips(); - if (suitableMusic.Count > 0 && !suitableMusic.Contains(currentMusic)) + if (suitableMusic.Count == 0) + { + targetMusic = null; + } + else if (!suitableMusic.Contains(currentMusic)) { int index = Rand.Int(suitableMusic.Count); @@ -272,7 +320,7 @@ namespace Barotrauma } catch (FileNotFoundException e) { - DebugConsole.ThrowError("Music clip " + targetMusic.file + " not found!"); + DebugConsole.ThrowError("Music clip " + targetMusic.file + " not found!", e); } currentMusic = targetMusic; @@ -349,10 +397,15 @@ namespace Barotrauma PlayDamageSound(damageType, damage, bodyPosition, 800.0f); } - public static void PlayDamageSound(DamageSoundType damageType, float damage, Vector2 position, float range = 2000.0f) + public static void PlayDamageSound(DamageSoundType damageType, float damage, Vector2 position, float range = 2000.0f, List tags = null) { damage = MathHelper.Clamp(damage+Rand.Range(-10.0f, 10.0f), 0.0f, 100.0f); - var sounds = damageSounds.Where(x => damage >= x.damageRange.X && damage <= x.damageRange.Y && x.damageType == damageType).ToList(); + var sounds = damageSounds.FindAll(s => + damage >= s.damageRange.X && + damage <= s.damageRange.Y && + s.damageType == damageType && + (string.IsNullOrEmpty(s.requiredTag) || (tags != null && tags.Contains(s.requiredTag)))); + if (!sounds.Any()) return; int selectedSound = Rand.Int(sounds.Count); diff --git a/Subsurface/Source/Sprite.cs b/Subsurface/Source/Sprite.cs index 2f377e951..0788538fd 100644 --- a/Subsurface/Source/Sprite.cs +++ b/Subsurface/Source/Sprite.cs @@ -223,77 +223,79 @@ namespace Barotrauma DrawTiled(spriteBatch, pos, targetSize, Vector2.Zero, color); } - public void DrawTiled(SpriteBatch spriteBatch, Vector2 pos, Vector2 targetSize, Vector2 startOffset, Color color, Point offset) + public void DrawTiled(SpriteBatch spriteBatch, Vector2 pos, Vector2 targetSize, Color color, Point offset, float? overrideDepth = null) { //how many times the texture needs to be drawn on the x-axis - int xTiles = (int)Math.Ceiling((targetSize.X + startOffset.X) / sourceRect.Width); + int xTiles = (int)Math.Ceiling(targetSize.X / sourceRect.Width); //how many times the texture needs to be drawn on the y-axis - int yTiles = (int)Math.Ceiling((targetSize.Y + startOffset.Y) / sourceRect.Height); - + int yTiles = (int)Math.Ceiling(targetSize.Y / sourceRect.Height); + + float depth = overrideDepth == null ? this.depth : (float)overrideDepth; + Rectangle texPerspective = sourceRect; texPerspective.Location += offset; - while (texPerspective.Location.X >= sourceRect.X + sourceRect.Width) - texPerspective.X = sourceRect.X + (texPerspective.Location.X - (sourceRect.X + sourceRect.Width)); - while (texPerspective.Location.Y >= sourceRect.Y + sourceRect.Height) - texPerspective.Y = sourceRect.Y + (texPerspective.Location.Y - (sourceRect.Y + sourceRect.Height)); + while (texPerspective.X >= sourceRect.Right) + texPerspective.X = sourceRect.X + (texPerspective.X - sourceRect.Right); + while (texPerspective.Y >= sourceRect.Bottom) + texPerspective.Y = sourceRect.Y + (texPerspective.Y - sourceRect.Bottom); - texPerspective.Width = (int)Math.Min(targetSize.X, sourceRect.Width); + float top = pos.Y; texPerspective.Height = (int)Math.Min(targetSize.Y, sourceRect.Height); + for (int y = 0; y < yTiles; y++) { + var movementY = texPerspective.Height; + texPerspective.Height = Math.Min((int)(targetSize.Y - texPerspective.Height * y), texPerspective.Height); + + float left = pos.X; texPerspective.Width = (int)Math.Min(targetSize.X, sourceRect.Width); - texPerspective.Height = (int)Math.Min(targetSize.Y, sourceRect.Height); - float top = pos.Y + texPerspective.Height * y; + for (int x = 0; x < xTiles; x++) { - float left = pos.X + texPerspective.Width * x; - texPerspective.Width = Math.Min((int)(targetSize.X - texPerspective.Width * x), texPerspective.Width); - texPerspective.Height = Math.Min((int)(targetSize.Y - texPerspective.Height * y), texPerspective.Height); - var movementX = texPerspective.Width; - var movementY = texPerspective.Height; + texPerspective.Width = Math.Min((int)(targetSize.X - texPerspective.Width * x), texPerspective.Width); + if (texPerspective.Right > sourceRect.Right) { + int diff = texPerspective.Right - sourceRect.Right; if (effects.HasFlag(SpriteEffects.FlipHorizontally)) { - int diff = (texPerspective.X + texPerspective.Width) - (sourceRect.Right); - - spriteBatch.Draw(texture, - new Vector2(left, top), - new Rectangle(sourceRect.X, texPerspective.Y, diff, texPerspective.Height), + spriteBatch.Draw(texture, + new Vector2(left, top), + new Rectangle(sourceRect.X, texPerspective.Y, diff, texPerspective.Height), color, rotation, Vector2.Zero, 1.0f, effects, depth); - + texPerspective.Width -= diff; left += diff; } else { - float diff = (texPerspective.X + texPerspective.Width) - (sourceRect.X + sourceRect.Width); texPerspective.Width -= (int)diff; - spriteBatch.Draw(texture, - new Vector2(left + texPerspective.Width, top), - new Rectangle(sourceRect.X, texPerspective.Y, (int)diff, texPerspective.Height), - color, rotation, Vector2.Zero, 1.0f, effects, depth); + spriteBatch.Draw(texture, + new Vector2(left + texPerspective.Width, top), + new Rectangle(sourceRect.X, texPerspective.Y, (int)diff, texPerspective.Height), + color, rotation, Vector2.Zero, 1.0f, effects, depth); } } else if (texPerspective.Bottom > sourceRect.Bottom) { - int diff = (texPerspective.Bottom) - (sourceRect.Bottom); + int diff = texPerspective.Bottom - sourceRect.Bottom; texPerspective.Height -= diff; - spriteBatch.Draw(texture, - new Vector2(left, top + texPerspective.Height), - new Rectangle(texPerspective.X, sourceRect.Y, texPerspective.Width, diff), + spriteBatch.Draw(texture, + new Vector2(left, top + texPerspective.Height), + new Rectangle(texPerspective.X, sourceRect.Y, texPerspective.Width, diff), color, rotation, Vector2.Zero, 1.0f, effects, depth); } spriteBatch.Draw(texture, new Vector2(left, top), texPerspective, color, rotation, Vector2.Zero, 1.0f, effects, depth); - if (texPerspective.X + movementX >= sourceRect.Right) - texPerspective.X = sourceRect.X; - if (texPerspective.Y + movementY >= sourceRect.Y + sourceRect.Height) - texPerspective.Y = sourceRect.Y; + if (texPerspective.X + movementX >= sourceRect.Right) texPerspective.X = sourceRect.X; + left += movementX; } + + if (texPerspective.Y + movementY >= sourceRect.Bottom) texPerspective.Y = sourceRect.Y; + top += movementY; } } diff --git a/Subsurface/Source/Utils/MathUtils.cs b/Subsurface/Source/Utils/MathUtils.cs index 695be7904..ccdf61cc5 100644 --- a/Subsurface/Source/Utils/MathUtils.cs +++ b/Subsurface/Source/Utils/MathUtils.cs @@ -233,10 +233,44 @@ namespace Barotrauma new Vector2(rect.Right, rect.Y - rect.Height)); } + public static List GetLineRectangleIntersections(Vector2 a1, Vector2 a2, Rectangle rect) + { + List intersections = new List(); + + Vector2? intersection = GetLineIntersection(a1, a2, + new Vector2(rect.X, rect.Y), + new Vector2(rect.Right, rect.Y)); + + if (intersection != null) intersections.Add((Vector2)intersection); + + intersection = GetLineIntersection(a1, a2, + new Vector2(rect.X, rect.Y - rect.Height), + new Vector2(rect.Right, rect.Y - rect.Height)); + + if (intersection != null) intersections.Add((Vector2)intersection); + + intersection = GetLineIntersection(a1, a2, + new Vector2(rect.X, rect.Y), + new Vector2(rect.X, rect.Y - rect.Height)); + + if (intersection != null) intersections.Add((Vector2)intersection); + + intersection = GetLineIntersection(a1, a2, + new Vector2(rect.Right, rect.Y), + new Vector2(rect.Right, rect.Y - rect.Height)); + + if (intersection != null) intersections.Add((Vector2)intersection); + + return intersections; + } + public static float LineToPointDistance(Vector2 lineA, Vector2 lineB, Vector2 point) { - return (float)(Math.Abs((lineB.X-lineA.X)*(lineA.Y - point.Y) - (lineA.X - point.X)*(lineB.Y-lineA.Y)) / - Math.Sqrt(Math.Pow(lineB.X - lineA.X, 2) + Math.Pow(lineB.Y - lineA.Y, 2))); + float xDiff = lineB.X - lineA.X; + float yDiff = lineB.Y - lineA.Y; + + return (float)(Math.Abs(xDiff * (lineA.Y - point.Y) - yDiff * (lineA.X - point.X)) / + Math.Sqrt(xDiff * xDiff + yDiff * yDiff)); } public static bool CircleIntersectsRectangle(Vector2 circlePos, float radius, Rectangle rect) diff --git a/Subsurface/Source/Utils/SaveUtil.cs b/Subsurface/Source/Utils/SaveUtil.cs index 3a4a3a5bb..b78fee054 100644 --- a/Subsurface/Source/Utils/SaveUtil.cs +++ b/Subsurface/Source/Utils/SaveUtil.cs @@ -22,9 +22,19 @@ namespace Barotrauma fileName = Path.Combine(SaveFolder, fileName); string tempPath = Path.Combine(SaveFolder, "temp"); - - Directory.CreateDirectory(tempPath); + DirectoryInfo dir = new DirectoryInfo(tempPath); + + Directory.CreateDirectory(tempPath); + try + { + ClearFolder(tempPath); + } + catch + { + + } + try { if (Submarine.MainSub != null) @@ -274,5 +284,22 @@ namespace Barotrauma using (GZipStream zipStream = new GZipStream(inFile, CompressionMode.Decompress, true)) while (DecompressFile(sDir, zipStream, progress)) ; } + + private static void ClearFolder(string FolderName) + { + DirectoryInfo dir = new DirectoryInfo(FolderName); + + foreach (FileInfo fi in dir.GetFiles()) + { + fi.IsReadOnly = false; + fi.Delete(); + } + + foreach (DirectoryInfo di in dir.GetDirectories()) + { + ClearFolder(di.FullName); + di.Delete(); + } + } } } diff --git a/Subsurface/Submarines/Aegir Mark III.sub b/Subsurface/Submarines/Aegir Mark III.sub index 6cab2cb69..da7dc9ada 100644 Binary files a/Subsurface/Submarines/Aegir Mark III.sub and b/Subsurface/Submarines/Aegir Mark III.sub differ diff --git a/Subsurface/Submarines/Nehalennia.sub b/Subsurface/Submarines/Nehalennia.sub index 1a8b8aa01..512b0e158 100644 Binary files a/Subsurface/Submarines/Nehalennia.sub and b/Subsurface/Submarines/Nehalennia.sub differ diff --git a/Subsurface/Submarines/Vellamo.sub b/Subsurface/Submarines/Vellamo.sub index 6d35b7f4d..90cb4f5a0 100644 Binary files a/Subsurface/Submarines/Vellamo.sub and b/Subsurface/Submarines/Vellamo.sub differ diff --git a/Subsurface/changelog.txt b/Subsurface/changelog.txt index b13ee2981..759fcc61e 100644 --- a/Subsurface/changelog.txt +++ b/Subsurface/changelog.txt @@ -1,3 +1,55 @@ +--------------------------------------------------------------------------------------------------------- +v0.5.4.2 +--------------------------------------------------------------------------------------------------------- + +- fixed crashes when removing nodes from a wire (i.e. right clicking with a wire equipped) +- fixed inventory not being drawn in the correct position if switching to a character who's been +dragged/grabbed by some other character +- fixed wires becoming disconnected when copypasting them +- wire nodes can't be moved when connecting wires to a connection panel +- fixed repeating crash messageboxes if the game fails to resolve a SharpDX exception on startup +- fixed crashing when switching to wiring mode while editing some value of an item +- fixed keyboard focus staying in textboxes after the textbox has been hidden (for example, +the input fields in the submarine saving prompt) +- fixed error message spam if a docking port is linked to another port in the same sub +- submarine lists in the editor, main menu and server menu are updated when new subs are saved/received +- fixed item editing menu staying on the screen when loading another sub in the editor +- ruins cant span above the top of the level anymore +- the size of the docked subs is taken into account when generating the level +- fixed autorestart timer not resetting at the clients' end if the server fails to start a shift and +resets the timer +- docked subs are forced to correct positions during loading (subs won't get stuck inside each other +even if the submarines are slightly overlapping in the editor) + +- all sounds are paused when switching to submarine editor +- replaced the solid black color inside ice walls with a proper texture +- the background ice texture loops better + +--------------------------------------------------------------------------------------------------------- +v0.5.4.1 +--------------------------------------------------------------------------------------------------------- + +Bugfixes: + - copypasted items are now correctly aligned to the "grid" + - cabinets can be copypasted from a sub to another without the items inside disappearing + - placing explosives inside an item and that item inside another item doesn't prevent explosions + - fixed a bug that occasionally caused crashing when the game happens to generate a very small level + +Sub editor: + - structures/items that are behind something else can be selected using a listbox that appears + when hovering the cursor over them + - wires have to be selected by clicking before any of the points can be moved (makes it possible + to move the correct wire even if it's overlapping with other wires) + - the selected wire is renderer over all structures + - points can be added to wires by clicking while holding ctrl + - disabled music + +Misc: + - some rendering optimization + - pathfinding and waypoint generation improvements + - made mantises more aggressive + - water flows more slowly through partially damaged walls + --------------------------------------------------------------------------------------------------------- v0.5.4.0 ---------------------------------------------------------------------------------------------------------