private static DamageRecord ParseDS(string[] data, int isAreIndex, int byIndex, int forIndex) { DamageRecord record = null; string defender = string.Join(" ", data, 0, isAreIndex); uint damage = StatsUtil.ParseUInt(data[forIndex + 1]); string attacker; if (data[byIndex + 1] == "YOUR") { attacker = "you"; } else { attacker = string.Join(" ", data, byIndex + 1, forIndex - byIndex - 2); attacker = attacker.Substring(0, attacker.Length - 2); } // check for pets HasOwner(attacker, out string attackerOwner); HasOwner(defender, out string defenderOwner); if (attacker != null && defender != null) { record = BuildRecord(attacker, defender, damage, attackerOwner, defenderOwner, Labels.DS, Labels.DS); } return(record); }
private static DamageRecord ParseHasTaken(string[] data, int takenIndex, int fromIndex, int byIndex, StringBuilder builder) { DamageRecord record = null; uint damage = StatsUtil.ParseUInt(data[takenIndex + 1]); string defender = string.Join(" ", data, 0, takenIndex - 1); string spell = null; string attacker = null; if (byIndex > -1 && fromIndex < byIndex) { spell = string.Join(" ", data, fromIndex + 1, byIndex - fromIndex - 1); attacker = ReadStringToPeriod(data, byIndex, builder); } else if (data[fromIndex + 1] == "your") { spell = ReadStringToPeriod(data, fromIndex + 1, builder); attacker = "you"; } if (attacker != null && spell != null) { // check for pets HasOwner(attacker, out string attackerOwner); HasOwner(defender, out string defenderOwner); if (attacker != null && defender != null) { record = BuildRecord(attacker, defender, damage, attackerOwner, defenderOwner, spell, GetTypeFromSpell(spell, Labels.DOT)); } } return(record); }
private static DamageRecord ParseExtra(string[] data, int takenIndex, int extraIndex, int fromIndex, List <string> nameList) { DamageRecord record = null; uint damage = StatsUtil.ParseUInt(data[extraIndex + 1]); string defender = string.Join(" ", data, 0, takenIndex - 1); string attacker = null; string spell = null; if (data.Length > fromIndex + 1) { int person = fromIndex + 1; if (data[person] == "your") { attacker = "you"; } else { int len = data[person].Length; if (len > 2 && data[person][len - 2] == '\'' && data[person][len - 1] == 's') { attacker = data[person].Substring(0, len - 2); } } if (attacker != null) { nameList.Clear(); for (int i = person + 1; i < data.Length; i++) { if (data[i] == "spell.") { break; } else { nameList.Add(data[i]); } } spell = string.Join(" ", nameList); } } // check for pets HasOwner(attacker, out string attackerOwner); HasOwner(defender, out string defenderOwner); if (attacker != null && defender != null) { record = BuildRecord(attacker, defender, damage, attackerOwner, defenderOwner, spell, Labels.BANE); } return(record); }
private static DamageRecord ParseHasTaken(string[] data, int takenIndex, int fromIndex, int byIndex, StringBuilder builder) { DamageRecord record = null; uint damage = StatsUtil.ParseUInt(data[takenIndex + 1]); string defender = string.Join(" ", data, 0, takenIndex - 1); string spell = null; string attacker = null; if (byIndex > -1 && fromIndex < byIndex) { attacker = ReadStringToPeriod(data, byIndex, builder); if (fromIndex > -1) { spell = string.Join(" ", data, fromIndex + 1, byIndex - fromIndex - 1); } else { spell = attacker; var spellData = DataManager.Instance.GetSpellByName(spell); if (spellData != null && ((spellData.ClassMask > 0 && spellData.Level < 255) || spellData.NameAbbrv != spellData.Name)) { attacker = Labels.UNK; } } } else if (fromIndex > -1 && data[fromIndex + 1] == "your") { spell = ReadStringToPeriod(data, fromIndex + 1, builder); attacker = "you"; } if (attacker != null && spell != null) { // check for pets HasOwner(attacker, out string attackerOwner); HasOwner(defender, out string defenderOwner); if (attacker != null && defender != null) { record = BuildRecord(attacker, defender, damage, attackerOwner, defenderOwner, spell, GetTypeFromSpell(spell, Labels.DOT)); } } return(record); }
private static DamageRecord ParseYouHaveTaken(string[] data, int takenIndex, int fromIndex, int byIndex, StringBuilder builder) { DamageRecord record = null; string defender = "you"; string attacker = ReadStringToPeriod(data, byIndex, builder); string spell = string.Join(" ", data, fromIndex + 1, byIndex - fromIndex - 1); uint damage = StatsUtil.ParseUInt(data[takenIndex + 1]); // check for pets HasOwner(attacker, out string attackerOwner); if (attacker != null && defender != null) { record = BuildRecord(attacker, defender, damage, attackerOwner, null, spell, GetTypeFromSpell(spell, Labels.DD)); } return(record); }
private static bool ParseCurrency(string[] pieces, int startIndex, int toIndex, out string item, out uint count) { bool parsed = true; item = null; count = 0; List <string> tmp = new List <string>(); for (int i = startIndex; i < toIndex; i += 2) { if (pieces[i] == "and") { i -= 1; continue; } if (StatsUtil.ParseUInt(pieces[i]) is uint value && Currency.FirstOrDefault(curr => pieces[i + 1].StartsWith(curr, StringComparison.OrdinalIgnoreCase)) is string type) { tmp.Add(pieces[i] + " " + type); count += value * Rates[pieces[i + 1][0]]; }
private static DamageRecord ParseYouHaveTaken(string[] data, int takenIndex, int fromIndex, int byIndex, StringBuilder builder) { DamageRecord record = null; string defender = "you"; string attacker = null; string spell = null; if (byIndex == -1) { spell = ReadStringToPeriod(data, fromIndex, builder); var spellData = DataManager.Instance.GetSpellByName(spell); if (spellData != null && ((spellData.ClassMask > 0 && spellData.Level < 255) || spellData.NameAbbrv != spellData.Name)) { defender = null; } else { attacker = spell; } } else { attacker = ReadStringToPeriod(data, byIndex, builder); spell = string.Join(" ", data, fromIndex + 1, byIndex - fromIndex - 1); } uint damage = StatsUtil.ParseUInt(data[takenIndex + 1]); // check for pets HasOwner(attacker, out string attackerOwner); if (attacker != null && defender != null) { record = BuildRecord(attacker, defender, damage, attackerOwner, null, spell, GetTypeFromSpell(spell, Labels.DD)); } return(record); }
private static DamageRecord ParsePointsOf(string[] data, bool isNonMelee, int forIndex, int byIndex, int hitIndex, StringBuilder builder, List <string> nameList) { DamageRecord record = null; uint damage = StatsUtil.ParseUInt(data[forIndex + 1]); string type = null; string subType = null; string attacker = null; if (byIndex > 1) { // possible spell subType = ReadStringToPeriod(data, byIndex, builder); } // before hit nameList.Clear(); for (int i = hitIndex - 1; i >= 0; i--) { if (data[hitIndex].EndsWith(".", StringComparison.Ordinal)) { break; } else { nameList.Insert(0, data[i]); } } if (nameList.Count > 0) { attacker = string.Join(" ", nameList); } if (!isNonMelee) { subType = GetTypeFromHit(data[hitIndex], out bool additional); if (subType != null) { type = Labels.MELEE; if (additional) { hitIndex++; // multi-word hit value } } } if (!string.IsNullOrEmpty(subType) && isNonMelee) { type = GetTypeFromSpell(subType, Labels.DD); } string defender = string.Join(" ", data, hitIndex + 1, forIndex - hitIndex - 1); // check for pets HasOwner(attacker, out string attackerOwner); HasOwner(defender, out string defenderOwner); // some new special cases if (!string.IsNullOrEmpty(subType) && subType.StartsWith("Elemental Conversion", StringComparison.Ordinal)) { PlayerManager.Instance.AddVerifiedPet(defender); } else if (!string.IsNullOrEmpty(attacker) && !string.IsNullOrEmpty(defender)) { record = BuildRecord(attacker, defender, damage, attackerOwner, defenderOwner, subType, type); } return(record); }
public static void Process(LineData lineData) { bool handled = false; try { string[] split = lineData.Action.Split(' '); if (split != null && split.Length >= 2) { // [Sun Mar 01 22:20:36 2020] A shaded torch has been awakened by Drogbaa. // [Sun Mar 01 20:35:55 2020] The master looter, Qulas, looted 32426 platinum from the corpse. // [Sun Mar 01 23:51:02 2020] You receive 129 platinum, 2 gold and 1 copper as your split (with a lucky bonus). // [Sun Feb 02 22:43:51 2020] You receive 28 platinum, 7 gold, 2 silver and 5 copper as your split. // [Sun Feb 02 23:31:23 2020] You receive 57 platinum as your split. // [Fri Feb 07 22:01:20 2020] --Kizant has looted a Lesser Engraved Velium Rune from Velden Dragonbane's corpse.-- // [Sat Feb 08 01:20:26 2020] --Proximoe has looted a Velium Infused Spider Silk from a restless devourer's corpse.-- // [Sat Feb 08 21:21:36 2020] --You have looted a Cold-Forged Cudgel from Queen Dracnia's corpse.-- // [Mon Apr 27 22:32:04 2020] Restless Tijoely resisted your Stormjolt Vortex Effect! // [Mon Apr 27 20:51:22 2020] Kazint's Scorching Beam Rk. III spell has been reflected by a shadow reflection. // [Sun Mar 28 19:42:46 2021] A Draconic Lava Chain Feet Ornament was given to Aldryn. string looter = null; int awakenedIndex = -1; int lootedIndex = -1; int masterLootIndex = -1; int receiveIndex = -1; int resistedIndex = -1; int isIndex = -1; for (int i = 0; i < split.Length && !handled; i++) { if (i == 0 && split[0].StartsWith("--", StringComparison.OrdinalIgnoreCase)) { looter = split[0] == "--You" ? ConfigUtil.PlayerName : split[0].TrimStart('-'); } else { switch (split[i]) { case "awakened": awakenedIndex = i; break; case "is": isIndex = i; break; case "looted": lootedIndex = i; break; case "looter,": masterLootIndex = (i == 2 && split[1] == "master" && split[0] == "The") ? masterLootIndex = i + 1 : -1; break; case "receive": receiveIndex = (i == 1 && split[0] == "You") ? i : -1; break; case "reflected": if (split.Length > 6 && i >= 6 && i + 2 < split.Length && split[0].StartsWith(ConfigUtil.PlayerName, StringComparison.Ordinal) && split[i - 1] == "been" && split[i - 2] == "has" && split[i - 3] == "spell" && split[i + 1] == "by") { // var spell = string.Join(" ", split, 1, i - 4); var npc = string.Join(" ", split, i + 2, split.Length - i - 2).TrimEnd('.'); DataManager.Instance.UpdateNpcSpellReflectStats(npc); handled = true; } break; case "resisted": resistedIndex = i; break; case "your": if (resistedIndex > 0 && resistedIndex + 1 == i && split.Length > i + 1 && split[split.Length - 1].EndsWith("!", StringComparison.Ordinal)) { string npc = string.Join(" ", split, 0, resistedIndex); string spell = string.Join(" ", split, i + 1, split.Length - i - 1).TrimEnd('!'); DataManager.Instance.AddResistRecord(new ResistRecord() { Defender = npc, Spell = spell }, DateUtil.ParseLogDate(lineData.Line)); handled = true; } break; case "by": if (awakenedIndex > -1 && awakenedIndex == (i - 1) && split.Length > 5 && split[i - 2] == "been" && split[i - 3] == "has") { string awakened = string.Join(" ", split, 0, i - 3); string breaker = string.Join(" ", split, i + 1, split.Length - i - 1).TrimEnd('.'); DataManager.Instance.AddMiscRecord(new MezBreakRecord { Breaker = breaker, Awakened = awakened }, DateUtil.ParseLogDate(lineData.Line)); handled = true; } else if (isIndex > 0 && StruckByTypes.ContainsKey(split[i - 1])) { // ignore common lines like: is struck by handled = true; } break; case "from": if (masterLootIndex > -1 && lootedIndex > masterLootIndex && split.Length > lootedIndex + 1 && split.Length > 3) { string name = split[3].TrimEnd(','); if (ParseCurrency(split, lootedIndex + 1, i, out string item, out uint count)) { PlayerManager.Instance.AddVerifiedPlayer(name); LootRecord record = new LootRecord() { Item = item, Player = name, Quantity = count, IsCurrency = true }; DataManager.Instance.AddLootRecord(record, DateUtil.ParseLogDate(lineData.Line)); handled = true; } } else if (!string.IsNullOrEmpty(looter) && lootedIndex == 2 && split.Length > 4) { // covers "a" or "an" uint count = split[3][0] == 'a' ? 1 : StatsUtil.ParseUInt(split[3]); string item = string.Join(" ", split, 4, i - 4); string npc = string.Join(" ", split, i + 1, split.Length - i - 1).TrimEnd(LootedFromTrim).Replace("'s corpse", ""); if (count > 0 && count != ushort.MaxValue) { PlayerManager.Instance.AddVerifiedPlayer(looter); LootRecord record = new LootRecord() { Item = item, Player = looter, Quantity = count, IsCurrency = false, Npc = npc }; DataManager.Instance.AddLootRecord(record, DateUtil.ParseLogDate(lineData.Line)); handled = true; } } break; case "given": if (split[i - 1] == "was" && split.Length == (i + 3) && split[i + 1] == "to") { string player = split[i + 2]; if (player.Length > 3) { looter = player.Substring(0, player.Length - 1); looter = looter.Equals("you", StringComparison.OrdinalIgnoreCase) ? ConfigUtil.PlayerName : looter; string item = string.Join(" ", split, 1, i - 2); LootRecord record = new LootRecord() { Item = item, Player = looter, Quantity = 0, IsCurrency = false, Npc = "Assigned (Not Looted)" }; DataManager.Instance.AddLootRecord(record, DateUtil.ParseLogDate(lineData.Line)); handled = true; } } break; case "split.": case "split": if (receiveIndex > -1 && split[i - 1] == "your" && split[i - 2] == "as") { if (ParseCurrency(split, 2, i - 2, out string item, out uint count)) { LootRecord record = new LootRecord() { Item = item, Player = ConfigUtil.PlayerName, Quantity = count, IsCurrency = true }; DataManager.Instance.AddLootRecord(record, DateUtil.ParseLogDate(lineData.Line)); handled = true; } } break; } } } } } catch (ArgumentNullException ne) { LOG.Error(ne); } catch (NullReferenceException nr) { LOG.Error(nr); } catch (ArgumentOutOfRangeException aor) { LOG.Error(aor); } catch (ArgumentException ae) { LOG.Error(ae); } DebugUtil.UnregisterLine(lineData.LineNumber, handled); }
private static HealRecord HandleHealed(ProcessLine pline) { // [Sun Feb 24 21:00:58 2019] Foob's promised interposition is fulfilled Foob healed himself for 44238 hit points by Promised Interposition Heal V. (Lucky Critical) // [Sun Feb 24 21:01:01 2019] Rowanoak is soothed by Brell's Soothing Wave. Farzi healed Rowanoak for 524 hit points by Brell's Sacred Soothing Wave. // [Sun Feb 24 21:00:52 2019] Kuvani healed Tolzol over time for 11000 hit points by Spirit of the Wood XXXIV. // [Sun Feb 24 21:00:52 2019] Kuvani healed Foob over time for 9409 (11000) hit points by Spirit of the Wood XXXIV. // [Sun Feb 24 21:00:58 2019] Fllint healed Foob for 11820 hit points by Blessing of the Ancients III. // [Sun Feb 24 21:01:00 2019] Tolzol healed itself for 548 hit points. // [Sun Feb 24 21:01:01 2019] Piemastaj`s pet has been healed for 15000 hit points by Enhanced Theft of Essence Effect X. // [Sun Feb 24 23:30:51 2019] Piemastaj`s pet glows with holy light. Findawenye healed Piemastaj`s pet for 2823 (78079) hit points by Mending Splash Rk. III. (Critical) // [Mon Feb 18 21:21:12 2019] Nylenne has been healed over time for 8211 hit points by Roar of the Lion 6. // [Mon Feb 18 21:20:39 2019] You have been healed over time for 1063 (8211) hit points by Roar of the Lion 6. // [Mon Feb 18 21:17:35 2019] Snowzz healed Malkatar over time for 8211 hit points by Roar of the Lion 6. // [Wed Nov 06 14:19:54 2019] Your ward heals you as it breaks! You healed Niktaza for 8970 (86306) hit points by Healing Ward. (Critical) HealRecord record = null; string part = pline.ActionPart; int optional = pline.OptionalIndex; string test = part.Substring(0, optional); bool done = false; string healer = ""; string healed = ""; string spell = null; string type = Labels.HEAL; uint heal = 0; uint overHeal = 0; int previous = test.Length >= 2 ? test.LastIndexOf(" ", test.Length - 2, StringComparison.Ordinal) : -1; if (previous > -1) { if (test.IndexOf("are ", previous + 1, StringComparison.Ordinal) > -1) { done = true; } else if (previous - 1 >= 0 && (test[previous - 1] == '.' || test[previous - 1] == '!') || previous - 9 > 0 && test.IndexOf("fulfilled", previous - 9, StringComparison.Ordinal) > -1) { healer = test.Substring(previous + 1); } else if (previous - 4 >= 0 && test.IndexOf("has been", previous - 3, StringComparison.Ordinal) > -1) { healed = test.Substring(0, previous - 4); if (part.Length > optional + 17 && part.IndexOf("over time", optional + 8, 9, StringComparison.Ordinal) > -1) { type = Labels.HOT; } } else if (previous - 5 >= 0 && test.IndexOf("have been", previous - 4, StringComparison.Ordinal) > -1) { healed = test.Substring(0, previous - 5); if (part.Length > optional + 17 && part.IndexOf("over time", optional + 8, 9, StringComparison.Ordinal) > -1) { type = Labels.HOT; } } } else { healer = test.Substring(0, optional); } if (!done) { int amountIndex = -1; if (healed.Length == 0) { int afterHealed = optional + 8; int forIndex = part.IndexOf(" for ", afterHealed, StringComparison.Ordinal); if (forIndex > 1) { if (forIndex - 9 >= 0 && part.IndexOf("over time", forIndex - 9, StringComparison.Ordinal) > -1) { type = Labels.HOT; healed = part.Substring(afterHealed, forIndex - afterHealed - 10); } else { healed = part.Substring(afterHealed, forIndex - afterHealed); } amountIndex = forIndex + 5; } } else { if (type == Labels.HEAL) { amountIndex = optional + 12; } else if (type == Labels.HOT) { amountIndex = optional + 22; } } if (amountIndex > -1) { int amountEnd = part.IndexOf(" ", amountIndex, StringComparison.Ordinal); if (amountEnd > -1) { uint value = StatsUtil.ParseUInt(part.Substring(amountIndex, amountEnd - amountIndex)); if (value != uint.MaxValue) { heal = value; } int overEnd = -1; if (part.Length > amountEnd + 1 && part[amountEnd + 1] == '(') { overEnd = part.IndexOf(")", amountEnd + 2, StringComparison.Ordinal); if (overEnd > -1) { uint value2 = StatsUtil.ParseUInt(part.Substring(amountEnd + 2, overEnd - amountEnd - 2)); if (value2 != uint.MaxValue) { overHeal = value2; } } } int rest = overEnd > -1 ? overEnd : amountEnd; int byIndex = part.IndexOf(" by ", rest, StringComparison.Ordinal); if (byIndex > -1) { int periodIndex = part.LastIndexOf(".", StringComparison.Ordinal); if (periodIndex > -1 && periodIndex - byIndex - 4 > 0) { spell = part.Substring(byIndex + 4, periodIndex - byIndex - 4); } } } } if (healed.Length > 0) { // check for pets int possessive = healed.IndexOf("`s ", StringComparison.Ordinal); if (possessive > -1) { if (PlayerManager.Instance.IsVerifiedPlayer(healed.Substring(0, possessive))) { PlayerManager.Instance.AddVerifiedPet(healed); } // dont count swarm pets healer = ""; heal = 0; } if (healer.Length > 0 && heal != 0) { record = new HealRecord() { Total = heal, OverTotal = overHeal, Healer = string.Intern(healer), Healed = string.Intern(healed), Type = string.Intern(type), ModifiersMask = -1 }; record.SubType = string.IsNullOrEmpty(spell) ? Labels.SELFHEAL : string.Intern(spell); if (part[part.Length - 1] == ')') { // using 4 here since the shortest modifier should at least be 3 even in the future. probably. int firstParen = part.LastIndexOf('(', part.Length - 4); if (firstParen > -1) { record.ModifiersMask = LineModifiersParser.Parse(part.Substring(firstParen + 1, part.Length - 1 - firstParen - 1)); if (LineModifiersParser.IsTwincast(record.ModifiersMask)) { PlayerManager.Instance.AddVerifiedPlayer(record.Healer); } } } } } } return(record); }
public static void Process(LineData lineData) { try { string[] split = lineData.Action.Split(' '); if (split != null && split.Length > 2) { // [Sun Mar 01 22:20:36 2020] A shaded torch has been awakened by Drogbaa. // [Sun Mar 01 22:34:58 2020] You have entered The Eastern Wastes. // [Sun Mar 01 20:35:55 2020] The master looter, Qulas, looted 32426 platinum from the corpse. // [Sun Mar 01 23:51:02 2020] You receive 129 platinum, 2 gold and 1 copper as your split (with a lucky bonus). // [Sun Feb 02 22:43:51 2020] You receive 28 platinum, 7 gold, 2 silver and 5 copper as your split. // [Sun Feb 02 23:31:23 2020] You receive 57 platinum as your split. // [Fri Feb 07 22:01:20 2020] --Kizant has looted a Lesser Engraved Velium Rune from Velden Dragonbane's corpse.-- // [Sat Feb 08 01:20:26 2020] --Proximoe has looted a Velium Infused Spider Silk from a restless devourer's corpse.-- // [Sat Feb 08 21:21:36 2020] --You have looted a Cold-Forged Cudgel from Queen Dracnia's corpse.-- string looter = null; int awakenedIndex = -1; int lootedIndex = -1; int masterLootIndex = -1; int receiveIndex = -1; bool handled = false; for (int i = 0; i < split.Length && !handled; i++) { if (i == 0 && split[0].StartsWith("--")) { looter = split[0] == "--You" ? ConfigUtil.PlayerName : split[0].TrimStart('-'); } else { switch (split[i]) { case "awakened": awakenedIndex = i; break; case "looted": lootedIndex = i; break; case "looter,": masterLootIndex = (i == 2 && split[1] == "master" && split[0] == "The") ? masterLootIndex = i + 1 : -1; break; case "receive": receiveIndex = (i == 1 && split[0] == "You") ? i : -1; break; case "by": if (awakenedIndex > -1 && awakenedIndex == (i - 1) && split.Length > 5 && split[i - 2] == "been" && split[i - 3] == "has") { string awakened = string.Join(" ", split, 0, i - 3); string breaker = string.Join(" ", split, i + 1, split.Length - i - 1).TrimEnd('.'); DataManager.Instance.AddMiscRecord(new MezBreakRecord() { Breaker = breaker, Awakened = awakened }, DateUtil.ParseLogDate(lineData.Line)); handled = true; } break; case "entered": if (i == 2 && split[1] == "have" && split[0] == "You" && split.Length > 2) { string zone = string.Join(" ", split, 3, split.Length - 3).TrimEnd('.'); DataManager.Instance.AddMiscRecord(new ZoneRecord() { Zone = zone }, DateUtil.ParseLogDate(lineData.Line)); handled = true; } break; case "from": if (masterLootIndex > -1 && lootedIndex > masterLootIndex && split.Length > lootedIndex + 1 && split.Length > 3) { string name = split[3].TrimEnd(','); if (ParseCurrency(split, lootedIndex + 1, i, out string item, out uint count)) { PlayerManager.Instance.AddVerifiedPlayer(name); LootRecord record = new LootRecord() { Item = item, Player = name, Quantity = count, IsCurrency = true }; DataManager.Instance.AddLootRecord(record, DateUtil.ParseLogDate(lineData.Line)); handled = true; } } else if (!string.IsNullOrEmpty(looter) && lootedIndex == 2 && split.Length > 4) { // covers "a" or "an" uint count = split[3][0] == 'a' ? 1 : StatsUtil.ParseUInt(split[3]); string item = string.Join(" ", split, 4, i - 4); string npc = string.Join(" ", split, i + 1, split.Length - i - 1).TrimEnd(LootedFromTrim).Replace("'s corpse", ""); if (count > 0 && count != ushort.MaxValue) { PlayerManager.Instance.AddVerifiedPlayer(looter); LootRecord record = new LootRecord() { Item = item, Player = looter, Quantity = count, IsCurrency = false, Npc = npc }; DataManager.Instance.AddLootRecord(record, DateUtil.ParseLogDate(lineData.Line)); handled = true; } } break; case "split": if (receiveIndex > -1 && split[i - 1] == "your" && split[i - 2] == "as") { if (ParseCurrency(split, 2, i - 2, out string item, out uint count)) { LootRecord record = new LootRecord() { Item = item, Player = ConfigUtil.PlayerName, Quantity = count, IsCurrency = true }; DataManager.Instance.AddLootRecord(record, DateUtil.ParseLogDate(lineData.Line)); handled = true; } } break; } } } } } catch (ArgumentNullException ne) { LOG.Error(ne); } catch (NullReferenceException nr) { LOG.Error(nr); } catch (ArgumentOutOfRangeException aor) { LOG.Error(aor); } catch (ArgumentException ae) { LOG.Error(ae); } }
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); }