diff --git a/OverlayPlugin.Core/EventSources/BuiltinEventConfig.cs b/OverlayPlugin.Core/EventSources/BuiltinEventConfig.cs index f0a87dc5c..bde814991 100644 --- a/OverlayPlugin.Core/EventSources/BuiltinEventConfig.cs +++ b/OverlayPlugin.Core/EventSources/BuiltinEventConfig.cs @@ -12,6 +12,8 @@ public class BuiltinEventConfig public event EventHandler SortKeyChanged; public event EventHandler SortDescChanged; public event EventHandler UpdateDpsDuringImportChanged; + public event EventHandler EndEncounterAfterWipeChanged; + public event EventHandler EndEncounterOutOfCombatChanged; private int updateInterval; public int UpdateInterval { @@ -97,6 +99,40 @@ public bool UpdateDpsDuringImport } } + private bool endEncounterAfterWipe; + public bool EndEncounterAfterWipe + { + get + { + return this.endEncounterAfterWipe; + } + set + { + if (this.endEncounterAfterWipe != value) + { + this.endEncounterAfterWipe = value; + EndEncounterAfterWipeChanged?.Invoke(this, new EventArgs()); + } + } + } + + private bool endEncounterOutOfCombat; + public bool EndEncounterOutOfCombat + { + get + { + return this.endEncounterOutOfCombat; + } + set + { + if (this.endEncounterOutOfCombat != value) + { + this.endEncounterOutOfCombat = value; + EndEncounterOutOfCombatChanged?.Invoke(this, new EventArgs()); + } + } + } + // Data that overlays can save/load via event handlers. public Dictionary OverlayData = new Dictionary(); @@ -107,6 +143,8 @@ public BuiltinEventConfig() this.sortKey = "encdps"; this.sortDesc = true; this.updateDpsDuringImport = false; + this.endEncounterAfterWipe = false; + this.endEncounterOutOfCombat = false; } public static BuiltinEventConfig LoadConfig(IPluginConfig Config) @@ -142,6 +180,16 @@ public static BuiltinEventConfig LoadConfig(IPluginConfig Config) result.updateDpsDuringImport = value.ToObject(); } + if (obj.TryGetValue("EndEncounterAfterWipe", out value)) + { + result.endEncounterAfterWipe = value.ToObject(); + } + + if (obj.TryGetValue("EndEncounterOutOfCombat", out value)) + { + result.endEncounterOutOfCombat = value.ToObject(); + } + if (obj.TryGetValue("OverlayData", out value)) { result.OverlayData = value.ToObject>(); diff --git a/OverlayPlugin.Core/EventSources/BuiltinEventConfigPanel.Designer.cs b/OverlayPlugin.Core/EventSources/BuiltinEventConfigPanel.Designer.cs index 19d3a922a..da964dca2 100644 --- a/OverlayPlugin.Core/EventSources/BuiltinEventConfigPanel.Designer.cs +++ b/OverlayPlugin.Core/EventSources/BuiltinEventConfigPanel.Designer.cs @@ -29,105 +29,137 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BuiltinEventConfigPanel)); - this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - this.textEnmityInterval = new System.Windows.Forms.TextBox(); - this.label5 = new System.Windows.Forms.Label(); - this.comboSortKey = new System.Windows.Forms.ComboBox(); - this.label1 = new System.Windows.Forms.Label(); - this.label2 = new System.Windows.Forms.Label(); - this.textUpdateInterval = new System.Windows.Forms.TextBox(); - this.label3 = new System.Windows.Forms.Label(); - this.checkSortDesc = new System.Windows.Forms.CheckBox(); - this.label4 = new System.Windows.Forms.Label(); - this.cbUpdateDuringImport = new System.Windows.Forms.CheckBox(); - this.tableLayoutPanel1.SuspendLayout(); - this.SuspendLayout(); - // - // tableLayoutPanel1 - // - resources.ApplyResources(this.tableLayoutPanel1, "tableLayoutPanel1"); - this.tableLayoutPanel1.Controls.Add(this.textEnmityInterval, 1, 4); - this.tableLayoutPanel1.Controls.Add(this.label5, 0, 4); - this.tableLayoutPanel1.Controls.Add(this.comboSortKey, 1, 1); - this.tableLayoutPanel1.Controls.Add(this.label1, 0, 1); - this.tableLayoutPanel1.Controls.Add(this.label2, 0, 0); - this.tableLayoutPanel1.Controls.Add(this.textUpdateInterval, 1, 0); - this.tableLayoutPanel1.Controls.Add(this.label3, 0, 2); - this.tableLayoutPanel1.Controls.Add(this.checkSortDesc, 1, 2); - this.tableLayoutPanel1.Controls.Add(this.label4, 0, 3); - this.tableLayoutPanel1.Controls.Add(this.cbUpdateDuringImport, 1, 3); - this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - // - // textEnmityInterval - // - resources.ApplyResources(this.textEnmityInterval, "textEnmityInterval"); - this.textEnmityInterval.Name = "textEnmityInterval"; - this.textEnmityInterval.Leave += new System.EventHandler(this.TextEnmityInterval_Leave); - // - // label5 - // - resources.ApplyResources(this.label5, "label5"); - this.label5.Name = "label5"; - // - // comboSortKey - // - resources.ApplyResources(this.comboSortKey, "comboSortKey"); - this.comboSortKey.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.comboSortKey.FormattingEnabled = true; - this.comboSortKey.Name = "comboSortKey"; - // - // label1 - // - resources.ApplyResources(this.label1, "label1"); - this.label1.Name = "label1"; - // - // label2 - // - resources.ApplyResources(this.label2, "label2"); - this.label2.Name = "label2"; - // - // textUpdateInterval - // - resources.ApplyResources(this.textUpdateInterval, "textUpdateInterval"); - this.textUpdateInterval.Name = "textUpdateInterval"; - this.textUpdateInterval.Leave += new System.EventHandler(this.TextUpdateInterval_Leave); - // - // label3 - // - resources.ApplyResources(this.label3, "label3"); - this.label3.Name = "label3"; - // - // checkSortDesc - // - resources.ApplyResources(this.checkSortDesc, "checkSortDesc"); - this.checkSortDesc.Name = "checkSortDesc"; - this.checkSortDesc.UseVisualStyleBackColor = true; - this.checkSortDesc.CheckedChanged += new System.EventHandler(this.CheckSortDesc_CheckedChanged); - // - // label4 - // - resources.ApplyResources(this.label4, "label4"); - this.label4.Name = "label4"; - // - // cbUpdateDuringImport - // - resources.ApplyResources(this.cbUpdateDuringImport, "cbUpdateDuringImport"); - this.cbUpdateDuringImport.Name = "cbUpdateDuringImport"; - this.cbUpdateDuringImport.UseVisualStyleBackColor = true; - this.cbUpdateDuringImport.CheckedChanged += new System.EventHandler(this.cbUpdateDuringImport_CheckedChanged); - // - // BuiltinEventConfigPanel - // - resources.ApplyResources(this, "$this"); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.BackColor = System.Drawing.SystemColors.ControlLightLight; - this.Controls.Add(this.tableLayoutPanel1); - this.Name = "BuiltinEventConfigPanel"; - this.tableLayoutPanel1.ResumeLayout(false); - this.tableLayoutPanel1.PerformLayout(); - this.ResumeLayout(false); - + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BuiltinEventConfigPanel)); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.cbEndEncounterOutOfCombat = new System.Windows.Forms.CheckBox(); + this.cbEndEncounterAfterWipe = new System.Windows.Forms.CheckBox(); + this.label7 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.textEnmityInterval = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.comboSortKey = new System.Windows.Forms.ComboBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.textUpdateInterval = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.checkSortDesc = new System.Windows.Forms.CheckBox(); + this.label4 = new System.Windows.Forms.Label(); + this.cbUpdateDuringImport = new System.Windows.Forms.CheckBox(); + this.tableLayoutPanel1.SuspendLayout(); + this.SuspendLayout(); + // + // tableLayoutPanel1 + // + resources.ApplyResources(this.tableLayoutPanel1, "tableLayoutPanel1"); + this.tableLayoutPanel1.Controls.Add(this.cbEndEncounterOutOfCombat, 1, 6); + this.tableLayoutPanel1.Controls.Add(this.cbEndEncounterAfterWipe, 1, 5); + this.tableLayoutPanel1.Controls.Add(this.label7, 0, 6); + this.tableLayoutPanel1.Controls.Add(this.label6, 0, 5); + this.tableLayoutPanel1.Controls.Add(this.textEnmityInterval, 1, 4); + this.tableLayoutPanel1.Controls.Add(this.label5, 0, 4); + this.tableLayoutPanel1.Controls.Add(this.comboSortKey, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.label1, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.label2, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.textUpdateInterval, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.label3, 0, 2); + this.tableLayoutPanel1.Controls.Add(this.checkSortDesc, 1, 2); + this.tableLayoutPanel1.Controls.Add(this.label4, 0, 3); + this.tableLayoutPanel1.Controls.Add(this.cbUpdateDuringImport, 1, 3); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + // + // cbEndEncounterOutOfCombat + // + resources.ApplyResources(this.cbEndEncounterOutOfCombat, "cbEndEncounterOutOfCombat"); + this.cbEndEncounterOutOfCombat.Name = "cbEndEncounterOutOfCombat"; + this.cbEndEncounterOutOfCombat.UseVisualStyleBackColor = true; + this.cbEndEncounterOutOfCombat.CheckedChanged += new System.EventHandler(this.cbEndEncounterOutOfCombat_CheckedChanged); + // + // cbEndEncounterAfterWipe + // + resources.ApplyResources(this.cbEndEncounterAfterWipe, "cbEndEncounterAfterWipe"); + this.cbEndEncounterAfterWipe.Name = "cbEndEncounterAfterWipe"; + this.cbEndEncounterAfterWipe.UseVisualStyleBackColor = true; + this.cbEndEncounterAfterWipe.CheckedChanged += new System.EventHandler(this.cbEndEncounterAfterWipe_CheckedChanged); + // + // label7 + // + resources.ApplyResources(this.label7, "label7"); + this.label7.Name = "label7"; + // + // label6 + // + resources.ApplyResources(this.label6, "label6"); + this.label6.Name = "label6"; + // + // textEnmityInterval + // + resources.ApplyResources(this.textEnmityInterval, "textEnmityInterval"); + this.textEnmityInterval.Name = "textEnmityInterval"; + this.textEnmityInterval.Leave += new System.EventHandler(this.TextEnmityInterval_Leave); + // + // label5 + // + resources.ApplyResources(this.label5, "label5"); + this.label5.Name = "label5"; + // + // comboSortKey + // + resources.ApplyResources(this.comboSortKey, "comboSortKey"); + this.comboSortKey.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboSortKey.FormattingEnabled = true; + this.comboSortKey.Name = "comboSortKey"; + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // label2 + // + resources.ApplyResources(this.label2, "label2"); + this.label2.Name = "label2"; + // + // textUpdateInterval + // + resources.ApplyResources(this.textUpdateInterval, "textUpdateInterval"); + this.textUpdateInterval.Name = "textUpdateInterval"; + this.textUpdateInterval.Leave += new System.EventHandler(this.TextUpdateInterval_Leave); + // + // label3 + // + resources.ApplyResources(this.label3, "label3"); + this.label3.Name = "label3"; + // + // checkSortDesc + // + resources.ApplyResources(this.checkSortDesc, "checkSortDesc"); + this.checkSortDesc.Name = "checkSortDesc"; + this.checkSortDesc.UseVisualStyleBackColor = true; + this.checkSortDesc.CheckedChanged += new System.EventHandler(this.CheckSortDesc_CheckedChanged); + // + // label4 + // + resources.ApplyResources(this.label4, "label4"); + this.label4.Name = "label4"; + // + // cbUpdateDuringImport + // + resources.ApplyResources(this.cbUpdateDuringImport, "cbUpdateDuringImport"); + this.cbUpdateDuringImport.Name = "cbUpdateDuringImport"; + this.cbUpdateDuringImport.UseVisualStyleBackColor = true; + this.cbUpdateDuringImport.CheckedChanged += new System.EventHandler(this.cbUpdateDuringImport_CheckedChanged); + // + // BuiltinEventConfigPanel + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.Controls.Add(this.tableLayoutPanel1); + this.Name = "BuiltinEventConfigPanel"; + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.ResumeLayout(false); + } #endregion @@ -142,6 +174,10 @@ private void InitializeComponent() private System.Windows.Forms.Label label4; private System.Windows.Forms.CheckBox cbUpdateDuringImport; private System.Windows.Forms.TextBox textEnmityInterval; - private System.Windows.Forms.Label label5; - } + private System.Windows.Forms.Label label5; + private System.Windows.Forms.CheckBox cbEndEncounterOutOfCombat; + private System.Windows.Forms.CheckBox cbEndEncounterAfterWipe; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label6; + } } diff --git a/OverlayPlugin.Core/EventSources/BuiltinEventConfigPanel.cs b/OverlayPlugin.Core/EventSources/BuiltinEventConfigPanel.cs index 96eb9b44f..be7166734 100644 --- a/OverlayPlugin.Core/EventSources/BuiltinEventConfigPanel.cs +++ b/OverlayPlugin.Core/EventSources/BuiltinEventConfigPanel.cs @@ -49,6 +49,9 @@ private void SetupControlProperties() this.checkSortDesc.Checked = config.SortDesc; this.cbUpdateDuringImport.Checked = config.UpdateDpsDuringImport; + + this.cbEndEncounterAfterWipe.Checked = config.EndEncounterAfterWipe; + this.cbEndEncounterOutOfCombat.Checked = config.EndEncounterOutOfCombat; } private void SetupConfigEventHandlers() @@ -92,6 +95,22 @@ private void SetupConfigEventHandlers() this.cbUpdateDuringImport.Checked = config.UpdateDpsDuringImport; }); }; + + this.config.EndEncounterAfterWipeChanged += (o, e) => + { + this.InvokeIfRequired(() => + { + this.cbEndEncounterAfterWipe.Checked = config.EndEncounterAfterWipe; + }); + }; + + this.config.EndEncounterOutOfCombatChanged += (o, e) => + { + this.InvokeIfRequired(() => + { + this.cbEndEncounterOutOfCombat.Checked = config.EndEncounterOutOfCombat; + }); + }; } private void InvokeIfRequired(Action action) @@ -133,6 +152,16 @@ private void cbUpdateDuringImport_CheckedChanged(object sender, EventArgs e) this.config.UpdateDpsDuringImport = this.cbUpdateDuringImport.Checked; } + private void cbEndEncounterAfterWipe_CheckedChanged(object sender, EventArgs e) + { + this.config.EndEncounterAfterWipe = this.cbEndEncounterAfterWipe.Checked; + } + + private void cbEndEncounterOutOfCombat_CheckedChanged(object sender, EventArgs e) + { + this.config.EndEncounterOutOfCombat = this.cbEndEncounterOutOfCombat.Checked; + } + private void TextEnmityInterval_Leave(object sender, EventArgs e) { if (int.TryParse(this.textEnmityInterval.Text, out int value)) diff --git a/OverlayPlugin.Core/EventSources/BuiltinEventConfigPanel.resx b/OverlayPlugin.Core/EventSources/BuiltinEventConfigPanel.resx index 53de3096a..7f95c9e93 100644 --- a/OverlayPlugin.Core/EventSources/BuiltinEventConfigPanel.resx +++ b/OverlayPlugin.Core/EventSources/BuiltinEventConfigPanel.resx @@ -1,465 +1,597 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - 2 - - - - Fill - - - - 158, 107 - - - 490, 20 - - - 14 - - - textEnmityInterval - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tableLayoutPanel1 - - - 0 - - - True - - - Fill - - - NoControl - - - 3, 104 - - - 149, 26 - - - 13 - - - Enmity update interval (ms) - - - MiddleLeft - - - label5 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tableLayoutPanel1 - - - 1 - - - Fill - - - 158, 29 - - - 490, 21 - - - 5 - - - comboSortKey - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tableLayoutPanel1 - - - 2 - - - True - - - Fill - - - 3, 26 - - - 149, 26 - - - 6 - - - Sort By - - - MiddleLeft - - - label1 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tableLayoutPanel1 - - - 3 - - - True - - - Fill - - - 3, 0 - - - 149, 26 - - - 7 - - - DPS update interval seconds - - - MiddleLeft - - - label2 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tableLayoutPanel1 - - - 4 - - - Fill - - - 158, 3 - - - 490, 20 - - - 8 - - - textUpdateInterval - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tableLayoutPanel1 - - - 5 - - - True - - - Fill - - - 3, 52 - - - 149, 26 - - - 9 - - - Sort Descending (highest first) - - - MiddleLeft - - - label3 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tableLayoutPanel1 - - - 6 - - - True - - - Fill - - - 158, 55 - - - 490, 20 - - - 10 - - - checkSortDesc - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tableLayoutPanel1 - - - 7 - - - True - - - Fill - - - 3, 78 - - - 149, 26 - - - 11 - - - Update DPS during log import - - - MiddleLeft - - - label4 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tableLayoutPanel1 - - - 8 - - - True - - - Fill - - - 158, 81 - - - 490, 20 - - - 12 - - - cbUpdateDuringImport - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tableLayoutPanel1 - - - 9 - - - Fill - - - 0, 0 - - - 6 - - - 651, 388 - - - 1 - - - tableLayoutPanel1 - - - System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 0 - - - <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="textEnmityInterval" Row="4" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="label5" Row="4" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="comboSortKey" Row="1" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="label1" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="label2" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="textUpdateInterval" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="label3" Row="2" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="checkSortDesc" Row="2" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="label4" Row="3" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="cbUpdateDuringImport" Row="3" RowSpan="1" Column="1" ColumnSpan="1" /></Controls><Columns Styles="Absolute,155,Percent,100" /><Rows Styles="Absolute,26,Absolute,26,Absolute,26,Absolute,26,Absolute,26,Absolute,20" /></TableLayoutSettings> - - - True - - - 6, 13 - - - 651, 388 - - - BuiltinEventConfigPanel - - - System.Windows.Forms.UserControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 2 + + + True + + + + Fill + + + NoControl + + + + 208, 153 + + + 440, 14 + + + 18 + + + cbEndEncounterOutOfCombat + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 0 + + + True + + + Fill + + + NoControl + + + 208, 133 + + + 440, 14 + + + 17 + + + cbEndEncounterAfterWipe + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 1 + + + True + + + Fill + + + NoControl + + + 3, 150 + + + 199, 20 + + + 16 + + + End ACT encounter out of combat + + + MiddleLeft + + + label7 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 2 + + + True + + + Fill + + + NoControl + + + 3, 130 + + + 199, 20 + + + 15 + + + End ACT encounter after wipe + + + MiddleLeft + + + label6 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 3 + + + Fill + + + 208, 107 + + + 440, 20 + + + 14 + + + textEnmityInterval + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 4 + + + True + + + Fill + + + NoControl + + + 3, 104 + + + 199, 26 + + + 13 + + + Enmity update interval (ms) + + + MiddleLeft + + + label5 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 5 + + + Fill + + + 208, 29 + + + 440, 21 + + + 5 + + + comboSortKey + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 6 + + + True + + + Fill + + + 3, 26 + + + 199, 26 + + + 6 + + + Sort By + + + MiddleLeft + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 7 + + + True + + + Fill + + + 3, 0 + + + 199, 26 + + + 7 + + + DPS update interval seconds + + + MiddleLeft + + + label2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 8 + + + Fill + + + 208, 3 + + + 440, 20 + + + 8 + + + textUpdateInterval + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 9 + + + True + + + Fill + + + 3, 52 + + + 199, 26 + + + 9 + + + Sort Descending (highest first) + + + MiddleLeft + + + label3 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 10 + + + True + + + Fill + + + 208, 55 + + + 440, 20 + + + 10 + + + checkSortDesc + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 11 + + + True + + + Fill + + + 3, 78 + + + 199, 26 + + + 11 + + + Update DPS during log import + + + MiddleLeft + + + label4 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 12 + + + True + + + Fill + + + 208, 81 + + + 440, 20 + + + 12 + + + cbUpdateDuringImport + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 13 + + + Fill + + + 0, 0 + + + 8 + + + 651, 388 + + + 1 + + + tableLayoutPanel1 + + + System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="cbEndEncounterOutOfCombat" Row="6" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="cbEndEncounterAfterWipe" Row="5" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="label7" Row="6" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="label6" Row="5" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="textEnmityInterval" Row="4" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="label5" Row="4" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="comboSortKey" Row="1" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="label1" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="label2" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="textUpdateInterval" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="label3" Row="2" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="checkSortDesc" Row="2" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="label4" Row="3" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="cbUpdateDuringImport" Row="3" RowSpan="1" Column="1" ColumnSpan="1" /></Controls><Columns Styles="Absolute,205,Percent,100" /><Rows Styles="Absolute,26,Absolute,26,Absolute,26,Absolute,26,Absolute,26,Absolute,20,Absolute,20,Absolute,20" /></TableLayoutSettings> + + + True + + + 6, 13 + + + 651, 388 + + + BuiltinEventConfigPanel + + + System.Windows.Forms.UserControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + \ No newline at end of file diff --git a/OverlayPlugin.Core/EventSources/EnmityEventSource.cs b/OverlayPlugin.Core/EventSources/EnmityEventSource.cs index 260b5b91c..25fe6db46 100644 --- a/OverlayPlugin.Core/EventSources/EnmityEventSource.cs +++ b/OverlayPlugin.Core/EventSources/EnmityEventSource.cs @@ -1,9 +1,11 @@ +using Advanced_Combat_Tracker; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; +using System.Threading.Tasks; using System.Windows.Forms; namespace RainbowMage.OverlayPlugin.EventSources @@ -20,6 +22,21 @@ public class EnmityEventSource : EventSourceBase private const string EnmityTargetDataEvent = "EnmityTargetData"; // All of the mobs with aggro on the player. Equivalent of the sidebar aggro list in game. private const string EnmityAggroListEvent = "EnmityAggroList"; + // State of combat, both act and game. + private const string InCombatEvent = "InCombat"; + + [Serializable] + internal class InCombatDataObject { + public string type = InCombatEvent; + public bool inACTCombat = false; + public bool inGameCombat = false; + }; + InCombatDataObject sentCombatData; + + // Unlike "sentCombatData" which caches sent data, this variable caches each update. + private bool lastInGameCombat = false; + private const int endEncounterOutOfCombatDelayMs = 5000; + CancellationTokenSource endEncounterToken; public BuiltinEventConfig Config { get; set; } @@ -51,6 +68,7 @@ public EnmityEventSource(ILogger logger) : base(logger) RegisterEventTypes(new List { EnmityTargetDataEvent, EnmityAggroListEvent, }); + RegisterCachedEventType(InCombatEvent); } public override Control CreateConfigControl() @@ -117,6 +135,43 @@ protected override void Update() memoryValid = true; } + // Handle optional "end encounter of combat" logic. + bool inGameCombat = memory.GetInCombat(); + // If we've transitioned to being out of combat, start a delayed task to end the ACT encounter. + if (Config.EndEncounterOutOfCombat && lastInGameCombat && !inGameCombat) + { + endEncounterToken = new CancellationTokenSource(); + Task.Run(async delegate + { + await Task.Delay(endEncounterOutOfCombatDelayMs, endEncounterToken.Token); + ActGlobals.oFormActMain.Invoke((Action)(() => + { + ActGlobals.oFormActMain.EndCombat(true); + })); + }); + } + // If combat starts again, cancel any outstanding tasks to stop the ACT encounter. + // If the task has already run, this will not do anything. + if (inGameCombat && endEncounterToken != null) + { + endEncounterToken.Cancel(); + endEncounterToken = null; + } + lastInGameCombat = inGameCombat; + + if (HasSubscriber(InCombatEvent)) + { + bool inACTCombat = Advanced_Combat_Tracker.ActGlobals.oFormActMain.InCombat; + if (sentCombatData == null || sentCombatData.inACTCombat != inACTCombat || sentCombatData.inGameCombat != inGameCombat) + { + if (sentCombatData == null) + sentCombatData = new InCombatDataObject(); + sentCombatData.inACTCombat = inACTCombat; + sentCombatData.inGameCombat = inGameCombat; + this.DispatchAndCacheEvent(JObject.FromObject(sentCombatData)); + } + } + bool targetData = HasSubscriber(EnmityTargetDataEvent); bool aggroList = HasSubscriber(EnmityAggroListEvent); if (!targetData && !aggroList) diff --git a/OverlayPlugin.Core/EventSources/EnmityMemory50.cs b/OverlayPlugin.Core/EventSources/EnmityMemory50.cs index 3aa714690..71f74d612 100644 --- a/OverlayPlugin.Core/EventSources/EnmityMemory50.cs +++ b/OverlayPlugin.Core/EventSources/EnmityMemory50.cs @@ -16,15 +16,19 @@ public class EnmityMemory50 : EnmityMemory private IntPtr targetAddress = IntPtr.Zero; private IntPtr enmityAddress = IntPtr.Zero; private IntPtr aggroAddress = IntPtr.Zero; + private IntPtr inCombatAddress = IntPtr.Zero; private const string charmapSignature = "488b420848c1e8033da701000077248bc0488d0d"; private const string targetSignature = "41bc000000e041bd01000000493bc47555488d0d"; private const string enmitySignature = "83f9ff7412448b048e8bd3488d0d"; + private const string inCombatSignature = "84c07425450fb6c7488d0d"; // Offsets from the signature to find the correct address. private const int charmapSignatureOffset = 0; private const int targetSignatureOffset = 192; private const int enmitySignatureOffset = -4648; + private const int inCombatSignatureBaseOffset = 0; + private const int inCombatSignatureOffsetOffset = 5; // Offset from the enmityAddress to find various enmity data structures. private const int aggroEnmityOffset = 0x908; @@ -52,6 +56,7 @@ private void ResetPointers(object sender, EventArgs _) targetAddress = IntPtr.Zero; enmityAddress = IntPtr.Zero; aggroAddress = IntPtr.Zero; + inCombatAddress = IntPtr.Zero; } private bool HasValidPointers() @@ -64,6 +69,8 @@ private bool HasValidPointers() return false; if (aggroAddress == IntPtr.Zero) return false; + if (inCombatAddress == IntPtr.Zero) + return false; return true; } @@ -137,9 +144,29 @@ private bool GetPointerAddress() success = false; } + /// IN COMBAT + // The in combat address is set from a combination of two values, a base address and an offset. + // They are found adjacent to the same signature, but at different offsets. + var baseList = memory.SigScan(inCombatSignature, inCombatSignatureBaseOffset, bRIP); + // SigScan returns pointers, but the offset is a 32-bit immediate value. Do not use RIP. + var offsetList = memory.SigScan(inCombatSignature, inCombatSignatureOffsetOffset, false); + if (baseList != null && baseList.Count > 0 && offsetList != null && offsetList.Count > 0) + { + var baseAddress = baseList[0]; + var offset = (int)(((UInt64)offsetList[0]) & 0xFFFFFFFF); + inCombatAddress = IntPtr.Add(baseAddress, offset); + } + else + { + inCombatAddress = IntPtr.Zero; + fail.Add(nameof(inCombatAddress)); + success = false; + } + logger.Log(LogLevel.Debug, "charmapAddress: 0x{0:X}", charmapAddress.ToInt64()); logger.Log(LogLevel.Debug, "enmityAddress: 0x{0:X}", enmityAddress.ToInt64()); logger.Log(LogLevel.Debug, "targetAddress: 0x{0:X}", targetAddress.ToInt64()); + logger.Log(LogLevel.Debug, "inCombatAddress: 0x{0:X}", inCombatAddress.ToInt64()); Combatant c = GetSelfCombatant(); if (c != null) { @@ -537,5 +564,13 @@ public unsafe EffectEntry GetEffectEntryFromBytes(byte[] source, int num = 0) return effectEntry; } } + + public override bool GetInCombat() + { + if (inCombatAddress == IntPtr.Zero) + return false; + byte[] bytes = memory.Read8(inCombatAddress, 1); + return bytes[0] != 0; + } } } \ No newline at end of file diff --git a/OverlayPlugin.Core/EventSources/EnmityMemory52.cs b/OverlayPlugin.Core/EventSources/EnmityMemory52.cs index 572fd026f..22004d285 100644 --- a/OverlayPlugin.Core/EventSources/EnmityMemory52.cs +++ b/OverlayPlugin.Core/EventSources/EnmityMemory52.cs @@ -16,17 +16,21 @@ public class EnmityMemory52 : EnmityMemory private IntPtr targetAddress = IntPtr.Zero; private IntPtr enmityAddress = IntPtr.Zero; private IntPtr aggroAddress = IntPtr.Zero; + private IntPtr inCombatAddress = IntPtr.Zero; private const string charmapSignature = "48c1ea0381faa7010000????8bc2488d0d"; private const string targetSignatureH0 = "83E901740832C04883C4205BC3488D0D"; // pre hotfix private const string targetSignatureH1 = "e8f2652f0084c00f8591010000488d0d"; // post hotfix 1 private const string enmitySignature = "83f9ff7412448b048e8bd3488d0d"; + private const string inCombatSignature = "84c07425450fb6c7488d0d"; // Offsets from the signature to find the correct address. private const int charmapSignatureOffset = 0; private const int targetSignatureOffset = 0; private const int enmitySignatureOffset = -2608; private const int aggroEnmityOffset = -2336; + private const int inCombatSignatureBaseOffset = 0; + private const int inCombatSignatureOffsetOffset = 5; // Offsets from the targetAddress to find the correct target type. private const int targetTargetOffset = 176; @@ -51,6 +55,7 @@ private void ResetPointers(object sender, EventArgs _) targetAddress = IntPtr.Zero; enmityAddress = IntPtr.Zero; aggroAddress = IntPtr.Zero; + inCombatAddress = IntPtr.Zero; } private bool HasValidPointers() @@ -63,6 +68,8 @@ private bool HasValidPointers() return false; if (aggroAddress == IntPtr.Zero) return false; + if (inCombatAddress == IntPtr.Zero) + return false; return true; } @@ -140,10 +147,30 @@ private bool GetPointerAddress() success = false; } + /// IN COMBAT + // The in combat address is set from a combination of two values, a base address and an offset. + // They are found adjacent to the same signature, but at different offsets. + var baseList = memory.SigScan(inCombatSignature, inCombatSignatureBaseOffset, bRIP); + // SigScan returns pointers, but the offset is a 32-bit immediate value. Do not use RIP. + var offsetList = memory.SigScan(inCombatSignature, inCombatSignatureOffsetOffset, false); + if (baseList != null && baseList.Count > 0 && offsetList != null && offsetList.Count > 0) + { + var baseAddress = baseList[0]; + var offset = (int)(((UInt64)offsetList[0]) & 0xFFFFFFFF); + inCombatAddress = IntPtr.Add(baseAddress, offset); + } + else + { + inCombatAddress = IntPtr.Zero; + fail.Add(nameof(inCombatAddress)); + success = false; + } + logger.Log(LogLevel.Debug, "charmapAddress: 0x{0:X}", charmapAddress.ToInt64()); logger.Log(LogLevel.Debug, "enmityAddress: 0x{0:X}", enmityAddress.ToInt64()); logger.Log(LogLevel.Debug, "aggroAddress: 0x{0:X}", aggroAddress.ToInt64()); logger.Log(LogLevel.Debug, "targetAddress: 0x{0:X}", targetAddress.ToInt64()); + logger.Log(LogLevel.Debug, "inCombatAddress: 0x{0:X}", inCombatAddress.ToInt64()); Combatant c = GetSelfCombatant(); if (c != null) { @@ -591,5 +618,13 @@ public unsafe EffectEntry GetEffectEntryFromBytes(byte[] source, int num = 0) return effectEntry; } } + + public override bool GetInCombat() + { + if (inCombatAddress == IntPtr.Zero) + return false; + byte[] bytes = memory.Read8(inCombatAddress, 1); + return bytes[0] != 0; + } } } diff --git a/OverlayPlugin.Core/EventSources/EnmityMemoryCommon.cs b/OverlayPlugin.Core/EventSources/EnmityMemoryCommon.cs index 62e5263c5..aac9834f8 100644 --- a/OverlayPlugin.Core/EventSources/EnmityMemoryCommon.cs +++ b/OverlayPlugin.Core/EventSources/EnmityMemoryCommon.cs @@ -102,5 +102,6 @@ public abstract class EnmityMemory abstract public List GetCombatantList(); abstract public List GetEnmityEntryList(List combatantList); abstract public unsafe List GetAggroList(List combatantList); + abstract public bool GetInCombat(); } } diff --git a/OverlayPlugin.Core/EventSources/MiniParseEventSource.cs b/OverlayPlugin.Core/EventSources/MiniParseEventSource.cs index 316d9dc42..725272d7a 100644 --- a/OverlayPlugin.Core/EventSources/MiniParseEventSource.cs +++ b/OverlayPlugin.Core/EventSources/MiniParseEventSource.cs @@ -317,6 +317,19 @@ private void LogLineHandler(bool isImport, LogLineEventArgs args) charName, })); break; + + case LogMessageType.Network6D: + if (!Config.EndEncounterAfterWipe) break; + if (line.Length < 4) break; + + if (line[3] == "40000010") + { + ActGlobals.oFormActMain.Invoke((Action)(() => + { + ActGlobals.oFormActMain.EndCombat(true); + })); + } + break; } DispatchEvent(JObject.FromObject(new