Unstable 0.16.2.0
This commit is contained in:
@@ -73,7 +73,6 @@ namespace Barotrauma
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
// TODO: move this into the character editor
|
||||
//var mouthPos = ragdoll.GetMouthPosition();
|
||||
//if (mouthPos != null)
|
||||
//{
|
||||
@@ -173,6 +172,7 @@ namespace Barotrauma
|
||||
|
||||
public float DefaultSpriteDepth { get; private set; }
|
||||
|
||||
public WearableSprite HairWithHatSprite { get; set; }
|
||||
public WearableSprite HuskSprite { get; private set; }
|
||||
public WearableSprite HerpesSprite { get; private set; }
|
||||
|
||||
@@ -236,8 +236,8 @@ namespace Barotrauma
|
||||
|
||||
public string HitSoundTag => Params?.Sound?.Tag;
|
||||
|
||||
private List<WearableSprite> wearableTypeHidingSprites = new List<WearableSprite>();
|
||||
private List<WearableType> wearableTypesToHide = new List<WearableType>();
|
||||
private readonly List<WearableSprite> wearableTypeHidingSprites = new List<WearableSprite>();
|
||||
private readonly HashSet<WearableType> wearableTypesToHide = new HashSet<WearableType>();
|
||||
private bool enableHuskSprite;
|
||||
public bool EnableHuskSprite
|
||||
{
|
||||
@@ -895,7 +895,15 @@ namespace Barotrauma
|
||||
foreach (WearableSprite wearable in OtherWearables)
|
||||
{
|
||||
if (wearable.Type == WearableType.Husk) { continue; }
|
||||
if (wearableTypesToHide.Contains(wearable.Type)) { continue; }
|
||||
if (wearableTypesToHide.Contains(wearable.Type))
|
||||
{
|
||||
if (wearable.Type == WearableType.Hair && HairWithHatSprite != null)
|
||||
{
|
||||
DrawWearable(HairWithHatSprite, depthStep, spriteBatch, blankColor, alpha: color.A / 255f, spriteEffect);
|
||||
depthStep += step;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
DrawWearable(wearable, depthStep, spriteBatch, blankColor, alpha: color.A / 255f, spriteEffect);
|
||||
//if there are multiple sprites on this limb, make the successive ones be drawn in front
|
||||
depthStep += step;
|
||||
@@ -1195,6 +1203,9 @@ namespace Barotrauma
|
||||
HuskSprite?.Sprite.Remove();
|
||||
HuskSprite = null;
|
||||
|
||||
HairWithHatSprite?.Sprite.Remove();
|
||||
HairWithHatSprite = null;
|
||||
|
||||
HerpesSprite?.Sprite.Remove();
|
||||
HerpesSprite = null;
|
||||
|
||||
|
||||
@@ -32,7 +32,8 @@ namespace Barotrauma
|
||||
|
||||
public void ClientExecute(string[] args)
|
||||
{
|
||||
if (!CheatsEnabled && IsCheat)
|
||||
bool allowCheats = GameMain.NetworkMember == null && (GameMain.GameSession?.GameMode is TestGameMode || Screen.Selected is EditorScreen);
|
||||
if (!allowCheats && !CheatsEnabled && IsCheat)
|
||||
{
|
||||
NewMessage("You need to enable cheats using the command \"enablecheats\" before you can use the command \"" + names[0] + "\".", Color.Red);
|
||||
#if USE_STEAM
|
||||
@@ -743,7 +744,7 @@ namespace Barotrauma
|
||||
AssignOnExecute("explosion", (string[] args) =>
|
||||
{
|
||||
Vector2 explosionPos = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
float range = 500, force = 10, damage = 50, structureDamage = 10, itemDamage = 100, empStrength = 0.0f, ballastFloraStrength = 50f;
|
||||
float range = 500, force = 10, damage = 50, structureDamage = 20, itemDamage = 100, empStrength = 0.0f, ballastFloraStrength = 50f;
|
||||
if (args.Length > 0) float.TryParse(args[0], out range);
|
||||
if (args.Length > 1) float.TryParse(args[1], out force);
|
||||
if (args.Length > 2) float.TryParse(args[2], out damage);
|
||||
@@ -1894,7 +1895,12 @@ namespace Barotrauma
|
||||
ThrowError($"\"{args[0]}\" is not a valid Level.PositionType. Available options are: {string.Join(", ", enums)}");
|
||||
return;
|
||||
}
|
||||
debugLines = EventSet.GetDebugStatistics(filter: monsterEvent => monsterEvent.SpawnPosType.HasFlag(spawnType));
|
||||
bool fullLog = false;
|
||||
if (args.Length > 1)
|
||||
{
|
||||
bool.TryParse(args[1], out fullLog);
|
||||
}
|
||||
debugLines = EventSet.GetDebugStatistics(filter: monsterEvent => monsterEvent.SpawnPosType.HasFlag(spawnType), fullLog: fullLog);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2409,7 +2415,7 @@ namespace Barotrauma
|
||||
TextManager.CheckForDuplicates(args[0]);
|
||||
}));
|
||||
|
||||
commands.Add(new Command("writetocsv", "Writes the default language (English) to a .csv file.", (string[] args) =>
|
||||
commands.Add(new Command("writetocsv|xmltocsv", "Writes the default language (English) to a .csv file.", (string[] args) =>
|
||||
{
|
||||
TextManager.WriteToCSV();
|
||||
NPCConversation.WriteToCSV();
|
||||
|
||||
@@ -1091,6 +1091,29 @@ namespace Barotrauma
|
||||
var maxVersion = new Version(attribute.Value);
|
||||
if (GameMain.Version > maxVersion) { return false; }
|
||||
break;
|
||||
case "buildconfiguration":
|
||||
switch (attribute.Value.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "debug":
|
||||
#if DEBUG
|
||||
return true;
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
case "unstable":
|
||||
#if UNSTABLE
|
||||
return true;
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
case "release":
|
||||
#if !DEBUG && !UNSTABLE
|
||||
return true;
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -439,7 +439,7 @@ namespace Barotrauma
|
||||
for (int i = 0; i < Content.CountChildren; i++)
|
||||
{
|
||||
GUIComponent child = Content.GetChild(i);
|
||||
if (!child.Visible) { continue; }
|
||||
if (child == null || !child.Visible) { continue; }
|
||||
if (RectTransform != null)
|
||||
{
|
||||
callback(i, new Point(x, y));
|
||||
|
||||
@@ -43,36 +43,42 @@ namespace Barotrauma
|
||||
private bool needsRefresh, needsBuyingRefresh, needsSellingRefresh, needsItemsToSellRefresh, needsSellingFromSubRefresh, needsItemsToSellFromSubRefresh;
|
||||
|
||||
private Point resolutionWhenCreated;
|
||||
private bool hadPermissions;
|
||||
|
||||
private Dictionary<ItemPrefab, int> OwnedItems { get; } = new Dictionary<ItemPrefab, int>();
|
||||
|
||||
private CargoManager CargoManager => campaignUI.Campaign.CargoManager;
|
||||
private Location CurrentLocation => campaignUI.Campaign.Map?.CurrentLocation;
|
||||
private int PlayerMoney => campaignUI.Campaign.Money;
|
||||
private bool HasPermissions => campaignUI.Campaign.AllowedToManageCampaign();
|
||||
|
||||
private bool IsBuying => activeTab switch
|
||||
{
|
||||
StoreTab.Buy => true,
|
||||
StoreTab.Sell => false,
|
||||
StoreTab.SellFromSub => false,
|
||||
StoreTab.SellSub => false,
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
private GUIListBox ActiveShoppingCrateList => activeTab switch
|
||||
{
|
||||
StoreTab.Buy => shoppingCrateBuyList,
|
||||
StoreTab.Sell => shoppingCrateSellList,
|
||||
StoreTab.SellFromSub => shoppingCrateSellFromSubList,
|
||||
StoreTab.SellSub => shoppingCrateSellFromSubList,
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
|
||||
private bool IsTabUnavailable(StoreTab tab) => !tabLists.ContainsKey(tab);
|
||||
|
||||
public enum StoreTab
|
||||
{
|
||||
/// <summary>
|
||||
/// Buy items from the store
|
||||
/// </summary>
|
||||
Buy,
|
||||
/// <summary>
|
||||
/// Sell items from the character inventory
|
||||
/// </summary>
|
||||
Sell,
|
||||
SellFromSub
|
||||
/// <summary>
|
||||
/// Sell items from the sub
|
||||
/// </summary>
|
||||
SellSub
|
||||
}
|
||||
|
||||
private enum SortingMethod
|
||||
@@ -84,11 +90,117 @@ namespace Barotrauma
|
||||
CategoryAsc
|
||||
}
|
||||
|
||||
#region Permissions
|
||||
|
||||
private bool hadPermissions, hadBuyPermissions, hadSellInventoryPermissions, hadSellSubPermissions;
|
||||
|
||||
private bool HasPermissions
|
||||
{
|
||||
get => GetPermissions();
|
||||
set => hadPermissions = value;
|
||||
}
|
||||
private bool HasBuyPermissions
|
||||
{
|
||||
get => HasPermissions || GetPermissions(StoreTab.Buy);
|
||||
set => hadBuyPermissions = value;
|
||||
}
|
||||
private bool HasSellInventoryPermissions
|
||||
{
|
||||
get => HasPermissions || GetPermissions(StoreTab.Sell);
|
||||
set => hadSellInventoryPermissions = value;
|
||||
}
|
||||
private bool HasSellSubPermissions
|
||||
{
|
||||
get => HasPermissions || GetPermissions(StoreTab.SellSub);
|
||||
set => hadSellSubPermissions = value;
|
||||
}
|
||||
|
||||
private bool GetPermissions(StoreTab? tab = null)
|
||||
{
|
||||
if (!tab.HasValue)
|
||||
{
|
||||
return campaignUI.Campaign.AllowedToManageCampaign() || campaignUI.Campaign.AllowedToManageCampaign(Networking.ClientPermissions.CampaignStore);
|
||||
}
|
||||
else
|
||||
{
|
||||
return tab.Value switch
|
||||
{
|
||||
StoreTab.Buy => campaignUI.Campaign.AllowedToManageCampaign(Networking.ClientPermissions.BuyItems),
|
||||
StoreTab.Sell => campaignUI.Campaign.AllowedToManageCampaign(Networking.ClientPermissions.SellInventoryItems),
|
||||
StoreTab.SellSub => campaignUI.Campaign.AllowedToManageCampaign(Networking.ClientPermissions.SellSubItems),
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePermissions(StoreTab? tab = null)
|
||||
{
|
||||
HasPermissions = GetPermissions();
|
||||
if (!tab.HasValue)
|
||||
{
|
||||
HasBuyPermissions = GetPermissions(StoreTab.Buy);
|
||||
HasSellInventoryPermissions = GetPermissions(StoreTab.Sell);
|
||||
HasSellSubPermissions = GetPermissions(StoreTab.SellSub);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (tab.Value)
|
||||
{
|
||||
case StoreTab.Buy:
|
||||
HasBuyPermissions = GetPermissions(tab.Value);
|
||||
break;
|
||||
case StoreTab.Sell:
|
||||
HasSellInventoryPermissions = GetPermissions(tab.Value);
|
||||
break;
|
||||
case StoreTab.SellSub:
|
||||
HasSellSubPermissions = GetPermissions(tab.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasTabPermissions(StoreTab tab)
|
||||
{
|
||||
return tab switch
|
||||
{
|
||||
StoreTab.Buy => HasBuyPermissions,
|
||||
StoreTab.Sell => HasSellInventoryPermissions,
|
||||
StoreTab.SellSub => HasSellSubPermissions,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
private bool HasActiveTabPermissions()
|
||||
{
|
||||
return HasTabPermissions(activeTab);
|
||||
}
|
||||
|
||||
private bool HavePermissionsChanged(StoreTab? tab = null)
|
||||
{
|
||||
if (!tab.HasValue)
|
||||
{
|
||||
return hadPermissions != HasPermissions;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool hadTabPermissions = tab.Value switch
|
||||
{
|
||||
StoreTab.Buy => hadBuyPermissions,
|
||||
StoreTab.Sell => hadSellInventoryPermissions,
|
||||
StoreTab.SellSub => hadSellSubPermissions,
|
||||
_ => false
|
||||
};
|
||||
return hadTabPermissions != HasTabPermissions(tab.Value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public Store(CampaignUI campaignUI, GUIComponent parentComponent)
|
||||
{
|
||||
this.campaignUI = campaignUI;
|
||||
this.parentComponent = parentComponent;
|
||||
hadPermissions = HasPermissions;
|
||||
UpdatePermissions();
|
||||
CreateUI();
|
||||
campaignUI.Campaign.Map.OnLocationChanged += UpdateLocation;
|
||||
if (CurrentLocation?.Reputation != null)
|
||||
@@ -109,7 +221,7 @@ namespace Barotrauma
|
||||
|
||||
public void Refresh(bool updateOwned = true)
|
||||
{
|
||||
hadPermissions = HasPermissions;
|
||||
UpdatePermissions();
|
||||
if (updateOwned) { UpdateOwnedItems(); }
|
||||
RefreshBuying(updateOwned: false);
|
||||
RefreshSelling(updateOwned: false);
|
||||
@@ -122,7 +234,7 @@ namespace Barotrauma
|
||||
if (updateOwned) { UpdateOwnedItems(); }
|
||||
RefreshShoppingCrateBuyList();
|
||||
RefreshStoreBuyList();
|
||||
var hasPermissions = HasPermissions;
|
||||
bool hasPermissions = HasTabPermissions(StoreTab.Buy);
|
||||
storeBuyList.Enabled = hasPermissions;
|
||||
shoppingCrateBuyList.Enabled = hasPermissions;
|
||||
needsBuyingRefresh = false;
|
||||
@@ -133,7 +245,7 @@ namespace Barotrauma
|
||||
if (updateOwned) { UpdateOwnedItems(); }
|
||||
RefreshShoppingCrateSellList();
|
||||
RefreshStoreSellList();
|
||||
var hasPermissions = HasPermissions;
|
||||
bool hasPermissions = HasTabPermissions(StoreTab.Sell);
|
||||
storeSellList.Enabled = hasPermissions;
|
||||
shoppingCrateSellList.Enabled = hasPermissions;
|
||||
needsSellingRefresh = false;
|
||||
@@ -141,13 +253,11 @@ namespace Barotrauma
|
||||
|
||||
private void RefreshSellingFromSub(bool updateOwned = true, bool updateItemsToSellFromSub = true)
|
||||
{
|
||||
if (IsTabUnavailable(StoreTab.SellFromSub)) { return; }
|
||||
if (updateOwned) { UpdateOwnedItems(); }
|
||||
if (updateItemsToSellFromSub) RefreshItemsToSellFromSub();
|
||||
RefreshShoppingCrateSellFromSubList();
|
||||
RefreshStoreSellFromSubList();
|
||||
// TODO: Separate permissions from regular campaign permissions
|
||||
var hasPermissions = HasPermissions;
|
||||
bool hasPermissions = HasTabPermissions(StoreTab.SellSub);
|
||||
storeSellFromSubList.Enabled = hasPermissions;
|
||||
shoppingCrateSellFromSubList.Enabled = hasPermissions;
|
||||
needsSellingFromSubRefresh = false;
|
||||
@@ -261,7 +371,7 @@ namespace Barotrauma
|
||||
{
|
||||
StoreTab.Buy => CurrentLocation.StoreCurrentBalance + buyTotal,
|
||||
StoreTab.Sell => CurrentLocation.StoreCurrentBalance - sellTotal,
|
||||
StoreTab.SellFromSub => CurrentLocation.StoreCurrentBalance - sellFromSubTotal,
|
||||
StoreTab.SellSub => CurrentLocation.StoreCurrentBalance - sellFromSubTotal,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
if (balanceAfterTransaction != CurrentLocation.StoreCurrentBalance)
|
||||
@@ -325,10 +435,9 @@ namespace Barotrauma
|
||||
tabSortingMethods.Clear();
|
||||
foreach (StoreTab tab in tabs)
|
||||
{
|
||||
if (tab == StoreTab.SellFromSub && GameMain.IsMultiplayer) { continue; }
|
||||
string text = tab switch
|
||||
{
|
||||
StoreTab.SellFromSub => TextManager.Get("submarine"),
|
||||
StoreTab.SellSub => TextManager.Get("submarine"),
|
||||
_ => TextManager.Get("campaignstoretab." + tab)
|
||||
};
|
||||
var tabButton = new GUIButton(new RectTransform(new Vector2(1.0f / (tabs.Length + 1), 1.0f), modeButtonContainer.RectTransform),
|
||||
@@ -456,16 +565,13 @@ namespace Barotrauma
|
||||
storeRequestedGoodGroup = CreateDealsGroup(storeSellList);
|
||||
tabLists.Add(StoreTab.Sell, storeSellList);
|
||||
|
||||
if (GameMain.IsSingleplayer)
|
||||
storeSellFromSubList = new GUIListBox(new RectTransform(Vector2.One, storeItemListContainer.RectTransform))
|
||||
{
|
||||
storeSellFromSubList = new GUIListBox(new RectTransform(Vector2.One, storeItemListContainer.RectTransform))
|
||||
{
|
||||
AutoHideScrollBar = false,
|
||||
Visible = false
|
||||
};
|
||||
storeRequestedSubGoodGroup = CreateDealsGroup(storeSellFromSubList);
|
||||
tabLists.Add(StoreTab.SellFromSub, storeSellFromSubList);
|
||||
}
|
||||
AutoHideScrollBar = false,
|
||||
Visible = false
|
||||
};
|
||||
storeRequestedSubGoodGroup = CreateDealsGroup(storeSellFromSubList);
|
||||
tabLists.Add(StoreTab.SellSub, storeSellFromSubList);
|
||||
|
||||
// Shopping Crate ------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -526,10 +632,7 @@ namespace Barotrauma
|
||||
var shoppingCrateListContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.8f), shoppingCrateInventoryContainer.RectTransform), style: null);
|
||||
shoppingCrateBuyList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
||||
shoppingCrateSellList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
||||
if (GameMain.IsSingleplayer)
|
||||
{
|
||||
shoppingCrateSellFromSubList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
||||
}
|
||||
shoppingCrateSellFromSubList = new GUIListBox(new RectTransform(Vector2.One, shoppingCrateListContainer.RectTransform)) { Visible = false };
|
||||
|
||||
var relevantBalanceContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), shoppingCrateInventoryContainer.RectTransform), isHorizontal: true)
|
||||
{
|
||||
@@ -569,16 +672,16 @@ namespace Barotrauma
|
||||
clearAllButton = new GUIButton(new RectTransform(new Vector2(0.35f, 1.0f), buttonContainer.RectTransform), TextManager.Get("campaignstore.clearall"))
|
||||
{
|
||||
ClickSound = GUISoundType.DecreaseQuantity,
|
||||
Enabled = HasPermissions,
|
||||
Enabled = HasActiveTabPermissions(),
|
||||
ForceUpperCase = true,
|
||||
OnClicked = (button, userData) =>
|
||||
{
|
||||
if (!HasPermissions) { return false; }
|
||||
if (!HasActiveTabPermissions()) { return false; }
|
||||
var itemsToRemove = activeTab switch
|
||||
{
|
||||
StoreTab.Buy => new List<PurchasedItem>(CargoManager.ItemsInBuyCrate),
|
||||
StoreTab.Sell => new List<PurchasedItem>(CargoManager.ItemsInSellCrate),
|
||||
StoreTab.SellFromSub => new List<PurchasedItem>(CargoManager.ItemsInSellFromSubCrate),
|
||||
StoreTab.SellSub => new List<PurchasedItem>(CargoManager.ItemsInSellFromSubCrate),
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
itemsToRemove.ForEach(i => ClearFromShoppingCrate(i));
|
||||
@@ -637,7 +740,6 @@ namespace Barotrauma
|
||||
|
||||
private void ChangeStoreTab(StoreTab tab)
|
||||
{
|
||||
if (IsTabUnavailable(tab)) { return; }
|
||||
activeTab = tab;
|
||||
foreach (GUIButton tabButton in storeTabButtons)
|
||||
{
|
||||
@@ -680,7 +782,7 @@ namespace Barotrauma
|
||||
}
|
||||
shoppingCrateSellList.Visible = true;
|
||||
break;
|
||||
case StoreTab.SellFromSub:
|
||||
case StoreTab.SellSub:
|
||||
storeBuyList.Visible = false;
|
||||
storeSellList.Visible = false;
|
||||
if (storeSellFromSubList != null)
|
||||
@@ -699,7 +801,6 @@ namespace Barotrauma
|
||||
|
||||
private void FilterStoreItems(MapEntityCategory? category, string filter)
|
||||
{
|
||||
if (IsTabUnavailable(activeTab)) { return; }
|
||||
selectedItemCategory = category;
|
||||
var list = tabLists[activeTab];
|
||||
filter = filter?.ToLower();
|
||||
@@ -733,7 +834,7 @@ namespace Barotrauma
|
||||
float prevBuyListScroll = storeBuyList.BarScroll;
|
||||
float prevShoppingCrateScroll = shoppingCrateBuyList.BarScroll;
|
||||
|
||||
bool hasPermissions = HasPermissions;
|
||||
bool hasPermissions = HasBuyPermissions;
|
||||
HashSet<GUIComponent> existingItemFrames = new HashSet<GUIComponent>();
|
||||
|
||||
int dailySpecialCount = CurrentLocation?.DailySpecials.Count() ?? 3;
|
||||
@@ -816,7 +917,7 @@ namespace Barotrauma
|
||||
{
|
||||
float prevSellListScroll = storeSellList.BarScroll;
|
||||
float prevShoppingCrateScroll = shoppingCrateSellList.BarScroll;
|
||||
bool hasPermissions = HasPermissions;
|
||||
bool hasPermissions = HasTabPermissions(StoreTab.Sell);
|
||||
HashSet<GUIComponent> existingItemFrames = new HashSet<GUIComponent>();
|
||||
|
||||
if ((storeRequestedGoodGroup != null) != CurrentLocation.RequestedGoods.Any())
|
||||
@@ -894,7 +995,7 @@ namespace Barotrauma
|
||||
{
|
||||
float prevSellListScroll = storeSellFromSubList.BarScroll;
|
||||
float prevShoppingCrateScroll = shoppingCrateSellFromSubList.BarScroll;
|
||||
bool hasPermissions = HasPermissions;
|
||||
bool hasPermissions = HasSellSubPermissions;
|
||||
HashSet<GUIComponent> existingItemFrames = new HashSet<GUIComponent>();
|
||||
|
||||
if ((storeRequestedSubGoodGroup != null) != CurrentLocation.RequestedGoods.Any())
|
||||
@@ -938,12 +1039,12 @@ namespace Barotrauma
|
||||
if (itemFrame == null)
|
||||
{
|
||||
var parentComponent = isRequestedGood ? storeRequestedSubGoodGroup : storeSellFromSubList as GUIComponent;
|
||||
itemFrame = CreateItemFrame(new PurchasedItem(itemPrefab, itemQuantity), parentComponent, StoreTab.SellFromSub, forceDisable: !hasPermissions);
|
||||
itemFrame = CreateItemFrame(new PurchasedItem(itemPrefab, itemQuantity), parentComponent, StoreTab.SellSub, forceDisable: !hasPermissions);
|
||||
}
|
||||
else
|
||||
{
|
||||
(itemFrame.UserData as PurchasedItem).Quantity = itemQuantity;
|
||||
SetQuantityLabelText(StoreTab.SellFromSub, itemFrame);
|
||||
SetQuantityLabelText(StoreTab.SellSub, itemFrame);
|
||||
SetOwnedLabelText(itemFrame);
|
||||
SetPriceGetters(itemFrame, false);
|
||||
}
|
||||
@@ -961,8 +1062,8 @@ namespace Barotrauma
|
||||
removedItemFrames.AddRange(storeRequestedSubGoodGroup.Children.Where(c => c.UserData is PurchasedItem).Except(existingItemFrames).ToList());
|
||||
}
|
||||
removedItemFrames.ForEach(f => f.RectTransform.Parent = null);
|
||||
if (activeTab == StoreTab.SellFromSub) { FilterStoreItems(); }
|
||||
SortItems(StoreTab.SellFromSub);
|
||||
if (activeTab == StoreTab.SellSub) { FilterStoreItems(); }
|
||||
SortItems(StoreTab.SellSub);
|
||||
|
||||
storeSellFromSubList.BarScroll = prevSellListScroll;
|
||||
shoppingCrateSellFromSubList.BarScroll = prevShoppingCrateScroll;
|
||||
@@ -1062,17 +1163,14 @@ namespace Barotrauma
|
||||
|
||||
private void RefreshShoppingCrateList(List<PurchasedItem> items, GUIListBox listBox, StoreTab tab)
|
||||
{
|
||||
bool hasPermissions = HasPermissions;
|
||||
bool hasPermissions = HasTabPermissions(tab);
|
||||
HashSet<GUIComponent> existingItemFrames = new HashSet<GUIComponent>();
|
||||
int totalPrice = 0;
|
||||
foreach (PurchasedItem item in items)
|
||||
{
|
||||
PriceInfo priceInfo = item.ItemPrefab.GetPriceInfo(CurrentLocation);
|
||||
if (priceInfo == null) { continue; }
|
||||
|
||||
var itemFrame = listBox.Content.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab.Identifier == item.ItemPrefab.Identifier);
|
||||
if (!(item.ItemPrefab.GetPriceInfo(CurrentLocation) is { } priceInfo)) { continue; }
|
||||
GUINumberInput numInput = null;
|
||||
if (itemFrame == null)
|
||||
if (!(listBox.Content.FindChild(c => c.UserData is PurchasedItem pi && pi.ItemPrefab.Identifier == item.ItemPrefab.Identifier) is { } itemFrame))
|
||||
{
|
||||
itemFrame = CreateItemFrame(item, listBox, tab, forceDisable: !hasPermissions);
|
||||
numInput = itemFrame.FindChild(c => c is GUINumberInput, recursive: true) as GUINumberInput;
|
||||
@@ -1100,10 +1198,21 @@ namespace Barotrauma
|
||||
}
|
||||
suppressBuySell = false;
|
||||
|
||||
var price = tab == StoreTab.Buy ?
|
||||
CurrentLocation.GetAdjustedItemBuyPrice(item.ItemPrefab, priceInfo: priceInfo) :
|
||||
CurrentLocation.GetAdjustedItemSellPrice(item.ItemPrefab, priceInfo: priceInfo);
|
||||
totalPrice += item.Quantity * price;
|
||||
try
|
||||
{
|
||||
int price = tab switch
|
||||
{
|
||||
StoreTab.Buy => CurrentLocation.GetAdjustedItemBuyPrice(item.ItemPrefab, priceInfo: priceInfo),
|
||||
StoreTab.Sell => CurrentLocation.GetAdjustedItemSellPrice(item.ItemPrefab, priceInfo: priceInfo),
|
||||
StoreTab.SellSub => CurrentLocation.GetAdjustedItemSellPrice(item.ItemPrefab, priceInfo: priceInfo),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
totalPrice += item.Quantity * price;
|
||||
}
|
||||
catch (NotImplementedException e)
|
||||
{
|
||||
DebugConsole.ShowError($"Error getting item price: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
}
|
||||
}
|
||||
|
||||
var removedItemFrames = listBox.Content.Children.Except(existingItemFrames).ToList();
|
||||
@@ -1119,7 +1228,7 @@ namespace Barotrauma
|
||||
case StoreTab.Sell:
|
||||
sellTotal = totalPrice;
|
||||
break;
|
||||
case StoreTab.SellFromSub:
|
||||
case StoreTab.SellSub:
|
||||
sellFromSubTotal = totalPrice;
|
||||
break;
|
||||
}
|
||||
@@ -1135,7 +1244,7 @@ namespace Barotrauma
|
||||
|
||||
private void RefreshShoppingCrateSellList() => RefreshShoppingCrateList(CargoManager.ItemsInSellCrate, shoppingCrateSellList, StoreTab.Sell);
|
||||
|
||||
private void RefreshShoppingCrateSellFromSubList() => RefreshShoppingCrateList(CargoManager.ItemsInSellFromSubCrate, shoppingCrateSellFromSubList, StoreTab.SellFromSub);
|
||||
private void RefreshShoppingCrateSellFromSubList() => RefreshShoppingCrateList(CargoManager.ItemsInSellFromSubCrate, shoppingCrateSellFromSubList, StoreTab.SellSub);
|
||||
|
||||
private void SortItems(GUIListBox list, SortingMethod sortingMethod)
|
||||
{
|
||||
@@ -1286,14 +1395,12 @@ namespace Barotrauma
|
||||
|
||||
private void SortItems(StoreTab tab, SortingMethod sortingMethod)
|
||||
{
|
||||
if (IsTabUnavailable(tab)) { return; }
|
||||
tabSortingMethods[tab] = sortingMethod;
|
||||
SortItems(tabLists[tab], sortingMethod);
|
||||
}
|
||||
|
||||
private void SortItems(StoreTab tab)
|
||||
{
|
||||
if (IsTabUnavailable(tab)) { return; }
|
||||
SortItems(tab, tabSortingMethods[tab]);
|
||||
}
|
||||
|
||||
@@ -1301,12 +1408,6 @@ namespace Barotrauma
|
||||
|
||||
private GUIComponent CreateItemFrame(PurchasedItem pi, GUIComponent parentComponent, StoreTab containingTab, bool forceDisable = false)
|
||||
{
|
||||
var tooltip = pi.ItemPrefab.Name;
|
||||
if (!string.IsNullOrWhiteSpace(pi.ItemPrefab.Description))
|
||||
{
|
||||
tooltip += "\n" + pi.ItemPrefab.Description;
|
||||
}
|
||||
|
||||
GUIListBox parentListBox = parentComponent as GUIListBox;
|
||||
int width = 0;
|
||||
RectTransform parent = null;
|
||||
@@ -1320,7 +1421,11 @@ namespace Barotrauma
|
||||
width = parentComponent.Rect.Width;
|
||||
parent = parentComponent.RectTransform;
|
||||
}
|
||||
|
||||
string tooltip = pi.ItemPrefab.Name;
|
||||
if (!string.IsNullOrWhiteSpace(pi.ItemPrefab.Description))
|
||||
{
|
||||
tooltip += $"\n{pi.ItemPrefab.Description}";
|
||||
}
|
||||
GUIFrame frame = new GUIFrame(new RectTransform(new Point(width, (int)(GUI.yScale * 80)), parent: parent), style: "ListBoxElement")
|
||||
{
|
||||
ToolTip = tooltip,
|
||||
@@ -1338,8 +1443,7 @@ namespace Barotrauma
|
||||
var iconRelativeWidth = 0.0f;
|
||||
var priceAndButtonRelativeWidth = 1.0f - nameAndIconRelativeWidth;
|
||||
|
||||
Sprite itemIcon = pi.ItemPrefab.InventoryIcon ?? pi.ItemPrefab.sprite;
|
||||
if (itemIcon != null)
|
||||
if ((pi.ItemPrefab.InventoryIcon ?? pi.ItemPrefab.sprite) is { } itemIcon)
|
||||
{
|
||||
iconRelativeWidth = (0.9f * mainGroup.Rect.Height) / mainGroup.Rect.Width;
|
||||
GUIImage img = new GUIImage(new RectTransform(new Vector2(iconRelativeWidth, 0.9f), mainGroup.RectTransform), itemIcon, scaleToFit: true)
|
||||
@@ -1425,7 +1529,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (suppressBuySell) { return; }
|
||||
PurchasedItem purchasedItem = numberInput.UserData as PurchasedItem;
|
||||
if (!HasPermissions)
|
||||
if (!HasActiveTabPermissions())
|
||||
{
|
||||
numberInput.IntValue = purchasedItem.Quantity;
|
||||
return;
|
||||
@@ -1528,11 +1632,16 @@ namespace Barotrauma
|
||||
OwnedItems.Clear();
|
||||
|
||||
// Add items on the sub(s)
|
||||
Submarine.MainSub?.GetItems(true)
|
||||
.Where(i => i.Components.All(c => !(c is Holdable h) || !h.Attachable || !h.Attached) &&
|
||||
i.Components.All(c => !(c is Wire w) || w.Connections.All(c => c == null)) &&
|
||||
ItemAndAllContainersInteractable(i))
|
||||
.ForEach(i => AddToOwnedItems(i.Prefab));
|
||||
if (Submarine.MainSub?.GetItems(true) is List<Item> subItems)
|
||||
{
|
||||
foreach (var subItem in subItems)
|
||||
{
|
||||
if (!subItem.Components.All(c => !(c is Holdable h) || !h.Attachable || !h.Attached)) { continue; }
|
||||
if (!subItem.Components.All(c => !(c is Wire w) || w.Connections.All(c => c == null))) { continue; }
|
||||
if (!ItemAndAllContainersInteractable(subItem)) { continue; }
|
||||
AddToOwnedItems(subItem.Prefab);
|
||||
}
|
||||
}
|
||||
|
||||
// Add items in character inventories
|
||||
foreach (var item in Item.ItemList)
|
||||
@@ -1664,14 +1773,22 @@ namespace Barotrauma
|
||||
|
||||
private int GetMaxAvailable(ItemPrefab itemPrefab, StoreTab mode)
|
||||
{
|
||||
var list = mode switch
|
||||
List<PurchasedItem> list = null;
|
||||
try
|
||||
{
|
||||
StoreTab.Buy => CurrentLocation.StoreStock,
|
||||
StoreTab.Sell => itemsToSell,
|
||||
StoreTab.SellFromSub => itemsToSellFromSub,
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
if (list.Find(i => i.ItemPrefab == itemPrefab) is PurchasedItem item)
|
||||
list = mode switch
|
||||
{
|
||||
StoreTab.Buy => CurrentLocation?.StoreStock,
|
||||
StoreTab.Sell => itemsToSell,
|
||||
StoreTab.SellSub => itemsToSellFromSub,
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
}
|
||||
catch (NotImplementedException e)
|
||||
{
|
||||
DebugConsole.ShowError($"Error getting item availability: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
}
|
||||
if (list != null && list.Find(i => i.ItemPrefab == itemPrefab) is PurchasedItem item)
|
||||
{
|
||||
if (mode == StoreTab.Buy)
|
||||
{
|
||||
@@ -1691,8 +1808,8 @@ namespace Barotrauma
|
||||
|
||||
private bool ModifyBuyQuantity(PurchasedItem item, int quantity)
|
||||
{
|
||||
if (item == null || item.ItemPrefab == null) { return false; }
|
||||
if (!HasPermissions) { return false; }
|
||||
if (item?.ItemPrefab == null) { return false; }
|
||||
if (!HasBuyPermissions) { return false; }
|
||||
if (quantity > 0)
|
||||
{
|
||||
var itemInCrate = CargoManager.ItemsInBuyCrate.Find(i => i.ItemPrefab == item.ItemPrefab);
|
||||
@@ -1703,13 +1820,13 @@ namespace Barotrauma
|
||||
}
|
||||
CargoManager.ModifyItemQuantityInBuyCrate(item.ItemPrefab, quantity);
|
||||
GameMain.Client?.SendCampaignState();
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ModifySellQuantity(PurchasedItem item, int quantity)
|
||||
{
|
||||
if (item == null || item.ItemPrefab == null) { return false; }
|
||||
if (!HasPermissions) { return false; }
|
||||
if (item?.ItemPrefab == null) { return false; }
|
||||
if (!HasSellInventoryPermissions) { return false; }
|
||||
if (quantity > 0)
|
||||
{
|
||||
// Make sure there's enough available to sell
|
||||
@@ -1718,45 +1835,68 @@ namespace Barotrauma
|
||||
if (totalQuantityToSell > GetMaxAvailable(item.ItemPrefab, StoreTab.Sell)) { return false; }
|
||||
}
|
||||
CargoManager.ModifyItemQuantityInSellCrate(item.ItemPrefab, quantity);
|
||||
//GameMain.Client?.SendCampaignState();
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ModifySellFromSubQuantity(PurchasedItem item, int quantity)
|
||||
{
|
||||
if (item == null || item.ItemPrefab == null) { return false; }
|
||||
if (!HasPermissions) { return false; }
|
||||
if (item?.ItemPrefab == null) { return false; }
|
||||
if (!HasSellSubPermissions) { return false; }
|
||||
if (quantity > 0)
|
||||
{
|
||||
// Make sure there's enough available to sell
|
||||
var itemToSell = CargoManager.ItemsInSellFromSubCrate.Find(i => i.ItemPrefab == item.ItemPrefab);
|
||||
var totalQuantityToSell = itemToSell != null ? itemToSell.Quantity + quantity : quantity;
|
||||
if (totalQuantityToSell > GetMaxAvailable(item.ItemPrefab, StoreTab.SellFromSub)) { return false; }
|
||||
if (totalQuantityToSell > GetMaxAvailable(item.ItemPrefab, StoreTab.SellSub)) { return false; }
|
||||
}
|
||||
CargoManager.ModifyItemQuantityInSellFromSubCrate(item.ItemPrefab, quantity);
|
||||
// TODO: GameMain.Client?.SendCampaignState();
|
||||
return false;
|
||||
GameMain.Client?.SendCampaignState();
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool AddToShoppingCrate(PurchasedItem item, int quantity = 1) => activeTab switch
|
||||
private bool AddToShoppingCrate(PurchasedItem item, int quantity = 1)
|
||||
{
|
||||
StoreTab.Buy => ModifyBuyQuantity(item, quantity),
|
||||
StoreTab.Sell => ModifySellQuantity(item, quantity),
|
||||
StoreTab.SellFromSub => ModifySellFromSubQuantity(item, quantity),
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
if (item == null) { return false; }
|
||||
try
|
||||
{
|
||||
return activeTab switch
|
||||
{
|
||||
StoreTab.Buy => ModifyBuyQuantity(item, quantity),
|
||||
StoreTab.Sell => ModifySellQuantity(item, quantity),
|
||||
StoreTab.SellSub => ModifySellFromSubQuantity(item, quantity),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
}
|
||||
catch (NotImplementedException e)
|
||||
{
|
||||
DebugConsole.ShowError($"Error adding an item to the shopping crate: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool ClearFromShoppingCrate(PurchasedItem item) => activeTab switch
|
||||
private bool ClearFromShoppingCrate(PurchasedItem item)
|
||||
{
|
||||
StoreTab.Buy => ModifyBuyQuantity(item, -item.Quantity),
|
||||
StoreTab.Sell => ModifySellQuantity(item, -item.Quantity),
|
||||
StoreTab.SellFromSub => ModifySellFromSubQuantity(item, -item.Quantity),
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
if (item == null) { return false; }
|
||||
try
|
||||
{
|
||||
return activeTab switch
|
||||
{
|
||||
StoreTab.Buy => ModifyBuyQuantity(item, -item.Quantity),
|
||||
StoreTab.Sell => ModifySellQuantity(item, -item.Quantity),
|
||||
StoreTab.SellSub => ModifySellFromSubQuantity(item, -item.Quantity),
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
}
|
||||
catch (NotImplementedException e)
|
||||
{
|
||||
DebugConsole.ShowError($"Error clearing the shopping crate: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool BuyItems()
|
||||
{
|
||||
if (!HasPermissions) { return false; }
|
||||
if (!HasBuyPermissions) { return false; }
|
||||
|
||||
var itemsToPurchase = new List<PurchasedItem>(CargoManager.ItemsInBuyCrate);
|
||||
var itemsToRemove = new List<PurchasedItem>();
|
||||
@@ -1788,15 +1928,24 @@ namespace Barotrauma
|
||||
|
||||
private bool SellItems()
|
||||
{
|
||||
if (!HasPermissions) { return false; }
|
||||
var itemsToSell = activeTab switch
|
||||
if (!HasActiveTabPermissions()) { return false; }
|
||||
List<PurchasedItem> itemsToSell;
|
||||
try
|
||||
{
|
||||
StoreTab.Sell => new List<PurchasedItem>(CargoManager.ItemsInSellCrate),
|
||||
StoreTab.SellFromSub => new List<PurchasedItem>(CargoManager.ItemsInSellFromSubCrate),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
itemsToSell = activeTab switch
|
||||
{
|
||||
StoreTab.Sell => new List<PurchasedItem>(CargoManager.ItemsInSellCrate),
|
||||
StoreTab.SellSub => new List<PurchasedItem>(CargoManager.ItemsInSellFromSubCrate),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
}
|
||||
catch (NotImplementedException e)
|
||||
{
|
||||
DebugConsole.ShowError($"Error confirming the store transaction: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
return false;
|
||||
}
|
||||
var itemsToRemove = new List<PurchasedItem>();
|
||||
var totalValue = 0;
|
||||
int totalValue = 0;
|
||||
foreach (PurchasedItem item in itemsToSell)
|
||||
{
|
||||
if (item?.ItemPrefab?.GetPriceInfo(CurrentLocation) is PriceInfo priceInfo)
|
||||
@@ -1811,11 +1960,7 @@ namespace Barotrauma
|
||||
itemsToRemove.ForEach(i => itemsToSell.Remove(i));
|
||||
if (itemsToSell.None() || totalValue > CurrentLocation.StoreCurrentBalance) { return false; }
|
||||
CargoManager.SellItems(itemsToSell, activeTab);
|
||||
if (activeTab == StoreTab.Sell)
|
||||
{
|
||||
// TODO: Implement selling sub items in multiplayer
|
||||
GameMain.Client?.SendCampaignState();
|
||||
}
|
||||
GameMain.Client?.SendCampaignState();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1831,7 +1976,7 @@ namespace Barotrauma
|
||||
int total = activeTab switch
|
||||
{
|
||||
StoreTab.Sell => sellTotal,
|
||||
StoreTab.SellFromSub => sellFromSubTotal,
|
||||
StoreTab.SellSub => sellFromSubTotal,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
shoppingCrateTotal.Text = GetCurrencyFormatted(total);
|
||||
@@ -1863,21 +2008,29 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private void SetConfirmButtonStatus() => confirmButton.Enabled =
|
||||
HasPermissions && ActiveShoppingCrateList.Content.RectTransform.Children.Any() &&
|
||||
activeTab switch
|
||||
{
|
||||
StoreTab.Buy => buyTotal <= PlayerMoney,
|
||||
StoreTab.Sell => CurrentLocation != null && sellTotal <= CurrentLocation.StoreCurrentBalance,
|
||||
StoreTab.SellFromSub => CurrentLocation != null && sellFromSubTotal <= CurrentLocation.StoreCurrentBalance,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
private void SetConfirmButtonStatus()
|
||||
{
|
||||
confirmButton.Enabled =
|
||||
HasActiveTabPermissions() &&
|
||||
ActiveShoppingCrateList.Content.RectTransform.Children.Any() &&
|
||||
activeTab switch
|
||||
{
|
||||
StoreTab.Buy => buyTotal <= PlayerMoney,
|
||||
StoreTab.Sell => CurrentLocation != null && sellTotal <= CurrentLocation.StoreCurrentBalance,
|
||||
StoreTab.SellSub => CurrentLocation != null && sellFromSubTotal <= CurrentLocation.StoreCurrentBalance,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
private void SetClearAllButtonStatus() => clearAllButton.Enabled =
|
||||
HasPermissions && ActiveShoppingCrateList.Content.RectTransform.Children.Any();
|
||||
private void SetClearAllButtonStatus()
|
||||
{
|
||||
clearAllButton.Enabled =
|
||||
HasActiveTabPermissions() &&
|
||||
ActiveShoppingCrateList.Content.RectTransform.Children.Any();
|
||||
}
|
||||
|
||||
private float ownedItemsUpdateTimer = 0.0f, sellableItemsFromSubUpdateTimer = 0.0f;
|
||||
private readonly float timerUpdateInterval = 1.5f;
|
||||
private const float timerUpdateInterval = 1.5f;
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
@@ -1914,10 +2067,10 @@ namespace Barotrauma
|
||||
|
||||
if (needsItemsToSellRefresh) { RefreshItemsToSell(); }
|
||||
if (needsItemsToSellFromSubRefresh) { RefreshItemsToSellFromSub(); }
|
||||
if (needsRefresh || hadPermissions != HasPermissions) { Refresh(updateOwned: ownedItemsUpdateTimer > 0.0f); }
|
||||
if (needsBuyingRefresh) { RefreshBuying(); }
|
||||
if (needsSellingRefresh) { RefreshSelling(); }
|
||||
if (needsSellingFromSubRefresh) { RefreshSellingFromSub(updateItemsToSellFromSub: sellableItemsFromSubUpdateTimer > 0.0f); }
|
||||
if (needsRefresh || HavePermissionsChanged()) { Refresh(updateOwned: ownedItemsUpdateTimer > 0.0f); }
|
||||
if (needsBuyingRefresh || HavePermissionsChanged(StoreTab.Buy)) { RefreshBuying(updateOwned: ownedItemsUpdateTimer > 0.0f); }
|
||||
if (needsSellingRefresh || HavePermissionsChanged(StoreTab.Sell)) { RefreshSelling(updateOwned: ownedItemsUpdateTimer > 0.0f); }
|
||||
if (needsSellingFromSubRefresh || HavePermissionsChanged(StoreTab.SellSub)) { RefreshSellingFromSub(updateItemsToSellFromSub: sellableItemsFromSubUpdateTimer > 0.0f); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,6 +167,7 @@ namespace Barotrauma
|
||||
//TODO: move this somewhere else
|
||||
public static void UpdateCategoryList(GUIListBox categoryList, CampaignMode campaign, Submarine? drawnSubmarine, IEnumerable<UpgradeCategory> applicableCategories)
|
||||
{
|
||||
var subItems = GetSubItems();
|
||||
foreach (GUIComponent component in categoryList.Content.Children)
|
||||
{
|
||||
if (!(component.UserData is CategoryData data)) { continue; }
|
||||
@@ -178,7 +179,7 @@ namespace Barotrauma
|
||||
var customizeButton = component.FindChild("customizebutton", true);
|
||||
if (customizeButton != null)
|
||||
{
|
||||
customizeButton.Visible = HasSwappableItems(data.Category);
|
||||
customizeButton.Visible = HasSwappableItems(data.Category, subItems);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -719,16 +720,19 @@ namespace Barotrauma
|
||||
|
||||
private bool customizeTabOpen;
|
||||
|
||||
private static bool HasSwappableItems(UpgradeCategory category)
|
||||
private static bool HasSwappableItems(UpgradeCategory category, List<Item>? subItems = null)
|
||||
{
|
||||
if (Submarine.MainSub == null) { return false; }
|
||||
return Submarine.MainSub.GetItems(true).Any(i =>
|
||||
subItems ??= GetSubItems();
|
||||
return subItems.Any(i =>
|
||||
i.Prefab.SwappableItem != null &&
|
||||
!i.HiddenInGame && i.AllowSwapping &&
|
||||
(i.Prefab.SwappableItem.CanBeBought || ItemPrefab.Prefabs.Any(ip => ip.SwappableItem?.ReplacementOnUninstall == i.Prefab.Identifier)) &&
|
||||
Submarine.MainSub.IsEntityFoundOnThisSub(i, true) && category.ItemTags.Any(t => i.HasTag(t)));
|
||||
}
|
||||
|
||||
private static List<Item> GetSubItems() => Submarine.MainSub?.GetItems(true) ?? new List<Item>();
|
||||
|
||||
private void SelectUpgradeCategory(List<UpgradePrefab> prefabs, UpgradeCategory category, Submarine submarine)
|
||||
{
|
||||
if (selectedUpgradeCategoryLayout == null) { return; }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Items.Components;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
@@ -7,37 +8,6 @@ namespace Barotrauma
|
||||
{
|
||||
partial class CargoManager
|
||||
{
|
||||
private class SoldEntity
|
||||
{
|
||||
public enum SellStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Entity sold in SP. Or, entity sold by client and confirmed by server in MP.
|
||||
/// </summary>
|
||||
Confirmed,
|
||||
/// <summary>
|
||||
/// Entity sold by client in MP. Client has received at least one update from server after selling, but this entity wasn't yet confirmed.
|
||||
/// </summary>
|
||||
Unconfirmed,
|
||||
/// <summary>
|
||||
/// Entity sold by client in MP. Client hasn't yet received an update from server after selling.
|
||||
/// </summary>
|
||||
Local
|
||||
}
|
||||
|
||||
public Item Item { get; }
|
||||
public SellStatus Status { get; set; }
|
||||
|
||||
private SoldEntity(Item item, SellStatus status)
|
||||
{
|
||||
Item = item;
|
||||
Status = status;
|
||||
}
|
||||
|
||||
public static SoldEntity CreateInSinglePlayer(Item item) => new SoldEntity(item, SellStatus.Confirmed);
|
||||
public static SoldEntity CreateInMultiPlayer(Item item) => new SoldEntity(item, SellStatus.Local);
|
||||
}
|
||||
|
||||
private List<SoldEntity> SoldEntities { get; } = new List<SoldEntity>();
|
||||
|
||||
// The bag slot is intentionally left out since we want to be able to sell items from there
|
||||
@@ -67,31 +37,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Item> GetSellableItemsFromSub()
|
||||
{
|
||||
if (Submarine.MainSub == null) { return new List<Item>(); }
|
||||
var confirmedSoldEntities = GetConfirmedSoldEntities();
|
||||
return Submarine.MainSub.GetItems(true).FindAll(item =>
|
||||
{
|
||||
if (!IsItemSellable(item, confirmedSoldEntities)) { return false; }
|
||||
if (item.GetRootInventoryOwner() is Character) { return false; }
|
||||
if (!item.Components.All(c => !(c is Holdable h) || !h.Attachable || !h.Attached)) { return false; }
|
||||
if (!item.Components.All(c => !(c is Wire w) || w.Connections.All(c => c == null))) { return false; }
|
||||
if (!ItemAndAllContainersInteractable(item)) { return false; }
|
||||
return true;
|
||||
}).Distinct();
|
||||
|
||||
static bool ItemAndAllContainersInteractable(Item item)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!item.IsPlayerTeamInteractable) { return false; }
|
||||
item = item.Container;
|
||||
} while (item != null);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<SoldEntity> GetConfirmedSoldEntities()
|
||||
{
|
||||
// Only consider items which have been:
|
||||
@@ -100,24 +45,6 @@ namespace Barotrauma
|
||||
return SoldEntities.Where(se => se.Status != SoldEntity.SellStatus.Unconfirmed);
|
||||
}
|
||||
|
||||
private bool IsItemSellable(Item item, IEnumerable<SoldEntity> confirmedSoldEntities)
|
||||
{
|
||||
if (!item.Prefab.CanBeSold) { return false; }
|
||||
if (item.SpawnedInCurrentOutpost) { return false; }
|
||||
if (!item.Prefab.AllowSellingWhenBroken && item.ConditionPercentage < 90.0f) { return false; }
|
||||
if (confirmedSoldEntities.Any(it => it.Item == item)) { return false; }
|
||||
if (item.OwnInventory?.Container is ItemContainer itemContainer)
|
||||
{
|
||||
var containedItems = item.ContainedItems;
|
||||
if (containedItems.None()) { return true; }
|
||||
// Allow selling the item if contained items are unsellable and set to be removed on deconstruct
|
||||
if (itemContainer.RemoveContainedItemsOnDeconstruct && containedItems.All(it => !it.Prefab.CanBeSold)) { return true; }
|
||||
// Otherwise there must be no contained items or the contained items must be confirmed as sold
|
||||
if (!containedItems.All(it => confirmedSoldEntities.Any(se => se.Item == it))) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetItemsInBuyCrate(List<PurchasedItem> items)
|
||||
{
|
||||
ItemsInBuyCrate.Clear();
|
||||
@@ -125,15 +52,21 @@ namespace Barotrauma
|
||||
OnItemsInBuyCrateChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void SetItemsInSubSellCrate(List<PurchasedItem> items)
|
||||
{
|
||||
ItemsInSellFromSubCrate.Clear();
|
||||
ItemsInSellFromSubCrate.AddRange(items);
|
||||
OnItemsInSellFromSubCrateChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void SetSoldItems(List<SoldItem> items)
|
||||
{
|
||||
SoldItems.Clear();
|
||||
SoldItems.AddRange(items);
|
||||
|
||||
foreach (SoldEntity se in SoldEntities)
|
||||
foreach (var se in SoldEntities)
|
||||
{
|
||||
if (se.Status == SoldEntity.SellStatus.Confirmed) { continue; }
|
||||
if (SoldItems.Any(si => si.ID == se.Item.ID && si.ItemPrefab == se.Item.Prefab && (GameMain.Client == null || GameMain.Client.ID == si.SellerID)))
|
||||
if (SoldItems.Any(si => Match(si, se, true)))
|
||||
{
|
||||
se.Status = SoldEntity.SellStatus.Confirmed;
|
||||
}
|
||||
@@ -142,13 +75,28 @@ namespace Barotrauma
|
||||
se.Status = SoldEntity.SellStatus.Unconfirmed;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
static bool Match(SoldItem soldItem, SoldEntity soldEntity, bool matchId)
|
||||
{
|
||||
if (soldItem.ItemPrefab != soldEntity.ItemPrefab) { return false; }
|
||||
if (matchId && (soldEntity.Item == null || soldItem.ID != soldEntity.Item.ID)) { return false; }
|
||||
if (soldItem.Origin == SoldItem.SellOrigin.Character && GameMain.Client != null && soldItem.SellerID != GameMain.Client.ID) { return false; }
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void ModifyItemQuantityInSellCrate(ItemPrefab itemPrefab, int changeInQuantity)
|
||||
{
|
||||
PurchasedItem itemToSell = ItemsInSellCrate.Find(i => i.ItemPrefab == itemPrefab);
|
||||
var itemToSell = ItemsInSellCrate.Find(i => i.ItemPrefab == itemPrefab);
|
||||
if (itemToSell != null)
|
||||
{
|
||||
itemToSell.Quantity += changeInQuantity;
|
||||
@@ -186,74 +134,69 @@ namespace Barotrauma
|
||||
|
||||
public void SellItems(List<PurchasedItem> itemsToSell, Store.StoreTab sellingMode)
|
||||
{
|
||||
var sellableItems = sellingMode switch
|
||||
IEnumerable<Item> sellableItems;
|
||||
try
|
||||
{
|
||||
Store.StoreTab.Sell => GetSellableItems(Character.Controlled),
|
||||
Store.StoreTab.SellFromSub => GetSellableItemsFromSub(),
|
||||
_ => throw new System.NotImplementedException(),
|
||||
};
|
||||
sellableItems = sellingMode switch
|
||||
{
|
||||
Store.StoreTab.Sell => GetSellableItems(Character.Controlled),
|
||||
Store.StoreTab.SellSub => GetSellableItemsFromSub(),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
}
|
||||
catch (NotImplementedException e)
|
||||
{
|
||||
DebugConsole.ShowError($"Error selling items: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||
return;
|
||||
}
|
||||
bool canAddToRemoveQueue = campaign.IsSinglePlayer && Entity.Spawner != null;
|
||||
var sellerId = GameMain.Client?.ID ?? 0;
|
||||
|
||||
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)
|
||||
{
|
||||
var itemValue = item.Quantity * sellValues[item.ItemPrefab];
|
||||
|
||||
int itemValue = item.Quantity * sellValues[item.ItemPrefab];
|
||||
// check if the store can afford the item
|
||||
if (Location.StoreCurrentBalance < 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);
|
||||
if (matchingItems.Count() <= item.Quantity)
|
||||
int count = Math.Min(item.Quantity, matchingItems.Count());
|
||||
SoldItem.SellOrigin origin = sellingMode == Store.StoreTab.Sell ? SoldItem.SellOrigin.Character : SoldItem.SellOrigin.Submarine;
|
||||
if (origin == SoldItem.SellOrigin.Character || GameMain.IsSingleplayer)
|
||||
{
|
||||
foreach (Item i in matchingItems)
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
SoldItems.Add(new SoldItem(i.Prefab, i.ID, canAddToRemoveQueue, sellerId));
|
||||
SoldEntities.Add(campaign.IsSinglePlayer ? SoldEntity.CreateInSinglePlayer(i) : SoldEntity.CreateInMultiPlayer(i));
|
||||
if (canAddToRemoveQueue) { Entity.Spawner.AddToRemoveQueue(i); }
|
||||
var matchingItem = matchingItems.ElementAt(i);
|
||||
SoldItems.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.AddToRemoveQueue(matchingItem); }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < item.Quantity; i++)
|
||||
// When selling from the sub in multiplayer, the server will determine the items that are sold
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var matchingItem = matchingItems.ElementAt(i);
|
||||
SoldItems.Add(new SoldItem(matchingItem.Prefab, matchingItem.ID, canAddToRemoveQueue, sellerId));
|
||||
SoldEntities.Add(campaign.IsSinglePlayer ? SoldEntity.CreateInSinglePlayer(matchingItem) : SoldEntity.CreateInMultiPlayer(matchingItem));
|
||||
if (canAddToRemoveQueue) { Entity.Spawner.AddToRemoveQueue(matchingItem); }
|
||||
SoldItems.Add(new SoldItem(item.ItemPrefab, Entity.NullEntityID, canAddToRemoveQueue, sellerId, origin));
|
||||
SoldEntities.Add(new SoldEntity(item.ItemPrefab, SoldEntity.SellStatus.Local));
|
||||
}
|
||||
}
|
||||
|
||||
// Exchange money
|
||||
Location.StoreCurrentBalance -= itemValue;
|
||||
campaign.Money += itemValue;
|
||||
|
||||
GameAnalyticsManager.AddMoneyGainedEvent(itemValue, GameAnalyticsManager.MoneySource.Store, item.ItemPrefab.Identifier);
|
||||
|
||||
// Remove from the sell crate
|
||||
// TODO: Simplify duplicate logic?
|
||||
if (sellingMode == Store.StoreTab.Sell && ItemsInSellCrate.Find(pi => pi.ItemPrefab == item.ItemPrefab) is { } inventoryItem)
|
||||
if ((sellingMode == Store.StoreTab.Sell ? ItemsInSellCrate : ItemsInSellFromSubCrate)?.Find(pi => pi.ItemPrefab == item.ItemPrefab) is { } itemToSell)
|
||||
{
|
||||
inventoryItem.Quantity -= item.Quantity;
|
||||
if (inventoryItem.Quantity < 1)
|
||||
itemToSell.Quantity -= item.Quantity;
|
||||
if (itemToSell.Quantity < 1)
|
||||
{
|
||||
ItemsInSellCrate.Remove(inventoryItem);
|
||||
}
|
||||
}
|
||||
else if(sellingMode == Store.StoreTab.SellFromSub && ItemsInSellFromSubCrate.Find(pi => pi.ItemPrefab == item.ItemPrefab) is { } subItem)
|
||||
{
|
||||
subItem.Quantity -= item.Quantity;
|
||||
if (subItem.Quantity < 1)
|
||||
{
|
||||
ItemsInSellFromSubCrate.Remove(subItem);
|
||||
(sellingMode == Store.StoreTab.Sell ? ItemsInSellCrate : ItemsInSellFromSubCrate)?.Remove(itemToSell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OnSoldItemsChanged?.Invoke();
|
||||
}
|
||||
|
||||
|
||||
@@ -145,12 +145,14 @@ namespace Barotrauma
|
||||
string msgCommand = ChatMessage.GetChatMessageCommand(text, out string msg);
|
||||
// add to local history
|
||||
ChatBox.ChatManager.Store(text);
|
||||
WifiComponent headset = null;
|
||||
ChatMessageType messageType =
|
||||
((msgCommand == "r" || msgCommand == "radio") && ChatMessage.CanUseRadio(Character.Controlled, out headset)) ? ChatMessageType.Radio : ChatMessageType.Default;
|
||||
AddSinglePlayerChatMessage(
|
||||
Character.Controlled.Info.Name,
|
||||
msg,
|
||||
((msgCommand == "r" || msgCommand == "radio") && ChatMessage.CanUseRadio(Character.Controlled)) ? ChatMessageType.Radio : ChatMessageType.Default,
|
||||
msg, messageType,
|
||||
Character.Controlled);
|
||||
if (ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent headset))
|
||||
if (messageType == ChatMessageType.Radio && headset != null)
|
||||
{
|
||||
Signal s = new Signal(msg, sender: Character.Controlled, source: headset.Item);
|
||||
headset.TransmitSignal(s, sentFromChat: true);
|
||||
@@ -819,7 +821,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
OrderChatMessage msg = new OrderChatMessage(order, "", priority, order.IsReport ? hull : order.TargetEntity, null, orderGiver);
|
||||
OrderChatMessage msg = new OrderChatMessage(order, "", priority, order.IsReport ? hull : order.TargetEntity, null, orderGiver, isNewOrder: isNewOrder);
|
||||
GameMain.Client?.SendChatMessage(msg);
|
||||
}
|
||||
}
|
||||
@@ -836,7 +838,7 @@ namespace Barotrauma
|
||||
}
|
||||
else if (orderGiver != null)
|
||||
{
|
||||
OrderChatMessage msg = new OrderChatMessage(order, option, priority, order?.TargetSpatialEntity ?? order?.TargetItemComponent?.Item, character, orderGiver);
|
||||
OrderChatMessage msg = new OrderChatMessage(order, option, priority, order?.TargetSpatialEntity ?? order?.TargetItemComponent?.Item, character, orderGiver, isNewOrder: isNewOrder);
|
||||
GameMain.Client?.SendChatMessage(msg);
|
||||
}
|
||||
}
|
||||
@@ -2533,6 +2535,7 @@ namespace Barotrauma
|
||||
{
|
||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, dismissedOrderPrefab, -1));
|
||||
}
|
||||
shortcutNodes.RemoveAll(n => n.UserData is Order o && !IsOrderAvailable(o));
|
||||
if (shortcutNodes.Count < 1) { return; }
|
||||
shortcutCenterNode = new GUIFrame(new RectTransform(shortcutCenterNodeSize, parent: commandFrame.RectTransform, anchor: Anchor.Center), style: null)
|
||||
{
|
||||
@@ -2573,7 +2576,7 @@ namespace Barotrauma
|
||||
|
||||
private void CreateOrderNodes(OrderCategory orderCategory)
|
||||
{
|
||||
var orders = Order.PrefabList.FindAll(o => o.Category == orderCategory && !o.IsReport);
|
||||
var orders = Order.PrefabList.FindAll(o => o.Category == orderCategory && !o.IsReport && IsOrderAvailable(o));
|
||||
Order order;
|
||||
bool disableNode;
|
||||
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance,
|
||||
@@ -2725,6 +2728,7 @@ namespace Barotrauma
|
||||
contextualOrders.Add(new OrderInfo(Order.GetPrefab(orderIdentifier), null));
|
||||
}
|
||||
}
|
||||
contextualOrders.RemoveAll(o => !IsOrderAvailable(o.Order));
|
||||
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance, contextualOrders.Count, MathHelper.ToRadians(90f + 180f / contextualOrders.Count));
|
||||
bool disableNode = !CanCharacterBeHeard();
|
||||
for (int i = 0; i < contextualOrders.Count; i++)
|
||||
@@ -3483,6 +3487,20 @@ namespace Barotrauma
|
||||
return character?.Info?.GetManualOrderPriority(order) ?? CharacterInfo.HighestManualOrderPriority;
|
||||
}
|
||||
|
||||
private bool IsOrderAvailable(Order order)
|
||||
{
|
||||
if (order == null) { return false; }
|
||||
switch (order.Identifier.ToLowerInvariant())
|
||||
{
|
||||
case "assaultenemy":
|
||||
Character character = characterContext ?? Character.Controlled;
|
||||
if (character?.Submarine == null) { return false; }
|
||||
return character.Submarine.GetConnectedSubs().Any(s => s.TeamID != character.TeamID);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#region Crew Member Assignment Logic
|
||||
private bool CanOpenManualAssignment(GUIComponent node)
|
||||
{
|
||||
@@ -3559,7 +3577,7 @@ namespace Barotrauma
|
||||
bool hasLeaks = Character.Controlled.CurrentHull.ConnectedGaps.Any(g => !g.IsRoomToRoom && g.Open > 0.0f);
|
||||
ToggleReportButton("reportbreach", hasLeaks);
|
||||
|
||||
bool hasIntruders = Character.CharacterList.Any(c => c.CurrentHull == Character.Controlled.CurrentHull && AIObjectiveFightIntruders.IsValidTarget(c, Character.Controlled));
|
||||
bool hasIntruders = Character.CharacterList.Any(c => c.CurrentHull == Character.Controlled.CurrentHull && AIObjectiveFightIntruders.IsValidTarget(c, Character.Controlled, false));
|
||||
ToggleReportButton("reportintruders", hasIntruders);
|
||||
|
||||
foreach (GUIComponent reportButton in ReportButtonFrame.Children)
|
||||
|
||||
@@ -97,17 +97,16 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// There is a server-side implementation of the method in <see cref="MultiPlayerCampaign"/>
|
||||
/// </summary>
|
||||
public bool AllowedToManageCampaign()
|
||||
public bool AllowedToManageCampaign(ClientPermissions permissions = ClientPermissions.ManageCampaign)
|
||||
{
|
||||
//allow ending the round if the client has permissions, is the owner, the only client in the server,
|
||||
//allow managing the round if the client has permissions, is the owner, the only client in the server,
|
||||
//or if no-one has management permissions
|
||||
if (GameMain.Client == null) { return true; }
|
||||
return
|
||||
GameMain.Client.HasPermission(ClientPermissions.ManageCampaign) ||
|
||||
GameMain.Client.HasPermission(permissions) ||
|
||||
GameMain.Client.ConnectedClients.Count == 1 ||
|
||||
GameMain.Client.IsServerOwner ||
|
||||
GameMain.Client.ConnectedClients.None(c =>
|
||||
c.InGame && (c.IsOwner || c.HasPermission(ClientPermissions.ManageCampaign)));
|
||||
GameMain.Client.ConnectedClients.None(c => c.InGame && (c.IsOwner || c.HasPermission(permissions)));
|
||||
}
|
||||
|
||||
public override void Draw(SpriteBatch spriteBatch)
|
||||
|
||||
+23
-10
@@ -545,14 +545,21 @@ namespace Barotrauma
|
||||
foreach (PurchasedItem pi in CargoManager.ItemsInBuyCrate)
|
||||
{
|
||||
msg.Write(pi.ItemPrefab.Identifier);
|
||||
msg.WriteRangedInteger(pi.Quantity, 0, 100);
|
||||
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, 100);
|
||||
msg.WriteRangedInteger(pi.Quantity, 0, CargoManager.MaxQuantity);
|
||||
}
|
||||
|
||||
msg.Write((UInt16)CargoManager.SoldItems.Count);
|
||||
@@ -562,6 +569,7 @@ namespace Barotrauma
|
||||
msg.Write((UInt16)si.ID);
|
||||
msg.Write(si.Removed);
|
||||
msg.Write(si.SellerID);
|
||||
msg.Write((byte)si.Origin);
|
||||
}
|
||||
|
||||
msg.Write((ushort)UpgradeManager.PurchasedUpgrades.Count);
|
||||
@@ -640,6 +648,15 @@ namespace Barotrauma
|
||||
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++)
|
||||
@@ -657,7 +674,8 @@ namespace Barotrauma
|
||||
UInt16 id = msg.ReadUInt16();
|
||||
bool removed = msg.ReadBoolean();
|
||||
byte sellerId = msg.ReadByte();
|
||||
soldItems.Add(new SoldItem(ItemPrefab.Prefabs[itemPrefabIdentifier], id, removed, sellerId));
|
||||
byte origin = msg.ReadByte();
|
||||
soldItems.Add(new SoldItem(ItemPrefab.Prefabs[itemPrefabIdentifier], id, removed, sellerId, (SoldItem.SellOrigin)origin));
|
||||
}
|
||||
|
||||
ushort pendingUpgradeCount = msg.ReadUInt16();
|
||||
@@ -678,13 +696,9 @@ namespace Barotrauma
|
||||
for (int i = 0; i < purchasedItemSwapCount; i++)
|
||||
{
|
||||
UInt16 itemToRemoveID = msg.ReadUInt16();
|
||||
Item itemToRemove = Entity.FindEntityByID(itemToRemoveID) as Item;
|
||||
|
||||
string itemToInstallIdentifier = msg.ReadString();
|
||||
ItemPrefab itemToInstall = string.IsNullOrEmpty(itemToInstallIdentifier) ? null : ItemPrefab.Find(string.Empty, itemToInstallIdentifier);
|
||||
|
||||
if (itemToRemove == null) { continue; }
|
||||
|
||||
if (!(Entity.FindEntityByID(itemToRemoveID) is Item itemToRemove)) { continue; }
|
||||
purchasedItemSwaps.Add(new PurchasedItemSwap(itemToRemove, itemToInstall));
|
||||
}
|
||||
|
||||
@@ -728,12 +742,11 @@ namespace Barotrauma
|
||||
campaign.Map.SelectMission(selectedMissionIndices);
|
||||
campaign.Map.AllowDebugTeleport = allowDebugTeleport;
|
||||
campaign.CargoManager.SetItemsInBuyCrate(buyCrateItems);
|
||||
campaign.CargoManager.SetItemsInSubSellCrate(subSellCrateItems);
|
||||
campaign.CargoManager.SetPurchasedItems(purchasedItems);
|
||||
campaign.CargoManager.SetSoldItems(soldItems);
|
||||
if (storeBalance.HasValue) { campaign.Map.CurrentLocation.StoreCurrentBalance = storeBalance.Value; }
|
||||
campaign.UpgradeManager.SetPendingUpgrades(pendingUpgrades);
|
||||
campaign.UpgradeManager.PurchasedUpgrades.Clear();
|
||||
|
||||
campaign.UpgradeManager.PurchasedUpgrades.Clear();
|
||||
foreach (var purchasedItemSwap in purchasedItemSwaps)
|
||||
{
|
||||
|
||||
@@ -1116,6 +1116,7 @@ namespace Barotrauma.Items.Components
|
||||
foreach (DockingPort dockingPort in DockingPort.List)
|
||||
{
|
||||
if (Level.Loaded != null && dockingPort.Item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
|
||||
if (dockingPort.Item.HiddenInGame) { continue; }
|
||||
if (dockingPort.Item.Submarine == null) { continue; }
|
||||
if (dockingPort.Item.Submarine.Info.IsWreck) { continue; }
|
||||
// docking ports should be shown even if defined as not, if the submarine is the same as the sonar's
|
||||
|
||||
@@ -682,7 +682,7 @@ namespace Barotrauma.Items.Components
|
||||
enterOutpostPrompt?.Close();
|
||||
}
|
||||
}
|
||||
else if (DockingSources.Any(d => d.Docked))
|
||||
else if (connectedPorts.Any(d => d.Docked))
|
||||
{
|
||||
dockingButton.Text = undockText;
|
||||
dockingContainer.Visible = true;
|
||||
@@ -819,7 +819,7 @@ namespace Barotrauma.Items.Components
|
||||
Connection dockingConnection = item.Connections?.FirstOrDefault(c => c.Name == "toggle_docking");
|
||||
if (dockingConnection != null)
|
||||
{
|
||||
connectedPorts = item.GetConnectedComponentsRecursive<DockingPort>(dockingConnection);
|
||||
connectedPorts = item.GetConnectedComponentsRecursive<DockingPort>(dockingConnection, ignoreInactiveRelays: true);
|
||||
}
|
||||
checkConnectedPortsTimer = CheckConnectedPortsInterval;
|
||||
}
|
||||
|
||||
@@ -199,6 +199,26 @@ namespace Barotrauma.Items.Components
|
||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||
{
|
||||
snapped = msg.ReadBoolean();
|
||||
|
||||
if (!snapped)
|
||||
{
|
||||
UInt16 targetId = msg.ReadUInt16();
|
||||
UInt16 sourceId = msg.ReadUInt16();
|
||||
byte limbIndex = msg.ReadByte();
|
||||
|
||||
Item target = Entity.FindEntityByID(targetId) as Item;
|
||||
if (target == null) { return; }
|
||||
var source = Entity.FindEntityByID(sourceId);
|
||||
if (source is Character sourceCharacter && limbIndex >= 0 && limbIndex < sourceCharacter.AnimController.Limbs.Length)
|
||||
{
|
||||
Limb sourceLimb = sourceCharacter.AnimController.Limbs[limbIndex];
|
||||
Attach(sourceLimb, target);
|
||||
}
|
||||
else if (source is ISpatialEntity spatialEntity)
|
||||
{
|
||||
Attach(spatialEntity, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
|
||||
@@ -135,7 +135,13 @@ namespace Barotrauma.Items.Components
|
||||
wireSprite = overrideSprite ?? defaultWireSprite;
|
||||
}
|
||||
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||
{
|
||||
Draw(spriteBatch, editing, Vector2.Zero, itemDepth);
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, Vector2 offset, float itemDepth = -1)
|
||||
{
|
||||
if (sections.Count == 0 && !IsActive || Hidden)
|
||||
{
|
||||
@@ -156,6 +162,8 @@ namespace Barotrauma.Items.Components
|
||||
drawOffset = sub.DrawPosition + sub.HiddenSubPosition;
|
||||
}
|
||||
|
||||
drawOffset += offset;
|
||||
|
||||
float baseDepth = UseSpriteDepth ? item.SpriteDepth : wireSprite.Depth;
|
||||
float depth = item.IsSelected ? 0.0f : SubEditorScreen.IsWiringMode() ? 0.02f : baseDepth + (item.ID % 100) * 0.000001f;// item.GetDrawDepth(wireSprite.Depth, wireSprite);
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -208,9 +207,9 @@ namespace Barotrauma
|
||||
"watersplash",
|
||||
(Submarine == null ? pos : pos + Submarine.Position) - Vector2.UnitY * Rand.Range(0.0f, 10.0f),
|
||||
velocity, 0, flowTargetHull);
|
||||
|
||||
if (particle != null)
|
||||
{
|
||||
if (particle.CurrentHull == null) { GameMain.ParticleManager.RemoveParticle(particle); }
|
||||
particle.Size *= Math.Min(Math.Abs(flowForce.X / 500.0f), 5.0f);
|
||||
}
|
||||
}
|
||||
@@ -238,9 +237,9 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Math.Sign(flowTargetHull.Rect.Y - rect.Y) != Math.Sign(lerpedFlowForce.Y)) return;
|
||||
if (Math.Sign(flowTargetHull.Rect.Y - rect.Y) != Math.Sign(lerpedFlowForce.Y)) { return; }
|
||||
|
||||
float particlesPerSec = open * rect.Width * 0.3f * particleAmountMultiplier;
|
||||
float particlesPerSec = Math.Max(open * rect.Width * 0.3f * particleAmountMultiplier, 20.0f);
|
||||
float emitInterval = 1.0f / particlesPerSec;
|
||||
while (particleTimer > emitInterval)
|
||||
{
|
||||
@@ -252,17 +251,21 @@ namespace Barotrauma
|
||||
if (flowTargetHull.WaterVolume < flowTargetHull.Volume * 0.95f)
|
||||
{
|
||||
var splash = GameMain.ParticleManager.CreateParticle(
|
||||
"watersplash",
|
||||
Submarine == null ? pos : pos + Submarine.Position,
|
||||
velocity, 0, FlowTargetHull);
|
||||
if (splash != null) splash.Size = splash.Size * MathHelper.Clamp(rect.Width / 50.0f, 0.8f, 4.0f);
|
||||
"watersplash",
|
||||
Submarine == null ? pos : pos + Submarine.Position,
|
||||
velocity, 0, FlowTargetHull);
|
||||
if (splash != null)
|
||||
{
|
||||
if (splash.CurrentHull == null) { GameMain.ParticleManager.RemoveParticle(splash); }
|
||||
splash.Size *= MathHelper.Clamp(rect.Width / 50.0f, 1.5f, 4.0f);
|
||||
}
|
||||
}
|
||||
if (Math.Abs(flowForce.Y) > 190.0f && Rand.Range(0.0f, 1.0f) < 0.3f && flowTargetHull.WaterVolume > flowTargetHull.Volume * 0.1f)
|
||||
{
|
||||
GameMain.ParticleManager.CreateParticle(
|
||||
"bubbles",
|
||||
Submarine == null ? pos : pos + Submarine.Position,
|
||||
flowForce / 2.0f, 0, FlowTargetHull);
|
||||
"bubbles",
|
||||
Submarine == null ? pos : pos + Submarine.Position,
|
||||
flowForce / 2.0f, 0, FlowTargetHull);
|
||||
}
|
||||
particleTimer -= emitInterval;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,19 @@ namespace Barotrauma
|
||||
|
||||
private double lastAmbientLightEditTime;
|
||||
|
||||
private float drawSurface;
|
||||
|
||||
public float DrawSurface
|
||||
{
|
||||
get { return drawSurface; }
|
||||
set
|
||||
{
|
||||
if (Math.Abs(drawSurface - value) < 0.00001f) { return; }
|
||||
drawSurface = MathHelper.Clamp(value, rect.Y - rect.Height, rect.Y);
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool SelectableInEditor
|
||||
{
|
||||
get
|
||||
@@ -138,8 +151,15 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
partial void UpdateProjSpecific(float deltaTime, Camera cam)
|
||||
partial void UpdateProjSpecific(float deltaTime, Camera _)
|
||||
{
|
||||
float waterDepth = WaterVolume / rect.Width;
|
||||
//interpolate the position of the rendered surface towards the "target surface"
|
||||
drawSurface = Math.Max(MathHelper.Lerp(
|
||||
drawSurface,
|
||||
rect.Y - rect.Height + waterDepth,
|
||||
deltaTime * 10.0f), rect.Y - rect.Height);
|
||||
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
serverUpdateDelay -= deltaTime;
|
||||
@@ -171,55 +191,56 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (!IdFreed)
|
||||
{
|
||||
if (EditWater)
|
||||
{
|
||||
Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
if (Submarine.RectContains(WorldRect, position))
|
||||
{
|
||||
if (PlayerInput.PrimaryMouseButtonHeld())
|
||||
{
|
||||
WaterVolume += 1500.0f;
|
||||
networkUpdatePending = true;
|
||||
serverUpdateDelay = 0.5f;
|
||||
}
|
||||
else if (PlayerInput.SecondaryMouseButtonHeld())
|
||||
{
|
||||
WaterVolume -= 1500.0f;
|
||||
networkUpdatePending = true;
|
||||
serverUpdateDelay = 0.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (EditFire)
|
||||
{
|
||||
Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
if (Submarine.RectContains(WorldRect, position))
|
||||
{
|
||||
if (PlayerInput.PrimaryMouseButtonClicked())
|
||||
{
|
||||
new FireSource(position, this, isNetworkMessage: true);
|
||||
networkUpdatePending = true;
|
||||
serverUpdateDelay = 0.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (waterVolume < 1.0f) { return; }
|
||||
/*if (waterVolume < 1.0f) { return; }
|
||||
for (int i = 1; i < waveY.Length - 1; i++)
|
||||
{
|
||||
float maxDelta = Math.Max(Math.Abs(rightDelta[i]), Math.Abs(leftDelta[i]));
|
||||
if (maxDelta > 1.0f && maxDelta > Rand.Range(1.0f, 10.0f))
|
||||
if (maxDelta > 0.1f && maxDelta > Rand.Range(0.1f, 10.0f))
|
||||
{
|
||||
var particlePos = new Vector2(rect.X + WaveWidth * i, surface + waveY[i]);
|
||||
if (Submarine != null) particlePos += Submarine.Position;
|
||||
if (Submarine != null) { particlePos += Submarine.Position; }
|
||||
|
||||
GameMain.ParticleManager.CreateParticle("mist",
|
||||
particlePos,
|
||||
new Vector2(0.0f, -50.0f), 0.0f, this);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
public static void UpdateCheats(float deltaTime, Camera cam)
|
||||
{
|
||||
bool primaryMouseButtonHeld = PlayerInput.PrimaryMouseButtonHeld();
|
||||
bool secondaryMouseButtonHeld = PlayerInput.SecondaryMouseButtonHeld();
|
||||
if (!primaryMouseButtonHeld && !secondaryMouseButtonHeld) { return; }
|
||||
|
||||
Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
Hull hull = FindHull(position);
|
||||
|
||||
if (hull == null || hull.IdFreed) { return; }
|
||||
if (EditWater)
|
||||
{
|
||||
if (primaryMouseButtonHeld)
|
||||
{
|
||||
hull.WaterVolume += 100000.0f * deltaTime;
|
||||
hull.networkUpdatePending = true;
|
||||
hull.serverUpdateDelay = 0.5f;
|
||||
}
|
||||
else if (secondaryMouseButtonHeld)
|
||||
{
|
||||
hull.WaterVolume -= 100000.0f * deltaTime;
|
||||
hull.networkUpdatePending = true;
|
||||
hull.serverUpdateDelay = 0.5f;
|
||||
}
|
||||
|
||||
}
|
||||
else if (EditFire)
|
||||
{
|
||||
if (primaryMouseButtonHeld)
|
||||
{
|
||||
new FireSource(position, hull, isNetworkMessage: true);
|
||||
hull.networkUpdatePending = true;
|
||||
hull.serverUpdateDelay = 0.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -194,7 +194,11 @@ namespace Barotrauma
|
||||
private void RemoveFogOfWar(Location location, bool removeFromAdjacentLocations = true)
|
||||
{
|
||||
if (location == null) { return; }
|
||||
Vector2 mapTileSize = mapTiles[0, 0].size * generationParams.MapTileScale;
|
||||
|
||||
var mapTile = generationParams.MapTiles.Values.FirstOrDefault()?.FirstOrDefault();
|
||||
if (mapTile == null) { return; }
|
||||
|
||||
Vector2 mapTileSize = mapTile.size * generationParams.MapTileScale;
|
||||
int startX = (int)Math.Max(Math.Floor(location.MapPosition.X / mapTileSize.X - 0.25f), 0);
|
||||
int startY = (int)Math.Max(Math.Floor(location.MapPosition.Y / mapTileSize.Y - 0.25f), 0);
|
||||
int endX = (int)Math.Min(Math.Floor(location.MapPosition.X / mapTileSize.X + 0.25f), mapTiles.GetLength(0));
|
||||
|
||||
@@ -768,34 +768,40 @@ namespace Barotrauma
|
||||
switch (e)
|
||||
{
|
||||
case Item item:
|
||||
{
|
||||
if (item.FlippedX && item.Prefab.CanSpriteFlipX) spriteEffects ^= SpriteEffects.FlipHorizontally;
|
||||
if (item.flippedY && item.Prefab.CanSpriteFlipY) spriteEffects ^= SpriteEffects.FlipVertically;
|
||||
break;
|
||||
}
|
||||
{
|
||||
if (item.FlippedX && item.Prefab.CanSpriteFlipX) { spriteEffects ^= SpriteEffects.FlipHorizontally; }
|
||||
if (item.flippedY && item.Prefab.CanSpriteFlipY) { spriteEffects ^= SpriteEffects.FlipVertically; }
|
||||
var wire = item.GetComponent<Wire>();
|
||||
if (wire != null && !wire.Item.body.Enabled)
|
||||
{
|
||||
wire.Draw(spriteBatch, editing: false, new Vector2(moveAmount.X, -moveAmount.Y));
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Structure structure:
|
||||
{
|
||||
if (structure.FlippedX && structure.Prefab.CanSpriteFlipX) spriteEffects ^= SpriteEffects.FlipHorizontally;
|
||||
if (structure.flippedY && structure.Prefab.CanSpriteFlipY) spriteEffects ^= SpriteEffects.FlipVertically;
|
||||
break;
|
||||
}
|
||||
{
|
||||
if (structure.FlippedX && structure.Prefab.CanSpriteFlipX) { spriteEffects ^= SpriteEffects.FlipHorizontally; }
|
||||
if (structure.flippedY && structure.Prefab.CanSpriteFlipY) { spriteEffects ^= SpriteEffects.FlipVertically; }
|
||||
break;
|
||||
}
|
||||
case WayPoint wayPoint:
|
||||
{
|
||||
Vector2 drawPos = e.WorldPosition;
|
||||
drawPos.Y = -drawPos.Y;
|
||||
drawPos += moveAmount;
|
||||
wayPoint.Draw(spriteBatch, drawPos);
|
||||
continue;
|
||||
}
|
||||
{
|
||||
Vector2 drawPos = e.WorldPosition;
|
||||
drawPos.Y = -drawPos.Y;
|
||||
drawPos += moveAmount;
|
||||
wayPoint.Draw(spriteBatch, drawPos);
|
||||
continue;
|
||||
}
|
||||
case LinkedSubmarine linkedSub:
|
||||
{
|
||||
var ma = moveAmount;
|
||||
ma.Y = -ma.Y;
|
||||
Vector2 lPos = linkedSub.Position;
|
||||
lPos += ma;
|
||||
linkedSub.Draw(spriteBatch, lPos, alpha: 0.5f);
|
||||
break;
|
||||
}
|
||||
{
|
||||
var ma = moveAmount;
|
||||
ma.Y = -ma.Y;
|
||||
Vector2 lPos = linkedSub.Position;
|
||||
lPos += ma;
|
||||
linkedSub.Draw(spriteBatch, lPos, alpha: 0.5f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
e.prefab?.DrawPlacing(spriteBatch,
|
||||
new Rectangle(e.WorldRect.Location + new Point((int)moveAmount.X, (int)-moveAmount.Y), e.WorldRect.Size), e.Scale, spriteEffects);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -91,7 +91,7 @@ namespace Barotrauma
|
||||
public void CreateSpecsWindow(GUIListBox parent, ScalableFont font, bool includeTitle = true, bool includeClass = true, bool includeDescription = false)
|
||||
{
|
||||
float leftPanelWidth = 0.6f;
|
||||
float rightPanelWidth = 0.4f;
|
||||
float rightPanelWidth = 0.4f / leftPanelWidth;
|
||||
string className = !HasTag(SubmarineTag.Shuttle) ? TextManager.Get($"submarineclass.{SubmarineClass}") : TextManager.Get("shuttle");
|
||||
|
||||
int classHeight = (int)GUI.SubHeadingFont.MeasureString(className).Y;
|
||||
@@ -110,6 +110,17 @@ namespace Barotrauma
|
||||
submarineClassText = new GUITextBlock(new RectTransform(new Point(leftPanelWidthInt, classHeight), parent.Content.RectTransform), className, textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont) { CanBeFocused = false };
|
||||
submarineClassText.RectTransform.MinSize = new Point(0, (int)submarineClassText.TextSize.Y);
|
||||
}
|
||||
|
||||
if (Price > 0)
|
||||
{
|
||||
var priceText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), parent.Content.RectTransform),
|
||||
TextManager.Get("subeditor.price"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
||||
{ CanBeFocused = false };
|
||||
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), priceText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
|
||||
TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", Price)), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
||||
{ CanBeFocused = false };
|
||||
}
|
||||
|
||||
Vector2 realWorldDimensions = Dimensions * Physics.DisplayToRealWorldRatio;
|
||||
if (realWorldDimensions != Vector2.Zero)
|
||||
{
|
||||
|
||||
@@ -2870,19 +2870,16 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void SendCampaignState()
|
||||
{
|
||||
MultiPlayerCampaign campaign = GameMain.GameSession.GameMode as MultiPlayerCampaign;
|
||||
if (campaign == null)
|
||||
if (!(GameMain.GameSession.GameMode is MultiPlayerCampaign campaign))
|
||||
{
|
||||
DebugConsole.ThrowError("Failed send campaign state to the server (no campaign active).\n" + Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.Write((byte)ClientPacketHeader.SERVER_COMMAND);
|
||||
msg.Write((UInt16)ClientPermissions.ManageCampaign);
|
||||
campaign.ClientWrite(msg);
|
||||
msg.Write((byte)ServerNetObject.END_OF_MESSAGE);
|
||||
|
||||
clientPeer.Send(msg, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
|
||||
@@ -196,6 +196,19 @@ namespace Barotrauma.Particles
|
||||
particles[particleCount] = swap;
|
||||
}
|
||||
|
||||
|
||||
public void RemoveParticle(Particle particle)
|
||||
{
|
||||
for (int i = 0; i < particleCount; i++)
|
||||
{
|
||||
if (particles[i] == particle)
|
||||
{
|
||||
RemoveParticle(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
MaxParticles = GameMain.Config.ParticleLimit;
|
||||
|
||||
+5
-1
@@ -244,7 +244,11 @@ namespace Barotrauma
|
||||
|
||||
foreach (string saveFile in saveFiles)
|
||||
{
|
||||
if (string.IsNullOrEmpty(saveFile)) { continue; }
|
||||
if (string.IsNullOrEmpty(saveFile))
|
||||
{
|
||||
DebugConsole.AddWarning("Error when updating campaign load menu: path to a save file was empty.\n" + Environment.StackTrace);
|
||||
continue;
|
||||
}
|
||||
|
||||
string fileName = saveFile;
|
||||
string subName = "";
|
||||
|
||||
+35
-24
@@ -500,29 +500,34 @@ namespace Barotrauma.CharacterEditor
|
||||
int index = 0;
|
||||
bool isSwimming = character.AnimController.ForceSelectAnimationType == AnimationType.SwimFast || character.AnimController.ForceSelectAnimationType == AnimationType.SwimSlow;
|
||||
bool isMovingFast = character.AnimController.ForceSelectAnimationType == AnimationType.Run || character.AnimController.ForceSelectAnimationType == AnimationType.SwimFast;
|
||||
if (isMovingFast)
|
||||
if (character.AnimController.CanWalk)
|
||||
{
|
||||
if (isSwimming || !character.AnimController.CanWalk)
|
||||
if (isMovingFast)
|
||||
{
|
||||
index = !character.AnimController.CanWalk ? (int)AnimationType.SwimFast : (int)AnimationType.SwimSlow;
|
||||
if (isSwimming)
|
||||
{
|
||||
index = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
index = (int)AnimationType.Walk;
|
||||
if (isSwimming)
|
||||
{
|
||||
index = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = 1;
|
||||
}
|
||||
}
|
||||
index -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isSwimming || !character.AnimController.CanWalk)
|
||||
{
|
||||
index = !character.AnimController.CanWalk ? (int)AnimationType.SwimSlow : (int)AnimationType.SwimFast;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = (int)AnimationType.Run;
|
||||
}
|
||||
index -= 1;
|
||||
index = isMovingFast ? 0 : 1;
|
||||
}
|
||||
if (animSelection.SelectedIndex != index)
|
||||
{
|
||||
@@ -536,17 +541,13 @@ namespace Barotrauma.CharacterEditor
|
||||
bool isSwimming = character.AnimController.ForceSelectAnimationType == AnimationType.SwimFast || character.AnimController.ForceSelectAnimationType == AnimationType.SwimSlow;
|
||||
if (isSwimming)
|
||||
{
|
||||
animSelection.Select((int)AnimationType.Walk - 1);
|
||||
animSelection.Select(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
animSelection.Select((int)AnimationType.SwimSlow - 1);
|
||||
animSelection.Select(2);
|
||||
}
|
||||
}
|
||||
if (PlayerInput.KeyHit(Keys.F))
|
||||
{
|
||||
SetToggle(freezeToggle, !freezeToggle.Selected);
|
||||
}
|
||||
if (PlayerInput.SecondaryMouseButtonClicked() || PlayerInput.KeyHit(Keys.Escape))
|
||||
{
|
||||
bool reset = false;
|
||||
@@ -853,6 +854,16 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
DrawRagdoll(spriteBatch, (float)deltaTime);
|
||||
}
|
||||
// Mouth
|
||||
Limb head = character.AnimController.GetLimb(LimbType.Head);
|
||||
if (head != null && character.CanEat && selectedLimbs.Contains(head))
|
||||
{
|
||||
var mouthPos = character.AnimController.GetMouthPosition();
|
||||
if (mouthPos.HasValue)
|
||||
{
|
||||
ShapeExtensions.DrawPoint(spriteBatch, SimToScreen(mouthPos.Value), GUI.Style.Red, size: 8);
|
||||
}
|
||||
}
|
||||
if (showSpritesheet)
|
||||
{
|
||||
DrawSpritesheetEditor(spriteBatch, (float)deltaTime);
|
||||
@@ -2606,13 +2617,13 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
animSelection.AddItem(AnimationType.Walk.ToString(), AnimationType.Walk);
|
||||
animSelection.AddItem(AnimationType.Run.ToString(), AnimationType.Run);
|
||||
if (character.IsHumanoid)
|
||||
{
|
||||
animSelection.AddItem(AnimationType.Crouch.ToString(), AnimationType.Crouch);
|
||||
}
|
||||
}
|
||||
animSelection.AddItem(AnimationType.SwimSlow.ToString(), AnimationType.SwimSlow);
|
||||
animSelection.AddItem(AnimationType.SwimFast.ToString(), AnimationType.SwimFast);
|
||||
if (character.AnimController.CanWalk && character.IsHumanoid)
|
||||
{
|
||||
animSelection.AddItem(AnimationType.Crouch.ToString(), AnimationType.Crouch);
|
||||
}
|
||||
if (character.AnimController.ForceSelectAnimationType == AnimationType.NotDefined)
|
||||
{
|
||||
animSelection.SelectItem(character.AnimController.CanWalk ? AnimationType.Walk : AnimationType.SwimSlow);
|
||||
|
||||
@@ -717,7 +717,7 @@ namespace Barotrauma
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void QuickStart(bool fixedSeed = false, string sub = null, float difficulty = 40, LevelGenerationParams levelGenerationParams = null)
|
||||
public void QuickStart(bool fixedSeed = false, string sub = null, float difficulty = 50, LevelGenerationParams levelGenerationParams = null)
|
||||
{
|
||||
if (fixedSeed)
|
||||
{
|
||||
@@ -1396,7 +1396,7 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ForbiddenWordFilter.IsForbidden(name, out string forbiddenWord))
|
||||
if (isPublicBox.Selected && ForbiddenWordFilter.IsForbidden(name, out string forbiddenWord))
|
||||
{
|
||||
var msgBox = new GUIMessageBox("",
|
||||
TextManager.GetWithVariables("forbiddenservernameverification", new string[] { "[forbiddenword]", "[servername]" }, new string[] { forbiddenWord, name }),
|
||||
|
||||
Reference in New Issue
Block a user