using System; using System.Threading.Tasks; using UnityEngine; using WulaFallenEmpire.EventSystem.AI.Agent; namespace WulaFallenEmpire.EventSystem.AI.Tools { /// /// 视觉点击工具 - 使用 VLM 分析屏幕后模拟鼠标点击 /// 适用于原版 API 无法直接操作的 mod UI 元素 /// public class Tool_VisualClick : AITool { public override string Name => "visual_click"; public override string Description => "在指定的屏幕位置执行鼠标点击。坐标使用比例值 (0-1),(0,0) 是左上角,(1,1) 是右下角。" + "适用于点击无法通过 API 操作的 mod 按钮或 UI 元素。先使用 analyze_screen 获取目标位置分析。"; public override string UsageSchema => "0-1之间的X比例0-1之间的Y比例可选,true为右键"; public override Task ExecuteAsync(string args) { try { var argsDict = ParseXmlArgs(args); // 解析 X 坐标 if (!argsDict.TryGetValue("x", out string xStr) || !float.TryParse(xStr, out float x)) { return Task.FromResult("Error: 缺少有效的 x 坐标 (0-1之间的比例值)"); } // 解析 Y 坐标 if (!argsDict.TryGetValue("y", out string yStr) || !float.TryParse(yStr, out float y)) { return Task.FromResult("Error: 缺少有效的 y 坐标 (0-1之间的比例值)"); } // 验证范围 if (x < 0 || x > 1 || y < 0 || y > 1) { return Task.FromResult($"Error: 坐标 ({x}, {y}) 超出范围,必须在 0-1 之间"); } // 解析右键选项 bool rightClick = false; if (argsDict.TryGetValue("right_click", out string rightStr)) { rightClick = rightStr.ToLowerInvariant() == "true" || rightStr == "1"; } // 执行点击 bool success = Agent.MouseSimulator.ClickAtProportional(x, y, rightClick); if (success) { string clickType = rightClick ? "右键" : "左键"; int screenX = Mathf.RoundToInt(x * Screen.width); int screenY = Mathf.RoundToInt(y * Screen.height); WulaLog.Debug($"[Tool_VisualClick] {clickType}点击 ({x:F3}, {y:F3}) -> 屏幕 ({screenX}, {screenY})"); return Task.FromResult($"Success: 已在屏幕位置 ({screenX}, {screenY}) 执行{clickType}点击"); } else { return Task.FromResult("Error: 点击操作失败"); } } catch (Exception ex) { WulaLog.Debug($"[Tool_VisualClick] Error: {ex}"); return Task.FromResult($"Error: 点击操作失败 - {ex.Message}"); } } } /// /// 视觉输入文本工具 - 在当前焦点位置输入文本 /// public class Tool_VisualTypeText : AITool { public override string Name => "visual_type_text"; public override string Description => "在当前焦点位置输入文本。适用于需要文本输入的对话框或输入框。应先用 visual_click 点击输入框获取焦点。"; public override string UsageSchema => "要输入的文本"; public override Task ExecuteAsync(string args) { try { var argsDict = ParseXmlArgs(args); if (!argsDict.TryGetValue("text", out string text) || string.IsNullOrEmpty(text)) { return Task.FromResult("Error: 缺少要输入的文本"); } // 获取当前鼠标位置 var pos = MouseSimulator.GetCurrentPosition(); float propX = Mathf.Clamp01((float)pos.x / Screen.width); float propY = Mathf.Clamp01((float)pos.y / Screen.height); WulaLog.Debug($"[VisualTypeText] Current Pos: ({pos.x}, {pos.y}) -> Proportional: ({propX:F3}, {propY:F3})"); return Task.FromResult(VisualInteractionTools.TypeText(propX, propY, text)); } catch (Exception ex) { WulaLog.Debug($"[Tool_VisualTypeText] Error: {ex}"); return Task.FromResult($"Error: 输入文本失败 - {ex.Message}"); } } } /// /// 视觉滚动工具 - 在当前位置滚动鼠标滚轮 /// public class Tool_VisualScroll : AITool { public override string Name => "visual_scroll"; public override string Description => "在当前鼠标位置滚动。可选先移动到指定位置再滚动。delta 正数向上滚动,负数向下滚动。"; public override string UsageSchema => "滚动量,正数向上负数向下可选,0-1 X坐标可选,0-1 Y坐标"; public override Task ExecuteAsync(string args) { try { var argsDict = ParseXmlArgs(args); if (!argsDict.TryGetValue("delta", out string deltaStr) || !int.TryParse(deltaStr, out int delta)) { return Task.FromResult("Error: 缺少有效的 delta 值"); } // 可选:先移动到指定位置 if (argsDict.TryGetValue("x", out string xStr) && argsDict.TryGetValue("y", out string yStr)) { if (float.TryParse(xStr, out float x) && float.TryParse(yStr, out float y)) { Agent.MouseSimulator.MoveToProportional(x, y); System.Threading.Thread.Sleep(10); } } Agent.MouseSimulator.Scroll(delta); string direction = delta > 0 ? "向上" : "向下"; return Task.FromResult($"Success: 已{direction}滚动 {Math.Abs(delta)} 单位"); } catch (Exception ex) { WulaLog.Debug($"[Tool_VisualScroll] Error: {ex}"); return Task.FromResult($"Error: 滚动操作失败 - {ex.Message}"); } } } }