2 using Microsoft.Xna.Framework;
4 using System.Collections.Generic;
19 ForceMapUI || CoroutineManager.IsCoroutineRunning(
"LevelTransition") ||
27 if (CoroutineManager.IsCoroutineRunning(
"LevelTransition") || CoroutineManager.IsCoroutineRunning(
"SubmarineTransition") || gameOver) {
return; }
35 roundSummary.ContinueButton.
Visible)
47 private float endTimer;
49 private bool savedOnStart;
51 private bool gameOver;
53 private Character lastControlledCharacter;
55 private bool showCampaignResetText;
59 get {
return PurchasedHullRepairsInLatestSave; }
62 PurchasedHullRepairsInLatestSave = value;
75 get {
return PurchasedItemRepairsInLatestSave; }
78 PurchasedItemRepairsInLatestSave = value;
82 #region Constructors/initialization
92 map =
new Map(
this, mapSeed);
97 var variant = Rand.Range(0, jobPrefab.
Variants);
107 private SinglePlayerCampaign(XElement element) : base(GameModePreset.SinglePlayerCampaign, CampaignSettings.
Empty)
110 foreach (var subElement
in element.Elements())
112 switch (subElement.Name.ToString().ToLowerInvariant())
122 foreach (var subElement
in element.Elements())
124 switch (subElement.Name.ToString().ToLowerInvariant())
126 case CampaignSettings.LowerCaseSaveElementName:
127 Settings =
new CampaignSettings(subElement);
130 GameMain.GameSession.CrewManager =
new CrewManager(subElement,
true);
139 case "pendingupgrades":
140 case "upgrademanager":
146 case Wallet.LowerCaseSaveElementName:
153 GameMain.GameSession.EventManager.Load(subElement);
163 int oldMoney = element.GetAttributeInt(
"money", 0);
173 PurchasedHullRepairsInLatestSave = element.GetAttributeBool(
"purchasedhullrepairs",
false);
174 PurchasedItemRepairsInLatestSave = element.GetAttributeBool(
"purchaseditemrepairs",
false);
175 CheatsEnabled = element.GetAttributeBool(
"cheatsenabled",
false);
178 DebugConsole.CheatsEnabled =
true;
179 if (!AchievementManager.CheatsEnabled)
181 AchievementManager.CheatsEnabled =
true;
182 new GUIMessageBox(
"Cheats enabled",
"Cheat commands have been enabled on the campaign. You will not receive Steam Achievements until you restart the game.");
188 throw new System.Exception(
"Failed to load the campaign save file (saved with an older, incompatible version of Barotrauma).");
206 private void InitUI()
213 StartRound = () => { TryEndRound(); }
220 onConfirm: () => TryEndRound(),
242 GUI.SetSavingIndicatorState(
true);
255 GUI.DisableSavingIndicatorDelayed();
266 private IEnumerable<CoroutineStatus> DoLoadInitialLevel(
LevelData level,
bool mirror)
271 CoroutineManager.StartCoroutine(DoInitialCameraTransition(),
"SinglePlayerCampaign.DoInitialCameraTransition");
276 private IEnumerable<CoroutineStatus> DoInitialCameraTransition()
278 while (GameMain.Instance.LoadingScreenOpen)
280 yield
return CoroutineStatus.
Running;
283 if (prevControlled?.AIController !=
null)
285 prevControlled.AIController.Enabled =
false;
288 prevControlled?.ClearInputs();
290 GUI.DisableHUD =
true;
291 while (GameMain.Instance.LoadingScreenOpen)
293 yield
return CoroutineStatus.Running;
298 if (SlideshowPrefab.Prefabs.TryGet(
"campaignstart".ToIdentifier(), out var slideshow))
302 var outpost = GameMain.GameSession.Level.StartOutpost;
303 var borders = outpost.GetDockedBorders();
304 borders.Location += outpost.WorldPosition.ToPoint();
305 GameMain.GameScreen.Cam.Position =
new Vector2(borders.X + borders.Width / 2, borders.Y - borders.Height / 2);
306 float startZoom = 0.8f /
307 ((float)Math.Max(borders.Width, borders.Height) / (float)GameMain.GameScreen.Cam.Resolution.X);
308 GameMain.GameScreen.Cam.Zoom = GameMain.GameScreen.Cam.MinZoom = Math.Min(startZoom, GameMain.GameScreen.Cam.MinZoom);
311 GUI.PreventPauseMenuToggle =
true;
312 yield
return CoroutineStatus.Running;
314 GUI.PreventPauseMenuToggle =
false;
315 var transition =
new CameraTransition(prevControlled, GameMain.GameScreen.Cam,
321 startZoom: startZoom, endZoom: 1.0f)
323 AllowInterrupt =
true,
324 RemoveControlFromCharacter =
false
326 while (transition.Running)
328 yield
return CoroutineStatus.Running;
330 showCampaignResetText =
false;
334 ISpatialEntity transitionTarget;
335 transitionTarget = (ISpatialEntity)prevControlled ??
Submarine.MainSub;
337 var transition =
new CameraTransition(transitionTarget, GameMain.GameScreen.Cam,
340 losFadeIn: prevControlled !=
null,
342 startZoom: 0.5f, endZoom: 1.0f)
344 AllowInterrupt =
true,
345 RemoveControlFromCharacter =
false
347 while (transition.Running)
349 yield
return CoroutineStatus.Running;
353 if (prevControlled !=
null)
355 prevControlled.SelectedItem = prevControlled.SelectedSecondaryItem =
null;
356 if (prevControlled.AIController !=
null)
358 prevControlled.AIController.Enabled =
true;
362 if (prevControlled !=
null)
366 GUI.DisableHUD =
false;
367 yield
return CoroutineStatus.Success;
374 SoundPlayer.OverrideMusicType = (success ?
"endround" :
"crewdead").ToIdentifier();
375 SoundPlayer.OverrideMusicDuration = 18.0f;
376 GUI.SetSavingIndicatorState(success);
391 if (continueButton !=
null)
393 continueButton.Visible =
false;
399 switch (transitionType)
402 throw new InvalidOperationException(
"Level transition failed (no transitions available).");
429 transitionType ==
TransitionType.LeaveLocation ? Alignment.BottomCenter : Alignment.Center,
435 float fadeOutDuration = endTransition.PanDuration;
437 while (t < fadeOutDuration || endTransition.Running)
439 t += CoroutineManager.DeltaTime;
440 overlayColor = Color.Lerp(Color.Transparent, Color.White, t / fadeOutDuration);
456 EnableRoundSummaryGameOverState();
464 if (continueButton !=
null)
466 continueButton.Visible =
true;
469 GUI.DisableHUD =
false;
470 GUI.ClearCursorWait();
475 GUI.SetSavingIndicatorState(
false);
484 GUI.DisableHUD =
false;
487 showCampaignResetText =
true;
493 public override void Update(
float deltaTime)
495 if (CoroutineManager.IsCoroutineRunning(
"LevelTransition") || CoroutineManager.IsCoroutineRunning(
"SubmarineTransition") || gameOver) {
return; }
497 base.Update(deltaTime);
509 roundSummary.ContinueButton.
Visible)
520 if (!GUI.DisableHUD && !GUI.DisableUpperHUD)
523 if (CoroutineManager.IsCoroutineRunning(
"LevelTransition") ||
ForceMapUI) {
return; }
569 else if (transitionType ==
TransitionType.ProgressToNextLocation &&
574 else if (transitionType ==
TransitionType.ReturnToPreviousLocation &&
583 HintManager.OnAvailableTransition(transitionType);
595 endTimer -= deltaTime;
596 if (endTimer <= 0.0f) { GameOver(); }
600 private bool TryEndRound()
603 if (leavingSub ==
null || transitionType ==
TransitionType.None) {
return false; }
605 if (nextLevel ==
null)
613 else if (transitionType ==
TransitionType.ProgressToNextEmptyLocation)
619 if (subsToLeaveBehind.Any())
621 LocalizedString msg = TextManager.Get(subsToLeaveBehind.Count == 1 ?
"LeaveSubBehind" :
"LeaveSubsBehind");
623 var msgBox =
new GUIMessageBox(TextManager.Get(
"Warning"), msg,
new LocalizedString[] { TextManager.Get(
"Yes"), TextManager.Get(
"No") });
624 msgBox.Buttons[0].OnClicked += (btn, userdata) => {
LoadNewLevel();
return true; } ;
625 msgBox.Buttons[0].OnClicked += msgBox.Close;
626 msgBox.Buttons[0].UserData =
Submarine.Loaded.FindAll(s => !subsToLeaveBehind.Contains(s));
627 msgBox.Buttons[1].OnClicked += msgBox.Close;
637 private void GameOver()
640 GameMain.GameSession.EndRound(
"", transitionType:
TransitionType.None);
641 EnableRoundSummaryGameOverState();
644 private void EnableRoundSummaryGameOverState()
646 var roundSummary = GameMain.GameSession.RoundSummary;
647 if (roundSummary !=
null)
649 roundSummary.ContinueButton.Visible =
false;
650 roundSummary.ContinueButton.IgnoreLayoutGroups =
true;
652 new GUIButton(
new RectTransform(
new Vector2(0.25f, 1.0f), roundSummary.ButtonArea.RectTransform),
653 TextManager.Get(
"QuitButton"))
655 OnClicked = (GUIButton button,
object obj) =>
657 GameMain.MainMenuScreen.Select();
658 GUIMessageBox.MessageBoxes.Remove(roundSummary.Frame);
662 new GUIButton(
new RectTransform(
new Vector2(0.25f, 1.0f), roundSummary.ButtonArea.RectTransform),
663 TextManager.Get(
"LoadGameButton"))
665 OnClicked = (GUIButton button,
object obj) =>
667 GameMain.GameSession.LoadPreviousSave();
668 GUIMessageBox.MessageBoxes.Remove(roundSummary.Frame);
675 public override void Save(XElement element,
bool isSavingOnLoading)
677 XElement modeElement =
new XElement(
"SinglePlayerCampaign",
693 if (c.
Info ==
null) {
continue; }
715 modeElement.Add(
Bank.Save());
716 element.Add(modeElement);
void SaveActiveOrders(XElement parentElement=null)
UpgradeManager UpgradeManager
void LoadStats(XElement element)
Task SelectSummaryScreen(RoundSummary roundSummary, LevelData newLevel, bool mirror, Action action)
TransitionType GetAvailableTransition()
bool PurchasedLostShuttlesInLatestSave
SlideshowPlayer SlideshowPlayer
readonly CampaignMetadata CampaignMetadata
GUIFrame campaignUIContainer
bool??????? ShowCampaignUI
virtual Wallet Wallet
Gets the current personal wallet In singleplayer this is the campaign bank and in multiplayer this is...
void SavePets(XElement parentElement=null)
CampaignSettings Settings
SubmarineInfo PendingSubmarineSwitch
GUIButton CreateEndRoundButton()
XElement ActiveOrdersElement
SubmarineInfo GetPredefinedStartOutpost()
const float EndTransitionDuration
void KeepCharactersCloseToOutpost(float deltaTime)
static List< Submarine > GetSubsToLeaveBehind(Submarine leavingSub)
void TryEndRoundWithFuelCheck(Action onConfirm, Action onReturnToMapScreen)
readonly CargoManager CargoManager
CampaignMode.InteractionType SelectedTab
void SelectTab(CampaignMode.InteractionType tab, Character npc=null)
void InitPurchasedIDCards()
void CreatePurchasedItems()
void SavePurchasedItems(XElement parentElement)
void LoadPurchasedItems(XElement element)
void Save(XElement healthElement)
CharacterHealth CharacterHealth
static void SaveInventory(Inventory inventory, XElement parentElement)
static readonly List< Character > CharacterList
CharacterInventory Inventory
static bool DisableControls
static Character? Controlled
Stores information about the Character that is needed between rounds in the menu etc....
static void SaveOrderData(CharacterInfo characterInfo, XElement parentElement)
Save current orders to the parameter element
static readonly Identifier HumanSpeciesName
void Update(float deltaTime)
static CoroutineStatus Running
static CoroutineStatus Success
Responsible for keeping track of the characters in the player crew, saving and loading their orders,...
ChatBox ChatBox
Present only in single player games. In multiplayer. The chatbox is found from GameSession....
IEnumerable< Character > GetCharacters()
void RemoveCharacterInfo(CharacterInfo characterInfo)
Remove info of a selected character. The character will not be visible in any menus or the round summ...
void ClearCurrentOrders()
bool IsFired(Character character)
void AddCharacterInfo(CharacterInfo characterInfo)
XElement Save(XElement parentElement)
Saves the current crew. Note that this is client-only code (only used in the single player campaign) ...
void UpdateReports()
Enables/disables report buttons when needed
void InitSinglePlayerRound()
void RegisterEventHistory(bool registerFinishedOnly=false)
Registers the exhaustible events in the level as exhausted, and adds the current events to the event ...
void UpdateManually(float deltaTime, bool alsoChildren=false, bool recursive=true)
By default, all the gui elements are updated automatically in the same order they appear on the updat...
static readonly List< GUIComponent > MessageBoxes
static GUIComponent VisibleBox
static GameSession?? GameSession
CoroutineHandle ShowLoading(IEnumerable< CoroutineStatus > loader, bool waitKeyHit=true)
static GameScreen GameScreen
static CampaignEndScreen CampaignEndScreen
CampaignDataPath DataPath
RoundSummary RoundSummary
SubmarineInfo SubmarineInfo
readonly EventManager EventManager
void StartRound(string levelSeed, float? difficulty=null, LevelGenerationParams? levelGenerationParams=null, Identifier forceBiome=default)
void EndRound(string endMessage, CampaignMode.TransitionType transitionType=CampaignMode.TransitionType.None, TraitorManager.TraitorResults? traitorResults=null)
void DeleteAllItems()
Deletes all items inside the inventory (and also recursively all items inside the items)
static readonly PrefabCollection< JobPrefab > Prefabs
Sprite GetPortrait(int randomSeed)
void ProgressWorld(CampaignMode campaign, CampaignMode.TransitionType transitionType, float roundDuration)
void Visit(Location location)
static Map Load(CampaignMode campaign, XElement element)
Load a previously saved map from an xml element
List< Location > Locations
void SetLocation(int index)
Location SelectedLocation
void Save(XElement element)
LocationConnection SelectedConnection
void MoveToNextLocation()
void SelectLocation(int index)
override void Save(XElement element, bool isSavingOnLoading)
const int MinimumInitialMoney
override void EndCampaignProjSpecific()
override bool PurchasedLostShuttles
override void HUDScaleChanged()
static SinglePlayerCampaign StartNew(string mapSeed, CampaignSettings startingSettings)
Start a completely new single player campaign
override bool PurchasedItemRepairs
override bool PurchasedHullRepairs
override IEnumerable< CoroutineStatus > DoLevelTransition(TransitionType transitionType, LevelData newLevel, Submarine leavingSub, bool mirror)
override void UpdateWhilePaused(float deltaTime)
static SinglePlayerCampaign Load(XElement element)
Load a previously saved single player campaign from xml
override void Update(float deltaTime)
override void LoadInitialLevel()
Load the first level and start the round after loading a save file
IEnumerable< Submarine > DockedTo
static Submarine MainSub
Note that this can be null in some situations, e.g. editors and missions that don't load a submarine.
IEnumerable< Submarine > GetConnectedSubs()
Returns a list of all submarines that are connected to this one via docking ports,...
This class handles all upgrade logic. Storing, applying, checking and validation of upgrades.
void Save(XElement? parent)
void SanityCheckUpgrades()
Validates that upgrade values stored in CampaignMetadata matches the values on the submarine and fixe...
void ApplyUpgrades()
Applies all our pending upgrades to the submarine.
@ Character
Characters only