public void ProcessItem(IdentResponse item) { TotalSpells += item.Spells.Count; if (item.Spells.Count < MinSpells) { MinSpells = item.Spells.Count; } if (item.Spells.Count > MaxSpells) { MaxSpells = item.Spells.Count; } foreach (var id in item.Spells) { var spell = SpellTools.GetSpell(id); HitsByBuffLevels.TryGetValue(spell.BuffLevel, out var count1); count1++; HitsByBuffLevels[spell.BuffLevel] = count1; HitsByCantrip.TryGetValue(spell.CantripLevel, out var count2); count2++; HitsByCantrip[spell.CantripLevel] = count2; HitsBySpellID.TryGetValue(id, out var count3); count3++; HitsBySpellID[id] = count3; } }
public void ProcessItem(IdentResponse item) { TotalItems++; TotalSpells += item.Spells.Count; if (item.Spells.Count < MinSpells) { MinSpells = item.Spells.Count; } if (item.Spells.Count > MaxSpells) { MaxSpells = item.Spells.Count; } var cantripCount = 0; var buffCount = 0; foreach (var id in item.Spells) { var spell = SpellTools.GetSpell(id); if (spell.BuffLevel != Spell.BuffLevels.None) { HitsByBuffLevels.TryGetValue(spell.BuffLevel, out var count1); count1++; HitsByBuffLevels[spell.BuffLevel] = count1; buffCount++; } if (spell.CantripLevel != Spell.CantripLevels.None) { HitsByCantrip.TryGetValue(spell.CantripLevel, out var count2); count2++; HitsByCantrip[spell.CantripLevel] = count2; cantripCount++; } HitsBySpellID.TryGetValue(id, out var count3); count3++; HitsBySpellID[id] = count3; } if (!BuffLevelCountHits.ContainsKey(buffCount)) { BuffLevelCountHits.Add(buffCount, 0); } BuffLevelCountHits[buffCount]++; if (!CantripCountHits.ContainsKey(cantripCount)) { CantripCountHits.Add(cantripCount, 0); } CantripCountHits[cantripCount]++; }
/// <summary> /// This will init ItemSetID and CachedSpells. /// </summary> public void BuiltItemSearchCache() { ItemSetId = IntValues.ContainsKey(265) ? IntValues[265] : 0; foreach (var spellId in Spells) { try { Spell spell = SpellTools.GetSpell(spellId); cachedSpells.Add(spell); } catch (ArgumentException) { MessageBox.Show("Unable to cache spell id: " + spellId + " on item: " + Name + ". Spell ID not found in the master table."); } } }
internal static void init(IModEvents events, IInputHelper inputHelper, Func <long> getNewId) { MoreMagic.events = events; MoreMagic.inputHelper = inputHelper; SpaceEvents.ActionActivated += actionTriggered; // Inject our new schools SchoolTools schoolTools = new SchoolTools(); schoolTools.Populate(); // Inject our new spells SpellTools spellTools = new SpellTools(); spellTools.Populate(); OnAnalyzeCast += onAnalyze; }
public string ToString(bool showBuffedValues, bool showValueAndBurden) { System.Text.StringBuilder sb = new System.Text.StringBuilder(); if (mwo.Values(IntValueKey.Material) > 0) { if (Dictionaries.MaterialInfo.ContainsKey(mwo.Values(IntValueKey.Material))) { sb.Append(Dictionaries.MaterialInfo[mwo.Values(IntValueKey.Material)] + " "); } else { sb.Append("unknown material " + mwo.Values(IntValueKey.Material) + " "); } } sb.Append(mwo.Name); if (mwo.Values((IntValueKey)353) > 0) { if (Dictionaries.MasteryInfo.ContainsKey(mwo.Values((IntValueKey)353))) { sb.Append(" (" + Dictionaries.MasteryInfo[mwo.Values((IntValueKey)353)] + ")"); } else { sb.Append(" (Unknown mastery " + mwo.Values((IntValueKey)353) + ")"); } } int set = mwo.Values((IntValueKey)265, 0); if (set != 0) { sb.Append(", "); if (Dictionaries.AttributeSetInfo.ContainsKey(set)) { sb.Append(Dictionaries.AttributeSetInfo[set]); } else { sb.Append("Unknown set " + set); } } if (mwo.Values(IntValueKey.ArmorLevel) > 0) { sb.Append(", AL " + mwo.Values(IntValueKey.ArmorLevel)); } if (mwo.Values(IntValueKey.Imbued) > 0) { sb.Append(","); if ((mwo.Values(IntValueKey.Imbued) & 1) == 1) { sb.Append(" CS"); } if ((mwo.Values(IntValueKey.Imbued) & 2) == 2) { sb.Append(" CB"); } if ((mwo.Values(IntValueKey.Imbued) & 4) == 4) { sb.Append(" AR"); } if ((mwo.Values(IntValueKey.Imbued) & 8) == 8) { sb.Append(" SlashRend"); } if ((mwo.Values(IntValueKey.Imbued) & 16) == 16) { sb.Append(" PierceRend"); } if ((mwo.Values(IntValueKey.Imbued) & 32) == 32) { sb.Append(" BludgeRend"); } if ((mwo.Values(IntValueKey.Imbued) & 64) == 64) { sb.Append(" AcidRend"); } if ((mwo.Values(IntValueKey.Imbued) & 128) == 128) { sb.Append(" FrostRend"); } if ((mwo.Values(IntValueKey.Imbued) & 256) == 256) { sb.Append(" LightRend"); } if ((mwo.Values(IntValueKey.Imbued) & 512) == 512) { sb.Append(" FireRend"); } if ((mwo.Values(IntValueKey.Imbued) & 1024) == 1024) { sb.Append(" MeleeImbue"); } if ((mwo.Values(IntValueKey.Imbued) & 4096) == 4096) { sb.Append(" MagicImbue"); } if ((mwo.Values(IntValueKey.Imbued) & 8192) == 8192) { sb.Append(" Hematited"); } if ((mwo.Values(IntValueKey.Imbued) & 536870912) == 536870912) { sb.Append(" MagicAbsorb"); } } if (mwo.Values(IntValueKey.NumberTimesTinkered) > 0) { sb.Append(", Tinks " + mwo.Values(IntValueKey.NumberTimesTinkered)); } if (mwo.Values(IntValueKey.MaxDamage) != 0 && mwo.Values(DoubleValueKey.Variance) != 0) { sb.Append(", " + (mwo.Values(IntValueKey.MaxDamage) - (mwo.Values(IntValueKey.MaxDamage) * mwo.Values(DoubleValueKey.Variance))).ToString("N2") + "-" + mwo.Values(IntValueKey.MaxDamage)); } else if (mwo.Values(IntValueKey.MaxDamage) != 0 && mwo.Values(DoubleValueKey.Variance) == 0) { sb.Append(", " + mwo.Values(IntValueKey.MaxDamage)); } if (mwo.Values(IntValueKey.ElementalDmgBonus, 0) != 0) { sb.Append(", +" + mwo.Values(IntValueKey.ElementalDmgBonus)); } if (mwo.Values(DoubleValueKey.DamageBonus, 1) != 1) { sb.Append(", +" + Math.Round(((mwo.Values(DoubleValueKey.DamageBonus) - 1) * 100)) + "%"); } if (mwo.Values(DoubleValueKey.ElementalDamageVersusMonsters, 1) != 1) { sb.Append(", +" + Math.Round(((mwo.Values(DoubleValueKey.ElementalDamageVersusMonsters) - 1) * 100)) + "%vs. Monsters"); } if (mwo.Values(DoubleValueKey.AttackBonus, 1) != 1) { sb.Append(", +" + Math.Round(((mwo.Values(DoubleValueKey.AttackBonus) - 1) * 100)) + "%a"); } if (mwo.Values(DoubleValueKey.MeleeDefenseBonus, 1) != 1) { sb.Append(", " + Math.Round(((mwo.Values(DoubleValueKey.MeleeDefenseBonus) - 1) * 100)) + "%md"); } if (mwo.Values(DoubleValueKey.MagicDBonus, 1) != 1) { sb.Append(", " + Math.Round(((mwo.Values(DoubleValueKey.MagicDBonus) - 1) * 100), 1) + "%mgc.d"); } if (mwo.Values(DoubleValueKey.MissileDBonus, 1) != 1) { sb.Append(", " + Math.Round(((mwo.Values(DoubleValueKey.MissileDBonus) - 1) * 100), 1) + "%msl.d"); } if (mwo.Values(DoubleValueKey.ManaCBonus) != 0) { sb.Append(", " + Math.Round((mwo.Values(DoubleValueKey.ManaCBonus) * 100)) + "%mc"); } if (showBuffedValues && (mwo.ObjectClass == (int)ObjectClass.MeleeWeapon || mwo.ObjectClass == (int)ObjectClass.MissileWeapon || mwo.ObjectClass == (int)ObjectClass.WandStaffOrb)) { sb.Append(", ("); // (Damage) if (mwo.ObjectClass == (int)ObjectClass.MeleeWeapon) { sb.Append(mwo.CalcedBuffedTinkedDoT.ToString("N1") + "/" + mwo.GetBuffedIntValueKey((int)IntValueKey.MaxDamage)); } if (mwo.ObjectClass == (int)ObjectClass.MissileWeapon) { sb.Append(mwo.CalcedBuffedMissileDamage.ToString("N1")); } if (mwo.ObjectClass == (int)ObjectClass.WandStaffOrb) { sb.Append(((mwo.GetBuffedDoubleValueKey((int)DoubleValueKey.ElementalDamageVersusMonsters) - 1) * 100).ToString("N1")); } // (AttackBonus/MeleeDefenseBonus/ManaCBonus) sb.Append(" "); if (mwo.Values(DoubleValueKey.AttackBonus, 1) != 1) { sb.Append(Math.Round(((mwo.GetBuffedDoubleValueKey((int)DoubleValueKey.AttackBonus) - 1) * 100)).ToString("N1") + "/"); } if (mwo.Values(DoubleValueKey.MeleeDefenseBonus, 1) != 1) { sb.Append(Math.Round(((mwo.GetBuffedDoubleValueKey((int)DoubleValueKey.MeleeDefenseBonus) - 1) * 100)).ToString("N1")); } if (mwo.Values(DoubleValueKey.ManaCBonus) != 0) { sb.Append("/" + Math.Round(mwo.GetBuffedDoubleValueKey((int)DoubleValueKey.ManaCBonus) * 100)); } sb.Append(")"); } if (mwo.Spells.Count > 0) { List <int> sortedSpellIds = new List <int>(); foreach (var spell in mwo.Spells) { sortedSpellIds.Add(spell); } sortedSpellIds.Sort(); sortedSpellIds.Reverse(); foreach (int spellId in sortedSpellIds) { Spell spell = SpellTools.GetSpell(spellId); if (spell == null) { continue; } // If the item is not loot generated, show all spells if (!mwo.IntValues.ContainsKey((int)IntValueKey.Material)) { goto ShowSpell; } // Always show Minor/Major/Epic Impen if (spell.Name.Contains("Minor Impenetrability") || spell.Name.Contains("Major Impenetrability") || spell.Name.Contains("Epic Impenetrability") || spell.Name.Contains("Legendary Impenetrability")) { goto ShowSpell; } // Always show trinket spells if (spell.Name.Contains("Augmented")) { goto ShowSpell; } if (mwo.Values(IntValueKey.Unenchantable, 0) != 0) { // Show banes and impen on unenchantable equipment if (spell.Name.Contains(" Bane") || spell.Name.Contains("Impen") || spell.Name.StartsWith("Brogard")) { goto ShowSpell; } } else { // Hide banes and impen on enchantable equipment if (spell.Name.Contains(" Bane") || spell.Name.Contains("Impen") || spell.Name.StartsWith("Brogard")) { continue; } } //Debug.WriteToChat(spellById.Name + ", Difficulty: " + spellById.Difficulty + ", Family: " + spellById.Family + ", Generation: " + spellById.Generation + ", Type: " + spellById.Type + ", " + spellById.Unknown1 + " " + spellById.Unknown2 + " " + spellById.Unknown3 + " " + spellById.Unknown4 + " " + spellById.Unknown5 + " " + spellById.Unknown6 + " " + spellById.Unknown7 + " " + spellById.Unknown8 + " " + spellById.Unknown9 + " " + spellById.Unknown10); // <{Mag-Tools}>: Major Coordination, Difficulty: 15, Family: 267, Generation: 1, Type: 1, 0 1 1 2572 -2.07525870829232E+20 0 0 0 0 0 // <{Mag-Tools}>: Epic Magic Resistance, Difficulty: 20, Family: 299, Generation: 1, Type: 1, 0 1 1 4704 -2.07525870829232E+20 0 0 0 0 0 // <{Mag-Tools}>: Epic Life Magic Aptitude, Difficulty: 20, Family: 357, Generation: 1, Type: 1, 0 1 1 4700 -2.07525870829232E+20 0 0 0 0 0 // <{Mag-Tools}>: Epic Endurance, Difficulty: 20, Family: 263, Generation: 1, Type: 1, 0 1 1 4226 -2.07525870829232E+20 0 0 0 0 0 // <{Mag-Tools}>: Essence Glutton, Difficulty: 30, Family: 279, Generation: 1, Type: 1, 0 0 1 2666 -2.07525870829232E+20 0 0 0 0 0 // <{Mag-Tools}>: Might of the Lugians, Difficulty: 300, Family: 1, Generation: 1, Type: 1, 0 0 1 2087 -2.07525870829232E+20 0 0 0 0 0 // <{Mag-Tools}>: Executor's Blessing, Difficulty: 300, Family: 115, Generation: 1, Type: 1, 0 0 1 2053 -2.07525870829232E+20 0 0 0 0 0 // <{Mag-Tools}>: Regeneration Other Incantation, Difficulty: 400, Family: 93, Generation: 1, Type: 1, 5 0.25 1 3982 -2.07525870829232E+20 0 0 0 0 0 // Focusing stone // <{Mag-Tools}>: Brilliance, Difficulty: 250, Family: 15, Generation: 1, Type: 1, 5 0.25 1 2348 -2.07525870829232E+20 0 0 0 0 0 // <{Mag-Tools}>: Concentration, Difficulty: 100, Family: 13, Generation: 1, Type: 1, 0 0 1 2347 -2.07525870829232E+20 0 0 0 0 0 // <{Mag-Tools}>: Malediction, Difficulty: 50, Family: 284, Generation: 1, Type: 1, 0 0 1 2346 -2.07525870829232E+20 0 0 0 0 0 // Weapon buffs // <{Mag-Tools}>: Elysa's Sight, Difficulty: 300, Family: 152, Generation: 1, Type: 1, 25 0 1 2106 -2.07525870829232E+20 0 0 0 0 0 (Attack Skill) // <{Mag-Tools}>: Infected Caress, Difficulty: 300, Family: 154, Generation: 1, Type: 1, 25 0 1 2096 -2.07525870829232E+20 0 0 0 0 0 (Damage) // <{Mag-Tools}>: Infected Spirit Caress, Difficulty: 300, Family: 154, Generation: 1, Type: 1, 25 0 1 3259 -2.07525870829232E+20 0 0 0 0 0 (Damage) // <{Mag-Tools}>: Cragstone's Will, Difficulty: 300, Family: 156, Generation: 1, Type: 1, 25 0 1 2101 -2.07525870829232E+20 0 0 0 0 0 (Defense) // <{Mag-Tools}>: Atlan's Alacrity, Difficulty: 300, Family: 158, Generation: 1, Type: 1, 25 0 1 2116 -2.07525870829232E+20 0 0 0 0 0 (Speed) // <{Mag-Tools}>: Mystic's Blessing, Difficulty: 300, Family: 195, Generation: 1, Type: 1, 25 0 1 2117 -2.07525870829232E+20 0 0 0 0 0 (Mana C) // <{Mag-Tools}>: Vision of the Hunter, Difficulty: 500, Family: 325, Generation: 1, Type: 1, 25 0 1 2968 -2.07525870829232E+20 0 0 0 0 0 (Damage Mod) if ((spell.Family >= 152 && spell.Family <= 158) || spell.Family == 195 || spell.Family == 325) { // This is a weapon buff // Lvl 6 if (spell.Difficulty == 250) { continue; } // Lvl 7 if (spell.Difficulty == 300) { goto ShowSpell; } // Lvl 8+ if (spell.Difficulty >= 400) { goto ShowSpell; } continue; } // This is not a weapon buff. // Filter all 1-5 spells if (spell.Name.EndsWith(" I") || spell.Name.EndsWith(" II") || spell.Name.EndsWith(" III") || spell.Name.EndsWith(" IV") || spell.Name.EndsWith(" V")) { continue; } // Filter 6's if (spell.Name.EndsWith(" VI")) { continue; } // Filter 7's if (spell.Difficulty == 300) { continue; } // Filter 8's if (spell.Name.Contains("Incantation")) { continue; } ShowSpell: sb.Append(", " + spell.Name); } } // Wield Lvl 180 if (mwo.Values(IntValueKey.WieldReqValue) > 0) { // I don't quite understand this. if (mwo.Values(IntValueKey.WieldReqType) == 7 && mwo.Values(IntValueKey.WieldReqAttribute) == 1) { sb.Append(", Wield Lvl " + mwo.Values(IntValueKey.WieldReqValue)); } else { if (Dictionaries.SkillInfo.ContainsKey(mwo.Values(IntValueKey.WieldReqAttribute))) { sb.Append(", " + Dictionaries.SkillInfo[mwo.Values(IntValueKey.WieldReqAttribute)] + " " + mwo.Values(IntValueKey.WieldReqValue)); } else { sb.Append(", Unknown skill: " + mwo.Values(IntValueKey.WieldReqAttribute) + " " + mwo.Values(IntValueKey.WieldReqValue)); } } } // Summoning Gem if (mwo.Values((IntValueKey)369) > 0) { sb.Append(", Lvl " + mwo.Values((IntValueKey)369)); } // Melee Defense 300 to Activate // If the activation is lower than the wield requirement, don't show it. if (mwo.Values(IntValueKey.SkillLevelReq) > 0 && (mwo.Values(IntValueKey.WieldReqAttribute) != mwo.Values(IntValueKey.ActivationReqSkillId) || mwo.Values(IntValueKey.WieldReqValue) < mwo.Values(IntValueKey.SkillLevelReq))) { if (Dictionaries.SkillInfo.ContainsKey(mwo.Values(IntValueKey.ActivationReqSkillId))) { sb.Append(", " + Dictionaries.SkillInfo[mwo.Values(IntValueKey.ActivationReqSkillId)] + " " + mwo.Values(IntValueKey.SkillLevelReq) + " to Activate"); } else { sb.Append(", Unknown skill: " + mwo.Values(IntValueKey.ActivationReqSkillId) + " " + mwo.Values(IntValueKey.SkillLevelReq) + " to Activate"); } } // Summoning Gem if (mwo.Values((IntValueKey)366) > 0 && mwo.Values((IntValueKey)367) > 0) { if (Dictionaries.SkillInfo.ContainsKey(mwo.Values((IntValueKey)366))) { sb.Append(", " + Dictionaries.SkillInfo[mwo.Values((IntValueKey)366)] + " " + mwo.Values((IntValueKey)367)); } else { sb.Append(", Unknown skill: " + mwo.Values((IntValueKey)366) + " " + mwo.Values((IntValueKey)367)); } } // Summoning Gem if (mwo.Values((IntValueKey)368) > 0 && mwo.Values((IntValueKey)367) > 0) { if (Dictionaries.SkillInfo.ContainsKey(mwo.Values((IntValueKey)368))) { sb.Append(", Spec " + Dictionaries.SkillInfo[mwo.Values((IntValueKey)368)] + " " + mwo.Values((IntValueKey)367)); } else { sb.Append(", Unknown skill spec: " + mwo.Values((IntValueKey)368) + " " + mwo.Values((IntValueKey)367)); } } if (mwo.Values(IntValueKey.LoreRequirement) > 0) { sb.Append(", Diff " + mwo.Values(IntValueKey.LoreRequirement)); } if (mwo.ObjectClass == (int)ObjectClass.Salvage) { if (mwo.Values(DoubleValueKey.SalvageWorkmanship) > 0) { sb.Append(", Work " + mwo.Values(DoubleValueKey.SalvageWorkmanship).ToString("N2")); } } else { if (mwo.Values(IntValueKey.Workmanship) > 0 && mwo.Values(IntValueKey.NumberTimesTinkered) != 10) // Don't show the work if its already 10 tinked. { sb.Append(", Craft " + mwo.Values(IntValueKey.Workmanship)); } } if (mwo.ObjectClass == (int)ObjectClass.Armor && mwo.Values(IntValueKey.Unenchantable, 0) != 0) { sb.Append(", [" + mwo.Values(DoubleValueKey.SlashProt).ToString("N1") + "/" + mwo.Values(DoubleValueKey.PierceProt).ToString("N1") + "/" + mwo.Values(DoubleValueKey.BludgeonProt).ToString("N1") + "/" + mwo.Values(DoubleValueKey.ColdProt).ToString("N1") + "/" + mwo.Values(DoubleValueKey.FireProt).ToString("N1") + "/" + mwo.Values(DoubleValueKey.AcidProt).ToString("N1") + "/" + mwo.Values(DoubleValueKey.LightningProt).ToString("N1") + "]"); } if (showValueAndBurden) { if (mwo.Values(IntValueKey.Value) > 0) { sb.Append(", Value " + String.Format("{0:n0}", mwo.Values(IntValueKey.Value))); } if (mwo.Values(IntValueKey.Burden) > 0) { sb.Append(", BU " + mwo.Values(IntValueKey.Burden)); } } if (mwo.TotalRating > 0) { sb.Append(", ["); bool first = true; if (mwo.DamRating > 0) { sb.Append("D " + mwo.DamRating); first = false; } if (mwo.DamResistRating > 0) { if (!first) { sb.Append(", "); } sb.Append("DR " + mwo.DamResistRating); first = false; } if (mwo.CritRating > 0) { if (!first) { sb.Append(", "); } sb.Append("C " + mwo.CritRating); first = false; } if (mwo.CritDamRating > 0) { if (!first) { sb.Append(", "); } sb.Append("CD " + mwo.CritDamRating); first = false; } if (mwo.CritResistRating > 0) { if (!first) { sb.Append(", "); } sb.Append("CR " + mwo.CritResistRating); first = false; } if (mwo.CritDamResistRating > 0) { if (!first) { sb.Append(", "); } sb.Append("CDR " + mwo.CritDamResistRating); first = false; } if (mwo.HealBoostRating > 0) { if (!first) { sb.Append(", "); } sb.Append("HB " + mwo.HealBoostRating); first = false; } if (mwo.VitalityRating > 0) { if (!first) { sb.Append(", "); } sb.Append("V " + mwo.VitalityRating); first = false; } sb.Append("]"); } if (mwo.ObjectClass == (int)ObjectClass.Misc && mwo.Name.Contains("Keyring")) { sb.Append(", Keys: " + mwo.Values(IntValueKey.KeysHeld) + ", Uses: " + mwo.Values(IntValueKey.UsesRemaining)); } return(sb.ToString()); }
private void btnCalculatePossibilities_Click(object sender, System.EventArgs e) { if (filtersControl1.CantripsToLookFor.Count == 0) { if (MessageBox.Show("You have no spells selected. Your search results won't be very useful. Would you like to go ahead anyway?" + Environment.NewLine + Environment.NewLine + "To select spells, load defsults or click the spells you want on the bottom of the filters group on Tab labeled 'Step 1. Add Inventory'", "No Spells Selected", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.No) { return; } } btnCalculatePossibilities.Enabled = false; treeView1.Nodes.Clear(); PopulateFromEquipmentGroup(null); if (armorSearcher != null) { armorSearcher.SuitCreated -= new Action <CompletedSuit>(armorSearcher_SuitCreated); armorSearcher.SearchCompleted -= new Action(ThreadFinished); } accessorySearchers.Clear(); abortedSearch = false; SearcherConfiguration config = new SearcherConfiguration(); config.CantripsToLookFor = filtersControl1.CantripsToLookFor; config.PrimaryArmorSet = filtersControl1.PrimaryArmorSetId; config.SecondaryArmorSet = filtersControl1.SecondaryArmorSetId; // Build the list of items we're going to use in our search searchItems = new List <LeanMyWorldObject>(); // Only add items that meet our minimum requirements foreach (var piece in boundList) { if (piece.Locked || (!piece.Exclude && config.ItemPassesRules(piece))) { searchItems.Add(new LeanMyWorldObject(piece)); } } var possibleSpells = new List <Spell>(); // Go through our Equipment and remove/disable any extra spells that we're not looking for foreach (var piece in searchItems) { piece.SpellsToUseInSearch.Clear(); foreach (Spell spell in piece.ExtendedMyWorldObject.CachedSpells) { if (config.SpellPassesRules(spell) && !spell.IsOfSameFamilyAndGroup(SpellTools.GetSpell(4667))) // Epic Impenetrability { piece.SpellsToUseInSearch.Add(spell); if (!possibleSpells.Contains(spell)) { possibleSpells.Add(spell); } } } } // Go through our possible spells and make sure they are all unique. This will also keep the lowest level spell that passed our rules for (int i = possibleSpells.Count - 1; i >= 0; i--) { for (int j = 0; j < i; j++) { if (possibleSpells[j].IsOfSameFamilyAndGroup(possibleSpells[i])) { if (possibleSpells[j].Surpasses(possibleSpells[i])) { possibleSpells.RemoveAt(j); } else { possibleSpells.RemoveAt(j); } goto next; } } next :; } // Now, we create our bitmapped spell map if (possibleSpells.Count > 32) { MessageBox.Show("Too many spells."); btnCalculatePossibilities.Enabled = true; return; } Dictionary <Spell, int> spellMap = new Dictionary <Spell, int>(); for (int i = 0; i < possibleSpells.Count; i++) { spellMap.Add(possibleSpells[i], 1 << i); } // Now, we update each item with the new spell map foreach (var piece in searchItems) { piece.SpellBitmap = 0; foreach (var spell in piece.SpellsToUseInSearch) { foreach (var kvp in spellMap) { if (spell.IsOfSameFamilyAndGroup(kvp.Key)) { piece.SpellBitmap |= kvp.Value; } } } } // Build our base suit from locked in pieces CompletedSuit baseSuit = new CompletedSuit(); // Add locked pieces in order of slots covered, starting with the fewest for (int slotCount = 1; slotCount <= 5; slotCount++) { foreach (var item in searchItems) { // Don't add items that we don't care about if (item.EquippableSlots == EquipMask.None || item.EquippableSlots == EquipMask.MeleeWeapon || item.EquippableSlots == EquipMask.MissileWeapon || item.EquippableSlots == EquipMask.TwoHanded || item.EquippableSlots == EquipMask.Held || item.EquippableSlots == EquipMask.MissileAmmo) { continue; } if (item.EquippableSlots == EquipMask.Cloak || item.EquippableSlots == EquipMask.SigilOne || item.EquippableSlots == EquipMask.SigilTwo || item.EquippableSlots == EquipMask.SigilThree) { continue; } if (item.ExtendedMyWorldObject.Locked && item.EquippableSlots.GetTotalBitsSet() == slotCount) { try { if (item.EquippableSlots.GetTotalBitsSet() > 1 && item.EquippableSlots.IsBodyArmor() && MessageBox.Show(item.ExtendedMyWorldObject.Name + " covers multiple slots. Would you like to reduce it?", "Add Item", MessageBoxButtons.YesNo) == DialogResult.Yes) { var reductionOptions = item.Coverage.ReductionOptions(); EquipMask slotFlag = EquipMask.None; foreach (var option in reductionOptions) { if (option == CoverageMask.OuterwearChest && baseSuit[EquipMask.ChestArmor] == null) { slotFlag = EquipMask.ChestArmor; break; } if (option == CoverageMask.OuterwearUpperArms && baseSuit[EquipMask.UpperArmArmor] == null) { slotFlag = EquipMask.UpperArmArmor; break; } if (option == CoverageMask.OuterwearLowerArms && baseSuit[EquipMask.LowerArmArmor] == null) { slotFlag = EquipMask.LowerArmArmor; break; } if (option == CoverageMask.OuterwearAbdomen && baseSuit[EquipMask.AbdomenArmor] == null) { slotFlag = EquipMask.AbdomenArmor; break; } if (option == CoverageMask.OuterwearUpperLegs && baseSuit[EquipMask.UpperLegArmor] == null) { slotFlag = EquipMask.UpperLegArmor; break; } if (option == CoverageMask.OuterwearLowerLegs && baseSuit[EquipMask.LowerLegArmor] == null) { slotFlag = EquipMask.LowerLegArmor; break; } if (option == CoverageMask.Feet && baseSuit[EquipMask.FootWear] == null) { slotFlag = EquipMask.FootWear; break; } } if (slotFlag == EquipMask.None) { MessageBox.Show("Unable to reduce " + item + " into an open single slot." + Environment.NewLine + "Reduction coverage option not expected or not open."); } else { baseSuit.AddItem(slotFlag, item); } } else if (!baseSuit.AddItem(item)) { MessageBox.Show("Failed to add " + item.ExtendedMyWorldObject.Name + " to base suit of armor."); } } catch (ArgumentException) // Item failed to add { MessageBox.Show("Failed to add " + item.ExtendedMyWorldObject.Name + " to base suit of armor. It overlaps another piece"); } } } } if (baseSuit.Count > 0) { AddCompletedSuitToTreeView(baseSuit); } armorSearcher = new ArmorSearcher(config, searchItems, baseSuit); armorSearcherHighestItemCount = 0; armorSearcher.SuitCreated += new Action <CompletedSuit>(armorSearcher_SuitCreated); armorSearcher.SearchCompleted += new Action(ThreadFinished); startTime = DateTime.Now; armorThreadCounter = 1; accessoryThreadQueueCounter = 0; accessoryThreadRunningCounter = 0; timerCalculatorUpdator.Start(); new Thread(() => { // Do the actual search here armorSearcher.Start(); Interlocked.Decrement(ref armorThreadCounter); ThreadFinished(); }).Start(); btnStopCalculating.Enabled = true; progressBar1.Style = ProgressBarStyle.Marquee; }
public override string ToString() { var sb = new StringBuilder(); sb.AppendLine("Total Spells: " + TotalSpells.ToString("N0") + " Min Spells: " + MinSpells.ToString("N0") + " Max Spells: " + MaxSpells.ToString("N0")); sb.AppendLine("Hits By Buff Level: "); var sortedKeys1 = HitsByBuffLevels.Keys.ToList(); sortedKeys1.Sort(); foreach (var key in sortedKeys1) { sb.AppendLine(key.ToString().PadLeft(9) + " [" + HitsByBuffLevels[key].ToString("N0").PadLeft(6) + " " + (HitsByBuffLevels[key] / (float)TotalSpells * 100).ToString("N1").PadLeft(4) + "%]"); } sb.AppendLine("Hits By Cantrip ID: "); var sortedKeys2 = HitsByCantrip.Keys.ToList(); sortedKeys2.Sort(); foreach (var key in sortedKeys2) { sb.AppendLine(key.ToString().PadLeft(9) + " [" + HitsByCantrip[key].ToString("N0").PadLeft(6) + " " + (HitsByCantrip[key] / (float)TotalSpells * 100).ToString("N1").PadLeft(4) + "%]"); } sb.AppendLine("Hits By Spell ID: "); var sortedKeys3 = HitsBySpellID.Keys.ToList(); sortedKeys3.Sort(); foreach (var key in sortedKeys3) { sb.AppendLine(key.ToString().PadLeft(4) + " [" + HitsBySpellID[key].ToString("N0").PadLeft(6) + " " + (HitsBySpellID[key] / (float)TotalSpells * 100).ToString("N1").PadLeft(4) + "%] " + SpellTools.GetSpell(key).Name); } return(sb.ToString()); }
public void LoadDefaults(string skill) { suspendChangedEvent = true; Clear(); // Attributes switch (skill) { case "War": case "Void": Add(SpellTools.GetSpell(6104)); Add(SpellTools.GetSpell(6103)); Add(SpellTools.GetSpell(6106)); Add(SpellTools.GetSpell(6105)); Add(SpellTools.GetSpell(6101)); break; case "Generic": case "Missile": case "Heavy": case "Light": case "Finesse": case "Two Hand": case "Dual Wield": Add(SpellTools.GetSpell(6107)); Add(SpellTools.GetSpell(6104)); Add(SpellTools.GetSpell(6103)); Add(SpellTools.GetSpell(6106)); Add(SpellTools.GetSpell(6105)); Add(SpellTools.GetSpell(6101)); break; case "Tinker": Add(SpellTools.GetSpell(6107)); Add(SpellTools.GetSpell(6104)); Add(SpellTools.GetSpell(6103)); Add(SpellTools.GetSpell(6105)); break; } // Wards switch (skill) { case "Generic": case "War": case "Void": case "Missile": case "Heavy": case "Light": case "Finesse": case "Two Hand": case "Dual Wield": Add(SpellTools.GetSpell(6085)); Add(SpellTools.GetSpell(6084)); Add(SpellTools.GetSpell(6081)); Add(SpellTools.GetSpell(6082)); Add(SpellTools.GetSpell(6083)); Add(SpellTools.GetSpell(6080)); Add(SpellTools.GetSpell(6079)); break; case "Tinker": break; } // Magic/Melee/Armor switch (skill) { case "Generic": case "War": case "Void": case "Missile": case "Heavy": case "Light": case "Finesse": case "Two Hand": case "Dual Wield": Add(SpellTools.GetSpell(6055)); Add(SpellTools.GetSpell(6063)); Add(SpellTools.GetSpell(6102)); break; case "Tinker": break; } // Skills switch (skill) { case "War": Add(SpellTools.GetSpell(6075)); break; case "Void": Add(SpellTools.GetSpell(6074)); break; case "Missile": Add(SpellTools.GetSpell(6044)); Add(SpellTools.GetSpell(6053)); // Healing Add(SpellTools.GetSpell(6052)); // Fletching break; case "Heavy": Add(SpellTools.GetSpell(6072)); Add(SpellTools.GetSpell(6053)); // Healing break; case "Light": Add(SpellTools.GetSpell(6043)); Add(SpellTools.GetSpell(6053)); // Healing break; case "Finesse": Add(SpellTools.GetSpell(6047)); Add(SpellTools.GetSpell(6053)); // Healing break; case "Two Hand": Add(SpellTools.GetSpell(6073)); Add(SpellTools.GetSpell(6053)); // Healing break; case "Dual Wield": Add(SpellTools.GetSpell(6050)); Add(SpellTools.GetSpell(6053)); // Healing break; case "Tinker": Add(SpellTools.GetSpell(6057)); Add(SpellTools.GetSpell(6042)); Add(SpellTools.GetSpell(6039)); Add(SpellTools.GetSpell(6062)); Add(SpellTools.GetSpell(6045)); Add(SpellTools.GetSpell(6040)); break; } if (CollectionChanged != null) { CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } suspendChangedEvent = false; }
public CantripSelectorControl() { InitializeComponent(); dataGridView1.Rows.Add(7); dataGridView1[0, 0].Value = "Strength"; dataGridView1[0, 0].Tag = new [] { SpellTools.GetSpell(6107), SpellTools.GetSpell(3965), SpellTools.GetSpell(2576), SpellTools.GetSpell(2583) }; dataGridView1[0, 1].Value = "Endurance"; dataGridView1[0, 1].Tag = new [] { SpellTools.GetSpell(6104), SpellTools.GetSpell(4226), SpellTools.GetSpell(2573), SpellTools.GetSpell(2580) }; dataGridView1[0, 2].Value = "Coordination"; dataGridView1[0, 2].Tag = new [] { SpellTools.GetSpell(6103), SpellTools.GetSpell(3963), SpellTools.GetSpell(2572), SpellTools.GetSpell(2579) }; dataGridView1[0, 3].Value = "Quickness"; dataGridView1[0, 3].Tag = new [] { SpellTools.GetSpell(6106), SpellTools.GetSpell(4019), SpellTools.GetSpell(2575), SpellTools.GetSpell(2582) }; dataGridView1[0, 4].Value = "Focus"; dataGridView1[0, 4].Tag = new [] { SpellTools.GetSpell(6105), SpellTools.GetSpell(3964), SpellTools.GetSpell(2574), SpellTools.GetSpell(2581) }; dataGridView1[0, 5].Value = "Willpower"; dataGridView1[0, 5].Tag = new [] { SpellTools.GetSpell(6101), SpellTools.GetSpell(4227), SpellTools.GetSpell(2577), SpellTools.GetSpell(2584) }; // dataGridView1[1, 0].Value = "Slashing Ward"; dataGridView1[1, 0].Tag = new [] { SpellTools.GetSpell(6085), SpellTools.GetSpell(4678), SpellTools.GetSpell(2614), SpellTools.GetSpell(2621) }; // 3957 Epic Slashing Ward dataGridView1[1, 1].Value = "Piercing Ward"; dataGridView1[1, 1].Tag = new [] { SpellTools.GetSpell(6084), SpellTools.GetSpell(4677), SpellTools.GetSpell(2613), SpellTools.GetSpell(2620) }; // 3956 Epic Piercing Ward dataGridView1[1, 2].Value = "Bludgeoning Ward"; dataGridView1[1, 2].Tag = new [] { SpellTools.GetSpell(6081), SpellTools.GetSpell(4674), SpellTools.GetSpell(2610), SpellTools.GetSpell(2617) }; dataGridView1[1, 3].Value = "Flame Ward"; dataGridView1[1, 3].Tag = new [] { SpellTools.GetSpell(6082), SpellTools.GetSpell(4675), SpellTools.GetSpell(2611), SpellTools.GetSpell(2618) }; dataGridView1[1, 4].Value = "Frost Ward"; dataGridView1[1, 4].Tag = new [] { SpellTools.GetSpell(6083), SpellTools.GetSpell(4676), SpellTools.GetSpell(2612), SpellTools.GetSpell(2619) }; dataGridView1[1, 5].Value = "Acid Ward"; dataGridView1[1, 5].Tag = new [] { SpellTools.GetSpell(6080), SpellTools.GetSpell(4673), SpellTools.GetSpell(2609), SpellTools.GetSpell(2616) }; dataGridView1[1, 6].Value = "Storm Ward"; dataGridView1[1, 6].Tag = new [] { SpellTools.GetSpell(6079), SpellTools.GetSpell(4679), SpellTools.GetSpell(2615), SpellTools.GetSpell(2622) }; dataGridView1[2, 0].Value = "Life Magic"; dataGridView1[2, 0].Tag = new [] { SpellTools.GetSpell(6060), SpellTools.GetSpell(4700), SpellTools.GetSpell(2520), SpellTools.GetSpell(2555) }; dataGridView1[2, 1].Value = "Creature Ench"; dataGridView1[2, 1].Tag = new [] { SpellTools.GetSpell(6046), SpellTools.GetSpell(4689), SpellTools.GetSpell(2507), SpellTools.GetSpell(2542) }; dataGridView1[2, 2].Value = "Item Ench"; dataGridView1[2, 2].Tag = new [] { SpellTools.GetSpell(6056), SpellTools.GetSpell(4697), SpellTools.GetSpell(2516), SpellTools.GetSpell(2551) }; dataGridView1[2, 3].Value = "War Magic"; dataGridView1[2, 3].Tag = new [] { SpellTools.GetSpell(6075), SpellTools.GetSpell(4715), SpellTools.GetSpell(2534), SpellTools.GetSpell(2569) }; dataGridView1[2, 4].Value = "Void Magic"; dataGridView1[2, 4].Tag = new [] { SpellTools.GetSpell(6074), SpellTools.GetSpell(5429), SpellTools.GetSpell(5428), SpellTools.GetSpell(5427) }; dataGridView1[2, 5].Value = "Mana C"; dataGridView1[2, 5].Tag = new [] { SpellTools.GetSpell(6064), SpellTools.GetSpell(4705), SpellTools.GetSpell(2525), SpellTools.GetSpell(2560) }; dataGridView1[2, 6].Value = "Arcane"; dataGridView1[2, 6].Tag = new [] { SpellTools.GetSpell(6041), SpellTools.GetSpell(4684), SpellTools.GetSpell(2502), SpellTools.GetSpell(2537) }; dataGridView1[3, 0].Value = "Missile"; dataGridView1[3, 0].Tag = new [] { SpellTools.GetSpell(6044), SpellTools.GetSpell(4687), SpellTools.GetSpell(2505), SpellTools.GetSpell(2540) }; // 4690 4713,Epic Missile Weapon Aptitude 2508 2532,Major Missile Weapon Aptitude 2543 2567,Minor Missile Weapon Aptitude dataGridView1[3, 1].Value = "Heavy"; dataGridView1[3, 1].Tag = new [] { SpellTools.GetSpell(6072), SpellTools.GetSpell(4712), SpellTools.GetSpell(2531), SpellTools.GetSpell(2566) }; dataGridView1[3, 2].Value = "Light"; dataGridView1[3, 2].Tag = new [] { SpellTools.GetSpell(6043), SpellTools.GetSpell(4686), SpellTools.GetSpell(2504), SpellTools.GetSpell(2539) }; // 4702 4709 4711 4714,Epic Light Weapon Aptitude 2522 2528 2530 2533,Major Light Weapon Aptitude 2557 2563 2565 2568,Minor Light Weapon Aptitude dataGridView1[3, 3].Value = "Finesse"; dataGridView1[3, 3].Tag = new [] { SpellTools.GetSpell(6047), SpellTools.GetSpell(4691), SpellTools.GetSpell(2509), SpellTools.GetSpell(2544) }; dataGridView1[3, 4].Value = "Healing"; dataGridView1[3, 4].Tag = new [] { SpellTools.GetSpell(6053), SpellTools.GetSpell(4694), SpellTools.GetSpell(2513), SpellTools.GetSpell(2548) }; dataGridView1[3, 5].Value = "Shield"; dataGridView1[3, 5].Tag = new [] { SpellTools.GetSpell(6069), SpellTools.GetSpell(5896), SpellTools.GetSpell(5891), SpellTools.GetSpell(5886) }; dataGridView1[4, 0].Value = "Two Hand"; dataGridView1[4, 0].Tag = new [] { SpellTools.GetSpell(6073), SpellTools.GetSpell(5034), SpellTools.GetSpell(5070), SpellTools.GetSpell(5072) }; dataGridView1[4, 1].Value = "Dual Wield"; dataGridView1[4, 1].Tag = new [] { SpellTools.GetSpell(6050), SpellTools.GetSpell(5894), SpellTools.GetSpell(5889), SpellTools.GetSpell(5884) }; dataGridView1[4, 2].Value = "Dirty Fighting"; dataGridView1[4, 2].Tag = new [] { SpellTools.GetSpell(6049), SpellTools.GetSpell(5893), SpellTools.GetSpell(5888), SpellTools.GetSpell(5883) }; dataGridView1[4, 3].Value = "Recklessness"; dataGridView1[4, 3].Tag = new [] { SpellTools.GetSpell(6067), SpellTools.GetSpell(5895), SpellTools.GetSpell(5890), SpellTools.GetSpell(5885) }; dataGridView1[4, 4].Value = "Sneak Attack"; dataGridView1[4, 4].Tag = new [] { SpellTools.GetSpell(6070), SpellTools.GetSpell(5897), SpellTools.GetSpell(5892), SpellTools.GetSpell(5887) }; dataGridView1[4, 5].Value = "Summoning"; dataGridView1[4, 5].Tag = new [] { SpellTools.GetSpell(6125), SpellTools.GetSpell(6124), SpellTools.GetSpell(6126), SpellTools.GetSpell(6127) }; // // dataGridView1[5, 0].Value = "Invulnerability"; dataGridView1[5, 0].Tag = new [] { SpellTools.GetSpell(6055), SpellTools.GetSpell(4696), SpellTools.GetSpell(2515), SpellTools.GetSpell(2550) }; dataGridView1[5, 1].Value = "Magic Resistance"; dataGridView1[5, 1].Tag = new [] { SpellTools.GetSpell(6063), SpellTools.GetSpell(4704), SpellTools.GetSpell(2524), SpellTools.GetSpell(2559) }; dataGridView1[5, 2].Value = "Impregnability"; dataGridView1[5, 2].Tag = new [] { SpellTools.GetSpell(6054), SpellTools.GetSpell(4695), SpellTools.GetSpell(2514), SpellTools.GetSpell(2549) }; dataGridView1[5, 3].Value = "Armor"; dataGridView1[5, 3].Tag = new [] { SpellTools.GetSpell(6102), SpellTools.GetSpell(4911), SpellTools.GetSpell(2571), SpellTools.GetSpell(2578) }; dataGridView1[5, 4].Value = "Deception"; dataGridView1[5, 4].Tag = new [] { SpellTools.GetSpell(6048), SpellTools.GetSpell(4020), SpellTools.GetSpell(2510), SpellTools.GetSpell(2545) }; dataGridView1[5, 5].Value = "Person"; dataGridView1[5, 5].Tag = new [] { SpellTools.GetSpell(6066), SpellTools.GetSpell(4707), SpellTools.GetSpell(2527), SpellTools.GetSpell(2562) }; dataGridView1[5, 6].Value = "Monster"; dataGridView1[5, 6].Tag = new [] { SpellTools.GetSpell(6065), SpellTools.GetSpell(4706), SpellTools.GetSpell(2526), SpellTools.GetSpell(2561) }; dataGridView1[6, 0].Value = "Item Tinker"; dataGridView1[6, 0].Tag = new [] { SpellTools.GetSpell(6057), SpellTools.GetSpell(4698), SpellTools.GetSpell(2517), SpellTools.GetSpell(2552) }; // 5033,Epic Item Tinkering Expertise 5069,Major Item Tinkering Expertise 5071,Minor Item Tinkering Expertise dataGridView1[6, 1].Value = "Armor Tinker"; dataGridView1[6, 1].Tag = new [] { SpellTools.GetSpell(6042), SpellTools.GetSpell(4685), SpellTools.GetSpell(2503), SpellTools.GetSpell(2538) }; dataGridView1[6, 2].Value = "Weapon Tinker"; dataGridView1[6, 2].Tag = new [] { SpellTools.GetSpell(6039), SpellTools.GetSpell(4912), SpellTools.GetSpell(2535), SpellTools.GetSpell(2570) }; dataGridView1[6, 3].Value = "Magic Item"; dataGridView1[6, 3].Tag = new [] { SpellTools.GetSpell(6062), SpellTools.GetSpell(4703), SpellTools.GetSpell(2523), SpellTools.GetSpell(2558) }; dataGridView1[6, 4].Value = "Cooking"; dataGridView1[6, 4].Tag = new [] { SpellTools.GetSpell(6045), SpellTools.GetSpell(4688), SpellTools.GetSpell(2506), SpellTools.GetSpell(2541) }; dataGridView1[6, 5].Value = "Alchemy"; dataGridView1[6, 5].Tag = new [] { SpellTools.GetSpell(6040), SpellTools.GetSpell(4683), SpellTools.GetSpell(2501), SpellTools.GetSpell(2536) }; dataGridView1[6, 6].Value = "Fletching"; dataGridView1[6, 6].Tag = new [] { SpellTools.GetSpell(6052), SpellTools.GetSpell(4693), SpellTools.GetSpell(2512), SpellTools.GetSpell(2547) }; // Run through and check for errors /* * foreach (DataGridViewRow row in dataGridView1.Rows) * { * foreach (DataGridViewCell cell in row.Cells) * { * if (cell.Tag == null) * continue; * * Spell[] cellSpells = cell.Tag as Spell[]; * * if (cellSpells != null) * { * for (int i = 1 ; i < cellSpells.Length ; i++) * { * if (!cellSpells[0].IsOfSameFamilyAndGroup(cellSpells[i])) * throw new System.Exception("Spell group mismatch detected for cell: " + cell.Value + " " + cellSpells[0] + " - " + cellSpells[i]); * } * } * } * } */ }
/// <summary> /// Will return -1 for player, 0 if a tier was unable to be calculated, or the tier #. /// </summary> public static int Calculate(IEnumerable <IdentResponse> items) { int tier = 0; // Calculate the loot tiers // Reference: http://asheron.wikia.com/wiki/Loot foreach (var item in items) { if ((item.LongValues.ContainsKey(IntValueKey.NumTimesTinkered) && item.LongValues[IntValueKey.NumTimesTinkered] > 0) || item.ActiveSpells.Count > 0) { return(-1); } // Exclude trophy items from tier calculation if (!item.LongValues.ContainsKey(IntValueKey.ItemWorkmanship)) { goto bypassNonRandomLootGenItems; } // Melee if (item.LongValues.ContainsKey(IntValueKey.WieldRequirements) && item.LongValues[IntValueKey.WieldRequirements] == (int)WieldRequirement.RawSkill && item.LongValues.ContainsKey(IntValueKey.WieldSkillType) && (item.LongValues[IntValueKey.WieldSkillType] == (int)Skill.TwoHandedCombat || item.LongValues[IntValueKey.WieldSkillType] == (int)Skill.HeavyWeapons || item.LongValues[IntValueKey.WieldSkillType] == (int)Skill.LightWeapons || item.LongValues[IntValueKey.WieldSkillType] == (int)Skill.FinesseWeapons) && item.LongValues.ContainsKey(IntValueKey.WieldDifficulty)) { switch (item.LongValues[IntValueKey.WieldDifficulty]) { case 250: if (tier < 2) { tier = 2; } break; case 300: if (tier < 3) { tier = 3; } break; case 325: if (tier < 4) { tier = 4; } break; case 350: if (tier < 5) { tier = 5; } break; case 370: case 400: if (tier < 6) { tier = 6; } break; case 420: if (tier < 7) { tier = 7; } break; case 430: tier = 8; break; } } // Missile if (item.LongValues.ContainsKey(IntValueKey.WieldRequirements) && item.LongValues[IntValueKey.WieldRequirements] == (int)WieldRequirement.RawSkill && item.LongValues.ContainsKey(IntValueKey.WieldSkillType) && item.LongValues[IntValueKey.WieldSkillType] == (int)Skill.MissileWeapons && item.LongValues.ContainsKey(IntValueKey.WieldDifficulty)) { switch (item.LongValues[IntValueKey.WieldDifficulty]) { case 250: if (tier < 2) { tier = 2; } break; case 270: if (tier < 3) { tier = 3; } break; case 290: if (tier < 4) { tier = 4; } break; case 315: if (tier < 5) { tier = 5; } break; case 335: case 360: if (tier < 6) { tier = 6; } break; case 375: if (tier < 7) { tier = 7; } break; case 385: tier = 8; break; } } // Magic if (item.LongValues.ContainsKey(IntValueKey.WieldRequirements) && item.LongValues[IntValueKey.WieldRequirements] == (int)WieldRequirement.RawSkill && item.LongValues.ContainsKey(IntValueKey.WieldSkillType) && (item.LongValues[IntValueKey.WieldSkillType] == (int)Skill.WarMagic || item.LongValues[IntValueKey.WieldSkillType] == (int)Skill.VoidMagic) && item.LongValues.ContainsKey(IntValueKey.WieldDifficulty)) { switch (item.LongValues[IntValueKey.WieldDifficulty]) { case 290: if (tier < 4) { tier = 4; } break; case 310: if (tier < 5) { tier = 5; } break; case 330: case 355: if (tier < 6) { tier = 6; } break; case 375: if (tier < 7) { tier = 7; } break; case 385: tier = 8; break; } } // Wield Level if (item.LongValues.ContainsKey(IntValueKey.WieldRequirements) && item.LongValues[IntValueKey.WieldRequirements] == (int)WieldRequirement.Level && item.LongValues.ContainsKey(IntValueKey.WieldDifficulty)) { switch (item.LongValues[IntValueKey.WieldDifficulty]) { case 150: if (tier < 7) { tier = 7; } break; case 180: tier = 8; break; } } if (item.LongValues.ContainsKey(IntValueKey.ItemWorkmanship)) { if (item.LongValues[IntValueKey.ItemWorkmanship] == 1 && tier < 1) { tier = 1; } if (item.LongValues[IntValueKey.ItemWorkmanship] == 2 && tier < 1) { tier = 1; } if (item.LongValues[IntValueKey.ItemWorkmanship] == 3 && tier < 1) { tier = 1; } if (item.LongValues[IntValueKey.ItemWorkmanship] == 4 && tier < 1) { tier = 1; } if (item.LongValues[IntValueKey.ItemWorkmanship] == 5 && tier < 1) { tier = 1; } if (item.LongValues[IntValueKey.ItemWorkmanship] == 6 && tier < 2) { tier = 2; } if (item.LongValues[IntValueKey.ItemWorkmanship] == 7 && tier < 3) { tier = 3; } if (item.LongValues[IntValueKey.ItemWorkmanship] == 8 && tier < 4) { tier = 4; } if (item.LongValues[IntValueKey.ItemWorkmanship] == 9 && tier < 5) { tier = 5; } if (item.LongValues[IntValueKey.ItemWorkmanship] == 10 && tier < 6) { tier = 6; } } bypassNonRandomLootGenItems: // Gems in higher tiers can come with low spells, so we don't do spell checks on these objects if (item.LongValues.ContainsKey(IntValueKey.ItemWorkmanship)) { foreach (var spellId in item.Spells) { var spell = SpellTools.GetSpell(spellId); if (spell.BuffLevel == Spell.BuffLevels.I && tier < 1) { tier = 1; } if (spell.BuffLevel == Spell.BuffLevels.II && tier < 1) { tier = 1; } if (spell.BuffLevel == Spell.BuffLevels.III && tier < 1) { tier = 1; } if (spell.BuffLevel == Spell.BuffLevels.IV && tier < 2) { tier = 2; } if (spell.BuffLevel == Spell.BuffLevels.V && tier < 2) { tier = 2; } if (spell.BuffLevel == Spell.BuffLevels.VI && tier < 3) { tier = 3; } if (spell.BuffLevel == Spell.BuffLevels.VII && tier < 5) { tier = 5; } if (spell.BuffLevel == Spell.BuffLevels.VIII && tier < 7) { tier = 7; } if (spell.CantripLevel == Spell.CantripLevels.Major && tier < 2) { tier = 2; } if (spell.CantripLevel == Spell.CantripLevels.Epic && tier < 7) { tier = 7; } if (spell.CantripLevel == Spell.CantripLevels.Legendary && tier < 8) { tier = 8; } } } } return(tier); }
public bool ItemPassesFilters(ExtendedMyWorldObject mwo) { if (checkRemoveEquipped.Checked && mwo.EquippedSlot != EquipMask.None) { return(false); } if (chkRemoveUnequipped.Checked && mwo.EquippedSlot == EquipMask.None) { return(false); } int value; int.TryParse(txtMinimumBaseArmorLevel.Text, out value); if ((mwo.ObjClass == ObjectClass.Armor || mwo.ObjClass == ObjectClass.Clothing) && mwo.CalcedStartingArmorLevel < value && mwo.EquippableSlots.IsCoreBodyArmor()) { return(false); } int.TryParse(txtMaximumBaseArmorLevel.Text, out value); if ((mwo.ObjClass == ObjectClass.Armor || mwo.ObjClass == ObjectClass.Clothing) && mwo.CalcedStartingArmorLevel > value && mwo.EquippableSlots.IsCoreBodyArmor()) { return(false); } int.TryParse(txtMinimumExtremityArmorLevel.Text, out value); if ((mwo.ObjClass == ObjectClass.Armor || mwo.ObjClass == ObjectClass.Clothing) && mwo.CalcedStartingArmorLevel < value && mwo.EquippableSlots.IsExtremityBodyArmor()) { return(false); } int.TryParse(txtMaximumExtremityArmorLevel.Text, out value); if ((mwo.ObjClass == ObjectClass.Armor || mwo.ObjClass == ObjectClass.Clothing) && mwo.CalcedStartingArmorLevel > value && mwo.EquippableSlots.IsExtremityBodyArmor()) { return(false); } if (mwo.EquippableSlots.IsBodyArmor()) { if (!chkBodyArmorClothing.Checked) { return(false); } } else if (mwo.EquippableSlots.IsUnderwear()) { if (!chkShirtPants.Checked) { return(false); } } else if (mwo.ObjClass == ObjectClass.Jewelry) { if (!chkJewelry.Checked) { return(false); } if (!chkJewelryNecklace.Checked && mwo.EquippableSlots == EquipMask.NeckWear) { return(false); } if (!chkJewelryTrinket.Checked && mwo.EquippableSlots == EquipMask.TrinketOne) { return(false); } if (!chkJewelryBracelet.Checked && mwo.EquippableSlots == (EquipMask.WristWearLeft | EquipMask.WristWearRight)) { return(false); } if (!chkJewelryRing.Checked && mwo.EquippableSlots == (EquipMask.FingerWearLeft | EquipMask.FingerWearRight)) { return(false); } } else if (mwo.ObjClass == ObjectClass.MeleeWeapon) { if (!chkMeleeWeapon.Checked) { return(false); } if (!chkMeleeHeavy.Checked && mwo.EquipSkill == "Heavy Weapons") { return(false); } if (!chkMeleeLight.Checked && mwo.EquipSkill == "Light Weapons") { return(false); } if (!chkMeleeFinesse.Checked && mwo.EquipSkill == "Finesse Weapons") { return(false); } if (!chkMelee2H.Checked && mwo.EquipSkill == "Two Handed Combat") { return(false); } if (!chkMasteryUA.Checked && mwo.Mastery == "Unarmed Weapon") { return(false); } if (!chkMasterySword.Checked && mwo.Mastery == "Sword") { return(false); } if (!chkMasteryAxe.Checked && mwo.Mastery == "Axe") { return(false); } if (!chkMasteryMace.Checked && mwo.Mastery == "Mace") { return(false); } if (!chkMasterySpear.Checked && mwo.Mastery == "Spear") { return(false); } if (!chkMasteryDagger.Checked && mwo.Mastery == "Dagger") { return(false); } if (!chkMasteryStaff.Checked && mwo.Mastery == "Staff") { return(false); } } else if (mwo.ObjClass == ObjectClass.MissileWeapon) { if (!chkMissileWeapon.Checked) { return(false); } if (!chkMasteryBow.Checked && mwo.Mastery == "Bow") { return(false); } if (!chkMasteryCrossbow.Checked && mwo.Mastery == "Crossbow") { return(false); } if (!chkMasteryThrown.Checked && mwo.Mastery == "Thrown") { return(false); } } else if (mwo.ObjClass == ObjectClass.WandStaffOrb) { if (!chkWandStaffOrb.Checked) { return(false); } if (!chkWandStaffOrbWar.Checked && mwo.IntValues.ContainsKey(158) && mwo.IntValues[158] == 2 && mwo.IntValues.ContainsKey(159) && mwo.IntValues[159] == 0x22) { return(false); } if (!chkWandStaffOrbVoid.Checked && mwo.IntValues.ContainsKey(158) && mwo.IntValues[158] == 2 && mwo.IntValues.ContainsKey(159) && mwo.IntValues[159] == 0x2B) { return(false); } } else if (mwo.ObjClass == ObjectClass.Salvage) { if (!chkSalvage.Checked) { return(false); } } else if (mwo.ObjClass == ObjectClass.Container || mwo.ObjClass == ObjectClass.Foci) { if (!chkContainersFoci.Checked) { return(false); } } else if (mwo.ObjClass == ObjectClass.Money || mwo.ObjClass == ObjectClass.TradeNote || mwo.ObjClass == ObjectClass.Key) { if (!chkMoneyNotesKeys.Checked) { return(false); } } else if (mwo.ObjClass == ObjectClass.SpellComponent || mwo.ObjClass == ObjectClass.HealingKit || mwo.ObjClass == ObjectClass.Food || mwo.ObjClass == ObjectClass.ManaStone) { if (!chkCompsKitsFoodManaStones.Checked) { return(false); } } else if (mwo.ObjClass == ObjectClass.Misc && mwo.Name.Contains("Essence") && !mwo.Name.Contains("Corrupted") && !mwo.Name.Contains("Degenerate")) { if (!chkPets.Checked) { return(false); } } else if (mwo.ObjClass != 0) // All Else { if (!chkAllElseObjectClasses.Checked) { return(false); } } if (mwo.EquippableSlots.IsBodyArmor()) { // Both are No Armor Set and the item has a set if (PrimaryArmorSetId == 0 && SecondaryArmorSetId == 0 && mwo.ItemSetId != 0) { return(false); } if (PrimaryArmorSetId != 255 && SecondaryArmorSetId != 255) { if (PrimaryArmorSetId != mwo.ItemSetId && SecondaryArmorSetId != mwo.ItemSetId) { return(false); } } } // Regex String Match if (!String.IsNullOrEmpty(txtRegexStringMatch.Text)) { var regex = new Regex(txtRegexStringMatch.Text, RegexOptions.IgnoreCase); bool hasSpellMatch = false; foreach (var spellID in mwo.Spells) { Spell spell = SpellTools.GetSpell(spellID); if (spell == null) { continue; } if (regex.IsMatch(spell.Name)) { hasSpellMatch = true; break; } } if (!hasSpellMatch) { var itemInfo = new ItemInfo(mwo); if (!regex.IsMatch(itemInfo.ToString())) { return(false); } } } // Spell Quantities int minLegendaries; int.TryParse(txtMinLegendaries.Text, out minLegendaries); int maxLegendaries; int.TryParse(txtMaxLegendaries.Text, out maxLegendaries); int minEpics; int.TryParse(txtMinEpics.Text, out minEpics); int maxEpics; int.TryParse(txtMaxEpics.Text, out maxEpics); int legendaries = 0; int epics = 0; foreach (Spell spell in mwo.CachedSpells) { if (spell.CantripLevel >= Spell.CantripLevels.Legendary) { legendaries++; } if (spell.CantripLevel >= Spell.CantripLevels.Epic) { epics++; } } if (legendaries < minLegendaries || legendaries > maxLegendaries || epics < minEpics || epics > maxEpics) { return(false); } // Ratings if (mwo.ObjClass == ObjectClass.Armor || mwo.ObjClass == ObjectClass.Clothing || mwo.ObjClass == ObjectClass.Jewelry) { if (mwo.ObjClass == ObjectClass.Armor || mwo.ObjClass == ObjectClass.Clothing) { if (int.TryParse(txtMinOffensiveRating.Text, out value)) { if (Math.Max(mwo.CritDamRating, 0) + Math.Max(mwo.CritRating, 0) + Math.Max(mwo.DamRating, 0) < value) { return(false); } } if (int.TryParse(txtMaxOffensiveRating.Text, out value)) { if (Math.Max(mwo.CritDamRating, 0) + Math.Max(mwo.CritRating, 0) + Math.Max(mwo.DamRating, 0) > value) { return(false); } } if (int.TryParse(txtMinDefensiveRating.Text, out value)) { if (Math.Max(mwo.CritDamResistRating, 0) + Math.Max(mwo.CritResistRating, 0) + Math.Max(mwo.DamResistRating, 0) < value) { return(false); } } if (int.TryParse(txtMaxDefensiveRating.Text, out value)) { if (Math.Max(mwo.CritDamResistRating, 0) + Math.Max(mwo.CritResistRating, 0) + Math.Max(mwo.DamResistRating, 0) > value) { return(false); } } } if (mwo.ObjClass == ObjectClass.Jewelry) { if (int.TryParse(txtMinOtherRating.Text, out value)) { if (Math.Max(mwo.HealBoostRating, 0) + Math.Max(mwo.VitalityRating, 0) < value) { return(false); } } if (int.TryParse(txtMaxOtherRating.Text, out value)) { if (Math.Max(mwo.HealBoostRating, 0) + Math.Max(mwo.VitalityRating, 0) > value) { return(false); } } } if (int.TryParse(txtMinTotalRating.Text, out value)) { if (Math.Max(mwo.TotalRating, 0) < value) { return(false); } } if (int.TryParse(txtMaxTotalRating.Text, out value)) { if (Math.Max(mwo.TotalRating, 0) > value) { return(false); } } } // Wield Requirements if (int.TryParse(txtWieldRequirementLevelMin.Text, out value)) { if (Math.Max(mwo.WieldLevel, 0) < value) { return(false); } } if (int.TryParse(txtWieldRequirementLevelMax.Text, out value)) { if (Math.Max(mwo.WieldLevel, 0) > value) { return(false); } } if (int.TryParse(txtWieldRequirementSkillMin.Text, out value)) { if (Math.Max(mwo.SkillLevel, 0) < value) { return(false); } } if (int.TryParse(txtWieldRequirementSkillMax.Text, out value)) { if (Math.Max(mwo.SkillLevel, 0) > value) { return(false); } } // Spell Selector if (cantripSelectorControl1.Count > 0) { foreach (var spell in mwo.CachedSpells) { foreach (Spell desiredSpell in cantripSelectorControl1) { if (spell.IsSameOrSurpasses(desiredSpell)) { goto end; } } } return(false); end :; } return(true); }
/// <summary> /// Will return -1 for player, 0 if a tier was unable to be calculated, or the tier #. /// </summary> public static int Calculate(IEnumerable <IdentResponse> items) { int tier = 0; // Calculate the loot tiers // Reference: http://asheron.wikia.com/wiki/Loot foreach (var item in items) { if ((item.LongValues.ContainsKey(IntValueKey.NumberTimesTinkered) && item.LongValues[IntValueKey.NumberTimesTinkered] > 0) || item.ActiveSpells.Count > 0) { return(-1); } // Exclude trophy items from tier calculation if (!item.LongValues.ContainsKey(IntValueKey.Workmanship)) { goto bypassNonRandomLootGenItems; } // Heavy/Light/Finesse if (item.LongValues.ContainsKey(IntValueKey.WieldReqAttribute) && (item.LongValues[IntValueKey.WieldReqAttribute] == 0x2C || item.LongValues[IntValueKey.WieldReqAttribute] == 0x2D || item.LongValues[IntValueKey.WieldReqAttribute] == 0x2E) && item.LongValues.ContainsKey(IntValueKey.WieldReqValue)) { switch (item.LongValues[IntValueKey.WieldReqValue]) { case 250: if (tier < 2) { tier = 2; } break; case 300: if (tier < 3) { tier = 3; } break; case 350: if (tier < 5) { tier = 5; } break; case 370: case 400: if (tier < 6) { tier = 6; } break; case 420: if (tier < 7) { tier = 7; } break; case 430: tier = 8; break; } } // Missile if (item.LongValues.ContainsKey(IntValueKey.WieldReqAttribute) && item.LongValues[IntValueKey.WieldReqAttribute] == 0x2F && item.LongValues.ContainsKey(IntValueKey.WieldReqValue)) { switch (item.LongValues[IntValueKey.WieldReqValue]) { case 250: if (tier < 2) { tier = 2; } break; case 270: if (tier < 3) { tier = 3; } break; //case 290: case 315: if (tier < 5) { tier = 5; } break; case 360: if (tier < 6) { tier = 6; } break; case 375: if (tier < 7) { tier = 7; } break; case 385: tier = 8; break; } } // Magic if (item.LongValues.ContainsKey(IntValueKey.WieldReqAttribute) && item.LongValues[IntValueKey.WieldReqAttribute] == 0x22 && item.LongValues.ContainsKey(IntValueKey.WieldReqValue)) { switch (item.LongValues[IntValueKey.WieldReqValue]) { //case 290: case 310: if (tier < 5) { tier = 5; } break; case 355: if (tier < 6) { tier = 6; } break; case 375: if (tier < 7) { tier = 7; } break; case 385: tier = 8; break; } } if (item.LongValues.ContainsKey(IntValueKey.Workmanship)) { if (item.LongValues[IntValueKey.Workmanship] == 1 && tier < 1) { tier = 1; } if (item.LongValues[IntValueKey.Workmanship] == 2 && tier < 1) { tier = 1; } if (item.LongValues[IntValueKey.Workmanship] == 3 && tier < 1) { tier = 1; } if (item.LongValues[IntValueKey.Workmanship] == 4 && tier < 1) { tier = 1; } if (item.LongValues[IntValueKey.Workmanship] == 5 && tier < 1) { tier = 1; } if (item.LongValues[IntValueKey.Workmanship] == 6 && tier < 2) { tier = 2; } if (item.LongValues[IntValueKey.Workmanship] == 7 && tier < 3) { tier = 3; } if (item.LongValues[IntValueKey.Workmanship] == 8 && tier < 4) { tier = 4; } if (item.LongValues[IntValueKey.Workmanship] == 9 && tier < 5) { tier = 5; } if (item.LongValues[IntValueKey.Workmanship] == 10 && tier < 6) { tier = 6; } } bypassNonRandomLootGenItems: // Gems in higher tiers can come with low spells, so we don't do spell checks on these objects if (item.LongValues.ContainsKey(IntValueKey.Workmanship)) { foreach (var spellId in item.Spells) { var spell = SpellTools.GetSpell(spellId); if (spell.BuffLevel == Spell.BuffLevels.I && tier < 1) { tier = 1; } if (spell.BuffLevel == Spell.BuffLevels.II && tier < 1) { tier = 1; } if (spell.BuffLevel == Spell.BuffLevels.III && tier < 1) { tier = 1; } if (spell.BuffLevel == Spell.BuffLevels.IV && tier < 2) { tier = 2; } if (spell.BuffLevel == Spell.BuffLevels.V && tier < 2) { tier = 2; } if (spell.BuffLevel == Spell.BuffLevels.VI && tier < 3) { tier = 3; } if (spell.BuffLevel == Spell.BuffLevels.VII && tier < 5) { tier = 5; } if (spell.BuffLevel == Spell.BuffLevels.VIII && tier < 7) { tier = 7; } if (spell.CantripLevel == Spell.CantripLevels.Major && tier < 2) { tier = 2; } if (spell.CantripLevel == Spell.CantripLevels.Epic && tier < 7) { tier = 7; } if (spell.CantripLevel == Spell.CantripLevels.Legendary && tier < 8) { tier = 8; } } } } return(tier); }
public override string ToString() { var sb = new StringBuilder(); sb.AppendLine("Total Items: " + TotalItems.ToString("N0") + " Total Spells: " + TotalSpells.ToString("N0") + " Min Spells: " + MinSpells.ToString("N0") + " Max Spells: " + MaxSpells.ToString("N0")); { { sb.AppendLine("Hits By Buff Level: "); var totalHitsByBuffLevels = HitsByBuffLevel.Values.Sum(); var sortedKeys = HitsByBuffLevel.Keys.ToList(); sortedKeys.Sort(); foreach (var key in sortedKeys) { sb.AppendLine(key.ToString().PadLeft(9) + " [" + HitsByBuffLevel[key].ToString("N0").PadLeft(7) + " " + (HitsByBuffLevel[key] / (float)totalHitsByBuffLevels * 100).ToString("N1").PadLeft(6) + "%]"); } } sb.AppendLine("Buff Count Probabilities: "); if (BuffCountHits.Count > 0) { for (int i = BuffCountHits.Keys.Min(); i <= BuffCountHits.Keys.Max(); i++) { if (BuffCountHits.ContainsKey(i)) { sb.AppendLine(i.ToString().PadLeft(9) + " [" + BuffCountHits[i].ToString("N0").PadLeft(7) + " " + (BuffCountHits[i] / (float)TotalItems * 100).ToString("N3").PadLeft(6) + "%]"); } else { sb.AppendLine(i.ToString().PadLeft(9) + " [" + "0".PadLeft(7) + " " + "]"); } } } { sb.AppendLine("Buff Hits By Spell ID: "); var sortedKeys = BuffHitsBySpellID.Keys.ToList(); sortedKeys.Sort(); foreach (var key in sortedKeys) { sb.AppendLine(key.ToString().PadLeft(4) + " [" + BuffHitsBySpellID[key].ToString("N0").PadLeft(7) + " " + (BuffHitsBySpellID[key] / (float)TotalSpells * 100).ToString("N1").PadLeft(4) + "%] " + SpellTools.GetSpell(key).Name); } } { sb.AppendLine("Buff Hits By Spell Category: "); var sortedKeys = BuffHitsBySpellCategory.Keys.ToList(); sortedKeys.Sort(); foreach (var key in sortedKeys) { sb.AppendLine(key.ToString().PadLeft(4) + " [" + BuffHitsBySpellCategory[key].ToString("N0").PadLeft(7) + " " + (BuffHitsBySpellCategory[key] / (float)TotalSpells * 100).ToString("N1").PadLeft(4) + "%] " + (SpellCategory)key); } } } sb.AppendLine(); { { sb.AppendLine("Hits By Cantrip Level: "); var totalHitsByCantrip = HitsByCantripLevel.Values.Sum(); var sortedKeys = HitsByCantripLevel.Keys.ToList(); sortedKeys.Sort(); foreach (var key in sortedKeys) { sb.AppendLine(key.ToString().PadLeft(9) + " [" + HitsByCantripLevel[key].ToString("N0").PadLeft(7) + " " + (HitsByCantripLevel[key] / (float)totalHitsByCantrip * 100).ToString("N1").PadLeft(6) + "%]"); } } sb.AppendLine("Cantrip Count Probabilities: "); if (CantripCountHits.Count > 0) { for (int i = CantripCountHits.Keys.Min(); i <= CantripCountHits.Keys.Max(); i++) { if (CantripCountHits.ContainsKey(i)) { sb.AppendLine(i.ToString().PadLeft(9) + " [" + CantripCountHits[i].ToString("N0").PadLeft(7) + " " + (CantripCountHits[i] / (float)TotalItems * 100).ToString("N3").PadLeft(6) + "%]"); } else { sb.AppendLine(i.ToString().PadLeft(9) + " [" + "0".PadLeft(7) + " " + "]"); } } } { sb.AppendLine("Cantrip Hits By Spell ID: "); var sortedKeys = CantripHitsBySpellID.Keys.ToList(); sortedKeys.Sort(); foreach (var key in sortedKeys) { sb.AppendLine(key.ToString().PadLeft(4) + " [" + CantripHitsBySpellID[key].ToString("N0").PadLeft(7) + " " + (CantripHitsBySpellID[key] / (float)TotalSpells * 100).ToString("N1").PadLeft(4) + "%] " + SpellTools.GetSpell(key).Name); } } { sb.AppendLine("Cantrip Hits By Spell Category: "); var sortedKeys = CantripHitsBySpellCategory.Keys.ToList(); sortedKeys.Sort(); foreach (var key in sortedKeys) { sb.AppendLine(key.ToString().PadLeft(4) + " [" + CantripHitsBySpellCategory[key].ToString("N0").PadLeft(7) + " " + (CantripHitsBySpellCategory[key] / (float)TotalSpells * 100).ToString("N1").PadLeft(4) + "%] " + (SpellCategory)key); } } } return(sb.ToString()); }