using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; namespace D2Multi { /// Grid row binding for mission flags across difficulties. public sealed class CharacterMissionGridRow : INotifyPropertyChanged { readonly D2Character _character; public CharacterMissionGridRow(D2Character character) { _character = character ?? throw new ArgumentNullException(nameof(character)); D2CharacterMissionHelper.EnsureAllMissions(_character); } public D2Character Character => _character; public string Name { get => _character.Name ?? string.Empty; set { var v = value ?? string.Empty; if (string.Equals(_character.Name, v, StringComparison.Ordinal)) return; _character.Name = v; OnPropertyChanged(nameof(Name)); } } public string Class { get => _character.Class ?? string.Empty; set { var v = value ?? string.Empty; if (string.Equals(_character.Class, v, StringComparison.Ordinal)) return; _character.Class = v; OnPropertyChanged(nameof(Class)); } } public bool NormalA1 { get => Mission(D2Level.Normal).A1_Enpowered; set => SetA1(D2Level.Normal, value); } public bool NormalA5 { get => Mission(D2Level.Normal).A5_Socket; set => SetA5(D2Level.Normal, value); } public bool NightmareA1 { get => Mission(D2Level.Nightmare).A1_Enpowered; set => SetA1(D2Level.Nightmare, value); } public bool NightmareA5 { get => Mission(D2Level.Nightmare).A5_Socket; set => SetA5(D2Level.Nightmare, value); } public bool HellA1 { get => Mission(D2Level.Hell).A1_Enpowered; set => SetA1(D2Level.Hell, value); } public bool HellA5 { get => Mission(D2Level.Hell).A5_Socket; set => SetA5(D2Level.Hell, value); } /// Count of quest rewards not yet claimed (false = still available). public int MissionsAvailable { get { var n = 0; foreach (var lvl in AllLevels) { var m = Mission(lvl); if (!m.A1_Enpowered) n++; if (!m.A5_Socket) n++; } return n; } } static readonly D2Level[] AllLevels = { D2Level.Normal, D2Level.Nightmare, D2Level.Hell }; D2Mission Mission(D2Level level) => D2CharacterMissionHelper.GetMission(_character, level); void SetA1(D2Level level, bool value) { var m = Mission(level); if (m.A1_Enpowered == value) return; m.A1_Enpowered = value; OnPropertyChanged(PropForA1(level)); OnPropertyChanged(nameof(MissionsAvailable)); } void SetA5(D2Level level, bool value) { var m = Mission(level); if (m.A5_Socket == value) return; m.A5_Socket = value; OnPropertyChanged(PropForA5(level)); OnPropertyChanged(nameof(MissionsAvailable)); } static string PropForA1(D2Level level) { switch (level) { case D2Level.Normal: return nameof(NormalA1); case D2Level.Nightmare: return nameof(NightmareA1); default: return nameof(HellA1); } } static string PropForA5(D2Level level) { switch (level) { case D2Level.Normal: return nameof(NormalA5); case D2Level.Nightmare: return nameof(NightmareA5); default: return nameof(HellA5); } } public event PropertyChangedEventHandler PropertyChanged; void OnPropertyChanged(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); public static List FromAccount(D2Account account) { if (account?.Characters == null || account.Characters.Count == 0) return new List(); return account.Characters.Select(c => new CharacterMissionGridRow(c)).ToList(); } } static class D2CharacterMissionHelper { public static void EnsureAllMissions(D2Character character) { if (character.Missions == null) character.Missions = new List(); foreach (D2Level lvl in Enum.GetValues(typeof(D2Level))) { if (character.Missions.All(m => m.Level != lvl)) character.Missions.Add(new D2Mission { Level = lvl }); } } public static D2Mission GetMission(D2Character character, D2Level level) { EnsureAllMissions(character); return character.Missions.First(m => m.Level == level); } public static D2Character CreateNewCharacter() { var c = new D2Character { Name = "New character", Class = string.Empty, Missions = new List() }; EnsureAllMissions(c); return c; } } }