Actors and objects

This commit is contained in:
Raymond 2021-08-10 18:15:33 -04:00
parent a7d9673bed
commit 3a29603def
32 changed files with 1700 additions and 999 deletions

View file

@ -5,13 +5,12 @@ using System.Linq;
using System.Numerics;
using Dalamud.Game;
using Dalamud.Game.ClientState;
using Dalamud.Game.ClientState.Actors.Types;
using Dalamud.Game.ClientState.Actors.Types.NonPlayer;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.GamePad;
using Dalamud.Game.ClientState.JobGauge.Enums;
using Dalamud.Game.ClientState.JobGauge.Types;
using Dalamud.Game.ClientState.Objects.SubKinds;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Game.Gui.Addons;
using Dalamud.Game.Gui.Toast;
using Dalamud.Game.Text;
@ -37,8 +36,8 @@ namespace Dalamud.Interface.Internal.Windows
private string serverOpString;
private DataKind currentKind;
private bool drawActors = false;
private float maxActorDrawDistance = 20;
private bool drawCharas = false;
private float maxCharaDrawDistance = 20;
private string inputSig = string.Empty;
private IntPtr sigResult = IntPtr.Zero;
@ -50,6 +49,7 @@ namespace Dalamud.Interface.Internal.Windows
private IntPtr findAgentInterfacePtr;
private bool resolveGameData = false;
private bool resolveObjects = false;
private UIDebug addonInspector = null;
@ -89,10 +89,11 @@ namespace Dalamud.Interface.Internal.Windows
{
Server_OpCode,
Address,
Actor_Table,
Object_Table,
Fate_Table,
Font_Test,
Party_List,
Buddy_List,
Plugin_IPC,
Condition,
Gauge,
@ -127,18 +128,23 @@ namespace Dalamud.Interface.Internal.Windows
if (string.IsNullOrEmpty(dataKind))
return;
if (dataKind == "ai")
dataKind = "Addon Inspector";
dataKind = dataKind switch
{
"ai" => "Addon Inspector",
"at" => "Object Table", // Actor Table
"ot" => "Object Table",
_ => dataKind,
};
dataKind = dataKind.Replace(" ", string.Empty).ToLower();
var dataKinds = Enum.GetValues(typeof(DataKind))
var matched = Enum.GetValues(typeof(DataKind))
.Cast<DataKind>()
.Where(k => nameof(k).Replace("_", string.Empty).ToLower() == dataKind)
.ToList();
.Where(k => Enum.GetName(typeof(DataKind), k).Replace("_", string.Empty).ToLower() == dataKind)
.FirstOrDefault();
if (dataKinds.Count > 0)
if (matched != default)
{
this.currentKind = dataKinds.First();
this.currentKind = matched;
}
else
{
@ -189,8 +195,8 @@ namespace Dalamud.Interface.Internal.Windows
this.DrawAddress();
break;
case DataKind.Actor_Table:
this.DrawActorTable();
case DataKind.Object_Table:
this.DrawObjectTable();
break;
case DataKind.Fate_Table:
@ -205,6 +211,10 @@ namespace Dalamud.Interface.Internal.Windows
this.DrawPartyList();
break;
case DataKind.Buddy_List:
this.DrawBuddyList();
break;
case DataKind.Plugin_IPC:
this.DrawPluginIPC();
break;
@ -309,24 +319,18 @@ namespace Dalamud.Interface.Internal.Windows
}
}
private void DrawActorTable()
private void DrawObjectTable()
{
var stateString = string.Empty;
// LocalPlayer is null in a number of situations (at least with the current visible-actors list)
// which would crash here.
if (this.dalamud.ClientState.Actors.Length == 0)
{
ImGui.TextUnformatted("Data not ready.");
}
else if (this.dalamud.ClientState.LocalPlayer == null)
if (this.dalamud.ClientState.LocalPlayer == null)
{
ImGui.TextUnformatted("LocalPlayer null.");
}
else
{
stateString += $"FrameworkBase: {this.dalamud.Framework.Address.BaseAddress.ToInt64():X}\n";
stateString += $"ActorTableLen: {this.dalamud.ClientState.Actors.Length}\n";
stateString += $"ObjectTableLen: {this.dalamud.ClientState.Objects.Length}\n";
stateString += $"LocalPlayerName: {this.dalamud.ClientState.LocalPlayer.Name}\n";
stateString += $"CurrentWorldName: {(this.resolveGameData ? this.dalamud.ClientState.LocalPlayer.CurrentWorld.GameData.Name : this.dalamud.ClientState.LocalPlayer.CurrentWorld.Id.ToString())}\n";
stateString += $"HomeWorldName: {(this.resolveGameData ? this.dalamud.ClientState.LocalPlayer.HomeWorld.GameData.Name : this.dalamud.ClientState.LocalPlayer.HomeWorld.Id.ToString())}\n";
@ -336,29 +340,29 @@ namespace Dalamud.Interface.Internal.Windows
ImGui.TextUnformatted(stateString);
ImGui.Checkbox("Draw actors on screen", ref this.drawActors);
ImGui.SliderFloat("Draw Distance", ref this.maxActorDrawDistance, 2f, 40f);
ImGui.Checkbox("Draw characters on screen", ref this.drawCharas);
ImGui.SliderFloat("Draw Distance", ref this.maxCharaDrawDistance, 2f, 40f);
for (var i = 0; i < this.dalamud.ClientState.Actors.Length; i++)
for (var i = 0; i < this.dalamud.ClientState.Objects.Length; i++)
{
var actor = this.dalamud.ClientState.Actors[i];
var obj = this.dalamud.ClientState.Objects[i];
if (actor == null)
if (obj == null)
continue;
this.PrintActor(actor, i.ToString());
this.PrintGameObject(obj, i.ToString());
if (this.drawActors && this.dalamud.Framework.Gui.WorldToScreen(actor.Position, out var screenCoords))
if (this.drawCharas && this.dalamud.Framework.Gui.WorldToScreen(obj.Position, out var screenCoords))
{
// So, while WorldToScreen will return false if the point is off of game client screen, to
// to avoid performance issues, we have to manually determine if creating a window would
// produce a new viewport, and skip rendering it if so
var actorText = $"{actor.Address.ToInt64():X}:{actor.ActorId:X}[{i}] - {actor.ObjectKind} - {actor.Name}";
var objectText = $"{obj.Address.ToInt64():X}:{obj.ObjectId:X}[{i}] - {obj.ObjectKind} - {obj.Name}";
var screenPos = ImGui.GetMainViewport().Pos;
var screenSize = ImGui.GetMainViewport().Size;
var windowSize = ImGui.CalcTextSize(actorText);
var windowSize = ImGui.CalcTextSize(objectText);
// Add some extra safety padding
windowSize.X += ImGui.GetStyle().WindowPadding.X + 10;
@ -368,12 +372,12 @@ namespace Dalamud.Interface.Internal.Windows
screenCoords.Y + windowSize.Y > screenPos.Y + screenSize.Y)
continue;
if (actor.YalmDistanceX > this.maxActorDrawDistance)
if (obj.YalmDistanceX > this.maxCharaDrawDistance)
continue;
ImGui.SetNextWindowPos(new Vector2(screenCoords.X, screenCoords.Y));
ImGui.SetNextWindowBgAlpha(Math.Max(1f - (actor.YalmDistanceX / this.maxActorDrawDistance), 0.2f));
ImGui.SetNextWindowBgAlpha(Math.Max(1f - (obj.YalmDistanceX / this.maxCharaDrawDistance), 0.2f));
if (ImGui.Begin(
$"Actor{i}##ActorWindow{i}",
ImGuiWindowFlags.NoDecoration |
@ -384,7 +388,7 @@ namespace Dalamud.Interface.Internal.Windows
ImGuiWindowFlags.NoDocking |
ImGuiWindowFlags.NoFocusOnAppearing |
ImGuiWindowFlags.NoNav))
ImGui.Text(actorText);
ImGui.Text(objectText);
ImGui.End();
}
}
@ -453,30 +457,118 @@ namespace Dalamud.Interface.Internal.Windows
private void DrawPartyList()
{
var partyString = string.Empty;
ImGui.Checkbox("Resolve Actors", ref this.resolveObjects);
if (this.dalamud.ClientState.PartyList.Length == 0)
ImGui.Text($"GroupManager: {this.dalamud.ClientState.PartyList.GroupManagerAddress.ToInt64():X}");
ImGui.Text($"GroupList: {this.dalamud.ClientState.PartyList.GroupListAddress.ToInt64():X}");
ImGui.Text($"AllianceList: {this.dalamud.ClientState.PartyList.AllianceListAddress.ToInt64():X}");
ImGui.Text($"{this.dalamud.ClientState.PartyList.Length} Members");
for (var i = 0; i < this.dalamud.ClientState.PartyList.Length; i++)
{
ImGui.TextUnformatted("Data not ready.");
}
else
{
partyString += $"{this.dalamud.ClientState.PartyList.Count} Members\n";
for (var i = 0; i < this.dalamud.ClientState.PartyList.Count; i++)
var member = this.dalamud.ClientState.PartyList[i];
if (member == null)
{
var member = this.dalamud.ClientState.PartyList[i];
if (member == null)
{
partyString +=
$"[{i}] was null\n";
continue;
}
partyString +=
$"[{i}] {member.CharacterName} - {member.ObjectKind} - {member.Actor.ActorId}\n";
ImGui.Text($"[{i}] was null");
continue;
}
ImGui.TextUnformatted(partyString);
ImGui.Text($"[{i}] {member.Address.ToInt64():X} - {member.Name} - {member.GameObject.ObjectId}");
if (this.resolveObjects)
{
var actor = member.GameObject;
if (actor == null)
{
ImGui.Text("Actor was null");
}
else
{
this.PrintGameObject(actor, "-");
}
}
}
}
private void DrawBuddyList()
{
ImGui.Checkbox("Resolve Actors", ref this.resolveObjects);
ImGui.Text($"BuddyList: {this.dalamud.ClientState.BuddyList.BuddyListAddress.ToInt64():X}");
{
var member = this.dalamud.ClientState.BuddyList.CompanionBuddy;
if (member == null)
{
ImGui.Text("[Companion] null");
}
else
{
ImGui.Text($"[Companion] {member.Address.ToInt64():X} - {member.ObjectId} - {member.DataID}");
if (this.resolveObjects)
{
var actor = member.Actor;
if (actor == null)
{
ImGui.Text("Actor was null");
}
else
{
this.PrintGameObject(actor, "-");
}
}
}
}
{
var member = this.dalamud.ClientState.BuddyList.PetBuddy;
if (member == null)
{
ImGui.Text("[Pet] null");
}
else
{
ImGui.Text($"[Pet] {member.Address.ToInt64():X} - {member.ObjectId} - {member.DataID}");
if (this.resolveObjects)
{
var actor = member.Actor;
if (actor == null)
{
ImGui.Text("Actor was null");
}
else
{
this.PrintGameObject(actor, "-");
}
}
}
}
{
var count = this.dalamud.ClientState.BuddyList.Length;
if (count == 0)
{
ImGui.Text("[BattleBuddy] None present");
}
else
{
for (var i = 0; i < count; i++)
{
var member = this.dalamud.ClientState.BuddyList[i];
ImGui.Text($"[BattleBuddy] [{i}] {member.Address.ToInt64():X} - {member.ObjectId} - {member.DataID}");
if (this.resolveObjects)
{
var actor = member.Actor;
if (actor == null)
{
ImGui.Text("Actor was null");
}
else
{
this.PrintGameObject(actor, "-");
}
}
}
}
}
}
@ -783,26 +875,26 @@ namespace Dalamud.Interface.Internal.Windows
{
var targetMgr = this.dalamud.ClientState.Targets;
if (targetMgr.CurrentTarget != null)
if (targetMgr.Target != null)
{
this.PrintActor(targetMgr.CurrentTarget, "CurrentTarget");
Util.ShowObject(targetMgr.CurrentTarget);
this.PrintGameObject(targetMgr.Target, "CurrentTarget");
Util.ShowObject(targetMgr.Target);
}
if (targetMgr.FocusTarget != null)
this.PrintActor(targetMgr.FocusTarget, "FocusTarget");
this.PrintGameObject(targetMgr.FocusTarget, "FocusTarget");
if (targetMgr.MouseOverTarget != null)
this.PrintActor(targetMgr.MouseOverTarget, "MouseOverTarget");
this.PrintGameObject(targetMgr.MouseOverTarget, "MouseOverTarget");
if (targetMgr.PreviousTarget != null)
this.PrintActor(targetMgr.PreviousTarget, "PreviousTarget");
this.PrintGameObject(targetMgr.PreviousTarget, "PreviousTarget");
if (targetMgr.SoftTarget != null)
this.PrintActor(targetMgr.SoftTarget, "SoftTarget");
this.PrintGameObject(targetMgr.SoftTarget, "SoftTarget");
if (ImGui.Button("Clear CT"))
targetMgr.ClearCurrentTarget();
targetMgr.ClearTarget();
if (ImGui.Button("Clear FT"))
targetMgr.ClearFocusTarget();
@ -812,7 +904,7 @@ namespace Dalamud.Interface.Internal.Windows
if (localPlayer != null)
{
if (ImGui.Button("Set CT"))
targetMgr.SetCurrentTarget(localPlayer);
targetMgr.SetTarget(localPlayer);
if (ImGui.Button("Set FT"))
targetMgr.SetFocusTarget(localPlayer);
@ -924,9 +1016,10 @@ namespace Dalamud.Interface.Internal.Windows
$"L3 {resolve(GamepadButtons.L3)} " +
$"R3 {resolve(GamepadButtons.R3)} ");
}
#if DEBUG
ImGui.Text($"GamepadInput 0x{this.dalamud.ClientState.GamepadState.GamepadInputAddress.ToInt64():X}");
#if DEBUG
if (ImGui.IsItemHovered())
ImGui.SetMouseCursor(ImGuiMouseCursor.Hand);
@ -969,15 +1062,15 @@ namespace Dalamud.Interface.Internal.Windows
}
}
private void PrintActor(Actor actor, string tag)
private void PrintGameObject(GameObject actor, string tag)
{
var actorString =
$"{actor.Address.ToInt64():X}:{actor.ActorId:X}[{tag}] - {actor.ObjectKind} - {actor.Name} - X{actor.Position.X} Y{actor.Position.Y} Z{actor.Position.Z} D{actor.YalmDistanceX} R{actor.Rotation} - Target: {actor.TargetActorID:X}\n";
$"{actor.Address.ToInt64():X}:{actor.ObjectId:X}[{tag}] - {actor.ObjectKind} - {actor.Name} - X{actor.Position.X} Y{actor.Position.Y} Z{actor.Position.Z} D{actor.YalmDistanceX} R{actor.Rotation} - Target: {actor.TargetObjectId:X}\n";
if (actor is Npc npc)
actorString += $" DataId: {npc.BaseId} NameId:{npc.NameId}\n";
actorString += $" DataId: {npc.DataId} NameId:{npc.NameId}\n";
if (actor is Chara chara)
if (actor is Character chara)
{
actorString +=
$" Level: {chara.Level} ClassJob: {(this.resolveGameData ? chara.ClassJob.GameData.Name : chara.ClassJob.Id.ToString())} CHP: {chara.CurrentHp} MHP: {chara.MaxHp} CMP: {chara.CurrentMp} MMP: {chara.MaxMp}\n Customize: {BitConverter.ToString(chara.Customize).Replace("-", " ")} StatusFlags: {chara.StatusFlags}\n";