feat: begin adding phantom characters
This commit is contained in:
parent
c9f9ea7e3d
commit
288ac50a6b
@ -2,6 +2,7 @@ using Dalamud.IoC;
|
|||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using OrangeGuidanceTomestone.MiniPenumbra;
|
using OrangeGuidanceTomestone.MiniPenumbra;
|
||||||
|
using OrangeGuidanceTomestone.Util;
|
||||||
|
|
||||||
namespace OrangeGuidanceTomestone;
|
namespace OrangeGuidanceTomestone;
|
||||||
|
|
||||||
@ -45,6 +46,7 @@ public class Plugin : IDalamudPlugin {
|
|||||||
internal Vfx Vfx { get; }
|
internal Vfx Vfx { get; }
|
||||||
internal PluginUi Ui { get; }
|
internal PluginUi Ui { get; }
|
||||||
internal Messages Messages { get; }
|
internal Messages Messages { get; }
|
||||||
|
internal ActorManager ActorManager { get; }
|
||||||
internal VfxReplacer VfxReplacer { get; }
|
internal VfxReplacer VfxReplacer { get; }
|
||||||
internal Commands Commands { get; }
|
internal Commands Commands { get; }
|
||||||
internal Pinger Pinger { get; }
|
internal Pinger Pinger { get; }
|
||||||
@ -57,6 +59,7 @@ public class Plugin : IDalamudPlugin {
|
|||||||
this.Config = this.Interface!.GetPluginConfig() as Configuration ?? new Configuration();
|
this.Config = this.Interface!.GetPluginConfig() as Configuration ?? new Configuration();
|
||||||
this.Vfx = new Vfx(this);
|
this.Vfx = new Vfx(this);
|
||||||
this.Messages = new Messages(this);
|
this.Messages = new Messages(this);
|
||||||
|
this.ActorManager = new ActorManager(this);
|
||||||
this.Ui = new PluginUi(this);
|
this.Ui = new PluginUi(this);
|
||||||
this.VfxReplacer = new VfxReplacer(this);
|
this.VfxReplacer = new VfxReplacer(this);
|
||||||
this.Commands = new Commands(this);
|
this.Commands = new Commands(this);
|
||||||
@ -72,6 +75,7 @@ public class Plugin : IDalamudPlugin {
|
|||||||
this.Commands.Dispose();
|
this.Commands.Dispose();
|
||||||
this.VfxReplacer.Dispose();
|
this.VfxReplacer.Dispose();
|
||||||
this.Ui.Dispose();
|
this.Ui.Dispose();
|
||||||
|
this.ActorManager.Dispose();
|
||||||
this.Messages.Dispose();
|
this.Messages.Dispose();
|
||||||
this.Vfx.Dispose();
|
this.Vfx.Dispose();
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ using Dalamud.Interface;
|
|||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using OrangeGuidanceTomestone.Helpers;
|
using OrangeGuidanceTomestone.Helpers;
|
||||||
|
using OrangeGuidanceTomestone.Util;
|
||||||
|
|
||||||
namespace OrangeGuidanceTomestone.Ui;
|
namespace OrangeGuidanceTomestone.Ui;
|
||||||
|
|
||||||
@ -11,6 +12,11 @@ internal class Viewer {
|
|||||||
|
|
||||||
internal bool Visible;
|
internal bool Visible;
|
||||||
|
|
||||||
|
internal delegate void MessageViewDelegate(Message? message);
|
||||||
|
internal event MessageViewDelegate View;
|
||||||
|
|
||||||
|
private Guid _lastViewed = Guid.Empty;
|
||||||
|
|
||||||
private int _idx;
|
private int _idx;
|
||||||
|
|
||||||
internal Viewer(Plugin plugin) {
|
internal Viewer(Plugin plugin) {
|
||||||
@ -19,6 +25,11 @@ internal class Viewer {
|
|||||||
|
|
||||||
internal void Draw() {
|
internal void Draw() {
|
||||||
if (!this.Visible) {
|
if (!this.Visible) {
|
||||||
|
if (this._lastViewed != Guid.Empty) {
|
||||||
|
this.View(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._lastViewed = Guid.Empty;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,8 +39,8 @@ internal class Viewer {
|
|||||||
flags |= this.Plugin.Config.ClickThroughViewer ? ImGuiWindowFlags.NoInputs : ImGuiWindowFlags.None;
|
flags |= this.Plugin.Config.ClickThroughViewer ? ImGuiWindowFlags.NoInputs : ImGuiWindowFlags.None;
|
||||||
ImGui.SetNextWindowSize(new Vector2(350, 175), ImGuiCond.FirstUseEver);
|
ImGui.SetNextWindowSize(new Vector2(350, 175), ImGuiCond.FirstUseEver);
|
||||||
ImGui.SetNextWindowBgAlpha(this.Plugin.Config.ViewerOpacity / 100.0f);
|
ImGui.SetNextWindowBgAlpha(this.Plugin.Config.ViewerOpacity / 100.0f);
|
||||||
|
using var end = new OnDispose(ImGui.End);
|
||||||
if (!ImGui.Begin("Messages", ref this.Visible, flags)) {
|
if (!ImGui.Begin("Messages", ref this.Visible, flags)) {
|
||||||
ImGui.End();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +58,7 @@ internal class Viewer {
|
|||||||
ImGui.TextUnformatted("No nearby messages");
|
ImGui.TextUnformatted("No nearby messages");
|
||||||
}
|
}
|
||||||
|
|
||||||
goto End;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._idx >= nearby.Count) {
|
if (this._idx >= nearby.Count) {
|
||||||
@ -55,9 +66,11 @@ internal class Viewer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!ImGui.BeginTable("##viewer-table", 3)) {
|
if (!ImGui.BeginTable("##viewer-table", 3)) {
|
||||||
goto End;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using var endTable = new OnDispose(ImGui.EndTable);
|
||||||
|
|
||||||
ImGui.TableSetupColumn("##prev-arrow", ImGuiTableColumnFlags.WidthFixed);
|
ImGui.TableSetupColumn("##prev-arrow", ImGuiTableColumnFlags.WidthFixed);
|
||||||
ImGui.TableSetupColumn("##content", ImGuiTableColumnFlags.WidthStretch);
|
ImGui.TableSetupColumn("##content", ImGuiTableColumnFlags.WidthStretch);
|
||||||
ImGui.TableSetupColumn("##next-arrow", ImGuiTableColumnFlags.WidthFixed);
|
ImGui.TableSetupColumn("##next-arrow", ImGuiTableColumnFlags.WidthFixed);
|
||||||
@ -82,6 +95,16 @@ internal class Viewer {
|
|||||||
|
|
||||||
if (ImGui.TableSetColumnIndex(1) && this._idx > -1 && this._idx < nearby.Count) {
|
if (ImGui.TableSetColumnIndex(1) && this._idx > -1 && this._idx < nearby.Count) {
|
||||||
var message = nearby[this._idx];
|
var message = nearby[this._idx];
|
||||||
|
if (this._lastViewed != message.Id) {
|
||||||
|
try {
|
||||||
|
this.View(message);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Plugin.Log.Error(ex, "Error in View event");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._lastViewed = message.Id;
|
||||||
|
|
||||||
var size = ImGui.CalcTextSize(message.Text, ImGui.GetContentRegionAvail().X).Y;
|
var size = ImGui.CalcTextSize(message.Text, ImGui.GetContentRegionAvail().X).Y;
|
||||||
size += ImGui.GetStyle().ItemSpacing.Y * 2;
|
size += ImGui.GetStyle().ItemSpacing.Y * 2;
|
||||||
size += ImGui.CalcTextSize("A").Y;
|
size += ImGui.CalcTextSize("A").Y;
|
||||||
@ -176,10 +199,5 @@ internal class Viewer {
|
|||||||
ImGui.EndDisabled();
|
ImGui.EndDisabled();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.EndTable();
|
|
||||||
|
|
||||||
End:
|
|
||||||
ImGui.End();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
117
client/Util/ActorManager.cs
Normal file
117
client/Util/ActorManager.cs
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
using Dalamud.Plugin.Services;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.Game.Object;
|
||||||
|
|
||||||
|
namespace OrangeGuidanceTomestone.Util;
|
||||||
|
|
||||||
|
internal class ActorManager : IDisposable {
|
||||||
|
private Plugin Plugin { get; }
|
||||||
|
private uint? _idx;
|
||||||
|
private readonly Queue<Mode> _tasks = [];
|
||||||
|
|
||||||
|
private enum Mode {
|
||||||
|
None,
|
||||||
|
Enable,
|
||||||
|
Disable,
|
||||||
|
Delete,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal ActorManager(Plugin plugin) {
|
||||||
|
this.Plugin = plugin;
|
||||||
|
this.Plugin.Framework.Update += this.OnFramework;
|
||||||
|
this.Plugin.Ui.Viewer.View += this.OnView;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() {
|
||||||
|
this.Plugin.Ui.Viewer.View -= this.OnView;
|
||||||
|
this.Plugin.Framework.Update -= this.OnFramework;
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe void OnFramework(IFramework framework) {
|
||||||
|
if (this._idx is not { } idx) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._tasks.TryPeek(out var mode)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var success = false;
|
||||||
|
|
||||||
|
var objMan = ClientObjectManager.Instance();
|
||||||
|
var obj = objMan->GetObjectByIndex((ushort) idx);
|
||||||
|
if (obj == null) {
|
||||||
|
Plugin.Log.Warning("actor by index was null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case Mode.Disable: {
|
||||||
|
obj->DisableDraw();
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Mode.Enable: {
|
||||||
|
if (!obj->IsReadyToDraw()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->EnableDraw();
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Mode.Delete: {
|
||||||
|
objMan->DeleteObjectByIndex((ushort) idx, 0);
|
||||||
|
this._idx = null;
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
this._tasks.Dequeue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnView(Message? message) {
|
||||||
|
this.Despawn();
|
||||||
|
|
||||||
|
if (message != null) {
|
||||||
|
this.Spawn(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal unsafe void Spawn(Message message) {
|
||||||
|
if (this._idx != null) {
|
||||||
|
Plugin.Log.Warning("refusing to spawn more than one actor");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var objMan = ClientObjectManager.Instance();
|
||||||
|
var idx = objMan->CreateBattleCharacter();
|
||||||
|
if (idx == 0xFFFFFFFF) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._idx = idx;
|
||||||
|
|
||||||
|
var chara = (BattleChara*) objMan->GetObjectByIndex((ushort) idx);
|
||||||
|
|
||||||
|
chara->Position = message.Position;
|
||||||
|
chara->Rotation = message.Yaw;
|
||||||
|
var drawData = &chara->DrawData;
|
||||||
|
drawData->CustomizeData = new CustomizeData();
|
||||||
|
|
||||||
|
chara->Alpha = 0.25f;
|
||||||
|
chara->SetMode(CharacterModes.AnimLock, 0);
|
||||||
|
chara->Timeline.BaseOverride = 4818;
|
||||||
|
|
||||||
|
this._tasks.Enqueue(Mode.Enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal unsafe void Despawn() {
|
||||||
|
Plugin.Log.Debug("despawning actor");
|
||||||
|
this._tasks.Enqueue(Mode.Disable);
|
||||||
|
this._tasks.Enqueue(Mode.Delete);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user