Release v0.15.12.0
This commit is contained in:
@@ -130,6 +130,7 @@ namespace Barotrauma
|
||||
public static GUIStyle Style;
|
||||
|
||||
private static Texture2D t;
|
||||
public static Texture2D WhiteTexture => t;
|
||||
private static Sprite[] MouseCursorSprites => Style.CursorSprite;
|
||||
|
||||
private static bool debugDrawSounds, debugDrawEvents, debugDrawMetadata;
|
||||
@@ -163,6 +164,7 @@ namespace Barotrauma
|
||||
public static ScalableFont SubHeadingFont => Style?.SubHeadingFont;
|
||||
public static ScalableFont DigitalFont => Style?.DigitalFont;
|
||||
public static ScalableFont HotkeyFont => Style?.HotkeyFont;
|
||||
public static ScalableFont MonospacedFont => Style?.MonospacedFont;
|
||||
|
||||
public static ScalableFont CJKFont { get; private set; }
|
||||
|
||||
@@ -306,7 +308,7 @@ namespace Barotrauma
|
||||
});
|
||||
|
||||
SubmarineIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(452, 385, 182, 81), new Vector2(0.5f, 0.5f));
|
||||
arrow = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(392, 393, 49, 45), new Vector2(0.5f, 0.5f));
|
||||
arrow = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(393, 393, 49, 45), new Vector2(0.5f, 0.5f));
|
||||
SpeechBubbleIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(385, 449, 66, 60), new Vector2(0.5f, 0.5f));
|
||||
BrokenIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(898, 386, 123, 123), new Vector2(0.5f, 0.5f));
|
||||
}
|
||||
@@ -672,6 +674,12 @@ namespace Barotrauma
|
||||
spriteBatch.End();
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: SamplerStateClamp, rasterizerState: GameMain.ScissorTestEnable);
|
||||
|
||||
if (GameMain.GameSession?.CrewManager is { DraggedOrder: { SymbolSprite: { } orderSprite, Color: var color }, DragOrder: true })
|
||||
{
|
||||
float spriteSize = Math.Max(orderSprite.size.X, orderSprite.size.Y);
|
||||
orderSprite.Draw(spriteBatch, PlayerInput.LatestMousePosition, color, orderSprite.size / 2f, scale: 32f / spriteSize * Scale);
|
||||
}
|
||||
|
||||
var sprite = MouseCursorSprites[(int)MouseCursor] ?? MouseCursorSprites[(int)CursorState.Default];
|
||||
sprite.Draw(spriteBatch, PlayerInput.LatestMousePosition, Color.White, sprite.Origin, 0f, Scale / 1.5f);
|
||||
|
||||
@@ -855,11 +863,10 @@ namespace Barotrauma
|
||||
int index = 0;
|
||||
if (updateList.Count > 0)
|
||||
{
|
||||
index = updateList.Count - 1;
|
||||
while (updateList[index].UpdateOrder > item.UpdateOrder)
|
||||
index = updateList.Count;
|
||||
while (index > 0 && updateList[index-1].UpdateOrder > item.UpdateOrder)
|
||||
{
|
||||
index--;
|
||||
if (index == 0) { break; }
|
||||
}
|
||||
}
|
||||
if (!updateListSet.Contains(item))
|
||||
@@ -927,13 +934,14 @@ namespace Barotrauma
|
||||
GUIComponent prevMouseOn = MouseOn;
|
||||
MouseOn = null;
|
||||
int inventoryIndex = -1;
|
||||
|
||||
if (Inventory.IsMouseOnInventory())
|
||||
|
||||
Inventory.RefreshMouseOnInventory();
|
||||
if (Inventory.IsMouseOnInventory)
|
||||
{
|
||||
inventoryIndex = updateList.IndexOf(CharacterHUD.HUDFrame);
|
||||
}
|
||||
|
||||
if (!PlayerInput.PrimaryMouseButtonHeld() && !PlayerInput.PrimaryMouseButtonClicked())
|
||||
if ((!PlayerInput.PrimaryMouseButtonHeld() && !PlayerInput.PrimaryMouseButtonClicked()) || (prevMouseOn == null && !PlayerInput.SecondaryMouseButtonHeld()))
|
||||
{
|
||||
for (var i = updateList.Count - 1; i > inventoryIndex; i--)
|
||||
{
|
||||
@@ -941,10 +949,9 @@ namespace Barotrauma
|
||||
if (!c.CanBeFocused) { continue; }
|
||||
if (c.MouseRect.Contains(PlayerInput.MousePosition))
|
||||
{
|
||||
if ((!PlayerInput.PrimaryMouseButtonHeld() && !PlayerInput.PrimaryMouseButtonClicked()) || c == prevMouseOn)
|
||||
if ((!PlayerInput.PrimaryMouseButtonHeld() && !PlayerInput.PrimaryMouseButtonClicked()) || c == prevMouseOn || prevMouseOn == null)
|
||||
{
|
||||
MouseOn = c;
|
||||
var sakdjfnsjkd = c.MouseRect;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -958,7 +965,6 @@ namespace Barotrauma
|
||||
MouseCursor = UpdateMouseCursorState(MouseOn);
|
||||
return MouseOn;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static CursorState UpdateMouseCursorState(GUIComponent c)
|
||||
@@ -1050,23 +1056,26 @@ namespace Barotrauma
|
||||
{
|
||||
if (listBox.DraggedElement != null) { return CursorState.Dragging; }
|
||||
if (listBox.CanDragElements) { return CursorState.Move; }
|
||||
|
||||
var hoverParent = c;
|
||||
while (true)
|
||||
|
||||
if (listBox.HoverCursor != CursorState.Default)
|
||||
{
|
||||
if (hoverParent == parent || hoverParent == null) { break; }
|
||||
if (hoverParent.State == GUIComponent.ComponentState.Hover) { return CursorState.Hand; }
|
||||
hoverParent = hoverParent.Parent;
|
||||
var hoverParent = c;
|
||||
while (true)
|
||||
{
|
||||
if (hoverParent == parent || hoverParent == null) { break; }
|
||||
if (hoverParent.State == GUIComponent.ComponentState.Hover) { return CursorState.Hand; }
|
||||
hoverParent = hoverParent.Parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (parent != null && parent.CanBeFocused)
|
||||
{
|
||||
if (!parent.Rect.Equals(monitorRect)) { return parent.HoverCursor; }
|
||||
}
|
||||
}
|
||||
|
||||
if (Inventory.IsMouseOnInventory()) { return Inventory.GetInventoryMouseCursor(); }
|
||||
|
||||
if (Inventory.IsMouseOnInventory) { return Inventory.GetInventoryMouseCursor(); }
|
||||
|
||||
var character = Character.Controlled;
|
||||
// ReSharper disable once InvertIf
|
||||
@@ -1343,7 +1352,7 @@ namespace Barotrauma
|
||||
|
||||
/// <param name="createOffset">Should the indicator move based on the camera position?</param>
|
||||
/// <param name="overrideAlpha">Override the distance-based alpha value with the specified alpha value</param>
|
||||
public static void DrawIndicator(SpriteBatch spriteBatch, in Vector2 worldPosition, Camera cam, in Vector2 visibleRange, Sprite sprite, in Color color,
|
||||
public static void DrawIndicator(SpriteBatch spriteBatch, in Vector2 worldPosition, Camera cam, in Range<float> visibleRange, Sprite sprite, in Color color,
|
||||
bool createOffset = true, float scaleMultiplier = 1.0f, float? overrideAlpha = null)
|
||||
{
|
||||
Vector2 diff = worldPosition - cam.WorldViewCenter;
|
||||
@@ -1351,9 +1360,9 @@ namespace Barotrauma
|
||||
|
||||
float symbolScale = Math.Min(64.0f / sprite.size.X, 1.0f) * scaleMultiplier * Scale;
|
||||
|
||||
if (overrideAlpha.HasValue || (dist > visibleRange.X && dist < visibleRange.Y))
|
||||
if (overrideAlpha.HasValue || (dist > visibleRange.Start && dist < visibleRange.End))
|
||||
{
|
||||
float alpha = overrideAlpha ?? MathUtils.Min((dist - visibleRange.X) / 100.0f, 1.0f - ((dist - visibleRange.Y + 100f) / 100.0f), 1.0f);
|
||||
float alpha = overrideAlpha ?? MathUtils.Min((dist - visibleRange.Start) / 100.0f, 1.0f - ((dist - visibleRange.End + 100f) / 100.0f), 1.0f);
|
||||
Vector2 targetScreenPos = cam.WorldToScreen(worldPosition);
|
||||
|
||||
if (!createOffset)
|
||||
@@ -1417,7 +1426,7 @@ namespace Barotrauma
|
||||
public static void DrawIndicator(SpriteBatch spriteBatch, Vector2 worldPosition, Camera cam, float hideDist, Sprite sprite, Color color,
|
||||
bool createOffset = true, float scaleMultiplier = 1.0f, float? overrideAlpha = null)
|
||||
{
|
||||
DrawIndicator(spriteBatch, worldPosition, cam, new Vector2(hideDist, float.PositiveInfinity), sprite, color, createOffset, scaleMultiplier, overrideAlpha);
|
||||
DrawIndicator(spriteBatch, worldPosition, cam, new Range<float>(hideDist, float.PositiveInfinity), sprite, color, createOffset, scaleMultiplier, overrideAlpha);
|
||||
}
|
||||
|
||||
public static void DrawLine(SpriteBatch sb, Vector2 start, Vector2 end, Color clr, float depth = 0.0f, float width = 1)
|
||||
@@ -1520,6 +1529,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawFilledRectangle(SpriteBatch sb, RectangleF rect, Color clr, float depth = 0.0f)
|
||||
{
|
||||
DrawFilledRectangle(sb, rect.Location, rect.Size, clr, depth);
|
||||
}
|
||||
|
||||
public static void DrawFilledRectangle(SpriteBatch sb, Vector2 start, Vector2 size, Color clr, float depth = 0.0f)
|
||||
{
|
||||
if (size.X < 0)
|
||||
@@ -2433,14 +2447,43 @@ namespace Barotrauma
|
||||
{
|
||||
if (messages.Any(msg => msg.Text == message)) { return; }
|
||||
messages.Add(new GUIMessage(message, color, lifeTime ?? MathHelper.Clamp(message.Length / 5.0f, 3.0f, 10.0f), font ?? LargeFont));
|
||||
if (playSound) SoundPlayer.PlayUISound(GUISoundType.UIMessage);
|
||||
if (playSound) { SoundPlayer.PlayUISound(GUISoundType.UIMessage); }
|
||||
}
|
||||
|
||||
public static void AddMessage(string message, Color color, Vector2 pos, Vector2 velocity, float lifeTime = 3.0f, bool playSound = true, GUISoundType soundType = GUISoundType.UIMessage, int subId = -1)
|
||||
{
|
||||
Submarine sub = Submarine.Loaded.FirstOrDefault(s => s.ID == subId);
|
||||
messages.Add(new GUIMessage(message, color, pos, velocity, lifeTime, Alignment.Center, LargeFont, sub: sub));
|
||||
if (playSound) SoundPlayer.PlayUISound(soundType);
|
||||
|
||||
var newMessage = new GUIMessage(message, color, pos, velocity, lifeTime, Alignment.Center, Font, sub: sub);
|
||||
if (playSound) { SoundPlayer.PlayUISound(soundType); }
|
||||
bool overlapFound = true;
|
||||
int tries = 0;
|
||||
while (overlapFound)
|
||||
{
|
||||
overlapFound = false;
|
||||
foreach (var otherMessage in messages)
|
||||
{
|
||||
float xDiff = otherMessage.Pos.X - newMessage.Pos.X;
|
||||
if (Math.Abs(xDiff) > (newMessage.Size.X + otherMessage.Size.X) / 2) { continue; }
|
||||
float yDiff = otherMessage.Pos.Y - newMessage.Pos.Y;
|
||||
if (Math.Abs(yDiff) > (newMessage.Size.Y + otherMessage.Size.Y) / 2) { continue; }
|
||||
Vector2 moveDir = -(new Vector2(xDiff, yDiff) + Rand.Vector(1.0f));
|
||||
if (moveDir.LengthSquared() > 0.0001f)
|
||||
{
|
||||
moveDir = Vector2.Normalize(moveDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
moveDir = Rand.Vector(1.0f);
|
||||
}
|
||||
moveDir.Y = -Math.Abs(moveDir.Y);
|
||||
newMessage.Pos -= Vector2.UnitY * 10;
|
||||
}
|
||||
tries++;
|
||||
if (tries > 20) { break; }
|
||||
}
|
||||
|
||||
messages.Add(newMessage);
|
||||
}
|
||||
|
||||
public static void ClearMessages()
|
||||
|
||||
@@ -52,13 +52,13 @@ namespace Barotrauma
|
||||
|
||||
public GUIComponent GetChild(int index)
|
||||
{
|
||||
if (index < 0 || index >= CountChildren) return null;
|
||||
if (index < 0 || index >= CountChildren) { return null; }
|
||||
return RectTransform.GetChild(index).GUIComponent;
|
||||
}
|
||||
|
||||
public int GetChildIndex(GUIComponent child)
|
||||
{
|
||||
if (child == null) return -1;
|
||||
if (child == null) { return -1; }
|
||||
return RectTransform.GetChildIndex(child.RectTransform);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (GUIComponent child in Children)
|
||||
{
|
||||
if (child.UserData == obj || (child.userData != null && child.userData.Equals(obj))) return child;
|
||||
if (child.UserData == obj || (child.userData != null && child.userData.Equals(obj))) { return child; }
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -175,6 +175,8 @@ namespace Barotrauma
|
||||
|
||||
public bool GlowOnSelect { get; set; }
|
||||
|
||||
public Vector2 UVOffset { get; set; }
|
||||
|
||||
private CoroutineHandle pulsateCoroutine;
|
||||
|
||||
protected Color flashColor;
|
||||
@@ -256,9 +258,9 @@ namespace Barotrauma
|
||||
|
||||
protected Rectangle ClampRect(Rectangle r)
|
||||
{
|
||||
if (Parent == null || !ClampMouseRectToParent) return r;
|
||||
if (Parent == null || !ClampMouseRectToParent) { return r; }
|
||||
Rectangle parentRect = Parent.ClampRect(Parent.Rect);
|
||||
if (parentRect.Width <= 0 || parentRect.Height <= 0) return Rectangle.Empty;
|
||||
if (parentRect.Width <= 0 || parentRect.Height <= 0) { return Rectangle.Empty; }
|
||||
if (parentRect.X > r.X)
|
||||
{
|
||||
int diff = parentRect.X - r.X;
|
||||
@@ -281,7 +283,7 @@ namespace Barotrauma
|
||||
int diff = (r.Y + r.Height) - (parentRect.Y + parentRect.Height);
|
||||
r.Height -= diff;
|
||||
}
|
||||
if (r.Width <= 0 || r.Height <= 0) return Rectangle.Empty;
|
||||
if (r.Width <= 0 || r.Height <= 0) { return Rectangle.Empty; }
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -295,7 +297,7 @@ namespace Barotrauma
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!CanBeFocused) return Rectangle.Empty;
|
||||
if (!CanBeFocused) { return Rectangle.Empty; }
|
||||
return ClampMouseRectToParent ? ClampRect(Rect) : Rect;
|
||||
}
|
||||
}
|
||||
@@ -431,7 +433,7 @@ namespace Barotrauma
|
||||
#region Updating
|
||||
public virtual void AddToGUIUpdateList(bool ignoreChildren = false, int order = 0)
|
||||
{
|
||||
if (!Visible) return;
|
||||
if (!Visible) { return; }
|
||||
|
||||
UpdateOrder = order;
|
||||
GUI.AddToUpdateList(this);
|
||||
@@ -463,7 +465,7 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public void UpdateManually(float deltaTime, bool alsoChildren = false, bool recursive = true)
|
||||
{
|
||||
if (!Visible) return;
|
||||
if (!Visible) { return; }
|
||||
|
||||
AutoUpdate = false;
|
||||
Update(deltaTime);
|
||||
@@ -475,7 +477,7 @@ namespace Barotrauma
|
||||
|
||||
protected virtual void Update(float deltaTime)
|
||||
{
|
||||
if (!Visible) return;
|
||||
if (!Visible) { return; }
|
||||
|
||||
if (CanBeFocused && OnSecondaryClicked != null)
|
||||
{
|
||||
@@ -555,7 +557,7 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public virtual void DrawManually(SpriteBatch spriteBatch, bool alsoChildren = false, bool recursive = true)
|
||||
{
|
||||
if (!Visible) return;
|
||||
if (!Visible) { return; }
|
||||
|
||||
AutoDraw = false;
|
||||
Draw(spriteBatch);
|
||||
@@ -598,7 +600,7 @@ namespace Barotrauma
|
||||
|
||||
protected virtual void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (!Visible) return;
|
||||
if (!Visible) { return; }
|
||||
var rect = Rect;
|
||||
|
||||
GetBlendedColor(GetColor(State), ref _currentColor);
|
||||
@@ -653,7 +655,7 @@ namespace Barotrauma
|
||||
? MathUtils.InverseLerp(0, SpriteCrossFadeTime, ToolBox.GetEasing(uiSprite.TransitionMode, spriteFadeTimer)) : 0;
|
||||
if (alphaMultiplier > 0)
|
||||
{
|
||||
uiSprite.Draw(spriteBatch, rect, previousColor * alphaMultiplier, SpriteEffects);
|
||||
uiSprite.Draw(spriteBatch, rect, previousColor * alphaMultiplier, SpriteEffects, uvOffset: UVOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -667,7 +669,11 @@ namespace Barotrauma
|
||||
? MathUtils.InverseLerp(SpriteCrossFadeTime, 0, ToolBox.GetEasing(uiSprite.TransitionMode, spriteFadeTimer)) : (_currentColor.A / 255.0f);
|
||||
if (alphaMultiplier > 0)
|
||||
{
|
||||
uiSprite.Draw(spriteBatch, rect, _currentColor * alphaMultiplier, SpriteEffects);
|
||||
// * (rect.Location.Y - PlayerInput.MousePosition.Y) / rect.Height
|
||||
Vector2 offset = new Vector2(
|
||||
MathUtils.PositiveModulo((int)-UVOffset.X, uiSprite.Sprite.SourceRect.Width),
|
||||
MathUtils.PositiveModulo((int)-UVOffset.Y, uiSprite.Sprite.SourceRect.Height));
|
||||
uiSprite.Draw(spriteBatch, rect, _currentColor * alphaMultiplier, SpriteEffects, uvOffset: offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -708,7 +714,7 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public void DrawToolTip(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (!Visible) return;
|
||||
if (!Visible) { return; }
|
||||
DrawToolTip(spriteBatch, ToolTip, GUI.MouseOn.Rect, TooltipRichTextData);
|
||||
}
|
||||
|
||||
@@ -1048,7 +1054,7 @@ namespace Barotrauma
|
||||
{
|
||||
case "language":
|
||||
string[] languages = element.GetAttributeStringArray(attribute.Name.ToString(), new string[0]);
|
||||
if (!languages.Any(l => GameMain.Config.Language.ToLower() == l.ToLower())) { return false; }
|
||||
if (!languages.Any(l => GameMain.Config.Language.Equals(l, StringComparison.OrdinalIgnoreCase))) { return false; }
|
||||
break;
|
||||
case "gameversion":
|
||||
var version = new Version(attribute.Value);
|
||||
@@ -1213,8 +1219,7 @@ namespace Barotrauma
|
||||
|
||||
private static GUIImage LoadGUIImage(XElement element, RectTransform parent)
|
||||
{
|
||||
Sprite sprite = null;
|
||||
|
||||
Sprite sprite;
|
||||
string url = element.GetAttributeString("url", "");
|
||||
if (!string.IsNullOrEmpty(url))
|
||||
{
|
||||
|
||||
@@ -23,6 +23,8 @@ namespace Barotrauma
|
||||
private bool selectMultiple;
|
||||
|
||||
public bool Dropped { get; set; }
|
||||
|
||||
public bool AllowNonText { get; set; }
|
||||
|
||||
public object SelectedItemData
|
||||
{
|
||||
@@ -318,9 +320,9 @@ namespace Barotrauma
|
||||
if (textBlock == null)
|
||||
{
|
||||
textBlock = component.GetChild<GUITextBlock>();
|
||||
if (textBlock == null) return false;
|
||||
if (textBlock is null && !AllowNonText) { return false; }
|
||||
}
|
||||
button.Text = textBlock.Text;
|
||||
button.Text = textBlock?.Text ?? "";
|
||||
}
|
||||
Dropped = false;
|
||||
// TODO: OnSelected can be called multiple times and when it shouldn't be called -> turn into an event so that nobody else can call it.
|
||||
|
||||
@@ -5,8 +5,8 @@ using System.Linq;
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class GUIFrame : GUIComponent
|
||||
{
|
||||
public int OutlineThickness { get; set; }
|
||||
{
|
||||
public float OutlineThickness { get; set; }
|
||||
|
||||
public GUIFrame(RectTransform rectT, string style = "", Color? color = null) : base(style, rectT)
|
||||
{
|
||||
@@ -28,7 +28,7 @@ namespace Barotrauma
|
||||
|
||||
if (OutlineColor != Color.Transparent)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, Rect, OutlineColor * (OutlineColor.A/255.0f), false, thickness: OutlineThickness);
|
||||
GUI.DrawRectangle(spriteBatch, Rect, OutlineColor, false, thickness: OutlineThickness);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace Barotrauma
|
||||
if (BlendState != null)
|
||||
{
|
||||
spriteBatch.End();
|
||||
spriteBatch.Begin(blendState: BlendState, samplerState: GUI.SamplerState);
|
||||
spriteBatch.Begin(blendState: BlendState, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
||||
}
|
||||
|
||||
if (style != null)
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Barotrauma
|
||||
public GUIFrame Content { get; private set; }
|
||||
public GUIScrollBar ScrollBar { get; private set; }
|
||||
|
||||
private Dictionary<GUIComponent, bool> childVisible = new Dictionary<GUIComponent, bool>();
|
||||
private readonly Dictionary<GUIComponent, bool> childVisible = new Dictionary<GUIComponent, bool>();
|
||||
|
||||
private int totalSize;
|
||||
private bool childrenNeedsRecalculation;
|
||||
@@ -224,7 +224,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (value == false && canDragElements && draggedElement != null)
|
||||
{
|
||||
draggedElement = null;
|
||||
DraggedElement = null;
|
||||
}
|
||||
canDragElements = value;
|
||||
}
|
||||
@@ -233,11 +233,29 @@ namespace Barotrauma
|
||||
private GUIComponent draggedElement;
|
||||
private Rectangle draggedReferenceRectangle;
|
||||
private Point draggedReferenceOffset;
|
||||
public bool HasDraggedElementIndexChanged { get; private set; }
|
||||
|
||||
public GUIComponent DraggedElement => draggedElement;
|
||||
public GUIComponent DraggedElement
|
||||
{
|
||||
get
|
||||
{
|
||||
return draggedElement;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == draggedElement) { return; }
|
||||
draggedElement = value;
|
||||
HasDraggedElementIndexChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly bool isHorizontal;
|
||||
|
||||
/// <summary>
|
||||
/// Setting this to true and CanBeFocused to false allows the list background to be unfocusable while the elements can still be interacted with.
|
||||
/// </summary>
|
||||
public bool CanInteractWhenUnfocusable { get; set; } = false;
|
||||
|
||||
/// <param name="isScrollBarOnDefaultSide">For horizontal listbox, default side is on the bottom. For vertical, it's on the right.</param>
|
||||
public GUIListBox(RectTransform rectT, bool isHorizontal = false, Color? color = null, string style = "", bool isScrollBarOnDefaultSide = true, bool useMouseDownToSelect = false) : base(style, rectT)
|
||||
{
|
||||
@@ -472,7 +490,7 @@ namespace Barotrauma
|
||||
if (!PlayerInput.PrimaryMouseButtonHeld())
|
||||
{
|
||||
OnRearranged?.Invoke(this, draggedElement.UserData);
|
||||
draggedElement = null;
|
||||
DraggedElement = null;
|
||||
RepositionChildren();
|
||||
}
|
||||
else
|
||||
@@ -518,6 +536,7 @@ namespace Barotrauma
|
||||
if (currIndex != index)
|
||||
{
|
||||
draggedElement.RectTransform.RepositionChildInHierarchy(currIndex);
|
||||
HasDraggedElementIndexChanged = true;
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -556,7 +575,7 @@ namespace Barotrauma
|
||||
if (child == null || !child.Visible) { continue; }
|
||||
|
||||
// selecting
|
||||
if (Enabled && CanBeFocused && child.CanBeFocused && child.Rect.Contains(PlayerInput.MousePosition) && GUI.IsMouseOn(child))
|
||||
if (Enabled && (CanBeFocused || CanInteractWhenUnfocusable) && child.CanBeFocused && child.Rect.Contains(PlayerInput.MousePosition) && GUI.IsMouseOn(child))
|
||||
{
|
||||
child.State = ComponentState.Hover;
|
||||
|
||||
@@ -577,7 +596,7 @@ namespace Barotrauma
|
||||
|
||||
if (CanDragElements && PlayerInput.PrimaryMouseButtonDown() && GUI.MouseOn == child)
|
||||
{
|
||||
draggedElement = child;
|
||||
DraggedElement = child;
|
||||
draggedReferenceRectangle = child.Rect;
|
||||
draggedReferenceOffset = child.RectTransform.AbsoluteOffset;
|
||||
}
|
||||
@@ -608,7 +627,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (child == Content || child == ScrollBar || child == ContentBackground) { continue; }
|
||||
child.AddToGUIUpdateList(ignoreChildren, order);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (GUIComponent child in Content.Children)
|
||||
@@ -637,7 +656,7 @@ namespace Barotrauma
|
||||
OnAddedToGUIUpdateList?.Invoke(this);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int lastVisible = 0;
|
||||
for (int i = 0; i < Content.CountChildren; i++)
|
||||
{
|
||||
@@ -681,6 +700,8 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void ForceUpdate() => Update((float)Timing.Step);
|
||||
|
||||
protected override void Update(float deltaTime)
|
||||
{
|
||||
if (!Visible) { return; }
|
||||
@@ -750,7 +771,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if ((GUI.IsMouseOn(this) || GUI.IsMouseOn(ScrollBar)) && AllowMouseWheelScroll && PlayerInput.ScrollWheelSpeed != 0)
|
||||
if (PlayerInput.ScrollWheelSpeed != 0 && AllowMouseWheelScroll && (FindScrollableParentListBox(GUI.MouseOn) == this || GUI.IsMouseOn(ScrollBar)))
|
||||
{
|
||||
if (SmoothScroll)
|
||||
{
|
||||
@@ -773,7 +794,6 @@ namespace Barotrauma
|
||||
ScrollBar.BarScroll -= (PlayerInput.ScrollWheelSpeed / 500.0f) * BarSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ScrollBar.Enabled = ScrollBarEnabled && BarSize < 1.0f;
|
||||
if (AutoHideScrollBar)
|
||||
@@ -785,6 +805,13 @@ namespace Barotrauma
|
||||
UpdateDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
private static GUIListBox FindScrollableParentListBox(GUIComponent target)
|
||||
{
|
||||
if (target is GUIListBox listBox && listBox.ScrollBarEnabled && listBox.BarSize < 1.0f) { return listBox; }
|
||||
if (target?.Parent == null) { return null; }
|
||||
return FindScrollableParentListBox(target.Parent);
|
||||
}
|
||||
|
||||
public void SelectNext(bool force = false, bool autoScroll = true, bool takeKeyBoardFocus = false)
|
||||
{
|
||||
@@ -982,7 +1009,7 @@ namespace Barotrauma
|
||||
if (child == null) { return; }
|
||||
child.RectTransform.Parent = null;
|
||||
if (selected.Contains(child)) { selected.Remove(child); }
|
||||
if (draggedElement == child) { draggedElement = null; }
|
||||
if (draggedElement == child) { DraggedElement = null; }
|
||||
UpdateScrollBarSize();
|
||||
}
|
||||
|
||||
@@ -999,7 +1026,6 @@ namespace Barotrauma
|
||||
ContentBackground.DrawManually(spriteBatch, alsoChildren: false);
|
||||
|
||||
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
|
||||
RasterizerState prevRasterizerState = spriteBatch.GraphicsDevice.RasterizerState;
|
||||
if (HideChildrenOutsideFrame)
|
||||
{
|
||||
spriteBatch.End();
|
||||
@@ -1027,7 +1053,7 @@ namespace Barotrauma
|
||||
{
|
||||
spriteBatch.End();
|
||||
spriteBatch.GraphicsDevice.ScissorRectangle = prevScissorRect;
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: prevRasterizerState);
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
||||
}
|
||||
|
||||
if (ScrollBarVisible)
|
||||
|
||||
@@ -79,14 +79,14 @@ namespace Barotrauma
|
||||
new Rectangle(
|
||||
sliderArea.X + (int)sliceBorderSizes.X,
|
||||
sliderArea.Y,
|
||||
(int)((sliderArea.Width - sliceBorderSizes.X - sliceBorderSizes.Z) * fillAmount),
|
||||
(int)Math.Round((sliderArea.Width - sliceBorderSizes.X - sliceBorderSizes.Z) * fillAmount),
|
||||
sliderArea.Height)
|
||||
:
|
||||
new Rectangle(
|
||||
sliderArea.X,
|
||||
(int)(sliderArea.Bottom - (sliderArea.Height - sliceBorderSizes.Y - sliceBorderSizes.W) * fillAmount - sliceBorderSizes.W),
|
||||
(int)Math.Round(sliderArea.Bottom - (sliderArea.Height - sliceBorderSizes.Y - sliceBorderSizes.W) * fillAmount - sliceBorderSizes.W),
|
||||
sliderArea.Width,
|
||||
(int)((sliderArea.Height - sliceBorderSizes.Y - sliceBorderSizes.W) * fillAmount));
|
||||
(int)Math.Round((sliderArea.Height - sliceBorderSizes.Y - sliceBorderSizes.W) * fillAmount));
|
||||
|
||||
sliderRect.Width = Math.Max(sliderRect.Width, 1);
|
||||
sliderRect.Height = Math.Max(sliderRect.Height, 1);
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class GUIScissorComponent: GUIComponent
|
||||
{
|
||||
public GUIComponent Content;
|
||||
|
||||
public GUIScissorComponent(RectTransform rectT) : base(null, rectT)
|
||||
{
|
||||
Content = new GUIFrame(new RectTransform(Vector2.One, rectT), style: null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
|
||||
protected override void Update(float deltaTime)
|
||||
{
|
||||
base.Update(deltaTime);
|
||||
|
||||
foreach (GUIComponent child in Children)
|
||||
{
|
||||
if (child == Content) { continue; }
|
||||
throw new InvalidOperationException($"Children were found in {nameof(GUIScissorComponent)}, Add them to {nameof(GUIScissorComponent)}.{nameof(Content)} instead.");
|
||||
}
|
||||
|
||||
ClampChildMouseRects(Content);
|
||||
}
|
||||
|
||||
protected override void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (!Visible) { return; }
|
||||
|
||||
Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
|
||||
RasterizerState prevRasterizerState = spriteBatch.GraphicsDevice.RasterizerState;
|
||||
|
||||
spriteBatch.End();
|
||||
spriteBatch.GraphicsDevice.ScissorRectangle = Rectangle.Intersect(prevScissorRect, Rect);
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
|
||||
|
||||
foreach (GUIComponent child in Content.Children)
|
||||
{
|
||||
if (!child.Visible) { continue; }
|
||||
child.DrawManually(spriteBatch, alsoChildren: true, recursive: true);
|
||||
}
|
||||
|
||||
spriteBatch.End();
|
||||
spriteBatch.GraphicsDevice.ScissorRectangle = prevScissorRect;
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: prevRasterizerState);
|
||||
}
|
||||
|
||||
private void ClampChildMouseRects(GUIComponent child)
|
||||
{
|
||||
child.ClampMouseRectToParent = true;
|
||||
|
||||
if (child is GUIListBox) { return; }
|
||||
|
||||
foreach (GUIComponent grandChild in child.Children)
|
||||
{
|
||||
ClampChildMouseRects(grandChild);
|
||||
}
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList(bool ignoreChildren = false, int order = 0)
|
||||
{
|
||||
if (!Visible) { return; }
|
||||
|
||||
UpdateOrder = order;
|
||||
GUI.AddToUpdateList(this);
|
||||
|
||||
if (ignoreChildren)
|
||||
{
|
||||
OnAddedToGUIUpdateList?.Invoke(this);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (GUIComponent child in Content.Children)
|
||||
{
|
||||
if (!child.Visible) { continue; }
|
||||
child.AddToGUIUpdateList(false, order);
|
||||
}
|
||||
OnAddedToGUIUpdateList?.Invoke(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace Barotrauma
|
||||
{
|
||||
private Dictionary<string, GUIComponentStyle> componentStyles;
|
||||
|
||||
private XElement configElement;
|
||||
private readonly XElement configElement;
|
||||
|
||||
private GraphicsDevice graphicsDevice;
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace Barotrauma
|
||||
public ScalableFont SubHeadingFont { get; private set; }
|
||||
public ScalableFont DigitalFont { get; private set; }
|
||||
public ScalableFont HotkeyFont { get; private set; }
|
||||
public ScalableFont MonospacedFont { get; private set; }
|
||||
|
||||
public Dictionary<ScalableFont, bool> ForceFontUpperCase
|
||||
{
|
||||
@@ -40,12 +41,20 @@ namespace Barotrauma
|
||||
public SpriteSheet SavingIndicator { get; private set; }
|
||||
|
||||
public UISprite UIGlow { get; private set; }
|
||||
|
||||
public UISprite PingCircle { get; private set; }
|
||||
|
||||
public UISprite UIGlowCircular { get; private set; }
|
||||
|
||||
public UISprite UIGlowSolidCircular { get; private set; }
|
||||
public UISprite UIThermalGlow { get; private set; }
|
||||
|
||||
public UISprite ButtonPulse { get; private set; }
|
||||
|
||||
public SpriteSheet FocusIndicator { get; private set; }
|
||||
|
||||
public UISprite IconOverflowIndicator { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// General green color used for elements whose colors are set from code
|
||||
/// </summary>
|
||||
@@ -82,6 +91,12 @@ namespace Barotrauma
|
||||
public Color TextColorDark { get; private set; } = Color.Black * 0.9f;
|
||||
public Color TextColorDim { get; private set; } = Color.White * 0.6f;
|
||||
|
||||
public Color ItemQualityColorPoor { get; private set; } = Color.DarkRed;
|
||||
public Color ItemQualityColorNormal { get; private set; } = Color.Gray;
|
||||
public Color ItemQualityColorGood { get; private set; } = Color.LightGreen;
|
||||
public Color ItemQualityColorExcellent { get; private set; } = Color.LightBlue;
|
||||
public Color ItemQualityColorMasterwork { get; private set; } = Color.MediumPurple;
|
||||
|
||||
public Color ColorReputationVeryLow { get; private set; } = Color.Red;
|
||||
public Color ColorReputationLow { get; private set; } = Color.Orange;
|
||||
public Color ColorReputationNeutral { get; private set; } = Color.White * 0.8f;
|
||||
@@ -235,6 +250,9 @@ namespace Barotrauma
|
||||
case "uiglow":
|
||||
UIGlow = new UISprite(subElement);
|
||||
break;
|
||||
case "pingcircle":
|
||||
PingCircle = new UISprite(subElement);
|
||||
break;
|
||||
case "radiation":
|
||||
RadiationSprite = new UISprite(subElement);
|
||||
break;
|
||||
@@ -244,9 +262,18 @@ namespace Barotrauma
|
||||
case "uiglowcircular":
|
||||
UIGlowCircular = new UISprite(subElement);
|
||||
break;
|
||||
case "uiglowsolidcircular":
|
||||
UIGlowSolidCircular = new UISprite(subElement);
|
||||
break;
|
||||
case "uithermalglow":
|
||||
UIThermalGlow = new UISprite(subElement);
|
||||
break;
|
||||
case "endroundbuttonpulse":
|
||||
ButtonPulse = new UISprite(subElement);
|
||||
break;
|
||||
case "iconoverflowindicator":
|
||||
IconOverflowIndicator = new UISprite(subElement);
|
||||
break;
|
||||
case "focusindicator":
|
||||
FocusIndicator = new SpriteSheet(subElement);
|
||||
break;
|
||||
@@ -277,6 +304,10 @@ namespace Barotrauma
|
||||
DigitalFont = LoadFont(subElement, graphicsDevice);
|
||||
ForceFontUpperCase[DigitalFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||
break;
|
||||
case "monospacedfont":
|
||||
MonospacedFont = LoadFont(subElement, graphicsDevice);
|
||||
ForceFontUpperCase[MonospacedFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||
break;
|
||||
case "hotkeyfont":
|
||||
HotkeyFont = LoadFont(subElement, graphicsDevice);
|
||||
ForceFontUpperCase[HotkeyFont] = subElement.GetAttributeBool("forceuppercase", false);
|
||||
@@ -446,7 +477,7 @@ namespace Barotrauma
|
||||
|
||||
public void Apply(GUIComponent targetComponent, string styleName = "", GUIComponent parent = null)
|
||||
{
|
||||
GUIComponentStyle componentStyle = null;
|
||||
GUIComponentStyle componentStyle = null;
|
||||
if (parent != null)
|
||||
{
|
||||
GUIComponentStyle parentStyle = parent.Style;
|
||||
@@ -461,7 +492,7 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
string childStyleName = string.IsNullOrEmpty(styleName) ? targetComponent.GetType().Name : styleName;
|
||||
parentStyle.ChildStyles.TryGetValue(childStyleName.ToLowerInvariant(), out componentStyle);
|
||||
}
|
||||
@@ -477,8 +508,25 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
targetComponent.ApplyStyle(componentStyle);
|
||||
|
||||
targetComponent.ApplyStyle(componentStyle);
|
||||
}
|
||||
|
||||
public Color GetQualityColor(int quality)
|
||||
{
|
||||
switch (quality)
|
||||
{
|
||||
case 1:
|
||||
return ItemQualityColorGood;
|
||||
case 2:
|
||||
return ItemQualityColorExcellent;
|
||||
case 3:
|
||||
return ItemQualityColorMasterwork;
|
||||
case -1:
|
||||
return ItemQualityColorPoor;
|
||||
default:
|
||||
return ItemQualityColorNormal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ namespace Barotrauma
|
||||
if (GUI.MouseOn != null) { return false; }
|
||||
|
||||
//don't close when hovering over an inventory element
|
||||
if (Inventory.IsMouseOnInventory()) { return false; }
|
||||
if (Inventory.IsMouseOnInventory) { return false; }
|
||||
|
||||
bool input = PlayerInput.PrimaryMouseButtonDown() || PlayerInput.SecondaryMouseButtonClicked();
|
||||
return input && !rect.Contains(PlayerInput.MousePosition);
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace Barotrauma
|
||||
|
||||
private readonly object loadMutex = new object();
|
||||
private float? loadState;
|
||||
|
||||
|
||||
public float? LoadState
|
||||
{
|
||||
get
|
||||
@@ -90,8 +90,8 @@ namespace Barotrauma
|
||||
{
|
||||
return loadState;
|
||||
}
|
||||
}
|
||||
set
|
||||
}
|
||||
set
|
||||
{
|
||||
lock (loadMutex)
|
||||
{
|
||||
@@ -141,7 +141,7 @@ namespace Barotrauma
|
||||
GameMain.Config.EnableSplashScreen = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var titleStyle = GUI.Style?.GetComponentStyle("TitleText");
|
||||
Sprite titleSprite = null;
|
||||
if (!WaitForLanguageSelection && titleStyle != null && titleStyle.Sprites.ContainsKey(GUIComponent.ComponentState.None))
|
||||
@@ -177,8 +177,8 @@ namespace Barotrauma
|
||||
color: Color.White * noiseStrength * 0.1f,
|
||||
textureScale: Vector2.One * noiseScale);
|
||||
|
||||
titleSprite?.Draw(spriteBatch, new Vector2(GameMain.GraphicsWidth * 0.05f, GameMain.GraphicsHeight * 0.125f),
|
||||
Color.White, origin: new Vector2(0.0f, titleSprite.SourceRect.Height / 2.0f),
|
||||
titleSprite?.Draw(spriteBatch, new Vector2(GameMain.GraphicsWidth * 0.05f, GameMain.GraphicsHeight * 0.125f),
|
||||
Color.White, origin: new Vector2(0.0f, titleSprite.SourceRect.Height / 2.0f),
|
||||
scale: GameMain.GraphicsHeight / 2000.0f);
|
||||
|
||||
if (WaitForLanguageSelection)
|
||||
@@ -193,7 +193,7 @@ namespace Barotrauma
|
||||
if (LoadState == 100.0f)
|
||||
{
|
||||
#if DEBUG
|
||||
if (GameMain.Config.AutomaticQuickStartEnabled || GameMain.Config.AutomaticCampaignLoadEnabled && GameMain.FirstLoad)
|
||||
if (GameMain.Config.AutomaticQuickStartEnabled || GameMain.Config.AutomaticCampaignLoadEnabled || GameMain.Config.TestScreenEnabled && GameMain.FirstLoad)
|
||||
{
|
||||
loadText = "QUICKSTARTING ...";
|
||||
}
|
||||
@@ -211,6 +211,13 @@ namespace Barotrauma
|
||||
if (LoadState != null)
|
||||
{
|
||||
loadText += " " + (int)LoadState + " %";
|
||||
|
||||
#if DEBUG
|
||||
if (GameMain.FirstLoad && GameMain.CancelQuickStart)
|
||||
{
|
||||
loadText += " (Quickstart aborted)";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (GUI.LargeFont != null)
|
||||
@@ -265,7 +272,7 @@ namespace Barotrauma
|
||||
decorativeGraph.Draw(spriteBatch, (int)(decorativeGraph.FrameCount * noiseVal),
|
||||
new Vector2(GameMain.GraphicsWidth * 0.001f, GameMain.GraphicsHeight * 0.24f),
|
||||
Color.White, Vector2.Zero, 0.0f, decorativeScale, SpriteEffects.FlipVertically);
|
||||
|
||||
|
||||
decorativeMap.Draw(spriteBatch, (int)(decorativeMap.FrameCount * noiseVal),
|
||||
new Vector2(GameMain.GraphicsWidth * 0.99f, GameMain.GraphicsHeight * 0.66f),
|
||||
Color.White, decorativeMap.FrameSize.ToVector2(), 0.0f, decorativeScale);
|
||||
@@ -281,9 +288,9 @@ namespace Barotrauma
|
||||
}
|
||||
else if (noiseVal < 0.5f)
|
||||
{
|
||||
randText =
|
||||
Rand.Int(100).ToString().PadLeft(2, '0') + " " +
|
||||
Rand.Int(100).ToString().PadLeft(2, '0') + " " +
|
||||
randText =
|
||||
Rand.Int(100).ToString().PadLeft(2, '0') + " " +
|
||||
Rand.Int(100).ToString().PadLeft(2, '0') + " " +
|
||||
Rand.Int(100).ToString().PadLeft(2, '0') + " " +
|
||||
Rand.Int(100).ToString().PadLeft(2, '0');
|
||||
}
|
||||
@@ -299,12 +306,12 @@ namespace Barotrauma
|
||||
{
|
||||
if (languageSelectionFont == null)
|
||||
{
|
||||
languageSelectionFont = new ScalableFont("Content/Fonts/NotoSans/NotoSans-Bold.ttf",
|
||||
languageSelectionFont = new ScalableFont("Content/Fonts/NotoSans/NotoSans-Bold.ttf",
|
||||
(uint)(30 * (GameMain.GraphicsHeight / 1080.0f)), graphicsDevice);
|
||||
}
|
||||
if (languageSelectionFontCJK == null)
|
||||
{
|
||||
languageSelectionFontCJK = new ScalableFont("Content/Fonts/NotoSans/NotoSansCJKsc-Bold.otf",
|
||||
languageSelectionFontCJK = new ScalableFont("Content/Fonts/NotoSans/NotoSansCJKsc-Bold.otf",
|
||||
(uint)(30 * (GameMain.GraphicsHeight / 1080.0f)), graphicsDevice, dynamicLoading: true);
|
||||
}
|
||||
if (languageSelectionCursor == null)
|
||||
@@ -320,11 +327,11 @@ namespace Barotrauma
|
||||
var font = TextManager.IsCJK(localizedLanguageName) ? languageSelectionFontCJK : languageSelectionFont;
|
||||
|
||||
Vector2 textSize = font.MeasureString(localizedLanguageName);
|
||||
bool hover =
|
||||
Math.Abs(PlayerInput.MousePosition.X - textPos.X) < textSize.X / 2 &&
|
||||
bool hover =
|
||||
Math.Abs(PlayerInput.MousePosition.X - textPos.X) < textSize.X / 2 &&
|
||||
Math.Abs(PlayerInput.MousePosition.Y - textPos.Y) < textSpacing.Y / 2;
|
||||
|
||||
font.DrawString(spriteBatch, localizedLanguageName, textPos - textSize / 2,
|
||||
font.DrawString(spriteBatch, localizedLanguageName, textPos - textSize / 2,
|
||||
hover ? Color.White : Color.White * 0.6f);
|
||||
if (hover && PlayerInput.PrimaryMouseButtonClicked())
|
||||
{
|
||||
@@ -394,14 +401,14 @@ namespace Barotrauma
|
||||
LoadState = null;
|
||||
SetSelectedTip(TextManager.Get("LoadingScreenTip", true));
|
||||
currentBackgroundTexture = LocationType.List.GetRandom()?.GetPortrait(Rand.Int(int.MaxValue))?.Texture;
|
||||
|
||||
|
||||
while (!drawn)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
CoroutineManager.StartCoroutine(loader);
|
||||
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
while (CoroutineManager.IsCoroutineRunning(loader.ToString()))
|
||||
|
||||
@@ -55,14 +55,47 @@ namespace Barotrauma
|
||||
var texture = GetTexture(spriteBatch);
|
||||
|
||||
for (var i = 0; i < points.Count - 1; i++)
|
||||
DrawPolygonEdge(spriteBatch, texture, points[i] + offset, points[i + 1] + offset, color, thickness);
|
||||
DrawPolygonEdge(spriteBatch, points[i] + offset, points[i + 1] + offset, color, thickness);
|
||||
|
||||
DrawPolygonEdge(spriteBatch, texture, points[points.Count - 1] + offset, points[0] + offset, color,
|
||||
DrawPolygonEdge(spriteBatch, points[points.Count - 1] + offset, points[0] + offset, color,
|
||||
thickness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a closed polygon from an array of points
|
||||
/// </summary>
|
||||
public static void DrawPolygonInner(this SpriteBatch spriteBatch, Vector2 offset, IReadOnlyList<Vector2> points, Color color, float thickness = 1f)
|
||||
{
|
||||
if (points.Count == 0) { return; }
|
||||
|
||||
private static void DrawPolygonEdge(SpriteBatch spriteBatch, Texture2D texture, Vector2 point1, Vector2 point2,
|
||||
Color color, float thickness)
|
||||
if (points.Count == 1)
|
||||
{
|
||||
DrawPoint(spriteBatch, points[0], color, (int)thickness);
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < points.Count - 1; i++)
|
||||
{
|
||||
Vector2 point1 = points[i] + offset,
|
||||
point2 = points[i + 1] + offset;
|
||||
|
||||
DrawPolygonEdgeInner(spriteBatch, point1, point2, color, thickness);
|
||||
}
|
||||
|
||||
DrawPolygonEdgeInner(spriteBatch, points[^1] + offset, points[0] + offset, color, thickness);
|
||||
}
|
||||
|
||||
private static void DrawPolygonEdgeInner(SpriteBatch spriteBatch, Vector2 point1, Vector2 point2, Color color, float thickness)
|
||||
{
|
||||
var length = Vector2.Distance(point1, point2) + thickness;
|
||||
var angle = (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X);
|
||||
var scale = new Vector2(length, thickness);
|
||||
Vector2 middle = new Vector2((point1.X + point2.X) / 2f, (point1.Y + point2.Y) / 2f);
|
||||
Texture2D tex = GetTexture(spriteBatch);
|
||||
spriteBatch.Draw(GetTexture(spriteBatch), middle, null, color, angle, new Vector2(tex.Width / 2f, tex.Height / 2f), scale, SpriteEffects.None, 0);
|
||||
}
|
||||
|
||||
private static void DrawPolygonEdge(SpriteBatch spriteBatch, Vector2 point1, Vector2 point2, Color color, float thickness)
|
||||
{
|
||||
var length = Vector2.Distance(point1, point2);
|
||||
var angle = (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X);
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Barotrauma
|
||||
private Color storeSpecialColor;
|
||||
|
||||
private GUIListBox shoppingCrateBuyList, shoppingCrateSellList, shoppingCrateSellFromSubList;
|
||||
private GUITextBlock shoppingCrateTotal;
|
||||
private GUITextBlock relevantBalanceName, shoppingCrateTotal;
|
||||
private GUIButton clearAllButton, confirmButton;
|
||||
|
||||
private bool needsRefresh, needsBuyingRefresh, needsSellingRefresh, needsItemsToSellRefresh, needsSellingFromSubRefresh, needsItemsToSellFromSubRefresh;
|
||||
@@ -58,7 +58,6 @@ namespace Barotrauma
|
||||
StoreTab.SellFromSub => false,
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
private bool IsSelling => !IsBuying;
|
||||
private GUIListBox ActiveShoppingCrateList => activeTab switch
|
||||
{
|
||||
StoreTab.Buy => shoppingCrateBuyList,
|
||||
@@ -222,16 +221,8 @@ namespace Barotrauma
|
||||
TextScale = 1.1f,
|
||||
TextGetter = () =>
|
||||
{
|
||||
if (CurrentLocation != null)
|
||||
{
|
||||
merchantBalanceBlock.TextColor = CurrentLocation.BalanceColor;
|
||||
return GetCurrencyFormatted(CurrentLocation.StoreCurrentBalance);
|
||||
}
|
||||
else
|
||||
{
|
||||
merchantBalanceBlock.TextColor = Color.Red;
|
||||
return GetCurrencyFormatted(0);
|
||||
}
|
||||
merchantBalanceBlock.TextColor = CurrentLocation?.BalanceColor ?? Color.Red;
|
||||
return GetMerchantBalanceText();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -375,28 +366,37 @@ namespace Barotrauma
|
||||
//don't show categories with no buyable items
|
||||
itemCategories.RemoveAll(c => !ItemPrefab.Prefabs.Any(ep => ep.Category.HasFlag(c) && ep.CanBeBought));
|
||||
itemCategoryButtons.Clear();
|
||||
var categoryButton = new GUIButton(new RectTransform(new Point(categoryButtonContainer.Rect.Width, categoryButtonContainer.Rect.Width), categoryButtonContainer.RectTransform), style: "CategoryButton.All")
|
||||
{
|
||||
ToolTip = TextManager.Get("MapEntityCategory.All"),
|
||||
OnClicked = OnClickedCategoryButton
|
||||
};
|
||||
itemCategoryButtons.Add(categoryButton);
|
||||
foreach (MapEntityCategory category in itemCategories)
|
||||
{
|
||||
var categoryButton = new GUIButton(new RectTransform(new Point(categoryButtonContainer.Rect.Width, categoryButtonContainer.Rect.Width), categoryButtonContainer.RectTransform),
|
||||
categoryButton = new GUIButton(new RectTransform(new Point(categoryButtonContainer.Rect.Width, categoryButtonContainer.Rect.Width), categoryButtonContainer.RectTransform),
|
||||
style: "CategoryButton." + category)
|
||||
{
|
||||
ToolTip = TextManager.Get("MapEntityCategory." + category),
|
||||
UserData = category,
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
MapEntityCategory? newCategory = !btn.Selected ? (MapEntityCategory?)userdata : null;
|
||||
if (newCategory.HasValue) { searchBox.Text = ""; }
|
||||
if (newCategory != selectedItemCategory) { tabLists[activeTab].ScrollBar.BarScroll = 0f; }
|
||||
FilterStoreItems(newCategory, searchBox.Text);
|
||||
return true;
|
||||
}
|
||||
OnClicked = OnClickedCategoryButton
|
||||
};
|
||||
itemCategoryButtons.Add(categoryButton);
|
||||
categoryButton.RectTransform.SizeChanged += () =>
|
||||
}
|
||||
bool OnClickedCategoryButton(GUIButton button, object userData)
|
||||
{
|
||||
MapEntityCategory? newCategory = !button.Selected ? (MapEntityCategory?)userData : null;
|
||||
if (newCategory.HasValue) { searchBox.Text = ""; }
|
||||
if (newCategory != selectedItemCategory) { tabLists[activeTab].ScrollBar.BarScroll = 0f; }
|
||||
FilterStoreItems(newCategory, searchBox.Text);
|
||||
return true;
|
||||
}
|
||||
foreach (var btn in itemCategoryButtons)
|
||||
{
|
||||
btn.RectTransform.SizeChanged += () =>
|
||||
{
|
||||
var sprite = categoryButton.Frame.sprites[GUIComponent.ComponentState.None].First();
|
||||
categoryButton.RectTransform.NonScaledSize =
|
||||
new Point(categoryButton.Rect.Width, (int)(categoryButton.Rect.Width * ((float)sprite.Sprite.SourceRect.Height / sprite.Sprite.SourceRect.Width)));
|
||||
var sprite = btn.Frame.sprites[GUIComponent.ComponentState.None].First();
|
||||
btn.RectTransform.NonScaledSize = new Point(btn.Rect.Width, (int)(btn.Rect.Width * ((float)sprite.Sprite.SourceRect.Height / sprite.Sprite.SourceRect.Width)));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -503,11 +503,11 @@ namespace Barotrauma
|
||||
ForceUpperCase = true
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), playerBalanceContainer.RectTransform),
|
||||
"", font: GUI.SubHeadingFont, textAlignment: Alignment.TopRight)
|
||||
"", textColor: Color.White, font: GUI.SubHeadingFont, textAlignment: Alignment.TopRight)
|
||||
{
|
||||
AutoScaleVertical = true,
|
||||
TextScale = 1.1f,
|
||||
TextGetter = () => GetCurrencyFormatted(PlayerMoney)
|
||||
TextGetter = GetPlayerBalanceText
|
||||
};
|
||||
|
||||
// Divider ------------------------------------------------
|
||||
@@ -523,7 +523,7 @@ namespace Barotrauma
|
||||
RelativeSpacing = 0.015f,
|
||||
Stretch = true
|
||||
};
|
||||
var shoppingCrateListContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.85f), shoppingCrateInventoryContainer.RectTransform), style: null);
|
||||
var shoppingCrateListContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.8f), shoppingCrateInventoryContainer.RectTransform), style: null);
|
||||
shoppingCrateBuyList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
||||
shoppingCrateSellList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
||||
if (GameMain.IsSingleplayer)
|
||||
@@ -531,6 +531,21 @@ namespace Barotrauma
|
||||
shoppingCrateSellFromSubList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
||||
}
|
||||
|
||||
var relevantBalanceContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), shoppingCrateInventoryContainer.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
relevantBalanceName = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), relevantBalanceContainer.RectTransform), "", font: GUI.Font)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), relevantBalanceContainer.RectTransform), "", textColor: Color.White, font: GUI.SubHeadingFont, textAlignment: Alignment.Right)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
TextScale = 1.1f,
|
||||
TextGetter = () => IsBuying ? GetPlayerBalanceText() : GetMerchantBalanceText()
|
||||
};
|
||||
|
||||
var totalContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), shoppingCrateInventoryContainer.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true
|
||||
@@ -576,10 +591,14 @@ namespace Barotrauma
|
||||
resolutionWhenCreated = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
}
|
||||
|
||||
private GUILayoutGroup CreateDealsGroup(GUIListBox parentList)
|
||||
private string GetMerchantBalanceText() => GetCurrencyFormatted(CurrentLocation?.StoreCurrentBalance ?? 0);
|
||||
|
||||
private string GetPlayerBalanceText() => GetCurrencyFormatted(PlayerMoney);
|
||||
|
||||
private GUILayoutGroup CreateDealsGroup(GUIListBox parentList, int elementCount = 4)
|
||||
{
|
||||
var elementHeight = (int)(GUI.yScale * 80);
|
||||
var frame = new GUIFrame(new RectTransform(new Point(parentList.Content.Rect.Width, 4 * elementHeight + 3), parent: parentList.Content.RectTransform), style: null);
|
||||
var frame = new GUIFrame(new RectTransform(new Point(parentList.Content.Rect.Width, elementCount * elementHeight + 3), parent: parentList.Content.RectTransform), style: null);
|
||||
frame.UserData = "deals";
|
||||
var dealsGroup = new GUILayoutGroup(new RectTransform(Vector2.One, frame.RectTransform, anchor: Anchor.Center), childAnchor: Anchor.TopCenter);
|
||||
var dealsHeader = new GUILayoutGroup(new RectTransform(new Point((int)(0.95f * parentList.Content.Rect.Width), elementHeight), parent: dealsGroup.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
|
||||
@@ -604,17 +623,14 @@ namespace Barotrauma
|
||||
{
|
||||
prevLocation.Reputation.OnReputationValueChanged = null;
|
||||
}
|
||||
|
||||
foreach (ItemPrefab itemPrefab in ItemPrefab.Prefabs)
|
||||
if (ItemPrefab.Prefabs.Any(p => p.CanBeBoughtAtLocation(CurrentLocation, out PriceInfo _)))
|
||||
{
|
||||
if (itemPrefab.CanBeBoughtAtLocation(CurrentLocation, out PriceInfo _))
|
||||
selectedItemCategory = null;
|
||||
searchBox.Text = "";
|
||||
ChangeStoreTab(StoreTab.Buy);
|
||||
if (newLocation?.Reputation != null)
|
||||
{
|
||||
ChangeStoreTab(StoreTab.Buy);
|
||||
if (newLocation?.Reputation != null)
|
||||
{
|
||||
newLocation.Reputation.OnReputationValueChanged += () => { needsRefresh = true; };
|
||||
}
|
||||
return;
|
||||
newLocation.Reputation.OnReputationValueChanged += () => { needsRefresh = true; };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -628,6 +644,7 @@ namespace Barotrauma
|
||||
tabButton.Selected = (StoreTab)tabButton.UserData == activeTab;
|
||||
}
|
||||
sortingDropDown.SelectItem(tabSortingMethods[tab]);
|
||||
relevantBalanceName.Text = IsBuying ? TextManager.Get("campaignstore.balance") : TextManager.Get("campaignstore.storebalance");
|
||||
SetShoppingCrateTotalText();
|
||||
SetClearAllButtonStatus();
|
||||
SetConfirmButtonBehavior();
|
||||
@@ -697,7 +714,7 @@ namespace Barotrauma
|
||||
}
|
||||
foreach (GUIButton btn in itemCategoryButtons)
|
||||
{
|
||||
btn.Selected = category.HasValue && (MapEntityCategory)btn.UserData == selectedItemCategory;
|
||||
btn.Selected = (MapEntityCategory?)btn.UserData == selectedItemCategory;
|
||||
}
|
||||
list.UpdateScrollBarSize();
|
||||
}
|
||||
@@ -709,6 +726,8 @@ namespace Barotrauma
|
||||
FilterStoreItems(category, searchBox.Text);
|
||||
}
|
||||
|
||||
int prevDailySpecialCount;
|
||||
|
||||
private void RefreshStoreBuyList()
|
||||
{
|
||||
float prevBuyListScroll = storeBuyList.BarScroll;
|
||||
@@ -717,11 +736,14 @@ namespace Barotrauma
|
||||
bool hasPermissions = HasPermissions;
|
||||
HashSet<GUIComponent> existingItemFrames = new HashSet<GUIComponent>();
|
||||
|
||||
if ((storeDailySpecialsGroup != null) != CurrentLocation.DailySpecials.Any())
|
||||
int dailySpecialCount = CurrentLocation?.DailySpecials.Count() ?? 3;
|
||||
|
||||
if ((storeDailySpecialsGroup != null) != CurrentLocation.DailySpecials.Any() || dailySpecialCount != prevDailySpecialCount)
|
||||
{
|
||||
if (storeDailySpecialsGroup == null)
|
||||
if (storeDailySpecialsGroup == null || dailySpecialCount != prevDailySpecialCount)
|
||||
{
|
||||
storeDailySpecialsGroup = CreateDealsGroup(storeBuyList);
|
||||
storeBuyList.RemoveChild(storeDailySpecialsGroup?.Parent);
|
||||
storeDailySpecialsGroup = CreateDealsGroup(storeBuyList, 1 + dailySpecialCount);
|
||||
storeDailySpecialsGroup.Parent.SetAsFirstChild();
|
||||
}
|
||||
else
|
||||
@@ -730,6 +752,7 @@ namespace Barotrauma
|
||||
storeDailySpecialsGroup = null;
|
||||
}
|
||||
storeBuyList.RecalculateChildren();
|
||||
prevDailySpecialCount = dailySpecialCount;
|
||||
}
|
||||
|
||||
foreach (PurchasedItem item in CurrentLocation.StoreStock)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System.Linq;
|
||||
@@ -18,8 +19,8 @@ namespace Barotrauma
|
||||
private static UISprite spectateIcon, disconnectedIcon;
|
||||
private static Sprite ownerIcon, moderatorIcon;
|
||||
|
||||
private enum InfoFrameTab { Crew, Mission, Reputation, MyCharacter, Traitor, Submarine };
|
||||
private static InfoFrameTab selectedTab;
|
||||
public enum InfoFrameTab { Crew, Mission, Reputation, Traitor, Submarine, Talents };
|
||||
public static InfoFrameTab selectedTab;
|
||||
private GUIFrame infoFrame, contentFrame;
|
||||
|
||||
private readonly List<GUIButton> tabButtons = new List<GUIButton>();
|
||||
@@ -33,6 +34,8 @@ namespace Barotrauma
|
||||
private List<CharacterTeamType> teamIDs;
|
||||
private const string inLobbyString = "\u2022 \u2022 \u2022";
|
||||
|
||||
private GUIFrame pendingChangesFrame = null;
|
||||
|
||||
public static Color OwnCharacterBGColor = Color.Gold * 0.7f;
|
||||
|
||||
private class LinkedGUI
|
||||
@@ -48,7 +51,7 @@ namespace Barotrauma
|
||||
private readonly GUIFrame frame;
|
||||
|
||||
public LinkedGUI(Client client, GUIFrame frame, bool hasCharacter, GUITextBlock textBlock)
|
||||
{
|
||||
{
|
||||
this.client = client;
|
||||
this.textBlock = textBlock;
|
||||
this.frame = frame;
|
||||
@@ -125,7 +128,7 @@ namespace Barotrauma
|
||||
|
||||
public TabMenu()
|
||||
{
|
||||
if (!initialized) Initialize();
|
||||
if (!initialized) { Initialize(); }
|
||||
|
||||
CreateInfoFrame(selectedTab);
|
||||
SelectInfoFrameTab(null, selectedTab);
|
||||
@@ -133,6 +136,17 @@ namespace Barotrauma
|
||||
|
||||
public void Update()
|
||||
{
|
||||
GameSession.UpdateTalentNotificationIndicator(talentPointNotification);
|
||||
if (Character.Controlled is { } controlled && talentResetButton != null && talentApplyButton != null)
|
||||
{
|
||||
int talentCount = selectedTalents.Count - controlled.Info.GetUnlockedTalentsInTree().Count();
|
||||
talentResetButton.Enabled = talentApplyButton.Enabled = talentCount > 0;
|
||||
if (talentApplyButton.Enabled && talentApplyButton.FlashTimer <= 0.0f)
|
||||
{
|
||||
talentApplyButton.Flash(GUI.Style.Orange);
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedTab != InfoFrameTab.Crew) return;
|
||||
if (linkedGUIList == null) return;
|
||||
|
||||
@@ -182,16 +196,8 @@ namespace Barotrauma
|
||||
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, infoFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
|
||||
|
||||
//this used to be a switch expression but i changed it because it killed enc :(
|
||||
Vector2 contentFrameSize;
|
||||
switch (selectedTab)
|
||||
{
|
||||
case InfoFrameTab.MyCharacter:
|
||||
contentFrameSize = new Vector2(0.45f, 0.5f);
|
||||
break;
|
||||
default:
|
||||
contentFrameSize = new Vector2(0.45f, 0.667f);
|
||||
break;
|
||||
}
|
||||
//now it's not even a switch statement anymore :(
|
||||
Vector2 contentFrameSize = new Vector2(0.45f, 0.667f);
|
||||
contentFrame = new GUIFrame(new RectTransform(contentFrameSize, infoFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.12f) });
|
||||
|
||||
var horizontalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.958f, 0.943f), contentFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, GUI.IntScale(25f)) }, isHorizontal: true)
|
||||
@@ -242,6 +248,17 @@ namespace Barotrauma
|
||||
{
|
||||
TextGetter = () => TextManager.GetWithVariable("campaignmoney", "[money]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", campaignMode.Money))
|
||||
};
|
||||
GUIFrame bottomDisclaimerFrame = new GUIFrame(new RectTransform(new Vector2(contentFrameSize.X, 0.1f), infoFrame.RectTransform)
|
||||
{
|
||||
AbsoluteOffset = new Point(contentFrame.Rect.X, contentFrame.Rect.Bottom + GUI.IntScale(8))
|
||||
}, style: null);
|
||||
|
||||
pendingChangesFrame = new GUIFrame(new RectTransform(Vector2.One, bottomDisclaimerFrame.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
if (GameMain.NetLobbyScreen?.CampaignCharacterDiscarded ?? false)
|
||||
{
|
||||
NetLobbyScreen.CreateChangesPendingFrame(pendingChangesFrame);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -254,10 +271,17 @@ namespace Barotrauma
|
||||
|
||||
var submarineButton = createTabButton(InfoFrameTab.Submarine, "submarine");
|
||||
|
||||
if (GameMain.NetworkMember != null)
|
||||
var talentsButton = createTabButton(InfoFrameTab.Talents, "tabmenu.character");
|
||||
talentsButton.OnAddedToGUIUpdateList += (component) =>
|
||||
{
|
||||
var myCharacterButton = createTabButton(InfoFrameTab.MyCharacter, "tabmenu.character");
|
||||
}
|
||||
talentsButton.Enabled = Character.Controlled?.Info != null;
|
||||
if (!talentsButton.Enabled && selectedTab == InfoFrameTab.Talents)
|
||||
{
|
||||
SelectInfoFrameTab(null, InfoFrameTab.Crew);
|
||||
}
|
||||
};
|
||||
|
||||
talentPointNotification = GameSession.CreateTalentIconNotification(talentsButton);
|
||||
}
|
||||
|
||||
private bool SelectInfoFrameTab(GUIButton button, object userData)
|
||||
@@ -289,13 +313,12 @@ namespace Barotrauma
|
||||
if (traitor == null || traitorMission == null) return false;
|
||||
CreateTraitorInfo(infoFrameHolder, traitorMission, traitor);
|
||||
break;
|
||||
case InfoFrameTab.MyCharacter:
|
||||
if (GameMain.NetworkMember == null) { return false; }
|
||||
GameMain.NetLobbyScreen.CreatePlayerFrame(infoFrameHolder);
|
||||
break;
|
||||
case InfoFrameTab.Submarine:
|
||||
CreateSubmarineInfo(infoFrameHolder, Submarine.MainSub);
|
||||
break;
|
||||
case InfoFrameTab.Talents:
|
||||
CreateTalentInfo(infoFrameHolder);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -408,7 +431,7 @@ namespace Barotrauma
|
||||
if (GameMain.IsMultiplayer)
|
||||
{
|
||||
CreateMultiPlayerList(false);
|
||||
CreateMultiPlayerLogContent(crewFrame);
|
||||
CreateMultiPlayerLogContent(crewFrame);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -599,7 +622,7 @@ namespace Barotrauma
|
||||
AbsoluteSpacing = 2
|
||||
};
|
||||
|
||||
new GUICustomComponent(new RectTransform(new Point(jobColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform, Anchor.Center),
|
||||
new GUICustomComponent(new RectTransform(new Point(jobColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform, Anchor.Center),
|
||||
onDraw: (sb, component) => DrawNotInGameIcon(sb, component.Rect, client))
|
||||
{
|
||||
CanBeFocused = false,
|
||||
@@ -828,7 +851,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
private static readonly List<Pair<string, PlayerConnectionChangeType>> storedMessages = new List<Pair<string, PlayerConnectionChangeType>>();
|
||||
|
||||
|
||||
public static void StorePlayerConnectionChangeMessage(ChatMessage message)
|
||||
{
|
||||
if (!GameMain.GameSession?.IsRunning ?? true) { return; }
|
||||
@@ -841,7 +864,7 @@ namespace Barotrauma
|
||||
TabMenu instance = GameSession.TabMenuInstance;
|
||||
instance.AddLineToLog(msg, message.ChangeType);
|
||||
instance.RemoveCurrentElements();
|
||||
instance.CreateMultiPlayerList(true);
|
||||
instance.CreateMultiPlayerList(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -960,7 +983,7 @@ namespace Barotrauma
|
||||
GUIFrame missionDescriptionHolder = new GUIFrame(new RectTransform(Vector2.One, missionList.Content.RectTransform), style: null);
|
||||
GUILayoutGroup missionTextGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.744f, 0f), missionDescriptionHolder.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(iconSize + spacing, 0) }, false, childAnchor: Anchor.TopLeft)
|
||||
{
|
||||
AbsoluteSpacing = spacing
|
||||
AbsoluteSpacing = spacing
|
||||
};
|
||||
string descriptionText = mission.Description;
|
||||
foreach (string missionMessage in mission.ShownMessages)
|
||||
@@ -988,7 +1011,7 @@ namespace Barotrauma
|
||||
float ySize = missionNameSize.Y + missionDescriptionSize.Y + missionRewardSize.Y + missionReputationSize.Y + missionTextGroup.AbsoluteSpacing * 4;
|
||||
bool displayDifficulty = mission.Difficulty.HasValue;
|
||||
if (displayDifficulty) { ySize += missionRewardSize.Y; }
|
||||
|
||||
|
||||
missionDescriptionHolder.RectTransform.NonScaledSize = new Point(missionDescriptionHolder.RectTransform.NonScaledSize.X, (int)ySize);
|
||||
missionTextGroup.RectTransform.NonScaledSize = new Point(missionTextGroup.RectTransform.NonScaledSize.X, missionDescriptionHolder.RectTransform.NonScaledSize.Y);
|
||||
|
||||
@@ -999,8 +1022,8 @@ namespace Barotrauma
|
||||
int iconHeight = Math.Max(missionTextGroup.RectTransform.NonScaledSize.Y, (int)(iconWidth * iconAspectRatio));
|
||||
Point iconSize = new Point(iconWidth, iconHeight);*/
|
||||
|
||||
new GUIImage(new RectTransform(new Point(iconSize), missionDescriptionHolder.RectTransform), mission.Prefab.Icon, null, true)
|
||||
{
|
||||
new GUIImage(new RectTransform(new Point(iconSize), missionDescriptionHolder.RectTransform), mission.Prefab.Icon, null, true)
|
||||
{
|
||||
Color = mission.Prefab.IconColor,
|
||||
HoverColor = mission.Prefab.IconColor,
|
||||
SelectedColor = mission.Prefab.IconColor,
|
||||
@@ -1159,5 +1182,506 @@ namespace Barotrauma
|
||||
sub.Info.CreateSpecsWindow(specsListBox, GUI.Font, includeTitle: false, includeClass: false, includeDescription: true);
|
||||
}
|
||||
}
|
||||
private Color unselectedColor = new Color(240, 255, 255, 225);
|
||||
private Color selectedColor = new Color(220, 255, 220, 225);
|
||||
private Color ownedColor = new Color(140, 180, 140, 225);
|
||||
private Color unselectableColor = new Color(100, 100, 100, 225);
|
||||
private Color pressedColor = new Color(60, 60, 60, 225);
|
||||
|
||||
private readonly List<(GUIButton button, GUIComponent icon)> talentButtons = new List<(GUIButton button, GUIComponent icon)>();
|
||||
private readonly List<(string talentTree, int index, GUIImage icon, GUIFrame background, GUIFrame backgroundGlow)> talentCornerIcons = new List<(string talentTree, int index, GUIImage icon, GUIFrame background, GUIFrame backgroundGlow)>();
|
||||
private List<string> selectedTalents = new List<string>();
|
||||
|
||||
private GUITextBlock experienceText;
|
||||
private GUIProgressBar experienceBar;
|
||||
private GUITextBlock talentPointText;
|
||||
private GUIListBox skillListBox;
|
||||
|
||||
private GUIButton talentApplyButton,
|
||||
talentResetButton;
|
||||
|
||||
private GUIImage talentPointNotification;
|
||||
|
||||
private readonly ImmutableDictionary<TalentTree.TalentTreeStageState, GUIComponentStyle> talentStageStyles = new Dictionary<TalentTree.TalentTreeStageState, GUIComponentStyle>
|
||||
{
|
||||
{ TalentTree.TalentTreeStageState.Invalid, GUI.Style.GetComponentStyle("TalentTreeLocked") },
|
||||
{ TalentTree.TalentTreeStageState.Locked, GUI.Style.GetComponentStyle("TalentTreeLocked") },
|
||||
{ TalentTree.TalentTreeStageState.Unlocked, GUI.Style.GetComponentStyle("TalentTreePurchased") },
|
||||
{ TalentTree.TalentTreeStageState.Available, GUI.Style.GetComponentStyle("TalentTreeUnlocked") },
|
||||
{ TalentTree.TalentTreeStageState.Highlighted, GUI.Style.GetComponentStyle("TalentTreeAvailable") },
|
||||
}.ToImmutableDictionary();
|
||||
|
||||
private readonly ImmutableDictionary<TalentTree.TalentTreeStageState, Color> talentStageBackgroundColors = new Dictionary<TalentTree.TalentTreeStageState, Color>
|
||||
{
|
||||
{ TalentTree.TalentTreeStageState.Invalid, new Color(48,48,48,255) },
|
||||
{ TalentTree.TalentTreeStageState.Locked, new Color(48,48,48,255) },
|
||||
{ TalentTree.TalentTreeStageState.Unlocked, new Color(24,37,31,255) },
|
||||
{ TalentTree.TalentTreeStageState.Available, new Color(50,47,33,255) },
|
||||
{ TalentTree.TalentTreeStageState.Highlighted, new Color(50,47,33,255) },
|
||||
}.ToImmutableDictionary();
|
||||
|
||||
private void CreateTalentInfo(GUIFrame infoFrame)
|
||||
{
|
||||
infoFrame.ClearChildren();
|
||||
talentButtons.Clear();
|
||||
talentCornerIcons.Clear();
|
||||
|
||||
Character controlledCharacter = Character.Controlled;
|
||||
if (controlledCharacter == null) { return; }
|
||||
|
||||
GUIFrame talentFrameBackground = new GUIFrame(new RectTransform(Vector2.One, infoFrame.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox");
|
||||
int padding = GUI.IntScale(15);
|
||||
GUIFrame talentFrameContent = new GUIFrame(new RectTransform(new Point(talentFrameBackground.Rect.Width - padding, talentFrameBackground.Rect.Height - padding), infoFrame.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
GUIFrame paddedTalentFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.9f), talentFrameContent.RectTransform, Anchor.Center), style: null);
|
||||
|
||||
GUIFrame talentFrameMain = new GUIFrame(new RectTransform(Vector2.One, paddedTalentFrame.RectTransform), style: null);
|
||||
|
||||
GUIFrame characterSettingsFrame = null;
|
||||
GUILayoutGroup characterLayout = null;
|
||||
if (!(GameMain.NetworkMember is null))
|
||||
{
|
||||
characterSettingsFrame = new GUIFrame(new RectTransform(Vector2.One, talentFrameContent.RectTransform), style: null) { Visible = false };
|
||||
characterLayout = new GUILayoutGroup(new RectTransform(Vector2.One, characterSettingsFrame.RectTransform));
|
||||
GUIFrame containerFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.9f), characterLayout.RectTransform), style: null);
|
||||
GUIFrame playerFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.7f), containerFrame.RectTransform, Anchor.Center), style: null);
|
||||
GameMain.NetLobbyScreen.CreatePlayerFrame(playerFrame, alwaysAllowEditing: true, createPendingText: false);
|
||||
}
|
||||
|
||||
if (controlledCharacter.Info is null)
|
||||
{
|
||||
DebugConsole.ThrowError("No character info found for talent UI");
|
||||
return;
|
||||
}
|
||||
|
||||
selectedTalents = controlledCharacter.Info.GetUnlockedTalentsInTree().ToList();
|
||||
|
||||
GUILayoutGroup talentFrameLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), talentFrameMain.RectTransform, anchor: Anchor.Center), childAnchor: Anchor.TopCenter)
|
||||
{
|
||||
AbsoluteSpacing = GUI.IntScale(5)
|
||||
};
|
||||
|
||||
GUILayoutGroup talentInfoLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), talentFrameLayoutGroup.RectTransform, Anchor.Center), isHorizontal: true);
|
||||
|
||||
CharacterInfo info = controlledCharacter.Info;
|
||||
Job job = info.Job;
|
||||
|
||||
new GUICustomComponent(new RectTransform(new Vector2(0.25f, 1f), talentInfoLayoutGroup.RectTransform), onDraw: (batch, component) =>
|
||||
{
|
||||
float posY = component.Rect.Center.Y - component.Rect.Width / 2;
|
||||
info.DrawPortrait(batch, new Vector2(component.Rect.X, posY), Vector2.Zero, component.Rect.Width, false, false);
|
||||
});
|
||||
|
||||
GUILayoutGroup nameLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 1f), talentInfoLayoutGroup.RectTransform)) { RelativeSpacing = 0.05f };
|
||||
|
||||
Vector2 nameSize = GUI.SubHeadingFont.MeasureString(info.Name);
|
||||
GUITextBlock nameBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), info.Name, font: GUI.SubHeadingFont) { TextColor = job.Prefab.UIColor };
|
||||
nameBlock.RectTransform.NonScaledSize = nameSize.Pad(nameBlock.Padding).ToPoint();
|
||||
|
||||
Vector2 jobSize = GUI.SmallFont.MeasureString(job.Name);
|
||||
GUITextBlock jobBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), job.Name, font: GUI.SmallFont) { TextColor = job.Prefab.UIColor };
|
||||
jobBlock.RectTransform.NonScaledSize = jobSize.Pad(jobBlock.Padding).ToPoint();
|
||||
|
||||
string traitString = TextManager.AddPunctuation(':', TextManager.Get("PersonalityTrait"), TextManager.Get("personalitytrait." + info.PersonalityTrait.Name.Replace(" ", "")));
|
||||
Vector2 traitSize = GUI.SmallFont.MeasureString(traitString);
|
||||
GUITextBlock traitBlock = new GUITextBlock(new RectTransform(Vector2.One, nameLayout.RectTransform), traitString, font: GUI.SmallFont);
|
||||
traitBlock.RectTransform.NonScaledSize = traitSize.Pad(traitBlock.Padding).ToPoint();
|
||||
|
||||
GUIFrame endocrineFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.35f), nameLayout.RectTransform, Anchor.BottomCenter), style: null);
|
||||
|
||||
if (!(GameMain.NetworkMember is null))
|
||||
{
|
||||
GUIButton newCharacterBox = new GUIButton(new RectTransform(new Vector2(0.675f, 1f), endocrineFrame.RectTransform, Anchor.TopLeft), text: GameMain.NetLobbyScreen.CampaignCharacterDiscarded ? TextManager.Get("settings") : TextManager.Get("createnew"))
|
||||
{
|
||||
IgnoreLayoutGroups = true
|
||||
};
|
||||
|
||||
newCharacterBox.OnClicked = (button, o) =>
|
||||
{
|
||||
if (!GameMain.NetLobbyScreen.CampaignCharacterDiscarded)
|
||||
{
|
||||
GameMain.NetLobbyScreen.TryDiscardCampaignCharacter(() =>
|
||||
{
|
||||
newCharacterBox.Text = TextManager.Get("settings");
|
||||
|
||||
if (pendingChangesFrame != null)
|
||||
{
|
||||
NetLobbyScreen.CreateChangesPendingFrame(pendingChangesFrame);
|
||||
}
|
||||
OpenMenu();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
OpenMenu();
|
||||
return true;
|
||||
|
||||
void OpenMenu()
|
||||
{
|
||||
characterSettingsFrame!.Visible = true;
|
||||
talentFrameMain.Visible = false;
|
||||
}
|
||||
};
|
||||
|
||||
if (!(characterLayout is null))
|
||||
{
|
||||
GUILayoutGroup characterCloseButtonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.1f), characterLayout.RectTransform), childAnchor: Anchor.BottomRight);
|
||||
new GUIButton(new RectTransform(new Vector2(0.4f, 1f), characterCloseButtonLayout.RectTransform), TextManager.Get("ApplySettingsButton")) //TODO: Is this text appropriate for this circumstance for all languages?
|
||||
{
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
characterSettingsFrame!.Visible = false;
|
||||
talentFrameMain.Visible = true;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerable<TalentPrefab> endocrineTalents = info.GetEndocrineTalents().Select(e => TalentPrefab.TalentPrefabs.Find(c => c.Identifier.Equals(e, StringComparison.OrdinalIgnoreCase)));
|
||||
|
||||
if (endocrineTalents.Count() > 0)
|
||||
{
|
||||
GUIImage endocrineIcon = new GUIImage(new RectTransform(new Vector2(0.275f, 1f), endocrineFrame.RectTransform, anchor: Anchor.TopRight, scaleBasis: ScaleBasis.Normal), style: "EndocrineReminderIcon")
|
||||
{
|
||||
ToolTip = $"{TextManager.Get("afflictionname.endocrineboost")}\n\n{string.Join(", ", endocrineTalents.Select(e => e.DisplayName))}"
|
||||
};
|
||||
}
|
||||
|
||||
GUILayoutGroup skillLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 1f), talentInfoLayoutGroup.RectTransform)) { Stretch = true };
|
||||
|
||||
string skillString = TextManager.Get("skills");
|
||||
Vector2 skillSize = GUI.SubHeadingFont.MeasureString(skillString);
|
||||
GUITextBlock skillBlock = new GUITextBlock(new RectTransform(Vector2.One, skillLayout.RectTransform), skillString, font: GUI.SubHeadingFont);
|
||||
skillBlock.RectTransform.NonScaledSize = skillSize.Pad(skillBlock.Padding).ToPoint();
|
||||
|
||||
skillListBox = new GUIListBox(new RectTransform(new Vector2(1f, 1f - skillBlock.RectTransform.RelativeSize.Y), skillLayout.RectTransform), style: null);
|
||||
CreateTalentSkillList(controlledCharacter, skillListBox);
|
||||
|
||||
if (!TalentTree.JobTalentTrees.TryGetValue(controlledCharacter.Info.Job.Prefab.Identifier, out TalentTree talentTree)) { return; }
|
||||
|
||||
new GUIFrame(new RectTransform(new Vector2(1f, 1f), talentFrameLayoutGroup.RectTransform), style: "HorizontalLine");
|
||||
|
||||
GUIListBox talentTreeListBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.7f), talentFrameLayoutGroup.RectTransform, Anchor.TopCenter), isHorizontal: true, style: null);
|
||||
|
||||
List<GUITextBlock> subTreeNames = new List<GUITextBlock>();
|
||||
foreach (var subTree in talentTree.TalentSubTrees)
|
||||
{
|
||||
GUIFrame subTreeFrame = new GUIFrame(new RectTransform(new Vector2(0.333f, 1f), talentTreeListBox.Content.RectTransform, anchor: Anchor.TopLeft), style: null);
|
||||
GUILayoutGroup subTreeLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1f, 1f), subTreeFrame.RectTransform, Anchor.Center), false, childAnchor: Anchor.TopCenter);
|
||||
|
||||
GUIFrame subtreeTitleFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.111f), subTreeLayoutGroup.RectTransform, anchor: Anchor.TopCenter), style: null);
|
||||
int elementPadding = GUI.IntScale(8);
|
||||
Point headerSize = subtreeTitleFrame.RectTransform.NonScaledSize;
|
||||
GUIFrame subTreeTitleBackground = new GUIFrame(new RectTransform(new Point(headerSize.X - elementPadding, headerSize.Y), subtreeTitleFrame.RectTransform, anchor: Anchor.Center), style: "SubtreeHeader");
|
||||
subTreeNames.Add(new GUITextBlock(new RectTransform(Vector2.One, subTreeTitleBackground.RectTransform, anchor: Anchor.TopCenter), subTree.DisplayName, font: GUI.SubHeadingFont, textAlignment: Alignment.Center));
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
GUIFrame talentOptionFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.222f), subTreeLayoutGroup.RectTransform, anchor: Anchor.TopCenter), style: null);
|
||||
|
||||
Point talentFrameSize = talentOptionFrame.RectTransform.NonScaledSize;
|
||||
|
||||
GUIFrame talentBackground = new GUIFrame(new RectTransform(new Point(talentFrameSize.X - elementPadding, talentFrameSize.Y - elementPadding), talentOptionFrame.RectTransform, anchor: Anchor.Center), style: "TalentBackground");
|
||||
GUIFrame talentBackgroundHighlight = new GUIFrame(new RectTransform(Vector2.One, talentBackground.RectTransform, anchor: Anchor.Center), style: "TalentBackgroundGlow") { Visible = false };
|
||||
|
||||
GUIImage cornerIcon = new GUIImage(new RectTransform(new Vector2(0.2f), talentOptionFrame.RectTransform, anchor: Anchor.BottomRight, scaleBasis: ScaleBasis.BothHeight) { MaxSize = new Point(16) }, style: null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
Point iconSize = cornerIcon.RectTransform.NonScaledSize;
|
||||
cornerIcon.RectTransform.AbsoluteOffset = new Point(iconSize.X / 2, iconSize.Y / 2);
|
||||
|
||||
if (subTree.TalentOptionStages.Count > i)
|
||||
{
|
||||
TalentOption talentOption = subTree.TalentOptionStages[i];
|
||||
|
||||
GUILayoutGroup talentOptionCenterGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 0.7f), talentOptionFrame.RectTransform, Anchor.Center), childAnchor: Anchor.CenterLeft);
|
||||
|
||||
GUILayoutGroup talentOptionLayoutGroup = new GUILayoutGroup(new RectTransform(Vector2.One, talentOptionCenterGroup.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true };
|
||||
|
||||
foreach (TalentPrefab talent in talentOption.Talents)
|
||||
{
|
||||
GUIFrame talentFrame = new GUIFrame(new RectTransform(Vector2.One, talentOptionLayoutGroup.RectTransform), style: null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
GUIFrame croppedTalentFrame = new GUIFrame(new RectTransform(Vector2.One, talentFrame.RectTransform, anchor: Anchor.Center, scaleBasis: ScaleBasis.BothHeight), style: null);
|
||||
|
||||
GUIButton talentButton = new GUIButton(new RectTransform(Vector2.One, croppedTalentFrame.RectTransform, anchor: Anchor.Center), style: null)
|
||||
{
|
||||
ToolTip = $"{talent.DisplayName}\n\n{talent.Description}",
|
||||
UserData = talent.Identifier,
|
||||
PressedColor = pressedColor,
|
||||
OnClicked = (button, userData) =>
|
||||
{
|
||||
// deselect other buttons in tier by removing their selected talents from pool
|
||||
foreach (GUIButton guiButton in talentOptionLayoutGroup.GetAllChildren<GUIButton>())
|
||||
{
|
||||
if (guiButton.UserData is string otherTalentIdentifier && guiButton != button)
|
||||
{
|
||||
if (!controlledCharacter.HasTalent(otherTalentIdentifier))
|
||||
{
|
||||
selectedTalents.Remove(otherTalentIdentifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
string talentIdentifier = userData as string;
|
||||
|
||||
if (TalentTree.IsViableTalentForCharacter(controlledCharacter, talentIdentifier, selectedTalents))
|
||||
{
|
||||
if (!selectedTalents.Contains(talentIdentifier))
|
||||
{
|
||||
selectedTalents.Add(talentIdentifier);
|
||||
}
|
||||
}
|
||||
else if (!controlledCharacter.HasTalent(talentIdentifier))
|
||||
{
|
||||
selectedTalents.Remove(talentIdentifier);
|
||||
}
|
||||
|
||||
UpdateTalentButtons();
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
talentButton.Color = talentButton.HoverColor = talentButton.PressedColor = talentButton.SelectedColor = Color.Transparent;
|
||||
|
||||
GUIComponent iconImage;
|
||||
if (talent.Icon is null)
|
||||
{
|
||||
iconImage = new GUITextBlock(new RectTransform(Vector2.One, talentButton.RectTransform, anchor: Anchor.Center), text: "???", font: GUI.LargeFont, textAlignment: Alignment.Center, style: null)
|
||||
{
|
||||
OutlineColor = GUI.Style.Red,
|
||||
TextColor = GUI.Style.Red,
|
||||
PressedColor = unselectableColor,
|
||||
CanBeFocused = false,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
iconImage = new GUIImage(new RectTransform(Vector2.One, talentButton.RectTransform, anchor: Anchor.Center), sprite: talent.Icon, scaleToFit: true)
|
||||
{
|
||||
PressedColor = unselectableColor,
|
||||
CanBeFocused = false,
|
||||
};
|
||||
}
|
||||
|
||||
talentButtons.Add((talentButton, iconImage));
|
||||
}
|
||||
|
||||
talentCornerIcons.Add((subTree.Identifier, i, cornerIcon, talentBackground, talentBackgroundHighlight));
|
||||
}
|
||||
}
|
||||
}
|
||||
GUITextBlock.AutoScaleAndNormalize(subTreeNames);
|
||||
|
||||
GUILayoutGroup talentBottomFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.07f), talentFrameLayoutGroup.RectTransform, Anchor.TopCenter), isHorizontal: true) { RelativeSpacing = 0.01f };
|
||||
|
||||
GUILayoutGroup experienceLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.59f, 1f), talentBottomFrame.RectTransform));
|
||||
GUIFrame experienceBarFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.5f), experienceLayout.RectTransform), style: null);
|
||||
|
||||
experienceBar = new GUIProgressBar(new RectTransform(new Vector2(1f, 1f), experienceBarFrame.RectTransform, Anchor.CenterLeft),
|
||||
barSize: controlledCharacter.Info.GetProgressTowardsNextLevel(), color: GUI.Style.Green)
|
||||
{
|
||||
IsHorizontal = true
|
||||
};
|
||||
|
||||
experienceText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), experienceBarFrame.RectTransform, anchor: Anchor.Center), "", font: GUI.Font, textAlignment: Alignment.CenterRight)
|
||||
{
|
||||
Shadow = true
|
||||
};
|
||||
|
||||
talentPointText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), experienceLayout.RectTransform, anchor: Anchor.Center), "", font: GUI.SubHeadingFont, parseRichText: true, textAlignment: Alignment.CenterRight) { AutoScaleVertical = true };
|
||||
|
||||
talentResetButton = new GUIButton(new RectTransform(new Vector2(0.19f, 1f), talentBottomFrame.RectTransform), text: TextManager.Get("reset"), style: "GUIButtonFreeScale")
|
||||
{
|
||||
OnClicked = ResetTalentSelection
|
||||
};
|
||||
talentApplyButton = new GUIButton(new RectTransform(new Vector2(0.19f, 1f), talentBottomFrame.RectTransform), text: TextManager.Get("applysettingsbutton"), style: "GUIButtonFreeScale")
|
||||
{
|
||||
OnClicked = ApplyTalentSelection,
|
||||
};
|
||||
GUITextBlock.AutoScaleAndNormalize(talentResetButton.TextBlock, talentApplyButton.TextBlock);
|
||||
|
||||
UpdateTalentButtons();
|
||||
}
|
||||
|
||||
private void CreateTalentSkillList(Character character, GUIListBox parent)
|
||||
{
|
||||
parent.Content.ClearChildren();
|
||||
List<GUITextBlock> skillNames = new List<GUITextBlock>();
|
||||
foreach (Skill skill in character.Info.Job.Skills)
|
||||
{
|
||||
GUILayoutGroup skillContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.2f), parent.Content.RectTransform), isHorizontal: true) { CanBeFocused = false };
|
||||
|
||||
skillNames.Add(new GUITextBlock(new RectTransform(new Vector2(0.7f, 1f), skillContainer.RectTransform), TextManager.Get($"skillname.{skill.Identifier}", returnNull: true) ?? skill.Identifier));
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), skillContainer.RectTransform), Math.Floor(skill.Level).ToString("F0"), textAlignment: Alignment.CenterRight) { Padding = new Vector4(0, 0, 4, 0) };
|
||||
|
||||
float modifiedSkillLevel = character.GetSkillLevel(skill.Identifier);
|
||||
if (!MathUtils.NearlyEqual(MathF.Floor(modifiedSkillLevel), MathF.Floor(skill.Level)))
|
||||
{
|
||||
int skillChange = (int)MathF.Floor(modifiedSkillLevel - skill.Level);
|
||||
string stringColor = true switch
|
||||
{
|
||||
true when skillChange > 0 => XMLExtensions.ColorToString(GUI.Style.Green),
|
||||
true when skillChange < 0 => XMLExtensions.ColorToString(GUI.Style.Red),
|
||||
_ => XMLExtensions.ColorToString(GUI.Style.TextColor)
|
||||
};
|
||||
|
||||
string changeText = $"(‖color:{stringColor}‖{(skillChange > 0 ? "+" : string.Empty) + skillChange}‖color:end‖)";
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), skillContainer.RectTransform), changeText, parseRichText: true) { Padding = Vector4.Zero };
|
||||
}
|
||||
skillContainer.Recalculate();
|
||||
}
|
||||
|
||||
parent.RecalculateChildren();
|
||||
GUITextBlock.AutoScaleAndNormalize(skillNames);
|
||||
}
|
||||
|
||||
private void UpdateTalentButtons()
|
||||
{
|
||||
Character controlledCharacter = Character.Controlled;
|
||||
|
||||
experienceText.Text = $"{controlledCharacter.Info.ExperiencePoints - controlledCharacter.Info.GetExperienceRequiredForCurrentLevel()} / {controlledCharacter.Info.GetExperienceRequiredToLevelUp() - controlledCharacter.Info.GetExperienceRequiredForCurrentLevel()}";
|
||||
experienceBar.BarSize = controlledCharacter.Info.GetProgressTowardsNextLevel();
|
||||
//experienceBar.ToolTip = $"{controlledCharacter.Info.ExperiencePoints - controlledCharacter.Info.GetExperienceRequiredForCurrentLevel()} / {controlledCharacter.Info.GetExperienceRequiredToLevelUp() - controlledCharacter.Info.GetExperienceRequiredForCurrentLevel()}";
|
||||
|
||||
selectedTalents = TalentTree.CheckTalentSelection(controlledCharacter, selectedTalents);
|
||||
|
||||
string pointsLeft = controlledCharacter.Info.GetAvailableTalentPoints().ToString();
|
||||
|
||||
int talentCount = selectedTalents.Count - controlledCharacter.Info.GetUnlockedTalentsInTree().Count();
|
||||
|
||||
if (talentCount > 0)
|
||||
{
|
||||
string pointsUsed = $"‖color:{XMLExtensions.ColorToString(GUI.Style.Red)}‖{-talentCount}‖color:end‖";
|
||||
string localizedString = TextManager.GetWithVariables("talentmenu.points.spending", new []{ "[amount]", "[used]" }, new []{ pointsLeft, pointsUsed});
|
||||
talentPointText.SetRichText(localizedString);
|
||||
}
|
||||
else
|
||||
{
|
||||
talentPointText.SetRichText(TextManager.GetWithVariable("talentmenu.points", "[amount]", pointsLeft));
|
||||
}
|
||||
|
||||
foreach (var (talentTree, index, icon, frame, glow) in talentCornerIcons)
|
||||
{
|
||||
TalentTree.TalentTreeStageState state = TalentTree.GetTalentOptionStageState(controlledCharacter, talentTree, index, selectedTalents);
|
||||
GUIComponentStyle newStyle = talentStageStyles[state];
|
||||
icon.ApplyStyle(newStyle);
|
||||
icon.Color = newStyle.Color;
|
||||
frame.Color = talentStageBackgroundColors[state];
|
||||
glow.Visible = state == TalentTree.TalentTreeStageState.Highlighted;
|
||||
}
|
||||
|
||||
foreach (var talentButton in talentButtons)
|
||||
{
|
||||
string talentIdentifier = talentButton.button.UserData as string;
|
||||
bool unselectable = !TalentTree.IsViableTalentForCharacter(controlledCharacter, talentIdentifier, selectedTalents) || controlledCharacter.HasTalent(talentIdentifier);
|
||||
Color newTalentColor = unselectable ? unselectableColor : unselectedColor;
|
||||
Color hoverColor = Color.White;
|
||||
|
||||
if (controlledCharacter.HasTalent(talentIdentifier))
|
||||
{
|
||||
newTalentColor = GUI.Style.Green;
|
||||
}
|
||||
else if (selectedTalents.Contains(talentIdentifier))
|
||||
{
|
||||
newTalentColor = GUI.Style.Orange;
|
||||
hoverColor = Color.Lerp(GUI.Style.Orange, Color.White, 0.7f);
|
||||
}
|
||||
|
||||
talentButton.icon.Color = newTalentColor;
|
||||
talentButton.icon.HoverColor = hoverColor;
|
||||
}
|
||||
|
||||
CreateTalentSkillList(controlledCharacter, skillListBox);
|
||||
}
|
||||
|
||||
private void ApplyTalents(Character controlledCharacter)
|
||||
{
|
||||
selectedTalents = TalentTree.CheckTalentSelection(controlledCharacter, selectedTalents);
|
||||
foreach (string talent in selectedTalents)
|
||||
{
|
||||
controlledCharacter.GiveTalent(talent);
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
GameMain.Client.CreateEntityEvent(controlledCharacter, new object[] { NetEntityEvent.Type.UpdateTalents });
|
||||
}
|
||||
}
|
||||
UpdateTalentButtons();
|
||||
}
|
||||
|
||||
private bool ApplyTalentSelection(GUIButton guiButton, object userData)
|
||||
{
|
||||
Character controlledCharacter = Character.Controlled;
|
||||
ApplyTalents(controlledCharacter);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ResetTalentSelection(GUIButton guiButton, object userData)
|
||||
{
|
||||
Character controlledCharacter = Character.Controlled;
|
||||
selectedTalents = controlledCharacter.Info.GetUnlockedTalentsInTree().ToList();
|
||||
UpdateTalentButtons();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnExperienceChanged(Character character)
|
||||
{
|
||||
if (character != Character.Controlled) { return; }
|
||||
UpdateTalentButtons();
|
||||
}
|
||||
|
||||
private readonly StatTypes[] basicStats = new StatTypes[]
|
||||
{
|
||||
StatTypes.MaximumHealthMultiplier,
|
||||
StatTypes.MovementSpeed,
|
||||
StatTypes.SwimmingSpeed,
|
||||
StatTypes.RepairSpeed,
|
||||
};
|
||||
|
||||
private readonly StatTypes[] combatStats = new StatTypes[]
|
||||
{
|
||||
StatTypes.MeleeAttackMultiplier,
|
||||
StatTypes.MeleeAttackSpeed,
|
||||
StatTypes.RangedAttackSpeed,
|
||||
StatTypes.TurretAttackSpeed,
|
||||
};
|
||||
|
||||
private readonly StatTypes[] miscStats = new StatTypes[]
|
||||
{
|
||||
StatTypes.ReputationGainMultiplier,
|
||||
StatTypes.MissionMoneyGainMultiplier,
|
||||
StatTypes.ExperienceGainMultiplier,
|
||||
StatTypes.MissionExperienceGainMultiplier,
|
||||
};
|
||||
|
||||
private void CreateCharacterSheet(GUILayoutGroup characterInfoColumn)
|
||||
{
|
||||
Character controlledCharacter = Character.Controlled;
|
||||
|
||||
CreateRow(basicStats);
|
||||
CreateRow(combatStats);
|
||||
CreateRow(miscStats);
|
||||
|
||||
void CreateRow(StatTypes[] statTypes)
|
||||
{
|
||||
GUILayoutGroup characterInfoRow = new GUILayoutGroup(new RectTransform(new Vector2(0.33f, 1.0f), characterInfoColumn.RectTransform, anchor: Anchor.TopLeft), childAnchor: Anchor.TopCenter);
|
||||
foreach (StatTypes statType in statTypes)
|
||||
{
|
||||
ShowStat(statType, characterInfoRow);
|
||||
}
|
||||
}
|
||||
|
||||
void ShowStat(StatTypes statType, GUILayoutGroup characterInfoRow)
|
||||
{
|
||||
GUIFrame textInfoFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.33f), characterInfoRow.RectTransform, Anchor.TopCenter), style: null);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1f, 1f), textInfoFrame.RectTransform, Anchor.TopLeft), statType.ToString(), font: GUI.SmallFont, textAlignment: Alignment.TopLeft);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1f, 1f), textInfoFrame.RectTransform, Anchor.TopLeft), (int)(100f * (1 + controlledCharacter.GetStatValue(statType))) + "%", font: GUI.Font, textAlignment: Alignment.TopRight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,8 +115,9 @@ namespace Barotrauma
|
||||
return MathHelper.Clamp(Math.Min(Math.Min(scale.X, scale.Y), GUI.SlicedSpriteScale), minBorderScale, maxBorderScale);
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, Rectangle rect, Color color, SpriteEffects spriteEffects = SpriteEffects.None)
|
||||
public void Draw(SpriteBatch spriteBatch, Rectangle rect, Color color, SpriteEffects spriteEffects = SpriteEffects.None, Vector2? uvOffset = null)
|
||||
{
|
||||
uvOffset ??= Vector2.Zero;
|
||||
if (Sprite.Texture == null)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, rect, Color.Magenta);
|
||||
@@ -157,7 +158,7 @@ namespace Barotrauma
|
||||
else if (Tile)
|
||||
{
|
||||
Vector2 startPos = new Vector2(rect.X, rect.Y);
|
||||
Sprite.DrawTiled(spriteBatch, startPos, new Vector2(rect.Width, rect.Height), color);
|
||||
Sprite.DrawTiled(spriteBatch, startPos, new Vector2(rect.Width, rect.Height), color, startOffset: uvOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1045,10 +1045,10 @@ namespace Barotrauma
|
||||
public static GUIFrame CreateUpgradeFrame(UpgradePrefab prefab, UpgradeCategory category, CampaignMode campaign, RectTransform rectTransform, bool addBuyButton = true)
|
||||
{
|
||||
int price = prefab.Price.GetBuyprice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation);
|
||||
return CreateUpgradeEntry(rectTransform, prefab.Sprite, prefab.Name, prefab.Description, price, new CategoryData(category, prefab), addBuyButton);
|
||||
return CreateUpgradeEntry(rectTransform, prefab.Sprite, prefab.Name, prefab.Description, price, new CategoryData(category, prefab), addBuyButton, upgradePrefab: prefab, currentLevel: campaign.UpgradeManager.GetUpgradeLevel(prefab, category));
|
||||
}
|
||||
|
||||
public static GUIFrame CreateUpgradeEntry(RectTransform parent, Sprite sprite, string title, string body, int price, object? userData, bool addBuyButton = true, bool addProgressBar = true, string buttonStyle = "UpgradeBuyButton")
|
||||
public static GUIFrame CreateUpgradeEntry(RectTransform parent, Sprite sprite, string title, string body, int price, object? userData, bool addBuyButton = true, bool addProgressBar = true, string buttonStyle = "UpgradeBuyButton", UpgradePrefab upgradePrefab = null, int currentLevel = 0)
|
||||
{
|
||||
float progressBarHeight = 0.25f;
|
||||
|
||||
@@ -1089,7 +1089,7 @@ namespace Barotrauma
|
||||
//negative price = refund
|
||||
if (price < 0) { formattedPrice = "+" + formattedPrice; }
|
||||
buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, prefabLayout), childAnchor: Anchor.TopCenter) { UserData = "buybutton" };
|
||||
var priceText = new GUITextBlock(rectT(1, 0.4f, buyButtonLayout), formattedPrice, textAlignment: Alignment.Center);
|
||||
var priceText = new GUITextBlock(rectT(1, 0.2f, buyButtonLayout), formattedPrice, textAlignment: Alignment.Center);
|
||||
if (price < 0)
|
||||
{
|
||||
priceText.TextColor = GUI.Style.Green;
|
||||
@@ -1099,6 +1099,11 @@ namespace Barotrauma
|
||||
priceText.Text = string.Empty;
|
||||
}
|
||||
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: buttonStyle) { Enabled = false };
|
||||
if (upgradePrefab != null)
|
||||
{
|
||||
var increaseText = new GUITextBlock(rectT(1, 0.2f, buyButtonLayout), "", textAlignment: Alignment.Center);
|
||||
UpdateUpgradePercentageText(increaseText, upgradePrefab, currentLevel);
|
||||
}
|
||||
}
|
||||
|
||||
description.CalculateHeightFromText();
|
||||
@@ -1127,6 +1132,19 @@ namespace Barotrauma
|
||||
return prefabFrame;
|
||||
}
|
||||
|
||||
private static void UpdateUpgradePercentageText(GUITextBlock text, UpgradePrefab upgradePrefab, int currentLevel)
|
||||
{
|
||||
float nextIncrease = upgradePrefab.IncreaseOnTooltip * (Math.Min(currentLevel + 1, upgradePrefab.MaxLevel));
|
||||
if (nextIncrease != 0f)
|
||||
{
|
||||
text.Text = $"{Math.Round(nextIncrease, 1)} %";
|
||||
if (currentLevel == upgradePrefab.MaxLevel)
|
||||
{
|
||||
text.TextColor = Color.Gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateUpgradeEntry(UpgradePrefab prefab, UpgradeCategory category, GUIComponent parent, List<Item>? itemsOnSubmarine)
|
||||
{
|
||||
if (Campaign is null) { return; }
|
||||
@@ -1541,7 +1559,9 @@ namespace Barotrauma
|
||||
|
||||
if (prefabFrame.FindChild("buybutton", true) is { } buttonParent)
|
||||
{
|
||||
GUITextBlock priceLabel = buttonParent.GetChild<GUITextBlock>();
|
||||
List<GUITextBlock> textBlocks = buttonParent.GetAllChildren<GUITextBlock>().ToList();
|
||||
|
||||
GUITextBlock priceLabel = textBlocks[0];
|
||||
int price = prefab.Price.GetBuyprice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation);
|
||||
|
||||
if (priceLabel != null && !WaitForServerUpdate)
|
||||
@@ -1562,6 +1582,11 @@ namespace Barotrauma
|
||||
button.Enabled = false;
|
||||
}
|
||||
}
|
||||
GUITextBlock increaseLabel = textBlocks[1];
|
||||
if (increaseLabel != null && !WaitForServerUpdate)
|
||||
{
|
||||
UpdateUpgradePercentageText(increaseLabel, prefab, currentLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user