예제 #1
0
        public void AddHit(FightHitEvent hit)
        {
            if (hit.Source == Name)
            {
                SourceHitCount += 1;
                SourceHitSum   += hit.Amount;

                var at = AttackTypes.FirstOrDefault(x => x.Type == hit.Type);
                if (at == null)
                {
                    at      = new CombatantHit();
                    at.Type = hit.Type;
                    AttackTypes.Add(at);
                }
                at.NormalHitCount += 1;
                at.NormalHitSum   += hit.Amount;

                //if (hit.Amount > ht.MaxHit)
                //    ht.MaxHit = hit.Amount;
            }
            else if (hit.Target == Name)
            {
                TargetHitCount += 1;
                TargetHitSum   += hit.Amount;
            }
        }
예제 #2
0
        public void FightHit_Nuke()
        {
            FightHitEvent hit    = null;
            var           parser = new LogParser(PLAYER);

            parser.OnFightHit += (args) => hit = args;

            // outgoing (personal name is always shown like a 3rd party)
            parser.ParseLine("[Thu May 12 17:11:52 2016] Rumstil hit A singedbones skeleton for 37469 points of non-melee damage.");
            //parser.ParseLine("[Thu May 12 17:11:52 2016] You deliver a critical blast! (37469)");
            //parser.ParseLine("[Thu May 12 17:11:52 2016] A singedbones skeleton is caught in a hot summer's storm.");
            Assert.NotNull(hit);
            Assert.Equal(37469, hit.Amount);
            Assert.Equal("Rumstil", hit.Source);
            Assert.Equal("A singedbones skeleton", hit.Target);
            Assert.Equal("nuke", hit.Type);

            // incoming
            hit = null;
            parser.ParseLine("[Sun Nov 08 21:50:16 2015] A vicious shadow bites at your soul.  You have taken 1138 points of damage.");
            Assert.NotNull(hit);
            Assert.Equal(1138, hit.Amount);
            Assert.Null(hit.Source);
            Assert.Equal(PLAYER, hit.Target);
            Assert.Equal("A vicious shadow bites at your soul.", hit.Spell);
            Assert.Equal("nuke", hit.Type);

            // todo: incoming 3rd party
        }
예제 #3
0
        public void FightHit_DoT()
        {
            FightHitEvent hit    = null;
            var           parser = new LogParser(PLAYER);

            parser.OnFightHit += (args) => hit = args;

            // personal DoT
            hit = null;
            parser.ParseLine("[Sun Nov 08 19:41:40 2015] A corricaux echo has taken 3936 damage from your Glistenwing Swarm.");
            Assert.NotNull(hit);
            Assert.Equal(3936, hit.Amount);
            Assert.Equal(PLAYER, hit.Source);
            Assert.Equal("A corricaux echo", hit.Target);
            Assert.Equal("Glistenwing Swarm", hit.Spell);
            Assert.Equal("dot", hit.Type);

            // 3rd party DoT
            hit = null;
            parser.ParseLine("[Wed Nov 04 20:26:51 2015] Warpriest Poxxil has taken 14841 damage from Fourier by Mental Contortion V.");
            Assert.NotNull(hit);
            Assert.Equal(14841, hit.Amount);
            Assert.Equal("Fourier", hit.Source);
            Assert.Equal("Warpriest Poxxil", hit.Target);
            Assert.Equal("Mental Contortion V", hit.Spell);
            Assert.Equal("dot", hit.Type);

            // 3rd party DoT from dead caster or trap
            hit = null;
            parser.ParseLine("[Wed Nov 04 20:26:51 2015] Warpriest Poxxil has taken 14841 damage by Mental Contortion V.");
            Assert.NotNull(hit);
            Assert.Equal(14841, hit.Amount);
            Assert.Null(hit.Source);
            Assert.Equal("Warpriest Poxxil", hit.Target);
            Assert.Equal("Mental Contortion V", hit.Spell);
            Assert.Equal("dot", hit.Type);

            // incoming DoT
            hit = null;
            parser.ParseLine("[Wed Nov 04 20:26:51 2015] You have taken 3251 damage from Deadly Screech by The Cliknar Queen");
            Assert.NotNull(hit);
            Assert.Equal(3251, hit.Amount);
            Assert.Equal("The Cliknar Queen", hit.Source);
            Assert.Equal(PLAYER, hit.Target);
            Assert.Equal("Deadly Screech", hit.Spell);
            Assert.Equal("dot", hit.Type);

            // incoming DoT from dead caster or trap
            hit = null;
            parser.ParseLine("[Wed Nov 04 20:26:51 2015] You have taken 3251 damage from Deadly Screech");
            Assert.NotNull(hit);
            Assert.Equal(3251, hit.Amount);
            Assert.Null(hit.Source);
            Assert.Equal(PLAYER, hit.Target);
            Assert.Equal("Deadly Screech", hit.Spell);
            Assert.Equal("dot", hit.Type);
        }
예제 #4
0
        public virtual void TrackFightHit(FightHitEvent hit)
        {
            var f = AddFight(hit);

            if (f == null)
            {
                return;
            }

            var source = f.Participants.First(x => x.Name == hit.Source);

            source.AddHit(hit);

            var target = f.Participants.First(x => x.Name == hit.Target);

            target.AddHit(hit);

            // there are no crit notifications for DoTs but we can guess when they occur by
            // treating everything that does 125% more damage than the minimum as a crit
            // todo: do DoTs have partial resists?
            if (hit.Type == "dot" && hit.Spell != null)
            {
                int min;
                if (!MinDoTDamage.TryGetValue(hit.Spell, out min) || min > hit.Amount)
                {
                    MinDoTDamage[hit.Spell] = min = hit.Amount;
                }
                if (hit.Amount >= min * 2.25)
                {
                    LastCritical = new FightCritEvent {
                        Timestamp = hit.Timestamp, Source = hit.Source, Amount = hit.Amount, Sequence = FightCritEventSequence.BeforeHit
                    }
                }
                ;
            }

            // update hit for crit notification that occured before hit
            if (LastCritical != null && LastCritical.Sequence == FightCritEventSequence.BeforeHit && LastCritical.Source == hit.Source)
            {
                var ht = source.AttackTypes.First(x => x.Type == hit.Type);
                ht.NormalHitCount -= 1;
                ht.NormalHitSum   -= hit.Amount;
                ht.CritHitCount   += 1;
                ht.CritHitSum     += hit.Amount;
            }

            LastFight    = f;
            LastHit      = hit;
            LastCritical = null;
        }
예제 #5
0
        public void FightHit_DS()
        {
            FightHitEvent hit    = null;
            var           parser = new LogParser(PLAYER);

            parser.OnFightHit += (args) => hit = args;

            parser.ParseLine("[Thu May 12 15:49:46 2016] A soldier is pierced by YOUR thorns for 703 points of non-melee damage.");
            Assert.NotNull(hit);
            Assert.Equal(703, hit.Amount);
            Assert.Equal(PLAYER, hit.Source);
            Assert.Equal("A soldier", hit.Target);
            Assert.Equal("dmgshield", hit.Type);
        }
예제 #6
0
        // runes are currently handled by FightMiss but perhaps they should also be hits for 0 damage?
        //private static readonly Regex RuneRegex = new Regex(@"^(.+?) (?:try|tries) to (\w+) (.+?), but .*? magical skin absorbs the blow!$", RegexOptions.Compiled | RegexOptions.RightToLeft);

        //[EventParser]
        private void CheckFightHit(LogLine line)
        {
            if (OnFightHit == null)
            {
                return;
            }

            var m = MeleeHitRegex.Match(line.RawText);

            if (m.Success)
            {
                var type = m.Groups[2].Value;
                if (type == "frenzy on" || type == "frenzies on")
                {
                    type = "frenzy";
                }

                var hit = new FightHitEvent()
                {
                    Timestamp = line.Timestamp,
                    Source    = FixName(m.Groups[1].Value),
                    Type      = type,
                    Target    = FixName(m.Groups[3].Value),
                    Amount    = Int32.Parse(m.Groups[4].Value)
                };
                OnFightHit(hit);
                return;
            }

            m = RampageRegex.Match(line.RawText);
            if (m.Success)
            {
                var type = m.Groups[4].Value;
                if (type == "Rampage")
                {
                    type = "rampage";
                }
                if (type == "Wild Rampage")
                {
                    type = "wildramp";
                }

                var hit = new FightHitEvent()
                {
                    Timestamp = line.Timestamp,
                    Source    = FixName(m.Groups[1].Value),
                    Target    = FixName(m.Groups[2].Value),
                    Amount    = Int32.Parse(m.Groups[3].Value),
                    Type      = type
                };
                OnFightHit(hit);
                return;
            }


            /*
             * m = MiscHitRegex.Match(line.Text);
             * if (m.Success)
             * {
             *  var hit = new FightHit()
             *  {
             *      Timestamp = line.Timestamp,
             *      Target = FixName(m.Groups[1].Value),
             *      Amount = Int32.Parse(m.Groups[2].Value),
             *      Type = "hit",
             *  };
             *  OnFightHit(hit);
             *  return;
             * }
             */

            m = NukeDamageRegex.Match(line.RawText);
            if (m.Success)
            {
                var hit = new FightHitEvent()
                {
                    Timestamp = line.Timestamp,
                    Source    = FixName(m.Groups[1].Value),
                    Target    = FixName(m.Groups[2].Value),
                    Amount    = Int32.Parse(m.Groups[3].Value),
                    Type      = "nuke"
                };
                OnFightHit(hit);
                return;
            }

            m = IncNukeDamageRegex.Match(line.RawText);
            if (m.Success)
            {
                var hit = new FightHitEvent()
                {
                    Timestamp = line.Timestamp,
                    Target    = Player.Name,
                    Spell     = m.Groups[1].Value,
                    Amount    = Int32.Parse(m.Groups[2].Value),
                    Type      = "nuke"
                };
                OnFightHit(hit);
                return;
            }

            m = DoTDamageRegex.Match(line.RawText);
            if (m.Success)
            {
                var hit = new FightHitEvent()
                {
                    Timestamp      = line.Timestamp,
                    Target         = FixName(m.Groups[1].Value),
                    Amount         = Int32.Parse(m.Groups[2].Value),
                    Source         = FixName(Coalesce(m.Groups[3], m.Groups[4])),
                    SourceIsCorpse = m.Groups[4].Value.EndsWith(CorpseSuffix),
                    Spell          = m.Groups[5].Value,
                    Type           = "dot"
                };
                OnFightHit(hit);
                return;
            }

            m = IncDoTDamageRegex.Match(line.RawText);
            if (m.Success)
            {
                var hit = new FightHitEvent()
                {
                    Timestamp      = line.Timestamp,
                    Target         = Player.Name,
                    Amount         = Int32.Parse(m.Groups[1].Value),
                    Spell          = m.Groups[2].Value,
                    Source         = FixName(m.Groups[3].Value),
                    SourceIsCorpse = m.Groups[3].Value.EndsWith(CorpseSuffix),
                    Type           = "dot"
                };
                OnFightHit(hit);
                return;
            }

            m = DamageShieldRegex.Match(line.RawText);
            if (m.Success)
            {
                var hit = new FightHitEvent()
                {
                    Timestamp = line.Timestamp,
                    Source    = Player.Name,
                    Target    = m.Groups[1].Value,
                    Amount    = Int32.Parse(m.Groups[2].Value),
                    Type      = "dmgshield"
                };
                OnFightHit(hit);
                return;
            }

#if DEBUG
            //m = UnknownHitRegex.Match(line.RawText);
            //if (m.Success)
            //{
            //    Console.Error.WriteLine(line.RawText);
            //    OnFightHit(new FightHitEvent { Timestamp = line.Timestamp, Target = "N/A", Source = "N/A", Type = line.RawText });
            //}
#endif
        }
예제 #7
0
        public void FightHit_Melee()
        {
            FightHitEvent hit    = null;
            var           parser = new LogParser(PLAYER);

            parser.OnFightHit += (args) => hit = args;

            // personal hit
            hit = null;
            parser.ParseLine("[Wed Apr 20 18:36:59 2016] You pierce A skeletal minion for 1424 points of damage.");
            Assert.NotNull(hit);
            Assert.Equal(1424, hit.Amount);
            Assert.Equal(PLAYER, hit.Source);
            Assert.Equal("A skeletal minion", hit.Target);
            Assert.Equal("pierce", hit.Type);

            // 3rd party hit
            hit = null;
            parser.ParseLine("[Sun May 08 20:13:09 2016] Jonekab frenzies on An aggressive corpse for 429 points of damage.");
            Assert.NotNull(hit);
            Assert.Equal(429, hit.Amount);
            Assert.Equal("Jonekab", hit.Source);
            Assert.Equal("An aggressive corpse", hit.Target);
            Assert.Equal("frenzy", hit.Type);

            // incoming hit
            hit = null;
            parser.ParseLine("[Wed Apr 27 09:46:20 2016] A ghoul hits YOU for 3551 points of damage.");
            Assert.NotNull(hit);
            Assert.Equal(3551, hit.Amount);
            Assert.Equal("A ghoul", hit.Source);
            Assert.Equal(PLAYER, hit.Target);
            Assert.Equal("hit", hit.Type);

            // rampage
            hit = null;
            parser.ParseLine("[Wed Apr 27 09:46:20 2016] Praetor Ledalus Thaddaeus slashes Rumstil for 9456 points of damage. (Rampage)");
            Assert.NotNull(hit);
            Assert.Equal(9456, hit.Amount);
            Assert.Equal("Praetor Ledalus Thaddaeus", hit.Source);
            Assert.Equal("Rumstil", hit.Target);
            Assert.Equal("rampage", hit.Type);

            // frenzy on - 2 word attack skill
            hit = null;
            parser.ParseLine("[Wed Apr 27 09:46:20 2016] A ghoul frenzies on YOU for 3551 points of damage.");
            Assert.NotNull(hit);
            Assert.Equal(3551, hit.Amount);
            Assert.Equal("A ghoul", hit.Source);
            Assert.Equal(PLAYER, hit.Target);
            Assert.Equal("frenzy", hit.Type);

            // make sure the extra non-melee message from archery and other skill attacks is not processed twice
            // this was also the format used by old damage shield messages
            // [Thu May 19 10:37:29 2016] a fright funnel was hit by non-melee for 186844 points of damage.
            // [Thu May 19 10:37:29 2016] You gain party experience!!
            // [Thu May 19 10:37:29 2016] You hit a fright funnel for 186844 points of damage.
            hit = null;
            parser.ParseLine("[Thu May 12 17:11:55 2016] A singedbones skeleton was hit by non-melee for 246657 points of damage.");
            Assert.Null(hit);
        }