private void MenuItemExportHTMLClick(object sender, RoutedEventArgs e) { var tables = new Dictionary <string, SummaryTable>(); if (DamageWindow?.Content is DamageSummary damageSummary && DamageWindow?.IsOpen == true) { tables.Add(DamageWindow.Title, damageSummary); } if (HealingWindow?.Content is HealingSummary healingSummary && HealingWindow?.IsOpen == true) { tables.Add(HealingWindow.Title, healingSummary); } if (TankingWindow?.Content is TankingSummary tankingSummary && TankingWindow?.IsOpen == true) { tables.Add(TankingWindow.Title, tankingSummary); } if (tables.Count > 0) { TextFormatUtils.ExportAsHTML(tables); } else { _ = MessageBox.Show("Nothing to Save. Display a Summary View and Try Again.", Properties.Resources.FILEMENU_EXPORT_SUMMARY, MessageBoxButton.OK, MessageBoxImage.Exclamation); } }
internal Fight GetFight(string name) { Fight result = null; if (!string.IsNullOrEmpty(name)) { if (!ActiveFights.TryGetValue(name, out result)) { ActiveFights.TryGetValue(TextFormatUtils.FlipCase(name), out result); } } return(result); }
private void CopyCsvClick(object sender, RoutedEventArgs e) { if (LastSortedValues != null) { try { List <string> header = new List <string> { "Seconds", choicesList.SelectedValue as string, "Name" }; var data = new List <List <object> >(); LastSortedValues.Where(values => LastFilter == null || LastFilter(values.First())).ToList().ForEach(sortedValue => { foreach (var chartData in sortedValue) { double chartValue = 0; if (CurrentConfig == CONFIG_AVG) { chartValue = chartData.Avg; } else if (CurrentConfig == CONFIG_CRIT_RATE) { chartValue = chartData.CritRate; } else if (CurrentConfig == CONFIG_TOTAL) { chartValue = chartData.Total; } else if (CurrentConfig == CONFIG_VPS) { chartValue = chartData.VPS; } data.Add(new List <object> { chartData.CurrentTime, chartValue, chartData.Name }); Clipboard.SetDataObject(TextFormatUtils.BuildCsv(header, data, titleLabel.Content as string)); } }); } catch (ExternalException ex) { LOG.Error(ex); } } }
private void CopyCsvClick(object sender, RoutedEventArgs e) { try { var export = BuildExportData(); string result = TextFormatUtils.BuildCsv(export.Item1, export.Item2); Clipboard.SetDataObject(result); } catch (ArgumentNullException ane) { Clipboard.SetDataObject("EQ Log Parser Error: Failed to create BBCode\r\n"); LOG.Error(ane); } catch (ExternalException ex) { LOG.Error(ex); } }
private void CopyGamparseClick(object sender, RoutedEventArgs e) { try { var export = DataGridUtils.BuildExportData(dataGrid); string result = TextFormatUtils.BuildGamparseList(export.Item1, export.Item2, titleLabel.Content as string); Clipboard.SetDataObject(result); } catch (ArgumentNullException ane) { Clipboard.SetDataObject("EQ Log Parser Error: Failed to create BBCode\r\n"); LOG.Error(ane); } catch (ExternalException ex) { LOG.Error(ex); } }
internal static void CopyCsvFromTable(DataGrid dataGrid, string title) { try { var export = BuildExportData(dataGrid); string result = TextFormatUtils.BuildCsv(export.Item1, export.Item2, title); Clipboard.SetDataObject(result); } catch (ArgumentNullException ane) { Clipboard.SetDataObject("EQ Log Parser Error: Failed to create CSV\r\n"); LOG.Error(ane); } catch (ExternalException ex) { LOG.Error(ex); } }
private void CopyCsvClick(object sender, RoutedEventArgs e) { try { var header = new List <string> { "Hit Value", "Frequency", "Difference" }; List <List <object> > data = new List <List <object> >(); for (int i = 0; i < YValues.Count; i++) { data.Add(new List <object> { XValues[i], YValues[i], XValuesDiff[i] }); } Clipboard.SetDataObject(TextFormatUtils.BuildCsv(header, data)); } catch (ExternalException ex) { LOG.Error(ex); } }
private DataManager() { DictionaryListHelper <string, SpellData> helper = new DictionaryListHelper <string, SpellData>(); var spellList = new List <SpellData>(); ConfigUtil.ReadList(@"data\spells.txt").ForEach(line => { try { var spellData = TextFormatUtils.ParseCustomSpellData(line); if (spellData != null) { spellList.Add(spellData); SpellsNameDB[spellData.Name] = spellData; if (!SpellsAbbrvDB.ContainsKey(spellData.NameAbbrv)) { SpellsAbbrvDB[spellData.NameAbbrv] = spellData; } else if (string.Compare(SpellsAbbrvDB[spellData.NameAbbrv].Name, spellData.Name, true, CultureInfo.CurrentCulture) < 0) { // try to keep the newest version SpellsAbbrvDB[spellData.NameAbbrv] = spellData; } if (spellData.LandsOnOther.StartsWith("'s ", StringComparison.Ordinal)) { spellData.LandsOnOther = spellData.LandsOnOther.Substring(3); helper.AddToList(PosessiveLandsOnOthers, spellData.LandsOnOther, spellData); } else if (spellData.LandsOnOther.Length > 1) { spellData.LandsOnOther = spellData.LandsOnOther.Substring(1); helper.AddToList(NonPosessiveLandsOnOthers, spellData.LandsOnOther, spellData); } if (spellData.LandsOnYou.Length > 0) // just do stuff in common { helper.AddToList(LandsOnYou, spellData.LandsOnYou, spellData); } } } catch (OverflowException ex) { LOG.Error("Error reading spell data", ex); } }); // sort by duration for the timeline to pick better options foreach (var key in NonPosessiveLandsOnOthers.Keys) { NonPosessiveLandsOnOthers[key].Sort((a, b) => { int result = b.Duration.CompareTo(a.Duration); return(result != 0 ? result : b.ID.CompareTo(a.ID)); }); } foreach (var key in PosessiveLandsOnOthers.Keys) { PosessiveLandsOnOthers[key].Sort((a, b) => { int result = b.Duration.CompareTo(a.Duration); return(result != 0 ? result : b.ID.CompareTo(a.ID)); }); } foreach (var key in LandsOnYou.Keys) { LandsOnYou[key].Sort((a, b) => { int result = b.Duration.CompareTo(a.Duration); return(result != 0 ? result : b.ID.CompareTo(a.ID)); }); } Dictionary <string, byte> keepOut = new Dictionary <string, byte>(); var classEnums = Enum.GetValues(typeof(SpellClass)).Cast <SpellClass>().ToList(); spellList.ForEach(spell => { // exact match meaning class-only spell that are of certain target types var tgt = (SpellTarget)spell.Target; if ((tgt == SpellTarget.SELF || (spell.Level <= 250 && (tgt == SpellTarget.SINGLETARGET || tgt == SpellTarget.LOS))) && classEnums.Contains((SpellClass)spell.ClassMask)) { // these need to be unique and keep track if a conflict is found if (SpellsToClass.ContainsKey(spell.Name)) { SpellsToClass.Remove(spell.Name); keepOut[spell.Name] = 1; } else if (!keepOut.ContainsKey(spell.Name)) { SpellsToClass[spell.Name] = (SpellClass)spell.ClassMask; } } }); // load NPCs ConfigUtil.ReadList(@"data\npcs.txt").ForEach(line => AllNpcs[line.Trim()] = 1); PlayerManager.Instance.EventsNewTakenPetOrPlayerAction += (sender, name) => RemoveFight(name); PlayerManager.Instance.EventsNewVerifiedPlayer += (sender, name) => RemoveFight(name); PlayerManager.Instance.EventsNewVerifiedPet += (sender, name) => RemoveFight(name); }
internal bool IsLifetimeNpc(string name) => LifetimeFights.ContainsKey(name) || LifetimeFights.ContainsKey(TextFormatUtils.FlipCase(name));
private DataManager() { DictionaryListHelper <string, SpellData> helper = new DictionaryListHelper <string, SpellData>(); var spellList = new List <SpellData>(); // build ranks cache Enumerable.Range(1, 9).ToList().ForEach(r => RanksCache[r.ToString(CultureInfo.CurrentCulture)] = ""); Enumerable.Range(1, 200).ToList().ForEach(r => RanksCache[TextFormatUtils.IntToRoman(r)] = ""); RanksCache["Third"] = "Root"; RanksCache["Fifth"] = "Root"; RanksCache["Octave"] = "Root"; ConfigUtil.ReadList(@"data\spells.txt").ForEach(line => { try { var spellData = ParseCustomSpellData(line); if (spellData != null) { spellList.Add(spellData); SpellsNameDB[spellData.Name] = spellData; if (!SpellsAbbrvDB.ContainsKey(spellData.NameAbbrv)) { SpellsAbbrvDB[spellData.NameAbbrv] = spellData; } else if (string.Compare(SpellsAbbrvDB[spellData.NameAbbrv].Name, spellData.Name, true, CultureInfo.CurrentCulture) < 0) { // try to keep the newest version SpellsAbbrvDB[spellData.NameAbbrv] = spellData; } if (spellData.LandsOnOther.StartsWith("'s ", StringComparison.Ordinal)) { spellData.LandsOnOther = spellData.LandsOnOther.Substring(3); helper.AddToList(PosessiveLandsOnOthers, spellData.LandsOnOther, spellData); } else if (!string.IsNullOrEmpty(spellData.LandsOnOther)) { spellData.LandsOnOther = spellData.LandsOnOther.Substring(1); helper.AddToList(NonPosessiveLandsOnOthers, spellData.LandsOnOther, spellData); } if (!string.IsNullOrEmpty(spellData.LandsOnYou)) // just do stuff in common { helper.AddToList(LandsOnYou, spellData.LandsOnYou, spellData); } } } catch (OverflowException ex) { LOG.Error("Error reading spell data", ex); } }); // sort by duration for the timeline to pick better options NonPosessiveLandsOnOthers.Values.ToList().ForEach(value => value.Sort((a, b) => DurationCompare(a, b))); PosessiveLandsOnOthers.Values.ToList().ForEach(value => value.Sort((a, b) => DurationCompare(a, b))); LandsOnYou.Values.ToList().ForEach(value => value.Sort((a, b) => DurationCompare(a, b))); var keepOut = new Dictionary <string, byte>(); var classEnums = Enum.GetValues(typeof(SpellClass)).Cast <SpellClass>().ToList(); spellList.ForEach(spell => { // exact match meaning class-only spell that are of certain target types var tgt = (SpellTarget)spell.Target; if ((tgt == SpellTarget.SELF || (spell.Level <= 250 && (tgt == SpellTarget.SINGLETARGET || tgt == SpellTarget.LOS))) && classEnums.Contains((SpellClass)spell.ClassMask)) { // these need to be unique and keep track if a conflict is found if (SpellsToClass.ContainsKey(spell.Name)) { SpellsToClass.Remove(spell.Name); keepOut[spell.Name] = 1; } else if (!keepOut.ContainsKey(spell.Name)) { SpellsToClass[spell.Name] = (SpellClass)spell.ClassMask; } } }); // load NPCs ConfigUtil.ReadList(@"data\npcs.txt").ForEach(line => AllNpcs[line.Trim()] = 1); // Load Adps AdpsKeys.ForEach(adpsKey => AdpsActive[adpsKey] = new Dictionary <string, uint>()); AdpsKeys.ForEach(adpsKey => AdpsValues[adpsKey] = new Dictionary <string, uint>()); string key = null; foreach (var line in ConfigUtil.ReadList(@"data\adpsMeter.txt")) { if (!string.IsNullOrEmpty(line) && line.Trim() is string trimmed && trimmed.Length > 0) { if (trimmed[0] != '#' && !string.IsNullOrEmpty(key)) { if (trimmed.Split('|') is string[] multiple && multiple.Length > 0) { foreach (var spellLine in multiple) { if (spellLine.Split('=') is string[] list && list.Length == 2 && uint.TryParse(list[1], out uint rate)) { if (SpellsAbbrvDB.TryGetValue(list[0], out SpellData spellData) || SpellsNameDB.TryGetValue(list[0], out spellData)) { AdpsValues[key][spellData.NameAbbrv] = rate; if (!AdpsWearOff.TryGetValue(spellData.WearOff, out HashSet <SpellData> wearOffList)) { AdpsWearOff[spellData.WearOff] = new HashSet <SpellData>(); } AdpsWearOff[spellData.WearOff].Add(spellData); if (!AdpsLandsOn.TryGetValue(spellData.LandsOnYou, out HashSet <SpellData> landsOnList)) { AdpsLandsOn[spellData.LandsOnYou] = new HashSet <SpellData>(); } AdpsLandsOn[spellData.LandsOnYou].Add(spellData); } } } } } else if (AdpsKeys.Contains(trimmed)) { key = trimmed; } } } PlayerManager.Instance.EventsNewTakenPetOrPlayerAction += (sender, name) => RemoveFight(name); PlayerManager.Instance.EventsNewVerifiedPlayer += (sender, name) => RemoveFight(name); PlayerManager.Instance.EventsNewVerifiedPet += (sender, name) => RemoveFight(name); int DurationCompare(SpellData a, SpellData b) { if (b.Duration.CompareTo(a.Duration) is int result && result == 0) { if (int.TryParse(a.ID, out int aInt) && int.TryParse(b.ID, out int bInt) && aInt != bInt) { result = aInt > bInt ? -1 : 1; } } return(result); } }
private void Load() { Helpers.SetBusy(true); var npcStatsRows = new Dictionary <string, NpcStatsRow>(); foreach (var kv in DataManager.Instance.GetNpcResistStats()) { if (!PlayerManager.Instance.IsPetOrPlayer(kv.Key) && !PlayerManager.Instance.IsPetOrPlayer(TextFormatUtils.ToUpper(kv.Key))) { var row = new NpcStatsRow { Name = TextFormatUtils.CapitalizeNpc(kv.Key) }; foreach (var resists in kv.Value) { var rate = GetRate(resists.Value.Landed, resists.Value.Resisted); switch (resists.Key) { case SpellResist.AVERAGE: row.Average = rate.Item1; row.AverageText = rate.Item2; row.AverageTotal = resists.Value.Landed + resists.Value.Resisted; break; case SpellResist.COLD: row.Cold = rate.Item1; row.ColdText = rate.Item2; row.ColdTotal = resists.Value.Landed + resists.Value.Resisted; break; case SpellResist.CORRUPTION: row.Corruption = rate.Item1; row.CorruptionText = rate.Item2; row.CorruptionTotal = resists.Value.Landed + resists.Value.Resisted; break; case SpellResist.DISEASE: row.Disease = rate.Item1; row.DiseaseText = rate.Item2; row.DiseaseTotal = resists.Value.Landed + resists.Value.Resisted; break; case SpellResist.FIRE: row.Fire = rate.Item1; row.FireText = rate.Item2; row.FireTotal = resists.Value.Landed + resists.Value.Resisted; break; case SpellResist.LOWEST: row.Lowest = rate.Item1; row.LowestText = rate.Item2; row.LowestTotal = resists.Value.Landed + resists.Value.Resisted; break; case SpellResist.MAGIC: row.Magic = rate.Item1; row.MagicText = rate.Item2; row.MagicTotal = resists.Value.Landed + resists.Value.Resisted; break; case SpellResist.PHYSICAL: row.Physical = rate.Item1; row.PhysicalText = rate.Item2; row.PhysicalTotal = resists.Value.Landed + resists.Value.Resisted; break; case SpellResist.POISON: row.Poison = rate.Item1; row.PoisonText = rate.Item2; row.PoisonTotal = resists.Value.Landed + resists.Value.Resisted; break; } } npcStatsRows[kv.Key] = row; } } foreach (var kv in DataManager.Instance.GetNpcTotalSpellCounts()) { if (!npcStatsRows.TryGetValue(kv.Key, out NpcStatsRow updateRow)) { updateRow = new NpcStatsRow { Name = TextFormatUtils.CapitalizeNpc(kv.Key) }; } var rate = GetRate(kv.Value.Landed, kv.Value.Reflected); updateRow.Reflected = rate.Item1; updateRow.ReflectedText = rate.Item2; updateRow.ReflectedTotal = kv.Value.Landed + kv.Value.Reflected; } dataGrid.ItemsSource = npcStatsRows.Values.OrderBy(row => row.Name).ToList(); titleLabel.Content = npcStatsRows.Values.Count == 0 ? NODATA : "Your Spell Stats for " + npcStatsRows.Count + " Unique NPCs"; Helpers.SetBusy(false); Tuple <double, string> GetRate(uint landed, uint notLanded) { Tuple <double, string> results; double computed = 0.0; uint total = landed + notLanded; if (landed == 0 && total > 0) { computed = 1.0; } else if (total > 0) { computed = notLanded / (double)total; } if (total > 0) { computed = Math.Round(computed * 100, 2); string computedString = string.Format(CultureInfo.CurrentCulture, "{0} ({1}/{2})", computed, notLanded, total); results = new Tuple <double, string>(computed, computedString); } else { results = new Tuple <double, string>(0.0, "-"); } return(results); } }
public static void Process(LineData lineData) { bool handled = false; try { string[] split = lineData.Action.Split(' '); if (split != null && split.Length >= 2) { int stop = split.Length - 1; if (!string.IsNullOrEmpty(split[stop]) && split[stop][split[stop].Length - 1] == ')') { for (int i = stop; i >= 0 && stop > 2; i--) { if (!string.IsNullOrEmpty(split[i]) && split[i][0] == '(') { stop = i - 1; break; } } } // see if it's a died message right away if (split.Length > 1 && stop >= 1 && split[stop] == "died.") { var test = string.Join(" ", split, 0, stop); if (!string.IsNullOrEmpty(test)) { UpdateSlain(test, "", lineData); handled = true; } } if (!handled) { int byIndex = -1, forIndex = -1, pointsOfIndex = -1, endDamage = -1, byDamage = -1, extraIndex = -1; int fromDamage = -1, hasIndex = -1, haveIndex = -1, hitType = -1, hitTypeAdd = -1, slainIndex = -1; int takenIndex = -1, tryIndex = -1, yourIndex = -1, isIndex = -1, dsIndex = -1, butIndex = -1; int missType = -1, nonMeleeIndex = -1; string subType = null; bool found = false; for (int i = 0; i <= stop && !found; i++) { if (!string.IsNullOrEmpty(split[i])) { switch (split[i]) { case "healed": found = true; // short circuit break; case "but": butIndex = i; break; case "is": case "was": isIndex = i; break; case "has": hasIndex = i; break; case "have": haveIndex = i; break; case "by": byIndex = i; if (slainIndex > -1) { found = true; // short circut } else if (i > 4 && split[i - 1] == "damage") { byDamage = i - 1; } break; case "from": if (i > 3 && split[i - 1] == "damage") { fromDamage = i - 1; if (pointsOfIndex > -1 && extraIndex > -1) { found = true; // short circut } else if (stop > (i + 1) && split[i + 1] == "your") { yourIndex = i + 1; } } break; case "damage.": if (i == stop) { endDamage = i; } break; case "non-melee": nonMeleeIndex = i; if (i > 9 && stop == (i + 1) && split[i + 1] == "damage." && pointsOfIndex == (i - 2) && forIndex == (i - 4)) { dsIndex = i - 5; found = true; // short circut } break; case "point": case "points": if (stop >= (i + 1) && split[i + 1] == "of") { pointsOfIndex = i; if (i > 2 && split[i - 2] == "for") { forIndex = i - 2; } } break; case "blocks!": missType = (stop == i && butIndex > -1 && i > tryIndex) ? 0 : missType; break; case "shield!": case "staff!": missType = (i > 5 && stop == i && butIndex > -1 && i > tryIndex && split[i - 2] == "with" && split[i - 3].StartsWith("block", StringComparison.OrdinalIgnoreCase)) ? 0 : missType; break; case "dodge!": case "dodges!": missType = (stop == i && butIndex > -1 && i > tryIndex) ? 1 : missType; break; case "miss!": case "misses!": missType = (stop == i && butIndex > -1 && i > tryIndex) ? 2 : missType; break; case "parries!": missType = (stop == i && butIndex > -1 && i > tryIndex) ? 3 : missType; break; case "INVULNERABLE!": missType = (stop == i && butIndex > -1 && i > tryIndex) ? 4 : missType; break; case "slain": slainIndex = i; break; case "taken": if (i > 1 && (hasIndex == (i - 1) || haveIndex == (i - 1))) { takenIndex = i - 1; if (stop > (i + 2) && split[i + 1] == "an" && split[i + 2] == "extra") { extraIndex = i + 2; } } break; // Old (EQEMU) crit and crippling blow handling case "hit!": if (stop == i && split.Length > 4 && split[i - 1] == "critical" && split[i - 3] == "scores") { LastCrit = new OldCritData { Attacker = split[0], LineData = lineData }; } break; case "Crippling": if (stop == (i + 1) && split.Length > 4 && split[i + 1].StartsWith("Blow!") && split[i - 2] == "lands") { LastCrit = new OldCritData { Attacker = split[0], LineData = lineData }; } break; default: if (slainIndex == -1 && i > 0 && string.IsNullOrEmpty(subType) && HitMap.TryGetValue(split[i], out subType)) { hitType = i; if (i < stop && HitAdditionalMap.ContainsKey(split[i])) { hitTypeAdd = i + i; } if (i > 2 && split[i - 1] == "to" && (split[i - 2] == "tries" || split[i - 2] == "try")) { tryIndex = i - 2; } } break; } } } // [Sun Apr 18 19:36:39 2021] Tantor is pierced by Tolzol's thorns for 6718 points of non-melee damage. // [Mon Apr 19 22:02:52 2021] Honvar is tormented by Reisil's frost for 7809 points of non-melee damage. // [Sun Apr 25 13:47:12 2021] Test One Hundred Three is burned by YOUR flames for 5224 points of non-melee damage. // [Sun Apr 18 14:16:13 2021] A failed reclaimer is pierced by YOUR thorns for 193 points of non-melee damage. if (dsIndex > -1 && pointsOfIndex > dsIndex && isIndex > -1 && isIndex < dsIndex && byIndex > isIndex) { string attacker = string.Join(" ", split, byIndex + 1, dsIndex - byIndex - 1); if (!string.IsNullOrEmpty(attacker)) { var valid = attacker == "YOUR"; if (!valid && attacker.EndsWith("'s", StringComparison.OrdinalIgnoreCase)) { attacker = attacker.Substring(0, attacker.Length - 2); valid = true; } if (valid) { string defender = string.Join(" ", split, 0, isIndex); uint damage = StatsUtil.ParseUInt(split[pointsOfIndex - 1]); handled = CreateDamageRecord(lineData, split, stop, attacker, defender, damage, Labels.DS, Labels.DS); } } } // [Mon May 10 22:18:46 2021] A dendridic shard was chilled to the bone for 410 points of non-melee damage. else if (dsIndex > -1 && pointsOfIndex > dsIndex && isIndex > -1 && isIndex < dsIndex && byIndex == -1) { string defender = string.Join(" ", split, 0, isIndex); uint damage = StatsUtil.ParseUInt(split[pointsOfIndex - 1]); handled = CreateDamageRecord(lineData, split, stop, Labels.RS, defender, damage, Labels.DS, Labels.DS); } // [Tue Mar 26 22:43:47 2019] a wave sentinel has taken an extra 6250000 points of non-melee damage from Kazint's Greater Fetter spell. else if (extraIndex > -1 && pointsOfIndex == (extraIndex + 2) && fromDamage == (pointsOfIndex + 3) && split[stop] == "spell.") { if (split[fromDamage + 2].EndsWith("'s", StringComparison.OrdinalIgnoreCase)) { string attacker = split[fromDamage + 2].Substring(0, split[fromDamage + 2].Length - 2); string defender = string.Join(" ", split, 0, takenIndex); uint damage = StatsUtil.ParseUInt(split[extraIndex + 1]); string spell = string.Join(" ", split, fromDamage + 3, stop - fromDamage - 3); var spellData = DataManager.Instance.GetDamagingSpellByName(spell); SpellResist resist = spellData != null ? spellData.Resist : SpellResist.UNDEFINED; handled = CreateDamageRecord(lineData, split, stop, attacker, defender, damage, Labels.BANE, spell, resist); } } // [Sun Apr 18 21:26:15 2021] Astralx crushes Sontalak for 126225 points of damage. (Strikethrough Critical) // [Sun Apr 18 20:20:32 2021] Susarrak the Crusader claws Villette for 27699 points of damage. (Strikethrough Wild Rampage) else if (!string.IsNullOrEmpty(subType) && endDamage > -1 && pointsOfIndex == (endDamage - 2) && forIndex > -1 && hitType < forIndex) { int hitTypeMod = hitTypeAdd > 0 ? 1 : 0; string attacker = string.Join(" ", split, 0, hitType); string defender = string.Join(" ", split, hitType + hitTypeMod + 1, forIndex - hitType - hitTypeMod - 1); subType = TextFormatUtils.ToUpper(subType); uint damage = StatsUtil.ParseUInt(split[pointsOfIndex - 1]); handled = CreateDamageRecord(lineData, split, stop, attacker, defender, damage, Labels.MELEE, subType); } // [Sun Apr 18 20:24:56 2021] Sonozen hit Jortreva the Crusader for 38948 points of fire damage by Burst of Flames. (Lucky Critical Twincast) else if (byDamage > 3 && pointsOfIndex == (byDamage - 3) && byIndex == (byDamage + 1) && forIndex > -1 && subType == "hits" && hitType < forIndex && split[stop].Length > 0 && split[stop][split[stop].Length - 1] == '.') { string spell = string.Join(" ", split, byIndex + 1, stop - byIndex); if (!string.IsNullOrEmpty(spell) && spell[spell.Length - 1] == '.') { spell = spell.Substring(0, spell.Length - 1); string attacker = string.Join(" ", split, 0, hitType); string defender = string.Join(" ", split, hitType + 1, forIndex - hitType - 1); string type = GetTypeFromSpell(spell, Labels.DD); uint damage = StatsUtil.ParseUInt(split[pointsOfIndex - 1]); SpellResist resist = SpellResist.UNDEFINED; SpellResistMap.TryGetValue(split[byDamage - 1], out resist); // extra way to check for pets if (spell.StartsWith("Elemental Conversion", StringComparison.Ordinal)) { PlayerManager.Instance.AddVerifiedPet(defender); } handled = CreateDamageRecord(lineData, split, stop, attacker, defender, damage, type, spell, resist); } } // [Sun Apr 18 20:32:39 2021] Dovhesi has taken 173674 damage from Curse of the Shrine by Grendish the Crusader. // [Sun Apr 18 20:32:42 2021] Grendish the Crusader has taken 1003231 damage from Pyre of Klraggek Rk. III by Atvar. (Lucky Critical) // [Thu Mar 18 18:48:10 2021] You have taken 4852 damage from Nectar of Misery by Commander Gartik. // [Thu Mar 18 01:05:46 2021] A gnoll has taken 108790 damage from your Mind Coil Rk. II. // Old (eqemu) [Sat Jan 15 21:09:10 2022] Pixtt Invi Mal has taken 189 damage from Goanna by Tuyen`s Chant of Fire. else if (fromDamage > 3 && takenIndex == (fromDamage - 3) && (byIndex > fromDamage || yourIndex > fromDamage)) { string attacker = null; string spell = null; if (byIndex > -1) { attacker = string.Join(" ", split, byIndex + 1, stop - byIndex); attacker = (!string.IsNullOrEmpty(attacker) && attacker[attacker.Length - 1] == '.') ? attacker.Substring(0, attacker.Length - 1) : null; spell = string.Join(" ", split, fromDamage + 2, byIndex - fromDamage - 2); } else if (yourIndex > -1) { attacker = split[yourIndex]; spell = string.Join(" ", split, yourIndex + 1, stop - yourIndex); spell = (!string.IsNullOrEmpty(spell) && spell[spell.Length - 1] == '.') ? spell.Substring(0, spell.Length - 1) : Labels.DOT; } if (!string.IsNullOrEmpty(attacker) && !string.IsNullOrEmpty(spell)) { string type; SpellData spellData = DataManager.Instance.GetDamagingSpellByName(spell); // Old (eqemu) if attacker is actually a spell then swap attacker and spell // Spells dont change on eqemu servers so this should always be a spell even with old spell data if (spellData == null && DataManager.Instance.IsOldSpell(attacker)) { // check that we can't find a spell where the player name is var temp = attacker; attacker = spell; spell = temp; type = Labels.DOT; } else { type = GetTypeFromSpell(spell, Labels.DOT); } string defender = string.Join(" ", split, 0, takenIndex); uint damage = StatsUtil.ParseUInt(split[fromDamage - 1]); SpellResist resist = spellData != null ? spellData.Resist : SpellResist.UNDEFINED; handled = CreateDamageRecord(lineData, split, stop, attacker, defender, damage, type, spell, resist); } } // [Mon Apr 26 21:07:21 2021] Lawlstryke has taken 216717 damage by Wisp Explosion. else if (byDamage > -1 && takenIndex == (byDamage - 3)) { string defender = string.Join(" ", split, 0, takenIndex); uint damage = StatsUtil.ParseUInt(split[byDamage - 1]); string spell = string.Join(" ", split, byDamage + 2, stop - byDamage - 1); if (!string.IsNullOrEmpty(spell) && spell[spell.Length - 1] == '.') { spell = spell.Substring(0, spell.Length - 1); } SpellResist resist = SpellResist.UNDEFINED; if (DataManager.Instance.GetDamagingSpellByName(spell) is SpellData spellData && spellData != null) { resist = spellData.Resist; } handled = CreateDamageRecord(lineData, split, stop, "", defender, damage, Labels.DOT, spell, resist, true); } // Old (eqemu direct damage) [Sat Jan 15 21:08:54 2022] Jaun hit Pixtt Invi Mal for 150 points of non-melee damage. else if (hitType > -1 && forIndex > -1 && forIndex < pointsOfIndex && nonMeleeIndex > pointsOfIndex) { int hitTypeMod = hitTypeAdd > 0 ? 1 : 0; string attacker = string.Join(" ", split, 0, hitType); string defender = string.Join(" ", split, hitType + hitTypeMod + 1, forIndex - hitType - hitTypeMod - 1); uint damage = StatsUtil.ParseUInt(split[pointsOfIndex - 1]); handled = CreateDamageRecord(lineData, split, stop, attacker, defender, damage, Labels.DD, Labels.DD); } // [Mon Aug 05 02:05:12 2019] An enchanted Syldon stalker tries to crush YOU, but misses! (Strikethrough) // [Sat Aug 03 00:20:57 2019] You try to crush a Kar`Zok soldier, but miss! (Riposte Strikethrough) // [Sat Apr 24 01:08:49 2021] Test One Hundred Three tries to punch Kazint, but misses! // [Sat Apr 24 01:08:49 2021] Test One Hundred Three tries to punch Kazint, but Kazint dodges! // [Sat Apr 24 01:10:17 2021] Test One Hundred Three tries to punch YOU, but YOU dodge! // [Sat Apr 24 01:10:17 2021] Kazint tries to crush Test One Hundred Three, but Test One Hundred Three dodges! // [Sun Apr 18 19:45:21 2021] You try to crush a primal guardian, but a primal guardian parries! // [Mon May 31 20:29:49 2021] A bloodthirsty gnawer tries to bite Vandil, but Vandil parries! // [Sun Apr 25 22:56:22 2021] Romance tries to bash Vulak`Aerr, but Vulak`Aerr parries! // [Sun Jul 28 20:12:46 2019] Drogbaa tries to slash Whirlrender Scout, but misses! (Strikethrough) // [Tue Mar 30 16:43:54 2021] You try to crush a desert madman, but a desert madman blocks! // [Mon Apr 26 22:40:10 2021] An ancient warden tries to hit Reisil, but Reisil blocks with his shield! // [Sun Mar 21 00:11:31 2021] A carrion bat tries to bite YOU, but YOU block with your shield! // [Mon Apr 26 14:51:01 2021] A windchill sprite tries to smash YOU, but YOU block with your staff! // [Mon May 10 22:18:46 2021] Tolzol tries to crush Dendritic Golem, but Dendritic Golem is INVULNERABLE! else if (tryIndex > -1 && butIndex > tryIndex && missType > -1) { string label = null; switch (missType) { case 0: label = Labels.BLOCK; break; case 1: label = Labels.DODGE; break; case 2: label = Labels.MISS; break; case 3: label = Labels.PARRY; break; case 4: label = Labels.INVULNERABLE; break; } if (!string.IsNullOrEmpty(label)) { int hitTypeMod = hitTypeAdd > 0 ? 1 : 0; string defender = string.Join(" ", split, hitType + hitTypeMod + 1, butIndex - hitType - hitTypeMod - 1); if (!string.IsNullOrEmpty(defender) && defender[defender.Length - 1] == ',') { defender = defender.Substring(0, defender.Length - 1); string attacker = string.Join(" ", split, 0, tryIndex); subType = TextFormatUtils.ToUpper(subType); handled = CreateDamageRecord(lineData, split, stop, attacker, defender, 0, label, subType); } } } // [Sun Apr 18 21:26:20 2021] Strangle`s pet has been slain by Kzerk! else if (slainIndex > -1 && byIndex == (slainIndex + 1) && hasIndex > 0 && stop > (slainIndex + 1) && split[hasIndex + 1] == "been") { string killer = string.Join(" ", split, byIndex + 1, stop - byIndex); killer = killer.Length > 1 && killer[killer.Length - 1] == '!' ? killer.Substring(0, killer.Length - 1) : killer; string slain = string.Join(" ", split, 0, hasIndex); handled = UpdateSlain(slain, killer, lineData); HasOwner(slain, out string t1); HasOwner(killer, out string t2); } // [Mon Apr 19 02:22:09 2021] You have been slain by an armed flyer! else if (stop > 4 && slainIndex == 3 && byIndex == 4 && split[0] == "You" && split[1] == "have" && split[2] == "been") { string killer = string.Join(" ", split, 5, stop - 4); killer = killer.Length > 1 && killer[killer.Length - 1] == '!' ? killer.Substring(0, killer.Length - 1) : killer; string slain = ConfigUtil.PlayerName; handled = UpdateSlain(slain, killer, lineData); } // [Mon Apr 19 02:22:09 2021] You have slain a failed bodyguard! else if (slainIndex == 2 && split[0] == "You" && split[1] == "have") { string killer = ConfigUtil.PlayerName; string slain = string.Join(" ", split, 3, stop - 2); slain = slain.Length > 1 && slain[slain.Length - 1] == '!' ? slain.Substring(0, slain.Length - 1) : slain; handled = UpdateSlain(slain, killer, lineData); } } } } catch (Exception e) { LOG.Error(e); } DebugUtil.UnregisterLine(lineData.LineNumber, handled); }