OrangeGuidanceTomestone/client/Util/ActorManager.cs

131 lines
3.5 KiB
C#
Raw Normal View History

2024-07-22 05:44:50 +00:00
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 {
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: {
2024-07-22 06:07:05 +00:00
Plugin.Log.Debug("disabling actor");
2024-07-22 05:44:50 +00:00
obj->DisableDraw();
success = true;
break;
}
case Mode.Enable: {
if (!obj->IsReadyToDraw()) {
2024-07-22 06:07:05 +00:00
Plugin.Log.Debug("not ready to draw");
2024-07-22 05:44:50 +00:00
break;
}
2024-07-22 06:07:05 +00:00
Plugin.Log.Debug("drawing actor");
2024-07-22 05:44:50 +00:00
obj->EnableDraw();
success = true;
break;
}
case Mode.Delete: {
2024-07-22 06:07:05 +00:00
Plugin.Log.Debug("deleting actor");
2024-07-22 05:44:50 +00:00
objMan->DeleteObjectByIndex((ushort) idx, 0);
this._idx = null;
success = true;
break;
}
}
if (success) {
2024-07-22 06:07:05 +00:00
var res = this._tasks.Dequeue();
Plugin.Log.Debug($"deq {Enum.GetName(res)}");
2024-07-22 05:44:50 +00:00
}
}
private void OnView(Message? message) {
2024-07-22 06:07:05 +00:00
var msg = message == null ? "null" : "not null";
Plugin.Log.Debug($"OnView message is {msg}");
2024-07-22 05:44:50 +00:00
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;
}
2024-07-22 06:07:05 +00:00
Plugin.Log.Debug("spawning actor");
2024-07-22 05:44:50 +00:00
var objMan = ClientObjectManager.Instance();
var idx = objMan->CreateBattleCharacter();
if (idx == 0xFFFFFFFF) {
2024-07-22 06:07:05 +00:00
Plugin.Log.Debug("actor could not be spawned");
2024-07-22 05:44:50 +00:00
return;
}
this._idx = idx;
var chara = (BattleChara*) objMan->GetObjectByIndex((ushort) idx);
2024-07-22 06:07:05 +00:00
chara->ObjectKind = ObjectKind.BattleNpc;
2024-07-22 05:44:50 +00:00
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);
}
2024-07-22 06:07:05 +00:00
internal void Despawn() {
if (this._idx == null) {
return;
}
2024-07-22 05:44:50 +00:00
this._tasks.Enqueue(Mode.Disable);
this._tasks.Enqueue(Mode.Delete);
}
}