private static DamageRecord ValidateDamage(DamageRecord record, SpellResist resist = SpellResist.UNDEFINED) { if (record != null) { // handle riposte separately if (LineModifiersParser.IsRiposte(record.ModifiersMask)) { record.SubType = Labels.RIPOSTE; } if (InIgnoreList(record.Defender)) { record = null; } else { // Needed to replace 'You' and 'you', etc record.Attacker = PlayerManager.Instance.ReplacePlayer(record.Attacker, record.Defender); record.Defender = PlayerManager.Instance.ReplacePlayer(record.Defender, record.Attacker); if (string.IsNullOrEmpty(record.Attacker)) { record.Attacker = Labels.ENVDAMAGE; } if (resist != SpellResist.UNDEFINED && ConfigUtil.PlayerName == record.Attacker && record.Defender != record.Attacker) { DataManager.Instance.UpdateNpcSpellResistStats(record.Defender, resist); } } } 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 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 BuildRecord(string attacker, string defender, uint damage, string attackerOwner, string defenderOwner, string subType, string type) { DamageRecord record = null; if (!string.IsNullOrEmpty(type) && !string.IsNullOrEmpty(subType)) { if (attacker.EndsWith("'s corpse", StringComparison.Ordinal)) { attacker = attacker.Substring(0, attacker.Length - 9); } record = new DamageRecord() { Attacker = string.Intern(FixName(attacker)), Defender = string.Intern(FixName(defender)), Type = string.Intern(type), SubType = string.Intern(subType), Total = damage, ModifiersMask = -1 }; if (attackerOwner != null) { record.AttackerOwner = string.Intern(attackerOwner); } if (defenderOwner != null) { record.DefenderOwner = string.Intern(defenderOwner); } } return(record); }
private static void AddPlayerTime(Fight fight, DamageRecord record, string player, double time) { var isInitialTanking = fight.DamageBlocks.Count == 0; var segments = isInitialTanking ? fight.InitialTankSegments : fight.DamageSegments; var subSegments = isInitialTanking ? fight.InitialTankSubSegments : fight.DamageSubSegments; StatsUtil.UpdateTimeSegments(segments, subSegments, Helpers.CreateRecordKey(record.Type, record.SubType), player, time); }
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 void UpdateSubStats(PlayerSubStats subStats, DamageRecord record, double beginTime) { uint critHits = subStats.CritHits; StatsUtil.UpdateStats(subStats, record, beginTime); // dont count misses or where no damage was done if (record.Total > 0) { Dictionary <long, int> values = subStats.CritHits > critHits ? subStats.CritFreqValues : subStats.NonCritFreqValues; Helpers.LongIntAddHelper.Add(values, record.Total, 1); } }
private Fight Get(DamageRecord record, double currentTime, string origTimeString, bool defender) { string npc = defender ? record.Defender : record.Attacker; Fight fight = DataManager.Instance.GetFight(npc); if (fight == null) { fight = Create(npc, currentTime, origTimeString); } return(fight); }
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 bool IsValidAttack(DamageRecord record, out bool defender) { bool valid = false; defender = false; if (!record.Attacker.Equals(record.Defender, StringComparison.OrdinalIgnoreCase)) { var isAttackerPlayer = record.Attacker == Labels.UNK || PlayerManager.Instance.IsPetOrPlayer(record.Attacker); var isDefenderPlayer = record.Attacker == Labels.UNK || PlayerManager.Instance.IsPetOrPlayer(record.Defender); var isAttackerNpc = !isAttackerPlayer && DataManager.Instance.IsKnownNpc(record.Attacker); var isDefenderNpc = !isDefenderPlayer && DataManager.Instance.IsKnownNpc(record.Defender); if (isDefenderNpc && !isAttackerNpc) { valid = isAttackerPlayer || PlayerManager.Instance.IsPossiblePlayerName(record.Attacker); defender = true; } else if (!isDefenderNpc && isAttackerNpc) { valid = true; defender = false; } else if (!isDefenderNpc && !isAttackerNpc) { if (isDefenderPlayer || isAttackerPlayer) { valid = isDefenderPlayer != isAttackerPlayer; defender = !isDefenderPlayer; } else { defender = PlayerManager.Instance.IsPossiblePlayerName(record.Attacker) || !PlayerManager.Instance.IsPossiblePlayerName(record.Defender); valid = true; } } else if (isDefenderNpc && isAttackerNpc && DataManager.Instance.GetFight(record.Defender) != null && DataManager.Instance.GetFight(record.Attacker) == null) { valid = true; defender = true; } } return(valid); }
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 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 bool IsValidAttack(DamageRecord record, double currentTime, out bool defender) { bool valid = false; defender = false; if (!record.Attacker.Equals(record.Defender, StringComparison.OrdinalIgnoreCase)) { var isDefenderNpc = record.Defender.StartsWith("Combat Dummy", StringComparison.OrdinalIgnoreCase) || DataManager.Instance.IsKnownNpc(record.Defender); var isAttackerNpc = record.Attacker.StartsWith("Combat Dummy", StringComparison.OrdinalIgnoreCase) || DataManager.Instance.IsKnownNpc(record.Attacker); var isAttackerPlayer = PlayerManager.Instance.IsPetOrPlayer(record.Attacker); if (isDefenderNpc && !isAttackerNpc) { valid = isAttackerPlayer || Helpers.IsPossiblePlayerName(record.Attacker); defender = true; } else if (!isDefenderNpc && isAttackerNpc) { valid = true; defender = false; } else if (!isDefenderNpc && !isAttackerNpc) { var isDefenderPlayer = PlayerManager.Instance.IsPetOrPlayer(record.Defender); valid = (isAttackerPlayer || !Helpers.IsPossiblePlayerName(record.Attacker)) && !isDefenderPlayer; defender = true; } else if (isDefenderNpc && isAttackerNpc && DataManager.Instance.GetFight(record.Defender, currentTime) != null && DataManager.Instance.GetFight(record.Attacker, currentTime) == null) { valid = true; defender = true; } } return(valid); }
private static DamageRecord ValidateDamage(DamageRecord record) { if (record != null) { // handle riposte separately if (LineModifiersParser.IsRiposte(record.ModifiersMask)) { record.SubType = Labels.RIPOSTE; } if (InIgnoreList(record.Defender)) { record = null; } else { // Needed to replace 'You' and 'you', etc record.Attacker = PlayerManager.Instance.ReplacePlayer(record.Attacker, record.Defender); record.Defender = PlayerManager.Instance.ReplacePlayer(record.Defender, record.Attacker); } } return(record); }
private static bool IsValidAttack(DamageRecord record, bool isAttackerPlayer, out bool npcDefender) { bool valid = false; npcDefender = false; if (!record.Attacker.Equals(record.Defender, StringComparison.OrdinalIgnoreCase)) { var isAttackerPlayerSpell = record.AttackerIsSpell && RecentSpellCache.ContainsKey(record.Attacker); isAttackerPlayer = isAttackerPlayer || isAttackerPlayerSpell; var isDefenderPlayer = PlayerManager.Instance.IsPetOrPlayer(record.Defender); var isAttackerNpc = (!isAttackerPlayer && DataManager.Instance.IsKnownNpc(record.Attacker)) || (record.AttackerIsSpell && !isAttackerPlayerSpell); var isDefenderNpc = (!isDefenderPlayer && DataManager.Instance.IsKnownNpc(record.Defender)) || isAttackerPlayerSpell; if (isDefenderNpc && !isAttackerNpc) { valid = isAttackerPlayer || PlayerManager.Instance.IsPossiblePlayerName(record.Attacker); npcDefender = true; } else if (!isDefenderNpc && isAttackerNpc) { valid = isDefenderPlayer || PlayerManager.Instance.IsPossiblePlayerName(record.Defender); npcDefender = false; } else if (!isDefenderNpc && !isAttackerNpc) { if (isDefenderPlayer || isAttackerPlayer) { valid = isDefenderPlayer != isAttackerPlayer; if (!valid) { if (PlayerManager.Instance.IsCharmPet(record.Attacker)) { valid = true; npcDefender = false; } else if (PlayerManager.Instance.IsCharmPet(record.Defender)) { valid = true; npcDefender = true; } } else { npcDefender = !isDefenderPlayer; } } else { npcDefender = PlayerManager.Instance.IsPossiblePlayerName(record.Attacker) || !PlayerManager.Instance.IsPossiblePlayerName(record.Defender); valid = true; } } else if (isDefenderNpc && isAttackerNpc && DataManager.Instance.GetFight(record.Defender) != null && DataManager.Instance.GetFight(record.Attacker) == null) { valid = true; npcDefender = true; } } return(valid); }
private static DamageRecord ParseDamage(string actionPart) { DamageRecord record = null; ParseType parseType = ParseType.UNKNOWN; string withoutMods = actionPart; int modifiersIndex = -1; if (actionPart[actionPart.Length - 1] == ')') { // using 4 here since the shortest modifier should at least be 3 even in the future. probably. modifiersIndex = actionPart.LastIndexOf('(', actionPart.Length - 4); if (modifiersIndex > -1) { withoutMods = actionPart.Substring(0, modifiersIndex); } } int pointsIndex = -1; int forIndex = -1; int fromIndex = -1; int byIndex = -1; int takenIndex = -1; int hitIndex = -1; int extraIndex = -1; int isAreIndex = -1; bool nonMelee = false; List <string> nameList = new List <string>(); StringBuilder builder = new StringBuilder(); var data = withoutMods.Split(' '); SpellResist resist = SpellResist.UNDEFINED; for (int i = 0; i < data.Length; i++) { switch (data[i]) { case "taken": takenIndex = i; int test1 = i - 1; if (test1 > 0 && data[test1] == "has") { parseType = ParseType.HASTAKEN; int test2 = i + 2; if (data.Length > test2 && data[test2] == "extra" && data[test2 - 1] == "an") { extraIndex = test2; } } else if (test1 >= 1 && data[test1] == "have" && data[test1 - 1] == "You") { parseType = ParseType.YOUHAVETAKEN; } break; case "by": byIndex = i; break; case "non-melee": nonMelee = true; break; case "is": case "are": isAreIndex = i; break; case "for": int next = i + 1; if (data.Length > next && data[next].Length > 0 && char.IsNumber(data[next][0])) { forIndex = i; } break; case "from": fromIndex = i; break; case "points": int ofIndex = i + 1; if (ofIndex < data.Length && data[ofIndex] == "of") { parseType = ParseType.POINTSOF; pointsIndex = i; int resistIndex = ofIndex + 1; if (resistIndex < data.Length && SpellResistMap.TryGetValue(data[resistIndex], out SpellResist value)) { resist = value; nonMelee = true; } } break; default: if (HitMap.ContainsKey(data[i])) { hitIndex = i; } break; } } if (parseType == ParseType.POINTSOF && forIndex > -1 && forIndex < pointsIndex && hitIndex > -1) { record = ParsePointsOf(data, nonMelee, forIndex, byIndex, hitIndex, builder, nameList); } else if (parseType == ParseType.HASTAKEN && takenIndex < fromIndex && fromIndex > -1) { record = ParseHasTaken(data, takenIndex, fromIndex, byIndex, builder); } else if (parseType == ParseType.POINTSOF && extraIndex > -1 && takenIndex > -1 && takenIndex < fromIndex) { record = ParseExtra(data, takenIndex, extraIndex, fromIndex, nameList); } // there are more messages without a specificied attacker or spell but do these first else if (parseType == ParseType.YOUHAVETAKEN && takenIndex > -1 && fromIndex > -1 && byIndex > fromIndex) { record = ParseYouHaveTaken(data, takenIndex, fromIndex, byIndex, builder); } else if (parseType == ParseType.POINTSOF && isAreIndex > -1 && byIndex > isAreIndex && forIndex > byIndex) { record = ParseDS(data, isAreIndex, byIndex, forIndex); } if (record != null && modifiersIndex > -1) { record.ModifiersMask = LineModifiersParser.Parse(actionPart.Substring(modifiersIndex + 1, actionPart.Length - 1 - modifiersIndex - 1)); } return(ValidateDamage(record, resist)); }
private static DamageRecord ParseMiss(string actionPart, int index) { // [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) DamageRecord record = null; string withoutMods = actionPart; int modifiersIndex = -1; if (actionPart[actionPart.Length - 1] == ')') { // using 4 here since the shortest modifier should at least be 3 even in the future. probably. modifiersIndex = actionPart.LastIndexOf('(', actionPart.Length - 4); if (modifiersIndex > -1) { withoutMods = actionPart.Substring(0, modifiersIndex); } } int tryStartIndex; int hitStartIndex = -1; int missesIndex = index - LineParsing.ACTIONINDEX; if (withoutMods[0] == 'Y' && withoutMods[1] == 'o' && withoutMods[2] == 'u') { tryStartIndex = 3; hitStartIndex = 11; } else { tryStartIndex = withoutMods.IndexOf(" tries to ", StringComparison.Ordinal); if (tryStartIndex > -1) { hitStartIndex = tryStartIndex + 10; } } if (tryStartIndex > -1 && hitStartIndex > -1 && tryStartIndex < missesIndex) { int hitEndIndex = withoutMods.IndexOf(" ", hitStartIndex, StringComparison.Ordinal); if (hitEndIndex > -1) { string hit = withoutMods.Substring(hitStartIndex, hitEndIndex - hitStartIndex); string subType = GetTypeFromHit(hit, out bool additional); if (subType != null) { int hitLength = hit.Length + (additional ? 3 : 0); // check for pets string attacker = withoutMods.Substring(0, tryStartIndex); int defStart = hitStartIndex + hitLength + 1; int missesEnd = missesIndex - defStart; if (missesEnd > 0) { string defender = withoutMods.Substring(defStart, missesEnd); HasOwner(attacker, out string attackerOwner); HasOwner(defender, out string defenderOwner); if (attacker != null && defender != null) { record = BuildRecord(attacker, defender, 0, attackerOwner, defenderOwner, subType, Labels.MISS); } if (record != null && modifiersIndex > -1) { record.ModifiersMask = LineModifiersParser.Parse(actionPart.Substring(modifiersIndex + 1, actionPart.Length - 1 - modifiersIndex - 1)); } } } } } return(ValidateDamage(record)); }
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); }
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); }
internal OverlayDamageStats ComputeOverlayDamageStats(DamageRecord record, double beginTime, OverlayDamageStats overlayStats = null) { if (overlayStats == null) { overlayStats = new OverlayDamageStats { RaidStats = new PlayerStats() }; overlayStats.RaidStats.BeginTime = beginTime; } else { overlayStats.RaidStats = overlayStats.RaidStats; } if (overlayStats.UniqueNpcs.Count == 0 || (beginTime - overlayStats.RaidStats.LastTime > DataManager.FIGHT_TIMEOUT)) { overlayStats.RaidStats.Total = 0; overlayStats.RaidStats.BeginTime = beginTime; overlayStats.UniqueNpcs.Clear(); overlayStats.TopLevelStats.Clear(); overlayStats.AggregateStats.Clear(); overlayStats.IndividualStats.Clear(); } overlayStats.RaidStats.LastTime = beginTime; overlayStats.RaidStats.TotalSeconds = overlayStats.RaidStats.LastTime - overlayStats.RaidStats.BeginTime + 1; if (record != null && (record.Type != Labels.BANE || MainWindow.IsBaneDamageEnabled)) { overlayStats.UniqueNpcs[record.Defender] = 1; overlayStats.RaidStats.Total += record.Total; // see if there's a pet mapping, check this first string pname = PlayerManager.Instance.GetPlayerFromPet(record.Attacker); if (pname != null || !string.IsNullOrEmpty(pname = record.AttackerOwner)) { PlayerHasPet[pname] = 1; PetToPlayer[record.Attacker] = pname; } bool isPet = PetToPlayer.TryGetValue(record.Attacker, out string player); bool needAggregate = isPet || (!isPet && PlayerHasPet.ContainsKey(record.Attacker) && overlayStats.TopLevelStats.ContainsKey(record.Attacker + " +Pets")); if (!needAggregate || player == Labels.UNASSIGNED) { // not a pet PlayerStats stats = StatsUtil.CreatePlayerStats(overlayStats.IndividualStats, record.Attacker); StatsUtil.UpdateStats(stats, record, beginTime); overlayStats.TopLevelStats[record.Attacker] = stats; stats.TotalSeconds = stats.LastTime - stats.BeginTime + 1; } else { string origName = player ?? record.Attacker; string aggregateName = origName + " +Pets"; PlayerStats aggregatePlayerStats; aggregatePlayerStats = StatsUtil.CreatePlayerStats(overlayStats.IndividualStats, aggregateName, origName); overlayStats.TopLevelStats[aggregateName] = aggregatePlayerStats; if (overlayStats.TopLevelStats.ContainsKey(origName)) { var origPlayer = overlayStats.TopLevelStats[origName]; StatsUtil.MergeStats(aggregatePlayerStats, origPlayer); overlayStats.TopLevelStats.Remove(origName); overlayStats.IndividualStats.Remove(origName); } if (record.Attacker != origName && overlayStats.TopLevelStats.ContainsKey(record.Attacker)) { var origPet = overlayStats.TopLevelStats[record.Attacker]; StatsUtil.MergeStats(aggregatePlayerStats, origPet); overlayStats.TopLevelStats.Remove(record.Attacker); overlayStats.IndividualStats.Remove(record.Attacker); } StatsUtil.UpdateStats(aggregatePlayerStats, record, beginTime); aggregatePlayerStats.TotalSeconds = aggregatePlayerStats.LastTime - aggregatePlayerStats.BeginTime + 1; } overlayStats.RaidStats.DPS = (long)Math.Round(overlayStats.RaidStats.Total / overlayStats.RaidStats.TotalSeconds, 2); var list = overlayStats.TopLevelStats.Values.OrderByDescending(item => item.Total).ToList(); int found = list.FindIndex(stats => stats.Name.StartsWith(ConfigUtil.PlayerName, StringComparison.Ordinal)); int renumber; if (found > 4) { var you = list[found]; you.Rank = Convert.ToUInt16(found + 1); overlayStats.StatsList.Clear(); overlayStats.StatsList.AddRange(list.Take(4)); overlayStats.StatsList.Add(you); renumber = overlayStats.StatsList.Count - 1; } else { overlayStats.StatsList.Clear(); overlayStats.StatsList.AddRange(list.Take(5)); renumber = overlayStats.StatsList.Count; } for (int i = 0; i < renumber; i++) { overlayStats.StatsList[i].Rank = Convert.ToUInt16(i + 1); } // only calculate the top few Parallel.ForEach(overlayStats.StatsList, top => StatsUtil.UpdateCalculations(top, overlayStats.RaidStats)); overlayStats.TargetTitle = (overlayStats.UniqueNpcs.Count > 1 ? "Combined (" + overlayStats.UniqueNpcs.Count + "): " : "") + record.Defender; overlayStats.TimeTitle = string.Format(CultureInfo.CurrentCulture, StatsUtil.TIME_FORMAT, overlayStats.RaidStats.TotalSeconds); overlayStats.TotalTitle = string.Format(CultureInfo.CurrentCulture, StatsUtil.TOTAL_FORMAT, StatsUtil.FormatTotals(overlayStats.RaidStats.Total), " Damage ", StatsUtil.FormatTotals(overlayStats.RaidStats.DPS)); } return(overlayStats); }
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); } }
override protected bool IsValid(RecordWrapper wrapper) { DamageRecord record = wrapper?.Record as DamageRecord; return(record.Type != Labels.BANE || MainWindow.IsBaneDamageEnabled); }
internal void BuildTotalStats(GenerateStatsOptions options) { lock (DamageGroups) { Selected = options.Npcs; Title = options.Name; try { FireNewStatsEvent(options); RaidTotals = StatsUtil.CreatePlayerStats(Labels.RAID); DamageGroups.Clear(); DamageGroupIds.Clear(); PlayerHasPet.Clear(); PetToPlayer.Clear(); Resists.Clear(); var damageBlocks = new List <ActionBlock>(); Selected.ForEach(fight => { StatsUtil.UpdateTimeDiffs(RaidTotals, fight); damageBlocks.AddRange(fight.DamageBlocks); if (fight.GroupId > -1) { DamageGroupIds[fight.GroupId] = 1; } }); damageBlocks.Sort((a, b) => a.BeginTime.CompareTo(b.BeginTime)); if (damageBlocks.Count > 0) { RaidTotals.TotalSeconds = RaidTotals.TimeDiffs.Sum(); var newBlock = new List <ActionBlock>(); var timeIndex = 0; damageBlocks.ForEach(block => { if (block.BeginTime > RaidTotals.LastTimes[timeIndex]) { timeIndex++; if (newBlock.Count > 0) { DamageGroups.Add(newBlock); } newBlock = new List <ActionBlock>(); } newBlock.Add(block); block.Actions.ForEach(action => { DamageRecord damage = action as DamageRecord; // see if there's a pet mapping, check this first string pname = PlayerManager.Instance.GetPlayerFromPet(damage.Attacker); if (!string.IsNullOrEmpty(pname) || !string.IsNullOrEmpty(pname = damage.AttackerOwner)) { PlayerHasPet[pname] = 1; PetToPlayer[damage.Attacker] = pname; } }); }); DamageGroups.Add(newBlock); for (int i = 0; i < RaidTotals.BeginTimes.Count && i < RaidTotals.LastTimes.Count; i++) { var group = DataManager.Instance.GetResistsDuring(RaidTotals.BeginTimes[i], RaidTotals.LastTimes[i]); group.ForEach(block => Resists.AddRange(block.Actions)); } ComputeDamageStats(options); } else if (Selected == null || Selected.Count == 0) { FireNoDataEvent(options, "NONPC"); } else { FireNoDataEvent(options, "NODATA"); } } catch (ArgumentNullException ne) { LOG.Error(ne); } catch (NullReferenceException nr) { LOG.Error(nr); } catch (ArgumentOutOfRangeException aor) { LOG.Error(aor); } catch (ArgumentException ae) { LOG.Error(ae); } catch (OutOfMemoryException oem) { LOG.Error(oem); } } }
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); } } }
internal void ComputeOverlayDamageStats(DamageRecord record, double beginTime, int timeout, OverlayDamageStats overlayStats = null) { try { // set current time overlayStats.LastTime = beginTime; if (record != null && (record.Type != Labels.BANE || MainWindow.IsBaneDamageEnabled)) { overlayStats.RaidStats.Total += record.Total; var raidTimeRange = new TimeRange(); overlayStats.InactiveFights.ForEach(fight => raidTimeRange.Add(new TimeSegment(Math.Max(fight.BeginDamageTime, overlayStats.BeginTime), fight.LastDamageTime))); overlayStats.ActiveFights.ForEach(fight => raidTimeRange.Add(new TimeSegment(Math.Max(fight.BeginDamageTime, overlayStats.BeginTime), fight.LastDamageTime))); overlayStats.RaidStats.TotalSeconds = Math.Max(raidTimeRange.GetTotal(), overlayStats.RaidStats.TotalSeconds); // update pets UpdatePetMapping(record); bool isPet = PetToPlayer.TryGetValue(record.Attacker, out string player); bool needAggregate = isPet || (!isPet && PlayerPets.ContainsKey(record.Attacker) && overlayStats.TopLevelStats.ContainsKey(record.Attacker + " +Pets")); if (!needAggregate) { // not a pet PlayerStats stats = StatsUtil.CreatePlayerStats(overlayStats.IndividualStats, record.Attacker); overlayStats.TopLevelStats[record.Attacker] = stats; StatsUtil.UpdateStats(stats, record); stats.LastTime = beginTime; } else { string origName = player ?? record.Attacker; string aggregateName = origName + " +Pets"; PlayerStats aggregatePlayerStats; aggregatePlayerStats = StatsUtil.CreatePlayerStats(overlayStats.IndividualStats, aggregateName, origName); overlayStats.TopLevelStats[aggregateName] = aggregatePlayerStats; if (overlayStats.TopLevelStats.ContainsKey(origName)) { var origPlayer = overlayStats.TopLevelStats[origName]; StatsUtil.MergeStats(aggregatePlayerStats, origPlayer); overlayStats.TopLevelStats.Remove(origName); overlayStats.IndividualStats.Remove(origName); } if (record.Attacker != origName && overlayStats.TopLevelStats.ContainsKey(record.Attacker)) { var origPet = overlayStats.TopLevelStats[record.Attacker]; StatsUtil.MergeStats(aggregatePlayerStats, origPet); overlayStats.TopLevelStats.Remove(record.Attacker); overlayStats.IndividualStats.Remove(record.Attacker); } StatsUtil.UpdateStats(aggregatePlayerStats, record); aggregatePlayerStats.LastTime = beginTime; } overlayStats.RaidStats.DPS = (long)Math.Round(overlayStats.RaidStats.Total / overlayStats.RaidStats.TotalSeconds, 2); var list = overlayStats.TopLevelStats.Values.OrderByDescending(item => item.Total).ToList(); int found = list.FindIndex(stats => stats.Name.StartsWith(ConfigUtil.PlayerName, StringComparison.Ordinal)); var you = found > -1 ? list[found] : null; int renumber; if (found > 4) { you.Rank = Convert.ToUInt16(found + 1); overlayStats.StatsList.Clear(); overlayStats.StatsList.AddRange(list.Where(stats => (stats != null && stats == you) || beginTime - stats.LastTime <= timeout).Take(4)); overlayStats.StatsList.Add(you); renumber = overlayStats.StatsList.Count - 1; } else { overlayStats.StatsList.Clear(); overlayStats.StatsList.AddRange(list.Where(stats => (stats != null && stats == you) || beginTime - stats.LastTime <= timeout).Take(5)); renumber = overlayStats.StatsList.Count; } for (int i = 0; i < overlayStats.StatsList.Count; i++) { if (i < renumber) { overlayStats.StatsList[i].Rank = Convert.ToUInt16(i + 1); } // only update time if damage changed if (overlayStats.StatsList[i].LastTime == beginTime && overlayStats.StatsList[i].CalcTime != beginTime) { var timeRange = new TimeRange(); if (PlayerPets.TryGetValue(overlayStats.StatsList[i].OrigName, out ConcurrentDictionary <string, byte> mapping)) { mapping.Keys.ToList().ForEach(key => { AddSegments(timeRange, overlayStats.InactiveFights, key, overlayStats.BeginTime); AddSegments(timeRange, overlayStats.ActiveFights, key, overlayStats.BeginTime); }); } AddSegments(timeRange, overlayStats.InactiveFights, overlayStats.StatsList[i].OrigName, overlayStats.BeginTime); AddSegments(timeRange, overlayStats.ActiveFights, overlayStats.StatsList[i].OrigName, overlayStats.BeginTime); overlayStats.StatsList[i].TotalSeconds = Math.Max(timeRange.GetTotal(), overlayStats.StatsList[i].TotalSeconds); overlayStats.StatsList[i].CalcTime = beginTime; } StatsUtil.UpdateCalculations(overlayStats.StatsList[i], overlayStats.RaidStats); } var count = overlayStats.InactiveFights.Count + overlayStats.ActiveFights.Count; overlayStats.TargetTitle = (count > 1 ? "C(" + count + "): " : "") + record.Defender; overlayStats.TimeTitle = string.Format(CultureInfo.CurrentCulture, StatsUtil.TIME_FORMAT, overlayStats.RaidStats.TotalSeconds); overlayStats.TotalTitle = string.Format(CultureInfo.CurrentCulture, StatsUtil.TOTAL_FORMAT, StatsUtil.FormatTotals(overlayStats.RaidStats.Total), " Damage ", StatsUtil.FormatTotals(overlayStats.RaidStats.DPS)); } } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { if (ex is ArgumentNullException || ex is NullReferenceException || ex is ArgumentOutOfRangeException || ex is ArgumentException || ex is OutOfMemoryException) { LOG.Error(ex); } } void AddSegments(TimeRange range, List <Fight> fights, string key, double start) { fights.ForEach(fight => { if (fight.DamageSegments.TryGetValue(key, out TimeSegment segment) && segment.EndTime >= start) { range.Add(new TimeSegment(Math.Max(segment.BeginTime, start), segment.EndTime)); } }); } }
internal static bool IsMelee(DamageRecord record) { return(record.Type == Labels.MELEE || record.Type == Labels.MISS || record.Type == Labels.PARRY || record.Type == Labels.DODGE || record.Type == Labels.BLOCK || record.Type == Labels.INVULNERABLE); }
private static void UpdateSubStats(PlayerSubStats subStats, DamageRecord record, double beginTime) { StatsUtil.UpdateStats(subStats, record, beginTime); }