From 3bf3db80781db67aacaf573be1d9e212da6d626b Mon Sep 17 00:00:00 2001 From: Jackson <9527380+Jaksuhn@users.noreply.github.com> Date: Sat, 29 Jun 2024 11:56:49 +0200 Subject: [PATCH 1/4] submods --- ClickLib | 2 +- ECommons | 2 +- PunishLib | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ClickLib b/ClickLib index 63389e9..28a9e52 160000 --- a/ClickLib +++ b/ClickLib @@ -1 +1 @@ -Subproject commit 63389e90de9d6efe474d2fa4eb08744a324196ed +Subproject commit 28a9e526610a8a5420cd7259d42521396201e12c diff --git a/ECommons b/ECommons index febf904..096a19f 160000 --- a/ECommons +++ b/ECommons @@ -1 +1 @@ -Subproject commit febf9047bee31ca3022b657174f4a7925115dbb2 +Subproject commit 096a19feb68351bd438baa3b562c31f358bbd03d diff --git a/PunishLib b/PunishLib index 87c5303..51821ce 160000 --- a/PunishLib +++ b/PunishLib @@ -1 +1 @@ -Subproject commit 87c5303b97158a93568b0de19d887c9dc39bcdf7 +Subproject commit 51821ce7ee9251f1d1b7284168f7b53f5c0835ec From 1d10b5f02f0649220dcc8e14b41a17bfe46b836d Mon Sep 17 00:00:00 2001 From: Jackson <9527380+Jaksuhn@users.noreply.github.com> Date: Fri, 31 Oct 2025 10:36:58 +0000 Subject: [PATCH 2/4] Update ECommons --- ECommons | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ECommons b/ECommons index f5a0888..2d22a93 160000 --- a/ECommons +++ b/ECommons @@ -1 +1 @@ -Subproject commit f5a0888baa50a7903d8bd625cb838ce5bff8d459 +Subproject commit 2d22a93ec22b7b38051c0079eec8af6399c029dd From 07876da316fec7de42b0b772e62b7fc5619ff48c Mon Sep 17 00:00:00 2001 From: Jackson <9527380+Jaksuhn@users.noreply.github.com> Date: Fri, 2 Jan 2026 11:12:16 +0000 Subject: [PATCH 3/4] mvp cleanup couple null checks, cleaner atkvalues, using lifecycle instead of checking for addon on tick, and some regular cleanup --- PandorasBox/Features/UI/AutoVoteMvp.cs | 129 ++++++++++--------------- 1 file changed, 50 insertions(+), 79 deletions(-) diff --git a/PandorasBox/Features/UI/AutoVoteMvp.cs b/PandorasBox/Features/UI/AutoVoteMvp.cs index 484f437..608d00e 100644 --- a/PandorasBox/Features/UI/AutoVoteMvp.cs +++ b/PandorasBox/Features/UI/AutoVoteMvp.cs @@ -1,3 +1,9 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Dalamud.Bindings.ImGui; +using Dalamud.Game.Addon.Lifecycle; +using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; using Dalamud.Game.ClientState.Party; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling.Payloads; @@ -5,47 +11,34 @@ using ECommons.DalamudServices; using ECommons.GameHelpers; using FFXIVClientStructs.FFXIV.Client.Game; +using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Client.UI.Agent; using FFXIVClientStructs.FFXIV.Component.GUI; -using Dalamud.Bindings.ImGui; using PandorasBox.FeaturesSetup; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; namespace PandorasBox.Features.UI; public class AutoVoteMvp : Feature { public override string Name => "Auto-Commendation after Duty"; - public override string Description => "Automatically give a commendation to a random player in your party at the end of a duty."; - public override FeatureType FeatureType => FeatureType.UI; public override bool UseAutoConfig => false; - - private List PremadePartyID { get; set; } = new(); - - private List DeadPlayers { get; set; } = new(); - - private Dictionary DeathTracker { get; set; } = new(); + private List PremadePartyID { get; set; } = []; + private List DeadPlayers { get; set; } = []; + private Dictionary DeathTracker { get; set; } = []; public class Configs : FeatureConfig { public int Priority = 0; - public bool HideChat = false; - public bool ExcludeDeaths = false; - public int HowManyDeaths = 1; - public bool ResetOnWipe = false; } - public Configs Config { get; private set; } + public Configs Config { get; private set; } = null!; public override unsafe void Enable() { @@ -57,6 +50,7 @@ public override unsafe void Enable() } Config = LoadConfig() ?? new Configs(); Svc.Framework.Update += FrameworkUpdate; + Svc.AddonLifecycle.RegisterListener(AddonEvent.PostSetup, "BannerMIP", OnBannerSetup); Svc.Condition.ConditionChange += UpdatePartyCache; base.Enable(); } @@ -85,6 +79,7 @@ public override void Disable() { SaveConfig(Config); Svc.Framework.Update -= FrameworkUpdate; + Svc.AddonLifecycle.UnregisterListener(OnBannerSetup); Svc.Condition.ConditionChange -= UpdatePartyCache; base.Disable(); } @@ -94,13 +89,16 @@ private unsafe void FrameworkUpdate(IFramework framework) if (Player.Object == null) return; if (Svc.ClientState.IsPvP) return; CheckForDeadPartyMembers(); + } - var bannerWindow = (AtkUnitBase*)Svc.GameGui.GetAddonByName("BannerMIP", 1).Address; - if (bannerWindow == null) return; - + private unsafe void OnBannerSetup(AddonEvent type, AddonArgs args) + { + if (Svc.ClientState.IsPvP) return; + var atk = (AtkUnitBase*)args.Addon.Address; try { - VoteBanner(bannerWindow, ChoosePlayer(bannerWindow)); + if (ChoosePlayer(atk) is not -1 and var playerIndex) + VoteBanner((AtkUnitBase*)args.Addon.Address, playerIndex); } catch (Exception e) { @@ -110,58 +108,40 @@ private unsafe void FrameworkUpdate(IFramework framework) private void CheckForDeadPartyMembers() { - if (Svc.Party.Any()) + if (!Svc.Party.Any()) { - if (Config.ResetOnWipe && Svc.Party.All(x => x.GameObject?.IsDead == true)) - { - DeathTracker.Clear(); - } + DeathTracker.Clear(); + DeadPlayers.Clear(); + return; + } - foreach (var pm in Svc.Party) - { - if (pm.GameObject == null) continue; - if (pm.EntityId == Svc.Objects.LocalPlayer?.GameObjectId) continue; - if (pm.GameObject.IsDead) - { - if (DeadPlayers.Contains(pm.EntityId)) continue; - DeadPlayers.Add(pm.EntityId); - if (DeathTracker.ContainsKey(pm.EntityId)) - DeathTracker[pm.EntityId] += 1; - else - DeathTracker.TryAdd(pm.EntityId, 1); + if (Config.ResetOnWipe && Svc.Party.All(x => x.GameObject?.IsDead == true)) + DeathTracker.Clear(); - } + foreach (var pm in Svc.Party.Where(pm => pm.GameObject != null && pm.EntityId != Svc.Objects.LocalPlayer?.GameObjectId)) + { + if (pm.GameObject?.IsDead ?? false) + { + if (DeadPlayers.Contains(pm.EntityId)) continue; + DeadPlayers.Add(pm.EntityId); + if (DeathTracker.ContainsKey(pm.EntityId)) + DeathTracker[pm.EntityId] += 1; else - { - DeadPlayers.Remove(pm.EntityId); - } + DeathTracker.TryAdd(pm.EntityId, 1); } - } - else - { - DeathTracker.Clear(); - DeadPlayers.Clear(); + else + DeadPlayers.Remove(pm.EntityId); } } private unsafe int ChoosePlayer(AtkUnitBase* bannerWindow) { - var hud = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework.Instance() - ->GetUIModule()->GetAgentModule()->GetAgentHUD(); - + var hud = UIModule.Instance()->GetAgentModule()->GetAgentHUD(); if (hud == null) throw new Exception("HUD is empty!"); - foreach (var member in Svc.Party.Cast()) - { - var m2 = (FFXIVClientStructs.FFXIV.Client.Game.Group.PartyMember*)member.Address; - var name = m2->NameString; - Svc.Log.Debug($"{name} {m2->Flags.ToString("g")}"); - } - - var list = Svc.Party.Where(i => - i.EntityId != Player.Object.GameObjectId && i.GameObject != null && !PremadePartyID.Any(y => y == i.Name.GetText())) - .Select(PartyMember => (Math.Max(0, GetPartySlotIndex(PartyMember.EntityId, hud) - 1), PartyMember)) - .ToList(); + var list = Svc.Party.Where(i => i.EntityId != Svc.Objects.LocalPlayer?.GameObjectId && i.GameObject != null && !PremadePartyID.Any(y => y == i.Name.TextValue)) + .Select(PartyMember => (Math.Max(0, GetPartySlotIndex(PartyMember.EntityId, hud) - 1), PartyMember)) + .ToList(); if (!list.Any()) return -1; @@ -218,8 +198,8 @@ private unsafe int ChoosePlayer(AtkUnitBase* bannerWindow) if (!Config.HideChat) { var payload = PandoraPayload.Payloads.ToList(); - payload.AddRange(new List() - { + payload.AddRange( + [ new TextPayload("Commend given to "), voteTarget.member.ClassJob.Value!.Role switch { @@ -227,12 +207,11 @@ private unsafe int ChoosePlayer(AtkUnitBase* bannerWindow) 4 => new IconPayload(BitmapFontIcon.Healer), _ => new IconPayload(BitmapFontIcon.DPS), }, - new PlayerPayload(voteTarget.member.Name.TextValue, voteTarget.member.World.Value!.RowId), - }); + new PlayerPayload(voteTarget.member.Name.TextValue, voteTarget.member.World.Value.RowId), + ]); Svc.Chat.Print(new SeString(payload)); } - Svc.Log.Debug($"Commed {name} at index {i}, {bannerWindow->AtkValues[i - 14].UInt}"); return (int)bannerWindow->AtkValues[i - 14].UInt; } } @@ -260,18 +239,10 @@ private static T RandomPick(IEnumerable list) private static unsafe void VoteBanner(AtkUnitBase* bannerWindow, int index) { if (index == -1) return; - var atkValues = (AtkValue*)Marshal.AllocHGlobal(2 * sizeof(AtkValue)); - atkValues[0].Type = atkValues[1].Type = FFXIVClientStructs.FFXIV.Component.GUI.ValueType.Int; - atkValues[0].Int = 12; - atkValues[1].Int = index; - try - { - bannerWindow->FireCallback(2, atkValues); - } - finally - { - Marshal.FreeHGlobal(new nint(atkValues)); - } + var atkValues = stackalloc AtkValue[2]; + atkValues[0].SetInt(12); + atkValues[1].SetInt(index); + bannerWindow->FireCallback(2, atkValues); } protected override DrawConfigDelegate DrawConfigTree => (ref bool _) => From abf256ff265a0030cb7f17ef349abf709dac2634 Mon Sep 17 00:00:00 2001 From: Jackson <9527380+Jaksuhn@users.noreply.github.com> Date: Fri, 2 Jan 2026 11:13:31 +0000 Subject: [PATCH 4/4] add back debug --- PandorasBox/Features/UI/AutoVoteMvp.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/PandorasBox/Features/UI/AutoVoteMvp.cs b/PandorasBox/Features/UI/AutoVoteMvp.cs index 608d00e..dce4a3a 100644 --- a/PandorasBox/Features/UI/AutoVoteMvp.cs +++ b/PandorasBox/Features/UI/AutoVoteMvp.cs @@ -212,6 +212,7 @@ private unsafe int ChoosePlayer(AtkUnitBase* bannerWindow) Svc.Chat.Print(new SeString(payload)); } + Svc.Log.Debug($"Commed {name} at index {i}, {bannerWindow->AtkValues[i - 14].UInt}"); return (int)bannerWindow->AtkValues[i - 14].UInt; } }