diff --git a/Barotrauma/BarotraumaClient/Source/Characters/AI/HumanAIController.cs b/Barotrauma/BarotraumaClient/Source/Characters/AI/HumanAIController.cs index 3d9f63ed6..d694786a9 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/AI/HumanAIController.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/AI/HumanAIController.cs @@ -39,6 +39,10 @@ namespace Barotrauma { GUI.DrawString(spriteBatch, pos + textOffset, $"ORDER: {currentOrder.DebugTag} ({currentOrder.GetPriority().FormatZeroDecimal()})", Color.White, Color.Black); } + else if (ObjectiveManager.WaitTimer > 0) + { + GUI.DrawString(spriteBatch, pos + textOffset, $"Waiting... {ObjectiveManager.WaitTimer.FormatZeroDecimal()}", Color.White, Color.Black); + } var currentObjective = ObjectiveManager.CurrentObjective; if (currentObjective != null) { diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs index bcf133b30..fa30d8a82 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs @@ -108,6 +108,61 @@ namespace Barotrauma } } + //unconscious/dead characters can't correct their position using AnimController movement + // -> we need to correct it manually + if (!character.AllowInput) + { + float mainLimbDistSqrd = Vector2.DistanceSquared(MainLimb.PullJointWorldAnchorA, Collider.SimPosition); + float mainLimbErrorTolerance = 0.1f; + //if the main limb is roughly at the correct position and the collider isn't moving (much at least), + //don't attempt to correct the position. + if (mainLimbDistSqrd > mainLimbErrorTolerance || Collider.LinearVelocity.LengthSquared() > 0.05f) + { + MainLimb.PullJointWorldAnchorB = Collider.SimPosition; + MainLimb.PullJointEnabled = true; + } + character.SelectedConstruction = character.MemState[0].SelectedItem; + } + + if (character.MemState[0].Animation == AnimController.Animation.CPR) + { + character.AnimController.Anim = AnimController.Animation.CPR; + } + else if (character.AnimController.Anim == AnimController.Animation.CPR) + { + character.AnimController.Anim = AnimController.Animation.None; + } + + Vector2 newVelocity = Collider.LinearVelocity; + Vector2 newPosition = Collider.SimPosition; + float newRotation = Collider.Rotation; + float newAngularVelocity = Collider.AngularVelocity; + Collider.CorrectPosition(character.MemState, out newPosition, out newVelocity, out newRotation, out newAngularVelocity); + + newVelocity = newVelocity.ClampLength(100.0f); + if (!MathUtils.IsValid(newVelocity)) { newVelocity = Vector2.Zero; } + overrideTargetMovement = newVelocity.LengthSquared() > 0.01f ? newVelocity : Vector2.Zero; + + Collider.LinearVelocity = newVelocity; + Collider.AngularVelocity = newAngularVelocity; + + float distSqrd = Vector2.DistanceSquared(newPosition, Collider.SimPosition); + float errorTolerance = character.AllowInput ? 0.01f : 0.2f; + if (distSqrd > errorTolerance) + { + if (distSqrd > 10.0f || !character.AllowInput) + { + Collider.TargetRotation = newRotation; + SetPosition(newPosition, lerp: distSqrd < 5.0f, ignorePlatforms: false); + } + else + { + Collider.TargetRotation = newRotation; + Collider.TargetPosition = newPosition; + Collider.MoveToTargetPosition(true); + } + } + //unconscious/dead characters can't correct their position using AnimController movement // -> we need to correct it manually if (!character.AllowInput) @@ -151,32 +206,34 @@ namespace Barotrauma } } - - if (character.MemLocalState.Count > 120) character.MemLocalState.RemoveRange(0, character.MemLocalState.Count - 120); - character.MemState.Clear(); + character.MemLocalState.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) + else { - if (impact > 3.0f) { PlayImpactSound(limb); } - } - else if (body.UserData is Limb || body == Collider.FarseerBody) - { - if (!character.IsRemotePlayer && impact > ImpactTolerance) + //remove states with a timestamp (there may still timestamp-based states + //in the list if the controlled character switches from timestamp-based interpolation to ID-based) + character.MemState.RemoveAll(m => m.Timestamp > 0.0f); + + for (int i = 0; i < character.MemLocalState.Count; i++) { - SoundPlayer.PlayDamageSound("LimbBlunt", strongestImpact, Collider); + if (character.Submarine == null) + { + //transform in-sub coordinates to outside coordinates + if (character.MemLocalState[i].Position.Y > lowestSubPos) + { + character.MemLocalState[i].TransformInToOutside(); + } + } + else if (currentHull?.Submarine != null) + { + //transform outside coordinates to in-sub coordinates + if (character.MemLocalState[i].Position.Y < lowestSubPos) + { + character.MemLocalState[i].TransformOutToInside(currentHull.Submarine); + } + } + } - } - 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; diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs b/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs index c888d06cd..0289f5e3d 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs @@ -74,17 +74,12 @@ namespace Barotrauma public CrewManager(XElement element, bool isSinglePlayer) : this(isSinglePlayer) { - if (GameMain.Client != null) + if (!isSinglePlayer) { - //let the server create random conversations in MP + DebugConsole.ThrowError("Cannot add messages to single player chat box in multiplayer mode!\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)); - } + if (string.IsNullOrEmpty(text)) { return; } var characterInfo = new CharacterInfo(subElement); characterInfos.Add(characterInfo); @@ -95,6 +90,7 @@ namespace Barotrauma break; } } + ChatBox.AddMessage(ChatMessage.Create(senderName, text, messageType, sender)); } partial void InitProjectSpecific() @@ -242,24 +238,27 @@ namespace Barotrauma public IEnumerable GetCharacters() { - if (characterInfos.Contains(characterInfo)) - { - DebugConsole.ThrowError("Tried to add the same character info to CrewManager twice.\n" + Environment.StackTrace); - return; - } + if (character?.Inventory == null) return null; - characterInfos.Add(characterInfo); + 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(); } public IEnumerable GetCharacterInfos() { - if (character == null) + if (GameMain.Client != null) { - DebugConsole.ThrowError("Tried to remove a null character from CrewManager.\n" + Environment.StackTrace); + //let the server create random conversations in MP return; } - characters.Remove(character); - if (removeInfo) characterInfos.Remove(character.Info); + List availableSpeakers = Character.CharacterList.FindAll(c => + c.AIController is HumanAIController && + !c.IsDead && + c.SpeechImpediment <= 100.0f); + pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers)); } public void AddCharacter(Character character) @@ -633,183 +632,9 @@ namespace Barotrauma { characterListBox.BarScroll = roundedPos; } - 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; + soundIcon.Visible = !muted && !mutedLocally; + soundIconDisabled.Visible = muted || mutedLocally; + soundIconDisabled.ToolTip = TextManager.Get(mutedLocally ? "MutedLocally" : "MutedGlobally"); } private IEnumerable KillCharacterAnim(GUIComponent component) @@ -953,12 +778,6 @@ 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) @@ -1016,23 +835,19 @@ namespace Barotrauma } } } - - character.SetOrder(order, option, orderGiver, speak: orderGiver != character); - if (IsSinglePlayer) + //only one target (or an order with no particular targets), just show options + else { - 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) + 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) { - GameMain.Client.SendChatMessage(msg); - } - } - DisplayCharacterOrder(character, order); - } + 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); /// /// Create the UI panel that's used to select the target and options for a given order @@ -1330,7 +1145,7 @@ namespace Barotrauma ChatBox.Update(deltaTime); ChatBox.InputBox.Visible = Character.Controlled != null; - if (!DebugConsole.IsOpen && ChatBox.InputBox.Visible) + if (!DebugConsole.IsOpen && ChatBox.InputBox.Visible && GUI.KeyboardDispatcher.Subscriber == null) { if (PlayerInput.KeyHit(InputType.Chat) && !ChatBox.InputBox.Selected) { diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Reactor.cs index 7fa05648b..1fc3955ca 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Reactor.cs @@ -220,7 +220,7 @@ namespace Barotrauma.Items.Components AutoScale = true }; autoTempSlider = new GUIScrollBar(new RectTransform(new Vector2(0.6f, 0.15f), columnRight.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.1f) }, - barSize: 0.55f, style: "OnOffSlider") + barSize: 0.55f, style: "OnOffSlider", isHorizontal: true) { ToolTip = TextManager.Get("ReactorTipAutoTemp"), IsBooleanSwitch = true, @@ -233,10 +233,10 @@ namespace Barotrauma.Items.Components } }; var sliderSprite = autoTempSlider.Frame.Style.Sprites[GUIComponent.ComponentState.None].First(); - autoTempSlider.RectTransform.MaxSize = sliderSprite.Sprite.size.ToPoint(); + autoTempSlider.RectTransform.MaxSize = sliderSprite.Sprite.SourceRect.Size; onOffSwitch = new GUIScrollBar(new RectTransform(new Vector2(0.4f, 0.3f), columnRight.RectTransform, Anchor.TopRight), - barSize: 0.2f, style: "OnOffLever") + barSize: 0.2f, style: "OnOffLever", isHorizontal: false) { IsBooleanSwitch = true, MinValue = 0.25f, @@ -249,7 +249,7 @@ namespace Barotrauma.Items.Components } }; var switchSprite = onOffSwitch.Frame.Style.Sprites[GUIComponent.ComponentState.None].First(); - onOffSwitch.RectTransform.MaxSize = switchSprite.Sprite.size.ToPoint(); + onOffSwitch.RectTransform.MaxSize = switchSprite.Sprite.SourceRect.Size; var lever = onOffSwitch.GetChild(); lever.RectTransform.NonScaledSize = new Point(lever.Rect.Width + 30, lever.Rect.Height); diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs index aaa57c4af..e7e032352 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs @@ -17,6 +17,8 @@ namespace Barotrauma.Items.Components Passive }; + private bool dynamicDockingIndicator = true; + private bool unsentChanges; private float networkUpdateTimer; @@ -653,7 +655,7 @@ namespace Barotrauma.Items.Components Vector2 dockingDir = sourcePortPos - targetPortPos; Vector2 normalizedDockingDir = Vector2.Normalize(dockingDir); - if (!DynamicDockingIndicator) + if (!dynamicDockingIndicator) { if (steering.DockingSource.IsHorizontal) { diff --git a/Barotrauma/BarotraumaClient/Source/Items/Item.cs b/Barotrauma/BarotraumaClient/Source/Items/Item.cs index 0a22f2292..253e69008 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Item.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Item.cs @@ -775,6 +775,37 @@ namespace Barotrauma ic.DrawHUD(spriteBatch, character); } } + } + + List texts = new List(); + public List GetHUDTexts(Character character) + { + texts.Clear(); + foreach (ItemComponent ic in components) + { + if (string.IsNullOrEmpty(ic.DisplayMsg)) continue; + if (!ic.CanBePicked && !ic.CanBeSelected) continue; + if (ic is Holdable holdable && !holdable.CanBeDeattached()) continue; + + Color color = Color.Gray; + bool hasRequiredSkillsAndItems = ic.HasRequiredSkills(character) && ic.HasRequiredItems(character, false); + if (hasRequiredSkillsAndItems) + { + if (ic is Repairable repairable) + { + if (Condition < repairable.ShowRepairUIThreshold) + { + color = Color.Cyan; + } + } + else + { + color = Color.Cyan; + } + } + + texts.Add(new ColoredText(ic.DisplayMsg, color, false)); + } return texts; } diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs index 22ef99f72..065fb65cb 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs @@ -134,6 +134,8 @@ namespace Barotrauma private GUILayoutGroup subPreviewContainer; + private GUILayoutGroup subPreviewContainer; + private GUIButton loadGameButton; public Action StartNewGame; diff --git a/Barotrauma/BarotraumaClient/Source/Screens/GameScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/GameScreen.cs index 6bf9ad2c3..58712b928 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/GameScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/GameScreen.cs @@ -149,8 +149,8 @@ namespace Barotrauma //These will be visible through the LOS effect. //Could be drawn with one Submarine.DrawBack call, but we can avoid sorting by depth by doing it like this. spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, DepthStencilState.None, null, null, cam.Transform); - Submarine.DrawBack(spriteBatch, false, s => s is Structure && s.ResizeVertical && s.ResizeHorizontal); - Submarine.DrawBack(spriteBatch, false, s => s is Structure && !(s.ResizeVertical && s.ResizeHorizontal) && ((Structure)s).Prefab.BackgroundSprite != null); + Submarine.DrawBack(spriteBatch, false, e => e is Structure s && (s.ResizeVertical || s.ResizeHorizontal) && !s.DrawDamageEffect); + Submarine.DrawBack(spriteBatch, false, e => e is Structure s && !(s.ResizeVertical && s.ResizeHorizontal) && s.Prefab.BackgroundSprite != null); spriteBatch.End(); graphics.SetRenderTarget(null); diff --git a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs index 393aa09d9..d538d9850 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs @@ -817,7 +817,7 @@ namespace Barotrauma { if (dummyCharacter != null) RemoveDummyCharacter(); - dummyCharacter = Character.Create(Character.HumanConfigFile, Vector2.Zero, ""); + dummyCharacter = Character.Create(Character.HumanConfigFile, Vector2.Zero, "", hasAi: false); //make space for the entity menu for (int i = 0; i < dummyCharacter.Inventory.SlotPositions.Length; i++) @@ -2282,6 +2282,11 @@ namespace Barotrauma GameMain.LightManager.UpdateLightMap(graphics, spriteBatch, cam); } + foreach (Submarine sub in Submarine.Loaded) + { + sub.UpdateTransform(); + } + spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, null, null, null, diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/IndoorsSteeringManager.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/IndoorsSteeringManager.cs index 43da0bb56..e0708c410 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/IndoorsSteeringManager.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/IndoorsSteeringManager.cs @@ -320,6 +320,8 @@ namespace Barotrauma var door = node.ConnectedDoor; if (door != null) { + if (door.IsOpen) { return true; } + if (door.IsStuck) { return false; } if (door.HasIntegratedButtons) { if (!door.HasRequiredItems(character, false)) @@ -396,7 +398,7 @@ namespace Barotrauma } } - if (door == null) return; + if (door == null) { return; } //toggle the door if it's the previous node and open, or if it's current node and closed if (door.IsOpen != shouldBeOpen) diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjective.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjective.cs index 2cdbef6b8..b9a12922c 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjective.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjective.cs @@ -115,17 +115,20 @@ namespace Barotrauma public virtual void Update(float deltaTime) { - var subObjective = objectiveManager.CurrentObjective?.CurrentSubObjective; if (objectiveManager.CurrentOrder == this) { Priority = AIObjectiveManager.OrderPriority; } - else if (objectiveManager.CurrentObjective == this || subObjective == this) + else if (objectiveManager.WaitTimer <= 0) { - Priority += Devotion * PriorityModifier * deltaTime; + var subObjective = objectiveManager.CurrentObjective?.CurrentSubObjective; + if ((objectiveManager.CurrentObjective == this || subObjective == this)) + { + Priority += Devotion * PriorityModifier * deltaTime; + } + Priority = MathHelper.Clamp(Priority, 0, 100); + subObjectives.ForEach(so => so.Update(deltaTime)); } - Priority = MathHelper.Clamp(Priority, 0, 100); - subObjectives.ForEach(so => so.Update(deltaTime)); } /// diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs index 494e8a9e3..1578f37c0 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs @@ -261,7 +261,7 @@ namespace Barotrauma if (character.CurrentHull == null) { currenthullSafety = 0; - Priority = 5; + Priority = 100; return; } if (character.OxygenAvailable < CharacterHealth.LowOxygenThreshold) { Priority = 100; } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs index 603683343..7a605f1a6 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveIdle.cs @@ -40,6 +40,44 @@ namespace Barotrauma public override bool IsLoop { get => true; set => throw new System.Exception("Trying to set the value for IsLoop from: " + System.Environment.StackTrace); } + private float randomTimer; + private float randomUpdateInterval = 5; + public float Random { get; private set; } + + public void SetRandom() + { + Random = Rand.Range(0.5f, 1.5f); + randomTimer = randomUpdateInterval; + } + + public override float GetPriority() + { + float max = Math.Min(Math.Min(AIObjectiveManager.RunPriority, AIObjectiveManager.OrderPriority) - 1, 100); + float initiative = character.GetSkillLevel("initiative"); + Priority = MathHelper.Lerp(1, max, MathUtils.InverseLerp(100, 0, initiative * Random)); + return Priority; + } + + 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; + + public override bool IsLoop { get => true; set => throw new System.Exception("Trying to set the value for IsLoop from: " + System.Environment.StackTrace); } + // TODO: take the initiative into account public override float GetPriority() => 1; @@ -56,13 +94,6 @@ namespace Barotrauma { character.SelectedConstruction = null; } - - bool currentHullForbidden = IsForbidden(character.CurrentHull); - if (!currentHullForbidden && !character.AnimController.InWater && !character.IsClimbing && HumanAIController.ObjectiveManager.WaitTimer > 0) - { - SteeringManager.Reset(); - return; - } if (!character.IsClimbing) { character.SelectedConstruction = null; @@ -74,7 +105,7 @@ namespace Barotrauma bool currentTargetIsInvalid = currentTarget == null || IsForbidden(currentTarget) || (PathSteering.CurrentPath != null && PathSteering.CurrentPath.Nodes.Any(n => HumanAIController.UnsafeHulls.Contains(n.CurrentHull))); - if (currentTargetIsInvalid || (currentTarget == null && currentHullForbidden)) + if (currentTargetIsInvalid || currentTarget == null && IsForbidden(character.CurrentHull)) { newTargetTimer = 0; standStillTimer = 0; @@ -276,7 +307,7 @@ namespace Barotrauma } } - private bool IsForbidden(Hull hull) + public static bool IsForbidden(Hull hull) { if (hull == null) { return true; } string hullName = hull.RoomName?.ToLowerInvariant(); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveManager.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveManager.cs index 2035ad807..b22b14e76 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveManager.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveManager.cs @@ -19,7 +19,7 @@ namespace Barotrauma private Character character; /// - /// When set above zero, the character will stand still doing nothing until the timer runs out. Only affects idling. + /// When set above zero, the character will stand still doing nothing until the timer runs out. Does not affect orders. /// public float WaitTimer; @@ -31,7 +31,7 @@ namespace Barotrauma public AIObjectiveManager(Character character) { this.character = character; - CreateAutomaticObjectives(); + CreateAutonomousObjectives(); } public void AddObjective(AIObjective objective) @@ -49,7 +49,7 @@ namespace Barotrauma public Dictionary DelayedObjectives { get; private set; } = new Dictionary(); - public void CreateAutomaticObjectives() + public void CreateAutonomousObjectives() { Objectives.Clear(); AddObjective(new AIObjectiveFindSafety(character, this)); @@ -109,6 +109,7 @@ namespace Barotrauma if (previousObjective != CurrentObjective) { CurrentObjective?.OnSelected(); + GetObjective().SetRandom(); } return CurrentObjective; } @@ -157,8 +158,31 @@ namespace Barotrauma public void DoCurrentObjective(float deltaTime) { - if (WaitTimer > 0.0f) { WaitTimer -= deltaTime; } - CurrentObjective?.TryComplete(deltaTime); + if (WaitTimer <= 0) + { + CurrentObjective?.TryComplete(deltaTime); + } + else + { + if (CurrentOrder != null) + { + CurrentOrder.TryComplete(deltaTime); + } + else + { + WaitTimer -= deltaTime; + if (character.AIController is HumanAIController humanAI && humanAI.SteeringManager != null) + { + if (!character.AnimController.InWater && + !character.IsClimbing && + !humanAI.UnsafeHulls.Contains(character.CurrentHull) && + !AIObjectiveIdle.IsForbidden(character.CurrentHull)) + { + humanAI.SteeringManager.Reset(); + } + } + } + } } public void SetOrder(AIObjective objective) @@ -172,7 +196,7 @@ namespace Barotrauma if (CurrentOrder == null) { // Recreate objectives, because some of them may be removed, if impossible to complete (e.g. due to path finding) - CreateAutomaticObjectives(); + CreateAutonomousObjectives(); } } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs index cb69401e1..8935a5168 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs @@ -579,7 +579,7 @@ namespace Barotrauma if (limpAmount > 0.0f) { //make the footpos oscillate when limping - footMid += ((float)Math.Max(Math.Abs(walkPosX) * limpAmount, 0.0f) * 0.3f); + footMid += (Math.Max(Math.Abs(walkPosX) * limpAmount, 0.0f) * Math.Min(Math.Abs(TargetMovement.X), 0.3f)); } movement = overrideTargetMovement == Vector2.Zero ? @@ -788,13 +788,19 @@ namespace Barotrauma //get the upper arm to point downwards var arm = GetLimb(armType); - arm.body.SmoothRotate(MathHelper.Clamp(-arm.body.AngularVelocity, -0.1f, 0.1f), arm.Mass * 10.0f); + if (Math.Abs(arm.body.AngularVelocity) < 10.0f) + { + arm.body.SmoothRotate(MathHelper.Clamp(-arm.body.AngularVelocity, -0.1f, 0.1f), arm.Mass * 10.0f); + } //get the elbow to a neutral rotation - LimbJoint elbow = + if (Math.Abs(hand.body.AngularVelocity) < 10.0f) + { + LimbJoint elbow = GetJointBetweenLimbs(armType, hand.type) ?? GetJointBetweenLimbs(armType, foreArmType); - hand.body.ApplyTorque(-elbow.JointAngle * hand.Mass * 10.0f); + hand.body.ApplyTorque(MathHelper.Clamp(-elbow.JointAngle, -MathHelper.PiOver2, MathHelper.PiOver2) * hand.Mass * 10.0f); + } } } } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs index 3d57328e5..46ff1d502 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/Ragdoll.cs @@ -674,8 +674,6 @@ namespace Barotrauma velocity -= ((Submarine)f2.Body.UserData).Velocity; } - if (character.Submarine == null && f2.Body.UserData is Submarine) velocity -= ((Submarine)f2.Body.UserData).Velocity; - float impact = Vector2.Dot(velocity, -normal); if (f1.Body == Collider.FarseerBody || !Collider.Enabled) { @@ -694,6 +692,11 @@ namespace Barotrauma character.AddDamage(impactPos, new List() { AfflictionPrefab.InternalDamage.Instantiate((impact - ImpactTolerance) * 10.0f) }, 0.0f, true); strongestImpact = Math.Max(strongestImpact, impact - ImpactTolerance); character.ApplyStatusEffects(ActionType.OnImpact, 1.0f); + //briefly disable impact damage + //otherwise the character will take damage multiple times when for example falling, + //because we use the velocity of the collider to determine the impact + //(i.e. the character would take damage until the collider hits the floor and stops) + character.DisableImpactDamageTimer = 0.25f; } } } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/CharacterInfo.cs b/Barotrauma/BarotraumaShared/Source/Characters/CharacterInfo.cs index cb7df70ec..f6f4af9ca 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/CharacterInfo.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/CharacterInfo.cs @@ -729,6 +729,8 @@ namespace Barotrauma partial void LoadAttachmentSprites(); + // TODO: change the formula so that it's not linear and so that it takes into account the usefulness of the skill + // -> give a weight to each skill, because some are much more valuable than others? private int CalculateSalary() { if (Name == null || Job == null) return 0; diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs index be373b5d8..6f3068515 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs @@ -26,6 +26,8 @@ namespace Barotrauma.Items.Components private bool autoOrientGap; private bool isStuck; + public bool IsStuck => isStuck; + private float resetPredictionTimer; private Rectangle doorRect; @@ -227,9 +229,7 @@ namespace Barotrauma.Items.Components { msg = msg ?? (HasIntegratedButtons ? accessDeniedTxt : cannotOpenText); } - if (item.Condition <= RepairThreshold) { return true; } - //this is a bit pointless atm because if canBePicked is false it won't allow you to do Pick() anyway, however it's still good for future-proofing. - return requiredItems.Any() ? base.HasRequiredItems(character, addMessage, msg) : canBePicked; + return isBroken || base.HasRequiredItems(character, addMessage, msg); } public override bool Pick(Character picker) diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs index b36f62573..b24f8bf79 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs @@ -412,7 +412,8 @@ namespace Barotrauma.Items.Components object value = property.GetValue(target); if (value.GetType() == typeof(float)) { - user.UpdateHUDProgressBar(door, door.Item.WorldPosition, (float)value / 100, Color.DarkGray * 0.5f, Color.White); + var progressBar = user.UpdateHUDProgressBar(door, door.Item.WorldPosition, (float)value / 100, Color.DarkGray * 0.5f, Color.White); + if (progressBar != null) { progressBar.Size = new Vector2(60.0f, 20.0f); } } } } diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs index 6aa2c2514..76b490647 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Deconstructor.cs @@ -658,6 +658,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/Sonar.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Sonar.cs index fb62df7af..c18e1ad02 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Sonar.cs @@ -86,17 +86,7 @@ namespace Barotrauma.Items.Components { get { return zoom; } } - - //TODO: remove, only for testing -#if DEBUG - [Serialize(false, false), Editable] - public bool DynamicDockingIndicator - { - get; - set; - } -#endif - + public override bool IsActive { get diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs index 2aafee648..a251165ce 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs @@ -212,6 +212,33 @@ 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/Signal/CustomInterface.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/CustomInterface.cs index 48b98b710..c521952de 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/CustomInterface.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/CustomInterface.cs @@ -125,7 +125,7 @@ namespace Barotrauma.Items.Components for (int i = 0; i < labels.Length; i++) { labels[i] = i < newLabels.Length ? newLabels[i] : customInterfaceElementList[i].Label; - customInterfaceElementList[i].Label = labels[i]; + customInterfaceElementList[i].Label = TextManager.Get(labels[i], returnNull: true) ?? labels[i]; } UpdateLabelsProjSpecific(); } @@ -170,5 +170,12 @@ namespace Barotrauma.Items.Components } } } + + public override XElement Save(XElement parentElement) + { + labels = customInterfaceElementList.Select(ci => ci.Label).ToArray(); + signals = customInterfaceElementList.Select(ci => ci.Signal).ToArray(); + return base.Save(parentElement); + } } } diff --git a/Barotrauma/BarotraumaShared/Source/Items/Item.cs b/Barotrauma/BarotraumaShared/Source/Items/Item.cs index 60941dd53..64344d9b5 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Item.cs @@ -1428,6 +1428,10 @@ namespace Barotrauma { ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime); } + if (!broken) + { + ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime); + } ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime); if (body == null || !body.Enabled || !inWater || ParentInventory != null || Removed) { return; } @@ -1954,29 +1958,6 @@ namespace Barotrauma if (remove) { Spawner?.AddToRemoveQueue(this); } } - List texts = new List(); - public List GetHUDTexts(Character character) - { - texts.Clear(); - foreach (ItemComponent ic in components) - { - if (string.IsNullOrEmpty(ic.DisplayMsg)) continue; - if (!ic.CanBePicked && !ic.CanBeSelected) continue; - if (ic is Holdable holdable && !holdable.CanBeDeattached()) continue; - - Color color = Color.Gray; - bool hasRequiredSkillsAndItems = ic.HasRequiredSkills(character) && ic.HasRequiredItems(character, false); - if (hasRequiredSkillsAndItems) - { - color = Color.Cyan; - } - - texts.Add(new ColoredText(ic.DisplayMsg, color, false)); - } - - if (remove) { Spawner?.AddToRemoveQueue(this); } - } - public bool Combine(Item item) { bool isCombined = false; diff --git a/Barotrauma/BarotraumaShared/Source/Map/Hull.cs b/Barotrauma/BarotraumaShared/Source/Map/Hull.cs index ae59b864c..5e2c1f95f 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Hull.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Hull.cs @@ -474,6 +474,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 diff --git a/Barotrauma/BarotraumaShared/Source/Map/Map/LocationTypeChange.cs b/Barotrauma/BarotraumaShared/Source/Map/Map/LocationTypeChange.cs index 267cf68f8..85f101d09 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Map/LocationTypeChange.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Map/LocationTypeChange.cs @@ -27,7 +27,9 @@ namespace Barotrauma DisallowedAdjacentLocations = element.GetAttributeStringArray("disallowedadjacentlocations", new string[0]).ToList(); RequiredAdjacentLocations = element.GetAttributeStringArray("requiredadjacentlocations", new string[0]).ToList(); - Messages = TextManager.GetAll("LocationChange." + currentType + ".ChangeTo." + ChangeToType); + string messageTag = element.GetAttributeString("messagetag", "LocationChange." + currentType + ".ChangeTo." + ChangeToType); + + Messages = TextManager.GetAll(messageTag); if (Messages == null) { DebugConsole.ThrowError("No messages defined for the location type change " + currentType + " -> " + ChangeToType); diff --git a/Barotrauma/BarotraumaShared/Source/PlayerInput.cs b/Barotrauma/BarotraumaShared/Source/PlayerInput.cs index 8ad826eea..6f0fc8417 100644 --- a/Barotrauma/BarotraumaShared/Source/PlayerInput.cs +++ b/Barotrauma/BarotraumaShared/Source/PlayerInput.cs @@ -88,7 +88,7 @@ namespace Barotrauma public override bool Equals(object obj) { - if (obj is KeyOrMouse keyOrMouse ) + if (obj is KeyOrMouse keyOrMouse) { if (MouseButton.HasValue) { @@ -156,6 +156,26 @@ namespace Barotrauma { get { return GameMain.Config.KeyBind(inputType); } } +#if CLIENT + private KeyOrMouse binding + { + get { return GameMain.Config.KeyBind(inputType); } + } + + public KeyOrMouse State + { + get { return binding; } + } + + public void SetState() + { + hit = binding.IsHit(); + if (hit) hitQueue = true; + + held = binding.IsDown(); + if (held) heldQueue = true; + } +#endif public KeyOrMouse State { diff --git a/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub b/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub index 6ba4eb52d..31768888f 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub and b/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub index de829c19f..dca23e2e5 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub and b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Humpback.sub b/Barotrauma/BarotraumaShared/Submarines/Humpback.sub index 50175a38b..9ea542115 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Humpback.sub and b/Barotrauma/BarotraumaShared/Submarines/Humpback.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Orca.sub b/Barotrauma/BarotraumaShared/Submarines/Orca.sub index f2528e7dd..fc8a21a44 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Orca.sub and b/Barotrauma/BarotraumaShared/Submarines/Orca.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Selkie.sub b/Barotrauma/BarotraumaShared/Submarines/Selkie.sub index 72e8f6ace..59dc7cc11 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Selkie.sub and b/Barotrauma/BarotraumaShared/Submarines/Selkie.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Typhon.sub b/Barotrauma/BarotraumaShared/Submarines/Typhon.sub index b24ff03bd..9f1f5b9da 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Typhon.sub and b/Barotrauma/BarotraumaShared/Submarines/Typhon.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Venture.sub b/Barotrauma/BarotraumaShared/Submarines/Venture.sub index e6df2ee70..f06df8916 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Venture.sub and b/Barotrauma/BarotraumaShared/Submarines/Venture.sub differ