Unstable 0.1300.0.10
This commit is contained in:
@@ -215,8 +215,10 @@ namespace Barotrauma
|
||||
public Inventory Inventory;
|
||||
public readonly Item Item;
|
||||
public readonly bool IsSubSlot;
|
||||
public string Tooltip;
|
||||
public List<RichTextData> TooltipRichTextData;
|
||||
public string Tooltip { get; private set; }
|
||||
public List<RichTextData> TooltipRichTextData { get; private set;}
|
||||
|
||||
public int tooltipDisplayedCondition;
|
||||
|
||||
public SlotReference(Inventory parentInventory, VisualSlot slot, int slotIndex, bool isSubSlot, Inventory subInventory = null)
|
||||
{
|
||||
@@ -227,13 +229,26 @@ namespace Barotrauma
|
||||
IsSubSlot = isSubSlot;
|
||||
Item = ParentInventory.GetItemAt(slotIndex);
|
||||
|
||||
IEnumerable<Item> itemsInSlot = null;
|
||||
if (parentInventory != null && Item != null)
|
||||
{
|
||||
itemsInSlot = parentInventory.GetItemsAt(slotIndex);
|
||||
}
|
||||
RefreshTooltip();
|
||||
}
|
||||
|
||||
TooltipRichTextData = RichTextData.GetRichTextData(GetTooltip(Item, itemsInSlot), out Tooltip);
|
||||
public bool TooltipNeedsRefresh()
|
||||
{
|
||||
if (Item == null) { return false; }
|
||||
return (int)Item.ConditionPercentage != tooltipDisplayedCondition;
|
||||
}
|
||||
|
||||
public void RefreshTooltip()
|
||||
{
|
||||
if (Item == null) { return; }
|
||||
IEnumerable<Item> itemsInSlot = null;
|
||||
if (ParentInventory != null && Item != null)
|
||||
{
|
||||
itemsInSlot = ParentInventory.GetItemsAt(SlotIndex);
|
||||
}
|
||||
TooltipRichTextData = RichTextData.GetRichTextData(GetTooltip(Item, itemsInSlot), out string newTooltip);
|
||||
Tooltip = newTooltip;
|
||||
tooltipDisplayedCondition = (int)Item.ConditionPercentage;
|
||||
}
|
||||
|
||||
private string GetTooltip(Item item, IEnumerable<Item> itemsInSlot)
|
||||
@@ -1370,6 +1385,10 @@ namespace Barotrauma
|
||||
{
|
||||
Rectangle slotRect = selectedSlot.Slot.Rect;
|
||||
slotRect.Location += selectedSlot.Slot.DrawOffset.ToPoint();
|
||||
if (selectedSlot.TooltipNeedsRefresh())
|
||||
{
|
||||
selectedSlot.RefreshTooltip();
|
||||
}
|
||||
DrawToolTip(spriteBatch, selectedSlot.Tooltip, slotRect, selectedSlot.TooltipRichTextData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3288,9 +3288,12 @@ namespace Barotrauma.Networking
|
||||
if (respawnManager != null)
|
||||
{
|
||||
string respawnText = string.Empty;
|
||||
float textScale = 1.0f;
|
||||
Color textColor = Color.White;
|
||||
bool canChooseRespawn = GameMain.GameSession.GameMode is CampaignMode && Character.Controlled == null && Level.Loaded?.Type != LevelData.LevelType.Outpost;
|
||||
bool canChooseRespawn =
|
||||
GameMain.GameSession.GameMode is CampaignMode &&
|
||||
Character.Controlled == null &&
|
||||
Level.Loaded?.Type != LevelData.LevelType.Outpost &&
|
||||
(characterInfo == null || HasSpawned);
|
||||
if (respawnManager.CurrentState == RespawnManager.State.Waiting &&
|
||||
respawnManager.RespawnCountdownStarted)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.1300.0.9</Version>
|
||||
<Version>0.1300.0.10</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.1300.0.9</Version>
|
||||
<Version>0.1300.0.10</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma</Product>
|
||||
<Version>0.1300.0.9</Version>
|
||||
<Version>0.1300.0.10</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>Barotrauma</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.1300.0.9</Version>
|
||||
<Version>0.1300.0.10</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.1300.0.9</Version>
|
||||
<Version>0.1300.0.10</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -1333,15 +1333,23 @@ namespace Barotrauma.Networking
|
||||
else if (mpCampaign != null)
|
||||
{
|
||||
var availableTransition = mpCampaign.GetAvailableTransition(out _, out _);
|
||||
//don't force location if we've teleported
|
||||
bool forceLocation = !mpCampaign.Map.AllowDebugTeleport || mpCampaign.Map.CurrentLocation == Level.Loaded.StartLocation;
|
||||
switch (availableTransition)
|
||||
{
|
||||
case CampaignMode.TransitionType.ReturnToPreviousEmptyLocation:
|
||||
mpCampaign.Map.SelectLocation(
|
||||
mpCampaign.Map.CurrentLocation.Connections.Find(c => c.LevelData == Level.Loaded?.LevelData).OtherLocation(mpCampaign.Map.CurrentLocation));
|
||||
if (forceLocation)
|
||||
{
|
||||
mpCampaign.Map.SelectLocation(
|
||||
mpCampaign.Map.CurrentLocation.Connections.Find(c => c.LevelData == Level.Loaded?.LevelData).OtherLocation(mpCampaign.Map.CurrentLocation));
|
||||
}
|
||||
mpCampaign.LoadNewLevel();
|
||||
break;
|
||||
case CampaignMode.TransitionType.ProgressToNextEmptyLocation:
|
||||
mpCampaign.Map.SetLocation(mpCampaign.Map.Locations.IndexOf(Level.Loaded.EndLocation));
|
||||
if (forceLocation)
|
||||
{
|
||||
mpCampaign.Map.SetLocation(mpCampaign.Map.Locations.IndexOf(Level.Loaded.EndLocation));
|
||||
}
|
||||
mpCampaign.LoadNewLevel();
|
||||
break;
|
||||
case CampaignMode.TransitionType.None:
|
||||
|
||||
@@ -76,9 +76,14 @@ namespace Barotrauma.Networking
|
||||
return botsToRespawn;
|
||||
}
|
||||
|
||||
private bool RespawnPending()
|
||||
private bool ShouldStartRespawnCountdown()
|
||||
{
|
||||
int characterToRespawnCount = GetClientsToRespawn().Count();
|
||||
return ShouldStartRespawnCountdown(characterToRespawnCount);
|
||||
}
|
||||
|
||||
private bool ShouldStartRespawnCountdown(int characterToRespawnCount)
|
||||
{
|
||||
int totalCharacterCount = GameMain.Server.ConnectedClients.Count;
|
||||
return (float)characterToRespawnCount >= Math.Max((float)totalCharacterCount * GameMain.Server.ServerSettings.MinRespawnRatio, 1.0f);
|
||||
}
|
||||
@@ -90,12 +95,27 @@ namespace Barotrauma.Networking
|
||||
RespawnShuttle.Velocity = Vector2.Zero;
|
||||
}
|
||||
|
||||
bool respawnPending = RespawnPending();
|
||||
if (respawnPending != RespawnCountdownStarted)
|
||||
int clientsToRespawn = GetClientsToRespawn().Count();
|
||||
if (RespawnCountdownStarted)
|
||||
{
|
||||
RespawnCountdownStarted = respawnPending;
|
||||
RespawnTime = DateTime.Now + new TimeSpan(0, 0, 0, 0, (int)(GameMain.Server.ServerSettings.RespawnInterval * 1000.0f));
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
if (clientsToRespawn == 0)
|
||||
{
|
||||
RespawnCountdownStarted = false;
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool shouldStartCountdown = ShouldStartRespawnCountdown(clientsToRespawn);
|
||||
if (shouldStartCountdown)
|
||||
{
|
||||
RespawnCountdownStarted = true;
|
||||
if (RespawnTime < DateTime.Now)
|
||||
{
|
||||
RespawnTime = DateTime.Now + new TimeSpan(0, 0, 0, 0, (int)(GameMain.Server.ServerSettings.RespawnInterval * 1000.0f));
|
||||
}
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (RespawnCountdownStarted && DateTime.Now > RespawnTime)
|
||||
@@ -198,7 +218,7 @@ namespace Barotrauma.Networking
|
||||
ReturnTime = DateTime.Now;
|
||||
ReturnCountdownStarted = true;
|
||||
}
|
||||
else if (!RespawnPending())
|
||||
else if (!ShouldStartRespawnCountdown())
|
||||
{
|
||||
//don't start counting down until someone else needs to respawn
|
||||
ReturnTime = DateTime.Now + new TimeSpan(0, 0, 0, 0, milliseconds: (int)(maxTransportTime * 1000));
|
||||
@@ -340,7 +360,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
var characterData = campaign?.GetClientCharacterData(clients[i]);
|
||||
if (characterData != null && Level.Loaded?.Type != LevelData.LevelType.Outpost)
|
||||
if (characterData != null && Level.Loaded?.Type != LevelData.LevelType.Outpost && characterData.HasSpawned)
|
||||
{
|
||||
var respawnPenaltyAffliction = AfflictionPrefab.List.FirstOrDefault(a => a.AfflictionType.Equals("respawnpenalty", StringComparison.OrdinalIgnoreCase));
|
||||
if (respawnPenaltyAffliction != null)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Barotrauma</RootNamespace>
|
||||
<Authors>FakeFish, Undertow Games</Authors>
|
||||
<Product>Barotrauma Dedicated Server</Product>
|
||||
<Version>0.1300.0.9</Version>
|
||||
<Version>0.1300.0.10</Version>
|
||||
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<AssemblyName>DedicatedServer</AssemblyName>
|
||||
|
||||
@@ -267,7 +267,7 @@ namespace Barotrauma
|
||||
|
||||
public void UnequipEmptyItems(Item parentItem, bool avoidDroppingInSea = true) => UnequipEmptyItems(Character, parentItem, avoidDroppingInSea);
|
||||
|
||||
public void UnequipContainedItems(Item parentItem, Func<Item, bool> predicate, bool avoidDroppingInSea = true) => UnequipContainedItems(Character, parentItem, predicate, avoidDroppingInSea);
|
||||
public void UnequipContainedItems(Item parentItem, Func<Item, bool> predicate = null, bool avoidDroppingInSea = true) => UnequipContainedItems(Character, parentItem, predicate, avoidDroppingInSea);
|
||||
|
||||
public static void UnequipEmptyItems(Character character, Item parentItem, bool avoidDroppingInSea = true) => UnequipContainedItems(character, parentItem, it => it.Condition <= 0, avoidDroppingInSea);
|
||||
|
||||
@@ -275,14 +275,14 @@ namespace Barotrauma
|
||||
{
|
||||
var inventory = parentItem.OwnInventory;
|
||||
if (inventory == null) { return; }
|
||||
if (inventory.AllItems.Any(predicate))
|
||||
if (predicate == null || inventory.AllItems.Any(predicate))
|
||||
{
|
||||
foreach (Item containedItem in inventory.AllItemsMod)
|
||||
{
|
||||
if (containedItem == null) { continue; }
|
||||
if (predicate(containedItem))
|
||||
if (predicate == null || predicate(containedItem))
|
||||
{
|
||||
if (character.Submarine == null && avoidDroppingInSea)
|
||||
if (character.Submarine != Submarine.MainSub && avoidDroppingInSea)
|
||||
{
|
||||
// If we are outside of main sub, try to put the item in the inventory instead dropping it in the sea.
|
||||
if (character.Inventory.TryPutItem(containedItem, character, CharacterInventory.anySlot))
|
||||
|
||||
@@ -186,11 +186,14 @@ namespace Barotrauma
|
||||
{
|
||||
findSafety.Priority = 0;
|
||||
}
|
||||
distanceTimer -= deltaTime;
|
||||
if (distanceTimer < 0)
|
||||
if (!character.IsOnPlayerTeam && !objectiveManager.IsCurrentObjective<AIObjectiveFightIntruders>())
|
||||
{
|
||||
distanceTimer = distanceCheckInterval;
|
||||
sqrDistance = Vector2.DistanceSquared(character.WorldPosition, Enemy.WorldPosition);
|
||||
distanceTimer -= deltaTime;
|
||||
if (distanceTimer < 0)
|
||||
{
|
||||
distanceTimer = distanceCheckInterval;
|
||||
sqrDistance = Vector2.DistanceSquared(character.WorldPosition, Enemy.WorldPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ namespace Barotrauma
|
||||
public float ConditionLevel { get; set; } = 1;
|
||||
public bool Equip { get; set; }
|
||||
public bool RemoveEmpty { get; set; } = true;
|
||||
public bool RemoveExisting { get; set; }
|
||||
|
||||
public bool MoveWholeStack { get; set; }
|
||||
|
||||
@@ -105,7 +106,11 @@ namespace Barotrauma
|
||||
}
|
||||
if (character.CanInteractWith(container.Item, checkLinked: false))
|
||||
{
|
||||
if (RemoveEmpty)
|
||||
if (RemoveExisting)
|
||||
{
|
||||
HumanAIController.UnequipContainedItems(container.Item);
|
||||
}
|
||||
else if (RemoveEmpty)
|
||||
{
|
||||
HumanAIController.UnequipEmptyItems(container.Item);
|
||||
}
|
||||
@@ -128,7 +133,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ItemToContain.ParentInventory == character.Inventory)
|
||||
if (ItemToContain.ParentInventory == character.Inventory && character.Submarine == Submarine.MainSub)
|
||||
{
|
||||
ItemToContain.Drop(character);
|
||||
}
|
||||
|
||||
@@ -60,11 +60,12 @@ namespace Barotrauma
|
||||
{
|
||||
HumanAIController.UnequipContainedItems(targetItem, it => !it.HasTag("oxygensource"));
|
||||
HumanAIController.UnequipEmptyItems(targetItem);
|
||||
float min = character.Submarine == null ? 0.01f : MIN_OXYGEN;
|
||||
// Seek oxygen that has at least 10% condition left, if we are inside a friendly sub.
|
||||
// The margin helps us to survive, because we might need some oxygen before we can find more oxygen.
|
||||
// When we are venturing outside of our sub, let's just suppose that we have enough oxygen with us and optimize it so that we don't keep switching off half used tanks.
|
||||
float min = character.Submarine != Submarine.MainSub ? 0.01f : MIN_OXYGEN;
|
||||
if (targetItem.OwnInventory != null && targetItem.OwnInventory.AllItems.None(it => it != null && it.HasTag(OXYGEN_SOURCE) && it.Condition > min))
|
||||
{
|
||||
// No valid oxygen source loaded.
|
||||
// Seek oxygen that has at least 10% condition left.
|
||||
TryAddSubObjective(ref getOxygen, () =>
|
||||
{
|
||||
if (character.IsOnPlayerTeam)
|
||||
@@ -82,20 +83,22 @@ namespace Barotrauma
|
||||
{
|
||||
AllowToFindDivingGear = false,
|
||||
AllowDangerousPressure = true,
|
||||
ConditionLevel = MIN_OXYGEN
|
||||
ConditionLevel = MIN_OXYGEN,
|
||||
RemoveExisting = true
|
||||
};
|
||||
},
|
||||
onAbandon: () =>
|
||||
{
|
||||
getOxygen = null;
|
||||
int remainingTanks = ReportOxygenTankCount();
|
||||
// Try to seek any oxygen sources.
|
||||
// Try to seek any oxygen sources, even if they have minimal amount of oxygen.
|
||||
TryAddSubObjective(ref getOxygen, () =>
|
||||
{
|
||||
return new AIObjectiveContainItem(character, OXYGEN_SOURCE, targetItem.GetComponent<ItemContainer>(), objectiveManager, spawnItemIfNotFound: character.TeamID == CharacterTeamType.FriendlyNPC)
|
||||
{
|
||||
AllowToFindDivingGear = false,
|
||||
AllowDangerousPressure = true
|
||||
AllowDangerousPressure = true,
|
||||
RemoveExisting = true
|
||||
};
|
||||
},
|
||||
onAbandon: () =>
|
||||
|
||||
@@ -50,7 +50,10 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HumanAIController.NeedsDivingGear(character.CurrentHull, out _) && !HumanAIController.HasDivingGear(character, conditionPercentage: AIObjectiveFindDivingGear.MIN_OXYGEN))
|
||||
if (HumanAIController.NeedsDivingGear(character.CurrentHull, out bool needsSuit) &&
|
||||
(needsSuit ?
|
||||
!HumanAIController.HasDivingSuit(character, conditionPercentage: AIObjectiveFindDivingGear.MIN_OXYGEN) :
|
||||
!HumanAIController.HasDivingMask(character, conditionPercentage: AIObjectiveFindDivingGear.MIN_OXYGEN)))
|
||||
{
|
||||
Priority = 100;
|
||||
}
|
||||
|
||||
@@ -279,9 +279,13 @@ namespace Barotrauma
|
||||
if (character.TeamID == CharacterTeamType.FriendlyNPC != item.SpawnedInOutpost) { continue; }
|
||||
}
|
||||
if (!CheckItem(item)) { continue; }
|
||||
if (ignoredContainerIdentifiers != null && item.Container != null)
|
||||
if (item.Container != null)
|
||||
{
|
||||
if (ignoredContainerIdentifiers.Contains(item.ContainerIdentifier)) { continue; }
|
||||
if (item.Container.HasTag("donttakeitems")) { continue; }
|
||||
if (ignoredContainerIdentifiers != null)
|
||||
{
|
||||
if (ignoredContainerIdentifiers.Contains(item.ContainerIdentifier)) { continue; }
|
||||
}
|
||||
}
|
||||
// Don't allow going into another sub, unless it's connected and of the same team and type.
|
||||
if (!character.Submarine.IsEntityFoundOnThisSub(item, includingConnectedSubs: true)) { continue; }
|
||||
@@ -423,7 +427,7 @@ namespace Barotrauma
|
||||
// TODO: Use the item name as the variable here.
|
||||
if (character.IsOnPlayerTeam && objectiveManager.CurrentOrder == objectiveManager.CurrentObjective)
|
||||
{
|
||||
string msg = TextManager.Get("dialogcannotreachtarget", true);
|
||||
string msg = TextManager.Get("dialogcannotfinditem", true);
|
||||
if (msg != null)
|
||||
{
|
||||
character.Speak(msg, identifier: "dialogcannotfinditem", minDurationBetweenSimilar: 20.0f);
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace Barotrauma
|
||||
public override bool CanBePut(Item item, int i)
|
||||
{
|
||||
return
|
||||
base.CanBePut(item, i) && item.AllowedSlots.Contains(SlotTypes[i]) &&
|
||||
base.CanBePut(item, i) && item.AllowedSlots.Any(s => s.HasFlag(SlotTypes[i])) &&
|
||||
(SlotTypes[i] == InvSlotType.Any || slots[i].ItemCount < 1);
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ namespace Barotrauma
|
||||
if (allowedSlots != null && !allowedSlots.Contains(InvSlotType.Any))
|
||||
{
|
||||
int slot = FindLimbSlot(allowedSlots.First());
|
||||
if (slot > -1 && slots[slot].Items.Any(it => it != item) && slots[slot].First().Prefab.AllowDroppingOnSwap)
|
||||
if (slot > -1 && slots[slot].Items.Any(it => it != item) && slots[slot].First().AllowDroppingOnSwapWith(item))
|
||||
{
|
||||
foreach (Item existingItem in slots[slot].Items.ToList())
|
||||
{
|
||||
|
||||
@@ -12,11 +12,11 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Steering : Powered, IServerSerializable, IClientSerializable
|
||||
{
|
||||
public const float AutopilotMinDistToPathNode = 30.0f;
|
||||
|
||||
private const float AutopilotRayCastInterval = 0.5f;
|
||||
private const float RecalculatePathInterval = 5.0f;
|
||||
|
||||
private const float AutopilotMinDistToPathNode = 30.0f;
|
||||
|
||||
private const float AutoPilotSteeringLerp = 0.1f;
|
||||
|
||||
private const float AutoPilotMaxSpeed = 0.5f;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Barotrauma.Networking;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
@@ -31,6 +32,19 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can be used to display messages on the terminal via status effects
|
||||
/// </summary>
|
||||
public string ShowMessage
|
||||
{
|
||||
get { return messageHistory.Count == 0 ? string.Empty : messageHistory.Last(); }
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value)) { return; }
|
||||
ShowOnDisplay(value);
|
||||
}
|
||||
}
|
||||
|
||||
private string OutputValue { get; set; }
|
||||
|
||||
public Terminal(Item item, XElement element)
|
||||
|
||||
@@ -659,12 +659,12 @@ namespace Barotrauma
|
||||
else
|
||||
{
|
||||
swapSuccessful =
|
||||
(existingItems.All(existingItem => otherInventory.TryPutItem(existingItem, otherIndex, false, false, user, createNetworkEvent)) ||
|
||||
existingItems.Count == 1 && otherInventory.TryPutItem(existingItems.First(),user, CharacterInventory.anySlot, createNetworkEvent))
|
||||
(existingItems.All(existingItem => otherInventory.TryPutItem(existingItem, otherIndex, false, false, user, createNetworkEvent)) ||
|
||||
existingItems.Count == 1 && otherInventory.TryPutItem(existingItems.First(), user, CharacterInventory.anySlot, createNetworkEvent))
|
||||
&&
|
||||
stackedItems.Distinct().All(stackedItem => TryPutItem(stackedItem, index, false, false, user, createNetworkEvent));
|
||||
|
||||
if (!swapSuccessful && existingItems.Count == 1 && existingItems[0].Prefab.AllowDroppingOnSwap)
|
||||
if (!swapSuccessful && existingItems.Count == 1 && existingItems[0].AllowDroppingOnSwapWith(item))
|
||||
{
|
||||
existingItems[0].Drop(user, createNetworkEvent);
|
||||
swapSuccessful = stackedItems.Distinct().Any(stackedItem => TryPutItem(stackedItem, index, false, false, user, createNetworkEvent));
|
||||
|
||||
@@ -1102,6 +1102,27 @@ namespace Barotrauma
|
||||
if (findNewHull) { FindHull(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is dropping the item allowed when trying to swap it with the other item
|
||||
/// </summary>
|
||||
public bool AllowDroppingOnSwapWith(Item otherItem)
|
||||
{
|
||||
if (!Prefab.AllowDroppingOnSwap || otherItem == null) { return false; }
|
||||
if (Prefab.AllowDroppingOnSwapWith.Any())
|
||||
{
|
||||
foreach (string tagOrIdentifier in Prefab.AllowDroppingOnSwapWith)
|
||||
{
|
||||
if (otherItem.prefab.Identifier.Equals(tagOrIdentifier, StringComparison.OrdinalIgnoreCase)) { return true; }
|
||||
if (otherItem.HasTag(tagOrIdentifier)) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetActiveSprite()
|
||||
{
|
||||
SetActiveSpriteProjSpecific();
|
||||
|
||||
@@ -517,6 +517,12 @@ namespace Barotrauma
|
||||
[Serialize(false, false)]
|
||||
public bool AllowDroppingOnSwap { get; private set; }
|
||||
|
||||
private readonly HashSet<string> allowDroppingOnSwapWith = new HashSet<string>();
|
||||
public IEnumerable<string> AllowDroppingOnSwapWith
|
||||
{
|
||||
get { return allowDroppingOnSwapWith; }
|
||||
}
|
||||
|
||||
public Vector2 Size => size;
|
||||
|
||||
public bool CanBeBought => (DefaultPrice != null && DefaultPrice.CanBeBought) || (locationPrices != null && locationPrices.Any(p => p.Value.CanBeBought));
|
||||
@@ -657,7 +663,7 @@ namespace Barotrauma
|
||||
{
|
||||
category = MapEntityCategory.Misc;
|
||||
}
|
||||
Category = category;
|
||||
Category = category;
|
||||
|
||||
var parentType = element.Parent?.GetAttributeString("itemtype", "") ?? string.Empty;
|
||||
|
||||
@@ -695,7 +701,7 @@ namespace Barotrauma
|
||||
identifier = GenerateLegacyIdentifier(originalName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (string.Equals(parentType, "wrecked", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
@@ -703,7 +709,7 @@ namespace Barotrauma
|
||||
name = TextManager.GetWithVariable("wreckeditemformat", "[name]", name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
DebugConsole.ThrowError($"Unnamed item ({identifier}) in {filePath}!");
|
||||
@@ -715,11 +721,11 @@ namespace Barotrauma
|
||||
(element.GetAttributeStringArray("aliases", null, convertToLowerInvariant: true) ??
|
||||
element.GetAttributeStringArray("Aliases", new string[0], convertToLowerInvariant: true));
|
||||
Aliases.Add(originalName.ToLowerInvariant());
|
||||
|
||||
Triggers = new List<Rectangle>();
|
||||
DeconstructItems = new List<DeconstructItem>();
|
||||
FabricationRecipes = new List<FabricationRecipe>();
|
||||
DeconstructTime = 1.0f;
|
||||
|
||||
Triggers = new List<Rectangle>();
|
||||
DeconstructItems = new List<DeconstructItem>();
|
||||
FabricationRecipes = new List<FabricationRecipe>();
|
||||
DeconstructTime = 1.0f;
|
||||
|
||||
if (element.Attribute("allowasextracargo") != null)
|
||||
{
|
||||
@@ -755,6 +761,16 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
var allowDroppingOnSwapWith = element.GetAttributeStringArray("allowdroppingonswapwith", new string[0]);
|
||||
if (allowDroppingOnSwapWith.Any())
|
||||
{
|
||||
AllowDroppingOnSwap = true;
|
||||
foreach (string tag in allowDroppingOnSwapWith)
|
||||
{
|
||||
this.allowDroppingOnSwapWith.Add(tag);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
|
||||
@@ -203,9 +203,9 @@ namespace Barotrauma
|
||||
public void AutoOrient()
|
||||
{
|
||||
Vector2 searchPosLeft = new Vector2(rect.X, rect.Y - rect.Height / 2);
|
||||
Hull hullLeft = Hull.FindHullOld(searchPosLeft, null, false);
|
||||
Hull hullLeft = Hull.FindHullUnoptimized(searchPosLeft, null, false);
|
||||
Vector2 searchPosRight = new Vector2(rect.Right, rect.Y - rect.Height / 2);
|
||||
Hull hullRight = Hull.FindHullOld(searchPosRight, null, false);
|
||||
Hull hullRight = Hull.FindHullUnoptimized(searchPosRight, null, false);
|
||||
|
||||
if (hullLeft != null && hullRight != null && hullLeft != hullRight)
|
||||
{
|
||||
@@ -214,9 +214,9 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
Vector2 searchPosTop = new Vector2(rect.Center.X, rect.Y);
|
||||
Hull hullTop = Hull.FindHullOld(searchPosTop, null, false);
|
||||
Hull hullTop = Hull.FindHullUnoptimized(searchPosTop, null, false);
|
||||
Vector2 searchPosBottom = new Vector2(rect.Center.X, rect.Y - rect.Height);
|
||||
Hull hullBottom = Hull.FindHullOld(searchPosBottom, null, false);
|
||||
Hull hullBottom = Hull.FindHullUnoptimized(searchPosBottom, null, false);
|
||||
|
||||
if (hullTop != null && hullBottom != null && hullTop != hullBottom)
|
||||
{
|
||||
@@ -261,8 +261,8 @@ namespace Barotrauma
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
hulls[i] = Hull.FindHullOld(searchPos[i], null, false);
|
||||
if (hulls[i] == null) hulls[i] = Hull.FindHullOld(searchPos[i], null, false, true);
|
||||
hulls[i] = Hull.FindHullUnoptimized(searchPos[i], null, false);
|
||||
if (hulls[i] == null) hulls[i] = Hull.FindHullUnoptimized(searchPos[i], null, false, true);
|
||||
}
|
||||
|
||||
if (hulls[0] == null && hulls[1] == null) { return; }
|
||||
|
||||
@@ -990,7 +990,13 @@ namespace Barotrauma
|
||||
return float.MaxValue;
|
||||
}
|
||||
|
||||
//returns the water block which contains the point (or null if it isn't inside any)
|
||||
/// <summary>
|
||||
/// Returns the hull which contains the point (or null if it isn't inside any)
|
||||
/// </summary>
|
||||
/// <param name="position">The position to check</param>
|
||||
/// <param name="guess">This hull is checked first: if the current hull is known, this can be used as an optimization</param>
|
||||
/// <param name="useWorldCoordinates">Should world coordinates or the sub's local coordinates be used?</param>
|
||||
/// <param name="inclusive">Does being exactly at the edge of the hull count as being inside?</param>
|
||||
public static Hull FindHull(Vector2 position, Hull guess = null, bool useWorldCoordinates = true, bool inclusive = true)
|
||||
{
|
||||
if (EntityGrids == null) return null;
|
||||
@@ -1038,20 +1044,19 @@ namespace Barotrauma
|
||||
return null;
|
||||
}
|
||||
|
||||
//returns the water block which contains the point (or null if it isn't inside any)
|
||||
public static Hull FindHullOld(Vector2 position, Hull guess = null, bool useWorldCoordinates = true, bool inclusive = true)
|
||||
/// <summary>
|
||||
/// Returns the hull which contains the point (or null if it isn't inside any). The difference to FindHull is that this method goes through all hulls without trying
|
||||
/// to first find the sub the point is inside and checking the hulls in that sub.
|
||||
/// = This is slower, use with caution in situations where the sub's extents or hulls may have changed after it was loaded.
|
||||
/// </summary>
|
||||
public static Hull FindHullUnoptimized(Vector2 position, Hull guess = null, bool useWorldCoordinates = true, bool inclusive = true)
|
||||
{
|
||||
return FindHullOld(position, hullList, guess, useWorldCoordinates, inclusive);
|
||||
}
|
||||
|
||||
public static Hull FindHullOld(Vector2 position, List<Hull> hulls, Hull guess = null, bool useWorldCoordinates = true, bool inclusive = true)
|
||||
{
|
||||
if (guess != null && hulls.Contains(guess))
|
||||
if (guess != null && hullList.Contains(guess))
|
||||
{
|
||||
if (Submarine.RectContains(useWorldCoordinates ? guess.WorldRect : guess.rect, position, inclusive)) return guess;
|
||||
}
|
||||
|
||||
foreach (Hull hull in hulls)
|
||||
foreach (Hull hull in hullList)
|
||||
{
|
||||
if (Submarine.RectContains(useWorldCoordinates ? hull.WorldRect : hull.rect, position, inclusive)) return hull;
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ namespace Barotrauma
|
||||
|
||||
public class AbyssIsland
|
||||
{
|
||||
public readonly Rectangle Area;
|
||||
public Rectangle Area;
|
||||
public readonly List<VoronoiCell> Cells;
|
||||
|
||||
public AbyssIsland(Rectangle area, List<VoronoiCell> cells)
|
||||
@@ -844,6 +844,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
foreach (AbyssIsland island in AbyssIslands)
|
||||
{
|
||||
island.Area = new Rectangle(borders.Width - island.Area.Right, island.Area.Y, island.Area.Width, island.Area.Height);
|
||||
}
|
||||
|
||||
foreach (Cave cave in Caves)
|
||||
{
|
||||
cave.Area = new Rectangle(borders.Width - cave.Area.Right, cave.Area.Y, cave.Area.Width, cave.Area.Height);
|
||||
@@ -1328,7 +1333,6 @@ namespace Barotrauma
|
||||
for (int i = 0; i < tunnel.Cells.Count; i++)
|
||||
{
|
||||
tunnel.Cells[i].CellType = CellType.Path;
|
||||
|
||||
var newWaypoint = new WayPoint(new Rectangle((int)tunnel.Cells[i].Site.Coord.X, (int)tunnel.Cells[i].Center.Y, 10, 10), null)
|
||||
{
|
||||
Tunnel = tunnel
|
||||
@@ -1385,8 +1389,23 @@ namespace Barotrauma
|
||||
ConvertUnits.ToSimUnits(wayPoint.WorldPosition),
|
||||
ConvertUnits.ToSimUnits(closestWaypoint.WorldPosition), collisionCategory: Physics.CollisionLevel | Physics.CollisionWall) == null)
|
||||
{
|
||||
wayPoint.linkedTo.Add(closestWaypoint);
|
||||
closestWaypoint.linkedTo.Add(wayPoint);
|
||||
Vector2 diff = closestWaypoint.WorldPosition - wayPoint.WorldPosition;
|
||||
float dist = diff.Length();
|
||||
float step = ConvertUnits.ToDisplayUnits(Steering.AutopilotMinDistToPathNode) * 0.8f;
|
||||
|
||||
WayPoint prevWaypoint = wayPoint;
|
||||
for (float x = step; x < dist - step; x += step)
|
||||
{
|
||||
var newWaypoint = new WayPoint(wayPoint.WorldPosition + (diff / dist * x), SpawnType.Path, submarine: null)
|
||||
{
|
||||
Tunnel = tunnel
|
||||
};
|
||||
prevWaypoint.linkedTo.Add(newWaypoint);
|
||||
newWaypoint.linkedTo.Add(prevWaypoint);
|
||||
prevWaypoint = newWaypoint;
|
||||
}
|
||||
prevWaypoint.linkedTo.Add(closestWaypoint);
|
||||
closestWaypoint.linkedTo.Add(prevWaypoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1104,8 +1104,35 @@ namespace Barotrauma
|
||||
DebugConsole.ThrowError($"Failed to connect waypoints between outpost modules. No waypoint in the {GetOpposingGapPosition(module.ThisGapPosition).ToString().ToLower()} gap of the module \"{module.PreviousModule.Info.Name}\".");
|
||||
continue;
|
||||
}
|
||||
startWaypoint.linkedTo.Add(endWaypoint);
|
||||
endWaypoint.linkedTo.Add(startWaypoint);
|
||||
|
||||
if (startWaypoint.WorldPosition.X > endWaypoint.WorldPosition.X)
|
||||
{
|
||||
var temp = startWaypoint;
|
||||
startWaypoint = endWaypoint;
|
||||
endWaypoint = temp;
|
||||
}
|
||||
|
||||
if (hallwayLength > 100 && isHorizontal)
|
||||
{
|
||||
WayPoint prevWayPoint = startWaypoint;
|
||||
for (float x = leftHull.Rect.Right + 50; x < rightHull.Rect.X - 50; x += 100.0f)
|
||||
{
|
||||
var newWayPoint = new WayPoint(new Vector2(x, hullBounds.Y + 110.0f), SpawnType.Path, sub);
|
||||
prevWayPoint.linkedTo.Add(newWayPoint);
|
||||
newWayPoint.linkedTo.Add(prevWayPoint);
|
||||
prevWayPoint = newWayPoint;
|
||||
}
|
||||
if (prevWayPoint != null)
|
||||
{
|
||||
prevWayPoint.linkedTo.Add(endWaypoint);
|
||||
endWaypoint.linkedTo.Add(prevWayPoint);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
startWaypoint.linkedTo.Add(endWaypoint);
|
||||
endWaypoint.linkedTo.Add(startWaypoint);
|
||||
}
|
||||
|
||||
WayPoint closestWaypoint = null;
|
||||
float closestDistSqr = 30.0f * 30.0f;
|
||||
|
||||
@@ -786,6 +786,13 @@ namespace Barotrauma
|
||||
public void FindHull()
|
||||
{
|
||||
CurrentHull = Hull.FindHull(WorldPosition, CurrentHull);
|
||||
#if CLIENT
|
||||
//we may not be able to find the hull with the optimized method in the sub editor if new hulls have been added, use the unoptimized method
|
||||
if (Screen.Selected == GameMain.SubEditorScreen)
|
||||
{
|
||||
CurrentHull ??= Hull.FindHullUnoptimized(WorldPosition);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void OnMapLoaded()
|
||||
|
||||
Binary file not shown.
@@ -1,3 +1,31 @@
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.1300.0.10 (unstable)
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
Changes:
|
||||
- Only allow dropping a diving suit when trying to swap it with another suit, not when trying to swap it with for example body armor (#5519).
|
||||
- Don't show the "respawn with penalty" tickbox when spawning as a returning player.
|
||||
- Made abandoned outposts a bit more common.
|
||||
- Once the respawn countdown starts, it doesn't stop even if some players change their mind and decide to wait for the next round as long as there's at least one player waiting to respawn.
|
||||
|
||||
Fixes:
|
||||
- Fixed logbooks being empty in the wreck salvage missions.
|
||||
- Addressed the lag spikes occasionally caused by Spineling's spikes when they hit/get stuck to something.
|
||||
- Fixed bots throw full oxygen tanks away when they are not in the main sub (e.g. in wrecks), resulting in suffocation because they can't use the oxygen (#5525).
|
||||
- Fixed bots waiting for the oxygen tanks to be entirely drained before swapping new tanks in (#5524).
|
||||
- Fixed water particle effects not showing up when water flows between certain rooms in Remora.
|
||||
- Fixed misaligned trigger area on Remora's smaller engine (#5514).
|
||||
- Fixed players who spawn as their previous character mid-round always getting the Reaper's Tax affliction in mp campaign (#5517).
|
||||
- Fixed resizeable outpost hallway modules not having waypoints and thus causing navigation issues.
|
||||
- Fixed bots abandoning the combat objectives when the target is farther than 2000px away. The behavior was only intended for non-friendly npcs, like bandits or outpost security.
|
||||
- Fixed items that are being held in both hands (e.g. underwater scooter) getting duffelbagged between campaign rounds (#5511).
|
||||
- Fixed clients failing to select the correct connection if you teleport from an empty location to another with console commands (#5510).
|
||||
- Revert the previous fix to prevent the bots to take items contained inside fabricators/deconstructors (#5431) and use "donttakeitems" tag to fix it.
|
||||
- Fixed bots saying "Can't reach target [name]".
|
||||
- Fixed inventory tooltip not changing when the cursor is hovered on the slot and the condition of the item changes (#5508).
|
||||
- Fixed waypoints not being able to find hulls that have been added since the sub was last saved in the sub editor, causing them to appear blue (#5194).
|
||||
- Fixed abyss islands not showing up on sonar in mirrored levels.
|
||||
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.1300.0.9 (unstable)
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user