private void FileLoadingCallback(string line, long position) { if ((int)((DamageProcessor.Size() + HealingProcessor.Size() + MiscProcessor.Size() + CastProcessor.Size()) / 10000) is int sleep && sleep > 10) { Thread.Sleep(4 * (sleep - 10)); } Interlocked.Exchange(ref FilePosition, position); Interlocked.Add(ref LineCount, 1); if (PreLineParser.NeedProcessing(line, out string action)) { var lineData = new LineData() { Line = line, LineNumber = LineCount, Action = action }; // avoid having other things parse chat by accident if (ChatLineParser.Process(lineData) is ChatType chatType) { PlayerChatManager.Add(chatType); } else if (CurrentLogOption != LogOption.ARCHIVE) { // 4 is for the number of processors DebugUtil.RegisterLine(LineCount, line, 4); CastProcessor.Add(lineData); DamageProcessor.Add(lineData); HealingProcessor.Add(lineData); MiscProcessor.Add(lineData); } } }
public void Add(LineData data) { lock (QueueLock) { Queue.Add(data); LinesAdded++; } }
internal static ChatType Process(LineData lineData) { var chatType = ParseChatType(lineData.Line); if (chatType != null && chatType.SenderIsYou == false && chatType.Sender != null) { if (chatType.Channel == ChatChannels.GUILD || chatType.Channel == ChatChannels.RAID || chatType.Channel == ChatChannels.FELLOWSHIP) { PlayerManager.Instance.AddVerifiedPlayer(chatType.Sender); } } return(chatType); }
internal static ChatType Process(LineData lineData) { var chatType = ParseChatType(lineData.Line); if (chatType != null && chatType.SenderIsYou == false && chatType.Sender != null) { if (chatType.Channel == ChatChannels.Guild || chatType.Channel == ChatChannels.Raid || chatType.Channel == ChatChannels.Fellowship) { PlayerManager.Instance.AddVerifiedPlayer(chatType.Sender, DateUtil.ParseLogDate(lineData.Line, out _)); } } return(chatType); }
public static void Process(LineData lineData) { string line = lineData.Line; bool handled = false; try { int index; if (line.Length >= 51 && (index = line.LastIndexOf(" healed ", line.Length, line.Length - LineParsing.ActionIndex, StringComparison.Ordinal)) > -1) { ProcessLine pline = new ProcessLine() { Line = line, ActionPart = line.Substring(LineParsing.ActionIndex) }; pline.OptionalIndex = index - LineParsing.ActionIndex; pline.TimeString = pline.Line.Substring(1, 24); pline.CurrentTime = DateUtil.ParseDate(pline.TimeString); HealRecord record = HandleHealed(pline); if (record != null) { DataManager.Instance.AddHealRecord(record, pline.CurrentTime); handled = true; } } } 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 bool UpdateSlain(string slain, string killer, LineData lineData) { bool handled = false; if (!string.IsNullOrEmpty(slain) && killer != null && !InIgnoreList(slain)) // killer may not be known so empty string is OK { killer = killer.Length > 2 ? PlayerManager.Instance.ReplacePlayer(killer, killer) : killer; slain = PlayerManager.Instance.ReplacePlayer(slain, slain); // clear your ADPS if you died if (slain == ConfigUtil.PlayerName) { DataManager.Instance.ClearActiveAdps(); } double currentTime = DateUtil.ParseLogDate(lineData.Line, out _); if (!double.IsNaN(currentTime)) { CheckSlainQueue(currentTime); lock (SlainQueue) { if (!SlainQueue.Contains(slain) && DataManager.Instance.GetFight(slain) != null) { SlainQueue.Add(slain); SlainTime = currentTime; } } var death = new DeathRecord() { Killed = string.Intern(slain), Killer = killer }; DataManager.Instance.AddDeathRecord(death, currentTime); handled = true; } } return(handled); }
public static void Process(LineData lineData) { string line = lineData.Line; try { var actionPart = line.Substring(LineParsing.ACTIONINDEX); var timeString = line.Substring(1, 24); var currentTime = DateUtil.ParseDate(timeString); // handle Slain queue if (!double.IsNaN(SlainTime) && currentTime > SlainTime) { SlainQueue.ForEach(slain => { if (!DataManager.Instance.RemoveActiveFight(slain) && char.IsUpper(slain[0])) { DataManager.Instance.RemoveActiveFight(char.ToLower(slain[0], CultureInfo.CurrentCulture) + slain.Substring(1)); } }); SlainQueue.Clear(); SlainTime = double.NaN; } int index; if (line.Length >= 40 && line.IndexOf(" damage", LineParsing.ACTIONINDEX + 13, StringComparison.Ordinal) > -1) { DamageRecord record = ParseDamage(actionPart); if (record != null) { DamageProcessedEvent e = new DamageProcessedEvent() { Record = record, OrigTimeString = timeString, BeginTime = currentTime }; EventsDamageProcessed?.Invoke(record, e); if (record.Type == Labels.DD) { if (SpecialCodes.Keys.FirstOrDefault(special => !string.IsNullOrEmpty(record.SubType) && record.SubType.Contains(special)) is string key && !string.IsNullOrEmpty(key)) { DataManager.Instance.AddSpecial(new SpecialSpell() { Code = SpecialCodes[key], Player = record.Attacker, BeginTime = currentTime }); } } } } else if (line.Length >= 49 && (index = line.IndexOf(", but miss", LineParsing.ACTIONINDEX + 22, StringComparison.Ordinal)) > -1) { DamageRecord record = ParseMiss(actionPart, index); if (record != null) { DamageProcessedEvent e = new DamageProcessedEvent() { Record = record, OrigTimeString = timeString, BeginTime = currentTime }; EventsDamageProcessed?.Invoke(record, e); } } else if (line.Length > 35 && line.EndsWith(" died.", StringComparison.Ordinal)) { var test = line.Substring(LineParsing.ACTIONINDEX, line.Length - LineParsing.ACTIONINDEX - 6); if (!SlainQueue.Contains(test) && DataManager.Instance.GetFight(test) != null) { SlainQueue.Add(test); SlainTime = currentTime; } if (test == "You") { test = ConfigUtil.PlayerName; DataManager.Instance.ClearActiveAdps(); } var death = new DeathRecord() { Killed = string.Intern(test), Killer = "" }; DataManager.Instance.AddDeathRecord(death, currentTime); } else if (line.Length > 30 && line.Length < 102 && (index = line.IndexOf(" slain ", LineParsing.ACTIONINDEX, StringComparison.Ordinal)) > -1) { HandleSlain(actionPart, currentTime, index - LineParsing.ACTIONINDEX); } } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception e) #pragma warning restore CA1031 // Do not catch general exception types { if (e is ArgumentNullException || e is NullReferenceException || e is ArgumentOutOfRangeException || e is ArgumentException) { LOG.Error(e); } } }
public static void Process(LineData lineData) { bool handled = false; try { string[] split = lineData.Action.Split(' '); if (split != null && split.Length > 1 && !split[0].Contains(".")) { string player = null; string spellName = null; bool isYou = false; bool isSpell = false; bool isInterrupted = false; // [Sat Mar 14 19:57:48 2020] You activate Venon's Vindication. // [Mon Mar 02 19:46:09 2020] You begin casting Shield of Destiny Rk. II. // [Sat Mar 14 19:45:40 2020] You begin singing Agilmente's Aria of Eagles. // [Tue Dec 25 11:38:42 2018] You begin casting Focus of Arcanum VI. // [Sun Dec 02 16:33:37 2018] You begin singing Vainglorious Shout VI. // [Mon Mar 02 19:44:27 2020] Stabborz activates Conditioned Reflexes Rk. II. // [Mon Mar 02 19:47:43 2020] Sancus begins casting Burnout XIV Rk. II. // [Mon Mar 02 19:33:49 2020] Iggokk begins singing Shauri's Sonorous Clouding III. // [Tue Dec 25 09:58:20 2018] Sylfvia begins to cast a spell. <Syllable of Mending Rk. II> // [Tue Dec 25 14:19:57 2018] Sonozen begins to sing a song. <Lyre Leap> // [Thu Apr 18 01:38:10 2019] Incogitable's Dizzying Wheel Rk. II spell is interrupted. // [Thu Apr 18 01:38:00 2019] Your Stormjolt Vortex Rk. III spell is interrupted. // [Sun Mar 01 22:34:58 2020] You have entered The Eastern Wastes. if (split[0] == "You") { player = ConfigUtil.PlayerName; isYou = true; if (split[1] == "activate") { spellName = ParseNewSpellName(split, 2); } // ZONE EVENT - moved here to keep it in the same thread as lands on message parsing if (split[1] == "have" && split[2] == "entered") { string zone = string.Join(" ", split, 3, split.Length - 3).TrimEnd('.'); DataManager.Instance.AddMiscRecord(new ZoneRecord { Zone = zone }, DateUtil.ParseLogDate(lineData.Line, out _)); handled = true; if (!zone.StartsWith("an area", StringComparison.OrdinalIgnoreCase)) { DataManager.Instance.ZoneChanged(); } } else if (split[1] == "begin") { if (split[2] == "casting") { spellName = ParseNewSpellName(split, 3); isSpell = true; } else if (split[2] == "singing") { spellName = ParseNewSpellName(split, 3); } } } else if (split[1] == "activates") { player = split[0]; spellName = ParseNewSpellName(split, 2); } else if (split[1] == "begins") { if (split[2] == "casting") { player = split[0]; spellName = ParseNewSpellName(split, 3); isSpell = true; } else if (split[2] == "singing") { player = split[0]; spellName = ParseNewSpellName(split, 3); } else if (split.Length > 5 && split[2] == "to" && split[4] == "a") { if (split[3] == "cast" && split[5] == "spell.") { player = split[0]; spellName = ParseOldSpellName(split, 6); isSpell = true; } else if (split[3] == "sing" && split[5] == "song.") { player = split[0]; spellName = ParseOldSpellName(split, 6); } } } else if (split.Length > 4 && split[split.Length - 1] == "interrupted." && split[split.Length - 2] == "is" && split[split.Length - 3] == "spell") { isInterrupted = true; spellName = string.Join(" ", split, 1, split.Length - 4); if (split[0] == "Your") { player = ConfigUtil.PlayerName; } else if (split[0].Length > 3 && split[0][split[0].Length - 1] == 's' && split[0][split[0].Length - 2] == '\'') { player = split[0].Substring(0, split[0].Length - 2); } } if (!handled && !string.IsNullOrEmpty(player) && !string.IsNullOrEmpty(spellName)) { double currentTime = DateUtil.ParseDate(lineData.Line.Substring(1, 24)); if (!isInterrupted) { if (isSpell && isYou) { // For some reason Glyphs don't show up for current player CheckForSpecial(SpecialYouCodes, spellName, player, currentTime); } var spellData = DataManager.Instance.GetSpellByName(spellName); DataManager.Instance.AddSpellCast(new SpellCast { Caster = player, Spell = string.Intern(spellName), SpellData = spellData, BeginTime = currentTime }, currentTime); } else { DataManager.Instance.HandleSpellInterrupt(player, spellName, currentTime); } handled = true; } if (!handled && lineData.Line[lineData.Line.Length - 1] != ')') { if (split[0].Length > 3 && split[0][split[0].Length - 1] == 's' && split[0][split[0].Length - 2] == '\'') { player = string.Intern(split[0].Substring(0, split[0].Length - 2)); var landsOnPosessiveMessage = string.Join(" ", split, 1, split.Length - 1); List <SpellData> result = DataManager.Instance.GetPosessiveLandsOnOther(player, landsOnPosessiveMessage, out _); if (result != null) { double currentTime = DateUtil.ParseDate(lineData.Line.Substring(1, 24)); var newSpell = new ReceivedSpell { Receiver = player, BeginTime = currentTime }; if (result.Count == 1) { newSpell.SpellData = result.First(); CheckForSpecial(SpecialLandsOnCodes, newSpell.SpellData.Name, newSpell.Receiver, currentTime); } else { newSpell.Ambiguity.AddRange(result); } // valid lands on other. check for pet receiving DPS AA if (PetCheck.ContainsKey(landsOnPosessiveMessage)) { PlayerManager.Instance.AddVerifiedPet(player); } DataManager.Instance.AddReceivedSpell(newSpell, currentTime); handled = true; } } else if (split.Length > 0) { string landsOnMessage = string.Join(" ", split, 1, split.Length - 1); int midPeriod = -1; // some abilities like staunch show a lands on message followed by a heal. so search based on first sentence if (landsOnMessage.Length >= 2) { if ((midPeriod = landsOnMessage.LastIndexOf('.', landsOnMessage.Length - 2)) > -1) { landsOnMessage = landsOnMessage.Substring(0, midPeriod + 1); } } player = split[0]; List <SpellData> result = DataManager.Instance.GetNonPosessiveLandsOnOther(player, landsOnMessage, out _); if (result == null) { result = DataManager.Instance.GetLandsOnYou(player, player + " " + landsOnMessage, out _); if (result != null) { player = ConfigUtil.PlayerName; } } else { // valid lands on other. check for pet receiving DPS AA if (PetCheck.ContainsKey(landsOnMessage)) { PlayerManager.Instance.AddVerifiedPet(player); } } if (result != null) { double currentTime = DateUtil.ParseDate(lineData.Line.Substring(1, 24)); var newSpell = new ReceivedSpell() { Receiver = string.Intern(player), BeginTime = currentTime }; if (result.Count == 1) { newSpell.SpellData = result.First(); CheckForSpecial(SpecialLandsOnCodes, newSpell.SpellData.Name, newSpell.Receiver, currentTime); } else { newSpell.Ambiguity.AddRange(result); } DataManager.Instance.AddReceivedSpell(newSpell, currentTime); handled = true; } } } } } catch (Exception e) { LOG.Error(e); } DebugUtil.UnregisterLine(lineData.LineNumber, handled); }
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); }
public static void Process(LineData lineData) { try { string[] split = lineData.Action.Split(' '); if (split != null && split.Length > 2 && !split[0].Contains(".")) { string player = null; string spellName = null; bool isYou = false; bool isSpell = false; bool isInterrupted = false; bool handled = false; // [Sat Mar 14 19:57:48 2020] You activate Venon's Vindication. // [Mon Mar 02 19:46:09 2020] You begin casting Shield of Destiny Rk. II. // [Sat Mar 14 19:45:40 2020] You begin singing Agilmente's Aria of Eagles. // [Tue Dec 25 11:38:42 2018] You begin casting Focus of Arcanum VI. // [Sun Dec 02 16:33:37 2018] You begin singing Vainglorious Shout VI. // [Mon Mar 02 19:44:27 2020] Stabborz activates Conditioned Reflexes Rk. II. // [Mon Mar 02 19:47:43 2020] Sancus begins casting Burnout XIV Rk. II. // [Mon Mar 02 19:33:49 2020] Iggokk begins singing Shauri's Sonorous Clouding III. // [Tue Dec 25 09:58:20 2018] Sylfvia begins to cast a spell. <Syllable of Mending Rk. II> // [Tue Dec 25 14:19:57 2018] Sonozen begins to sing a song. <Lyre Leap> // [Thu Apr 18 01:38:10 2019] Incogitable's Dizzying Wheel Rk. II spell is interrupted. // [Thu Apr 18 01:38:00 2019] Your Stormjolt Vortex Rk. III spell is interrupted. if (split[0] == "You") { player = ConfigUtil.PlayerName; isYou = true; if (split[1] == "activate") { spellName = ParseNewSpellName(split, 2); } else if (split[1] == "begin") { if (split[2] == "casting") { spellName = ParseNewSpellName(split, 3); isSpell = true; } else if (split[2] == "singing") { spellName = ParseNewSpellName(split, 3); } } } else if (split[1] == "activates") { player = split[0]; spellName = ParseNewSpellName(split, 2); } else if (split[1] == "begins") { if (split[2] == "casting") { player = split[0]; spellName = ParseNewSpellName(split, 3); isSpell = true; } else if (split[2] == "singing") { player = split[0]; spellName = ParseNewSpellName(split, 3); } else if (split.Length > 5 && split[2] == "to" && split[4] == "a") { if (split[3] == "cast" && split[5] == "spell.") { player = split[0]; spellName = ParseOldSpellName(split, 6); isSpell = true; } else if (split[3] == "sing" && split[5] == "song.") { player = split[0]; spellName = ParseOldSpellName(split, 6); } } } else if (split.Length > 4 && split[split.Length - 1] == "interrupted." && split[split.Length - 2] == "is" && split[split.Length - 3] == "spell") { isInterrupted = true; spellName = string.Join(" ", split, 1, split.Length - 4); if (split[0] == "Your") { player = ConfigUtil.PlayerName; } else if (split[0].Length > 3 && split[0][split[0].Length - 1] == 's' && split[0][split[0].Length - 2] == '\'') { player = split[0].Substring(0, split[0].Length - 2); } } if (!string.IsNullOrEmpty(player) && !string.IsNullOrEmpty(spellName)) { double currentTime = DateUtil.ParseDate(lineData.Line.Substring(1, 24)); if (!isInterrupted) { if (isSpell && isYou) { // For some reason Glyphs don't show up for current player CheckForSpecial(SpecialYouCodes, spellName, player, currentTime); } else if (isSpell && !isYou) { // Some spells only show up as casting CheckForSpecial(SpecialOtherCodes, spellName, player, currentTime); } DataManager.Instance.AddSpellCast(new SpellCast() { Caster = player, Spell = string.Intern(spellName) }, currentTime); } else { DataManager.Instance.HandleSpellInterrupt(player, spellName, currentTime); } handled = true; } if (!handled && lineData.Line[lineData.Line.Length - 1] != ')') { if (split[0].Length > 3 && split[0][split[0].Length - 1] == 's' && split[0][split[0].Length - 2] == '\'') { SpellData result = DataManager.Instance.GetPosessiveLandsOnOther(string.Join(" ", split, 1, split.Length - 1), out _); if (result != null) { double currentTime = DateUtil.ParseDate(lineData.Line.Substring(1, 24)); var newSpell = new ReceivedSpell() { Receiver = string.Intern(split[0].Substring(0, split[0].Length - 2)), SpellData = result }; DataManager.Instance.AddReceivedSpell(newSpell, currentTime); CheckForSpecial(SpecialLandsOnCodes, result.Name, newSpell.Receiver, currentTime); } } else { string landsOnMessage = string.Join(" ", split, 1, split.Length - 1); int midPeriod = -1; // some abilities like staunch show a lands on message followed by a heal. so search based on first sentence if ((midPeriod = landsOnMessage.LastIndexOf('.', landsOnMessage.Length - 2)) > -1) { landsOnMessage = landsOnMessage.Substring(0, midPeriod + 1); } player = split[0]; SpellData result = DataManager.Instance.GetNonPosessiveLandsOnOther(landsOnMessage, out _); if (result == null) { result = DataManager.Instance.GetLandsOnYou(player + " " + landsOnMessage, out _); if (result != null) { player = ConfigUtil.PlayerName; } } if (result != null) { double currentTime = DateUtil.ParseDate(lineData.Line.Substring(1, 24)); var newSpell = new ReceivedSpell() { Receiver = string.Intern(player), SpellData = result }; DataManager.Instance.AddReceivedSpell(newSpell, currentTime); CheckForSpecial(SpecialLandsOnCodes, result.Name, newSpell.Receiver, currentTime); } } } } } 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) { string line = lineData.Line; try { var actionPart = line.Substring(LineParsing.ACTIONINDEX); var timeString = line.Substring(1, 24); var currentTime = DateUtil.ParseDate(timeString); // handle Slain queue if (!double.IsNaN(SlainTime) && currentTime > SlainTime) { SlainQueue.ForEach(slain => { if (!DataManager.Instance.RemoveActiveFight(slain) && char.IsUpper(slain[0])) { DataManager.Instance.RemoveActiveFight(char.ToLower(slain[0], CultureInfo.CurrentCulture) + slain.Substring(1)); } }); SlainQueue.Clear(); SlainTime = double.NaN; } int index; if (line.Length >= 40 && line.IndexOf(" damage", LineParsing.ACTIONINDEX + 13, StringComparison.Ordinal) > -1) { DamageRecord record = ParseDamage(actionPart); if (record != null) { DamageProcessedEvent e = new DamageProcessedEvent() { Record = record, OrigTimeString = timeString, BeginTime = currentTime }; EventsDamageProcessed?.Invoke(record, e); if (record.Type == Labels.DD) { if (SpecialCodes.Keys.FirstOrDefault(special => !string.IsNullOrEmpty(record.SubType) && record.SubType.Contains(special)) is string key && !string.IsNullOrEmpty(key)) { DataManager.Instance.AddSpecial(new SpecialSpell() { Code = SpecialCodes[key], Player = record.Attacker, BeginTime = currentTime }); } } } } else if (line.Length >= 49 && (index = line.IndexOf(", but miss", LineParsing.ACTIONINDEX + 22, StringComparison.Ordinal)) > -1) { DamageRecord record = ParseMiss(actionPart, index); if (record != null) { DamageProcessedEvent e = new DamageProcessedEvent() { Record = record, OrigTimeString = timeString, BeginTime = currentTime }; EventsDamageProcessed?.Invoke(record, e); } } else if (line.Length > 30 && line.Length < 102 && (index = line.IndexOf(" slain ", LineParsing.ACTIONINDEX, StringComparison.Ordinal)) > -1) { HandleSlain(actionPart, currentTime, index - LineParsing.ACTIONINDEX); } else if (line.Length >= 40 && line.Length < 110 && (index = line.IndexOf(" resisted your ", LineParsing.ACTIONINDEX, StringComparison.Ordinal)) > -1) { var optionalIndex = index - LineParsing.ACTIONINDEX; // [Mon Feb 11 20:00:28 2019] An inferno flare resisted your Frostreave Strike III! string defender = actionPart.Substring(0, optionalIndex); string spell = actionPart.Substring(optionalIndex + 15, actionPart.Length - optionalIndex - 15 - 1); DataManager.Instance.AddResistRecord(new ResistRecord() { Spell = spell }, currentTime); } } 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) { 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); }
private static bool CreateDamageRecord(LineData lineData, string[] split, int stop, string attacker, string defender, uint damage, string type, string subType, SpellResist resist = SpellResist.UNDEFINED, bool attackerIsSpell = false) { bool success = false; if (damage != uint.MaxValue && !string.IsNullOrEmpty(type) && !string.IsNullOrEmpty(subType) && !InIgnoreList(defender)) { // Needed to replace 'You' and 'you', etc defender = PlayerManager.Instance.ReplacePlayer(defender, defender); if (string.IsNullOrEmpty(attacker)) { attacker = subType; } else if (attacker.EndsWith("'s corpse", StringComparison.Ordinal)) { attacker = attacker.Substring(0, attacker.Length - 9); } else { // Needed to replace 'You' and 'you', etc attacker = PlayerManager.Instance.ReplacePlayer(attacker, attacker); } if (resist != SpellResist.UNDEFINED && ConfigUtil.PlayerName == attacker && defender != attacker) { DataManager.Instance.UpdateNpcSpellResistStats(defender, resist); } // check for pets HasOwner(attacker, out string attackerOwner); HasOwner(defender, out string defenderOwner); DamageRecord record = new DamageRecord { Attacker = string.Intern(FixName(attacker)), Defender = string.Intern(FixName(defender)), Type = string.Intern(type), SubType = string.Intern(subType), Total = damage, AttackerOwner = attackerOwner != null?string.Intern(attackerOwner) : null, DefenderOwner = defenderOwner != null?string.Intern(defenderOwner) : null, ModifiersMask = -1, AttackerIsSpell = attackerIsSpell }; var currentTime = DateUtil.ParseLogDate(lineData.Line, out string timeString); if (split.Length > stop + 1) { // improve this later so maybe the string doesn't have to be re-joined string modifiers = string.Join(" ", split, stop + 1, split.Length - stop - 1); record.ModifiersMask = LineModifiersParser.Parse(record.Attacker, modifiers.Substring(1, modifiers.Length - 2), currentTime); } if (!double.IsNaN(currentTime)) { // handle old style crits for eqemu if (LastCrit != null && LastCrit.Attacker == record.Attacker && LastCrit.LineData.LineNumber == (lineData.LineNumber - 1)) { var critTime = DateUtil.ParseLogDate(LastCrit.LineData.Line, out string _); if (!double.IsNaN(critTime) && (currentTime - critTime) <= 1) { record.ModifiersMask = (record.ModifiersMask == -1) ? LineModifiersParser.CRIT : record.ModifiersMask | LineModifiersParser.CRIT; } LastCrit = null; } CheckSlainQueue(currentTime); DamageProcessedEvent e = new DamageProcessedEvent() { Record = record, OrigTimeString = timeString, BeginTime = currentTime }; EventsDamageProcessed?.Invoke(record, e); success = true; if (record.Type == Labels.DD && SpecialCodes.Keys.FirstOrDefault(special => !string.IsNullOrEmpty(record.SubType) && record.SubType.Contains(special)) is string key && !string.IsNullOrEmpty(key)) { DataManager.Instance.AddSpecial(new SpecialSpell() { Code = SpecialCodes[key], Player = record.Attacker, BeginTime = currentTime }); } } } return(success); }