diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs index 8f9276859..bcf133b30 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs @@ -152,6 +152,32 @@ namespace Barotrauma } + if (character.MemLocalState.Count > 120) character.MemLocalState.RemoveRange(0, character.MemLocalState.Count - 120); + character.MemState.Clear(); + } + } + + partial void ImpactProjSpecific(float impact, Body body) + { + float volume = MathHelper.Clamp(impact - 3.0f, 0.5f, 1.0f); + + if (body.UserData is Limb limb && character.Stun <= 0f) + { + if (impact > 3.0f) { PlayImpactSound(limb); } + } + else if (body.UserData is Limb || body == Collider.FarseerBody) + { + if (!character.IsRemotePlayer && impact > ImpactTolerance) + { + SoundPlayer.PlayDamageSound("LimbBlunt", strongestImpact, Collider); + } + } + if (Character.Controlled == character) + { + GameMain.GameScreen.Cam.Shake = Math.Min(Math.Max(strongestImpact, GameMain.GameScreen.Cam.Shake), 3.0f); + } + } + if (character.MemState.Count < 1) return; overrideTargetMovement = Vector2.Zero; diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs b/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs index e9bd2ba83..8b52b1fd9 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs @@ -74,12 +74,17 @@ namespace Barotrauma public CrewManager(XElement element, bool isSinglePlayer) : this(isSinglePlayer) { - if (!isSinglePlayer) + if (GameMain.Client != null) { - DebugConsole.ThrowError("Cannot add messages to single player chat box in multiplayer mode!\n" + Environment.StackTrace); + //let the server create random conversations in MP return; } - if (string.IsNullOrEmpty(text)) { return; } + List availableSpeakers = Character.CharacterList.FindAll(c => + c.AIController is HumanAIController && + !c.IsDead && + c.SpeechImpediment <= 100.0f); + pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers)); + } var characterInfo = new CharacterInfo(subElement); characterInfos.Add(characterInfo); @@ -90,7 +95,6 @@ namespace Barotrauma break; } } - ChatBox.AddMessage(ChatMessage.Create(senderName, text, messageType, sender)); } partial void InitProjectSpecific() @@ -239,27 +243,24 @@ namespace Barotrauma public IEnumerable GetCharacters() { - if (character?.Inventory == null) return null; + if (characterInfos.Contains(characterInfo)) + { + DebugConsole.ThrowError("Tried to add the same character info to CrewManager twice.\n" + Environment.StackTrace); + return; + } - var radioItem = character.Inventory.Items.FirstOrDefault(it => it != null && it.GetComponent() != null); - if (radioItem == null) return null; - if (requireEquipped && !character.HasEquippedItem(radioItem)) return null; - - return radioItem.GetComponent(); + characterInfos.Add(characterInfo); } public IEnumerable GetCharacterInfos() { - if (GameMain.Client != null) + if (character == null) { - //let the server create random conversations in MP + DebugConsole.ThrowError("Tried to remove a null character from CrewManager.\n" + Environment.StackTrace); return; } - List availableSpeakers = Character.CharacterList.FindAll(c => - c.AIController is HumanAIController && - !c.IsDead && - c.SpeechImpediment <= 100.0f); - pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers)); + characters.Remove(character); + if (removeInfo) characterInfos.Remove(character.Info); } public void AddCharacter(Character character) @@ -633,9 +634,183 @@ namespace Barotrauma { characterListBox.BarScroll = roundedPos; } - soundIcon.Visible = !muted && !mutedLocally; - soundIconDisabled.Visible = muted || mutedLocally; - soundIconDisabled.ToolTip = TextManager.Get(mutedLocally ? "MutedLocally" : "MutedGlobally"); + var characterArea = new GUIButton(new RectTransform(new Point(characterInfoWidth, frame.Rect.Height), frame.RectTransform, Anchor.CenterLeft), style: "GUITextBox") + { + UserData = character, + Color = frame.Color, + SelectedColor = frame.SelectedColor, + HoverColor = frame.HoverColor, + ToolTip = characterToolTip + }; + + var soundIcon = new GUIImage(new RectTransform(new Point((int)(characterArea.Rect.Height * 0.5f)), characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(5, 0) }, + "GUISoundIcon") + { + UserData = "soundicon", + CanBeFocused = false, + Visible = true + }; + soundIcon.Color = new Color(soundIcon.Color, 0.0f); + new GUIImage(new RectTransform(new Point((int)(characterArea.Rect.Height * 0.5f)), characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(5, 0) }, + "GUISoundIconDisabled") + { + UserData = "soundicondisabled", + CanBeFocused = true, + Visible = false + }; + + if (isSinglePlayer) + { + characterArea.OnClicked = CharacterClicked; + } + else + { + characterArea.CanBeFocused = false; + characterArea.CanBeSelected = false; + } + + var characterImage = new GUICustomComponent(new RectTransform(new Point(characterArea.Rect.Height), characterArea.RectTransform, Anchor.CenterLeft), + onDraw: (sb, component) => character.Info.DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2())) + { + CanBeFocused = false, + HoverColor = Color.White, + SelectedColor = Color.White, + ToolTip = characterToolTip + }; + + var characterName = new GUITextBlock(new RectTransform(new Point(characterArea.Rect.Width - characterImage.Rect.Width - soundIcon.Rect.Width - 10, characterArea.Rect.Height), + characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(soundIcon.Rect.Width + 10, 0) }, + character.Name, textColor: frame.Color, font: GUI.SmallFont, wrap: true) + { + Color = frame.Color, + HoverColor = Color.Transparent, + SelectedColor = Color.Transparent, + CanBeFocused = false, + ToolTip = characterToolTip, + AutoScale = true + }; + + //---------------- order buttons ---------------- + + var orderButtonFrame = new GUILayoutGroup(new RectTransform(new Point(100, frame.Rect.Height), frame.RectTransform) + { AbsoluteOffset = new Point(characterInfoWidth + spacing, 0) }, + isHorizontal: true, childAnchor: Anchor.CenterLeft) + { + AbsoluteSpacing = (int)(10 * GUI.Scale), + UserData = "orderbuttons", + CanBeFocused = false + }; + + //listbox for holding the orders inappropriate for this character + //(so we can easily toggle their visibility) + var wrongOrderList = new GUIListBox(new RectTransform(new Point(50, orderButtonFrame.Rect.Height), orderButtonFrame.RectTransform), isHorizontal: true, style: null) + { + ScrollBarEnabled = false, + ScrollBarVisible = false, + Enabled = false, + Spacing = spacing, + ClampMouseRectToParent = false + }; + wrongOrderList.Content.ClampMouseRectToParent = false; + + for (int i = 0; i < orders.Count; i++) + { + var order = orders[i]; + if (order.TargetAllCharacters) continue; + + RectTransform btnParent = (i >= correctOrderCount + neutralOrderCount) ? + wrongOrderList.Content.RectTransform : + orderButtonFrame.RectTransform; + + var btn = new GUIButton(new RectTransform(new Point(iconSize, iconSize), btnParent, Anchor.CenterLeft), + style: null) + { + UserData = order + }; + + new GUIFrame(new RectTransform(new Vector2(1.5f), btn.RectTransform, Anchor.Center), "OuterGlow") + { + Color = Color.Lerp(order.Color, frame.Color, 0.5f) * 0.8f, + HoverColor = Color.Lerp(order.Color, frame.Color, 0.5f) * 1.0f, + PressedColor = Color.Lerp(order.Color, frame.Color, 0.5f) * 0.6f, + UserData = "selected", + CanBeFocused = false, + Visible = false + }; + + var img = new GUIImage(new RectTransform(Vector2.One, btn.RectTransform), order.Prefab.SymbolSprite); + img.Scale = iconSize / (float)img.SourceRect.Width; + img.Color = Color.Lerp(order.Color, frame.Color, 0.5f); + img.ToolTip = order.Name; + img.HoverColor = Color.Lerp(img.Color, Color.White, 0.5f); + + btn.OnClicked += (GUIButton button, object userData) => + { + if (Character.Controlled == null || Character.Controlled.SpeechImpediment >= 100.0f) return false; + + if (btn.GetChildByUserData("selected").Visible) + { + SetCharacterOrder(character, Order.PrefabList.Find(o => o.AITag == "dismissed"), null, Character.Controlled); + } + else + { + if (order.ItemComponentType != null || order.ItemIdentifiers.Length > 0 || order.Options.Length > 1) + { + CreateOrderTargetFrame(button, character, order); + } + else + { + SetCharacterOrder(character, order, null, Character.Controlled); + } + } + return true; + }; + btn.UserData = order; + btn.ToolTip = order.Name; + + //divider between different groups of orders + if (i == correctOrderCount - 1 || i == correctOrderCount + neutralOrderCount - 1) + { + //TODO: divider sprite + new GUIFrame(new RectTransform(new Point(8, iconSize), orderButtonFrame.RectTransform), style: "GUIButton"); + } + } + + var toggleWrongOrderBtn = new GUIButton(new RectTransform(new Point((int)(30 * GUI.Scale), wrongOrderList.Rect.Height), wrongOrderList.Content.RectTransform), + "", style: "UIToggleButton") + { + UserData = "togglewrongorder", + CanBeFocused = false + }; + + wrongOrderList.RectTransform.NonScaledSize = new Point( + wrongOrderList.Content.Children.Sum(c => c.Rect.Width + wrongOrderList.Spacing), + wrongOrderList.RectTransform.NonScaledSize.Y); + wrongOrderList.RectTransform.SetAsLastChild(); + + new GUIFrame(new RectTransform(new Point( + wrongOrderList.Rect.Width - toggleWrongOrderBtn.Rect.Width - wrongOrderList.Spacing * 2, + wrongOrderList.Rect.Height), wrongOrderList.Content.RectTransform), + style: null) + { + CanBeFocused = false + }; + + //scale to fit the content + orderButtonFrame.RectTransform.NonScaledSize = new Point( + orderButtonFrame.Children.Sum(c => c.Rect.Width + orderButtonFrame.AbsoluteSpacing), + orderButtonFrame.RectTransform.NonScaledSize.Y); + + frame.RectTransform.NonScaledSize = new Point( + characterInfoWidth + spacing + (orderButtonFrame.Rect.Width - wrongOrderList.Rect.Width), + frame.RectTransform.NonScaledSize.Y); + + characterListBox.RectTransform.NonScaledSize = new Point( + characterListBox.Content.Children.Max(c => c.Rect.Width) + wrongOrderList.Rect.Width, + characterListBox.RectTransform.NonScaledSize.Y); + characterListBox.Content.RectTransform.NonScaledSize = characterListBox.RectTransform.NonScaledSize; + characterListBox.UpdateScrollBarSize(); + return frame; } private IEnumerable KillCharacterAnim(GUIComponent component) @@ -779,6 +954,12 @@ namespace Barotrauma } return; } + List availableSpeakers = Character.CharacterList.FindAll(c => + c.AIController is HumanAIController && + !c.IsDead && + c.SpeechImpediment <= 100.0f); + pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers)); + } character.SetOrder(order, option, orderGiver, speak: orderGiver != character); if (IsSinglePlayer) @@ -836,19 +1017,23 @@ namespace Barotrauma } } } - //only one target (or an order with no particular targets), just show options - else + + character.SetOrder(order, option, orderGiver, speak: orderGiver != character); + if (IsSinglePlayer) { - orderTargetFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.2f + order.Options.Length * 0.1f, 0.18f), GUI.Canvas) - { AbsoluteOffset = new Point(orderButton.Rect.Center.X, orderButton.Rect.Bottom) }, - isHorizontal: true, childAnchor: Anchor.BottomLeft) + orderGiver?.Speak( + order.GetChatMessage(character.Name, orderGiver.CurrentHull?.DisplayName, givingOrderToSelf: character == orderGiver, orderOption: option), null); + } + else if (orderGiver != null) + { + OrderChatMessage msg = new OrderChatMessage(order, option, order.TargetItemComponent?.Item, character, orderGiver); + if (GameMain.Client != null) { - UserData = character, - Stretch = true - }; - //line connecting the order button to the option buttons - //TODO: sprite - new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), orderTargetFrame.RectTransform), style: null); + GameMain.Client.SendChatMessage(msg); + } + } + DisplayCharacterOrder(character, order); + } /// /// Create the UI panel that's used to select the target and options for a given order diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs index e7e032352..035c833a1 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs @@ -316,9 +316,9 @@ namespace Barotrauma.Items.Components } Steering steering = item.GetComponent(); - if (steering != null && steering.DockingModeEnabled) + if (steering != null && steering.DockingModeEnabled && steering.ActiveDockingSource != null) { - float dockingDist = Vector2.Distance(steering.DockingSource.Item.WorldPosition, steering.DockingTarget.Item.WorldPosition); + float dockingDist = Vector2.Distance(steering.ActiveDockingSource.Item.WorldPosition, steering.DockingTarget.Item.WorldPosition); if (prevDockingDist > steering.DockingAssistThreshold && dockingDist <= steering.DockingAssistThreshold) { zoom = Math.Max(zoom, MathHelper.Lerp(MinZoom, MaxZoom, 0.25f)); @@ -599,7 +599,7 @@ namespace Barotrauma.Items.Components float scale = displayScale * zoom; Steering steering = item.GetComponent(); - if (steering != null && steering.DockingModeEnabled) + if (steering != null && steering.DockingModeEnabled && steering.ActiveDockingSource != null) { DrawDockingIndicator(spriteBatch, steering, ref transducerCenter); } @@ -633,21 +633,21 @@ namespace Barotrauma.Items.Components { float scale = displayScale * zoom; - Vector2 worldFocusPos = (steering.DockingSource.Item.WorldPosition + steering.DockingTarget.Item.WorldPosition) / 2.0f; + Vector2 worldFocusPos = (steering.ActiveDockingSource.Item.WorldPosition + steering.DockingTarget.Item.WorldPosition) / 2.0f; worldFocusPos.X = steering.DockingTarget.Item.WorldPosition.X; DisplayOffset = Vector2.Lerp(DisplayOffset, worldFocusPos - transducerCenter, 0.1f); transducerCenter += DisplayOffset; - Vector2 sourcePortDiff = (steering.DockingSource.Item.WorldPosition - transducerCenter) * scale; + Vector2 sourcePortDiff = (steering.ActiveDockingSource.Item.WorldPosition - transducerCenter) * scale; Vector2 sourcePortPos = new Vector2(sourcePortDiff.X, -sourcePortDiff.Y); Vector2 targetPortDiff = (steering.DockingTarget.Item.WorldPosition - transducerCenter) * scale; Vector2 targetPortPos = new Vector2(targetPortDiff.X, -targetPortDiff.Y); Vector2 midPos = (sourcePortPos + targetPortPos) / 2.0f; - System.Diagnostics.Debug.Assert(steering.DockingSource.IsHorizontal == steering.DockingTarget.IsHorizontal); - Vector2 diff = steering.DockingTarget.Item.WorldPosition - steering.DockingSource.Item.WorldPosition; + System.Diagnostics.Debug.Assert(steering.ActiveDockingSource.IsHorizontal == steering.DockingTarget.IsHorizontal); + Vector2 diff = steering.DockingTarget.Item.WorldPosition - steering.ActiveDockingSource.Item.WorldPosition; float dist = diff.Length(); bool readyToDock = Math.Abs(diff.X) < steering.DockingTarget.DistanceTolerance.X && @@ -657,7 +657,7 @@ namespace Barotrauma.Items.Components Vector2 normalizedDockingDir = Vector2.Normalize(dockingDir); if (!dynamicDockingIndicator) { - if (steering.DockingSource.IsHorizontal) + if (steering.ActiveDockingSource.IsHorizontal) { normalizedDockingDir = new Vector2(Math.Sign(normalizedDockingDir.X), 0.0f); } @@ -709,7 +709,7 @@ namespace Barotrauma.Items.Components float indicatorSectorLength = (float)(midLength / Math.Cos(indicatorSector)); bool withinSector = - (Math.Abs(diff.X) < steering.DockingSource.DistanceTolerance.X && Math.Abs(diff.Y) < steering.DockingSource.DistanceTolerance.Y) || + (Math.Abs(diff.X) < steering.ActiveDockingSource.DistanceTolerance.X && Math.Abs(diff.Y) < steering.ActiveDockingSource.DistanceTolerance.Y) || Vector2.Dot(normalizedDockingDir, MathUtils.RotatePoint(normalizedDockingDir, indicatorSector)) < Vector2.Dot(normalizedDockingDir, Vector2.Normalize(dockingDir)); diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs index 3891c990c..3d8f96eb4 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs @@ -76,8 +76,9 @@ namespace Barotrauma.Items.Components get; set; } - - public DockingPort DockingSource, DockingTarget; + + public List DockingSources = new List(); + public DockingPort ActiveDockingSource, DockingTarget; private bool searchedConnectedDockingPort; @@ -357,17 +358,24 @@ namespace Barotrauma.Items.Components private void FindConnectedDockingPort() { - DockingSource = - (item.linkedTo.FirstOrDefault(l => l is Item item && item.GetComponent() != null) as Item)?.GetComponent(); - if (DockingSource == null) + foreach (MapEntity linkedTo in item.linkedTo) { - var dockingConnection = item.Connections.FirstOrDefault(c => c.Name == "toggle_docking"); - if (dockingConnection != null) + if (linkedTo is Item item) { - var connectedPorts = item.GetConnectedComponentsRecursive(dockingConnection); - DockingSource = connectedPorts.Find(p => p.Item.Submarine == item.Submarine); + var port = item.GetComponent(); + if (port != null) + { + DockingSources.Add(port); + } } } + + var dockingConnection = item.Connections.FirstOrDefault(c => c.Name == "toggle_docking"); + if (dockingConnection != null) + { + var connectedPorts = item.GetConnectedComponentsRecursive(dockingConnection); + DockingSources.AddRange(connectedPorts.Where(p => p.Item.Submarine != null && !p.Item.Submarine.IsOutpost)); + } } /// @@ -560,10 +568,10 @@ namespace Barotrauma.Items.Components dockingContainer.Visible = DockingModeEnabled; statusContainer.Visible = !DockingModeEnabled; - if (DockingModeEnabled) + if (DockingModeEnabled && ActiveDockingSource != null) { - if (Math.Abs(DockingSource.Item.WorldPosition.X - DockingTarget.Item.WorldPosition.X) < DockingSource.DistanceTolerance.X && - Math.Abs(DockingSource.Item.WorldPosition.Y - DockingTarget.Item.WorldPosition.Y) < DockingSource.DistanceTolerance.Y) + if (Math.Abs(ActiveDockingSource.Item.WorldPosition.X - DockingTarget.Item.WorldPosition.X) < ActiveDockingSource.DistanceTolerance.X && + Math.Abs(ActiveDockingSource.Item.WorldPosition.Y - DockingTarget.Item.WorldPosition.Y) < ActiveDockingSource.DistanceTolerance.Y) { dockingButton.Text = dockText; if (dockingButton.FlashTimer <= 0.0f) @@ -573,7 +581,7 @@ namespace Barotrauma.Items.Components } } } - else if (DockingSource != null && DockingSource.Docked) + else if (DockingSources.Any(d => d.Docked)) { dockingButton.Text = undockText; dockingContainer.Visible = true; @@ -722,7 +730,7 @@ namespace Barotrauma.Items.Components if (dist < closestDist) { DockingModeEnabled = true; - DockingSource = sourcePort; + ActiveDockingSource = sourcePort; DockingTarget = targetPort; } } diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs index 7d128859d..4db6803b3 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs @@ -516,6 +516,8 @@ namespace Barotrauma private GUILayoutGroup subPreviewContainer; + private GUILayoutGroup subPreviewContainer; + private GUIButton loadGameButton; public Action StartNewGame; diff --git a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs index 287ac0265..96c441896 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs @@ -789,6 +789,10 @@ namespace Barotrauma GUI.Draw(Cam, spriteBatch); + spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, GameMain.ScissorTestEnable); + + GUI.Draw(Cam, spriteBatch); + GUI.Draw(Cam, spriteBatch); #if DEBUG diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs index 948f4d413..26cb19289 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFixLeak.cs @@ -101,6 +101,32 @@ namespace Barotrauma { #if DEBUG DebugConsole.ThrowError("AIObjectiveFixLeak failed - the item \"" + weldingTool + "\" has no RepairTool component but is tagged as a welding tool"); +#endif + abandon = true; + return; + } + Vector2 gapDiff = Leak.WorldPosition - character.WorldPosition; + // TODO: use the collider size/reach? + if (!character.AnimController.InWater && Math.Abs(gapDiff.X) < 100 && gapDiff.Y < 0.0f && gapDiff.Y > -150) + { + HumanAIController.AnimController.Crouching = true; + } + float reach = ConvertUnits.ToSimUnits(repairTool.Range); + bool canOperate = ConvertUnits.ToSimUnits(gapDiff.Length()) < reach * 1.5f; + if (canOperate) + { + TryAddSubObjective(ref operateObjective, () => new AIObjectiveOperateItem(repairTool, character, objectiveManager, option: "", requireEquip: true, operateTarget: Leak)); + } + else + { + TryAddSubObjective(ref gotoObjective, () => new AIObjectiveGoTo(ConvertUnits.ToSimUnits(GetStandPosition()), character, objectiveManager) { CloseEnough = reach * 0.75f }); + } + if (subObjectives.Any()) { return; } + var repairTool = weldingTool.GetComponent(); + if (repairTool == null) + { +#if DEBUG + DebugConsole.ThrowError("AIObjectiveFixLeak failed - the item \"" + weldingTool + "\" has no RepairTool component but is tagged as a welding tool"); #endif abandon = true; return; diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs index eeef8131c..1e1e961f6 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs @@ -73,6 +73,21 @@ namespace Barotrauma } } + public override void Update(float deltaTime) + { + if (objectiveManager.CurrentObjective == this) + { + if (randomTimer > 0) + { + randomTimer -= deltaTime; + } + else + { + SetRandom(); + } + } + } + public override bool IsCompleted() => false; public override bool CanBeCompleted => true; diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs index f02f16793..62cde0e8f 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs @@ -434,6 +434,10 @@ namespace Barotrauma { isCompleted = true; } + if (component.AIOperate(deltaTime, character, this)) + { + isCompleted = true; + } } else { diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs index 8ecdcdec6..d20a57d69 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs @@ -563,6 +563,25 @@ namespace Barotrauma.Items.Components } } + if (targetItem.Prefab.DeconstructItems.Any()) + { + inputContainer.Inventory.RemoveItem(targetItem); + Entity.Spawner.AddToRemoveQueue(targetItem); + MoveInputQueue(); + PutItemsToLinkedContainer(); + } + else + { + if (outputContainer.Inventory.Items.All(i => i != null)) + { + targetItem.Drop(dropper: null); + } + else + { + outputContainer.Inventory.TryPutItem(targetItem, user: null, createNetworkEvent: true); + } + } + if (targetItem.Prefab.DeconstructItems.Any()) { inputContainer.Inventory.RemoveItem(targetItem); diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs index a251165ce..2aafee648 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs @@ -212,33 +212,6 @@ namespace Barotrauma.Items.Components } } - public Vector2? PosToMaintain - { - get { return posToMaintain; } - set { posToMaintain = value; } - } - - struct ObstacleDebugInfo - { - public Vector2 Point1; - public Vector2 Point2; - - public Vector2? Intersection; - - public float Dot; - - public Vector2 AvoidStrength; - - public ObstacleDebugInfo(GraphEdge edge, Vector2? intersection, float dot, Vector2 avoidStrength) - { - Point1 = edge.Point1; - Point2 = edge.Point2; - Intersection = intersection; - Dot = dot; - AvoidStrength = avoidStrength; - } - } - //edge point 1, edge point 2, avoid strength private List debugDrawObstacles = new List(); diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Turret.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Turret.cs index 2e500837e..d8ad6eda2 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Turret.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Turret.cs @@ -495,10 +495,10 @@ namespace Barotrauma.Items.Components character.CursorPosition = closestEnemy.WorldPosition; if (item.Submarine != null) character.CursorPosition -= item.Submarine.Position; - if (item.RequireAimToUse) - { - character.SetInput(InputType.Aim, false, true); - } + + //force aim input even if the turret doesn't require it, + //because the cursor position (and consequently, turret aim direction) is only synced to clients when aiming + character.SetInput(InputType.Aim, false, true); float enemyAngle = MathUtils.VectorToAngle(closestEnemy.WorldPosition - item.WorldPosition); float turretAngle = -rotation; diff --git a/Barotrauma/BarotraumaShared/Source/Items/Item.cs b/Barotrauma/BarotraumaShared/Source/Items/Item.cs index 4392ee683..71bbfaf9b 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Item.cs @@ -1128,10 +1128,6 @@ namespace Barotrauma { ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime); } - if (!broken) - { - ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime); - } if (body == null || !body.Enabled || !inWater || ParentInventory != null || Removed) { return; } @@ -1176,59 +1172,6 @@ namespace Barotrauma } } - public void UpdateTransform() - { - Submarine prevSub = Submarine; - - FindHull(); - - if (body == null || !body.Enabled || !inWater || ParentInventory != null || Removed) { return; } - - Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition); - rect.X = (int)(displayPos.X - rect.Width / 2.0f); - rect.Y = (int)(displayPos.Y + rect.Height / 2.0f); - - if (Math.Abs(body.LinearVelocity.X) > NetConfig.MaxPhysicsBodyVelocity || - Math.Abs(body.LinearVelocity.Y) > NetConfig.MaxPhysicsBodyVelocity) - { - body.LinearVelocity = new Vector2( - MathHelper.Clamp(body.LinearVelocity.X, -NetConfig.MaxPhysicsBodyVelocity, NetConfig.MaxPhysicsBodyVelocity), - MathHelper.Clamp(body.LinearVelocity.Y, -NetConfig.MaxPhysicsBodyVelocity, NetConfig.MaxPhysicsBodyVelocity)); - } - } - - public void UpdateTransform() - { - Submarine prevSub = Submarine; - - FindHull(); - - if (Submarine == null && prevSub != null) - { - body.SetTransform(body.SimPosition + prevSub.SimPosition, body.Rotation); - } - else if (Submarine != null && prevSub == null) - { - body.SetTransform(body.SimPosition - Submarine.SimPosition, body.Rotation); - } - else if (Submarine != null && prevSub != null && Submarine != prevSub) - { - body.SetTransform(body.SimPosition + prevSub.SimPosition - Submarine.SimPosition, body.Rotation); - } - - Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition); - rect.X = (int)(displayPos.X - rect.Width / 2.0f); - rect.Y = (int)(displayPos.Y + rect.Height / 2.0f); - - if (Math.Abs(body.LinearVelocity.X) > NetConfig.MaxPhysicsBodyVelocity || - Math.Abs(body.LinearVelocity.Y) > NetConfig.MaxPhysicsBodyVelocity) - { - body.LinearVelocity = new Vector2( - MathHelper.Clamp(body.LinearVelocity.X, -NetConfig.MaxPhysicsBodyVelocity, NetConfig.MaxPhysicsBodyVelocity), - MathHelper.Clamp(body.LinearVelocity.Y, -NetConfig.MaxPhysicsBodyVelocity, NetConfig.MaxPhysicsBodyVelocity)); - } - } - public void UpdateTransform() { Submarine prevSub = Submarine; diff --git a/Barotrauma/BarotraumaShared/Source/Map/Hull.cs b/Barotrauma/BarotraumaShared/Source/Map/Hull.cs index aedadbf34..659b9ea94 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Hull.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Hull.cs @@ -341,6 +341,25 @@ namespace Barotrauma } } + public string DisplayName + { + get; + private set; + } + + private string roomName; + [Editable, Serialize("", true, translationTextTag: "RoomName.")] + public string RoomName + { + get { return roomName; } + set + { + if (roomName == value) { return; } + roomName = value; + DisplayName = TextManager.Get(roomName, returnNull: true) ?? roomName; + } + } + public override Rectangle Rect { get