Пример #1
0
        private void HandleDamageProcessed(object sender, DamageProcessedEvent processed)
        {
            if (LastFightProcessTime != processed.BeginTime)
            {
                DataManager.Instance.CheckExpireFights(processed.BeginTime);
                ValidCombo.Clear();

                if (processed.BeginTime - LastFightProcessTime > RECENTSPELLTIME)
                {
                    RecentSpellCache.Clear();
                }
            }

            // cache recent player spells to help determine who the caster was
            var isAttackerPlayer = PlayerManager.Instance.IsPetOrPlayer(processed.Record.Attacker) || processed.Record.Attacker == Labels.RS;

            if (isAttackerPlayer && (processed.Record.Type == Labels.DD || processed.Record.Type == Labels.DOT || processed.Record.Type == Labels.PROC))
            {
                RecentSpellCache[processed.Record.SubType] = true;
            }

            string comboKey = processed.Record.Attacker + "=" + processed.Record.Defender;

            if (ValidCombo.TryGetValue(comboKey, out bool defender) || IsValidAttack(processed.Record, isAttackerPlayer, out defender))
            {
                ValidCombo[comboKey] = defender;
                bool   isNonTankingFight = false;
                string origTimeString    = processed.OrigTimeString.Substring(4, 15);

                // fix for unknown spells having a good name to work from
                if (processed.Record.AttackerIsSpell && defender)
                {
                    processed.Record.Attacker = Labels.UNK;
                }

                Fight fight = Get(processed.Record, processed.BeginTime, origTimeString, defender);

                if (defender)
                {
                    Helpers.AddAction(fight.DamageBlocks, processed.Record, processed.BeginTime);
                    AddPlayerTime(fight, processed.Record, processed.Record.Attacker, processed.BeginTime);
                    fight.BeginDamageTime = double.IsNaN(fight.BeginDamageTime) ? processed.BeginTime : fight.BeginDamageTime;
                    fight.LastDamageTime  = processed.BeginTime;

                    if (StatsUtil.IsHitType(processed.Record.Type))
                    {
                        fight.DamageHits++;
                        fight.Total      += processed.Record.Total;
                        isNonTankingFight = fight.DamageHits == 1;

                        var attacker = processed.Record.AttackerOwner ?? processed.Record.Attacker;
                        if (fight.PlayerTotals.TryGetValue(attacker, out FightTotalDamage total))
                        {
                            total.Damage         += (processed.Record.Type == Labels.BANE) ? 0 : processed.Record.Total;
                            total.DamageWithBane += processed.Record.Total;
                            total.Name            = processed.Record.Attacker;
                            total.PetOwner        = total.PetOwner ?? processed.Record.AttackerOwner;
                            total.UpdateTime      = processed.BeginTime;
                        }
                        else
                        {
                            fight.PlayerTotals[attacker] = new FightTotalDamage
                            {
                                Damage         = (processed.Record.Type == Labels.BANE) ? 0 : processed.Record.Total,
                                DamageWithBane = processed.Record.Total,
                                Name           = processed.Record.Attacker,
                                PetOwner       = processed.Record.AttackerOwner,
                                UpdateTime     = processed.BeginTime,
                                BeginTime      = processed.BeginTime
                            };
                        }

                        SpellDamageStats stats = null;
                        var spellKey           = processed.Record.Attacker + "++" + processed.Record.SubType;
                        if (processed.Record.Type == Labels.DD)
                        {
                            if (!fight.DDDamage.TryGetValue(spellKey, out stats))
                            {
                                stats = new SpellDamageStats {
                                    Caster = processed.Record.Attacker, Spell = processed.Record.SubType
                                };
                                fight.DDDamage[spellKey] = stats;
                            }
                        }
                        else if (processed.Record.Type == Labels.DOT)
                        {
                            if (!fight.DoTDamage.TryGetValue(spellKey, out stats))
                            {
                                stats = new SpellDamageStats {
                                    Caster = processed.Record.Attacker, Spell = processed.Record.SubType
                                };
                                fight.DoTDamage[spellKey] = stats;
                            }
                        }

                        if (stats != null)
                        {
                            stats.Count += 1;
                            stats.Max    = Math.Max(processed.Record.Total, stats.Max);
                            stats.Total += processed.Record.Total;
                        }

                        // only a pet can 'hit' with a Flurry since players only crush/slash/punch/pierce with main hand weapons
                        if (processed.Record.AttackerOwner == null && processed.Record.Type == Labels.MELEE && processed.Record.SubType == "Hits" &&
                            LineModifiersParser.IsFlurry(processed.Record.ModifiersMask))
                        {
                            PlayerManager.Instance.AddVerifiedPet(processed.Record.Attacker);
                        }
                    }
                }
                else
                {
                    Helpers.AddAction(fight.TankingBlocks, processed.Record, processed.BeginTime);
                    AddPlayerTime(fight, processed.Record, processed.Record.Defender, processed.BeginTime);
                    fight.BeginTankingTime = double.IsNaN(fight.BeginTankingTime) ? processed.BeginTime : fight.BeginTankingTime;
                    fight.LastTankingTime  = processed.BeginTime;

                    if (StatsUtil.IsHitType(processed.Record.Type))
                    {
                        fight.TankHits++;
                    }
                }

                fight.LastTime       = processed.BeginTime;
                LastFightProcessTime = processed.BeginTime;

                var ttl = fight.LastTime - fight.BeginTime + 1;
                fight.TooltipText = string.Format(CultureInfo.CurrentCulture, "#Hits To Players: {0}, #Hits From Players: {1}, Time Alive: {2}s", fight.TankHits, fight.DamageHits, ttl);

                DataManager.Instance.UpdateIfNewFightMap(fight.CorrectMapKey, fight, isNonTankingFight);
            }
        }
Пример #2
0
        internal static CombinedStats ComputeOverlayStats(int mode, int maxRows, string selectedClass)
        {
            CombinedStats combined = null;

            var   allDamage    = 0L;
            var   allTime      = new TimeRange();
            var   playerTotals = new Dictionary <string, OverlayPlayerTotal>();
            var   playerHasPet = new Dictionary <string, bool>();
            var   updateTime   = 0d;
            var   oldestTime   = 0d;
            var   fights       = DataManager.Instance.GetOverlayFights();
            Fight oldestFight  = null;
            bool  baneEnabled  = MainWindow.IsBaneDamageEnabled;

            // clear out anything pending in the queue
            DamageLineParser.CheckSlainQueue(DateUtil.ToDouble(DateTime.Now.AddSeconds(-3)));

            if (fights.Count > 0)
            {
                oldestFight = fights[0];
                foreach (var fight in fights.Where(fight => !fight.Dead || mode > 0))
                {
                    foreach (var keypair in fight.PlayerTotals)
                    {
                        var player = keypair.Key;
                        if (!string.IsNullOrEmpty(keypair.Value.PetOwner))
                        {
                            player = keypair.Value.PetOwner;
                            playerHasPet[player] = true;
                        }
                        else if (PlayerManager.Instance.GetPlayerFromPet(player) is string owner && owner != Labels.UNASSIGNED)
                        {
                            player = owner;
                            playerHasPet[player] = true;
                        }

                        allDamage += baneEnabled ? keypair.Value.DamageWithBane : keypair.Value.Damage;
                        allTime.Add(new TimeSegment(keypair.Value.BeginTime, fight.LastDamageTime));

                        if (updateTime == 0)
                        {
                            updateTime  = keypair.Value.UpdateTime;
                            oldestTime  = keypair.Value.UpdateTime;
                            oldestFight = fight;
                        }
                        else
                        {
                            updateTime = Math.Max(updateTime, keypair.Value.UpdateTime);
                            if (oldestTime > keypair.Value.UpdateTime)
                            {
                                oldestTime  = keypair.Value.UpdateTime;
                                oldestFight = fight;
                            }
                        }

                        if (playerTotals.TryGetValue(player, out OverlayPlayerTotal total))
                        {
                            total.Damage += baneEnabled ? keypair.Value.DamageWithBane : keypair.Value.Damage;
                            total.Range.Add(new TimeSegment(keypair.Value.BeginTime, keypair.Value.UpdateTime));
                            total.UpdateTime = Math.Max(total.UpdateTime, keypair.Value.UpdateTime);
                        }
                        else
                        {
                            playerTotals[player] = new OverlayPlayerTotal
                            {
                                Name       = player,
                                Damage     = baneEnabled ? keypair.Value.DamageWithBane : keypair.Value.Damage,
                                Range      = new TimeRange(new TimeSegment(keypair.Value.BeginTime, keypair.Value.UpdateTime)),
                                UpdateTime = keypair.Value.UpdateTime
                            };
                        }
                    }
                }

                var timeout      = mode == 0 ? DataManager.FIGHTTIMEOUT : mode;
                var totalSeconds = allTime.GetTotal();
                if (oldestFight != null && totalSeconds > 0 && allDamage > 0 && (DateTime.Now - DateTime.MinValue.AddSeconds(updateTime)).TotalSeconds <= timeout)
                {
                    int rank     = 1;
                    var list     = new List <PlayerStats>();
                    var totalDps = (long)Math.Round(allDamage / totalSeconds, 2);
                    int myIndex  = -1;

                    foreach (var total in playerTotals.Values.OrderByDescending(total => total.Damage))
                    {
                        var time = total.Range.GetTotal();
                        if (time > 0 && (DateTime.Now - DateTime.MinValue.AddSeconds(total.UpdateTime)).TotalSeconds <= DataManager.MAXTIMEOUT)
                        {
                            PlayerStats playerStats = new PlayerStats()
                            {
                                Name         = playerHasPet.ContainsKey(total.Name) ? total.Name + " +Pets" : total.Name,
                                Total        = total.Damage,
                                DPS          = (long)Math.Round(total.Damage / time, 2),
                                TotalSeconds = time,
                                Rank         = (ushort)rank++,
                                ClassName    = PlayerManager.Instance.GetPlayerClass(total.Name),
                                OrigName     = total.Name
                            };

                            if (playerStats.Name.StartsWith(ConfigUtil.PlayerName, StringComparison.Ordinal))
                            {
                                myIndex = list.Count;
                            }

                            if (myIndex == list.Count || selectedClass == Properties.Resources.ANY_CLASS || selectedClass == playerStats.ClassName)
                            {
                                list.Add(playerStats);
                            }
                        }
                    }

                    if (myIndex > (maxRows - 1))
                    {
                        var me = list[myIndex];
                        list = list.Take(maxRows - 1).ToList();
                        list.Add(me);
                    }
                    else
                    {
                        list = list.Take(maxRows).ToList();
                    }

                    combined = new CombinedStats();
                    combined.StatsList.AddRange(list);
                    combined.RaidStats = new PlayerStats {
                        Total = allDamage, DPS = totalDps, TotalSeconds = totalSeconds
                    };
                    combined.TargetTitle = (fights.Count > 1 ? "C(" + fights.Count + "): " : "") + oldestFight.Name;

                    // these are here to support copy/paste of the parse
                    combined.TimeTitle  = string.Format(CultureInfo.CurrentCulture, StatsUtil.TIME_FORMAT, combined.RaidStats.TotalSeconds);
                    combined.TotalTitle = string.Format(CultureInfo.CurrentCulture, StatsUtil.TOTAL_FORMAT, StatsUtil.FormatTotals(combined.RaidStats.Total),
                                                        " Damage ", StatsUtil.FormatTotals(combined.RaidStats.DPS));
                }
            }

            return(combined);
        }