(965c31410a) Unstable v0.10.4.0

This commit is contained in:
Juan Pablo Arce
2020-07-21 08:57:50 -03:00
parent 4f8bd39789
commit 33d3a41104
546 changed files with 45952 additions and 25762 deletions
@@ -0,0 +1,120 @@
using Barotrauma.Media;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
namespace Barotrauma
{
class CampaignEndScreen : Screen
{
private Video video;
private readonly CreditsPlayer creditsPlayer;
private readonly Camera cam;
public Action OnFinished;
private string textOverlay;
private float textOverlayTimer;
private Vector2 textOverlaySize;
public CampaignEndScreen()
{
creditsPlayer = new CreditsPlayer(new RectTransform(Vector2.One, Frame.RectTransform), "Content/Texts/Credits.xml")
{
AutoRestart = false,
ScrollBarEnabled = false,
AllowMouseWheelScroll = false
};
new GUIButton(new RectTransform(new Vector2(0.1f), creditsPlayer.RectTransform, Anchor.BottomRight, maxSize: new Point(300, 50)) { AbsoluteOffset = new Point(GUI.IntScale(20)) },
TextManager.Get("close"))
{
OnClicked = (btn, userdata) =>
{
creditsPlayer.Scroll = 1.0f;
return true;
}
};
cam = new Camera();
}
public override void Select()
{
base.Select();
textOverlay = ToolBox.WrapText(TextManager.Get("campaignend1"), GameMain.GraphicsWidth / 3, GUI.Font);
textOverlaySize = GUI.Font.MeasureString(textOverlay);
textOverlayTimer = 0.0f;
video = Video.Load(GameMain.GraphicsDeviceManager.GraphicsDevice, GameMain.SoundManager, "Content/SplashScreens/Ending.webm");
video.Play();
creditsPlayer.Restart();
creditsPlayer.Visible = false;
SteamAchievementManager.UnlockAchievement("campaigncompleted", unlockClients: true);
}
public override void Deselect()
{
video?.Dispose();
video = null;
GUI.HideCursor = false;
SoundPlayer.OverrideMusicType = null;
}
public override void Update(double deltaTime)
{
if (creditsPlayer.Finished)
{
OnFinished?.Invoke();
SoundPlayer.OverrideMusicType = null;
}
}
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
{
spriteBatch.Begin();
graphics.Clear(Color.Black);
if (video.IsPlaying)
{
GUI.HideCursor = !GUI.PauseMenuOpen;
spriteBatch.Draw(video.GetTexture(), new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
}
else
{
SoundPlayer.OverrideMusicType = "ending";
float duration = 20.0f;
float creditsDelay = 3.0f;
if (textOverlayTimer < duration + creditsDelay)
{
float textAlpha;
float fadeInTime = 5.0f, fadeOutTime = 3.0f;
textOverlayTimer += (float)deltaTime;
if (textOverlayTimer < fadeInTime)
{
textAlpha = textOverlayTimer / fadeInTime;
}
else if (textOverlayTimer > duration - fadeOutTime)
{
textAlpha = Math.Min((duration - textOverlayTimer) / fadeOutTime, 1.0f);
}
else
{
textAlpha = 1.0f;
}
GUI.Font.DrawString(spriteBatch, textOverlay, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) / 2 - textOverlaySize / 2, Color.White * textAlpha);
}
else
{
GUI.HideCursor = false;
creditsPlayer.Visible = true;
}
}
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Deferred, null, GUI.SamplerState, null, GameMain.ScissorTestEnable);
GUI.Draw(cam, spriteBatch);
spriteBatch.End();
}
}
}
@@ -5,6 +5,7 @@ using System.Collections.Generic;
using Barotrauma.IO;
using System.Linq;
using System.Xml.Linq;
using System.Globalization;
namespace Barotrauma
{
@@ -14,6 +15,7 @@ namespace Barotrauma
private GUIListBox subList;
private GUIListBox saveList;
private List<GUITickBox> subTickBoxes;
private GUITextBox saveNameBox, seedBox;
@@ -90,8 +92,10 @@ namespace Barotrauma
}
else // Spacing to fix the multiplayer campaign setup layout
{
CreateMultiplayerCampaignSubList(leftColumn.RectTransform);
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.25f), leftColumn.RectTransform), style: null);
//new GUIFrame(new RectTransform(new Vector2(1.0f, 0.25f), leftColumn.RectTransform), style: null);
}
// New game right side
@@ -100,13 +104,11 @@ namespace Barotrauma
Stretch = true
};
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.13f),
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.12f),
(isMultiplayer ? leftColumn : rightColumn).RectTransform) { MaxSize = new Point(int.MaxValue, 60) }, childAnchor: Anchor.TopRight);
if (!isMultiplayer) { buttonContainer.IgnoreLayoutGroups = true; }
StartButton = new GUIButton(new RectTransform(isMultiplayer ? new Vector2(0.5f, 1.0f) : Vector2.One,
buttonContainer.RectTransform, Anchor.BottomRight) { MaxSize = new Point(350, 60) },
TextManager.Get("StartCampaignButton"), style: "GUIButtonLarge")
StartButton = new GUIButton(new RectTransform(new Vector2(0.45f, 1f), buttonContainer.RectTransform, Anchor.BottomRight) { MaxSize = new Point(350, 60) }, TextManager.Get("StartCampaignButton"))
{
OnClicked = (GUIButton btn, object userData) =>
{
@@ -128,6 +130,12 @@ namespace Barotrauma
if (GameMain.NetLobbyScreen.SelectedSub == null) { return false; }
selectedSub = GameMain.NetLobbyScreen.SelectedSub;
}
if (selectedSub.SubmarineClass == SubmarineClass.Undefined)
{
new GUIMessageBox(TextManager.Get("error"), TextManager.Get("undefinedsubmarineselected"));
return false;
}
if (string.IsNullOrEmpty(selectedSub.MD5Hash.Hash))
{
@@ -218,6 +226,106 @@ namespace Barotrauma
UpdateLoadMenu(saveFiles);
}
private void CreateMultiplayerCampaignSubList(RectTransform parent)
{
GUILayoutGroup subHolder = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.725f), parent))
{
RelativeSpacing = 0.005f,
Stretch = true
};
var subLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.055f), subHolder.RectTransform) { MinSize = new Point(0, 25) }, TextManager.Language == "English" ? "Purchasable submarines" : TextManager.Get("workshoplabelsubmarines"), font: GUI.SubHeadingFont);
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), subHolder.RectTransform), isHorizontal: true)
{
Stretch = true
};
var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), filterContainer.RectTransform), TextManager.Get("serverlog.filter"), textAlignment: Alignment.CenterLeft, font: GUI.Font);
var searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform, Anchor.CenterRight), font: GUI.Font, createClearButton: true);
filterContainer.RectTransform.MinSize = searchBox.RectTransform.MinSize;
searchBox.OnSelected += (sender, userdata) => { searchTitle.Visible = false; };
searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; };
searchBox.OnTextChanged += (textBox, text) =>
{
foreach (GUIComponent child in subList.Content.Children)
{
if (!(child.UserData is SubmarineInfo sub)) { continue; }
child.Visible = string.IsNullOrEmpty(text) ? true : sub.DisplayName.ToLower().Contains(text.ToLower());
}
return true;
};
subList = new GUIListBox(new RectTransform(Vector2.One, subHolder.RectTransform));
subTickBoxes = new List<GUITickBox>();
for (int i = 0; i < GameMain.Client.ServerSubmarines.Count; i++)
{
SubmarineInfo sub = GameMain.Client.ServerSubmarines[i];
if (!sub.IsCampaignCompatible) continue;
var frame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), subList.Content.RectTransform) { MinSize = new Point(0, 20) },
style: "ListBoxElement")
{
ToolTip = sub.Description,
UserData = sub
};
int buttonSize = (int)(frame.Rect.Height * 0.8f);
GUITickBox tickBox = new GUITickBox(new RectTransform(new Vector2(0.8f, 1.0f), frame.RectTransform, Anchor.CenterLeft), ToolBox.LimitString(sub.DisplayName, GUI.Font, subList.Content.Rect.Width - 65))
{
UserData = sub,
OnSelected = (GUITickBox box) =>
{
GameMain.Client.RequestCampaignSub(box.UserData as SubmarineInfo, box.Selected);
return true;
}
};
subTickBoxes.Add(tickBox);
tickBox.Selected = GameMain.NetLobbyScreen.CampaignSubmarines.Contains(sub);
frame.RectTransform.MinSize = new Point(0, tickBox.RectTransform.MinSize.Y);
var subTextBlock = tickBox.TextBlock;
var matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == sub.Name && s.MD5Hash?.Hash == sub.MD5Hash?.Hash);
if (matchingSub == null) matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == sub.Name);
if (matchingSub == null)
{
subTextBlock.TextColor = new Color(subTextBlock.TextColor, 0.5f);
frame.ToolTip = TextManager.Get("SubNotFound");
}
else if (matchingSub?.MD5Hash == null || matchingSub.MD5Hash?.Hash != sub.MD5Hash?.Hash)
{
subTextBlock.TextColor = new Color(subTextBlock.TextColor, 0.5f);
frame.ToolTip = TextManager.Get("SubDoesntMatch");
}
if (!sub.RequiredContentPackagesInstalled)
{
subTextBlock.TextColor = Color.Lerp(subTextBlock.TextColor, Color.DarkRed, 0.5f);
frame.ToolTip = TextManager.Get("ContentPackageMismatch") + "\n\n" + frame.RawToolTip;
}
var classText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight),
TextManager.Get($"submarineclass.{sub.SubmarineClass}"), textAlignment: Alignment.CenterRight, font: GUI.SmallFont)
{
TextColor = subTextBlock.TextColor * 0.8f,
ToolTip = subTextBlock.RawToolTip
};
}
}
public void RefreshMultiplayerCampaignSubUI(List<SubmarineInfo> campaignSubs)
{
for (int i = 0; i < subTickBoxes.Count; i++)
{
subTickBoxes[i].Selected = campaignSubs.Contains(subTickBoxes[i].UserData as SubmarineInfo);
}
}
public void RandomizeSeed()
{
seedBox.Text = ToolBox.RandomSeed(8);
@@ -239,9 +347,15 @@ namespace Barotrauma
(subPreviewContainer.Parent as GUILayoutGroup)?.Recalculate();
subPreviewContainer.ClearChildren();
SubmarineInfo sub = obj as SubmarineInfo;
if (sub == null) { return true; }
if (!(obj is SubmarineInfo sub)) { return true; }
#if !DEBUG
if (!isMultiplayer && sub.Price > CampaignMode.MaxInitialSubmarinePrice && !GameMain.DebugDraw)
{
StartButton.Enabled = false;
return false;
}
#endif
StartButton.Enabled = true;
sub.CreatePreviewWindow(subPreviewContainer);
return true;
}
@@ -262,10 +376,10 @@ namespace Barotrauma
};
msgBox.Buttons[0].OnClicked += msgBox.Close;
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 10);
while (GameMain.NetLobbyScreen.CampaignUI == null && DateTime.Now < timeOut)
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 20);
while (Screen.Selected != GameMain.GameScreen && DateTime.Now < timeOut)
{
msgBox.Header.Text = headerText + new string('.', ((int)Timing.TotalTime % 3 + 1));
msgBox.Header.Text = headerText + new string('.', (int)Timing.TotalTime % 3 + 1);
yield return CoroutineStatus.Running;
}
msgBox.Close();
@@ -281,11 +395,13 @@ namespace Barotrauma
public void UpdateSubList(IEnumerable<SubmarineInfo> submarines)
{
#if !DEBUG
var subsToShow = submarines.Where(s => !s.HasTag(SubmarineTag.HideInMenus));
#else
var subsToShow = submarines;
#endif
var subsToShow = submarines.Where(s => s.IsCampaignCompatibleIgnoreClass).ToList();
subsToShow.Sort((s1, s2) =>
{
int p1 = s1.Price > CampaignMode.MaxInitialSubmarinePrice ? 10 : 0;
int p2 = s2.Price > CampaignMode.MaxInitialSubmarinePrice ? 10 : 0;
return p1.CompareTo(p2) * 100 + s1.Name.CompareTo(s2.Name);
});
subList.ClearChildren();
@@ -299,30 +415,28 @@ namespace Barotrauma
UserData = sub
};
if(!sub.RequiredContentPackagesInstalled)
if (!sub.RequiredContentPackagesInstalled)
{
textBlock.TextColor = Color.Lerp(textBlock.TextColor, Color.DarkRed, .5f);
textBlock.ToolTip = TextManager.Get("ContentPackageMismatch") + "\n\n" + textBlock.RawToolTip;
}
if (sub.HasTag(SubmarineTag.Shuttle))
var priceText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), textBlock.RectTransform, Anchor.CenterRight),
TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", sub.Price)), textAlignment: Alignment.CenterRight, font: GUI.SmallFont)
{
textBlock.TextColor = textBlock.TextColor * 0.85f;
var shuttleText = new GUITextBlock(new RectTransform(new Point(100, textBlock.Rect.Height), textBlock.RectTransform, Anchor.CenterRight)
{
IsFixedSize = false
},
TextManager.Get("Shuttle", fallBackTag: "RespawnShuttle"), textAlignment: Alignment.Right, font: GUI.SmallFont)
{
TextColor = textBlock.TextColor * 0.8f,
ToolTip = textBlock.RawToolTip
};
TextColor = sub.Price > CampaignMode.MaxInitialSubmarinePrice ? GUI.Style.Red : textBlock.TextColor * 0.8f,
ToolTip = textBlock.ToolTip
};
#if !DEBUG
if (sub.Price > CampaignMode.MaxInitialSubmarinePrice && !GameMain.DebugDraw)
{
textBlock.CanBeFocused = false;
}
#endif
}
if (SubmarineInfo.SavedSubmarines.Any())
{
var nonShuttles = subsToShow.Where(s => !s.HasTag(SubmarineTag.Shuttle)).ToList();
var nonShuttles = subsToShow.Where(s => s.Type == SubmarineType.Player && !s.HasTag(SubmarineTag.Shuttle) && s.Price <= CampaignMode.MaxInitialSubmarinePrice).ToList();
if (nonShuttles.Count > 0)
{
subList.Select(nonShuttles[Rand.Int(nonShuttles.Count)]);
@@ -389,6 +503,7 @@ namespace Barotrauma
CanBeFocused = false
};
bool isCompatible = true;
if (!isMultiplayer)
{
nameText.Text = Path.GetFileNameWithoutExtension(saveFile);
@@ -406,10 +521,10 @@ namespace Barotrauma
saveList.Content.RemoveChild(saveFrame);
continue;
}
subName = doc.Root.GetAttributeString("submarine", "");
saveTime = doc.Root.GetAttributeString("savetime", "");
contentPackageStr = doc.Root.GetAttributeString("selectedcontentpackages", "");
subName = doc.Root.GetAttributeString("submarine", "");
saveTime = doc.Root.GetAttributeString("savetime", "");
isCompatible = SaveUtil.IsSaveFileCompatible(doc);
contentPackageStr = doc.Root.GetAttributeString("selectedcontentpackages", "");
prevSaveFiles?.Add(saveFile);
}
else
@@ -436,6 +551,11 @@ namespace Barotrauma
saveFrame.ToolTip = string.Join("\n", errorMsg, TextManager.Get("campaignmode.contentpackagemismatchwarning"));
}
}
if (!isCompatible)
{
nameText.TextColor = GUI.Style.Red;
saveFrame.ToolTip = TextManager.Get("campaignmode.incompatiblesave");
}
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), saveFrame.RectTransform, Anchor.BottomLeft),
text: subName, font: GUI.SmallFont)
@@ -516,13 +636,13 @@ namespace Barotrauma
}
XDocument doc = SaveUtil.LoadGameSessionDoc(fileName);
if (doc == null)
if (doc?.Root == null)
{
DebugConsole.ThrowError("Error loading save file \"" + fileName + "\". The file may be corrupted.");
return false;
}
loadGameButton.Enabled = true;
loadGameButton.Enabled = SaveUtil.IsSaveFileCompatible(doc);
RemoveSaveFrame();
File diff suppressed because it is too large Load Diff
@@ -159,7 +159,7 @@ namespace Barotrauma.CharacterEditor
OnPostSpawn();
}
OpenDoors();
GameMain.Instance.OnResolutionChanged += OnResolutionChanged;
GameMain.Instance.ResolutionChanged += OnResolutionChanged;
Instance = this;
if (!GameMain.Config.EditorDisclaimerShown)
@@ -266,7 +266,7 @@ namespace Barotrauma.CharacterEditor
Reset(Character.CharacterList.Where(c => VanillaCharacters.Any(vchar => vchar == c.ConfigPath)));
#endif
}
GameMain.Instance.OnResolutionChanged -= OnResolutionChanged;
GameMain.Instance.ResolutionChanged -= OnResolutionChanged;
GameMain.LightManager.LightingEnabled = true;
ClearWidgets();
ClearSelection();
@@ -12,9 +12,39 @@ namespace Barotrauma
private float scrollSpeed;
public bool AutoRestart = true;
public bool Finished
{
get { return listBox.BarScroll >= 1.0f; }
}
public bool ScrollBarEnabled
{
get { return listBox.ScrollBarEnabled; }
set { listBox.ScrollBarEnabled = value; }
}
public bool AllowMouseWheelScroll
{
get { return listBox.AllowMouseWheelScroll; }
set { listBox.AllowMouseWheelScroll = value; }
}
public float Scroll
{
get { return listBox.BarScroll; }
set { listBox.BarScroll = value; }
}
public CreditsPlayer(RectTransform rectT, string configFile) : base(null, rectT)
{
GameMain.Instance.OnResolutionChanged += () => { ClearChildren(); Load(); };
GameMain.Instance.ResolutionChanged += () =>
{
ClearChildren();
Load();
};
var doc = XMLExtensions.TryLoadXml(configFile);
if (doc == null) { return; }
@@ -35,7 +65,7 @@ namespace Barotrauma
foreach (XElement subElement in configElement.Elements())
{
GUIComponent.FromXML(subElement, listBox.Content.RectTransform);
FromXML(subElement, listBox.Content.RectTransform);
}
foreach (GUIComponent child in listBox.Content.Children)
{
@@ -53,9 +83,11 @@ namespace Barotrauma
protected override void Update(float deltaTime)
{
if (!Visible) { return; }
listBox.BarScroll += scrollSpeed / listBox.TotalSize * deltaTime;
if (listBox.BarScroll >= 1.0f)
if (AutoRestart && listBox.BarScroll >= 1.0f)
{
listBox.BarScroll = 0.0f;
}
@@ -0,0 +1,662 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Barotrauma
{
internal class EditorNode
{
public Vector2 Position { get; set; }
public Vector2 Size { get; set; }
public int ID;
private const int HeaderSize = 32;
public Rectangle HeaderRectangle => new Rectangle(Position.ToPoint(), new Point((int) Size.X, HeaderSize));
public Rectangle Rectangle => new Rectangle(new Point((int) Position.X, (int) Position.Y + HeaderSize), Size.ToPoint());
public string Name { get; protected set; }
public bool CanAddConnections { get; set; }
public readonly List<NodeConnection> Connections = new List<NodeConnection>();
public readonly List<NodeConnectionType> RemovableTypes = new List<NodeConnectionType>();
public bool IsHighlighted;
public bool IsSelected;
protected EditorNode(string name)
{
Name = name;
Position = Vector2.Zero;
}
public virtual XElement Save()
{
throw new NotImplementedException();
}
public XElement SaveConnections()
{
XElement allConnections = new XElement("Connections", new XAttribute("i", ID));
foreach (NodeConnection connection in Connections)
{
XElement connectionElement = new XElement("Connection");
connectionElement.Add(new XAttribute("i", connection.ID));
connectionElement.Add(new XAttribute("type", connection.Type.Label));
if (connection.EndConversation)
{
connectionElement.Add(new XAttribute("endconversation", connection.EndConversation));
}
if (!string.IsNullOrWhiteSpace(connection.OptionText))
{
connectionElement.Add(new XAttribute("optiontext", connection.OptionText));
}
if (!string.IsNullOrWhiteSpace(connection.OverrideValue?.ToString()))
{
connectionElement.Add(new XAttribute("overridevalue", connection.OverrideValue?.ToString()));
connectionElement.Add(new XAttribute("valuetype", connection.OverrideValue?.GetType().ToString()));
}
foreach (var nodeConnection in connection.ConnectedTo)
{
XElement connectedTo = new XElement("ConnectedTo",
new XAttribute("i", nodeConnection.ID),
new XAttribute("node", nodeConnection.Parent.ID));
connectionElement.Add(connectedTo);
}
allConnections.Add(connectionElement);
}
return allConnections;
}
public void LoadConnections(XElement element)
{
foreach (XElement subElement in element.Elements())
{
int id = subElement.GetAttributeInt("i", -1);
string? connectionType = subElement.GetAttributeString("type", null);
bool endConversation = subElement.GetAttributeBool("endconversation", false);
if (id < 0) { continue; }
NodeConnection? connection = Connections.Find(c => c.ID == id);
if (connection == null)
{
if (string.Equals(connectionType, NodeConnectionType.Option.Label, StringComparison.InvariantCultureIgnoreCase))
{
connection = new NodeConnection(this, NodeConnectionType.Option) { ID = id, EndConversation = endConversation };
Connections.Add(connection);
}
else
{
continue;
}
}
string? optionText = subElement.GetAttributeString("optiontext", null);
string? overrideValue = subElement.GetAttributeString("overridevalue", null);
string? valueType = subElement.GetAttributeString("valuetype", null);
if (optionText != null) { connection.OptionText = optionText; }
if (overrideValue != null && valueType != null)
{
Type? type = Type.GetType(valueType);
if (type != null)
{
if (type.IsEnum)
{
Array enums = Enum.GetValues(type);
foreach (object? @enum in enums)
{
if (string.Equals(@enum?.ToString(), overrideValue, StringComparison.InvariantCultureIgnoreCase))
{
connection.OverrideValue = @enum;
}
}
}
else
{
connection.OverrideValue = Convert.ChangeType(overrideValue, type);
}
}
}
foreach (XElement connectedTo in subElement.Elements())
{
int id2 = connectedTo.GetAttributeInt("i", -1);
int node = connectedTo.GetAttributeInt("node", -1);
if (id2 < 0 || node < 0) { continue; }
EditorNode? otherNode = EventEditorScreen.nodeList.Find(editorNode => editorNode.ID == node);
NodeConnection? otherConnection = otherNode?.Connections.Find(c => c.ID == id2);
if (otherConnection != null)
{
connection.ConnectedTo.Add(otherConnection);
}
}
}
}
public static EditorNode? Load(XElement element)
{
return element.Name.ToString().ToLowerInvariant() switch
{
"eventnode" => EventNode.LoadEventNode(element),
"valuenode" => ValueNode.LoadValueNode(element),
"customnode" => CustomNode.LoadCustomNode(element),
_ => null
};
}
public virtual XElement? ToXML()
{
XElement newElement = new XElement(Name);
foreach (var connection in Connections)
{
if (connection.Type == NodeConnectionType.Value)
{
if (connection.GetValue() != null)
{
newElement.Add(new XAttribute(connection.Attribute?.ToLowerInvariant(), connection.GetValue()));
}
}
}
newElement.Add(new XAttribute("_npos", XMLExtensions.Vector2ToString(Position)));
return newElement;
}
public void Connect(EditorNode otherNode, NodeConnectionType type)
{
NodeConnection? conn = Connections.Find(connection => connection.Type == type && !connection.ConnectedTo.Any());
NodeConnection? found = otherNode.Connections.Find(connection => connection.Type == NodeConnectionType.Activate);
if (found != null)
{
conn?.ConnectedTo.Add(found);
}
}
public void Connect(NodeConnection connection, NodeConnection ownConnection)
{
connection.ConnectedTo.Add(ownConnection);
}
public void Disconnect(NodeConnection conn)
{
foreach (var connection in EventEditorScreen.nodeList.SelectMany(editorNode => editorNode.Connections.Where(connection => connection.ConnectedTo.Contains(conn))))
{
connection.ConnectedTo.Remove(conn);
}
}
public void ClearConnections()
{
foreach (NodeConnection conn in Connections)
{
conn.ClearConnections();
}
}
public virtual Rectangle GetDrawRectangle()
{
return Rectangle;
}
public NodeConnection? GetConnectionOnMouse(Vector2 mousePos)
{
return Connections.FirstOrDefault(eventNodeConnection => eventNodeConnection.DrawRectangle.Contains(mousePos));
}
public void Draw(SpriteBatch spriteBatch)
{
DrawBack(spriteBatch);
DrawFront(spriteBatch);
}
protected virtual void DrawFront(SpriteBatch spriteBatch) { }
protected virtual Color BackgroundColor => new Color(150, 150, 150);
private void DrawBack(SpriteBatch spriteBatch)
{
Color outlineColor = Color.White * 0.8f;
Color fontColor = Color.White;
Color headerColor = IsHighlighted ? new Color(100, 100, 100) : new Color(120, 120, 120);
if (IsSelected)
{
headerColor = new Color(80, 80, 80);
}
float camZoom = Screen.Selected is EventEditorScreen eventEditor ? eventEditor.Cam.Zoom : 1.0f;
Rectangle bodyRect = GetDrawRectangle();
GUI.DrawRectangle(spriteBatch, HeaderRectangle, headerColor, isFilled: true, depth: 1.0f);
GUI.DrawRectangle(spriteBatch, bodyRect, BackgroundColor, isFilled: true, depth: 1.0f);
GUI.DrawRectangle(spriteBatch, HeaderRectangle, outlineColor, isFilled: false, depth: 1.0f, thickness: (int) Math.Max(1, 1.25f / camZoom));
GUI.DrawRectangle(spriteBatch, bodyRect, outlineColor, isFilled: false, depth: 1.0f, thickness: (int) Math.Max(1, 1.25f / camZoom));
int x = 0, y = 0;
foreach (NodeConnection connection in Connections)
{
switch (connection.Type.NodeSide)
{
case NodeConnectionType.Side.Left:
connection.Draw(spriteBatch, Rectangle, y);
y++;
break;
case NodeConnectionType.Side.Right:
connection.Draw(spriteBatch, Rectangle, x);
x++;
break;
}
}
Vector2 headerSize = GUI.SubHeadingFont.MeasureString(Name);
GUI.SubHeadingFont.DrawString(spriteBatch, Name, HeaderRectangle.Location.ToVector2() + (HeaderRectangle.Size.ToVector2() / 2) - (headerSize / 2), fontColor);
}
public virtual void AddOption()
{
Connections.Add(new NodeConnection(this, NodeConnectionType.Option));
}
public void RemoveOption(NodeConnection connection)
{
int index = Connections.IndexOf(connection);
foreach (var nodeConnection in Connections.Skip(index))
{
nodeConnection.ID--;
}
Connections.Remove(connection);
}
public EditorNode? GetNext()
{
var nextNode = Connections.Find(connection => connection.Type == NodeConnectionType.Next);
return nextNode?.ConnectedTo.FirstOrDefault()?.Parent;
}
public EditorNode? GetNext(NodeConnectionType type)
{
var nextNode = Connections.Find(connection => connection.Type == type);
return nextNode?.ConnectedTo.FirstOrDefault()?.Parent;
}
public static bool IsInstanceOf(Type type1, Type type2)
{
return type1.IsAssignableFrom(type2) || type1.IsSubclassOf(type2);
}
public EditorNode? GetParent()
{
var myNode = Connections.Find(connection => connection.Type == NodeConnectionType.Activate);
if (myNode == null) { return null; }
foreach (EditorNode editorNode in EventEditorScreen.nodeList)
{
List<NodeConnection> childConnection = editorNode.Connections.Where(connection => connection.Type == NodeConnectionType.Next ||
connection.Type == NodeConnectionType.Option ||
connection.Type == NodeConnectionType.Failure ||
connection.Type == NodeConnectionType.Success ||
connection.Type == NodeConnectionType.Add).ToList();
if (childConnection.Any(connection => connection != null && connection.ConnectedTo.Contains(myNode)))
{
return editorNode;
}
}
return null;
}
}
internal class EventNode : EditorNode
{
private readonly Type type;
public EventNode(Type type, string name) : base(name)
{
this.type = type;
Size = new Vector2(256, 256);
PropertyInfo[] properties = type.GetProperties().Where(info => info.CustomAttributes.Any(data => data.AttributeType == typeof(Serialize))).ToArray();
Connections.Add(new NodeConnection(this, NodeConnectionType.Activate));
Connections.Add(new NodeConnection(this, NodeConnectionType.Next));
foreach (PropertyInfo property in properties)
{
Connections.Add(new NodeConnection(this, NodeConnectionType.Value, property.Name, property.PropertyType, property));
}
if (IsInstanceOf(type, typeof(BinaryOptionAction)))
{
Connections.Add(new NodeConnection(this, NodeConnectionType.Success));
Connections.Add(new NodeConnection(this, NodeConnectionType.Failure));
}
if (IsInstanceOf(type, typeof(ConversationAction)))
{
CanAddConnections = true;
RemovableTypes.Add(NodeConnectionType.Option);
}
if (IsInstanceOf(type, typeof(StatusEffectAction)) || IsInstanceOf(type, typeof(MissionAction)))
{
Connections.Add(new NodeConnection(this, NodeConnectionType.Add));
}
}
public override XElement Save()
{
XElement newElement = new XElement(nameof(EventNode),
new XAttribute("i", ID),
new XAttribute("type", type.ToString()),
new XAttribute("name", Name),
new XAttribute("xpos", Position.X),
new XAttribute("ypos", Position.Y));
return newElement;
}
public static EditorNode? LoadEventNode(XElement element)
{
if (!string.Equals(element.Name.ToString(), nameof(EventNode), StringComparison.InvariantCultureIgnoreCase)) { return null; }
Type? t = Type.GetType(element.GetAttributeString("type", string.Empty));
if (t == null) { return null; }
EventNode newNode = new EventNode(t, element.GetAttributeString("name", string.Empty)) { ID = element.GetAttributeInt("i", -1) };
float posX = element.GetAttributeFloat("xpos", 0f);
float posY = element.GetAttributeFloat("ypos", 0f);
newNode.Position = new Vector2(posX, posY);
return newNode;
}
public override Rectangle GetDrawRectangle()
{
return ScaleRectFromConnections(Connections, Rectangle);
}
public static Rectangle ScaleRectFromConnections(List<NodeConnection> connections, Rectangle baseRect)
{
// determine how big this box should get based on how many input/output nodes the sides have
int y = connections.Count(connection => connection.Type.NodeSide == NodeConnectionType.Side.Left),
x = connections.Count(connection => connection.Type.NodeSide == NodeConnectionType.Side.Right);
int maxHeight = Math.Max(x, y);
Rectangle bodyRect = baseRect;
bodyRect.Height = bodyRect.Height / 8 * maxHeight;
return bodyRect;
}
public Tuple<EditorNode?, string?, bool>[] GetOptions()
{
IEnumerable<NodeConnection> myNode = Connections.Where(connection => connection.Type == NodeConnectionType.Option).ToArray();
List<Tuple<EditorNode?, string?, bool>> list = new List<Tuple<EditorNode?, string?, bool>>();
if (myNode != null)
{
foreach (NodeConnection connection in myNode)
{
if (connection.ConnectedTo.Any())
{
foreach (NodeConnection nodeConnection in connection.ConnectedTo)
{
list.Add(Tuple.Create((EditorNode?) nodeConnection.Parent, connection.OptionText, connection.EndConversation));
}
}
else
{
list.Add(Tuple.Create<EditorNode?, string?, bool>(null, connection.OptionText, connection.EndConversation));
}
}
}
return list.ToArray();
}
}
internal class ValueNode : EditorNode
{
private object? nodeValue;
public object? Value
{
get => nodeValue;
set
{
nodeValue = value;
if (value is string str)
{
WrappedText = TextManager.Get(str, true) is { } translated ? translated : str;
}
else
{
WrappedText = value?.ToString() ?? string.Empty;
}
valueTextSize = GUI.SubHeadingFont.MeasureString(WrappedText);
}
}
private Vector2 valueTextSize = Vector2.Zero;
public Type Type { get; }
public ValueNode(Type type, string name) : base(name)
{
Type = type;
Value = type.IsValueType ? Activator.CreateInstance(type) : null;
Size = new Vector2(256, 32);
Connections.Add(new NodeConnection(this, NodeConnectionType.Out, "Output", Type));
}
public override XElement Save()
{
XElement newElement = new XElement(nameof(ValueNode));
newElement.Add(new XAttribute("i", ID));
if (Value != null)
{
newElement.Add(new XAttribute("value", Value));
}
newElement.Add(new XAttribute("type", Type.ToString()));
newElement.Add(new XAttribute("name", Name));
newElement.Add(new XAttribute("xpos", Position.X));
newElement.Add(new XAttribute("ypos", Position.Y));
return newElement;
}
public override XElement? ToXML() { return null; }
public static EditorNode? LoadValueNode(XElement element)
{
if (!string.Equals(element.Name.ToString(), nameof(ValueNode), StringComparison.InvariantCultureIgnoreCase)) { return null; }
string? value = element.GetAttributeString("value", null);
Type? type = Type.GetType(element.GetAttributeString("type", string.Empty));
if (type != null)
{
ValueNode newNode = new ValueNode(type, element.GetAttributeString("name", string.Empty)) { ID = element.GetAttributeInt("i", -1) };
float posX = element.GetAttributeFloat("xpos", 0f);
float posY = element.GetAttributeFloat("ypos", 0f);
newNode.Position = new Vector2(posX, posY);
if (value != null)
{
if (type.IsEnum)
{
Array enums = Enum.GetValues(type);
foreach (object? @enum in enums)
{
if (string.Equals(@enum?.ToString(), value, StringComparison.InvariantCultureIgnoreCase))
{
newNode.Value = @enum;
}
}
}
else
{
newNode.Value = Convert.ChangeType(value, type);
}
}
return newNode;
}
return null;
}
protected override Color BackgroundColor => new Color(50, 50, 50);
private string? wrappedText;
private string? WrappedText
{
get => wrappedText;
set
{
string valueText = value ?? "null";
int width = Rectangle.Width;
if (width == 0)
{
wrappedText = valueText;
return;
}
if (width > 16)
{
width -= 16;
}
valueText = ToolBox.WrapText(valueText, width, GUI.SubHeadingFont);
wrappedText = valueText;
}
}
public override Rectangle GetDrawRectangle()
{
Rectangle drawRectangle = Rectangle;
Vector2 size = GUI.SubHeadingFont.MeasureString(WrappedText);
drawRectangle.Height = (int) Math.Max(size.Y + 16, drawRectangle.Height);
return drawRectangle;
}
protected override void DrawFront(SpriteBatch spriteBatch)
{
base.DrawFront(spriteBatch);
Vector2 pos = GetDrawRectangle().Location.ToVector2() + (GetDrawRectangle().Size.ToVector2() / 2) - (valueTextSize / 2);
Rectangle drawRect = Rectangle;
drawRect.Inflate(-1, -1);
GUI.DrawString(spriteBatch, pos, WrappedText, NodeConnection.GetPropertyColor(Type), font: GUI.SubHeadingFont);
}
}
class SpecialNode : EditorNode
{
public SpecialNode(string name) : base(name)
{
Size = new Vector2(256, 256);
}
public override Rectangle GetDrawRectangle()
{
return EventNode.ScaleRectFromConnections(Connections, Rectangle);
}
}
class CustomNode : SpecialNode
{
public CustomNode(string name) : base(name)
{
CanAddConnections = true;
RemovableTypes.Add(NodeConnectionType.Value);
Connections.Add(new NodeConnection(this, NodeConnectionType.Activate));
Connections.Add(new NodeConnection(this, NodeConnectionType.Next));
Connections.Add(new NodeConnection(this, NodeConnectionType.Add));
}
public CustomNode() : this("Custom")
{
Prompt(s =>
{
Name = s;
return true;
});
}
public override void AddOption()
{
Prompt(s =>
{
Connections.Add(new NodeConnection(this, NodeConnectionType.Value, s, typeof(string)));
return true;
});
}
public override XElement Save()
{
XElement newElement = new XElement(nameof(CustomNode));
newElement.Add(new XAttribute("i", ID));
newElement.Add(new XAttribute("name", Name));
newElement.Add(new XAttribute("xpos", Position.X));
newElement.Add(new XAttribute("ypos", Position.Y));
foreach (NodeConnection connection in Connections.FindAll(connection => connection.Type == NodeConnectionType.Value))
{
newElement.Add(new XElement("Value", new XAttribute("name", connection.Attribute)));
}
return newElement;
}
public static EditorNode? LoadCustomNode(XElement element)
{
if (!string.Equals(element.Name.ToString(), nameof(CustomNode), StringComparison.OrdinalIgnoreCase)) { return null; }
CustomNode newNode = new CustomNode(element.GetAttributeString("name", string.Empty)) { ID = element.GetAttributeInt("i", -1) };
float posX = element.GetAttributeFloat("xpos", 0f);
float posY = element.GetAttributeFloat("ypos", 0f);
newNode.Position = new Vector2(posX, posY);
foreach (XElement valueElement in element.Elements())
{
newNode.Connections.Add(new NodeConnection(newNode, NodeConnectionType.Value, valueElement.GetAttributeString("name", string.Empty), typeof(string)));
}
return newNode;
}
private static void Prompt(Func<string, bool> OnAccepted)
{
var msgBox = new GUIMessageBox(TextManager.Get("Name"), "", new[] { TextManager.Get("Ok"), TextManager.Get("Cancel") }, new Vector2(0.2f, 0.175f), minSize: new Point(300, 175));
var layout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.25f), msgBox.Content.RectTransform), isHorizontal: true);
GUITextBox nameInput = new GUITextBox(new RectTransform(Vector2.One, layout.RectTransform));
msgBox.Buttons[1].OnClicked = delegate
{
msgBox.Close();
return true;
};
msgBox.Buttons[0].OnClicked = delegate
{
OnAccepted.Invoke(nameInput.Text);
msgBox.Close();
return true;
};
}
}
}
@@ -0,0 +1,351 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Barotrauma
{
internal class NodeConnectionType
{
public static readonly NodeConnectionType Activate = new NodeConnectionType(Side.Left, "Activate");
public static readonly NodeConnectionType Value = new NodeConnectionType(Side.Left, "Value");
public static readonly NodeConnectionType Option = new NodeConnectionType(Side.Right, "Option", new[] { Activate });
public static readonly NodeConnectionType Add = new NodeConnectionType(Side.Right, "Add", new[] { Activate });
public static readonly NodeConnectionType Success = new NodeConnectionType(Side.Right, "Success", new[] { Activate });
public static readonly NodeConnectionType Failure = new NodeConnectionType(Side.Right, "Failure", new[] { Activate });
public static readonly NodeConnectionType Next = new NodeConnectionType(Side.Right, "Next", new[] { Activate });
public static readonly NodeConnectionType Out = new NodeConnectionType(Side.Right, "Out", new[] { Value });
public enum Side
{
Left,
Right
}
public Side NodeSide { get; }
public string Label { get; }
public NodeConnectionType[]? AllowedConnections { get; }
private NodeConnectionType(Side side, string name, NodeConnectionType[]? allowedConnections = null)
{
NodeSide = side;
Label = name;
AllowedConnections = allowedConnections;
}
}
internal class NodeConnection
{
public string Attribute { get; }
public int ID { get; set; }
public bool EndConversation { get; set; }
private string? optionText;
public string? OptionText
{
get => optionText;
set
{
optionText = value;
actualValue = WrappedValue = TextManager.Get(value, true) is { } translated ? translated : value;
}
}
public NodeConnectionType Type { get; }
public Type? ValueType { get; }
private object? overrideValue;
private object? actualValue;
public object? OverrideValue
{
get => overrideValue;
set
{
overrideValue = value;
if (value is string str)
{
actualValue = WrappedValue = TextManager.Get(str, true) is { } translated ? translated : str;
}
else
{
actualValue = WrappedValue = value?.ToString() ?? string.Empty;
}
}
}
private string? wrappedValue;
private string? WrappedValue
{
get => wrappedValue;
set
{
string valueText = value ?? string.Empty;
if (string.IsNullOrWhiteSpace(valueText))
{
wrappedValue = null;
return;
}
Vector2 textSize = GUI.SmallFont.MeasureString(valueText);
bool wasWrapped = false;
while (textSize.X > 96)
{
wasWrapped = true;
valueText = $"{valueText}...".Substring(0, valueText.Length - 4);
textSize = GUI.SmallFont.MeasureString($"{valueText}...");
}
if (wasWrapped)
{
valueText = valueText.TrimEnd(' ') + "...";
}
wrappedValue = valueText;
}
}
public PropertyInfo? PropertyInfo { get; }
public Rectangle DrawRectangle = Rectangle.Empty;
public readonly EditorNode Parent;
public readonly List<NodeConnection> ConnectedTo = new List<NodeConnection>();
private readonly Color bgColor = Color.DarkGray * 0.8f;
private readonly Color outlineColor = Color.White * 0.8f;
public object? GetValue()
{
if (OverrideValue != null)
{
return OverrideValue;
}
foreach (EditorNode editorNode in EventEditorScreen.nodeList)
{
var outNode = editorNode.Connections.Find(connection => connection.Type == NodeConnectionType.Out);
if (outNode != null && outNode.ConnectedTo.Contains(this))
{
return (outNode.Parent as ValueNode)?.Value;
}
}
return null;
}
public void ClearConnections()
{
foreach (var connection in EventEditorScreen.nodeList.SelectMany(editorNode => editorNode.Connections.Where(connection => connection.ConnectedTo.Contains(this))))
{
connection.ConnectedTo.Remove(this);
}
ConnectedTo.Clear();
}
public NodeConnection(EditorNode parent, NodeConnectionType type, string attribute = "", Type? valueType = null, PropertyInfo? propertyInfo = null)
{
Type = type;
ValueType = valueType;
Attribute = attribute;
PropertyInfo = propertyInfo;
Parent = parent;
ID = parent.Connections.Count;
}
private Point GetRenderPos(Rectangle parentRectangle, int yOffset)
{
int x = Type.NodeSide == NodeConnectionType.Side.Left ? parentRectangle.Left - 15 : parentRectangle.Right - 1;
return new Point(x, parentRectangle.Y + 8 + parentRectangle.Height / 8 * yOffset);
}
public void Draw(SpriteBatch spriteBatch, Rectangle parentRectangle, int yOffset)
{
float camZoom = Screen.Selected is EventEditorScreen eventEditor ? eventEditor.Cam.Zoom : 1.0f;
Point pos = GetRenderPos(parentRectangle, yOffset);
DrawRectangle = new Rectangle(pos, new Point(16, 16));
GUI.DrawRectangle(spriteBatch, DrawRectangle, bgColor, isFilled: true);
GUI.DrawRectangle(spriteBatch, DrawRectangle, EndConversation ? GUI.Style.Red : outlineColor, isFilled: false, thickness: (int)Math.Max(1, 1.25f / camZoom));
string label = string.IsNullOrWhiteSpace(Attribute) ? Type.Label : Attribute;
float xPos = parentRectangle.Center.X > pos.X ? 24 : -8 - GUI.SmallFont.MeasureString(label).X;
if (Type != NodeConnectionType.Out)
{
Vector2 size = GUI.SmallFont.MeasureString(label);
Vector2 positon = new Vector2(pos.X + xPos, pos.Y);
Rectangle bgRect = new Rectangle(positon.ToPoint(), size.ToPoint());
bgRect.Inflate(4, 4);
GUI.DrawRectangle(spriteBatch, bgRect, Color.Black * 0.6f, isFilled: true);
GUI.DrawString(spriteBatch, positon, label, GetPropertyColor(ValueType), font: GUI.SmallFont);
Vector2 mousePos = Screen.Selected.Cam.ScreenToWorld(PlayerInput.MousePosition);
mousePos.Y = -mousePos.Y;
if (bgRect.Contains(mousePos))
{
CustomAttributeData? attribute = PropertyInfo?.CustomAttributes.FirstOrDefault();
if (attribute?.AttributeType == typeof(Serialize))
{
if (attribute.ConstructorArguments.Count > 2)
{
string? description = attribute.ConstructorArguments[2].Value as string;
if (!string.IsNullOrWhiteSpace(description))
{
EventEditorScreen.DrawnTooltip = description;
}
}
}
}
}
if (OverrideValue != null)
{
DrawLabel(spriteBatch, new Vector2(DrawRectangle.Center.X - 96, pos.Y + (DrawRectangle.Height / 2) - (20 / 2)), WrappedValue ?? "null", actualValue?.ToString() ?? string.Empty);
}
if (OptionText != null)
{
DrawLabel(spriteBatch, new Vector2(DrawRectangle.Center.X, pos.Y + (DrawRectangle.Height / 2) - (20 / 2)), WrappedValue ?? "null", actualValue?.ToString() ?? string.Empty);
}
if (Parent.IsHighlighted)
{
DrawConnections(spriteBatch, yOffset, Math.Max(8.0f, 8.0f / camZoom), Color.Red);
}
DrawConnections(spriteBatch, yOffset, width: Math.Max(2.0f, 2.0f / camZoom));
if (EventEditorScreen.DraggedConnection == this)
{
DrawSquareLine(spriteBatch, EventEditorScreen.DraggingPosition, yOffset, width: Math.Max(2.0f, 2.0f / camZoom));
}
}
private void DrawConnections(SpriteBatch spriteBatch, int yOffset, float width = 2, Color? overrideColor = null)
{
foreach (NodeConnection? eventNodeConnection in ConnectedTo)
{
if (eventNodeConnection != null)
{
DrawSquareLine(spriteBatch, new Vector2(eventNodeConnection.DrawRectangle.Left + 1, eventNodeConnection.DrawRectangle.Center.Y), yOffset, width, overrideColor);
}
}
}
private void DrawLabel(SpriteBatch spriteBatch, Vector2 pos, string text, string fullText)
{
float camZoom = Screen.Selected is EventEditorScreen eventEditor ? eventEditor.Cam.Zoom : 1.0f;
Rectangle valueRect = new Rectangle((int)pos.X, (int)pos.Y, 96, 20);
Vector2 textSize = GUI.SmallFont.MeasureString(text);
Vector2 position = valueRect.Location.ToVector2() + valueRect.Size.ToVector2() / 2 - textSize / 2;
Rectangle drawRect = valueRect;
drawRect.Inflate(4, 4);
GUI.DrawRectangle(spriteBatch, drawRect, new Color(50, 50, 50), isFilled: true);
GUI.DrawRectangle(spriteBatch, drawRect, EndConversation ? GUI.Style.Red : outlineColor, isFilled: false, thickness: (int)Math.Max(1, 1.25f / camZoom));
GUI.DrawString(spriteBatch, position, text, GetPropertyColor(ValueType), font: GUI.SmallFont);
DrawRectangle = Rectangle.Union(DrawRectangle, drawRect);
if (!string.IsNullOrWhiteSpace(fullText))
{
Vector2 mousePos = Screen.Selected.Cam.ScreenToWorld(PlayerInput.MousePosition);
mousePos.Y = -mousePos.Y;
if (DrawRectangle.Contains(mousePos))
{
EventEditorScreen.DrawnTooltip = fullText;
}
}
}
private void DrawSquareLine(SpriteBatch spriteBatch, Vector2 position, int yOffset, float width = 2, Color? overrideColor = null)
{
// draw a line between 2 nodes using points
// the order of this array is messed up, I know
// order of points is from start node to end node: 0, 4, 1, 2, 5, 3
Vector2[] points = new Vector2[6];
int xOffset = 24 * (yOffset + 1);
points[0] = new Vector2(DrawRectangle.Right, DrawRectangle.Center.Y);
points[3] = position;
points[1] = points[0];
points[2] = points[3];
points[4] = points[1];
points[5] = points[2];
points[1].X += (points[2].X - points[1].X) / 2;
points[1].X = Math.Max(points[1].X, points[0].X + xOffset);
points[2].X = points[1].X;
// if the node is "behind" us do some magic to make the line curve to prevent overlapping
if (points[1].X <= points[0].X + xOffset)
{
points[4].X += xOffset;
points[1].X = points[4].X;
points[1].Y += (points[2].Y - points[1].Y) / 2;
}
if (points[2].X >= points[3].X - xOffset)
{
points[5].X -= xOffset;
points[2].X = points[5].X;
points[2].Y -= points[2].Y - points[1].Y;
}
Color drawColor = Parent is ValueNode ? GetPropertyColor(ValueType) : GUI.Style.Red;
if (overrideColor != null)
{
drawColor = overrideColor.Value;
}
GUI.DrawLine(spriteBatch, points[0], points[4], drawColor, width: (int)width);
GUI.DrawLine(spriteBatch, points[4], points[1], drawColor, width: (int)width);
GUI.DrawLine(spriteBatch, points[1], points[2], drawColor, width: (int)width);
GUI.DrawLine(spriteBatch, points[2], points[5], drawColor, width: (int)width);
GUI.DrawLine(spriteBatch, points[5], points[3], drawColor, width: (int)width);
}
private static readonly Color defaultColor = new Color(139, 233, 253);
private static readonly Color yellowColor = new Color(241, 250, 140);
private static readonly Color pinkColor = new Color(255, 121, 198);
private static readonly Color purpleColor = new Color(189, 147, 249);
public static Color GetPropertyColor(Type? valueType)
{
Color color = defaultColor;
if (valueType == typeof(bool))
color = pinkColor;
else if (valueType == typeof(string))
color = yellowColor;
else if (valueType == typeof(int) ||
valueType == typeof(float) ||
valueType == typeof(double))
color = purpleColor;
else if (valueType == null) color = Color.White;
return color;
}
public bool CanConnect(NodeConnection otherNode)
{
if (otherNode.OverrideValue != null)
{
return false;
}
return Type.AllowedConnections == null || Type.AllowedConnections.Contains(otherNode.Type);
}
}
}
@@ -20,6 +20,8 @@ namespace Barotrauma
private Texture2D damageStencil;
private Texture2D distortTexture;
private float fadeToBlackState;
public Effect PostProcessEffect { get; private set; }
public Effect GradientEffect { get; private set; }
@@ -29,7 +31,7 @@ namespace Barotrauma
cam.Translate(new Vector2(-10.0f, 50.0f));
CreateRenderTargets(graphics);
GameMain.Instance.OnResolutionChanged += () =>
GameMain.Instance.ResolutionChanged += () =>
{
CreateRenderTargets(graphics);
};
@@ -111,10 +113,10 @@ namespace Barotrauma
sw.Restart();
spriteBatch.Begin(SpriteSortMode.Deferred, null, GUI.SamplerState, null, GameMain.ScissorTestEnable);
if (Character.Controlled != null && cam != null) Character.Controlled.DrawHUD(spriteBatch, cam);
if (GameMain.GameSession != null) GameMain.GameSession.Draw(spriteBatch);
if (Character.Controlled != null && cam != null) { Character.Controlled.DrawHUD(spriteBatch, cam); }
if (GameMain.GameSession != null) { GameMain.GameSession.Draw(spriteBatch); }
if (Character.Controlled == null && !GUI.DisableHUD)
{
@@ -402,6 +404,31 @@ namespace Barotrauma
PostProcessEffect.CurrentTechnique.Passes[0].Apply();
}
Quad.Render();
if (fadeToBlackState > 0.0f)
{
spriteBatch.Begin(SpriteSortMode.Deferred);
GUI.DrawRectangle(spriteBatch, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Lerp(Color.TransparentBlack, Color.Black, fadeToBlackState), isFilled: true);
spriteBatch.End();
}
}
partial void UpdateProjSpecific(double deltaTime)
{
if (ConversationAction.FadeScreenToBlack)
{
fadeToBlackState = Math.Min(fadeToBlackState + (float)deltaTime, 1.0f);
}
else
{
fadeToBlackState = Math.Max(fadeToBlackState - (float)deltaTime, 0.0f);
}
if (!PlayerInput.PrimaryMouseButtonHeld())
{
Inventory.draggingSlot = null;
Inventory.draggingItem = null;
}
}
}
}
@@ -1,8 +1,10 @@
using Barotrauma.Lights;
using Barotrauma.Extensions;
using Barotrauma.Lights;
using Barotrauma.RuinGeneration;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
#if DEBUG
@@ -27,7 +29,7 @@ namespace Barotrauma
private LevelGenerationParams selectedParams;
private LevelObjectPrefab selectedLevelObject;
private GUIListBox paramsList, ruinParamsList, levelObjectList;
private GUIListBox paramsList, ruinParamsList, outpostParamsList, levelObjectList;
private GUIListBox editorContainer;
private GUIButton spriteEditDoneButton;
@@ -65,7 +67,9 @@ namespace Barotrauma
return true;
};
ruinParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), paddedLeftPanel.RectTransform));
var ruinTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.ruinparams"), font: GUI.SubHeadingFont);
ruinParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedLeftPanel.RectTransform));
ruinParamsList.OnSelected += (GUIComponent component, object obj) =>
{
var ruinGenerationParams = obj as RuinGenerationParams;
@@ -74,7 +78,111 @@ namespace Barotrauma
return true;
};
new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedLeftPanel.RectTransform),
var outpostTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.outpostparams"), font: GUI.SubHeadingFont);
GUITextBlock.AutoScaleAndNormalize(ruinTitle, outpostTitle);
outpostParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), paddedLeftPanel.RectTransform));
outpostParamsList.OnSelected += (GUIComponent component, object obj) =>
{
var outpostGenerationParams = obj as OutpostGenerationParams;
editorContainer.ClearChildren();
var outpostParamsEditor = new SerializableEntityEditor(editorContainer.Content.RectTransform, outpostGenerationParams, false, true, elementHeight: 20);
// location type -------------------------
var locationTypeGroup = new GUILayoutGroup(new RectTransform(new Point(editorContainer.Content.Rect.Width, 20)), isHorizontal: true, childAnchor: Anchor.CenterLeft)
{
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), locationTypeGroup.RectTransform), TextManager.Get("outpostmoduleallowedlocationtypes"), textAlignment: Alignment.CenterLeft);
HashSet<string> availableLocationTypes = new HashSet<string> { "any" };
foreach (LocationType locationType in LocationType.List) { availableLocationTypes.Add(locationType.Identifier); }
var locationTypeDropDown = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1f), locationTypeGroup.RectTransform),
text: string.Join(", ", outpostGenerationParams.AllowedLocationTypes.Select(lt => TextManager.Capitalize(lt)) ?? "any".ToEnumerable()), selectMultiple: true);
foreach (string locationType in availableLocationTypes)
{
locationTypeDropDown.AddItem(TextManager.Capitalize(locationType), locationType);
if (outpostGenerationParams.AllowedLocationTypes.Contains(locationType))
{
locationTypeDropDown.SelectItem(locationType);
}
}
if (!outpostGenerationParams.AllowedLocationTypes.Any())
{
locationTypeDropDown.SelectItem("any");
}
locationTypeDropDown.OnSelected += (_, __) =>
{
outpostGenerationParams.SetAllowedLocationTypes(locationTypeDropDown.SelectedDataMultiple.Cast<string>());
locationTypeDropDown.Text = ToolBox.LimitString(locationTypeDropDown.Text, locationTypeDropDown.Font, locationTypeDropDown.Rect.Width);
return true;
};
locationTypeGroup.RectTransform.MinSize = new Point(locationTypeGroup.Rect.Width, locationTypeGroup.RectTransform.Children.Max(c => c.MinSize.Y));
outpostParamsEditor.AddCustomContent(locationTypeGroup, 100);
// module count -------------------------
var moduleLabel = new GUITextBlock(new RectTransform(new Point(editorContainer.Content.Rect.Width, (int)(70 * GUI.Scale))), TextManager.Get("submarinetype.outpostmodules"), font: GUI.SubHeadingFont);
outpostParamsEditor.AddCustomContent(moduleLabel, 100);
foreach (KeyValuePair<string, int> moduleCount in outpostGenerationParams.ModuleCounts)
{
var moduleCountGroup = new GUILayoutGroup(new RectTransform(new Point(editorContainer.Content.Rect.Width, (int)(25 * GUI.Scale))), isHorizontal: true, childAnchor: Anchor.CenterLeft);
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), moduleCountGroup.RectTransform), TextManager.Capitalize(moduleCount.Key), textAlignment: Alignment.CenterLeft);
new GUINumberInput(new RectTransform(new Vector2(0.5f, 1f), moduleCountGroup.RectTransform), GUINumberInput.NumberType.Int)
{
MinValueInt = 0,
MaxValueInt = 100,
IntValue = moduleCount.Value,
OnValueChanged = (numInput) =>
{
outpostGenerationParams.SetModuleCount(moduleCount.Key, numInput.IntValue);
if (numInput.IntValue == 0)
{
outpostParamsList.Select(outpostParamsList.SelectedData);
}
}
};
moduleCountGroup.RectTransform.MinSize = new Point(moduleCountGroup.Rect.Width, moduleCountGroup.RectTransform.Children.Max(c => c.MinSize.Y));
outpostParamsEditor.AddCustomContent(moduleCountGroup, 100);
}
// add module count -------------------------
var addModuleCountGroup = new GUILayoutGroup(new RectTransform(new Point(editorContainer.Content.Rect.Width, (int)(40 * GUI.Scale))), isHorizontal: true, childAnchor: Anchor.Center);
HashSet<string> availableFlags = new HashSet<string>();
foreach (string flag in OutpostGenerationParams.Params.SelectMany(p => p.ModuleCounts.Select(m => m.Key))) { availableFlags.Add(flag); }
foreach (var sub in SubmarineInfo.SavedSubmarines)
{
if (sub.OutpostModuleInfo == null) { continue; }
foreach (string flag in sub.OutpostModuleInfo.ModuleFlags) { availableFlags.Add(flag); }
}
var moduleTypeDropDown = new GUIDropDown(new RectTransform(new Vector2(0.8f, 0.8f), addModuleCountGroup.RectTransform),
text: TextManager.Get("leveleditor.addmoduletype"));
foreach (string flag in availableFlags)
{
if (outpostGenerationParams.ModuleCounts.Any(mc => mc.Key.Equals(flag, StringComparison.OrdinalIgnoreCase))) { continue; }
moduleTypeDropDown.AddItem(TextManager.Capitalize(flag), flag);
}
moduleTypeDropDown.OnSelected += (_, userdata) =>
{
outpostGenerationParams.SetModuleCount(userdata as string, 1);
outpostParamsList.Select(outpostParamsList.SelectedData);
return true;
};
addModuleCountGroup.RectTransform.MinSize = new Point(addModuleCountGroup.Rect.Width, addModuleCountGroup.RectTransform.Children.Max(c => c.MinSize.Y));
outpostParamsEditor.AddCustomContent(addModuleCountGroup, 100);
return true;
};
var createLevelObjButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedLeftPanel.RectTransform),
TextManager.Get("leveleditor.createlevelobj"))
{
OnClicked = (btn, obj) =>
@@ -83,6 +191,7 @@ namespace Barotrauma
return true;
}
};
GUITextBlock.AutoScaleAndNormalize(createLevelObjButton.TextBlock);
lightingEnabled = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform),
TextManager.Get("leveleditor.lightingenabled"));
@@ -130,7 +239,9 @@ namespace Barotrauma
{
Submarine.Unload();
GameMain.LightManager.ClearLights();
Level.CreateRandom(seedBox.Text, generationParams: selectedParams).Generate(mirror: false);
LevelData levelData = LevelData.CreateRandom(seedBox.Text, generationParams: selectedParams);
levelData.ForceOutpostGenerationParams = outpostParamsList.SelectedData as OutpostGenerationParams;
Level.Generate(levelData, mirror: false);
GameMain.LightManager.AddLight(pointerLightSource);
cam.Position = new Vector2(Level.Loaded.Size.X / 2, Level.Loaded.Size.Y / 2);
foreach (GUITextBlock param in paramsList.Content.Children)
@@ -142,6 +253,56 @@ namespace Barotrauma
}
};
new GUIButton(new RectTransform(new Vector2(1.0f, 0.05f), paddedRightPanel.RectTransform),
TextManager.Get("leveleditor.test"))
{
OnClicked = (btn, obj) =>
{
if (Level.Loaded?.LevelData == null) { return false; }
GameMain.GameScreen.Select();
var currEntities = Entity.GetEntities().ToList();
if (Submarine.MainSub != null)
{
var toRemove = Entity.GetEntities().Where(e => e.Submarine == Submarine.MainSub).ToList();
foreach (Entity ent in toRemove)
{
ent.Remove();
}
Submarine.MainSub.Remove();
}
//TODO: hacky workaround to check for wrecks and outposts, refactor SubmarineInfo and ContentType at some point
var nonPlayerFiles = ContentPackage.GetFilesOfType(GameMain.Config.SelectedContentPackages, ContentType.Wreck).ToList();
nonPlayerFiles.AddRange(ContentPackage.GetFilesOfType(GameMain.Config.SelectedContentPackages, ContentType.Outpost));
nonPlayerFiles.AddRange(ContentPackage.GetFilesOfType(GameMain.Config.SelectedContentPackages, ContentType.OutpostModule));
SubmarineInfo subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name.Equals(GameMain.Config.QuickStartSubmarineName, StringComparison.InvariantCultureIgnoreCase));
subInfo ??= SubmarineInfo.SavedSubmarines.GetRandom(s =>
s.IsPlayer && !s.HasTag(SubmarineTag.Shuttle) &&
!nonPlayerFiles.Any(f => f.Path.CleanUpPath().Equals(s.FilePath.CleanUpPath(), StringComparison.InvariantCultureIgnoreCase)));
GameSession gameSession = new GameSession(subInfo, "", GameModePreset.TestMode, null);
gameSession.StartRound(Level.Loaded.LevelData);
(gameSession.GameMode as TestGameMode).OnRoundEnd = () =>
{
GameMain.LevelEditorScreen.Select();
Submarine.MainSub.Remove();
var toRemove = Entity.GetEntities().Where(e => !currEntities.Contains(e)).ToList();
foreach (Entity ent in toRemove)
{
ent.Remove();
}
Submarine.MainSub = null;
};
GameMain.GameSession = gameSession;
return true;
}
};
bottomPanel = new GUIFrame(new RectTransform(new Vector2(0.75f, 0.22f), Frame.RectTransform, Anchor.BottomLeft)
{ MaxSize = new Point(GameMain.GraphicsWidth - rightPanel.Rect.Width, 1000) }, style: "GUIFrameBottom");
@@ -182,6 +343,7 @@ namespace Barotrauma
editingSprite = null;
UpdateParamsList();
UpdateRuinParamsList();
UpdateOutpostParamsList();
UpdateLevelObjectsList();
}
@@ -200,7 +362,7 @@ namespace Barotrauma
foreach (LevelGenerationParams genParams in LevelGenerationParams.LevelParams)
{
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), paramsList.Content.RectTransform) { MinSize = new Point(0, 20) },
genParams.Name)
genParams.Identifier)
{
Padding = Vector4.Zero,
UserData = genParams
@@ -224,6 +386,22 @@ namespace Barotrauma
}
}
private void UpdateOutpostParamsList()
{
editorContainer.ClearChildren();
outpostParamsList.Content.ClearChildren();
foreach (OutpostGenerationParams genParams in OutpostGenerationParams.Params)
{
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), outpostParamsList.Content.RectTransform) { MinSize = new Point(0, 20) },
genParams.Name)
{
Padding = Vector4.Zero,
UserData = genParams
};
}
}
private void UpdateLevelObjectsList()
{
editorContainer.ClearChildren();
@@ -273,15 +451,15 @@ namespace Barotrauma
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), commonnessContainer.RectTransform),
TextManager.GetWithVariable("leveleditor.levelobjcommonness", "[leveltype]", selectedParams.Name), textAlignment: Alignment.Center);
TextManager.GetWithVariable("leveleditor.levelobjcommonness", "[leveltype]", selectedParams.Identifier), textAlignment: Alignment.Center);
new GUINumberInput(new RectTransform(new Vector2(0.5f, 0.4f), commonnessContainer.RectTransform), GUINumberInput.NumberType.Float)
{
MinValueFloat = 0,
MaxValueFloat = 100,
FloatValue = levelObjectPrefab.GetCommonness(selectedParams.Name),
FloatValue = levelObjectPrefab.GetCommonness(selectedParams.Identifier),
OnValueChanged = (numberInput) =>
{
levelObjectPrefab.OverrideCommonness[selectedParams.Name] = numberInput.FloatValue;
levelObjectPrefab.OverrideCommonness[selectedParams.Identifier] = numberInput.FloatValue;
}
};
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), commonnessContainer.RectTransform), style: null);
@@ -411,7 +589,7 @@ namespace Barotrauma
foreach (GUIComponent levelObjFrame in levelObjectList.Content.Children)
{
var levelObj = levelObjFrame.UserData as LevelObjectPrefab;
float commonness = levelObj.GetCommonness(selectedParams.Name);
float commonness = levelObj.GetCommonness(selectedParams.Identifier);
levelObjFrame.Color = commonness > 0.0f ? GUI.Style.Green * 0.4f : Color.Transparent;
levelObjFrame.SelectedColor = commonness > 0.0f ? GUI.Style.Green * 0.6f : Color.White * 0.5f;
levelObjFrame.HoverColor = commonness > 0.0f ? GUI.Style.Green * 0.7f : Color.White * 0.6f;
@@ -428,7 +606,7 @@ namespace Barotrauma
{
var levelObj1 = c1.GUIComponent.UserData as LevelObjectPrefab;
var levelObj2 = c2.GUIComponent.UserData as LevelObjectPrefab;
return Math.Sign(levelObj2.GetCommonness(selectedParams.Name) - levelObj1.GetCommonness(selectedParams.Name));
return Math.Sign(levelObj2.GetCommonness(selectedParams.Identifier) - levelObj1.GetCommonness(selectedParams.Identifier));
});
}
@@ -520,14 +698,15 @@ namespace Barotrauma
{
foreach (XElement subElement in element.Elements())
{
if (subElement.Name.ToString().Equals(genParams.Name, StringComparison.OrdinalIgnoreCase))
{
SerializableProperty.SerializeProperties(genParams, subElement, true);
}
string id = element.GetAttributeString("identifier", null) ?? element.Name.ToString();
if (!id.Equals(genParams.Name, StringComparison.OrdinalIgnoreCase)) { continue; }
SerializableProperty.SerializeProperties(genParams, element, true);
}
}
else if (element.Name.ToString().Equals(genParams.Name, StringComparison.OrdinalIgnoreCase))
{
else
{
string id = element.GetAttributeString("identifier", null) ?? element.Name.ToString();
if (!id.Equals(genParams.Name, StringComparison.OrdinalIgnoreCase)) { continue; }
SerializableProperty.SerializeProperties(genParams, element, true);
}
break;
@@ -575,7 +754,8 @@ namespace Barotrauma
bool elementFound = false;
foreach (XElement element in doc.Root.Elements())
{
if (!element.Name.ToString().Equals(genParams.Name, StringComparison.OrdinalIgnoreCase)) { continue; }
string id = element.GetAttributeString("identifier", null) ?? element.Name.ToString();
if (!id.Equals(genParams.Name, StringComparison.OrdinalIgnoreCase)) { continue; }
SerializableProperty.SerializeProperties(genParams, element, true);
elementFound = true;
}
@@ -1,94 +0,0 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace Barotrauma
{
class LobbyScreen : Screen
{
private CampaignUI campaignUI;
private GUIFrame campaignUIContainer;
private CrewManager CrewManager
{
get { return GameMain.GameSession.CrewManager; }
}
public CampaignUI CampaignUI
{
get { return campaignUI; }
}
public string GetMoney()
{
return campaignUI == null ? "" : campaignUI.GetMoney();
}
public LobbyScreen()
{
campaignUIContainer = new GUIFrame(new RectTransform(Vector2.One, Frame.RectTransform, Anchor.Center), style: null);
}
public override void Select()
{
base.Select();
CampaignMode campaign = GameMain.GameSession.GameMode as CampaignMode;
if (campaign == null) { return; }
campaign.Map.SelectLocation(-1);
campaignUIContainer.ClearChildren();
campaignUI = new CampaignUI(campaign, campaignUIContainer)
{
StartRound = StartRound,
OnLocationSelected = SelectLocation
};
campaignUI.UpdateCharacterLists();
GameAnalyticsManager.SetCustomDimension01("singleplayer");
}
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
{
graphics.Clear(Color.Black);
GUI.DrawBackgroundSprite(spriteBatch,
GameMain.GameSession.Map.CurrentLocation.Type.GetPortrait(GameMain.GameSession.Map.CurrentLocation.PortraitId));
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
GUI.Draw(Cam, spriteBatch);
spriteBatch.End();
}
public void SelectLocation(Location location, LocationConnection locationConnection)
{
}
private void StartRound()
{
if (GameMain.GameSession.Map.SelectedConnection == null) return;
GameMain.Instance.ShowLoading(LoadRound());
}
private IEnumerable<object> LoadRound()
{
GameMain.GameSession.StartRound(campaignUI.SelectedLevel,
mirrorLevel: GameMain.GameSession.Map.CurrentLocation != GameMain.GameSession.Map.SelectedConnection.Locations[0]);
GameMain.GameScreen.Select();
yield return CoroutineStatus.Success;
}
public bool QuitToMainMenu(GUIButton button, object selection)
{
GameMain.MainMenuScreen.Select();
return true;
}
}
}
@@ -54,7 +54,7 @@ namespace Barotrauma
#region Creation
public MainMenuScreen(GameMain game)
{
GameMain.Instance.OnResolutionChanged += () =>
GameMain.Instance.ResolutionChanged += () =>
{
if (Selected == this && selectedTab == Tab.Settings)
{
@@ -688,13 +688,12 @@ namespace Barotrauma
if (selectedSub == null)
{
DebugConsole.NewMessage("Loading a random sub.", Color.White);
var subs = SubmarineInfo.SavedSubmarines.Where(s => !s.HasTag(SubmarineTag.Shuttle) && !s.HasTag(SubmarineTag.HideInMenus));
var subs = SubmarineInfo.SavedSubmarines.Where(s => s.Type == SubmarineType.Player && !s.HasTag(SubmarineTag.Shuttle) && !s.HasTag(SubmarineTag.HideInMenus));
selectedSub = subs.ElementAt(Rand.Int(subs.Count()));
}
var gamesession = new GameSession(
selectedSub,
"Data/Saves/test.xml",
GameModePreset.List.Find(gm => gm.Identifier == "devsandbox"),
GameModePreset.DevSandbox,
missionPrefab: null);
//(gamesession.GameMode as SinglePlayerCampaign).GenerateMap(ToolBox.RandomSeed(8));
gamesession.StartRound(fixedSeed ? "abcd" : ToolBox.RandomSeed(8), difficulty: 40);
@@ -703,13 +702,6 @@ namespace Barotrauma
string[] jobIdentifiers = new string[] { "captain", "engineer", "mechanic", "securityofficer", "medicaldoctor" };
foreach (string job in jobIdentifiers)
{
var spawnPoint = WayPoint.GetRandom(SpawnType.Human, null, Submarine.MainSub, useSyncedRand: true);
if (spawnPoint == null)
{
DebugConsole.ThrowError("No spawnpoints found in the selected submarine. Quickstart failed.");
GameMain.MainMenuScreen.Select();
return;
}
var jobPrefab = JobPrefab.Get(job);
var variant = Rand.Range(0, jobPrefab.Variants);
var characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: jobPrefab, variant: variant);
@@ -717,12 +709,9 @@ namespace Barotrauma
{
DebugConsole.ThrowError("Failed to find the job \"" + job + "\"!");
}
var newCharacter = Character.Create(CharacterPrefab.HumanSpeciesName, spawnPoint.WorldPosition, ToolBox.RandomSeed(8), characterInfo);
newCharacter.GiveJobItems(spawnPoint);
gamesession.CrewManager.AddCharacter(newCharacter);
Character.Controlled = newCharacter;
}
gamesession.CrewManager.AddCharacterInfo(characterInfo);
}
gamesession.CrewManager.InitSinglePlayerRound();
}
public void SetEnableModsNotification(bool visible)
@@ -870,7 +859,7 @@ namespace Barotrauma
}
#endif
*/
GameMain.NetLobbyScreen?.Release();
GameMain.NetLobbyScreen = new NetLobbyScreen();
try
{
@@ -1081,11 +1070,8 @@ namespace Barotrauma
selectedSub = new SubmarineInfo(Path.Combine(SaveUtil.TempPath, selectedSub.Name + ".sub"));
GameMain.GameSession = new GameSession(selectedSub, saveName,
GameModePreset.List.Find(g => g.Identifier == "singleplayercampaign"));
(GameMain.GameSession.GameMode as CampaignMode).GenerateMap(mapSeed);
GameMain.LobbyScreen.Select();
GameMain.GameSession = new GameSession(selectedSub, saveName, GameModePreset.SinglePlayerCampaign, mapSeed);
((SinglePlayerCampaign)GameMain.GameSession.GameMode).LoadNewLevel();
}
private void LoadGame(string saveFile)
@@ -1102,8 +1088,8 @@ namespace Barotrauma
return;
}
GameMain.LobbyScreen.Select();
//TODO
//GameMain.LobbyScreen.Select();
}
#region UI Methods
@@ -1145,6 +1131,8 @@ namespace Barotrauma
int port = NetConfig.DefaultPort;
int queryPort = NetConfig.DefaultQueryPort;
int maxPlayers = 8;
bool karmaEnabled = true;
string selectedKarmaPreset = "";
PlayStyle selectedPlayStyle = PlayStyle.Casual;
if (File.Exists(ServerSettings.SettingsFile))
{
@@ -1154,6 +1142,8 @@ namespace Barotrauma
port = settingsDoc.Root.GetAttributeInt("port", port);
queryPort = settingsDoc.Root.GetAttributeInt("queryport", queryPort);
maxPlayers = settingsDoc.Root.GetAttributeInt("maxplayers", maxPlayers);
karmaEnabled = settingsDoc.Root.GetAttributeBool("karmaenabled", true);
selectedKarmaPreset = settingsDoc.Root.GetAttributeString("karmapreset", "default");
string playStyleStr = settingsDoc.Root.GetAttributeString("playstyle", "Casual");
Enum.TryParse(playStyleStr, out selectedPlayStyle);
}
@@ -1333,10 +1323,12 @@ namespace Barotrauma
foreach (string karmaPreset in tempKarmaManager.Presets.Keys)
{
karmaPresetDD.AddItem(TextManager.Get("KarmaPreset." + karmaPreset), karmaPreset);
if (karmaPreset == "default") { karmaPresetDD.SelectItem(karmaPreset); }
if (karmaPreset == selectedKarmaPreset) { karmaPresetDD.SelectItem(karmaPreset); }
}
if (karmaPresetDD.SelectedIndex == -1) { karmaPresetDD.Select(0); }
karmaEnabledBox.Selected = karmaEnabled;
tickboxAreaLower.RectTransform.MaxSize = karmaEnabledBox.RectTransform.MaxSize;
//spacing
@@ -52,6 +52,8 @@ namespace Barotrauma
public readonly GUIFrame MissionTypeFrame;
public readonly GUIFrame CampaignSetupFrame;
public readonly GUIFrame CampaignFrame;
public readonly GUIButton ContinueCampaignButton, QuitCampaignButton;
private readonly GUITickBox[] missionTypeTickBoxes;
private readonly GUIListBox missionTypeList;
@@ -61,8 +63,8 @@ namespace Barotrauma
get; private set;
}
private readonly GUIComponent gameModeContainer, campaignContainer;
private readonly GUIButton gameModeViewButton, campaignViewButton, spectateButton;
private readonly GUIComponent gameModeContainer;
private readonly GUIButton spectateButton;
private readonly GUILayoutGroup roundControlsHolder;
public GUIButton SettingsButton { get; private set; }
public static GUIButton JobInfoFrame;
@@ -79,11 +81,11 @@ namespace Barotrauma
private readonly GUITickBox autoRestartBox;
private readonly GUITextBlock autoRestartText;
private GUIDropDown shuttleList;
private GUITickBox shuttleTickBox;
private CampaignUI campaignUI;
private GUIComponent settingsBlocker;
private Sprite backgroundSprite;
@@ -223,6 +225,12 @@ namespace Barotrauma
get { return shuttleList.SelectedData as SubmarineInfo; }
}
public CampaignSetupUI CampaignSetupUI;
public List<SubmarineInfo> CampaignSubmarines = new List<SubmarineInfo>();
// Passed onto the gamesession when created
public List<SubmarineInfo> ServerOwnedSubmarines = new List<SubmarineInfo>();
public bool UsingShuttle
{
get { return shuttleTickBox.Selected; }
@@ -308,12 +316,6 @@ namespace Barotrauma
}
}
public CampaignUI CampaignUI
{
get { return campaignUI; }
}
public NetLobbyScreen()
{
float panelSpacing = 0.005f;
@@ -323,22 +325,6 @@ namespace Barotrauma
RelativeSpacing = panelSpacing
};
GameMain.Instance.OnResolutionChanged += () =>
{
foreach (GUIComponent c in Frame.GetAllChildren())
{
if (c.Style != null)
{
c.ApplySizeRestrictions(c.Style);
}
}
if (innerFrame != null)
{
innerFrame.RectTransform.MaxSize = new Point(int.MaxValue, GameMain.GraphicsHeight - 50);
}
};
var panelContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), innerFrame.RectTransform, Anchor.Center), isHorizontal: true)
{
Stretch = true,
@@ -385,25 +371,6 @@ namespace Barotrauma
RelativeSpacing = 0.025f
};
//gamemode tab buttons ------------------------------------------------------------
var gameModeTabButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.03f), panelHolder.RectTransform), isHorizontal: true)
{
RelativeSpacing = 0.01f
};
gameModeViewButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.4f), gameModeTabButtonContainer.RectTransform),
TextManager.Get("GameMode"), style: "GUITabButton")
{
Selected = true,
OnClicked = (bt, userData) => { ToggleCampaignView(false); return true; }
};
campaignViewButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.4f), gameModeTabButtonContainer.RectTransform),
TextManager.Get("CampaignLabel"), style: "GUITabButton")
{
Enabled = false,
OnClicked = (bt, userData) => { ToggleCampaignView(true); return true; }
};
//server game panel ------------------------------------------------------------
modeFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), panelHolder.RectTransform))
@@ -417,11 +384,6 @@ namespace Barotrauma
Stretch = true
};
campaignContainer = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.9f), modeFrame.RectTransform, Anchor.Center), style: null)
{
Visible = false
};
var disconnectButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), bottomBarLeft.RectTransform), TextManager.Get("disconnect"))
{
OnClicked = (bt, userdata) => { GameMain.QuitToMainMenu(save: false, showVerificationPrompt: true); return true; }
@@ -462,14 +424,6 @@ namespace Barotrauma
Stretch = true
};
GameMain.Instance.OnResolutionChanged += () =>
{
if (panelContainer != null && sideBar != null)
{
sideBar.RectTransform.MaxSize = new Point(650, panelContainer.RectTransform.Rect.Height);
}
};
//player info panel ------------------------------------------------------------
myCharacterFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), sideBar.RectTransform));
@@ -483,9 +437,6 @@ namespace Barotrauma
UserData = "spectate"
};
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, gameModeTabButtonContainer.RectTransform.RelativeSize.Y), sideBar.RectTransform), style: null);
// Social area
GUIFrame logBackground = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), sideBar.RectTransform));
@@ -643,7 +594,7 @@ namespace Barotrauma
};
roundControlsHolder = new GUILayoutGroup(new RectTransform(Vector2.One, bottomBarRight.RectTransform),
isHorizontal: true)
isHorizontal: true, childAnchor: Anchor.CenterLeft)
{
Stretch = true
};
@@ -675,11 +626,6 @@ namespace Barotrauma
clientHiddenElements.Add(StartButton);
bottomBar.RectTransform.MinSize =
new Point(0, (int)Math.Max(ReadyToStartBox.RectTransform.MinSize.Y / 0.75f, StartButton.RectTransform.MinSize.Y));
GameMain.Instance.OnResolutionChanged += () =>
{
bottomBar.RectTransform.MinSize =
new Point(0, (int)Math.Max(ReadyToStartBox.RectTransform.MinSize.Y / 0.75f, StartButton.RectTransform.MinSize.Y));
};
//autorestart ------------------------------------------------------------------
@@ -728,10 +674,6 @@ namespace Barotrauma
clientHiddenElements.Add(SettingsButton);
lobbyHeader.RectTransform.MinSize = new Point(0, Math.Max(ServerName.Rect.Height, SettingsButton.Rect.Height));
GameMain.Instance.OnResolutionChanged += () =>
{
lobbyHeader.RectTransform.MinSize = new Point(0, Math.Max(ServerName.Rect.Height, SettingsButton.Rect.Height));
};
GUILayoutGroup lobbyContent = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.9f), infoFrameContent.RectTransform), isHorizontal: true)
{
@@ -861,10 +803,6 @@ namespace Barotrauma
};
shuttleList.ListBox.RectTransform.MinSize = new Point(250, 0);
shuttleHolder.RectTransform.MinSize = new Point(0, shuttleList.RectTransform.Children.Max(c => c.MinSize.Y));
GameMain.Instance.OnResolutionChanged += () =>
{
shuttleHolder.RectTransform.MinSize = new Point(0, shuttleList.RectTransform.Children.Max(c => c.MinSize.Y));
};
subPreviewContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.9f), rightColumn.RectTransform), style: null);
subPreviewContainer.RectTransform.SizeChanged += () =>
@@ -875,84 +813,7 @@ namespace Barotrauma
//------------------------------------------------------------------------------------------------------------------
// Gamemode panel
//------------------------------------------------------------------------------------------------------------------
GUILayoutGroup miscSettingsHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), gameModeContainer.RectTransform),
isHorizontal: true, childAnchor: Anchor.CenterLeft)
{
Stretch = true,
RelativeSpacing = 0.01f
};
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), gameModeContainer.RectTransform), style: "HorizontalLine");
miscSettingsHolder.RectTransform.SizeChanged += () =>
{
miscSettingsHolder.Recalculate();
foreach (GUIComponent child in miscSettingsHolder.Children)
{
if (child is GUITextBlock textBlock)
{
textBlock.TextScale = 1;
textBlock.AutoScaleHorizontal = true;
textBlock.SetTextPos();
}
else if (child is GUITickBox tickBox)
{
tickBox.TextBlock.TextScale = 1;
tickBox.TextBlock.AutoScaleHorizontal = true;
tickBox.TextBlock.SetTextPos();
}
}
};
//seed ------------------------------------------------------------------
var seedLabel = new GUITextBlock(new RectTransform(Vector2.One, miscSettingsHolder.RectTransform), TextManager.Get("LevelSeed"), font: GUI.SubHeadingFont);
seedLabel.RectTransform.MaxSize = new Point((int)(seedLabel.TextSize.X + 30 * GUI.Scale), int.MaxValue);
SeedBox = new GUITextBox(new RectTransform(new Vector2(0.25f, 1.0f), miscSettingsHolder.RectTransform));
SeedBox.OnDeselected += (textBox, key) =>
{
GameMain.Client.ServerSettings.ClientAdminWrite(ServerSettings.NetFlags.LevelSeed);
};
clientDisabledElements.Add(SeedBox);
LevelSeed = ToolBox.RandomSeed(8);
//level difficulty ------------------------------------------------------------------
var difficultyLabel = new GUITextBlock(new RectTransform(Vector2.One, miscSettingsHolder.RectTransform), TextManager.Get("LevelDifficulty"), font: GUI.SubHeadingFont)
{
ToolTip = TextManager.Get("leveldifficultyexplanation")
};
levelDifficultyScrollBar = new GUIScrollBar(new RectTransform(new Vector2(0.25f, 1.0f), miscSettingsHolder.RectTransform), style: "GUISlider", barSize: 0.2f)
{
Step = 0.01f,
Range = new Vector2(0.0f, 100.0f),
ToolTip = TextManager.Get("leveldifficultyexplanation"),
OnReleased = (scrollbar, value) =>
{
GameMain.Client.ServerSettings.ClientAdminWrite(ServerSettings.NetFlags.Misc, levelDifficulty: scrollbar.BarScrollValue);
return true;
}
};
difficultyLabel.RectTransform.MaxSize = new Point((int)(difficultyLabel.TextSize.X + 30 * GUI.Scale), int.MaxValue);
var difficultyName = new GUITextBlock(new RectTransform(new Vector2(0.25f, 1.0f), miscSettingsHolder.RectTransform), "")
{
ToolTip = TextManager.Get("leveldifficultyexplanation")
};
levelDifficultyScrollBar.OnMoved = (scrollbar, value) =>
{
if (EventManagerSettings.List.Count == 0) { return true; }
difficultyName.Text =
EventManagerSettings.List[Math.Min((int)Math.Floor(value * EventManagerSettings.List.Count), EventManagerSettings.List.Count - 1)].Name
+ " (" + ((int)Math.Round(scrollbar.BarScrollValue)) + " %)";
difficultyName.TextColor = ToolBox.GradientLerp(scrollbar.BarScroll, GUI.Style.Green, GUI.Style.Orange, GUI.Style.Red);
return true;
};
clientDisabledElements.Add(levelDifficultyScrollBar);
//gamemode ------------------------------------------------------------------
GUILayoutGroup gameModeBackground = new GUILayoutGroup(new RectTransform(Vector2.One, gameModeContainer.RectTransform), isHorizontal: true)
{
Stretch = true,
@@ -1005,10 +866,6 @@ namespace Barotrauma
style: "GameModeIcon." + mode.Identifier, scaleToFit: true);
modeFrame.RectTransform.MinSize = new Point(0, (int)(modeContent.Children.Sum(c => c.Rect.Height + modeContent.AbsoluteSpacing) / modeContent.RectTransform.RelativeSize.Y));
GameMain.Instance.OnResolutionChanged += () =>
{
modeFrame.RectTransform.MinSize = new Point(0, (int)(modeContent.Children.Sum(c => c.Rect.Height + modeContent.AbsoluteSpacing) / modeContent.RectTransform.RelativeSize.Y));
};
}
var gameModeSpecificFrame = new GUIFrame(new RectTransform(new Vector2(0.333f, 1.0f), gameModeBackground.RectTransform), style: null);
@@ -1016,6 +873,31 @@ namespace Barotrauma
{
Visible = false
};
CampaignFrame = new GUIFrame(new RectTransform(Vector2.One, gameModeSpecificFrame.RectTransform), style: null)
{
Visible = false
};
GUILayoutGroup campaignContent = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.5f), CampaignFrame.RectTransform, Anchor.Center))
{
RelativeSpacing = 0.05f,
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), campaignContent.RectTransform),
TextManager.Get("gamemode.multiplayercampaign"), font: GUI.SubHeadingFont, textAlignment: Alignment.Center);
ContinueCampaignButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.3f), campaignContent.RectTransform),
TextManager.Get("campaigncontinue"), textAlignment: Alignment.Center)
{
OnClicked = (_, __) => { GameMain.Client?.RequestStartRound(true); return true; }
};
QuitCampaignButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.3f), campaignContent.RectTransform),
TextManager.Get("pausemenusavequit"), textAlignment: Alignment.Center)
{
OnClicked = (_, __) =>
{
GameMain.Client.RequestSelectMode(modeList.Content.GetChildIndex(modeList.Content.GetChildByUserData(GameModePreset.Sandbox)));
return true;
}
};
//mission type ------------------------------------------------------------------
MissionTypeFrame = new GUIFrame(new RectTransform(Vector2.One, gameModeSpecificFrame.RectTransform), style: null);
@@ -1062,23 +944,74 @@ namespace Barotrauma
index++;
}
clientDisabledElements.AddRange(missionTypeTickBoxes);
//traitor probability ------------------------------------------------------------------
//------------------------------------------------------------------
// settings panel
//------------------------------------------------------------------
GUILayoutGroup settingsHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.333f, 1.0f), gameModeBackground.RectTransform))
{
Stretch = true
};
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.055f), settingsHolder.RectTransform) { MinSize = new Point(0, 25) }, style: null);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.055f), settingsHolder.RectTransform) { MinSize = new Point(0, 25) },
TextManager.Get("Settings"), font: GUI.SubHeadingFont);
var settingsFrame = new GUIFrame(new RectTransform(Vector2.One, settingsHolder.RectTransform), style: "InnerFrame");
var settingsContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), settingsFrame.RectTransform, Anchor.Center))
{
RelativeSpacing = 0.025f
};
//seed ------------------------------------------------------------------
var seedLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), settingsContent.RectTransform), TextManager.Get("LevelSeed"));
SeedBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), seedLabel.RectTransform, Anchor.CenterRight));
SeedBox.OnDeselected += (textBox, key) =>
{
GameMain.Client.ServerSettings.ClientAdminWrite(ServerSettings.NetFlags.LevelSeed);
};
clientDisabledElements.Add(SeedBox);
LevelSeed = ToolBox.RandomSeed(8);
//level difficulty ------------------------------------------------------------------
var difficultyHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), settingsContent.RectTransform), style: null);
var difficultyLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), difficultyHolder.RectTransform), TextManager.Get("LevelDifficulty"))
{
ToolTip = TextManager.Get("leveldifficultyexplanation")
};
levelDifficultyScrollBar = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.5f), difficultyHolder.RectTransform, Anchor.BottomCenter), style: "GUISlider", barSize: 0.2f)
{
Step = 0.01f,
Range = new Vector2(0.0f, 100.0f),
ToolTip = TextManager.Get("leveldifficultyexplanation"),
OnReleased = (scrollbar, value) =>
{
GameMain.Client.ServerSettings.ClientAdminWrite(ServerSettings.NetFlags.Misc, levelDifficulty: scrollbar.BarScrollValue);
return true;
}
};
var difficultyName = new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), difficultyLabel.RectTransform), "", textAlignment: Alignment.CenterRight)
{
ToolTip = TextManager.Get("leveldifficultyexplanation")
};
levelDifficultyScrollBar.OnMoved = (scrollbar, value) =>
{
if (EventManagerSettings.List.Count == 0) { return true; }
difficultyName.Text =
EventManagerSettings.List[Math.Min((int)Math.Floor(value * EventManagerSettings.List.Count), EventManagerSettings.List.Count - 1)].Name
+ " (" + ((int)Math.Round(scrollbar.BarScrollValue)) + " %)";
difficultyName.TextColor = ToolBox.GradientLerp(scrollbar.BarScroll, GUI.Style.Green, GUI.Style.Orange, GUI.Style.Red);
return true;
};
clientDisabledElements.Add(levelDifficultyScrollBar);
//traitor probability ------------------------------------------------------------------
var traitorsSettingHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), settingsContent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true };
new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.0f), traitorsSettingHolder.RectTransform), TextManager.Get("Traitors"), wrap: true);
@@ -1162,18 +1095,21 @@ namespace Barotrauma
};
List<GUIComponent> settingsElements = settingsContent.Children.ToList();
int spacingElementCount = 0;
for (int i = 0; i < settingsElements.Count; i++)
{
settingsElements[i].RectTransform.MinSize = new Point(0, Math.Max(settingsElements[i].RectTransform.Children.Max(c => c.Rect.Height), (int)(20 * GUI.Scale)));
if (settingsElements[i] is GUITextBlock)
if (settingsElements[i].CountChildren > 0)
{
var spacing = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.03f), settingsContent.RectTransform), style: null);
spacing.RectTransform.RepositionChildInHierarchy(i + spacingElementCount);
spacingElementCount++;
settingsElements[i].RectTransform.MinSize = new Point(0, Math.Max(settingsElements[i].RectTransform.Children.Max(c => c.Rect.Height), (int)(20 * GUI.Scale)));
}
}
settingsBlocker = new GUIFrame(new RectTransform(Vector2.One, settingsFrame.RectTransform), style: "InnerFrame")
{
Color = Color.Black * 0.5f,
IgnoreLayoutGroups = true,
Visible = false
};
clientDisabledElements.AddRange(botSpawnModeButtons);
}
@@ -1181,15 +1117,10 @@ namespace Barotrauma
{
CoroutineManager.StopCoroutines("WaitForStartRound");
GUIMessageBox.CloseAll();
if (StartButton != null)
{
StartButton.Enabled = true;
}
if (campaignUI?.StartButton != null)
{
campaignUI.StartButton.Enabled = true;
}
GUI.ClearCursorWait();
}
@@ -1205,8 +1136,7 @@ namespace Barotrauma
}
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 10);
while (Selected == GameMain.NetLobbyScreen &&
DateTime.Now < timeOut)
while (Selected == GameMain.NetLobbyScreen && DateTime.Now < timeOut)
{
msgBox.Header.Text = headerText + new string('.', ((int)Timing.TotalTime % 3 + 1));
yield return CoroutineStatus.Running;
@@ -1265,30 +1195,18 @@ namespace Barotrauma
clientReadonlyElements.ForEach(c => c.Readonly = true);
clientHiddenElements.ForEach(c => c.Visible = false);
UpdatePermissions();
RefreshEnabledElements();
if (GameMain.Client != null)
{
ChatManager.RegisterKeys(chatInput, GameMain.Client.ChatBox.ChatManager);
spectateButton.Visible = GameMain.Client.GameStarted;
ReadyToStartBox.Parent.Visible = !GameMain.Client.GameStarted;
ReadyToStartBox.Selected = false;
if (campaignUI != null)
{
campaignUI.SelectTab(CampaignUI.Tab.Map);
if (campaignUI.StartButton != null)
{
campaignUI.StartButton.Visible = !GameMain.Client.GameStarted &&
(GameMain.Client.HasPermission(ClientPermissions.ManageRound) ||
GameMain.Client.HasPermission(ClientPermissions.ManageCampaign));
}
}
GameMain.Client.SetReadyToStart(ReadyToStartBox);
}
else
{
spectateButton.Visible = false;
ReadyToStartBox.Parent.Visible = false;
}
SetSpectate(spectateBox.Selected);
@@ -1308,7 +1226,7 @@ namespace Barotrauma
base.Select();
}
public void UpdatePermissions()
public void RefreshEnabledElements()
{
ServerName.Readonly = !GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
ServerMessage.Readonly = !GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
@@ -1329,33 +1247,28 @@ namespace Barotrauma
SettingsButton.Visible = GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
SettingsButton.OnClicked = GameMain.Client.ServerSettings.ToggleSettingsFrame;
StartButton.Visible = GameMain.Client.HasPermission(ClientPermissions.ManageRound) && !GameMain.Client.GameStarted && !campaignContainer.Visible;
StartButton.Visible = GameMain.Client.HasPermission(ClientPermissions.ManageRound) && !GameMain.Client.GameStarted && !CampaignSetupFrame.Visible && !CampaignFrame.Visible;
ServerName.Readonly = !GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
ServerMessage.Readonly = !GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
shuttleTickBox.Enabled = GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
SubList.Enabled = GameMain.Client.ServerSettings.Voting.AllowSubVoting || GameMain.Client.HasPermission(ClientPermissions.SelectSub);
shuttleList.Enabled = GameMain.Client.HasPermission(ClientPermissions.SelectSub);
SubList.Enabled = !CampaignFrame.Visible && (GameMain.Client.ServerSettings.Voting.AllowSubVoting || GameMain.Client.HasPermission(ClientPermissions.SelectSub));
shuttleList.Enabled = shuttleTickBox.Enabled = !CampaignFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.SelectSub);
ModeList.Enabled = GameMain.Client.ServerSettings.Voting.AllowModeVoting || GameMain.Client.HasPermission(ClientPermissions.SelectMode);
LogButtons.Visible = GameMain.Client.HasPermission(ClientPermissions.ServerLog);
GameMain.Client.ShowLogButton.Visible = GameMain.Client.HasPermission(ClientPermissions.ServerLog);
if (campaignUI?.StartButton != null)
{
campaignUI.StartButton.Visible = !GameMain.Client.GameStarted &&
(GameMain.Client.HasPermission(ClientPermissions.ManageRound) ||
GameMain.Client.HasPermission(ClientPermissions.ManageCampaign));
}
roundControlsHolder.Children.ForEach(c => c.IgnoreLayoutGroups = !c.Visible);
roundControlsHolder.Recalculate();
ReadyToStartBox.Parent.Visible = !GameMain.Client.GameStarted && SelectedMode != GameModePreset.MultiPlayerCampaign;
RefreshGameModeContent();
}
public void ShowSpectateButton()
{
if (GameMain.Client == null) return;
if (GameMain.Client == null) { return; }
spectateButton.Visible = true;
spectateButton.Enabled = true;
StartButton.Visible = false;
}
@@ -1373,7 +1286,7 @@ namespace Barotrauma
else if (campaignCharacterInfo != null)
{
campaignCharacterInfo = null;
UpdatePlayerFrame(campaignCharacterInfo, false);
UpdatePlayerFrame(null, false);
}
}
@@ -1392,7 +1305,7 @@ namespace Barotrauma
private void UpdatePlayerFrame(CharacterInfo characterInfo, bool allowEditing, GUIComponent parent)
{
if (characterInfo == null)
if (characterInfo == null || CampaignCharacterDiscarded)
{
characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, GameMain.Client.Name, null);
characterInfo.RecreateHead(
@@ -1409,7 +1322,7 @@ namespace Barotrauma
parent.ClearChildren();
bool isGameRunning = GameMain.GameSession?.GameMode?.IsRunning ?? false;
bool isGameRunning = GameMain.GameSession?.IsRunning ?? false;
infoContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, isGameRunning ? 0.95f : 0.9f), parent.RectTransform, Anchor.BottomCenter), childAnchor: Anchor.TopCenter)
{
@@ -1538,19 +1451,20 @@ namespace Barotrauma
}
else
{
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), infoContainer.RectTransform), characterInfo.Job.Name, textAlignment: Alignment.Center, wrap: true)
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContainer.RectTransform), characterInfo.Job.Name, textAlignment: Alignment.Center, font: GUI.SubHeadingFont, wrap: true)
{
HoverColor = Color.Transparent,
SelectedColor = Color.Transparent
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), infoContainer.RectTransform), TextManager.Get("Skills"));
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContainer.RectTransform), TextManager.Get("Skills"), font: GUI.SubHeadingFont);
foreach (Skill skill in characterInfo.Job.Skills)
{
Color textColor = Color.White * (0.5f + skill.Level / 200.0f);
var skillText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.08f), infoContainer.RectTransform),
" - " + TextManager.AddPunctuation(':', TextManager.Get("SkillName." + skill.Identifier), ((int)skill.Level).ToString()),
textColor);
var skillText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContainer.RectTransform),
" - " + TextManager.AddPunctuation(':', TextManager.Get("SkillName." + skill.Identifier), ((int)skill.Level).ToString()),
textColor,
font: GUI.SmallFont);
}
// Spacing
@@ -1568,7 +1482,7 @@ namespace Barotrauma
{
CampaignCharacterDiscarded = true;
campaignCharacterInfo = null;
UpdatePlayerFrame(null, true);
UpdatePlayerFrame(null, true, parent);
return true;
};
confirmation.Buttons[1].OnClicked += confirmation.Close;
@@ -1751,7 +1665,6 @@ namespace Barotrauma
//make shuttles more dim in the sub list (selecting a shuttle as the main sub is allowed but not recommended)
if (subList == this.subList.Content)
{
shuttleText.RectTransform.RelativeOffset = new Vector2(0.1f, 0.0f);
subTextBlock.TextColor *= 0.5f;
foreach (GUIComponent child in frame.Children)
{
@@ -1759,6 +1672,17 @@ namespace Barotrauma
}
}
}
else
{
var classText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight),
TextManager.Get($"submarineclass.{sub.SubmarineClass}"), textAlignment: Alignment.CenterRight, font: GUI.SmallFont)
{
UserData = "classtext",
TextColor = subTextBlock.TextColor * 0.8f,
ToolTip = subTextBlock.RawToolTip
};
}
}
public bool VotableClicked(GUIComponent component, object userData)
@@ -1807,12 +1731,12 @@ namespace Barotrauma
{
if (GameMain.Client.HasPermission(ClientPermissions.SelectMode))
{
string presetName = ((GameModePreset)(component.UserData)).Identifier;
string presetName = ((GameModePreset)component.UserData).Identifier;
//display a verification prompt when switching away from the campaign
if (HighlightedModeIndex == SelectedModeIndex &&
(GameMain.NetLobbyScreen.ModeList.SelectedData as GameModePreset)?.Identifier == "multiplayercampaign" &&
presetName != "multiplayercampaign")
(GameMain.NetLobbyScreen.ModeList.SelectedData as GameModePreset) == GameModePreset.MultiPlayerCampaign &&
presetName != GameModePreset.MultiPlayerCampaign.Identifier)
{
var verificationBox = new GUIMessageBox("", TextManager.Get("endcampaignverification"), new string[] { TextManager.Get("yes"), TextManager.Get("no") });
verificationBox.Buttons[0].OnClicked += (btn, userdata) =>
@@ -1863,7 +1787,7 @@ namespace Barotrauma
UserData = client
};
var soundIcon = new GUIImage(new RectTransform(new Point((int)(textBlock.Rect.Height * 0.8f)), textBlock.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(5, 0) },
sprite: GUI.Style.GetComponentStyle("GUISoundIcon").Sprites[GUIComponent.ComponentState.None].FirstOrDefault().Sprite, scaleToFit: true)
sprite: GUI.Style.GetComponentStyle("GUISoundIcon").GetDefaultSprite(), scaleToFit: true)
{
UserData = new Pair<string, float>("soundicon", 0.0f),
CanBeFocused = false,
@@ -3037,7 +2961,7 @@ namespace Barotrauma
if (save)
{
if (GameMain.GameSession?.GameMode?.IsRunning ?? false)
if (GameMain.GameSession?.IsRunning ?? false)
{
TabMenu.PendingChanges = true;
CreateChangesPendingText();
@@ -3054,8 +2978,7 @@ namespace Barotrauma
{
if (modeIndex < 0 || modeIndex >= modeList.Content.CountChildren) { return; }
if (campaignUI != null &&
((GameModePreset)modeList.Content.GetChild(modeIndex).UserData).Identifier != "multiplayercampaign")
if ((GameModePreset)modeList.Content.GetChild(modeIndex).UserData != GameModePreset.MultiPlayerCampaign)
{
ToggleCampaignMode(false);
}
@@ -3063,8 +2986,12 @@ namespace Barotrauma
if ((HighlightedModeIndex == selectedModeIndex || HighlightedModeIndex < 0) && modeList.SelectedIndex != modeIndex) { modeList.Select(modeIndex, true); }
selectedModeIndex = modeIndex;
MissionTypeFrame.Visible = SelectedMode != null && SelectedMode.Identifier == "mission" && HighlightedModeIndex == SelectedModeIndex;
CampaignSetupFrame.Visible = !MissionTypeFrame.Visible && SelectedMode.Identifier == "multiplayercampaign";
if (SelectedMode != GameModePreset.MultiPlayerCampaign && GameMain.GameSession?.GameMode is CampaignMode && Selected == this)
{
GameMain.GameSession = null;
}
RefreshGameModeContent();
}
public void HighlightMode(int modeIndex)
@@ -3072,70 +2999,72 @@ namespace Barotrauma
if (modeIndex < 0 || modeIndex >= modeList.Content.CountChildren) { return; }
HighlightedModeIndex = modeIndex;
MissionTypeFrame.Visible = SelectedMode != null && SelectedMode.Identifier == "mission" && HighlightedModeIndex == SelectedModeIndex;
CampaignSetupFrame.Visible = SelectedMode != null && SelectedMode.Identifier == "multiplayercampaign";
RefreshGameModeContent();
}
public void ToggleCampaignView(bool enabled)
private void RefreshGameModeContent()
{
campaignContainer.Visible = enabled;
gameModeContainer.Visible = !enabled;
if (GameMain.Client == null) { return; }
campaignViewButton.Selected = enabled;
gameModeViewButton.Selected = !enabled;
autoRestartBox.Parent.Visible = true;
settingsBlocker.Visible = false;
if (SelectedMode == GameModePreset.Mission)
{
MissionTypeFrame.Visible = true;
CampaignFrame.Visible = CampaignSetupFrame.Visible = false;
}
else if (SelectedMode == GameModePreset.MultiPlayerCampaign)
{
MissionTypeFrame.Visible = autoRestartBox.Parent.Visible = false;
if (GameMain.GameSession?.GameMode is CampaignMode campaign && campaign.Map != null)
{
//campaign running
settingsBlocker.Visible = true;
CampaignFrame.Visible = GameMain.Client.HasPermission(ClientPermissions.ManageCampaign);
ContinueCampaignButton.Enabled = !GameMain.Client.GameStarted && (GameMain.Client.HasPermission(ClientPermissions.ManageCampaign) || GameMain.Client.HasPermission(ClientPermissions.ManageRound));
QuitCampaignButton.Enabled = GameMain.Client.HasPermission(ClientPermissions.ManageCampaign);
CampaignSetupFrame.Visible = false;
}
else
{
CampaignFrame.Visible = false;
CampaignSetupFrame.Visible = GameMain.Client.HasPermission(ClientPermissions.ManageCampaign);
}
}
else
{
MissionTypeFrame.Visible = CampaignFrame.Visible = CampaignSetupFrame.Visible = false;
CampaignFrame.Visible = CampaignSetupFrame.Visible = false;
}
ReadyToStartBox.Parent.Visible = !GameMain.Client.GameStarted && SelectedMode != GameModePreset.MultiPlayerCampaign;
StartButton.Visible =
GameMain.Client.HasPermission(ClientPermissions.ManageRound) &&
!GameMain.Client.GameStarted &&
!CampaignSetupFrame.Visible &&
!CampaignFrame.Visible;
}
public void ToggleCampaignMode(bool enabled)
{
ToggleCampaignView(enabled);
if (!enabled)
{
//remove campaign character from the panel
if (campaignCharacterInfo != null) { UpdatePlayerFrame(null); }
campaignCharacterInfo = null;
CampaignCharacterDiscarded = false;
UpdatePlayerFrame(null);
}
subList.Enabled = !enabled && AllowSubSelection;
shuttleList.Enabled = !enabled && GameMain.Client.HasPermission(ClientPermissions.SelectSub);
StartButton.Visible = GameMain.Client.HasPermission(ClientPermissions.ManageRound) && !GameMain.Client.GameStarted && !enabled;
if (campaignViewButton != null) { campaignViewButton.Enabled = enabled; }
if (enabled)
{
if (campaignUI == null || campaignUI.Campaign != GameMain.GameSession.GameMode)
{
campaignContainer.ClearChildren();
campaignUI = new CampaignUI(GameMain.GameSession.GameMode as CampaignMode, campaignContainer)
{
StartRound = () =>
{
GameMain.Client.RequestStartRound();
CoroutineManager.StartCoroutine(WaitForStartRound(campaignUI.StartButton), "WaitForStartRound");
}
};
var campaignMenuContainer = new GUIFrame(new RectTransform(new Vector2(0.4f, 1.0f), campaignContainer.RectTransform, Anchor.TopRight), style: null)
{
Color = Color.Black
};
CampaignUI.SetMenuPanelParent(campaignMenuContainer.RectTransform);
CampaignUI.SetMissionPanelParent(campaignMenuContainer.RectTransform);
GameMain.GameSession.Map.CenterOffset = new Vector2(-campaignContainer.Rect.Width / 5, 0);
}
modeList.Select(2, true);
}
else
{
campaignUI = null;
CampaignFrame.Visible = CampaignSetupFrame.Visible = false;
}
/*if (GameMain.Server != null)
RefreshEnabledElements();
if (enabled)
{
lastUpdateID++;
}*/
modeList.Select(2, true);
}
}
public void TryDisplayCampaignSubmarine(SubmarineInfo submarine)
@@ -3172,8 +3101,8 @@ namespace Barotrauma
{
if (!(button.UserData is Pair<JobPrefab, int> jobPrefab)) { return false; }
JobInfoFrame = jobPrefab.First.CreateInfoFrame(jobPrefab.Second);
GUIButton closeButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.05f), JobInfoFrame.GetChild(2).GetChild(0).RectTransform, Anchor.BottomRight),
JobInfoFrame = jobPrefab.First.CreateInfoFrame(out GUIComponent buttonContainer);
GUIButton closeButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.05f), buttonContainer.RectTransform, Anchor.BottomRight),
TextManager.Get("Close"))
{
OnClicked = CloseJobInfo
@@ -3281,7 +3210,7 @@ namespace Barotrauma
if (!GameMain.Config.AreJobPreferencesEqual(jobNamePreferences))
{
if (GameMain.GameSession?.GameMode?.IsRunning ?? false)
if (GameMain.GameSession?.IsRunning ?? false)
{
TabMenu.PendingChanges = true;
CreateChangesPendingText();
@@ -3310,6 +3239,9 @@ namespace Barotrauma
public Pair<string, string> FailedSelectedSub;
public Pair<string, string> FailedSelectedShuttle;
public List<Pair<string, string>> FailedCampaignSubs = new List<Pair<string, string>>();
public List<Pair<string, string>> FailedOwnedSubs = new List<Pair<string, string>>();
public bool TrySelectSub(string subName, string md5Hash, GUIListBox subList)
{
if (GameMain.Client == null) { return false; }
@@ -3423,6 +3355,77 @@ namespace Barotrauma
return false;
}
public bool CheckIfCampaignSubMatches(SubmarineInfo serverSubmarine, string deliveryData)
{
if (GameMain.Client == null) return false;
//already downloading the selected sub file
if (GameMain.Client.FileReceiver.ActiveTransfers.Any(t => t.FileName == serverSubmarine.Name + ".sub"))
{
return false;
}
SubmarineInfo purchasableSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == serverSubmarine.Name && s.MD5Hash?.Hash == serverSubmarine.MD5Hash?.Hash);
if (purchasableSub != null)
{
return true;
}
purchasableSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == serverSubmarine.Name);
string errorMsg = "";
if (purchasableSub == null)
{
errorMsg = TextManager.GetWithVariable("SubNotFoundError", "[subname]", serverSubmarine.Name) + " ";
}
else if (purchasableSub.MD5Hash?.Hash == null)
{
errorMsg = TextManager.GetWithVariable("SubLoadError", "[subname]", serverSubmarine.Name) + " ";
/*GUITextBlock textBlock = subList.Content.GetChildByUserData(sub)?.GetChild<GUITextBlock>();
if (textBlock != null) { textBlock.TextColor = GUI.Style.Red; }*/
}
else
{
errorMsg = TextManager.GetWithVariables("SubDoesntMatchError", new string[3] { "[subname]", "[myhash]", "[serverhash]" },
new string[3] { purchasableSub.Name, purchasableSub.MD5Hash.ShortHash, Md5Hash.GetShortHash(serverSubmarine.MD5Hash.Hash) }) + " ";
}
errorMsg += TextManager.Get("DownloadSubQuestion");
//already showing a message about the same sub
if (GUIMessageBox.MessageBoxes.Any(mb => mb.UserData as string == "request" + serverSubmarine.Name))
{
return false;
}
var requestFileBox = new GUIMessageBox(TextManager.Get("DownloadSubLabel"), errorMsg,
new string[] { TextManager.Get("Yes"), TextManager.Get("No") })
{
UserData = "request" + serverSubmarine.Name
};
requestFileBox.Buttons[0].UserData = new string[] { serverSubmarine.Name, serverSubmarine.MD5Hash.Hash };
requestFileBox.Buttons[0].OnClicked += requestFileBox.Close;
requestFileBox.Buttons[0].OnClicked += (GUIButton button, object userdata) =>
{
string[] fileInfo = (string[])userdata;
if (deliveryData == "owned")
{
FailedOwnedSubs.Add(new Pair<string, string>(fileInfo[0], fileInfo[1]));
}
else if (deliveryData == "campaign")
{
FailedCampaignSubs.Add(new Pair<string, string>(fileInfo[0], fileInfo[1]));
}
GameMain.Client?.RequestFile(FileTransferType.Submarine, fileInfo[0], fileInfo[1]);
return true;
};
requestFileBox.Buttons[1].OnClicked += requestFileBox.Close;
return false;
}
private void CreateSubPreview(SubmarineInfo sub)
{
subPreviewContainer?.ClearChildren();
@@ -3442,5 +3445,10 @@ namespace Barotrauma
}
}
}
public void OnRoundEnded()
{
CampaignCharacterDiscarded = false;
}
}
}
@@ -88,9 +88,8 @@ namespace Barotrauma
public ParticleEditorScreen()
{
cam = new Camera();
GameMain.Instance.OnResolutionChanged += CreateUI;
GameMain.Instance.ResolutionChanged += CreateUI;
CreateUI();
}
private void CreateUI()
@@ -0,0 +1,55 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
namespace Barotrauma
{
class RoundSummaryScreen : Screen
{
private Sprite backgroundSprite;
private RoundSummary roundSummary;
private string loadText;
private RectTransform prevGuiElementParent;
public static RoundSummaryScreen Select(Sprite backgroundSprite, RoundSummary roundSummary)
{
var summaryScreen = new RoundSummaryScreen()
{
roundSummary = roundSummary,
backgroundSprite = backgroundSprite,
prevGuiElementParent = roundSummary.Frame.RectTransform.Parent,
loadText = TextManager.Get("campaignstartingpleasewait")
};
roundSummary.Frame.RectTransform.Parent = summaryScreen.Frame.RectTransform;
summaryScreen.Select();
summaryScreen.AddToGUIUpdateList();
return summaryScreen;
}
public override void Deselect()
{
roundSummary.Frame.RectTransform.Parent = prevGuiElementParent;
}
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
{
spriteBatch.Begin(SpriteSortMode.Deferred, null, GUI.SamplerState, null, GameMain.ScissorTestEnable);
if (backgroundSprite != null)
{
float scale = Math.Max(GameMain.GraphicsWidth / backgroundSprite.size.X, GameMain.GraphicsHeight / backgroundSprite.size.Y);
backgroundSprite.Draw(spriteBatch, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) / 2, Color.White, backgroundSprite.size / 2, scale: scale);
}
GUI.Draw(Cam, spriteBatch);
string loadingText = loadText + new string('.', (int)Timing.TotalTime % 3 + 1);
Vector2 textSize = GUI.LargeFont.MeasureString(loadText);
GUI.DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth / 2, GameMain.GraphicsHeight * 0.95f) - textSize / 2, loadingText, Color.White, font: GUI.LargeFont);
spriteBatch.End();
}
}
}
@@ -64,6 +64,12 @@ namespace Barotrauma
GUI.ScreenOverlayColor = to;
yield return CoroutineStatus.Success;
}
}
public virtual void Release()
{
frame.RectTransform.Parent = null;
frame = null;
}
}
}
@@ -67,7 +67,7 @@ namespace Barotrauma
private List<ServerInfo> favoriteServers;
private List<ServerInfo> recentServers;
private readonly HashSet<string> activePings = new HashSet<string>();
private readonly Dictionary<string, int> activePings = new Dictionary<string, int>();
private enum ServerListTab
{
@@ -161,7 +161,7 @@ namespace Barotrauma
private const float sidebarWidth = 0.2f;
public ServerListScreen()
{
GameMain.Instance.OnResolutionChanged += CreateUI;
GameMain.Instance.ResolutionChanged += CreateUI;
CreateUI();
}
@@ -953,6 +953,7 @@ namespace Barotrauma
base.Update(deltaTime);
UpdateFriendsList();
UpdateInfoQueries();
if (PlayerInput.PrimaryMouseButtonClicked())
{
@@ -984,7 +985,7 @@ namespace Barotrauma
//never show newer versions
//(ignore revision number, it doesn't affect compatibility)
if (remoteVersion != null &&
(remoteVersion.Major > GameMain.Version.Major || remoteVersion.Minor > GameMain.Version.Minor || remoteVersion.Build > GameMain.Version.Build))
ToolBox.VersionNewerIgnoreRevision(GameMain.Version, remoteVersion))
{
child.Visible = false;
}
@@ -1047,6 +1048,28 @@ namespace Barotrauma
serverList.UpdateScrollBarSize();
}
private Queue<ServerInfo> pendingQueries = new Queue<ServerInfo>();
int activeQueries = 0;
private void QueueInfoQuery(ServerInfo info)
{
pendingQueries.Enqueue(info);
}
private void OnQueryDone(ServerInfo info)
{
activeQueries--;
}
public void UpdateInfoQueries()
{
while (activeQueries < 25 && pendingQueries.Count > 0)
{
activeQueries++;
var info = pendingQueries.Dequeue();
info.QueryLiveInfo(UpdateServerInfo, OnQueryDone);
}
}
private void ShowDirectJoinPrompt()
{
var msgBox = new GUIMessageBox(TextManager.Get("ServerListDirectJoin"), "",
@@ -1134,7 +1157,7 @@ namespace Barotrauma
SelectedTab = ServerListTab.Favorites;
FilterServers();
serverInfo.QueryLiveInfo(UpdateServerInfo);
QueueInfoQuery(serverInfo);
msgBox.Close();
return false;
@@ -1276,11 +1299,12 @@ namespace Barotrauma
avatarFunc = Steamworks.SteamFriends.GetLargeAvatarAsync;
break;
}
TaskPool.Add(avatarFunc(friend.Id), (Task<Steamworks.Data.Image?> task) =>
TaskPool.Add($"Get{avatarSize}AvatarAsync", avatarFunc(friend.Id), (task) =>
{
if (!task.Result.HasValue) { return; }
Steamworks.Data.Image? img = ((Task<Steamworks.Data.Image?>)task).Result;
if (!img.HasValue) { return; }
var avatarImage = task.Result.Value;
var avatarImage = img.Value;
const int desaturatedWeight = 180;
@@ -1477,10 +1501,13 @@ namespace Barotrauma
CoroutineManager.StopCoroutines("EstimateLobbyPing");
TaskPool.Add(Steamworks.SteamNetworkingUtils.WaitForPingDataAsync(), (task) =>
if (SteamManager.IsInitialized)
{
steamPingInfoReady = true;
});
TaskPool.Add("WaitForPingDataAsync (serverlist)", Steamworks.SteamNetworkingUtils.WaitForPingDataAsync(), (task) =>
{
steamPingInfoReady = true;
});
}
friendsListUpdateTime = Timing.TotalTime - 1.0;
UpdateFriendsList();
@@ -1526,7 +1553,7 @@ namespace Barotrauma
foreach (ServerInfo info in knownServers)
{
AddToServerList(info);
info.QueryLiveInfo(UpdateServerInfo);
QueueInfoQuery(info);
}
}
}
@@ -1823,7 +1850,7 @@ namespace Barotrauma
yield return CoroutineStatus.Running;
}
Steamworks.Data.PingLocation pingLocation = serverInfo.PingLocation.Value;
Steamworks.Data.NetPingLocation pingLocation = serverInfo.PingLocation.Value;
serverInfo.Ping = Steamworks.SteamNetworkingUtils.LocalPingLocation?.EstimatePingTo(pingLocation) ?? -1;
serverInfo.PingChecked = true;
serverPingText.TextColor = GetPingTextColor(serverInfo.Ping);
@@ -1977,25 +2004,25 @@ namespace Barotrauma
lock (activePings)
{
if (activePings.Contains(serverInfo.IP)) { return; }
activePings.Add(serverInfo.IP);
if (activePings.ContainsKey(serverInfo.IP)) { return; }
activePings.Add(serverInfo.IP, activePings.Any() ? activePings.Values.Max()+1 : 0);
}
serverInfo.PingChecked = false;
serverInfo.Ping = -1;
TaskPool.Add(PingServerAsync(serverInfo?.IP, 1000),
TaskPool.Add($"PingServerAsync ({serverInfo?.IP ?? "NULL"})", PingServerAsync(serverInfo.IP, 1000),
new Tuple<ServerInfo, GUITextBlock>(serverInfo, serverPingText),
(rtt, obj) =>
{
var info = obj.Item1;
var text = obj.Item2;
info.Ping = rtt.Result; info.PingChecked = true;
info.Ping = ((Task<int>)rtt).Result; info.PingChecked = true;
text.TextColor = GetPingTextColor(info.Ping);
text.Text = info.Ping > -1 ? info.Ping.ToString() : "?";
lock (activePings)
{
activePings.Remove(serverInfo.IP);
activePings.Remove(info.IP);
}
});
}
@@ -2009,12 +2036,12 @@ namespace Barotrauma
public async Task<int> PingServerAsync(string ip, int timeOut)
{
await Task.Yield();
int activePingCount = 100;
while (activePingCount > 25)
bool shouldGo = false;
while (!shouldGo)
{
lock (activePings)
{
activePingCount = activePings.Count;
shouldGo = activePings.Count(kvp => kvp.Value < activePings[ip]) < 25;
}
await Task.Delay(25);
}
@@ -64,7 +64,7 @@ namespace Barotrauma
public SpriteEditorScreen()
{
cam = new Camera();
GameMain.Instance.OnResolutionChanged += CreateUI;
GameMain.Instance.ResolutionChanged += CreateUI;
CreateUI();
}
@@ -15,6 +15,7 @@ namespace Barotrauma
{
private GUIFrame menu;
private GUIListBox subscribedItemList, topItemList;
private GUITextBox subscribedItemFilter, topItemFilter;
private GUIListBox publishedItemList, myItemList;
@@ -66,7 +67,7 @@ namespace Barotrauma
public SteamWorkshopScreen()
{
GameMain.Instance.OnResolutionChanged += CreateUI;
GameMain.Instance.ResolutionChanged += CreateUI;
CreateUI();
Steamworks.SteamUGC.GlobalOnItemInstalled += OnItemInstalled;
@@ -135,7 +136,7 @@ namespace Barotrauma
}
};
CreateFilterBox(modsContainer, subscribedItemList);
subscribedItemFilter = CreateFilterBox(modsContainer, subscribedItemList);
modsPreviewFrame = new GUIFrame(new RectTransform(new Vector2(0.6f, 1.0f), tabs[(int)Tab.Mods].RectTransform, Anchor.TopRight), style: null);
@@ -165,7 +166,7 @@ namespace Barotrauma
}
};
CreateFilterBox(listContainer, topItemList);
topItemFilter = CreateFilterBox(listContainer, topItemList);
new GUIButton(new RectTransform(new Vector2(1.0f, 0.02f), listContainer.RectTransform), TextManager.Get("FindModsButton"), style: "GUIButtonSmall")
{
@@ -239,7 +240,7 @@ namespace Barotrauma
subscribedCoroutine = CoroutineManager.StartCoroutine(PollSubscribedItems());
}
private void CreateFilterBox(GUIComponent parent, GUIListBox listbox)
private GUITextBox CreateFilterBox(GUIComponent parent, GUIListBox listbox)
{
var filterContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), parent.RectTransform), isHorizontal: true)
{
@@ -260,6 +261,8 @@ namespace Barotrauma
}
return true;
};
return searchBox;
}
public override void Select()
@@ -475,6 +478,18 @@ namespace Barotrauma
return;
}
string text = string.Empty;
if (listBox == subscribedItemList)
{
text = subscribedItemFilter.Text;
}
else if (listBox == topItemList)
{
text = topItemFilter.Text;
}
bool visible = string.IsNullOrEmpty(text) ? true : (item?.Title?.ToLower().Contains(text.ToLower()) ?? false);
int prevIndex = -1;
var existingFrame = listBox.Content.FindChild((component) => { return (component.UserData is Steamworks.Ugc.Item?) && (component.UserData as Steamworks.Ugc.Item?)?.Id == item?.Id; });
if (existingFrame != null)
@@ -486,7 +501,8 @@ namespace Barotrauma
var itemFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), listBox.Content.RectTransform, minSize: new Point(0, 80)),
style: "ListBoxElement")
{
UserData = item
UserData = item,
Visible = visible
};
if (prevIndex > -1)
{
@@ -615,7 +631,7 @@ namespace Barotrauma
{
DebugConsole.NewMessage(errorMsg, Color.Red);
titleText.TextColor = Color.Red;
titleText.ToolTip = itemFrame.ToolTip = TextManager.GetWithVariables("WorkshopItemUpdateFailed", new string[2] { "[itemname]", "[errormessage]" }, new string[2] { TextManager.EnsureUTF8(item?.Title), errorMsg });
titleText.ToolTip = itemFrame.ToolTip = TextManager.GetWithVariables("WorkshopItemUpdateFailed", new string[2] { "[itemname]", "[errormessage]" }, new string[2] { item?.Title, errorMsg });
}
}
}
@@ -630,7 +646,7 @@ namespace Barotrauma
{
DebugConsole.NewMessage(errorMsg, Color.Red);
titleText.TextColor = Color.Red;
titleText.ToolTip = itemFrame.ToolTip = TextManager.GetWithVariables("WorkshopItemUpdateFailed", new string[2] { "[itemname]", "[errormessage]" }, new string[2] { TextManager.EnsureUTF8(item?.Title), errorMsg });
titleText.ToolTip = itemFrame.ToolTip = TextManager.GetWithVariables("WorkshopItemUpdateFailed", new string[2] { "[itemname]", "[errormessage]" }, new string[2] { item?.Title, errorMsg });
}
}
}
@@ -765,7 +781,7 @@ namespace Barotrauma
{
if (response.ResponseStatus == ResponseStatus.Completed)
{
TaskPool.Add(WritePreviewImageAsync(response, previewImagePath), (task) => { action?.Invoke(); });
TaskPool.Add("WritePreviewImageAsync", WritePreviewImageAsync(response, previewImagePath), (task) => { action?.Invoke(); });
}
}
@@ -799,7 +815,7 @@ namespace Barotrauma
if (File.Exists(previewImagePath))
{
TaskPool.Add(LoadPreviewImageAsync(item?.PreviewImageUrl, previewImagePath),
TaskPool.Add("LoadPreviewImageAsync", LoadPreviewImageAsync(item?.PreviewImageUrl, previewImagePath),
new Tuple<Steamworks.Ugc.Item?, GUIListBox>(item, listBox),
(task, tuple) =>
{
@@ -807,7 +823,7 @@ namespace Barotrauma
var previewImage = lb.Content.FindChild(item)?.GetChildByUserData("previewimage") as GUIImage;
if (previewImage != null)
{
previewImage.Sprite = task.Result;
previewImage.Sprite = ((Task<Sprite>)task).Result;
}
else
{
@@ -1449,7 +1465,7 @@ namespace Barotrauma
{
if (itemEditor == null) { return false; }
RemoveItemFromLists(itemEditor.Value.FileId);
TaskPool.Add(Steamworks.SteamUGC.DeleteFileAsync(itemEditor.Value.FileId),
TaskPool.Add("DeleteFileAsync", Steamworks.SteamUGC.DeleteFileAsync(itemEditor.Value.FileId),
(t) =>
{
if (t.Status == TaskStatus.Faulted)
@@ -1600,7 +1616,7 @@ namespace Barotrauma
if (contentFile.Type == ContentType.Executable ||
contentFile.Type == ContentType.ServerExecutable)
{
fileExists |= File.Exists(contentFile.Path + ".dll");
fileExists |= File.Exists(Path.GetFileNameWithoutExtension(contentFile.Path) + ".dll");
}
if (!fileExists)
@@ -1640,7 +1656,7 @@ namespace Barotrauma
if (contentFile.Type == ContentType.Executable ||
contentFile.Type == ContentType.ServerExecutable)
{
fileExists |= File.Exists(contentFile.Path + ".dll");
fileExists |= File.Exists(Path.GetFileNameWithoutExtension(contentFile.Path) + ".dll");
}
var fileFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.12f), createItemFileList.Content.RectTransform) { MinSize = new Point(0, 20) },
@@ -8,6 +8,7 @@ using System.Linq;
using System.Threading;
using System.Xml.Linq;
using Microsoft.Xna.Framework.Input;
using System.Threading.Tasks;
#if DEBUG
using System.IO;
#else
@@ -294,6 +295,7 @@ namespace Barotrauma
};
foreach (SubmarineInfo sub in SubmarineInfo.SavedSubmarines)
{
if (sub.Type != SubmarineType.Player) { continue; }
linkedSubBox.AddItem(sub.Name, sub);
}
linkedSubBox.OnSelected += SelectLinkedSub;
@@ -715,8 +717,13 @@ namespace Barotrauma
GameMain.GameScreen.Select();
GameSession gameSession = new GameSession(backedUpSubInfo, "", GameModePreset.List.Find(gm => gm.Identifier == "subtest"), null);
GameSession gameSession = new GameSession(backedUpSubInfo, "", GameModePreset.TestMode, null);
gameSession.StartRound(null, false);
(gameSession.GameMode as TestGameMode).OnRoundEnd = () =>
{
Submarine.Unload();
GameMain.SubEditorScreen.Select();
};
return true;
}
@@ -824,7 +831,8 @@ namespace Barotrauma
OnClicked = (btn, userData) =>
{
ItemAssemblyPrefab assemblyPrefab = (ItemAssemblyPrefab) userData;
if (assemblyPrefab != null) {
if (assemblyPrefab != null)
{
var msgBox = new GUIMessageBox(
TextManager.Get("DeleteDialogLabel"),
TextManager.GetWithVariable("DeleteDialogQuestion", "[file]", assemblyPrefab.Name),
@@ -873,6 +881,11 @@ namespace Barotrauma
new Color(20, 20, 20, 255);
UpdateEntityList();
if (!wasSelectedBefore)
{
OpenEntityMenu(MapEntityCategory.Structure);
wasSelectedBefore = true;
}
isAutoSaving = false;
if (!wasSelectedBefore)
@@ -906,7 +919,6 @@ namespace Barotrauma
Submarine.MainSub = new Submarine(subInfo);
}
Submarine.MainSub.SetPrevTransform(Submarine.MainSub.Position);
Submarine.MainSub.UpdateTransform(interpolate: false);
cam.Position = Submarine.MainSub.Position + Submarine.MainSub.HiddenSubPosition;
@@ -916,6 +928,7 @@ namespace Barotrauma
linkedSubBox.ClearChildren();
foreach (SubmarineInfo sub in SubmarineInfo.SavedSubmarines)
{
if (sub.Type != SubmarineType.Player) { continue; }
linkedSubBox.AddItem(sub.Name, sub);
}
@@ -1214,12 +1227,89 @@ namespace Barotrauma
nameBox.Flash();
return false;
}
var result = SaveSubToFile(nameBox.Text);
string specialSavePath = "";
if (Submarine.MainSub.Info.Type != SubmarineType.Player)
{
ContentType contentType = ContentType.Submarine;
switch (Submarine.MainSub.Info.Type)
{
case SubmarineType.OutpostModule:
if (Submarine.MainSub.Info?.OutpostModuleInfo != null)
{
contentType = ContentType.OutpostModule;
}
break;
case SubmarineType.Outpost:
contentType = ContentType.Outpost;
break;
case SubmarineType.Wreck:
contentType = ContentType.Wreck;
break;
}
if (contentType != ContentType.Submarine)
{
#if DEBUG
var existingFiles = ContentPackage.GetFilesOfType(GameMain.VanillaContent.ToEnumerable(), contentType);
#else
var existingFiles = ContentPackage.GetFilesOfType(GameMain.Config.SelectedContentPackages.Where(c => c != GameMain.VanillaContent), contentType);
#endif
specialSavePath = existingFiles.FirstOrDefault(f =>
Path.GetFullPath(f.Path) != Path.GetFullPath(SubmarineInfo.SavePath) && ContentPackage.IsModFilePathAllowed(f.Path))?.Path;
if (!string.IsNullOrEmpty(specialSavePath))
{
specialSavePath = Path.GetDirectoryName(specialSavePath);
}
}
}
else if (Submarine.MainSub.Info.SubmarineClass == SubmarineClass.Undefined && !Submarine.MainSub.Info.HasTag(SubmarineTag.Shuttle))
{
var msgBox = new GUIMessageBox(TextManager.Get("warning"), TextManager.Get("undefinedsubmarineclasswarning"), new string[] { TextManager.Get("yes"), TextManager.Get("no") });
msgBox.Buttons[0].OnClicked = (bt, userdata) =>
{
SaveSubToFile(nameBox.Text);
saveFrame = null;
msgBox.Close();
return true;
};
msgBox.Buttons[1].OnClicked = (bt, userdata) =>
{
msgBox.Close();
return true;
};
return true;
}
if (!string.IsNullOrEmpty(specialSavePath) &&
(string.IsNullOrEmpty(Submarine.MainSub?.Info.FilePath) || Path.GetFileNameWithoutExtension(Submarine.MainSub.Info.Name) != nameBox.Text || Path.GetDirectoryName(Submarine.MainSub?.Info.FilePath) != specialSavePath))
{
var msgBox = new GUIMessageBox("", TextManager.GetWithVariables("savesubtospecialfolderprompt",
new string[] { "[type]", "[outpostpath]" }, new string[] { TextManager.Get("submarinetype." + Submarine.MainSub.Info.Type), specialSavePath }),
new string[] { TextManager.Get("yes"), TextManager.Get("no") });
msgBox.Buttons[0].OnClicked = (bt, userdata) =>
{
SaveSubToFile(nameBox.Text, specialSavePath);
saveFrame = null;
msgBox.Close();
return true;
};
msgBox.Buttons[1].OnClicked = (bt, userdata) =>
{
SaveSubToFile(nameBox.Text);
saveFrame = null;
msgBox.Close();
return true;
};
return true;
}
var result = SaveSubToFile(nameBox.Text, specialSavePath);
saveFrame = null;
return result;
}
private bool SaveSubToFile(string name)
private bool SaveSubToFile(string name, string specialSavePath = null)
{
if (string.IsNullOrWhiteSpace(name))
{
@@ -1236,7 +1326,37 @@ namespace Barotrauma
string savePath = name + ".sub";
string prevSavePath = null;
if (!string.IsNullOrEmpty(Submarine.MainSub?.Info.FilePath) &&
string directoryName = Submarine.MainSub?.Info?.FilePath == null ?
SubmarineInfo.SavePath : Path.GetDirectoryName(Submarine.MainSub.Info.FilePath);
if (!string.IsNullOrEmpty(specialSavePath))
{
directoryName = specialSavePath;
savePath = Path.Combine(directoryName, savePath);
ContentPackage contentPackage = GameMain.Config.SelectedContentPackages.Find(cp => cp.Files.Any(f => Path.GetDirectoryName(f.Path) == directoryName));
bool allowSavingToVanilla = false;
#if DEBUG
allowSavingToVanilla = true;
#endif
if (!contentPackage.Files.Any(f => Path.GetFullPath(f.Path) == Path.GetFullPath(savePath)) && (allowSavingToVanilla || contentPackage != GameMain.VanillaContent))
{
var msgBox = new GUIMessageBox("", TextManager.GetWithVariable("addtocontentpackageprompt", "[packagename]", contentPackage.Name),
new string[] { TextManager.Get("yes"), TextManager.Get("no") });
msgBox.Buttons[0].OnClicked = (bt, userdata) =>
{
contentPackage.AddFile(savePath, ContentType.OutpostModule);
contentPackage.Save(contentPackage.Path);
msgBox.Close();
return true;
};
msgBox.Buttons[1].OnClicked = (bt, userdata) =>
{
msgBox.Close();
return true;
};
}
}
else if (!string.IsNullOrEmpty(Submarine.MainSub?.Info.FilePath) &&
Submarine.MainSub.Info.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
{
prevSavePath = Submarine.MainSub.Info.FilePath.CleanUpPath();
@@ -1251,11 +1371,28 @@ namespace Barotrauma
if (contentPackage != null)
{
Steamworks.Data.PublishedFileId packageId = Steam.SteamManager.GetWorkshopItemIDFromUrl(contentPackage.SteamWorkshopUrl);
Steamworks.Ugc.Item? item = Steamworks.Ugc.Item.GetAsync(packageId).Result;
Task<Steamworks.Ugc.Item?> itemInfoTask = Steamworks.Ugc.Item.GetAsync(packageId);
Task<Steamworks.Ugc.Item?> itemUpdateTask = Task.Run(async () =>
{
while (!itemInfoTask.IsCompleted)
{
Steamworks.SteamClient.RunCallbacks();
await Task.Delay(16);
}
return itemInfoTask.Result;
});
Steamworks.Ugc.Item? item = itemUpdateTask.Result;
if (item?.Owner.Id == Steam.SteamManager.GetSteamID())
{
forceToSubFolder = false;
contentPackage.Files.Add(new ContentFile(Path.Combine(prevDir, savePath).CleanUpPath(), ContentType.Submarine));
string targetPath = Path.Combine(prevDir, savePath).CleanUpPath();
if (!contentPackage.Files.Any(f => f.Type == ContentType.Submarine &&
f.Path.CleanUpPath().Equals(targetPath, StringComparison.InvariantCultureIgnoreCase)))
{
contentPackage.Files.Add(new ContentFile(targetPath, ContentType.Submarine));
}
contentPackage.Save(contentPackage.Path);
}
}
@@ -1311,8 +1448,11 @@ namespace Barotrauma
if (prevSavePath != null && prevSavePath != savePath) { SubmarineInfo.RefreshSavedSub(prevSavePath); }
linkedSubBox.ClearChildren();
foreach (SubmarineInfo sub in SubmarineInfo.SavedSubmarines) { linkedSubBox.AddItem(sub.Name, sub); }
foreach (SubmarineInfo sub in SubmarineInfo.SavedSubmarines)
{
if (sub.Type != SubmarineType.Player) { continue; }
linkedSubBox.AddItem(sub.Name, sub);
}
subNameLabel.Text = ToolBox.LimitString(Submarine.MainSub.Info.Name, subNameLabel.Font, subNameLabel.Rect.Width);
}
@@ -1335,8 +1475,8 @@ namespace Barotrauma
};
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, saveFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.4f, 0.5f), saveFrame.RectTransform, Anchor.Center) { MinSize = new Point(750, 400) });
var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.55f, 0.6f), saveFrame.RectTransform, Anchor.Center) { MinSize = new Point(750, 500) });
var paddedSaveFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), innerFrame.RectTransform, Anchor.Center)) { Stretch = true, RelativeSpacing = 0.02f };
//var header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedSaveFrame.RectTransform), TextManager.Get("SaveSubDialogHeader"), font: GUI.LargeFont);
@@ -1374,13 +1514,13 @@ namespace Barotrauma
submarineNameCharacterCount.Text = nameBox.Text.Length + " / " + submarineNameLimit;
var descriptionHeaderGroup = new GUILayoutGroup(new RectTransform(new Vector2(.975f, 0.03f), leftColumn.RectTransform), true);
var descriptionHeaderGroup = new GUILayoutGroup(new RectTransform(new Vector2(.975f, 0.03f), leftColumn.RectTransform), isHorizontal: true);
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), descriptionHeaderGroup.RectTransform), TextManager.Get("SaveSubDialogDescription"), font: GUI.SubHeadingFont);
submarineDescriptionCharacterCount = new GUITextBlock(new RectTransform(new Vector2(.5f, 1f), descriptionHeaderGroup.RectTransform), string.Empty, textAlignment: Alignment.TopRight);
var descriptionContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.25f), leftColumn.RectTransform));
descriptionBox = new GUITextBox(new RectTransform(Vector2.One, descriptionContainer.Content.RectTransform, Anchor.Center),
descriptionBox = new GUITextBox(new RectTransform(Vector2.One, descriptionContainer.Content.RectTransform, Anchor.Center),
font: GUI.SmallFont, style: "GUITextBoxNoBorder", wrap: true, textAlignment: Alignment.TopLeft)
{
Padding = new Vector4(10 * GUI.Scale)
@@ -1405,7 +1545,292 @@ namespace Barotrauma
descriptionBox.Text = GetSubDescription();
var crewSizeArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.04f), leftColumn.RectTransform), isHorizontal: true)
var subTypeContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.01f), leftColumn.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft)
{
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(0.4f, 1f), subTypeContainer.RectTransform), TextManager.Get("submarinetype"));
var subTypeDropdown = new GUIDropDown(new RectTransform(new Vector2(0.6f, 1f), subTypeContainer.RectTransform));
subTypeContainer.RectTransform.MinSize = new Point(0, subTypeContainer.RectTransform.Children.Max(c => c.MinSize.Y));
subTypeDropdown.AddItem(TextManager.Get("submarinetype.player"), SubmarineType.Player);
subTypeDropdown.AddItem(TextManager.Get("submarinetype.outpostmodule"), SubmarineType.OutpostModule);
subTypeDropdown.AddItem(TextManager.Get("submarinetype.outpost"), SubmarineType.Outpost);
subTypeDropdown.AddItem(TextManager.Get("submarinetype.wreck"), SubmarineType.Wreck);
//---------------------------------------
var outpostSettingsContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), leftColumn.RectTransform))
{
IgnoreLayoutGroups = true,
CanBeFocused = true,
Visible = false,
Stretch = true
};
new GUIFrame(new RectTransform(Vector2.One, outpostSettingsContainer.RectTransform), "InnerFrame")
{
IgnoreLayoutGroups = true
};
// module flags ---------------------
var outpostModuleGroup = new GUILayoutGroup(new RectTransform(new Vector2(.975f, 0.1f), outpostSettingsContainer.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), outpostModuleGroup.RectTransform), TextManager.Get("outpostmoduletype"), textAlignment: Alignment.CenterLeft);
HashSet<string> availableFlags = new HashSet<string>();
foreach (string flag in OutpostGenerationParams.Params.SelectMany(p => p.ModuleCounts.Select(m => m.Key))) { availableFlags.Add(flag); }
foreach (var sub in SubmarineInfo.SavedSubmarines)
{
if (sub.OutpostModuleInfo == null) { continue; }
foreach (string flag in sub.OutpostModuleInfo.ModuleFlags)
{
if (flag == "none") { continue; }
availableFlags.Add(flag);
}
}
var moduleTypeDropDown = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1f), outpostModuleGroup.RectTransform),
text: string.Join(", ", Submarine.MainSub?.Info?.OutpostModuleInfo?.ModuleFlags.Select(s => TextManager.Capitalize(s)) ?? "None".ToEnumerable()), selectMultiple: true);
foreach (string flag in availableFlags)
{
moduleTypeDropDown.AddItem(TextManager.Capitalize(flag), flag);
if (Submarine.MainSub?.Info?.OutpostModuleInfo == null) { continue; }
if (Submarine.MainSub.Info.OutpostModuleInfo.ModuleFlags.Contains(flag))
{
moduleTypeDropDown.SelectItem(flag);
}
}
moduleTypeDropDown.OnSelected += (_, __) =>
{
if (Submarine.MainSub?.Info?.OutpostModuleInfo == null) { return false; }
Submarine.MainSub.Info.OutpostModuleInfo.SetFlags(moduleTypeDropDown.SelectedDataMultiple.Cast<string>());
moduleTypeDropDown.Text = ToolBox.LimitString(
Submarine.MainSub.Info.OutpostModuleInfo.ModuleFlags.Any(f => f != "none") ? moduleTypeDropDown.Text : "None",
moduleTypeDropDown.Font, moduleTypeDropDown.Rect.Width);
return true;
};
outpostModuleGroup.RectTransform.MinSize = new Point(0, outpostModuleGroup.RectTransform.Children.Max(c => c.MinSize.Y));
// module flags ---------------------
var allowAttachGroup = new GUILayoutGroup(new RectTransform(new Vector2(.975f, 0.1f), outpostSettingsContainer.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), allowAttachGroup.RectTransform), TextManager.Get("outpostmoduleallowattachto"), textAlignment: Alignment.CenterLeft);
var allowAttachDropDown = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1f), allowAttachGroup.RectTransform),
text: string.Join(", ", Submarine.MainSub?.Info?.OutpostModuleInfo?.AllowAttachToModules.Select(s => TextManager.Capitalize(s)) ?? "Any".ToEnumerable()), selectMultiple: true);
allowAttachDropDown.AddItem(TextManager.Capitalize("any"), "any");
if (Submarine.MainSub.Info.OutpostModuleInfo == null ||
!Submarine.MainSub.Info.OutpostModuleInfo.AllowAttachToModules.Any() ||
Submarine.MainSub.Info.OutpostModuleInfo.AllowAttachToModules.All(s => s.Equals("any", StringComparison.OrdinalIgnoreCase)))
{
allowAttachDropDown.SelectItem("any");
}
foreach (string flag in availableFlags)
{
if (flag.Equals("any", StringComparison.OrdinalIgnoreCase) || flag.Equals("none", StringComparison.OrdinalIgnoreCase)) { continue; }
allowAttachDropDown.AddItem(TextManager.Capitalize(flag), flag);
if (Submarine.MainSub?.Info?.OutpostModuleInfo == null) { continue; }
if (Submarine.MainSub.Info.OutpostModuleInfo.AllowAttachToModules.Contains(flag))
{
allowAttachDropDown.SelectItem(flag);
}
}
allowAttachDropDown.OnSelected += (_, __) =>
{
if (Submarine.MainSub?.Info?.OutpostModuleInfo == null) { return false; }
Submarine.MainSub.Info.OutpostModuleInfo.SetAllowAttachTo(allowAttachDropDown.SelectedDataMultiple.Cast<string>());
allowAttachDropDown.Text = ToolBox.LimitString(
Submarine.MainSub.Info.OutpostModuleInfo.ModuleFlags.Any(f => f != "none") ? allowAttachDropDown.Text : "None",
allowAttachDropDown.Font, allowAttachDropDown.Rect.Width);
return true;
};
allowAttachGroup.RectTransform.MinSize = new Point(0, allowAttachGroup.RectTransform.Children.Max(c => c.MinSize.Y));
// location types ---------------------
var locationTypeGroup = new GUILayoutGroup(new RectTransform(new Vector2(.975f, 0.1f), outpostSettingsContainer.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), locationTypeGroup.RectTransform), TextManager.Get("outpostmoduleallowedlocationtypes"), textAlignment: Alignment.CenterLeft);
HashSet<string> availableLocationTypes = new HashSet<string> { "any" };
foreach (LocationType locationType in LocationType.List) { availableLocationTypes.Add(locationType.Identifier); }
var locationTypeDropDown = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1f), locationTypeGroup.RectTransform),
text: string.Join(", ", Submarine.MainSub?.Info?.OutpostModuleInfo?.AllowedLocationTypes.Select(lt => TextManager.Capitalize(lt)) ?? "any".ToEnumerable()), selectMultiple: true);
foreach (string locationType in availableLocationTypes)
{
locationTypeDropDown.AddItem(TextManager.Capitalize(locationType), locationType);
if (Submarine.MainSub?.Info?.OutpostModuleInfo == null) { continue; }
if (Submarine.MainSub.Info.OutpostModuleInfo.AllowedLocationTypes.Contains(locationType))
{
locationTypeDropDown.SelectItem(locationType);
}
}
if (!Submarine.MainSub.Info?.OutpostModuleInfo?.AllowedLocationTypes?.Any() ?? true) { locationTypeDropDown.SelectItem("any"); }
locationTypeDropDown.OnSelected += (_, __) =>
{
Submarine.MainSub?.Info?.OutpostModuleInfo?.SetAllowedLocationTypes(locationTypeDropDown.SelectedDataMultiple.Cast<string>());
locationTypeDropDown.Text = ToolBox.LimitString(locationTypeDropDown.Text, locationTypeDropDown.Font, locationTypeDropDown.Rect.Width);
return true;
};
locationTypeGroup.RectTransform.MinSize = new Point(0, locationTypeGroup.RectTransform.Children.Max(c => c.MinSize.Y));
// gap positions ---------------------
var gapPositionGroup = new GUILayoutGroup(new RectTransform(new Vector2(.975f, 0.1f), outpostSettingsContainer.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), gapPositionGroup.RectTransform), TextManager.Get("outpostmodulegappositions"), textAlignment: Alignment.CenterLeft);
var gapPositionDropDown = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1f), gapPositionGroup.RectTransform),
text: "", selectMultiple: true);
Submarine.MainSub.Info?.OutpostModuleInfo?.DetermineGapPositions(Submarine.MainSub);
foreach (var gapPos in Enum.GetValues(typeof(OutpostModuleInfo.GapPosition)))
{
if ((OutpostModuleInfo.GapPosition)gapPos == OutpostModuleInfo.GapPosition.None) { continue; }
gapPositionDropDown.AddItem(TextManager.Capitalize(gapPos.ToString()), gapPos);
if (Submarine.MainSub.Info?.OutpostModuleInfo?.GapPositions.HasFlag((OutpostModuleInfo.GapPosition)gapPos) ?? false)
{
gapPositionDropDown.SelectItem(gapPos);
}
}
gapPositionDropDown.OnSelected += (_, __) =>
{
if (Submarine.MainSub.Info?.OutpostModuleInfo == null) { return false; }
Submarine.MainSub.Info.OutpostModuleInfo.GapPositions = OutpostModuleInfo.GapPosition.None;
if (gapPositionDropDown.SelectedDataMultiple.Any())
{
List<string> gapPosTexts = new List<string>();
foreach (OutpostModuleInfo.GapPosition gapPos in gapPositionDropDown.SelectedDataMultiple)
{
Submarine.MainSub.Info.OutpostModuleInfo.GapPositions |= gapPos;
gapPosTexts.Add(TextManager.Capitalize(gapPos.ToString()));
}
gapPositionDropDown.Text = ToolBox.LimitString(string.Join(", ", gapPosTexts), gapPositionDropDown.Font, gapPositionDropDown.Rect.Width);
}
else
{
gapPositionDropDown.Text = ToolBox.LimitString("None", gapPositionDropDown.Font, gapPositionDropDown.Rect.Width);
}
return true;
};
gapPositionGroup.RectTransform.MinSize = new Point(0, gapPositionGroup.RectTransform.Children.Max(c => c.MinSize.Y));
// -------------------
var maxModuleCountGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), outpostSettingsContainer.RectTransform), isHorizontal: true)
{
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), maxModuleCountGroup.RectTransform),
TextManager.Get("OutPostModuleMaxCount"), textAlignment: Alignment.CenterLeft, wrap: true)
{
ToolTip = TextManager.Get("OutPostModuleMaxCountToolTip")
};
new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), maxModuleCountGroup.RectTransform), GUINumberInput.NumberType.Int)
{
ToolTip = TextManager.Get("OutPostModuleMaxCountToolTip"),
IntValue = Submarine.MainSub?.Info?.OutpostModuleInfo?.MaxCount ?? 1000,
MinValueInt = 0,
MaxValueInt = 1000,
OnValueChanged = (numberInput) =>
{
Submarine.MainSub.Info.OutpostModuleInfo.MaxCount = numberInput.IntValue;
}
};
var commonnessGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), outpostSettingsContainer.RectTransform), isHorizontal: true)
{
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), commonnessGroup.RectTransform),
TextManager.Get("subeditor.outpostcommonness"), textAlignment: Alignment.CenterLeft, wrap: true);
new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), commonnessGroup.RectTransform), GUINumberInput.NumberType.Int)
{
FloatValue = Submarine.MainSub?.Info?.OutpostModuleInfo?.Commonness ?? 10,
MinValueFloat = 0,
MaxValueFloat = 100,
OnValueChanged = (numberInput) =>
{
Submarine.MainSub.Info.OutpostModuleInfo.Commonness = numberInput.FloatValue;
}
};
outpostSettingsContainer.RectTransform.MinSize = new Point(0, outpostSettingsContainer.RectTransform.Children.Sum(c => c.Children.Any() ? c.Children.Max(c2 => c2.MinSize.Y) : 0));
//------------------------------------------------------------------
var subSettingsContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), leftColumn.RectTransform))
{
Stretch = true
};
new GUIFrame(new RectTransform(Vector2.One, subSettingsContainer.RectTransform), "InnerFrame")
{
IgnoreLayoutGroups = true
};
var priceGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), subSettingsContainer.RectTransform), isHorizontal: true)
{
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), priceGroup.RectTransform),
TextManager.Get("subeditor.price"), textAlignment: Alignment.CenterLeft, wrap: true);
int basePrice = GameMain.DebugDraw ? 0 : Submarine.MainSub?.CalculateBasePrice() ?? 1000;
new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), priceGroup.RectTransform), GUINumberInput.NumberType.Int, hidePlusMinusButtons: true)
{
IntValue = Math.Max(Submarine.MainSub?.Info?.Price ?? basePrice, basePrice),
MinValueInt = basePrice,
MaxValueInt = 999999,
OnValueChanged = (numberInput) =>
{
Submarine.MainSub.Info.Price = numberInput.IntValue;
}
};
if (!Submarine.MainSub.Info.HasTag(SubmarineTag.Shuttle))
{
var classGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), subSettingsContainer.RectTransform), isHorizontal: true)
{
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), classGroup.RectTransform),
TextManager.Get("submarineclass"), textAlignment: Alignment.CenterLeft, wrap: true);
GUIDropDown classDropDown = new GUIDropDown(new RectTransform(new Vector2(0.4f, 1.0f), classGroup.RectTransform));
classDropDown.RectTransform.MinSize = new Point(0, subTypeContainer.RectTransform.Children.Max(c => c.MinSize.Y));
classDropDown.AddItem(TextManager.Get("submarineclass.undefined"), SubmarineClass.Undefined);
classDropDown.AddItem(TextManager.Get("submarineclass.scout"), SubmarineClass.Scout);
classDropDown.AddItem(TextManager.Get("submarineclass.attack"), SubmarineClass.Attack);
classDropDown.AddItem(TextManager.Get("submarineclass.transport"), SubmarineClass.Transport);
classDropDown.AddItem(TextManager.Get("submarineclass.deepdiver"), SubmarineClass.DeepDiver);
classDropDown.OnSelected += (selected, userdata) =>
{
SubmarineClass submarineClass = (SubmarineClass)userdata;
Submarine.MainSub.Info.SubmarineClass = submarineClass;
return true;
};
classDropDown.SelectItem(Submarine.MainSub.Info.SubmarineClass);
}
var crewSizeArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), subSettingsContainer.RectTransform), isHorizontal: true)
{
Stretch = true,
AbsoluteSpacing = 5
@@ -1413,13 +1838,13 @@ namespace Barotrauma
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), crewSizeArea.RectTransform),
TextManager.Get("RecommendedCrewSize"), textAlignment: Alignment.CenterLeft, wrap: true, font: GUI.SmallFont);
var crewSizeMin = new GUINumberInput(new RectTransform(new Vector2(0.1f, 1.0f), crewSizeArea.RectTransform), GUINumberInput.NumberType.Int)
var crewSizeMin = new GUINumberInput(new RectTransform(new Vector2(0.17f, 1.0f), crewSizeArea.RectTransform), GUINumberInput.NumberType.Int, relativeButtonAreaWidth: 0.25f)
{
MinValueInt = 1,
MaxValueInt = 128
};
new GUITextBlock(new RectTransform(new Vector2(0.1f, 1.0f), crewSizeArea.RectTransform), "-", textAlignment: Alignment.Center);
var crewSizeMax = new GUINumberInput(new RectTransform(new Vector2(0.1f, 1.0f), crewSizeArea.RectTransform), GUINumberInput.NumberType.Int)
new GUITextBlock(new RectTransform(new Vector2(0.06f, 1.0f), crewSizeArea.RectTransform), "-", textAlignment: Alignment.Center);
var crewSizeMax = new GUINumberInput(new RectTransform(new Vector2(0.17f, 1.0f), crewSizeArea.RectTransform), GUINumberInput.NumberType.Int, relativeButtonAreaWidth: 0.25f)
{
MinValueInt = 1,
MaxValueInt = 128
@@ -1439,7 +1864,7 @@ namespace Barotrauma
Submarine.MainSub.Info.RecommendedCrewSizeMax = crewSizeMax.IntValue;
};
var crewExpArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.04f), leftColumn.RectTransform), isHorizontal: true)
var crewExpArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), subSettingsContainer.RectTransform), isHorizontal: true)
{
Stretch = true,
AbsoluteSpacing = 5
@@ -1484,9 +1909,27 @@ namespace Barotrauma
crewExperienceLevels[0] : Submarine.MainSub.Info.RecommendedCrewExperience;
experienceText.Text = TextManager.Get((string)experienceText.UserData);
}
subTypeDropdown.OnSelected += (selected, userdata) =>
{
SubmarineType type = (SubmarineType)userdata;
Submarine.MainSub.Info.Type = type;
if (type == SubmarineType.OutpostModule)
{
Submarine.MainSub.Info.OutpostModuleInfo ??= new OutpostModuleInfo(Submarine.MainSub.Info);
}
outpostSettingsContainer.Visible = type == SubmarineType.OutpostModule;
outpostSettingsContainer.IgnoreLayoutGroups = !outpostSettingsContainer.Visible;
subSettingsContainer.Visible = type == SubmarineType.Player;
subSettingsContainer.IgnoreLayoutGroups = !subSettingsContainer.Visible;
return true;
};
subTypeDropdown.SelectItem(Submarine.MainSub.Info.Type);
subSettingsContainer.RectTransform.MinSize = new Point(0, subSettingsContainer.RectTransform.Children.Sum(c => c.Children.Any() ? c.Children.Max(c2 => c2.MinSize.Y) : 0));
// right column ---------------------------------------------------
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), rightColumn.RectTransform), TextManager.Get("SubPreviewImage"), font: GUI.SubHeadingFont);
var previewImageHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.5f), rightColumn.RectTransform), style: null) { Color = Color.Black, CanBeFocused = false };
@@ -1633,6 +2076,12 @@ namespace Barotrauma
};
paddedSaveFrame.Recalculate();
leftColumn.Recalculate();
subSettingsContainer.RectTransform.MinSize = outpostSettingsContainer.RectTransform.MinSize =
new Point(0, Math.Max(subSettingsContainer.Rect.Height, outpostSettingsContainer.Rect.Height));
subSettingsContainer.Recalculate();
outpostSettingsContainer.Recalculate();
descriptionBox.Text = Submarine.MainSub == null ? "" : Submarine.MainSub.Info.Description;
submarineDescriptionCharacterCount.Text = descriptionBox.Text.Length + " / " + submarineDescriptionLimit;
@@ -1843,8 +2292,23 @@ namespace Barotrauma
searchBox.OnDeselected += (sender, userdata) => { searchTitle.Visible = true; };
searchBox.OnTextChanged += (textBox, text) => { FilterSubs(subList, text); return true; };
foreach (SubmarineInfo sub in SubmarineInfo.SavedSubmarines)
List<SubmarineInfo> sortedSubs = new List<SubmarineInfo>(SubmarineInfo.SavedSubmarines);
sortedSubs.Sort((s1, s2) => { return s1.Type.CompareTo(s2.Type) * 100 + s1.Name.CompareTo(s2.Name); });
SubmarineInfo prevSub = null;
foreach (SubmarineInfo sub in sortedSubs)
{
if (prevSub == null || prevSub.Type != sub.Type)
{
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), subList.Content.RectTransform) { MinSize = new Point(0, 35) },
TextManager.Get("SubmarineType." + sub.Type), font: GUI.LargeFont, textAlignment: Alignment.Center, style: "ListBoxElement")
{
CanBeFocused = false
};
prevSub = sub;
}
GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), subList.Content.RectTransform) { MinSize = new Point(0, 30) },
ToolBox.LimitString(sub.Name, GUI.Font, subList.Rect.Width - 80))
{
@@ -1861,6 +2325,15 @@ namespace Barotrauma
ToolTip = textBlock.RawToolTip
};
}
else if (sub.IsPlayer)
{
var classText = new GUITextBlock(new RectTransform(new Vector2(0.2f, 1.0f), textBlock.RectTransform, Anchor.CenterRight),
TextManager.Get($"submarineclass.{sub.SubmarineClass}"), textAlignment: Alignment.CenterRight, font: GUI.SmallFont)
{
TextColor = textBlock.TextColor * 0.8f,
ToolTip = textBlock.RawToolTip
};
}
}
var deleteButton = new GUIButton(new RectTransform(Vector2.One, deleteButtonHolder.RectTransform, Anchor.TopCenter),
@@ -1914,7 +2387,7 @@ namespace Barotrauma
{
foreach (GUIComponent child in subList.Content.Children)
{
if (!(child.UserData is SubmarineInfo sub)) { return; }
if (!(child.UserData is SubmarineInfo sub)) { continue; }
child.Visible = string.IsNullOrEmpty(filter) || sub.Name.ToLower().Contains(filter.ToLower());
}
}
@@ -2474,6 +2947,8 @@ namespace Barotrauma
private void CloseItem()
{
if (dummyCharacter == null) { return; }
//nothing to close -> return
if (DraggedItemPrefab == null && dummyCharacter?.SelectedConstruction == null && OpenedItem == null) { return; }
DraggedItemPrefab = null;
dummyCharacter.SelectedConstruction = null;
OpenedItem?.Drop(dummyCharacter);
@@ -3694,6 +4169,10 @@ namespace Barotrauma
private void CreateImage(int width, int height, System.IO.Stream stream)
{
MapEntity.SelectedList.Clear();
foreach (MapEntity me in MapEntity.mapEntityList)
{
me.IsHighlighted = false;
}
var prevScissorRect = GameMain.Instance.GraphicsDevice.ScissorRectangle;
@@ -3707,24 +4186,14 @@ namespace Barotrauma
Matrix.CreateScale(new Vector3(scale, scale, 1)) *
viewMatrix;
/*Sprite backgroundSprite = LevelGenerationParams.LevelParams.Find(l => l.BackgroundTopSprite != null).BackgroundTopSprite;*/
using (RenderTarget2D rt = new RenderTarget2D(
GameMain.Instance.GraphicsDevice,
width, height, false, SurfaceFormat.Color, DepthFormat.None))
using (SpriteBatch spriteBatch = new SpriteBatch(GameMain.Instance.GraphicsDevice))
{
GameMain.Instance.GraphicsDevice.SetRenderTarget(rt);
GameMain.Instance.GraphicsDevice.Clear(new Color(8, 13, 19));
/*if (backgroundSprite != null)
{
spriteBatch.Begin();
backgroundSprite.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(width, height), color: new Color(0.025f, 0.075f, 0.131f, 1.0f));
spriteBatch.End();
}*/
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, null, null, null, null, transform);
Submarine.Draw(spriteBatch);
Submarine.DrawFront(spriteBatch);