Merge branch 'dev' of https://github.com/Regalis11/Barotrauma into unstable
This commit is contained in:
@@ -80,7 +80,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (ID != Entity.NullEntityID)
|
||||
{
|
||||
DebugConsole.ShowError("Error setting SoldItem.ID: ID has already been set and should not be changed.");
|
||||
DebugConsole.LogError("Error setting SoldItem.ID: ID has already been set and should not be changed.");
|
||||
return;
|
||||
}
|
||||
ID = id;
|
||||
@@ -128,7 +128,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (Item != null)
|
||||
{
|
||||
DebugConsole.ShowError($"Trying to set SoldEntity.Item, but it's already set!\n{Environment.StackTrace.CleanupStackTrace()}");
|
||||
DebugConsole.LogError($"Trying to set SoldEntity.Item, but it's already set!\n{Environment.StackTrace.CleanupStackTrace()}");
|
||||
return;
|
||||
}
|
||||
Item = item;
|
||||
@@ -302,6 +302,10 @@ namespace Barotrauma
|
||||
var itemsInStoreCrate = GetBuyCrateItems(storeIdentifier, create: true);
|
||||
foreach (PurchasedItem item in itemsToPurchase)
|
||||
{
|
||||
// Exchange money
|
||||
int itemValue = item.Quantity * buyValues[item.ItemPrefab];
|
||||
if (!campaign.TryPurchase(client, itemValue)) { continue; }
|
||||
|
||||
// Add to the purchased items
|
||||
var purchasedItem = itemsPurchasedFromStore.Find(pi => pi.ItemPrefab == item.ItemPrefab);
|
||||
if (purchasedItem != null)
|
||||
@@ -313,9 +317,6 @@ namespace Barotrauma
|
||||
purchasedItem = new PurchasedItem(item.ItemPrefab, item.Quantity, client);
|
||||
itemsPurchasedFromStore.Add(purchasedItem);
|
||||
}
|
||||
// Exchange money
|
||||
int itemValue = item.Quantity * buyValues[item.ItemPrefab];
|
||||
campaign.TryPurchase(client, itemValue);
|
||||
if (GameMain.IsSingleplayer)
|
||||
{
|
||||
GameAnalyticsManager.AddMoneySpentEvent(itemValue, GameAnalyticsManager.MoneySink.Store, item.ItemPrefab.Identifier.Value);
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using Barotrauma.Extensions;
|
||||
#if CLIENT
|
||||
using Barotrauma.Tutorials;
|
||||
#endif
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -195,6 +198,34 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the character from the crew (and crew menus).
|
||||
/// </summary>
|
||||
/// <param name="character">The character to remove</param>
|
||||
/// <param name="removeInfo">If the character info is also removed, the character will not be visible in the round summary.</param>
|
||||
public void RemoveCharacter(Character character, bool removeInfo = false, bool resetCrewListIndex = true)
|
||||
{
|
||||
if (character == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Tried to remove a null character from CrewManager.\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
characters.Remove(character);
|
||||
if (removeInfo)
|
||||
{
|
||||
characterInfos.Remove(character.Info);
|
||||
#if CLIENT
|
||||
RemoveCharacterFromCrewList(character);
|
||||
#endif
|
||||
}
|
||||
#if CLIENT
|
||||
if (resetCrewListIndex)
|
||||
{
|
||||
ResetCrewListIndex(character);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public void AddCharacterInfo(CharacterInfo characterInfo)
|
||||
{
|
||||
if (characterInfos.Contains(characterInfo))
|
||||
@@ -348,6 +379,9 @@ namespace Barotrauma
|
||||
private void UpdateConversations(float deltaTime)
|
||||
{
|
||||
if (GameMain.GameSession?.GameMode?.Preset == GameModePreset.TestMode) { return; }
|
||||
#if CLIENT
|
||||
if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode && tutorialMode.Tutorial is Tutorial tutorial && tutorial.TutorialPrefab.DisableBotConversations) { return; }
|
||||
#endif
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.ServerSettings.DisableBotConversations) { return; }
|
||||
|
||||
conversationTimer -= deltaTime;
|
||||
|
||||
@@ -96,20 +96,17 @@ namespace Barotrauma
|
||||
private object GetTypeOrDefault(Identifier identifier, Type type, object defaultValue)
|
||||
{
|
||||
object? value = GetValue(identifier);
|
||||
|
||||
if (value == null)
|
||||
if (value != null)
|
||||
{
|
||||
SetValue(identifier, defaultValue);
|
||||
if (value.GetType() == type)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError($"Attempted to get value \"{identifier}\" as a {type} but the value is {value.GetType()}.");
|
||||
}
|
||||
}
|
||||
else if (value.GetType() == type)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError($"Attempted to get value \"{identifier}\" as a {type} but the value is {value.GetType()}.");
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Barotrauma
|
||||
public double TotalPlayTime;
|
||||
public int TotalPassedLevels;
|
||||
|
||||
public enum InteractionType { None, Talk, Examine, Map, Crew, Store, Repair, Upgrade, PurchaseSub, MedicalClinic, Cargo }
|
||||
public enum InteractionType { None, Talk, Examine, Map, Crew, Store, Upgrade, PurchaseSub, MedicalClinic, Cargo }
|
||||
|
||||
public static bool BlocksInteraction(InteractionType interactionType)
|
||||
{
|
||||
@@ -85,7 +85,9 @@ namespace Barotrauma
|
||||
|
||||
public bool CheatsEnabled;
|
||||
|
||||
public const int HullRepairCost = 500, ItemRepairCost = 500, ShuttleReplaceCost = 1000;
|
||||
public const float HullRepairCostPerDamage = 0.5f, ItemRepairCostPerRepairDuration = 1.0f;
|
||||
public const int ShuttleReplaceCost = 1000;
|
||||
public const int MaxHullRepairCost = 2000, MaxItemRepairCost = 2000;
|
||||
|
||||
protected bool wasDocked;
|
||||
|
||||
@@ -131,6 +133,8 @@ namespace Barotrauma
|
||||
protected set;
|
||||
}
|
||||
|
||||
public bool PurchasedLostShuttlesInLatestSave, PurchasedHullRepairsInLatestSave, PurchasedItemRepairsInLatestSave;
|
||||
|
||||
public virtual bool PurchasedHullRepairs { get; set; }
|
||||
public virtual bool PurchasedLostShuttles { get; set; }
|
||||
public virtual bool PurchasedItemRepairs { get; set; }
|
||||
@@ -152,8 +156,9 @@ namespace Barotrauma
|
||||
{
|
||||
if (!(e.ChangedData.BalanceChanged is Some<int> { Value: var changed })) { return; }
|
||||
|
||||
bool isGain = changed > 0;
|
||||
if (changed != 0) { return; }
|
||||
|
||||
bool isGain = changed > 0;
|
||||
Color clr = isGain ? GUIStyle.Yellow : GUIStyle.Red;
|
||||
|
||||
switch (e.Owner)
|
||||
@@ -225,7 +230,8 @@ namespace Barotrauma
|
||||
#if CLIENT
|
||||
prevCampaignUIAutoOpenType = TransitionType.None;
|
||||
#endif
|
||||
if (PurchasedHullRepairs)
|
||||
|
||||
if (PurchasedHullRepairsInLatestSave)
|
||||
{
|
||||
foreach (Structure wall in Structure.WallList)
|
||||
{
|
||||
@@ -238,9 +244,9 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
PurchasedHullRepairs = false;
|
||||
PurchasedHullRepairsInLatestSave = PurchasedHullRepairs = false;
|
||||
}
|
||||
if (PurchasedItemRepairs)
|
||||
if (PurchasedItemRepairsInLatestSave)
|
||||
{
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
@@ -253,13 +259,46 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
PurchasedItemRepairs = false;
|
||||
PurchasedItemRepairsInLatestSave = PurchasedItemRepairs = false;
|
||||
}
|
||||
PurchasedLostShuttles = false;
|
||||
PurchasedLostShuttlesInLatestSave = PurchasedLostShuttles = false;
|
||||
var connectedSubs = Submarine.MainSub.GetConnectedSubs();
|
||||
wasDocked = Level.Loaded.StartOutpost != null && connectedSubs.Contains(Level.Loaded.StartOutpost);
|
||||
}
|
||||
|
||||
public int GetHullRepairCost()
|
||||
{
|
||||
float totalDamage = 0;
|
||||
foreach (Structure wall in Structure.WallList)
|
||||
{
|
||||
if (wall.Submarine == null || wall.Submarine.Info.Type != SubmarineType.Player) { continue; }
|
||||
if (wall.Submarine == Submarine.MainSub || Submarine.MainSub.DockedTo.Contains(wall.Submarine))
|
||||
{
|
||||
for (int i = 0; i < wall.SectionCount; i++)
|
||||
{
|
||||
totalDamage += wall.SectionDamage(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (int)Math.Min(totalDamage * HullRepairCostPerDamage, MaxHullRepairCost);
|
||||
}
|
||||
|
||||
public int GetItemRepairCost()
|
||||
{
|
||||
float totalRepairDuration = 0.0f;
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (item.Submarine == null || item.Submarine.Info.Type != SubmarineType.Player) { continue; }
|
||||
if (item.Submarine == Submarine.MainSub || Submarine.MainSub.DockedTo.Contains(item.Submarine))
|
||||
{
|
||||
var repairable = item.GetComponent<Repairable>();
|
||||
if (repairable == null) { continue; }
|
||||
totalRepairDuration += repairable.FixDurationHighSkill * (1.0f - item.Condition / item.MaxCondition);
|
||||
}
|
||||
}
|
||||
return (int)Math.Min(totalRepairDuration * ItemRepairCostPerRepairDuration, MaxItemRepairCost);
|
||||
}
|
||||
|
||||
public void InitCampaignData()
|
||||
{
|
||||
Factions = new List<Faction>();
|
||||
@@ -689,7 +728,7 @@ namespace Barotrauma
|
||||
}
|
||||
foreach (LocationConnection connection in Map.Connections)
|
||||
{
|
||||
connection.Difficulty = connection.Biome.MaxDifficulty;
|
||||
connection.Difficulty = connection.Biome.AdjustedMaxDifficulty;
|
||||
connection.LevelData = new LevelData(connection)
|
||||
{
|
||||
IsBeaconActive = false
|
||||
@@ -698,7 +737,7 @@ namespace Barotrauma
|
||||
}
|
||||
foreach (Location location in Map.Locations)
|
||||
{
|
||||
location.LevelData = new LevelData(location, location.Biome.MaxDifficulty);
|
||||
location.LevelData = new LevelData(location, location.Biome.AdjustedMaxDifficulty);
|
||||
location.Reset();
|
||||
}
|
||||
Map.SetLocation(Map.Locations.IndexOf(Map.StartLocation));
|
||||
|
||||
+4
-15
@@ -1,27 +1,16 @@
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class CharacterCampaignData
|
||||
{
|
||||
public CharacterInfo CharacterInfo
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public readonly CharacterInfo CharacterInfo;
|
||||
|
||||
public readonly string Name;
|
||||
|
||||
public string ClientEndPoint
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public ulong SteamID
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public readonly Address ClientAddress;
|
||||
public readonly Option<AccountId> AccountId;
|
||||
|
||||
private XElement itemData;
|
||||
private XElement healthData;
|
||||
|
||||
+15
-17
@@ -10,8 +10,6 @@ namespace Barotrauma
|
||||
{
|
||||
partial class MultiPlayerCampaign : CampaignMode
|
||||
{
|
||||
public const int MinimumInitialMoney = 500;
|
||||
|
||||
[Flags]
|
||||
public enum NetFlags : UInt16
|
||||
{
|
||||
@@ -151,9 +149,9 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
private void Load(XElement element)
|
||||
{
|
||||
PurchasedLostShuttles = element.GetAttributeBool("purchasedlostshuttles", false);
|
||||
PurchasedHullRepairs = element.GetAttributeBool("purchasedhullrepairs", false);
|
||||
PurchasedItemRepairs = element.GetAttributeBool("purchaseditemrepairs", false);
|
||||
PurchasedLostShuttlesInLatestSave = element.GetAttributeBool("purchasedlostshuttles", false);
|
||||
PurchasedHullRepairsInLatestSave = element.GetAttributeBool("purchasedhullrepairs", false);
|
||||
PurchasedItemRepairsInLatestSave = element.GetAttributeBool("purchaseditemrepairs", false);
|
||||
CheatsEnabled = element.GetAttributeBool("cheatsenabled", false);
|
||||
if (CheatsEnabled)
|
||||
{
|
||||
@@ -294,14 +292,14 @@ namespace Barotrauma
|
||||
|
||||
private static void WriteItems(IWriteMessage msg, Dictionary<Identifier, List<PurchasedItem>> purchasedItems)
|
||||
{
|
||||
msg.Write((byte)purchasedItems.Count);
|
||||
msg.WriteByte((byte)purchasedItems.Count);
|
||||
foreach (var storeItems in purchasedItems)
|
||||
{
|
||||
msg.Write(storeItems.Key);
|
||||
msg.Write((UInt16)storeItems.Value.Count);
|
||||
msg.WriteIdentifier(storeItems.Key);
|
||||
msg.WriteUInt16((UInt16)storeItems.Value.Count);
|
||||
foreach (var item in storeItems.Value)
|
||||
{
|
||||
msg.Write(item.ItemPrefabIdentifier);
|
||||
msg.WriteIdentifier(item.ItemPrefabIdentifier);
|
||||
msg.WriteRangedInteger(item.Quantity, 0, CargoManager.MaxQuantity);
|
||||
}
|
||||
}
|
||||
@@ -328,18 +326,18 @@ namespace Barotrauma
|
||||
|
||||
private static void WriteItems(IWriteMessage msg, Dictionary<Identifier, List<SoldItem>> soldItems)
|
||||
{
|
||||
msg.Write((byte)soldItems.Count);
|
||||
msg.WriteByte((byte)soldItems.Count);
|
||||
foreach (var storeItems in soldItems)
|
||||
{
|
||||
msg.Write(storeItems.Key);
|
||||
msg.Write((UInt16)storeItems.Value.Count);
|
||||
msg.WriteIdentifier(storeItems.Key);
|
||||
msg.WriteUInt16((UInt16)storeItems.Value.Count);
|
||||
foreach (var item in storeItems.Value)
|
||||
{
|
||||
msg.Write(item.ItemPrefab.Identifier);
|
||||
msg.Write((UInt16)item.ID);
|
||||
msg.Write(item.Removed);
|
||||
msg.Write(item.SellerID);
|
||||
msg.Write((byte)item.Origin);
|
||||
msg.WriteIdentifier(item.ItemPrefab.Identifier);
|
||||
msg.WriteUInt16((UInt16)item.ID);
|
||||
msg.WriteBoolean(item.Removed);
|
||||
msg.WriteByte(item.SellerID);
|
||||
msg.WriteByte((byte)item.Origin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Networking;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -11,37 +13,37 @@ namespace Barotrauma
|
||||
|
||||
public void AssignTeamIDs(IEnumerable<Client> clients)
|
||||
{
|
||||
int teamWeight = 0;
|
||||
List<Client> randList = new List<Client>(clients);
|
||||
for (int i = 0; i < randList.Count; i++)
|
||||
int team1Count = 0, team2Count = 0;
|
||||
//if a client has a preference, assign them to that team
|
||||
List<Client> unassignedClients = new List<Client>(clients);
|
||||
for (int i = 0; i < unassignedClients.Count; i++)
|
||||
{
|
||||
if (randList[i].PreferredTeam == CharacterTeamType.Team1 ||
|
||||
randList[i].PreferredTeam == CharacterTeamType.Team2)
|
||||
if (unassignedClients[i].PreferredTeam == CharacterTeamType.Team1 ||
|
||||
unassignedClients[i].PreferredTeam == CharacterTeamType.Team2)
|
||||
{
|
||||
randList[i].TeamID = randList[i].PreferredTeam;
|
||||
teamWeight += randList[i].PreferredTeam == CharacterTeamType.Team1 ? -1 : 1;
|
||||
randList.RemoveAt(i);
|
||||
assignTeam(unassignedClients[i], unassignedClients[i].PreferredTeam);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i<randList.Count; i++)
|
||||
{
|
||||
Client a = randList[i];
|
||||
int oi = Rand.Range(0, randList.Count - 1);
|
||||
Client b = randList[oi];
|
||||
randList[i] = b;
|
||||
randList[oi] = a;
|
||||
}
|
||||
int halfPlayers = (randList.Count / 2) + teamWeight;
|
||||
for (int i = 0; i < randList.Count; i++)
|
||||
|
||||
//assign the rest of the clients to the team that has the least players
|
||||
while (unassignedClients.Any())
|
||||
{
|
||||
if (i < halfPlayers)
|
||||
var randomClient = unassignedClients.GetRandom(Rand.RandSync.Unsynced);
|
||||
assignTeam(randomClient, team1Count < team2Count ? CharacterTeamType.Team1 : CharacterTeamType.Team2);
|
||||
}
|
||||
|
||||
void assignTeam(Client client, CharacterTeamType team)
|
||||
{
|
||||
client.TeamID = team;
|
||||
unassignedClients.Remove(client);
|
||||
if (team == CharacterTeamType.Team1)
|
||||
{
|
||||
randList[i].TeamID = CharacterTeamType.Team1;
|
||||
team1Count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
randList[i].TeamID = CharacterTeamType.Team2;
|
||||
team2Count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class TutorialPrefab : Prefab
|
||||
{
|
||||
|
||||
public static readonly PrefabCollection<TutorialPrefab> Prefabs =
|
||||
#if CLIENT
|
||||
new PrefabCollection<TutorialPrefab>(onSort: MainMenuScreen.UpdateInstanceTutorialButtons);
|
||||
#else
|
||||
new PrefabCollection<TutorialPrefab>();
|
||||
#endif
|
||||
|
||||
public readonly int Order;
|
||||
public readonly bool DisableBotConversations;
|
||||
public readonly bool AllowCharacterSwitch;
|
||||
|
||||
public readonly ContentPath SubmarinePath = ContentPath.FromRaw("Content/Tutorials/Dugong_Tutorial.sub");
|
||||
public readonly ContentPath OutpostPath = ContentPath.FromRaw("Content/Tutorials/TutorialOutpost.sub");
|
||||
public readonly string LevelSeed;
|
||||
public readonly string LevelParams;
|
||||
|
||||
private readonly ContentXElement tutorialCharacterElement;
|
||||
public readonly ImmutableArray<Identifier> StartingItemTags;
|
||||
|
||||
public readonly Identifier EventIdentifier;
|
||||
|
||||
public readonly Sprite Banner;
|
||||
|
||||
public TutorialPrefab(ContentFile file, ContentXElement element) : base(file, element.GetAttributeIdentifier("identifier", ""))
|
||||
{
|
||||
Order = element.GetAttributeInt("order", int.MaxValue);
|
||||
DisableBotConversations = element.GetAttributeBool("disablebotconversations", true);
|
||||
AllowCharacterSwitch = element.GetAttributeBool("allowcharacterswitch", false);
|
||||
|
||||
SubmarinePath = element.GetAttributeContentPath("submarinepath") ?? SubmarinePath;
|
||||
OutpostPath = element.GetAttributeContentPath("outpostpath") ?? OutpostPath;
|
||||
LevelSeed = element.GetAttributeString("levelseed", "nLoZLLtza");
|
||||
LevelParams = element.GetAttributeString("levelparams", "ColdCavernsTutorial");
|
||||
|
||||
tutorialCharacterElement = element.GetChildElement("characterinfo");
|
||||
if (tutorialCharacterElement != null)
|
||||
{
|
||||
StartingItemTags = tutorialCharacterElement
|
||||
.GetAttributeIdentifierArray("startingitemtags", new Identifier[0])
|
||||
.ToImmutableArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
StartingItemTags = ImmutableArray<Identifier>.Empty;
|
||||
}
|
||||
|
||||
var bannerElement = element.GetChildElement("banner");
|
||||
if (bannerElement != null)
|
||||
{
|
||||
Banner = new Sprite(bannerElement, lazyLoad: true);
|
||||
}
|
||||
|
||||
EventIdentifier = element.GetChildElement("scriptedevent")?.GetAttributeIdentifier("identifier", "") ?? Identifier.Empty;
|
||||
}
|
||||
|
||||
public CharacterInfo GetTutorialCharacterInfo()
|
||||
{
|
||||
if (tutorialCharacterElement == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Identifier speciesName = tutorialCharacterElement.GetAttributeIdentifier("speciesname", CharacterPrefab.HumanSpeciesName);
|
||||
Identifier jobPrefabIdentifier = tutorialCharacterElement.GetAttributeIdentifier("jobidentifier", "assistant");
|
||||
if (!JobPrefab.Prefabs.TryGet(jobPrefabIdentifier, out var jobPrefab))
|
||||
{
|
||||
jobPrefab = JobPrefab.Prefabs.First();
|
||||
}
|
||||
int jobVariant = tutorialCharacterElement.GetAttributeInt("variant", 0);
|
||||
var characterInfo = new CharacterInfo(speciesName, jobOrJobPrefab: jobPrefab, variant: jobVariant);
|
||||
foreach (var skillElement in tutorialCharacterElement.GetChildElements("skill"))
|
||||
{
|
||||
Identifier skillIdentifier = skillElement.GetAttributeIdentifier("identifier", "");
|
||||
if (skillIdentifier.IsEmpty) { continue; }
|
||||
float level = skillElement.GetAttributeFloat("level", 0.0f);
|
||||
characterInfo.SetSkillLevel(skillIdentifier, level);
|
||||
}
|
||||
return characterInfo;
|
||||
}
|
||||
|
||||
public override void Dispose() { }
|
||||
}
|
||||
}
|
||||
@@ -211,7 +211,7 @@ namespace Barotrauma
|
||||
if (selectedSub != null)
|
||||
{
|
||||
campaign.Bank.Deduct(selectedSub.Price);
|
||||
campaign.Bank.Balance = Math.Max(campaign.Bank.Balance, MultiPlayerCampaign.MinimumInitialMoney);
|
||||
campaign.Bank.Balance = Math.Max(campaign.Bank.Balance, 0);
|
||||
}
|
||||
return campaign;
|
||||
}
|
||||
@@ -222,7 +222,7 @@ namespace Barotrauma
|
||||
if (selectedSub != null)
|
||||
{
|
||||
campaign.Bank.TryDeduct(selectedSub.Price);
|
||||
campaign.Bank.Balance = Math.Max(campaign.Bank.Balance, MultiPlayerCampaign.MinimumInitialMoney);
|
||||
campaign.Bank.Balance = Math.Max(campaign.Bank.Balance, 0);
|
||||
}
|
||||
return campaign;
|
||||
}
|
||||
@@ -604,7 +604,7 @@ namespace Barotrauma
|
||||
if (GameMode is MultiPlayerCampaign mpCampaign)
|
||||
{
|
||||
mpCampaign.UpgradeManager.ApplyUpgrades();
|
||||
mpCampaign.UpgradeManager.SanityCheckUpgrades(Submarine);
|
||||
mpCampaign.UpgradeManager.SanityCheckUpgrades();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -874,7 +874,7 @@ namespace Barotrauma
|
||||
double roundDuration = Timing.TotalTime - RoundStartTime;
|
||||
GameAnalyticsManager.AddProgressionEvent(
|
||||
success ? GameAnalyticsManager.ProgressionStatus.Complete : GameAnalyticsManager.ProgressionStatus.Fail,
|
||||
GameMode?.Name?.Value ?? "none",
|
||||
GameMode?.Preset.Identifier.Value ?? "none",
|
||||
roundDuration);
|
||||
string eventId = "EndRound:" + (GameMode?.Preset?.Identifier.Value ?? "none") + ":";
|
||||
LogEndRoundStats(eventId);
|
||||
|
||||
@@ -60,16 +60,6 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public const bool UpgradeAlsoConnectedSubs = true;
|
||||
|
||||
/// <summary>
|
||||
/// Prevents the player from upgrading the submarine when we are switching to a new one.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// In singleplayer we check if CampaignMode.PendingSubmarineSwitch is not null indicating we are switching submarines
|
||||
/// but in multiplayer that value is not synced so we use this variable instead by setting it to false in <see cref="UpgradeManager.ClientRead"/>
|
||||
/// and then set it back to true when the round ends in <see cref="MultiPlayerCampaign.End"/>
|
||||
/// </remarks>
|
||||
public bool CanUpgrade = true;
|
||||
|
||||
/// <summary>
|
||||
/// This is used by the client in multiplayer, acts like a secondary PendingUpgrades list
|
||||
/// but is not affected by server messages.
|
||||
@@ -422,14 +412,14 @@ namespace Barotrauma
|
||||
#endif
|
||||
}
|
||||
|
||||
public List<Item> GetLinkedItemsToSwap(Item item)
|
||||
public static ICollection<Item> GetLinkedItemsToSwap(Item item)
|
||||
{
|
||||
List<Item> linkedItems = new List<Item>() { item };
|
||||
HashSet<Item> linkedItems = new HashSet<Item>() { item };
|
||||
foreach (MapEntity linkedEntity in item.linkedTo)
|
||||
{
|
||||
foreach (MapEntity secondLinkedEntity in linkedEntity.linkedTo)
|
||||
{
|
||||
if (!(secondLinkedEntity is Item linkedItem) || linkedItem == item) { continue; }
|
||||
if (secondLinkedEntity is not Item linkedItem || linkedItem == item) { continue; }
|
||||
if (linkedItem.AllowSwapping &&
|
||||
linkedItem.Prefab.SwappableItem != null && (linkedItem.Prefab.SwappableItem.CanBeBought || item.Prefab.SwappableItem.ReplacementOnUninstall == ((MapEntity)linkedItem).Prefab.Identifier) &&
|
||||
linkedItem.Prefab.SwappableItem.SwapIdentifier.Equals(item.Prefab.SwappableItem.SwapIdentifier, StringComparison.OrdinalIgnoreCase))
|
||||
@@ -522,8 +512,11 @@ namespace Barotrauma
|
||||
/// Should be called after every round start right after <see cref="ApplyUpgrades"/>
|
||||
/// </summary>
|
||||
/// <param name="submarine"></param>
|
||||
public void SanityCheckUpgrades(Submarine submarine)
|
||||
public void SanityCheckUpgrades()
|
||||
{
|
||||
Submarine submarine = GameMain.GameSession?.Submarine ?? Submarine.MainSub;
|
||||
if (submarine is null) { return; }
|
||||
|
||||
// check walls
|
||||
foreach (Structure wall in submarine.GetWalls(UpgradeAlsoConnectedSubs))
|
||||
{
|
||||
@@ -531,23 +524,8 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (UpgradePrefab prefab in UpgradePrefab.Prefabs)
|
||||
{
|
||||
int level = GetRealUpgradeLevel(prefab, category);
|
||||
if (level == 0 || !prefab.IsWallUpgrade) { continue; }
|
||||
|
||||
Upgrade? upgrade = wall.GetUpgrade(prefab.Identifier);
|
||||
|
||||
bool isOverMax = IsOverMaxLevel(level, prefab);
|
||||
if (isOverMax)
|
||||
{
|
||||
SetUpgradeLevel(prefab, category, prefab.MaxLevel);
|
||||
level = prefab.MaxLevel;
|
||||
}
|
||||
|
||||
if (upgrade == null || upgrade.Level != level || isOverMax)
|
||||
{
|
||||
DebugLog($"{((MapEntity)wall).Prefab.Name} has incorrect \"{prefab.Name}\" level! Expected {level} but got {upgrade?.Level ?? 0}. Fixing...");
|
||||
FixUpgradeOnItem(wall, prefab, level);
|
||||
}
|
||||
if (!prefab.IsWallUpgrade) { continue; }
|
||||
TryFixUpgrade(wall, category, prefab);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -559,35 +537,38 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (UpgradePrefab prefab in UpgradePrefab.Prefabs)
|
||||
{
|
||||
if (!category.CanBeApplied(item, prefab)) { continue; }
|
||||
|
||||
int level = GetRealUpgradeLevel(prefab, category);
|
||||
if (level == 0) { continue; }
|
||||
|
||||
Upgrade? upgrade = item.GetUpgrade(prefab.Identifier);
|
||||
bool isOverMax = IsOverMaxLevel(level, prefab);
|
||||
if (isOverMax)
|
||||
{
|
||||
SetUpgradeLevel(prefab, category, prefab.MaxLevel);
|
||||
level = prefab.MaxLevel;
|
||||
}
|
||||
|
||||
if (upgrade == null || upgrade.Level != level || isOverMax)
|
||||
{
|
||||
DebugLog($"{((MapEntity)item).Prefab.Name} has incorrect \"{prefab.Name}\" level! Expected {level} but got {upgrade?.Level ?? 0}{(isOverMax ? " (Over max level!)" : string.Empty)}. Fixing...");
|
||||
FixUpgradeOnItem(item, prefab, level);
|
||||
}
|
||||
TryFixUpgrade(item, category, prefab);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsOverMaxLevel(int level, UpgradePrefab prefab) => level > prefab.MaxLevel;
|
||||
void TryFixUpgrade(MapEntity entity, UpgradeCategory category, UpgradePrefab prefab)
|
||||
{
|
||||
if (!category.CanBeApplied(entity, prefab)) { return; }
|
||||
|
||||
int level = GetRealUpgradeLevel(prefab, category);
|
||||
int maxLevel = submarine.Info is { } info ? prefab.GetMaxLevel(info) : prefab.MaxLevel;
|
||||
if (maxLevel < level) { level = maxLevel; }
|
||||
|
||||
if (level == 0) { return; }
|
||||
|
||||
Upgrade? upgrade = entity.GetUpgrade(prefab.Identifier);
|
||||
|
||||
if (upgrade == null || upgrade.Level != level)
|
||||
{
|
||||
DebugLog($"{entity.Prefab.Name} has incorrect \"{prefab.Name}\" level! Expected {level} but got {upgrade?.Level ?? 0}. Fixing...");
|
||||
FixUpgradeOnItem((ISerializableEntity)entity, prefab, level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void FixUpgradeOnItem(ISerializableEntity target, UpgradePrefab prefab, int level)
|
||||
{
|
||||
if (target is MapEntity mapEntity)
|
||||
{
|
||||
// do not fix what's not broken
|
||||
if (level == 0) { return; }
|
||||
|
||||
mapEntity.SetUpgrade(new Upgrade(target, prefab, level), false);
|
||||
}
|
||||
}
|
||||
@@ -713,9 +694,9 @@ namespace Barotrauma
|
||||
|
||||
public bool CanUpgradeSub()
|
||||
{
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return CanUpgrade; }
|
||||
|
||||
return Campaign.PendingSubmarineSwitch == null;
|
||||
return
|
||||
Campaign.PendingSubmarineSwitch == null ||
|
||||
Campaign.PendingSubmarineSwitch.Name == Submarine.MainSub.Info.Name;
|
||||
}
|
||||
|
||||
public void Save(XElement? parent)
|
||||
@@ -728,7 +709,7 @@ namespace Barotrauma
|
||||
SavePendingUpgrades(upgradeManagerElement, PendingUpgrades);
|
||||
}
|
||||
|
||||
private void SavePendingUpgrades(XElement? parent, List<PurchasedUpgrade> upgrades)
|
||||
private static void SavePendingUpgrades(XElement? parent, List<PurchasedUpgrade> upgrades)
|
||||
{
|
||||
if (parent == null) { return; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user