diff --git a/BetterGenshinImpact/Core/Script/Dependence/Dispatcher.cs b/BetterGenshinImpact/Core/Script/Dependence/Dispatcher.cs
new file mode 100644
index 00000000..5dd7551a
--- /dev/null
+++ b/BetterGenshinImpact/Core/Script/Dependence/Dispatcher.cs
@@ -0,0 +1,22 @@
+using System;
+using BetterGenshinImpact.Core.Script.Dependence.Model;
+using BetterGenshinImpact.GameTask;
+
+namespace BetterGenshinImpact.Core.Script.Dependence;
+
+public class Dispatcher
+{
+ public void RunTask()
+ {
+ }
+
+ public void AddTimer(RealTimeTimer timer)
+ {
+ if (string.IsNullOrEmpty(timer.Name))
+ {
+ throw new ArgumentNullException(nameof(timer.Name), "实时任务名称不能为空");
+ }
+
+ TaskTriggerDispatcher.Instance().AddTrigger(timer.Name, timer.Config);
+ }
+}
diff --git a/BetterGenshinImpact/Core/Script/Dependence/Model/RealTimeTimer.cs b/BetterGenshinImpact/Core/Script/Dependence/Model/RealTimeTimer.cs
new file mode 100644
index 00000000..d002f81a
--- /dev/null
+++ b/BetterGenshinImpact/Core/Script/Dependence/Model/RealTimeTimer.cs
@@ -0,0 +1,23 @@
+namespace BetterGenshinImpact.Core.Script.Dependence.Model;
+
+///
+/// 实时任务计时器
+///
+public class RealTimeTimer
+{
+ ///
+ /// 实时任务触发器名称
+ ///
+ public string? Name { get; set; }
+
+ ///
+ /// 实时任务触发器时间间隔
+ /// 默认50ms
+ ///
+ public int Interval { get; set; } = 50;
+
+ ///
+ /// 实时任务配置
+ ///
+ public object? Config;
+}
diff --git a/BetterGenshinImpact/Core/Script/Dependence/Model/TimerConfig/AutoPickExternalConfig.cs b/BetterGenshinImpact/Core/Script/Dependence/Model/TimerConfig/AutoPickExternalConfig.cs
new file mode 100644
index 00000000..d3dbce8b
--- /dev/null
+++ b/BetterGenshinImpact/Core/Script/Dependence/Model/TimerConfig/AutoPickExternalConfig.cs
@@ -0,0 +1,13 @@
+namespace BetterGenshinImpact.Core.Script.Dependence.Model.TimerConfig;
+
+public class AutoPickExternalConfig
+{
+ // 关闭黑白名单
+ public bool DisabledBlackWhiteList { get; set; } = false;
+
+ // 需要F的文本(对话、拾取)
+ public string[] TextList { get; set; } = [];
+
+ // 无视文本和图标遇到F就点击
+ public bool ForceInteraction { get; set; } = false;
+}
diff --git a/BetterGenshinImpact/Core/Script/EngineExtend.cs b/BetterGenshinImpact/Core/Script/EngineExtend.cs
index 5edb6511..e9f7b774 100644
--- a/BetterGenshinImpact/Core/Script/EngineExtend.cs
+++ b/BetterGenshinImpact/Core/Script/EngineExtend.cs
@@ -15,6 +15,7 @@ public class EngineExtend
engine.AddHostObject("genshin", new Dependence.Genshin());
engine.AddHostObject("log", new Log());
engine.AddHostObject("file", new LimitedFile(workDir)); // 限制文件访问
+ engine.AddHostObject("dispatcher", new Dispatcher());
// 直接添加方法
#pragma warning disable CS8974 // Converting method group to non-delegate type
diff --git a/BetterGenshinImpact/Core/Script/Project/ScriptProject.cs b/BetterGenshinImpact/Core/Script/Project/ScriptProject.cs
index 18549e81..abe9392b 100644
--- a/BetterGenshinImpact/Core/Script/Project/ScriptProject.cs
+++ b/BetterGenshinImpact/Core/Script/Project/ScriptProject.cs
@@ -57,7 +57,7 @@ public class ScriptProject
}
}
- private async Task LoadCode()
+ public async Task LoadCode()
{
var code = await File.ReadAllTextAsync(Path.Combine(ProjectPath, Manifest.Main));
if (string.IsNullOrEmpty(code))
diff --git a/BetterGenshinImpact/GameTask/AutoPick/AutoPickTrigger.cs b/BetterGenshinImpact/GameTask/AutoPick/AutoPickTrigger.cs
index dd0e7026..49238218 100644
--- a/BetterGenshinImpact/GameTask/AutoPick/AutoPickTrigger.cs
+++ b/BetterGenshinImpact/GameTask/AutoPick/AutoPickTrigger.cs
@@ -17,6 +17,7 @@ using System.Windows.Forms;
using BetterGenshinImpact.Core.Recognition;
using Vanara.PInvoke;
using System.Windows.Input;
+using BetterGenshinImpact.Core.Script.Dependence.Model.TimerConfig;
namespace BetterGenshinImpact.GameTask.AutoPick;
@@ -48,14 +49,22 @@ public class AutoPickTrigger : ITaskTrigger
private User32.VK _pickVk = User32.VK.VK_F;
private RecognitionObject _pickRo;
+ // 外部配置
+ private AutoPickExternalConfig? _externalConfig;
+
public AutoPickTrigger()
{
_autoPickAssets = AutoPickAssets.Instance;
+ _pickRo = _autoPickAssets.FRo;
+ }
+
+ public AutoPickTrigger(AutoPickExternalConfig? config) : this()
+ {
+ _externalConfig = config;
}
public void Init()
{
- _pickRo = _autoPickAssets.FRo;
var keyName = TaskContext.Instance().Config.AutoPickConfig.PickKey;
if (!string.IsNullOrEmpty(keyName))
{
diff --git a/BetterGenshinImpact/GameTask/GameTaskManager.cs b/BetterGenshinImpact/GameTask/GameTaskManager.cs
index 6713a13e..5e13c55a 100644
--- a/BetterGenshinImpact/GameTask/GameTaskManager.cs
+++ b/BetterGenshinImpact/GameTask/GameTaskManager.cs
@@ -6,6 +6,7 @@ using OpenCvSharp;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using BetterGenshinImpact.Core.Script.Dependence.Model.TimerConfig;
using BetterGenshinImpact.GameTask.AutoFight.Assets;
using BetterGenshinImpact.GameTask.AutoFishing.Assets;
using BetterGenshinImpact.GameTask.AutoGeniusInvokation.Assets;
@@ -30,7 +31,7 @@ internal class GameTaskManager
/// 一定要在任务上下文初始化完毕后使用
///
///
- public static List LoadTriggers()
+ public static List LoadInitialTriggers()
{
ReloadAssets();
TriggerDictionary = new Dictionary()
@@ -40,10 +41,20 @@ internal class GameTaskManager
{ "AutoPick", new AutoPick.AutoPickTrigger() },
{ "QuickTeleport", new QuickTeleport.QuickTeleportTrigger() },
{ "AutoSkip", new AutoSkip.AutoSkipTrigger() },
- { "AutoFishing", new AutoFishing.AutoFishingTrigger() },
+ { "AutoFish", new AutoFishing.AutoFishingTrigger() },
{ "AutoCook", new AutoCook.AutoCookTrigger() }
};
+ return ConvertToTriggerList();
+ }
+
+ public static List ConvertToTriggerList()
+ {
+ if (TriggerDictionary is null)
+ {
+ return [];
+ }
+
var loadedTriggers = TriggerDictionary.Values.ToList();
loadedTriggers.ForEach(i => i.Init());
@@ -52,16 +63,45 @@ internal class GameTaskManager
return loadedTriggers;
}
+ public static void ClearTriggers()
+ {
+ TriggerDictionary?.Clear();
+ }
+
+ ///
+ /// 通过名称添加触发器
+ ///
+ ///
+ ///
+ public static void AddTrigger(string name, object? externalConfig)
+ {
+ TriggerDictionary ??= new Dictionary();
+ TriggerDictionary.Clear();
+
+ if (name == "AutoPick")
+ {
+ TriggerDictionary.Add("AutoPick", new AutoPick.AutoPickTrigger(externalConfig as AutoPickExternalConfig));
+ }
+ // else if (name == "AutoSkip")
+ // {
+ // TriggerDictionary.Add("AutoSkip", new AutoSkip.AutoSkipTrigger());
+ // }
+ // else if (name == "AutoFish")
+ // {
+ // TriggerDictionary.Add("AutoFish", new AutoFishing.AutoFishingTrigger());
+ // }
+ }
+
public static void RefreshTriggerConfigs()
{
if (TriggerDictionary is { Count: > 0 })
{
- TriggerDictionary["AutoPick"].Init();
- TriggerDictionary["AutoSkip"].Init();
- TriggerDictionary["AutoFishing"].Init();
- TriggerDictionary["QuickTeleport"].Init();
- TriggerDictionary["GameLoading"].Init();
- TriggerDictionary["AutoCook"].Init();
+ TriggerDictionary.GetValueOrDefault("AutoPick")?.Init();
+ TriggerDictionary.GetValueOrDefault("AutoSkip")?.Init();
+ TriggerDictionary.GetValueOrDefault("AutoFish")?.Init();
+ TriggerDictionary.GetValueOrDefault("QuickTeleport")?.Init();
+ TriggerDictionary.GetValueOrDefault("GameLoading")?.Init();
+ TriggerDictionary.GetValueOrDefault("AutoCook")?.Init();
// 清理画布
WeakReferenceMessenger.Default.Send(new PropertyChangedMessage