diff --git a/src/DiabloInterface.Lib/ApplicationConfig.cs b/src/DiabloInterface.Lib/ApplicationConfig.cs index 3528dad8..43a49051 100644 --- a/src/DiabloInterface.Lib/ApplicationConfig.cs +++ b/src/DiabloInterface.Lib/ApplicationConfig.cs @@ -31,6 +31,7 @@ public class ApplicationConfig public bool DisplayResistances { get; set; } = true; public bool DisplayBaseStats { get; set; } = true; public bool DisplayRunes { get; set; } + public bool PossibleRuneUpg { get; set; } public bool DisplayRunesHorizontal { get; set; } = true; public bool DisplayRunesHighContrast { get; set; } = false; public bool DisplayAdvancedStats { get; set; } diff --git a/src/DiabloInterface/Gui/ConfigWindow.cs b/src/DiabloInterface/Gui/ConfigWindow.cs index f446e304..ae58d2ec 100644 --- a/src/DiabloInterface/Gui/ConfigWindow.cs +++ b/src/DiabloInterface/Gui/ConfigWindow.cs @@ -80,6 +80,7 @@ public class ConfigWindow : WsExCompositedForm private ComboBox comboBoxRunesOrientation; private CheckBox chkHighContrastRunes; private CheckBox chkDisplayRunes; + private CheckBox chkUpgRunes; private CheckBox chkShowRealValues; private Controls.RuneSettingsPage runeSettingsPage; private Button btnSetPlayersXColor; @@ -178,6 +179,7 @@ private void InitializeComponent() chkShowRealValues = new CheckBox(); chkHighContrastRunes = new CheckBox(); chkDisplayRunes = new CheckBox(); + chkUpgRunes = new CheckBox(); btnSetBackgroundColor = new Button(); button1 = new Button(); btnSetLevelColor = new Button(); @@ -492,6 +494,7 @@ private void InitializeComponent() groupBox1.Controls.Add(chkShowRealValues); groupBox1.Controls.Add(chkHighContrastRunes); groupBox1.Controls.Add(chkDisplayRunes); + groupBox1.Controls.Add(chkUpgRunes); groupBox1.Controls.Add(btnSetBackgroundColor); groupBox1.Controls.Add(button1); groupBox1.Controls.Add(btnSetLevelColor); @@ -598,6 +601,11 @@ private void InitializeComponent() chkDisplayRunes.Size = new Size(57, 17); chkDisplayRunes.Text = "Runes"; + chkUpgRunes.AutoSize = true; + chkUpgRunes.Location = new Point(175, 341); + chkUpgRunes.Size = new Size(57, 17); + chkUpgRunes.Text = "Possible rune upgrades"; + btnSetBackgroundColor.Location = new Point(339, 308); btnSetBackgroundColor.Size = new Size(136, 22); btnSetBackgroundColor.Text = "Background color"; @@ -802,6 +810,7 @@ bool IsDirty || config.DisplayBaseStats != chkDisplayBaseStats.Checked || config.DisplayAdvancedStats != chkDisplayAdvancedStats.Checked || config.DisplayRunes != chkDisplayRunes.Checked + || config.PossibleRuneUpg != chkUpgRunes.Checked || config.DisplayRunesHorizontal != (comboBoxRunesOrientation.SelectedIndex == 0) || config.DisplayRunesHighContrast != chkHighContrastRunes.Checked || config.DisplayDifficultyPercentages != chkDisplayDifficultyPercents.Checked @@ -917,6 +926,7 @@ void ReloadWithConfig(ApplicationConfig c) chkDisplayBaseStats.Checked = config.DisplayBaseStats; chkDisplayAdvancedStats.Checked = config.DisplayAdvancedStats; chkDisplayRunes.Checked = config.DisplayRunes; + chkUpgRunes.Checked = config.PossibleRuneUpg; comboBoxRunesOrientation.SelectedIndex = config.DisplayRunesHorizontal ? 0 : 1; chkDisplayDifficultyPercents.Checked = config.DisplayDifficultyPercentages; chkHighContrastRunes.Checked = config.DisplayRunesHighContrast; @@ -1012,6 +1022,7 @@ ApplicationConfig CopyModifiedConfig() config.DisplayExpansionClassic = chkDisplayExpansionClassic.Checked; config.DisplayRunes = chkDisplayRunes.Checked; + config.PossibleRuneUpg = chkUpgRunes.Checked; config.DisplayRunesHorizontal = comboBoxRunesOrientation.SelectedIndex == 0; config.DisplayRunesHighContrast = chkHighContrastRunes.Checked; config.DisplayLayoutHorizontal = comboBoxLayout.SelectedIndex == 0; diff --git a/src/DiabloInterface/Gui/Controls/AbstractLayout.cs b/src/DiabloInterface/Gui/Controls/AbstractLayout.cs index 0e4abba7..c5214b3b 100644 --- a/src/DiabloInterface/Gui/Controls/AbstractLayout.cs +++ b/src/DiabloInterface/Gui/Controls/AbstractLayout.cs @@ -246,11 +246,15 @@ void UpdateRuneDisplay(IEnumerable itemIds) var panel = RuneLayoutPanel; if (panel == null) return; + // Count number of items of each type. Dictionary itemClassCounts = itemIds .GroupBy(id => id) + .Where(id => id.Key > 609 && id.Key < 644) .ToDictionary(g => g.Key, g => g.Count()); + List missingRunes = new List(); // Store runes we are missing to see if we can use the cube to make them. + foreach (RuneDisplayElement runeElement in panel.Controls) { var itemClassId = (int)runeElement.Rune + 610; @@ -259,8 +263,89 @@ void UpdateRuneDisplay(IEnumerable itemIds) { itemClassCounts[itemClassId]--; runeElement.SetHaveRune(true); + + // No use to store an empty element. + if (itemClassCounts[itemClassId] == 0) itemClassCounts.Remove(itemClassId); + + continue; + } + + // Since you can't make El Rune we dont need to add it to the list. + if (itemClassId > 610) missingRunes.Add(itemClassId); + + } + + // If we don't miss any runes or the function is not enabled just return. + if (!di.configService.CurrentConfig.PossibleRuneUpg || missingRunes.Count == 0) return; + + // The list of runes we can make. + List canMake = new List(); + + bool upgrade = true; + while (upgrade) + { + + foreach (KeyValuePair kvp in itemClassCounts.ToArray()) + { + + int neededForUpg = (kvp.Key > 631) ? 2 : 3; // Um and higher runes only need two of the same rune to upgrade. + // bool needGem = (kvp.Key >= 620); // Amn and higher runes also need a gem to upgrade. + + int newRunes = (kvp.Value / neededForUpg); + + if (newRunes > 0) + { + + int newRune = kvp.Key + 1; + + // Remove the runes we have used up + itemClassCounts[kvp.Key] = itemClassCounts[kvp.Key] - (newRunes * neededForUpg); + if (itemClassCounts[kvp.Key] == 0) itemClassCounts.Remove(kvp.Key); + + // Do we need this rune? + while ((missingRunes.Contains(newRune) && newRunes > 0)) + { + canMake.Add(newRune); + missingRunes.Remove(newRune); + newRunes--; + } + + // Do we still have runes? + if (newRunes > 0) + { + // Add upgraded runes to the itemClassCount + if (itemClassCounts.ContainsKey(newRune)) + { itemClassCounts[newRune] = itemClassCounts[newRune] + newRunes; } + else + { itemClassCounts.Add(newRune, newRunes); } + } + } } + + // Have we filled our order? + if (missingRunes.Count == 0) break; + // Can we still upgrade runes? + upgrade = (itemClassCounts.Where(x => (x.Key < 631 && x.Value >= 3) || (x.Key > 630 && x.Value >= 2)).ToList().Count > 0); } + + if (canMake.Count > 0) + { + foreach (RuneDisplayElement runeElement in panel.Controls) + { + if (runeElement.haveRune) continue; + + int runeId = (int)runeElement.Rune + 610; + + if (canMake.Contains(runeId)) + { + runeElement.SetCanMakeRune(true); + canMake.Remove(runeId); + if (canMake.Count == 0) break; + } + + } + } + } protected Size MeasureText(string str, Control control) diff --git a/src/DiabloInterface/Gui/Controls/RuneDisplayElement.cs b/src/DiabloInterface/Gui/Controls/RuneDisplayElement.cs index ca57c310..ab1ccd26 100644 --- a/src/DiabloInterface/Gui/Controls/RuneDisplayElement.cs +++ b/src/DiabloInterface/Gui/Controls/RuneDisplayElement.cs @@ -30,10 +30,11 @@ public class RuneDisplayElement : UserControl public Rune Rune { get; private set; } - private bool haveRune = false; + public bool haveRune { get; private set; } = false; Bitmap image; Bitmap imageRed; + Bitmap imageMake; private PictureBox pictureBox1; @@ -48,6 +49,7 @@ public RuneDisplayElement(Rune rune, bool highContrast, bool removable, bool hav { image = sprite.Clone(new Rectangle(0, (int)Rune * RuneSize, RuneSize, RuneSize), sprite.PixelFormat); imageRed = sprite.Clone(new Rectangle(RuneSize, (int)Rune * RuneSize, RuneSize, RuneSize), sprite.PixelFormat); + imageMake = sprite.Clone(new Rectangle(RuneSize*2, (int)Rune * RuneSize, RuneSize, RuneSize), sprite.PixelFormat); } pictureBox1 = new PictureBox(); @@ -81,6 +83,7 @@ void OnDisposed(object sender, EventArgs eventArgs) image?.Dispose(); imageRed?.Dispose(); + imageMake?.Dispose(); } internal void SetHaveRune(bool haveRune) @@ -88,5 +91,10 @@ internal void SetHaveRune(bool haveRune) this.haveRune = haveRune; pictureBox1.BackgroundImage = haveRune ? image : imageRed; } + + internal void SetCanMakeRune(bool canMk) + { + pictureBox1.BackgroundImage = canMk ? imageMake : imageRed; + } } } diff --git a/src/DiabloInterface/Resources/Images/Runes/runes-high-contrast.png b/src/DiabloInterface/Resources/Images/Runes/runes-high-contrast.png index 6c13cc54..74d74ccf 100644 Binary files a/src/DiabloInterface/Resources/Images/Runes/runes-high-contrast.png and b/src/DiabloInterface/Resources/Images/Runes/runes-high-contrast.png differ diff --git a/src/DiabloInterface/Resources/Images/Runes/runes.png b/src/DiabloInterface/Resources/Images/Runes/runes.png index d8498c37..1061126f 100644 Binary files a/src/DiabloInterface/Resources/Images/Runes/runes.png and b/src/DiabloInterface/Resources/Images/Runes/runes.png differ