diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Character.cs b/Barotrauma/BarotraumaClient/Source/Characters/Character.cs index 79abaed11..7fab0116d 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Character.cs @@ -226,15 +226,8 @@ namespace Barotrauma if (SelectedConstruction != null && SelectedConstruction.ActiveHUDs.Any(ic => ic.GuiFrame != null && HUD.CloseHUD(ic.GuiFrame.Rect))) { - if (GameMain.Client != null) - { - //emulate a Select input to get the character to deselect the item server-side - keys[(int)InputType.Select].Hit = true; - } - //reset focus to prevent us from accidentally interacting with another entity - focusedItem = null; - focusedCharacter = null; - findFocusedTimer = 0.2f; + //emulate a Select input to get the character to deselect the item server-side + keys[(int)InputType.Select].Hit = true; SelectedConstruction = null; } diff --git a/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs b/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs index 8c8733a36..bb327ac69 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs @@ -17,11 +17,12 @@ namespace Barotrauma private GUIFrame background, videoFrame, textFrame; private GUITextBlock title, textContent, objectiveTitle, objectiveText; private GUICustomComponent videoView; + private GUIButton okButton; private Color backgroundColor = new Color(0f, 0f, 0f, 1f); private Action callbackOnStop; - private Point scaledResolution; + private Point scaledVideoResolution; private readonly int borderSize = 20; private readonly Point buttonSize = new Point(160, 50); private readonly int titleHeight = 30; @@ -53,21 +54,20 @@ namespace Barotrauma public VideoPlayer() // GUI elements with size set to Point.Zero are resized based on content { int screenWidth = (int)(GameMain.GraphicsWidth * 0.55f); - scaledResolution = new Point(screenWidth, (int)(screenWidth / 16f * 9f)); + scaledVideoResolution = new Point(screenWidth, (int)(screenWidth / 16f * 9f)); - int width = scaledResolution.X; - int height = scaledResolution.Y; + int width = scaledVideoResolution.X; + int height = scaledVideoResolution.Y; - background = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight), GUI.Canvas, Anchor.Center), "InnerFrame", backgroundColor); - videoFrame = new GUIFrame(new RectTransform(Point.Zero, background.RectTransform, Anchor.Center, Pivot.Center) { AbsoluteOffset = new Point((int)(-100 / (GUI.Scale * 0.6f)), 0) }, "SonarFrame"); + background = new GUIFrame(new RectTransform(Point.Zero, GUI.Canvas, Anchor.Center), "InnerFrame", backgroundColor); + videoFrame = new GUIFrame(new RectTransform(Point.Zero, background.RectTransform, Anchor.Center, Pivot.Center), "SonarFrame"); textFrame = new GUIFrame(new RectTransform(Point.Zero, videoFrame.RectTransform, Anchor.CenterLeft, Pivot.CenterLeft), "TextFrame"); - textFrame.RectTransform.AbsoluteOffset = new Point(width + borderSize * 2, 0); videoView = new GUICustomComponent(new RectTransform(Point.Zero, videoFrame.RectTransform, Anchor.Center), (spriteBatch, guiCustomComponent) => { DrawVideo(spriteBatch, guiCustomComponent.Rect); }); - title = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft) { AbsoluteOffset = new Point(5, 10) }, string.Empty, font: GUI.VideoTitleFont, textColor: new Color(253, 174, 0), textAlignment: Alignment.Left); + title = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft), string.Empty, font: GUI.VideoTitleFont, textColor: new Color(253, 174, 0), textAlignment: Alignment.Left); - textContent = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft) { AbsoluteOffset = new Point(0, borderSize + titleHeight) }, string.Empty, font: GUI.Font, textAlignment: Alignment.TopLeft); + textContent = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft), string.Empty, font: GUI.Font, textAlignment: Alignment.TopLeft); objectiveTitle = new GUITextBlock(new RectTransform(new Vector2(1f, 0f), textFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), string.Empty, font: GUI.ObjectiveTitleFont, textAlignment: Alignment.CenterRight, textColor: Color.White); objectiveTitle.Text = TextManager.Get("NewObjective"); @@ -110,7 +110,7 @@ namespace Barotrauma currentVideo.Dispose(); currentVideo = null; - currentVideo = CreateVideo(scaledResolution); + currentVideo = CreateVideo(scaledVideoResolution); } public void AddToGUIUpdateList(bool ignoreChildren = false, int order = 0) @@ -131,67 +131,100 @@ namespace Barotrauma return; } - ResetFrameSizes(); - if (currentVideo != null) { currentVideo.Dispose(); currentVideo = null; } - currentVideo = CreateVideo(scaledResolution); - - videoFrame.RectTransform.NonScaledSize += scaledResolution + new Point(borderSize, borderSize); - videoView.RectTransform.NonScaledSize += scaledResolution; - + currentVideo = CreateVideo(scaledVideoResolution); title.Text = TextManager.Get(contentId); - title.RectTransform.NonScaledSize += new Point(textSettings.Width, titleHeight); - - if (!string.IsNullOrEmpty(textSettings.Text)) - { - textSettings.Text = ToolBox.WrapText(textSettings.Text, textSettings.Width, GUI.Font); - int wrappedHeight = textSettings.Text.Split('\n').Length * textHeight; - textFrame.RectTransform.NonScaledSize += new Point(textSettings.Width + borderSize, wrappedHeight + borderSize + buttonSize.Y + titleHeight); - textContent.RectTransform.NonScaledSize += new Point(textSettings.Width, wrappedHeight); - } - textContent.Text = textSettings.Text; + objectiveText.Text = objective; - if (!string.IsNullOrEmpty(objective)) - { - objectiveTitle.RectTransform.AbsoluteOffset = new Point(-10, textContent.RectTransform.Rect.Height + (int)(textHeight * 1.95f)); - objectiveText.RectTransform.AbsoluteOffset = new Point(-10, textContent.RectTransform.Rect.Height + objectiveTitle.Rect.Height + (int)(textHeight * 2.25f)); - - textFrame.RectTransform.NonScaledSize += new Point(0, objectiveFrameHeight); - objectiveText.RectTransform.NonScaledSize += new Point(textFrame.Rect.Width, textHeight); - objectiveText.Text = objective; - objectiveTitle.Visible = objectiveText.Visible = true; - } - else - { - textFrame.RectTransform.NonScaledSize += new Point(0, borderSize); - objectiveTitle.Visible = objectiveText.Visible = false; - } - - var okButton = new GUIButton(new RectTransform(buttonSize, textFrame.RectTransform, Anchor.BottomRight, Pivot.BottomRight) { AbsoluteOffset = new Point(20, 20) }, - TextManager.Get("OK")) - { - OnClicked = DisposeVideo - }; + AdjustFrames(videoSettings, textSettings); if (startPlayback) Play(); } - private void ResetFrameSizes() + private void AdjustFrames(VideoSettings videoSettings, TextSettings textSettings) { + int screenWidth = (int)(GameMain.GraphicsWidth * 0.55f); + scaledVideoResolution = new Point(screenWidth, (int)(screenWidth / 16f * 9f)); + + background.RectTransform.NonScaledSize = Point.Zero; videoFrame.RectTransform.NonScaledSize = Point.Zero; videoView.RectTransform.NonScaledSize = Point.Zero; title.RectTransform.NonScaledSize = Point.Zero; textFrame.RectTransform.NonScaledSize = Point.Zero; textContent.RectTransform.NonScaledSize = Point.Zero; - + objectiveText.RectTransform.NonScaledSize = Point.Zero; + + title.TextScale = textContent.TextScale = objectiveText.TextScale = objectiveTitle.TextScale = GUI.Scale; + + int scaledBorderSize = (int)(borderSize * GUI.Scale); + int scaledTextWidth = (int)(textSettings.Width * GUI.Scale); + int scaledTitleHeight = (int)(titleHeight * GUI.Scale); + int scaledTextHeight = (int)(textHeight * GUI.Scale); + int scaledObjectiveFrameHeight = (int)(objectiveFrameHeight * GUI.Scale); + + Point scaledButtonSize = new Point((int)(buttonSize.X * GUI.Scale), (int)(buttonSize.Y * GUI.Scale)); + + background.RectTransform.NonScaledSize = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight); + + videoFrame.RectTransform.NonScaledSize += scaledVideoResolution + new Point(scaledBorderSize, scaledBorderSize); + videoView.RectTransform.NonScaledSize += scaledVideoResolution; + + title.RectTransform.NonScaledSize += new Point(scaledTextWidth, scaledTitleHeight); + title.RectTransform.AbsoluteOffset = new Point((int)(5 * GUI.Scale), (int)(10 * GUI.Scale)); + + if (!string.IsNullOrEmpty(textSettings.Text)) + { + textSettings.Text = ToolBox.WrapText(textSettings.Text, scaledTextWidth, GUI.Font); + int wrappedHeight = textSettings.Text.Split('\n').Length * scaledTextHeight; + + textFrame.RectTransform.NonScaledSize += new Point(scaledTextWidth + scaledBorderSize, wrappedHeight + scaledBorderSize + scaledButtonSize.Y + scaledTitleHeight); + textFrame.RectTransform.AbsoluteOffset = new Point(scaledVideoResolution.X + scaledBorderSize * 2, 0); + + textContent.RectTransform.NonScaledSize += new Point(scaledTextWidth, wrappedHeight); + textContent.RectTransform.AbsoluteOffset = new Point(0, scaledBorderSize + scaledTitleHeight); + } + + if (!string.IsNullOrEmpty(objectiveText.Text)) + { + int scaledXOffset = (int)(-10 * GUI.Scale); + + objectiveTitle.RectTransform.AbsoluteOffset = new Point(scaledXOffset, textContent.RectTransform.Rect.Height + (int)(scaledTextHeight * 1.95f)); + objectiveText.RectTransform.AbsoluteOffset = new Point(scaledXOffset, textContent.RectTransform.Rect.Height + objectiveTitle.Rect.Height + (int)(scaledTextHeight * 2.25f)); + + textFrame.RectTransform.NonScaledSize += new Point(0, scaledObjectiveFrameHeight); + objectiveText.RectTransform.NonScaledSize += new Point(textFrame.Rect.Width, scaledTextHeight); + objectiveTitle.Visible = objectiveText.Visible = true; + } + else + { + textFrame.RectTransform.NonScaledSize += new Point(0, scaledBorderSize); + objectiveTitle.Visible = objectiveText.Visible = false; + } + + int totalFrameWidth = videoFrame.Rect.Width + textFrame.Rect.Width + scaledBorderSize * 2; + int xOffset = videoFrame.Rect.Width / 2 + scaledBorderSize - (videoFrame.Rect.Width / 2 - textFrame.Rect.Width / 2); + + + videoFrame.RectTransform.AbsoluteOffset = new Point(-xOffset, (int)(50 * GUI.Scale)); + + if (okButton != null) + { + textFrame.RemoveChild(okButton); + okButton = null; + } + + okButton = new GUIButton(new RectTransform(scaledButtonSize, textFrame.RectTransform, Anchor.BottomRight, Pivot.BottomRight) { AbsoluteOffset = new Point(scaledBorderSize, scaledBorderSize) }, TextManager.Get("OK")) + { + OnClicked = DisposeVideo + }; } private Video CreateVideo(Point resolution) diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs index fe46adeae..9b60c92aa 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs @@ -662,6 +662,7 @@ namespace Barotrauma.Tutorials if (gap.Submarine == null) continue; if (gap.Submarine.IsOutpost) continue; if (gap.Submarine != Submarine.MainSub) continue; + if (gap.FlowTargetHull.WaterPercentage <= 0.0f) continue; return true; } diff --git a/Barotrauma/BarotraumaClient/Source/Map/Lights/LightManager.cs b/Barotrauma/BarotraumaClient/Source/Map/Lights/LightManager.cs index f8d12f957..c61e3821d 100644 --- a/Barotrauma/BarotraumaClient/Source/Map/Lights/LightManager.cs +++ b/Barotrauma/BarotraumaClient/Source/Map/Lights/LightManager.cs @@ -453,10 +453,7 @@ namespace Barotrauma.Lights //raster pattern on top of everything spriteBatch.Begin(blendState: BlendState.AlphaBlend, samplerState: SamplerState.LinearWrap); - spriteBatch.Draw(highlightRaster, - new Rectangle(0, 0, HighlightMap.Width, HighlightMap.Height), - new Rectangle(0, 0, (int)(HighlightMap.Width / currLightMapScale * 0.5f), (int)(HighlightMap.Height / currLightMapScale * 0.5f)), - Color.White * 0.5f); + spriteBatch.Draw(highlightRaster, new Rectangle(0, 0, HighlightMap.Width, HighlightMap.Height), new Rectangle(0, 0, HighlightMap.Width, HighlightMap.Height), Color.White * 0.5f); spriteBatch.End(); DeformableSprite.Effect.CurrentTechnique = DeformableSprite.Effect.Techniques["DeformShader"]; diff --git a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs index ae3a090d2..97342cb7e 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs @@ -337,24 +337,7 @@ namespace Barotrauma var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.03f), paddedLeftPanel.RectTransform), TextManager.Get("ShowLighting")) { Selected = lightingEnabled, - OnSelected = (GUITickBox obj) => - { - lightingEnabled = obj.Selected; - if (lightingEnabled) - { - //turn off lights that are inside containers - foreach (Item item in Item.ItemList) - { - foreach (LightComponent lightComponent in item.GetComponents()) - { - lightComponent.Light.Color = item.Container != null || (item.body != null && !item.body.Enabled) ? - Color.Transparent : - lightComponent.LightColor; - } - } - } - return true; - } + OnSelected = (GUITickBox obj) => { lightingEnabled = obj.Selected; return true; } }; tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.03f), paddedLeftPanel.RectTransform), TextManager.Get("ShowWalls")) { diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/AITarget.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/AITarget.cs index 42f9d6515..ce68ecf63 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/AITarget.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/AITarget.cs @@ -115,13 +115,9 @@ namespace Barotrauma SonarLabel = element.GetAttributeString("sonarlabel", ""); } - public AITarget(Entity e, float sightRange = -1, float soundRange = 0) + public AITarget(Entity e, float sightRange = 3000, float soundRange = 0) { Entity = e; - if (sightRange < 0) - { - sightRange = StaticSightRange; - } SightRange = sightRange; SoundRange = soundRange; List.Add(this); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs index be09c3888..33b12d3e9 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs @@ -635,7 +635,6 @@ namespace Barotrauma var newLimb = GetAttackLimb(attackWorldPos, previousLimb); if (newLimb != null) { - // Attack with the new limb AttackingLimb = newLimb; } else @@ -660,49 +659,6 @@ namespace Barotrauma } } break; - case AIBehaviorAfterAttack.FallBackUntilCanAttack: - if (AttackingLimb.attack.SecondaryCoolDown <= 0) - { - // No (valid) secondary cooldown defined. - UpdateFallBack(attackWorldPos, deltaTime); - return; - } - else - { - if (AttackingLimb.attack.SecondaryCoolDownTimer <= 0) - { - // Don't allow attacking when the attack target has just changed. - if (_previousAiTarget != null && SelectedAiTarget != _previousAiTarget) - { - UpdateFallBack(attackWorldPos, deltaTime); - return; - } - else - { - // If the secondary cooldown is defined and expired, check if we can switch the attack - var previousLimb = AttackingLimb; - var newLimb = GetAttackLimb(attackWorldPos, previousLimb); - if (newLimb != null) - { - // Attack with the new limb - AttackingLimb = newLimb; - } - else - { - // No new limb was found. - UpdateFallBack(attackWorldPos, deltaTime); - return; - } - } - } - else - { - // Cooldown not yet expired -> steer away from the target - UpdateFallBack(attackWorldPos, deltaTime); - return; - } - } - break; case AIBehaviorAfterAttack.FallBack: default: UpdateFallBack(attackWorldPos, deltaTime); @@ -828,39 +784,20 @@ namespace Barotrauma { AttackContext currentContext = Character.GetAttackContext(); var target = wallTarget != null ? wallTarget.Structure : SelectedAiTarget.Entity; - Limb selectedLimb = null; - float currentPriority = 0; - foreach (Limb limb in Character.AnimController.Limbs) - { - if (limb == ignoredLimb) { continue; } - if (limb.IsSevered || limb.IsStuck) { continue; } - var attack = limb.attack; - if (attack == null) { continue; } - if (attack.CoolDownTimer > 0) { continue; } - if (!attack.IsValidContext(currentContext)) { continue; } - if (!attack.IsValidTarget(target)) { continue; } - if (target is ISerializableEntity se && target is Character) - { - // TODO: allow conditionals of which matching any is enough instead of having to fulfill all - if (attack.Conditionals.Any(c => !c.Matches(se))) { continue; } - } - float priority = CalculatePriority(limb, attackWorldPos); - if (priority > currentPriority) - { - currentPriority = priority; - selectedLimb = limb; - } - } - return selectedLimb; - - float CalculatePriority(Limb limb, Vector2 attackPos) - { - float dist = Vector2.Distance(limb.WorldPosition, attackPos); - // The limb is ignored if the target is not close. Prevents character going in reverse if very far away from it. - // We also need a max value that is more than the actual range. - float distanceFactor = MathHelper.Lerp(1, 0, MathUtils.InverseLerp(0, limb.attack.Range * 3, dist)); - return (1 + limb.attack.Priority) * distanceFactor; - } + var limbs = Character.AnimController.Limbs + .Where(l => + l != ignoredLimb && + l.attack != null && + l.attack.CoolDownTimer <= 0 && + !l.IsSevered && + !l.IsStuck && + l.attack.IsValidContext(currentContext) && + l.attack.IsValidTarget(target) && + l.attack.Conditionals.All(c => (target is ISerializableEntity se && c.Matches(se)) || !(target is ISerializableEntity) || !(target is Character))) + .OrderByDescending(l => l.attack.Priority) + .ThenBy(l => Vector2.Distance(l.WorldPosition, attackWorldPos)); + // TODO: priority should probably not override the distance -> use values instead of booleans + return limbs.FirstOrDefault(); } private void UpdateWallTarget() diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Attack.cs b/Barotrauma/BarotraumaShared/Source/Characters/Attack.cs index 0e84aa580..955ba731b 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Attack.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Attack.cs @@ -28,7 +28,6 @@ namespace Barotrauma public enum AIBehaviorAfterAttack { FallBack, - FallBackUntilCanAttack, PursueIfCanAttack, Pursue } @@ -189,7 +188,7 @@ namespace Barotrauma public readonly List Afflictions = new List(); /// - /// Only affects ai decision making. All the conditionals has to be met in order to select the attack. TODO: allow to define conditionals using any (implemented in StatusEffect -> move from there to PropertyConditional?) + /// Only affects ai decision making. /// public List Conditionals { get; private set; } = new List(); diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/ItemContainer.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/ItemContainer.cs index d9abe0511..aac7bf9df 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/ItemContainer.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/ItemContainer.cs @@ -162,7 +162,6 @@ namespace Barotrauma.Items.Components if (contained == null) continue; if (contained.TryInteract(character)) { - character.FocusedItem = contained; return false; } } @@ -179,7 +178,6 @@ namespace Barotrauma.Items.Components if (contained == null) continue; if (contained.TryInteract(picker)) { - picker.FocusedItem = contained; return true; } }