58c92888b7
commit 2f107db0475bf4b9a8b6f405b9ce8ec489cbc0ba Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Thu Feb 7 16:30:24 2019 +0200 Another nullref fix to the OpenHealthWindow property setter. Closes #1090 commit 1d15d18d2501bedaa1b42ac8e0e7e09e2600960e Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Thu Feb 7 16:19:05 2019 +0200 Fixed crashing when an incompatible content package is selected in config.xml or if the content package cannot be found. Happened because the game attempted to use TextManager.Get before text files had been loaded. Partially fixes #1093 commit 9ec1980fe90bcae65333c188b265ba16a6db6c05 Author: ezjamsen <ezjames.fi@gmail.com> Date: Thu Feb 7 16:16:53 2019 +0200 added correct effects for alien blood commit b6d2c56910b5d58477703abc6785ef80719a89a6 Author: ezjamsen <ezjames.fi@gmail.com> Date: Thu Feb 7 15:41:25 2019 +0200 adjustments to fent, glue and antibiotics commit 8df16acdaac0a521fe09fb62c6815a46a87f6f25 Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Thu Feb 7 15:30:51 2019 +0200 More descriptive ping exception error messages (only shown in debug builds now), some extra checks to prevent using the workshop without steam (although the checks that actually matter are implemented at Steam's side now) commit 959c503c140196287ab60ec2357feb8bd5c85b18 Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Thu Feb 7 14:00:48 2019 +0200 Don't allow severing the joint between a moloch's shell and the "bladder" commit 0c0b033016c2e82b8cf1b5a4e3f6faa9cde39f40 Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Thu Feb 7 13:51:58 2019 +0200 Fixed incorrect item panel positioning in the crew command interface when the sub is docked to something. Closes #1082 commit 68366a4bf3c73b70288f043199d3ab9b2f5f4d06 Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Thu Feb 7 13:23:38 2019 +0200 Fixed outdated damage modifiers in security and clown gear (used damage types instead of afflictions), not defining any affliction types for a damage modifier makes it affect all types of damage. Closes #1088 commit 5d3ab5084b8bc5357bc4a53993ad8dfcc44d0412 Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Thu Feb 7 13:04:55 2019 +0200 Fixed client-side nullref exception if the round ends while the health window is open. Closes #1090 commit 8249d789a60dfe4bcdd1705d26d6ca36ed407058 Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Thu Feb 7 12:48:34 2019 +0200 The dedicated server doesn't initialize a Steam client (not required to use any of the Steam server functionality). Fixes players being unable to log in as a client when they're hosting a dedicated server on another machine. TODO: SteamCMD support commit 55fb0bb1ba4bb8385dabbf6e40d4651bf86294a9 Author: ezjamsen <ezjames.fi@gmail.com> Date: Thu Feb 7 12:31:46 2019 +0200 Added linked hulls commit 937d50dca50d8c889a7c11b55765c208d2d16b67 Merge: 8109ae1a3 57731761f Author: EdusFF <pitkanen.eetu@gmail.com> Date: Thu Feb 7 12:16:43 2019 +0200 Merge branch 'dev' of https://github.com/Regalis11/Barotrauma into dev commit 8109ae1a3377910ff9bf066ccac582d879dfb0a4 Author: EdusFF <pitkanen.eetu@gmail.com> Date: Thu Feb 7 12:16:37 2019 +0200 Fixed: AI not reloading coilgun if an empty box of ammunition is inserted. commit 57731761f64bb33a4f4e7baa38367cfb7cf1f873 Author: itchyOwl <lauri.harkanen@gmail.com> Date: Thu Feb 7 12:10:59 2019 +0200 Refactor character head customization logic and store the data in a dedicated class. In the net lobby, generate new head when the user presses the right arrow button. Pressing the left arrow will restore the previous head. When the user presses the right arrow after the left arrow, the first head is restored again. So it's effectively (and technically) undo/redo logic. commit 37577931e2706ce432cee2d48cd55990bc2bab4a Author: itchyOwl <lauri.harkanen@gmail.com> Date: Thu Feb 7 12:04:49 2019 +0200 Add properties for getting the count of the undo and redo stacks. commit f226beb05a55749ac961e3a33ac594fdf903fc3b Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Wed Feb 6 21:15:56 2019 +0200 Fixes to hull linking & displaying them as one hull on the minimap: - Links between hulls are now saved. - Simplified grouping logic (just store a list of linked hulls in hulldata). - Fixed water/oxygen calculations (use the average of the values instead of their sum). TODO: DRY (there's now duplicate linking logic in Item and Hull), merge the hull sprites on the minimap, maybe automatize the linking? commit 5dfea1fbb24c5bd91605caf65baaac9aca9cfbbf Merge: 2ad9b5de4 d06a1557f Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Wed Feb 6 20:18:31 2019 +0200 Merge branch 'dev' of https://github.com/Regalis11/Barotrauma into dev commit d06a1557ffb85cd32bbb884fadef60b6d9dd27cf Author: Alex <olimpickusa6@gmail.com> Date: Wed Feb 6 18:26:40 2019 +0200 Test for connecting hulls task
639 lines
25 KiB
C#
639 lines
25 KiB
C#
using System.Linq;
|
|
using System.Xml.Linq;
|
|
using System.Collections.Generic;
|
|
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Input;
|
|
using System.Xml;
|
|
#if CLIENT
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
using Barotrauma.Tutorials;
|
|
#endif
|
|
using System;
|
|
|
|
namespace Barotrauma
|
|
{
|
|
public enum WindowMode
|
|
{
|
|
Windowed, Fullscreen, BorderlessWindowed
|
|
}
|
|
|
|
public enum LosMode
|
|
{
|
|
None,
|
|
Transparent,
|
|
Opaque
|
|
}
|
|
|
|
public partial class GameSettings
|
|
{
|
|
const string FilePath = "config.xml";
|
|
|
|
public int GraphicsWidth { get; set; }
|
|
public int GraphicsHeight { get; set; }
|
|
|
|
public bool VSyncEnabled { get; set; }
|
|
|
|
public bool EnableSplashScreen { get; set; }
|
|
|
|
public int ParticleLimit { get; set; }
|
|
|
|
public float LightMapScale { get; set; }
|
|
public bool SpecularityEnabled { get; set; }
|
|
public bool ChromaticAberrationEnabled { get; set; }
|
|
|
|
private KeyOrMouse[] keyMapping;
|
|
|
|
private WindowMode windowMode;
|
|
|
|
private LosMode losMode;
|
|
|
|
public List<string> jobPreferences;
|
|
|
|
private bool useSteamMatchmaking;
|
|
private bool requireSteamAuthentication;
|
|
|
|
public string QuickStartSubmarineName
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
#if DEBUG
|
|
//steam functionality can be enabled/disabled in debug builds
|
|
public bool UseSteam;
|
|
public bool RequireSteamAuthentication
|
|
{
|
|
get { return requireSteamAuthentication && UseSteam; }
|
|
set { requireSteamAuthentication = value; }
|
|
}
|
|
public bool UseSteamMatchmaking
|
|
{
|
|
get { return useSteamMatchmaking && UseSteam; }
|
|
set { useSteamMatchmaking = value; }
|
|
}
|
|
|
|
#else
|
|
//steam functionality determined at compile time
|
|
public bool UseSteam
|
|
{
|
|
get { return Steam.SteamManager.USE_STEAM; }
|
|
}
|
|
public bool RequireSteamAuthentication
|
|
{
|
|
get { return requireSteamAuthentication && Steam.SteamManager.USE_STEAM; }
|
|
set { requireSteamAuthentication = value; }
|
|
}
|
|
public bool UseSteamMatchmaking
|
|
{
|
|
get { return useSteamMatchmaking && Steam.SteamManager.USE_STEAM; }
|
|
set { useSteamMatchmaking = value; }
|
|
}
|
|
#endif
|
|
|
|
public WindowMode WindowMode
|
|
{
|
|
get { return windowMode; }
|
|
set { windowMode = value; }
|
|
}
|
|
|
|
public List<string> JobPreferences
|
|
{
|
|
get { return jobPreferences; }
|
|
set { jobPreferences = value; }
|
|
}
|
|
|
|
public int CharacterHeadIndex { get; set; }
|
|
public int CharacterHairIndex { get; set; }
|
|
public int CharacterBeardIndex { get; set; }
|
|
public int CharacterMoustacheIndex { get; set; }
|
|
public int CharacterFaceAttachmentIndex { get; set; }
|
|
|
|
public Gender CharacterGender { get; set; }
|
|
public Race CharacterRace { get; set; }
|
|
|
|
private float aimAssistAmount;
|
|
public float AimAssistAmount
|
|
{
|
|
get { return aimAssistAmount; }
|
|
set { aimAssistAmount = MathHelper.Clamp(value, 0.0f, 5.0f); }
|
|
}
|
|
|
|
private bool unsavedSettings;
|
|
public bool UnsavedSettings
|
|
{
|
|
get
|
|
{
|
|
return unsavedSettings;
|
|
}
|
|
private set
|
|
{
|
|
unsavedSettings = value;
|
|
#if CLIENT
|
|
if (applyButton != null)
|
|
{
|
|
//applyButton.Selected = unsavedSettings;
|
|
applyButton.Enabled = unsavedSettings;
|
|
applyButton.Text = unsavedSettings ? "Apply*" : "Apply";
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
private float soundVolume, musicVolume;
|
|
|
|
public float SoundVolume
|
|
{
|
|
get { return soundVolume; }
|
|
set
|
|
{
|
|
soundVolume = MathHelper.Clamp(value, 0.0f, 1.0f);
|
|
#if CLIENT
|
|
if (GameMain.SoundManager != null)
|
|
{
|
|
GameMain.SoundManager.SetCategoryGainMultiplier("default", soundVolume);
|
|
GameMain.SoundManager.SetCategoryGainMultiplier("ui", soundVolume);
|
|
GameMain.SoundManager.SetCategoryGainMultiplier("waterambience", soundVolume);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
public float MusicVolume
|
|
{
|
|
get { return musicVolume; }
|
|
set
|
|
{
|
|
musicVolume = MathHelper.Clamp(value, 0.0f, 1.0f);
|
|
#if CLIENT
|
|
GameMain.SoundManager?.SetCategoryGainMultiplier("music", musicVolume);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
public string Language
|
|
{
|
|
get { return TextManager.Language; }
|
|
set { TextManager.Language = value; }
|
|
}
|
|
|
|
public HashSet<ContentPackage> SelectedContentPackages { get; set; }
|
|
|
|
public string MasterServerUrl { get; set; }
|
|
public bool AutoCheckUpdates { get; set; }
|
|
public bool WasGameUpdated { get; set; }
|
|
|
|
private string defaultPlayerName;
|
|
public string DefaultPlayerName
|
|
{
|
|
get
|
|
{
|
|
return defaultPlayerName ?? "";
|
|
}
|
|
set
|
|
{
|
|
if (defaultPlayerName != value)
|
|
{
|
|
defaultPlayerName = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
public LosMode LosMode
|
|
{
|
|
get { return losMode; }
|
|
set { losMode = value; }
|
|
}
|
|
|
|
private const float MinHUDScale = 0.75f, MaxHUDScale = 1.25f;
|
|
public static float HUDScale { get; set; } = 1.0f;
|
|
private const float MinInventoryScale = 0.75f, MaxInventoryScale = 1.25f;
|
|
public static float InventoryScale { get; set; } = 1.0f;
|
|
|
|
public List<string> CompletedTutorialNames { get; private set; }
|
|
|
|
public static bool VerboseLogging { get; set; }
|
|
public static bool SaveDebugConsoleLogs { get; set; }
|
|
|
|
private static bool sendUserStatistics;
|
|
public static bool SendUserStatistics
|
|
{
|
|
get { return sendUserStatistics; }
|
|
set
|
|
{
|
|
sendUserStatistics = value;
|
|
GameMain.Config.Save();
|
|
}
|
|
}
|
|
public static bool ShowUserStatisticsPrompt { get; set; }
|
|
|
|
public GameSettings(string filePath)
|
|
{
|
|
SelectedContentPackages = new HashSet<ContentPackage>();
|
|
|
|
ContentPackage.LoadAll(ContentPackage.Folder);
|
|
CompletedTutorialNames = new List<string>();
|
|
Load(filePath);
|
|
}
|
|
|
|
public void Load(string filePath)
|
|
{
|
|
XDocument doc = XMLExtensions.TryLoadXml(filePath);
|
|
|
|
Language = doc.Root.GetAttributeString("language", "English");
|
|
|
|
MasterServerUrl = doc.Root.GetAttributeString("masterserverurl", "");
|
|
|
|
AutoCheckUpdates = doc.Root.GetAttributeBool("autocheckupdates", true);
|
|
WasGameUpdated = doc.Root.GetAttributeBool("wasgameupdated", false);
|
|
|
|
VerboseLogging = doc.Root.GetAttributeBool("verboselogging", false);
|
|
SaveDebugConsoleLogs = doc.Root.GetAttributeBool("savedebugconsolelogs", false);
|
|
if (doc.Root.Attribute("senduserstatistics") == null)
|
|
{
|
|
ShowUserStatisticsPrompt = true;
|
|
}
|
|
else
|
|
{
|
|
sendUserStatistics = doc.Root.GetAttributeBool("senduserstatistics", true);
|
|
}
|
|
|
|
#if DEBUG
|
|
UseSteam = doc.Root.GetAttributeBool("usesteam", true);
|
|
#endif
|
|
QuickStartSubmarineName = doc.Root.GetAttributeString("quickstartsub", "");
|
|
|
|
if (doc == null)
|
|
{
|
|
GraphicsWidth = 1024;
|
|
GraphicsHeight = 678;
|
|
|
|
MasterServerUrl = "";
|
|
|
|
SelectedContentPackages.Add(ContentPackage.List.Any() ? ContentPackage.List[0] : new ContentPackage(""));
|
|
|
|
jobPreferences = new List<string>();
|
|
foreach (JobPrefab job in JobPrefab.List)
|
|
{
|
|
jobPreferences.Add(job.Identifier);
|
|
}
|
|
return;
|
|
}
|
|
|
|
XElement graphicsMode = doc.Root.Element("graphicsmode");
|
|
GraphicsWidth = graphicsMode.GetAttributeInt("width", 0);
|
|
GraphicsHeight = graphicsMode.GetAttributeInt("height", 0);
|
|
VSyncEnabled = graphicsMode.GetAttributeBool("vsync", true);
|
|
|
|
XElement graphicsSettings = doc.Root.Element("graphicssettings");
|
|
ParticleLimit = graphicsSettings.GetAttributeInt("particlelimit", 1500);
|
|
LightMapScale = MathHelper.Clamp(graphicsSettings.GetAttributeFloat("lightmapscale", 0.5f), 0.1f, 1.0f);
|
|
SpecularityEnabled = graphicsSettings.GetAttributeBool("specularity", true);
|
|
ChromaticAberrationEnabled = graphicsSettings.GetAttributeBool("chromaticaberration", true);
|
|
HUDScale = graphicsSettings.GetAttributeFloat("hudscale", 1.0f);
|
|
InventoryScale = graphicsSettings.GetAttributeFloat("inventoryscale", 1.0f);
|
|
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
|
|
|
|
//FullScreenEnabled = ToolBox.GetAttributeBool(graphicsMode, "fullscreen", true);
|
|
|
|
var windowModeStr = graphicsMode.GetAttributeString("displaymode", "Fullscreen");
|
|
if (!Enum.TryParse<WindowMode>(windowModeStr, out windowMode))
|
|
{
|
|
windowMode = WindowMode.Fullscreen;
|
|
}
|
|
|
|
SoundVolume = doc.Root.GetAttributeFloat("soundvolume", 1.0f);
|
|
MusicVolume = doc.Root.GetAttributeFloat("musicvolume", 0.3f);
|
|
|
|
useSteamMatchmaking = doc.Root.GetAttributeBool("usesteammatchmaking", true);
|
|
requireSteamAuthentication = doc.Root.GetAttributeBool("requiresteamauthentication", true);
|
|
|
|
EnableSplashScreen = doc.Root.GetAttributeBool("enablesplashscreen", true);
|
|
|
|
AimAssistAmount = doc.Root.GetAttributeFloat("aimassistamount", 0.5f);
|
|
|
|
keyMapping = new KeyOrMouse[Enum.GetNames(typeof(InputType)).Length];
|
|
keyMapping[(int)InputType.Up] = new KeyOrMouse(Keys.W);
|
|
keyMapping[(int)InputType.Down] = new KeyOrMouse(Keys.S);
|
|
keyMapping[(int)InputType.Left] = new KeyOrMouse(Keys.A);
|
|
keyMapping[(int)InputType.Right] = new KeyOrMouse(Keys.D);
|
|
keyMapping[(int)InputType.Run] = new KeyOrMouse(Keys.LeftShift);
|
|
|
|
keyMapping[(int)InputType.Chat] = new KeyOrMouse(Keys.Tab);
|
|
keyMapping[(int)InputType.RadioChat] = new KeyOrMouse(Keys.OemPipe);
|
|
keyMapping[(int)InputType.CrewOrders] = new KeyOrMouse(Keys.C);
|
|
|
|
keyMapping[(int)InputType.Select] = new KeyOrMouse(Keys.E);
|
|
|
|
keyMapping[(int)InputType.SelectNextCharacter] = new KeyOrMouse(Keys.Tab);
|
|
keyMapping[(int)InputType.SelectPreviousCharacter] = new KeyOrMouse(Keys.Q);
|
|
|
|
keyMapping[(int)InputType.Use] = new KeyOrMouse(0);
|
|
keyMapping[(int)InputType.Aim] = new KeyOrMouse(1);
|
|
|
|
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", "");
|
|
CharacterHeadIndex = subElement.GetAttributeInt("headindex", Rand.Int(10));
|
|
CharacterGender = subElement.GetAttributeString("gender", Rand.Range(0.0f, 1.0f) < 0.5f ? "male" : "female")
|
|
.ToLowerInvariant() == "male" ? Gender.Male : Gender.Female;
|
|
if (Enum.TryParse(subElement.GetAttributeString("race", "white"), true, out Race r))
|
|
{
|
|
CharacterRace = r;
|
|
}
|
|
else
|
|
{
|
|
CharacterRace = Race.White;
|
|
}
|
|
CharacterHairIndex = subElement.GetAttributeInt("hairindex", -1);
|
|
CharacterBeardIndex = subElement.GetAttributeInt("beardindex", -1);
|
|
CharacterMoustacheIndex = subElement.GetAttributeInt("moustacheindex", -1);
|
|
CharacterFaceAttachmentIndex = subElement.GetAttributeInt("faceattachmentindex", -1);
|
|
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;
|
|
|
|
List<string> missingPackagePaths = new List<string>();
|
|
List<ContentPackage> incompatiblePackages = new List<ContentPackage>();
|
|
foreach (XElement subElement in doc.Root.Elements())
|
|
{
|
|
switch (subElement.Name.ToString().ToLowerInvariant())
|
|
{
|
|
case "contentpackage":
|
|
string path = System.IO.Path.GetFullPath(subElement.GetAttributeString("path", ""));
|
|
var matchingContentPackage = ContentPackage.List.Find(cp => System.IO.Path.GetFullPath(cp.Path) == path);
|
|
if (matchingContentPackage == null)
|
|
{
|
|
missingPackagePaths.Add(path);
|
|
}
|
|
else if (!matchingContentPackage.IsCompatible())
|
|
{
|
|
incompatiblePackages.Add(matchingContentPackage);
|
|
}
|
|
else
|
|
{
|
|
SelectedContentPackages.Add(matchingContentPackage);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
TextManager.LoadTextPacks(SelectedContentPackages);
|
|
|
|
//display error messages after all content packages have been loaded
|
|
//to make sure the package that contains text files has been loaded before we attempt to use TextManager
|
|
foreach (string missingPackagePath in missingPackagePaths)
|
|
{
|
|
DebugConsole.ThrowError(TextManager.Get("ContentPackageNotFound").Replace("[packagepath]", missingPackagePath));
|
|
}
|
|
foreach (ContentPackage incompatiblePackage in incompatiblePackages)
|
|
{
|
|
DebugConsole.ThrowError(TextManager.Get(incompatiblePackage.GameVersion <= new Version(0, 0, 0, 0) ? "IncompatibleContentPackageUnknownVersion" : "IncompatibleContentPackage")
|
|
.Replace("[packagename]", incompatiblePackage.Name)
|
|
.Replace("[packageversion]", incompatiblePackage.GameVersion.ToString())
|
|
.Replace("[gameversion]", GameMain.Version.ToString()));
|
|
}
|
|
foreach (ContentPackage contentPackage in SelectedContentPackages)
|
|
{
|
|
foreach (ContentFile file in contentPackage.Files)
|
|
{
|
|
if (!System.IO.File.Exists(file.Path))
|
|
{
|
|
DebugConsole.ThrowError("Error in content package \"" + contentPackage.Name + "\" - file \"" + file.Path + "\" not found.");
|
|
continue;
|
|
}
|
|
ToolBox.IsProperFilenameCase(file.Path);
|
|
}
|
|
}
|
|
if (!SelectedContentPackages.Any())
|
|
{
|
|
var availablePackage = ContentPackage.List.FirstOrDefault(cp => cp.IsCompatible() && cp.CorePackage);
|
|
if (availablePackage != null)
|
|
{
|
|
SelectedContentPackages.Add(availablePackage);
|
|
}
|
|
}
|
|
|
|
//save to get rid of the invalid selected packages in the config file
|
|
if (missingPackagePaths.Count > 0 || incompatiblePackages.Count > 0) { Save(); }
|
|
}
|
|
|
|
public KeyOrMouse KeyBind(InputType inputType)
|
|
{
|
|
return keyMapping[(int)inputType];
|
|
}
|
|
|
|
public void Save()
|
|
{
|
|
UnsavedSettings = false;
|
|
|
|
XDocument doc = new XDocument();
|
|
|
|
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("aimassistamount", aimAssistAmount));
|
|
|
|
if (!ShowUserStatisticsPrompt)
|
|
{
|
|
doc.Root.Add(new XAttribute("senduserstatistics", sendUserStatistics));
|
|
}
|
|
|
|
if (WasGameUpdated)
|
|
{
|
|
doc.Root.Add(new XAttribute("wasgameupdated", true));
|
|
}
|
|
|
|
XElement gMode = doc.Root.Element("graphicsmode");
|
|
if (gMode == null)
|
|
{
|
|
gMode = new XElement("graphicsmode");
|
|
doc.Root.Add(gMode);
|
|
}
|
|
|
|
if (GraphicsWidth == 0 || GraphicsHeight == 0)
|
|
{
|
|
gMode.ReplaceAttributes(new XAttribute("displaymode", windowMode));
|
|
}
|
|
else
|
|
{
|
|
gMode.ReplaceAttributes(
|
|
new XAttribute("width", GraphicsWidth),
|
|
new XAttribute("height", GraphicsHeight),
|
|
new XAttribute("vsync", VSyncEnabled),
|
|
new XAttribute("displaymode", windowMode));
|
|
}
|
|
|
|
XElement gSettings = doc.Root.Element("graphicssettings");
|
|
if (gSettings == null)
|
|
{
|
|
gSettings = new XElement("graphicssettings");
|
|
doc.Root.Add(gSettings);
|
|
}
|
|
|
|
gSettings.ReplaceAttributes(
|
|
new XAttribute("particlelimit", ParticleLimit),
|
|
new XAttribute("lightmapscale", LightMapScale),
|
|
new XAttribute("specularity", SpecularityEnabled),
|
|
new XAttribute("chromaticaberration", ChromaticAberrationEnabled),
|
|
new XAttribute("losmode", LosMode),
|
|
new XAttribute("hudscale", HUDScale),
|
|
new XAttribute("inventoryscale", InventoryScale));
|
|
|
|
foreach (ContentPackage contentPackage in SelectedContentPackages)
|
|
{
|
|
doc.Root.Add(new XElement("contentpackage",
|
|
new XAttribute("path", contentPackage.Path)));
|
|
}
|
|
|
|
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);
|
|
|
|
#if CLIENT
|
|
if (Tutorial.Tutorials != null)
|
|
{
|
|
foreach (Tutorial tutorial in Tutorial.Tutorials)
|
|
{
|
|
if (tutorial.Completed && !CompletedTutorialNames.Contains(tutorial.Name))
|
|
{
|
|
CompletedTutorialNames.Add(tutorial.Name);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
var tutorialElement = new XElement("tutorials");
|
|
foreach (string tutorialName in CompletedTutorialNames)
|
|
{
|
|
tutorialElement.Add(new XElement("Tutorial", new XAttribute("name", tutorialName)));
|
|
}
|
|
doc.Root.Add(tutorialElement);
|
|
|
|
XmlWriterSettings settings = new XmlWriterSettings
|
|
{
|
|
Indent = true,
|
|
OmitXmlDeclaration = true,
|
|
NewLineOnAttributes = true
|
|
};
|
|
|
|
try
|
|
{
|
|
using (var writer = XmlWriter.Create(FilePath, 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);
|
|
}
|
|
}
|
|
}
|
|
}
|