PartyDamage/Plugin.cs

225 lines
7.7 KiB
C#
Raw Normal View History

2024-07-25 03:49:23 +00:00
using System.Diagnostics;
using System.Globalization;
using System.Numerics;
using Dalamud.Game.Addon.Lifecycle;
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
using Dalamud.IoC;
using Dalamud.Memory;
2024-07-24 20:30:12 +00:00
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
2024-07-25 03:49:23 +00:00
using FFXIVClientStructs.FFXIV.Client.Game.Character;
2024-07-24 21:48:24 +00:00
using FFXIVClientStructs.FFXIV.Client.Game.Group;
2024-07-25 03:49:23 +00:00
using FFXIVClientStructs.FFXIV.Client.Game.UI;
using FFXIVClientStructs.FFXIV.Client.Graphics;
2024-07-24 21:48:24 +00:00
using FFXIVClientStructs.FFXIV.Client.UI;
2024-07-25 03:49:23 +00:00
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using FFXIVClientStructs.FFXIV.Client.UI.Info;
2024-07-24 21:48:24 +00:00
using FFXIVClientStructs.FFXIV.Component.GUI;
2024-07-25 03:49:23 +00:00
using ImGuiNET;
2024-07-24 20:30:12 +00:00
namespace PartyDamage;
public class Plugin : IDalamudPlugin {
[PluginService]
internal static IPluginLog Log { get; private set; }
2024-07-25 03:49:23 +00:00
[PluginService]
private IAddonLifecycle AddonLifecycle { get; init; }
2024-07-24 21:48:24 +00:00
[PluginService]
private IClientState ClientState { get; init; }
[PluginService]
private IFramework Framework { get; init; }
2024-07-25 03:49:23 +00:00
[PluginService]
private IPartyList PartyList { get; init; }
[PluginService]
private IDalamudPluginInterface Interface { get; init; }
2024-07-24 20:30:12 +00:00
private Client Client { get; }
public Plugin() {
this.Client = new Client();
2024-07-25 03:49:23 +00:00
this.AddonLifecycle!.RegisterListener(AddonEvent.PostUpdate, "_PartyList", this.UpdateList);
// this.Interface!.UiBuilder.Draw += this.Draw;
2024-07-24 20:30:12 +00:00
}
public void Dispose() {
2024-07-25 03:49:23 +00:00
// this.Interface.UiBuilder.Draw -= this.Draw;
this.AddonLifecycle.UnregisterListener(AddonEvent.PostUpdate, "_PartyList", this.UpdateList);
2024-07-24 20:30:12 +00:00
this.Client.Dispose();
}
2024-07-24 21:48:24 +00:00
2024-07-25 03:49:23 +00:00
private unsafe void Draw() {
if (this.Client.Data is not { } data) {
return;
}
var names = new List<string>();
foreach (var member in AgentHUD.Instance()->PartyMembers) {
if (member.Name == null) {
continue;
}
var name = MemoryHelper.ReadStringNullTerminated((nint) member.Name);
names.Add(name);
}
var list = (AddonPartyList*) AtkStage.Instance()->RaptureAtkUnitManager->GetAddonByName("_PartyList");
foreach (var combatant in data.Combatants.Values) {
var idx = combatant.Name == "YOU"
? 0
: names.IndexOf(combatant.Name);
if (idx == -1) {
continue;
}
var dpsText = combatant.EncDps switch {
float.NaN => "?",
float.PositiveInfinity => "0",
float.NegativeInfinity => "0",
< 1_000 => combatant.EncDps.ToString("N1"),
< 1_000_000 => $"{combatant.EncDps / 1_000:N1}K",
< 1_000_000_000 => $"{combatant.EncDps / 1_000_000:N1}M",
_ => combatant.EncDps.ToString("N1"),
};
var gauge = list->PartyMembers[idx].MPGaugeBar->OwnerNode;
var pos = new Vector2(
gauge->ScreenX + gauge->Width,
gauge->ScreenY + gauge->Height / 2f + 8
);
var size = ImGui.CalcTextSize(dpsText);
ImGui.GetBackgroundDrawList().AddRectFilled(
pos - Vector2.One * 2,
pos + size + Vector2.One * 2,
0xFF000000
);
ImGui.GetBackgroundDrawList().AddText(
pos,
0xFFFFFFFF,
dpsText
);
}
}
private Stopwatch Watch { get; } = Stopwatch.StartNew();
private unsafe void UpdateList(AddonEvent type, AddonArgs args) {
2024-07-24 21:48:24 +00:00
if (this.Client.Data is not { } data) {
return;
}
if (this.ClientState.LocalPlayer is not { } player) {
return;
}
2024-07-25 03:49:23 +00:00
var chara = (Character*) player.Address;
2024-07-24 21:48:24 +00:00
var list = (AddonPartyList*) AtkStage.Instance()->RaptureAtkUnitManager->GetAddonByName("_PartyList");
2024-07-25 03:49:23 +00:00
if (list->HoveredIndex >= 0 || list->TargetedIndex >= 0) {
return;
}
2024-07-24 21:48:24 +00:00
var names = new List<string>();
2024-07-25 03:49:23 +00:00
foreach (var member in AgentHUD.Instance()->PartyMembers) {
if (member.Name == null) {
continue;
}
// controller soft target not handled by hoveredindex above
if (chara->GetSoftTargetId() == member.EntityId) {
return;
}
2024-07-24 21:48:24 +00:00
2024-07-25 03:49:23 +00:00
var name = MemoryHelper.ReadStringNullTerminated((nint) member.Name);
names.Add(name);
2024-07-24 21:48:24 +00:00
}
var numPlayers = list->PartyMembers.Length;
foreach (var combatant in data.Combatants.Values) {
2024-07-24 22:04:52 +00:00
if (combatant.Name.EndsWith(" (YOU)")) {
var name = combatant.Name[..^6];
2024-07-25 03:49:23 +00:00
var chocoboName = UIState.Instance()->Buddy.CompanionInfo.NameString;
if (chocoboName == name) {
this.UpdateMember(list->Chocobo, data.Encounter, combatant);
2024-07-24 22:04:52 +00:00
continue;
}
}
2024-07-24 21:48:24 +00:00
var idx = combatant.Name == "YOU"
? 0
: names.IndexOf(combatant.Name);
if (idx == -1 || idx >= numPlayers) {
continue;
}
2024-07-25 03:49:23 +00:00
this.UpdateMember(list->PartyMembers[idx], data.Encounter, combatant);
2024-07-24 21:48:24 +00:00
}
}
2024-07-24 22:04:52 +00:00
2024-07-25 03:49:23 +00:00
private unsafe void UpdateMember(AddonPartyList.PartyListMemberStruct member, Encounter encounter, Combatant combatant) {
member.TargetGlow->ToggleVisibility(true);
member.TargetGlow->SetAlpha(128);
member.TargetGlow->SetScaleX(
encounter.EncDps == 0
? 0
: combatant.EncDps / encounter.EncDps
);
var left = (AtkTextNode*) member.MPGaugeBar->GetTextNodeById(2);
var right = (AtkTextNode*) member.MPGaugeBar->GetTextNodeById(3);
if (this.Watch.Elapsed.Seconds % 6 < 3) {
left->TextColor = new ByteColor {
RGBA = 0xFFFFFFFF,
};
right->TextColor = left->TextColor;
return;
}
left->TextColor = new ByteColor {
RGBA = 0xedffecff,
2024-07-24 22:04:52 +00:00
};
2024-07-25 03:49:23 +00:00
right->TextColor = left->TextColor;
if (combatant.EncDps == 0 || float.IsInfinity(combatant.EncDps) || float.IsNaN(combatant.EncDps)) {
left->SetText("0.");
right->SetText("00");
} else if (combatant.EncDps < 1_000) {
var dps = Math.Round(combatant.EncDps * 100).ToString(CultureInfo.InvariantCulture);
left->SetText($"{dps[..^2]}.");
right->SetText(dps[^2..]);
} else if (combatant.EncDps < 1_000_000) {
var dps = Math.Round(combatant.EncDps / 100).ToString(CultureInfo.InvariantCulture);
left->SetText($"{dps[..^1]}.");
right->SetText($"{dps[^1..]}K");
}
2024-07-24 22:04:52 +00:00
2024-07-25 03:49:23 +00:00
// var dpsText = combatant.EncDps switch {
// float.NaN => "?",
// float.PositiveInfinity => "0",
// float.NegativeInfinity => "0",
// < 1_000 => combatant.EncDps.ToString("N1"),
// < 1_000_000 => $"{combatant.EncDps / 1_000:N1}K",
// < 1_000_000_000 => $"{combatant.EncDps / 1_000_000:N1}M",
// _ => combatant.EncDps.ToString("N1"),
// };
// if (!member.CastingProgressBar->IsVisible()) {
// member.CastingActionName->ToggleVisibility(true);
// member.CastingActionName->SetText(dpsText);
// float x, y;
// member.CastingActionName->GetPositionFloat(&x, &y);
// member.CastingActionName->SetPositionFloat(200, 32);
// member.CastingActionName->AlignmentType = AlignmentType.Left;
// } else {
// member.CastingActionName->AlignmentType = AlignmentType.Right;
// member.CastingActionName->SetPositionFloat(0, 10);
// }
2024-07-24 22:04:52 +00:00
}
2024-07-24 20:30:12 +00:00
}