From daded9e405bc37b483801bc8166bdedaf451e2a1 Mon Sep 17 00:00:00 2001 From: NemophilaHare <1+nemophilahare@noreply.localhost> Date: Wed, 14 Oct 2026 01:41:17 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=A7=BB=E9=99=A4=E8=87=AA=E5=8A=A8Even?= =?UTF-8?q?tFinish=E5=8F=91=E5=8C=85=E9=81=BF=E5=85=8D=E9=93=83=E9=93=9B?= =?UTF-8?q?=E6=8E=89=E7=BA=BF=EF=BC=8C=E5=9C=B0=E9=9D=A2=E6=8A=80=E8=83=BD?= =?UTF-8?q?=E4=BC=98=E5=85=88=E5=8E=9F=E7=94=9FUseActionLocation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Configuration.cs | 2 +- Plugin.cs | 52 ++++++++++++++++++++++-------------------------- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/Configuration.cs b/Configuration.cs index 85bf116..f629de9 100644 --- a/Configuration.cs +++ b/Configuration.cs @@ -23,7 +23,7 @@ public sealed class Configuration : IPluginConfiguration public bool SmartGroundCastAtTarget { get; set; } = true; public bool FastEventFinish { 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) { return Published.Value(id); diff --git a/Plugin.cs b/Plugin.cs index d5f7144..aaca3a1 100644 --- a/Plugin.cs +++ b/Plugin.cs @@ -62,11 +62,9 @@ public sealed class Plugin : IDalamudPlugin private uint lastEventParam; private long lastEventTime; private long lastRetainerActionTime; - private long lastAutoEventFinishTime; private long lastTalkAdvanceTime; private long lastYesnoTime; private string statusFilterText = ""; - private uint pendingEventFinishId; private readonly IDisposable eventSubscription; public Plugin(IDalamudPluginInterface pluginInterface,ICommandManager commands,IFramework framework, @@ -116,17 +114,6 @@ public sealed class Plugin : IDalamudPlugin game.DrainFaults(modules); combat.Update(); 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.Empty); - var tx=network.EnqueueSend(packet); - notice=$"已自动结束事件 0x{finishId:X8} (事务 #{tx.Id})"; - }); - } if(config.FastEventFinish) Try(ProcessFastDialogAdvance); if(config.AutoRetainerReventure) Try(ProcessRetainerAutomation); } @@ -525,9 +512,9 @@ public sealed class Plugin : IDalamudPlugin 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; - if (ImGui.Checkbox("自动极速结束交互与对话 (FastEventFinish)##fastEventFinish", ref fastEv)) + if (ImGui.Checkbox("自动快进剧情与NPC对话 (Fast Talk)##fastEventFinish", ref fastEv)) { config.FastEventFinish = fastEv; Try(Save); @@ -625,29 +612,38 @@ public sealed class Plugin : IDalamudPlugin lastEventId=System.Buffers.Binary.BinaryPrimitives.ReadUInt32LittleEndian(msg.Payload.Slice(8,4)); lastEventParam=System.Buffers.Binary.BinaryPrimitives.ReadUInt32LittleEndian(msg.Payload.Slice(12,4)); lastEventTime=Environment.TickCount64; - if(config.FastEventFinish && lastEventId!=0 && Environment.TickCount64-lastAutoEventFinishTime>=800) - { - lastAutoEventFinishTime=Environment.TickCount64; - Volatile.Write(ref pendingEventFinishId,lastEventId); - } } } - private void ExecuteGroundCast(uint actionId,bool atTarget) + private unsafe void ExecuteGroundCast(uint actionId,bool atTarget) { - EnsureOpcodes(); if(actionId==0) throw new ArgumentException("请输入有效地面技能 ID"); - var session=game.ReadSendSession(); - if(!session.IsValid) throw new InvalidOperationException("当前角色或区域会话未就绪"); var player=game.Objects.LocalPlayer; if(player==null) throw new InvalidOperationException("本地角色未就绪"); 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); manualSendRequestId=manualSendRequestId>=ushort.MaxValue ? 1 : manualSendRequestId+1; var packet=AuditedPacketEncoder.EncodeActionSendPos(opcodes,gameVersion,actionId,1,(ushort)manualSendRequestId,targetPos,facing); 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})"; - chat.Print($"[IC Rebuild] 地面技能 {actionId} 已排队发送至 {destStr}"); + notice=$"已加入地面技能发包事务 #{tx.Id}:技能 {actionId} -> {destStr} ({targetPos.X:F1}, {targetPos.Y:F1}, {targetPos.Z:F1})"; + chat.Print($"[IC Rebuild] 地面技能 {actionId} 已排队发包至 {destStr}"); } private void ExecuteEventFinish(uint? explicitEventId=null) { @@ -731,7 +727,7 @@ public sealed class Plugin : IDalamudPlugin var mgr=FFXIVClientStructs.FFXIV.Client.UI.RaptureAtkUnitManager.Instance(); if(mgr==null) return; var now=Environment.TickCount64; - if(now-lastRetainerActionTime<450) return; + if(now-lastRetainerActionTime<750) return; var resultAddon=mgr->GetAddonByName("RetainerTaskResult",1); if(resultAddon!=null && resultAddon->IsVisible && resultAddon->IsReady) {