Client LuaCsForBarotrauma
MultiPlayerCampaignSetupUI.cs
1 using Microsoft.Xna.Framework;
2 using System;
3 using System.Collections.Generic;
4 using System.Globalization;
5 
6 namespace Barotrauma
7 {
9  {
10  private GUIButton deleteMpSaveButton;
11 
12  private int prevInitialMoney;
13 
14  private CampaignSettingElements campaignSettingElements;
15 
16  public bool LoadGameMenuVisible => loadGameContainer is { Visible: true };
17 
18  public MultiPlayerCampaignSetupUI(GUIComponent newGameContainer, GUIComponent loadGameContainer, List<CampaignMode.SaveInfo> saveFiles = null)
19  : base(newGameContainer, loadGameContainer)
20  {
21  var verticalLayout = new GUILayoutGroup(new RectTransform(Vector2.One, newGameContainer.RectTransform), isHorizontal: false)
22  {
23  Stretch = true,
24  RelativeSpacing = 0.025f
25  };
26 
27  GUILayoutGroup nameSeedLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), verticalLayout.RectTransform), isHorizontal: false)
28  {
29  Stretch = true
30  };
31 
32  GUILayoutGroup campaignSettingLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), verticalLayout.RectTransform), isHorizontal: false)
33  {
34  Stretch = true,
35  RelativeSpacing = 0.0f
36  };
37 
38  // New game
39  var saveLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.03f), nameSeedLayout.RectTransform) { MinSize = new Point(0, GUI.IntScale(24)) }, TextManager.Get("SaveName"), textAlignment: Alignment.CenterLeft);
40  saveNameBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), saveLabel.RectTransform, Anchor.CenterRight), string.Empty)
41  {
42  textFilterFunction = ToolBox.RemoveInvalidFileNameChars
43  };
45 
46  var seedLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.03f), nameSeedLayout.RectTransform) { MinSize = new Point(0, GUI.IntScale(24)) }, TextManager.Get("MapSeed"), textAlignment: Alignment.CenterLeft);
47  seedBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), seedLabel.RectTransform, Anchor.CenterRight), ToolBox.RandomSeed(8));
48  seedLabel.InheritTotalChildrenMinHeight();
49 
50  nameSeedLayout.InheritTotalChildrenMinHeight();
51 
52  campaignSettingElements = CreateCampaignSettingList(campaignSettingLayout, CampaignSettings.Empty, false);
53 
54  var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.1f),
55  verticalLayout.RectTransform) { MaxSize = new Point(int.MaxValue, GUI.IntScale(30)) }, childAnchor: Anchor.BottomRight, isHorizontal: true);
56 
57  prevInitialMoney = CampaignSettings.DefaultInitialMoney;
58  InitialMoneyText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1f), buttonContainer.RectTransform), "", font: GUIStyle.SmallFont, textColor: GUIStyle.Green, textAlignment: Alignment.CenterRight)
59  {
60  TextGetter = () =>
61  {
62  int defaultInitialMoney = CampaignSettings.DefaultInitialMoney;
63  int initialMoney = defaultInitialMoney;
64  if (CampaignModePresets.TryGetAttribute(
65  nameof(CampaignSettings.StartingBalanceAmount).ToIdentifier(),
66  campaignSettingElements.StartingFunds.GetValue().ToIdentifier(),
67  out var attribute))
68  {
69  initialMoney = attribute.GetAttributeInt(defaultInitialMoney);
70  }
71  if (prevInitialMoney != initialMoney)
72  {
74  prevInitialMoney = initialMoney;
75  }
77  {
78  initialMoney -= GameMain.NetLobbyScreen.SelectedSub.Price;
79  }
80  initialMoney = Math.Max(initialMoney, 0);
81 
82  return TextManager.GetWithVariable("campaignstartingmoney", "[money]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", initialMoney));
83  }
84  };
85 
86  verticalLayout.Recalculate();
87 
88  CreateLoadMenu(saveFiles);
89  }
90 
91  public bool StartGameClicked(GUIButton button, object userdata)
92  {
93  if (string.IsNullOrWhiteSpace(saveNameBox.Text))
94  {
95  saveNameBox.Flash(GUIStyle.Red, flashDuration: 5.0f);
96  saveNameBox.Pulsate(Vector2.One, Vector2.One * 1.2f, duration: 2.0f);
97  newGameContainer?.Flash(GUIStyle.Red, flashDuration: 0.5f);
98  return false;
99  }
100 
101  SubmarineInfo selectedSub = null;
102 
103  if (GameMain.NetLobbyScreen.SelectedSub == null) { return false; }
104  selectedSub = GameMain.NetLobbyScreen.SelectedSub;
105 
106  if (selectedSub.SubmarineClass == SubmarineClass.Undefined)
107  {
108  new GUIMessageBox(TextManager.Get("error"), TextManager.Get("undefinedsubmarineselected"));
109  return false;
110  }
111 
112  if (string.IsNullOrEmpty(selectedSub.MD5Hash.StringRepresentation))
113  {
114  new GUIMessageBox(TextManager.Get("error"), TextManager.Get("nohashsubmarineselected"));
115  return false;
116  }
117 
118  string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer, saveNameBox.Text);
119  bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled;
120 
121  CampaignSettings settings = campaignSettingElements.CreateSettings();
122 
123  if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
124  {
125  if (!hasRequiredContentPackages)
126  {
127  var msgBox = new GUIMessageBox(TextManager.Get("ContentPackageMismatch"),
128  TextManager.GetWithVariable("ContentPackageMismatchWarning", "[requiredcontentpackages]", string.Join(", ", selectedSub.RequiredContentPackages)),
129  new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") });
130 
131  msgBox.Buttons[0].OnClicked = msgBox.Close;
132  msgBox.Buttons[0].OnClicked += (button, obj) =>
133  {
134  if (GUIMessageBox.MessageBoxes.Count == 0)
135  {
136  StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text, settings);
137  CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
138  }
139  return true;
140  };
141 
142  msgBox.Buttons[1].OnClicked = msgBox.Close;
143  }
144 
145  if (selectedSub.HasTag(SubmarineTag.Shuttle))
146  {
147  var msgBox = new GUIMessageBox(TextManager.Get("ShuttleSelected"),
148  TextManager.Get("ShuttleWarning"),
149  new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") });
150 
151  msgBox.Buttons[0].OnClicked = (button, obj) =>
152  {
153  StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text, settings);
154  CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
155  return true;
156  };
157  msgBox.Buttons[0].OnClicked += msgBox.Close;
158 
159  msgBox.Buttons[1].OnClicked = msgBox.Close;
160  return false;
161  }
162  }
163  else
164  {
165  StartNewGame?.Invoke(selectedSub, savePath, seedBox.Text, settings);
166  CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
167  }
168 
169  return true;
170  }
171 
172  private IEnumerable<CoroutineStatus> WaitForCampaignSetup()
173  {
174  GUI.SetCursorWaiting();
175  var headerText = TextManager.Get("CampaignStartingPleaseWait");
176  var msgBox = new GUIMessageBox(headerText, TextManager.Get("CampaignStarting"), new LocalizedString[] { TextManager.Get("Cancel") });
177 
178  msgBox.Buttons[0].OnClicked = (btn, userdata) =>
179  {
182  GUI.ClearCursorWait();
183  CoroutineManager.StopCoroutines("WaitForCampaignSetup");
184  return true;
185  };
186  msgBox.Buttons[0].OnClicked += msgBox.Close;
187 
188  DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 20);
189  while (Screen.Selected != GameMain.GameScreen && DateTime.Now < timeOut)
190  {
191  msgBox.Header.Text = headerText + new string('.', (int)Timing.TotalTime % 3 + 1);
192  yield return CoroutineStatus.Running;
193  }
194  msgBox.Close();
195  GUI.ClearCursorWait();
196  yield return CoroutineStatus.Success;
197  }
198 
199  public override void CreateLoadMenu(IEnumerable<CampaignMode.SaveInfo> saveFiles = null)
200  {
201  prevSaveFiles?.Clear();
202  prevSaveFiles = null;
203  loadGameContainer.ClearChildren();
204 
205  if (saveFiles == null)
206  {
207  saveFiles = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Multiplayer);
208  }
209 
210  var leftColumn = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.85f), loadGameContainer.RectTransform), childAnchor: Anchor.TopCenter)
211  {
212  Stretch = true,
213  RelativeSpacing = 0.03f
214  };
215 
216  saveList = new GUIListBox(new RectTransform(Vector2.One, leftColumn.RectTransform))
217  {
218  PlaySoundOnSelect = true,
219  OnSelected = SelectSaveFile
220  };
221 
222  foreach (CampaignMode.SaveInfo saveInfo in saveFiles)
223  {
224  CreateSaveElement(saveInfo);
225  }
226 
227  SortSaveList();
228 
229  loadGameButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.12f), loadGameContainer.RectTransform, Anchor.BottomRight), TextManager.Get("LoadButton"))
230  {
231  OnClicked = (btn, obj) =>
232  {
233  if (saveList.SelectedData is not CampaignMode.SaveInfo saveInfo) { return false; }
234  if (string.IsNullOrWhiteSpace(saveInfo.FilePath)) { return false; }
235  LoadGame?.Invoke(saveInfo.FilePath);
236 
237  CoroutineManager.StartCoroutine(WaitForCampaignSetup(), "WaitForCampaignSetup");
238  return true;
239  },
240  Enabled = false
241  };
242  deleteMpSaveButton = new GUIButton(new RectTransform(new Vector2(0.45f, 0.12f), loadGameContainer.RectTransform, Anchor.BottomLeft),
243  TextManager.Get("Delete"), style: "GUIButtonSmall")
244  {
245  OnClicked = DeleteSave,
246  Visible = false
247  };
248  }
249 
250 
251  private bool SelectSaveFile(GUIComponent component, object obj)
252  {
253  if (obj is not CampaignMode.SaveInfo saveInfo) { return true; }
254  string fileName = saveInfo.FilePath;
255 
256  loadGameButton.Enabled = true;
257  deleteMpSaveButton.Visible = deleteMpSaveButton.Enabled = GameMain.Client.IsServerOwner;
258  deleteMpSaveButton.Enabled = GameMain.GameSession?.SavePath != fileName;
259  if (deleteMpSaveButton.Visible)
260  {
261  deleteMpSaveButton.UserData = saveInfo;
262  }
263  return true;
264  }
265  }
266 }
readonly GUIComponent newGameContainer
GUIComponent CreateSaveElement(CampaignMode.SaveInfo saveInfo)
Action< SubmarineInfo, string, string, CampaignSettings > StartNewGame
static CampaignSettingElements CreateCampaignSettingList(GUIComponent parent, CampaignSettings prevSettings, bool isSinglePlayer)
List< CampaignMode.SaveInfo > prevSaveFiles
bool DeleteSave(GUIButton button, object obj)
override bool Enabled
Definition: GUIButton.cs:27
virtual void Flash(Color? color=null, float flashDuration=1.5f, bool useRectangleFlash=false, bool useCircularFlash=false, Vector2? flashRectInflate=null)
void Pulsate(Vector2 startScale, Vector2 endScale, float duration)
void InheritTotalChildrenMinHeight()
Sets the minimum height of the transfrom to equal to the sum of the minimum heights of the children (...
RectTransform RectTransform
static readonly List< GUIComponent > MessageBoxes
override void Flash(Color? color=null, float flashDuration=1.5f, bool useRectangleFlash=false, bool useCircularFlash=false, Vector2? flashRectOffset=null)
Definition: GUITextBox.cs:411
static NetLobbyScreen NetLobbyScreen
Definition: GameMain.cs:55
readonly string StringRepresentation
Definition: Md5Hash.cs:32
bool StartGameClicked(GUIButton button, object userdata)
MultiPlayerCampaignSetupUI(GUIComponent newGameContainer, GUIComponent loadGameContainer, List< CampaignMode.SaveInfo > saveFiles=null)
override void CreateLoadMenu(IEnumerable< CampaignMode.SaveInfo > saveFiles=null)
SettingValue< StartingBalanceAmountOption > StartingFunds