(b451554e8) Merge remote-tracking branch 'origin/dev' into keymapping-refactor-test

This commit is contained in:
Joonas Rikkonen
2019-04-04 11:10:29 +03:00
parent b08a31a68f
commit cc122f2bbf
52 changed files with 601 additions and 786 deletions
+6 -3
View File
@@ -8,11 +8,14 @@ namespace Barotrauma
{ {
public static bool FollowSub = true; public static bool FollowSub = true;
private float defaultZoom = 1.3f; private float? defaultZoom;
public float DefaultZoom public float DefaultZoom
{ {
get { return defaultZoom; } get { return defaultZoom ?? (GameMain.Config == null || GameMain.Config.EnableMouseLook ? 1.3f : 1.0f); }
set { defaultZoom = MathHelper.Clamp(value, 0.5f, 2.0f); } set
{
defaultZoom = MathHelper.Clamp(value, 0.5f, 2.0f);
}
} }
private float zoomSmoothness = 8.0f; private float zoomSmoothness = 8.0f;
@@ -23,6 +23,8 @@ namespace Barotrauma
protected float hudInfoTimer; protected float hudInfoTimer;
protected bool hudInfoVisible; protected bool hudInfoVisible;
private float pressureParticleTimer;
private float findFocusedTimer; private float findFocusedTimer;
protected float lastRecvPositionUpdateTime; protected float lastRecvPositionUpdateTime;
@@ -165,27 +167,38 @@ namespace Barotrauma
keys[i].SetState(); keys[i].SetState();
} }
float targetOffsetAmount = 0.0f;
if (moveCam) if (moveCam)
{ {
if (needsAir && if (needsAir &&
pressureProtection < 80.0f && 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; 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, pressureParticleTimer += pressure * deltaTime;
(pressure / 50.0f) * Rand.Range(1.0f, 1.05f), if (pressureParticleTimer > 10.0f)
(pressure - 50.0f) / 50.0f); {
Particle p = GameMain.ParticleManager.CreateParticle("waterblood", WorldPosition + Rand.Vector(5.0f), Rand.Vector(10.0f));
pressureParticleTimer = 0.0f;
}
}
} }
if (IsHumanoid) if (IsHumanoid)
{ {
cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, 250.0f, deltaTime); cam.OffsetAmount = 250.0f;// MathHelper.Lerp(cam.OffsetAmount, 250.0f, deltaTime);
} }
else else
{ {
//increased visibility range when controlling large a non-humanoid //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,36 +211,49 @@ namespace Barotrauma
Vector2 mouseSimPos = ConvertUnits.ToSimUnits(cursorPosition); Vector2 mouseSimPos = ConvertUnits.ToSimUnits(cursorPosition);
if (GUI.PauseMenuOpen) if (GUI.PauseMenuOpen)
{ {
targetOffsetAmount = 0.0f;
cam.OffsetAmount = 0.0f; cam.OffsetAmount = 0.0f;
} }
else if (SelectedConstruction != null && ViewTarget == null && else if (SelectedConstruction != null && ViewTarget == null &&
SelectedConstruction.Components.Any(ic => ic?.GuiFrame != null && ic.ShouldDrawHUD(this))) SelectedConstruction.Components.Any(ic => ic?.GuiFrame != null && ic.ShouldDrawHUD(this)))
{ {
targetOffsetAmount = 0.0f;
cam.OffsetAmount = 0.0f; cam.OffsetAmount = 0.0f;
cursorPosition = cursorPosition =
SelectedConstruction.Position + 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 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) else if (Lights.LightManager.ViewTarget == this && Vector2.DistanceSquared(AnimController.Limbs[0].SimPosition, mouseSimPos) > 1.0f)
{ {
if (GUI.PauseMenuOpen || IsUnconscious) if (GUI.PauseMenuOpen || IsUnconscious)
{ {
if (deltaTime > 0.0f) cam.OffsetAmount = 0.0f; if (deltaTime > 0.0f)
{
targetOffsetAmount = 0.0f;
cam.OffsetAmount = 0.0f;
}
} }
else else
{ {
Body body = Submarine.CheckVisibility(AnimController.Limbs[0].SimPosition, mouseSimPos); 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; float sightDist = Submarine.LastPickedFraction;
if (body?.UserData is Structure && !((Structure)body.UserData).CastShadow) if (body?.UserData is Structure && !((Structure)body.UserData).CastShadow)
{ {
sightDist = 1.0f; 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 (SelectedConstruction != null && SelectedConstruction.ActiveHUDs.Any(ic => ic.GuiFrame != null && HUD.CloseHUD(ic.GuiFrame.Rect)))
{ {
if (GameMain.Client != null) if (GameMain.Client != null)
@@ -21,6 +21,8 @@ namespace Barotrauma
public bool CanBeSelected = true; public bool CanBeSelected = true;
private Color? defaultTextColor;
public override bool Enabled public override bool Enabled
{ {
get get
@@ -30,7 +32,7 @@ namespace Barotrauma
set set
{ {
if (value == enabled) return; if (value == enabled) { return; }
enabled = value; enabled = value;
if (color.A == 0) if (color.A == 0)
{ {
@@ -70,6 +70,7 @@ namespace Barotrauma
private GUIImage(RectTransform rectT, Sprite sprite, Rectangle? sourceRect, bool scaleToFit, string style) : base(style, rectT) private GUIImage(RectTransform rectT, Sprite sprite, Rectangle? sourceRect, bool scaleToFit, string style) : base(style, rectT)
{ {
this.scaleToFit = scaleToFit; this.scaleToFit = scaleToFit;
sprite?.EnsureLazyLoaded();
Sprite = sprite; Sprite = sprite;
if (sourceRect.HasValue) if (sourceRect.HasValue)
{ {
@@ -506,7 +506,7 @@ namespace Barotrauma
{ {
if (ScrollBar.IsHorizontal) if (ScrollBar.IsHorizontal)
{ {
if (pos + child.Rect.Height + spacing > Content.Rect.Height || child == children.Last()) if (pos + child.Rect.Height + spacing > Content.Rect.Height)
{ {
pos = 0; pos = 0;
totalSize += child.Rect.Width + spacing; totalSize += child.Rect.Width + spacing;
@@ -515,10 +515,14 @@ namespace Barotrauma
{ {
pos += child.Rect.Height + spacing; pos += child.Rect.Height + spacing;
} }
if (child == children.Last())
{
totalSize += child.Rect.Width + spacing;
}
} }
else else
{ {
if (pos + child.Rect.Width + spacing > Content.Rect.Width || child == children.Last()) if (pos + child.Rect.Width + spacing > Content.Rect.Width)
{ {
pos = 0; pos = 0;
totalSize += child.Rect.Height + spacing; totalSize += child.Rect.Height + spacing;
@@ -527,6 +531,11 @@ namespace Barotrauma
{ {
pos += child.Rect.Width + spacing; pos += child.Rect.Width + spacing;
} }
if (child == children.Last())
{
totalSize += child.Rect.Height + spacing;
}
} }
} }
} }
@@ -624,9 +624,10 @@ namespace Barotrauma.Tutorials
private Character CrewMemberWithJob(string job) private Character CrewMemberWithJob(string job)
{ {
job = job.ToLowerInvariant();
for (int i = 0; i < crew.Count; i++) 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; return null;
@@ -94,7 +94,7 @@ namespace Barotrauma
foreach (ContentPackage contentPackage in ContentPackage.List) 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, UserData = contentPackage,
OnSelected = SelectContentPackage, OnSelected = SelectContentPackage,
@@ -167,11 +167,11 @@ namespace Barotrauma
/// Graphics tab -------------------------------------------------------------- /// Graphics tab --------------------------------------------------------------
var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Graphics].RectTransform, Anchor.CenterLeft) var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Graphics].RectTransform, Anchor.TopLeft)
{ RelativeOffset = new Vector2(0.02f, 0.0f) }) { RelativeOffset = new Vector2(0.025f, 0.02f) })
{ RelativeSpacing = 0.01f }; { RelativeSpacing = 0.01f };
var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Graphics].RectTransform, Anchor.CenterRight) var rightColumn = new GUILayoutGroup(new RectTransform(new Vector2(0.46f, 0.95f), tabs[(int)Tab.Graphics].RectTransform, Anchor.TopRight)
{ RelativeOffset = new Vector2(0.02f, 0.0f) }) { RelativeOffset = new Vector2(0.025f, 0.02f) })
{ RelativeSpacing = 0.01f }; { RelativeSpacing = 0.01f };
var supportedDisplayModes = new List<DisplayMode>(); var supportedDisplayModes = new List<DisplayMode>();
@@ -368,12 +368,12 @@ namespace Barotrauma
/// Audio tab ---------------------------------------------------------------- /// 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) }) { RelativeOffset = new Vector2(0.0f, 0.02f) })
{ RelativeSpacing = 0.01f }; { RelativeSpacing = 0.01f };
GUITextBlock soundVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), audioSliders.RectTransform), TextManager.Get("SoundVolume")); 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.1f), audioSliders.RectTransform), GUIScrollBar soundScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform),
barSize: 0.05f) barSize: 0.05f)
{ {
UserData = soundVolumeText, UserData = soundVolumeText,
@@ -388,8 +388,8 @@ namespace Barotrauma
}; };
soundScrollBar.OnMoved(soundScrollBar, soundScrollBar.BarScroll); soundScrollBar.OnMoved(soundScrollBar, soundScrollBar.BarScroll);
GUITextBlock musicVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), audioSliders.RectTransform), TextManager.Get("MusicVolume")); 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.1f), audioSliders.RectTransform), GUIScrollBar musicScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform),
barSize: 0.05f) barSize: 0.05f)
{ {
UserData = musicVolumeText, UserData = musicVolumeText,
@@ -404,8 +404,8 @@ namespace Barotrauma
}; };
musicScrollBar.OnMoved(musicScrollBar, musicScrollBar.BarScroll); musicScrollBar.OnMoved(musicScrollBar, musicScrollBar.BarScroll);
GUITextBlock voiceChatVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), audioSliders.RectTransform), TextManager.Get("VoiceChatVolume")); 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.1f), audioSliders.RectTransform), GUIScrollBar voiceChatScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform),
barSize: 0.05f) barSize: 0.05f)
{ {
UserData = voiceChatVolumeText, UserData = voiceChatVolumeText,
@@ -426,11 +426,11 @@ namespace Barotrauma
muteOnFocusLostBox.OnSelected = (tickBox) => muteOnFocusLostBox.OnSelected = (tickBox) =>
{ {
MuteOnFocusLost = tickBox.Selected; MuteOnFocusLost = tickBox.Selected;
UnsavedSettings = true;
return 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<string> deviceNames = Alc.GetString((IntPtr)null, AlcGetStringList.CaptureDeviceSpecifier); IList<string> deviceNames = Alc.GetString((IntPtr)null, AlcGetStringList.CaptureDeviceSpecifier);
foreach (string name in deviceNames) foreach (string name in deviceNames)
@@ -440,7 +440,7 @@ namespace Barotrauma
if (string.IsNullOrWhiteSpace(VoiceCaptureDevice)) VoiceCaptureDevice = deviceNames[0]; if (string.IsNullOrWhiteSpace(VoiceCaptureDevice)) VoiceCaptureDevice = deviceNames[0];
#if (!OSX) #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) foreach (string name in deviceNames)
{ {
deviceList.AddItem(name, name); deviceList.AddItem(name, name);
@@ -454,13 +454,13 @@ namespace Barotrauma
return true; return true;
}; };
#else #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"), ToolTip = TextManager.Get("CurrentDeviceToolTip.OSX"),
TextAlignment = Alignment.CenterX 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"), ToolTip = TextManager.Get("RefreshDefaultDeviceToolTip"),
OnClicked = (bt, userdata) => OnClicked = (bt, userdata) =>
@@ -476,16 +476,13 @@ namespace Barotrauma
} }
}; };
#endif #endif
var radioButtonFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), audioSliders.RectTransform)) //var radioButtonFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.12f), audioSliders.RectTransform));
{
RelativeSpacing = 0.01f
};
GUIRadioButtonGroup voiceMode = new GUIRadioButtonGroup(); GUIRadioButtonGroup voiceMode = new GUIRadioButtonGroup();
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
string langStr = "VoiceMode." + ((VoiceMode)i).ToString(); 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") ToolTip = TextManager.Get(langStr + "ToolTip")
}; };
@@ -493,8 +490,8 @@ namespace Barotrauma
voiceMode.AddRadioButton((VoiceMode)i, tick); voiceMode.AddRadioButton((VoiceMode)i, tick);
} }
var micVolumeText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), audioSliders.RectTransform), TextManager.Get("MicrophoneVolume")); 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.1f), audioSliders.RectTransform), var micVolumeSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform),
barSize: 0.05f) barSize: 0.05f)
{ {
UserData = micVolumeText, UserData = micVolumeText,
@@ -511,9 +508,12 @@ namespace Barotrauma
}; };
micVolumeSlider.OnMoved(micVolumeSlider, micVolumeSlider.BarScroll); 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 extraVoiceSettingsContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), audioSliders.RectTransform, Anchor.BottomCenter), style: null);
var voiceKeyBox = new GUITextBox(new RectTransform(new Vector2(0.4f, 0.5f), voiceInputContainer.RectTransform, Anchor.TopRight),
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()) text: keyMapping[(int)InputType.Voice].ToString())
{ {
UserData = InputType.Voice UserData = InputType.Voice
@@ -521,22 +521,22 @@ namespace Barotrauma
voiceKeyBox.OnSelected += KeyBoxSelected; voiceKeyBox.OnSelected += KeyBoxSelected;
voiceKeyBox.SelectedColor = Color.Gold * 0.3f; voiceKeyBox.SelectedColor = Color.Gold * 0.3f;
var voiceActivityGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), audioSliders.RectTransform)); var voiceActivityGroup = new GUILayoutGroup(new RectTransform(Vector2.One, extraVoiceSettingsContainer.RectTransform));
GUITextBlock noiseGateText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), voiceActivityGroup.RectTransform), TextManager.Get("NoiseGateThreshold")) GUITextBlock noiseGateText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.25f), voiceActivityGroup.RectTransform), TextManager.Get("NoiseGateThreshold"))
{ {
TextGetter = () => TextGetter = () =>
{ {
return TextManager.Get("NoiseGateThreshold") + " " + ((int)NoiseGateThreshold).ToString() + " dB"; 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 = () => dbMeter.ProgressGetter = () =>
{ {
if (VoipCapture.Instance == null) return 0.0f; if (VoipCapture.Instance == null) return 0.0f;
dbMeter.Color = VoipCapture.Instance.LastdB > NoiseGateThreshold ? Color.Lime : Color.Orange; //TODO: i'm a filthy hack 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; 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.Frame.Visible = false;
noiseGateSlider.Step = 0.01f; noiseGateSlider.Step = 0.01f;
noiseGateSlider.Range = new Vector2(-100.0f, 0.0f); noiseGateSlider.Range = new Vector2(-100.0f, 0.0f);
@@ -592,8 +592,41 @@ namespace Barotrauma
voiceMode.Selected = VoiceSetting; voiceMode.Selected = VoiceSetting;
/// Controls tab ------------------------------------------------------------- /// Controls tab -------------------------------------------------------------
var controlsLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), tabs[(int)Tab.Controls].RectTransform, Anchor.Center)) var controlsLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), tabs[(int)Tab.Controls].RectTransform, Anchor.TopCenter)
{ RelativeSpacing = 0.01f }; { 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)) var inputFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.8f), controlsLayoutGroup.RectTransform))
{ Stretch = true }; { Stretch = true };
@@ -601,7 +634,7 @@ namespace Barotrauma
var inputNames = Enum.GetValues(typeof(InputType)); var inputNames = Enum.GetValues(typeof(InputType));
for (int i = 0; i < inputNames.Length; i++) 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) }, 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 }; TextManager.Get("InputType." + ((InputType)i)) + ": ", font: GUI.SmallFont) { ForceUpperCase = true };
var keyBox = new GUITextBox(new RectTransform(new Vector2(0.7f, 1.0f), inputContainer.RectTransform), var keyBox = new GUITextBox(new RectTransform(new Vector2(0.7f, 1.0f), inputContainer.RectTransform),
@@ -611,6 +644,9 @@ namespace Barotrauma
}; };
keyBox.OnSelected += KeyBoxSelected; keyBox.OnSelected += KeyBoxSelected;
keyBox.SelectedColor = Color.Gold * 0.3f; 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")); 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), GUIScrollBar aimAssistSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.05f), controlsLayoutGroup.RectTransform),
@@ -642,6 +678,22 @@ namespace Barotrauma
} }
}; };
new GUIButton(new RectTransform(new Vector2(0.25f, 0.07f), controlsLayoutGroup.RectTransform, Anchor.BottomRight), TextManager.Get("LegacyBindings"), style: "GUIButton")
{
IgnoreLayoutGroups = true,
OnClicked = (button, data) =>
{
// TODO: add a prompt?
SetDefaultBindings(legacy: true);
CheckBindings(true);
ApplySettings();
// TODO: refresh the settings frame instead of closing it.
if (Screen.Selected == GameMain.MainMenuScreen) GameMain.MainMenuScreen.ReturnToMainMenu(null, null);
GUI.SettingsMenuOpen = false;
return true;
}
};
//spacing //spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), generalLayoutGroup.RectTransform), style: null); new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), generalLayoutGroup.RectTransform), style: null);
@@ -672,7 +724,7 @@ namespace Barotrauma
CheckBindings(true); CheckBindings(true);
ApplySettings(); ApplySettings();
// TODO: refresh the settings frame instead of closing it. // TODO: refresh the settings frame instead of closing it.
GameMain.MainMenuScreen.ReturnToMainMenu(null, null); if (Screen.Selected == GameMain.MainMenuScreen) GameMain.MainMenuScreen.ReturnToMainMenu(null, null);
GUI.SettingsMenuOpen = false; GUI.SettingsMenuOpen = false;
return true; return true;
} }
@@ -880,8 +932,6 @@ namespace Barotrauma
ApplySettings(); ApplySettings();
if (Screen.Selected != GameMain.MainMenuScreen) GUI.SettingsMenuOpen = false; if (Screen.Selected != GameMain.MainMenuScreen) GUI.SettingsMenuOpen = false;
if (Screen.Selected != GameMain.MainMenuScreen) GUI.SettingsMenuOpen = false;
return true; return true;
} }
} }
@@ -17,6 +17,8 @@ namespace Barotrauma.Items.Components
private GUIButton activateButton; private GUIButton activateButton;
private GUITextBox itemFilterBox;
private GUIComponent inputInventoryHolder, outputInventoryHolder; private GUIComponent inputInventoryHolder, outputInventoryHolder;
private GUICustomComponent inputInventoryOverlay, outputInventoryOverlay; private GUICustomComponent inputInventoryOverlay, outputInventoryOverlay;
@@ -28,12 +30,25 @@ namespace Barotrauma.Items.Components
partial void InitProjSpecific() 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, Stretch = true,
RelativeSpacing = 0.02f 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)) itemList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.5f), paddedFrame.RectTransform))
{ {
OnSelected = (GUIComponent component, object userdata) => OnSelected = (GUIComponent component, object userdata) =>
@@ -50,7 +65,7 @@ namespace Barotrauma.Items.Components
CanBeFocused = false 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"); 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); 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) 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, UserData = fi,
HoverColor = Color.Gold * 0.2f, HoverColor = Color.Gold * 0.2f,
@@ -78,7 +93,7 @@ namespace Barotrauma.Items.Components
var itemIcon = fi.TargetItem.InventoryIcon ?? fi.TargetItem.sprite; var itemIcon = fi.TargetItem.InventoryIcon ?? fi.TargetItem.sprite;
if (itemIcon != null) 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) itemIcon, scaleToFit: true)
{ {
Color = fi.TargetItem.InventoryIconColor, 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), activateButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.07f), paddedFrame.RectTransform),
TextManager.Get("FabricatorCreate")) TextManager.Get("FabricatorCreate"), style: "GUIButtonLarge")
{ {
OnClicked = StartButtonClicked, OnClicked = StartButtonClicked,
UserData = selectedItem, 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) private bool SelectItem(Character user, FabricationRecipe selectedItem)
{ {
selectedItemFrame.ClearChildren(); selectedItemFrame.ClearChildren();
@@ -318,29 +371,7 @@ namespace Barotrauma.Items.Components
return true; return true;
} }
Rectangle slotRect = inputContainer.Inventory.slots[slotIndex].Rect; private bool StartButtonClicked(GUIButton button, object obj)
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<Rectangle, string>(slotRect, toolTipText);
}
slotIndex++;
}
}
}
private void DrawOutputOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
{ {
if (selectedItem == null) { return false; } if (selectedItem == null) { return false; }
if (!outputContainer.Inventory.IsEmpty()) if (!outputContainer.Inventory.IsEmpty())
@@ -353,19 +384,14 @@ namespace Barotrauma.Items.Components
{ {
StartFabricating(selectedItem, Character.Controlled); StartFabricating(selectedItem, Character.Controlled);
} }
else
if (tooltip != null)
{ {
GUIComponent.DrawToolTip(spriteBatch, tooltip.Second, tooltip.First); CancelFabricating(Character.Controlled);
tooltip = null;
} }
}
if (GameMain.Client != null) if (GameMain.Client != null)
{ {
FabricationRecipe recipe = child.UserData as FabricationRecipe; item.CreateClientEvent(this);
if (recipe?.DisplayName == null) { continue; }
child.Visible = recipe.DisplayName.ToLower().Contains(filter);
} }
itemList.UpdateScrollBarSize(); itemList.UpdateScrollBarSize();
itemList.BarScroll = 0.0f; itemList.BarScroll = 0.0f;
@@ -123,8 +123,16 @@ namespace Barotrauma
partial void InitProjSpecific() partial void InitProjSpecific()
{ {
Prefab.sprite?.EnsureLazyLoaded();
Prefab.InventoryIcon?.EnsureLazyLoaded();
foreach (BrokenItemSprite brokenSprite in Prefab.BrokenSprites)
{
brokenSprite.Sprite.EnsureLazyLoaded();
}
foreach (var decorativeSprite in ((ItemPrefab)prefab).DecorativeSprites) foreach (var decorativeSprite in ((ItemPrefab)prefab).DecorativeSprites)
{ {
decorativeSprite.Sprite.EnsureLazyLoaded();
spriteAnimState.Add(decorativeSprite, new SpriteState()); spriteAnimState.Add(decorativeSprite, new SpriteState());
} }
} }
@@ -607,6 +615,9 @@ namespace Barotrauma
if (GameMain.GameSession?.CrewManager != null) if (GameMain.GameSession?.CrewManager != null)
{ {
disallowedAreas.Add(GameMain.GameSession.CrewManager.GetCharacterListArea()); 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, GUI.PreventElementOverlap(elementsToMove, disallowedAreas,
@@ -28,12 +28,11 @@ namespace Barotrauma
public readonly string[] AllowedContainerIdentifiers; public readonly string[] AllowedContainerIdentifiers;
public readonly string[] AllowedContainerTags; public readonly string[] AllowedContainerTags;
public ContainedItemSprite(XElement element, string path = "") public ContainedItemSprite(XElement element, string path = "", bool lazyLoad = false)
{ {
Sprite = new Sprite(element, path); Sprite = new Sprite(element, path, lazyLoad: lazyLoad);
AllowedContainerIdentifiers = element.GetAttributeStringArray("allowedcontaineridentifiers", new string[0], convertToLowerInvariant: true); AllowedContainerIdentifiers = element.GetAttributeStringArray("allowedcontaineridentifiers", new string[0], convertToLowerInvariant: true);
AllowedContainerTags = element.GetAttributeStringArray("allowedcontainertags", new string[0], convertToLowerInvariant: true); AllowedContainerTags = element.GetAttributeStringArray("allowedcontainertags", new string[0], convertToLowerInvariant: true);
} }
public bool MatchesContainer(Item container) public bool MatchesContainer(Item container)
@@ -101,9 +100,9 @@ namespace Barotrauma
/// </summary> /// </summary>
public List<PropertyConditional> AnimationConditionals { get; private set; } = new List<PropertyConditional>(); public List<PropertyConditional> AnimationConditionals { get; private set; } = new List<PropertyConditional>();
public DecorativeSprite(XElement element, string path = "") public DecorativeSprite(XElement element, string path = "", bool lazyLoad = false)
{ {
Sprite = new Sprite(element, path); Sprite = new Sprite(element, path, lazyLoad: lazyLoad);
SerializableProperty.DeserializeProperties(this, element); SerializableProperty.DeserializeProperties(this, element);
foreach (XElement subElement in element.Elements()) foreach (XElement subElement in element.Elements())
@@ -76,6 +76,10 @@ namespace Barotrauma
partial void InitProjSpecific() partial void InitProjSpecific()
{ {
Prefab.Sprite?.EnsureLazyLoaded();
Prefab.SpecularSprite?.EnsureLazyLoaded();
Prefab.DeformableSprite?.EnsureLazyLoaded();
CurrentSwingAmount = Prefab.SwingAmountRad; CurrentSwingAmount = Prefab.SwingAmountRad;
CurrentScaleOscillation = Prefab.ScaleOscillation; CurrentScaleOscillation = Prefab.ScaleOscillation;
@@ -78,9 +78,8 @@ namespace Barotrauma.Lights
AmbientLight = new Color(20, 20, 20, 255); AmbientLight = new Color(20, 20, 20, 255);
visionCircle = Sprite.LoadTexture("Content/Lights/visioncircle.png"); visionCircle = Sprite.LoadTexture("Content/Lights/visioncircle.png", preMultiplyAlpha: false);
highlightRaster = Sprite.LoadTexture("Content/UI/HighlightRaster.png", preMultiplyAlpha: false);
highlightRaster = Sprite.LoadTexture("Content/UI/HighlightRaster.png");
CreateRenderTargets(graphics); CreateRenderTargets(graphics);
GameMain.Instance.OnResolutionChanged += () => GameMain.Instance.OnResolutionChanged += () =>
@@ -292,6 +291,11 @@ namespace Barotrauma.Lights
spriteBatch.Draw(HighlightMap, Vector2.Zero, Color.White); spriteBatch.Draw(HighlightMap, Vector2.Zero, Color.White);
spriteBatch.End(); 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 //draw characters to obstruct the highlighted items/characters and light sprites
//--------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------
@@ -91,7 +91,7 @@ namespace Barotrauma.Lights
} }
break; break;
case "lighttexture": case "lighttexture":
OverrideLightTexture = new Sprite(subElement); OverrideLightTexture = new Sprite(subElement, preMultiplyAlpha: false);
break; break;
} }
} }
@@ -211,7 +211,7 @@ namespace Barotrauma.Lights
{ {
if (lightTexture == null) if (lightTexture == null)
{ {
lightTexture = TextureLoader.FromFile("Content/Lights/pointlight_bright.png"); lightTexture = TextureLoader.FromFile("Content/Lights/pointlight_bright.png", preMultiplyAlpha: false);
} }
return lightTexture; return lightTexture;
@@ -56,6 +56,12 @@ namespace Barotrauma
set { textureOffset = value; } set { textureOffset = value; }
} }
partial void InitProjSpecific()
{
Prefab.sprite?.EnsureLazyLoaded();
Prefab.BackgroundSprite?.EnsureLazyLoaded();
}
partial void CreateConvexHull(Vector2 position, Vector2 size, float rotation) partial void CreateConvexHull(Vector2 position, Vector2 size, float rotation)
{ {
if (!CastShadow) { return; } if (!CastShadow) { return; }
@@ -52,7 +52,7 @@ namespace Barotrauma
damageEffect.Parameters["aMultiplier"].SetValue(50.0f); damageEffect.Parameters["aMultiplier"].SetValue(50.0f);
damageEffect.Parameters["cMultiplier"].SetValue(200.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); postProcessEffect.Parameters["xDistortTexture"].SetValue(distortTexture);
} }
@@ -172,6 +172,11 @@ namespace Barotrauma
{ {
base.Select(); base.Select();
foreach (LevelObjectPrefab levelObjPrefab in LevelObjectPrefab.List)
{
levelObjPrefab.Sprite?.EnsureLazyLoaded();
}
pointerLightSource = new LightSource(Vector2.Zero, 1000.0f, Color.White, submarine: null); pointerLightSource = new LightSource(Vector2.Zero, 1000.0f, Color.White, submarine: null);
GameMain.LightManager.AddLight(pointerLightSource); GameMain.LightManager.AddLight(pointerLightSource);
topPanel.ClearChildren(); topPanel.ClearChildren();
@@ -219,9 +219,9 @@ namespace Barotrauma
//spacing //spacing
new GUIFrame(new RectTransform(new Vector2(0.01f, 0.0f), optionHolder.RectTransform), style: null); 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, Stretch = false,
RelativeSpacing = 0.035f RelativeSpacing = 0.035f
@@ -688,7 +688,7 @@ namespace Barotrauma
if (backgroundSprite == null) 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) if (backgroundSprite != null)
@@ -22,7 +22,7 @@ namespace Barotrauma
"CrewExperienceHigh" "CrewExperienceHigh"
}; };
private readonly Point defaultPreviewImageSize = new Point(1200, 600); private readonly Point defaultPreviewImageSize = new Point(512, 368);
private Camera cam; private Camera cam;
@@ -65,6 +65,9 @@ namespace Barotrauma
private readonly string containerDeleteTag = "containerdelete"; 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 public override Camera Cam
{ {
get { return cam; } get { return cam; }
@@ -189,16 +192,17 @@ namespace Barotrauma
return true; return true;
}; };
LeftPanel = new GUIFrame(new RectTransform(new Vector2(0.08f, 1.0f), GUI.Canvas) { MinSize = new Point(170, 0) }, "GUIFrameLeft"); 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 * 0.8f), (int)(GameMain.GraphicsHeight - TopPanel.Rect.Height * 0.95f)), GUILayoutGroup paddedLeftPanel = new GUILayoutGroup(new RectTransform(new Point((int)(LeftPanel.Rect.Width), (int)(GameMain.GraphicsHeight - TopPanel.Rect.Height * 0.95f)),
LeftPanel.RectTransform, Anchor.Center) LeftPanel.RectTransform, Anchor.Center))
{ AbsoluteOffset = new Point(0, TopPanel.Rect.Height) })
{ {
RelativeSpacing = 0.01f,
Stretch = true 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") GUITextBlock itemCount = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedLeftPanel.RectTransform), "ItemCount")
{ {
TextGetter = GetItemCount TextGetter = GetItemCount
@@ -240,10 +244,9 @@ namespace Barotrauma
//Entity menu //Entity menu
//------------------------------------------------ //------------------------------------------------
EntityMenu = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth - LeftPanel.Rect.Width + 20, (int)(300 * GUI.Scale)), GUI.Canvas, Anchor.BottomRight), EntityMenu = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth - LeftPanel.Rect.Width, (int)(359 * GUI.Scale)), GUI.Canvas, Anchor.BottomRight), style: null) { Color = primaryColor };
style: "GUIFrameBottom");
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") style: "GUIButtonVerticalArrow")
{ {
OnClicked = (btn, userdata) => 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) isHorizontal: true)
{ {
RelativeSpacing = 0.01f, 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); entityList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.9f), entityListHolder.RectTransform, Anchor.BottomCenter))
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))
{ {
OnSelected = SelectPrefab, OnSelected = SelectPrefab,
UseGridLayout = true, UseGridLayout = true,
@@ -305,7 +312,10 @@ namespace Barotrauma
//empty guiframe as a separator //empty guiframe as a separator
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), paddedLeftPanel.RectTransform), style: null); 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"), ToolTip = TextManager.Get("CharacterModeToolTip"),
OnSelected = (GUITickBox tBox) => OnSelected = (GUITickBox tBox) =>
@@ -314,7 +324,11 @@ namespace Barotrauma
return true; 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"), ToolTip = TextManager.Get("WiringModeToolTip"),
OnSelected = (GUITickBox tBox) => OnSelected = (GUITickBox tBox) =>
@@ -333,9 +347,13 @@ namespace Barotrauma
OnClicked = GenerateWaypoints 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, Selected = lightingEnabled,
OnSelected = (GUITickBox obj) => OnSelected = (GUITickBox obj) =>
@@ -357,52 +375,49 @@ namespace Barotrauma
return true; 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, Selected = Structure.ShowWalls,
OnSelected = (GUITickBox obj) => { Structure.ShowWalls = obj.Selected; return true; } 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, Selected = Structure.ShowStructures,
OnSelected = (GUITickBox obj) => { Structure.ShowStructures = obj.Selected; return true; } 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, Selected = Item.ShowItems,
OnSelected = (GUITickBox obj) => { Item.ShowItems = obj.Selected; return true; } 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, Selected = WayPoint.ShowWayPoints,
OnSelected = (GUITickBox obj) => { WayPoint.ShowWayPoints = obj.Selected; return true; } 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, Selected = WayPoint.ShowSpawnPoints,
OnSelected = (GUITickBox obj) => { WayPoint.ShowSpawnPoints = obj.Selected; return true; } 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, Selected = Item.ShowLinks,
OnSelected = (GUITickBox obj) => { Item.ShowLinks = obj.Selected; return true; } 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, Selected = Hull.ShowHulls,
OnSelected = (GUITickBox obj) => { Hull.ShowHulls = obj.Selected; return true; } 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, Selected = Gap.ShowGaps,
OnSelected = (GUITickBox obj) => { Gap.ShowGaps = obj.Selected; return true; }, OnSelected = (GUITickBox obj) => { Gap.ShowGaps = obj.Selected; return true; },
}; };
//empty guiframe as a separator new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform, Anchor.BottomCenter) { AbsoluteOffset = new Point(10, 0) }, TextManager.Get("PreviouslyUsedLabel"));
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform), style: null); previouslyUsedList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), paddedLeftPanel.RectTransform, Anchor.BottomCenter) { AbsoluteOffset = new Point(10, 0) })
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))
{ {
OnSelected = SelectPrefab OnSelected = SelectPrefab
}; };
@@ -537,6 +552,15 @@ namespace Barotrauma
{ {
base.Select(); base.Select();
foreach (MapEntityPrefab prefab in MapEntityPrefab.List)
{
prefab.sprite?.EnsureLazyLoaded();
if (prefab is ItemPrefab itemPrefab)
{
itemPrefab.InventoryIcon?.EnsureLazyLoaded();
}
}
editorSelectedTime = DateTime.Now; editorSelectedTime = DateTime.Now;
GUI.ForceMouseOn(null); GUI.ForceMouseOn(null);
@@ -12,6 +12,8 @@ namespace Barotrauma
{ {
private static List<DeformableSprite> list = new List<DeformableSprite>(); private static List<DeformableSprite> list = new List<DeformableSprite>();
private bool initialized = false;
private int triangleCount; private int triangleCount;
private VertexBuffer vertexBuffer, flippedVertexBuffer; private VertexBuffer vertexBuffer, flippedVertexBuffer;
@@ -34,7 +36,7 @@ namespace Barotrauma
private Point spritePos; private Point spritePos;
private Point spriteSize; 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) if (effect == null)
{ {
@@ -56,11 +58,30 @@ namespace Barotrauma
throw new ArgumentException("Deformable sprites must have one or more subdivisions on each axis."); 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) foreach (DeformableSprite existing in list)
{ {
if (!existing.initialized || existing == this) { continue; }
//share vertex and index buffers if there's already //share vertex and index buffers if there's already
//an existing sprite with the same texture and subdivisions //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.subDivX == subDivX &&
existing.subDivY == subDivY && existing.subDivY == subDivY &&
existing.Sprite.SourceRect == Sprite.SourceRect) existing.Sprite.SourceRect == Sprite.SourceRect)
@@ -83,19 +104,18 @@ namespace Barotrauma
} }
} }
if (sprite.Texture != null) if (Sprite.Texture != null)
{ {
SetupVertexBuffers(); SetupVertexBuffers();
SetupIndexBuffer(); SetupIndexBuffer();
} }
list.Add(this);
} }
private void SetupVertexBuffers() private void SetupVertexBuffers()
{ {
Vector2 textureSize = new Vector2(sprite.Texture.Width, sprite.Texture.Height); Vector2 textureSize = new Vector2(Sprite.Texture.Width, Sprite.Texture.Height);
var pos = sprite.SourceRect.Location; var pos = Sprite.SourceRect.Location;
var size = sprite.SourceRect.Size; var size = Sprite.SourceRect.Size;
uvTopLeft = Vector2.Divide(pos.ToVector2(), textureSize); uvTopLeft = Vector2.Divide(pos.ToVector2(), textureSize);
uvBottomRight = Vector2.Divide((pos + size).ToVector2(), textureSize); uvBottomRight = Vector2.Divide((pos + size).ToVector2(), textureSize);
@@ -119,7 +139,7 @@ namespace Barotrauma
uvTopLeft + (uvBottomRight - uvTopLeft) * relativePos; uvTopLeft + (uvBottomRight - uvTopLeft) * relativePos;
vertices[x + y * (subDivX + 1)] = new VertexPositionColorTexture( 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, color: Color.White,
textureCoordinate: uvCoord); textureCoordinate: uvCoord);
} }
@@ -153,8 +173,8 @@ namespace Barotrauma
} }
} }
spritePos = sprite.SourceRect.Location; spritePos = Sprite.SourceRect.Location;
spriteSize = sprite.SourceRect.Size; spriteSize = Sprite.SourceRect.Size;
} }
private void SetupIndexBuffer() private void SetupIndexBuffer()
@@ -195,6 +215,8 @@ namespace Barotrauma
/// </summary> /// </summary>
public void Deform(Func<Vector2, Vector2> deformFunction) public void Deform(Func<Vector2, Vector2> deformFunction)
{ {
if (!initialized) { Init(); }
var deformAmount = new Vector2[subDivX + 1, subDivY + 1]; var deformAmount = new Vector2[subDivX + 1, subDivY + 1];
for (int x = 0; x <= subDivX; x++) for (int x = 0; x <= subDivX; x++)
{ {
@@ -208,6 +230,8 @@ namespace Barotrauma
public void Deform(Vector2[,] deform) public void Deform(Vector2[,] deform)
{ {
if (!initialized) { Init(); }
deformArrayWidth = deform.GetLength(0); deformArrayWidth = deform.GetLength(0);
deformArrayHeight = deform.GetLength(1); deformArrayHeight = deform.GetLength(1);
if (deformAmount == null || deformAmount.Length != deformArrayWidth * deformArrayHeight) if (deformAmount == null || deformAmount.Length != deformArrayWidth * deformArrayHeight)
@@ -234,6 +258,8 @@ namespace Barotrauma
public Matrix GetTransform(Vector3 pos, Vector2 origin, float rotate, Vector2 scale) public Matrix GetTransform(Vector3 pos, Vector2 origin, float rotate, Vector2 scale)
{ {
if (!initialized) { Init(); }
return return
Matrix.CreateTranslation(-origin.X, -origin.Y, 0) * Matrix.CreateTranslation(-origin.X, -origin.Y, 0) *
Matrix.CreateScale(scale.X, -scale.Y, 1.0f) * 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) 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 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(); SetupVertexBuffers();
} }
#if (LINUX || OSX) #if (LINUX || OSX)
effect.Parameters["TextureSampler+xTexture"].SetValue(sprite.Texture); effect.Parameters["TextureSampler+xTexture"].SetValue(Sprite.Texture);
#else #else
effect.Parameters["xTexture"].SetValue(sprite.Texture); effect.Parameters["xTexture"].SetValue(Sprite.Texture);
#endif #endif
Matrix matrix = GetTransform(pos, origin, rotate, scale); Matrix matrix = GetTransform(pos, origin, rotate, scale);
@@ -274,8 +301,8 @@ namespace Barotrauma
public void Remove() public void Remove()
{ {
sprite?.Remove(); Sprite?.Remove();
sprite = null; Sprite = null;
list.Remove(this); list.Remove(this);
@@ -55,6 +55,28 @@ namespace Barotrauma
if (sourceVector.W == 0.0f) sourceVector.W = texture.Height; 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() public void ReloadTexture()
{ {
var sprites = LoadedSprites.Where(s => s.Texture == texture).ToList(); var sprites = LoadedSprites.Where(s => s.Texture == texture).ToList();
@@ -76,11 +98,12 @@ namespace Barotrauma
public static Texture2D LoadTexture(string file, bool preMultiplyAlpha = true) public static Texture2D LoadTexture(string file, bool preMultiplyAlpha = true)
{ {
if (string.IsNullOrWhiteSpace(file)) { return new Texture2D(GameMain.GraphicsDeviceManager.GraphicsDevice, 1, 1); } if (string.IsNullOrWhiteSpace(file)) { return new Texture2D(GameMain.GraphicsDeviceManager.GraphicsDevice, 1, 1); }
file = Path.GetFullPath(file); file = Path.GetFullPath(file);
foreach (Sprite s in list) 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)) if (File.Exists(file))
@@ -362,7 +362,7 @@ namespace Barotrauma
} }
tempBuffer.Write(IsRagdolled); tempBuffer.Write(IsRagdolled);
tempBuffer.Write(AnimController.TargetDir == Direction.Right); tempBuffer.Write(AnimController.Dir > 0.0f);
} }
if (SelectedCharacter != null || SelectedConstruction != null) if (SelectedCharacter != null || SelectedConstruction != null)
@@ -381,6 +381,9 @@
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\8_Approach1\BaroTutorial_Approach.mp4"> <Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\8_Approach1\BaroTutorial_Approach.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\9_SwitchCharacter\BaroTutorial_SwitchCharacter.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\UI\tutorialAtlas.png"> <Content Include="$(MSBuildThisFileDirectory)Content\UI\tutorialAtlas.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@@ -1798,99 +1801,6 @@
</Content> </Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Texts\FinnishVanilla.xml"> <Content Include="$(MSBuildThisFileDirectory)Content\Texts\FinnishVanilla.xml">
</Content> </Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\1_CommandReactor\Sheets1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\1_CommandReactor\Sheets2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\2_NavConsole\Sheets1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\2_NavConsole\Sheets2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\2_NavConsole\Sheets3.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\2_NavConsole\Sheets4.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\2_NavConsole\Sheets5.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\3_Flood\Sheets1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\3_Flood\Sheets2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\3_Flood\Sheets3.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\3_Flood\Sheets4.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\3_Flood\Sheets5.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\4_Reactor\Sheets1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\4_Reactor\Sheets2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\4_Reactor\Sheets3.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\4_Reactor\Sheets4.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\4_Reactor\Sheets5.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\5_EnemyOnSonar\Sheets1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\5_EnemyOnSonar\Sheets2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\5_EnemyOnSonar\Sheets3.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\6_Degrading2\Sheets1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\6_Degrading2\Sheets2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\7_Medical\Sheets1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\7_Medical\Sheets2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\7_Medical\Sheets3.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\7_Medical\Sheets4.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\8_Approach1\Sheets1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\8_Approach1\Sheets2.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\8_Approach1\Sheets3.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\8_Approach1\Sheets4.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\ContextualTutorial\8_Approach1\Sheets5.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\Tutorials.xml"> <Content Include="$(MSBuildThisFileDirectory)Content\Tutorials\Tutorials.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@@ -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; Character.AnimController.TargetDir = Character.WorldPosition.X < attackWorldPos.X ? Direction.Right : Direction.Left;
} }
@@ -696,7 +696,7 @@ namespace Barotrauma
return; 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);
} }
} }
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Barotrauma.Extensions; using Barotrauma.Extensions;
using Barotrauma.Networking;
namespace Barotrauma namespace Barotrauma
{ {
@@ -1954,7 +1954,7 @@ namespace Barotrauma
if (PressureTimer >= 100.0f) 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) if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient)
{ {
Implode(); Implode();
@@ -2235,7 +2235,7 @@ namespace Barotrauma
if (limbHit == null) return new AttackResult(); 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 SERVER
if (attacker is Character attackingCharacter && attackingCharacter.AIController == null) if (attacker is Character attackingCharacter && attackingCharacter.AIController == null)
{ {
@@ -2321,7 +2321,8 @@ namespace Barotrauma
{ {
Vector2 diff = dir; Vector2 diff = dir;
if (diff == Vector2.Zero) diff = Rand.Vector(1.0f); 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); Vector2 simPos = hitLimb.SimPosition + ConvertUnits.ToSimUnits(dir);
AttackResult attackResult = hitLimb.AddDamage(simPos, afflictions, playSound); AttackResult attackResult = hitLimb.AddDamage(simPos, afflictions, playSound);
@@ -103,6 +103,7 @@ namespace Barotrauma
} }
public float CrushDepth { get; private set; } public float CrushDepth { get; private set; }
public float PressureKillDelay { get; private set; } = 5.0f;
public float Vitality { get; private set; } public float Vitality { get; private set; }
@@ -626,13 +626,17 @@ namespace Barotrauma
Limb limb = character.AnimController.Limbs[limbIndex]; Limb limb = character.AnimController.Limbs[limbIndex];
Vector2 forcePos = limb.pullJoint == null ? limb.body.SimPosition : limb.pullJoint.WorldAnchorA; 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 else
{ {
Vector2 forcePos = pullJoint == null ? body.SimPosition : pullJoint.WorldAnchorA; 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; return wasHit;
@@ -842,6 +842,7 @@ namespace Barotrauma
EnableSplashScreen = doc.Root.GetAttributeBool("enablesplashscreen", EnableSplashScreen); EnableSplashScreen = doc.Root.GetAttributeBool("enablesplashscreen", EnableSplashScreen);
AimAssistAmount = doc.Root.GetAttributeFloat("aimassistamount", AimAssistAmount); AimAssistAmount = doc.Root.GetAttributeFloat("aimassistamount", AimAssistAmount);
EnableMouseLook = doc.Root.GetAttributeBool("enablemouselook", EnableMouseLook);
foreach (XElement subElement in doc.Root.Elements()) foreach (XElement subElement in doc.Root.Elements())
{ {
@@ -910,7 +911,18 @@ namespace Barotrauma
foreach (XElement subElement in doc.Root.Elements()) foreach (XElement subElement in doc.Root.Elements())
{ {
switch (subElement.Name.ToString().ToLowerInvariant()) 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)
{ {
case "contentpackage": case "contentpackage":
string path = System.IO.Path.GetFullPath(subElement.GetAttributeString("path", "")); string path = System.IO.Path.GetFullPath(subElement.GetAttributeString("path", ""));
@@ -1018,370 +1030,6 @@ namespace Barotrauma
new XAttribute("quickstartsub", QuickStartSubmarineName), new XAttribute("quickstartsub", QuickStartSubmarineName),
new XAttribute("requiresteamauthentication", requireSteamAuthentication), new XAttribute("requiresteamauthentication", requireSteamAuthentication),
new XAttribute("autoupdateworkshopitems", AutoUpdateWorkshopItems), new XAttribute("autoupdateworkshopitems", AutoUpdateWorkshopItems),
new XAttribute("aimassistamount", aimAssistAmount));
if (!ShowUserStatisticsPrompt)
{
doc.Root.Add(new XAttribute("senduserstatistics", sendUserStatistics));
}
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)
{
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;
}
}
useSteamMatchmaking = doc.Root.GetAttributeBool("usesteammatchmaking", useSteamMatchmaking);
requireSteamAuthentication = doc.Root.GetAttributeBool("requiresteamauthentication", requireSteamAuthentication);
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())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "keymapping":
foreach (XAttribute attribute in subElement.Attributes())
{
if (Enum.TryParse(attribute.Name.ToString(), true, out InputType inputType))
{
if (int.TryParse(attribute.Value.ToString(), out int mouseButton))
{
keyMapping[(int)inputType] = new KeyOrMouse(mouseButton);
}
else
{
if (Enum.TryParse(attribute.Value.ToString(), true, out Keys key))
{
keyMapping[(int)inputType] = new KeyOrMouse(key);
}
}
}
}
break;
case "gameplay":
jobPreferences = new List<string>();
foreach (XElement ele in subElement.Element("jobpreferences").Elements("job"))
{
string jobIdentifier = ele.GetAttributeString("identifier", "");
if (string.IsNullOrEmpty(jobIdentifier)) continue;
jobPreferences.Add(jobIdentifier);
}
break;
case "player":
defaultPlayerName = subElement.GetAttributeString("name", defaultPlayerName);
CharacterHeadIndex = subElement.GetAttributeInt("headindex", CharacterHeadIndex);
if (Enum.TryParse(subElement.GetAttributeString("gender", "none"), true, out Gender g))
{
CharacterGender = g;
}
if (Enum.TryParse(subElement.GetAttributeString("race", "white"), true, out Race r))
{
CharacterRace = r;
}
else
{
CharacterRace = Race.White;
}
CharacterHairIndex = subElement.GetAttributeInt("hairindex", CharacterHairIndex);
CharacterBeardIndex = subElement.GetAttributeInt("beardindex", CharacterBeardIndex);
CharacterMoustacheIndex = subElement.GetAttributeInt("moustacheindex", CharacterMoustacheIndex);
CharacterFaceAttachmentIndex = subElement.GetAttributeInt("faceattachmentindex", CharacterFaceAttachmentIndex);
break;
case "tutorials":
foreach (XElement tutorialElement in subElement.Elements())
{
CompletedTutorialNames.Add(tutorialElement.GetAttributeString("name", ""));
}
break;
}
}
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<string>();
foreach (XElement subElement in doc.Root.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "contentpackage":
string path = System.IO.Path.GetFullPath(subElement.GetAttributeString("path", ""));
selectedContentPackagePaths.Add(path);
break;
}
}
LoadContentPackages(selectedContentPackagePaths);
}
public void ReloadContentPackages()
{
LoadContentPackages(selectedContentPackagePaths);
}
private void LoadContentPackages(IEnumerable<string> contentPackagePaths)
{
var missingPackagePaths = new List<string>();
var incompatiblePackages = new List<ContentPackage>();
SelectedContentPackages.Clear();
foreach (string path in contentPackagePaths)
{
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);
}
}
TextManager.LoadTextPacks(SelectedContentPackages);
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(); }
//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()));
}
}
#endregion
#region Save PlayerConfig
public void SaveNewPlayerConfig()
{
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("verboselogging", VerboseLogging),
new XAttribute("savedebugconsolelogs", SaveDebugConsoleLogs),
new XAttribute("enablesplashscreen", EnableSplashScreen),
new XAttribute("usesteammatchmaking", useSteamMatchmaking),
new XAttribute("quickstartsub", QuickStartSubmarineName),
new XAttribute("requiresteamauthentication", requireSteamAuthentication),
new XAttribute("autoupdateworkshopitems", AutoUpdateWorkshopItems),
new XAttribute("aimassistamount", aimAssistAmount), new XAttribute("aimassistamount", aimAssistAmount),
new XAttribute("enablemouselook", EnableMouseLook)); new XAttribute("enablemouselook", EnableMouseLook));
@@ -170,10 +170,6 @@ namespace Barotrauma.Items.Components
target.InitializeLinks(); target.InitializeLinks();
#if CLIENT
PlaySound(ActionType.OnUse, item.WorldPosition);
#endif
if (!item.linkedTo.Contains(target.item)) item.linkedTo.Add(target.item); if (!item.linkedTo.Contains(target.item)) item.linkedTo.Add(target.item);
if (!target.item.linkedTo.Contains(item)) target.item.linkedTo.Add(item); if (!target.item.linkedTo.Contains(item)) target.item.linkedTo.Add(item);
@@ -237,9 +233,9 @@ namespace Barotrauma.Items.Components
Math.Sign(DockingTarget.item.WorldPosition.X - item.WorldPosition.X) : Math.Sign(DockingTarget.item.WorldPosition.X - item.WorldPosition.X) :
Math.Sign(DockingTarget.item.WorldPosition.Y - item.WorldPosition.Y); Math.Sign(DockingTarget.item.WorldPosition.Y - item.WorldPosition.Y);
DockingTarget.DockingDir = -DockingDir; DockingTarget.DockingDir = -DockingDir;
#if CLIENT
PlaySound(ActionType.OnSecondaryUse, item.WorldPosition); ApplyStatusEffects(ActionType.OnUse, 1.0f);
#endif
Vector2 jointDiff = joint.WorldAnchorB - joint.WorldAnchorA; Vector2 jointDiff = joint.WorldAnchorB - joint.WorldAnchorA;
if (item.Submarine.PhysicsBody.Mass < DockingTarget.item.Submarine.PhysicsBody.Mass || if (item.Submarine.PhysicsBody.Mass < DockingTarget.item.Submarine.PhysicsBody.Mass ||
DockingTarget.item.Submarine.IsOutpost) DockingTarget.item.Submarine.IsOutpost)
@@ -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); int dir = IsHorizontal ? Math.Sign(c.SimPosition.Y - item.SimPosition.Y) : Math.Sign(c.SimPosition.X - item.SimPosition.X);
List<PhysicsBody> bodies = c.AnimController.Limbs.Select(l => l.body).ToList();
bodies.Add(c.AnimController.Collider);
bool soundPlayed = false; bool soundPlayed = false;
foreach (Limb limb in c.AnimController.Limbs) foreach (Limb limb in c.AnimController.Limbs)
{ {
float diff = 0.0f; if (PushBodyOutOfDoorway(c, limb.body, dir, simPos, simSize) && !soundPlayed)
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 CLIENT #if CLIENT
SoundPlayer.PlayDamageSound("LimbBlunt", 1.0f, limb.body); SoundPlayer.PlayDamageSound("LimbBlunt", 1.0f, limb.body);
#endif #endif
soundPlayed = true;
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));
} }
} }
PushBodyOutOfDoorway(c, c.AnimController.Collider, dir, simPos, simSize); 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; float diff = 0.0f;
if (!MathUtils.IsValid(body.SimPosition))
bool wasOpen = PredictedState == null ? isOpen : PredictedState.Value;
if (connection.Name == "toggle")
{ {
DebugConsole.ThrowError("Failed to push a limb out of a doorway - position of the body (character \"" + c.Name + "\") is not valid (" + 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, GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:LimbPosInvalid", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
@@ -480,6 +435,51 @@ namespace Barotrauma.Items.Components
diff = body.SimPosition.X - item.SimPosition.X; 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 SERVER
if (sender != null && wasOpen != isOpen) if (sender != null && wasOpen != isOpen)
{ {
@@ -1,4 +1,5 @@
using FarseerPhysics; using Barotrauma.Networking;
using FarseerPhysics;
using FarseerPhysics.Collision; using FarseerPhysics.Collision;
using FarseerPhysics.Dynamics; using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework; 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 //set the rotation of the projectile again because dropping the projectile resets the rotation
projectile.Item.SetTransform(projectilePos, projectile.Item.SetTransform(projectilePos,
rotation + ((item.body.Dir == 1.0f) ? projectile.LaunchRotationRadians : projectile.LaunchRotationRadians - MathHelper.Pi)); rotation + (projectile.Item.body.Dir * projectile.LaunchRotationRadians));
//recoil //recoil
item.body.ApplyLinearImpulse( 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); item.RemoveContained(projectile.Item);
@@ -107,10 +107,10 @@ namespace Barotrauma.Items.Components
#endif #endif
Character thrower = picker; Character thrower = picker;
item.Drop(thrower, createNetworkEvent: GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer); 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.Head).body.ApplyLinearImpulse(throwVector * 10.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
ac.GetLimb(LimbType.Torso).body.ApplyLinearImpulse(throwVector * 10.0f); ac.GetLimb(LimbType.Torso).body.ApplyLinearImpulse(throwVector * 10.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
Limb rightHand = ac.GetLimb(LimbType.RightHand); Limb rightHand = ac.GetLimb(LimbType.RightHand);
item.body.AngularVelocity = rightHand.body.AngularVelocity; item.body.AngularVelocity = rightHand.body.AngularVelocity;
@@ -211,12 +211,7 @@ namespace Barotrauma.Items.Components
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, outputContainer.Inventory, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition); Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, outputContainer.Inventory, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition);
} }
bool isNotClient = true; if ((GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer) && user != null && !user.Removed)
#if CLIENT
isNotClient = GameMain.Client == null;
#endif
if (isNotClient && user != null)
{ {
foreach (Skill skill in fabricatedItem.RequiredSkills) foreach (Skill skill in fabricatedItem.RequiredSkills)
{ {
@@ -377,23 +377,14 @@ namespace Barotrauma.Items.Components
target.Body.ApplyLinearImpulse(item.body.LinearVelocity * item.body.Mass); target.Body.ApplyLinearImpulse(item.body.LinearVelocity * item.body.Mass);
return true; 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; limb.character.LastDamageSource = item;
attackResult = attack.DoDamageToLimb(User, limb, item.WorldPosition, 1.0f); if (attack != null) { attackResult = attack.DoDamageToLimb(User, limb, item.WorldPosition, 1.0f); }
if (limb.character != null) character = limb.character; if (limb.character != null) { character = limb.character; }
} }
else if (target.Body.UserData is Structure structure) else if (target.Body.UserData is Structure structure)
{ {
attackResult = attack.DoDamage(User, structure, item.WorldPosition, 1.0f); if (attack != null) { attackResult = attack.DoDamage(User, structure, item.WorldPosition, 1.0f); }
}
} }
if (character != null) character.LastDamageSource = item; if (character != null) character.LastDamageSource = item;
@@ -22,6 +22,10 @@ namespace Barotrauma.Items.Components
private float blinkTimer; private float blinkTimer;
private bool itemLoaded;
private float blinkTimer;
public PhysicsBody ParentBody; public PhysicsBody ParentBody;
[Editable(MinValueFloat = 0.0f, MaxValueFloat = 2048.0f), Serialize(100.0f, true)] [Editable(MinValueFloat = 0.0f, MaxValueFloat = 2048.0f), Serialize(100.0f, true)]
@@ -77,7 +81,7 @@ namespace Barotrauma.Items.Components
IsActive = value; IsActive = value;
#if SERVER #if SERVER
if (GameMain.Server != null && GameMain.Server.GameStarted) { item.CreateServerEvent(this); } if (GameMain.Server != null && itemLoaded) { item.CreateServerEvent(this); }
#endif #endif
} }
} }
@@ -315,7 +315,7 @@ namespace Barotrauma.Items.Components
Vector2 diff = nodes[nodes.Count - 1] - newNodePos; Vector2 diff = nodes[nodes.Count - 1] - newNodePos;
Vector2 pullBackDir = diff == Vector2.Zero ? Vector2.Zero : Vector2.Normalize(diff); 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); user.AnimController.UpdateUseItem(true, user.WorldPosition + pullBackDir * 200.0f);
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer) if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
@@ -1145,24 +1145,6 @@ namespace Barotrauma
return; return;
} }
float forceFactor = 1.0f;
if (CurrentHull != null)
{
return;
}
float forceFactor = 1.0f;
if (CurrentHull != null)
{
return;
}
float forceFactor = 1.0f;
if (CurrentHull != null)
{
return;
}
float forceFactor = 1.0f; float forceFactor = 1.0f;
if (CurrentHull != null) if (CurrentHull != null)
{ {
@@ -1442,17 +1424,7 @@ namespace Barotrauma
} }
} }
#if CLIENT if (!pickHit && !selectHit) continue;
//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
}
}
if (!ic.HasRequiredSkills(picker, out Skill tempRequiredSkill)) hasRequiredSkills = false; if (!ic.HasRequiredSkills(picker, out Skill tempRequiredSkill)) hasRequiredSkills = false;
@@ -1653,6 +1625,8 @@ namespace Barotrauma
GameMain.NetworkMember != null && (GameMain.NetworkMember.IsServer || Character.Controlled == dropper)) GameMain.NetworkMember != null && (GameMain.NetworkMember.IsServer || Character.Controlled == dropper))
{ {
parentInventory.CreateNetworkEvent(); parentInventory.CreateNetworkEvent();
//send frequent updates after the item has been dropped
PositionUpdateInterval = 0.0f;
} }
} }
@@ -505,7 +505,7 @@ namespace Barotrauma
{ {
iconFolder = Path.GetDirectoryName(filePath); iconFolder = Path.GetDirectoryName(filePath);
} }
InventoryIcon = new Sprite(subElement, iconFolder); InventoryIcon = new Sprite(subElement, iconFolder, lazyLoad: true);
break; break;
case "brokensprite": case "brokensprite":
string brokenSpriteFolder = ""; string brokenSpriteFolder = "";
@@ -541,7 +541,7 @@ namespace Barotrauma
} }
else else
{ {
decorativeSprite = new DecorativeSprite(subElement, decorativeSpriteFolder); decorativeSprite = new DecorativeSprite(subElement, decorativeSpriteFolder, lazyLoad: true);
DecorativeSprites.Add(decorativeSprite); DecorativeSprites.Add(decorativeSprite);
groupID = decorativeSprite.RandomGroupID; groupID = decorativeSprite.RandomGroupID;
} }
@@ -558,7 +558,7 @@ namespace Barotrauma
{ {
containedSpriteFolder = Path.GetDirectoryName(filePath); containedSpriteFolder = Path.GetDirectoryName(filePath);
} }
var containedSprite = new ContainedItemSprite(subElement, containedSpriteFolder); var containedSprite = new ContainedItemSprite(subElement, containedSpriteFolder, lazyLoad: true);
if (containedSprite.Sprite != null) if (containedSprite.Sprite != null)
{ {
ContainedSprites.Add(containedSprite); ContainedSprites.Add(containedSprite);
@@ -568,7 +568,7 @@ namespace Barotrauma
public void Extinguish(float deltaTime, float amount, Vector2 position) 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); FireSources[i].Extinguish(deltaTime, amount, position);
} }
@@ -38,6 +38,9 @@ namespace Barotrauma
SerializableProperty.DeserializeProperties(this, configElement); SerializableProperty.DeserializeProperties(this, configElement);
name = TextManager.Get("EntityName." + identifier, returnNull: true) ?? name;
Description = TextManager.Get("EntityDescription." + identifier, returnNull: true) ?? Description;
int minX = int.MaxValue, minY = int.MaxValue; int minX = int.MaxValue, minY = int.MaxValue;
int maxX = int.MinValue, maxY = int.MinValue; int maxX = int.MinValue, maxY = int.MinValue;
DisplayEntities = new List<Pair<MapEntityPrefab, Rectangle>>(); DisplayEntities = new List<Pair<MapEntityPrefab, Rectangle>>();
@@ -331,13 +331,13 @@ namespace Barotrauma
switch (subElement.Name.ToString().ToLowerInvariant()) switch (subElement.Name.ToString().ToLowerInvariant())
{ {
case "sprite": case "sprite":
Sprite = new Sprite(subElement); Sprite = new Sprite(subElement, lazyLoad: true);
break; break;
case "specularsprite": case "specularsprite":
SpecularSprite = new Sprite(subElement); SpecularSprite = new Sprite(subElement, lazyLoad: true);
break; break;
case "deformablesprite": case "deformablesprite":
DeformableSprite = new DeformableSprite(subElement); DeformableSprite = new DeformableSprite(subElement, lazyLoad: true);
break; break;
case "overridecommonness": case "overridecommonness":
string levelType = subElement.GetAttributeString("leveltype", ""); string levelType = subElement.GetAttributeString("leveltype", "");
@@ -543,19 +543,19 @@ namespace Barotrauma
if (ForceVelocityLimit < 1000.0f) if (ForceVelocityLimit < 1000.0f)
body.ApplyForce(Force * currentForceFluctuation * distFactor, ForceVelocityLimit); body.ApplyForce(Force * currentForceFluctuation * distFactor, ForceVelocityLimit);
else else
body.ApplyForce(Force * currentForceFluctuation * distFactor); body.ApplyForce(Force * currentForceFluctuation * distFactor, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
break; break;
case TriggerForceMode.Acceleration: case TriggerForceMode.Acceleration:
if (ForceVelocityLimit < 1000.0f) if (ForceVelocityLimit < 1000.0f)
body.ApplyForce(Force * body.Mass * currentForceFluctuation * distFactor, ForceVelocityLimit); body.ApplyForce(Force * body.Mass * currentForceFluctuation * distFactor, ForceVelocityLimit);
else else
body.ApplyForce(Force * body.Mass * currentForceFluctuation * distFactor); body.ApplyForce(Force * body.Mass * currentForceFluctuation * distFactor, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
break; break;
case TriggerForceMode.Impulse: case TriggerForceMode.Impulse:
if (ForceVelocityLimit < 1000.0f) if (ForceVelocityLimit < 1000.0f)
body.ApplyLinearImpulse(Force * currentForceFluctuation * distFactor, ForceVelocityLimit); body.ApplyLinearImpulse(Force * currentForceFluctuation * distFactor, maxVelocity: ForceVelocityLimit);
else else
body.ApplyLinearImpulse(Force * currentForceFluctuation * distFactor); body.ApplyLinearImpulse(Force * currentForceFluctuation * distFactor, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
break; break;
case TriggerForceMode.LimitVelocity: case TriggerForceMode.LimitVelocity:
float maxVel = ForceVelocityLimit * currentForceFluctuation * distFactor; float maxVel = ForceVelocityLimit * currentForceFluctuation * distFactor;
@@ -563,7 +563,8 @@ namespace Barotrauma
{ {
body.ApplyForce( body.ApplyForce(
Vector2.Normalize(-body.LinearVelocity) * Vector2.Normalize(-body.LinearVelocity) *
Force.Length() * body.Mass * currentForceFluctuation * distFactor); Force.Length() * body.Mass * currentForceFluctuation * distFactor,
maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
} }
break; break;
} }
@@ -126,7 +126,7 @@ namespace Barotrauma
CanChangeTo.Add(new LocationTypeChange(Identifier, subElement)); CanChangeTo.Add(new LocationTypeChange(Identifier, subElement));
break; break;
case "portrait": case "portrait":
var portrait = new Sprite(subElement); var portrait = new Sprite(subElement, lazyLoad: true);
if (portrait != null) if (portrait != null)
{ {
portraits.Add(portrait); portraits.Add(portrait);
@@ -276,9 +276,10 @@ namespace Barotrauma
} }
StairDirection = Prefab.StairDirection; StairDirection = Prefab.StairDirection;
SerializableProperties = SerializableProperty.GetProperties(this); SerializableProperties = SerializableProperty.GetProperties(this);
InitProjSpecific();
if (Prefab.Body) if (Prefab.Body)
{ {
Bodies = new List<Body>(); Bodies = new List<Body>();
@@ -307,6 +308,8 @@ namespace Barotrauma
InsertToList(); InsertToList();
} }
partial void InitProjSpecific();
public override string ToString() public override string ToString()
{ {
return Name; return Name;
@@ -605,7 +605,7 @@ namespace Barotrauma
{ {
if (!IsValidValue(impulse, "impulse", -1e10f, 1e10f)) return; if (!IsValidValue(impulse, "impulse", -1e10f, 1e10f)) return;
if (!IsValidValue(point, "point")) 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); body.ApplyLinearImpulse(impulse, point);
} }
@@ -646,15 +646,20 @@ namespace Barotrauma
/// </summary> /// </summary>
public void ApplyForce(Vector2 force, float maxVelocity) public void ApplyForce(Vector2 force, float maxVelocity)
{ {
if (!IsValidValue(force, "force", -1e10f, 1e10f)) return;
if (!IsValidValue(maxVelocity, "max velocity")) return; if (!IsValidValue(maxVelocity, "max velocity")) return;
float currSpeed = body.LinearVelocity.Length();
Vector2 velocityAddition = force / Mass * (float)Timing.Step; Vector2 velocityAddition = force / Mass * (float)Timing.Step;
Vector2 newVelocity = body.LinearVelocity + velocityAddition; Vector2 newVelocity = body.LinearVelocity + velocityAddition;
newVelocity = newVelocity.ClampLength(Math.Max(currSpeed, maxVelocity));
body.ApplyForce((newVelocity - body.LinearVelocity) * Mass / (float)Timing.Step); float newSpeedSqr = newVelocity.LengthSquared();
if (newSpeedSqr > maxVelocity * maxVelocity)
{
newVelocity = newVelocity.ClampLength(maxVelocity);
}
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) public void ApplyForce(Vector2 force, Vector2 point)
@@ -5,30 +5,25 @@ namespace Barotrauma
{ {
partial class DeformableSprite partial class DeformableSprite
{ {
private Sprite sprite;
public Vector2 Size public Vector2 Size
{ {
get { return sprite.size; } get { return Sprite.size; }
} }
public Vector2 Origin public Vector2 Origin
{ {
get { return sprite.Origin; } get { return Sprite.Origin; }
set { sprite.Origin = value; } 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 = "") partial void InitProjSpecific(XElement element, int? subdivisionsX, int? subdivisionsY, bool lazyLoad = false);
{
sprite = new Sprite(element, file: filePath);
InitProjSpecific(element, subdivisionsX, subdivisionsY);
}
partial void InitProjSpecific(XElement element, int? subdivisionsX, int? subdivisionsY);
} }
} }
@@ -103,8 +103,9 @@ namespace Barotrauma
partial void LoadTexture(ref Vector4 sourceVector, ref bool shouldReturn, bool premultiplyAlpha = true); partial void LoadTexture(ref Vector4 sourceVector, ref bool shouldReturn, bool premultiplyAlpha = true);
partial void CalculateSourceRect(); 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; SourceElement = element;
if (file == "") if (file == "")
{ {
@@ -127,8 +128,12 @@ namespace Barotrauma
Name = SourceElement.GetAttributeString("name", null); Name = SourceElement.GetAttributeString("name", null);
Vector4 sourceVector = SourceElement.GetAttributeVector4("sourcerect", Vector4.Zero); Vector4 sourceVector = SourceElement.GetAttributeVector4("sourcerect", Vector4.Zero);
preMultipliedAlpha = preMultiplyAlpha ?? SourceElement.GetAttributeBool("premultiplyalpha", true);
bool shouldReturn = false; bool shouldReturn = false;
LoadTexture(ref sourceVector, ref shouldReturn, SourceElement.GetAttributeBool("premultiplyalpha", true)); if (!lazyLoad)
{
LoadTexture(ref sourceVector, ref shouldReturn, preMultipliedAlpha);
}
if (shouldReturn) return; if (shouldReturn) return;
sourceRect = new Rectangle((int)sourceVector.X, (int)sourceVector.Y, (int)sourceVector.Z, (int)sourceVector.W); sourceRect = new Rectangle((int)sourceVector.X, (int)sourceVector.Y, (int)sourceVector.Z, (int)sourceVector.W);
size = SourceElement.GetAttributeVector2("size", Vector2.One); size = SourceElement.GetAttributeVector2("size", Vector2.One);
@@ -31,6 +31,8 @@ namespace Barotrauma
public readonly HashSet<Character> ReactorMeltdown = new HashSet<Character>(); public readonly HashSet<Character> ReactorMeltdown = new HashSet<Character>();
public readonly HashSet<Character> Casualties = new HashSet<Character>(); public readonly HashSet<Character> Casualties = new HashSet<Character>();
public bool SubWasDamaged;
} }
private static RoundData roundData; private static RoundData roundData;
@@ -110,7 +112,47 @@ namespace Barotrauma
UnlockAchievement("subdeep", true, c => c != null && c.Submarine == sub && !c.IsDead && !c.IsUnconscious); 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) public static void OnBiomeDiscovered(Biome biome)
@@ -274,14 +316,21 @@ namespace Barotrauma
//made it to the destination //made it to the destination
if (gameSession.Submarine.AtEndPosition) if (gameSession.Submarine.AtEndPosition)
{ {
bool noDamageRun = !roundData.SubWasDamaged && !roundData.Casualties.Any(c => !(c.AIController is EnemyAIController));
#if SERVER #if SERVER
if (GameMain.Server != null) 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 //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)); UnlockAchievement("survivereactormeltdown", true, c => c != null && !c.IsDead && roundData.ReactorMeltdown.Contains(c));
if (noDamageRun)
{
UnlockAchievement("nodamagerun", true, c => c != null && !c.IsDead);
}
} }
#endif #endif
#if CLIENT #if CLIENT
if (noDamageRun) { UnlockAchievement("nodamagerun"); }
if (roundData.ReactorMeltdown.Any()) //in SP getting to the destination after a meltdown is enough if (roundData.ReactorMeltdown.Any()) //in SP getting to the destination after a meltdown is enough
{ {
UnlockAchievement("survivereactormeltdown"); UnlockAchievement("survivereactormeltdown");
@@ -302,6 +351,11 @@ namespace Barotrauma
UnlockAchievement(charactersInSub[0], "lonesailor"); UnlockAchievement(charactersInSub[0], "lonesailor");
} }
} }
foreach (Character character in charactersInSub)
{
if (character.Info.Job == null) { continue; }
UnlockAchievement(character, character.Info.Job.Prefab.Identifier + "round");
}
} }
} }
Binary file not shown.
Binary file not shown.
Binary file not shown.