/// <summary> /// Creates possible attributes from the SkillTree nodes. /// Only non unique and not blacklisted attributes are selected. /// </summary> private static IEnumerable <string> CreatePossibleAttributes() { return(from node in SkillTree.Skillnodes.Values from attr in SkillTree.ExpandHybridAttributes(node.Attributes) where !AttributeBlackList.Contains(attr.Key) group attr by attr.Key into attrGroup where attrGroup.Count() > 1 select attrGroup.First().Key); }
/// <summary> /// Loads the attributes from the current tree as AttributeConstraints /// and Check-tags nodes that have unique attributes. /// </summary> /// <remarks> /// Character class changes after calling this method will not influence the attributes /// (which have the old character class calculated into them) /// </remarks> private void LoadAttributesFromTree() { Tree.UntagAllNodes(); var attributes = new Dictionary <string, float>(); foreach (var node in Tree.SkilledNodes) { var skillNode = SkillTree.Skillnodes[node]; var hasUniqueAttribute = false; foreach (var attribute in SkillTree.ExpandHybridAttributes(skillNode.Attributes)) { var attr = attribute.Key; if (_attributes.Contains(attr)) { if (attribute.Value.Count == 0) { continue; } if (attributes.ContainsKey(attr)) { attributes[attr] += attribute.Value[0]; } else { attributes[attr] = attribute.Value[0]; } } else if (!AttributeBlackList.Contains(attr)) { hasUniqueAttribute = true; } } if (hasUniqueAttribute) { Tree.CycleNodeTagForward(skillNode); } } foreach (var attr in CreateInitialAttributes()) { if (attributes.ContainsKey(attr.Key)) { attributes[attr.Key] += attr.Value; } } AttributeConstraints.Clear(); foreach (var attribute in attributes) { AttributeConstraints.Add(new AttributeConstraint(attribute.Key) { TargetValue = attribute.Value }); } }
/// <summary> /// Extracts attributes from the skill tree nodes and fills _nodeAttributes /// and _areTravelNodes. /// </summary> private void ExtractNodeAttributes() { var skillNodes = Settings.SubsetTree.Count > 0 ? Settings.SubsetTree.ToDictionary(id => id, id => SkillTree.Skillnodes[id]) : SkillTree.Skillnodes; _nodeAttributes = new Dictionary <ushort, List <Tuple <int, float> > >(skillNodes.Count); _areTravelNodes = new Dictionary <ushort, bool>(skillNodes.Count); foreach (var node in skillNodes) { var id = node.Key; var skillNode = node.Value; // Remove attributes that have no constraints. // Replace attributes that have constraints with a tuple of their number and the value. // For attributes with more than one value, the first one is selected, // that is reasonable for the attributes the skill tree currently has. // Attributes without value are not supported. If a constraint referencing an attribute // without value slips through, it will break. _nodeAttributes[id] = (from attr in SkillTree.ExpandHybridAttributes(skillNode.Attributes) where _attrNameLookup.ContainsKey(attr.Key) from constraint in _attrNameLookup[attr.Key] let value = attr.Value[0] * _attrConversionMultipliers[Tuple.Create(attr.Key, constraint)] select Tuple.Create(constraint, value)) .ToList(); // Set if the node is a travel node. if (skillNode.Attributes.Count == 1 && TravelNodeRegex.IsMatch(skillNode.Attributes.Keys.First()) && skillNode.Attributes.Values.First().Any(v => (int)v == 10)) { _areTravelNodes[id] = true; } else { _areTravelNodes[id] = false; } } }