v0.14.6.0
This commit is contained in:
@@ -208,6 +208,19 @@ namespace Barotrauma
|
||||
get { return pauseMenuOpen; }
|
||||
}
|
||||
|
||||
public static bool InputBlockingMenuOpen
|
||||
{
|
||||
get
|
||||
{
|
||||
return PauseMenuOpen ||
|
||||
SettingsMenuOpen ||
|
||||
DebugConsole.IsOpen ||
|
||||
GameSession.IsTabMenuOpen ||
|
||||
(GameMain.GameSession?.GameMode?.Paused ?? false) ||
|
||||
CharacterHUD.IsCampaignInterfaceOpen;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool PreventPauseMenuToggle = false;
|
||||
|
||||
public static Color ScreenOverlayColor
|
||||
@@ -226,6 +239,9 @@ namespace Barotrauma
|
||||
private static SavingIndicatorState savingIndicatorState = SavingIndicatorState.None;
|
||||
private static float? timeUntilSavingIndicatorDisabled;
|
||||
|
||||
private static string loadedSpritesText;
|
||||
private static DateTime loadedSpritesUpdateTime;
|
||||
|
||||
private enum SavingIndicatorState
|
||||
{
|
||||
None,
|
||||
@@ -441,9 +457,12 @@ namespace Barotrauma
|
||||
"Particle count: " + GameMain.ParticleManager.ParticleCount + "/" + GameMain.ParticleManager.MaxParticles,
|
||||
Color.Lerp(GUI.Style.Green, GUI.Style.Red, (GameMain.ParticleManager.ParticleCount / (float)GameMain.ParticleManager.MaxParticles)), Color.Black * 0.5f, 0, SmallFont);
|
||||
|
||||
DrawString(spriteBatch, new Vector2(10, 115),
|
||||
"Loaded sprites: " + Sprite.LoadedSprites.Count() + "\n(" + Sprite.LoadedSprites.Select(s => s.FilePath).Distinct().Count() + " unique textures)",
|
||||
Color.White, Color.Black * 0.5f, 0, SmallFont);
|
||||
if (loadedSpritesText == null || DateTime.Now > loadedSpritesUpdateTime)
|
||||
{
|
||||
loadedSpritesText = "Loaded sprites: " + Sprite.LoadedSprites.Count() + "\n(" + Sprite.LoadedSprites.Select(s => s.FilePath).Distinct().Count() + " unique textures)";
|
||||
loadedSpritesUpdateTime = DateTime.Now + new TimeSpan(0, 0, seconds: 5);
|
||||
}
|
||||
DrawString(spriteBatch, new Vector2(10, 115), loadedSpritesText, Color.White, Color.Black * 0.5f, 0, SmallFont);
|
||||
|
||||
if (debugDrawSounds)
|
||||
{
|
||||
@@ -978,8 +997,7 @@ namespace Barotrauma
|
||||
return editor.GetMouseCursorState();
|
||||
// Portrait area during gameplay
|
||||
case GameScreen _ when !(Character.Controlled?.ShouldLockHud() ?? true):
|
||||
if (HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) ||
|
||||
Rectangle.Union(HUDLayoutSettings.AfflictionAreaLeft, HUDLayoutSettings.HealthBarArea).Contains(PlayerInput.MousePosition))
|
||||
if (HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) || CharacterHealth.IsMouseOnHealthBar())
|
||||
{
|
||||
return CursorState.Hand;
|
||||
}
|
||||
@@ -1331,7 +1349,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, Vector2 worldPosition, Camera cam, float hideDist, Sprite sprite, Color color,
|
||||
public static void DrawIndicator(SpriteBatch spriteBatch, in Vector2 worldPosition, Camera cam, in Vector2 visibleRange, Sprite sprite, in Color color,
|
||||
bool createOffset = true, float scaleMultiplier = 1.0f, float? overrideAlpha = null)
|
||||
{
|
||||
Vector2 diff = worldPosition - cam.WorldViewCenter;
|
||||
@@ -1339,9 +1357,9 @@ namespace Barotrauma
|
||||
|
||||
float symbolScale = Math.Min(64.0f / sprite.size.X, 1.0f) * scaleMultiplier * Scale;
|
||||
|
||||
if (overrideAlpha.HasValue || dist > hideDist)
|
||||
if (overrideAlpha.HasValue || (dist > visibleRange.X && dist < visibleRange.Y))
|
||||
{
|
||||
float alpha = overrideAlpha ?? Math.Min((dist - hideDist) / 100.0f, 1.0f);
|
||||
float alpha = overrideAlpha ?? MathUtils.Min((dist - visibleRange.X) / 100.0f, 1.0f - ((dist - visibleRange.Y + 100f) / 100.0f), 1.0f);
|
||||
Vector2 targetScreenPos = cam.WorldToScreen(worldPosition);
|
||||
|
||||
if (!createOffset)
|
||||
@@ -1352,8 +1370,9 @@ namespace Barotrauma
|
||||
|
||||
float screenDist = Vector2.Distance(cam.WorldToScreen(cam.WorldViewCenter), targetScreenPos);
|
||||
float angle = MathUtils.VectorToAngle(diff);
|
||||
float originalAngle = angle;
|
||||
|
||||
float minAngleDiff = 0.05f;
|
||||
const float minAngleDiff = 0.05f;
|
||||
bool overlapFound = true;
|
||||
int iterations = 0;
|
||||
while (overlapFound && iterations < 10)
|
||||
@@ -1375,18 +1394,24 @@ namespace Barotrauma
|
||||
|
||||
usedIndicatorAngles.Add(angle);
|
||||
|
||||
Vector2 unclampedDiff = new Vector2(
|
||||
(float)Math.Cos(angle) * screenDist,
|
||||
(float)-Math.Sin(angle) * screenDist);
|
||||
|
||||
Vector2 iconDiff = new Vector2(
|
||||
(float)Math.Cos(angle) * Math.Min(GameMain.GraphicsWidth * 0.4f, screenDist + 10),
|
||||
(float)-Math.Sin(angle) * Math.Min(GameMain.GraphicsHeight * 0.4f, screenDist + 10));
|
||||
|
||||
angle = MathHelper.Lerp(originalAngle, angle, MathHelper.Clamp(((screenDist + 10f) - iconDiff.Length()) / 10f, 0f, 1f));
|
||||
|
||||
/*Vector2 unclampedDiff = new Vector2(
|
||||
(float)Math.Cos(angle) * screenDist,
|
||||
(float)-Math.Sin(angle) * screenDist);*/
|
||||
|
||||
iconDiff = new Vector2(
|
||||
(float)Math.Cos(angle) * Math.Min(GameMain.GraphicsWidth * 0.4f, screenDist),
|
||||
(float)-Math.Sin(angle) * Math.Min(GameMain.GraphicsHeight * 0.4f, screenDist));
|
||||
|
||||
Vector2 iconPos = cam.WorldToScreen(cam.WorldViewCenter) + iconDiff;
|
||||
sprite.Draw(spriteBatch, iconPos, color * alpha, rotate: 0.0f, scale: symbolScale);
|
||||
|
||||
if (unclampedDiff.Length() - 10 > iconDiff.Length())
|
||||
if (/*unclampedDiff.Length()*/ screenDist - 10 > iconDiff.Length())
|
||||
{
|
||||
Vector2 normalizedDiff = Vector2.Normalize(targetScreenPos - iconPos);
|
||||
Vector2 arrowOffset = normalizedDiff * sprite.size.X * symbolScale * 0.7f;
|
||||
@@ -1395,6 +1420,12 @@ 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);
|
||||
}
|
||||
|
||||
public static void DrawLine(SpriteBatch sb, Vector2 start, Vector2 end, Color clr, float depth = 0.0f, float width = 1)
|
||||
{
|
||||
DrawLine(sb, t, start, end, clr, depth, (int)width);
|
||||
@@ -1495,6 +1526,22 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawFilledRectangle(SpriteBatch sb, Vector2 start, Vector2 size, Color clr, float depth = 0.0f)
|
||||
{
|
||||
if (size.X < 0)
|
||||
{
|
||||
start.X += size.X;
|
||||
size.X = -size.X;
|
||||
}
|
||||
if (size.Y < 0)
|
||||
{
|
||||
start.Y += size.Y;
|
||||
size.Y = -size.Y;
|
||||
}
|
||||
|
||||
sb.Draw(t, start, null, clr, 0f, Vector2.Zero, size, SpriteEffects.None, depth);
|
||||
}
|
||||
|
||||
public static void DrawRectangle(SpriteBatch sb, Vector2 center, float width, float height, float rotation, Color clr, float depth = 0.0f, float thickness = 1)
|
||||
{
|
||||
Matrix rotate = Matrix.CreateRotationZ(rotation);
|
||||
@@ -1971,6 +2018,30 @@ namespace Barotrauma
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
public static GUIMessageBox AskForConfirmation(string header, string body, Action onConfirm, Action onDeny = null)
|
||||
{
|
||||
string[] buttons = { TextManager.Get("Ok"), TextManager.Get("Cancel") };
|
||||
GUIMessageBox msgBox = new GUIMessageBox(header, body, buttons, new Vector2(0.2f, 0.175f), minSize: new Point(300, 175));
|
||||
|
||||
// Cancel button
|
||||
msgBox.Buttons[1].OnClicked = delegate
|
||||
{
|
||||
onDeny?.Invoke();
|
||||
msgBox.Close();
|
||||
return true;
|
||||
};
|
||||
|
||||
// Ok button
|
||||
msgBox.Buttons[0].OnClicked = delegate
|
||||
{
|
||||
onConfirm.Invoke();
|
||||
msgBox.Close();
|
||||
return true;
|
||||
};
|
||||
return msgBox;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Element positioning
|
||||
@@ -2098,7 +2169,7 @@ namespace Barotrauma
|
||||
for (int j = i + 1; j < elements.Count; j++)
|
||||
{
|
||||
Rectangle rect2 = elements[j].Rect;
|
||||
if (!rect1.Intersects(rect2)) continue;
|
||||
if (!rect1.Intersects(rect2)) { continue; }
|
||||
|
||||
intersections = true;
|
||||
Point centerDiff = rect1.Center - rect2.Center;
|
||||
@@ -2127,10 +2198,10 @@ namespace Barotrauma
|
||||
elements[j].RectTransform.ScreenSpaceOffset += moveAmount2.ToPoint();
|
||||
}
|
||||
|
||||
if (disallowedAreas == null) continue;
|
||||
if (disallowedAreas == null) { continue; }
|
||||
foreach (Rectangle rect2 in disallowedAreas)
|
||||
{
|
||||
if (!rect1.Intersects(rect2)) continue;
|
||||
if (!rect1.Intersects(rect2)) { continue; }
|
||||
intersections = true;
|
||||
|
||||
Point centerDiff = rect1.Center - rect2.Center;
|
||||
@@ -2148,7 +2219,7 @@ namespace Barotrauma
|
||||
iterations++;
|
||||
}
|
||||
|
||||
Vector2 ClampMoveAmount(Rectangle Rect, Rectangle clampTo, Vector2 moveAmount)
|
||||
static Vector2 ClampMoveAmount(Rectangle Rect, Rectangle clampTo, Vector2 moveAmount)
|
||||
{
|
||||
if (Rect.Y < clampTo.Y)
|
||||
{
|
||||
@@ -2221,6 +2292,7 @@ namespace Barotrauma
|
||||
}
|
||||
};
|
||||
|
||||
bool IsOutpostLevel() => GameMain.GameSession != null && Level.IsLoadedOutpost;
|
||||
if (Screen.Selected == GameMain.GameScreen && GameMain.GameSession != null)
|
||||
{
|
||||
if (GameMain.GameSession.GameMode is SinglePlayerCampaign spMode)
|
||||
@@ -2253,45 +2325,22 @@ namespace Barotrauma
|
||||
};
|
||||
return true;
|
||||
};
|
||||
var saveAndQuitButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuSaveQuit"))
|
||||
if (IsOutpostLevel())
|
||||
{
|
||||
UserData = "save"
|
||||
};
|
||||
saveAndQuitButton.OnClicked += (btn, userdata) =>
|
||||
{
|
||||
//Only allow saving mid-round in outpost levels. Quitting in the middle of a mission reset progress to the start of the round.
|
||||
if (GameMain.GameSession == null)
|
||||
var saveAndQuitButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuSaveQuit"))
|
||||
{
|
||||
pauseMenuOpen = false;
|
||||
|
||||
}
|
||||
else if (GameMain.GameSession?.Campaign == null || Level.IsLoadedOutpost)
|
||||
{
|
||||
pauseMenuOpen = false;
|
||||
GameMain.QuitToMainMenu(save: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
var msgBox = new GUIMessageBox("", TextManager.Get("PauseMenuSaveAndQuitVerification", fallBackTag: "pausemenuquitverification"), new string[] { TextManager.Get("Yes"), TextManager.Get("Cancel") })
|
||||
{
|
||||
UserData = "verificationprompt"
|
||||
};
|
||||
msgBox.Buttons[0].OnClicked = (_, userdata) =>
|
||||
UserData = "save",
|
||||
OnClicked = (btn, userData) =>
|
||||
{
|
||||
pauseMenuOpen = false;
|
||||
GameMain.QuitToMainMenu(save: false);
|
||||
if (IsOutpostLevel())
|
||||
{
|
||||
GameMain.QuitToMainMenu(save: true);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||
msgBox.Buttons[1].OnClicked = (_, userdata) =>
|
||||
{
|
||||
pauseMenuOpen = false;
|
||||
msgBox.Close();
|
||||
return true;
|
||||
};
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
else if (GameMain.GameSession.GameMode is TestGameMode)
|
||||
{
|
||||
@@ -2313,7 +2362,7 @@ namespace Barotrauma
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
if (!GameMain.Client.HasPermission(ClientPermissions.ManageRound)) { return false; }
|
||||
if (GameMain.GameSession.GameMode is CampaignMode || (!Submarine.MainSub.AtStartExit && !Submarine.MainSub.AtEndExit))
|
||||
if (GameMain.GameSession.GameMode is CampaignMode && !IsOutpostLevel() || (!Submarine.MainSub.AtStartExit && !Submarine.MainSub.AtEndExit))
|
||||
{
|
||||
var msgBox = new GUIMessageBox("",
|
||||
TextManager.Get(GameMain.GameSession.GameMode is CampaignMode ? "PauseMenuReturnToServerLobbyVerification" : "EndRoundSubNotAtLevelEnd"),
|
||||
|
||||
@@ -201,7 +201,7 @@ namespace Barotrauma
|
||||
{
|
||||
base.ApplyStyle(style);
|
||||
|
||||
if (frame != null) { frame.ApplyStyle(style); }
|
||||
frame?.ApplyStyle(style);
|
||||
}
|
||||
|
||||
public override void Flash(Color? color = null, float flashDuration = 1.5f, bool useRectangleFlash = false, bool useCircularFlash = false, Vector2? flashRectInflate = null)
|
||||
|
||||
@@ -59,9 +59,7 @@ namespace Barotrauma
|
||||
|
||||
private bool useGridLayout;
|
||||
|
||||
private float targetScroll;
|
||||
|
||||
private GUIComponent pendingScroll;
|
||||
private GUIComponent scrollToElement;
|
||||
|
||||
public bool AllowMouseWheelScroll { get; set; } = true;
|
||||
|
||||
@@ -238,8 +236,6 @@ namespace Barotrauma
|
||||
|
||||
public GUIComponent DraggedElement => draggedElement;
|
||||
|
||||
private bool scheduledScroll = false;
|
||||
|
||||
private readonly bool isHorizontal;
|
||||
|
||||
/// <param name="isScrollBarOnDefaultSide">For horizontal listbox, default side is on the bottom. For vertical, it's on the right.</param>
|
||||
@@ -429,7 +425,14 @@ namespace Barotrauma
|
||||
int index = children.IndexOf(component);
|
||||
if (index < 0) { return; }
|
||||
|
||||
targetScroll = MathHelper.Clamp(MathHelper.Lerp(0, 1, MathUtils.InverseLerp(0, (children.Count - 0.9f), index)), ScrollBar.MinValue, ScrollBar.MaxValue);
|
||||
if (!Content.Children.Contains(component) || !component.Visible)
|
||||
{
|
||||
scrollToElement = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
scrollToElement = component;
|
||||
}
|
||||
}
|
||||
|
||||
public void ScrollToEnd(float duration)
|
||||
@@ -533,7 +536,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (SelectTop && Content.Children.Any() && pendingScroll == null)
|
||||
if (SelectTop && Content.Children.Any() && scrollToElement == null)
|
||||
{
|
||||
GUIComponent component = Content.Children.FirstOrDefault(c => (c.Rect.Y - Content.Rect.Y) / (float)c.Rect.Height > -0.1f);
|
||||
|
||||
@@ -563,7 +566,6 @@ namespace Barotrauma
|
||||
{
|
||||
if (SelectTop)
|
||||
{
|
||||
pendingScroll = child;
|
||||
ScrollToElement(child);
|
||||
Select(i, autoScroll: false, takeKeyBoardFocus: true);
|
||||
}
|
||||
@@ -728,25 +730,29 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SmoothScroll)
|
||||
{
|
||||
if (targetScroll > -1)
|
||||
{
|
||||
float distance = Math.Abs(targetScroll - BarScroll);
|
||||
float speed = Math.Max(distance * BarSize, 0.1f);
|
||||
BarScroll = (1.0f - speed) * BarScroll + speed * targetScroll;
|
||||
if (MathUtils.NearlyEqual(BarScroll, targetScroll) || GUIScrollBar.DraggingBar != null)
|
||||
{
|
||||
targetScroll = -1;
|
||||
pendingScroll = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (scrollToElement != null)
|
||||
{
|
||||
if (!scrollToElement.Visible || !Content.Children.Contains(scrollToElement))
|
||||
{
|
||||
scrollToElement = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
float diff = isHorizontal ? scrollToElement.Rect.X - Content.Rect.X : scrollToElement.Rect.Y - Content.Rect.Y;
|
||||
float speed = MathHelper.Clamp(Math.Abs(diff) * 0.1f, 5.0f, 100.0f);
|
||||
System.Diagnostics.Debug.WriteLine(speed);
|
||||
if (Math.Abs(diff) < speed || GUIScrollBar.DraggingBar != null)
|
||||
{
|
||||
speed = Math.Abs(diff);
|
||||
scrollToElement = null;
|
||||
}
|
||||
BarScroll += speed * Math.Sign(diff) / TotalSize;
|
||||
}
|
||||
}
|
||||
|
||||
if ((GUI.IsMouseOn(this) || GUI.IsMouseOn(ScrollBar)) && AllowMouseWheelScroll && PlayerInput.ScrollWheelSpeed != 0)
|
||||
{
|
||||
float speed = PlayerInput.ScrollWheelSpeed / 500.0f * BarSize;
|
||||
if (SmoothScroll)
|
||||
{
|
||||
if (ClampScrollToElements)
|
||||
@@ -762,13 +768,6 @@ namespace Barotrauma
|
||||
SelectNext(takeKeyBoardFocus: true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pendingScroll = null;
|
||||
if (targetScroll < 0) { targetScroll = BarScroll; }
|
||||
targetScroll -= speed;
|
||||
targetScroll = Math.Clamp(targetScroll, ScrollBar.MinValue, ScrollBar.MaxValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -799,7 +798,6 @@ namespace Barotrauma
|
||||
Select(index, force, !SmoothScroll && autoScroll, takeKeyBoardFocus: takeKeyBoardFocus);
|
||||
if (SmoothScroll)
|
||||
{
|
||||
pendingScroll = child;
|
||||
ScrollToElement(child);
|
||||
}
|
||||
break;
|
||||
@@ -819,7 +817,6 @@ namespace Barotrauma
|
||||
Select(index, force, !SmoothScroll && autoScroll, takeKeyBoardFocus: takeKeyBoardFocus);
|
||||
if (SmoothScroll)
|
||||
{
|
||||
pendingScroll = child;
|
||||
ScrollToElement(child);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -551,7 +551,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (openState >= 2.0f)
|
||||
{
|
||||
if (Parent != null) { Parent.RemoveChild(this); }
|
||||
Parent?.RemoveChild(this);
|
||||
if (MessageBoxes.Contains(this)) { MessageBoxes.Remove(this); }
|
||||
}
|
||||
}
|
||||
@@ -604,7 +604,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Parent != null) { Parent.RemoveChild(this); }
|
||||
Parent?.RemoveChild(this);
|
||||
if (MessageBoxes.Contains(this)) { MessageBoxes.Remove(this); }
|
||||
}
|
||||
|
||||
|
||||
@@ -140,6 +140,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (value == intValue) { return; }
|
||||
intValue = value;
|
||||
ClampIntValue();
|
||||
UpdateText();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -658,10 +658,7 @@ namespace Barotrauma
|
||||
currentTextColor * (currentTextColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth, RichTextData);
|
||||
}
|
||||
|
||||
if (Strikethrough != null)
|
||||
{
|
||||
Strikethrough.Draw(spriteBatch, (int)Math.Ceiling(TextSize.X / 2f), pos.X, ForceUpperCase ? pos.Y : pos.Y + GUI.Scale * 2f);
|
||||
}
|
||||
Strikethrough?.Draw(spriteBatch, (int)Math.Ceiling(TextSize.X / 2f), pos.X, ForceUpperCase ? pos.Y : pos.Y + GUI.Scale * 2f);
|
||||
}
|
||||
|
||||
if (overflowClipActive)
|
||||
|
||||
@@ -49,8 +49,11 @@ namespace Barotrauma
|
||||
get { return _caretIndex; }
|
||||
set
|
||||
{
|
||||
_caretIndex = value;
|
||||
caretPosDirty = true;
|
||||
if (value >= 0)
|
||||
{
|
||||
_caretIndex = value;
|
||||
caretPosDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
private bool caretPosDirty;
|
||||
@@ -454,7 +457,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (!isSelecting)
|
||||
{
|
||||
isSelecting = PlayerInput.KeyDown(Keys.LeftShift) || PlayerInput.KeyDown(Keys.RightShift);
|
||||
isSelecting = PlayerInput.IsShiftDown();
|
||||
}
|
||||
|
||||
if (mouseHeldInside && !PlayerInput.PrimaryMouseButtonHeld())
|
||||
@@ -879,15 +882,22 @@ namespace Barotrauma
|
||||
selectionEndIndex = Math.Min(CaretIndex, textDrawn.Length);
|
||||
selectionEndPos = caretPos;
|
||||
selectedCharacters = Math.Abs(selectionStartIndex - selectionEndIndex);
|
||||
if (IsLeftToRight)
|
||||
try
|
||||
{
|
||||
selectedText = Text.Substring(selectionStartIndex, selectedCharacters);
|
||||
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionStartIndex, selectedCharacters)) * TextBlock.TextScale;
|
||||
if (IsLeftToRight)
|
||||
{
|
||||
selectedText = Text.Substring(selectionStartIndex, Math.Min(selectedCharacters, Text.Length));
|
||||
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionStartIndex, Math.Min(selectedCharacters, textDrawn.Length))) * TextBlock.TextScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedText = Text.Substring(selectionEndIndex, Math.Min(selectedCharacters, Text.Length));
|
||||
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionEndIndex, Math.Min(selectedCharacters, textDrawn.Length))) * TextBlock.TextScale;
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (ArgumentOutOfRangeException exception)
|
||||
{
|
||||
selectedText = Text.Substring(selectionEndIndex, Math.Min(selectedCharacters, textDrawn.Length - selectionEndIndex));
|
||||
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionEndIndex, selectedCharacters)) * TextBlock.TextScale;
|
||||
DebugConsole.ThrowError($"GUITextBox: Invalid selection: ({exception})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,47 +17,63 @@ namespace Barotrauma
|
||||
private readonly Dictionary<StoreTab, GUIListBox> tabLists = new Dictionary<StoreTab, GUIListBox>();
|
||||
private readonly Dictionary<StoreTab, SortingMethod> tabSortingMethods = new Dictionary<StoreTab, SortingMethod>();
|
||||
private readonly List<PurchasedItem> itemsToSell = new List<PurchasedItem>();
|
||||
private readonly List<PurchasedItem> itemsToSellFromSub = new List<PurchasedItem>();
|
||||
|
||||
private StoreTab activeTab = StoreTab.Buy;
|
||||
private MapEntityCategory? selectedItemCategory;
|
||||
private bool suppressBuySell;
|
||||
private int buyTotal, sellTotal;
|
||||
private int buyTotal, sellTotal, sellFromSubTotal;
|
||||
|
||||
private GUITextBlock merchantBalanceBlock;
|
||||
private GUITextBlock currentSellValueBlock, newSellValueBlock;
|
||||
private GUIImage sellValueChangeArrow;
|
||||
private GUIDropDown sortingDropDown;
|
||||
private GUITextBox searchBox;
|
||||
private GUIListBox storeBuyList, storeSellList;
|
||||
private GUIListBox storeBuyList, storeSellList, storeSellFromSubList;
|
||||
/// <summary>
|
||||
/// Can be null when there are no deals at the current location
|
||||
/// </summary>
|
||||
private GUILayoutGroup storeDailySpecialsGroup, storeRequestedGoodGroup;
|
||||
private GUILayoutGroup storeDailySpecialsGroup, storeRequestedGoodGroup, storeRequestedSubGoodGroup;
|
||||
private Color storeSpecialColor;
|
||||
|
||||
private GUIListBox shoppingCrateBuyList, shoppingCrateSellList;
|
||||
private GUIListBox shoppingCrateBuyList, shoppingCrateSellList, shoppingCrateSellFromSubList;
|
||||
private GUITextBlock shoppingCrateTotal;
|
||||
private GUIButton clearAllButton, confirmButton;
|
||||
|
||||
private bool needsRefresh, needsBuyingRefresh, needsSellingRefresh, needsItemsToSellRefresh;
|
||||
private bool needsRefresh, needsBuyingRefresh, needsSellingRefresh, needsItemsToSellRefresh, needsSellingFromSubRefresh, needsItemsToSellFromSubRefresh;
|
||||
|
||||
private Point resolutionWhenCreated;
|
||||
private bool hadPermissions;
|
||||
|
||||
private Dictionary<ItemPrefab, int> OwnedItems { get; } = new Dictionary<ItemPrefab, int>();
|
||||
private Dictionary<ItemPrefab, int> OwnedItems { get; } = new Dictionary<ItemPrefab, int>();
|
||||
|
||||
private CargoManager CargoManager => campaignUI.Campaign.CargoManager;
|
||||
private Location CurrentLocation => campaignUI.Campaign.Map?.CurrentLocation;
|
||||
private int PlayerMoney => campaignUI.Campaign.Money;
|
||||
private bool HasPermissions => campaignUI.Campaign.AllowedToManageCampaign();
|
||||
private bool IsBuying => activeTab != StoreTab.Sell;
|
||||
private bool IsSelling => activeTab == StoreTab.Sell;
|
||||
private GUIListBox ActiveShoppingCrateList => IsBuying ? shoppingCrateBuyList : shoppingCrateSellList;
|
||||
private bool IsBuying => activeTab switch
|
||||
{
|
||||
StoreTab.Buy => true,
|
||||
StoreTab.Sell => false,
|
||||
StoreTab.SellFromSub => false,
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
private bool IsSelling => !IsBuying;
|
||||
private GUIListBox ActiveShoppingCrateList => activeTab switch
|
||||
{
|
||||
StoreTab.Buy => shoppingCrateBuyList,
|
||||
StoreTab.Sell => shoppingCrateSellList,
|
||||
StoreTab.SellFromSub => shoppingCrateSellFromSubList,
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
|
||||
private enum StoreTab
|
||||
private bool IsTabUnavailable(StoreTab tab) => !tabLists.ContainsKey(tab);
|
||||
|
||||
public enum StoreTab
|
||||
{
|
||||
Buy,
|
||||
Sell
|
||||
Sell,
|
||||
SellFromSub
|
||||
}
|
||||
|
||||
private enum SortingMethod
|
||||
@@ -73,11 +89,8 @@ namespace Barotrauma
|
||||
{
|
||||
this.campaignUI = campaignUI;
|
||||
this.parentComponent = parentComponent;
|
||||
|
||||
hadPermissions = HasPermissions;
|
||||
|
||||
CreateUI();
|
||||
|
||||
campaignUI.Campaign.Map.OnLocationChanged += UpdateLocation;
|
||||
if (CurrentLocation?.Reputation != null)
|
||||
{
|
||||
@@ -89,8 +102,10 @@ namespace Barotrauma
|
||||
campaignUI.Campaign.CargoManager.OnSoldItemsChanged += () =>
|
||||
{
|
||||
needsItemsToSellRefresh = true;
|
||||
needsItemsToSellFromSubRefresh = true;
|
||||
needsRefresh = true;
|
||||
};
|
||||
campaignUI.Campaign.CargoManager.OnItemsInSellFromSubCrateChanged += () => { needsSellingFromSubRefresh = true; };
|
||||
}
|
||||
|
||||
public void Refresh(bool updateOwned = true)
|
||||
@@ -99,6 +114,7 @@ namespace Barotrauma
|
||||
if (updateOwned) { UpdateOwnedItems(); }
|
||||
RefreshBuying(updateOwned: false);
|
||||
RefreshSelling(updateOwned: false);
|
||||
RefreshSellingFromSub(updateOwned: false);
|
||||
needsRefresh = false;
|
||||
}
|
||||
|
||||
@@ -124,6 +140,20 @@ namespace Barotrauma
|
||||
needsSellingRefresh = false;
|
||||
}
|
||||
|
||||
private void RefreshSellingFromSub(bool updateOwned = true, bool updateItemsToSellFromSub = true)
|
||||
{
|
||||
if (IsTabUnavailable(StoreTab.SellFromSub)) { return; }
|
||||
if (updateOwned) { UpdateOwnedItems(); }
|
||||
if (updateItemsToSellFromSub) RefreshItemsToSellFromSub();
|
||||
RefreshShoppingCrateSellFromSubList();
|
||||
RefreshStoreSellFromSubList();
|
||||
// TODO: Separate permissions from regular campaign permissions
|
||||
var hasPermissions = HasPermissions;
|
||||
storeSellFromSubList.Enabled = hasPermissions;
|
||||
shoppingCrateSellFromSubList.Enabled = hasPermissions;
|
||||
needsSellingFromSubRefresh = false;
|
||||
}
|
||||
|
||||
private void CreateUI()
|
||||
{
|
||||
if (parentComponent.FindChild(c => c.UserData as string == "glow") is GUIComponent glowChild)
|
||||
@@ -236,9 +266,13 @@ namespace Barotrauma
|
||||
{
|
||||
if (CurrentLocation != null)
|
||||
{
|
||||
int balanceAfterTransaction = IsBuying ?
|
||||
CurrentLocation.StoreCurrentBalance + buyTotal :
|
||||
CurrentLocation.StoreCurrentBalance - sellTotal;
|
||||
int balanceAfterTransaction = activeTab switch
|
||||
{
|
||||
StoreTab.Buy => CurrentLocation.StoreCurrentBalance + buyTotal,
|
||||
StoreTab.Sell => CurrentLocation.StoreCurrentBalance - sellTotal,
|
||||
StoreTab.SellFromSub => CurrentLocation.StoreCurrentBalance - sellFromSubTotal,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
if (balanceAfterTransaction != CurrentLocation.StoreCurrentBalance)
|
||||
{
|
||||
var newStatus = Location.GetStoreBalanceStatus(balanceAfterTransaction);
|
||||
@@ -300,8 +334,14 @@ namespace Barotrauma
|
||||
tabSortingMethods.Clear();
|
||||
foreach (StoreTab tab in tabs)
|
||||
{
|
||||
if (tab == StoreTab.SellFromSub && GameMain.IsMultiplayer) { continue; }
|
||||
string text = tab switch
|
||||
{
|
||||
StoreTab.SellFromSub => TextManager.Get("submarine"),
|
||||
_ => TextManager.Get("campaignstoretab." + tab)
|
||||
};
|
||||
var tabButton = new GUIButton(new RectTransform(new Vector2(1.0f / (tabs.Length + 1), 1.0f), modeButtonContainer.RectTransform),
|
||||
text: TextManager.Get("campaignstoretab." + tab), style: "GUITabButton")
|
||||
text: text, style: "GUITabButton")
|
||||
{
|
||||
UserData = tab,
|
||||
OnClicked = (button, userData) =>
|
||||
@@ -416,6 +456,17 @@ namespace Barotrauma
|
||||
storeRequestedGoodGroup = CreateDealsGroup(storeSellList);
|
||||
tabLists.Add(StoreTab.Sell, storeSellList);
|
||||
|
||||
if (GameMain.IsSingleplayer)
|
||||
{
|
||||
storeSellFromSubList = new GUIListBox(new RectTransform(Vector2.One, storeItemListContainer.RectTransform))
|
||||
{
|
||||
AutoHideScrollBar = false,
|
||||
Visible = false
|
||||
};
|
||||
storeRequestedSubGoodGroup = CreateDealsGroup(storeSellFromSubList);
|
||||
tabLists.Add(StoreTab.SellFromSub, storeSellFromSubList);
|
||||
}
|
||||
|
||||
// Shopping Crate ------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
var shoppingCrateContent = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 1.0f), campaignUI.GetTabContainer(CampaignMode.InteractionType.Store).RectTransform, anchor: Anchor.TopRight)
|
||||
@@ -475,6 +526,10 @@ namespace Barotrauma
|
||||
var shoppingCrateListContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.85f), 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)
|
||||
{
|
||||
shoppingCrateSellFromSubList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
||||
}
|
||||
|
||||
var totalContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), shoppingCrateInventoryContainer.RectTransform), isHorizontal: true)
|
||||
{
|
||||
@@ -504,7 +559,13 @@ namespace Barotrauma
|
||||
OnClicked = (button, userData) =>
|
||||
{
|
||||
if (!HasPermissions) { return false; }
|
||||
var itemsToRemove = new List<PurchasedItem>(IsBuying ? CargoManager.ItemsInBuyCrate : CargoManager.ItemsInSellCrate);
|
||||
var itemsToRemove = activeTab switch
|
||||
{
|
||||
StoreTab.Buy => new List<PurchasedItem>(CargoManager.ItemsInBuyCrate),
|
||||
StoreTab.Sell => new List<PurchasedItem>(CargoManager.ItemsInSellCrate),
|
||||
StoreTab.SellFromSub => new List<PurchasedItem>(CargoManager.ItemsInSellFromSubCrate),
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
itemsToRemove.ForEach(i => ClearFromShoppingCrate(i));
|
||||
return true;
|
||||
}
|
||||
@@ -560,6 +621,7 @@ namespace Barotrauma
|
||||
|
||||
private void ChangeStoreTab(StoreTab tab)
|
||||
{
|
||||
if (IsTabUnavailable(tab)) { return; }
|
||||
activeTab = tab;
|
||||
foreach (GUIButton tabButton in storeTabButtons)
|
||||
{
|
||||
@@ -571,24 +633,56 @@ namespace Barotrauma
|
||||
SetConfirmButtonBehavior();
|
||||
SetConfirmButtonStatus();
|
||||
FilterStoreItems();
|
||||
if (tab == StoreTab.Buy)
|
||||
switch (tab)
|
||||
{
|
||||
storeSellList.Visible = false;
|
||||
storeBuyList.Visible = true;
|
||||
shoppingCrateSellList.Visible = false;
|
||||
shoppingCrateBuyList.Visible = true;
|
||||
}
|
||||
else if (tab == StoreTab.Sell)
|
||||
{
|
||||
storeBuyList.Visible = false;
|
||||
storeSellList.Visible = true;
|
||||
shoppingCrateBuyList.Visible = false;
|
||||
shoppingCrateSellList.Visible = true;
|
||||
case StoreTab.Buy:
|
||||
storeSellList.Visible = false;
|
||||
if (storeSellFromSubList != null)
|
||||
{
|
||||
storeSellFromSubList.Visible = false;
|
||||
}
|
||||
storeBuyList.Visible = true;
|
||||
shoppingCrateSellList.Visible = false;
|
||||
if (shoppingCrateSellFromSubList != null)
|
||||
{
|
||||
shoppingCrateSellFromSubList.Visible = false;
|
||||
}
|
||||
shoppingCrateBuyList.Visible = true;
|
||||
break;
|
||||
case StoreTab.Sell:
|
||||
storeBuyList.Visible = false;
|
||||
if (storeSellFromSubList != null)
|
||||
{
|
||||
storeSellFromSubList.Visible = false;
|
||||
}
|
||||
storeSellList.Visible = true;
|
||||
shoppingCrateBuyList.Visible = false;
|
||||
if (shoppingCrateSellFromSubList != null)
|
||||
{
|
||||
shoppingCrateSellFromSubList.Visible = false;
|
||||
}
|
||||
shoppingCrateSellList.Visible = true;
|
||||
break;
|
||||
case StoreTab.SellFromSub:
|
||||
storeBuyList.Visible = false;
|
||||
storeSellList.Visible = false;
|
||||
if (storeSellFromSubList != null)
|
||||
{
|
||||
storeSellFromSubList.Visible = true;
|
||||
}
|
||||
shoppingCrateBuyList.Visible = false;
|
||||
shoppingCrateSellList.Visible = false;
|
||||
if (shoppingCrateSellFromSubList != null)
|
||||
{
|
||||
shoppingCrateSellFromSubList.Visible = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void FilterStoreItems(MapEntityCategory? category, string filter)
|
||||
{
|
||||
if (IsTabUnavailable(activeTab)) { return; }
|
||||
selectedItemCategory = category;
|
||||
var list = tabLists[activeTab];
|
||||
filter = filter?.ToLower();
|
||||
@@ -668,7 +762,7 @@ namespace Barotrauma
|
||||
if (itemFrame == null)
|
||||
{
|
||||
var parentComponent = isDailySpecial ? storeDailySpecialsGroup : storeBuyList as GUIComponent;
|
||||
itemFrame = CreateItemFrame(new PurchasedItem(itemPrefab, quantity), priceInfo, parentComponent, forceDisable: !hasPermissions);
|
||||
itemFrame = CreateItemFrame(new PurchasedItem(itemPrefab, quantity), parentComponent, StoreTab.Buy, forceDisable: !hasPermissions);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -688,7 +782,7 @@ namespace Barotrauma
|
||||
removedItemFrames.AddRange(storeDailySpecialsGroup.Children.Where(c => c.UserData is PurchasedItem).Except(existingItemFrames).ToList());
|
||||
}
|
||||
removedItemFrames.ForEach(f => f.RectTransform.Parent = null);
|
||||
if (IsBuying) { FilterStoreItems(); }
|
||||
if (activeTab == StoreTab.Buy) { FilterStoreItems(); }
|
||||
SortItems(StoreTab.Buy);
|
||||
|
||||
storeBuyList.BarScroll = prevBuyListScroll;
|
||||
@@ -743,7 +837,7 @@ namespace Barotrauma
|
||||
if (itemFrame == null)
|
||||
{
|
||||
var parentComponent = isRequestedGood ? storeRequestedGoodGroup : storeSellList as GUIComponent;
|
||||
itemFrame = CreateItemFrame(new PurchasedItem(itemPrefab, itemQuantity), priceInfo, parentComponent, forceDisable: !hasPermissions);
|
||||
itemFrame = CreateItemFrame(new PurchasedItem(itemPrefab, itemQuantity), parentComponent, StoreTab.Sell, forceDisable: !hasPermissions);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -766,13 +860,91 @@ namespace Barotrauma
|
||||
removedItemFrames.AddRange(storeRequestedGoodGroup.Children.Where(c => c.UserData is PurchasedItem).Except(existingItemFrames).ToList());
|
||||
}
|
||||
removedItemFrames.ForEach(f => f.RectTransform.Parent = null);
|
||||
if (IsSelling) { FilterStoreItems(); }
|
||||
if (activeTab == StoreTab.Sell) { FilterStoreItems(); }
|
||||
SortItems(StoreTab.Sell);
|
||||
|
||||
storeSellList.BarScroll = prevSellListScroll;
|
||||
shoppingCrateSellList.BarScroll = prevShoppingCrateScroll;
|
||||
}
|
||||
|
||||
private void RefreshStoreSellFromSubList()
|
||||
{
|
||||
float prevSellListScroll = storeSellFromSubList.BarScroll;
|
||||
float prevShoppingCrateScroll = shoppingCrateSellFromSubList.BarScroll;
|
||||
bool hasPermissions = HasPermissions;
|
||||
HashSet<GUIComponent> existingItemFrames = new HashSet<GUIComponent>();
|
||||
|
||||
if ((storeRequestedSubGoodGroup != null) != CurrentLocation.RequestedGoods.Any())
|
||||
{
|
||||
if (storeRequestedSubGoodGroup == null)
|
||||
{
|
||||
storeRequestedSubGoodGroup = CreateDealsGroup(storeSellList);
|
||||
storeRequestedSubGoodGroup.Parent.SetAsFirstChild();
|
||||
}
|
||||
else
|
||||
{
|
||||
storeSellFromSubList.RemoveChild(storeRequestedSubGoodGroup.Parent);
|
||||
storeRequestedSubGoodGroup = null;
|
||||
}
|
||||
storeSellFromSubList.RecalculateChildren();
|
||||
}
|
||||
|
||||
foreach (PurchasedItem item in itemsToSellFromSub)
|
||||
{
|
||||
CreateOrUpdateItemFrame(item.ItemPrefab, item.Quantity);
|
||||
}
|
||||
|
||||
foreach (var requestedGood in CurrentLocation.RequestedGoods)
|
||||
{
|
||||
if (itemsToSellFromSub.Any(pi => pi.ItemPrefab == requestedGood)) { continue; }
|
||||
CreateOrUpdateItemFrame(requestedGood, 0);
|
||||
}
|
||||
|
||||
void CreateOrUpdateItemFrame(ItemPrefab itemPrefab, int itemQuantity)
|
||||
{
|
||||
PriceInfo priceInfo = itemPrefab.GetPriceInfo(CurrentLocation);
|
||||
if (priceInfo == null) { return; }
|
||||
var isRequestedGood = CurrentLocation.RequestedGoods.Contains(itemPrefab);
|
||||
var itemFrame = isRequestedGood ?
|
||||
storeRequestedSubGoodGroup.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab == itemPrefab) :
|
||||
storeSellFromSubList.Content.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab == itemPrefab);
|
||||
if (CargoManager.ItemsInSellFromSubCrate.Find(i => i.ItemPrefab == itemPrefab) is PurchasedItem itemInSellFromSubCrate)
|
||||
{
|
||||
itemQuantity = Math.Max(itemQuantity - itemInSellFromSubCrate.Quantity, 0);
|
||||
}
|
||||
if (itemFrame == null)
|
||||
{
|
||||
var parentComponent = isRequestedGood ? storeRequestedSubGoodGroup : storeSellFromSubList as GUIComponent;
|
||||
itemFrame = CreateItemFrame(new PurchasedItem(itemPrefab, itemQuantity), parentComponent, StoreTab.SellFromSub, forceDisable: !hasPermissions);
|
||||
}
|
||||
else
|
||||
{
|
||||
(itemFrame.UserData as PurchasedItem).Quantity = itemQuantity;
|
||||
SetQuantityLabelText(StoreTab.SellFromSub, itemFrame);
|
||||
SetOwnedLabelText(itemFrame);
|
||||
SetPriceGetters(itemFrame, false);
|
||||
}
|
||||
SetItemFrameStatus(itemFrame, hasPermissions && itemQuantity > 0);
|
||||
if (itemQuantity < 1 && !isRequestedGood)
|
||||
{
|
||||
itemFrame.Visible = false;
|
||||
}
|
||||
existingItemFrames.Add(itemFrame);
|
||||
}
|
||||
|
||||
var removedItemFrames = storeSellFromSubList.Content.Children.Where(c => c.UserData is PurchasedItem).Except(existingItemFrames).ToList();
|
||||
if (storeRequestedSubGoodGroup != null)
|
||||
{
|
||||
removedItemFrames.AddRange(storeRequestedSubGoodGroup.Children.Where(c => c.UserData is PurchasedItem).Except(existingItemFrames).ToList());
|
||||
}
|
||||
removedItemFrames.ForEach(f => f.RectTransform.Parent = null);
|
||||
if (activeTab == StoreTab.SellFromSub) { FilterStoreItems(); }
|
||||
SortItems(StoreTab.SellFromSub);
|
||||
|
||||
storeSellFromSubList.BarScroll = prevSellListScroll;
|
||||
shoppingCrateSellFromSubList.BarScroll = prevShoppingCrateScroll;
|
||||
}
|
||||
|
||||
private void SetPriceGetters(GUIComponent itemFrame, bool buying)
|
||||
{
|
||||
if (itemFrame == null || !(itemFrame.UserData is PurchasedItem pi)) { return; }
|
||||
@@ -834,7 +1006,38 @@ namespace Barotrauma
|
||||
needsItemsToSellRefresh = false;
|
||||
}
|
||||
|
||||
private void RefreshShoppingCrateList(List<PurchasedItem> items, GUIListBox listBox)
|
||||
public void RefreshItemsToSellFromSub()
|
||||
{
|
||||
itemsToSellFromSub.Clear();
|
||||
var subItems = CargoManager.GetSellableItemsFromSub();
|
||||
foreach (Item subItem in subItems)
|
||||
{
|
||||
if (itemsToSellFromSub.FirstOrDefault(i => i.ItemPrefab == subItem.Prefab) is PurchasedItem item)
|
||||
{
|
||||
item.Quantity += 1;
|
||||
}
|
||||
else if (subItem.Prefab.GetPriceInfo(CurrentLocation) != null)
|
||||
{
|
||||
itemsToSellFromSub.Add(new PurchasedItem(subItem.Prefab, 1));
|
||||
}
|
||||
}
|
||||
|
||||
// Remove items from sell crate if they aren't on the sub anymore
|
||||
var itemsInCrate = new List<PurchasedItem>(CargoManager.ItemsInSellFromSubCrate);
|
||||
foreach (PurchasedItem crateItem in itemsInCrate)
|
||||
{
|
||||
var subItem = itemsToSellFromSub.Find(i => i.ItemPrefab == crateItem.ItemPrefab);
|
||||
var subItemQuantity = subItem != null ? subItem.Quantity : 0;
|
||||
if (crateItem.Quantity > subItemQuantity)
|
||||
{
|
||||
CargoManager.ModifyItemQuantityInSellFromSubCrate(crateItem.ItemPrefab, subItemQuantity - crateItem.Quantity);
|
||||
}
|
||||
}
|
||||
sellableItemsFromSubUpdateTimer = 0.0f;
|
||||
needsItemsToSellFromSubRefresh = false;
|
||||
}
|
||||
|
||||
private void RefreshShoppingCrateList(List<PurchasedItem> items, GUIListBox listBox, StoreTab tab)
|
||||
{
|
||||
bool hasPermissions = HasPermissions;
|
||||
HashSet<GUIComponent> existingItemFrames = new HashSet<GUIComponent>();
|
||||
@@ -848,7 +1051,7 @@ namespace Barotrauma
|
||||
GUINumberInput numInput = null;
|
||||
if (itemFrame == null)
|
||||
{
|
||||
itemFrame = CreateItemFrame(item, priceInfo, listBox, forceDisable: !hasPermissions);
|
||||
itemFrame = CreateItemFrame(item, listBox, tab, forceDisable: !hasPermissions);
|
||||
numInput = itemFrame.FindChild(c => c is GUINumberInput, recursive: true) as GUINumberInput;
|
||||
}
|
||||
else
|
||||
@@ -859,6 +1062,7 @@ namespace Barotrauma
|
||||
{
|
||||
numInput.UserData = item;
|
||||
numInput.Enabled = hasPermissions;
|
||||
numInput.MaxValueInt = GetMaxAvailable(item.ItemPrefab, tab);
|
||||
}
|
||||
SetOwnedLabelText(itemFrame);
|
||||
SetItemFrameStatus(itemFrame, hasPermissions);
|
||||
@@ -873,7 +1077,7 @@ namespace Barotrauma
|
||||
}
|
||||
suppressBuySell = false;
|
||||
|
||||
var price = listBox == shoppingCrateBuyList ?
|
||||
var price = tab == StoreTab.Buy ?
|
||||
CurrentLocation.GetAdjustedItemBuyPrice(item.ItemPrefab, priceInfo: priceInfo) :
|
||||
CurrentLocation.GetAdjustedItemSellPrice(item.ItemPrefab, priceInfo: priceInfo);
|
||||
totalPrice += item.Quantity * price;
|
||||
@@ -883,24 +1087,32 @@ namespace Barotrauma
|
||||
removedItemFrames.ForEach(f => listBox.Content.RemoveChild(f));
|
||||
|
||||
SortItems(listBox, SortingMethod.CategoryAsc);
|
||||
listBox.UpdateScrollBarSize();
|
||||
if (listBox == shoppingCrateBuyList)
|
||||
listBox.UpdateScrollBarSize();
|
||||
switch (tab)
|
||||
{
|
||||
buyTotal = totalPrice;
|
||||
if (IsBuying) { SetShoppingCrateTotalText(); }
|
||||
case StoreTab.Buy:
|
||||
buyTotal = totalPrice;
|
||||
break;
|
||||
case StoreTab.Sell:
|
||||
sellTotal = totalPrice;
|
||||
break;
|
||||
case StoreTab.SellFromSub:
|
||||
sellFromSubTotal = totalPrice;
|
||||
break;
|
||||
}
|
||||
else
|
||||
if (activeTab == tab)
|
||||
{
|
||||
sellTotal = totalPrice;
|
||||
if(IsSelling) { SetShoppingCrateTotalText(); }
|
||||
SetShoppingCrateTotalText();
|
||||
}
|
||||
SetClearAllButtonStatus();
|
||||
SetConfirmButtonStatus();
|
||||
}
|
||||
|
||||
private void RefreshShoppingCrateBuyList() => RefreshShoppingCrateList(CargoManager.ItemsInBuyCrate, shoppingCrateBuyList);
|
||||
private void RefreshShoppingCrateBuyList() => RefreshShoppingCrateList(CargoManager.ItemsInBuyCrate, shoppingCrateBuyList, StoreTab.Buy);
|
||||
|
||||
private void RefreshShoppingCrateSellList() => RefreshShoppingCrateList(CargoManager.ItemsInSellCrate, shoppingCrateSellList);
|
||||
private void RefreshShoppingCrateSellList() => RefreshShoppingCrateList(CargoManager.ItemsInSellCrate, shoppingCrateSellList, StoreTab.Sell);
|
||||
|
||||
private void RefreshShoppingCrateSellFromSubList() => RefreshShoppingCrateList(CargoManager.ItemsInSellFromSubCrate, shoppingCrateSellFromSubList, StoreTab.SellFromSub);
|
||||
|
||||
private void SortItems(GUIListBox list, SortingMethod sortingMethod)
|
||||
{
|
||||
@@ -932,7 +1144,7 @@ namespace Barotrauma
|
||||
else if (sortingMethod == SortingMethod.PriceAsc || sortingMethod == SortingMethod.PriceDesc)
|
||||
{
|
||||
SortItems(list, SortingMethod.AlphabeticalAsc);
|
||||
if (list == storeSellList || list == shoppingCrateSellList)
|
||||
if (list != storeBuyList && list != shoppingCrateBuyList)
|
||||
{
|
||||
list.Content.RectTransform.SortChildren(CompareBySellPrice);
|
||||
if (GetSpecialsGroup() is GUILayoutGroup specialsGroup)
|
||||
@@ -1014,6 +1226,10 @@ namespace Barotrauma
|
||||
{
|
||||
return storeRequestedGoodGroup;
|
||||
}
|
||||
else if (list == storeSellFromSubList)
|
||||
{
|
||||
return storeRequestedSubGoodGroup;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
@@ -1045,15 +1261,20 @@ namespace Barotrauma
|
||||
|
||||
private void SortItems(StoreTab tab, SortingMethod sortingMethod)
|
||||
{
|
||||
if (IsTabUnavailable(tab)) { return; }
|
||||
tabSortingMethods[tab] = sortingMethod;
|
||||
SortItems(tabLists[tab], sortingMethod);
|
||||
}
|
||||
|
||||
private void SortItems(StoreTab tab) => SortItems(tab, tabSortingMethods[tab]);
|
||||
private void SortItems(StoreTab tab)
|
||||
{
|
||||
if (IsTabUnavailable(tab)) { return; }
|
||||
SortItems(tab, tabSortingMethods[tab]);
|
||||
}
|
||||
|
||||
private void SortActiveTabItems(SortingMethod sortingMethod) => SortItems(activeTab, sortingMethod);
|
||||
|
||||
private GUIComponent CreateItemFrame(PurchasedItem pi, PriceInfo priceInfo, GUIComponent parentComponent, bool forceDisable = false)
|
||||
private GUIComponent CreateItemFrame(PurchasedItem pi, GUIComponent parentComponent, StoreTab containingTab, bool forceDisable = false)
|
||||
{
|
||||
var tooltip = pi.ItemPrefab.Name;
|
||||
if (!string.IsNullOrWhiteSpace(pi.ItemPrefab.Description))
|
||||
@@ -1114,8 +1335,8 @@ namespace Barotrauma
|
||||
CanBeFocused = false,
|
||||
Stretch = true
|
||||
};
|
||||
var isSellingRelatedList = parentComponent == storeSellList || parentComponent == storeRequestedGoodGroup || parentComponent == shoppingCrateSellList;
|
||||
var locationHasDealOnItem = isSellingRelatedList ?
|
||||
bool isSellingRelatedList = containingTab != StoreTab.Buy;
|
||||
bool locationHasDealOnItem = isSellingRelatedList ?
|
||||
CurrentLocation.RequestedGoods.Contains(pi.ItemPrefab) : CurrentLocation.DailySpecials.Contains(pi.ItemPrefab);
|
||||
GUITextBlock nameBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), nameAndQuantityGroup.RectTransform),
|
||||
pi.ItemPrefab.Name, font: GUI.SubHeadingFont, textAlignment: Alignment.BottomLeft)
|
||||
@@ -1140,14 +1361,15 @@ namespace Barotrauma
|
||||
};
|
||||
dealIcon.SetAsFirstChild();
|
||||
}
|
||||
var isParentOnLeftSideOfInterface = parentComponent == storeBuyList || parentComponent == storeDailySpecialsGroup ||
|
||||
parentComponent == storeSellList || parentComponent == storeRequestedGoodGroup;
|
||||
bool isParentOnLeftSideOfInterface = parentComponent == storeBuyList || parentComponent == storeDailySpecialsGroup ||
|
||||
parentComponent == storeSellList || parentComponent == storeRequestedGoodGroup ||
|
||||
parentComponent == storeSellFromSubList || parentComponent == storeRequestedSubGoodGroup;
|
||||
GUILayoutGroup shoppingCrateAmountGroup = null;
|
||||
GUINumberInput amountInput = null;
|
||||
if (isParentOnLeftSideOfInterface)
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), nameAndQuantityGroup.RectTransform),
|
||||
CreateQuantityLabelText(isSellingRelatedList ? StoreTab.Sell : StoreTab.Buy, pi.Quantity), font: GUI.Font, textAlignment: Alignment.BottomLeft)
|
||||
CreateQuantityLabelText(containingTab, pi.Quantity), font: GUI.Font, textAlignment: Alignment.BottomLeft)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
Shadow = locationHasDealOnItem,
|
||||
@@ -1156,7 +1378,7 @@ namespace Barotrauma
|
||||
UserData = "quantitylabel"
|
||||
};
|
||||
}
|
||||
else if (!isParentOnLeftSideOfInterface)
|
||||
else
|
||||
{
|
||||
var relativePadding = nameBlock.Padding.X / nameBlock.Rect.Width;
|
||||
shoppingCrateAmountGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f - relativePadding, 0.6f), nameAndQuantityGroup.RectTransform) { RelativeOffset = new Vector2(relativePadding, 0) },
|
||||
@@ -1167,7 +1389,7 @@ namespace Barotrauma
|
||||
amountInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), shoppingCrateAmountGroup.RectTransform), GUINumberInput.NumberType.Int)
|
||||
{
|
||||
MinValueInt = 0,
|
||||
MaxValueInt = GetMaxAvailable(pi.ItemPrefab, isSellingRelatedList ? StoreTab.Sell : StoreTab.Buy),
|
||||
MaxValueInt = GetMaxAvailable(pi.ItemPrefab, containingTab),
|
||||
UserData = pi,
|
||||
IntValue = pi.Quantity
|
||||
};
|
||||
@@ -1394,7 +1616,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private string CreateQuantityLabelText(StoreTab mode, int quantity) => mode == StoreTab.Sell ?
|
||||
private string CreateQuantityLabelText(StoreTab mode, int quantity) => mode != StoreTab.Buy ?
|
||||
TextManager.GetWithVariable("campaignstore.quantity", "[amount]", quantity.ToString()) :
|
||||
TextManager.GetWithVariable("campaignstore.instock", "[amount]", quantity.ToString());
|
||||
|
||||
@@ -1417,10 +1639,16 @@ namespace Barotrauma
|
||||
|
||||
private int GetMaxAvailable(ItemPrefab itemPrefab, StoreTab mode)
|
||||
{
|
||||
var list = mode == StoreTab.Sell ? itemsToSell : CurrentLocation.StoreStock;
|
||||
var list = mode switch
|
||||
{
|
||||
StoreTab.Buy => CurrentLocation.StoreStock,
|
||||
StoreTab.Sell => itemsToSell,
|
||||
StoreTab.SellFromSub => itemsToSellFromSub,
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
if (list.Find(i => i.ItemPrefab == itemPrefab) is PurchasedItem item)
|
||||
{
|
||||
if (mode != StoreTab.Sell)
|
||||
if (mode == StoreTab.Buy)
|
||||
{
|
||||
var purchasedItem = CargoManager.PurchasedItems.Find(i => i.ItemPrefab == item.ItemPrefab);
|
||||
if (purchasedItem != null) { return Math.Max(item.Quantity - purchasedItem.Quantity, 0); }
|
||||
@@ -1469,11 +1697,37 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool AddToShoppingCrate(PurchasedItem item, int quantity = 1) => IsBuying ?
|
||||
ModifyBuyQuantity(item, quantity) : ModifySellQuantity(item, quantity);
|
||||
private bool ModifySellFromSubQuantity(PurchasedItem item, int quantity)
|
||||
{
|
||||
if (item == null || item.ItemPrefab == null) { return false; }
|
||||
if (!HasPermissions) { return false; }
|
||||
if (quantity > 0)
|
||||
{
|
||||
// Make sure there's enough available to sell
|
||||
var itemToSell = CargoManager.ItemsInSellFromSubCrate.Find(i => i.ItemPrefab == item.ItemPrefab);
|
||||
var totalQuantityToSell = itemToSell != null ? itemToSell.Quantity + quantity : quantity;
|
||||
if (totalQuantityToSell > GetMaxAvailable(item.ItemPrefab, StoreTab.SellFromSub)) { return false; }
|
||||
}
|
||||
CargoManager.ModifyItemQuantityInSellFromSubCrate(item.ItemPrefab, quantity);
|
||||
// TODO: GameMain.Client?.SendCampaignState();
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool ClearFromShoppingCrate(PurchasedItem item) => IsBuying ?
|
||||
ModifyBuyQuantity(item, -item.Quantity) : ModifySellQuantity(item, -item.Quantity);
|
||||
private bool AddToShoppingCrate(PurchasedItem item, int quantity = 1) => activeTab switch
|
||||
{
|
||||
StoreTab.Buy => ModifyBuyQuantity(item, quantity),
|
||||
StoreTab.Sell => ModifySellQuantity(item, quantity),
|
||||
StoreTab.SellFromSub => ModifySellFromSubQuantity(item, quantity),
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
|
||||
private bool ClearFromShoppingCrate(PurchasedItem item) => activeTab switch
|
||||
{
|
||||
StoreTab.Buy => ModifyBuyQuantity(item, -item.Quantity),
|
||||
StoreTab.Sell => ModifySellQuantity(item, -item.Quantity),
|
||||
StoreTab.SellFromSub => ModifySellFromSubQuantity(item, -item.Quantity),
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
|
||||
private bool BuyItems()
|
||||
{
|
||||
@@ -1510,18 +1764,17 @@ namespace Barotrauma
|
||||
private bool SellItems()
|
||||
{
|
||||
if (!HasPermissions) { return false; }
|
||||
|
||||
var itemsToSell = new List<PurchasedItem>(CargoManager.ItemsInSellCrate);
|
||||
var itemsToSell = activeTab switch
|
||||
{
|
||||
StoreTab.Sell => new List<PurchasedItem>(CargoManager.ItemsInSellCrate),
|
||||
StoreTab.SellFromSub => new List<PurchasedItem>(CargoManager.ItemsInSellFromSubCrate),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
var itemsToRemove = new List<PurchasedItem>();
|
||||
var totalValue = 0;
|
||||
foreach (PurchasedItem item in itemsToSell)
|
||||
{
|
||||
if (item?.ItemPrefab == null)
|
||||
{
|
||||
itemsToRemove.Add(item);
|
||||
continue;
|
||||
}
|
||||
if (item.ItemPrefab.GetPriceInfo(CurrentLocation) is PriceInfo priceInfo)
|
||||
if (item?.ItemPrefab?.GetPriceInfo(CurrentLocation) is PriceInfo priceInfo)
|
||||
{
|
||||
totalValue += item.Quantity * CurrentLocation.GetAdjustedItemSellPrice(item.ItemPrefab, priceInfo: priceInfo);
|
||||
}
|
||||
@@ -1531,12 +1784,13 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
itemsToRemove.ForEach(i => itemsToSell.Remove(i));
|
||||
|
||||
if (itemsToSell.None() || totalValue > CurrentLocation.StoreCurrentBalance) { return false; }
|
||||
|
||||
CargoManager.SellItems(itemsToSell);
|
||||
GameMain.Client?.SendCampaignState();
|
||||
|
||||
CargoManager.SellItems(itemsToSell, activeTab);
|
||||
if (activeTab == StoreTab.Sell)
|
||||
{
|
||||
// TODO: Implement selling sub items in multiplayer
|
||||
GameMain.Client?.SendCampaignState();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1549,8 +1803,14 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
shoppingCrateTotal.Text = GetCurrencyFormatted(sellTotal);
|
||||
shoppingCrateTotal.TextColor = CurrentLocation != null && sellTotal > CurrentLocation.StoreCurrentBalance ? Color.Red : Color.White;
|
||||
int total = activeTab switch
|
||||
{
|
||||
StoreTab.Sell => sellTotal,
|
||||
StoreTab.SellFromSub => sellFromSubTotal,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
shoppingCrateTotal.Text = GetCurrencyFormatted(total);
|
||||
shoppingCrateTotal.TextColor = CurrentLocation != null && total > CurrentLocation.StoreCurrentBalance ? Color.Red : Color.White;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1580,13 +1840,19 @@ namespace Barotrauma
|
||||
|
||||
private void SetConfirmButtonStatus() => confirmButton.Enabled =
|
||||
HasPermissions && ActiveShoppingCrateList.Content.RectTransform.Children.Any() &&
|
||||
((IsBuying && buyTotal <= PlayerMoney) || (IsSelling && CurrentLocation != null && sellTotal <= CurrentLocation.StoreCurrentBalance));
|
||||
activeTab switch
|
||||
{
|
||||
StoreTab.Buy => buyTotal <= PlayerMoney,
|
||||
StoreTab.Sell => CurrentLocation != null && sellTotal <= CurrentLocation.StoreCurrentBalance,
|
||||
StoreTab.SellFromSub => CurrentLocation != null && sellFromSubTotal <= CurrentLocation.StoreCurrentBalance,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
|
||||
private void SetClearAllButtonStatus() => clearAllButton.Enabled =
|
||||
HasPermissions && ActiveShoppingCrateList.Content.RectTransform.Children.Any();
|
||||
|
||||
private float ownedItemsUpdateTimer = 0.0f;
|
||||
private readonly float ownedItemsUpdateInterval = 1.5f;
|
||||
private float ownedItemsUpdateTimer = 0.0f, sellableItemsFromSubUpdateTimer = 0.0f;
|
||||
private readonly float timerUpdateInterval = 1.5f;
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
@@ -1598,7 +1864,7 @@ namespace Barotrauma
|
||||
{
|
||||
// Update the owned items at short intervals and check if the interface should be refreshed
|
||||
ownedItemsUpdateTimer += deltaTime;
|
||||
if (ownedItemsUpdateTimer >= ownedItemsUpdateInterval)
|
||||
if (ownedItemsUpdateTimer >= timerUpdateInterval)
|
||||
{
|
||||
var prevOwnedItems = new Dictionary<ItemPrefab, int>(OwnedItems);
|
||||
UpdateOwnedItems();
|
||||
@@ -1612,12 +1878,21 @@ namespace Barotrauma
|
||||
needsRefresh = true;
|
||||
}
|
||||
}
|
||||
// Update the sellable sub items at short intervals and check if the interface should be refreshed
|
||||
sellableItemsFromSubUpdateTimer += deltaTime;
|
||||
if (sellableItemsFromSubUpdateTimer >= timerUpdateInterval)
|
||||
{
|
||||
needsItemsToSellFromSubRefresh = true;
|
||||
needsRefresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (needsItemsToSellRefresh) { RefreshItemsToSell(); }
|
||||
if (needsItemsToSellFromSubRefresh) { RefreshItemsToSellFromSub(); }
|
||||
if (needsRefresh || hadPermissions != HasPermissions) { Refresh(updateOwned: ownedItemsUpdateTimer > 0.0f); }
|
||||
if (needsBuyingRefresh) { RefreshBuying(); }
|
||||
if (needsSellingRefresh) { RefreshSelling(); }
|
||||
if (needsSellingFromSubRefresh) { RefreshSellingFromSub(updateItemsToSellFromSub: sellableItemsFromSubUpdateTimer > 0.0f); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ namespace Barotrauma
|
||||
private const int submarinesPerPage = 4;
|
||||
private int currentPage = 1;
|
||||
private int pageCount;
|
||||
private bool transferService, purchaseService, initialized;
|
||||
private readonly bool transferService, purchaseService;
|
||||
private bool initialized;
|
||||
private int deliveryFee;
|
||||
private string deliveryLocationName;
|
||||
|
||||
@@ -27,12 +28,12 @@ namespace Barotrauma
|
||||
private int selectionIndicatorThickness;
|
||||
private GUIImage listBackground;
|
||||
|
||||
private List<SubmarineInfo> subsToShow;
|
||||
private SubmarineDisplayContent[] submarineDisplays = new SubmarineDisplayContent[submarinesPerPage];
|
||||
private readonly List<SubmarineInfo> subsToShow;
|
||||
private readonly SubmarineDisplayContent[] submarineDisplays = new SubmarineDisplayContent[submarinesPerPage];
|
||||
private SubmarineInfo selectedSubmarine = null;
|
||||
private string purchaseAndSwitchText, purchaseOnlyText, deliveryText, currentSubText, deliveryFeeText, priceText, switchText, missingPreviewText, currencyShorthandText, currencyLongText;
|
||||
private RectTransform parent;
|
||||
private Action closeAction;
|
||||
private readonly RectTransform parent;
|
||||
private readonly Action closeAction;
|
||||
private Sprite pageIndicator;
|
||||
|
||||
public static readonly string[] DeliveryTextVariables = new string[] { "[submarinename1]", "[location1]", "[location2]", "[submarinename2]", "[amount]", "[currencyname]" };
|
||||
@@ -42,7 +43,7 @@ namespace Barotrauma
|
||||
|
||||
private static readonly string[] notEnoughCreditsDeliveryTextVariables = new string[] { "[currencyname]", "[submarinename]", "[location1]", "[location2]" };
|
||||
private static readonly string[] notEnoughCreditsPurchaseTextVariables = new string[] { "[currencyname]", "[submarinename]" };
|
||||
private string[] messageBoxOptions;
|
||||
private readonly string[] messageBoxOptions;
|
||||
|
||||
public const int DeliveryFeePerDistanceTravelled = 1000;
|
||||
public static bool ContentRefreshRequired = false;
|
||||
@@ -65,7 +66,7 @@ namespace Barotrauma
|
||||
|
||||
public SubmarineSelection(bool transfer, Action closeAction, RectTransform parent)
|
||||
{
|
||||
if (GameMain.GameSession.Campaign == null) return;
|
||||
if (GameMain.GameSession.Campaign == null) { return; }
|
||||
|
||||
transferService = transfer;
|
||||
purchaseService = !transfer;
|
||||
@@ -83,7 +84,7 @@ namespace Barotrauma
|
||||
messageBoxOptions = new string[2] { TextManager.Get("Yes") + " " + TextManager.Get("initiatevoting"), TextManager.Get("Cancel") };
|
||||
}
|
||||
|
||||
if (Submarine.MainSub?.Info == null) return;
|
||||
if (Submarine.MainSub?.Info == null) { return; }
|
||||
Initialize();
|
||||
}
|
||||
|
||||
@@ -184,8 +185,10 @@ namespace Barotrauma
|
||||
|
||||
for (int i = 0; i < submarineDisplays.Length; i++)
|
||||
{
|
||||
SubmarineDisplayContent submarineDisplayElement = new SubmarineDisplayContent();
|
||||
submarineDisplayElement.background = new GUIFrame(new RectTransform(new Vector2(1f / submarinesPerPage, 1f), submarineHorizontalGroup.RectTransform), style: null, new Color(8, 13, 19));
|
||||
SubmarineDisplayContent submarineDisplayElement = new SubmarineDisplayContent
|
||||
{
|
||||
background = new GUIFrame(new RectTransform(new Vector2(1f / submarinesPerPage, 1f), submarineHorizontalGroup.RectTransform), style: null, new Color(8, 13, 19))
|
||||
};
|
||||
submarineDisplayElement.submarineImage = new GUIImage(new RectTransform(new Vector2(0.8f, 1f), submarineDisplayElement.background.RectTransform, Anchor.Center), null, true);
|
||||
submarineDisplayElement.middleTextBlock = new GUITextBlock(new RectTransform(new Vector2(0.8f, 1f), submarineDisplayElement.background.RectTransform, Anchor.Center), string.Empty, textAlignment: Alignment.Center);
|
||||
submarineDisplayElement.submarineName = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUI.SubHeadingFont);
|
||||
@@ -433,7 +436,7 @@ namespace Barotrauma
|
||||
|
||||
private SubmarineInfo GetSubToDisplay(int index)
|
||||
{
|
||||
if (subsToShow.Count <= index || index < 0) return null;
|
||||
if (subsToShow.Count <= index || index < 0) { return null; }
|
||||
return subsToShow[index];
|
||||
}
|
||||
|
||||
@@ -626,7 +629,6 @@ namespace Barotrauma
|
||||
if (GameMain.Client == null)
|
||||
{
|
||||
SubmarineInfo newSub = GameMain.GameSession.SwitchSubmarine(selectedSubmarine, deliveryFee);
|
||||
GameMain.GameSession.Campaign.UpgradeManager.RefundResetAndReload(newSub);
|
||||
RefreshSubmarineDisplay(true);
|
||||
}
|
||||
else
|
||||
@@ -661,7 +663,6 @@ namespace Barotrauma
|
||||
{
|
||||
GameMain.GameSession.PurchaseSubmarine(selectedSubmarine);
|
||||
SubmarineInfo newSub = GameMain.GameSession.SwitchSubmarine(selectedSubmarine, 0);
|
||||
GameMain.GameSession.Campaign.UpgradeManager.RefundResetAndReload(newSub);
|
||||
RefreshSubmarineDisplay(true);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -228,7 +228,10 @@ namespace Barotrauma
|
||||
|
||||
var crewButton = createTabButton(InfoFrameTab.Crew, "crew");
|
||||
|
||||
var missionButton = createTabButton(InfoFrameTab.Mission, "mission");
|
||||
if (!(GameMain.GameSession?.GameMode is TestGameMode))
|
||||
{
|
||||
createTabButton(InfoFrameTab.Mission, "mission");
|
||||
}
|
||||
|
||||
if (GameMain.GameSession?.GameMode is CampaignMode campaignMode)
|
||||
{
|
||||
@@ -903,51 +906,68 @@ namespace Barotrauma
|
||||
infoFrame.ClearChildren();
|
||||
GUIFrame missionFrame = new GUIFrame(new RectTransform(Vector2.One, infoFrame.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox");
|
||||
int padding = (int)(0.0245f * missionFrame.Rect.Height);
|
||||
Location location = GameMain.GameSession.EndLocation != null ? GameMain.GameSession.EndLocation : GameMain.GameSession.StartLocation;
|
||||
GUIFrame missionFrameContent = new GUIFrame(new RectTransform(new Point(missionFrame.Rect.Width - padding * 2, missionFrame.Rect.Height - padding * 2), infoFrame.RectTransform, Anchor.Center), style: null);
|
||||
Location location = GameMain.GameSession.EndLocation ?? GameMain.GameSession.StartLocation;
|
||||
|
||||
GUILayoutGroup locationInfoContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.3f), missionFrameContent.RectTransform))
|
||||
{
|
||||
AbsoluteSpacing = GUI.IntScale(10)
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), locationInfoContainer.RectTransform), location.Name, font: GUI.LargeFont);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), locationInfoContainer.RectTransform), location.Type.Name, font: GUI.SubHeadingFont);
|
||||
|
||||
var biomeLabel = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), locationInfoContainer.RectTransform),
|
||||
TextManager.Get("Biome", fallBackTag: "location"), font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), biomeLabel.RectTransform), Level.Loaded.LevelData.Biome.DisplayName, textAlignment: Alignment.CenterRight);
|
||||
var difficultyLabel = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), locationInfoContainer.RectTransform),
|
||||
TextManager.Get("LevelDifficulty"), font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), difficultyLabel.RectTransform), ((int)Level.Loaded.LevelData.Difficulty) + " %", textAlignment: Alignment.CenterRight);
|
||||
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), missionFrameContent.RectTransform) { AbsoluteOffset = new Point(0, locationInfoContainer.Rect.Height + padding) }, style: "HorizontalLine")
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
int locationInfoYOffset = locationInfoContainer.Rect.Height + padding * 2;
|
||||
|
||||
Sprite portrait = location.Type.GetPortrait(location.PortraitId);
|
||||
bool hasPortrait = portrait != null && portrait.SourceRect.Width > 0 && portrait.SourceRect.Height > 0;
|
||||
int contentWidth = hasPortrait ? (int)(missionFrame.Rect.Width * 0.951f) : missionFrame.Rect.Width - padding * 2;
|
||||
|
||||
Vector2 locationNameSize = GUI.LargeFont.MeasureString(location.Name);
|
||||
Vector2 locationTypeSize = GUI.SubHeadingFont.MeasureString(location.Name);
|
||||
GUITextBlock locationNameText = new GUITextBlock(new RectTransform(new Point(contentWidth, (int)locationNameSize.Y), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, padding) }, location.Name, font: GUI.LargeFont);
|
||||
GUITextBlock locationTypeText = new GUITextBlock(new RectTransform(new Point(contentWidth, (int)locationTypeSize.Y), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationNameText.Rect.Height + padding) }, location.Type.Name, font: GUI.SubHeadingFont);
|
||||
|
||||
int locationInfoYOffset = locationNameText.Rect.Height + locationTypeText.Rect.Height + padding * 2;
|
||||
|
||||
GUIListBox missionList;
|
||||
int contentWidth = missionFrameContent.Rect.Width;
|
||||
|
||||
if (hasPortrait)
|
||||
{
|
||||
GUIFrame portraitHolder = new GUIFrame(new RectTransform(new Point(contentWidth, (int)(missionFrame.Rect.Height * 0.588f)), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationInfoYOffset) });
|
||||
float portraitAspectRatio = portrait.SourceRect.Width / portrait.SourceRect.Height;
|
||||
GUIImage portraitImage = new GUIImage(new RectTransform(new Vector2(1.0f, 1f), portraitHolder.RectTransform), portrait, scaleToFit: true);
|
||||
portraitHolder.RectTransform.NonScaledSize = new Point(portraitImage.Rect.Size.X, (int)(portraitImage.Rect.Size.X / portraitAspectRatio));
|
||||
GUIImage portraitImage = new GUIImage(new RectTransform(new Vector2(0.5f, 1f), locationInfoContainer.RectTransform, Anchor.CenterRight), portrait, scaleToFit: true)
|
||||
{
|
||||
IgnoreLayoutGroups = true
|
||||
};
|
||||
locationInfoContainer.Recalculate();
|
||||
portraitImage.RectTransform.NonScaledSize = new Point(Math.Min((int)(portraitImage.Rect.Size.Y * portraitAspectRatio), portraitImage.Rect.Width), portraitImage.Rect.Size.Y);
|
||||
}
|
||||
|
||||
missionList = new GUIListBox(new RectTransform(new Point(contentWidth, missionFrame.Rect.Bottom - portraitHolder.Rect.Bottom - padding), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, portraitHolder.RectTransform.AbsoluteOffset.Y + portraitHolder.Rect.Height + padding) });
|
||||
}
|
||||
else
|
||||
{
|
||||
missionList = new GUIListBox(new RectTransform(new Point(contentWidth, missionFrame.Rect.Height - locationInfoYOffset - padding), missionFrame.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationInfoYOffset) });
|
||||
}
|
||||
GUIListBox missionList = new GUIListBox(new RectTransform(new Point(contentWidth, missionFrameContent.Rect.Height - locationInfoYOffset), missionFrameContent.RectTransform, Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationInfoYOffset) });
|
||||
missionList.ContentBackground.Color = Color.Transparent;
|
||||
missionList.Spacing = GUI.IntScale(15);
|
||||
|
||||
if (GameMain.GameSession?.Missions != null)
|
||||
{
|
||||
int spacing = GUI.IntScale(5);
|
||||
int iconSize = (int)(GUI.LargeFont.MeasureChar('T').Y + GUI.Font.MeasureChar('T').Y * 4 + spacing * 4);
|
||||
|
||||
foreach (Mission mission in GameMain.GameSession.Missions)
|
||||
{
|
||||
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) { RelativeOffset = new Vector2(0.225f, 0f) }, false, childAnchor: Anchor.TopLeft)
|
||||
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 = GUI.IntScale(5)
|
||||
AbsoluteSpacing = spacing
|
||||
};
|
||||
string descriptionText = mission.Description;
|
||||
foreach (string missionMessage in mission.ShownMessages)
|
||||
{
|
||||
descriptionText += "\n\n" + missionMessage;
|
||||
}
|
||||
string rewardText = mission.GetMissionRewardText();
|
||||
string rewardText = mission.GetMissionRewardText(Submarine.MainSub);
|
||||
string reputationText = mission.GetReputationRewardText(mission.Locations[0]);
|
||||
|
||||
var missionNameRichTextData = RichTextData.GetRichTextData(mission.Name, out string missionNameString);
|
||||
@@ -974,12 +994,12 @@ namespace Barotrauma
|
||||
|
||||
if (mission.Prefab.Icon != null)
|
||||
{
|
||||
float iconAspectRatio = mission.Prefab.Icon.SourceRect.Width / mission.Prefab.Icon.SourceRect.Height;
|
||||
/*float iconAspectRatio = mission.Prefab.Icon.SourceRect.Width / mission.Prefab.Icon.SourceRect.Height;
|
||||
int iconWidth = (int)(0.225f * missionDescriptionHolder.RectTransform.NonScaledSize.X);
|
||||
int iconHeight = Math.Max(missionTextGroup.RectTransform.NonScaledSize.Y, (int)(iconWidth * iconAspectRatio));
|
||||
Point iconSize = new Point(iconWidth, iconHeight);
|
||||
Point iconSize = new Point(iconWidth, iconHeight);*/
|
||||
|
||||
new GUIImage(new RectTransform(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,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user