using DiabloInterface.D2; using DiabloInterface.D2.Readers; using DiabloInterface.D2.Struct; using DiabloInterface.Gui.Controls; using System; using System.Collections.Generic; using System.Drawing; using System.Text; using System.Windows.Forms; namespace DiabloInterface.Gui { public partial class DebugWindow : Form { /// <summary> /// Helper class for binding/unbinding autosplit event handlers. /// </summary> class AutosplitBinding { bool didUnbind; AutoSplit autoSplit; Action<AutoSplit> reachedHandler; Action<AutoSplit> resetHandler; public AutosplitBinding(AutoSplit autoSplit, Action<AutoSplit> reachedHandler, Action<AutoSplit> resetHandler) { this.autoSplit = autoSplit; this.reachedHandler = reachedHandler; this.resetHandler = resetHandler; this.autoSplit.Reached += reachedHandler; this.autoSplit.Reset += resetHandler; } ~AutosplitBinding() { Unbind(); } /// <summary> /// Unbding the autosplit handlers. /// </summary> public void Unbind() { if (didUnbind) return; didUnbind = true; autoSplit.Reached -= reachedHandler; autoSplit.Reset -= resetHandler; } } Label[] ActLabelsNormal; Label[] ActLabelsNightmare; Label[] ActLabelsHell; QuestDebugRow[,] QuestRowsNormal; QuestDebugRow[,] QuestRowsNightmare; QuestDebugRow[,] QuestRowsHell; List<AutosplitBinding> autoSplitBindings; public DebugWindow() { InitializeComponent(); } public void UpdateQuestData(ushort[] questBuffer, int difficulty) { QuestDebugRow[,] questRows; ushort questBits; switch (difficulty) { case 2: questRows = QuestRowsHell; break; case 1: questRows = QuestRowsNightmare; break; case 0: default: questRows = QuestRowsNormal; break; } for (int i = 0; i < questBuffer.Length; i++) { questBits = questBuffer[i]; D2QuestHelper.D2Quest q = D2QuestHelper.GetByQuestBufferIndex(i); if (q != null) { try { questRows[q.Act - 1, q.Quest - 1].Update(questBits); } catch (System.NullReferenceException ex) { // System.NullReferenceException } } } } void ClearAutoSplitBindings() { if (autoSplitBindings == null) { autoSplitBindings = new List<AutosplitBinding>(); } foreach (var binding in autoSplitBindings) { binding.Unbind(); } autoSplitBindings.Clear(); } public void UpdateAutosplits(List<AutoSplit> autoSplits) { // Unbinds and clears the binding list. ClearAutoSplitBindings(); int y = 0; autosplitPanel.Controls.Clear(); foreach (AutoSplit autoSplit in autoSplits) { Label splitLabel = new Label(); splitLabel.SetBounds(0, y, autosplitPanel.Bounds.Width, 16); splitLabel.Text = autoSplit.Name; splitLabel.ForeColor = autoSplit.IsReached ? Color.Green : Color.Red; Action<AutoSplit> splitReached = s => splitLabel.ForeColor = Color.Green; Action<AutoSplit> splitReset = s => splitLabel.ForeColor = Color.Red; // Bind autosplit events. var binding = new AutosplitBinding(autoSplit, splitReached, splitReset); autoSplitBindings.Add(binding); autosplitPanel.Controls.Add(splitLabel); y += 16; } } private void LoadQuests(Label[] actLabels, QuestDebugRow[,] questRows, TabPage tabPage) { int y; for (int i = 0; i < 5; i++) { y = i * 100 - (i > 3 ? 3 * 16 : 0); actLabels[i] = new Label(); actLabels[i].Text = "Act " + (i + 1); actLabels[i].Width = 80; actLabels[i].Location = new Point(20, y); tabPage.Controls.Add(actLabels[i]); for (int j = 0; j < (i == 3 ? 3 : 6); j++) { questRows[i, j] = new QuestDebugRow(D2QuestHelper.GetByActAndQuest(i + 1, j + 1)); questRows[i, j].Location = new Point(100, y + (j * 16)); tabPage.Controls.Add(questRows[i, j]); } } } private void DebugWindow_Load(object sender, EventArgs e) { ActLabelsNormal = new Label[5]; QuestRowsNormal = new QuestDebugRow[5, 6]; LoadQuests(ActLabelsNormal, QuestRowsNormal, tabPage1); ActLabelsNightmare = new Label[5]; QuestRowsNightmare = new QuestDebugRow[5, 6]; LoadQuests(ActLabelsNightmare, QuestRowsNightmare, tabPage2); ActLabelsHell = new Label[5]; QuestRowsHell = new QuestDebugRow[5, 6]; LoadQuests(ActLabelsHell, QuestRowsHell, tabPage3); } public void UpdateItemStats(ProcessMemoryReader r, D2MemoryTable memory, D2Unit pl) { InventoryReader inventoryReader = new InventoryReader(r, memory); UnitReader unitReader = new UnitReader(r, memory); // Build filter to get only equipped items. Func<D2ItemData, bool> filter = data => data.BodyLoc != BodyLocation.None; foreach (D2Unit item in inventoryReader.EnumerateInventory(filter)) { List<D2Stat> itemStats = unitReader.GetStats(item); if (itemStats == null) continue; StringBuilder statBuilder = new StringBuilder(); statBuilder.Append(inventoryReader.ItemReader.GetFullItemName(item)); statBuilder.Append("\n"); List<string> magicalStrings = inventoryReader.ItemReader.GetMagicalStrings(item); foreach (string str in magicalStrings) { statBuilder.Append(" "); statBuilder.Append(str); statBuilder.Append("\n"); } Control c = null; D2ItemData itemData = r.Read<D2ItemData>(item.UnitData); switch (itemData.BodyLoc) { case BodyLocation.Head: c = tabPageHead; break; case BodyLocation.Amulet: c = tabPageAmulet; break; case BodyLocation.BodyArmor: c = tabPageBody; break; case BodyLocation.PrimaryRight: c = tabPageWeaponRight; break; case BodyLocation.PrimaryLeft: c = tabPageWeaponLeft; break; case BodyLocation.RingRight: c = tabPageRingRight; break; case BodyLocation.RingLeft: c = tabPageRingLeft; break; //case BodyLocation.SecondaryLeft: c = tabPageRingRight; break; //case BodyLocation.SecondaryRight: c = tabPageRingLeft; break; case BodyLocation.Belt: c = tabPageBelt; break; case BodyLocation.Boots: c = tabPageFeet; break; case BodyLocation.Gloves: c = tabPageHand; break; } if (c != null) { if (c.Controls.Count == 0) { c.Invoke(new Action(delegate () { c.Controls.Add(new RichTextBox()); c.Controls[0].Dock = DockStyle.Fill; })); } c.Controls[0].Invoke(new Action(() => c.Controls[0].Text = statBuilder.ToString())); } } } } }