diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs index 43c08904d..9e95085aa 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Door.cs @@ -211,24 +211,32 @@ namespace Barotrauma.Items.Components #endif } - private string text = TextManager.Get("DoorMsgCannotOpen"); + private string accessDeniedTxt = TextManager.Get("AccessDenied"); + private bool hasIdCard; public override bool HasRequiredItems(Character character, bool addMessage, string msg = null) { if (item.Condition <= RepairThreshold) return true; //For repairing + var idCard = character.Inventory.FindItemByIdentifier("idcard"); + hasIdCard = requiredItems.Any(ri => ri.Value.Any(r => r.MatchesItem(idCard))); + Msg = hasIdCard ? "ItemMsgOpen" : "ItemMsgForceOpenCrowbar"; + ParseMsg(); + //this is a bit pointless atm because if canBePicked is false it won't allow you to do Pick() anyway, however it's still good for future-proofing. - return requiredItems.Any() ? base.HasRequiredItems(character, addMessage, msg ?? text) : canBePicked; + return requiredItems.Any() ? base.HasRequiredItems(character, addMessage, msg ?? accessDeniedTxt) : canBePicked; } public override bool Pick(Character picker) { - return item.Condition <= RepairThreshold ? true : base.Pick(picker); + if (item.Condition <= RepairThreshold) { return true; } + if (HasRequiredItems(picker, false) && hasIdCard) { return false; } + return base.Pick(picker); } public override bool OnPicked(Character picker) { if (item.Condition <= RepairThreshold) return true; //repairs - if (requiredItems.Any()) + if (requiredItems.Any() && !hasIdCard) { ForceOpen(ActionType.OnPicked); } @@ -247,9 +255,19 @@ namespace Barotrauma.Items.Components { //can only be selected if the item is broken if (item.Condition <= RepairThreshold) return true; //repairs - if (requiredItems.None()) + bool hasRequiredItems = HasRequiredItems(character, false); + if (requiredItems.None() || hasRequiredItems && hasIdCard) { + float originalPickingTime = PickingTime; + PickingTime = 0; ForceOpen(ActionType.OnUse); + PickingTime = originalPickingTime; + } + else if (hasRequiredItems) + { +#if CLIENT + GUI.AddMessage(accessDeniedTxt, Color.Red); +#endif } return false; } diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/ItemComponent.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/ItemComponent.cs index 00a376485..7a0027a89 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/ItemComponent.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/ItemComponent.cs @@ -538,7 +538,6 @@ namespace Barotrauma.Items.Components GameAnalyticsManager.AddErrorEventOnce("ItemComponent.DegreeOfSuccess:CharacterNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); return 0.0f; } - float average = skillSuccessSum / requiredSkills.Count; float skillSuccessSum = 0.0f; for (int i = 0; i < requiredSkills.Count; i++) @@ -582,38 +581,52 @@ namespace Barotrauma.Items.Components { if (!requiredItems.Any()) return true; if (character.Inventory == null) return false; - + bool hasRequiredItems = false; + bool canContinue = true; if (requiredItems.ContainsKey(RelatedItem.RelationType.Equipped)) { foreach (RelatedItem ri in requiredItems[RelatedItem.RelationType.Equipped]) { - if (character.SelectedItems.FirstOrDefault(it => it != null && it.Condition > 0.0f && ri.MatchesItem(it)) == null) + canContinue = CheckItems(ri, character.SelectedItems); + if (!canContinue) { break; } + } + } + if (canContinue) + { + if (requiredItems.ContainsKey(RelatedItem.RelationType.Picked)) + { + foreach (RelatedItem ri in requiredItems[RelatedItem.RelationType.Picked]) { -#if CLIENT - msg = msg ?? ri.Msg; - if (addMessage && !string.IsNullOrEmpty(msg)) - { - GUI.AddMessage(msg, Color.Red); - } -#endif - return false; + if (!CheckItems(ri, character.Inventory.Items)) { break; } } } } - if (requiredItems.ContainsKey(RelatedItem.RelationType.Picked)) - { - foreach (RelatedItem ri in requiredItems[RelatedItem.RelationType.Picked]) - { - if (character.Inventory.Items.FirstOrDefault(it => it != null && it.Condition > 0.0f && ri.MatchesItem(it)) == null) - { + #if CLIENT - msg = msg ?? ri.Msg; - if (addMessage && !string.IsNullOrEmpty(msg)) - { - GUI.AddMessage(msg, Color.Red); - } + if (!hasRequiredItems && addMessage && !string.IsNullOrEmpty(msg)) + { + GUI.AddMessage(msg, Color.Red); + } #endif - return false; + return hasRequiredItems; + + bool CheckItems(RelatedItem relatedItem, IEnumerable itemList) + { + bool Predicate(Item it) => it != null && it.Condition > 0.0f && relatedItem.MatchesItem(it); + bool shouldBreak = false; + if (relatedItem.IsOptional) + { + if (!hasRequiredItems) + { + hasRequiredItems = itemList.Any(Predicate); + } + } + else + { + hasRequiredItems = itemList.Any(Predicate); + if (!hasRequiredItems) + { + shouldBreak = true; } } if (!hasRequiredItems) @@ -625,8 +638,6 @@ namespace Barotrauma.Items.Components } return !shouldBreak; } - - return true; } public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null, Limb targetLimb = null, Character user = null) @@ -771,6 +782,7 @@ namespace Barotrauma.Items.Components { newRequiredItem.statusEffects = prevRequiredItem.statusEffects; newRequiredItem.Msg = prevRequiredItem.Msg; + newRequiredItem.IsOptional = prevRequiredItem.IsOptional; } if (!requiredItems.ContainsKey(newRequiredItem.Type)) diff --git a/Barotrauma/BarotraumaShared/Source/Items/RelatedItem.cs b/Barotrauma/BarotraumaShared/Source/Items/RelatedItem.cs index c2f13f46d..bbbfc6705 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/RelatedItem.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/RelatedItem.cs @@ -16,6 +16,8 @@ namespace Barotrauma Container } + public bool IsOptional { get; set; } + private string[] identifiers; private string[] excludedIdentifiers; @@ -138,7 +140,8 @@ namespace Barotrauma { element.Add( new XAttribute("identifiers", JoinedIdentifiers), - new XAttribute("type", type.ToString())); + new XAttribute("type", type.ToString()), + new XAttribute("optional", IsOptional)); if (excludedIdentifiers.Length > 0) { diff --git a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub index f8cfca265..7c0a77b8f 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub and b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Humpback.sub b/Barotrauma/BarotraumaShared/Submarines/Humpback.sub index 8490b95a4..6bc4c9ba1 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Humpback.sub and b/Barotrauma/BarotraumaShared/Submarines/Humpback.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Orca.sub b/Barotrauma/BarotraumaShared/Submarines/Orca.sub index 02d8316c3..780a762fe 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Orca.sub and b/Barotrauma/BarotraumaShared/Submarines/Orca.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Typhon.sub b/Barotrauma/BarotraumaShared/Submarines/Typhon.sub index da894c6e9..dcdc67b6d 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Typhon.sub and b/Barotrauma/BarotraumaShared/Submarines/Typhon.sub differ