using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; namespace Barotrauma { class RelatedItem { public enum RelationType { None, Contained, Equipped, Picked, Container } private string[] identifiers; private string[] excludedIdentifiers; private RelationType type; public List statusEffects; public string Msg; public RelationType Type { get { return type; } } public string JoinedIdentifiers { get { return string.Join(",", identifiers); } set { if (value == null) return; identifiers = value.Split(','); for (int i = 0; i < identifiers.Length; i++) { identifiers[i] = identifiers[i].Trim().ToLowerInvariant(); } } } public string[] Identifiers { get { return identifiers; } } public string JoinedExcludedIdentifiers { get { return string.Join(",", excludedIdentifiers); } set { if (value == null) return; excludedIdentifiers = value.Split(','); for (int i = 0; i < excludedIdentifiers.Length; i++) { excludedIdentifiers[i] = excludedIdentifiers[i].Trim().ToLowerInvariant(); } } } public bool MatchesItem(Item item) { if (item == null) return false; if (excludedIdentifiers.Any(id => item.Prefab.Identifier == id || item.HasTag(id))) return false; return identifiers.Any(id => item.Prefab.Identifier == id || item.HasTag(id)); } public RelatedItem(string[] identifiers, string[] excludedIdentifiers) { for (int i = 0; i < identifiers.Length; i++) { identifiers[i] = identifiers[i].Trim().ToLowerInvariant(); } this.identifiers = identifiers; for (int i = 0; i < excludedIdentifiers.Length; i++) { excludedIdentifiers[i] = excludedIdentifiers[i].Trim().ToLowerInvariant(); } this.excludedIdentifiers = excludedIdentifiers; statusEffects = new List(); } public bool CheckRequirements(Character character, Item parentItem) { switch (type) { case RelationType.Contained: if (parentItem == null) return false; var containedItems = parentItem.ContainedItems; if (containedItems == null) return false; foreach (Item contained in containedItems) { if (contained.Condition > 0.0f && MatchesItem(contained)) return true; } break; case RelationType.Container: if (parentItem == null || parentItem.Container == null) return false; return parentItem.Container.Condition > 0.0f && MatchesItem(parentItem.Container); case RelationType.Equipped: if (character == null) return false; foreach (Item equippedItem in character.SelectedItems) { if (equippedItem == null) continue; if (equippedItem.Condition > 0.0f && MatchesItem(equippedItem)) return true; } break; case RelationType.Picked: if (character == null || character.Inventory == null) return false; foreach (Item pickedItem in character.Inventory.Items) { if (pickedItem == null) continue; if (MatchesItem(pickedItem)) return true; } break; default: return true; } return false; } public void Save(XElement element) { element.Add( new XAttribute("identifiers", JoinedIdentifiers), new XAttribute("type", type.ToString())); if (excludedIdentifiers.Length > 0) { element.Add(new XAttribute("excludedidentifiers", JoinedExcludedIdentifiers)); } if (!string.IsNullOrWhiteSpace(Msg)) element.Add(new XAttribute("msg", Msg)); } public static RelatedItem Load(XElement element, string parentDebugName) { string[] identifiers; if (element.Attribute("name") != null) { //backwards compatibility + a console warning DebugConsole.ThrowError("Error in RelatedItem config (" + (string.IsNullOrEmpty(parentDebugName) ? element.ToString() : parentDebugName) + ") - use item identifiers or tags instead of names."); string[] itemNames = element.GetAttributeStringArray("name", new string[0]); //attempt to convert to identifiers and tags List convertedIdentifiers = new List(); foreach (string itemName in itemNames) { if (MapEntityPrefab.List.Find(me => me.Name == itemName) is ItemPrefab matchingItem) { convertedIdentifiers.Add(matchingItem.Identifier); } else { //no matching item found, this must be a tag convertedIdentifiers.Add(itemName); } } identifiers = convertedIdentifiers.ToArray(); } else { identifiers = element.GetAttributeStringArray("identifiers", new string[0]); if (identifiers.Length == 0) identifiers = element.GetAttributeStringArray("identifier", new string[0]); } string[] excludedIdentifiers = element.GetAttributeStringArray("excludedidentifiers", new string[0]); if (excludedIdentifiers.Length == 0) excludedIdentifiers = element.GetAttributeStringArray("excludedidentifier", new string[0]); if (identifiers.Length == 0 && excludedIdentifiers.Length == 0) return null; RelatedItem ri = new RelatedItem(identifiers, excludedIdentifiers); string typeStr = element.GetAttributeString("type", ""); if (string.IsNullOrEmpty(typeStr)) { if (element.Name.ToString().ToLowerInvariant() == "containable") typeStr = "Contained"; } if (!Enum.TryParse(typeStr, true, out ri.type)) { DebugConsole.ThrowError("Error in RelatedItem config ("+parentDebugName+") - \""+ typeStr +"\" is not a valid relation type."); return null; } string msgTag = element.GetAttributeString("msg", ""); string msg = TextManager.Get(msgTag, true); if (msg == null) { ri.Msg = msgTag; } else { #if CLIENT foreach (InputType inputType in Enum.GetValues(typeof(InputType))) { msg = msg.Replace("[" + inputType.ToString().ToLowerInvariant() + "]", GameMain.Config.KeyBind(inputType).ToString()); } ri.Msg = msg; #endif } foreach (XElement subElement in element.Elements()) { if (subElement.Name.ToString().ToLowerInvariant() != "statuseffect") continue; ri.statusEffects.Add(StatusEffect.Load(subElement, parentDebugName)); } return ri; } } }