Release 1.10.5.0 - Autumn Update 2025

This commit is contained in:
Regalis11
2025-09-17 13:44:21 +03:00
parent d13836ce87
commit caa0326cf8
120 changed files with 2584 additions and 635 deletions
@@ -233,7 +233,7 @@ namespace Barotrauma
protected virtual Color BackgroundColor => new Color(150, 150, 150);
private void DrawBack(SpriteBatch spriteBatch)
protected virtual void DrawBack(SpriteBatch spriteBatch)
{
Color outlineColor = Color.White * 0.8f;
Color fontColor = Color.White;
@@ -253,9 +253,19 @@ namespace Barotrauma
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));
DrawConnections(spriteBatch);
Vector2 headerSize = GUIStyle.SubHeadingFont.MeasureString(Name);
GUIStyle.SubHeadingFont.DrawString(spriteBatch, Name, HeaderRectangle.Location.ToVector2() + (HeaderRectangle.Size.ToVector2() / 2) - (headerSize / 2), fontColor);
}
protected virtual void DrawConnections(SpriteBatch spriteBatch)
{
int x = 0, y = 0;
foreach (EventEditorNodeConnection connection in Connections)
{
if (!ShouldDrawConnection(connection)) { continue; }
switch (connection.Type.NodeSide)
{
case NodeConnectionType.Side.Left:
@@ -268,9 +278,11 @@ namespace Barotrauma
break;
}
}
}
Vector2 headerSize = GUIStyle.SubHeadingFont.MeasureString(Name);
GUIStyle.SubHeadingFont.DrawString(spriteBatch, Name, HeaderRectangle.Location.ToVector2() + (HeaderRectangle.Size.ToVector2() / 2) - (headerSize / 2), fontColor);
protected virtual bool ShouldDrawConnection(EventEditorNodeConnection connection)
{
return true; // Base implementation draws all connections
}
public void AddConnection(NodeConnectionType connectionType)
@@ -337,6 +349,11 @@ namespace Barotrauma
{
private readonly Type type;
protected override Color BackgroundColor =>
EventEditorScreen.ConversationMode && !IsInstanceOf(type, typeof(ConversationAction))
? new Color(80, 80, 80) // Darker for non-conversation nodes in conversation mode
: new Color(150, 150, 150); // Normal color
public EventNode(Type type, string name) : base(name)
{
this.type = type;
@@ -387,8 +404,15 @@ namespace Barotrauma
Type? t = Type.GetType(element.GetAttributeString("type", string.Empty));
if (t == null) { return null; }
string name = element.GetAttributeString("name", string.Empty);
int id = element.GetAttributeInt("i", -1);
EventNode newNode = new EventNode(t, element.GetAttributeString("name", string.Empty)) { ID = element.GetAttributeInt("i", -1) };
// Create the appropriate node type based on whether it's a conversation action
EditorNode newNode = IsInstanceOf(t, typeof(ConversationAction))
? new EventConversationNode(t, name) { ID = id }
: new EventNode(t, name) { ID = id };
float posX = element.GetAttributeFloat("xpos", 0f);
float posY = element.GetAttributeFloat("ypos", 0f);
newNode.Position = new Vector2(posX, posY);
@@ -0,0 +1,398 @@
#nullable enable
using System;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;
namespace Barotrauma
{
/// <summary>
/// Base class for event nodes that display text content and can have inner Text nodes
/// </summary>
internal abstract class EventTextDisplayNode(Type type, string name) : EventNode(type, name)
{
protected virtual bool ShowOptions => false;
private new Rectangle HeaderRectangle
{
get
{
if (!EventEditorScreen.ConversationMode) { return base.HeaderRectangle; }
Rectangle drawRect = GetDrawRectangle();
return new Rectangle(Position.ToPoint(), new Point(drawRect.Width, 32));
}
}
public override Rectangle GetDrawRectangle()
{
if (!EventEditorScreen.ConversationMode) { return base.GetDrawRectangle(); }
var textConnection = Connections.Find(c => string.Equals(c.Attribute, "Text", StringComparison.OrdinalIgnoreCase));
var optionConnections = ShowOptions ? Connections.Where(c => c.Type == NodeConnectionType.Option) : Enumerable.Empty<EventEditorNodeConnection>();
const int width = 300;
int height = 50;
// Calculate height for text section
if (textConnection != null)
{
string textContent = GetTextContent(textConnection);
if (!string.IsNullOrEmpty(textContent) && GUIStyle.Font.Value != null)
{
string wrappedText = ToolBox.WrapText(textContent, width - 16, GUIStyle.Font.Value);
Vector2 textSize = GUIStyle.Font.MeasureString(wrappedText);
height += (int)textSize.Y + 10;
}
else
{
height += 25;
}
}
// Calculate height for each option (only for conversation nodes)
if (ShowOptions)
{
int optionIndex = 0;
foreach (var option in optionConnections)
{
string optionText = GetOptionText(option, optionIndex);
if (GUIStyle.Font.Value != null)
{
string wrappedOption = ToolBox.WrapText(optionText, width - 40, GUIStyle.Font.Value);
Vector2 optionSize = GUIStyle.Font.MeasureString(wrappedOption);
height += (int)optionSize.Y + 20;
}
else
{
height += 40;
}
optionIndex++;
}
}
Rectangle rect = Rectangle;
return new Rectangle(rect.X, rect.Y, width, height);
}
protected override void DrawBack(SpriteBatch spriteBatch)
{
if (!EventEditorScreen.ConversationMode)
{
base.DrawBack(spriteBatch);
return;
}
Rectangle bodyRect = GetDrawRectangle();
// Background colors
Color headerColor = IsSelected ? new Color(100, 150, 200) : new Color(120, 170, 220);
Color bodyColor = new Color(90, 120, 150);
Color borderColor = Color.LightBlue;
// Draw background
GUI.DrawRectangle(spriteBatch, HeaderRectangle, headerColor, isFilled: true, depth: 1.0f);
GUI.DrawRectangle(spriteBatch, bodyRect, bodyColor, isFilled: true, depth: 1.0f);
GUI.DrawRectangle(spriteBatch, HeaderRectangle, borderColor, isFilled: false, depth: 1.0f);
GUI.DrawRectangle(spriteBatch, bodyRect, borderColor, isFilled: false, depth: 1.0f);
// Draw header text
Vector2 headerSize = GUIStyle.SubHeadingFont.MeasureString(Name);
Vector2 headerPos = HeaderRectangle.Location.ToVector2() + (HeaderRectangle.Size.ToVector2() / 2) - (headerSize / 2);
GUIStyle.SubHeadingFont.DrawString(spriteBatch, Name, headerPos, Color.White);
// Draw text content
DrawTextContent(spriteBatch, bodyRect);
// Let base class handle standard connections (Activate, Next, etc.)
DrawConnections(spriteBatch);
}
protected virtual void DrawTextContent(SpriteBatch spriteBatch, Rectangle bodyRect)
{
var textConnection = Connections.Find(c => string.Equals(c.Attribute, "Text", StringComparison.OrdinalIgnoreCase));
var optionConnections = ShowOptions ? Connections.Where(c => c.Type == NodeConnectionType.Option) : Enumerable.Empty<EventEditorNodeConnection>();
Vector2 mousePos = Screen.Selected.Cam.ScreenToWorld(PlayerInput.MousePosition);
mousePos.Y = -mousePos.Y;
const int padding = 8;
int currentY = bodyRect.Y + padding + 30;
// Draw text section
if (textConnection != null)
{
string textContent = GetTextContent(textConnection);
// Wrap text and calculate height
string wrappedText = textContent;
int textHeight = 25;
if (GUIStyle.Font.Value != null)
{
wrappedText = ToolBox.WrapText(textContent, bodyRect.Width - 24, GUIStyle.Font.Value);
Vector2 textSize = GUIStyle.Font.MeasureString(wrappedText);
textHeight = (int)textSize.Y + 10;
}
Rectangle textRect = new Rectangle(bodyRect.X + padding, currentY, bodyRect.Width - padding * 2, textHeight);
// background
GUI.DrawRectangle(spriteBatch, textRect, new Color(70, 100, 130), isFilled: true);
GUI.DrawRectangle(spriteBatch, textRect, Color.CornflowerBlue, isFilled: false);
// wrapped text
Vector2 textPos = new Vector2(textRect.X + 4, textRect.Y + 4);
GUI.DrawString(spriteBatch, textPos, wrappedText, Color.Yellow, font: GUIStyle.Font);
// tooltip
if (textRect.Contains(mousePos))
{
string rawTextKey = GetRawTextKey(textConnection);
if (!string.IsNullOrEmpty(rawTextKey))
{
EventEditorScreen.DrawnTooltip = rawTextKey;
}
}
currentY += textHeight + 5;
}
// Draw options (only for conversation nodes)
if (ShowOptions)
{
DrawOptions(spriteBatch, bodyRect, optionConnections, currentY);
}
}
protected static void DrawOptions(SpriteBatch spriteBatch, Rectangle bodyRect, IEnumerable<EventEditorNodeConnection> optionConnections, int startY)
{
Vector2 mousePos = Screen.Selected.Cam.ScreenToWorld(PlayerInput.MousePosition);
mousePos.Y = -mousePos.Y;
const int padding = 8;
int currentY = startY;
int optionIndex = 0;
foreach (var option in optionConnections)
{
string optionText = GetOptionText(option, optionIndex);
// Wrap option text and calculate height
string wrappedOption = optionText;
int optionHeight = 30;
if (GUIStyle.Font.Value != null)
{
wrappedOption = ToolBox.WrapText(optionText, bodyRect.Width - 40, GUIStyle.Font.Value);
Vector2 optionSize = GUIStyle.Font.MeasureString(wrappedOption);
optionHeight = (int)optionSize.Y + 16;
}
Rectangle optionRect = new Rectangle(bodyRect.X + padding, currentY, bodyRect.Width - padding * 2, optionHeight);
// background - red for end conversation, blue for normal
Color optionBg = option.EndConversation ? new Color(120, 80, 80) : new Color(80, 80, 120);
GUI.DrawRectangle(spriteBatch, optionRect, optionBg, isFilled: true);
GUI.DrawRectangle(spriteBatch, optionRect, Color.White, isFilled: false);
Vector2 optionPos = new Vector2(optionRect.X + 4, optionRect.Y + 4);
GUI.DrawString(spriteBatch, optionPos, wrappedOption, Color.White, font: GUIStyle.Font);
// tooltip
if (optionRect.Contains(mousePos))
{
string rawOptionKey = option.OptionText ?? "";
if (!string.IsNullOrEmpty(rawOptionKey))
{
EventEditorScreen.DrawnTooltip = rawOptionKey;
}
}
// connection point
Rectangle connRect = new Rectangle(bodyRect.Right - 1, optionRect.Y + optionHeight / 2 - 8, 16, 16);
GUI.DrawRectangle(spriteBatch, connRect, Color.DarkGray, isFilled: true);
GUI.DrawRectangle(spriteBatch, connRect, Color.White, isFilled: false);
option.DrawRectangle = connRect;
// connection lines
foreach (var connected in option.ConnectedTo)
{
Vector2 start = new Vector2(connRect.Right, connRect.Center.Y);
Vector2 end = new Vector2(connected.DrawRectangle.Left, connected.DrawRectangle.Center.Y);
float knobLength = 24;
var (points, _) = ToolBox.GetSquareLineBetweenPoints(start, end, knobLength);
Color lineColor = GUIStyle.Red;
float lineWidth = Math.Max(2.0f, 2.0f / (Screen.Selected is EventEditorScreen eventEditor ? eventEditor.Cam.Zoom : 1.0f));
GUI.DrawLine(spriteBatch, points[0], points[1], lineColor, width: (int)lineWidth);
GUI.DrawLine(spriteBatch, points[1], points[2], lineColor, width: (int)lineWidth);
GUI.DrawLine(spriteBatch, points[2], points[3], lineColor, width: (int)lineWidth);
GUI.DrawLine(spriteBatch, points[3], points[4], lineColor, width: (int)lineWidth);
GUI.DrawLine(spriteBatch, points[4], points[5], lineColor, width: (int)lineWidth);
}
currentY += optionHeight + 5;
optionIndex++;
}
}
private static string GetOptionText(EventEditorNodeConnection option, int optionIndex)
{
string optionTextKey = option.OptionText ?? $"Option {optionIndex + 1}";
var allVariants = TextManager.GetAll(optionTextKey);
int variantCount = allVariants.Count();
return variantCount switch
{
> 1 => $"[{variantCount} variants] {string.Join(" / ", allVariants)}",
1 => allVariants.First(),
_ => optionTextKey
};
}
private string GetTextContent(EventEditorNodeConnection textConnection)
{
string textContent = "";
// First check if there's a direct text attribute
if (textConnection.OverrideValue != null)
{
textContent = textConnection.OverrideValue.ToString() ?? "";
}
else
{
object? connectedValue = textConnection.GetValue();
if (connectedValue != null)
{
textContent = connectedValue.ToString() ?? "";
}
}
// If no direct text, check for inner Text nodes via Add connections
if (string.IsNullOrEmpty(textContent))
{
var addConnection = Connections.FirstOrDefault(c => c.Type == NodeConnectionType.Add);
if (addConnection != null && addConnection.ConnectedTo.Any())
{
var connectedNode = addConnection.ConnectedTo.First();
if (connectedNode.Parent?.Name == "Text")
{
// Get the text content from the connected Text node
var textNodeConnection = connectedNode.Parent.Connections.FirstOrDefault(c =>
string.Equals(c.Attribute, "tag", StringComparison.OrdinalIgnoreCase));
if (textNodeConnection?.OverrideValue != null)
{
textContent = textNodeConnection.OverrideValue.ToString() ?? "";
}
}
}
}
// Translate the text if we found any
if (!string.IsNullOrEmpty(textContent))
{
var translated = TextManager.Get(textContent);
if (translated.Loaded)
{
textContent = translated.Value;
}
}
return textContent;
}
private string GetRawTextKey(EventEditorNodeConnection textConnection)
{
string textKey = "";
// First check if there's a direct text attribute
if (textConnection.OverrideValue != null)
{
textKey = textConnection.OverrideValue.ToString() ?? "";
}
else
{
var connectedValue = textConnection.GetValue();
if (connectedValue != null)
{
textKey = connectedValue.ToString() ?? "";
}
}
// If no direct text, check for inner Text nodes via Add connections
if (string.IsNullOrEmpty(textKey))
{
var addConnection = Connections.FirstOrDefault(c => c.Type == NodeConnectionType.Add);
if (addConnection != null && addConnection.ConnectedTo.Any())
{
var connectedNode = addConnection.ConnectedTo.First();
if (connectedNode.Parent?.Name == "Text")
{
// Get the text key from the connected Text node
var textNodeConnection = connectedNode.Parent.Connections.FirstOrDefault(c =>
string.Equals(c.Attribute, "tag", StringComparison.OrdinalIgnoreCase));
if (textNodeConnection?.OverrideValue != null)
{
textKey = textNodeConnection.OverrideValue.ToString() ?? "";
}
}
}
}
return textKey;
}
protected override bool ShouldDrawConnection(EventEditorNodeConnection connection)
{
if (!EventEditorScreen.ConversationMode) { return base.ShouldDrawConnection(connection); }
// In conversation mode, exclude Options and Text since we draw them manually
// Also exclude Add connections since we hide the child Text nodes and display their content inline
return connection.Type == NodeConnectionType.Activate ||
connection.Type == NodeConnectionType.Next;
}
protected override void DrawConnections(SpriteBatch spriteBatch)
{
if (!EventEditorScreen.ConversationMode)
{
base.DrawConnections(spriteBatch);
return;
}
// In conversation mode, use the correct rectangle for connection positioning
Rectangle correctRect = GetDrawRectangle();
int x = 0, y = 0;
foreach (EventEditorNodeConnection connection in Connections)
{
if (!ShouldDrawConnection(connection)) { continue; }
switch (connection.Type.NodeSide)
{
case NodeConnectionType.Side.Left:
connection.Draw(spriteBatch, correctRect, y);
y++;
break;
case NodeConnectionType.Side.Right:
connection.Draw(spriteBatch, correctRect, x);
x++;
break;
}
}
}
}
internal class EventConversationNode(Type type, string name) : EventTextDisplayNode(type, name)
{
protected override bool ShowOptions => true;
}
internal class EventLogNode(Type type, string name) : EventTextDisplayNode(type, name)
{
protected override bool ShowOptions => false;
}
}
@@ -18,6 +18,8 @@ namespace Barotrauma
public override Camera Cam { get; }
public static string? DrawnTooltip { get; set; }
public static bool ConversationMode { get; set; }
public static readonly List<EditorNode> nodeList = new List<EditorNode>();
@@ -37,6 +39,11 @@ namespace Barotrauma
private LocationType? lastTestType;
private GUITickBox? isTraitorEventBox;
private GUITickBox? conversationModeBox;
private readonly LanguageIdentifier originalLanguage;
private GUIDropDown? languageDropdown;
private static int CreateID()
{
@@ -50,25 +57,99 @@ namespace Barotrauma
{
Cam = new Camera();
nodeList.Clear();
originalLanguage = GameSettings.CurrentConfig.Language;
CreateGUI();
}
public override void Select()
{
GUI.PreventPauseMenuToggle = false;
projectName = TextManager.Get("EventEditor.Unnamed").Value;
UpdateLanguageDropdownSelection();
base.Select();
}
private void UpdateLanguageDropdownSelection()
{
if (languageDropdown == null) { return; }
languageDropdown.SelectItem(GameSettings.CurrentConfig.Language);
}
protected override void DeselectEditorSpecific()
{
// Restore the original language when leaving the editor
var config = GameSettings.CurrentConfig;
config.Language = originalLanguage;
GameSettings.SetCurrentConfig(config);
TextManager.LanguageChanged();
}
private static readonly HashSet<EditorNode> hiddenNodesInConversationMode = new HashSet<EditorNode>();
private static bool ShouldHideNodeInConversationMode(EditorNode node)
{
return hiddenNodesInConversationMode.Contains(node);
}
private static void UpdateHiddenNodesInConversationMode()
{
hiddenNodesInConversationMode.Clear();
// Find all text display nodes (ConversationAction and EventLogAction) and mark their inner Text nodes (and descendants) as hidden
foreach (var textDisplayNode in nodeList.Where(IsEventTextDisplayNode))
{
var addConnection = textDisplayNode.Connections.FirstOrDefault(c => c.Type == NodeConnectionType.Add);
if (addConnection != null && addConnection.ConnectedTo.Any())
{
foreach (var connectedNode in addConnection.ConnectedTo)
{
if (connectedNode.Parent?.Name == "Text")
{
MarkNodeAndDescendantsAsHidden(connectedNode.Parent);
}
}
}
}
}
private static bool IsEventTextDisplayNode(EditorNode node) => node is EventTextDisplayNode;
private static void MarkNodeAndDescendantsAsHidden(EditorNode node)
{
hiddenNodesInConversationMode.Add(node);
// Recursively mark all connected child nodes as hidden
foreach (var connection in node.Connections)
{
foreach (var connectedNode in connection.ConnectedTo)
{
if (connectedNode.Parent != null && !hiddenNodesInConversationMode.Contains(connectedNode.Parent))
{
MarkNodeAndDescendantsAsHidden(connectedNode.Parent);
}
}
}
}
private void CreateGUI()
{
GuiFrame = new GUIFrame(new RectTransform(new Vector2(0.2f, 0.4f), GUI.Canvas) { MinSize = new Point(300, 420) });
GuiFrame = new GUIFrame(new RectTransform(new Vector2(0.2f, 0.5f), GUI.Canvas) { MinSize = new Point(300, 520) });
GUILayoutGroup layoutGroup = new GUILayoutGroup(RectTransform(0.9f, 0.9f, GuiFrame, Anchor.Center)) { Stretch = true, AbsoluteSpacing = GUI.IntScale(5) };
// === BUTTONS === //
GUILayoutGroup buttonLayout = new GUILayoutGroup(RectTransform(1.0f, 0.50f, layoutGroup)) { RelativeSpacing = 0.04f };
GUIButton newProjectButton = new GUIButton(RectTransform(1.0f, 0.33f, buttonLayout), TextManager.Get("EventEditor.NewProject"));
GUIButton saveProjectButton = new GUIButton(RectTransform(1.0f, 0.33f, buttonLayout), TextManager.Get("EventEditor.SaveProject"));
GUIButton loadProjectButton = new GUIButton(RectTransform(1.0f, 0.33f, buttonLayout), TextManager.Get("EventEditor.LoadProject"));
GUIButton exportProjectButton = new GUIButton(RectTransform(1.0f, 0.33f, buttonLayout), TextManager.Get("EventEditor.Export"));
GUILayoutGroup buttonLayout = new GUILayoutGroup(RectTransform(1.0f, 0.40f, layoutGroup)) { RelativeSpacing = 0.04f };
GUIButton newProjectButton = new GUIButton(RectTransform(1.0f, 0.25f, buttonLayout), TextManager.Get("EventEditor.NewProject"));
GUIButton saveProjectButton = new GUIButton(RectTransform(1.0f, 0.25f, buttonLayout), TextManager.Get("EventEditor.SaveProject"));
GUIButton loadProjectButton = new GUIButton(RectTransform(1.0f, 0.25f, buttonLayout), TextManager.Get("EventEditor.LoadProject"));
GUIButton exportProjectButton = new GUIButton(RectTransform(1.0f, 0.25f, buttonLayout), TextManager.Get("EventEditor.Export"));
// === LOAD PREFAB === //
GUILayoutGroup loadEventLayout = new GUILayoutGroup(RectTransform(1.0f, 0.125f, layoutGroup));
GUILayoutGroup loadEventLayout = new GUILayoutGroup(RectTransform(1.0f, 0.10f, layoutGroup));
new GUITextBlock(RectTransform(1.0f, 0.5f, loadEventLayout), TextManager.Get("EventEditor.LoadEvent"), font: GUIStyle.SubHeadingFont);
GUILayoutGroup loadDropdownLayout = new GUILayoutGroup(RectTransform(1.0f, 0.5f, loadEventLayout), isHorizontal: true, childAnchor: Anchor.CenterLeft);
@@ -76,8 +157,7 @@ namespace Barotrauma
GUIButton loadButton = new GUIButton(RectTransform(0.2f, 1.0f, loadDropdownLayout), TextManager.Get("Load"));
// === ADD ACTION === //
GUILayoutGroup addActionLayout = new GUILayoutGroup(RectTransform(1.0f, 0.125f, layoutGroup));
GUILayoutGroup addActionLayout = new GUILayoutGroup(RectTransform(1.0f, 0.10f, layoutGroup));
new GUITextBlock(RectTransform(1.0f, 0.5f, addActionLayout), TextManager.Get("EventEditor.AddAction"), font: GUIStyle.SubHeadingFont);
GUILayoutGroup addActionDropdownLayout = new GUILayoutGroup(RectTransform(1.0f, 0.5f, addActionLayout), isHorizontal: true, childAnchor: Anchor.CenterLeft);
@@ -85,7 +165,7 @@ namespace Barotrauma
GUIButton addActionButton = new GUIButton(RectTransform(0.2f, 1.0f, addActionDropdownLayout), TextManager.Get("EventEditor.Add"));
// === ADD VALUE === //
GUILayoutGroup addValueLayout = new GUILayoutGroup(RectTransform(1.0f, 0.125f, layoutGroup));
GUILayoutGroup addValueLayout = new GUILayoutGroup(RectTransform(1.0f, 0.10f, layoutGroup));
new GUITextBlock(RectTransform(1.0f, 0.5f, addValueLayout), TextManager.Get("EventEditor.AddValue"), font: GUIStyle.SubHeadingFont);
GUILayoutGroup addValueDropdownLayout = new GUILayoutGroup(RectTransform(1.0f, 0.5f, addValueLayout), isHorizontal: true, childAnchor: Anchor.CenterLeft);
@@ -93,7 +173,7 @@ namespace Barotrauma
GUIButton addValueButton = new GUIButton(RectTransform(0.2f, 1.0f, addValueDropdownLayout), TextManager.Get("EventEditor.Add"));
// === ADD SPECIAL === //
GUILayoutGroup addSpecialLayout = new GUILayoutGroup(RectTransform(1.0f, 0.125f, layoutGroup));
GUILayoutGroup addSpecialLayout = new GUILayoutGroup(RectTransform(1.0f, 0.10f, layoutGroup));
new GUITextBlock(RectTransform(1.0f, 0.5f, addSpecialLayout), TextManager.Get("EventEditor.AddSpecial"), font: GUIStyle.SubHeadingFont);
GUILayoutGroup addSpecialDropdownLayout = new GUILayoutGroup(RectTransform(1.0f, 0.5f, addSpecialLayout), isHorizontal: true, childAnchor: Anchor.CenterLeft);
GUIDropDown addSpecialDropdown = new GUIDropDown(RectTransform(0.8f, 1.0f, addSpecialDropdownLayout), elementCount: 1);
@@ -156,7 +236,45 @@ namespace Barotrauma
return true;
};
isTraitorEventBox = new GUITickBox(RectTransform(1.0f, 0.125f, layoutGroup), "Traitor event");
isTraitorEventBox = new GUITickBox(RectTransform(1.0f, 0.10f, layoutGroup), "Traitor event");
// === CONVERSATION MODE CHECKBOX === //
conversationModeBox = new GUITickBox(RectTransform(1.0f, 0.10f, layoutGroup), "Conversation Mode");
conversationModeBox.Selected = ConversationMode;
conversationModeBox.OnSelected = box =>
{
ConversationMode = !ConversationMode;
UpdateHiddenNodesInConversationMode();
return true;
};
// === LANGUAGE SELECTION === //
GUILayoutGroup languageLayout = new GUILayoutGroup(RectTransform(1.0f, 0.10f, layoutGroup));
new GUITextBlock(RectTransform(1.0f, 0.5f, languageLayout), TextManager.Get("Language"), font: GUIStyle.SubHeadingFont);
var languages = TextManager.AvailableLanguages
.OrderBy(l => TextManager.GetTranslatedLanguageName(l).ToIdentifier());
languageDropdown = new GUIDropDown(RectTransform(1.0f, 0.5f, languageLayout), elementCount: 10);
foreach (var language in languages)
{
languageDropdown.AddItem(TextManager.GetTranslatedLanguageName(language), language);
}
// Select current language
languageDropdown.SelectItem(GameSettings.CurrentConfig.Language);
languageDropdown.OnSelected = (component, userData) =>
{
if (userData is LanguageIdentifier selectedLanguage)
{
var config = GameSettings.CurrentConfig;
config.Language = selectedLanguage;
GameSettings.SetCurrentConfig(config);
TextManager.LanguageChanged();
}
return true;
};
screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
}
@@ -323,6 +441,9 @@ namespace Barotrauma
{
GUI.NotifyPrompt(TextManager.Get("EventEditor.RandomGenerationHeader"), TextManager.Get("EventEditor.RandomGenerationBody"));
}
// Update hidden nodes after loading
UpdateHiddenNodesInConversationMode();
return true;
});
return true;
@@ -334,7 +455,22 @@ namespace Barotrauma
Vector2 spawnPos = Cam.WorldViewCenter;
spawnPos.Y = -spawnPos.Y;
EventNode newNode = new EventNode(type, type.Name) { ID = CreateID() };
// Create the appropriate node type based on the action type
EditorNode newNode;
if (EditorNode.IsInstanceOf(type, typeof(ConversationAction)))
{
newNode = new EventConversationNode(type, type.Name) { ID = CreateID() };
}
else if (EditorNode.IsInstanceOf(type, typeof(EventLogAction)))
{
newNode = new EventLogNode(type, type.Name) { ID = CreateID() };
}
else
{
newNode = new EventNode(type, type.Name) { ID = CreateID() };
}
newNode.Position = spawnPos - newNode.Size / 2;
nodeList.Add(newNode);
return true;
@@ -399,7 +535,19 @@ namespace Barotrauma
Type? t = Type.GetType($"Barotrauma.{subElement.Name}");
if (t != null && EditorNode.IsInstanceOf(t, typeof(EventAction)))
{
newNode = new EventNode(t, subElement.Name.ToString()) { Position = new Vector2(ident, 0), ID = CreateID() };
// Create the appropriate node type based on the action type
if (EditorNode.IsInstanceOf(t, typeof(ConversationAction)))
{
newNode = new EventConversationNode(t, subElement.Name.ToString()) { Position = new Vector2(ident, 0), ID = CreateID() };
}
else if (EditorNode.IsInstanceOf(t, typeof(EventLogAction)))
{
newNode = new EventLogNode(t, subElement.Name.ToString()) { Position = new Vector2(ident, 0), ID = CreateID() };
}
else
{
newNode = new EventNode(t, subElement.Name.ToString()) { Position = new Vector2(ident, 0), ID = CreateID() };
}
}
else
{
@@ -547,13 +695,6 @@ namespace Barotrauma
return new RectTransform(new Vector2(x, y), parent.RectTransform, anchor);
}
public override void Select()
{
GUI.PreventPauseMenuToggle = false;
projectName = TextManager.Get("EventEditor.Unnamed").Value;
base.Select();
}
public override void AddToGUIUpdateList()
{
GuiFrame.AddToGUIUpdateList();
@@ -671,6 +812,7 @@ namespace Barotrauma
private static void Load(XElement saveElement)
{
nodeList.Clear();
hiddenNodesInConversationMode.Clear();
projectName = saveElement.GetAttributeString("name", TextManager.Get("EventEditor.Unnamed").Value);
foreach (XElement element in saveElement.Elements())
{
@@ -702,6 +844,9 @@ namespace Barotrauma
}
}
}
// Update hidden nodes after loading
UpdateHiddenNodesInConversationMode();
}
private static void CreateContextMenu(EditorNode node, EventEditorNodeConnection? connection = null)
@@ -971,21 +1116,25 @@ namespace Barotrauma
foreach (EditorNode node in nodeList.Where(node => node is SpecialNode))
{
if (ConversationMode && ShouldHideNodeInConversationMode(node)) { continue; }
node.Draw(spriteBatch);
}
// Render value nodes below event nodes
foreach (EditorNode node in nodeList.Where(node => node is ValueNode))
{
if (ConversationMode && ShouldHideNodeInConversationMode(node)) { continue; }
node.Draw(spriteBatch);
}
foreach (EditorNode node in nodeList.Where(node => node is EventNode))
{
if (ConversationMode && ShouldHideNodeInConversationMode(node)) { continue; }
node.Draw(spriteBatch);
}
draggedNode?.Draw(spriteBatch);
foreach (var (node, _) in markedNodes)
{
node.Draw(spriteBatch);
@@ -1013,6 +1162,11 @@ namespace Barotrauma
CreateGUI();
}
if (PlayerInput.KeyHit(Keys.R) && PlayerInput.KeyDown(Keys.LeftShift))
{
CreateGUI();
}
Cam.MoveCamera((float) deltaTime, allowMove: true, allowZoom: GUI.MouseOn == null);
Vector2 mousePos = Cam.ScreenToWorld(PlayerInput.MousePosition);
mousePos.Y = -mousePos.Y;