Build 0.18.5.0
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
<CampaignSettingPresets>
|
||||
<CampaignSettingDefinitions>
|
||||
<StartingBalanceAmount high="10000" medium="8500" low="6000" />
|
||||
<ExtraEventManagerDifficulty easy="-15.0" normal="0.0" hard="20.0" hellish="60.0" />
|
||||
<LevelDifficultyMultiplier easy="0.6" normal="1.0" hard="1.6" hellish="10.0" />
|
||||
<ExtraEventManagerDifficulty easy="-15.0" medium="0.0" hard="20.0" hellish="60.0" />
|
||||
<LevelDifficultyMultiplier easy="0.6" medium="1.0" hard="1.6" hellish="10.0" />
|
||||
</CampaignSettingDefinitions>
|
||||
<CampaignSettings
|
||||
presetname="Easy"
|
||||
|
||||
+4
-9
@@ -2,7 +2,6 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -48,6 +47,9 @@ namespace Barotrauma
|
||||
|
||||
protected override bool Filter(Item target)
|
||||
{
|
||||
System.Diagnostics.Debug.Assert(target.GetComponent<Pickable>() is { } pickable && !pickable.IsAttached, "Invalid target in AIObjectiveCleanUpItems - the the objective should only be checking pickable, non-attached items.");
|
||||
System.Diagnostics.Debug.Assert(target.Prefab.PreferredContainers.Any(), "Invalid target in AIObjectiveCleanUpItems - the the objective should only be checking items that have preferred containers defined.");
|
||||
|
||||
// If the target was selected as a valid target, we'll have to accept it so that the objective can be completed.
|
||||
// The validity changes when a character picks the item up.
|
||||
if (!IsValidTarget(target, character, checkInventory: true)) { return Objectives.ContainsKey(target) && IsItemInsideValidSubmarine(target, character); }
|
||||
@@ -57,7 +59,7 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override IEnumerable<Item> GetList() => Item.ItemList;
|
||||
protected override IEnumerable<Item> GetList() => Item.CleanableItems;
|
||||
|
||||
protected override AIObjective ObjectiveConstructor(Item item)
|
||||
=> new AIObjectiveCleanupItem(item, character, objectiveManager, priorityModifier: PriorityModifier)
|
||||
@@ -102,9 +104,6 @@ namespace Barotrauma
|
||||
}
|
||||
if (character != null && !IsItemInsideValidSubmarine(item, character)) { return false; }
|
||||
if (item.HasBallastFloraInHull) { return false; }
|
||||
var pickable = item.GetComponent<Pickable>();
|
||||
if (pickable == null) { return false; }
|
||||
if (pickable is Holdable h && h.Attachable && h.Attached) { return false; }
|
||||
var wire = item.GetComponent<Wire>();
|
||||
if (wire != null)
|
||||
{
|
||||
@@ -118,10 +117,6 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (item.Prefab.PreferredContainers.None())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!checkInventory)
|
||||
{
|
||||
return true;
|
||||
|
||||
+1
-1
@@ -488,7 +488,7 @@ namespace Barotrauma
|
||||
if (hull != null)
|
||||
{
|
||||
itemsToClean.Clear();
|
||||
foreach (Item item in Item.ItemList)
|
||||
foreach (Item item in Item.CleanableItems)
|
||||
{
|
||||
if (item.CurrentHull != hull) { continue; }
|
||||
if (AIObjectiveCleanupItems.IsValidTarget(item, character, checkInventory: true, allowUnloading: false) && !ignoredItems.Contains(item))
|
||||
|
||||
+12
-4
@@ -39,12 +39,21 @@ namespace Barotrauma
|
||||
{
|
||||
TargetContainers.Add(targetContainer);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (!OrderPrefab.TargetItemsMatchItem(TargetContainerTags, item)) { continue; }
|
||||
TargetContainers.Add(item);
|
||||
}
|
||||
}
|
||||
TargetCondition = option == "turretammo" ? ItemCondition.Empty : ItemCondition.Full;
|
||||
}
|
||||
|
||||
protected override bool Filter(Item target)
|
||||
{
|
||||
if (!IsValidTarget(target, character, TargetContainerTags, TargetCondition)) { return false; }
|
||||
//don't pass TargetContainerTags to the method (no need to filter by tags anymore, it's already done when populating TargetContainers)
|
||||
if (!IsValidTarget(target, character, null, TargetCondition)) { return false; }
|
||||
if (target.CurrentHull == null || target.CurrentHull.FireSources.Count > 0) { return false; }
|
||||
if (Character.CharacterList.Any(c => c.CurrentHull == target.CurrentHull && !HumanAIController.IsFriendly(c) && HumanAIController.IsActive(c))) { return false; }
|
||||
return true;
|
||||
@@ -52,8 +61,7 @@ namespace Barotrauma
|
||||
|
||||
public static bool IsValidTarget(Item item, Character character, ImmutableArray<Identifier>? targetContainerTags = null, ItemCondition? targetCondition = null)
|
||||
{
|
||||
if (item == null) { return false; }
|
||||
if (item.Removed) { return false; }
|
||||
if (item == null || item.Removed) { return false; }
|
||||
if (targetContainerTags.HasValue && !OrderPrefab.TargetItemsMatchItem(targetContainerTags.Value, item)) { return false; }
|
||||
if (!(item.GetComponent<ItemContainer>() is ItemContainer container)) { return false; }
|
||||
if (container.Inventory == null) { return false; }
|
||||
@@ -88,7 +96,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
protected override IEnumerable<Item> GetList() => TargetContainers.Any() ? TargetContainers : Item.ItemList;
|
||||
protected override IEnumerable<Item> GetList() => TargetContainers;
|
||||
|
||||
protected override AIObjective ObjectiveConstructor(Item target)
|
||||
=> new AIObjectiveLoadItem(target, TargetContainerTags, TargetCondition, Option, character, objectiveManager, PriorityModifier);
|
||||
|
||||
+11
-7
@@ -13,7 +13,7 @@ namespace Barotrauma
|
||||
public override bool KeepDivingGearOn => true;
|
||||
public override bool AllowAutomaticItemUnequipping => true;
|
||||
|
||||
private IEnumerable<Pump> pumpList;
|
||||
private List<Pump> pumpList;
|
||||
|
||||
public AIObjectivePumpWater(Character character, AIObjectiveManager objectiveManager, Identifier option, float priorityModifier = 1)
|
||||
: base(character, objectiveManager, priorityModifier, option) { }
|
||||
@@ -26,13 +26,8 @@ namespace Barotrauma
|
||||
|
||||
protected override bool Filter(Pump pump)
|
||||
{
|
||||
if (pump == null) { return false; }
|
||||
if (pump.Item.IgnoreByAI(character)) { return false; }
|
||||
if (!pump.Item.IsInteractable(character)) { return false; }
|
||||
if (pump.Item.HasTag("ballast")) { return false; }
|
||||
if (pump.Item.Submarine == null) { return false; }
|
||||
if (pump.Item.CurrentHull == null) { return false; }
|
||||
if (pump.Item.Submarine.TeamID != character.TeamID) { return false; }
|
||||
if (pump.IsAutoControlled) { return false; }
|
||||
if (pump.Item.ConditionPercentage <= 0) { return false; }
|
||||
if (pump.Item.CurrentHull.FireSources.Count > 0) { return false; }
|
||||
@@ -50,7 +45,16 @@ namespace Barotrauma
|
||||
if (pumpList == null)
|
||||
{
|
||||
if (character == null || character.Submarine == null) { return Array.Empty<Pump>(); }
|
||||
pumpList = character.Submarine.GetItems(true).Select(i => i.GetComponent<Pump>()).Where(p => p != null);
|
||||
|
||||
pumpList = new List<Pump>();
|
||||
foreach (Item item in character.Submarine.GetItems(true))
|
||||
{
|
||||
var pump = item.GetComponent<Pump>();
|
||||
if (pump == null || pump.Item.Submarine == null || pump.Item.CurrentHull == null) { continue; }
|
||||
if (pump.Item.Submarine.TeamID != character.TeamID) { continue; }
|
||||
if (pump.Item.HasTag("ballast")) { continue; }
|
||||
pumpList.Add(pump);
|
||||
}
|
||||
}
|
||||
return pumpList;
|
||||
}
|
||||
|
||||
+4
-1
@@ -136,7 +136,7 @@ namespace Barotrauma
|
||||
return MathHelper.Lerp(0, 100, MathHelper.Clamp(damagePriority * successFactor, 0, 1));
|
||||
}
|
||||
|
||||
protected override IEnumerable<Item> GetList() => Item.ItemList;
|
||||
protected override IEnumerable<Item> GetList() => Item.RepairableItems;
|
||||
|
||||
protected override AIObjective ObjectiveConstructor(Item item)
|
||||
=> new AIObjectiveRepairItem(character, item, objectiveManager, priorityModifier: PriorityModifier, isPriority: item == PrioritizedItem);
|
||||
@@ -156,6 +156,9 @@ namespace Barotrauma
|
||||
if (character.IsOnPlayerTeam && item.Submarine.Info.IsOutpost) { return false; }
|
||||
if (!character.Submarine.IsEntityFoundOnThisSub(item, includingConnectedSubs: true)) { return false; }
|
||||
if (item.Repairables.None()) { return false; }
|
||||
|
||||
System.Diagnostics.Debug.Assert(item.Repairables.Any(), "Invalid target in AIObjectiveRepairItems - the objective should only be checking items that have a Repairable component (Item.RepairableItems)");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,7 +356,10 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public bool OmitJobInPortraitClothing;
|
||||
/// <summary>
|
||||
/// Can be used to disable displaying the job in any info panels
|
||||
/// </summary>
|
||||
public bool OmitJobInMenus;
|
||||
|
||||
private Sprite portrait;
|
||||
public Sprite Portrait
|
||||
@@ -434,7 +437,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (attachmentSprites == null)
|
||||
{
|
||||
LoadAttachmentSprites(OmitJobInPortraitClothing);
|
||||
LoadAttachmentSprites();
|
||||
}
|
||||
return attachmentSprites;
|
||||
}
|
||||
@@ -1092,7 +1095,7 @@ namespace Barotrauma
|
||||
|
||||
private static IEnumerable<float> GetWeights(IEnumerable<ContentXElement> elements) => elements.Select(h => h.GetAttributeFloat("commonness", 1f));
|
||||
|
||||
partial void LoadAttachmentSprites(bool omitJob);
|
||||
partial void LoadAttachmentSprites();
|
||||
|
||||
private int CalculateSalary()
|
||||
{
|
||||
|
||||
@@ -79,7 +79,6 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public static IReadOnlyDictionary<Identifier, float> ItemRepairPriorities => _itemRepairPriorities;
|
||||
|
||||
public static ContentXElement NoJobElement;
|
||||
public static JobPrefab Get(string identifier)
|
||||
{
|
||||
if (Prefabs.ContainsKey(identifier))
|
||||
@@ -213,7 +212,7 @@ namespace Barotrauma
|
||||
public SkillPrefab PrimarySkill => Skills?.FirstOrDefault(s => s.IsPrimarySkill);
|
||||
|
||||
public ContentXElement Element { get; private set; }
|
||||
public ContentXElement ClothingElement { get; private set; }
|
||||
|
||||
public int Variants { get; private set; }
|
||||
|
||||
public JobPrefab(ContentXElement element, JobsFile file) : base(file, element.GetAttributeIdentifier("identifier", ""))
|
||||
@@ -288,9 +287,6 @@ namespace Barotrauma
|
||||
Variants = variant;
|
||||
|
||||
Skills.Sort((x,y) => y.LevelRange.Start.CompareTo(x.LevelRange.Start));
|
||||
|
||||
// Disabled on purpose, TODO: remove all references?
|
||||
//ClothingElement = element.GetChildElement("PortraitClothing");
|
||||
}
|
||||
|
||||
public static JobPrefab Random(Rand.RandSync sync, Func<JobPrefab, bool> predicate = null) => Prefabs.GetRandom(p => !p.HiddenJob && (predicate == null || predicate(p)), sync);
|
||||
|
||||
@@ -121,7 +121,7 @@ namespace Barotrauma
|
||||
return folder.CleanUpPathCrossPlatform(correctFilenameCase: true);
|
||||
}
|
||||
|
||||
public static T GetDefaultRagdollParams<T>(Identifier speciesName) where T : RagdollParams, new() => GetRagdollParams<T>(speciesName, GetDefaultFileName(speciesName));
|
||||
public static T GetDefaultRagdollParams<T>(Identifier speciesName) where T : RagdollParams, new() => GetRagdollParams<T>(speciesName);
|
||||
|
||||
/// <summary>
|
||||
/// If the file name is left null, default file is selected. If fails, will select the default file. Note: Use the filename without the extensions, don't use the full path!
|
||||
|
||||
@@ -22,11 +22,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (var element in mainElement.Elements())
|
||||
{
|
||||
if (element.NameAsIdentifier() == "nojob")
|
||||
{
|
||||
JobPrefab.NoJobElement ??= element;
|
||||
}
|
||||
else if (element.NameAsIdentifier() == "ItemRepairPriorities")
|
||||
if (element.NameAsIdentifier() == "ItemRepairPriorities")
|
||||
{
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
|
||||
@@ -177,4 +177,11 @@ namespace Barotrauma
|
||||
Int,
|
||||
Float
|
||||
}
|
||||
|
||||
public enum ChatMode
|
||||
{
|
||||
None,
|
||||
Local,
|
||||
Radio
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1028,13 +1028,14 @@ namespace Barotrauma
|
||||
var itemsToTransfer = new List<(Item item, Item container)>();
|
||||
if (PendingSubmarineSwitch != null)
|
||||
{
|
||||
var connectedSubs = currentSub.GetConnectedSubs().Where(s => s.Info.Type == SubmarineType.Player).ToHashSet();
|
||||
// Remove items from the old sub
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (item.Removed) { continue; }
|
||||
if (item.NonInteractable) { continue; }
|
||||
if (item.HiddenInGame) { continue; }
|
||||
if (item.Submarine != currentSub) { continue; }
|
||||
if (!connectedSubs.Contains(item.Submarine)) { continue; }
|
||||
if (item.Prefab.DontTransferBetweenSubs) { continue; }
|
||||
if (item.GetRootInventoryOwner() is Character) { continue; }
|
||||
if (item.GetComponent<Holdable>() == null && item.GetComponent<Wearable>() == null && item.GetComponent<Projectile>() == null) { continue; }
|
||||
@@ -1058,9 +1059,10 @@ namespace Barotrauma
|
||||
{
|
||||
// Load the new sub
|
||||
var newSub = new Submarine(PendingSubmarineSwitch);
|
||||
var connectedSubs = newSub.GetConnectedSubs().Where(s => s.Info.Type == SubmarineType.Player).ToHashSet();
|
||||
// Move the transferred items
|
||||
List<ItemContainer> availableContainers = Item.ItemList
|
||||
.Where(it => it.Submarine == newSub && it.HasTag("crate") && !it.NonInteractable && !it.HiddenInGame && !it.Removed)
|
||||
.Where(it => connectedSubs.Contains(it.Submarine) && it.HasTag("crate") && !it.NonInteractable && !it.HiddenInGame && !it.Removed)
|
||||
.Select(it => it.GetComponent<ItemContainer>())
|
||||
.Where(c => c != null)
|
||||
.ToList();
|
||||
@@ -1070,7 +1072,7 @@ namespace Barotrauma
|
||||
item.Submarine = newSub;
|
||||
if (item.Container == null)
|
||||
{
|
||||
newContainer = newSub.FindContainerFor(item, onlyPrimary: true, checkTransferConditions: true);
|
||||
newContainer = newSub.FindContainerFor(item, onlyPrimary: true, checkTransferConditions: true, allowConnectedSubs: true);
|
||||
}
|
||||
if (item.Container == null && (newContainer == null || !newContainer.OwnInventory.TryPutItem(item, user: null, createNetworkEvent: false)))
|
||||
{
|
||||
@@ -1086,7 +1088,8 @@ namespace Barotrauma
|
||||
var cargoContainer = CargoManager.GetOrCreateCargoContainerFor(item.Prefab, spawnHull, ref availableContainers);
|
||||
if (cargoContainer == null || !cargoContainer.Inventory.TryPutItem(item, user: null, createNetworkEvent: false))
|
||||
{
|
||||
item.SetTransform(wp.SimPosition, 0.0f, findNewHull: false, setPrevTransform: false);
|
||||
Vector2 simPos = ConvertUnits.ToSimUnits(CargoManager.GetCargoPos(spawnHull, item.Prefab));
|
||||
item.SetTransform(simPos, 0.0f, findNewHull: false, setPrevTransform: false);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
+12
-2
@@ -71,12 +71,22 @@ namespace Barotrauma
|
||||
|
||||
public float GetFloat(Identifier identifier)
|
||||
{
|
||||
return values.TryGetValue(identifier, out Either<int, float> value) && value.TryGet(out float range) ? range : 0.0f;
|
||||
float range = 0;
|
||||
if (!values.TryGetValue(identifier, out Either<int, float> value) || !value.TryGet(out range))
|
||||
{
|
||||
DebugConsole.ThrowError($"CampaignSettings: Can't find value for {identifier}");
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
public int GetInt(Identifier identifier)
|
||||
{
|
||||
return values.TryGetValue(identifier, out Either<int, float> value) && value.TryGet(out int integer) ? integer : 0;
|
||||
int integer = 0;
|
||||
if (!values.TryGetValue(identifier, out Either<int, float> value) || !value.TryGet(out integer))
|
||||
{
|
||||
DebugConsole.ThrowError($"CampaignSettings: Can't find value for {identifier}");
|
||||
}
|
||||
return integer;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,13 +13,14 @@ namespace Barotrauma
|
||||
SelectNextCharacter,
|
||||
SelectPreviousCharacter,
|
||||
Voice,
|
||||
LocalVoice,
|
||||
Deselect,
|
||||
Shoot,
|
||||
Command,
|
||||
TakeOneFromInventorySlot,
|
||||
TakeHalfFromInventorySlot,
|
||||
NextFireMode,
|
||||
PreviousFireMode
|
||||
PreviousFireMode,
|
||||
ActiveChat,
|
||||
ToggleChatMode,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,7 +270,11 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
Body?.SetTransform(Body.SimPosition + ConvertUnits.ToSimUnits(amount), 0.0f);
|
||||
}
|
||||
|
||||
if (linkedGap != null)
|
||||
{
|
||||
RefreshLinkedGap();
|
||||
linkedGap.Rect = item.Rect;
|
||||
}
|
||||
#if CLIENT
|
||||
UpdateConvexHulls();
|
||||
#endif
|
||||
|
||||
@@ -41,6 +41,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private Character prevEquipper;
|
||||
|
||||
public override bool IsAttached => Attached;
|
||||
|
||||
private bool attachable, attached, attachedByDefault;
|
||||
private Voronoi2.VoronoiCell attachTargetCell;
|
||||
private PhysicsBody body;
|
||||
@@ -71,6 +73,7 @@ namespace Barotrauma.Items.Components
|
||||
set
|
||||
{
|
||||
attached = value;
|
||||
item.CheckCleanable();
|
||||
item.SetActiveSprite();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -20,6 +19,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private CoroutineHandle pickingCoroutine;
|
||||
|
||||
public virtual bool IsAttached => false;
|
||||
|
||||
public List<InvSlotType> AllowedSlots
|
||||
{
|
||||
get { return allowedSlots; }
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace Barotrauma.Items.Components
|
||||
get; set;
|
||||
}
|
||||
|
||||
[Serialize(true, IsPropertySaveable.No, description: "Can the item hit broken doors.")]
|
||||
[Serialize(true, IsPropertySaveable.No, description: "Can the item hit doors.")]
|
||||
public bool HitItems { get; set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No, description: "Can the item hit broken doors.")]
|
||||
|
||||
@@ -187,7 +187,7 @@ namespace Barotrauma.Items.Components
|
||||
[Serialize(false, IsPropertySaveable.No)]
|
||||
public bool RemoveContainedItemsOnDeconstruct { get; set; }
|
||||
|
||||
private readonly ImmutableArray<SlotRestrictions> slotRestrictions;
|
||||
private ImmutableArray<SlotRestrictions> slotRestrictions;
|
||||
|
||||
readonly List<ISerializableEntity> targets = new List<ISerializableEntity>();
|
||||
|
||||
@@ -215,13 +215,21 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override bool RecreateGUIOnResolutionChange => true;
|
||||
|
||||
public List<RelatedItem> ContainableItems { get; }
|
||||
public List<RelatedItem> ContainableItems { get; private set; }
|
||||
|
||||
public ItemContainer(Item item, ContentXElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
LoadContainableRestrictions(element);
|
||||
InitProjSpecific(element);
|
||||
}
|
||||
|
||||
public void LoadContainableRestrictions(ContentXElement element)
|
||||
{
|
||||
int totalCapacity = capacity;
|
||||
|
||||
ContainableItems?.Clear();
|
||||
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
@@ -242,7 +250,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
Inventory = new ItemInventory(item, this, totalCapacity, SlotsPerRow);
|
||||
|
||||
|
||||
List<SlotRestrictions> newSlotRestrictions = new List<SlotRestrictions>(totalCapacity);
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
@@ -253,7 +261,7 @@ namespace Barotrauma.Items.Components
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
if (subElement.Name.ToString().ToLowerInvariant() != "subcontainer") { continue; }
|
||||
|
||||
|
||||
int subCapacity = subElement.GetAttributeInt("capacity", 1);
|
||||
int subMaxStackSize = subElement.GetAttributeInt("maxstacksize", maxStackSize);
|
||||
|
||||
@@ -281,7 +289,6 @@ namespace Barotrauma.Items.Components
|
||||
capacity = totalCapacity;
|
||||
slotRestrictions = newSlotRestrictions.ToImmutableArray();
|
||||
System.Diagnostics.Debug.Assert(totalCapacity == slotRestrictions.Length);
|
||||
InitProjSpecific(element);
|
||||
}
|
||||
|
||||
public int GetMaxStackSize(int slotIndex)
|
||||
|
||||
@@ -114,6 +114,20 @@ namespace Barotrauma.Items.Components
|
||||
private set;
|
||||
} = true;
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No)]
|
||||
public bool NonInteractableWhenFlippedX
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No)]
|
||||
public bool NonInteractableWhenFlippedY
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Controller(Item item, ContentXElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
@@ -571,6 +585,18 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnItemLoaded()
|
||||
{
|
||||
if (item.FlippedX && NonInteractableWhenFlippedX)
|
||||
{
|
||||
item.NonInteractable = true;
|
||||
}
|
||||
else if (item.FlippedY && NonInteractableWhenFlippedY)
|
||||
{
|
||||
item.NonInteractable = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
@@ -435,7 +435,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("GridUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:Power", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
#endif
|
||||
|
||||
@@ -592,7 +592,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("PowerUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:Power", sw.ElapsedTicks);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ namespace Barotrauma
|
||||
Beard,
|
||||
Moustache,
|
||||
FaceAttachment,
|
||||
JobIndicator,
|
||||
Husk,
|
||||
Herpes
|
||||
}
|
||||
@@ -128,7 +127,6 @@ namespace Barotrauma
|
||||
case WearableType.Beard:
|
||||
case WearableType.Moustache:
|
||||
case WearableType.FaceAttachment:
|
||||
case WearableType.JobIndicator:
|
||||
case WearableType.Husk:
|
||||
case WearableType.Herpes:
|
||||
Limb = LimbType.Head;
|
||||
|
||||
@@ -29,6 +29,20 @@ namespace Barotrauma
|
||||
|
||||
public static IReadOnlyCollection<Item> DangerousItems { get { return dangerousItems; } }
|
||||
|
||||
private static readonly List<Item> repairableItems = new List<Item>();
|
||||
|
||||
/// <summary>
|
||||
/// Items that have one more more Repairable component
|
||||
/// </summary>
|
||||
public static IReadOnlyCollection<Item> RepairableItems => repairableItems;
|
||||
|
||||
private static readonly List<Item> cleanableItems = new List<Item>();
|
||||
|
||||
/// <summary>
|
||||
/// Items that may potentially need to be cleaned up (pickable, not attached to a wall, and not inside a valid container)
|
||||
/// </summary>
|
||||
public static IReadOnlyCollection<Item> CleanableItems => cleanableItems;
|
||||
|
||||
public new ItemPrefab Prefab => base.Prefab as ItemPrefab;
|
||||
|
||||
public static bool ShowLinks = true;
|
||||
@@ -186,6 +200,7 @@ namespace Barotrauma
|
||||
if (value != container)
|
||||
{
|
||||
container = value;
|
||||
CheckCleanable();
|
||||
SetActiveSprite();
|
||||
}
|
||||
}
|
||||
@@ -1009,10 +1024,9 @@ namespace Barotrauma
|
||||
|
||||
InsertToList();
|
||||
ItemList.Add(this);
|
||||
if (Prefab.IsDangerous)
|
||||
{
|
||||
dangerousItems.Add(this);
|
||||
}
|
||||
if (Prefab.IsDangerous) { dangerousItems.Add(this); }
|
||||
if (Repairables.Any()) { repairableItems.Add(this); }
|
||||
CheckCleanable();
|
||||
|
||||
DebugConsole.Log("Created " + Name + " (" + ID + ")");
|
||||
|
||||
@@ -1022,6 +1036,9 @@ namespace Barotrauma
|
||||
ApplyStatusEffects(ActionType.OnSpawn, 1.0f);
|
||||
Components.ForEach(c => c.ApplyStatusEffects(ActionType.OnSpawn, 1.0f));
|
||||
RecalculateConditionValues();
|
||||
#if CLIENT
|
||||
Submarine.ForceVisibilityRecheck();
|
||||
#endif
|
||||
}
|
||||
|
||||
partial void InitProjSpecific();
|
||||
@@ -1150,6 +1167,7 @@ namespace Barotrauma
|
||||
drawableComponents.Add(drawable);
|
||||
hasComponentsToDraw = true;
|
||||
#if CLIENT
|
||||
Submarine.ForceVisibilityRecheck();
|
||||
cachedVisibleExtents = null;
|
||||
#endif
|
||||
}
|
||||
@@ -1281,6 +1299,27 @@ namespace Barotrauma
|
||||
|
||||
partial void SetActiveSpriteProjSpecific();
|
||||
|
||||
/// <summary>
|
||||
/// Recheck if the item needs to be included in the list of cleanable items
|
||||
/// </summary>
|
||||
public void CheckCleanable()
|
||||
{
|
||||
var pickable = GetComponent<Pickable>();
|
||||
if (pickable != null && !pickable.IsAttached &&
|
||||
Prefab.PreferredContainers.Any() &&
|
||||
(container == null || container.HasTag("allowcleanup")))
|
||||
{
|
||||
if (!cleanableItems.Contains(this))
|
||||
{
|
||||
cleanableItems.Add(this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cleanableItems.Remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Move(Vector2 amount, bool ignoreContacts = false)
|
||||
{
|
||||
if (!MathUtils.IsValid(amount))
|
||||
@@ -2526,7 +2565,7 @@ namespace Barotrauma
|
||||
ic.WasUsed = true;
|
||||
#if CLIENT
|
||||
ic.PlaySound(ActionType.OnUse, character);
|
||||
#endif
|
||||
#endif
|
||||
ic.ApplyStatusEffects(ActionType.OnUse, deltaTime, character, targetLimb);
|
||||
|
||||
if (ic.DeleteOnUse) { remove = true; }
|
||||
@@ -2704,6 +2743,9 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
SetContainedItemPositions();
|
||||
#if CLIENT
|
||||
Submarine.ForceVisibilityRecheck();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Equip(Character character)
|
||||
@@ -3368,8 +3410,7 @@ namespace Barotrauma
|
||||
{
|
||||
ic.ShallowRemove();
|
||||
}
|
||||
ItemList.Remove(this);
|
||||
dangerousItems.Remove(this);
|
||||
RemoveFromLists();
|
||||
|
||||
if (body != null)
|
||||
{
|
||||
@@ -3427,8 +3468,8 @@ namespace Barotrauma
|
||||
ic.GuiFrame = null;
|
||||
#endif
|
||||
}
|
||||
ItemList.Remove(this);
|
||||
dangerousItems.Remove(this);
|
||||
|
||||
RemoveFromLists();
|
||||
|
||||
if (body != null)
|
||||
{
|
||||
@@ -3461,6 +3502,14 @@ namespace Barotrauma
|
||||
RemoveProjSpecific();
|
||||
}
|
||||
|
||||
private void RemoveFromLists()
|
||||
{
|
||||
ItemList.Remove(this);
|
||||
dangerousItems.Remove(this);
|
||||
repairableItems.Remove(this);
|
||||
cleanableItems.Remove(this);
|
||||
}
|
||||
|
||||
partial void RemoveProjSpecific();
|
||||
|
||||
public static void RemoveByPrefab(ItemPrefab prefab)
|
||||
|
||||
@@ -463,6 +463,15 @@ namespace Barotrauma.MapCreatures.Behavior
|
||||
}
|
||||
}
|
||||
|
||||
if (root == null)
|
||||
{
|
||||
Branches.ForEach(b => b.DisconnectedFromRoot = true);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckDisconnectedFromRoot();
|
||||
}
|
||||
|
||||
void LoadBranch(XElement branchElement, IdRemap idRemap)
|
||||
{
|
||||
Vector2 pos = branchElement.GetAttributeVector2("pos", Vector2.Zero);
|
||||
@@ -649,9 +658,10 @@ namespace Barotrauma.MapCreatures.Behavior
|
||||
toBeRemoved.Clear();
|
||||
foreach (BallastFloraBranch branch in Branches)
|
||||
{
|
||||
if (branch.ParentBranch != null && (branch.ParentBranch.DisconnectedFromRoot || branch.ParentBranch.Health <= 0.0f))
|
||||
if (branch.ParentBranch == null || branch.ParentBranch.DisconnectedFromRoot || branch.ParentBranch.Health <= 0.0f)
|
||||
{
|
||||
float speed = MathHelper.Lerp(5.0f, 0.1f, branch.ParentBranch.Health / branch.ParentBranch.MaxHealth);
|
||||
float parentHealth = branch.ParentBranch == null ? 0.0f : branch.ParentBranch.Health / branch.ParentBranch.MaxHealth;
|
||||
float speed = MathHelper.Lerp(5.0f, 0.1f, parentHealth);
|
||||
DamageBranch(branch, speed * speed * deltaTime, AttackType.CutFromRoot);
|
||||
}
|
||||
if (branch.Health <= 0.0f)
|
||||
@@ -1071,6 +1081,25 @@ namespace Barotrauma.MapCreatures.Behavior
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckDisconnectedFromRoot()
|
||||
{
|
||||
bool foundDisconnected;
|
||||
do
|
||||
{
|
||||
foundDisconnected = false;
|
||||
foreach (BallastFloraBranch branch in Branches)
|
||||
{
|
||||
if (branch.ParentBranch == null || branch.DisconnectedFromRoot) { continue; }
|
||||
if (branch.ParentBranch.Removed || branch.ParentBranch.DisconnectedFromRoot)
|
||||
{
|
||||
branch.DisconnectedFromRoot = true;
|
||||
foundDisconnected = true;
|
||||
}
|
||||
}
|
||||
} while (foundDisconnected);
|
||||
|
||||
}
|
||||
|
||||
public void RemoveBranch(BallastFloraBranch branch)
|
||||
{
|
||||
bool isClient = GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient;
|
||||
@@ -1081,20 +1110,7 @@ namespace Barotrauma.MapCreatures.Behavior
|
||||
Branches.Remove(branch);
|
||||
branch.Removed = true;
|
||||
|
||||
bool foundDisconnected = false;
|
||||
do
|
||||
{
|
||||
foundDisconnected = false;
|
||||
foreach (BallastFloraBranch otherBranch in Branches)
|
||||
{
|
||||
if (otherBranch.ParentBranch == null || otherBranch.DisconnectedFromRoot) { continue; }
|
||||
if (otherBranch.ParentBranch.Removed || otherBranch.ParentBranch.DisconnectedFromRoot)
|
||||
{
|
||||
otherBranch.DisconnectedFromRoot = true;
|
||||
foundDisconnected = true;
|
||||
}
|
||||
}
|
||||
} while (foundDisconnected);
|
||||
CheckDisconnectedFromRoot();
|
||||
|
||||
bodies.ForEachMod(body =>
|
||||
{
|
||||
|
||||
@@ -4056,7 +4056,11 @@ namespace Barotrauma
|
||||
string beaconStationName = System.IO.Path.GetFileNameWithoutExtension(contentFile.Path.Value);
|
||||
|
||||
BeaconStation = SpawnSubOnPath(beaconStationName, contentFile, SubmarineType.BeaconStation);
|
||||
if (BeaconStation == null) { return; }
|
||||
if (BeaconStation == null)
|
||||
{
|
||||
LevelData.HasBeaconStation = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Item sonarItem = Item.ItemList.Find(it => it.Submarine == BeaconStation && it.GetComponent<Sonar>() != null);
|
||||
if (sonarItem == null)
|
||||
@@ -4072,6 +4076,11 @@ namespace Barotrauma
|
||||
if (!LevelData.HasBeaconStation) { return; }
|
||||
if (GameMain.NetworkMember?.IsClient ?? false) { return; }
|
||||
|
||||
if (BeaconStation == null)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to prepare beacon station (no beacon station in the level).");
|
||||
}
|
||||
|
||||
List<Item> beaconItems = Item.ItemList.FindAll(it => it.Submarine == BeaconStation);
|
||||
|
||||
Item reactorItem = beaconItems.Find(it => it.GetComponent<Reactor>() != null);
|
||||
|
||||
@@ -567,6 +567,10 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public static void UpdateAll(float deltaTime, Camera cam)
|
||||
{
|
||||
#if CLIENT
|
||||
var sw = new System.Diagnostics.Stopwatch();
|
||||
sw.Start();
|
||||
#endif
|
||||
foreach (Hull hull in Hull.HullList)
|
||||
{
|
||||
hull.Update(deltaTime, cam);
|
||||
@@ -594,6 +598,11 @@ namespace Barotrauma
|
||||
gapUpdateTimer = 0;
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:MapEntity:Misc", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
#endif
|
||||
Powered.UpdatePower(deltaTime);
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
@@ -602,6 +611,11 @@ namespace Barotrauma
|
||||
|
||||
UpdateAllProjSpecific(deltaTime);
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:MapEntity:Items", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
#endif
|
||||
Spawner?.Update();
|
||||
}
|
||||
|
||||
|
||||
@@ -1857,15 +1857,23 @@ namespace Barotrauma
|
||||
|
||||
public void RefreshOutdoorNodes() => OutdoorNodes.ForEach(n => n?.Waypoint?.FindHull());
|
||||
|
||||
public Item FindContainerFor(Item item, bool onlyPrimary, bool checkTransferConditions = false)
|
||||
public Item FindContainerFor(Item item, bool onlyPrimary, bool checkTransferConditions = false, bool allowConnectedSubs = false)
|
||||
{
|
||||
var potentialContainers = new List<Item>();
|
||||
var connectedSubs = GetConnectedSubs().Where(s => s.Info.Type == SubmarineType.Player).ToHashSet();
|
||||
Item selectedContainer = null;
|
||||
foreach (Item potentialContainer in Item.ItemList)
|
||||
{
|
||||
if (potentialContainer.Removed) { continue; }
|
||||
if (potentialContainer.NonInteractable) { continue; }
|
||||
if (potentialContainer.HiddenInGame) { continue; }
|
||||
if (potentialContainer.Submarine != this) { continue; }
|
||||
if (allowConnectedSubs)
|
||||
{
|
||||
if (!connectedSubs.Contains(potentialContainer.Submarine)) { continue; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (potentialContainer.Submarine != this) { continue; }
|
||||
}
|
||||
if (potentialContainer == item) { continue; }
|
||||
if (potentialContainer.Condition <= 0) { continue; }
|
||||
if (potentialContainer.OwnInventory == null) { continue; }
|
||||
@@ -1875,13 +1883,15 @@ namespace Barotrauma
|
||||
if (!potentialContainer.OwnInventory.CanBePut(item)) { continue; }
|
||||
if (!container.ShouldBeContained(item, out _)) { continue; }
|
||||
if (!item.Prefab.IsContainerPreferred(item, container, out bool isPreferencesDefined, out bool isSecondary, checkTransferConditions: checkTransferConditions) || !isPreferencesDefined || onlyPrimary && isSecondary) { continue; }
|
||||
potentialContainers.Add(potentialContainer);
|
||||
if (!isSecondary)
|
||||
if (potentialContainer.Submarine == this && !isSecondary)
|
||||
{
|
||||
break;
|
||||
//valid primary container in the same sub -> perfect, let's use that one
|
||||
return potentialContainer;
|
||||
}
|
||||
selectedContainer = potentialContainer;
|
||||
|
||||
}
|
||||
return potentialContainers.LastOrDefault();
|
||||
return selectedContainer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +117,8 @@ namespace Barotrauma.Networking
|
||||
set;
|
||||
}
|
||||
|
||||
public ChatMode ChatMode { get; set; } = ChatMode.None;
|
||||
|
||||
protected ChatMessage(string senderName, string text, ChatMessageType type, Character sender, Client client, PlayerConnectionChangeType changeType = PlayerConnectionChangeType.None, Color? textColor = null)
|
||||
{
|
||||
Text = text;
|
||||
|
||||
@@ -23,7 +23,6 @@ namespace Barotrauma
|
||||
|
||||
private readonly Dictionary<string, Queue<long>> elapsedTicks = new Dictionary<string, Queue<long>>();
|
||||
private readonly Dictionary<string, long> avgTicksPerFrame = new Dictionary<string, long>();
|
||||
private readonly Dictionary<string, Dictionary<string, TickInfo>> partialTickInfos = new Dictionary<string, Dictionary<string, TickInfo>>();
|
||||
|
||||
#if CLIENT
|
||||
internal Graph UpdateTimeGraph = new Graph(500), DrawTimeGraph = new Graph(500);
|
||||
@@ -43,20 +42,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<string> tempSavedPartialIdentifiers = new List<string>();
|
||||
public IReadOnlyList<string> GetSavedPartialIdentifiers(string parentIdentifier)
|
||||
{
|
||||
lock (mutex)
|
||||
{
|
||||
tempSavedPartialIdentifiers.Clear();
|
||||
if (partialTickInfos.TryGetValue(parentIdentifier, out var tickInfos))
|
||||
{
|
||||
tempSavedPartialIdentifiers.AddRange(tickInfos.Keys);
|
||||
}
|
||||
}
|
||||
return tempSavedPartialIdentifiers;
|
||||
}
|
||||
|
||||
public void AddElapsedTicks(string identifier, long ticks)
|
||||
{
|
||||
lock (mutex)
|
||||
@@ -72,29 +57,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void AddPartialElapsedTicks(string parentIdentifier, string identifier, long ticks)
|
||||
{
|
||||
lock (mutex)
|
||||
{
|
||||
if (!partialTickInfos.TryGetValue(parentIdentifier, out var tickInfos))
|
||||
{
|
||||
tickInfos = new Dictionary<string, TickInfo>();
|
||||
partialTickInfos.Add(parentIdentifier, tickInfos);
|
||||
}
|
||||
if (!tickInfos.TryGetValue(identifier, out var tickInfo))
|
||||
{
|
||||
tickInfo = new TickInfo();
|
||||
tickInfos.Add(identifier, tickInfo);
|
||||
}
|
||||
tickInfo.ElapsedTicks.Enqueue(ticks);
|
||||
if (tickInfo.ElapsedTicks.Count > MaximumSamples)
|
||||
{
|
||||
tickInfo.ElapsedTicks.Dequeue();
|
||||
tickInfo.AvgTicksPerFrame = (long)tickInfo.ElapsedTicks.Average(i => i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float GetAverageElapsedMillisecs(string identifier)
|
||||
{
|
||||
long ticksPerFrame = 0;
|
||||
@@ -105,18 +67,6 @@ namespace Barotrauma
|
||||
return ticksPerFrame * 1000.0f / Stopwatch.Frequency;
|
||||
}
|
||||
|
||||
public float GetPartialAverageElapsedMillisecs(string parentIdentifier, string identifier)
|
||||
{
|
||||
long ticksPerFrame = 0;
|
||||
lock (mutex)
|
||||
{
|
||||
if (!partialTickInfos.TryGetValue(parentIdentifier, out var tickInfos)) { return 0.0f; }
|
||||
if (!tickInfos.TryGetValue(identifier, out var tickInfo)) { return 0.0f; }
|
||||
ticksPerFrame = tickInfo.AvgTicksPerFrame;
|
||||
}
|
||||
return ticksPerFrame * 1000.0f / Stopwatch.Frequency;
|
||||
}
|
||||
|
||||
public bool Update(double deltaTime)
|
||||
{
|
||||
if (deltaTime == 0.0f) { return false; }
|
||||
|
||||
@@ -149,19 +149,19 @@ namespace Barotrauma
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("GameSessionUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:GameSession", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
GameMain.ParticleManager.Update((float)deltaTime);
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("ParticleUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:Particles", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
if (Level.Loaded != null) Level.Loaded.Update((float)deltaTime, cam);
|
||||
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("LevelUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:Level", sw.ElapsedTicks);
|
||||
|
||||
if (Character.Controlled != null)
|
||||
{
|
||||
@@ -193,7 +193,7 @@ namespace Barotrauma
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("CharacterUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:Character", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
#endif
|
||||
|
||||
@@ -201,7 +201,7 @@ namespace Barotrauma
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("StatusEffectUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:StatusEffects", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
|
||||
if (Character.Controlled != null &&
|
||||
@@ -253,7 +253,7 @@ namespace Barotrauma
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("MapEntityUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:MapEntity", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
#endif
|
||||
Character.UpdateAnimAll((float)deltaTime);
|
||||
@@ -266,7 +266,7 @@ namespace Barotrauma
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("AnimUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:Ragdolls", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
#endif
|
||||
|
||||
@@ -277,7 +277,7 @@ namespace Barotrauma
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("SubmarineUpdate", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:Submarine", sw.ElapsedTicks);
|
||||
sw.Restart();
|
||||
#endif
|
||||
|
||||
@@ -297,7 +297,7 @@ namespace Barotrauma
|
||||
|
||||
#if CLIENT
|
||||
sw.Stop();
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Physics", sw.ElapsedTicks);
|
||||
GameMain.PerformanceCounter.AddElapsedTicks("Update:Physics", sw.ElapsedTicks);
|
||||
#endif
|
||||
UpdateProjSpecific(deltaTime);
|
||||
|
||||
|
||||
@@ -1119,7 +1119,12 @@ namespace Barotrauma
|
||||
itemComponent.SetRequiredItems(element, allowEmpty: true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (itemComponent is ItemContainer itemContainer &&
|
||||
(componentElement.GetChildElement("containable") != null || componentElement.GetChildElement("subcontainer") != null))
|
||||
{
|
||||
itemContainer.LoadContainableRestrictions(componentElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,6 +226,7 @@ namespace Barotrauma
|
||||
{
|
||||
MusicVolume = 0.3f,
|
||||
SoundVolume = 0.5f,
|
||||
UiVolume = 0.3f,
|
||||
VoiceChatVolume = 0.5f,
|
||||
VoiceChatCutoffPrevention = 0,
|
||||
MicrophoneVolume = 5,
|
||||
@@ -234,7 +235,6 @@ namespace Barotrauma
|
||||
UseDirectionalVoiceChat = true,
|
||||
VoipAttenuationEnabled = true,
|
||||
VoiceSetting = VoiceMode.PushToTalk,
|
||||
UseLocalVoiceByDefault = false,
|
||||
DisableVoiceChatFilters = false
|
||||
};
|
||||
return audioSettings;
|
||||
@@ -249,6 +249,7 @@ namespace Barotrauma
|
||||
|
||||
public float MusicVolume;
|
||||
public float SoundVolume;
|
||||
public float UiVolume;
|
||||
public float VoiceChatVolume;
|
||||
public int VoiceChatCutoffPrevention;
|
||||
public float MicrophoneVolume;
|
||||
@@ -264,7 +265,6 @@ namespace Barotrauma
|
||||
public string VoiceCaptureDevice;
|
||||
|
||||
public float NoiseGateThreshold;
|
||||
public bool UseLocalVoiceByDefault;
|
||||
public bool DisableVoiceChatFilters;
|
||||
}
|
||||
|
||||
@@ -286,12 +286,13 @@ namespace Barotrauma
|
||||
{ InputType.Aim, MouseButton.SecondaryMouse },
|
||||
|
||||
{ InputType.InfoTab, Keys.Tab },
|
||||
{ InputType.Chat, Keys.T },
|
||||
{ InputType.RadioChat, Keys.R },
|
||||
{ InputType.Chat, Keys.None },
|
||||
{ InputType.RadioChat, Keys.None },
|
||||
{ InputType.ActiveChat, Keys.T },
|
||||
{ InputType.CrewOrders, Keys.C },
|
||||
|
||||
{ InputType.Voice, Keys.V },
|
||||
{ InputType.LocalVoice, Keys.B },
|
||||
{ InputType.ToggleChatMode, Keys.R },
|
||||
{ InputType.Command, MouseButton.MiddleMouse },
|
||||
{ InputType.PreviousFireMode, MouseButton.MouseWheelDown },
|
||||
{ InputType.NextFireMode, MouseButton.MouseWheelUp },
|
||||
@@ -332,17 +333,35 @@ namespace Barotrauma
|
||||
if (!bindings.ContainsKey(inputType)) { bindings.Add(inputType, defaultBindings[inputType]); }
|
||||
}
|
||||
|
||||
bool playerConfigContainsNewChatBinds = false;
|
||||
foreach (XElement element in elements)
|
||||
{
|
||||
foreach (XAttribute attribute in element.Attributes())
|
||||
{
|
||||
if (Enum.TryParse(attribute.Name.LocalName, out InputType result))
|
||||
{
|
||||
if (!playerConfigContainsNewChatBinds)
|
||||
{
|
||||
playerConfigContainsNewChatBinds = result == InputType.ActiveChat;
|
||||
}
|
||||
bindings[result] = element.GetAttributeKeyOrMouse(attribute.Name.LocalName, bindings[result]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the old chat binds for configs saved before the introduction of the new chat binds
|
||||
if (!playerConfigContainsNewChatBinds)
|
||||
{
|
||||
if (bindings.ContainsKey(InputType.Chat))
|
||||
{
|
||||
bindings[InputType.Chat] = Keys.None;
|
||||
}
|
||||
if (bindings.ContainsKey(InputType.RadioChat))
|
||||
{
|
||||
bindings[InputType.RadioChat] = Keys.None;
|
||||
}
|
||||
}
|
||||
|
||||
Bindings = bindings.ToImmutableDictionary();
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ namespace Barotrauma
|
||||
/// Should the item spawn even if the container can't contain items of this type
|
||||
/// </summary>
|
||||
public readonly bool SpawnIfCantBeContained;
|
||||
public readonly float Speed;
|
||||
public readonly float Impulse;
|
||||
public readonly float Rotation;
|
||||
public readonly int Count;
|
||||
public readonly float Spread;
|
||||
@@ -198,7 +198,7 @@ namespace Barotrauma
|
||||
|
||||
SpawnIfInventoryFull = element.GetAttributeBool("spawnifinventoryfull", false);
|
||||
SpawnIfCantBeContained = element.GetAttributeBool("spawnifcantbecontained", true);
|
||||
Speed = element.GetAttributeFloat("speed", 0.0f);
|
||||
Impulse = element.GetAttributeFloat("impulse", element.GetAttributeFloat("speed", 0.0f));
|
||||
|
||||
Condition = MathHelper.Clamp(element.GetAttributeFloat("condition", 1.0f), 0.0f, 1.0f);
|
||||
|
||||
@@ -1708,7 +1708,7 @@ namespace Barotrauma
|
||||
throw new NotImplementedException("Spawn rotation type not implemented: " + chosenItemSpawnInfo.RotationType);
|
||||
}
|
||||
body.SetTransform(newItem.SimPosition, rotation);
|
||||
body.ApplyLinearImpulse(Rand.Vector(1) * chosenItemSpawnInfo.Speed);
|
||||
body.ApplyLinearImpulse(Rand.Vector(1) * chosenItemSpawnInfo.Impulse);
|
||||
}
|
||||
}
|
||||
newItem.Condition = newItem.MaxCondition * chosenItemSpawnInfo.Condition;
|
||||
|
||||
@@ -1,3 +1,38 @@
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.18.5.0
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
Chat improvements:
|
||||
- Chat mode (radio/local) can be toggled using a dropdown next to the chat box or with a dedicated "ToggleChatMode" keybind (R by default).
|
||||
- Voice chat now has only one push-to-talk keybind (V by default) which respects the selected chat mode.
|
||||
- There's now a dedicated "ActiveChat" keybind (T by default) to open the chat using the currently active chat mode.
|
||||
- If you want to keep the chat keybinds the way they were (separate keybinds for local and radio), you can rebind the "Chat" and "RadioChat" inputs back to T and R and the new "ToggleChatMode" and "ActiveChat" inputs to something else.
|
||||
|
||||
Changes:
|
||||
- Optimized bot AIs: in particular, the cleanup, repair, pump water and load items objectives. Should significantly improve performance when the bots are doing these objectives when there's a large number of items in the sub.
|
||||
- Optimized entity culling logic (determines which items/structures are currently visible in the screen).
|
||||
- Optimized a bunch of textures.
|
||||
- Improved the performance statistics view that's enabled with the "showperf" console command: more fine-grained stats and easier-to-read visuals.
|
||||
- Added UI volume slider.
|
||||
- Depth charges can be stored in coilgun ammo shelves.
|
||||
|
||||
Fixes:
|
||||
- Fixed ballast flora branches that have been disconnected from the root not being considered disconnected after a level transition (allowing them to keep growing).
|
||||
- Fixed "set default bindings" not doing anything in the settings menu.
|
||||
- Fixed door/hatch gaps not getting moved when snapping to grid in the sub editor.
|
||||
- Vertically mirrored beds can't be laid on.
|
||||
- Fixed wrecked reactors being forced to non-interactable even if made interactable in the sub editor.
|
||||
|
||||
Unstable only:
|
||||
- Fixed crashing when you try to edit beacon station settings on a station you haven't saved yet.
|
||||
- Fixed level difficulties being incorrect in the "normal" difficulty setting (levels were set to the minimum difficulty of the biome, instead of a linear increase across the biome).
|
||||
- Misc fixes and improvements to the new beacon stations.
|
||||
- Fixed "max missions per round" value not being restricted in the UI.
|
||||
- Fixed items not getting transferred to/from linked subs.
|
||||
|
||||
Modding:
|
||||
- Doors and hatches can now be mirrored in the sub editor (making them open from top to bottom, or from right to left).
|
||||
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
v0.18.4.0
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
@@ -12,6 +47,7 @@ Unstable only:
|
||||
- Fixed sprite editor crashing if you try to reload a texture twice.
|
||||
- Fixed drone/shuttles getting left behind in the outpost when you buy and switch to a sub that has a one.
|
||||
- Fixed crashing when closing the submarine preview window.
|
||||
- Disallowed mirroring beds vertically.
|
||||
|
||||
Changes:
|
||||
- Added some new campaign settings: starting balance, amount of starting items and difficulty.
|
||||
@@ -19,13 +55,17 @@ Changes:
|
||||
- Made the descriptions of some materials (that used to just say "useful for crafting") more descriptive.
|
||||
- Increased oxygen generator output in some vanilla subs.
|
||||
- Made handheld sonar beacon sound less grating.
|
||||
- Disallowed mirroring beds vertically.
|
||||
- The client who initiated a vote cannot take part in that vote (except if they're the only client who can vote, in which case the vote automatically passes).
|
||||
- Made flashlight flicker before the battery runs out.
|
||||
- Added some lootable money to corpses found in wrecks.
|
||||
- Removed the small equipment indicators next to the character portrait.
|
||||
- Added a bunch of new UI sounds (tickbox toggling, confirming transactions, increase/decrease sounds for number inputs, cart sound for adding/removing items in store interfaces, selecting/clicking components, sliders and modlist).
|
||||
|
||||
- Optimized many status effects by making them only execute once per second instead of every frame (most importantly, diving suits and volatile fuel rods).
|
||||
- Optimized talents: buffs are applied to characters periodically instead of every frame.
|
||||
- Optimized the logic that bots use to determine the safety of hulls.
|
||||
- Optimized items: stop updating items that don't need to be updated more aggressively.
|
||||
- Weapon holders now use the tag "mountableweapon" instead of "weapon" to determine which items can be placed in them. Allows tagging non-weapon items as mountable in the holder, without making bots consider it a weapon due to the "weapon" tag. Also allows to keep some weapons not-mountable.
|
||||
- Ammunition Shelf can now also store Depth Charges ("depthchargeammo" tag added)
|
||||
|
||||
Fixes:
|
||||
- Split campaign state networking messages into multiple ones. Previously all the campaign-related data (map state, reputation, upgrades, purchased items, selected missions) was included in the same message, and whenever anything in the data changed, the server would send all of it to clients. This would cause performance and bandwidth issues in some situations, for example when reputation was changing rapidly.
|
||||
|
||||
Reference in New Issue
Block a user