From 26503a975cd837c30271d29776d8861c96ee5497 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Sun, 17 Dec 2017 22:34:24 +0200 Subject: [PATCH] Fixed sub->sub and outside->sub visibility checks when determining name tag visibility. --- .../Source/Characters/Character.cs | 55 +++++++------------ .../Source/Characters/Character.cs | 51 +++++++++++++++++ 2 files changed, 70 insertions(+), 36 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Character.cs b/Barotrauma/BarotraumaClient/Source/Characters/Character.cs index bd5705ffb..8f5912e56 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Character.cs @@ -206,43 +206,29 @@ namespace Barotrauma partial void UpdateProjSpecific(float deltaTime, Camera cam) { - nameTimer -= deltaTime; - if (nameTimer <= 0.0f) + if (info != null) { - if (controlled == null) + nameTimer -= deltaTime; + if (nameTimer <= 0.0f) { - nameVisible = true; - } - //if the character is not in the camera view, the name can't be visible and we can avoid the expensive visibility checks - else if (WorldPosition.X < cam.WorldView.X || WorldPosition.X > cam.WorldView.Right || - WorldPosition.Y > cam.WorldView.Y || WorldPosition.Y < cam.WorldView.Y - cam.WorldView.Height) - { - nameVisible = false; - } - else - { - //Ideally it shouldn't send the character entirely if we can't see them but /shrug, this isn't the most hacker-proof game atm - Limb selfLimb = controlled.AnimController.GetLimb(LimbType.Head); - if (selfLimb == null) selfLimb = controlled.AnimController.GetLimb(LimbType.Torso); - - Limb targHead = AnimController.GetLimb(LimbType.Head); - if (targHead == null) targHead = AnimController.GetLimb(LimbType.Torso); - - if (selfLimb != null && targHead != null) + if (controlled == null) { - Vector2 diff = ConvertUnits.ToSimUnits(targHead.WorldPosition - selfLimb.WorldPosition); - - Body closestBody = Submarine.CheckVisibility(selfLimb.SimPosition, selfLimb.SimPosition + diff); - Structure wall = null; - if (closestBody != null) wall = closestBody.UserData as Structure; - nameVisible = closestBody == null || wall == null || !wall.CastShadow; + nameVisible = true; } - else + + //if the character is not in the camera view, the name can't be visible and we can avoid the expensive visibility checks + else if (WorldPosition.X < cam.WorldView.X || WorldPosition.X > cam.WorldView.Right || + WorldPosition.Y > cam.WorldView.Y || WorldPosition.Y < cam.WorldView.Y - cam.WorldView.Height) { nameVisible = false; } + else + { + //Ideally it shouldn't send the character entirely if we can't see them but /shrug, this isn't the most hacker-proof game atm + nameVisible = controlled.CanSeeCharacter(this); + } + nameTimer = Rand.Range(0.5f, 1.0f); } - nameTimer = Rand.Range(0.5f, 1.0f); } } @@ -294,23 +280,20 @@ namespace Barotrauma { GUI.SpeechBubbleIcon.Draw(spriteBatch, pos - Vector2.UnitY * 100.0f, speechBubbleColor * Math.Min(speechBubbleTimer, 1.0f), 0.0f, - Math.Min((float)speechBubbleTimer, 1.0f)); + Math.Min(speechBubbleTimer, 1.0f)); } if (this == controlled) return; - if (!nameVisible) return; - - if (info != null) + if (nameVisible && info != null) { string name = Info.DisplayName; - if (controlled == null && name != Info.Name) - name += " (Disguised)"; + if (controlled == null && name != Info.Name) name += " (Disguised)"; Vector2 namePos = new Vector2(pos.X, pos.Y - 110.0f - (5.0f / cam.Zoom)) - GUI.Font.MeasureString(name) * 0.5f / cam.Zoom; Color nameColor = Color.White; - if (Character.Controlled != null && TeamID != Character.Controlled.TeamID) + if (Controlled != null && TeamID != Controlled.TeamID) { nameColor = Color.Red; } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs index dc04384ba..6819a412f 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Xml.Linq; using Barotrauma.Items.Components; +using FarseerPhysics.Dynamics; namespace Barotrauma { @@ -982,6 +983,56 @@ namespace Barotrauma } } } + + public bool CanSeeCharacter(Character character) + { + Limb selfLimb = AnimController.GetLimb(LimbType.Head); + if (selfLimb == null) selfLimb = AnimController.GetLimb(LimbType.Torso); + if (selfLimb == null) selfLimb = AnimController.Limbs[0]; + + Limb targetLimb = character.AnimController.GetLimb(LimbType.Head); + if (targetLimb == null) targetLimb = character.AnimController.GetLimb(LimbType.Torso); + if (targetLimb == null) targetLimb = character.AnimController.Limbs[0]; + + if (selfLimb != null && targetLimb != null) + { + Vector2 diff = ConvertUnits.ToSimUnits(targetLimb.WorldPosition - selfLimb.WorldPosition); + + Body closestBody = null; + //both inside the same sub (or both outside) + //OR the we're inside, the other character outside + if (character.Submarine == Submarine || character.Submarine == null) + { + closestBody = Submarine.CheckVisibility(selfLimb.SimPosition, selfLimb.SimPosition + diff); + if (closestBody == null) return true; + } + //we're outside, the other character inside + else if (Submarine == null) + { + closestBody = Submarine.CheckVisibility(targetLimb.SimPosition, targetLimb.SimPosition - diff); + if (closestBody == null) return true; + } + //both inside different subs + else + { + closestBody = Submarine.CheckVisibility(selfLimb.SimPosition, selfLimb.SimPosition + diff); + if (closestBody != null && closestBody.UserData is Structure) + { + if (((Structure)closestBody.UserData).CastShadow) return false; + } + closestBody = Submarine.CheckVisibility(targetLimb.SimPosition, targetLimb.SimPosition - diff); + if (closestBody == null) return true; + + } + + Structure wall = closestBody.UserData as Structure; + return wall == null || !wall.CastShadow; + } + else + { + return false; + } + } public bool HasEquippedItem(Item item) {