fix: 移除自动EventFinish发包避免铃铛掉线,地面技能优先原生UseActionLocation

This commit is contained in:
2026-10-14 01:41:17 +08:00
parent 6bae98720f
commit daded9e405
2 changed files with 25 additions and 29 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ public sealed class Configuration : IPluginConfiguration
public bool SmartGroundCastAtTarget { get; set; } = true; public bool SmartGroundCastAtTarget { get; set; } = true;
public bool FastEventFinish { get; set; } = false; public bool FastEventFinish { get; set; } = false;
public bool FastSelectYesno { get; set; } = false; public bool FastSelectYesno { get; set; } = false;
public bool AutoRetainerReventure { get; set; } = true; public bool AutoRetainerReventure { get; set; } = false;
public float Value(int id) public float Value(int id)
{ {
return Published.Value(id); return Published.Value(id);
+26 -30
View File
@@ -62,11 +62,9 @@ public sealed class Plugin : IDalamudPlugin
private uint lastEventParam; private uint lastEventParam;
private long lastEventTime; private long lastEventTime;
private long lastRetainerActionTime; private long lastRetainerActionTime;
private long lastAutoEventFinishTime;
private long lastTalkAdvanceTime; private long lastTalkAdvanceTime;
private long lastYesnoTime; private long lastYesnoTime;
private string statusFilterText = ""; private string statusFilterText = "";
private uint pendingEventFinishId;
private readonly IDisposable eventSubscription; private readonly IDisposable eventSubscription;
public Plugin(IDalamudPluginInterface pluginInterface,ICommandManager commands,IFramework framework, public Plugin(IDalamudPluginInterface pluginInterface,ICommandManager commands,IFramework framework,
@@ -116,17 +114,6 @@ public sealed class Plugin : IDalamudPlugin
game.DrainFaults(modules); game.DrainFaults(modules);
combat.Update(); combat.Update();
network.PumpActiveSends(); network.PumpActiveSends();
var finishId=Interlocked.Exchange(ref pendingEventFinishId,0);
if(finishId!=0 && config.FastEventFinish)
{
Try(()=>
{
EnsureOpcodes();
var packet=AuditedPacketEncoder.EncodeEventFinish(opcodes,gameVersion,finishId,0,0,ReadOnlySpan<uint>.Empty);
var tx=network.EnqueueSend(packet);
notice=$"已自动结束事件 0x{finishId:X8} (事务 #{tx.Id})";
});
}
if(config.FastEventFinish) Try(ProcessFastDialogAdvance); if(config.FastEventFinish) Try(ProcessFastDialogAdvance);
if(config.AutoRetainerReventure) Try(ProcessRetainerAutomation); if(config.AutoRetainerReventure) Try(ProcessRetainerAutomation);
} }
@@ -525,9 +512,9 @@ public sealed class Plugin : IDalamudPlugin
if(ImGui.CollapsingHeader("2. 交互/剧情极速跳过与开箱 (Fast Event Finish / Interact)", ImGuiTreeNodeFlags.DefaultOpen)) if(ImGui.CollapsingHeader("2. 交互/剧情极速跳过与开箱 (Fast Event Finish / Interact)", ImGuiTreeNodeFlags.DefaultOpen))
{ {
ImGui.TextWrapped("监听 DOWN_EventStart,直接发送 UP_EventFinish 完成 NPC 对话、开宝箱、副本传送门与剧情过渡。"); ImGui.TextWrapped("支持自动极速快进剧情与NPC对白 Talk、自动确认 Yes/No 提示框,以及手动发包立即完成开箱/门锁事件。");
var fastEv = config.FastEventFinish; var fastEv = config.FastEventFinish;
if (ImGui.Checkbox("自动极速结束交互与对话 (FastEventFinish)##fastEventFinish", ref fastEv)) if (ImGui.Checkbox("自动快进剧情与NPC对话 (Fast Talk)##fastEventFinish", ref fastEv))
{ {
config.FastEventFinish = fastEv; config.FastEventFinish = fastEv;
Try(Save); Try(Save);
@@ -625,29 +612,38 @@ public sealed class Plugin : IDalamudPlugin
lastEventId=System.Buffers.Binary.BinaryPrimitives.ReadUInt32LittleEndian(msg.Payload.Slice(8,4)); lastEventId=System.Buffers.Binary.BinaryPrimitives.ReadUInt32LittleEndian(msg.Payload.Slice(8,4));
lastEventParam=System.Buffers.Binary.BinaryPrimitives.ReadUInt32LittleEndian(msg.Payload.Slice(12,4)); lastEventParam=System.Buffers.Binary.BinaryPrimitives.ReadUInt32LittleEndian(msg.Payload.Slice(12,4));
lastEventTime=Environment.TickCount64; lastEventTime=Environment.TickCount64;
if(config.FastEventFinish && lastEventId!=0 && Environment.TickCount64-lastAutoEventFinishTime>=800) }
}
private unsafe void ExecuteGroundCast(uint actionId,bool atTarget)
{ {
lastAutoEventFinishTime=Environment.TickCount64;
Volatile.Write(ref pendingEventFinishId,lastEventId);
}
}
}
private void ExecuteGroundCast(uint actionId,bool atTarget)
{
EnsureOpcodes();
if(actionId==0) throw new ArgumentException("请输入有效地面技能 ID"); if(actionId==0) throw new ArgumentException("请输入有效地面技能 ID");
var session=game.ReadSendSession();
if(!session.IsValid) throw new InvalidOperationException("当前角色或区域会话未就绪");
var player=game.Objects.LocalPlayer; var player=game.Objects.LocalPlayer;
if(player==null) throw new InvalidOperationException("本地角色未就绪"); if(player==null) throw new InvalidOperationException("本地角色未就绪");
Vector3 targetPos=atTarget && game.Targets.Target is { } target ? target.Position : player.Position; Vector3 targetPos=atTarget && game.Targets.Target is { } target ? target.Position : player.Position;
var destStr=atTarget && game.Targets.Target!=null ? $"目标【{game.Targets.Target.Name}】" : "自身脚下";
var am=FFXIVClientStructs.FFXIV.Client.Game.ActionManager.Instance();
if(am!=null)
{
var loc=targetPos;
var success=am->UseActionLocation(FFXIVClientStructs.FFXIV.Client.Game.ActionType.Action,actionId,0xE000_0000,&loc);
if(success)
{
notice=$"地面技能 {actionId} 已智能释放至 {destStr} ({targetPos.X:F1}, {targetPos.Y:F1}, {targetPos.Z:F1})";
chat.Print($"[IC Rebuild] 地面技能 {actionId} 已释放至 {destStr}");
return;
}
}
EnsureOpcodes();
var session=game.ReadSendSession();
if(!session.IsValid) throw new InvalidOperationException("当前角色或区域会话未就绪");
ushort facing=(ushort)((player.Rotation+MathF.PI)/(MathF.PI*2f)*ushort.MaxValue); ushort facing=(ushort)((player.Rotation+MathF.PI)/(MathF.PI*2f)*ushort.MaxValue);
manualSendRequestId=manualSendRequestId>=ushort.MaxValue ? 1 : manualSendRequestId+1; manualSendRequestId=manualSendRequestId>=ushort.MaxValue ? 1 : manualSendRequestId+1;
var packet=AuditedPacketEncoder.EncodeActionSendPos(opcodes,gameVersion,actionId,1,(ushort)manualSendRequestId,targetPos,facing); var packet=AuditedPacketEncoder.EncodeActionSendPos(opcodes,gameVersion,actionId,1,(ushort)manualSendRequestId,targetPos,facing);
var tx=network.EnqueueSend(packet); var tx=network.EnqueueSend(packet);
var destStr=atTarget && game.Targets.Target!=null ? $"目标【{game.Targets.Target.Name}】" : "自身脚下"; notice=$"已加入地面技能发包事务 #{tx.Id}:技能 {actionId} -> {destStr} ({targetPos.X:F1}, {targetPos.Y:F1}, {targetPos.Z:F1})";
notice=$"已加入地面技能事务 #{tx.Id}:技能 {actionId} -> {destStr} ({targetPos.X:F1}, {targetPos.Y:F1}, {targetPos.Z:F1})"; chat.Print($"[IC Rebuild] 地面技能 {actionId} 已排队发包至 {destStr}");
chat.Print($"[IC Rebuild] 地面技能 {actionId} 已排队发送至 {destStr}");
} }
private void ExecuteEventFinish(uint? explicitEventId=null) private void ExecuteEventFinish(uint? explicitEventId=null)
{ {
@@ -731,7 +727,7 @@ public sealed class Plugin : IDalamudPlugin
var mgr=FFXIVClientStructs.FFXIV.Client.UI.RaptureAtkUnitManager.Instance(); var mgr=FFXIVClientStructs.FFXIV.Client.UI.RaptureAtkUnitManager.Instance();
if(mgr==null) return; if(mgr==null) return;
var now=Environment.TickCount64; var now=Environment.TickCount64;
if(now-lastRetainerActionTime<450) return; if(now-lastRetainerActionTime<750) return;
var resultAddon=mgr->GetAddonByName("RetainerTaskResult",1); var resultAddon=mgr->GetAddonByName("RetainerTaskResult",1);
if(resultAddon!=null && resultAddon->IsVisible && resultAddon->IsReady) if(resultAddon!=null && resultAddon->IsVisible && resultAddon->IsReady)
{ {