Skip to content

Commit

Permalink
Add support for End of Dragons specializations
Browse files Browse the repository at this point in the history
  • Loading branch information
Sejsel committed Aug 18, 2021
1 parent 9a65092 commit 26b006e
Show file tree
Hide file tree
Showing 15 changed files with 122 additions and 19 deletions.
2 changes: 1 addition & 1 deletion ArcdpsLogManager/ArcdpsLogManager.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
Each new log data update causes a revision increase.
See LogDataUpdater for the updates.
-->
<Version>1.1.2.0</Version>
<Version>1.2.0.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Eto.Forms" Version="2.5.11-ci-20210422.772645364" />
Expand Down
6 changes: 5 additions & 1 deletion ArcdpsLogManager/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

This is the full changelog of the arcdps Log Manager.

## Log Manager v1.1.2 (unreleased)
## Log Manager v1.2.0

#### New features
- Added support for Virtuoso, Harbinger and Willbender
- Added support for EoD specializations in squad composition filters

#### Fixes
- Fixed broken profession detection for Core Guardians.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public SquadCompositionFilterPanel(ImageProvider imageProvider, LogFilters filte
// Elite specializations
var specializationFilterGroups = new[] {
filterSnapshot.HeartOfThornsSpecializationFilters,
filterSnapshot.PathOfFireSpecializationFilters
filterSnapshot.PathOfFireSpecializationFilters,
filterSnapshot.EndOfDragonsSpecializationFilters
};
foreach (var specializationFilters in specializationFilterGroups)
{
Expand Down Expand Up @@ -108,6 +109,7 @@ private Button ConstructResetButton(CompositionFilters filterSnapshot)
filterSnapshot.CoreProfessionFilters,
filterSnapshot.HeartOfThornsSpecializationFilters,
filterSnapshot.PathOfFireSpecializationFilters,
filterSnapshot.EndOfDragonsSpecializationFilters,
};
foreach (var group in filterGroups)
{
Expand Down
9 changes: 9 additions & 0 deletions ArcdpsLogManager/GameData/GameNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ public static string GetName(EliteSpecialization specialization)
EliteSpecialization.Spellbreaker => "Spellbreaker",
EliteSpecialization.Firebrand => "Firebrand",
EliteSpecialization.Renegade => "Renegade",
EliteSpecialization.Willbender => "Willbender",
EliteSpecialization.EoDWarrior => "Warrior (EoD)", // TODO: Update when announced
EliteSpecialization.EoDEngineer => "Engineer (EoD)", // TODO: Update when announced
EliteSpecialization.EoDRanger => "Ranger (EoD)", // TODO: Update when announced
EliteSpecialization.EoDThief => "Thief (EoD)", // TODO: Update when announced
EliteSpecialization.EoDElementalist => "Elementalist (EoD)", // TODO: Update when announced
EliteSpecialization.Virtuoso => "Virtuoso",
EliteSpecialization.Harbinger => "Harbinger",
EliteSpecialization.EoDRevenant => "Revenant (EoD)", // TODO: Update when announced
_ => throw new ArgumentOutOfRangeException(nameof(specialization), specialization, null)
};
}
Expand Down
20 changes: 10 additions & 10 deletions ArcdpsLogManager/GameData/ProfessionData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ namespace GW2Scratch.ArcdpsLogManager.GameData
{
public static class ProfessionData
{
public static IReadOnlyList<(Profession Profession, EliteSpecialization HoT, EliteSpecialization PoF)>
public static IReadOnlyList<(Profession Profession, EliteSpecialization HoT, EliteSpecialization PoF, EliteSpecialization EoD)>
Professions { get; } = new[]
{
(Profession.Warrior, EliteSpecialization.Berserker, EliteSpecialization.Spellbreaker),
(Profession.Guardian, EliteSpecialization.Dragonhunter, EliteSpecialization.Firebrand),
(Profession.Revenant, EliteSpecialization.Herald, EliteSpecialization.Renegade),
(Profession.Ranger, EliteSpecialization.Druid, EliteSpecialization.Soulbeast),
(Profession.Thief, EliteSpecialization.Daredevil, EliteSpecialization.Deadeye),
(Profession.Engineer, EliteSpecialization.Scrapper, EliteSpecialization.Holosmith),
(Profession.Necromancer, EliteSpecialization.Reaper, EliteSpecialization.Scourge),
(Profession.Elementalist, EliteSpecialization.Tempest, EliteSpecialization.Weaver),
(Profession.Mesmer, EliteSpecialization.Chronomancer, EliteSpecialization.Mirage),
(Profession.Warrior, EliteSpecialization.Berserker, EliteSpecialization.Spellbreaker, EliteSpecialization.EoDWarrior),
(Profession.Guardian, EliteSpecialization.Dragonhunter, EliteSpecialization.Firebrand, EliteSpecialization.Willbender),
(Profession.Revenant, EliteSpecialization.Herald, EliteSpecialization.Renegade, EliteSpecialization.EoDRevenant),
(Profession.Ranger, EliteSpecialization.Druid, EliteSpecialization.Soulbeast, EliteSpecialization.EoDRanger),
(Profession.Thief, EliteSpecialization.Daredevil, EliteSpecialization.Deadeye, EliteSpecialization.EoDThief),
(Profession.Engineer, EliteSpecialization.Scrapper, EliteSpecialization.Holosmith, EliteSpecialization.EoDEngineer),
(Profession.Necromancer, EliteSpecialization.Reaper, EliteSpecialization.Scourge, EliteSpecialization.Harbinger),
(Profession.Elementalist, EliteSpecialization.Tempest, EliteSpecialization.Weaver, EliteSpecialization.EoDElementalist),
(Profession.Mesmer, EliteSpecialization.Chronomancer, EliteSpecialization.Mirage, EliteSpecialization.Virtuoso),
};
}
}
12 changes: 12 additions & 0 deletions ArcdpsLogManager/ImageProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class ImageProvider
private Lazy<Image> TinyIconBerserker { get; } = new Lazy<Image>(Resources.GetTinyIconBerserker);
private Lazy<Image> TinyIconSpellbreaker { get; } = new Lazy<Image>(Resources.GetTinyIconSpellbreaker);
private Lazy<Image> TinyIconDragonhunter { get; } = new Lazy<Image>(Resources.GetTinyIconDragonhunter);
private Lazy<Image> TinyIconWillbender { get; } = new Lazy<Image>(Resources.GetTinyIconWillbender);
private Lazy<Image> TinyIconFirebrand { get; } = new Lazy<Image>(Resources.GetTinyIconFirebrand);
private Lazy<Image> TinyIconHerald { get; } = new Lazy<Image>(Resources.GetTinyIconHerald);
private Lazy<Image> TinyIconRenegade { get; } = new Lazy<Image>(Resources.GetTinyIconRenegade);
Expand All @@ -36,10 +37,12 @@ public class ImageProvider
private Lazy<Image> TinyIconHolosmith { get; } = new Lazy<Image>(Resources.GetTinyIconHolosmith);
private Lazy<Image> TinyIconReaper { get; } = new Lazy<Image>(Resources.GetTinyIconReaper);
private Lazy<Image> TinyIconScourge { get; } = new Lazy<Image>(Resources.GetTinyIconScourge);
private Lazy<Image> TinyIconHarbinger { get; } = new Lazy<Image>(Resources.GetTinyIconHarbinger);
private Lazy<Image> TinyIconTempest { get; } = new Lazy<Image>(Resources.GetTinyIconTempest);
private Lazy<Image> TinyIconWeaver { get; } = new Lazy<Image>(Resources.GetTinyIconWeaver);
private Lazy<Image> TinyIconChronomancer { get; } = new Lazy<Image>(Resources.GetTinyIconChronomancer);
private Lazy<Image> TinyIconMirage { get; } = new Lazy<Image>(Resources.GetTinyIconMirage);
private Lazy<Image> TinyIconVirtuoso { get; } = new Lazy<Image>(Resources.GetTinyIconVirtuoso);

// CATEGORIES
private Lazy<Image> TinyIconRaid { get; } = new Lazy<Image>(Resources.GetTinyIconRaid);
Expand Down Expand Up @@ -169,6 +172,7 @@ public Image GetTinyProfessionIcon(EliteSpecialization specialization)
EliteSpecialization.Spellbreaker => TinyIconSpellbreaker.Value,
EliteSpecialization.Dragonhunter => TinyIconDragonhunter.Value,
EliteSpecialization.Firebrand => TinyIconFirebrand.Value,
EliteSpecialization.Willbender => TinyIconWillbender.Value,
EliteSpecialization.Herald => TinyIconHerald.Value,
EliteSpecialization.Renegade => TinyIconRenegade.Value,
EliteSpecialization.Druid => TinyIconDruid.Value,
Expand All @@ -179,10 +183,18 @@ public Image GetTinyProfessionIcon(EliteSpecialization specialization)
EliteSpecialization.Holosmith => TinyIconHolosmith.Value,
EliteSpecialization.Reaper => TinyIconReaper.Value,
EliteSpecialization.Scourge => TinyIconScourge.Value,
EliteSpecialization.Harbinger => TinyIconHarbinger.Value,
EliteSpecialization.Tempest => TinyIconTempest.Value,
EliteSpecialization.Weaver => TinyIconWeaver.Value,
EliteSpecialization.Chronomancer => TinyIconChronomancer.Value,
EliteSpecialization.Mirage => TinyIconMirage.Value,
EliteSpecialization.Virtuoso => TinyIconVirtuoso.Value,
EliteSpecialization.EoDWarrior => TinyIconUnknownProfession.Value, // TODO: Add when announced
EliteSpecialization.EoDEngineer => TinyIconUnknownProfession.Value, // TODO: Add when announced
EliteSpecialization.EoDRanger => TinyIconUnknownProfession.Value, // TODO: Add when announced
EliteSpecialization.EoDThief => TinyIconUnknownProfession.Value, // TODO: Add when announced
EliteSpecialization.EoDElementalist => TinyIconUnknownProfession.Value, // TODO: Add when announced
EliteSpecialization.EoDRevenant => TinyIconUnknownProfession.Value, // TODO: Add when announced
_ => throw new ArgumentOutOfRangeException(nameof(specialization)),
};
}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 23 additions & 4 deletions ArcdpsLogManager/Logs/Filters/CompositionFilters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,31 @@ public class CompositionFilters : ILogFilter, INotifyPropertyChanged
public IReadOnlyList<CoreProfessionPlayerCountFilter> CoreProfessionFilters { get; }
public IReadOnlyList<EliteSpecializationPlayerCountFilter> HeartOfThornsSpecializationFilters { get; }
public IReadOnlyList<EliteSpecializationPlayerCountFilter> PathOfFireSpecializationFilters { get; }
public IReadOnlyList<EliteSpecializationPlayerCountFilter> EndOfDragonsSpecializationFilters { get; }

public CompositionFilters() : this(
ProfessionData.Professions.Select(x => x.Profession)
.Select(profession => new CoreProfessionPlayerCountFilter(profession)),
ProfessionData.Professions.Select(x => x.HoT)
.Select(specialization => new EliteSpecializationPlayerCountFilter(specialization)),
ProfessionData.Professions.Select(x => x.PoF)
.Select(specialization => new EliteSpecializationPlayerCountFilter(specialization)),
ProfessionData.Professions.Select(x => x.EoD)
.Select(specialization => new EliteSpecializationPlayerCountFilter(specialization))
)
{
}

private CompositionFilters(IEnumerable<CoreProfessionPlayerCountFilter> coreFilters,
IEnumerable<EliteSpecializationPlayerCountFilter> hotFilters,
IEnumerable<EliteSpecializationPlayerCountFilter> pofFilters)
IEnumerable<EliteSpecializationPlayerCountFilter> pofFilters,
IEnumerable<EliteSpecializationPlayerCountFilter> eodFilters
)
{
CoreProfessionFilters = coreFilters.ToList();
HeartOfThornsSpecializationFilters = hotFilters.ToList();
PathOfFireSpecializationFilters = pofFilters.ToList();
EndOfDragonsSpecializationFilters = eodFilters.ToList();

foreach (var filter in CoreProfessionFilters)
{
Expand All @@ -47,13 +53,19 @@ private CompositionFilters(IEnumerable<CoreProfessionPlayerCountFilter> coreFilt
{
filter.PropertyChanged += (_, _) => OnPropertyChanged(nameof(PathOfFireSpecializationFilters));
}

foreach (var filter in EndOfDragonsSpecializationFilters)
{
filter.PropertyChanged += (_, _) => OnPropertyChanged(nameof(EndOfDragonsSpecializationFilters));
}
}

public bool FilterLog(LogData log)
{
return CoreProfessionFilters.All(filter => filter.FilterLog(log)) &&
HeartOfThornsSpecializationFilters.All(filter => filter.FilterLog(log)) &&
PathOfFireSpecializationFilters.All(filter => filter.FilterLog(log));
PathOfFireSpecializationFilters.All(filter => filter.FilterLog(log)) &&
EndOfDragonsSpecializationFilters.All(filter => filter.FilterLog(log));
}

public event PropertyChangedEventHandler PropertyChanged;
Expand All @@ -68,15 +80,17 @@ public CompositionFilters DeepClone()
return new CompositionFilters(
CoreProfessionFilters.Select(x => x.DeepClone()),
HeartOfThornsSpecializationFilters.Select(x => x.DeepClone()),
PathOfFireSpecializationFilters.Select(x => x.DeepClone())
PathOfFireSpecializationFilters.Select(x => x.DeepClone()),
EndOfDragonsSpecializationFilters.Select(x => x.DeepClone())
);
}

protected bool Equals(CompositionFilters other)
{
return CoreProfessionFilters.SequenceEqual(other.CoreProfessionFilters)
&& HeartOfThornsSpecializationFilters.SequenceEqual(other.HeartOfThornsSpecializationFilters)
&& PathOfFireSpecializationFilters.SequenceEqual(other.PathOfFireSpecializationFilters);
&& PathOfFireSpecializationFilters.SequenceEqual(other.PathOfFireSpecializationFilters)
&& EndOfDragonsSpecializationFilters.SequenceEqual(other.EndOfDragonsSpecializationFilters);
}

public override bool Equals(object obj)
Expand Down Expand Up @@ -104,6 +118,11 @@ public override int GetHashCode()
{
code.Add(filter.GetHashCode());
}

foreach (var filter in EndOfDragonsSpecializationFilters)
{
code.Add(filter.GetHashCode());
}

return code.ToHashCode();
}
Expand Down
4 changes: 4 additions & 0 deletions ArcdpsLogManager/Logs/Updates/LogDataUpdater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ public class LogDataUpdater
new LogUpdate(log => log.ParsingVersion < new Version(1, 1, 2, 0)
&& log.Players.Any(x => x.Profession == Profession.None),
"Fixes broken profession detection for Core Guardians."),
new LogUpdate(log => log.ParsingVersion < new Version(1, 2, 0, 0)
&& log.GameBuild >= 118697
&& log.Players.Any(x => x.EliteSpecialization == EliteSpecialization.None),
"Add support for Virtuoso, Harbinger and Willbender."),
// When adding a new update, you need to increase the revision (last value) of the version in the .csproj file
// unless the version changes more significantly, in that case it can be reset to 0.
};
Expand Down
3 changes: 3 additions & 0 deletions ArcdpsLogManager/Resources.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public static Icon GetProgramIcon()
public static Image GetTinyIconSpellbreaker() => GetImage("Tango/Spellbreaker_tango_icon_20px.png");
public static Image GetTinyIconDragonhunter() => GetImage("Tango/Dragonhunter_tango_icon_20px.png");
public static Image GetTinyIconFirebrand() => GetImage("Tango/Firebrand_tango_icon_20px.png");
public static Image GetTinyIconWillbender() => GetImage("Tango/Willbender_tango_icon_20px.png");
public static Image GetTinyIconHerald() => GetImage("Tango/Herald_tango_icon_20px.png");
public static Image GetTinyIconRenegade() => GetImage("Tango/Renegade_tango_icon_20px.png");
public static Image GetTinyIconDruid() => GetImage("Tango/Druid_tango_icon_20px.png");
Expand All @@ -51,10 +52,12 @@ public static Icon GetProgramIcon()
public static Image GetTinyIconHolosmith() => GetImage("Tango/Holosmith_tango_icon_20px.png");
public static Image GetTinyIconReaper() => GetImage("Tango/Reaper_tango_icon_20px.png");
public static Image GetTinyIconScourge() => GetImage("Tango/Scourge_tango_icon_20px.png");
public static Image GetTinyIconHarbinger() => GetImage("Tango/Harbinger_tango_icon_20px.png");
public static Image GetTinyIconTempest() => GetImage("Tango/Tempest_tango_icon_20px.png");
public static Image GetTinyIconWeaver() => GetImage("Tango/Weaver_tango_icon_20px.png");
public static Image GetTinyIconChronomancer() => GetImage("Tango/Chronomancer_tango_icon_20px.png");
public static Image GetTinyIconMirage() => GetImage("Tango/Mirage_tango_icon_20px.png");
public static Image GetTinyIconVirtuoso() => GetImage("Tango/Virtuoso_tango_icon_20px.png");
// CATEGORIES
public static Image GetTinyIconRaid() => GetImage("ArenaNet/raid_icon_32px.png");
public static Image GetTinyIconFractals() => GetImage("ArenaNet/fractals_icon_32px.png");
Expand Down
32 changes: 31 additions & 1 deletion EVTCAnalytics/GameData/Characters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ public static class Characters
{Profession.Necromancer, EliteSpecialization.Scourge},
{Profession.Revenant, EliteSpecialization.Renegade}
};

private static readonly IReadOnlyDictionary<Profession, EliteSpecialization> EndOfDragonsSpecializationsByProfession =
new Dictionary<Profession, EliteSpecialization>
{
{Profession.Guardian, EliteSpecialization.Willbender},
{Profession.Warrior, EliteSpecialization.EoDWarrior},
{Profession.Engineer, EliteSpecialization.EoDEngineer},
{Profession.Ranger, EliteSpecialization.EoDRanger},
{Profession.Thief, EliteSpecialization.EoDThief},
{Profession.Elementalist, EliteSpecialization.EoDElementalist},
{Profession.Mesmer, EliteSpecialization.Virtuoso},
{Profession.Necromancer, EliteSpecialization.Harbinger},
{Profession.Revenant, EliteSpecialization.EoDRevenant}
};

/// <summary>
/// Ids of elite specializations as used internally in-game and publicly in the official API.
Expand All @@ -73,7 +87,10 @@ public static class Characters
{60, EliteSpecialization.Scourge},
{61, EliteSpecialization.Spellbreaker},
{62, EliteSpecialization.Firebrand},
{63, EliteSpecialization.Renegade}
{63, EliteSpecialization.Renegade},
{64, EliteSpecialization.Harbinger},
{65, EliteSpecialization.Willbender},
{66, EliteSpecialization.Virtuoso},
};

/// <summary>
Expand Down Expand Up @@ -104,6 +121,11 @@ public static EliteSpecialization GetPathOfFireEliteSpecialization(Profession pr
{
return PathOfFireSpecializationsByProfession[profession];
}

public static EliteSpecialization GetEndOfDragonsEliteSpecialization(Profession profession)
{
return EndOfDragonsSpecializationsByProfession[profession];
}

/// <summary>
/// Provides the base profession for an elite specialization.
Expand Down Expand Up @@ -133,6 +155,14 @@ public static Profession GetProfession(EliteSpecialization specialization)
return profession;
}
}

foreach (var (profession, spec) in EndOfDragonsSpecializationsByProfession)
{
if (specialization == spec)
{
return profession;
}
}

throw new NotSupportedException("Profession of elite specialization not found");
}
Expand Down
11 changes: 10 additions & 1 deletion EVTCAnalytics/Model/Agents/EliteSpecialization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ public enum EliteSpecialization
Scourge,
Spellbreaker,
Firebrand,
Renegade
Renegade,
Willbender,
EoDWarrior,
EoDEngineer,
EoDRanger,
EoDThief,
EoDElementalist,
Virtuoso,
Harbinger,
EoDRevenant,
}
}
11 changes: 11 additions & 0 deletions Tests/EVTCAnalytics.Tests/GameData/CharactersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ public void AllProfessionsHaveAPathOfFireEliteSpecialization()
Assert.AreNotEqual(EliteSpecialization.None, specialization);
}
}

[Test]
public void AllProfessionsHaveAnEndOfDragonsEliteSpecialization()
{
foreach (var profession in Characters.Professions)
{
EliteSpecialization specialization = EliteSpecialization.None;
Assert.DoesNotThrow(() => specialization = Characters.GetEndOfDragonsEliteSpecialization(profession));
Assert.AreNotEqual(EliteSpecialization.None, specialization);
}
}

[Test]
public void AllEliteSpecializationsHaveABaseProfession()
Expand Down

0 comments on commit 26b006e

Please sign in to comment.