Пример #1
0
 /// <summary>
 /// Creates a new instance of an <see cref="NPC"/>.
 /// </summary>
 public NPC(AgentOrigin agentOrigin, string name, int speciesId, int toughness, int concentration, int healing,
            int condition, int hitboxWidth, int hitboxHeight) : base(agentOrigin, name, hitboxWidth, hitboxHeight)
 {
     SpeciesId     = speciesId;
     Toughness     = toughness;
     Concentration = concentration;
     Healing       = healing;
     Condition     = condition;
 }
Пример #2
0
        /// <summary>
        /// Creates a new instance of a <see cref="Player"/> character.
        /// </summary>
        public Player(AgentOrigin agentOrigin, string name, int toughness, int concentration, int healing, int condition,
                      int hitboxWidth, int hitboxHeight, string accountName, Profession profession,
                      EliteSpecialization eliteSpecialization, int subgroup, bool identified)
            : base(agentOrigin, name, hitboxWidth, hitboxHeight)
        {
            Toughness     = toughness;
            Concentration = concentration;
            Healing       = healing;
            Condition     = condition;

            Identified          = identified;
            Subgroup            = subgroup;
            AccountName         = accountName;
            Profession          = profession;
            EliteSpecialization = eliteSpecialization;
        }
Пример #3
0
 public AttackTarget(AgentOrigin agentOrigin, int volatileId, string name, int hitboxWidth, int hitboxHeight)
     : base(agentOrigin, name, hitboxWidth, hitboxHeight)
 {
     VolatileId = volatileId;
 }
Пример #4
0
        private IEnumerable <Agent> GetAgents(ParsedLog log)
        {
            var idsByAddress = new Dictionary <ulong, int>();

            foreach (var combatItem in log.ParsedCombatItems)
            {
                if (combatItem.IsStateChange == StateChange.Normal)
                {
                    idsByAddress[combatItem.SrcAgent] = combatItem.SrcAgentId;
                }
            }

            var playerAddresses = new HashSet <ulong>();

            foreach (var agent in log.ParsedAgents)
            {
                if (agent.IsElite != 0xFFFFFFFF)
                {
                    // Player
                    uint       professionIndex = agent.Prof - 1;
                    Profession profession;

                    // We need to check if the profession is valid.
                    // The 2021-05-25 game update caused old versions of arcdps to report invalid profession values.
                    // Future game versions might also introduce new professions.
                    if (professionIndex < Professions.Length)
                    {
                        profession = Professions[professionIndex];
                    }
                    else
                    {
                        profession = Profession.None;
                    }

                    EliteSpecialization specialization;
                    if (agent.IsElite == 0)
                    {
                        specialization = EliteSpecialization.None;
                    }
                    else if (agent.IsElite == 1)
                    {
                        specialization = Characters.GetHeartOfThornsEliteSpecialization(profession);
                    }
                    else
                    {
                        specialization = Characters.GetEliteSpecializationFromId(agent.IsElite);
                    }

                    if (!idsByAddress.TryGetValue(agent.Address, out int id))
                    {
                        id = -1;
                    }

                    // All parts of the name of the player might not be available, most commonly in WvW logs.
                    var    nameParts       = agent.Name.Split(new[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
                    string characterName   = nameParts[0];
                    string accountName     = nameParts.Length > 1 ? nameParts[1] : ":Unknown";
                    string subgroupLiteral = nameParts.Length > 2 ? nameParts[2] : "";
                    bool   identified      = nameParts.Length >= 3;

                    if (!int.TryParse(subgroupLiteral, out int subgroup))
                    {
                        subgroup = -1;
                    }

                    if (playerAddresses.Contains(agent.Address))
                    {
                        // If there is already an agent with this address, this is the same player after changing
                        // characters. For now we simply merge everything into the first instance, even though that
                        // may result in a player using skills of a different profession, a better solution will be
                        // needed for the future.
                        continue;
                    }

                    playerAddresses.Add(agent.Address);

                    var origin = new AgentOrigin(new OriginalAgentData(agent.Address, id));
                    yield return(new Player(origin, characterName, agent.Toughness, agent.Concentration,
                                            agent.Healing, agent.Condition, agent.HitboxWidth, agent.HitboxHeight, accountName, profession,
                                            specialization, subgroup, identified));
                }
                else
                {
                    if (agent.Prof >> 16 == 0xFFFF)
                    {
                        // Gadget or Attack Target
                        int    volatileId = (int)(agent.Prof & 0xFFFF);
                        string name       = agent.Name.Trim('\0');

                        var origin = new AgentOrigin(new OriginalAgentData(agent.Address, volatileId));
                        if (name.StartsWith("at"))
                        {
                            // The attack target name is structured as "at[MasterAddress]-[GadgetId]-[MasterId]"
                            // Preferably, the AttackTarget statechange would be used to detect if this is an
                            // attack target to not rely on the name which could change in the future
                            yield return(new AttackTarget(origin, volatileId, name, agent.HitboxWidth,
                                                          agent.HitboxHeight));
                        }
                        else
                        {
                            yield return(new Gadget(origin, volatileId, name, agent.HitboxWidth,
                                                    agent.HitboxHeight));
                        }
                    }
                    else
                    {
                        // NPC
                        if (!idsByAddress.TryGetValue(agent.Address, out int id))
                        {
                            id = -1;
                        }

                        string name      = agent.Name.Trim('\0');
                        int    speciesId = (int)(agent.Prof & 0xFFFF);

                        var origin = new AgentOrigin(new OriginalAgentData(agent.Address, id));
                        yield return(new NPC(origin, name, speciesId, agent.Toughness, agent.Concentration,
                                             agent.Healing, agent.Condition, agent.HitboxWidth, agent.HitboxHeight));
                    }
                }
            }
        }