fix: queue actor actions
This commit is contained in:
parent
460261d830
commit
ed679ae141
@ -7,13 +7,7 @@ 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,
|
||||
}
|
||||
private readonly Queue<BaseActorAction> _tasks = [];
|
||||
|
||||
internal ActorManager(Plugin plugin) {
|
||||
this.Plugin = plugin;
|
||||
@ -31,49 +25,28 @@ internal class ActorManager : IDisposable {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._tasks.TryPeek(out var mode)) {
|
||||
if (!this._tasks.TryPeek(out var actorAction)) {
|
||||
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;
|
||||
var success = false;
|
||||
|
||||
if (actorAction.Tries < 10) {
|
||||
try {
|
||||
actorAction.Tries += 1;
|
||||
success = actorAction.Run(this, objMan);
|
||||
} catch (Exception ex) {
|
||||
Plugin.Log.Error(ex, "Error in actor action queue");
|
||||
}
|
||||
} else {
|
||||
Plugin.Log.Warning("too many retries, skipping");
|
||||
success = true;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case Mode.Disable: {
|
||||
Plugin.Log.Debug("disabling actor");
|
||||
obj->DisableDraw();
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
case Mode.Enable: {
|
||||
if (!obj->IsReadyToDraw()) {
|
||||
Plugin.Log.Debug("not ready to draw");
|
||||
break;
|
||||
}
|
||||
|
||||
Plugin.Log.Debug("drawing actor");
|
||||
obj->EnableDraw();
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
case Mode.Delete: {
|
||||
Plugin.Log.Debug("deleting actor");
|
||||
objMan->DeleteObjectByIndex((ushort) idx, 0);
|
||||
this._idx = null;
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
var res = this._tasks.Dequeue();
|
||||
Plugin.Log.Debug($"deq {Enum.GetName(res)}");
|
||||
this._tasks.Dequeue();
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,14 +68,64 @@ internal class ActorManager : IDisposable {
|
||||
|
||||
Plugin.Log.Debug("spawning actor");
|
||||
|
||||
var objMan = ClientObjectManager.Instance();
|
||||
var idx = objMan->CreateBattleCharacter();
|
||||
if (idx == 0xFFFFFFFF) {
|
||||
Plugin.Log.Debug("actor could not be spawned");
|
||||
|
||||
}
|
||||
|
||||
internal void Despawn() {
|
||||
if (this._idx == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._idx = idx;
|
||||
this._tasks.Enqueue(new DisableAction());
|
||||
this._tasks.Enqueue(new DeleteAction());
|
||||
}
|
||||
|
||||
private unsafe abstract class BaseActorAction {
|
||||
/// <summary>
|
||||
/// Run this action.
|
||||
/// </summary>
|
||||
/// <returns>true if the action is finished, false if it should be run again</returns>
|
||||
public abstract bool Run(ActorManager manager, ClientObjectManager* objMan);
|
||||
|
||||
public int Tries { get; set; }
|
||||
|
||||
protected bool TryGetBattleChara(
|
||||
ActorManager manager,
|
||||
ClientObjectManager* objMan,
|
||||
out BattleChara* chara
|
||||
) {
|
||||
chara = null;
|
||||
|
||||
if (manager._idx is not { } idx) {
|
||||
Plugin.Log.Warning("tried to get battlechara but idx was null");
|
||||
return false;
|
||||
}
|
||||
|
||||
var obj = objMan->GetObjectByIndex((ushort) idx);
|
||||
if (obj == null) {
|
||||
Plugin.Log.Warning("tried to get battlechara but it was null");
|
||||
return false;
|
||||
}
|
||||
|
||||
chara = (BattleChara*) obj;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe class SpawnAction(Message message) : BaseActorAction {
|
||||
public override bool Run(ActorManager manager, ClientObjectManager* objMan) {
|
||||
if (manager._idx != null) {
|
||||
Plugin.Log.Warning("refusing to spawn a second actor");
|
||||
return true;
|
||||
}
|
||||
|
||||
var idx = objMan->CreateBattleCharacter();
|
||||
if (idx == 0xFFFFFFFF) {
|
||||
Plugin.Log.Debug("actor could not be spawned");
|
||||
return true;
|
||||
}
|
||||
|
||||
manager._idx = idx;
|
||||
|
||||
var chara = (BattleChara*) objMan->GetObjectByIndex((ushort) idx);
|
||||
|
||||
@ -116,15 +139,51 @@ internal class ActorManager : IDisposable {
|
||||
chara->SetMode(CharacterModes.AnimLock, 0);
|
||||
chara->Timeline.BaseOverride = 4818;
|
||||
|
||||
this._tasks.Enqueue(Mode.Enable);
|
||||
manager._tasks.Enqueue(new EnableAction());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Despawn() {
|
||||
if (this._idx == null) {
|
||||
return;
|
||||
private unsafe class EnableAction : BaseActorAction {
|
||||
public override bool Run(ActorManager manager, ClientObjectManager* objMan) {
|
||||
if (!this.TryGetBattleChara(manager, objMan, out var chara)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this._tasks.Enqueue(Mode.Disable);
|
||||
this._tasks.Enqueue(Mode.Delete);
|
||||
if (!chara->IsReadyToDraw()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
chara->EnableDraw();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe class DisableAction : BaseActorAction {
|
||||
public override bool Run(ActorManager manager, ClientObjectManager* objMan) {
|
||||
if (!this.TryGetBattleChara(manager, objMan, out var chara)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
chara->DisableDraw();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe class DeleteAction : BaseActorAction {
|
||||
public override bool Run(ActorManager manager, ClientObjectManager* objMan) {
|
||||
if (manager._idx is not { } idx) {
|
||||
Plugin.Log.Warning("delete action but idx was null");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (objMan->GetObjectByIndex((ushort) idx) == null) {
|
||||
Plugin.Log.Warning("delete action but object at idx was null");
|
||||
return true;
|
||||
}
|
||||
|
||||
objMan->DeleteObjectByIndex((ushort) idx, 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user