Merge remote-tracking branch 'upstream/dev' into develop

This commit is contained in:
EvilFactory
2022-12-09 17:33:44 -03:00
416 changed files with 12674 additions and 5862 deletions
@@ -104,6 +104,7 @@ namespace Barotrauma
public struct CampaignSettingElements
{
public SettingValue<bool> TutorialEnabled;
public SettingValue<bool> RadiationEnabled;
public SettingValue<int> MaxMissionCount;
public SettingValue<StartingBalanceAmount> StartingFunds;
@@ -114,6 +115,7 @@ namespace Barotrauma
{
return new CampaignSettings(element: null)
{
TutorialEnabled = TutorialEnabled.GetValue(),
RadiationEnabled = RadiationEnabled.GetValue(),
MaxMissionCount = MaxMissionCount.GetValue(),
StartingBalanceAmount = StartingFunds.GetValue(),
@@ -159,7 +161,7 @@ namespace Barotrauma
}
}
protected static CampaignSettingElements CreateCampaignSettingList(GUIComponent parent, CampaignSettings prevSettings)
protected static CampaignSettingElements CreateCampaignSettingList(GUIComponent parent, CampaignSettings prevSettings, bool isSinglePlayer)
{
const float verticalSize = 0.14f;
@@ -180,6 +182,9 @@ namespace Barotrauma
Spacing = GUI.IntScale(5)
};
SettingValue<bool> tutorialEnabled = isSinglePlayer ?
CreateTickbox(settingsList.Content, TextManager.Get("CampaignOption.EnableTutorial"), TextManager.Get("campaignoption.enabletutorial.tooltip"), prevSettings.TutorialEnabled, verticalSize) :
new SettingValue<bool>(() => false, b => { });
SettingValue<bool> radiationEnabled = CreateTickbox(settingsList.Content, TextManager.Get("CampaignOption.EnableRadiation"), TextManager.Get("campaignoption.enableradiation.tooltip"), prevSettings.RadiationEnabled, verticalSize);
ImmutableArray<SettingCarouselElement<Identifier>> startingSetOptions = StartItemSet.Sets.OrderBy(s => s.Order).Select(set => new SettingCarouselElement<Identifier>(set.Identifier, $"startitemset.{set.Identifier}")).ToImmutableArray();
@@ -214,6 +219,7 @@ namespace Barotrauma
{
if (o is CampaignSettings settings)
{
tutorialEnabled.SetValue(isSinglePlayer && settings.TutorialEnabled);
radiationEnabled.SetValue(settings.RadiationEnabled);
maxMissionCountInput.SetValue(settings.MaxMissionCount);
startingFundsInput.SetValue(settings.StartingBalanceAmount);
@@ -226,6 +232,7 @@ namespace Barotrauma
return new CampaignSettingElements
{
TutorialEnabled = tutorialEnabled,
RadiationEnabled = radiationEnabled,
MaxMissionCount = maxMissionCountInput,
StartingFunds = startingFundsInput,
@@ -35,18 +35,18 @@ namespace Barotrauma
};
// New game
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.03f), nameSeedLayout.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SaveName"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.BottomLeft);
saveNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.03f), nameSeedLayout.RectTransform) { MinSize = new Point(0, 20) }, string.Empty)
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.03f), nameSeedLayout.RectTransform) { MinSize = new Point(0, GUI.IntScale(24)) }, TextManager.Get("SaveName"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.BottomLeft);
saveNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.03f), nameSeedLayout.RectTransform), string.Empty)
{
textFilterFunction = ToolBox.RemoveInvalidFileNameChars
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.03f), nameSeedLayout.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("MapSeed"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.BottomLeft);
seedBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.03f), nameSeedLayout.RectTransform) { MinSize = new Point(0, 20) }, ToolBox.RandomSeed(8));
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.03f), nameSeedLayout.RectTransform) { MinSize = new Point(0, GUI.IntScale(24)) }, TextManager.Get("MapSeed"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.BottomLeft);
seedBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.03f), nameSeedLayout.RectTransform), ToolBox.RandomSeed(8));
nameSeedLayout.RectTransform.MinSize = new Point(0, nameSeedLayout.Children.Sum(c => c.RectTransform.MinSize.Y));
CampaignSettingElements elements = CreateCampaignSettingList(campaignSettingLayout, CampaignSettings.Empty);
CampaignSettingElements elements = CreateCampaignSettingList(campaignSettingLayout, CampaignSettings.Empty, false);
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.1f),
verticalLayout.RectTransform) { MaxSize = new Point(int.MaxValue, 60) }, childAnchor: Anchor.BottomRight, isHorizontal: true);
@@ -370,7 +370,7 @@ namespace Barotrauma
GUILayoutGroup campaignSettingContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.8f), CampaignCustomizeSettings.Content.RectTransform, Anchor.TopCenter));
CampaignSettingElements elements = CreateCampaignSettingList(campaignSettingContent, prevSettings);
CampaignSettingElements elements = CreateCampaignSettingList(campaignSettingContent, prevSettings, true);
CampaignCustomizeSettings.Buttons[0].OnClicked += (button, o) =>
{
@@ -608,15 +608,16 @@ namespace Barotrauma
{
OnClicked = (btn, userdata) =>
{
var saveFolder = SaveUtil.GetSaveFolder(SaveUtil.SaveType.Singleplayer);
try
{
ToolBox.OpenFileWithShell(SaveUtil.SaveFolder);
ToolBox.OpenFileWithShell(saveFolder);
}
catch (Exception e)
{
new GUIMessageBox(
TextManager.Get("error"),
TextManager.GetWithVariables("showinfoldererror", ("[folder]", SaveUtil.SaveFolder), ("[errormessage]", e.Message)));
TextManager.Get("error"),
TextManager.GetWithVariables("showinfoldererror", ("[folder]", saveFolder), ("[errormessage]", e.Message)));
}
return true;
}
@@ -472,7 +472,12 @@ namespace Barotrauma
{
TextGetter = () =>
{
return TextManager.AddPunctuation(':', TextManager.Get("Missions"), $"{Campaign.NumberOfMissionsAtLocation(destination)}/{Campaign.Settings.TotalMaxMissionCount}");
int missionCount = 0;
if (GameMain.GameSession != null && Campaign.Map?.CurrentLocation?.SelectedMissions != null)
{
missionCount = Campaign.Map.CurrentLocation.SelectedMissions.Count(m => m.Locations.Contains(location) && !GameMain.GameSession.Missions.Contains(m));
}
return TextManager.AddPunctuation(':', TextManager.Get("Missions"), $"{missionCount}/{Campaign.Settings.TotalMaxMissionCount}");
}
};
@@ -39,6 +39,7 @@ namespace Barotrauma.CharacterEditor
private bool ShowExtraRagdollControls => editLimbs || editJoints;
public Character SpawnedCharacter => character;
private Character character;
private Vector2 spawnPosition;
@@ -1513,7 +1514,7 @@ namespace Barotrauma.CharacterEditor
}
}
private Character SpawnCharacter(Identifier speciesName, RagdollParams ragdoll = null)
public Character SpawnCharacter(Identifier speciesName, RagdollParams ragdoll = null)
{
DebugConsole.NewMessage(GetCharacterEditorTranslation("TryingToSpawnCharacter").Replace("[config]", speciesName.ToString()), Color.HotPink);
OnPreSpawn();
@@ -1765,9 +1766,15 @@ namespace Barotrauma.CharacterEditor
var modProject = new ModProject(contentPackage);
var newFile = ModProject.File.FromPath<CharacterFile>(configFilePath);
modProject.AddFile(newFile);
modProject.Save(contentPackage.Path);
contentPackage = ContentPackageManager.ReloadContentPackage(contentPackage);
var reloadResult = ContentPackageManager.ReloadContentPackage(contentPackage);
if (!reloadResult.TryUnwrapSuccess(out var newPackage))
{
throw new Exception($"Failed to reload package",
reloadResult.TryUnwrapFailure(out var exception) ? exception : null);
}
contentPackage = newPackage;
DebugConsole.NewMessage(GetCharacterEditorTranslation("ContentPackageSaved").Replace("[path]", contentPackage.Path));
@@ -3181,10 +3188,7 @@ namespace Barotrauma.CharacterEditor
OnClicked = (button, data) =>
{
ResetView();
CharacterParams.Serialize();
RagdollParams.Serialize();
AnimParams.ForEach(a => a.Serialize());
Wizard.Instance.CopyExisting(CharacterParams, RagdollParams, AnimParams);
PrepareCharacterCopy();
Wizard.Instance.SelectTab(Wizard.Tab.Character);
return true;
}
@@ -3209,9 +3213,17 @@ namespace Barotrauma.CharacterEditor
fileEditPanel.RectTransform.MinSize = new Point(0, (int)(layoutGroup.RectTransform.Children.Sum(c => c.MinSize.Y + layoutGroup.AbsoluteSpacing) * 1.2f));
}
#endregion
#endregion
#region ToggleButtons
public void PrepareCharacterCopy()
{
CharacterParams.Serialize();
RagdollParams.Serialize();
AnimParams.ForEach(a => a.Serialize());
Wizard.Instance.CopyExisting(CharacterParams, RagdollParams, AnimParams);
}
#region ToggleButtons
private enum Direction
{
Left,
@@ -101,7 +101,7 @@ namespace Barotrauma.CharacterEditor
{
bool isSamePackage = contentPackage.GetFiles<CharacterFile>().Any(f => Path.GetFileNameWithoutExtension(f.Path.Value) == name);
LocalizedString verificationText = isSamePackage ? GetCharacterEditorTranslation("existingcharacterfoundreplaceverification") : GetCharacterEditorTranslation("existingcharacterfoundoverrideverification");
var msgBox = new GUIMessageBox("", verificationText, new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") })
var msgBox = new GUIMessageBox("", verificationText, new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") }, type: GUIMessageBox.Type.Warning)
{
UserData = "verificationprompt"
};
@@ -356,7 +356,7 @@ namespace Barotrauma.CharacterEditor
}
if (ContentPackageManager.AllPackages.Any(cp => cp.Name.ToLower() == contentPackageNameElement.Text.ToLower()))
{
new GUIMessageBox("", TextManager.Get("charactereditor.contentpackagenameinuse", "leveleditorlevelobjnametaken"));
new GUIMessageBox("", TextManager.Get("charactereditor.contentpackagenameinuse", "leveleditorlevelobjnametaken"), type: GUIMessageBox.Type.Warning);
return false;
}
string modName = contentPackageNameElement.Text;
@@ -428,17 +428,26 @@ namespace Barotrauma.CharacterEditor
texturePathElement.Flash(useRectangleFlash: true);
return false;
}
if (Name == CharacterPrefab.HumanSpeciesName && !IsCopy)
{
// Force a copy when trying to override a human, because handling the crash would be very difficult (we require humans to have certain definitions).
if (!CharacterEditorScreen.Instance.SpawnedCharacter.IsHuman)
{
CharacterEditorScreen.Instance.SpawnCharacter(CharacterPrefab.HumanSpeciesName);
}
CharacterEditorScreen.Instance.PrepareCharacterCopy();
}
if (IsCopy)
{
SourceRagdoll.Texture = evaluatedTexturePath;
SourceRagdoll.CanEnterSubmarine = CanEnterSubmarine;
SourceRagdoll.CanWalk = CanWalk;
SourceRagdoll.Serialize();
Wizard.Instance.CreateCharacter(SourceRagdoll.MainElement, SourceCharacter.MainElement, SourceAnimations);
Instance.CreateCharacter(SourceRagdoll.MainElement, SourceCharacter.MainElement, SourceAnimations);
}
else
{
Wizard.Instance.SelectTab(Tab.Ragdoll);
Instance.SelectTab(Tab.Ragdoll);
}
return true;
};
@@ -470,9 +479,6 @@ namespace Barotrauma.CharacterEditor
Stretch = true,
RelativeSpacing = 0.02f
};
// HTML
GUIMessageBox htmlBox = null;
var loadHtmlButton = new GUIButton(new RectTransform(new Point(content.Rect.Width / 3, elementSize), content.RectTransform), GetCharacterEditorTranslation("LoadFromHTML"));
// Limbs
var limbsElement = new GUIFrame(new RectTransform(new Vector2(1, 0.05f), content.RectTransform), style: null) { CanBeFocused = false };
@@ -689,69 +695,6 @@ namespace Barotrauma.CharacterEditor
return true;
}
};
loadHtmlButton.OnClicked = (b, d) =>
{
if (htmlBox == null)
{
htmlBox = new GUIMessageBox(GetCharacterEditorTranslation("LoadHTML"), string.Empty, new LocalizedString[] { TextManager.Get("Close"), TextManager.Get("Load") }, new Vector2(0.65f, 1f));
htmlBox.Header.Font = GUIStyle.LargeFont;
var element = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.05f), htmlBox.Content.RectTransform), style: null, color: Color.Gray * 0.25f);
//new GUITextBlock(new RectTransform(new Vector2(0.3f, 1), element.RectTransform), GetCharacterEditorTranslation("HTMLPath"));
var htmlPathElement = new GUITextBox(new RectTransform(new Vector2(0.7f, 1), element.RectTransform, Anchor.TopRight), GetCharacterEditorTranslation("HTMLPath").Value);
LocalizedString title = GetCharacterEditorTranslation("SelectFile");
new GUIButton(new RectTransform(new Vector2(0.3f, 1), element.RectTransform), title)
{
OnClicked = (button, data) =>
{
FileSelection.OnFileSelected = (file) =>
{
htmlPathElement.Text = file;
};
FileSelection.ClearFileTypeFilters();
FileSelection.AddFileTypeFilter("HTML", "*.html, *.htm");
FileSelection.AddFileTypeFilter("All files", "*.*");
FileSelection.SelectFileTypeFilter("*.html, *.htm");
FileSelection.Open = true;
return true;
}
};
var list = new GUIListBox(new RectTransform(new Vector2(1, 0.8f), htmlBox.Content.RectTransform));
var htmlOutput = new GUITextBlock(new RectTransform(Vector2.One, list.Content.RectTransform), string.Empty) { CanBeFocused = false };
htmlBox.Buttons[0].OnClicked += (_b, _d) =>
{
htmlBox.Close();
return true;
};
htmlBox.Buttons[1].OnClicked += (_b, _d) =>
{
LimbGUIElements.ForEach(l => l.RectTransform.Parent = null);
LimbGUIElements.Clear();
JointGUIElements.ForEach(j => j.RectTransform.Parent = null);
JointGUIElements.Clear();
LimbXElements.Clear();
JointXElements.Clear();
ParseRagdollFromHTML(htmlPathElement.Text, (id, limbName, limbType, rect) =>
{
CreateLimbGUIElement(limbsList.Content.RectTransform, elementSize, id, limbName, limbType, rect);
}, (id1, id2, anchor1, anchor2, jointName) =>
{
CreateJointGUIElement(jointsList.Content.RectTransform, elementSize, id1, id2, anchor1, anchor2, jointName);
});
htmlOutput.Text = new XDocument(new XElement("Ragdoll", new object[]
{
new XAttribute("type", Name), LimbXElements.Values, JointXElements
})).ToString();
htmlOutput.CalculateHeightFromText();
list.UpdateScrollBarSize();
return true;
};
}
else
{
GUIMessageBox.MessageBoxes.Add(htmlBox);
}
return true;
};
// Previous
box.Buttons[0].OnClicked += (b, d) =>
{
@@ -1070,7 +1013,6 @@ namespace Barotrauma.CharacterEditor
// Rectangles
colliderAttributes.Add(new XAttribute("height", (int)(height * 0.85f)));
colliderAttributes.Add(new XAttribute("width", (int)(width * 0.85f)));
idToCodeName.TryGetValue(id, out string notes);
LimbXElements.Add(id.ToString(), new XElement("limb",
new XAttribute("id", id),
new XAttribute("name", limbName),
@@ -1107,188 +1049,6 @@ namespace Barotrauma.CharacterEditor
}
}
Dictionary<int, string> idToCodeName = new Dictionary<int, string>();
protected void ParseRagdollFromHTML(string path, Action<int, string, LimbType, Rectangle> limbCallback = null, Action<int, int, Vector2, Vector2, string> jointCallback = null)
{
// TODO: parse as xml files -> allows to load ragdolls onto the wizard.
//XDocument doc = XMLExtensions.TryLoadXml(path);
//var xElements = doc.Elements().ToArray();
string html = string.Empty;
try
{
html = File.ReadAllText(path);
}
catch (Exception e)
{
DebugConsole.ThrowError(GetCharacterEditorTranslation("FailedToReadHTML").Replace("[path]", path), e);
return;
}
var lines = html.Split(new string[] { "<div", "</div>", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)
.Where(s => s.Contains("left") && s.Contains("top") && s.Contains("width") && s.Contains("height"));
int id = 0;
Dictionary<string, int> hierarchyToID = new Dictionary<string, int>();
Dictionary<int, string> idToHierarchy = new Dictionary<int, string>();
Dictionary<int, string> idToPositionCode = new Dictionary<int, string>();
Dictionary<int, string> idToName = new Dictionary<int, string>();
idToCodeName.Clear();
foreach (var line in lines)
{
var codeNames = new string(line.SkipWhile(c => c != '>').Skip(1).ToArray()).Split(',');
for (int i = 0; i < codeNames.Length; i++)
{
string codeName = codeNames[i].Trim();
if (string.IsNullOrWhiteSpace(codeName)) { continue; }
idToCodeName.Add(id, codeName);
string limbName = new string(codeName.SkipWhile(c => c != '_').Skip(1).ToArray());
if (string.IsNullOrWhiteSpace(limbName)) { continue; }
idToName.Add(id, limbName);
var parts = line.Split(' ');
int ParseToInt(string selector)
{
string part = parts.First(p => p.Contains(selector));
string s = new string(part.SkipWhile(c => c != ':').Skip(1).TakeWhile(c => char.IsNumber(c)).ToArray());
int.TryParse(s, out int v);
return v;
};
// example: 111311cr -> 111311
string hierarchy = new string(codeName.TakeWhile(c => char.IsNumber(c)).ToArray());
if (hierarchyToID.ContainsKey(hierarchy))
{
DebugConsole.ThrowError(GetCharacterEditorTranslation("MultipleItemsWithSameHierarchy").Replace("[hierarchy]", hierarchy).Replace("[name]", codeName));
return;
}
hierarchyToID.Add(hierarchy, id);
idToHierarchy.Add(id, hierarchy);
string positionCode = new string(codeName.SkipWhile(c => char.IsNumber(c)).TakeWhile(c => c != '_').ToArray());
idToPositionCode.Add(id, positionCode.ToLowerInvariant());
int x = ParseToInt("left");
int y = ParseToInt("top");
int width = ParseToInt("width");
int height = ParseToInt("height");
// This is overridden when the data is loaded from the gui fields.
LimbXElements.Add(hierarchy, new XElement("limb",
new XAttribute("id", id),
new XAttribute("name", limbName),
new XAttribute("type", ParseLimbType(limbName).ToString()),
new XElement("sprite",
new XAttribute("texture", ""),
new XAttribute("sourcerect", $"{x}, {y}, {width}, {height}"))
));
limbCallback?.Invoke(id, limbName, ParseLimbType(limbName), new Rectangle(x, y, width, height));
id++;
}
}
for (int i = 0; i < id; i++)
{
if (idToHierarchy.TryGetValue(i, out string hierarchy))
{
if (hierarchy != "0")
{
// NEW LOGIC: if hierarchy length == 1, parent to 0
// Else parent to the last bone in the current hierarchy (11 is parented to 1, 212 is parented to 21 etc)
string parent = hierarchy.Length > 1 ? hierarchy.Remove(hierarchy.Length - 1, 1) : "0";
if (hierarchyToID.TryGetValue(parent, out int parentID))
{
Vector2 anchor1 = Vector2.Zero;
Vector2 anchor2 = Vector2.Zero;
idToName.TryGetValue(parentID, out string parentName);
idToName.TryGetValue(i, out string limbName);
string jointName = $"{GetCharacterEditorTranslation("Joint")} {parentName} - {limbName}";
if (idToPositionCode.TryGetValue(i, out string positionCode))
{
float scalar = 0.8f;
if (LimbXElements.TryGetValue(parent, out XElement parentElement))
{
Rectangle parentSourceRect = parentElement.Element("sprite").GetAttributeRect("sourcerect", Rectangle.Empty);
float parentWidth = parentSourceRect.Width / 2 * scalar;
float parentHeight = parentSourceRect.Height / 2 * scalar;
switch (positionCode)
{
case "tl": // -1, 1
anchor1 = new Vector2(-parentWidth, parentHeight);
break;
case "tc": // 0, 1
anchor1 = new Vector2(0, parentHeight);
break;
case "tr": // -1, 1
anchor1 = new Vector2(-parentWidth, parentHeight);
break;
case "cl": // -1, 0
anchor1 = new Vector2(-parentWidth, 0);
break;
case "cr": // 1, 0
anchor1 = new Vector2(parentWidth, 0);
break;
case "bl": // -1, -1
anchor1 = new Vector2(-parentWidth, -parentHeight);
break;
case "bc": // 0, -1
anchor1 = new Vector2(0, -parentHeight);
break;
case "br": // 1, -1
anchor1 = new Vector2(parentWidth, -parentHeight);
break;
}
if (LimbXElements.TryGetValue(hierarchy, out XElement element))
{
Rectangle sourceRect = element.Element("sprite").GetAttributeRect("sourcerect", Rectangle.Empty);
float width = sourceRect.Width / 2 * scalar;
float height = sourceRect.Height / 2 * scalar;
switch (positionCode)
{
// Inverse
case "tl":
// br
anchor2 = new Vector2(-width, -height);
break;
case "tc":
// bc
anchor2 = new Vector2(0, -height);
break;
case "tr":
// bl
anchor2 = new Vector2(-width, -height);
break;
case "cl":
// cr
anchor2 = new Vector2(width, 0);
break;
case "cr":
// cl
anchor2 = new Vector2(-width, 0);
break;
case "bl":
// tr
anchor2 = new Vector2(-width, height);
break;
case "bc":
// tc
anchor2 = new Vector2(0, height);
break;
case "br":
// tl
anchor2 = new Vector2(-width, height);
break;
}
}
}
}
// This is overridden when the data is loaded from the gui fields.
JointXElements.Add(new XElement("joint",
new XAttribute("name", jointName),
new XAttribute("limb1", parentID),
new XAttribute("limb2", i),
new XAttribute("limb1anchor", $"{anchor1.X.Format(2)}, {anchor1.Y.Format(2)}"),
new XAttribute("limb2anchor", $"{anchor2.X.Format(2)}, {anchor2.Y.Format(2)}")
));
jointCallback?.Invoke(parentID, i, anchor1, anchor2, jointName);
}
}
}
}
}
protected LimbType ParseLimbType(string limbName)
{
var limbType = LimbType.None;
@@ -16,8 +16,8 @@ namespace Barotrauma
GameMain.LightManager.LosEnabled = true;
Hull.EditFire = false;
Hull.EditWater = false;
#endif
HumanAIController.DisableCrewAI = false;
#endif
}
protected virtual void DeselectEditorSpecific() { }
@@ -10,8 +10,6 @@ namespace Barotrauma
{
partial class GameScreen : Screen
{
public override bool IsEditor => GameMain.GameSession?.GameMode is TestGameMode;
private RenderTarget2D renderTargetBackground;
private RenderTarget2D renderTarget;
private RenderTarget2D renderTargetWater;
@@ -47,7 +47,14 @@ namespace Barotrauma
private GUITextBox serverNameBox, passwordBox, maxPlayersBox;
private GUITickBox isPublicBox, wrongPasswordBanBox, karmaBox;
private GUIDropDown serverExecutableDropdown;
private readonly GUIButton joinServerButton, hostServerButton, steamWorkshopButton;
private readonly GUIButton joinServerButton, hostServerButton;
private readonly GUIFrame modsButtonContainer;
private readonly GUIButton modsButton, modUpdatesButton;
private Task<IReadOnlyList<Steamworks.Ugc.Item>> modUpdateTask;
private float modUpdateTimer = 0.0f;
private const float ModUpdateInterval = 60.0f;
private readonly GameMain game;
private GUIImage playstyleBanner;
@@ -268,15 +275,29 @@ namespace Barotrauma
RelativeSpacing = 0.035f
};
#if USE_STEAM
steamWorkshopButton = new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), customizeList.RectTransform), TextManager.Get("SteamWorkshopButton"), textAlignment: Alignment.Left, style: "MainMenuGUIButton")
modsButtonContainer = new GUIFrame(new RectTransform(Vector2.One, customizeList.RectTransform),
style: null);
modsButton = new GUIButton(new RectTransform(Vector2.One, modsButtonContainer.RectTransform),
TextManager.Get("settingstab.mods"), textAlignment: Alignment.Left, style: "MainMenuGUIButton")
{
ForceUpperCase = ForceUpperCase.Yes,
Enabled = true,
UserData = Tab.SteamWorkshop,
OnClicked = SelectTab
};
#endif
modUpdatesButton = new GUIButton(new RectTransform(Vector2.One * 0.95f, modsButtonContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight),
style: "GUIUpdateButton")
{
ToolTip = TextManager.Get("ModUpdatesAvailable"),
OnClicked = (_, _) =>
{
BulkDownloader.PrepareUpdates();
return false;
},
Visible = false
};
new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), customizeList.RectTransform), TextManager.Get("SubEditorButton"), textAlignment: Alignment.Left, style: "MainMenuGUIButton")
{
@@ -334,7 +355,7 @@ namespace Barotrauma
OnClicked = (button, userData) =>
{
string url = TextManager.Get("EditorDisclaimerWikiUrl").Fallback("https://barotraumagame.com/wiki").Value;
GameMain.Instance.ShowOpenUrlInWebBrowserPrompt(url, promptExtensionTag: "wikinotice");
GameMain.ShowOpenUrlInWebBrowserPrompt(url, promptExtensionTag: "wikinotice");
return true;
}
};
@@ -485,13 +506,17 @@ namespace Barotrauma
}
};
var tutorialPreview = new GUILayoutGroup(new RectTransform(new Vector2(0.6f, 1.0f), tutorialContent.RectTransform)) { RelativeSpacing = 0.05f, Stretch = true };
var imageContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.6f), tutorialPreview.RectTransform), style: "InnerFrame");
var imageContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), tutorialPreview.RectTransform), style: "InnerFrame");
tutorialBanner = new GUIImage(new RectTransform(Vector2.One, imageContainer.RectTransform), style: null, scaleToFit: true);
var infoContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.4f), tutorialPreview.RectTransform), style: "GUIFrameListBox");
var infoContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), infoContainer.RectTransform, Anchor.Center), childAnchor: Anchor.TopCenter);
var infoContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), tutorialPreview.RectTransform), style: "GUIFrameListBox");
var infoContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), infoContainer.RectTransform, Anchor.Center), childAnchor: Anchor.TopLeft)
{
AbsoluteSpacing = GUI.IntScale(10)
};
tutorialHeader = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.75f), infoContent.RectTransform), string.Empty, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Center);
tutorialHeader = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), string.Empty, font: GUIStyle.SubHeadingFont);
tutorialDescription = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), string.Empty, wrap: true);
var startButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.0f), infoContent.RectTransform, Anchor.BottomRight), text: TextManager.Get("startgamebutton"))
{
@@ -522,6 +547,10 @@ namespace Barotrauma
private void SelectTutorial(Tutorial tutorial)
{
tutorialHeader.Text = tutorial.DisplayName;
tutorialHeader.CalculateHeightFromText();
tutorialDescription.Text = tutorial.Description;
tutorialDescription.CalculateHeightFromText();
(tutorialDescription.Parent as GUILayoutGroup)?.Recalculate();
tutorial.TutorialPrefab.Banner?.EnsureLazyLoaded();
tutorialBanner.Sprite = tutorial.TutorialPrefab.Banner;
tutorialBanner.Color = tutorial.TutorialPrefab.Banner == null ? Color.Black : Color.White;
@@ -541,6 +570,8 @@ namespace Barotrauma
{
GameMain.LuaCs.Stop();
ResetModUpdateButton();
if (WorkshopItemsToUpdate.Any())
{
while (WorkshopItemsToUpdate.TryDequeue(out ulong workshopId))
@@ -727,6 +758,13 @@ namespace Barotrauma
}
#endregion
public void ResetModUpdateButton()
{
modUpdateTask = null;
modUpdateTimer = 0;
modUpdatesButton.Visible = false;
}
public void QuickStart(bool fixedSeed = false, Identifier sub = default, float difficulty = 50, LevelGenerationParams levelGenerationParams = null)
{
if (fixedSeed)
@@ -946,15 +984,36 @@ namespace Barotrauma
public override void Update(double deltaTime)
{
#if !DEBUG && USE_STEAM
modUpdateTimer -= (float)deltaTime;
if (modUpdateTimer <= 0.0f && modUpdateTask is not { IsCompleted: false })
{
modUpdateTask = BulkDownloader.GetItemsThatNeedUpdating();
modUpdateTimer = ModUpdateInterval;
}
#if DEBUG
hostServerButton.Enabled = true;
#else
if (GameSettings.CurrentConfig.UseSteamMatchmaking)
{
hostServerButton.Enabled = Steam.SteamManager.IsInitialized;
hostServerButton.Enabled = SteamManager.IsInitialized;
}
steamWorkshopButton.Enabled = Steam.SteamManager.IsInitialized;
#elif USE_STEAM
steamWorkshopButton.Enabled = true;
#endif
if (modUpdateTask is { IsCompletedSuccessfully: true })
{
modUpdatesButton.Visible = modUpdateTask.Result.Count > 0;
}
if (modUpdatesButton.Visible)
{
var modButtonLabelSize =
modsButton.Font.MeasureString(modsButton.Text).ToPoint()
+ new Point(GUI.IntScale(25));
modUpdatesButton.RectTransform.AbsoluteOffset =
(modButtonLabelSize.X, modsButton.Rect.Height / 2 - modUpdatesButton.Rect.Height / 2);
}
switch (selectedTab)
{
case Tab.NewGame:
@@ -1035,7 +1094,7 @@ namespace Barotrauma
GUI.DrawLine(spriteBatch, textPos, textPos - Vector2.UnitX * textSize.X, mouseOn ? Color.White : Color.White * 0.7f);
if (mouseOn && PlayerInput.PrimaryMouseButtonClicked())
{
GameMain.Instance.ShowOpenUrlInWebBrowserPrompt("http://privacypolicy.daedalic.com");
GameMain.ShowOpenUrlInWebBrowserPrompt("http://privacypolicy.daedalic.com");
}
}
textPos.Y -= textSize.Y;
@@ -1,6 +1,7 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Barotrauma.Extensions;
using Barotrauma.IO;
@@ -40,6 +41,13 @@ namespace Barotrauma
}
}
[DoesNotReturn]
private static void LogAndThrowException(string errorMsg, string analyticsId)
{
GameAnalyticsManager.AddErrorEventOnce(analyticsId, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
throw new InvalidOperationException(errorMsg);
}
public override void Select()
{
base.Select();
@@ -74,20 +82,11 @@ namespace Barotrauma
}
};
if (!GameMain.Client.IsServerOwner)
if (!GameMain.Client.IsServerOwner && GameMain.Client.ClientPeer.ServerContentPackages.Length == 0)
{
if (GameMain.Client.ClientPeer.ServerContentPackages.Length == 0)
{
string errorMsg = $"Error in ModDownloadScreen: the list of mods the server has enabled was empty. Content package list received: {GameMain.Client.ClientPeer.ContentPackageOrderReceived}";
GameAnalyticsManager.AddErrorEventOnce("ModDownloadScreen.Select:NoContentPackages", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
throw new InvalidOperationException(errorMsg);
}
if (GameMain.Client.ClientPeer.ServerContentPackages.None(p => p.CorePackage != null))
{
string errorMsg = $"Error in ModDownloadScreen: no core packages in the list of mods the server has enabled. Content package list received: {GameMain.Client.ClientPeer.ContentPackageOrderReceived}";
GameAnalyticsManager.AddErrorEventOnce("ModDownloadScreen.Select:NoCorePackage", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
throw new InvalidOperationException(errorMsg);
}
LogAndThrowException("Error in ModDownloadScreen: the list of mods the server has enabled was empty. "
+$"Content package list received: {GameMain.Client.ClientPeer.ContentPackageOrderReceived}",
analyticsId: "ModDownloadScreen.Select:NoContentPackages");
}
var missingPackages = GameMain.Client.ClientPeer.ServerContentPackages
@@ -96,11 +95,18 @@ namespace Barotrauma
{
if (!GameMain.Client.IsServerOwner)
{
var corePackage = GameMain.Client.ClientPeer.ServerContentPackages
.Select(p => p.CorePackage)
.OfType<CorePackage>().FirstOrDefault();
if (corePackage is null)
{
LogAndThrowException($"Error in ModDownloadScreen: no core packages in the list of mods the server has enabled. " +
$"Content package list received: {GameMain.Client.ClientPeer.ContentPackageOrderReceived}",
analyticsId: "ModDownloadScreen.Select:NoCorePackage");
}
ContentPackageManager.EnabledPackages.BackUp();
ContentPackageManager.EnabledPackages.SetCore(
GameMain.Client.ClientPeer.ServerContentPackages
.Select(p => p.CorePackage)
.OfType<CorePackage>().First());
ContentPackageManager.EnabledPackages.SetCore(corePackage);
List<RegularPackage> regularPackages =
GameMain.Client.ClientPeer.ServerContentPackages
.Select(p => p.RegularPackage)
@@ -114,6 +120,15 @@ namespace Barotrauma
return;
}
if (missingPackages.FirstOrDefault(p => p.IsVanilla) is { } mismatchedVanilla)
{
LogAndThrowException("Error in ModDownloadScreen: mismatched Vanilla package: "
+$"local hash is {ContentPackageManager.VanillaCorePackage?.Hash.StringRepresentation ?? "[NULL]"}, "
+$"remote hash is {mismatchedVanilla.Hash.StringRepresentation}. "
+$"Content package list received: {GameMain.Client.ClientPeer.ContentPackageOrderReceived}",
analyticsId: "ModDownloadScreen.Select:MismatchedVanilla");
}
GUIMessageBox msgBox = new GUIMessageBox(
TextManager.Get("ModDownloadTitle"),
"",
@@ -292,14 +307,23 @@ namespace Barotrauma
var serverPackages = GameMain.Client.ClientPeer.ServerContentPackages;
CorePackage corePackage
= downloadedPackages.FirstOrDefault(p => p is CorePackage) as CorePackage
?? serverPackages.FirstOrDefault(p => p.CorePackage != null)
?.CorePackage
?? serverPackages.FirstOrDefault(p => p.CorePackage != null)?.CorePackage
?? throw new Exception($"Failed to find core package to enable");
List<RegularPackage> regularPackages = new List<RegularPackage>();
foreach (var p in serverPackages)
{
if (p.CorePackage != null) { continue; }
if (p.CorePackage != null)
{
// This package is one of our installed core packages
continue;
}
if (corePackage.Hash.Equals(p.Hash))
{
// This package is the core package we downloaded from the server
continue;
}
RegularPackage? matchingPackage =
p.RegularPackage ?? downloadedPackages.FirstOrDefault(d => d is RegularPackage && d.Hash.Equals(p.Hash)) as RegularPackage;
if (matchingPackage is null)
@@ -357,9 +381,13 @@ namespace Barotrauma
string dir = path.RemoveFromEnd(ModReceiver.Extension, StringComparison.OrdinalIgnoreCase);
SaveUtil.DecompressToDirectory(path, dir, file => { });
ContentPackage newPackage
= ContentPackage.TryLoad($"{dir}/{ContentPackage.FileListFileName}")
?? throw new Exception($"Failed to load downloaded mod \"{currentDownload.Name}\"");
var result = ContentPackage.TryLoad(Path.Combine(dir, ContentPackage.FileListFileName));
if (!result.TryUnwrapSuccess(out var newPackage))
{
throw new Exception($"Failed to load downloaded mod \"{currentDownload.Name}\"",
result.TryUnwrapFailure(out var exception) ? exception : null);
}
if (!currentDownload.Hash.Equals(newPackage.Hash))
{
throw new Exception($"Hash mismatch for downloaded mod \"{currentDownload.Name}\" (expected {currentDownload.Hash}, got {newPackage.Hash})");
@@ -103,6 +103,10 @@ namespace Barotrauma
public GUIFrame JobPreferenceContainer;
public GUIListBox JobList;
private Identifier micIconStyle;
private float micCheckTimer;
const float MicCheckInterval = 1.0f;
private float autoRestartTimer;
//persistent characterinfo provided by the server
@@ -2656,27 +2660,9 @@ namespace Barotrauma
public override void Update(double deltaTime)
{
base.Update(deltaTime);
if (GameMain.Client == null) { return; }
Identifier currMicStyle = micIcon.Style.Element.NameAsIdentifier();
Identifier targetMicStyle = "GUIMicrophoneEnabled".ToIdentifier();
var voipCaptureDeviceNames = VoipCapture.CaptureDeviceNames;
if (voipCaptureDeviceNames.Count == 0)
{
targetMicStyle = "GUIMicrophoneUnavailable".ToIdentifier();
}
else if (GameSettings.CurrentConfig.Audio.VoiceSetting == VoiceMode.Disabled)
{
targetMicStyle = "GUIMicrophoneDisabled".ToIdentifier();
}
if (targetMicStyle != currMicStyle)
{
GUIStyle.Apply(micIcon, targetMicStyle);
}
UpdateMicIcon((float)deltaTime);
foreach (GUIComponent child in PlayerList.Content.Children)
{
@@ -2738,6 +2724,35 @@ namespace Barotrauma
if (!mouseRect.Contains(PlayerInput.MousePosition)) { jobVariantTooltip = null; }
}
}
private void UpdateMicIcon(float deltaTime)
{
micCheckTimer -= deltaTime;
if (micCheckTimer > 0.0f) { return; }
Identifier newMicIconStyle = "GUIMicrophoneEnabled".ToIdentifier();
if (GameSettings.CurrentConfig.Audio.VoiceSetting == VoiceMode.Disabled)
{
newMicIconStyle = "GUIMicrophoneDisabled".ToIdentifier();
}
else
{
var voipCaptureDeviceNames = VoipCapture.GetCaptureDeviceNames();
if (voipCaptureDeviceNames.Count == 0)
{
newMicIconStyle = "GUIMicrophoneUnavailable".ToIdentifier();
}
}
if (newMicIconStyle != micIconStyle)
{
micIconStyle = newMicIconStyle;
GUIStyle.Apply(micIcon, newMicIconStyle);
}
micCheckTimer = MicCheckInterval;
}
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
{
graphics.Clear(Color.Black);
@@ -1352,6 +1352,10 @@ namespace Barotrauma
private void AddToServerList(ServerInfo serverInfo, bool skipPing = false)
{
if (serverInfo.PlayerCount > serverInfo.MaxPlayers) { return; }
if (serverInfo.PlayerCount < 0) { return; }
if (serverInfo.MaxPlayers <= 0) { return; }
RemoveMsgFromServerList(MsgUserData.RefreshingServerList);
RemoveMsgFromServerList(MsgUserData.NoServers);
var serverFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.06f), serverList.Content.RectTransform) { MinSize = new Point(0, 35) },
@@ -379,6 +379,9 @@ namespace Barotrauma
void CreateSprite(ContentXElement element)
{
//empty element, probably an item variant?
if (element.Attributes().None()) { return; }
string spriteFolder = "";
ContentPath texturePath = null;
@@ -208,7 +208,7 @@ namespace Barotrauma
private GUIFrame wiringToolPanel;
private DateTime editorSelectedTime;
private Option<DateTime> editorSelectedTime;
private GUIImage previewImage;
private GUILayoutGroup previewImageButtonHolder;
@@ -354,9 +354,24 @@ namespace Barotrauma
ToolTip = RichString.Rich(TextManager.Get("SaveSubButton") + "‖color:125,125,125‖\nCtrl + S‖color:end‖"),
OnClicked = (btn, data) =>
{
#if DEBUG
if (ContentPackageManager.EnabledPackages.All.Any(cp => cp != ContentPackageManager.VanillaCorePackage && cp.Files.Any(f => f is not BaseSubFile)))
{
var msgBox = new GUIMessageBox("DEBUG-ONLY WARNING", "You currently have some mods enabled. Are you sure you want to save the submarine? If the mods override any vanilla content, saving the submarine may cause unintended changes.",
new LocalizedString[] { "Yes, I know what I'm doing", "Cancel" });
msgBox.Buttons[0].OnClicked = (btn, data) =>
{
msgBox.Close();
loadFrame = null;
CreateSaveScreen();
return true;
};
msgBox.Buttons[1].OnClicked += msgBox.Close;
return false;
}
#endif
loadFrame = null;
CreateSaveScreen();
return true;
}
};
@@ -984,6 +999,7 @@ namespace Barotrauma
foreach (MapEntityCategory category in Enum.GetValues(typeof(MapEntityCategory)))
{
if (category == MapEntityCategory.None) { continue; }
entityCategoryButtons.Add(new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), entityMenuTop.RectTransform, scaleBasis: ScaleBasis.BothHeight),
"", style: "CategoryButton." + category.ToString())
{
@@ -1071,6 +1087,7 @@ namespace Barotrauma
foreach (MapEntityCategory category in Enum.GetValues(typeof(MapEntityCategory)))
{
if (category == MapEntityCategory.None) { continue; }
LocalizedString categoryName = TextManager.Get("MapEntityCategory." + category);
maxTextWidth = (int)Math.Max(maxTextWidth, GUIStyle.SubHeadingFont.MeasureString(categoryName.Replace(" ", "\n")).X + GUI.IntScale(50));
foreach (MapEntityPrefab ep in MapEntityPrefab.List)
@@ -1394,7 +1411,7 @@ namespace Barotrauma
if (backedUpSubInfo != null) { name = backedUpSubInfo.Name; }
subNameLabel.Text = ToolBox.LimitString(name, subNameLabel.Font, subNameLabel.Rect.Width);
editorSelectedTime = DateTime.Now;
editorSelectedTime = Option<DateTime>.Some(DateTime.Now);
GUI.ForceMouseOn(null);
SetMode(Mode.Default);
@@ -1543,9 +1560,13 @@ namespace Barotrauma
autoSaveLabel?.Parent?.RemoveChild(autoSaveLabel);
autoSaveLabel = null;
TimeSpan timeInEditor = DateTime.Now - editorSelectedTime;
#if USE_STEAM
SteamAchievementManager.IncrementStat("hoursineditor".ToIdentifier(), (float)timeInEditor.TotalHours);
if (editorSelectedTime.TryUnwrap(out DateTime selectedTime))
{
TimeSpan timeInEditor = DateTime.Now - selectedTime;
SteamAchievementManager.IncrementStat("hoursineditor".ToIdentifier(), (float)timeInEditor.TotalHours);
editorSelectedTime = Option<DateTime>.None();
}
#endif
GUI.ForceMouseOn(null);
@@ -2490,7 +2511,7 @@ namespace Barotrauma
{
IntValue = MainSub.Info.Tier,
MinValueInt = 1,
MaxValueInt = 3,
MaxValueInt = SubmarineInfo.HighestTier,
OnValueChanged = (numberInput) =>
{
MainSub.Info.Tier = numberInput.IntValue;
@@ -2498,7 +2519,7 @@ namespace Barotrauma
};
if (MainSub?.Info != null)
{
MainSub.Info.Tier = Math.Clamp(MainSub.Info.Tier, 1, 3);
MainSub.Info.Tier = Math.Clamp(MainSub.Info.Tier, 1, SubmarineInfo.HighestTier);
}
var crewSizeArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), subSettingsContainer.RectTransform), isHorizontal: true)
@@ -3074,11 +3095,17 @@ namespace Barotrauma
XDocument doc = new XDocument(ItemAssemblyPrefab.Save(MapEntity.SelectedList.ToList(), nameBox.Text, descriptionBox.Text, hideInMenus));
doc.SaveSafe(filePath);
var resultPackage = ContentPackageManager.ReloadContentPackage(existingContentPackage) as RegularPackage;
if (!ContentPackageManager.EnabledPackages.Regular.Contains(resultPackage))
var result = ContentPackageManager.ReloadContentPackage(existingContentPackage);
if (!result.TryUnwrapSuccess(out var resultPackage))
{
ContentPackageManager.EnabledPackages.EnableRegular(resultPackage);
throw new Exception($"Failed to reload content package \"{existingContentPackage.Name}\"",
result.TryUnwrapFailure(out var exception) ? exception : null);
}
if (resultPackage is RegularPackage regularPackage
&& !ContentPackageManager.EnabledPackages.Regular.Contains(regularPackage))
{
ContentPackageManager.EnabledPackages.EnableRegular(regularPackage);
GameSettings.SaveCurrentConfig();
}
@@ -3089,7 +3116,7 @@ namespace Barotrauma
return false;
}
private void SnapToGrid()
private static void SnapToGrid()
{
// First move components
foreach (MapEntity e in MapEntity.SelectedList)
@@ -3102,6 +3129,10 @@ namespace Barotrauma
var wire = item.GetComponent<Wire>();
if (wire != null) { continue; }
item.Move(offset);
if (item.GetComponent<Door>()?.LinkedGap is Gap linkedGap)
{
linkedGap.Move(item.Position - linkedGap.Position);
}
}
else if (e is Structure structure)
{
@@ -3126,7 +3157,7 @@ namespace Barotrauma
}
}
private IEnumerable<SubmarineInfo> GetLoadableSubs()
private static IEnumerable<SubmarineInfo> GetLoadableSubs()
{
string downloadFolder = Path.GetFullPath(SaveUtil.SubmarineDownloadFolder);
return SubmarineInfo.SavedSubmarines.Where(s
@@ -3231,7 +3262,7 @@ namespace Barotrauma
}
string pathWithoutUserName = Path.GetFullPath(sub.FilePath);
string saveFolder = Path.GetFullPath(SaveUtil.SaveFolder);
string saveFolder = Path.GetFullPath(SaveUtil.DefaultSaveFolder);
if (pathWithoutUserName.StartsWith(saveFolder))
{
pathWithoutUserName = "..." + pathWithoutUserName[saveFolder.Length..];
@@ -3513,9 +3544,18 @@ namespace Barotrauma
public void LoadSub(SubmarineInfo info)
{
Submarine.Unload();
var selectedSub = new Submarine(info);
MainSub = selectedSub;
MainSub.UpdateTransform(interpolate: false);
Submarine selectedSub = null;
try
{
selectedSub = new Submarine(info);
MainSub = selectedSub;
MainSub.UpdateTransform(interpolate: false);
}
catch (Exception e)
{
DebugConsole.ThrowError("Failed to load the submarine. The submarine file might be corrupted.", e);
return;
}
ClearUndoBuffer();
CreateDummyCharacter();
@@ -4220,7 +4260,8 @@ namespace Barotrauma
GUIListBox listBox = new GUIListBox(new RectTransform(new Vector2(0.9f, 0.9f), frame.RectTransform, Anchor.Center))
{
PlaySoundOnSelect = true,
OnSelected = SelectWire
OnSelected = SelectWire,
CanTakeKeyBoardFocus = false
};
List<ItemPrefab> wirePrefabs = new List<ItemPrefab>();
@@ -5869,7 +5910,7 @@ namespace Barotrauma
decimal realWorldDistance = decimal.Round((decimal) (Vector2.Distance(startPos, mouseWorldPos) * Physics.DisplayToRealWorldRatio), 2);
Vector2 offset = new Vector2(GUI.IntScale(24));
GUI.DrawString(spriteBatch, PlayerInput.MousePosition + offset, $"{realWorldDistance}m", GUIStyle.TextColorNormal, font: GUIStyle.SubHeadingFont, backgroundColor: Color.Black, backgroundPadding: 4);
GUI.DrawString(spriteBatch, PlayerInput.MousePosition + offset, $"{realWorldDistance} m", GUIStyle.TextColorNormal, font: GUIStyle.Font, backgroundColor: Color.Black, backgroundPadding: 4);
}
spriteBatch.End();
@@ -21,6 +21,7 @@ namespace Barotrauma
public static Character? dummyCharacter;
public static Effect? BlueprintEffect;
public TabMenu? TabMenu;
public TestScreen()
{
@@ -49,9 +50,10 @@ namespace Barotrauma
}
dummyCharacter = Character.Create(CharacterPrefab.HumanSpeciesName, Vector2.Zero, "", id: Entity.DummyID, hasAi: false);
dummyCharacter.Info.Job = new Job(JobPrefab.Prefabs.Where(jp => TalentTree.JobTalentTrees.ContainsKey(jp.Identifier)).GetRandom(Rand.RandSync.Unsynced));
dummyCharacter.Info.Job = new Job(JobPrefab.Prefabs.FirstOrDefault(static jp => jp.Identifier == "assistant"));
dummyCharacter.Info.Name = "Galldren";
dummyCharacter.Inventory.CreateSlots();
dummyCharacter.Info.GiveExperience(999999);
miniMapItem = new Item(ItemPrefab.Find(null, "deconstructor".ToIdentifier()), Vector2.Zero, null, 1337, false);
@@ -61,6 +63,7 @@ namespace Barotrauma
}
Character.Controlled = dummyCharacter;
GameMain.World.ProcessChanges();
TabMenu = new TabMenu();
}
public override void AddToGUIUpdateList()
@@ -68,35 +71,37 @@ namespace Barotrauma
Frame.AddToGUIUpdateList();
CharacterHUD.AddToGUIUpdateList(dummyCharacter);
dummyCharacter?.SelectedItem?.AddToGUIUpdateList();
TabMenu?.AddToGUIUpdateList();
}
public override void Update(double deltaTime)
{
base.Update(deltaTime);
TabMenu?.Update((float)deltaTime);
if (dummyCharacter is { } dummy && miniMapItem is { } item)
{
if (dummy.SelectedItem != item)
{
dummy.SelectedItem = item;
}
dummy.SelectedItem?.UpdateHUD(Cam, dummy, (float)deltaTime);
Vector2 pos = FarseerPhysics.ConvertUnits.ToSimUnits(item.Position);
foreach (Limb limb in dummy.AnimController.Limbs)
{
limb.body.SetTransform(pos, 0.0f);
}
if (dummy.AnimController?.Collider is { } collider)
{
collider.SetTransform(pos, 0);
}
dummy.ControlLocalPlayer((float)deltaTime, Cam, false);
dummy.Control((float)deltaTime, Cam);
}
// if (dummyCharacter is { } dummy && miniMapItem is { } item)
// {
// if (dummy.SelectedConstruction != item)
// {
// dummy.SelectedConstruction = item;
// }
//
// dummy.SelectedConstruction?.UpdateHUD(Cam, dummy, (float)deltaTime);
// Vector2 pos = FarseerPhysics.ConvertUnits.ToSimUnits(item.Position);
//
// foreach (Limb limb in dummy.AnimController.Limbs)
// {
// limb.body.SetTransform(pos, 0.0f);
// }
//
// if (dummy.AnimController?.Collider is { } collider)
// {
// collider.SetTransform(pos, 0);
// }
//
// dummy.ControlLocalPlayer((float)deltaTime, Cam, false);
// dummy.Control((float)deltaTime, Cam);
// }
}
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)