public static RelatedItem Load(XElement element) { string nameString = element.GetAttributeString("name", ""); if (nameString == "") { return(null); } string[] names = nameString.Split(','); RelatedItem ri = new RelatedItem(names); try { ri.type = (RelationType)Enum.Parse(typeof(RelationType), element.GetAttributeString("type", "None")); } catch { ri.type = RelationType.None; } ri.Msg = element.GetAttributeString("msg", ""); foreach (XElement subElement in element.Elements()) { if (subElement.Name.ToString().ToLowerInvariant() != "statuseffect") { continue; } ri.statusEffects.Add(StatusEffect.Load(subElement)); } return(ri); }
protected override void Act(float deltaTime) { // Only continue when the get item sub objectives have been completed. if (subObjectives.Any()) { return; } foreach (Repairable repairable in Item.Repairables) { if (!repairable.HasRequiredItems(character, false)) { //make sure we have all the items required to fix the target item foreach (var kvp in repairable.requiredItems) { foreach (RelatedItem requiredItem in kvp.Value) { subObjectives.Add(new AIObjectiveGetItem(character, requiredItem.Identifiers, objectiveManager, true)); } } return; } } if (repairTool == null) { FindRepairTool(); } if (repairTool != null) { var containedItems = repairTool.Item.ContainedItems; if (containedItems == null) { #if DEBUG DebugConsole.ThrowError($"{character.Name}: AIObjectiveRepairItem failed - the item \"" + repairTool + "\" has no proper inventory"); #endif Abandon = true; return; } // Drop empty tanks foreach (Item containedItem in containedItems) { if (containedItem == null) { continue; } if (containedItem.Condition <= 0.0f) { containedItem.Drop(character); } } RelatedItem item = null; Item fuel = null; foreach (RelatedItem requiredItem in repairTool.requiredItems[RelatedItem.RelationType.Contained]) { item = requiredItem; fuel = containedItems.FirstOrDefault(it => it.Condition > 0.0f && requiredItem.MatchesItem(it)); if (fuel != null) { break; } } if (fuel == null) { RemoveSubObjective(ref goToObjective); TryAddSubObjective(ref refuelObjective, () => new AIObjectiveContainItem(character, item.Identifiers, repairTool.Item.GetComponent <ItemContainer>(), objectiveManager), onCompleted: () => RemoveSubObjective(ref refuelObjective), onAbandon: () => Abandon = true); return; } } if (character.CanInteractWith(Item, out _, checkLinked: false)) { HumanAIController.FaceTarget(Item); if (repairTool != null) { OperateRepairTool(deltaTime); } foreach (Repairable repairable in Item.Repairables) { if (repairable.CurrentFixer != null && repairable.CurrentFixer != character) { // Someone else is repairing the target. Abandon the objective if the other is better at this than us. Abandon = repairable.DegreeOfSuccess(character) < repairable.DegreeOfSuccess(repairable.CurrentFixer); } if (!Abandon) { if (character.SelectedConstruction != Item) { if (!Item.TryInteract(character, ignoreRequiredItems: true, forceSelectKey: true) && !Item.TryInteract(character, ignoreRequiredItems: true, forceActionKey: true)) { Abandon = true; } } if (previousCondition == -1) { previousCondition = Item.Condition; } else if (Item.Condition < previousCondition) { // If the current condition is less than the previous condition, we can't complete the task, so let's abandon it. The item is probably deteriorating at a greater speed than we can repair it. Abandon = true; } } if (Abandon) { if (IsRepairing) { character.Speak(TextManager.GetWithVariable("DialogCannotRepair", "[itemname]", Item.Name, true), null, 0.0f, "cannotrepair", 10.0f); } repairable.StopRepairing(character); } else if (repairable.CurrentFixer != character) { repairable.StartRepairing(character, Repairable.FixActions.Repair); } break; } } else { RemoveSubObjective(ref refuelObjective); // If cannot reach the item, approach it. TryAddSubObjective(ref goToObjective, constructor: () => { previousCondition = -1; var objective = new AIObjectiveGoTo(Item, character, objectiveManager) { // Don't stop in ladders, because we can't interact with other items while holding the ladders. endNodeFilter = node => node.Waypoint.Ladders == null }; if (repairTool != null) { objective.CloseEnough = repairTool.Range * 0.75f; } return(objective); }, onAbandon: () => { Abandon = true; if (IsRepairing) { character.Speak(TextManager.GetWithVariable("DialogCannotRepair", "[itemname]", Item.Name, true), null, 0.0f, "cannotrepair", 10.0f); } }); } }
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 <string> convertedIdentifiers = new List <string>(); 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)); } ri.IsOptional = element.GetAttributeBool("optional", false); return(ri); }
protected StatusEffect(XElement element, string parentDebugName) { requiredItems = new List <RelatedItem>(); spawnItems = new List <ItemSpawnInfo>(); Afflictions = new List <Affliction>(); ReduceAffliction = new List <Pair <string, float> >(); tags = new HashSet <string>(element.GetAttributeString("tags", "").Split(',')); Range = element.GetAttributeFloat("range", 0.0f); IEnumerable <XAttribute> attributes = element.Attributes(); List <XAttribute> propertyAttributes = new List <XAttribute>(); propertyConditionals = new List <PropertyConditional>(); foreach (XAttribute attribute in attributes) { switch (attribute.Name.ToString()) { case "type": if (!Enum.TryParse(attribute.Value, true, out type)) { DebugConsole.ThrowError("Invalid action type \"" + attribute.Value + "\" in StatusEffect (" + parentDebugName + ")"); } break; case "target": string[] Flags = attribute.Value.Split(','); foreach (string s in Flags) { if (!Enum.TryParse(s, true, out TargetType targetType)) { DebugConsole.ThrowError("Invalid target type \"" + s + "\" in StatusEffect (" + parentDebugName + ")"); } else { targetTypes |= targetType; } } break; case "disabledeltatime": disableDeltaTime = attribute.GetAttributeBool(false); break; case "setvalue": setValue = attribute.GetAttributeBool(false); break; case "targetnames": DebugConsole.ThrowError("Error in StatusEffect config (" + parentDebugName + ") - use identifiers or tags to define the targets instead of names."); break; case "targetidentifiers": string[] identifiers = attribute.Value.Split(','); targetIdentifiers = new HashSet <string>(); for (int i = 0; i < identifiers.Length; i++) { targetIdentifiers.Add(identifiers[i].Trim().ToLowerInvariant()); } break; case "duration": duration = attribute.GetAttributeFloat(0.0f); break; case "stackable": Stackable = attribute.GetAttributeBool(true); break; case "checkconditionalalways": CheckConditionalAlways = attribute.GetAttributeBool(false); break; case "conditionalcomparison": case "comparison": if (!Enum.TryParse(attribute.Value, out conditionalComparison)) { DebugConsole.ThrowError("Invalid conditional comparison type \"" + attribute.Value + "\" in StatusEffect (" + parentDebugName + ")"); } break; case "sound": DebugConsole.ThrowError("Error in StatusEffect " + element.Parent.Name.ToString() + " - sounds should be defined as child elements of the StatusEffect, not as attributes."); break; default: propertyAttributes.Add(attribute); break; } } int count = propertyAttributes.Count; propertyNames = new string[count]; propertyEffects = new object[count]; int n = 0; foreach (XAttribute attribute in propertyAttributes) { propertyNames[n] = attribute.Name.ToString().ToLowerInvariant(); propertyEffects[n] = XMLExtensions.GetAttributeObject(attribute); n++; } foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) { case "explosion": explosion = new Explosion(subElement, parentDebugName); break; case "fire": FireSize = subElement.GetAttributeFloat("size", 10.0f); break; case "use": case "useitem": useItemCount++; break; case "remove": case "removeitem": removeItem = true; break; case "requireditem": case "requireditems": RelatedItem newRequiredItem = RelatedItem.Load(subElement, parentDebugName); if (newRequiredItem == null) { DebugConsole.ThrowError("Error in StatusEffect config - requires an item with no identifiers."); continue; } requiredItems.Add(newRequiredItem); break; case "conditional": IEnumerable <XAttribute> conditionalAttributes = subElement.Attributes(); foreach (XAttribute attribute in conditionalAttributes) { if (attribute.Name.ToString().ToLowerInvariant() == "targetitemcomponent") { continue; } propertyConditionals.Add(new PropertyConditional(attribute)); } break; case "affliction": AfflictionPrefab afflictionPrefab; if (subElement.Attribute("name") != null) { DebugConsole.ThrowError("Error in StatusEffect (" + parentDebugName + ") - define afflictions using identifiers instead of names."); string afflictionName = subElement.GetAttributeString("name", "").ToLowerInvariant(); afflictionPrefab = AfflictionPrefab.List.Find(ap => ap.Name.ToLowerInvariant() == afflictionName); if (afflictionPrefab == null) { DebugConsole.ThrowError("Error in StatusEffect (" + parentDebugName + ") - Affliction prefab \"" + afflictionName + "\" not found."); continue; } } else { string afflictionIdentifier = subElement.GetAttributeString("identifier", "").ToLowerInvariant(); afflictionPrefab = AfflictionPrefab.List.Find(ap => ap.Identifier.ToLowerInvariant() == afflictionIdentifier); if (afflictionPrefab == null) { DebugConsole.ThrowError("Error in StatusEffect (" + parentDebugName + ") - Affliction prefab with the identifier \"" + afflictionIdentifier + "\" not found."); continue; } } float afflictionStrength = subElement.GetAttributeFloat(1.0f, "amount", "strength"); Afflictions.Add(afflictionPrefab.Instantiate(afflictionStrength)); break; case "reduceaffliction": if (subElement.Attribute("name") != null) { DebugConsole.ThrowError("Error in StatusEffect (" + parentDebugName + ") - define afflictions using identifiers or types instead of names."); ReduceAffliction.Add(new Pair <string, float>( subElement.GetAttributeString("name", "").ToLowerInvariant(), subElement.GetAttributeFloat(1.0f, "amount", "strength", "reduceamount"))); } else { string name = subElement.GetAttributeString("identifier", null) ?? subElement.GetAttributeString("type", null); name = name.ToLowerInvariant(); if (AfflictionPrefab.List.Any(ap => ap.Identifier == name || ap.AfflictionType == name)) { ReduceAffliction.Add(new Pair <string, float>( name, subElement.GetAttributeFloat(1.0f, "amount", "strength", "reduceamount"))); } else { DebugConsole.ThrowError("Error in StatusEffect (" + parentDebugName + ") - Affliction prefab with the identifier or type \"" + name + "\" not found."); } } break; case "spawnitem": var newSpawnItem = new ItemSpawnInfo(subElement, parentDebugName); if (newSpawnItem.ItemPrefab != null) { spawnItems.Add(newSpawnItem); } break; } } InitProjSpecific(element, parentDebugName); }
/// <summary> /// Reloads the ammunition found in the inventory. /// If seekAmmo is true, tries to get find the ammo elsewhere. /// </summary> private bool Reload(bool seekAmmo) { if (WeaponComponent == null) { return(false); } if (!WeaponComponent.requiredItems.ContainsKey(RelatedItem.RelationType.Contained)) { return(false); } var containedItems = Weapon.ContainedItems; // Drop empty ammo foreach (Item containedItem in containedItems) { if (containedItem == null) { continue; } if (containedItem.Condition <= 0) { containedItem.Drop(character); } } RelatedItem item = null; Item ammunition = null; string[] ammunitionIdentifiers = null; foreach (RelatedItem requiredItem in WeaponComponent.requiredItems[RelatedItem.RelationType.Contained]) { ammunition = containedItems.FirstOrDefault(it => it.Condition > 0 && requiredItem.MatchesItem(it)); if (ammunition != null) { // Ammunition still remaining return(true); } item = requiredItem; ammunitionIdentifiers = requiredItem.Identifiers; } // No ammo if (ammunition == null) { if (ammunitionIdentifiers != null) { // Try reload ammunition from inventory ammunition = character.Inventory.FindItem(i => ammunitionIdentifiers.Any(id => id == i.Prefab.Identifier || i.HasTag(id)) && i.Condition > 0, true); if (ammunition != null) { var container = Weapon.GetComponent <ItemContainer>(); if (container.Item.ParentInventory == character.Inventory) { if (!container.Inventory.CanBePut(ammunition)) { return(false); } character.Inventory.RemoveItem(ammunition); if (!container.Inventory.TryPutItem(ammunition, null)) { ammunition.Drop(character); } } else { container.Combine(ammunition, character); } } } } if (WeaponComponent.HasRequiredContainedItems(character, addMessage: false)) { return(true); } else if (ammunition == null && !HoldPosition && initialMode == CombatMode.Offensive && seekAmmo && ammunitionIdentifiers != null) { SeekAmmunition(ammunitionIdentifiers); } return(false); }
public static RelatedItem Load(XElement element, bool returnEmpty, 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 tags or identifiers instead of names."); string[] itemNames = element.GetAttributeStringArray("name", new string[0]); //attempt to convert to identifiers and tags List <string> convertedIdentifiers = new List <string>(); foreach (string itemName in itemNames) { var matchingItem = ItemPrefab.Prefabs.Find(me => me.Name == itemName); if (matchingItem != null) { convertedIdentifiers.Add(matchingItem.Identifier); } else { //no matching item found, this must be a tag convertedIdentifiers.Add(itemName); } } identifiers = convertedIdentifiers.ToArray(); } else { identifiers = element.GetAttributeStringArray("items", null, convertToLowerInvariant: true) ?? element.GetAttributeStringArray("item", null, convertToLowerInvariant: true); if (identifiers == null) { identifiers = element.GetAttributeStringArray("identifiers", null, convertToLowerInvariant: true) ?? element.GetAttributeStringArray("tags", null, convertToLowerInvariant: true); if (identifiers == null) { identifiers = element.GetAttributeStringArray("identifier", null, convertToLowerInvariant: true) ?? element.GetAttributeStringArray("tag", new string[0], convertToLowerInvariant: true); } } } string[] excludedIdentifiers = element.GetAttributeStringArray("excludeditems", null, convertToLowerInvariant: true) ?? element.GetAttributeStringArray("excludeditem", null, convertToLowerInvariant: true); if (excludedIdentifiers == null) { excludedIdentifiers = element.GetAttributeStringArray("excludedidentifiers", null, convertToLowerInvariant: true) ?? element.GetAttributeStringArray("excludedtags", null, convertToLowerInvariant: true); if (excludedIdentifiers == null) { excludedIdentifiers = element.GetAttributeStringArray("excludedidentifier", null, convertToLowerInvariant: true) ?? element.GetAttributeStringArray("excludedtag", new string[0], convertToLowerInvariant: true); } } if (identifiers.Length == 0 && excludedIdentifiers.Length == 0 && !returnEmpty) { return(null); } RelatedItem ri = new RelatedItem(identifiers, excludedIdentifiers); string typeStr = element.GetAttributeString("type", ""); if (string.IsNullOrEmpty(typeStr)) { switch (element.Name.ToString().ToLowerInvariant()) { case "containable": typeStr = "Contained"; break; case "suitablefertilizer": case "suitableseed": typeStr = "None"; break; } } if (!Enum.TryParse(typeStr, true, out ri.type)) { DebugConsole.ThrowError("Error in RelatedItem config (" + parentDebugName + ") - \"" + typeStr + "\" is not a valid relation type."); return(null); } ri.MsgTag = element.GetAttributeString("msg", ""); string msg = TextManager.Get(ri.MsgTag, true); if (msg == null) { ri.Msg = ri.MsgTag; } else { #if CLIENT foreach (InputType inputType in Enum.GetValues(typeof(InputType))) { msg = msg.Replace("[" + inputType.ToString().ToLowerInvariant() + "]", GameMain.Config.KeyBindText(inputType)); } ri.Msg = msg; #endif } foreach (XElement subElement in element.Elements()) { if (!subElement.Name.ToString().Equals("statuseffect", StringComparison.OrdinalIgnoreCase)) { continue; } ri.statusEffects.Add(StatusEffect.Load(subElement, parentDebugName)); } ri.IsOptional = element.GetAttributeBool("optional", false); ri.IgnoreInEditor = element.GetAttributeBool("ignoreineditor", false); ri.MatchOnEmpty = element.GetAttributeBool("matchonempty", false); return(ri); }
protected StatusEffect(XElement element) { requiredItems = new List <RelatedItem>(); #if CLIENT particleEmitters = new List <ParticleEmitterPrefab>(); #endif IEnumerable <XAttribute> attributes = element.Attributes(); List <XAttribute> propertyAttributes = new List <XAttribute>(); foreach (XAttribute attribute in attributes) { switch (attribute.Name.ToString()) { case "type": try { type = (ActionType)Enum.Parse(typeof(ActionType), attribute.Value, true); } catch { string[] split = attribute.Value.Split('='); type = (ActionType)Enum.Parse(typeof(ActionType), split[0], true); string[] containingNames = split[1].Split(','); onContainingNames = new HashSet <string>(); for (int i = 0; i < containingNames.Length; i++) { onContainingNames.Add(containingNames[i].Trim()); } } break; case "target": string[] Flags = attribute.Value.Split(','); foreach (string s in Flags) { targetTypes |= (TargetType)Enum.Parse(typeof(TargetType), s, true); } break; case "disabledeltatime": disableDeltaTime = ToolBox.GetAttributeBool(attribute, false); break; case "setvalue": setValue = ToolBox.GetAttributeBool(attribute, false); break; case "targetnames": string[] names = attribute.Value.Split(','); targetNames = new HashSet <string>(); for (int i = 0; i < names.Length; i++) { targetNames.Add(names[i].Trim()); } break; case "duration": duration = ToolBox.GetAttributeFloat(attribute, 0.0f); break; #if CLIENT case "sound": sound = Sound.Load(attribute.Value.ToString()); break; #endif default: propertyAttributes.Add(attribute); break; } } int count = propertyAttributes.Count; propertyNames = new string[count]; propertyEffects = new object[count]; int n = 0; foreach (XAttribute attribute in propertyAttributes) { propertyNames[n] = attribute.Name.ToString().ToLowerInvariant(); propertyEffects[n] = ToolBox.GetAttributeObject(attribute); n++; } foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) { case "explosion": explosion = new Explosion(subElement); break; case "fire": FireSize = ToolBox.GetAttributeFloat(subElement, "size", 10.0f); break; case "use": case "useitem": useItem = true; break; case "requireditem": case "requireditems": RelatedItem newRequiredItem = RelatedItem.Load(subElement); if (newRequiredItem == null) { continue; } requiredItems.Add(newRequiredItem); break; #if CLIENT case "particleemitter": particleEmitters.Add(new ParticleEmitterPrefab(subElement)); break; #endif } } }
protected StatusEffect(XElement element) { requiredItems = new List <RelatedItem>(); tags = new HashSet <string>(element.GetAttributeString("tags", "").Split(',')); #if CLIENT particleEmitters = new List <ParticleEmitter>(); #endif IEnumerable <XAttribute> attributes = element.Attributes(); List <XAttribute> propertyAttributes = new List <XAttribute>(); propertyConditionals = new List <PropertyConditional>(); foreach (XAttribute attribute in attributes) { switch (attribute.Name.ToString()) { case "type": try { type = (ActionType)Enum.Parse(typeof(ActionType), attribute.Value, true); } catch { string[] split = attribute.Value.Split('='); type = (ActionType)Enum.Parse(typeof(ActionType), split[0], true); string[] containingNames = split[1].Split(','); onContainingNames = new HashSet <string>(); for (int i = 0; i < containingNames.Length; i++) { onContainingNames.Add(containingNames[i].Trim()); } } break; case "target": string[] Flags = attribute.Value.Split(','); foreach (string s in Flags) { targetTypes |= (TargetType)Enum.Parse(typeof(TargetType), s, true); } break; case "disabledeltatime": disableDeltaTime = attribute.GetAttributeBool(false); break; case "setvalue": setValue = attribute.GetAttributeBool(false); break; case "targetnames": string[] names = attribute.Value.Split(','); targetNames = new HashSet <string>(); for (int i = 0; i < names.Length; i++) { targetNames.Add(names[i].Trim()); } break; case "duration": duration = attribute.GetAttributeFloat(0.0f); break; case "stackable": Stackable = attribute.GetAttributeBool(true); break; case "checkconditionalalways": CheckConditionalAlways = attribute.GetAttributeBool(false); break; case "sound": DebugConsole.ThrowError("Error in StatusEffect " + element.Parent.Name.ToString() + " - sounds should be defined as child elements of the StatusEffect, not as attributes."); break; default: propertyAttributes.Add(attribute); break; } } int count = propertyAttributes.Count; propertyNames = new string[count]; propertyEffects = new object[count]; int n = 0; foreach (XAttribute attribute in propertyAttributes) { propertyNames[n] = attribute.Name.ToString().ToLowerInvariant(); propertyEffects[n] = XMLExtensions.GetAttributeObject(attribute); n++; } foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) { case "explosion": explosion = new Explosion(subElement); break; case "fire": FireSize = subElement.GetAttributeFloat("size", 10.0f); break; case "use": case "useitem": useItemCount++; break; case "remove": case "removeitem": removeItem = true; break; case "requireditem": case "requireditems": RelatedItem newRequiredItem = RelatedItem.Load(subElement); if (newRequiredItem == null) { continue; } requiredItems.Add(newRequiredItem); break; case "conditional": IEnumerable <XAttribute> conditionalAttributes = subElement.Attributes(); foreach (XAttribute attribute in conditionalAttributes) { propertyConditionals.Add(new PropertyConditional(attribute)); } break; #if CLIENT case "particleemitter": particleEmitters.Add(new ParticleEmitter(subElement)); break; case "sound": sound = Sound.Load(subElement); loopSound = subElement.GetAttributeBool("loop", false); break; #endif } } }
/// <summary> /// Reloads the ammunition found in the inventory. /// If seekAmmo is true and the condition is met or not provided, tries to get find the ammo elsewhere. /// </summary> private bool Reload(bool seekAmmo, Func <bool> condition = null) { if (WeaponComponent == null) { return(false); } if (!WeaponComponent.requiredItems.ContainsKey(RelatedItem.RelationType.Contained)) { return(false); } var containedItems = Weapon.ContainedItems; RelatedItem item = null; Item ammunition = null; string[] ammunitionIdentifiers = null; foreach (RelatedItem requiredItem in WeaponComponent.requiredItems[RelatedItem.RelationType.Contained]) { ammunition = containedItems.FirstOrDefault(it => it.Condition > 0.0f && requiredItem.MatchesItem(it)); if (ammunition != null) { // Ammunition still remaining return(true); } item = requiredItem; ammunitionIdentifiers = requiredItem.Identifiers; } // No ammo if (ammunition == null) { var container = Weapon.GetComponent <ItemContainer>(); // Try reload ammunition in inventory foreach (string identifier in ammunitionIdentifiers) { foreach (var i in character.Inventory.Items) { if (i == null) { continue; } if (i.Prefab.Identifier == identifier || i.HasTag(identifier)) { if (i.Condition > 0) { container.Inventory.TryPutItem(ammunition, null); } } } } } if (WeaponComponent.HasRequiredContainedItems(false)) { return(true); } else if (ammunition == null) { if (seekAmmo && ammunitionIdentifiers != null && (condition == null || condition())) { SeekAmmunition(ammunitionIdentifiers); } } return(false); }