Unstable 0.17.4.0

This commit is contained in:
Markus Isberg
2022-03-30 00:08:09 +09:00
parent 2968e23ae8
commit c1b8e5a341
177 changed files with 3388 additions and 1977 deletions
@@ -45,28 +45,37 @@ namespace Barotrauma
return SoldEntities.Where(se => se.Status != SoldEntity.SellStatus.Unconfirmed);
}
public void SetItemsInBuyCrate(List<PurchasedItem> items)
public void SetItemsInBuyCrate(Dictionary<Identifier, List<PurchasedItem>> items)
{
ItemsInBuyCrate.Clear();
ItemsInBuyCrate.AddRange(items);
foreach (var entry in items)
{
ItemsInBuyCrate.Add(entry.Key, entry.Value);
}
OnItemsInBuyCrateChanged?.Invoke();
}
public void SetItemsInSubSellCrate(List<PurchasedItem> items)
public void SetItemsInSubSellCrate(Dictionary<Identifier, List<PurchasedItem>> items)
{
ItemsInSellFromSubCrate.Clear();
ItemsInSellFromSubCrate.AddRange(items);
foreach (var entry in items)
{
ItemsInSellFromSubCrate.Add(entry.Key, entry.Value);
}
OnItemsInSellFromSubCrateChanged?.Invoke();
}
public void SetSoldItems(List<SoldItem> items)
public void SetSoldItems(Dictionary<Identifier, List<SoldItem>> items)
{
SoldItems.Clear();
SoldItems.AddRange(items);
foreach (var entry in items)
{
SoldItems.Add(entry.Key, entry.Value);
}
foreach (var se in SoldEntities)
{
if (se.Status == SoldEntity.SellStatus.Confirmed) { continue; }
if (SoldItems.Any(si => Match(si, se, true)))
if (SoldItems.Any(si => si.Value.Any(si => Match(si, se, true))))
{
se.Status = SoldEntity.SellStatus.Confirmed;
}
@@ -75,13 +84,16 @@ namespace Barotrauma
se.Status = SoldEntity.SellStatus.Unconfirmed;
}
}
foreach (var si in SoldItems)
foreach (var soldItems in SoldItems.Values)
{
if (si.Origin != SoldItem.SellOrigin.Submarine) { continue; }
if (!(SoldEntities.FirstOrDefault(se => se.Item == null && Match(si, se, false)) is SoldEntity soldEntityMatch)) { continue; }
if (!(Entity.FindEntityByID(si.ID) is Item item)) { continue; }
soldEntityMatch.SetItem(item);
soldEntityMatch.Status = SoldEntity.SellStatus.Confirmed;
foreach (var si in soldItems)
{
if (si.Origin != SoldItem.SellOrigin.Submarine) { continue; }
if (!(SoldEntities.FirstOrDefault(se => se.Item == null && Match(si, se, false)) is SoldEntity soldEntityMatch)) { continue; }
if (!(Entity.FindEntityByID(si.ID) is Item item)) { continue; }
soldEntityMatch.SetItem(item);
soldEntityMatch.Status = SoldEntity.SellStatus.Confirmed;
}
}
OnSoldItemsChanged?.Invoke();
@@ -94,45 +106,24 @@ namespace Barotrauma
}
}
public void ModifyItemQuantityInSellCrate(ItemPrefab itemPrefab, int changeInQuantity)
public void ModifyItemQuantityInSellCrate(Identifier storeIdentifier, ItemPrefab itemPrefab, int changeInQuantity)
{
var itemToSell = ItemsInSellCrate.Find(i => i.ItemPrefab == itemPrefab);
if (itemToSell != null)
if (GetSellCrateItem(storeIdentifier, itemPrefab) is { } item)
{
itemToSell.Quantity += changeInQuantity;
if (itemToSell.Quantity < 1)
item.Quantity += changeInQuantity;
if (item.Quantity < 1)
{
ItemsInSellCrate.Remove(itemToSell);
GetSellCrateItems(storeIdentifier)?.Remove(item);
}
}
else if (changeInQuantity > 0)
{
itemToSell = new PurchasedItem(itemPrefab, changeInQuantity);
ItemsInSellCrate.Add(itemToSell);
GetSellCrateItems(storeIdentifier, create: true).Add(new PurchasedItem(itemPrefab, changeInQuantity));
}
OnItemsInSellCrateChanged?.Invoke();
}
public void ModifyItemQuantityInSellFromSubCrate(ItemPrefab itemPrefab, int changeInQuantity)
{
var itemToSell = ItemsInSellFromSubCrate.Find(i => i.ItemPrefab == itemPrefab);
if (itemToSell != null)
{
itemToSell.Quantity += changeInQuantity;
if (itemToSell.Quantity < 1)
{
ItemsInSellFromSubCrate.Remove(itemToSell);
}
}
else if (changeInQuantity > 0)
{
itemToSell = new PurchasedItem(itemPrefab, changeInQuantity);
ItemsInSellFromSubCrate.Add(itemToSell);
}
OnItemsInSellFromSubCrateChanged?.Invoke();
}
public void SellItems(List<PurchasedItem> itemsToSell, Store.StoreTab sellingMode)
public void SellItems(Identifier storeIdentifier, List<PurchasedItem> itemsToSell, Store.StoreTab sellingMode)
{
IEnumerable<Item> sellableItems;
try
@@ -146,19 +137,24 @@ namespace Barotrauma
}
catch (NotImplementedException e)
{
DebugConsole.ShowError($"Error selling items: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
DebugConsole.ShowError($"Error selling items: uknown store tab type \"{sellingMode}\".\n{e.StackTrace.CleanupStackTrace()}");
return;
}
bool canAddToRemoveQueue = campaign.IsSinglePlayer && Entity.Spawner != null;
byte sellerId = GameMain.Client?.ID ?? 0;
// Check all the prices before starting the transaction
// to make sure the modifiers stay the same for the whole transaction
Dictionary<ItemPrefab, int> sellValues = GetSellValuesAtCurrentLocation(itemsToSell.Select(i => i.ItemPrefab));
foreach (PurchasedItem item in itemsToSell)
// Check all the prices before starting the transaction to make sure the modifiers stay the same for the whole transaction
var sellValues = GetSellValuesAtCurrentLocation(storeIdentifier, itemsToSell.Select(i => i.ItemPrefab));
if (!(Location.GetStore(storeIdentifier) is { } store))
{
DebugConsole.ShowError($"Error selling items at {Location}: no store with identifier \"{storeIdentifier}\" exists.\n{Environment.StackTrace.CleanupStackTrace()}");
return;
}
var storeSpecificSoldItems = GetSoldItems(storeIdentifier, create: true);
foreach (var item in itemsToSell)
{
int itemValue = item.Quantity * sellValues[item.ItemPrefab];
// check if the store can afford the item
if (Location.StoreCurrentBalance < itemValue) { continue; }
if (store.Balance < itemValue) { continue; }
// TODO: Write logic for prioritizing certain items over others (e.g. lone Battery Cell should be preferred over one inside a Stun Baton)
var matchingItems = sellableItems.Where(i => i.Prefab == item.ItemPrefab);
int count = Math.Min(item.Quantity, matchingItems.Count());
@@ -168,7 +164,7 @@ namespace Barotrauma
for (int i = 0; i < count; i++)
{
var matchingItem = matchingItems.ElementAt(i);
SoldItems.Add(new SoldItem(matchingItem.Prefab, matchingItem.ID, canAddToRemoveQueue, sellerId, origin));
storeSpecificSoldItems.Add(new SoldItem(matchingItem.Prefab, matchingItem.ID, canAddToRemoveQueue, sellerId, origin));
SoldEntities.Add(new SoldEntity(matchingItem, campaign.IsSinglePlayer ? SoldEntity.SellStatus.Confirmed : SoldEntity.SellStatus.Local));
if (canAddToRemoveQueue) { Entity.Spawner.AddItemToRemoveQueue(matchingItem); }
}
@@ -178,22 +174,23 @@ namespace Barotrauma
// When selling from the sub in multiplayer, the server will determine the items that are sold
for (int i = 0; i < count; i++)
{
SoldItems.Add(new SoldItem(item.ItemPrefab, Entity.NullEntityID, canAddToRemoveQueue, sellerId, origin));
storeSpecificSoldItems.Add(new SoldItem(item.ItemPrefab, Entity.NullEntityID, canAddToRemoveQueue, sellerId, origin));
SoldEntities.Add(new SoldEntity(item.ItemPrefab, SoldEntity.SellStatus.Local));
}
}
// Exchange money
Location.StoreCurrentBalance -= itemValue;
store.Balance -= itemValue;
campaign.Bank.Give(itemValue);
GameAnalyticsManager.AddMoneyGainedEvent(itemValue, GameAnalyticsManager.MoneySource.Store, item.ItemPrefab.Identifier.Value);
// Remove from the sell crate
if ((sellingMode == Store.StoreTab.Sell ? ItemsInSellCrate : ItemsInSellFromSubCrate)?.Find(pi => pi.ItemPrefab == item.ItemPrefab) is { } itemToSell)
var sellCrate = (sellingMode == Store.StoreTab.Sell ? GetSellCrateItems(storeIdentifier) : GetSubCrateItems(storeIdentifier));
if (sellCrate?.Find(pi => pi.ItemPrefab == item.ItemPrefab) is { } itemToSell)
{
itemToSell.Quantity -= item.Quantity;
if (itemToSell.Quantity < 1)
{
(sellingMode == Store.StoreTab.Sell ? ItemsInSellCrate : ItemsInSellFromSubCrate)?.Remove(itemToSell);
sellCrate.Remove(itemToSell);
}
}
}
@@ -63,6 +63,10 @@ namespace Barotrauma
}
}
/// <summary>
/// Gets the current personal wallet
/// In singleplayer this is the campaign bank and in multiplayer this is the personal wallet
/// </summary>
public virtual Wallet Wallet => GetWallet();
public override void ShowStartMessage()
@@ -301,7 +305,7 @@ namespace Barotrauma
goto default;
default:
ShowCampaignUI = true;
CampaignUI.SelectTab(npc.CampaignInteractionType);
CampaignUI.SelectTab(npc.CampaignInteractionType, storeIdentifier: npc.MerchantIdentifier);
CampaignUI.UpgradeStore?.RefreshAll();
break;
}
@@ -553,36 +553,10 @@ namespace Barotrauma
msg.Write(PurchasedItemRepairs);
msg.Write(PurchasedLostShuttles);
msg.Write((UInt16)CargoManager.ItemsInBuyCrate.Count);
foreach (PurchasedItem pi in CargoManager.ItemsInBuyCrate)
{
msg.Write(pi.ItemPrefab.Identifier);
msg.WriteRangedInteger(pi.Quantity, 0, CargoManager.MaxQuantity);
}
msg.Write((UInt16)CargoManager.ItemsInSellFromSubCrate.Count);
foreach (PurchasedItem pi in CargoManager.ItemsInSellFromSubCrate)
{
msg.Write(pi.ItemPrefab.Identifier);
msg.WriteRangedInteger(pi.Quantity, 0, CargoManager.MaxQuantity);
}
msg.Write((UInt16)CargoManager.PurchasedItems.Count);
foreach (PurchasedItem pi in CargoManager.PurchasedItems)
{
msg.Write(pi.ItemPrefab.Identifier);
msg.WriteRangedInteger(pi.Quantity, 0, CargoManager.MaxQuantity);
}
msg.Write((UInt16)CargoManager.SoldItems.Count);
foreach (SoldItem si in CargoManager.SoldItems)
{
msg.Write(si.ItemPrefab.Identifier);
msg.Write((UInt16)si.ID);
msg.Write(si.Removed);
msg.Write(si.SellerID);
msg.Write((byte)si.Origin);
}
WriteItems(msg, CargoManager.ItemsInBuyCrate);
WriteItems(msg, CargoManager.ItemsInSellFromSubCrate);
WriteItems(msg, CargoManager.PurchasedItems);
WriteItems(msg, CargoManager.SoldItems);
msg.Write((ushort)UpgradeManager.PurchasedUpgrades.Count);
foreach (var (prefab, category, level) in UpgradeManager.PurchasedUpgrades)
@@ -644,50 +618,22 @@ namespace Barotrauma
availableMissions.Add((missionIdentifier, connectionIndex));
}
UInt16? storeBalance = null;
var storeBalances = new Dictionary<Identifier, UInt16>();
if (msg.ReadBoolean())
{
storeBalance = msg.ReadUInt16();
byte storeCount = msg.ReadByte();
for (int i = 0; i < storeCount; i++)
{
Identifier identifier = msg.ReadIdentifier();
UInt16 storeBalance = msg.ReadUInt16();
storeBalances.Add(identifier, storeBalance);
}
}
UInt16 buyCrateItemCount = msg.ReadUInt16();
List<PurchasedItem> buyCrateItems = new List<PurchasedItem>();
for (int i = 0; i < buyCrateItemCount; i++)
{
Identifier itemPrefabIdentifier = msg.ReadIdentifier();
int itemQuantity = msg.ReadRangedInteger(0, CargoManager.MaxQuantity);
buyCrateItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity));
}
UInt16 subSellCrateItemCount = msg.ReadUInt16();
List<PurchasedItem> subSellCrateItems = new List<PurchasedItem>();
for (int i = 0; i < subSellCrateItemCount; i++)
{
string itemPrefabIdentifier = msg.ReadString();
int itemQuantity = msg.ReadRangedInteger(0, CargoManager.MaxQuantity);
subSellCrateItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity));
}
UInt16 purchasedItemCount = msg.ReadUInt16();
List<PurchasedItem> purchasedItems = new List<PurchasedItem>();
for (int i = 0; i < purchasedItemCount; i++)
{
Identifier itemPrefabIdentifier = msg.ReadIdentifier();
int itemQuantity = msg.ReadRangedInteger(0, CargoManager.MaxQuantity);
purchasedItems.Add(new PurchasedItem(ItemPrefab.Prefabs[itemPrefabIdentifier], itemQuantity));
}
UInt16 soldItemCount = msg.ReadUInt16();
List<SoldItem> soldItems = new List<SoldItem>();
for (int i = 0; i < soldItemCount; i++)
{
Identifier itemPrefabIdentifier = msg.ReadIdentifier();
UInt16 id = msg.ReadUInt16();
bool removed = msg.ReadBoolean();
byte sellerId = msg.ReadByte();
byte origin = msg.ReadByte();
soldItems.Add(new SoldItem(ItemPrefab.Prefabs[itemPrefabIdentifier], id, removed, sellerId, (SoldItem.SellOrigin)origin));
}
var buyCrateItems = ReadPurchasedItems(msg, sender: null);
var subSellCrateItems = ReadPurchasedItems(msg, sender: null);
var purchasedItems = ReadPurchasedItems(msg, sender: null);
var soldItems = ReadSoldItems(msg);
ushort pendingUpgradeCount = msg.ReadUInt16();
List<PurchasedUpgrade> pendingUpgrades = new List<PurchasedUpgrade>();
@@ -756,7 +702,13 @@ namespace Barotrauma
campaign.CargoManager.SetItemsInSubSellCrate(subSellCrateItems);
campaign.CargoManager.SetPurchasedItems(purchasedItems);
campaign.CargoManager.SetSoldItems(soldItems);
if (storeBalance.HasValue) { campaign.Map.CurrentLocation.StoreCurrentBalance = storeBalance.Value; }
foreach (var balance in storeBalances)
{
if (campaign.Map.CurrentLocation.GetStore(balance.Key) is { } store)
{
store.Balance = balance.Value;
}
}
campaign.UpgradeManager.SetPendingUpgrades(pendingUpgrades);
campaign.UpgradeManager.PurchasedUpgrades.Clear();
foreach (var purchasedItemSwap in purchasedItemSwaps)
@@ -914,7 +866,7 @@ namespace Barotrauma
WalletInfo info = transaction.Info;
switch (transaction.CharacterID)
{
case Some<ushort> { Value: var charID}:
case Some<ushort> { Value: var charID }:
{
Character targetCharacter = Character.CharacterList?.FirstOrDefault(c => c.ID == charID);
if (targetCharacter is null) { break; }
@@ -121,7 +121,7 @@ namespace Barotrauma.Tutorials
return new CharacterInfo(
CharacterPrefab.HumanSpeciesName,
jobOrJobPrefab: new Job(
JobPrefab.Prefabs["medicaldoctor"], Rand.RandSync.Unsynced, 0,
JobPrefab.Prefabs["engineer"], Rand.RandSync.Unsynced, 0,
new Skill("medical".ToIdentifier(), 0),
new Skill("weapons".ToIdentifier(), 0),
new Skill("mechanical".ToIdentifier(), 20),
@@ -147,7 +147,7 @@ namespace Barotrauma.Tutorials
return new CharacterInfo(
CharacterPrefab.HumanSpeciesName,
jobOrJobPrefab: new Job(
JobPrefab.Prefabs["medicaldoctor"], Rand.RandSync.Unsynced, 0,
JobPrefab.Prefabs["mechanic"], Rand.RandSync.Unsynced, 0,
new Skill("medical".ToIdentifier(), 0),
new Skill("weapons".ToIdentifier(), 0),
new Skill("mechanical".ToIdentifier(), 50),
@@ -128,7 +128,7 @@ namespace Barotrauma.Tutorials
return new CharacterInfo(
CharacterPrefab.HumanSpeciesName,
jobOrJobPrefab: new Job(
JobPrefab.Prefabs["medicaldoctor"], Rand.RandSync.Unsynced, 0,
JobPrefab.Prefabs["securityofficer"], Rand.RandSync.Unsynced, 0,
new Skill("medical".ToIdentifier(), 20),
new Skill("weapons".ToIdentifier(), 70),
new Skill("mechanical".ToIdentifier(), 20),
@@ -318,7 +318,7 @@ namespace Barotrauma
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), RichString.Rich(displayedMission.GetMissionRewardText(Submarine.MainSub)));
if (GameMain.IsMultiplayer && Character.Controlled is { } controlled)
{
var (share, percentage) = Mission.GetRewardShare(controlled.Wallet.RewardDistribution, Mission.GetSalaryEligibleCrew(), Option<int>.Some(reward));
var (share, percentage, _) = Mission.GetRewardShare(controlled.Wallet.RewardDistribution, Mission.GetSalaryEligibleCrew().Where(c => c != controlled), Option<int>.Some(reward));
if (share > 0)
{
string shareFormatted = string.Format(CultureInfo.InvariantCulture, "{0:N0}", share);