diff --git a/Barotrauma/BarotraumaClient/Source/Camera.cs b/Barotrauma/BarotraumaClient/Source/Camera.cs index 4fa02a0ed..16cd6e371 100644 --- a/Barotrauma/BarotraumaClient/Source/Camera.cs +++ b/Barotrauma/BarotraumaClient/Source/Camera.cs @@ -8,11 +8,14 @@ namespace Barotrauma { public static bool FollowSub = true; - private float defaultZoom = 1.3f; + private float? defaultZoom; public float DefaultZoom { - get { return defaultZoom; } - set { defaultZoom = MathHelper.Clamp(value, 0.5f, 2.0f); } + get { return defaultZoom ?? (GameMain.Config == null || GameMain.Config.EnableMouseLook ? 1.3f : 1.0f); } + set + { + defaultZoom = MathHelper.Clamp(value, 0.5f, 2.0f); + } } private float zoomSmoothness = 8.0f; diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Character.cs b/Barotrauma/BarotraumaClient/Source/Characters/Character.cs index 6823e626c..8a797dfa8 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Character.cs @@ -23,6 +23,8 @@ namespace Barotrauma protected float hudInfoTimer; protected bool hudInfoVisible; + private float pressureParticleTimer; + private float findFocusedTimer; protected float lastRecvPositionUpdateTime; @@ -165,27 +167,38 @@ namespace Barotrauma keys[i].SetState(); } + float targetOffsetAmount = 0.0f; if (moveCam) { if (needsAir && pressureProtection < 80.0f && - (AnimController.CurrentHull == null || AnimController.CurrentHull.LethalPressure > 50.0f)) + (AnimController.CurrentHull == null || AnimController.CurrentHull.LethalPressure > 0.0f)) { float pressure = AnimController.CurrentHull == null ? 100.0f : AnimController.CurrentHull.LethalPressure; + if (pressure > 0.0f) + { + float zoomInEffectStrength = MathHelper.Clamp(pressure / 100.0f, 0.1f, 1.0f); + cam.Zoom = MathHelper.Lerp(cam.Zoom, + cam.DefaultZoom + (Math.Max(pressure, 10) / 150.0f) * Rand.Range(0.9f, 1.1f), + zoomInEffectStrength); - cam.Zoom = MathHelper.Lerp(cam.Zoom, - (pressure / 50.0f) * Rand.Range(1.0f, 1.05f), - (pressure - 50.0f) / 50.0f); + pressureParticleTimer += pressure * deltaTime; + if (pressureParticleTimer > 10.0f) + { + Particle p = GameMain.ParticleManager.CreateParticle("waterblood", WorldPosition + Rand.Vector(5.0f), Rand.Vector(10.0f)); + pressureParticleTimer = 0.0f; + } + } } if (IsHumanoid) { - cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, 250.0f, deltaTime); + cam.OffsetAmount = 250.0f;// MathHelper.Lerp(cam.OffsetAmount, 250.0f, deltaTime); } else { //increased visibility range when controlling large a non-humanoid - cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, MathHelper.Clamp(Mass, 250.0f, 800.0f), deltaTime); + cam.OffsetAmount = MathHelper.Clamp(Mass, 250.0f, 1500.0f); } } @@ -198,43 +211,55 @@ namespace Barotrauma Vector2 mouseSimPos = ConvertUnits.ToSimUnits(cursorPosition); if (GUI.PauseMenuOpen) { + targetOffsetAmount = 0.0f; cam.OffsetAmount = 0.0f; } else if (SelectedConstruction != null && ViewTarget == null && SelectedConstruction.Components.Any(ic => ic?.GuiFrame != null && ic.ShouldDrawHUD(this))) { + targetOffsetAmount = 0.0f; cam.OffsetAmount = 0.0f; cursorPosition = SelectedConstruction.Position + new Vector2(cursorPosition.X % 10.0f, cursorPosition.Y % 10.0f); //apply a little bit of movement to the cursor pos to prevent AFK kicking } + else if (!GameMain.Config.EnableMouseLook) + { + targetOffsetAmount = 0.0f; + cam.OffsetAmount = 0.0f; + } else if (Lights.LightManager.ViewTarget == this && Vector2.DistanceSquared(AnimController.Limbs[0].SimPosition, mouseSimPos) > 1.0f) { if (GUI.PauseMenuOpen || IsUnconscious) { - if (deltaTime > 0.0f) cam.OffsetAmount = 0.0f; + if (deltaTime > 0.0f) + { + targetOffsetAmount = 0.0f; + cam.OffsetAmount = 0.0f; + } } else { Body body = Submarine.CheckVisibility(AnimController.Limbs[0].SimPosition, mouseSimPos); - Structure structure = body == null ? null : body.UserData as Structure; + Structure structure = body?.UserData as Structure; float sightDist = Submarine.LastPickedFraction; if (body?.UserData is Structure && !((Structure)body.UserData).CastShadow) { sightDist = 1.0f; } - cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, Math.Max(250.0f, sightDist * 500.0f), 0.05f); + targetOffsetAmount = Math.Max(250.0f, sightDist * 500.0f); } } + cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, targetOffsetAmount, 0.05f); + if (SelectedConstruction != null && SelectedConstruction.ActiveHUDs.Any(ic => ic.GuiFrame != null && HUD.CloseHUD(ic.GuiFrame.Rect))) { if (GameMain.Client != null) { //emulate a Select input to get the character to deselect the item server-side - //keys[(int)InputType.Select].Hit = true; - keys[(int)InputType.Deselect].Hit = true; + keys[(int)InputType.Select].Hit = true; } //reset focus to prevent us from accidentally interacting with another entity focusedItem = null; diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs index 8f9c23d0a..cee060094 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterNetworking.cs @@ -48,12 +48,10 @@ namespace Barotrauma if (IsKeyDown(InputType.Run)) newInput |= InputNetFlags.Run; if (IsKeyDown(InputType.Crouch)) newInput |= InputNetFlags.Crouch; if (IsKeyHit(InputType.Select)) newInput |= InputNetFlags.Select; //TODO: clean up the way this input is registered - if (IsKeyHit(InputType.Deselect)) newInput |= InputNetFlags.Deselect; if (IsKeyHit(InputType.Health)) newInput |= InputNetFlags.Health; if (IsKeyHit(InputType.Grab)) newInput |= InputNetFlags.Grab; if (IsKeyDown(InputType.Use)) newInput |= InputNetFlags.Use; if (IsKeyDown(InputType.Aim)) newInput |= InputNetFlags.Aim; - if (IsKeyDown(InputType.Shoot)) newInput |= InputNetFlags.Shoot; if (IsKeyDown(InputType.Attack)) newInput |= InputNetFlags.Attack; if (IsKeyDown(InputType.Ragdoll)) newInput |= InputNetFlags.Ragdoll; @@ -127,7 +125,6 @@ namespace Barotrauma msg.WriteRangedInteger(0, (int)InputNetFlags.MaxVal, (int)memInput[i].states); msg.Write(memInput[i].intAim); if (memInput[i].states.HasFlag(InputNetFlags.Select) || - memInput[i].states.HasFlag(InputNetFlags.Deselect) || memInput[i].states.HasFlag(InputNetFlags.Use) || memInput[i].states.HasFlag(InputNetFlags.Health) || memInput[i].states.HasFlag(InputNetFlags.Grab)) diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUIButton.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUIButton.cs index 9dc8a8076..7917d904f 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUIButton.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUIButton.cs @@ -20,6 +20,8 @@ namespace Barotrauma public OnButtonDownHandler OnButtonDown; public bool CanBeSelected = true; + + private Color? defaultTextColor; public override bool Enabled { @@ -30,7 +32,7 @@ namespace Barotrauma set { - if (value == enabled) return; + if (value == enabled) { return; } enabled = value; if (color.A == 0) { diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUIImage.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUIImage.cs index 488541683..fcbafb160 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUIImage.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUIImage.cs @@ -70,6 +70,7 @@ namespace Barotrauma private GUIImage(RectTransform rectT, Sprite sprite, Rectangle? sourceRect, bool scaleToFit, string style) : base(style, rectT) { this.scaleToFit = scaleToFit; + sprite?.EnsureLazyLoaded(); Sprite = sprite; if (sourceRect.HasValue) { diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs index 292f85b37..d8ac5bc80 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs @@ -624,9 +624,10 @@ namespace Barotrauma.Tutorials private Character CrewMemberWithJob(string job) { + job = job.ToLowerInvariant(); for (int i = 0; i < crew.Count; i++) { - if (crew[i].Info.Job.Name == job) return crew[i]; + if (crew[i].Info.Job.Prefab.Identifier.ToLowerInvariant() == job) return crew[i]; } return null; diff --git a/Barotrauma/BarotraumaClient/Source/GameSettings.cs b/Barotrauma/BarotraumaClient/Source/GameSettings.cs index 96d604bff..0b3746ba4 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSettings.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSettings.cs @@ -94,7 +94,7 @@ namespace Barotrauma foreach (ContentPackage contentPackage in ContentPackage.List) { - var tickBox = new GUITickBox(new RectTransform(new Vector2(0.05f, 0.05f), contentPackageList.Content.RectTransform, minSize: new Point(32, 32)), contentPackage.Name) + var tickBox = new GUITickBox(new RectTransform(new Point(32, 32), contentPackageList.Content.RectTransform), contentPackage.Name) { UserData = contentPackage, OnSelected = SelectContentPackage, @@ -167,11 +167,11 @@ namespace Barotrauma /// Graphics tab -------------------------------------------------------------- - var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Graphics].RectTransform, Anchor.CenterLeft) - { RelativeOffset = new Vector2(0.02f, 0.0f) }) + var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Graphics].RectTransform, Anchor.TopLeft) + { RelativeOffset = new Vector2(0.025f, 0.02f) }) { RelativeSpacing = 0.01f }; - var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Graphics].RectTransform, Anchor.CenterRight) - { RelativeOffset = new Vector2(0.02f, 0.0f) }) + var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Graphics].RectTransform, Anchor.TopRight) + { RelativeOffset = new Vector2(0.025f, 0.02f) }) { RelativeSpacing = 0.01f }; var supportedDisplayModes = new List(); @@ -368,12 +368,12 @@ namespace Barotrauma /// Audio tab ---------------------------------------------------------------- - var audioSliders = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.4f), tabs[(int)Tab.Audio].RectTransform, Anchor.TopCenter) + var audioSliders = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), tabs[(int)Tab.Audio].RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.02f) }) { RelativeSpacing = 0.01f }; - GUITextBlock soundVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), audioSliders.RectTransform), TextManager.Get("SoundVolume")); - GUIScrollBar soundScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.1f), audioSliders.RectTransform), + GUITextBlock soundVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), TextManager.Get("SoundVolume")); + GUIScrollBar soundScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), barSize: 0.05f) { UserData = soundVolumeText, @@ -388,8 +388,8 @@ namespace Barotrauma }; soundScrollBar.OnMoved(soundScrollBar, soundScrollBar.BarScroll); - GUITextBlock musicVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), audioSliders.RectTransform), TextManager.Get("MusicVolume")); - GUIScrollBar musicScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.1f), audioSliders.RectTransform), + GUITextBlock musicVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), TextManager.Get("MusicVolume")); + GUIScrollBar musicScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), barSize: 0.05f) { UserData = musicVolumeText, @@ -404,8 +404,8 @@ namespace Barotrauma }; musicScrollBar.OnMoved(musicScrollBar, musicScrollBar.BarScroll); - GUITextBlock voiceChatVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), audioSliders.RectTransform), TextManager.Get("VoiceChatVolume")); - GUIScrollBar voiceChatScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.1f), audioSliders.RectTransform), + GUITextBlock voiceChatVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), TextManager.Get("VoiceChatVolume")); + GUIScrollBar voiceChatScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), barSize: 0.05f) { UserData = voiceChatVolumeText, @@ -426,11 +426,11 @@ namespace Barotrauma muteOnFocusLostBox.OnSelected = (tickBox) => { MuteOnFocusLost = tickBox.Selected; - + UnsavedSettings = true; return true; }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), audioSliders.RectTransform), TextManager.Get("VoiceChat")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), TextManager.Get("VoiceChat")); IList deviceNames = Alc.GetString((IntPtr)null, AlcGetStringList.CaptureDeviceSpecifier); foreach (string name in deviceNames) @@ -440,7 +440,7 @@ namespace Barotrauma if (string.IsNullOrWhiteSpace(VoiceCaptureDevice)) VoiceCaptureDevice = deviceNames[0]; #if (!OSX) - var deviceList = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.1f), audioSliders.RectTransform), VoiceCaptureDevice, deviceNames.Count); + var deviceList = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), VoiceCaptureDevice, deviceNames.Count); foreach (string name in deviceNames) { deviceList.AddItem(name, name); @@ -454,13 +454,13 @@ namespace Barotrauma return true; }; #else - var suavemente = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), audioSliders.RectTransform), TextManager.Get("CurrentDevice") + ": " + VoiceCaptureDevice) + var suavemente = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), TextManager.Get("CurrentDevice") + ": " + VoiceCaptureDevice) { ToolTip = TextManager.Get("CurrentDeviceToolTip.OSX"), TextAlignment = Alignment.CenterX }; - new GUIButton(new RectTransform(new Vector2(1.0f, 0.25f), audioSliders.RectTransform), TextManager.Get("RefreshDefaultDevice")) + new GUIButton(new RectTransform(new Vector2(1.0f, 0.15f), audioSliders.RectTransform), TextManager.Get("RefreshDefaultDevice")) { ToolTip = TextManager.Get("RefreshDefaultDeviceToolTip"), OnClicked = (bt, userdata) => @@ -476,16 +476,13 @@ namespace Barotrauma } }; #endif - var radioButtonFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), audioSliders.RectTransform)) - { - RelativeSpacing = 0.01f - }; + //var radioButtonFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.12f), audioSliders.RectTransform)); GUIRadioButtonGroup voiceMode = new GUIRadioButtonGroup(); for (int i = 0; i < 3; i++) { string langStr = "VoiceMode." + ((VoiceMode)i).ToString(); - var tick = new GUITickBox(new RectTransform(new Point(32, 32), radioButtonFrame.RectTransform), TextManager.Get(langStr)) + var tick = new GUITickBox(new RectTransform(new Point(32, 32), audioSliders.RectTransform), TextManager.Get(langStr)) { ToolTip = TextManager.Get(langStr + "ToolTip") }; @@ -493,8 +490,8 @@ namespace Barotrauma voiceMode.AddRadioButton((VoiceMode)i, tick); } - var micVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), audioSliders.RectTransform), TextManager.Get("MicrophoneVolume")); - var micVolumeSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.1f), audioSliders.RectTransform), + var micVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), TextManager.Get("MicrophoneVolume")); + var micVolumeSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), barSize: 0.05f) { UserData = micVolumeText, @@ -511,9 +508,12 @@ namespace Barotrauma }; micVolumeSlider.OnMoved(micVolumeSlider, micVolumeSlider.BarScroll); - var voiceInputContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), audioSliders.RectTransform, Anchor.BottomCenter)); - new GUITextBlock(new RectTransform(new Vector2(0.6f, 0.5f), voiceInputContainer.RectTransform), TextManager.Get("InputType.Voice") + ": "); - var voiceKeyBox = new GUITextBox(new RectTransform(new Vector2(0.4f, 0.5f), voiceInputContainer.RectTransform, Anchor.TopRight), + + var extraVoiceSettingsContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), audioSliders.RectTransform, Anchor.BottomCenter), style: null); + + var voiceInputContainer = new GUILayoutGroup(new RectTransform(Vector2.One, extraVoiceSettingsContainer.RectTransform, Anchor.BottomCenter)); + new GUITextBlock(new RectTransform(new Vector2(0.6f, 0.25f), voiceInputContainer.RectTransform), TextManager.Get("InputType.Voice") + ": "); + var voiceKeyBox = new GUITextBox(new RectTransform(new Vector2(0.4f, 0.25f), voiceInputContainer.RectTransform, Anchor.TopRight), text: keyMapping[(int)InputType.Voice].ToString()) { UserData = InputType.Voice @@ -521,22 +521,22 @@ namespace Barotrauma voiceKeyBox.OnSelected += KeyBoxSelected; voiceKeyBox.SelectedColor = Color.Gold * 0.3f; - var voiceActivityGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), audioSliders.RectTransform)); - GUITextBlock noiseGateText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), voiceActivityGroup.RectTransform), TextManager.Get("NoiseGateThreshold")) + var voiceActivityGroup = new GUILayoutGroup(new RectTransform(Vector2.One, extraVoiceSettingsContainer.RectTransform)); + GUITextBlock noiseGateText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), voiceActivityGroup.RectTransform), TextManager.Get("NoiseGateThreshold")) { TextGetter = () => { return TextManager.Get("NoiseGateThreshold") + " " + ((int)NoiseGateThreshold).ToString() + " dB"; } }; - var dbMeter = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.5f), voiceActivityGroup.RectTransform), 0.0f, Color.Lime); + var dbMeter = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.25f), voiceActivityGroup.RectTransform), 0.0f, Color.Lime); dbMeter.ProgressGetter = () => { if (VoipCapture.Instance == null) return 0.0f; dbMeter.Color = VoipCapture.Instance.LastdB > NoiseGateThreshold ? Color.Lime : Color.Orange; //TODO: i'm a filthy hack return ((float)VoipCapture.Instance.LastdB + 100.0f) / 100.0f; }; - var noiseGateSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 1.0f), dbMeter.RectTransform, Anchor.Center), color: Color.White, barSize: 0.03f); + var noiseGateSlider = new GUIScrollBar(new RectTransform(Vector2.One, dbMeter.RectTransform, Anchor.Center), color: Color.White, barSize: 0.03f); noiseGateSlider.Frame.Visible = false; noiseGateSlider.Step = 0.01f; noiseGateSlider.Range = new Vector2(-100.0f, 0.0f); @@ -592,8 +592,41 @@ namespace Barotrauma voiceMode.Selected = VoiceSetting; /// Controls tab ------------------------------------------------------------- - var controlsLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), tabs[(int)Tab.Controls].RectTransform, Anchor.Center)) - { RelativeSpacing = 0.01f }; + var controlsLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), tabs[(int)Tab.Controls].RectTransform, Anchor.TopCenter) + { RelativeOffset = new Vector2(0.0f, 0.02f) }) + { RelativeSpacing = 0.01f }; + + GUITextBlock aimAssistText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), controlsLayoutGroup.RectTransform), TextManager.Get("AimAssist")) + { + ToolTip = TextManager.Get("AimAssistToolTip") + }; + GUIScrollBar aimAssistSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), controlsLayoutGroup.RectTransform), + barSize: 0.05f) + { + UserData = aimAssistText, + BarScroll = MathUtils.InverseLerp(0.0f, 5.0f, AimAssistAmount), + ToolTip = TextManager.Get("AimAssistToolTip"), + OnMoved = (scrollBar, scroll) => + { + ChangeSliderText(scrollBar, scroll); + AimAssistAmount = MathHelper.Lerp(0.0f, 5.0f, scroll); + return true; + }, + Step = 0.1f + }; + aimAssistSlider.OnMoved(aimAssistSlider, aimAssistSlider.BarScroll); + + new GUITickBox(new RectTransform(new Point(32, 32), controlsLayoutGroup.RectTransform), TextManager.Get("EnableMouseLook")) + { + ToolTip = TextManager.Get("EnableMouseLookToolTip"), + Selected = EnableMouseLook, + OnSelected = (tickBox) => + { + EnableMouseLook = tickBox.Selected; + UnsavedSettings = true; + return true; + } + }; var inputFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.8f), controlsLayoutGroup.RectTransform)) { Stretch = true }; @@ -601,7 +634,7 @@ namespace Barotrauma var inputNames = Enum.GetValues(typeof(InputType)); for (int i = 0; i < inputNames.Length; i++) { - var inputContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.06f), inputFrame.RectTransform)) { Stretch = true, IsHorizontal = true, RelativeSpacing = 0.05f }; + var inputContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.06f), inputFrame.RectTransform)) { Stretch = true, IsHorizontal = true, RelativeSpacing = 0.05f, Color = new Color(12, 14, 15, 215) }; new GUITextBlock(new RectTransform(new Vector2(0.3f, 1.0f), inputContainer.RectTransform, Anchor.TopLeft) { MinSize = new Point(150, 0) }, TextManager.Get("InputType." + ((InputType)i)) + ": ", font: GUI.SmallFont) { ForceUpperCase = true }; var keyBox = new GUITextBox(new RectTransform(new Vector2(0.7f, 1.0f), inputContainer.RectTransform), @@ -611,6 +644,9 @@ namespace Barotrauma }; keyBox.OnSelected += KeyBoxSelected; keyBox.SelectedColor = Color.Gold * 0.3f; + + //spacing + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), inputFrame.RectTransform), style: null); } GUITextBlock aimAssistText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), controlsLayoutGroup.RectTransform), TextManager.Get("AimAssist")); GUIScrollBar aimAssistSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), controlsLayoutGroup.RectTransform), @@ -631,6 +667,9 @@ namespace Barotrauma //spacing new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), generalLayoutGroup.RectTransform), style: null); + //spacing + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), generalLayoutGroup.RectTransform), style: null); + new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), buttonArea.RectTransform, Anchor.BottomLeft), TextManager.Get("Cancel"), style: "GUIButtonLarge") { diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Fabricator.cs index bca922a12..ec569f3ca 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Fabricator.cs @@ -17,6 +17,8 @@ namespace Barotrauma.Items.Components private GUIButton activateButton; + private GUITextBox itemFilterBox; + private GUIComponent inputInventoryHolder, outputInventoryHolder; private GUICustomComponent inputInventoryOverlay, outputInventoryOverlay; @@ -28,12 +30,25 @@ namespace Barotrauma.Items.Components partial void InitProjSpecific() { - var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter) + var paddedFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), GuiFrame.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter) { Stretch = true, RelativeSpacing = 0.02f }; + var filterArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.06f), paddedFrame.RectTransform), isHorizontal: true) + { + Stretch = true, + UserData = "filterarea" + }; + new GUITextBlock(new RectTransform(new Vector2(0.25f, 1.0f), filterArea.RectTransform), TextManager.Get("FilterMapEntities"), font: GUI.Font); + itemFilterBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1.0f), filterArea.RectTransform), font: GUI.Font); + itemFilterBox.OnTextChanged += (textBox, text) => { FilterEntities(text); return true; }; + var clearButton = new GUIButton(new RectTransform(new Vector2(0.1f, 1.0f), filterArea.RectTransform), "x") + { + OnClicked = (btn, userdata) => { ClearFilter(); itemFilterBox.Flash(Color.White); return true; } + }; + itemList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.5f), paddedFrame.RectTransform)) { OnSelected = (GUIComponent component, object userdata) => @@ -50,7 +65,7 @@ namespace Barotrauma.Items.Components CanBeFocused = false }; - var outputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.3f), paddedFrame.RectTransform), isHorizontal: true); + var outputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.25f), paddedFrame.RectTransform), isHorizontal: true); selectedItemFrame = new GUIFrame(new RectTransform(new Vector2(0.75f, 1.0f), outputArea.RectTransform), style: "InnerFrame"); outputInventoryHolder = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), outputArea.RectTransform), style: null); @@ -61,7 +76,7 @@ namespace Barotrauma.Items.Components foreach (FabricationRecipe fi in fabricationRecipes) { - GUIFrame frame = new GUIFrame(new RectTransform(new Point(itemList.Rect.Width, 50), itemList.Content.RectTransform), style: null) + GUIFrame frame = new GUIFrame(new RectTransform(new Point(itemList.Rect.Width, 30), itemList.Content.RectTransform), style: null) { UserData = fi, HoverColor = Color.Gold * 0.2f, @@ -78,7 +93,7 @@ namespace Barotrauma.Items.Components var itemIcon = fi.TargetItem.InventoryIcon ?? fi.TargetItem.sprite; if (itemIcon != null) { - GUIImage img = new GUIImage(new RectTransform(new Point(40, 40), frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(3, 0) }, + GUIImage img = new GUIImage(new RectTransform(new Point(30, 30), frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(3, 0) }, itemIcon, scaleToFit: true) { Color = fi.TargetItem.InventoryIconColor, @@ -88,7 +103,7 @@ namespace Barotrauma.Items.Components } activateButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.07f), paddedFrame.RectTransform), - TextManager.Get("FabricatorCreate")) + TextManager.Get("FabricatorCreate"), style: "GUIButtonLarge") { OnClicked = StartButtonClicked, UserData = selectedItem, @@ -257,6 +272,44 @@ namespace Barotrauma.Items.Components } } + private bool FilterEntities(string filter) + { + if (string.IsNullOrWhiteSpace(filter)) + { + itemList.Content.Children.ForEach(c => c.Visible = true); + return true; + } + + filter = filter.ToLower(); + foreach (GUIComponent child in itemList.Content.Children) + { + FabricationRecipe recipe = child.UserData as FabricationRecipe; + if (recipe?.DisplayName == null) { continue; } + child.Visible = recipe.DisplayName.ToLower().Contains(filter); + } + itemList.UpdateScrollBarSize(); + itemList.BarScroll = 0.0f; + + float degreeOfSuccess = user == null ? 0.0f : DegreeOfSuccess(user, selectedItem.RequiredSkills); + if (degreeOfSuccess > 0.5f) { degreeOfSuccess = 1.0f; } + + float requiredTime = user == null ? selectedItem.RequiredTime : GetRequiredTime(selectedItem, user); + string requiredTimeText = TextManager.Get("FabricatorRequiredTime") + ": " + ToolBox.SecondsToReadableTime(requiredTime); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), + requiredTimeText, textColor: ToolBox.GradientLerp(degreeOfSuccess, Color.Red, Color.Yellow, Color.LightGreen), font: GUI.SmallFont); + + return true; + } + + public bool ClearFilter() + { + FilterEntities(""); + itemList.UpdateScrollBarSize(); + itemList.BarScroll = 0.0f; + itemFilterBox.Text = ""; + return true; + } + private bool SelectItem(Character user, FabricationRecipe selectedItem) { selectedItemFrame.ClearChildren(); @@ -318,29 +371,7 @@ namespace Barotrauma.Items.Components return true; } - Rectangle slotRect = inputContainer.Inventory.slots[slotIndex].Rect; - - itemIcon.Draw( - spriteBatch, - slotRect.Center.ToVector2(), - color: requiredItem.ItemPrefab.InventoryIconColor * 0.3f, - scale: Math.Min(slotRect.Width / itemIcon.size.X, slotRect.Height / itemIcon.size.Y)); - - if (slotRect.Contains(PlayerInput.MousePosition)) - { - string toolTipText = requiredItem.ItemPrefab.Name; - if (!string.IsNullOrEmpty(requiredItem.ItemPrefab.Description)) - { - toolTipText += '\n' + requiredItem.ItemPrefab.Description; - } - tooltip = new Pair(slotRect, toolTipText); - } - - slotIndex++; - } - } - } - private void DrawOutputOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent) + private bool StartButtonClicked(GUIButton button, object obj) { if (selectedItem == null) { return false; } if (!outputContainer.Inventory.IsEmpty()) @@ -353,19 +384,14 @@ namespace Barotrauma.Items.Components { StartFabricating(selectedItem, Character.Controlled); } - - if (tooltip != null) + else { - GUIComponent.DrawToolTip(spriteBatch, tooltip.Second, tooltip.First); - tooltip = null; + CancelFabricating(Character.Controlled); } - } if (GameMain.Client != null) { - FabricationRecipe recipe = child.UserData as FabricationRecipe; - if (recipe?.DisplayName == null) { continue; } - child.Visible = recipe.DisplayName.ToLower().Contains(filter); + item.CreateClientEvent(this); } itemList.UpdateScrollBarSize(); itemList.BarScroll = 0.0f; @@ -378,6 +404,9 @@ namespace Barotrauma.Items.Components return true; } + return true; + } + public override void UpdateHUD(Character character, float deltaTime, Camera cam) { activateButton.Enabled = false; diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs index 53df689c9..dc51312ea 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs @@ -425,7 +425,7 @@ namespace Barotrauma.Items.Components { if (steerArea.Rect.Contains(PlayerInput.MousePosition)) { - if (!PlayerInput.KeyDown(InputType.Deselect) && !PlayerInput.KeyHit(InputType.Deselect)) + if (!PlayerInput.KeyDown(InputType.Select) && !PlayerInput.KeyHit(InputType.Select)) { Character.DisableControls = true; } diff --git a/Barotrauma/BarotraumaClient/Source/Items/Item.cs b/Barotrauma/BarotraumaClient/Source/Items/Item.cs index 574b97e2e..ad33c471c 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Item.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Item.cs @@ -607,6 +607,9 @@ namespace Barotrauma if (GameMain.GameSession?.CrewManager != null) { disallowedAreas.Add(GameMain.GameSession.CrewManager.GetCharacterListArea()); + disallowedAreas.Add(new Rectangle( + HUDLayoutSettings.ChatBoxArea.X - 50, HUDLayoutSettings.ChatBoxArea.Y, + HUDLayoutSettings.ChatBoxArea.Width + 50, HUDLayoutSettings.ChatBoxArea.Height)); } GUI.PreventElementOverlap(elementsToMove, disallowedAreas, diff --git a/Barotrauma/BarotraumaClient/Source/Map/Levels/LevelObjects/LevelObject.cs b/Barotrauma/BarotraumaClient/Source/Map/Levels/LevelObjects/LevelObject.cs index aca975434..181e555c8 100644 --- a/Barotrauma/BarotraumaClient/Source/Map/Levels/LevelObjects/LevelObject.cs +++ b/Barotrauma/BarotraumaClient/Source/Map/Levels/LevelObjects/LevelObject.cs @@ -76,6 +76,10 @@ namespace Barotrauma partial void InitProjSpecific() { + Prefab.Sprite?.EnsureLazyLoaded(); + Prefab.SpecularSprite?.EnsureLazyLoaded(); + Prefab.DeformableSprite?.EnsureLazyLoaded(); + CurrentSwingAmount = Prefab.SwingAmountRad; CurrentScaleOscillation = Prefab.ScaleOscillation; diff --git a/Barotrauma/BarotraumaClient/Source/Map/Lights/LightManager.cs b/Barotrauma/BarotraumaClient/Source/Map/Lights/LightManager.cs index ca4b9c13f..a1fb2e137 100644 --- a/Barotrauma/BarotraumaClient/Source/Map/Lights/LightManager.cs +++ b/Barotrauma/BarotraumaClient/Source/Map/Lights/LightManager.cs @@ -78,9 +78,8 @@ namespace Barotrauma.Lights AmbientLight = new Color(20, 20, 20, 255); - visionCircle = Sprite.LoadTexture("Content/Lights/visioncircle.png"); - - highlightRaster = Sprite.LoadTexture("Content/UI/HighlightRaster.png"); + visionCircle = Sprite.LoadTexture("Content/Lights/visioncircle.png", preMultiplyAlpha: false); + highlightRaster = Sprite.LoadTexture("Content/UI/HighlightRaster.png", preMultiplyAlpha: false); CreateRenderTargets(graphics); GameMain.Instance.OnResolutionChanged += () => @@ -292,6 +291,11 @@ namespace Barotrauma.Lights spriteBatch.Draw(HighlightMap, Vector2.Zero, Color.White); spriteBatch.End(); } + GameMain.ParticleManager.Draw(spriteBatch, true, null, Particles.ParticleBlendState.Additive); + spriteBatch.End(); + + //draw a black rectangle on hulls to hide background lights behind subs + //--------------------------------------------------------------------------------------------------- //draw characters to obstruct the highlighted items/characters and light sprites //--------------------------------------------------------------------------------------------------- diff --git a/Barotrauma/BarotraumaClient/Source/Map/Lights/LightSource.cs b/Barotrauma/BarotraumaClient/Source/Map/Lights/LightSource.cs index 9ff808757..946001c44 100644 --- a/Barotrauma/BarotraumaClient/Source/Map/Lights/LightSource.cs +++ b/Barotrauma/BarotraumaClient/Source/Map/Lights/LightSource.cs @@ -91,7 +91,7 @@ namespace Barotrauma.Lights } break; case "lighttexture": - OverrideLightTexture = new Sprite(subElement); + OverrideLightTexture = new Sprite(subElement, preMultiplyAlpha: false); break; } } @@ -211,7 +211,7 @@ namespace Barotrauma.Lights { if (lightTexture == null) { - lightTexture = TextureLoader.FromFile("Content/Lights/pointlight_bright.png"); + lightTexture = TextureLoader.FromFile("Content/Lights/pointlight_bright.png", preMultiplyAlpha: false); } return lightTexture; diff --git a/Barotrauma/BarotraumaClient/Source/Screens/GameScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/GameScreen.cs index f14fa62fd..6d1e9ba04 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/GameScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/GameScreen.cs @@ -52,7 +52,7 @@ namespace Barotrauma damageEffect.Parameters["aMultiplier"].SetValue(50.0f); damageEffect.Parameters["cMultiplier"].SetValue(200.0f); - distortTexture = TextureLoader.FromFile("Content/Effects/distortnormals.png"); + distortTexture = TextureLoader.FromFile("Content/Effects/distortnormals.png", preMultiplyAlpha: false); postProcessEffect.Parameters["xDistortTexture"].SetValue(distortTexture); } diff --git a/Barotrauma/BarotraumaClient/Source/Screens/LevelEditorScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/LevelEditorScreen.cs index 792ba1d17..ba8a40c79 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/LevelEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/LevelEditorScreen.cs @@ -172,6 +172,11 @@ namespace Barotrauma { base.Select(); + foreach (LevelObjectPrefab levelObjPrefab in LevelObjectPrefab.List) + { + levelObjPrefab.Sprite?.EnsureLazyLoaded(); + } + pointerLightSource = new LightSource(Vector2.Zero, 1000.0f, Color.White, submarine: null); GameMain.LightManager.AddLight(pointerLightSource); topPanel.ClearChildren(); diff --git a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs index d08ca487d..b2657292a 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs @@ -219,9 +219,9 @@ namespace Barotrauma //spacing new GUIFrame(new RectTransform(new Vector2(0.01f, 0.0f), optionHolder.RectTransform), style: null); - var optionButtons = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 1.0f), parent: optionHolder.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.15f) }); + var optionButtons = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 1.0f), parent: optionHolder.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.05f) }); - var optionList = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.15f), parent: optionButtons.RectTransform)) + var optionList = new GUILayoutGroup(new RectTransform(new Vector2(0.8f, 0.3f), parent: optionButtons.RectTransform)) { Stretch = false, RelativeSpacing = 0.035f @@ -688,7 +688,7 @@ namespace Barotrauma if (backgroundSprite == null) { - backgroundSprite = (LocationType.List.Where(l => l.UseInMainMenu).GetRandom()).GetPortrait(0); + backgroundSprite = (LocationType.List.Where(l => l.UseInMainMenu).GetRandom())?.GetPortrait(0); } if (backgroundSprite != null) diff --git a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs index 43959fdad..dff6f1674 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs @@ -22,7 +22,7 @@ namespace Barotrauma "CrewExperienceHigh" }; - private readonly Point defaultPreviewImageSize = new Point(1200, 600); + private readonly Point defaultPreviewImageSize = new Point(512, 368); private Camera cam; @@ -65,6 +65,9 @@ namespace Barotrauma private readonly string containerDeleteTag = "containerdelete"; + private Color primaryColor = new Color(12, 14, 15, 190); + private Color secondaryColor = new Color(12, 14, 15, 215); + public override Camera Cam { get { return cam; } @@ -189,16 +192,17 @@ namespace Barotrauma return true; }; - LeftPanel = new GUIFrame(new RectTransform(new Vector2(0.08f, 1.0f), GUI.Canvas) { MinSize = new Point(170, 0) }, "GUIFrameLeft"); - GUILayoutGroup paddedLeftPanel = new GUILayoutGroup(new RectTransform( - new Point((int)(LeftPanel.Rect.Width * 0.8f), (int)(GameMain.GraphicsHeight - TopPanel.Rect.Height * 0.95f)), - LeftPanel.RectTransform, Anchor.Center) - { AbsoluteOffset = new Point(0, TopPanel.Rect.Height) }) + LeftPanel = new GUIFrame(new RectTransform(new Vector2(0.08f, 1.0f), GUI.Canvas) { MinSize = new Point(170, 0) }, style: null) { Color = primaryColor }; + + GUILayoutGroup paddedLeftPanel = new GUILayoutGroup(new RectTransform(new Point((int)(LeftPanel.Rect.Width), (int)(GameMain.GraphicsHeight - TopPanel.Rect.Height * 0.95f)), + LeftPanel.RectTransform, Anchor.Center)) { - RelativeSpacing = 0.01f, Stretch = true }; + //empty guiframe as a separator + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), paddedLeftPanel.RectTransform) { AbsoluteOffset = new Point(0, TopPanel.Rect.Height) }, style: null); + GUITextBlock itemCount = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedLeftPanel.RectTransform), "ItemCount") { TextGetter = GetItemCount @@ -240,10 +244,9 @@ namespace Barotrauma //Entity menu //------------------------------------------------ - EntityMenu = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth - LeftPanel.Rect.Width + 20, (int)(300 * GUI.Scale)), GUI.Canvas, Anchor.BottomRight), - style: "GUIFrameBottom"); + EntityMenu = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth - LeftPanel.Rect.Width, (int)(359 * GUI.Scale)), GUI.Canvas, Anchor.BottomRight), style: null) { Color = primaryColor }; - toggleEntityMenuButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.1f), EntityMenu.RectTransform, Anchor.TopCenter, Pivot.BottomCenter) { RelativeOffset = new Vector2(0.0f, -0.12f) }, + toggleEntityMenuButton = new GUIButton(new RectTransform(new Vector2(0.15f, 0.1f), EntityMenu.RectTransform, Anchor.TopCenter, Pivot.BottomCenter) { RelativeOffset = new Vector2(0.0f, -0.05f) }, style: "GUIButtonVerticalArrow") { OnClicked = (btn, userdata) => @@ -259,7 +262,25 @@ namespace Barotrauma } }; - var tabButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.1f), EntityMenu.RectTransform, Anchor.TopRight, Pivot.BottomRight), + var paddedTab = new GUIFrame(new RectTransform(new Vector2(1.0f, 1.0f), EntityMenu.RectTransform, Anchor.Center), style: null); + + var filterArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), paddedTab.RectTransform), isHorizontal: true) + { + Color = secondaryColor, + Stretch = true, + UserData = "filterarea" + }; + new GUITextBlock(new RectTransform(new Vector2(0.05f, 1.0f), filterArea.RectTransform), TextManager.Get("FilterMapEntities"), font: GUI.Font); + entityFilterBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1.0f), filterArea.RectTransform), font: GUI.Font); + entityFilterBox.OnTextChanged += (textBox, text) => { FilterEntities(text); return true; }; + var clearButton = new GUIButton(new RectTransform(new Vector2(0.02f, 1.0f), filterArea.RectTransform), "x") + { + OnClicked = (btn, userdata) => { ClearFilter(); entityFilterBox.Flash(Color.White); return true; } + }; + + var entityListHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.85f), paddedTab.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, 0.05f) }); + + var tabButtonHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.1f), entityListHolder.RectTransform, Anchor.TopRight, Pivot.BottomRight), isHorizontal: true) { RelativeSpacing = 0.01f, @@ -280,21 +301,7 @@ namespace Barotrauma }); } - var paddedTab = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.8f), EntityMenu.RectTransform, Anchor.Center), style: null); - var filterArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), paddedTab.RectTransform), isHorizontal: true) - { - AbsoluteSpacing = 5, - Stretch = true, - UserData = "filterarea" - }; - new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), filterArea.RectTransform), TextManager.Get("FilterMapEntities"), font: GUI.SmallFont); - entityFilterBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1.0f), filterArea.RectTransform), font: GUI.SmallFont); - entityFilterBox.OnTextChanged += (textBox, text) => { FilterEntities(text); return true; }; - var clearButton = new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), filterArea.RectTransform), "x") - { - OnClicked = (btn, userdata) => { ClearFilter(); entityFilterBox.Flash(Color.White); return true; } - }; - entityList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.85f), paddedTab.RectTransform, Anchor.BottomCenter)) + entityList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.9f), entityListHolder.RectTransform, Anchor.BottomCenter)) { OnSelected = SelectPrefab, UseGridLayout = true, @@ -305,7 +312,10 @@ namespace Barotrauma //empty guiframe as a separator new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), paddedLeftPanel.RectTransform), style: null); - characterModeTickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform), TextManager.Get("CharacterModeButton")) + var characterModeTickBoxHolder = new GUILayoutGroup(new RectTransform(new Vector2(paddedLeftPanel.RectTransform.RelativeSize.X, 0.01f), paddedLeftPanel.RectTransform) { MinSize = new Point(0, 32) }) + { Color = secondaryColor }; + + characterModeTickBox = new GUITickBox(new RectTransform(new Point(32, 32), characterModeTickBoxHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("CharacterModeButton")) { ToolTip = TextManager.Get("CharacterModeToolTip"), OnSelected = (GUITickBox tBox) => @@ -314,7 +324,11 @@ namespace Barotrauma return true; } }; - wiringModeTickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform), TextManager.Get("WiringModeButton")) + + var wiringModeTickBoxHolder = new GUILayoutGroup(new RectTransform(new Vector2(paddedLeftPanel.RectTransform.RelativeSize.X, 0.01f), paddedLeftPanel.RectTransform) { MinSize = new Point(0, 32) }) + { Color = secondaryColor }; + + wiringModeTickBox = new GUITickBox(new RectTransform(new Point(32, 32), wiringModeTickBoxHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("WiringModeButton")) { ToolTip = TextManager.Get("WiringModeToolTip"), OnSelected = (GUITickBox tBox) => @@ -333,9 +347,13 @@ namespace Barotrauma OnClicked = GenerateWaypoints }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.03f), paddedLeftPanel.RectTransform), TextManager.Get("ShowEntitiesLabel")); + // empty guiframe as a separator + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), paddedLeftPanel.RectTransform), style: null); - var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.03f), paddedLeftPanel.RectTransform), TextManager.Get("ShowLighting")) + var showEntitiesHolder = new GUILayoutGroup(new RectTransform(new Vector2(paddedLeftPanel.RectTransform.RelativeSize.X, 0.3f), paddedLeftPanel.RectTransform)) + { Color = secondaryColor, Stretch = true, RelativeSpacing = 0.05f }; + + var tickBox = new GUITickBox(new RectTransform(new Point(32, 32), showEntitiesHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowLighting")) { Selected = lightingEnabled, OnSelected = (GUITickBox obj) => @@ -357,52 +375,49 @@ namespace Barotrauma return true; } }; - tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.03f), paddedLeftPanel.RectTransform), TextManager.Get("ShowWalls")) + tickBox = new GUITickBox(new RectTransform(new Point(32, 32), showEntitiesHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowWalls")) { Selected = Structure.ShowWalls, OnSelected = (GUITickBox obj) => { Structure.ShowWalls = obj.Selected; return true; } }; - tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.03f), paddedLeftPanel.RectTransform), TextManager.Get("ShowStructures")) + tickBox = new GUITickBox(new RectTransform(new Point(32, 32), showEntitiesHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowStructures")) { Selected = Structure.ShowStructures, OnSelected = (GUITickBox obj) => { Structure.ShowStructures = obj.Selected; return true; } }; - tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.03f), paddedLeftPanel.RectTransform), TextManager.Get("ShowItems")) + tickBox = new GUITickBox(new RectTransform(new Point(32, 32), showEntitiesHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowItems")) { Selected = Item.ShowItems, OnSelected = (GUITickBox obj) => { Item.ShowItems = obj.Selected; return true; } }; - tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.03f), paddedLeftPanel.RectTransform), TextManager.Get("ShowWaypoints")) + tickBox = new GUITickBox(new RectTransform(new Point(32, 32), showEntitiesHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowWaypoints")) { Selected = WayPoint.ShowWayPoints, OnSelected = (GUITickBox obj) => { WayPoint.ShowWayPoints = obj.Selected; return true; } }; - tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.03f), paddedLeftPanel.RectTransform), TextManager.Get("ShowSpawnpoints")) + tickBox = new GUITickBox(new RectTransform(new Point(32, 32), showEntitiesHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowSpawnpoints")) { Selected = WayPoint.ShowSpawnPoints, OnSelected = (GUITickBox obj) => { WayPoint.ShowSpawnPoints = obj.Selected; return true; } }; - tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.03f), paddedLeftPanel.RectTransform), TextManager.Get("ShowLinks")) + tickBox = new GUITickBox(new RectTransform(new Point(32, 32), showEntitiesHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowLinks")) { Selected = Item.ShowLinks, OnSelected = (GUITickBox obj) => { Item.ShowLinks = obj.Selected; return true; } }; - tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.03f), paddedLeftPanel.RectTransform), TextManager.Get("ShowHulls")) + tickBox = new GUITickBox(new RectTransform(new Point(32, 32), showEntitiesHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowHulls")) { Selected = Hull.ShowHulls, OnSelected = (GUITickBox obj) => { Hull.ShowHulls = obj.Selected; return true; } }; - tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.03f), paddedLeftPanel.RectTransform), TextManager.Get("ShowGaps")) + tickBox = new GUITickBox(new RectTransform(new Point(32, 32), showEntitiesHolder.RectTransform) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("ShowGaps")) { Selected = Gap.ShowGaps, OnSelected = (GUITickBox obj) => { Gap.ShowGaps = obj.Selected; return true; }, }; - //empty guiframe as a separator - new GUIFrame(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform), style: null); - - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform), TextManager.Get("PreviouslyUsedLabel")); - previouslyUsedList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.25f), paddedLeftPanel.RectTransform)) + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform, Anchor.BottomCenter) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("PreviouslyUsedLabel")); + previouslyUsedList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), paddedLeftPanel.RectTransform, Anchor.BottomCenter) { AbsoluteOffset = new Point(10, 0) }) { OnSelected = SelectPrefab }; diff --git a/Barotrauma/BarotraumaClient/Source/Sprite/DeformableSprite.cs b/Barotrauma/BarotraumaClient/Source/Sprite/DeformableSprite.cs index 54f33dbb6..537cdb93b 100644 --- a/Barotrauma/BarotraumaClient/Source/Sprite/DeformableSprite.cs +++ b/Barotrauma/BarotraumaClient/Source/Sprite/DeformableSprite.cs @@ -12,6 +12,8 @@ namespace Barotrauma { private static List list = new List(); + private bool initialized = false; + private int triangleCount; private VertexBuffer vertexBuffer, flippedVertexBuffer; @@ -34,7 +36,7 @@ namespace Barotrauma private Point spritePos; private Point spriteSize; - partial void InitProjSpecific(XElement element, int? subdivisionsX, int? subdivisionsY) + partial void InitProjSpecific(XElement element, int? subdivisionsX, int? subdivisionsY, bool lazyLoad) { if (effect == null) { @@ -56,11 +58,30 @@ namespace Barotrauma throw new ArgumentException("Deformable sprites must have one or more subdivisions on each axis."); } + if (!lazyLoad) + { + Init(); + } + + list.Add(this); + } + + public void EnsureLazyLoaded() + { + if (!initialized) { Init(); } + } + + private void Init() + { + if (initialized) { return; } + initialized = true; + foreach (DeformableSprite existing in list) { + if (!existing.initialized || existing == this) { continue; } //share vertex and index buffers if there's already //an existing sprite with the same texture and subdivisions - if (existing.sprite.Texture == sprite.Texture && + if (existing.Sprite.Texture == Sprite.Texture && existing.subDivX == subDivX && existing.subDivY == subDivY && existing.Sprite.SourceRect == Sprite.SourceRect) @@ -83,19 +104,18 @@ namespace Barotrauma } } - if (sprite.Texture != null) + if (Sprite.Texture != null) { SetupVertexBuffers(); SetupIndexBuffer(); } - list.Add(this); } private void SetupVertexBuffers() { - Vector2 textureSize = new Vector2(sprite.Texture.Width, sprite.Texture.Height); - var pos = sprite.SourceRect.Location; - var size = sprite.SourceRect.Size; + Vector2 textureSize = new Vector2(Sprite.Texture.Width, Sprite.Texture.Height); + var pos = Sprite.SourceRect.Location; + var size = Sprite.SourceRect.Size; uvTopLeft = Vector2.Divide(pos.ToVector2(), textureSize); uvBottomRight = Vector2.Divide((pos + size).ToVector2(), textureSize); @@ -119,7 +139,7 @@ namespace Barotrauma uvTopLeft + (uvBottomRight - uvTopLeft) * relativePos; vertices[x + y * (subDivX + 1)] = new VertexPositionColorTexture( - position: new Vector3(relativePos.X * sprite.SourceRect.Width, relativePos.Y * sprite.SourceRect.Height, 0.0f), + position: new Vector3(relativePos.X * Sprite.SourceRect.Width, relativePos.Y * Sprite.SourceRect.Height, 0.0f), color: Color.White, textureCoordinate: uvCoord); } @@ -153,8 +173,8 @@ namespace Barotrauma } } - spritePos = sprite.SourceRect.Location; - spriteSize = sprite.SourceRect.Size; + spritePos = Sprite.SourceRect.Location; + spriteSize = Sprite.SourceRect.Size; } private void SetupIndexBuffer() @@ -195,6 +215,8 @@ namespace Barotrauma /// public void Deform(Func deformFunction) { + if (!initialized) { Init(); } + var deformAmount = new Vector2[subDivX + 1, subDivY + 1]; for (int x = 0; x <= subDivX; x++) { @@ -208,6 +230,8 @@ namespace Barotrauma public void Deform(Vector2[,] deform) { + if (!initialized) { Init(); } + deformArrayWidth = deform.GetLength(0); deformArrayHeight = deform.GetLength(1); if (deformAmount == null || deformAmount.Length != deformArrayWidth * deformArrayHeight) @@ -234,6 +258,8 @@ namespace Barotrauma public Matrix GetTransform(Vector3 pos, Vector2 origin, float rotate, Vector2 scale) { + if (!initialized) { Init(); } + return Matrix.CreateTranslation(-origin.X, -origin.Y, 0) * Matrix.CreateScale(scale.X, -scale.Y, 1.0f) * @@ -243,18 +269,19 @@ namespace Barotrauma public void Draw(Camera cam, Vector3 pos, Vector2 origin, float rotate, Vector2 scale, Color color, bool flip = false) { - if (sprite.Texture == null) { return; } + if (Sprite.Texture == null) { return; } + if (!initialized) { Init(); } // If the source rect is modified, we should recalculate the vertex buffer. - if (sprite.SourceRect.Location != spritePos || sprite.SourceRect.Size != spriteSize) + if (Sprite.SourceRect.Location != spritePos || Sprite.SourceRect.Size != spriteSize) { SetupVertexBuffers(); } #if (LINUX || OSX) - effect.Parameters["TextureSampler+xTexture"].SetValue(sprite.Texture); + effect.Parameters["TextureSampler+xTexture"].SetValue(Sprite.Texture); #else - effect.Parameters["xTexture"].SetValue(sprite.Texture); + effect.Parameters["xTexture"].SetValue(Sprite.Texture); #endif Matrix matrix = GetTransform(pos, origin, rotate, scale); @@ -274,8 +301,8 @@ namespace Barotrauma public void Remove() { - sprite?.Remove(); - sprite = null; + Sprite?.Remove(); + Sprite = null; list.Remove(this); diff --git a/Barotrauma/BarotraumaClient/Source/Sprite/Sprite.cs b/Barotrauma/BarotraumaClient/Source/Sprite/Sprite.cs index b4c33733d..50640ffbf 100644 --- a/Barotrauma/BarotraumaClient/Source/Sprite/Sprite.cs +++ b/Barotrauma/BarotraumaClient/Source/Sprite/Sprite.cs @@ -55,6 +55,28 @@ namespace Barotrauma if (sourceVector.W == 0.0f) sourceVector.W = texture.Height; } + public void EnsureLazyLoaded() + { + if (!lazyLoad || texture != null) { return; } + + Vector4 sourceVector = Vector4.Zero; + bool temp2 = false; + LoadTexture(ref sourceVector, ref temp2, preMultipliedAlpha); + if (sourceRect.Width == 0 && sourceRect.Height == 0) + { + sourceRect = new Rectangle((int)sourceVector.X, (int)sourceVector.Y, (int)sourceVector.Z, (int)sourceVector.W); + size = SourceElement.GetAttributeVector2("size", Vector2.One); + size.X *= sourceRect.Width; + size.Y *= sourceRect.Height; + RelativeOrigin = SourceElement.GetAttributeVector2("origin", new Vector2(0.5f, 0.5f)); + } + foreach (Sprite s in list) + { + if (s == this) { continue; } + if (s.FullPath == FullPath && s.texture != null) { s.texture = texture; } + } + } + public void ReloadTexture() { var sprites = LoadedSprites.Where(s => s.Texture == texture).ToList(); @@ -76,11 +98,12 @@ namespace Barotrauma public static Texture2D LoadTexture(string file, bool preMultiplyAlpha = true) { + if (string.IsNullOrWhiteSpace(file)) { return new Texture2D(GameMain.GraphicsDeviceManager.GraphicsDevice, 1, 1); } file = Path.GetFullPath(file); foreach (Sprite s in list) { - if (s.FullPath == file) return s.texture; + if (s.FullPath == file && s.texture != null) { return s.texture; } } if (File.Exists(file)) diff --git a/Barotrauma/BarotraumaServer/Source/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaServer/Source/Characters/CharacterNetworking.cs index 8854987f8..bd80dfedc 100644 --- a/Barotrauma/BarotraumaServer/Source/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaServer/Source/Characters/CharacterNetworking.cs @@ -87,7 +87,6 @@ namespace Barotrauma //reset focus when attempting to use/select something if (memInput[memInput.Count - 1].states.HasFlag(InputNetFlags.Use) || memInput[memInput.Count - 1].states.HasFlag(InputNetFlags.Select) || - memInput[memInput.Count - 1].states.HasFlag(InputNetFlags.Deselect) || memInput[memInput.Count - 1].states.HasFlag(InputNetFlags.Health) || memInput[memInput.Count - 1].states.HasFlag(InputNetFlags.Grab)) { @@ -181,7 +180,6 @@ namespace Barotrauma newAim = msg.ReadUInt16(); if (newInput.HasFlag(InputNetFlags.Select) || - newInput.HasFlag(InputNetFlags.Deselect) || newInput.HasFlag(InputNetFlags.Use) || newInput.HasFlag(InputNetFlags.Health) || newInput.HasFlag(InputNetFlags.Grab)) @@ -327,27 +325,23 @@ namespace Barotrauma bool aiming = false; bool use = false; bool attack = false; - bool shoot = false; if (IsRemotePlayer) { aiming = dequeuedInput.HasFlag(InputNetFlags.Aim); use = dequeuedInput.HasFlag(InputNetFlags.Use); attack = dequeuedInput.HasFlag(InputNetFlags.Attack); - shoot = dequeuedInput.HasFlag(InputNetFlags.Shoot); } else if (keys != null) { aiming = keys[(int)InputType.Aim].GetHeldQueue; use = keys[(int)InputType.Use].GetHeldQueue; attack = keys[(int)InputType.Attack].GetHeldQueue; - shoot = keys[(int)InputType.Shoot].GetHeldQueue; networkUpdateSent = true; } tempBuffer.Write(aiming); - tempBuffer.Write(shoot); tempBuffer.Write(use); if (AnimController is HumanoidAnimController) { @@ -362,7 +356,7 @@ namespace Barotrauma } tempBuffer.Write(IsRagdolled); - tempBuffer.Write(AnimController.TargetDir == Direction.Right); + tempBuffer.Write(AnimController.Dir > 0.0f); } if (SelectedCharacter != null || SelectedConstruction != null) diff --git a/Barotrauma/BarotraumaShared/SharedContent.projitems b/Barotrauma/BarotraumaShared/SharedContent.projitems index 3f84508f8..0a05f74a7 100644 --- a/Barotrauma/BarotraumaShared/SharedContent.projitems +++ b/Barotrauma/BarotraumaShared/SharedContent.projitems @@ -381,6 +381,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -1798,99 +1801,6 @@ - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - PreserveNewest diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs index bd2b5a4c8..3d5c95995 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs @@ -530,7 +530,8 @@ namespace Barotrauma } } - if (Math.Abs(Character.AnimController.movement.X) > 0.1f && !Character.AnimController.InWater) + if (Math.Abs(Character.AnimController.movement.X) > 0.1f && !Character.AnimController.InWater && + (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer || Character.Controlled == Character)) { Character.AnimController.TargetDir = Character.WorldPosition.X < attackWorldPos.X ? Direction.Right : Direction.Left; } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs index 0d4f621fd..8aac40d42 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs @@ -204,10 +204,7 @@ namespace Barotrauma private void Attack(float deltaTime) { character.CursorPosition = Enemy.Position; - if (Weapon.RequireAimToUse) - { - character.SetInput(InputType.Aim, false, true); - } + character.SetInput(InputType.Aim, false, true); if (WeaponComponent is MeleeWeapon meleeWeapon) { if (Vector2.DistanceSquared(character.Position, Enemy.Position) <= meleeWeapon.Range * meleeWeapon.Range) diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveRepairItem.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveRepairItem.cs index 51668ae2a..8d65800fd 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveRepairItem.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveRepairItem.cs @@ -161,10 +161,7 @@ namespace Barotrauma private void OperateRepairTool(float deltaTime) { character.CursorPosition = Item.Position; - if (Item.RequireAimToUse) - { - character.SetInput(InputType.Aim, false, true); - } + character.SetInput(InputType.Aim, false, true); Vector2 fromToolToTarget = Item.Position - repairTool.Item.Position; if (fromToolToTarget.LengthSquared() < MathUtils.Pow(repairTool.Range / 2, 2)) { diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs index a099d8382..6e1406f46 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs @@ -696,7 +696,7 @@ namespace Barotrauma return; } - limb.body.ApplyForce(diff * (float)(Math.Sin(WalkPos) * Math.Sqrt(limb.Mass)) * 30.0f * animStrength); + limb.body.ApplyForce(diff * (float)(Math.Sin(WalkPos) * Math.Sqrt(limb.Mass)) * 30.0f * animStrength, maxVelocity: 10.0f); } } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs index c0c2fa178..0c001afcb 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using Barotrauma.Extensions; +using Barotrauma.Networking; namespace Barotrauma { @@ -1122,6 +1123,7 @@ namespace Barotrauma //prevent the hands from going above the top of the ladders handPos.Y = Math.Min(-0.5f, handPos.Y); + // TODO: lock only one hand when aiming? if (!PlayerInput.KeyDown(InputType.Aim) || Math.Abs(movement.Y) > 0.01f) { MoveLimb(leftHand, diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs index 09cb6ab3b..6b0c25c5a 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs @@ -892,8 +892,6 @@ namespace Barotrauma return !(dequeuedInput.HasFlag(InputNetFlags.Crouch)) && (prevDequeuedInput.HasFlag(InputNetFlags.Crouch)); case InputType.Select: return dequeuedInput.HasFlag(InputNetFlags.Select); //TODO: clean up the way this input is registered - case InputType.Deselect: - return dequeuedInput.HasFlag(InputNetFlags.Deselect); case InputType.Health: return dequeuedInput.HasFlag(InputNetFlags.Health); case InputType.Grab: @@ -1272,51 +1270,18 @@ namespace Barotrauma { for (int i = 0; i < selectedItems.Length; i++ ) { - if (selectedItems[i] == null) { continue; } - if (i == 1 && selectedItems[0] == selectedItems[1]) { continue; } - var item = selectedItems[i]; - if (item == null) { continue; } - if (IsKeyDown(InputType.Aim) || !item.RequireAimToSecondaryUse) - { - item.SecondaryUse(deltaTime, this); - } - if (IsKeyDown(InputType.Use) && !item.IsShootable) - { - if (!item.RequireAimToUse || IsKeyDown(InputType.Aim)) - { - item.Use(deltaTime, this); - } - } - if (IsKeyDown(InputType.Shoot) && item.IsShootable) - { - if (!item.RequireAimToUse || IsKeyDown(InputType.Aim)) - { - item.Use(deltaTime, this); - } - } + if (selectedItems[i] == null) continue; + if (i == 1 && selectedItems[0] == selectedItems[1]) continue; + + if (IsKeyDown(InputType.Use)) selectedItems[i].Use(deltaTime, this); + if (IsKeyDown(InputType.Aim) && selectedItems[i] != null) selectedItems[i].SecondaryUse(deltaTime, this); } } if (SelectedConstruction != null) { - if (IsKeyDown(InputType.Aim) || !SelectedConstruction.RequireAimToSecondaryUse) - { - SelectedConstruction.SecondaryUse(deltaTime, this); - } - if (IsKeyDown(InputType.Use) && !SelectedConstruction.IsShootable) - { - if (!SelectedConstruction.RequireAimToUse || IsKeyDown(InputType.Aim)) - { - SelectedConstruction.Use(deltaTime, this); - } - } - if (IsKeyDown(InputType.Shoot) && SelectedConstruction.IsShootable) - { - if (!SelectedConstruction.RequireAimToUse || IsKeyDown(InputType.Aim)) - { - SelectedConstruction.Use(deltaTime, this); - } - } + if (IsKeyDown(InputType.Use)) SelectedConstruction.Use(deltaTime, this); + if (SelectedConstruction != null && IsKeyDown(InputType.Aim)) SelectedConstruction.SecondaryUse(deltaTime, this); } if (SelectedCharacter != null) @@ -1794,7 +1759,7 @@ namespace Barotrauma } #endif } - else if (IsKeyHit(InputType.Deselect) && SelectedConstruction != null) + else if (IsKeyHit(InputType.Select) && SelectedConstruction != null) { SelectedConstruction = null; #if CLIENT @@ -1939,7 +1904,7 @@ namespace Barotrauma //cannot be protected from pressure when below crush depth protectedFromPressure = protectedFromPressure && WorldPosition.Y > CharacterHealth.CrushDepth; //implode if not protected from pressure, and either outside or in a high-pressure hull - if (!protectedFromPressure && + if (!protectedFromPressure && (AnimController.CurrentHull == null || AnimController.CurrentHull.LethalPressure >= 80.0f)) { if (CharacterHealth.PressureKillDelay <= 0.0f) @@ -1954,7 +1919,7 @@ namespace Barotrauma if (PressureTimer >= 100.0f) { - if (Controlled == this) cam.Zoom = 5.0f; + if (Controlled == this) { cam.Zoom = 5.0f; } if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient) { Implode(); @@ -2235,7 +2200,7 @@ namespace Barotrauma if (limbHit == null) return new AttackResult(); - limbHit.body?.ApplyLinearImpulse(attack.TargetImpulseWorld + attack.TargetForceWorld * deltaTime); + limbHit.body?.ApplyLinearImpulse(attack.TargetImpulseWorld + attack.TargetForceWorld * deltaTime, maxVelocity: NetConfig.MaxPhysicsBodyVelocity); #if SERVER if (attacker is Character attackingCharacter && attackingCharacter.AIController == null) { @@ -2321,7 +2286,8 @@ namespace Barotrauma { Vector2 diff = dir; if (diff == Vector2.Zero) diff = Rand.Vector(1.0f); - hitLimb.body.ApplyLinearImpulse(Vector2.Normalize(diff) * attackImpulse, hitLimb.SimPosition + ConvertUnits.ToSimUnits(diff)); + hitLimb.body.ApplyLinearImpulse(Vector2.Normalize(diff) * attackImpulse, hitLimb.SimPosition + ConvertUnits.ToSimUnits(diff), + maxVelocity: NetConfig.MaxPhysicsBodyVelocity); } Vector2 simPos = hitLimb.SimPosition + ConvertUnits.ToSimUnits(dir); AttackResult attackResult = hitLimb.AddDamage(simPos, afflictions, playSound); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs index 4f0068328..ac52f3b2b 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/CharacterNetworking.cs @@ -55,12 +55,8 @@ namespace Barotrauma Ragdoll = 0x800, Health = 0x1000, Grab = 0x2000, - Deselect = 0x4000, // 16384 - Shoot = 0x8000, // 32768 - MaxVal = 0xFFFF // 65535 - //MaxVal = 0x7FFF // 32767 - //MaxVal = 0x3FFF // 16383 + MaxVal = 0x3FFF } private InputNetFlags dequeuedInput = 0; private InputNetFlags prevDequeuedInput = 0; diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaShared/Source/Characters/Health/CharacterHealth.cs index 5d6f70a83..e7f908c4e 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Health/CharacterHealth.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Health/CharacterHealth.cs @@ -103,6 +103,7 @@ namespace Barotrauma } public float CrushDepth { get; private set; } + public float PressureKillDelay { get; private set; } = 5.0f; public float Vitality { get; private set; } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Limb.cs b/Barotrauma/BarotraumaShared/Source/Characters/Limb.cs index dbd782551..2814b127c 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Limb.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Limb.cs @@ -626,13 +626,17 @@ namespace Barotrauma Limb limb = character.AnimController.Limbs[limbIndex]; Vector2 forcePos = limb.pullJoint == null ? limb.body.SimPosition : limb.pullJoint.WorldAnchorA; - limb.body.ApplyLinearImpulse(limb.Mass * attack.Force * Vector2.Normalize(attackSimPos - SimPosition), forcePos); + limb.body.ApplyLinearImpulse(limb.Mass * attack.Force * Vector2.Normalize(attackSimPos - SimPosition), forcePos, + maxVelocity: NetConfig.MaxPhysicsBodyVelocity); } } else { Vector2 forcePos = pullJoint == null ? body.SimPosition : pullJoint.WorldAnchorA; - body.ApplyLinearImpulse(Mass * attack.Force * Vector2.Normalize(attackSimPos - SimPosition), forcePos); + body.ApplyLinearImpulse( + Mass * attack.Force * Vector2.Normalize(attackSimPos - SimPosition), + forcePos, + maxVelocity: NetConfig.MaxPhysicsBodyVelocity); } } return wasHit; diff --git a/Barotrauma/BarotraumaShared/Source/GameSettings.cs b/Barotrauma/BarotraumaShared/Source/GameSettings.cs index ca5b0b711..852ecc8cb 100644 --- a/Barotrauma/BarotraumaShared/Source/GameSettings.cs +++ b/Barotrauma/BarotraumaShared/Source/GameSettings.cs @@ -297,60 +297,8 @@ namespace Barotrauma LoadPlayerConfig(); } - private void CheckBindings(bool useDefaults) - { - foreach (InputType inputType in Enum.GetValues(typeof(InputType))) - { - var binding = keyMapping[(int)inputType]; - if (binding == null) - { - switch (inputType) - { - case InputType.Deselect: - if (useDefaults) - { - binding = new KeyOrMouse(1); - } - else - { - // Legacy support - var selectKey = keyMapping[(int)InputType.Select]; - if (selectKey != null && selectKey.Key != Keys.None) - { - binding = new KeyOrMouse(selectKey.Key); - } - } - break; - case InputType.Shoot: - if (useDefaults) - { - binding = new KeyOrMouse(0); - } - else - { - // Legacy support - var useKey = keyMapping[(int)InputType.Use]; - if (useKey != null && useKey.MouseButton.HasValue) - { - binding = new KeyOrMouse(useKey.MouseButton.Value); - } - } - break; - default: - break; - } - if (binding == null) - { - DebugConsole.ThrowError("Key binding for the input type \"" + inputType + " not set!"); - binding = new KeyOrMouse(Keys.D1); - } - keyMapping[(int)inputType] = binding; - } - } - } - #region Load DefaultConfig - private void LoadDefaultConfig() + public void LoadDefaultConfig() { XDocument doc = XMLExtensions.TryLoadXml(savePath); @@ -448,9 +396,12 @@ namespace Barotrauma keyMapping[(int)InputType.Voice] = new KeyOrMouse(Keys.V); - keyMapping[(int)InputType.Use] = new KeyOrMouse(Keys.E); + keyMapping[(int)InputType.SelectNextCharacter] = new KeyOrMouse(Keys.Tab); + keyMapping[(int)InputType.SelectPreviousCharacter] = new KeyOrMouse(Keys.Q); - keyMapping[(int)InputType.Select] = new KeyOrMouse(0); + keyMapping[(int)InputType.Voice] = new KeyOrMouse(Keys.V); + + keyMapping[(int)InputType.Use] = new KeyOrMouse(0); keyMapping[(int)InputType.Aim] = new KeyOrMouse(1); foreach (XElement subElement in doc.Root.Elements()) @@ -758,6 +709,275 @@ namespace Barotrauma losMode = LosMode.Transparent; } +#if CLIENT + if (GraphicsWidth == 0 || GraphicsHeight == 0) + { + GraphicsWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width; + GraphicsHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height; + } +#endif + + var windowModeStr = graphicsMode.GetAttributeString("displaymode", "Fullscreen"); + if (!Enum.TryParse(windowModeStr, out windowMode)) + { + windowMode = WindowMode.Fullscreen; + } + + XElement audioSettings = doc.Root.Element("audio"); + if (audioSettings != null) + { + SoundVolume = audioSettings.GetAttributeFloat("soundvolume", SoundVolume); + MusicVolume = audioSettings.GetAttributeFloat("musicvolume", MusicVolume); + VoiceChatVolume = audioSettings.GetAttributeFloat("voicechatvolume", VoiceChatVolume); + string voiceSettingStr = audioSettings.GetAttributeString("voicesetting", "Disabled"); + VoiceCaptureDevice = audioSettings.GetAttributeString("voicecapturedevice", ""); + NoiseGateThreshold = audioSettings.GetAttributeFloat("noisegatethreshold", -45); + var voiceSetting = VoiceMode.Disabled; + if (Enum.TryParse(voiceSettingStr, out voiceSetting)) + { + VoiceSetting = voiceSetting; + } + } + + List missingPackagePaths = new List(); + List incompatiblePackages = new List(); + foreach (XElement subElement in doc.Root.Elements()) + { + switch (subElement.Name.ToString().ToLowerInvariant()) + { + case "contentpackage": + string path = System.IO.Path.GetFullPath(subElement.GetAttributeString("path", "")); + var matchingContentPackage = ContentPackage.List.Find(cp => System.IO.Path.GetFullPath(cp.Path) == path); + if (matchingContentPackage == null) + { + missingPackagePaths.Add(path); + } + else if (!matchingContentPackage.IsCompatible()) + { + incompatiblePackages.Add(matchingContentPackage); + } + else + { + SelectedContentPackages.Add(matchingContentPackage); + } + break; + } + } + + TextManager.LoadTextPacks(SelectedContentPackages); + + //display error messages after all content packages have been loaded + //to make sure the package that contains text files has been loaded before we attempt to use TextManager + foreach (string missingPackagePath in missingPackagePaths) + { + DebugConsole.ThrowError(TextManager.Get("ContentPackageNotFound").Replace("[packagepath]", missingPackagePath)); + } + foreach (ContentPackage incompatiblePackage in incompatiblePackages) + { + DebugConsole.ThrowError(TextManager.Get(incompatiblePackage.GameVersion <= new Version(0, 0, 0, 0) ? "IncompatibleContentPackageUnknownVersion" : "IncompatibleContentPackage") + .Replace("[packagename]", incompatiblePackage.Name) + .Replace("[packageversion]", incompatiblePackage.GameVersion.ToString()) + .Replace("[gameversion]", GameMain.Version.ToString())); + } + foreach (ContentPackage contentPackage in SelectedContentPackages) + { + foreach (ContentFile file in contentPackage.Files) + { + if (!System.IO.File.Exists(file.Path)) + { + DebugConsole.ThrowError("Error in content package \"" + contentPackage.Name + "\" - file \"" + file.Path + "\" not found."); + continue; + } + ToolBox.IsProperFilenameCase(file.Path); + } + } + if (!SelectedContentPackages.Any()) + { + var availablePackage = ContentPackage.List.FirstOrDefault(cp => cp.IsCompatible() && cp.CorePackage); + if (availablePackage != null) + { + SelectedContentPackages.Add(availablePackage); + } + } + + //save to get rid of the invalid selected packages in the config file + if (missingPackagePaths.Count > 0 || incompatiblePackages.Count > 0) { SaveNewPlayerConfig(); } + } + #endregion + + #region Save DefaultConfig + private void SaveNewDefaultConfig() + { + XDocument doc = new XDocument(); + UnsavedSettings = false; + + if (doc.Root == null) + { + doc.Add(new XElement("config")); + } + + doc.Root.Add( + new XAttribute("language", TextManager.Language), + new XAttribute("masterserverurl", MasterServerUrl), + new XAttribute("autocheckupdates", AutoCheckUpdates), + new XAttribute("musicvolume", musicVolume), + new XAttribute("soundvolume", soundVolume), + new XAttribute("voicechatvolume", voiceChatVolume), + new XAttribute("verboselogging", VerboseLogging), + new XAttribute("savedebugconsolelogs", SaveDebugConsoleLogs), + new XAttribute("enablesplashscreen", EnableSplashScreen), + new XAttribute("usesteammatchmaking", useSteamMatchmaking), + new XAttribute("quickstartsub", QuickStartSubmarineName), + new XAttribute("requiresteamauthentication", requireSteamAuthentication), + new XAttribute("aimassistamount", aimAssistAmount)); + + if (!ShowUserStatisticsPrompt) + { + doc.Root.Add(new XAttribute("senduserstatistics", sendUserStatistics)); + } + + if (WasGameUpdated) + { + doc.Root.Add(new XAttribute("wasgameupdated", true)); + } + + XElement gMode = doc.Root.Element("graphicsmode"); + if (gMode == null) + { + gMode = new XElement("graphicsmode"); + doc.Root.Add(gMode); + } + if (GraphicsWidth == 0 || GraphicsHeight == 0) + { + gMode.ReplaceAttributes(new XAttribute("displaymode", windowMode)); + } + else + { + gMode.ReplaceAttributes( + new XAttribute("width", GraphicsWidth), + new XAttribute("height", GraphicsHeight), + new XAttribute("vsync", VSyncEnabled), + new XAttribute("displaymode", windowMode)); + } + + XElement gSettings = doc.Root.Element("graphicssettings"); + if (gSettings == null) + { + gSettings = new XElement("graphicssettings"); + doc.Root.Add(gSettings); + } + + gSettings.ReplaceAttributes( + new XAttribute("particlelimit", ParticleLimit), + new XAttribute("lightmapscale", LightMapScale), + new XAttribute("specularity", SpecularityEnabled), + new XAttribute("chromaticaberration", ChromaticAberrationEnabled), + new XAttribute("losmode", LosMode), + new XAttribute("hudscale", HUDScale), + new XAttribute("inventoryscale", InventoryScale)); + + foreach (ContentPackage contentPackage in SelectedContentPackages) + { + if (contentPackage.Path.Contains(vanillaContentPackagePath)) + { + doc.Root.Add(new XElement("contentpackage", new XAttribute("path", contentPackage.Path))); + break; + } + } + + var keyMappingElement = new XElement("keymapping"); + doc.Root.Add(keyMappingElement); + for (int i = 0; i < keyMapping.Length; i++) + { + if (keyMapping[i].MouseButton == null) + { + keyMappingElement.Add(new XAttribute(((InputType)i).ToString(), keyMapping[i].Key)); + } + else + { + keyMappingElement.Add(new XAttribute(((InputType)i).ToString(), keyMapping[i].MouseButton)); + } + } + + var gameplay = new XElement("gameplay"); + var jobPreferences = new XElement("jobpreferences"); + foreach (string jobName in JobPreferences) + { + jobPreferences.Add(new XElement("job", new XAttribute("identifier", jobName))); + } + gameplay.Add(jobPreferences); + doc.Root.Add(gameplay); + + var playerElement = new XElement("player", + new XAttribute("name", defaultPlayerName ?? ""), + new XAttribute("headindex", CharacterHeadIndex), + new XAttribute("gender", CharacterGender), + new XAttribute("race", CharacterRace), + new XAttribute("hairindex", CharacterHairIndex), + new XAttribute("beardindex", CharacterBeardIndex), + new XAttribute("moustacheindex", CharacterMoustacheIndex), + new XAttribute("faceattachmentindex", CharacterFaceAttachmentIndex)); + doc.Root.Add(playerElement); + + XmlWriterSettings settings = new XmlWriterSettings + { + Indent = true, + OmitXmlDeclaration = true, + NewLineOnAttributes = true + }; + + try + { + using (var writer = XmlWriter.Create(savePath, settings)) + { + doc.WriteTo(writer); + writer.Flush(); + } + } + catch (Exception e) + { + DebugConsole.ThrowError("Saving game settings failed.", e); + GameAnalyticsManager.AddErrorEventOnce("GameSettings.Save:SaveFailed", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, + "Saving game settings failed.\n" + e.Message + "\n" + e.StackTrace); + } + } + #endregion + + #region Load PlayerConfig + // TODO: DRY + public void LoadPlayerConfig() + { + XDocument doc = XMLExtensions.LoadXml(playerSavePath); + + if (doc == null || doc.Root == null) + { + ShowUserStatisticsPrompt = true; + SaveNewPlayerConfig(); + return; + } + + Language = doc.Root.GetAttributeString("language", Language); + AutoCheckUpdates = doc.Root.GetAttributeBool("autocheckupdates", AutoCheckUpdates); + sendUserStatistics = doc.Root.GetAttributeBool("senduserstatistics", true); + + XElement graphicsMode = doc.Root.Element("graphicsmode"); + GraphicsWidth = graphicsMode.GetAttributeInt("width", GraphicsWidth); + GraphicsHeight = graphicsMode.GetAttributeInt("height", GraphicsHeight); + VSyncEnabled = graphicsMode.GetAttributeBool("vsync", VSyncEnabled); + + XElement graphicsSettings = doc.Root.Element("graphicssettings"); + ParticleLimit = graphicsSettings.GetAttributeInt("particlelimit", ParticleLimit); + LightMapScale = MathHelper.Clamp(graphicsSettings.GetAttributeFloat("lightmapscale", LightMapScale), 0.1f, 1.0f); + SpecularityEnabled = graphicsSettings.GetAttributeBool("specularity", SpecularityEnabled); + ChromaticAberrationEnabled = graphicsSettings.GetAttributeBool("chromaticaberration", ChromaticAberrationEnabled); + HUDScale = graphicsSettings.GetAttributeFloat("hudscale", HUDScale); + InventoryScale = graphicsSettings.GetAttributeFloat("inventoryscale", InventoryScale); + var losModeStr = graphicsSettings.GetAttributeString("losmode", "Transparent"); + if (!Enum.TryParse(losModeStr, out losMode)) + { + losMode = LosMode.Transparent; + } + #if CLIENT if (GraphicsWidth == 0 || GraphicsHeight == 0) { @@ -794,6 +1014,7 @@ namespace Barotrauma EnableSplashScreen = doc.Root.GetAttributeBool("enablesplashscreen", EnableSplashScreen); AimAssistAmount = doc.Root.GetAttributeFloat("aimassistamount", AimAssistAmount); + EnableMouseLook = doc.Root.GetAttributeBool("enablemouselook", EnableMouseLook); foreach (XElement subElement in doc.Root.Elements()) { @@ -856,6 +1077,15 @@ namespace Barotrauma } } + foreach (InputType inputType in Enum.GetValues(typeof(InputType))) + { + if (keyMapping[(int)inputType] == null) + { + DebugConsole.ThrowError("Key binding for the input type \"" + inputType + " not set!"); + keyMapping[(int)inputType] = new KeyOrMouse(Keys.D1); + } + } + UnsavedSettings = false; selectedContentPackagePaths = new HashSet(); @@ -872,7 +1102,6 @@ namespace Barotrauma } LoadContentPackages(selectedContentPackagePaths); - return true; } public void ReloadContentPackages() @@ -962,7 +1191,6 @@ namespace Barotrauma new XAttribute("autocheckupdates", AutoCheckUpdates), new XAttribute("musicvolume", musicVolume), new XAttribute("soundvolume", soundVolume), - new XAttribute("voicechatvolume", voiceChatVolume), new XAttribute("verboselogging", VerboseLogging), new XAttribute("savedebugconsolelogs", SaveDebugConsoleLogs), new XAttribute("enablesplashscreen", EnableSplashScreen), @@ -970,7 +1198,8 @@ namespace Barotrauma new XAttribute("quickstartsub", QuickStartSubmarineName), new XAttribute("requiresteamauthentication", requireSteamAuthentication), new XAttribute("autoupdateworkshopitems", AutoUpdateWorkshopItems), - new XAttribute("aimassistamount", aimAssistAmount)); + new XAttribute("aimassistamount", aimAssistAmount), + new XAttribute("enablemouselook", EnableMouseLook)); if (!ShowUserStatisticsPrompt) { @@ -1112,7 +1341,6 @@ namespace Barotrauma public void ResetToDefault() { LoadDefaultConfig(); - CheckBindings(true); SaveNewPlayerConfig(); } diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs index c6ca050f5..73826cd2c 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs @@ -396,70 +396,25 @@ namespace Barotrauma.Items.Components } int dir = IsHorizontal ? Math.Sign(c.SimPosition.Y - item.SimPosition.Y) : Math.Sign(c.SimPosition.X - item.SimPosition.X); - List bodies = c.AnimController.Limbs.Select(l => l.body).ToList(); - bodies.Add(c.AnimController.Collider); - bool soundPlayed = false; foreach (Limb limb in c.AnimController.Limbs) { - float diff = 0.0f; - if (!MathUtils.IsValid(body.SimPosition)) - { - DebugConsole.ThrowError("Failed to push a limb out of a doorway - position of the body (character \"" + c.Name + "\") is not valid (" + body.SimPosition + ")"); - GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:LimbPosInvalid", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, - "Failed to push a character out of a doorway - position of the character \"" + c.Name + "\" is not valid (" + body.SimPosition + ")." + - " Removed: " + c.Removed + - " Remoteplayer: " + c.IsRemotePlayer); - continue; - } - - if (IsHorizontal) - { - if (body.SimPosition.X < simPos.X || body.SimPosition.X > simPos.X + simSize.X) continue; - diff = body.SimPosition.Y - item.SimPosition.Y; - } - else - { - if (body.SimPosition.Y > simPos.Y || body.SimPosition.Y < simPos.Y - simSize.Y) continue; - diff = body.SimPosition.X - item.SimPosition.X; - } - - if (Math.Sign(diff) != dir) + if (PushBodyOutOfDoorway(c, limb.body, dir, simPos, simSize) && !soundPlayed) { #if CLIENT SoundPlayer.PlayDamageSound("LimbBlunt", 1.0f, limb.body); #endif - - if (IsHorizontal) - { - body.SetTransform(new Vector2(body.SimPosition.X, item.SimPosition.Y + dir * simSize.Y * 2.0f), body.Rotation); - body.ApplyLinearImpulse(new Vector2(isOpen ? 0.0f : 1.0f, dir * 2.0f)); - } - else - { - body.SetTransform(new Vector2(item.SimPosition.X + dir * simSize.X * 1.2f, body.SimPosition.Y), body.Rotation); - body.ApplyLinearImpulse(new Vector2(dir * 0.5f, isOpen ? 0.0f : -1.0f)); - } - } - - if (IsHorizontal) - { - if (Math.Abs(body.SimPosition.Y - item.SimPosition.Y) > simSize.Y * 0.5f) continue; - - body.ApplyLinearImpulse(new Vector2(isOpen ? 0.0f : 1.0f, dir * 0.5f)); + soundPlayed = true; } } PushBodyOutOfDoorway(c, c.AnimController.Collider, dir, simPos, simSize); } } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + private bool PushBodyOutOfDoorway(Character c, PhysicsBody body, int dir, Vector2 doorRectSimPos, Vector2 doorRectSimSize) { - if (isStuck) return; - - bool wasOpen = PredictedState == null ? isOpen : PredictedState.Value; - - if (connection.Name == "toggle") + float diff = 0.0f; + if (!MathUtils.IsValid(body.SimPosition)) { DebugConsole.ThrowError("Failed to push a limb out of a doorway - position of the body (character \"" + c.Name + "\") is not valid (" + body.SimPosition + ")"); GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:LimbPosInvalid", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, @@ -480,6 +435,51 @@ namespace Barotrauma.Items.Components diff = body.SimPosition.X - item.SimPosition.X; } + //if the limb is at a different side of the door than the character (collider), + //immediately teleport it to the correct side + if (Math.Sign(diff) != dir) + { + if (IsHorizontal) + { + body.SetTransform(new Vector2(body.SimPosition.X, item.SimPosition.Y + dir * doorRectSimSize.Y * 2.0f), body.Rotation); + } + else + { + body.SetTransform(new Vector2(item.SimPosition.X + dir * doorRectSimSize.X * 1.2f, body.SimPosition.Y), body.Rotation); + } + } + + //apply an impulse to push the limb further from the door + if (IsHorizontal) + { + if (Math.Abs(body.SimPosition.Y - item.SimPosition.Y) > doorRectSimSize.Y * 0.5f) { return false; } + body.ApplyLinearImpulse(new Vector2(isOpen ? 0.0f : 1.0f, dir * 2.0f), maxVelocity: NetConfig.MaxPhysicsBodyVelocity); + } + else + { + if (Math.Abs(body.SimPosition.X - item.SimPosition.X) > doorRectSimSize.X * 0.5f) { return false; } + body.ApplyLinearImpulse(new Vector2(dir * 2.0f, isOpen ? 0.0f : -1.0f), maxVelocity: NetConfig.MaxPhysicsBodyVelocity); + } + + c.SetStun(0.2f); + return true; + } + + public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + { + if (isStuck) return; + + bool wasOpen = PredictedState == null ? isOpen : PredictedState.Value; + + if (connection.Name == "toggle") + { + SetState(!wasOpen, false, true); + } + else if (connection.Name == "set_state") + { + SetState(signal != "0", false, true); + } + #if SERVER if (sender != null && wasOpen != isOpen) { diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Holdable.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Holdable.cs index fdc3b8a06..e5171e5c8 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Holdable.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Holdable.cs @@ -471,7 +471,7 @@ namespace Barotrauma.Items.Components swingState %= 1.0f; if (SwingWhenHolding || (SwingWhenAiming && picker.IsKeyDown(InputType.Aim)) || - (SwingWhenUsing && picker.IsKeyDown(InputType.Aim) && picker.IsKeyDown(InputType.Shoot))) + (SwingWhenUsing && picker.IsKeyDown(InputType.Aim) && picker.IsKeyDown(InputType.Use))) { swing = swingAmount * new Vector2( PerlinNoise.GetPerlin(swingState * SwingSpeed * 0.1f, swingState * SwingSpeed * 0.1f) - 0.5f, @@ -489,8 +489,7 @@ namespace Barotrauma.Items.Components { scaledHandlePos[0] = handlePos[0] * item.Scale; scaledHandlePos[1] = handlePos[1] * item.Scale; - bool aim = picker.IsKeyDown(InputType.Aim) && aimPos != Vector2.Zero && (picker.SelectedConstruction == null || picker.SelectedConstruction.GetComponent() != null); - picker.AnimController.HoldItem(deltaTime, item, scaledHandlePos, holdPos + swing, aimPos + swing, aim, holdAngle); + picker.AnimController.HoldItem(deltaTime, item, scaledHandlePos, holdPos + swing, aimPos + swing, picker.IsKeyDown(InputType.Aim) && aimPos != Vector2.Zero, holdAngle); } else { diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/MeleeWeapon.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/MeleeWeapon.cs index d46a5878f..e12a3c799 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/MeleeWeapon.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/MeleeWeapon.cs @@ -149,8 +149,7 @@ namespace Barotrauma.Items.Components //TODO: refactor the hitting logic (get rid of the magic numbers, make it possible to use different kinds of animations for different items) if (!hitting) { - bool aim = picker.IsKeyDown(InputType.Aim) && reloadTimer <= 0 && (picker.SelectedConstruction == null || picker.SelectedConstruction.GetComponent() != null); - if (aim) + if (picker.IsKeyDown(InputType.Aim) && reloadTimer <= 0) { hitPos = MathUtils.WrapAnglePi(Math.Min(hitPos + deltaTime * 5f, MathHelper.PiOver4)); ac.HoldItem(deltaTime, item, handlePos, aimPos, Vector2.Zero, false, hitPos, holdAngle + hitPos); diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RangedWeapon.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RangedWeapon.cs index daa4a5a89..ca790d3c6 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RangedWeapon.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RangedWeapon.cs @@ -1,4 +1,5 @@ -using FarseerPhysics; +using Barotrauma.Networking; +using FarseerPhysics; using FarseerPhysics.Collision; using FarseerPhysics.Dynamics; using Microsoft.Xna.Framework; @@ -166,11 +167,12 @@ namespace Barotrauma.Items.Components //set the rotation of the projectile again because dropping the projectile resets the rotation projectile.Item.SetTransform(projectilePos, - rotation + ((item.body.Dir == 1.0f) ? projectile.LaunchRotationRadians : projectile.LaunchRotationRadians - MathHelper.Pi)); + rotation + (projectile.Item.body.Dir * projectile.LaunchRotationRadians)); //recoil item.body.ApplyLinearImpulse( - new Vector2((float)Math.Cos(projectile.Item.body.Rotation), (float)Math.Sin(projectile.Item.body.Rotation)) * item.body.Mass * -50.0f); + new Vector2((float)Math.Cos(projectile.Item.body.Rotation), (float)Math.Sin(projectile.Item.body.Rotation)) * item.body.Mass * -50.0f, + maxVelocity: NetConfig.MaxPhysicsBodyVelocity); item.RemoveContained(projectile.Item); diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs index 5cd310ad7..6251f88b1 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs @@ -79,8 +79,7 @@ namespace Barotrauma.Items.Components break; } } - item.IsShootable = true; - item.RequireAimToUse = true; + InitProjSpecific(element); } @@ -312,10 +311,7 @@ namespace Barotrauma.Items.Components sinTime += deltaTime; character.CursorPosition = leak.Position + VectorExtensions.Forward(Item.body.TransformedRotation + (float)Math.Sin(sinTime), dist); - if (item.RequireAimToUse) - { - character.SetInput(InputType.Aim, false, true); - } + character.SetInput(InputType.Aim, false, true); // Press the trigger only when the tool is approximately facing the target. // If the character is climbing, ignore the check, because we cannot aim while climbing. diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Throwable.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Throwable.cs index 6af9e1527..7e29caa55 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Throwable.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/Throwable.cs @@ -107,10 +107,10 @@ namespace Barotrauma.Items.Components #endif Character thrower = picker; item.Drop(thrower, createNetworkEvent: GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer); - item.body.ApplyLinearImpulse(throwVector * throwForce * item.body.Mass * 3.0f); + item.body.ApplyLinearImpulse(throwVector * throwForce * item.body.Mass * 3.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity); - ac.GetLimb(LimbType.Head).body.ApplyLinearImpulse(throwVector*10.0f); - ac.GetLimb(LimbType.Torso).body.ApplyLinearImpulse(throwVector * 10.0f); + ac.GetLimb(LimbType.Head).body.ApplyLinearImpulse(throwVector * 10.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity); + ac.GetLimb(LimbType.Torso).body.ApplyLinearImpulse(throwVector * 10.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity); Limb rightHand = ac.GetLimb(LimbType.RightHand); item.body.AngularVelocity = rightHand.body.AngularVelocity; diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Fabricator.cs index 562cd475f..80b083a3e 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Fabricator.cs @@ -210,13 +210,8 @@ namespace Barotrauma.Items.Components { Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, outputContainer.Inventory, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition); } - - bool isNotClient = true; -#if CLIENT - isNotClient = GameMain.Client == null; -#endif - - if (isNotClient && user != null) + + if ((GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer) && user != null && !user.Removed) { foreach (Skill skill in fabricatedItem.RequiredSkills) { diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Projectile.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Projectile.cs index f53a6a6bb..596e50d1e 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Projectile.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Projectile.cs @@ -377,23 +377,14 @@ namespace Barotrauma.Items.Components target.Body.ApplyLinearImpulse(item.body.LinearVelocity * item.body.Mass); return true; } - else if (target.Body.UserData is Limb limb) - { - //severed limbs don't deactivate the projectile (but may still slow it down enough to make it inactive) - if (limb.IsSevered) - { - target.Body.ApplyLinearImpulse(item.body.LinearVelocity * item.body.Mass); - return true; - } - limb.character.LastDamageSource = item; - attackResult = attack.DoDamageToLimb(User, limb, item.WorldPosition, 1.0f); - if (limb.character != null) character = limb.character; - } - else if (target.Body.UserData is Structure structure) - { - attackResult = attack.DoDamage(User, structure, item.WorldPosition, 1.0f); - } + limb.character.LastDamageSource = item; + if (attack != null) { attackResult = attack.DoDamageToLimb(User, limb, item.WorldPosition, 1.0f); } + if (limb.character != null) { character = limb.character; } + } + else if (target.Body.UserData is Structure structure) + { + if (attack != null) { attackResult = attack.DoDamage(User, structure, item.WorldPosition, 1.0f); } } if (character != null) character.LastDamageSource = item; diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/LightComponent.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/LightComponent.cs index 30c1a1d15..7845f609c 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/LightComponent.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/LightComponent.cs @@ -22,6 +22,10 @@ namespace Barotrauma.Items.Components private float blinkTimer; + private bool itemLoaded; + + private float blinkTimer; + public PhysicsBody ParentBody; [Editable(MinValueFloat = 0.0f, MaxValueFloat = 2048.0f), Serialize(100.0f, true)] @@ -77,7 +81,7 @@ namespace Barotrauma.Items.Components IsActive = value; #if SERVER - if (GameMain.Server != null && GameMain.Server.GameStarted) { item.CreateServerEvent(this); } + if (GameMain.Server != null && itemLoaded) { item.CreateServerEvent(this); } #endif } } diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/Wire.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/Wire.cs index 8b89d237a..0d76efa20 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/Wire.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/Wire.cs @@ -315,7 +315,7 @@ namespace Barotrauma.Items.Components Vector2 diff = nodes[nodes.Count - 1] - newNodePos; Vector2 pullBackDir = diff == Vector2.Zero ? Vector2.Zero : Vector2.Normalize(diff); - user.AnimController.Collider.ApplyForce(pullBackDir * user.Mass * 50.0f); + user.AnimController.Collider.ApplyForce(pullBackDir * user.Mass * 50.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity); user.AnimController.UpdateUseItem(true, user.WorldPosition + pullBackDir * 200.0f); if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer) diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Turret.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Turret.cs index 202f33fd1..91255ae23 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Turret.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Turret.cs @@ -163,8 +163,7 @@ namespace Barotrauma.Items.Components break; } } - item.IsShootable = true; - item.RequireAimToUse = false; + InitProjSpecific(element); } @@ -489,10 +488,7 @@ 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); - } + character.SetInput(InputType.Aim, false, true); float enemyAngle = MathUtils.VectorToAngle(closestEnemy.WorldPosition - item.WorldPosition); float turretAngle = -rotation; @@ -505,7 +501,7 @@ namespace Barotrauma.Items.Components if (objective.Option.ToLowerInvariant() == "fireatwill") { character?.Speak(TextManager.Get("DialogFireTurret").Replace("[itemname]", item.Name), null, 0.0f, "fireturret", 5.0f); - character.SetInput(InputType.Shoot, true, true); + character.SetInput(InputType.Use, true, true); } return false; diff --git a/Barotrauma/BarotraumaShared/Source/Items/Item.cs b/Barotrauma/BarotraumaShared/Source/Items/Item.cs index d9dc33341..af3fd92ae 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Item.cs @@ -235,30 +235,6 @@ namespace Barotrauma set { /*do nothing*/ } } - /// - /// Should the item's Use method be called with the "Use" or with the "Shoot" key? - /// - [Serialize(false, false)] - public bool IsShootable { get; set; } - - /// - /// If true, the user has to hold the "aim" key before use is registered. False by default. - /// - [Serialize(false, false)] - public bool RequireAimToUse - { - get; set; - } - - /// - /// If true, the user has to hold the "aim" key before secondary use is registered. True by default. - /// - [Serialize(true, false)] - public bool RequireAimToSecondaryUse - { - get; set; - } - public Color Color { get { return spriteColor; } @@ -1151,6 +1127,12 @@ namespace Barotrauma return; } + float forceFactor = 1.0f; + if (CurrentHull != null) + { + return; + } + float forceFactor = 1.0f; if (CurrentHull != null) { @@ -1395,40 +1377,20 @@ namespace Barotrauma } else { - if (picker.IsKeyDown(InputType.Aim)) + if (forceSelectKey) { - pickHit = false; - selectHit = false; + if (ic.PickKey == InputType.Select) pickHit = true; + if (ic.SelectKey == InputType.Select) selectHit = true; + } + else if (forceActionKey) + { + if (ic.PickKey == InputType.Use) pickHit = true; + if (ic.SelectKey == InputType.Use) selectHit = true; } else { - if (forceSelectKey) - { - if (ic.PickKey == InputType.Select) pickHit = true; - if (ic.SelectKey == InputType.Select) selectHit = true; - } - else if (forceActionKey) - { - if (ic.PickKey == InputType.Use) pickHit = true; - if (ic.SelectKey == InputType.Use) selectHit = true; - } - else - { - pickHit = picker.IsKeyHit(ic.PickKey); - selectHit = picker.IsKeyHit(ic.SelectKey); - -#if CLIENT - //if the cursor is on a UI component, disable interaction with the left mouse button - //to prevent accidentally selecting items when clicking UI elements - if (picker == Character.Controlled && GUI.MouseOn != null) - { - if (GameMain.Config.KeyBind(ic.PickKey).MouseButton == 0) pickHit = false; - if (GameMain.Config.KeyBind(ic.SelectKey).MouseButton == 0) selectHit = false; - } -#endif - } - } - } + pickHit = picker.IsKeyHit(ic.PickKey); + selectHit = picker.IsKeyHit(ic.SelectKey); #if CLIENT //if the cursor is on a UI component, disable interaction with the left mouse button @@ -1442,6 +1404,9 @@ namespace Barotrauma } } + + if (!pickHit && !selectHit) continue; + if (!ic.HasRequiredSkills(picker, out Skill tempRequiredSkill)) hasRequiredSkills = false; bool showUiMsg = false; @@ -1491,6 +1456,7 @@ namespace Barotrauma return true; } + public void Use(float deltaTime, Character character = null, Limb targetLimb = null) { if (RequireAimToUse && !character.IsKeyDown(InputType.Aim)) @@ -1641,6 +1607,8 @@ namespace Barotrauma GameMain.NetworkMember != null && (GameMain.NetworkMember.IsServer || Character.Controlled == dropper)) { parentInventory.CreateNetworkEvent(); + //send frequent updates after the item has been dropped + PositionUpdateInterval = 0.0f; } } diff --git a/Barotrauma/BarotraumaShared/Source/Map/Hull.cs b/Barotrauma/BarotraumaShared/Source/Map/Hull.cs index c3e9b1eae..cc1b0cbbd 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Hull.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Hull.cs @@ -568,7 +568,7 @@ namespace Barotrauma public void Extinguish(float deltaTime, float amount, Vector2 position) { - for (int i = FireSources.Count - 1; i >= 0; i-- ) + for (int i = FireSources.Count - 1; i >= 0; i--) { FireSources[i].Extinguish(deltaTime, amount, position); } diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelObjectPrefab.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelObjectPrefab.cs index 79c61f55e..34d0f2991 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelObjectPrefab.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelObjectPrefab.cs @@ -331,13 +331,13 @@ namespace Barotrauma switch (subElement.Name.ToString().ToLowerInvariant()) { case "sprite": - Sprite = new Sprite(subElement); + Sprite = new Sprite(subElement, lazyLoad: true); break; case "specularsprite": - SpecularSprite = new Sprite(subElement); + SpecularSprite = new Sprite(subElement, lazyLoad: true); break; case "deformablesprite": - DeformableSprite = new DeformableSprite(subElement); + DeformableSprite = new DeformableSprite(subElement, lazyLoad: true); break; case "overridecommonness": string levelType = subElement.GetAttributeString("leveltype", ""); diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelTrigger.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelTrigger.cs index 1c3ec2339..0bcb4a4e7 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelTrigger.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelTrigger.cs @@ -543,19 +543,19 @@ namespace Barotrauma if (ForceVelocityLimit < 1000.0f) body.ApplyForce(Force * currentForceFluctuation * distFactor, ForceVelocityLimit); else - body.ApplyForce(Force * currentForceFluctuation * distFactor); + body.ApplyForce(Force * currentForceFluctuation * distFactor, maxVelocity: NetConfig.MaxPhysicsBodyVelocity); break; case TriggerForceMode.Acceleration: if (ForceVelocityLimit < 1000.0f) body.ApplyForce(Force * body.Mass * currentForceFluctuation * distFactor, ForceVelocityLimit); else - body.ApplyForce(Force * body.Mass * currentForceFluctuation * distFactor); + body.ApplyForce(Force * body.Mass * currentForceFluctuation * distFactor, maxVelocity: NetConfig.MaxPhysicsBodyVelocity); break; case TriggerForceMode.Impulse: if (ForceVelocityLimit < 1000.0f) - body.ApplyLinearImpulse(Force * currentForceFluctuation * distFactor, ForceVelocityLimit); + body.ApplyLinearImpulse(Force * currentForceFluctuation * distFactor, maxVelocity: ForceVelocityLimit); else - body.ApplyLinearImpulse(Force * currentForceFluctuation * distFactor); + body.ApplyLinearImpulse(Force * currentForceFluctuation * distFactor, maxVelocity: NetConfig.MaxPhysicsBodyVelocity); break; case TriggerForceMode.LimitVelocity: float maxVel = ForceVelocityLimit * currentForceFluctuation * distFactor; @@ -563,7 +563,8 @@ namespace Barotrauma { body.ApplyForce( Vector2.Normalize(-body.LinearVelocity) * - Force.Length() * body.Mass * currentForceFluctuation * distFactor); + Force.Length() * body.Mass * currentForceFluctuation * distFactor, + maxVelocity: NetConfig.MaxPhysicsBodyVelocity); } break; } diff --git a/Barotrauma/BarotraumaShared/Source/Map/Map/LocationType.cs b/Barotrauma/BarotraumaShared/Source/Map/Map/LocationType.cs index aecfd8149..7e22a1f71 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Map/LocationType.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Map/LocationType.cs @@ -126,7 +126,7 @@ namespace Barotrauma CanChangeTo.Add(new LocationTypeChange(Identifier, subElement)); break; case "portrait": - var portrait = new Sprite(subElement); + var portrait = new Sprite(subElement, lazyLoad: true); if (portrait != null) { portraits.Add(portrait); diff --git a/Barotrauma/BarotraumaShared/Source/Physics/PhysicsBody.cs b/Barotrauma/BarotraumaShared/Source/Physics/PhysicsBody.cs index 0f4a6a40b..b8823bf70 100644 --- a/Barotrauma/BarotraumaShared/Source/Physics/PhysicsBody.cs +++ b/Barotrauma/BarotraumaShared/Source/Physics/PhysicsBody.cs @@ -605,7 +605,7 @@ namespace Barotrauma { if (!IsValidValue(impulse, "impulse", -1e10f, 1e10f)) return; if (!IsValidValue(point, "point")) return; - if (!IsValidValue(impulse / body.Mass, "new velocity")) return; + if (!IsValidValue(impulse / body.Mass, "new velocity", -1000.0f, 1000.0f)) return; body.ApplyLinearImpulse(impulse, point); } @@ -646,15 +646,20 @@ namespace Barotrauma /// public void ApplyForce(Vector2 force, float maxVelocity) { - if (!IsValidValue(force, "force", -1e10f, 1e10f)) return; if (!IsValidValue(maxVelocity, "max velocity")) return; - float currSpeed = body.LinearVelocity.Length(); Vector2 velocityAddition = force / Mass * (float)Timing.Step; Vector2 newVelocity = body.LinearVelocity + velocityAddition; - newVelocity = newVelocity.ClampLength(Math.Max(currSpeed, maxVelocity)); + + float newSpeedSqr = newVelocity.LengthSquared(); + if (newSpeedSqr > maxVelocity * maxVelocity) + { + newVelocity = newVelocity.ClampLength(maxVelocity); + } - body.ApplyForce((newVelocity - body.LinearVelocity) * Mass / (float)Timing.Step); + Vector2 clampedForce = (newVelocity - body.LinearVelocity) * Mass / (float)Timing.Step; + if (!IsValidValue(force, "clamped force", -1e10f, 1e10f)) return; + body.ApplyForce(force); } public void ApplyForce(Vector2 force, Vector2 point) diff --git a/Barotrauma/BarotraumaShared/Source/PlayerInput.cs b/Barotrauma/BarotraumaShared/Source/PlayerInput.cs index 0898b8588..6de3c7927 100644 --- a/Barotrauma/BarotraumaShared/Source/PlayerInput.cs +++ b/Barotrauma/BarotraumaShared/Source/PlayerInput.cs @@ -15,9 +15,7 @@ namespace Barotrauma Ragdoll, Health, Grab, SelectNextCharacter, SelectPreviousCharacter, - Voice, - Deselect, - Shoot + Voice } public class KeyOrMouse diff --git a/Barotrauma/BarotraumaShared/Source/Sprite/DeformableSprite.cs b/Barotrauma/BarotraumaShared/Source/Sprite/DeformableSprite.cs index aad048132..81ed6f9e8 100644 --- a/Barotrauma/BarotraumaShared/Source/Sprite/DeformableSprite.cs +++ b/Barotrauma/BarotraumaShared/Source/Sprite/DeformableSprite.cs @@ -5,30 +5,25 @@ namespace Barotrauma { partial class DeformableSprite { - private Sprite sprite; - public Vector2 Size { - get { return sprite.size; } + get { return Sprite.size; } } public Vector2 Origin { - get { return sprite.Origin; } - set { sprite.Origin = value; } + get { return Sprite.Origin; } + set { Sprite.Origin = value; } } - public Sprite Sprite + public Sprite Sprite { get; private set; } + + public DeformableSprite(XElement element, int? subdivisionsX = null, int? subdivisionsY = null, string filePath = "", bool lazyLoad = false) { - get { return sprite; } + Sprite = new Sprite(element, file: filePath, lazyLoad: lazyLoad); + InitProjSpecific(element, subdivisionsX, subdivisionsY, lazyLoad); } - public DeformableSprite(XElement element, int? subdivisionsX = null, int? subdivisionsY = null, string filePath = "") - { - sprite = new Sprite(element, file: filePath); - InitProjSpecific(element, subdivisionsX, subdivisionsY); - } - - partial void InitProjSpecific(XElement element, int? subdivisionsX, int? subdivisionsY); + partial void InitProjSpecific(XElement element, int? subdivisionsX, int? subdivisionsY, bool lazyLoad = false); } } diff --git a/Barotrauma/BarotraumaShared/Source/Sprite/Sprite.cs b/Barotrauma/BarotraumaShared/Source/Sprite/Sprite.cs index 445129402..7862e4e82 100644 --- a/Barotrauma/BarotraumaShared/Source/Sprite/Sprite.cs +++ b/Barotrauma/BarotraumaShared/Source/Sprite/Sprite.cs @@ -103,8 +103,9 @@ namespace Barotrauma partial void LoadTexture(ref Vector4 sourceVector, ref bool shouldReturn, bool premultiplyAlpha = true); partial void CalculateSourceRect(); - public Sprite(XElement element, string path = "", string file = "") + public Sprite(XElement element, string path = "", string file = "", bool? preMultiplyAlpha = null, bool lazyLoad = false) { + this.lazyLoad = lazyLoad; SourceElement = element; if (file == "") { @@ -127,8 +128,12 @@ namespace Barotrauma Name = SourceElement.GetAttributeString("name", null); Vector4 sourceVector = SourceElement.GetAttributeVector4("sourcerect", Vector4.Zero); + preMultipliedAlpha = preMultiplyAlpha ?? SourceElement.GetAttributeBool("premultiplyalpha", true); bool shouldReturn = false; - LoadTexture(ref sourceVector, ref shouldReturn, SourceElement.GetAttributeBool("premultiplyalpha", true)); + if (!lazyLoad) + { + LoadTexture(ref sourceVector, ref shouldReturn, preMultipliedAlpha); + } if (shouldReturn) return; sourceRect = new Rectangle((int)sourceVector.X, (int)sourceVector.Y, (int)sourceVector.Z, (int)sourceVector.W); size = SourceElement.GetAttributeVector2("size", Vector2.One); diff --git a/Barotrauma/BarotraumaShared/Source/SteamAchievementManager.cs b/Barotrauma/BarotraumaShared/Source/SteamAchievementManager.cs index 04e32f2d0..8ab8db1a8 100644 --- a/Barotrauma/BarotraumaShared/Source/SteamAchievementManager.cs +++ b/Barotrauma/BarotraumaShared/Source/SteamAchievementManager.cs @@ -31,6 +31,8 @@ namespace Barotrauma public readonly HashSet ReactorMeltdown = new HashSet(); public readonly HashSet Casualties = new HashSet(); + + public bool SubWasDamaged; } private static RoundData roundData; @@ -110,7 +112,47 @@ namespace Barotrauma UnlockAchievement("subdeep", true, c => c != null && c.Submarine == sub && !c.IsDead && !c.IsUnconscious); } } - } + + if (!roundData.SubWasDamaged) + { + roundData.SubWasDamaged = SubWallsDamaged(Submarine.MainSub); + } + } + + if (GameMain.GameSession != null && Character.Controlled != null) + { + if (Character.Controlled.HasEquippedItem("clownmask") && + Character.Controlled.HasEquippedItem("clowncostume")) + { + UnlockAchievement(Character.Controlled, "clowncostume"); + } + + if (Submarine.MainSub != null && Character.Controlled.Submarine == null) + { + float dist = 500 / Physics.DisplayToRealWorldRatio; + if (Vector2.DistanceSquared(Character.Controlled.WorldPosition, Submarine.MainSub.WorldPosition) > + dist * dist) + { + UnlockAchievement(Character.Controlled, "crewaway"); + } + } + } + } + + private static bool SubWallsDamaged(Submarine sub) + { + foreach (Structure structure in Structure.WallList) + { + if (structure.Submarine != sub || structure.HasBody) { continue; } + for (int i = 0; i < structure.SectionCount; i++) + { + if (structure.SectionIsLeaking(i)) + { + return true; + } + } + } + return false; } public static void OnBiomeDiscovered(Biome biome) @@ -274,14 +316,21 @@ namespace Barotrauma //made it to the destination if (gameSession.Submarine.AtEndPosition) { + bool noDamageRun = !roundData.SubWasDamaged && !roundData.Casualties.Any(c => !(c.AIController is EnemyAIController)); + #if SERVER if (GameMain.Server != null) { //in MP all characters that were inside the sub during reactor meltdown and still alive at the end of the round get an achievement UnlockAchievement("survivereactormeltdown", true, c => c != null && !c.IsDead && roundData.ReactorMeltdown.Contains(c)); + if (noDamageRun) + { + UnlockAchievement("nodamagerun", true, c => c != null && !c.IsDead); + } } #endif #if CLIENT + if (noDamageRun) { UnlockAchievement("nodamagerun"); } if (roundData.ReactorMeltdown.Any()) //in SP getting to the destination after a meltdown is enough { UnlockAchievement("survivereactormeltdown"); @@ -302,6 +351,11 @@ namespace Barotrauma UnlockAchievement(charactersInSub[0], "lonesailor"); } } + foreach (Character character in charactersInSub) + { + if (character.Info.Job == null) { continue; } + UnlockAchievement(character, character.Info.Job.Prefab.Identifier + "round"); + } } } diff --git a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub index 6403c9fd9..4ac57dc62 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub and b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Remora.sub b/Barotrauma/BarotraumaShared/Submarines/Remora.sub index ede107e94..54b336683 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Remora.sub and b/Barotrauma/BarotraumaShared/Submarines/Remora.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Venture.sub b/Barotrauma/BarotraumaShared/Submarines/Venture.sub index 2ed054c24..188b52454 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Venture.sub and b/Barotrauma/BarotraumaShared/Submarines/Venture.sub differ diff --git a/Barotrauma/BarotraumaShared/config.xml b/Barotrauma/BarotraumaShared/config.xml index ad11bfb26..86606c419 100644 --- a/Barotrauma/BarotraumaShared/config.xml +++ b/Barotrauma/BarotraumaShared/config.xml @@ -23,8 +23,8 @@