public IEnumerable <Rotation> GetRotations() { var log = GetLog(); var players = log.Agents.OfType <Player>(); if (characterNames != null) { players = players.Where(x => characterNames.Contains(x.Name)); } var rotationCalculator = new RotationCalculator(); foreach (var player in players) { var playerRotation = rotationCalculator.GetRotation(log, player); var items = new List <RotationItem>(); foreach (var item in playerRotation.Items) { if (item is SkillCastItem skillCast) { items.Add(GetSkillCast(skillCast)); } else if (item is WeaponSwapItem weaponSwap) { items.Add(GetWeaponSwap(weaponSwap)); } } yield return(new Rotation(player.Name, player.Profession, player.EliteSpecialization, items)); } }
private void CalculatePlayerData() { var players = GetPlayers(); var deathCounts = players.ToDictionary(x => x, x => 0); var downCounts = players.ToDictionary(x => x, x => 0); var usedSkills = players.ToDictionary(x => x, x => new HashSet <Skill>()); foreach (var deadEvent in log.Events.OfType <AgentDeadEvent>().Where(x => x.Agent is Player)) { var player = (Player)deadEvent.Agent; deathCounts[player]++; } foreach (var downEvent in log.Events.OfType <AgentDownedEvent>().Where(x => x.Agent is Player)) { var player = (Player)downEvent.Agent; downCounts[player]++; } // Buff damage events only tell us which conditions/buffs, not what skill actually applied them foreach (var damageEvent in log.Events.OfType <PhysicalDamageEvent>().Where(x => x.Attacker is Player)) { var player = (Player)damageEvent.Attacker; usedSkills[player].Add(damageEvent.Skill); } foreach (var activationEvent in log.Events.OfType <SkillCastEvent>().Where(x => x.Agent is Player)) { var player = (Player)activationEvent.Agent; usedSkills[player].Add(activationEvent.Skill); } var playerData = new List <PlayerData>(); foreach (var player in players) { HashSet <SkillData> utilitySkills = null; HashSet <SkillData> healingSkills = null; HashSet <SkillData> eliteSkills = null; if (ApiData != null) { utilitySkills = new HashSet <SkillData>(); healingSkills = new HashSet <SkillData>(); eliteSkills = new HashSet <SkillData>(); foreach (var usedSkill in usedSkills[player]) { var skillData = ApiData.GetSkillData(usedSkill); // Skills may be also registered as used if they affect other players and do damage through them if (skillData != null && skillData.Professions.Contains(player.Profession)) { if (skillData.Slot == SkillSlot.Elite) { eliteSkills.Add(skillData); } else if (skillData.Slot == SkillSlot.Utility) { utilitySkills.Add(skillData); } else if (skillData.Slot == SkillSlot.Heal) { healingSkills.Add(skillData); } } } } WeaponType land1Weapon1 = WeaponType.Other; WeaponType land1Weapon2 = WeaponType.Other; WeaponType land2Weapon1 = WeaponType.Other; WeaponType land2Weapon2 = WeaponType.Other; IEnumerable <SkillData> land1WeaponSkills = null; IEnumerable <SkillData> land2WeaponSkills = null; // TODO: Dual wield skill handling for Thieves if (ApiData != null) { WeaponSet currentWeaponSet = WeaponSet.Unknown; // We are only interested in land weapons. This may be imperfect if started on an underwater set. var firstWeaponSwap = log.Events.OfType <AgentWeaponSwapEvent>().FirstOrDefault(x => x.NewWeaponSet == WeaponSet.Land1 || x.NewWeaponSet == WeaponSet.Land2); if (firstWeaponSwap == null) { currentWeaponSet = WeaponSet.Land1; } else { // First weapon set is the other one than the first swap swaps to (unless it was an underwater one) currentWeaponSet = firstWeaponSwap.NewWeaponSet == WeaponSet.Land1 ? WeaponSet.Land2 : WeaponSet.Land1; } foreach (var logEvent in log.Events) { if (logEvent is AgentWeaponSwapEvent weaponSwapEvent && weaponSwapEvent.Agent == player) { currentWeaponSet = weaponSwapEvent.NewWeaponSet; continue; } SkillData skillData = null; if (logEvent is StartSkillCastEvent castEvent && castEvent.Agent == player) { skillData = ApiData.GetSkillData(castEvent.Skill); } if (skillData != null) { if (skillData.Professions.Contains(player.Profession) && skillData.Type == SkillType.Weapon) { if (skillData.WeaponType.IsTwoHanded() || skillData.Slot == SkillSlot.Weapon1 || skillData.Slot == SkillSlot.Weapon2 || skillData.Slot == SkillSlot.Weapon3) { if (currentWeaponSet == WeaponSet.Land1) { land1Weapon1 = skillData.WeaponType; } else if (currentWeaponSet == WeaponSet.Land2) { land2Weapon1 = skillData.WeaponType; } } if (skillData.WeaponType.IsTwoHanded() || skillData.Slot == SkillSlot.Weapon4 || skillData.Slot == SkillSlot.Weapon5) { if (currentWeaponSet == WeaponSet.Land1) { land1Weapon2 = skillData.WeaponType; } else if (currentWeaponSet == WeaponSet.Land2) { land2Weapon2 = skillData.WeaponType; } } } } } land1WeaponSkills = WeaponSkillData .GetWeaponSkillIds(player.Profession, land1Weapon1, land1Weapon2) .Select(x => x == -1 ? null : ApiData.GetSkillData(x)); land2WeaponSkills = WeaponSkillData .GetWeaponSkillIds(player.Profession, land2Weapon1, land2Weapon2) .Select(x => x == -1 ? null : ApiData.GetSkillData(x)); } if (ApiData != null) { var skillDetections = SkillDetections.GetSkillDetections(player.Profession).ToArray(); foreach (var e in log.Events) { foreach (var detection in skillDetections) { if (detection.Detection.IsDetected(player, e)) { var skill = ApiData.GetSkillData(detection.SkillId); if (detection.Slot == SkillSlot.Utility) { utilitySkills.Add(skill); } else if (detection.Slot == SkillSlot.Heal) { healingSkills.Add(skill); } else if (detection.Slot == SkillSlot.Elite) { eliteSkills.Add(skill); } } } } } var ignoredSkills = SkillDetections.GetIgnoredSkillIds(player.Profession); healingSkills?.RemoveWhere(x => ignoredSkills.Contains(x.Id)); utilitySkills?.RemoveWhere(x => ignoredSkills.Contains(x.Id)); eliteSkills?.RemoveWhere(x => ignoredSkills.Contains(x.Id)); var specializationDetections = SpecializationDetections.GetSpecializationDetections(player.Profession).ToArray(); var badges = new List <PlayerBadge>(); var specializations = new HashSet <CoreSpecialization>(); foreach (var e in log.Events) { foreach (var detection in specializationDetections) { if (detection.Detection.IsDetected(player, e)) { specializations.Add(detection.Specialization); } } } foreach (var spec in specializations.OrderBy(x => x.ToString())) { badges.Add(new PlayerBadge(spec.ToString(), BadgeType.Specialization)); } var rotation = RotationCalculator.GetRotation(log, player); var data = new PlayerData(player, downCounts[player], deathCounts[player], rotation, usedSkills[player], healingSkills, utilitySkills, eliteSkills, land1Weapon1, land1Weapon2, land2Weapon1, land2Weapon2, land1WeaponSkills, land2WeaponSkills, badges); playerData.Add(data); } logPlayerData = playerData; }