2 using System.Collections.Generic;
3 using System.Collections.Immutable;
4 using Microsoft.Xna.Framework;
5 using Microsoft.Xna.Framework.Graphics;
8 using System.Globalization;
17 private static bool initialized =
false;
19 private static UISprite spectateIcon, disconnectedIcon;
20 private static Sprite ownerIcon, moderatorIcon;
24 private GUIFrame infoFrame, contentFrame;
26 private readonly List<GUIButton> tabButtons =
new List<GUIButton>();
28 private List<LinkedGUI> linkedGUIList;
31 private float sizeMultiplier = 1f;
33 private IEnumerable<Character> crew;
34 private List<CharacterTeamType> teamIDs;
35 private const string inLobbyString =
"\u2022 \u2022 \u2022";
40 private bool isTransferMenuOpen;
41 private bool isSending;
44 private float transferMenuOpenState;
45 private bool transferMenuStateCompleted;
46 private readonly HashSet<Identifier> registeredEvents =
new HashSet<Identifier>();
47 private readonly TalentMenu talentMenu =
new TalentMenu();
49 private class LinkedGUI
51 private const ushort lowPingThreshold = 100;
52 private const ushort mediumPingThreshold = 200;
56 private ushort currentPing;
58 private readonly
bool wasCharacterAlive;
62 private readonly
GUIImage permissionIcon;
67 this.textBlock = textBlock;
69 this.permissionIcon = permissionIcon;
76 this.character = character;
77 this.textBlock = textBlock;
79 wasCharacterAlive = character !=
null && !character.
IsDead;
82 public bool HasMultiplayerCharacterChanged()
84 if (
Client ==
null) {
return false; }
86 if (GameSettings.CurrentConfig.VerboseLogging)
90 DebugConsole.Log($
"Refreshing tab menu crew list (client \"{Client.Name}\"'s character changed from \"{character?.Name ?? "null"}\" to \"{Client.Character?.Name ?? "null"}\")");
96 public bool HasCharacterDied()
98 if (character ==
null) {
return false; }
99 bool isAlive = !(character?.IsDead ??
true);
100 if (GameSettings.CurrentConfig.VerboseLogging)
102 if (wasCharacterAlive && !isAlive)
104 DebugConsole.Log(
Client ==
null ?
105 $
"Refreshing tab menu crew list (character \"{character?.Name ?? "null"}\" died)" :
106 $
"Refreshing tab menu crew list (client \"{Client.Name}\"'s character \"{character?.Name ?? "null"}\" died)");
108 else if (!wasCharacterAlive && isAlive)
110 DebugConsole.Log(
Client ==
null ?
112 $
"Refreshing tab menu crew list (character \"{character?.Name ?? "null"}\" came back to life)" :
113 $
"Refreshing tab menu crew list (client \"{Client.Name}\"'s character \"{character?.Name ?? "null"}\" came back to life)");
116 return isAlive != wasCharacterAlive;
119 public void TryPingRefresh()
121 if (
Client ==
null) {
return; }
124 textBlock.Text = currentPing.ToString();
125 textBlock.TextColor = GetPingColor();
128 public void TryPermissionIconRefresh(Sprite icon)
130 if (
Client ==
null || permissionIcon ==
null) {
return; }
131 permissionIcon.Sprite = icon;
134 private Color GetPingColor()
136 if (currentPing < lowPingThreshold)
138 return GUIStyle.Green;
140 else if (currentPing < mediumPingThreshold)
142 return GUIStyle.Yellow;
150 public void Remove(GUIFrame parent)
152 parent.RemoveChild(frame);
160 ownerIcon = GUIStyle.GetComponentStyle(
"OwnerIcon").GetDefaultSprite();
161 moderatorIcon = GUIStyle.GetComponentStyle(
"ModeratorIcon").GetDefaultSprite();
179 float menuOpenSpeed = deltaTime * 10f;
180 if (isTransferMenuOpen)
182 if (transferMenuStateCompleted)
184 transferMenuOpenState = transferMenuOpenState < 0.25f ? Math.Min(0.25f, transferMenuOpenState + (menuOpenSpeed / 2f)) : 0.25f;
188 if (transferMenuOpenState > 0.15f)
190 transferMenuStateCompleted =
false;
191 transferMenuOpenState = Math.Max(0.15f, transferMenuOpenState - menuOpenSpeed);
195 transferMenuStateCompleted =
true;
201 transferMenuStateCompleted =
false;
202 if (transferMenuOpenState < 1f)
204 transferMenuOpenState = Math.Min(1f, transferMenuOpenState + menuOpenSpeed);
208 if (transferMenu !=
null && transferMenuButton !=
null)
210 int pos = (int)(transferMenuOpenState * -transferMenu.
Rect.Height);
216 talentMenu?.Update();
219 if (linkedGUIList ==
null) {
return; }
223 for (
int i = 0; i < linkedGUIList.Count; i++)
225 linkedGUIList[i].TryPingRefresh();
226 linkedGUIList[i].TryPermissionIconRefresh(GetPermissionIcon(linkedGUIList[i].
Client));
227 if (linkedGUIList[i].HasMultiplayerCharacterChanged() || linkedGUIList[i].HasCharacterDied())
229 RemoveCurrentElements();
230 CreateMultiPlayerList(
true);
237 for (
int i = 0; i < linkedGUIList.Count; i++)
239 if (linkedGUIList[i].HasCharacterDied())
241 RemoveCurrentElements();
242 CreateSinglePlayerList(
true);
257 storedMessages.Clear();
270 Vector2 contentFrameSize =
new Vector2(0.45f, 0.667f);
275 RelativeSpacing = 0.01f
278 var buttonArea =
new GUILayoutGroup(
new RectTransform(
new Vector2(0.07f, 1f), parent: horizontalLayoutGroup.RectTransform), isHorizontal:
false)
280 AbsoluteSpacing = GUI.IntScale(5f)
282 var innerLayoutGroup =
new GUILayoutGroup(
new RectTransform(
new Vector2(0.92f, 1f), horizontalLayoutGroup.RectTransform))
284 RelativeSpacing = 0.01f,
288 float absoluteSpacing = innerLayoutGroup.
RelativeSpacing * innerLayoutGroup.Rect.Height;
289 int multiplier = GameMain.GameSession?.GameMode is CampaignMode ? 2 : 1;
290 int infoFrameHolderHeight = Math.Min((
int)(0.97f * innerLayoutGroup.Rect.Height), (
int)(innerLayoutGroup.Rect.Height - multiplier * (GUI.IntScale(15f) + absoluteSpacing)));
291 infoFrameHolder =
new GUIFrame(
new RectTransform(
new Point(innerLayoutGroup.Rect.Width, infoFrameHolderHeight), parent: innerLayoutGroup.RectTransform), style:
null);
293 GUIButton createTabButton(
InfoFrameTab tab,
string textTag)
295 var newButton =
new GUIButton(
new RectTransform(Vector2.One, buttonArea.RectTransform, scaleBasis:
ScaleBasis.BothWidth), style: $
"InfoFrameTabButton.{tab}")
298 ToolTip = TextManager.Get(textTag),
301 tabButtons.Add(newButton);
305 var crewButton = createTabButton(
InfoFrameTab.Crew,
"crew");
307 if (GameMain.GameSession?.GameMode is not TestGameMode)
309 var missionBtn = createTabButton(
InfoFrameTab.Mission,
"mission");
310 eventLogNotification = GameSession.CreateNotificationIcon(missionBtn);
311 eventLogNotification.
Visible = GameMain.GameSession?.EventManager?.EventLog?.UnreadEntries ??
false;
312 if (eventLogNotification.
Visible)
314 eventLogNotification.
Pulsate(Vector2.One, Vector2.One * 2, 1.0f);
318 if (GameMain.GameSession?.GameMode is CampaignMode campaignMode)
320 var reputationButton = createTabButton(
InfoFrameTab.Reputation,
"reputation");
322 var balanceFrame =
new GUIFrame(
new RectTransform(
new Point(innerLayoutGroup.Rect.Width, innerLayoutGroup.Rect.Height - infoFrameHolderHeight), parent: innerLayoutGroup.RectTransform), style:
"InnerFrame");
323 GUILayoutGroup salaryFrame =
new GUILayoutGroup(
new RectTransform(
new Vector2(0.66f, 1f), balanceFrame.RectTransform), isHorizontal:
true, childAnchor:
Anchor.CenterLeft);
325 GUIScrollBar salaryScrollBar =
null;
326 GUITextBlock salaryPercentage =
null;
327 if (GameMain.GameSession?.GameMode is MultiPlayerCampaign)
329 float value = campaignMode.Bank.RewardDistribution;
330 GUITextBlock salaryText =
new GUITextBlock(
new RectTransform(
new Vector2(0.25f, 1f), salaryFrame.RectTransform), TextManager.Get(
"defaultsalary"), textAlignment: Alignment.Center)
332 AutoScaleHorizontal =
true
334 salaryScrollBar =
new GUIScrollBar(
new RectTransform(
new Vector2(0.4f, 1f), salaryFrame.RectTransform), barSize: 0.1f, style:
"GUISlider")
336 Range =
new Vector2(0, 1),
337 BarScrollValue = value / 100f,
342 salaryPercentage =
new GUITextBlock(
new RectTransform(
new Vector2(0.15f, 1f), salaryFrame.RectTransform),
"0", textAlignment: Alignment.Center)
344 Text = ValueToPercentage(RoundRewardDistribution(salaryScrollBar.BarScroll, salaryScrollBar.Step))
347 salaryScrollBar.OnMoved = (scrollBar, value) =>
349 salaryPercentage.Text = ValueToPercentage(RoundRewardDistribution(value, scrollBar.Step));
352 salaryScrollBar.OnReleased = (bar, scroll) =>
354 int newRewardDistribution = RoundRewardDistribution(scroll, bar.Step);
355 SetRewardDistribution(Option.None, newRewardDistribution);
359 var resetButton =
new GUIButton(
new RectTransform(
new Vector2(0.2f, 1f), salaryFrame.RectTransform), TextManager.Get(
"ResetSalaries"), style:
"GUIButtonSmall")
361 TextBlock = { AutoScaleHorizontal =
true },
362 ToolTip = TextManager.Get(
"resetsalaries.tooltip"),
363 OnClicked = (button, userData) =>
365 GUI.AskForConfirmation(TextManager.Get(
"ResetSalaries"), TextManager.Get(
"ResetSalaries.Warning"), onConfirm: ResetRewardDistributions);
370 void UpdateSliderEnabled()
371 => salaryScrollBar.Enabled = resetButton.Enabled = CampaignMode.AllowedToManageWallets();
372 UpdateSliderEnabled();
374 Identifier defaultSalaryEventIdentifier =
"DefaultSalarySlider".ToIdentifier();
375 GameMain.Client?.OnPermissionChanged?.RegisterOverwriteExisting(defaultSalaryEventIdentifier, _ => UpdateSliderEnabled());
377 GUITextBlock balanceText =
new GUITextBlock(
new RectTransform(
new Vector2(0.33f, 1f), balanceFrame.RectTransform,
Anchor.TopRight),
string.Empty, textAlignment: Alignment.Right);
378 if (GameMain.IsMultiplayer)
380 balanceText.ToolTip = TextManager.Get(
"bankdescription");
382 GUIFrame bottomDisclaimerFrame =
new GUIFrame(
new RectTransform(
new Vector2(contentFrameSize.X, 0.1f), infoFrame.
RectTransform)
384 AbsoluteOffset = new Point(contentFrame.Rect.X, contentFrame.Rect.Bottom + GUI.IntScale(8))
387 PendingChangesFrame =
new GUIFrame(
new RectTransform(Vector2.One, bottomDisclaimerFrame.RectTransform,
Anchor.Center), style:
null);
389 if (GameMain.NetLobbyScreen?.CampaignCharacterDiscarded ??
false)
394 SetBalanceText(balanceText, campaignMode.Bank.Balance);
395 Identifier eventIdentifier = nameof(CreateInfoFrame).ToIdentifier();
396 campaignMode.OnMoneyChanged.RegisterOverwriteExisting(eventIdentifier, e =>
398 if (!e.Owner.IsNone()) { return; }
399 SetBalanceText(balanceText, e.Wallet.Balance);
401 if (salaryPercentage is not
null && salaryScrollBar is not
null)
403 float rewardDistribution = e.Wallet.RewardDistribution;
404 salaryScrollBar.BarScrollValue = rewardDistribution / 100f;
405 salaryPercentage.Text = ValueToPercentage(rewardDistribution);
408 registeredEvents.Add(eventIdentifier);
410 static void SetBalanceText(GUITextBlock text,
int balance)
412 text.Text = TextManager.GetWithVariable(
"bankbalanceformat",
"[money]",
string.Format(CultureInfo.InvariantCulture,
"{0:N0}", balance));
415 LocalizedString ValueToPercentage(
float value)
416 => TextManager.GetWithVariable(
"percentageformat",
"[value]", $
"{(int)MathF.Round(value)}");
419 var submarineButton = createTabButton(
InfoFrameTab.Submarine,
"submarine");
421 var talentsButton = createTabButton(
InfoFrameTab.Talents,
"tabmenu.character");
422 talentsButton.OnAddedToGUIUpdateList += (component) =>
424 talentsButton.Enabled =
Character.Controlled?.Info !=
null || GameMain.Client?.CharacterInfo !=
null;
425 if (!talentsButton.Enabled && selectedTab ==
InfoFrameTab.Talents)
431 talentPointNotification = GameSession.CreateNotificationIcon(talentsButton);
438 CreateInfoFrame(selectedTab);
439 tabButtons.ForEach(tb => tb.Selected = (
InfoFrameTab)tb.UserData == selectedTab);
444 CreateCrewListFrame(infoFrameHolder);
447 CreateMissionInfo(infoFrameHolder);
466 private const float jobColumnWidthPercentage = 0.138f,
467 characterColumnWidthPercentage = 0.45f,
468 pingColumnWidthPercentage = 0.206f,
469 walletColumnWidthPercentage = 0.206f;
471 private int jobColumnWidth, characterColumnWidth, pingColumnWidth, walletColumnWidth;
473 private void CreateCrewListFrame(
GUIFrame crewFrame)
476 teamIDs = crew.Select(c => c.TeamID).Distinct().ToList();
479 if (teamIDs.Count > 1 && GameMain.Client?.Character !=
null)
482 teamIDs = teamIDs.OrderBy(i => i != ownTeam).ThenBy(i => i).ToList();
487 var content =
new GUILayoutGroup(
new RectTransform(Vector2.One, crewFrame.
RectTransform));
489 crewListArray =
new GUIListBox[teamIDs.Count];
490 GUILayoutGroup[] headerFrames =
new GUILayoutGroup[teamIDs.Count];
492 float nameHeight = 0.075f;
494 Vector2 crewListSize =
new Vector2(1f, 1f / teamIDs.Count - (teamIDs.Count > 1 ? nameHeight * 1.1f : 0f));
495 for (
int i = 0; i < teamIDs.Count; i++)
497 if (teamIDs.Count > 1)
499 new GUITextBlock(
new RectTransform(
new Vector2(1.0f, nameHeight), content.RectTransform), CombatMission.GetTeamName(teamIDs[i]), textColor: i == 0 ? GUIStyle.Green : GUIStyle.Orange) {
ForceUpperCase =
ForceUpperCase.Yes };
502 headerFrames[i] =
new GUILayoutGroup(
new RectTransform(Vector2.Zero, content.RectTransform,
Anchor.TopLeft,
Pivot.BottomLeft) { AbsoluteOffset = new Point(2, -1) }, isHorizontal:
true)
508 GUIListBox crewList =
new GUIListBox(
new RectTransform(crewListSize, content.RectTransform))
510 Padding =
new Vector4(2, 5, 0, 0),
511 AutoHideScrollBar =
false,
512 PlaySoundOnSelect =
true
514 crewList.UpdateDimensions();
516 if (teamIDs.Count > 1)
518 crewList.OnSelected = (component, obj) =>
520 for (
int i = 0; i < crewListArray.Length; i++)
522 if (crewListArray[i] == crewList)
continue;
525 SelectElement(component.UserData, crewList);
531 crewList.OnSelected = (component, obj) =>
533 SelectElement(component.UserData, crewList);
538 crewListArray[i] = crewList;
541 for (
int i = 0; i < teamIDs.Count; i++)
543 headerFrames[i].
RectTransform.
RelativeSize =
new Vector2(1f - crewListArray[i].ScrollBar.Rect.Width / (
float)crewListArray[i].Rect.Width, GUIStyle.HotkeyFont.Size / (
float)crewFrame.
RectTransform.
Rect.Height * 1.5f);
545 if (!GameMain.IsMultiplayer)
547 CreateSinglePlayerListContentHolder(headerFrames[i]);
551 CreateMultiPlayerListContentHolder(headerFrames[i]);
555 crewFrame.
RectTransform.
AbsoluteOffset =
new Point(0, (
int)(headerFrames[0].Rect.Height * headerFrames.Length) - (teamIDs.Count > 1 ? GUI.IntScale(10f) : 0));
557 float totalRelativeHeight = 0.0f;
558 if (teamIDs.Count > 1) { totalRelativeHeight += teamIDs.Count * nameHeight; }
559 headerFrames.ForEach(f => totalRelativeHeight += f.RectTransform.RelativeSize.Y);
560 crewListArray.ForEach(f => totalRelativeHeight += f.RectTransform.RelativeSize.Y);
561 if (totalRelativeHeight > 1.0f)
563 float heightOverflow = totalRelativeHeight - 1.0f;
564 float heightToReduce = heightOverflow / crewListArray.Length;
565 crewListArray.ForEach(l =>
567 l.RectTransform.Resize(l.RectTransform.RelativeSize -
new Vector2(0.0f, heightToReduce));
568 l.UpdateDimensions();
572 if (GameMain.IsMultiplayer)
574 CreateMultiPlayerList(
false);
575 CreateMultiPlayerLogContent(crewFrame);
579 CreateSinglePlayerList(
false);
583 private void CreateSinglePlayerListContentHolder(GUILayoutGroup headerFrame)
585 GUIButton jobButton =
new GUIButton(
new RectTransform(
new Vector2(0f, 1f), headerFrame.RectTransform), TextManager.Get(
"tabmenu.job"), style:
"GUIButtonSmallFreeScale");
586 GUIButton characterButton =
new GUIButton(
new RectTransform(
new Vector2(0f, 1f), headerFrame.RectTransform), TextManager.Get(
"name"), style:
"GUIButtonSmallFreeScale");
588 sizeMultiplier = (headerFrame.Rect.Width - headerFrame.AbsoluteSpacing * (headerFrame.CountChildren - 1)) / (float)headerFrame.Rect.Width;
590 jobButton.RectTransform.RelativeSize =
new Vector2(jobColumnWidthPercentage * sizeMultiplier, 1f);
591 characterButton.RectTransform.RelativeSize =
new Vector2((1f - jobColumnWidthPercentage * sizeMultiplier) * sizeMultiplier, 1f);
593 jobButton.TextBlock.Font = characterButton.TextBlock.Font = GUIStyle.HotkeyFont;
594 jobButton.CanBeFocused = characterButton.CanBeFocused =
false;
595 jobButton.TextBlock.ForceUpperCase = characterButton.TextBlock.ForceUpperCase =
ForceUpperCase.Yes;
597 jobColumnWidth = jobButton.Rect.Width;
598 characterColumnWidth = characterButton.Rect.Width;
601 private void CreateSinglePlayerList(
bool refresh)
605 crew = GameMain.GameSession.CrewManager.GetCharacters();
608 linkedGUIList =
new List<LinkedGUI>();
610 for (
int i = 0; i < teamIDs.Count; i++)
612 foreach (Character character
in crew.Where(c => c.TeamID == teamIDs[i]))
614 CreateSinglePlayerCharacterElement(character, i);
619 private void CreateSinglePlayerCharacterElement(Character character,
int i)
621 GUIFrame frame =
new GUIFrame(
new RectTransform(
new Point(crewListArray[i].Content.Rect.Width, GUI.IntScale(33f)), crewListArray[i].Content.RectTransform), style:
"ListBoxElement")
623 UserData = character,
627 var paddedFrame =
new GUILayoutGroup(
new RectTransform(
new Vector2(1.0f, 0.9f), frame.RectTransform,
Anchor.Center), isHorizontal:
true)
632 new GUICustomComponent(
new RectTransform(
new Point(jobColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform,
Anchor.Center), onDraw: (sb, component) => character.Info.DrawJobIcon(sb, component.Rect))
634 CanBeFocused =
false,
635 HoverColor = Color.White,
636 SelectedColor = Color.White
639 GUITextBlock characterNameBlock =
new GUITextBlock(
new RectTransform(
new Point(characterColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform),
640 ToolBox.LimitString(character.Info.Name, GUIStyle.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: character.Info.Job.Prefab.UIColor);
642 linkedGUIList.Add(
new LinkedGUI(character, frame, textBlock:
null));
645 private void CreateMultiPlayerListContentHolder(GUILayoutGroup headerFrame)
647 bool isCampaign = GameMain.GameSession?.Campaign is MultiPlayerCampaign;
648 GUIButton jobButton =
new GUIButton(
new RectTransform(
new Vector2(0f, 1f), headerFrame.RectTransform), TextManager.Get(
"tabmenu.job"), style:
"GUIButtonSmallFreeScale");
649 GUIButton characterButton =
new GUIButton(
new RectTransform(
new Vector2(0f, 1f), headerFrame.RectTransform), TextManager.Get(
"name"), style:
"GUIButtonSmallFreeScale");
650 GUIButton pingButton =
new GUIButton(
new RectTransform(
new Vector2(0f, 1f), headerFrame.RectTransform), TextManager.Get(
"serverlistping"), style:
"GUIButtonSmallFreeScale");
653 GUIButton walletButton =
new GUIButton(
new RectTransform(
new Vector2(0f, 1f), headerFrame.RectTransform)
655 RelativeSize = new Vector2(walletColumnWidthPercentage * sizeMultiplier, 1f)
656 }, TextManager.Get(
"crewwallet.wallet"), style:
"GUIButtonSmallFreeScale")
658 TextBlock = { Font = GUIStyle.HotkeyFont },
659 CanBeFocused =
false,
662 walletColumnWidth = walletButton.Rect.Width;
665 sizeMultiplier = (headerFrame.Rect.Width - headerFrame.AbsoluteSpacing * (headerFrame.CountChildren - 1)) / (float)headerFrame.Rect.Width;
667 jobButton.RectTransform.RelativeSize =
new Vector2(jobColumnWidthPercentage * sizeMultiplier, 1f);
668 characterButton.RectTransform.RelativeSize =
new Vector2((characterColumnWidthPercentage + (isCampaign ? 0 : walletColumnWidthPercentage)) * sizeMultiplier, 1f);
669 pingButton.RectTransform.RelativeSize =
new Vector2(pingColumnWidthPercentage * sizeMultiplier, 1f);
671 jobButton.TextBlock.Font = characterButton.TextBlock.Font = pingButton.TextBlock.Font = GUIStyle.HotkeyFont;
672 jobButton.CanBeFocused = characterButton.CanBeFocused = pingButton.CanBeFocused =
false;
673 jobButton.TextBlock.ForceUpperCase = characterButton.TextBlock.ForceUpperCase = pingButton.ForceUpperCase =
ForceUpperCase.Yes;
675 jobColumnWidth = jobButton.Rect.Width;
676 characterColumnWidth = characterButton.Rect.Width;
677 pingColumnWidth = pingButton.Rect.Width;
680 private void CreateMultiPlayerList(
bool refresh)
684 crew = GameMain.GameSession.CrewManager.GetCharacters();
687 linkedGUIList =
new List<LinkedGUI>();
689 var connectedClients = GameMain.Client.ConnectedClients;
691 for (
int i = 0; i < teamIDs.Count; i++)
693 foreach (Character character
in crew.Where(c => c.TeamID == teamIDs[i]))
695 if (!(character is AICharacter) && connectedClients.Any(c => c.Character ==
null && c.Name == character.Name)) {
continue; }
696 CreateMultiPlayerCharacterElement(character, GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.Character == character), i);
700 for (
int j = 0; j < connectedClients.Count; j++)
702 Client client = connectedClients[j];
705 CreateMultiPlayerClientElement(client);
710 private void CreateMultiPlayerCharacterElement(Character character,
Client client,
int i)
712 GUIFrame frame =
new GUIFrame(
new RectTransform(
new Point(crewListArray[i].Content.Rect.Width, GUI.IntScale(33f)), crewListArray[i].Content.RectTransform), style:
"ListBoxElement")
714 UserData = character,
715 Color = (GameMain.NetworkMember !=
null && GameMain.Client.Character == character) ?
OwnCharacterBGColor : Color.Transparent
718 frame.OnSecondaryClicked += (component, data) =>
720 NetLobbyScreen.CreateModerationContextMenu(client);
724 var paddedFrame =
new GUILayoutGroup(
new RectTransform(
new Vector2(1.0f, 0.9f), frame.RectTransform,
Anchor.Center), isHorizontal:
true)
729 new GUICustomComponent(
new RectTransform(
new Point(jobColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform,
Anchor.Center), onDraw: (sb, component) => character.Info.DrawJobIcon(sb, component.Rect))
731 CanBeFocused =
false,
732 HoverColor = Color.White,
733 SelectedColor = Color.White
738 CreateNameWithPermissionIcon(client, paddedFrame, out GUIImage permissionIcon);
739 linkedGUIList.Add(
new LinkedGUI(client, frame,
740 new GUITextBlock(
new RectTransform(
new Point(pingColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform), client.
Ping.ToString(), textAlignment: Alignment.Center),
745 GUITextBlock characterNameBlock =
new GUITextBlock(
new RectTransform(
new Point(characterColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform),
746 ToolBox.LimitString(character.Info.Name, GUIStyle.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: character.Info.Job.Prefab.UIColor);
748 if (character is AICharacter)
750 linkedGUIList.Add(
new LinkedGUI(character, frame,
751 new GUITextBlock(
new RectTransform(
new Point(pingColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform), TextManager.Get(
"tabmenu.bot"), textAlignment: Alignment.Center) { ForceUpperCase = ForceUpperCase.Yes }));
755 linkedGUIList.Add(
new LinkedGUI(client:
null, frame, textBlock:
null, permissionIcon:
null));
757 new GUICustomComponent(
new RectTransform(
new Point(pingColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform,
Anchor.Center), onDraw: (sb, component) => DrawDisconnectedIcon(sb, component.Rect))
759 CanBeFocused =
false,
760 HoverColor = Color.White,
761 SelectedColor = Color.White
766 CreateWalletCrewFrame(character, paddedFrame);
769 private void CreateMultiPlayerClientElement(
Client client)
771 int teamIndex = GetTeamIndex(client);
772 if (teamIndex == -1) teamIndex = 0;
774 GUIFrame frame =
new GUIFrame(
new RectTransform(
new Point(crewListArray[teamIndex].Content.Rect.Width, GUI.IntScale(33f)), crewListArray[teamIndex].Content.RectTransform), style:
"ListBoxElement")
777 Color = Color.Transparent
780 frame.OnSecondaryClicked += (component, data) =>
782 NetLobbyScreen.CreateModerationContextMenu(client);
786 var paddedFrame =
new GUILayoutGroup(
new RectTransform(
new Vector2(1.0f, 0.9f), frame.RectTransform,
Anchor.Center), isHorizontal:
true)
791 new GUICustomComponent(
new RectTransform(
new Point(jobColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform,
Anchor.Center),
792 onDraw: (sb, component) => DrawNotInGameIcon(sb, component.Rect, client))
794 CanBeFocused =
false,
795 HoverColor = Color.White,
796 SelectedColor = Color.White
799 CreateNameWithPermissionIcon(client, paddedFrame, out GUIImage permissionIcon);
800 linkedGUIList.Add(
new LinkedGUI(client, frame,
801 new GUITextBlock(
new RectTransform(
new Point(pingColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform), client.
Ping.ToString(), textAlignment: Alignment.Center),
806 CreateWalletCrewFrame(character, paddedFrame);
810 private int GetTeamIndex(
Client client)
812 if (teamIDs.Count <= 1) {
return 0; }
821 foreach (Character c
in crew)
825 return teamIDs.IndexOf(c.TeamID);
831 foreach (Character c
in crew)
833 if (client.
Name == c.Name)
835 return teamIDs.IndexOf(c.TeamID);
843 private void CreateWalletCrewFrame(Character character, GUILayoutGroup paddedFrame)
845 if (!(GameMain.GameSession?.Campaign is MultiPlayerCampaign)) {
return; }
847 GUILayoutGroup walletLayout =
new GUILayoutGroup(
new RectTransform(
new Point(walletColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform,
Anchor.Center), childAnchor:
Anchor.Center)
852 GUILayoutGroup paddedLayoutGroup =
new GUILayoutGroup(
new RectTransform(
new Vector2(0.9f, 1f), walletLayout.RectTransform,
Anchor.Center), isHorizontal:
true)
857 new GUIFrame(
new RectTransform(Vector2.One, paddedLayoutGroup.RectTransform), style:
null)
859 IgnoreLayoutGroups =
true,
860 ToolTip = TextManager.Get(
"walletdescription")
863 if (character.IsBot) {
return; }
865 Sprite walletSprite = GUIStyle.CrewWalletIconSmall.Value.Sprite;
867 GUIImage icon =
new GUIImage(
new RectTransform(Vector2.One, paddedLayoutGroup.RectTransform, scaleBasis:
ScaleBasis.BothHeight), walletSprite, scaleToFit:
true) { CanBeFocused =
false };
868 GUITextBlock walletBlock =
new GUITextBlock(
new RectTransform(Vector2.One, paddedLayoutGroup.RectTransform),
string.Empty, textAlignment: Alignment.Right, font: GUIStyle.Font)
870 AutoScaleHorizontal =
true,
871 Padding = Vector4.Zero,
875 GUIImage largeIcon =
new GUIImage(
new RectTransform(Vector2.One, paddedLayoutGroup.RectTransform), walletSprite, scaleToFit:
true)
877 CanBeFocused =
false,
878 IgnoreLayoutGroups =
true,
884 largeIcon.Visible =
true;
885 icon.Visible =
false;
886 walletBlock.Visible =
false;
887 largeIcon.Enabled =
false;
891 walletLayout.Recalculate();
892 paddedLayoutGroup.Recalculate();
893 SetWalletText(walletBlock, character.Wallet, icon, largeIcon);
895 if (GameMain.GameSession?.Campaign is MultiPlayerCampaign campaign)
897 Identifier eventIdentifier =
new Identifier($
"{nameof(CreateWalletCrewFrame)}.{character.ID}");
898 campaign.OnMoneyChanged.RegisterOverwriteExisting(eventIdentifier, e =>
900 if (!e.Owner.TryUnwrap(out var owner) || owner != character) { return; }
901 SetWalletText(walletBlock, e.Wallet, icon, largeIcon);
903 registeredEvents.Add(eventIdentifier);
906 static void SetWalletText(GUITextBlock block, Wallet wallet, GUIImage icon, GUIImage largeIcon)
908 const int million = 1000000,
909 tooSmallPixelTreshold = 50;
911 block.Text = TextManager.FormatCurrency(wallet.Balance);
912 block.ToolTip =
string.Empty;
914 if (wallet.Balance >= million)
916 block.Text = TextManager.Get(
"crewwallet.balance.toomuchtoshow");
917 block.ToolTip = block.Text;
920 largeIcon.Visible =
false;
922 block.Visible =
true;
924 if (tooSmallPixelTreshold > block.Rect.Width)
926 largeIcon.Visible =
true;
927 icon.Visible =
false;
928 block.Visible =
false;
929 largeIcon.ToolTip = block.Text;
934 private void CreateNameWithPermissionIcon(
Client client, GUILayoutGroup paddedFrame, out GUIImage permissionIcon)
936 GUITextBlock characterNameBlock;
937 Sprite permissionIconSprite = GetPermissionIcon(client);
939 Color nameColor = prefab !=
null ? prefab.
UIColor : Color.White;
941 Point iconSize =
new Point((
int)(paddedFrame.Rect.Height * 0.8f));
942 float characterNameWidthAdjustment = (iconSize.X + paddedFrame.AbsoluteSpacing) / characterColumnWidth;
944 characterNameBlock =
new GUITextBlock(
new RectTransform(
new Point(characterColumnWidth, paddedFrame.Rect.Height), paddedFrame.RectTransform),
945 ToolBox.LimitString(client.
Name, GUIStyle.Font, (
int)(characterColumnWidth - paddedFrame.Rect.Width * characterNameWidthAdjustment)), textAlignment: Alignment.Center, textColor: nameColor);
947 float iconWidth = iconSize.X / (float)characterColumnWidth;
948 int xOffset = (int)(jobColumnWidth + characterNameBlock.TextPos.X - GUIStyle.Font.MeasureString(characterNameBlock.Text).X / 2f - paddedFrame.AbsoluteSpacing - iconWidth * paddedFrame.Rect.Width);
949 permissionIcon =
new GUIImage(
new RectTransform(
new Vector2(iconWidth, 1f), paddedFrame.RectTransform) { AbsoluteOffset = new Point(xOffset + 2, 0) }, permissionIconSprite) { IgnoreLayoutGroups =
true };
954 characterNameBlock.Strikethrough =
new GUITextBlock.StrikethroughSettings(
null, GUI.IntScale(1f), GUI.IntScale(5f));
958 private Sprite GetPermissionIcon(
Client client)
960 if (GameMain.NetworkMember ==
null || client ==
null || !client.
HasPermissions) {
return null; }
968 return moderatorIcon;
972 private void DrawNotInGameIcon(SpriteBatch spriteBatch, Rectangle area,
Client client)
976 spectateIcon.
Draw(spriteBatch, area, Color.White);
987 Vector2 stringOffset = GUIStyle.Font.MeasureString(inLobbyString) / 2f;
988 GUIStyle.Font.DrawString(spriteBatch, inLobbyString, area.Center.ToVector2() - stringOffset, Color.White);
992 private void DrawDisconnectedIcon(SpriteBatch spriteBatch, Rectangle area)
994 disconnectedIcon.
Draw(spriteBatch, area, GUIStyle.Red);
1000 private bool SelectElement(
object userData, GUIComponent crewList)
1005 GUIComponent existingPreview = infoFrameHolder.
FindChild(
"SelectedCharacter");
1006 if (existingPreview !=
null) { infoFrameHolder.
RemoveChild(existingPreview); }
1008 GUIFrame background =
new GUIFrame(
new RectTransform(
new Vector2(0.543f, 0.69f), infoFrameHolder.
RectTransform,
Anchor.TopRight,
Pivot.TopLeft) { RelativeOffset = new Vector2(-0.061f, 0) })
1010 UserData =
"SelectedCharacter"
1013 if (character !=
null)
1015 if (GameMain.Client is
null)
1017 GUIComponent preview = character.Info.CreateInfoFrame(background,
false,
null);
1021 GUIComponent preview = character.Info.CreateInfoFrame(background,
false, GetPermissionIcon(GameMain.Client.ConnectedClients.Find(c => c.Character == character)));
1023 GameMain.Client.SelectCrewCharacter(character, preview);
1024 if (!character.IsBot && GameMain.GameSession?.Campaign is MultiPlayerCampaign mpCampaign) { CreateWalletFrame(background, character, mpCampaign); }
1027 if (background.FindChild(TalentMenu.ManageBotTalentsButtonUserData, recursive:
true) is GUIButton { Enabled: true } talentButton)
1029 talentButton.OnClicked = (button, o) =>
1031 talentMenu.CreateGUI(infoFrameHolder, character);
1036 else if (client !=
null)
1038 GUIComponent preview = CreateClientInfoFrame(background, client, GetPermissionIcon(client));
1039 GameMain.Client?.SelectCrewClient(client, preview);
1040 if (client.
Character !=
null && GameMain.GameSession?.Campaign is MultiPlayerCampaign mpCampaign)
1042 CreateWalletFrame(background, client.
Character, mpCampaign);
1049 private void CreateWalletFrame(GUIComponent parent, Character character, MultiPlayerCampaign campaign)
1051 if (campaign is
null) {
throw new ArgumentNullException(nameof(campaign),
"Tried to create a wallet frame when campaign was null"); }
1052 if (character is
null) {
throw new ArgumentNullException(nameof(character),
"Tried to create a wallet frame for a null character");}
1053 isTransferMenuOpen =
false;
1054 transferMenuOpenState = 1f;
1055 ImmutableHashSet<Character> salaryCrew = GameSession.GetSessionCrewCharacters(
CharacterType.Player).Where(c => c != character).ToImmutableHashSet();
1057 Wallet targetWallet = character.Wallet;
1059 GUIFrame walletFrame =
new GUIFrame(
new RectTransform(
new Vector2(1f, 0.35f), parent.RectTransform, anchor:
Anchor.TopLeft)
1061 RelativeOffset = new Vector2(0, 1.02f)
1064 GUILayoutGroup walletLayout =
new GUILayoutGroup(
new RectTransform(ToolBox.PaddingSizeParentRelative(walletFrame.RectTransform, 0.9f), walletFrame.RectTransform, anchor:
Anchor.Center));
1066 GUILayoutGroup headerLayout =
new GUILayoutGroup(
new RectTransform(
new Vector2(1f, 0.33f), walletLayout.RectTransform), isHorizontal:
true);
1067 GUIImage icon =
new GUIImage(
new RectTransform(Vector2.One, headerLayout.RectTransform, scaleBasis:
ScaleBasis.BothHeight), style:
"CrewWalletIconLarge", scaleToFit:
true);
1068 float relativeX = icon.RectTransform.NonScaledSize.X / (float)icon.Parent.RectTransform.NonScaledSize.X;
1069 GUILayoutGroup headerTextLayout =
new GUILayoutGroup(
new RectTransform(
new Vector2(1.0f - relativeX, 1f), headerLayout.RectTransform), isHorizontal:
true) { Stretch =
true };
1070 new GUITextBlock(
new RectTransform(
new Vector2(0.5f, 1f), headerTextLayout.RectTransform), TextManager.Get(
"crewwallet.wallet"), font: GUIStyle.LargeFont);
1071 GUIFrame walletTooltipFrame =
new GUIFrame(
new RectTransform(Vector2.One, headerLayout.RectTransform), style:
null)
1073 IgnoreLayoutGroups =
true,
1074 ToolTip = TextManager.Get(
"walletdescription")
1076 GUITextBlock moneyBlock =
new GUITextBlock(
new RectTransform(
new Vector2(0.5f, 1f), headerTextLayout.RectTransform), TextManager.FormatCurrency(targetWallet.Balance), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right);
1078 GUILayoutGroup middleLayout =
new GUILayoutGroup(
new RectTransform(
new Vector2(1f, 0.66f), walletLayout.RectTransform));
1079 GUILayoutGroup salaryTextLayout =
new GUILayoutGroup(
new RectTransform(
new Vector2(1f, 0.5f), middleLayout.RectTransform), isHorizontal:
true);
1080 GUITextBlock salaryTitle =
new GUITextBlock(
new RectTransform(
new Vector2(0.5f, 1f), salaryTextLayout.RectTransform), TextManager.Get(
"crewwallet.salary"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.BottomLeft);
1081 GUITextBlock rewardBlock =
new GUITextBlock(
new RectTransform(
new Vector2(0.5f, 1f), salaryTextLayout.RectTransform),
string.Empty, textAlignment: Alignment.BottomRight);
1082 GUIFrame salaryTooltipFrame =
new GUIFrame(
new RectTransform(Vector2.One, middleLayout.RectTransform), style:
null)
1084 IgnoreLayoutGroups =
true,
1085 ToolTip = TextManager.Get(
"crewwallet.salary.tooltip")
1087 GUILayoutGroup sliderLayout =
new GUILayoutGroup(
new RectTransform(
new Vector2(1f, 0.5f), middleLayout.RectTransform), isHorizontal:
true, childAnchor:
Anchor.Center);
1088 GUIScrollBar salarySlider =
new GUIScrollBar(
new RectTransform(
new Vector2(0.9f, 1f), sliderLayout.RectTransform), style:
"GUISlider", barSize: 0.03f)
1090 Range =
new Vector2(0, 1),
1091 BarScrollValue = targetWallet.RewardDistribution / 100f,
1094 OnMoved = (bar, scroll) =>
1096 int rewardDistribution = RoundRewardDistribution(scroll, bar.Step);
1097 SetRewardText(rewardDistribution, rewardBlock);
1100 OnReleased = (bar, scroll) =>
1102 int newRewardDistribution = RoundRewardDistribution(scroll, bar.Step);
1103 if (newRewardDistribution == targetWallet.RewardDistribution) {
return false; }
1104 SetRewardDistribution(Option.Some(character), newRewardDistribution);
1109 SetRewardText(targetWallet.RewardDistribution, rewardBlock);
1112 GUIScissorComponent scissorComponent =
new GUIScissorComponent(
new RectTransform(
new Vector2(0.85f, 1.25f), walletFrame.RectTransform,
Anchor.BottomCenter,
Pivot.TopCenter))
1114 CanBeFocused =
false
1116 transferMenu =
new GUIFrame(
new RectTransform(Vector2.One, scissorComponent.Content.RectTransform));
1118 GUILayoutGroup transferMenuLayout =
new GUILayoutGroup(
new RectTransform(
new Vector2(1f, 0.8f), transferMenu.
RectTransform,
Anchor.BottomLeft), childAnchor:
Anchor.Center);
1119 GUILayoutGroup paddedTransferMenuLayout =
new GUILayoutGroup(
new RectTransform(ToolBox.PaddingSizeParentRelative(transferMenuLayout.RectTransform, 0.85f), transferMenuLayout.RectTransform));
1120 GUILayoutGroup mainLayout =
new GUILayoutGroup(
new RectTransform(
new Vector2(1f, 0.5f), paddedTransferMenuLayout.RectTransform), isHorizontal:
true, childAnchor:
Anchor.CenterLeft);
1121 GUILayoutGroup leftLayout =
new GUILayoutGroup(
new RectTransform(
new Vector2(0.5f, 1f), mainLayout.RectTransform));
1122 GUITextBlock leftName =
new GUITextBlock(
new RectTransform(
new Vector2(1f, 0.5f), leftLayout.RectTransform), character.Name, textAlignment: Alignment.CenterLeft, font: GUIStyle.SubHeadingFont);
1123 GUITextBlock leftBalance =
new GUITextBlock(
new RectTransform(
new Vector2(1f, 0.5f), leftLayout.RectTransform), TextManager.FormatCurrency(targetWallet.Balance), textAlignment: Alignment.Left) { TextColor = GUIStyle.Blue };
1124 GUILayoutGroup rightLayout =
new GUILayoutGroup(
new RectTransform(
new Vector2(0.5f, 1f), mainLayout.RectTransform), childAnchor:
Anchor.TopRight);
1125 GUITextBlock rightName =
new GUITextBlock(
new RectTransform(
new Vector2(1f, 0.5f), rightLayout.RectTransform),
string.Empty, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterRight);
1126 GUITextBlock rightBalance =
new GUITextBlock(
new RectTransform(
new Vector2(1f, 0.5f), rightLayout.RectTransform),
string.Empty, textAlignment: Alignment.Right) { TextColor = GUIStyle.Red };
1127 GUILayoutGroup centerLayout =
new GUILayoutGroup(
new RectTransform(
new Vector2(1f, 0.9f), mainLayout.RectTransform,
Anchor.Center), childAnchor:
Anchor.Center) { IgnoreLayoutGroups =
true };
1128 new GUIFrame(
new RectTransform(
new Vector2(0f, 1f), centerLayout.RectTransform,
Anchor.Center), style:
"VerticalLine") { IgnoreLayoutGroups =
true };
1129 GUIButton centerButton =
new GUIButton(
new RectTransform(
new Vector2(1f), centerLayout.RectTransform, scaleBasis:
ScaleBasis.BothHeight, anchor:
Anchor.Center), style:
"GUIButtonTransferArrow");
1131 GUILayoutGroup inputLayout =
new GUILayoutGroup(
new RectTransform(
new Vector2(1f, 0.25f), paddedTransferMenuLayout.RectTransform), childAnchor:
Anchor.Center);
1132 GUINumberInput transferAmountInput =
new GUINumberInput(
new RectTransform(
new Vector2(0.5f, 1f), inputLayout.RectTransform),
NumberType.Int, buttonVisibility: GUINumberInput.ButtonVisibility.ForceHidden)
1137 GUILayoutGroup buttonLayout =
new GUILayoutGroup(
new RectTransform(
new Vector2(1f, 0.25f), paddedTransferMenuLayout.RectTransform), childAnchor:
Anchor.Center);
1138 GUILayoutGroup centerButtonLayout =
new GUILayoutGroup(
new RectTransform(
new Vector2(0.75f, 1f), buttonLayout.RectTransform), isHorizontal:
true);
1139 GUIButton resetButton =
new GUIButton(
new RectTransform(
new Vector2(0.5f, 1f), centerButtonLayout.RectTransform), TextManager.Get(
"reset"), style:
"GUIButtonFreeScale") { Enabled =
false };
1140 GUIButton confirmButton =
new GUIButton(
new RectTransform(
new Vector2(0.5f, 1f), centerButtonLayout.RectTransform), TextManager.Get(
"confirm"), style:
"GUIButtonFreeScale") { Enabled =
false };
1142 ImmutableArray<GUILayoutGroup> layoutGroups = ImmutableArray.Create(transferMenuLayout, paddedTransferMenuLayout, mainLayout, leftLayout, rightLayout);
1143 MedicalClinicUI.EnsureTextDoesntOverflow(character.Name, leftName, leftLayout.Rect, layoutGroups);
1144 transferMenuButton =
new GUIButton(
new RectTransform(
new Vector2(0.5f, 0.2f), walletFrame.RectTransform,
Anchor.BottomCenter,
Pivot.TopCenter), style:
"UIToggleButtonVertical")
1146 ToolTip = TextManager.Get(
"crewwallet.transfer.tooltip"),
1147 OnClicked = (button, o) =>
1149 isTransferMenuOpen = !isTransferMenuOpen;
1150 if (!isTransferMenuOpen)
1152 transferAmountInput.IntValue = 0;
1154 ToggleTransferMenuIcon(button, open: isTransferMenuOpen);
1159 Identifier eventIdentifier = nameof(CreateWalletFrame).ToIdentifier();
1161 ToggleTransferMenuIcon(transferMenuButton, open: isTransferMenuOpen);
1162 ToggleCenterButton(centerButton, isSending);
1165 GameMain.Client?.OnPermissionChanged.RegisterOverwriteExisting(eventIdentifier, e => UpdateWalletInterface(registerEvents:
false));
1166 UpdateWalletInterface(registerEvents:
true);
1168 void UpdateWalletInterface(
bool registerEvents)
1170 if (!(
Character.Controlled is { } myCharacter))
1172 salarySlider.Enabled =
false;
1173 transferAmountInput.Enabled =
false;
1174 centerButton.Enabled =
false;
1175 confirmButton.Enabled =
false;
1179 bool hasMoneyPermissions = CampaignMode.AllowedToManageWallets();
1180 salarySlider.Enabled = hasMoneyPermissions;
1182 switch (hasMoneyPermissions)
1185 rightName.Text = TextManager.Get(
"crewwallet.bank");
1186 otherWallet = campaign.Bank;
1188 case false when character == myCharacter:
1189 rightName.Text = TextManager.Get(
"crewwallet.bank");
1190 otherWallet = campaign.Bank;
1192 ToggleCenterButton(centerButton, isSending);
1195 rightName.Text = myCharacter.Name;
1196 otherWallet = campaign.PersonalWallet;
1200 MedicalClinicUI.EnsureTextDoesntOverflow(rightName.Text.ToString(), rightName, rightLayout.Rect, layoutGroups);
1202 UpdatedConfirmButtonText();
1204 if (!hasMoneyPermissions)
1208 centerButton.Enabled = centerButton.CanBeFocused =
false;
1211 salarySlider.Enabled = salarySlider.CanBeFocused =
false;
1214 leftBalance.Text = TextManager.FormatCurrency(otherWallet.Balance);
1218 if (!registerEvents) {
return; }
1220 centerButton.OnClicked = (btn, o) =>
1222 isSending = !isSending;
1223 UpdatedConfirmButtonText();
1224 ToggleCenterButton(btn, isSending);
1229 transferAmountInput.OnValueChanged = input =>
1234 transferAmountInput.OnValueEntered = input =>
1239 resetButton.OnClicked = (button, o) =>
1241 transferAmountInput.IntValue = 0;
1246 confirmButton.OnClicked = (button, o) =>
1248 int amount = transferAmountInput.IntValue;
1249 if (amount == 0) {
return false; }
1251 Option<Character> target1 = Option<Character>.Some(character),
1252 target2 = otherWallet == campaign.Bank ? Option<Character>.None() : Option<Character>.Some(myCharacter);
1253 if (isSending) { (target1, target2) = (target2, target1); }
1255 SendTransaction(target1, target2, amount);
1256 isTransferMenuOpen =
false;
1257 ToggleTransferMenuIcon(transferMenuButton, isTransferMenuOpen);
1261 campaign.OnMoneyChanged.RegisterOverwriteExisting(eventIdentifier, e =>
1263 if (e.Wallet == targetWallet)
1265 moneyBlock.Text = TextManager.FormatCurrency(e.Info.Balance);
1266 salarySlider.BarScrollValue = e.Info.RewardDistribution / 100f;
1267 SetRewardText(e.Info.RewardDistribution, rewardBlock);
1273 registeredEvents.Add(eventIdentifier);
1275 void UpdatedConfirmButtonText()
1277 confirmButton.Text = TextManager.Get(hasMoneyPermissions || isSending ?
"confirm" :
"crewwallet.requestmoney");
1280 void UpdateAllInputs()
1288 confirmButton.Enabled = resetButton.Enabled = transferAmountInput.IntValue > 0;
1289 if (transferAmountInput.IntValue == 0)
1291 rightBalance.Text = TextManager.FormatCurrency(otherWallet.Balance);
1292 rightBalance.TextColor = GUIStyle.TextColorNormal;
1293 leftBalance.Text = TextManager.FormatCurrency(targetWallet.Balance);
1294 leftBalance.TextColor = GUIStyle.TextColorNormal;
1298 rightBalance.Text = TextManager.FormatCurrency(otherWallet.Balance + transferAmountInput.IntValue);
1299 rightBalance.TextColor = GUIStyle.Blue;
1300 leftBalance.Text = TextManager.FormatCurrency(targetWallet.Balance - transferAmountInput.IntValue);
1301 leftBalance.TextColor = GUIStyle.Red;
1305 rightBalance.Text = TextManager.FormatCurrency(otherWallet.Balance - transferAmountInput.IntValue);
1306 rightBalance.TextColor = GUIStyle.Red;
1307 leftBalance.Text = TextManager.FormatCurrency(targetWallet.Balance + transferAmountInput.IntValue);
1308 leftBalance.TextColor = GUIStyle.Blue;
1312 void UpdateMaxInput()
1314 int maxValue = isSending ? targetWallet.Balance : otherWallet.Balance;
1315 transferAmountInput.MaxValueInt = maxValue;
1317 transferAmountInput.Enabled =
true;
1318 transferAmountInput.ToolTip =
string.Empty;
1320 if (!hasMoneyPermissions && GameMain.Client?.ServerSettings is { } serverSettings)
1322 transferAmountInput.MaxValueInt = Math.Min(maxValue, serverSettings.MaximumMoneyTransferRequest);
1323 if (serverSettings.MaximumMoneyTransferRequest <= 0)
1325 transferAmountInput.Enabled =
false;
1326 transferAmountInput.ToolTip = TextManager.Get(
"wallettransferrequestdisabled");
1332 void SetRewardText(
int value, GUITextBlock block)
1334 var (_, percentage, sum) = Mission.GetRewardShare(value, salaryCrew, Option<int>.
None());
1335 LocalizedString tooltip =
string.Empty;
1336 block.TextColor = GUIStyle.TextColorNormal;
1340 tooltip = TextManager.GetWithVariables(
"crewwallet.salary.over100toolitp", (
"[sum]", $
"{(int)sum}"), (
"[newvalue]", $
"{percentage}"));
1341 block.TextColor = GUIStyle.Orange;
1344 LocalizedString text = TextManager.GetWithVariable(
"percentageformat",
"[value]", $
"{value}");
1347 block.ToolTip = RichString.Rich(tooltip);
1350 static void ToggleTransferMenuIcon(GUIButton btn,
bool open)
1352 foreach (GUIComponent child
in btn.Children)
1354 child.SpriteEffects = open ? SpriteEffects.None : SpriteEffects.FlipVertically;
1358 static void ToggleCenterButton(GUIButton btn,
bool isSending)
1360 foreach (GUIComponent child
in btn.Children)
1362 child.SpriteEffects = isSending ? SpriteEffects.None : SpriteEffects.FlipHorizontally;
1366 static void SendTransaction(Option<Character> to, Option<Character> from,
int amount)
1368 INetSerializableStruct transfer =
new NetWalletTransfer
1370 Sender = from.Select(option => option.ID),
1371 Receiver = to.Select(option => option.ID),
1375 transfer.Write(msg);
1376 GameMain.Client?.ClientPeer?.Send(msg, DeliveryMethod.Reliable);
1380 static void SetRewardDistribution(Option<Character> character,
int newValue)
1382 INetSerializableStruct transfer =
new NetWalletSetSalaryUpdate
1384 Target = character.Select(c => c.ID),
1385 NewRewardDistribution = newValue
1388 transfer.Write(msg);
1389 GameMain.Client?.ClientPeer?.Send(msg, DeliveryMethod.Reliable);
1392 static void ResetRewardDistributions()
1395 GameMain.Client?.ClientPeer?.Send(msg, DeliveryMethod.Reliable);
1398 static int RoundRewardDistribution(
float scroll,
float step)
1399 => (int)MathUtils.RoundTowardsClosest(scroll * 100, step * 100);
1401 private GUIComponent CreateClientInfoFrame(GUIFrame frame,
Client client, Sprite permissionIcon =
null)
1403 GUIComponent paddedFrame;
1407 paddedFrame =
new GUILayoutGroup(
new RectTransform(
new Vector2(0.874f, 0.58f), frame.RectTransform,
Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.05f) })
1409 RelativeSpacing = 0.05f
1413 var headerArea =
new GUILayoutGroup(
new RectTransform(
new Vector2(1.0f, 0.322f), paddedFrame.RectTransform), isHorizontal:
true);
1415 new GUICustomComponent(
new RectTransform(
new Vector2(0.425f, 1.0f), headerArea.RectTransform),
1416 onDraw: (sb, component) => DrawNotInGameIcon(sb, component.Rect, client));
1418 GUIFont font = paddedFrame.Rect.Width < 280 ? GUIStyle.SmallFont : GUIStyle.Font;
1420 var headerTextArea =
new GUILayoutGroup(
new RectTransform(
new Vector2(0.575f, 1.0f), headerArea.RectTransform))
1422 RelativeSpacing = 0.02f,
1426 GUITextBlock clientNameBlock =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.0f), headerTextArea.RectTransform), ToolBox.LimitString(client.
Name, GUIStyle.Font, headerTextArea.Rect.Width), textColor: Color.White, font: GUIStyle.Font)
1429 Padding = Vector4.Zero
1432 if (permissionIcon !=
null)
1434 Point iconSize = permissionIcon.SourceRect.Size;
1435 int iconWidth = (int)((
float)clientNameBlock.Rect.Height / iconSize.Y * iconSize.X);
1436 new GUIImage(
new RectTransform(
new Point(iconWidth, clientNameBlock.Rect.Height), clientNameBlock.RectTransform) { AbsoluteOffset = new Point(-iconWidth - 2, 0) }, permissionIcon) { IgnoreLayoutGroups =
true };
1439 new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.0f), headerTextArea.RectTransform), client.
Spectating ? TextManager.Get(
"playingasspectator") : TextManager.Get(
"tabmenu.inlobby"), textColor: Color.White, font: font, wrap:
true)
1441 Padding = Vector4.Zero
1452 private void CreateMultiPlayerLogContent(GUIFrame crewFrame)
1454 var logContainer =
new GUIFrame(
new RectTransform(
new Vector2(0.543f, 0.717f), infoFrameHolder.
RectTransform,
Anchor.TopLeft,
Pivot.TopRight) { RelativeOffset = new Vector2(-0.145f, 0) });
1455 var innerFrame =
new GUIFrame(
new RectTransform(
new Vector2(0.900f, 0.900f), logContainer.RectTransform,
Anchor.TopCenter,
Pivot.TopCenter) { RelativeOffset = new Vector2(0f, 0.0475f) }, style:
null);
1456 var content =
new GUILayoutGroup(
new RectTransform(Vector2.One, innerFrame.RectTransform))
1461 logList =
new GUIListBox(
new RectTransform(Vector2.One, content.RectTransform))
1463 Padding =
new Vector4(0, 10 * GUI.Scale, 0, 10 * GUI.Scale),
1464 UserData = crewFrame,
1465 AutoHideScrollBar =
false,
1466 Spacing = (int)(5 * GUI.Scale)
1471 AddLineToLog(message, type);
1484 storedMessages.Add((msg, message.
ChangeType));
1489 instance.AddLineToLog(msg, message.
ChangeType);
1490 instance.RemoveCurrentElements();
1491 instance.CreateMultiPlayerList(
true);
1495 private void RemoveCurrentElements()
1497 for (
int i = 0; i < crewListArray.Length; i++)
1499 for (
int j = 0; j < linkedGUIList.Count; j++)
1501 linkedGUIList[j].Remove(crewListArray[i].Content);
1505 linkedGUIList.Clear();
1510 Color textColor = Color.White;
1515 textColor = GUIStyle.Green;
1518 textColor = GUIStyle.Orange;
1521 textColor = GUIStyle.Yellow;
1524 textColor = GUIStyle.Red;
1528 if (logList !=
null)
1530 var textBlock =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.0f), logList.
Content.
RectTransform), RichString.Rich(line), wrap:
true, font: GUIStyle.SmallFont)
1532 TextColor = textColor,
1533 CanBeFocused =
false,
1536 textBlock.CalculateHeightFromText();
1537 if (textBlock.HasColorHighlight)
1539 foreach (var data
in textBlock.RichTextData)
1541 textBlock.ClickableAreas.Add(
new GUITextBlock.ClickableArea()
1544 OnClick = GameMain.NetLobbyScreen.SelectPlayer,
1545 OnSecondaryClick = GameMain.NetLobbyScreen.ShowPlayerContextMenu
1552 private void CreateMissionInfo(GUIFrame infoFrame)
1554 if (Level.Loaded?.LevelData ==
null)
1556 DebugConsole.ThrowError(
"Failed to display mission info in the tab menu (no level loaded).\n" + Environment.StackTrace);
1560 infoFrame.ClearChildren();
1561 GUIFrame missionFrame =
new GUIFrame(
new RectTransform(Vector2.One, infoFrame.RectTransform,
Anchor.TopCenter), style:
"GUIFrameListBox");
1562 int padding = (int)(0.0245f * missionFrame.Rect.Height);
1563 GUIFrame missionFrameContent =
new GUIFrame(
new RectTransform(
new Point(missionFrame.Rect.Width - padding * 2, missionFrame.Rect.Height - padding * 2), infoFrame.RectTransform,
Anchor.Center), style:
null);
1564 Location location = GameMain.GameSession.StartLocation;
1565 if (Level.Loaded.Type == LevelData.LevelType.LocationConnection)
1567 location ??= GameMain.GameSession.EndLocation;
1570 GUILayoutGroup locationInfoContainer =
new GUILayoutGroup(
new RectTransform(
new Vector2(1.0f, 0.3f), missionFrameContent.RectTransform))
1572 AbsoluteSpacing = GUI.IntScale(10)
1575 Sprite portrait = location.Type.GetPortrait(location.PortraitId);
1576 bool hasPortrait = portrait !=
null && portrait.SourceRect.Width > 0 && portrait.SourceRect.Height > 0;
1577 int contentWidth = missionFrameContent.Rect.Width;
1580 float portraitAspectRatio = portrait.SourceRect.Width / portrait.SourceRect.Height;
1581 GUIImage portraitImage =
new GUIImage(
new RectTransform(
new Vector2(0.5f, 1f), locationInfoContainer.RectTransform,
Anchor.CenterRight), portrait, scaleToFit:
true)
1583 IgnoreLayoutGroups =
true
1585 locationInfoContainer.Recalculate();
1586 portraitImage.RectTransform.NonScaledSize =
new Point(Math.Min((
int)(portraitImage.Rect.Size.Y * portraitAspectRatio), portraitImage.Rect.Width), portraitImage.Rect.Size.Y);
1589 new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.0f), locationInfoContainer.RectTransform), location.DisplayName, font: GUIStyle.LargeFont);
1590 new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.0f), locationInfoContainer.RectTransform), location.Type.Name, font: GUIStyle.SubHeadingFont);
1592 if (location.Faction?.Prefab !=
null)
1594 var factionLabel =
new GUITextBlock(
new RectTransform(
new Vector2(0.5f, 0.0f), locationInfoContainer.RectTransform),
1595 TextManager.Get(
"Faction"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterLeft);
1596 new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 1.0f), factionLabel.RectTransform), location.Faction.Prefab.Name, textAlignment: Alignment.CenterRight);
1598 var biomeLabel =
new GUITextBlock(
new RectTransform(
new Vector2(0.5f, 0.0f), locationInfoContainer.RectTransform),
1599 TextManager.Get(
"Biome",
"location"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterLeft);
1600 new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 1.0f), biomeLabel.RectTransform), Level.Loaded.LevelData.Biome.DisplayName, textAlignment: Alignment.CenterRight);
1601 var difficultyLabel =
new GUITextBlock(
new RectTransform(
new Vector2(0.5f, 0.0f), locationInfoContainer.RectTransform),
1602 TextManager.Get(
"LevelDifficulty"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterLeft);
1603 new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 1.0f), difficultyLabel.RectTransform), TextManager.GetWithVariable(
"percentageformat",
"[value]", ((
int)Level.Loaded.LevelData.Difficulty).ToString()), textAlignment: Alignment.CenterRight);
1605 new GUIFrame(
new RectTransform(
new Vector2(1.0f, 0.01f), missionFrameContent.RectTransform) { AbsoluteOffset = new Point(0, locationInfoContainer.Rect.Height + padding) }, style:
"HorizontalLine")
1607 CanBeFocused =
false
1610 int locationInfoYOffset = locationInfoContainer.Rect.Height + padding * 2;
1612 GUIListBox missionList =
new GUIListBox(
new RectTransform(
new Point(contentWidth, missionFrameContent.Rect.Height - locationInfoYOffset), missionFrameContent.RectTransform,
Anchor.TopCenter) { AbsoluteOffset = new Point(0, locationInfoYOffset) });
1613 missionList.ContentBackground.Color = Color.Transparent;
1614 missionList.Spacing = GUI.IntScale(15);
1616 if (GameMain.GameSession?.Missions !=
null)
1618 foreach (Mission mission
in GameMain.GameSession.Missions)
1620 if (!mission.Prefab.ShowInMenus) {
continue; }
1622 var textContent =
new List<LocalizedString>()
1624 mission.GetMissionRewardText(
Submarine.MainSub),
1625 mission.GetReputationRewardText(),
1628 textContent.AddRange(mission.ShownMessages);
1630 RoundSummary.CreateMissionEntry(
1631 missionList.Content,
1634 mission.Difficulty ?? 0,
1635 mission.Prefab.Icon, mission.Prefab.IconColor,
1636 out GUIImage missionIcon);
1637 if (missionIcon !=
null)
1639 UpdateMissionStateIcon();
1640 mission.OnMissionStateChanged += (mission) => UpdateMissionStateIcon();
1642 void UpdateMissionStateIcon()
1644 if (mission.DisplayAsCompleted || mission.DisplayAsFailed)
1646 RoundSummary.UpdateMissionStateIcon(mission.DisplayAsCompleted, missionIcon);
1654 GUILayoutGroup missionTextGroup =
new GUILayoutGroup(
new RectTransform(
new Vector2(1f, 0f), missionList.RectTransform,
Anchor.CenterLeft),
false, childAnchor:
Anchor.TopLeft);
1655 new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), TextManager.Get(
"NoMission"), font: GUIStyle.LargeFont);
1658 GameMain.GameSession?.EventManager?.EventLog?.CreateEventLogUI(missionList.Content);
1659 GameMain.GameSession.EnableEventLogNotificationIcon(enabled:
false);
1661 RoundSummary.AddSeparators(missionList.Content);
1664 private static void CreateSubmarineInfo(GUIFrame infoFrame, Submarine sub)
1666 GUIFrame subInfoFrame =
new GUIFrame(
new RectTransform(Vector2.One, infoFrame.RectTransform,
Anchor.TopCenter), style:
"GUIFrameListBox");
1667 GUIFrame paddedFrame =
new GUIFrame(
new RectTransform(Vector2.One * 0.97f, subInfoFrame.RectTransform,
Anchor.Center), style:
null);
1669 var previewButton =
new GUIButton(
new RectTransform(
new Vector2(1.0f, 0.43f), paddedFrame.RectTransform), style:
null)
1671 OnClicked = (btn, obj) => { SubmarinePreview.Create(sub.Info);
return false; },
1674 var previewImage = sub.Info.PreviewImage ?? SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name.Equals(sub.Info.Name, StringComparison.OrdinalIgnoreCase))?.PreviewImage;
1675 if (previewImage ==
null)
1677 new GUITextBlock(
new RectTransform(Vector2.One, previewButton.RectTransform), TextManager.Get(
"SubPreviewImageNotFound"));
1681 var submarinePreviewBackground =
new GUIFrame(
new RectTransform(Vector2.One, previewButton.RectTransform), style:
null)
1683 Color = Color.Black,
1684 HoverColor = Color.Black,
1685 SelectedColor = Color.Black,
1686 PressedColor = Color.Black,
1687 CanBeFocused =
false,
1689 new GUIImage(
new RectTransform(
new Vector2(0.98f), submarinePreviewBackground.RectTransform,
Anchor.Center), previewImage, scaleToFit:
true) { CanBeFocused =
false };
1690 new GUIFrame(
new RectTransform(Vector2.One, submarinePreviewBackground.RectTransform),
"InnerGlow", color: Color.Black) { CanBeFocused =
false };
1693 new GUIFrame(
new RectTransform(Vector2.One * 0.12f, previewButton.RectTransform, anchor:
Anchor.BottomRight, pivot:
Pivot.BottomRight, scaleBasis:
ScaleBasis.BothHeight)
1695 AbsoluteOffset = new Point((int)(0.03f * previewButton.Rect.Height))
1697 "ExpandButton", Color.White)
1699 Color = Color.White,
1700 HoverColor = Color.White,
1701 PressedColor = Color.White
1704 var subInfoTextLayout =
new GUILayoutGroup(
new RectTransform(Vector2.One, paddedFrame.RectTransform));
1706 LocalizedString className = !sub.Info.HasTag(
SubmarineTag.Shuttle) ?
1707 TextManager.GetWithVariables(
"submarine.classandtier",
1708 (
"[class]", TextManager.Get($
"submarineclass.{sub.Info.SubmarineClass}")),
1709 (
"[tier]", TextManager.Get($
"submarinetier.{sub.Info.Tier}"))) :
1710 TextManager.Get(
"shuttle");
1712 int nameHeight = (int)GUIStyle.LargeFont.MeasureString(sub.Info.DisplayName,
true).Y;
1713 int classHeight = (int)GUIStyle.SubHeadingFont.MeasureString(className).Y;
1715 var submarineNameText =
new GUITextBlock(
new RectTransform(
new Point(subInfoTextLayout.Rect.Width, nameHeight + HUDLayoutSettings.Padding / 2), subInfoTextLayout.RectTransform), sub.Info.DisplayName, textAlignment: Alignment.CenterLeft, font: GUIStyle.LargeFont) { CanBeFocused =
false };
1716 submarineNameText.RectTransform.MinSize =
new Point(0, (
int)submarineNameText.TextSize.Y);
1717 var submarineClassText =
new GUITextBlock(
new RectTransform(
new Point(subInfoTextLayout.Rect.Width, classHeight), subInfoTextLayout.RectTransform), className, textAlignment: Alignment.CenterLeft, font: GUIStyle.SubHeadingFont) { CanBeFocused =
false };
1718 submarineClassText.RectTransform.MinSize =
new Point(0, (
int)submarineClassText.TextSize.Y);
1720 if (GameMain.GameSession?.GameMode is CampaignMode campaign)
1722 GUILayoutGroup headerLayout =
new GUILayoutGroup(
new RectTransform(
new Vector2(1f, 0.09f), paddedFrame.RectTransform) { RelativeOffset = new Vector2(0f, 0.43f) }, isHorizontal:
true) { Stretch =
true };
1723 GUIImage headerIcon =
new GUIImage(
new RectTransform(Vector2.One, headerLayout.RectTransform, scaleBasis:
ScaleBasis.BothHeight), style:
"SubmarineIcon");
1724 new GUITextBlock(
new RectTransform(Vector2.One, headerLayout.RectTransform), TextManager.Get(
"uicategory.upgrades"), font: GUIStyle.LargeFont);
1726 var upgradeRootLayout =
new GUILayoutGroup(
new RectTransform(
new Vector2(1f, 0.48f), paddedFrame.RectTransform,
Anchor.BottomLeft,
Pivot.BottomLeft), isHorizontal:
true);
1728 var upgradeCategoryPanel = UpgradeStore.CreateUpgradeCategoryList(
new RectTransform(
new Vector2(0.4f, 1f), upgradeRootLayout.RectTransform));
1729 upgradeCategoryPanel.HideChildrenOutsideFrame =
true;
1730 UpgradeStore.UpdateCategoryList(upgradeCategoryPanel, campaign, sub, UpgradeStore.GetApplicableCategories(sub).ToArray());
1731 GUIComponent[] toRemove = upgradeCategoryPanel.Content.FindChildren(c => !c.Enabled).ToArray();
1732 toRemove.ForEach(c => upgradeCategoryPanel.RemoveChild(c));
1734 var upgradePanel =
new GUIListBox(
new RectTransform(
new Vector2(0.6f, 1f), upgradeRootLayout.RectTransform));
1735 upgradeCategoryPanel.OnSelected = (component, userData) =>
1737 upgradePanel.ClearChildren();
1738 if (userData is UpgradeStore.CategoryData categoryData &&
Submarine.MainSub !=
null)
1740 foreach (UpgradePrefab prefab
in categoryData.Prefabs)
1742 var frame = UpgradeStore.CreateUpgradeFrame(prefab, categoryData.Category, campaign,
new RectTransform(
new Vector2(1f, 0.3f), upgradePanel.Content.RectTransform), addBuyButton:
false).Frame;
1743 UpgradeStore.UpdateUpgradeEntry(frame, prefab, categoryData.Category, campaign);
1751 var specsListBox =
new GUIListBox(
new RectTransform(
new Vector2(1f, 0.57f), paddedFrame.RectTransform,
Anchor.BottomLeft,
Pivot.BottomLeft))
1753 CurrentSelectMode = GUIListBox.SelectMode.None
1755 sub.Info.CreateSpecsWindow(specsListBox, GUIStyle.Font,
1756 includeTitle:
false,
1757 includeClass:
false,
1758 includeDescription:
true);
1762 private GUIImage talentPointNotification, eventLogNotification;
1767 List<GUITextBlock> skillNames =
new List<GUITextBlock>();
1768 foreach (
Skill skill
in info.Job.GetSkills())
1772 skillNames.Add(skillName);
1773 skillName.RectTransform.MinSize =
new Point(0, skillName.Rect.Height);
1778 float modifiedSkillLevel = MathF.Floor(character?.GetSkillLevel(skill.
Identifier) ?? skill.
Level);
1779 if (!MathUtils.NearlyEqual(MathF.Floor(modifiedSkillLevel), MathF.Floor(skill.
Level)))
1781 int skillChange = (int)MathF.Floor(modifiedSkillLevel - MathF.Floor(skill.
Level));
1782 string stringColor = skillChange
switch
1784 > 0 => XMLExtensions.ToStringHex(GUIStyle.Green),
1785 < 0 => XMLExtensions.ToStringHex(GUIStyle.Red),
1786 _ => XMLExtensions.ToStringHex(GUIStyle.TextColorNormal)
1789 RichString changeText =
RichString.
Rich($
"(‖color:{stringColor}‖{(skillChange > 0 ? "+
" : string.Empty) + skillChange}‖color:end‖)");
1795 parent.RecalculateChildren();
1802 talentMenu.UpdateTalentInfo();
1808 foreach (Identifier identifier
in registeredEvents)
1810 campaign.OnMoneyChanged.TryDeregister(identifier);
static Character? Controlled
Stores information about the Character that is needed between rounds in the menu etc....
GUIComponent CreateInfoFrame(GUIFrame frame, bool returnParent, Sprite permissionIcon=null)
void DrawJobIcon(SpriteBatch spriteBatch, Rectangle area, bool evaluateDisguise=false)
IEnumerable< Character > GetCharacters()
virtual void RemoveChild(GUIComponent child)
void Pulsate(Vector2 startScale, Vector2 endScale, float duration)
virtual void AddToGUIUpdateList(bool ignoreChildren=false, int order=0)
virtual void ClearChildren()
GUIComponent FindChild(Func< GUIComponent, bool > predicate, bool recursive=false)
RectTransform RectTransform
GUIFrame Content
A frame that contains the contents of the listbox. The frame itself is not rendered.
static void AutoScaleAndNormalize(params GUITextBlock[] textBlocks)
Set the text scale of the GUITextBlocks so that they all use the same scale and can fit the text with...
static GameSession?? GameSession
static bool IsMultiplayer
static TabMenu TabMenuInstance
static void UpdateTalentNotificationIndicator(GUIImage indicator)
RoundSummary RoundSummary
static bool IsTabMenuOpen
static GUIButton JobInfoFrame
static string GetTimeStamp()
PlayerConnectionChangeType ChangeType
static RichString Rich(LocalizedString str, Func< string, string >? postProcess=null)
void CreateReputationInfoPanel(GUIComponent parent, CampaignMode campaignMode)
readonly Identifier Identifier
void Draw(SpriteBatch spriteBatch, RectangleF rect, Color color, SpriteEffects spriteEffects=SpriteEffects.None, Vector2? uvOffset=null)
PlayerConnectionChangeType