diff --git a/Barotrauma/BarotraumaClient/Source/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaClient/Source/Characters/AI/EnemyAIController.cs index e112d338c..b20e0e7c8 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/AI/EnemyAIController.cs @@ -51,19 +51,19 @@ namespace Barotrauma } GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 80.0f, State.ToString(), stateColor, Color.Black); - if (latchOntoAI != null) + if (LatchOntoAI != null) { - foreach (Joint attachJoint in latchOntoAI.AttachJoints) + foreach (Joint attachJoint in LatchOntoAI.AttachJoints) { GUI.DrawLine(spriteBatch, ConvertUnits.ToDisplayUnits(new Vector2(attachJoint.WorldAnchorA.X, -attachJoint.WorldAnchorA.Y)), ConvertUnits.ToDisplayUnits(new Vector2(attachJoint.WorldAnchorB.X, -attachJoint.WorldAnchorB.Y)), Color.Green, 0, 4); } - if (latchOntoAI.WallAttachPos.HasValue) + if (LatchOntoAI.WallAttachPos.HasValue) { GUI.DrawLine(spriteBatch, pos, - ConvertUnits.ToDisplayUnits(new Vector2(latchOntoAI.WallAttachPos.Value.X, -latchOntoAI.WallAttachPos.Value.Y)), Color.Green, 0, 3); + ConvertUnits.ToDisplayUnits(new Vector2(LatchOntoAI.WallAttachPos.Value.X, -LatchOntoAI.WallAttachPos.Value.Y)), Color.Green, 0, 3); } } diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Character.cs b/Barotrauma/BarotraumaClient/Source/Characters/Character.cs index 87d29a9e2..615423b53 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Character.cs @@ -327,8 +327,6 @@ namespace Barotrauma debugInteractablesAtCursor.Clear(); debugInteractablesNearCursor.Clear(); - bool draggingItemToWorld = CharacterInventory.DraggingItemToWorld; - //reduce the amount of aim assist if an item has been selected //= can't switch selection to another item without deselecting the current one first UNLESS the cursor is directly on the item //otherwise it would be too easy to accidentally switch the selected item when rewiring items @@ -350,15 +348,6 @@ namespace Barotrauma if (item.body != null && !item.body.Enabled) continue; if (item.ParentInventory != null) continue; if (ignoredItems != null && ignoredItems.Contains(item)) continue; - - if (draggingItemToWorld) - { - if (item.OwnInventory == null || - !item.OwnInventory.CanBePut(CharacterInventory.draggingItem)) - { - continue; - } - } float distanceToItem = float.PositiveInfinity; if (item.IsInsideTrigger(displayPosition, out Rectangle transformedTrigger)) diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs index a2137e660..fd0af8cf0 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs @@ -248,7 +248,7 @@ namespace Barotrauma scale: scale); } - if (!GUI.DisableItemHighlights && !Inventory.DraggingItemToWorld) + if (!GUI.DisableItemHighlights) { var hudTexts = focusedItem.GetHUDTexts(character); diff --git a/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs b/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs index 8c8733a36..45bb4a52b 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs @@ -2,6 +2,7 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; using System.Xml.Linq; +using System.Collections.Generic; using Barotrauma.Media; using System.IO; using Microsoft.Xna.Framework.Input; @@ -11,8 +12,8 @@ namespace Barotrauma class VideoPlayer { private Video currentVideo; + private Point resolution; private string filePath; - private bool isPlaying; private GUIFrame background, videoFrame, textFrame; private GUITextBlock title, textContent, objectiveTitle, objectiveText; @@ -21,7 +22,14 @@ namespace Barotrauma private Color backgroundColor = new Color(0f, 0f, 0f, 1f); private Action callbackOnStop; - private Point scaledResolution; + private bool isPlaying; + + public bool IsPlaying() + { + return isPlaying; + } + + private Point defaultResolution = new Point(936, 540); private readonly int borderSize = 20; private readonly Point buttonSize = new Point(160, 50); private readonly int titleHeight = 30; @@ -43,35 +51,41 @@ namespace Barotrauma public struct VideoSettings { public string File; + public int Width; + public int Height; public VideoSettings(XElement element) { File = element.GetAttributeString("file", string.Empty); + Width = 0; + Height = 0; } } - public VideoPlayer() // GUI elements with size set to Point.Zero are resized based on content + public VideoPlayer() { int screenWidth = (int)(GameMain.GraphicsWidth * 0.55f); - scaledResolution = new Point(screenWidth, (int)(screenWidth / 16f * 9f)); + defaultResolution = new Point(screenWidth, (int)(screenWidth / 16f * 9f)); - int width = scaledResolution.X; - int height = scaledResolution.Y; + int width = defaultResolution.X; + int height = defaultResolution.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"); + videoFrame = new GUIFrame(new RectTransform(new Point(width + borderSize, height + borderSize), background.RectTransform, Anchor.Center, Pivot.Center) { AbsoluteOffset = new Point((int)(-100 / (GUI.Scale * 0.6f)), 0) }, "SonarFrame"); + //videoFrame.RectTransform.AbsoluteOffset = new Point(-borderSize, 0); - textFrame = new GUIFrame(new RectTransform(Point.Zero, videoFrame.RectTransform, Anchor.CenterLeft, Pivot.CenterLeft), "TextFrame"); - textFrame.RectTransform.AbsoluteOffset = new Point(width + borderSize * 2, 0); + textFrame = new GUIFrame(new RectTransform(new Point(width + borderSize, height + borderSize * 2), videoFrame.RectTransform, Anchor.CenterLeft, Pivot.CenterLeft), "TextFrame"); + textFrame.RectTransform.AbsoluteOffset = new Point(borderSize + videoFrame.Rect.Width, 0); - videoView = new GUICustomComponent(new RectTransform(Point.Zero, videoFrame.RectTransform, Anchor.Center), (spriteBatch, guiCustomComponent) => { DrawVideo(spriteBatch, guiCustomComponent.Rect); }); + videoView = new GUICustomComponent(new RectTransform(new Point(width, height), 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); - 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(new Vector2(1f, .8f), textFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft) { AbsoluteOffset = new Point(0, borderSize + titleHeight) }, 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"); - objectiveText = new GUITextBlock(new RectTransform(Point.Zero, textFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), string.Empty, font: GUI.ObjectiveNameFont, textColor: new Color(4, 180, 108), textAlignment: Alignment.CenterRight); + objectiveText = new GUITextBlock(new RectTransform(new Point(textFrame.Rect.Width, textHeight), textFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter), string.Empty, font: GUI.ObjectiveNameFont, textColor: new Color(4, 180, 108), textAlignment: Alignment.CenterRight); objectiveTitle.Visible = objectiveText.Visible = false; } @@ -110,16 +124,16 @@ namespace Barotrauma currentVideo.Dispose(); currentVideo = null; - currentVideo = CreateVideo(scaledResolution); + currentVideo = CreateVideo(); } public void AddToGUIUpdateList(bool ignoreChildren = false, int order = 0) { - if (!isPlaying) return; + if (!IsPlaying()) return; background.AddToGUIUpdateList(ignoreChildren, order); } - public void LoadContent(string contentPath, VideoSettings videoSettings, TextSettings textSettings, string contentId, bool startPlayback, string objective = "", Action callback = null) + public void LoadContentWithObjective(string contentPath, VideoSettings videoSettings, TextSettings textSettings, string contentId, bool startPlayback, string objective, Action callback = null) { callbackOnStop = callback; filePath = contentPath + videoSettings.File; @@ -139,10 +153,19 @@ namespace Barotrauma currentVideo = null; } - currentVideo = CreateVideo(scaledResolution); + resolution = new Point(videoSettings.Width, videoSettings.Height); - videoFrame.RectTransform.NonScaledSize += scaledResolution + new Point(borderSize, borderSize); - videoView.RectTransform.NonScaledSize += scaledResolution; + if (resolution.X == 0 || resolution.Y == 0) + { + resolution = defaultResolution; + } + + currentVideo = CreateVideo(); + + objectiveTitle.Visible = objectiveText.Visible = true; + + videoFrame.RectTransform.NonScaledSize += resolution + new Point(borderSize, borderSize); + videoView.RectTransform.NonScaledSize += resolution; title.Text = TextManager.Get(contentId); title.RectTransform.NonScaledSize += new Point(textSettings.Width, titleHeight); @@ -152,27 +175,79 @@ namespace Barotrauma 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.RectTransform.NonScaledSize = new Point(textSettings.Width, wrappedHeight); } textContent.Text = textSettings.Text; - 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)); + objectiveTitle.RectTransform.AbsoluteOffset = new Point(-10, textContent.RectTransform.Rect.Height + (int)(textHeight * 1.75f)); + 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, objectiveFrameHeight); + objectiveText.RectTransform.NonScaledSize += new Point(textFrame.Rect.Width, textHeight); + objectiveText.Text = objective; + + var okButton = new GUIButton(new RectTransform(buttonSize, textFrame.RectTransform, Anchor.BottomRight, Pivot.BottomRight) { AbsoluteOffset = new Point(20, 20) }, + TextManager.Get("OK")) { - textFrame.RectTransform.NonScaledSize += new Point(0, borderSize); - objectiveTitle.Visible = objectiveText.Visible = false; + OnClicked = DisposeVideo + }; + + if (startPlayback) Play(); + } + + public void LoadContent(string contentPath, VideoSettings videoSettings, TextSettings textSettings, string contentId, bool startPlayback, Action callback = null) + { + callbackOnStop = callback; + filePath = contentPath + videoSettings.File; + + if (!File.Exists(filePath)) + { + DebugConsole.ThrowError("No video found at: " + filePath); + DisposeVideo(null, null); + return; } + ResetFrameSizes(); + + if (currentVideo != null) + { + currentVideo.Dispose(); + currentVideo = null; + } + + resolution = new Point(0, 0); + + if (currentVideo == null) // No preloaded video found + { + resolution = new Point(videoSettings.Width, videoSettings.Height); + + if (resolution.X == 0 || resolution.Y == 0) + { + resolution = defaultResolution; + } + + currentVideo = CreateVideo(); + } + + objectiveTitle.Visible = objectiveText.Visible = false; + + videoFrame.RectTransform.NonScaledSize += resolution + new Point(borderSize, borderSize); + videoView.RectTransform.NonScaledSize += resolution; + + title.Text = TextManager.Get(contentId); + title.RectTransform.NonScaledSize += new Point(textSettings.Width, titleHeight); + + if (textSettings.Text != string.Empty) + { + 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; + var okButton = new GUIButton(new RectTransform(buttonSize, textFrame.RectTransform, Anchor.BottomRight, Pivot.BottomRight) { AbsoluteOffset = new Point(20, 20) }, TextManager.Get("OK")) { @@ -194,12 +269,13 @@ namespace Barotrauma objectiveText.RectTransform.NonScaledSize = Point.Zero; } - private Video CreateVideo(Point resolution) + private Video CreateVideo() { Video video = null; try { + //video = new Video(GameMain.Instance.GraphicsDevice, GameMain.SoundManager, "Content/splashscreen.mp4", 1280, 720); video = new Video(GameMain.Instance.GraphicsDevice, GameMain.SoundManager, filePath, (uint)resolution.X, (uint)resolution.Y); } catch (Exception e) diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs index b0c6a86bd..8d44d5ea2 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs @@ -5,6 +5,7 @@ using Microsoft.Xna.Framework; using Barotrauma.Items.Components; using System.Linq; using Microsoft.Xna.Framework.Input; +using System.Windows; namespace Barotrauma.Tutorials { @@ -41,8 +42,12 @@ namespace Barotrauma.Tutorials private bool disableTutorialOnDeficiencyFound = true; private GUIFrame holderFrame, objectiveFrame; + //private GUIButton toggleButton; + //private bool objectivesOpen = false; + //private float openState = 0f; private List activeObjectives = new List(); private string objectiveTranslated; + //private Point objectiveBaseOffset = Point.Zero; private float floodTutorialTimer = 0.0f; private const float floodTutorialDelay = 2.0f; @@ -108,6 +113,7 @@ namespace Barotrauma.Tutorials base.Initialize(); videoPlayer = new VideoPlayer(); characterTimeOnSonar = new List>(); + //objectivesOpen = true; } public void LoadPartiallyComplete(XElement element) @@ -131,6 +137,15 @@ namespace Barotrauma.Tutorials } } + private void PreloadVideoContent() // Have to see if needed with videos + { + /*for (int i = 0; i < segments.Count; i++) + { + if (segments[i].ContentType != ContentTypes.Video || segments[i].IsTriggered) continue; + spriteSheetPlayer.PreloadContent(playableContentPath, "tutorial", segments[i].Id, segments[i].VideoContent); + }*/ + } + public void SavePartiallyComplete(XElement element) { XElement tutorialElement = new XElement("contextualtutorial"); @@ -162,7 +177,10 @@ namespace Barotrauma.Tutorials { if (!Initialized) return; + PreloadVideoContent(); + base.Start(); + injuredMember = null; activeObjectives.Clear(); objectiveTranslated = TextManager.Get("Objective"); @@ -231,6 +249,21 @@ namespace Barotrauma.Tutorials { holderFrame = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight), GUI.Canvas, Anchor.Center)); objectiveFrame = new GUIFrame(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.ObjectiveAnchor, holderFrame.RectTransform), style: null); + + /*int toggleButtonWidth = (int)(30 * GUI.Scale); + int toggleButtonHeight = (int)(40 * GUI.Scale); + toggleButton = new GUIButton(new RectTransform(new Point(toggleButtonWidth, toggleButtonHeight), objectiveFrame.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(0, 20) }, style: "UIToggleButton"); + toggleButton.OnClicked += (GUIButton btn, object userdata) => + { + objectivesOpen = !objectivesOpen; + foreach (GUIComponent child in btn.Children) + { + child.SpriteEffects = objectivesOpen ? SpriteEffects.FlipHorizontally : SpriteEffects.None; + } + return true; + }; + + objectiveBaseOffset = new Point((int)(-2.5f * toggleButton.Rect.Width), 0);*/ } public override void AddToGUIUpdateList() @@ -278,11 +311,48 @@ namespace Barotrauma.Tutorials { CheckActiveObjectives(activeObjectives[i], deltaTime); } + + /*if (activeObjectives.Count > 0) + { + if (objectivesOpen) + { + openState -= deltaTime * 5.0f; + } + else + { + openState += deltaTime * 5.0f; + } + + openState = MathHelper.Clamp(openState, 0.0f, 1.0f); + + float widestObjective = 0f; + for (int i = 0; i < activeObjectives.Count; i++) + { + if (activeObjectives[i].ReplayButton.Rect.Width > widestObjective) + { + widestObjective = activeObjectives[i].ReplayButton.Rect.Width; + } + } + + float objectivesHiddenOffset = widestObjective + toggleButton.Rect.Width + 100f; + + for (int i = 0; i < activeObjectives.Count; i++) + { + activeObjectives[i].ReplayButton.RectTransform.AbsoluteOffset = objectiveBaseOffset + new Point((int)MathHelper.SmoothStep(0, objectivesHiddenOffset, openState), 0); + } + }*/ } private void ClosePreTextAndTriggerVideoCallback() { - videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(activeSegment.VideoContent), new VideoPlayer.TextSettings(activeSegment.VideoContent), activeSegment.Id, true, activeSegment.Objective, CurrentSegmentStopCallback); + if (!string.IsNullOrEmpty(activeSegment.Objective)) + { + videoPlayer.LoadContentWithObjective(playableContentPath, new VideoPlayer.VideoSettings(activeSegment.VideoContent), new VideoPlayer.TextSettings(activeSegment.VideoContent), activeSegment.Id, true, activeSegment.Objective, CurrentSegmentStopCallback); + } + else + { + videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(activeSegment.VideoContent), new VideoPlayer.TextSettings(activeSegment.VideoContent), activeSegment.Id, true, CurrentSegmentStopCallback); + } } private void CurrentSegmentStopCallback() @@ -734,7 +804,7 @@ namespace Barotrauma.Tutorials { if (ContentRunning) return; ContentRunning = true; - videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent), new VideoPlayer.TextSettings(segment.VideoContent), segment.Id, true, callback: () => ContentRunning = false); + videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent), new VideoPlayer.TextSettings(segment.VideoContent), segment.Id, true, () => ContentRunning = false); } private IEnumerable WaitToStop() diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/LevelResource.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/LevelResource.cs index b7951ce7d..8a73e7e2e 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/LevelResource.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/LevelResource.cs @@ -7,7 +7,7 @@ namespace Barotrauma.Items.Components { public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime) { - deattachTimer = msg.ReadSingle(); + DeattachTimer = msg.ReadSingle(); if (deattachTimer >= DeattachDuration) { holdable.DeattachFromWall(); diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/RepairTool.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/RepairTool.cs index f8f82df50..9b14effac 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/RepairTool.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/RepairTool.cs @@ -1,7 +1,6 @@ using Barotrauma.Particles; using FarseerPhysics; using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; using System.Linq; @@ -12,21 +11,12 @@ using System.Xml.Linq; namespace Barotrauma.Items.Components { partial class RepairTool -#if DEBUG - : IDrawableComponent -#endif { public ParticleEmitter ParticleEmitter { get; private set; } -#if DEBUG - public Vector2 DrawSize - { - get { return GameMain.DebugDraw ? Vector2.One * Range : Vector2.Zero; } - } -#endif private List ParticleEmitterHitStructure = new List(); private List ParticleEmitterHitCharacter = new List(); @@ -132,17 +122,5 @@ namespace Barotrauma.Items.Components emitter.Second.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi); } } -#if DEBUG - public void Draw(SpriteBatch spriteBatch, bool editing) - { - if (GameMain.DebugDraw && IsActive) - { - GUI.DrawLine(spriteBatch, - new Vector2(debugRayStartPos.X, -debugRayStartPos.Y), - new Vector2(debugRayEndPos.X, -debugRayEndPos.Y), - Color.Yellow); - } - } -#endif } } diff --git a/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs b/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs index 7944ddf9d..f9e043913 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs @@ -301,7 +301,7 @@ namespace Barotrauma protected virtual void ControlInput(Camera cam) { // Note that these targets are static. Therefore the outcome is the same if this method is called multiple times or only once. - if (selectedSlot != null && !DraggingItemToWorld) + if (selectedSlot != null || draggingItem != null) { cam.Freeze = true; } @@ -609,17 +609,8 @@ namespace Barotrauma if (selectedSlot == null) { - if (DraggingItemToWorld && - Character.Controlled.FocusedItem?.OwnInventory != null && - Character.Controlled.FocusedItem.OwnInventory.TryPutItem(draggingItem, Character.Controlled)) - { - GUI.PlayUISound(GUISoundType.PickItem); - } - else - { - GUI.PlayUISound(GUISoundType.DropItem); - draggingItem.Drop(Character.Controlled); - } + draggingItem.Drop(Character.Controlled); + GUI.PlayUISound(GUISoundType.DropItem); } else if (selectedSlot.ParentInventory.Items[selectedSlot.SlotIndex] != draggingItem) { @@ -711,27 +702,10 @@ namespace Barotrauma int iconSize = (int)(64 * GUI.Scale); float scale = Math.Min(Math.Min(iconSize / sprite.size.X, iconSize / sprite.size.Y), 1.5f); Vector2 itemPos = PlayerInput.MousePosition; - - if (GUI.MouseOn == null && selectedSlot == null) - { - var shadowSprite = GUI.Style.GetComponentStyle("OuterGlow").Sprites[GUIComponent.ComponentState.None][0]; - string toolTip = Character.Controlled.FocusedItem != null ? - TextManager.Get("PutItemIn").Replace("[itemname]", Character.Controlled.FocusedItem.Name) : - TextManager.Get("DropItem"); - int textWidth = (int)Math.Max(GUI.Font.MeasureString(draggingItem.Name).X, GUI.SmallFont.MeasureString(toolTip).X); - int textSpacing = (int)(15 * GUI.Scale); - Point shadowBorders = (new Point(40, 10)).Multiply(GUI.Scale); - shadowSprite.Draw(spriteBatch, - new Rectangle(itemPos.ToPoint() - new Point(iconSize / 2) - shadowBorders, new Point(iconSize + textWidth + textSpacing, iconSize) + shadowBorders.Multiply(2)), Color.Black * 0.8f); - GUI.DrawString(spriteBatch, new Vector2(itemPos.X + iconSize / 2 + textSpacing, itemPos.Y - iconSize / 2), draggingItem.Name, Color.White); - GUI.DrawString(spriteBatch, new Vector2(itemPos.X + iconSize / 2 + textSpacing, itemPos.Y), toolTip, - color: Character.Controlled.FocusedItem == null ? Color.Red : Color.LightGreen, - font: GUI.SmallFont); - } sprite.Draw(spriteBatch, itemPos + Vector2.One * 2, Color.Black, scale: scale); - sprite.Draw(spriteBatch, - itemPos, - sprite == draggingItem.Sprite ? draggingItem.GetSpriteColor() : draggingItem.GetInventoryIconColor(), + sprite.Draw(spriteBatch, + itemPos, + sprite == draggingItem.Sprite ? draggingItem.GetSpriteColor() : draggingItem.GetInventoryIconColor(), scale: scale); } } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs index be6ca7fcb..33b12d3e9 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs @@ -70,17 +70,28 @@ namespace Barotrauma private float raycastTimer; - private bool IsCoolDownRunning => attackingLimb != null && attackingLimb.attack.CoolDownTimer > 0; + private bool IsCoolDownRunning => AttackingLimb != null && AttackingLimb.attack.CoolDownTimer > 0; private bool aggressiveBoarding; - private LatchOntoAI latchOntoAI; - //a point in a wall which the Character is currently targeting private WallTarget wallTarget; //the limb selected for the current attack - private Limb attackingLimb; + private Limb _attackingLimb; + public Limb AttackingLimb + { + get { return _attackingLimb; } + private set + { + _attackingLimb = value; + Reverse = _attackingLimb != null && _attackingLimb.attack.Reverse; + if (Character.AnimController is FishAnimController fishController) + { + fishController.reverse = Reverse; + } + } + } //flee when the health is below this value private float fleeHealthThreshold; @@ -103,6 +114,8 @@ namespace Barotrauma private readonly float priorityFearIncreasement = 2; private readonly float memoryFadeTime = 0.5f; + public LatchOntoAI LatchOntoAI { get; private set; } + public bool AttackHumans { get @@ -121,11 +134,6 @@ namespace Barotrauma } } - public Limb AttackingLimb - { - get { return attackingLimb; } - } - public float CombatStrength { get { return combatStrength; } @@ -136,7 +144,7 @@ namespace Barotrauma get { //can't enter a submarine when attached to something - return latchOntoAI == null || !latchOntoAI.IsAttached; + return LatchOntoAI == null || !LatchOntoAI.IsAttached; } } @@ -144,11 +152,13 @@ namespace Barotrauma { get { - //can't flip when attached to something - return latchOntoAI == null || !latchOntoAI.IsAttached; + //can't flip when attached to something or when reversing + return !Reverse && (LatchOntoAI == null || !LatchOntoAI.IsAttached); } } + public bool Reverse { get; private set; } + public EnemyAIController(Character c, string file, string seed) : base(c) { targetMemories = new Dictionary(); @@ -196,7 +206,7 @@ namespace Barotrauma switch (subElement.Name.ToString().ToLowerInvariant()) { case "latchonto": - latchOntoAI = new LatchOntoAI(subElement, this); + LatchOntoAI = new LatchOntoAI(subElement, this); break; case "targetpriority": targetingPriorities.Add(subElement.GetAttributeString("tag", "").ToLowerInvariant(), new TargetingPriority(subElement)); @@ -305,7 +315,7 @@ namespace Barotrauma } } - latchOntoAI?.Update(this, deltaTime); + LatchOntoAI?.Update(this, deltaTime); if (SelectedAiTarget != null && (SelectedAiTarget.Entity == null || SelectedAiTarget.Entity.Removed)) { @@ -561,7 +571,7 @@ namespace Barotrauma if (Character.WorldPosition.Y < door.Item.WorldRect.Y && Character.WorldPosition.Y > door.Item.WorldRect.Y - door.Item.Rect.Height) { velocity.Y = 0; - latchOntoAI?.DeattachFromBody(); + LatchOntoAI?.DeattachFromBody(); Character.AnimController.ReleaseStuckLimbs(); steeringManager.SteeringManual(deltaTime, velocity); return; @@ -572,7 +582,7 @@ namespace Barotrauma if (Character.WorldPosition.X < door.Item.WorldRect.X && Character.WorldPosition.X > door.Item.WorldRect.Right) { velocity.X = 0; - latchOntoAI?.DeattachFromBody(); + LatchOntoAI?.DeattachFromBody(); Character.AnimController.ReleaseStuckLimbs(); steeringManager.SteeringManual(deltaTime, velocity); return; @@ -585,14 +595,14 @@ namespace Barotrauma bool canAttack = true; if (IsCoolDownRunning) { - switch (attackingLimb.attack.AfterAttack) + switch (AttackingLimb.attack.AfterAttack) { case AIBehaviorAfterAttack.Pursue: case AIBehaviorAfterAttack.PursueIfCanAttack: - if (attackingLimb.attack.SecondaryCoolDown <= 0) + if (AttackingLimb.attack.SecondaryCoolDown <= 0) { // No (valid) secondary cooldown defined. - if (attackingLimb.attack.AfterAttack == AIBehaviorAfterAttack.Pursue) + if (AttackingLimb.attack.AfterAttack == AIBehaviorAfterAttack.Pursue) { canAttack = false; } @@ -604,33 +614,33 @@ namespace Barotrauma } else { - if (attackingLimb.attack.SecondaryCoolDownTimer <= 0) + if (AttackingLimb.attack.SecondaryCoolDownTimer <= 0) { // Don't allow attacking when the attack target has just changed. if (_previousAiTarget != null && SelectedAiTarget != _previousAiTarget) { canAttack = false; - if (attackingLimb.attack.AfterAttack == AIBehaviorAfterAttack.PursueIfCanAttack) + if (AttackingLimb.attack.AfterAttack == AIBehaviorAfterAttack.PursueIfCanAttack) { // Fall back if cannot attack. UpdateFallBack(attackWorldPos, deltaTime); return; } - attackingLimb = null; + AttackingLimb = null; } else { // If the secondary cooldown is defined and expired, check if we can switch the attack - var previousLimb = attackingLimb; + var previousLimb = AttackingLimb; var newLimb = GetAttackLimb(attackWorldPos, previousLimb); if (newLimb != null) { - attackingLimb = newLimb; + AttackingLimb = newLimb; } else { // No new limb was found. - if (attackingLimb.attack.AfterAttack == AIBehaviorAfterAttack.Pursue) + if (AttackingLimb.attack.AfterAttack == AIBehaviorAfterAttack.Pursue) { canAttack = false; } @@ -657,20 +667,20 @@ namespace Barotrauma } } - if (attackingLimb == null || _previousAiTarget != SelectedAiTarget) + if (AttackingLimb == null || _previousAiTarget != SelectedAiTarget) { - attackingLimb = GetAttackLimb(attackWorldPos); + AttackingLimb = GetAttackLimb(attackWorldPos); } if (canAttack) { - canAttack = attackingLimb != null && attackingLimb.attack.CoolDownTimer <= 0; + canAttack = AttackingLimb != null && AttackingLimb.attack.CoolDownTimer <= 0; } float distance = 0; if (canAttack) { // Check that we can reach the target - distance = Vector2.Distance(attackingLimb.WorldPosition, attackWorldPos); - canAttack = distance < attackingLimb.attack.Range; + distance = Vector2.Distance(AttackingLimb.WorldPosition, attackWorldPos); + canAttack = distance < AttackingLimb.attack.Range; } // If the attacking limb is a hand or claw, for example, using it as the steering limb can end in the result where the character circles around the target. For example the Hammerhead steering with the claws when it should use the torso. @@ -679,7 +689,7 @@ namespace Barotrauma Limb steeringLimb; var torso = Character.AnimController.GetLimb(LimbType.Torso); var head = Character.AnimController.GetLimb(LimbType.Head); - if (attackingLimb == null) + if (AttackingLimb == null) { steeringLimb = head ?? torso; } @@ -687,7 +697,7 @@ namespace Barotrauma { if (head != null && torso != null) { - steeringLimb = Vector2.DistanceSquared(attackingLimb.SimPosition, head.SimPosition) < Vector2.DistanceSquared(attackingLimb.SimPosition, torso.SimPosition) ? head : torso; + steeringLimb = Vector2.DistanceSquared(AttackingLimb.SimPosition, head.SimPosition) < Vector2.DistanceSquared(AttackingLimb.SimPosition, torso.SimPosition) ? head : torso; } else { @@ -738,7 +748,7 @@ namespace Barotrauma if (canAttack) { - UpdateLimbAttack(deltaTime, attackingLimb, attackSimPos, distance); + UpdateLimbAttack(deltaTime, AttackingLimb, attackSimPos, distance); } } @@ -755,7 +765,7 @@ namespace Barotrauma { targetWorldPos.X = targetHull.WorldRect.Center.X; } - latchOntoAI?.DeattachFromBody(); + LatchOntoAI?.DeattachFromBody(); Character.AnimController.ReleaseStuckLimbs(); if (steeringManager is IndoorsSteeringManager) { @@ -778,6 +788,7 @@ namespace Barotrauma .Where(l => l != ignoredLimb && l.attack != null && + l.attack.CoolDownTimer <= 0 && !l.IsSevered && !l.IsStuck && l.attack.IsValidContext(currentContext) && @@ -846,7 +857,7 @@ namespace Barotrauma attachTargetNormal = new Vector2(Math.Sign(WorldPosition.X - wall.WorldPosition.X), 0.0f); sectionPos.X += (wall.BodyWidth <= 0.0f ? wall.Rect.Width : wall.BodyWidth) / 2 * attachTargetNormal.X; } - latchOntoAI?.SetAttachTarget(wall.Submarine.PhysicsBody.FarseerBody, wall.Submarine, ConvertUnits.ToSimUnits(sectionPos), attachTargetNormal); + LatchOntoAI?.SetAttachTarget(wall.Submarine.PhysicsBody.FarseerBody, wall.Submarine, ConvertUnits.ToSimUnits(sectionPos), attachTargetNormal); wallTarget = new WallTarget(sectionPos, wall, sectionIndex); } } @@ -864,7 +875,7 @@ namespace Barotrauma } } - latchOntoAI?.DeattachFromBody(); + LatchOntoAI?.DeattachFromBody(); Character.AnimController.ReleaseStuckLimbs(); if (attacker == null || attacker.AiTarget == null) return; @@ -974,7 +985,7 @@ namespace Barotrauma #region Targeting - private bool IsProperlyLatched => latchOntoAI != null && latchOntoAI.IsAttached && SelectedAiTarget?.Entity == wallTarget?.Structure; + private bool IsProperlyLatched => LatchOntoAI != null && LatchOntoAI.IsAttached && SelectedAiTarget?.Entity == wallTarget?.Structure; //goes through all the AItargets, evaluates how preferable it is to attack the target, //whether the Character can see/hear the target and chooses the most preferable target within @@ -1232,10 +1243,11 @@ namespace Barotrauma protected override void OnStateChanged(AIState from, AIState to) { - latchOntoAI?.DeattachFromBody(); + LatchOntoAI?.DeattachFromBody(); Character.AnimController.ReleaseStuckLimbs(); escapePoint = Vector2.Zero; wallTarget = null; + AttackingLimb = null; } private int GetMinimumPassableHoleCount() diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs index 37364e0bf..d0d0016fc 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs @@ -344,6 +344,8 @@ namespace Barotrauma } } + public bool reverse; + void UpdateSineAnim(float deltaTime) { if (CurrentSwimParams == null) { return; } @@ -367,8 +369,8 @@ namespace Barotrauma return; } - float movementAngle = MathUtils.VectorToAngle(movement) - MathHelper.PiOver2; - + Vector2 transformedMovement = reverse ? -movement : movement; + float movementAngle = MathUtils.VectorToAngle(transformedMovement) - MathHelper.PiOver2; float mainLimbAngle = 0; if (MainLimb.type == LimbType.Torso && TorsoAngle.HasValue) { @@ -386,7 +388,7 @@ namespace Barotrauma while (MainLimb.Rotation - (movementAngle + mainLimbAngle) < -MathHelper.Pi) { movementAngle -= MathHelper.TwoPi; - } + } if (CurrentSwimParams.RotateTowardsMovement) { @@ -410,16 +412,19 @@ namespace Barotrauma if (TailAngle.HasValue) { Limb tail = GetLimb(LimbType.Tail); - //tail?.body.SmoothRotate(movementAngle + TailAngle.Value * Dir, TailTorque); if (tail != null) { SmoothRotateWithoutWrapping(tail, movementAngle + TailAngle.Value * Dir, MainLimb, TailTorque); } } } - else + else if (MainLimb.type == LimbType.Head && HeadAngle.HasValue) { movementAngle = Dir > 0 ? -MathHelper.PiOver2 : MathHelper.PiOver2; + if (reverse) + { + movementAngle = MathUtils.WrapAngleTwoPi(movementAngle - MathHelper.Pi); + } if (MainLimb.type == LimbType.Head && HeadAngle.HasValue) { Collider.SmoothRotate(HeadAngle.Value * Dir, CurrentSwimParams.SteerTorque); @@ -449,7 +454,7 @@ namespace Barotrauma var waveAmplitude = Math.Abs(CurrentSwimParams.WaveAmplitude); if (waveLength > 0 && waveAmplitude > 0) { - WalkPos -= movement.Length() / Math.Abs(waveLength); + WalkPos -= transformedMovement.Length() / Math.Abs(waveLength); WalkPos = MathUtils.WrapAngleTwoPi(WalkPos); } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Attack.cs b/Barotrauma/BarotraumaShared/Source/Characters/Attack.cs index a80c796d3..955ba731b 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Attack.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Attack.cs @@ -81,6 +81,9 @@ namespace Barotrauma [Serialize(AIBehaviorAfterAttack.FallBack, true), Editable(ToolTip = "The preferred AI behavior after the attack.")] public AIBehaviorAfterAttack AfterAttack { get; private set; } + [Serialize(false, true), Editable(ToolTip = "Should the ai try to reverse when aiming with this attack?")] + public bool Reverse { get; private set; } + [Serialize(0.0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 2000.0f, ToolTip = "Min distance from the attack limb to the target before the AI tries to attack.")] public float Range { get; private set; } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs index adcdb54ac..a3fe980a6 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs @@ -1186,6 +1186,10 @@ namespace Barotrauma if (PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.F)) { AnimController.ReleaseStuckLimbs(); + if (AIController != null && AIController is EnemyAIController enemyAI) + { + enemyAI.LatchOntoAI?.DeattachFromBody(); + } } #endif @@ -1652,8 +1656,7 @@ namespace Barotrauma #if CLIENT if (isLocalPlayer) { - if (GUI.MouseOn == null && - (!CharacterInventory.IsMouseOnInventory() || CharacterInventory.DraggingItemToWorld)) + if (GUI.MouseOn == null && !CharacterInventory.IsMouseOnInventory()) { if (findFocusedTimer <= 0.0f || Screen.Selected == GameMain.SubEditorScreen) { diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/LevelResource.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/LevelResource.cs index 90a7a0665..458bf0c57 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/LevelResource.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/LevelResource.cs @@ -2,15 +2,12 @@ using Lidgren.Network; using Microsoft.Xna.Framework; using System; -using System.Linq; using System.Xml.Linq; namespace Barotrauma.Items.Components { partial class LevelResource : ItemComponent, IServerSerializable { - private float lastSentDeattachTimer; - [Serialize(1.0f, false)] public float DeattachDuration { @@ -24,29 +21,12 @@ namespace Barotrauma.Items.Components get { return deattachTimer; } set { - //clients don't deattach the item until the server says so (handled in ClientRead) - if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) - { - return; - } deattachTimer = Math.Max(0.0f, value); -#if SERVER - if (deattachTimer >= DeattachDuration) - { - if (holdable.Attached){ item.CreateServerEvent(this); } - holdable.DeattachFromWall(); - } - else if (Math.Abs(lastSentDeattachTimer - deattachTimer) > 0.1f) - { - item.CreateServerEvent(this); - lastSentDeattachTimer = deattachTimer; - } -#else - if (deattachTimer >= DeattachDuration) + //clients don't deattach the item until the server says so (handled in ClientRead) + if ((GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient) && deattachTimer >= DeattachDuration) { holdable.DeattachFromWall(); } -#endif } } @@ -87,10 +67,7 @@ namespace Barotrauma.Items.Components return; } holdable.Reattachable = false; - if (requiredItems.Any()) - { - holdable.PickingTime = float.MaxValue; - } + holdable.PickingTime = float.MaxValue; var body = item.body ?? holdable.Body; diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs index 153e694ef..5752bb1de 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs @@ -17,8 +17,6 @@ namespace Barotrauma.Items.Components private readonly List fixableEntities; private Vector2 pickedPosition; private float activeTimer; - - private Vector2 debugRayStartPos, debugRayEndPos; [Serialize(0.0f, false)] public float Range { get; set; } @@ -249,7 +247,6 @@ namespace Barotrauma.Items.Components var levelResource = targetItem.GetComponent(); if (levelResource != null && levelResource.IsActive && - levelResource.requiredItems.Any() && levelResource.HasRequiredItems(user, addMessage: false)) { levelResource.DeattachTimer += deltaTime; diff --git a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs index 738c9fa16..1629b9bff 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs @@ -678,24 +678,17 @@ namespace Barotrauma Body closestBody = null; if (allowInsideFixture) { - var aabb = new FarseerPhysics.Collision.AABB(rayStart - Vector2.One * 0.001f, rayStart + Vector2.One * 0.001f); + var aabb = new FarseerPhysics.Collision.AABB(rayStart - Vector2.UnitY * 0.001f, rayStart + Vector2.UnitY * 0.001f); GameMain.World.QueryAABB((fixture) => { - if (!CheckFixtureCollision(fixture, ignoredBodies, collisionCategory, ignoreSensors, customPredicate)) { return true; } - - fixture.Body.GetTransform(out FarseerPhysics.Common.Transform transform); - if (!fixture.Shape.TestPoint(ref transform, ref rayStart)) { return true; } - + if (!CheckFixtureCollision(fixture, ignoredBodies, collisionCategory, ignoreSensors, customPredicate)) { return false; } closestFraction = 0.0f; closestNormal = Vector2.Normalize(rayEnd - rayStart); if (fixture.Body != null) closestBody = fixture.Body; - return false; + return true; }, ref aabb); if (closestFraction <= 0.0f) { - lastPickedPosition = rayStart; - lastPickedFraction = closestFraction; - lastPickedNormal = closestNormal; return closestBody; } } @@ -747,21 +740,14 @@ namespace Barotrauma if (allowInsideFixture) { - var aabb = new FarseerPhysics.Collision.AABB(rayStart - Vector2.One * 0.001f, rayStart + Vector2.One * 0.001f); + var aabb = new FarseerPhysics.Collision.AABB(rayStart - Vector2.UnitY * 0.001f, rayStart + Vector2.UnitY * 0.001f); GameMain.World.QueryAABB((fixture) => { - if (bodies.Contains(fixture.Body) || fixture.Body == null) { return true; } - if (!CheckFixtureCollision(fixture, ignoredBodies, collisionCategory, ignoreSensors, customPredicate)) { return true; } - - fixture.Body.GetTransform(out FarseerPhysics.Common.Transform transform); - if (!fixture.Shape.TestPoint(ref transform, ref rayStart)) { return true; } - + if (bodies.Contains(fixture.Body) || fixture.Body == null) { return false; } + if (!CheckFixtureCollision(fixture, ignoredBodies, collisionCategory, ignoreSensors, customPredicate)) { return false; } closestFraction = 0.0f; - lastPickedPosition = rayStart; - lastPickedFraction = 0.0f; - lastPickedNormal = Vector2.Normalize(rayEnd - rayStart); bodies.Add(fixture.Body); - return false; + return true; }, ref aabb); }