private static bool DetermineWeaponLocal(ModLocation location, string attr) { if (attr == "#% increased Physical Damage") { // Implicit increased physical damage is global return(location != ModLocation.Implicit); } if (attr == "+# to Accuracy Rating") { // Crafted accuracy is global return(location != ModLocation.Crafted); } if (attr.StartsWith("Adds ") && (attr.EndsWith(" Damage") || attr.EndsWith(" Damage in Main Hand") || attr.EndsWith(" Damage in Off Hand"))) { return(true); } return(attr == "#% increased Attack Speed" || attr == "#% increased Accuracy Rating" || attr == "#% increased Critical Strike Chance" || attr.Contains("Damage Leeched as") || attr.Contains("Critical Strike Chance with this Weapon") || attr.Contains("Critical Strike Damage Multiplier with this Weapon") || attr == "+# to Weapon range"); }
private IEnumerable <ItemMod> CreateItemMods(ModLocation location, IEnumerable <StatIdValuePair> statValuePairs) { if (statValuePairs == null) { yield break; } // this list is used to translate the stats in order of appearance, // using merged.Keys wouldn't guarantee that var statIds = new List <string>(); var merged = new Dictionary <string, int>(); foreach (var pair in statValuePairs) { var stat = pair.StatId; statIds.Add(stat); var value = pair.Value; if (merged.ContainsKey(stat)) { value += merged[stat]; } merged[stat] = value; } var lines = EquipmentData.StatTranslator.GetTranslations(statIds) .Select(t => t.Translate(merged)) .Where(l => l != null); foreach (var line in lines) { var attr = ItemMod.Numberfilter.Replace(line, "#"); var isLocal = StatLocalityChecker.DetermineLocal(SelectedBase.ItemClass, location, attr); yield return(new ItemMod(line, isLocal)); } }
private ItemMod ItemModFromJson(JToken jsonMod, ModLocation location) { var valuePairs = (from a in jsonMod["values"] let vc = (ValueColoring)a[1].Value <int>() select new { Value = a[0].Value <string>(), ValueColor = vc }).ToList(); var values = valuePairs.Select(p => p.Value).ToList(); var valueColors = (from p in valuePairs let valueCount = ItemMod.Numberfilter.Matches(p.Value).Count select Enumerable.Repeat(p.ValueColor, valueCount)) .Flatten(); /* displayMode: * - 0: `attribute = name + ": " + values.Join(", ")` if in "properties" or `attribute = name + " " + value` if in "requirements" * - 1: `attribute = values.Join(", ") + " " + name` * - 2: experience bar for gems, not applicable * - 3: `attribute = name.Replace(%i with values[i])` */ var name = jsonMod["name"].Value <string>(); var mode0Separator = location == ModLocation.Requirement ? " " : ": "; string attribute; if (values.Any() && !string.IsNullOrEmpty(name)) { switch (int.Parse(jsonMod["displayMode"].Value <string>(), CultureInfo.InvariantCulture)) { case 0: attribute = name + mode0Separator + string.Join(", ", values); break; case 1: attribute = string.Join(", ", values) + " " + name; break; case 2: throw new NotSupportedException("Experience bar display mode is not supported."); case 3: attribute = Regex.Replace(name, @"%\d", m => values[int.Parse(m.Value.Substring(1))]); break; default: throw new NotSupportedException("Unsupported display mode: " + jsonMod["displayMode"].Value <string>()); } } else if (string.IsNullOrEmpty(name)) { attribute = string.Join(", ", values); } else { attribute = name; } return(ItemModFromString(attribute, location, valueColors)); }
private ItemMod ItemModFromString(string attribute, ModLocation location, IEnumerable <ValueColoring> valueColor = null) { var isLocal = StatLocalityChecker.DetermineLocal(ItemClass, location, attribute); var itemMod = new ItemMod(attribute, isLocal); if (valueColor != null) { itemMod.ValueColors = valueColor.ToList(); } return(itemMod); }
/// <summary> /// Determines whether a <see cref="ItemMod"/> with the given text, class and location is applied /// locally or not /// </summary> public static bool DetermineLocal(ItemClass itemclass, ModLocation location, string attr) { if (location == ModLocation.Property || location == ModLocation.Requirement) { // local or not doesn't really apply to properties and requirements return(true); } if (attr == "#% reduced Attribute Requirements" || attr.Contains("+# to Level of Socketed ")) { return(true); } if (attr == "+#% Chance to Block") { // Chance to Block is only local on shields. return(itemclass == ItemClass.Shield); } switch (itemclass) { case ItemClass.Belt: case ItemClass.Ring: case ItemClass.Amulet: case ItemClass.Quiver: case ItemClass.Jewel: case ItemClass.ActiveSkillGem: case ItemClass.SupportSkillGem: // These item classes have no local mods. return(false); case ItemClass.OneHandSword: case ItemClass.ThrustingOneHandSword: case ItemClass.OneHandAxe: case ItemClass.OneHandMace: case ItemClass.Sceptre: case ItemClass.Dagger: case ItemClass.Claw: case ItemClass.Wand: case ItemClass.FishingRod: case ItemClass.TwoHandSword: case ItemClass.TwoHandAxe: case ItemClass.TwoHandMace: case ItemClass.Bow: case ItemClass.Staff: return(DetermineWeaponLocal(location, attr)); case ItemClass.Shield: case ItemClass.Boots: case ItemClass.BodyArmour: case ItemClass.Gloves: case ItemClass.Helmet: return(DetermineArmourLocal(attr)); case ItemClass.LifeFlask: case ItemClass.ManaFlask: case ItemClass.HybridFlask: case ItemClass.UtilityFlask: case ItemClass.CriticalUtilityFlask: case ItemClass.Unknown: case ItemClass.Any: // These item classes are not supported. return(false); default: throw new ArgumentOutOfRangeException(nameof(itemclass), itemclass, "Unsupported item class"); } }