using Barotrauma.Extensions;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Barotrauma
{
class SinglePlayerCampaign : CampaignMode
{
public const int MinimumInitialMoney = 0;
public override bool Paused
{
get { return ForceMapUI || CoroutineManager.IsCoroutineRunning("LevelTransition") || ShowCampaignUI && CampaignUI.SelectedTab == InteractionType.Map; }
}
public override void UpdateWhilePaused(float deltaTime)
{
if (CoroutineManager.IsCoroutineRunning("LevelTransition") || CoroutineManager.IsCoroutineRunning("SubmarineTransition") || gameOver) { return; }
if (PlayerInput.SecondaryMouseButtonClicked() ||
PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape))
{
ShowCampaignUI = false;
if (GUIMessageBox.VisibleBox?.UserData is RoundSummary roundSummary &&
roundSummary.ContinueButton != null &&
roundSummary.ContinueButton.Visible)
{
GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox);
}
}
if (CrewManager.ChatBox != null)
{
CrewManager.ChatBox.Update(deltaTime);
}
CrewManager.UpdateReports();
}
private float endTimer;
private bool savedOnStart;
private bool gameOver;
private Character lastControlledCharacter;
private bool showCampaignResetText;
#region Constructors/initialization
///
/// Instantiates a new single player campaign
///
private SinglePlayerCampaign(string mapSeed, CampaignSettings settings) : base(GameModePreset.SinglePlayerCampaign)
{
CampaignMetadata = new CampaignMetadata(this);
UpgradeManager = new UpgradeManager(this);
map = new Map(this, mapSeed, settings);
Settings = settings;
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs)
{
for (int i = 0; i < jobPrefab.InitialCount; i++)
{
var variant = Rand.Range(0, jobPrefab.Variants);
CrewManager.AddCharacterInfo(new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: jobPrefab, variant: variant));
}
}
InitCampaignData();
InitUI();
}
///
/// Loads a previously saved single player campaign from XML
///
private SinglePlayerCampaign(XElement element) : base(GameModePreset.SinglePlayerCampaign)
{
IsFirstRound = false;
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "campaignsettings":
Settings = new CampaignSettings(subElement);
break;
case "crew":
GameMain.GameSession.CrewManager = new CrewManager(subElement, true);
break;
case "map":
map = Map.Load(this, subElement, Settings);
break;
case "metadata":
CampaignMetadata = new CampaignMetadata(this, subElement);
break;
case "cargo":
CargoManager.LoadPurchasedItems(subElement);
break;
case "pendingupgrades": //backwards compatibility
case "upgrademanager":
UpgradeManager = new UpgradeManager(this, subElement, isSingleplayer: true);
break;
case "pets":
petsElement = subElement;
break;
}
}
CampaignMetadata ??= new CampaignMetadata(this);
UpgradeManager ??= new UpgradeManager(this);
InitCampaignData();
InitUI();
Money = element.GetAttributeInt("money", 0);
PurchasedLostShuttles = element.GetAttributeBool("purchasedlostshuttles", false);
PurchasedHullRepairs = element.GetAttributeBool("purchasedhullrepairs", false);
PurchasedItemRepairs = element.GetAttributeBool("purchaseditemrepairs", false);
CheatsEnabled = element.GetAttributeBool("cheatsenabled", false);
if (CheatsEnabled)
{
DebugConsole.CheatsEnabled = true;
#if USE_STEAM
if (!SteamAchievementManager.CheatsEnabled)
{
SteamAchievementManager.CheatsEnabled = true;
new GUIMessageBox("Cheats enabled", "Cheat commands have been enabled on the campaign. You will not receive Steam Achievements until you restart the game.");
}
#endif
}
if (map == null)
{
throw new System.Exception("Failed to load the campaign save file (saved with an older, incompatible version of Barotrauma).");
}
savedOnStart = true;
}
///
/// Start a completely new single player campaign
///
public static SinglePlayerCampaign StartNew(string mapSeed, SubmarineInfo selectedSub, CampaignSettings settings)
{
var campaign = new SinglePlayerCampaign(mapSeed, settings);
return campaign;
}
///
/// Load a previously saved single player campaign from xml
///
///
///
public static SinglePlayerCampaign Load(XElement element)
{
return new SinglePlayerCampaign(element);
}
private void InitUI()
{
int buttonHeight = (int)(GUI.Scale * 40);
int buttonWidth = GUI.IntScale(450);
endRoundButton = new GUIButton(HUDLayoutSettings.ToRectTransform(new Rectangle((GameMain.GraphicsWidth / 2) - (buttonWidth / 2), HUDLayoutSettings.ButtonAreaTop.Center.Y - (buttonHeight / 2), buttonWidth, buttonHeight), GUICanvas.Instance),
TextManager.Get("EndRound"), textAlignment: Alignment.Center, style: "EndRoundButton")
{
Pulse = true,
TextBlock =
{
Shadow = true,
AutoScaleHorizontal = true
},
OnClicked = (btn, userdata) =>
{
var availableTransition = GetAvailableTransition(out _, out _);
if (Character.Controlled != null &&
availableTransition == TransitionType.ReturnToPreviousLocation &&
Character.Controlled?.Submarine == Level.Loaded?.StartOutpost)
{
TryEndRound();
}
else if (Character.Controlled != null &&
availableTransition == TransitionType.ProgressToNextLocation &&
Character.Controlled?.Submarine == Level.Loaded?.EndOutpost)
{
TryEndRound();
}
else
{
ShowCampaignUI = true;
CampaignUI.SelectTab(InteractionType.Map);
}
return true;
}
};
campaignUIContainer = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: "InnerGlow", color: Color.Black);
CampaignUI = new CampaignUI(this, campaignUIContainer)
{
StartRound = () => { TryEndRound(); }
};
}
#endregion
public override void Start()
{
base.Start();
CargoManager.CreatePurchasedItems();
UpgradeManager.ApplyUpgrades();
UpgradeManager.SanityCheckUpgrades(Submarine.MainSub);
if (!savedOnStart)
{
GUI.SetSavingIndicatorState(true);
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
savedOnStart = true;
}
crewDead = false;
endTimer = 5.0f;
CrewManager.InitSinglePlayerRound();
if (petsElement != null)
{
PetBehavior.LoadPets(petsElement);
}
CrewManager.LoadActiveOrders();
GUI.DisableSavingIndicatorDelayed();
}
protected override void LoadInitialLevel()
{
//no level loaded yet -> show a loading screen and load the current location (outpost)
GameMain.Instance.ShowLoading(
DoLoadInitialLevel(map.SelectedConnection?.LevelData ?? map.CurrentLocation.LevelData,
mirror: map.CurrentLocation != map.SelectedConnection?.Locations[0]));
}
private IEnumerable