Shigure
Shigure 是 荒坂公司(Arasaka Corporation)开发的冲锋枪,有时人们只想把子弹全打出去,在硝烟过后品味眼前的一片狼藉。
它需要配合 冬月电子(Fuyutsuki Electronics)的 Fuyutsui使用。
免责声明 (Disclaimer)
-
合规责任
Shigure 仅供技术研究、学习交流和个人实验使用。下载、安装、复制、修改、分发或使用本软件前,用户应自行确认相关行为符合所在地法律法规,以及目标软件、游戏平台或服务提供商的用户协议、服务条款和社区规则。
-
账号与处罚风险
本软件可能涉及窗口状态读取、按键发送或自动化辅助流程。此类行为可能被游戏运营商、反作弊系统或相关服务提供商认定为违规,并导致账号限制、角色封禁、数据丢失、收益回收或其他处罚。用户应充分了解并自行承担全部风险,开发者不对由此产生的任何后果负责。
-
无担保声明
本项目基于 MIT License 开源发布,详见 LICENSE。软件按“原样”(AS IS)提供,不对稳定性、准确性、完整性、安全性、兼容性、持续可用性或特定用途适用性作出任何明示或暗示保证。因使用或无法使用本软件导致的直接、间接、偶然、特殊或后续损失,均由用户自行承担。
-
商业使用与衍生版本
MIT License 允许在许可证范围内复制、修改、分发和再许可本软件,但任何组织或个人若将本软件或其衍生版本用于商业用途、付费服务、代练、外挂销售、打包分发或其他可能违反第三方服务条款的场景,应独立承担由此引发的法律纠纷、平台追责、知识产权争议、账号处罚和赔偿责任。原开发者不参与此类商业运营,也不承担连带责任。
-
使用即表示接受
一旦开始使用本软件,即视为用户已阅读、理解并同意本免责声明及 MIT License 的全部内容。若不同意,请立即停止使用并删除本软件及其副本。
真实作用
Shigure 是一个 Windows WinForms 桌面程序,用于扫描目标窗口状态、根据职业 keymap 选择按键,并把实时状态、队伍信息、逻辑输出和运行日志集中显示在 UI 中。
当前版本:1.2.0.0
当前界面
- 置顶浮动条:无边框小窗口,显示 Shigure 标题和逻辑状态,右侧有
开关(文字在开启/关闭间切换)、设置、✕三个按钮;窗口可拖动、可从边缘缩放,启动后会自动启动运行循环。 - 设置窗口:点击
设置打开,集中包含通用、模块、状态、队伍、逻辑、日志、关于七个页签。 - 通用页:可设置触发键、发送模式和当前使用的模块。模块选择器会根据实时识别到的职业 / 专精 / 队伍类型 / 英雄天赋筛选可用模块,可保持自动选择最匹配模块,也可从符合条件的模块中手动指定一个。点击触发键按钮后按下目标键即可录入,支持键盘按键、
XBUTTON1、XBUTTON2,不支持ALT。 - 模块页:左侧列出全部模块,右侧可新建、编辑、删除模块,并编辑模块名称、匹配条件(职业 / 专精 / 队伍类型 / 英雄天赋)和判断规则。这个页面只负责逻辑编辑;具体启用或选择哪个模块在“通用”页完成。规则表的“技能”“目标”列为下拉菜单(选项来自当前选中职业的 keymap),“条件”列为只读,点击后弹出可视化条件编辑器。页面内嵌“动态单位 / 数量字段”面板,可定义如“最低血量单位”这类按队伍状态实时解析的单位,供“目标”和“条件”引用。
- 状态页:显示当前匹配的模块名以及扫描后构建出的状态字段,右侧并列显示
spells技能状态。 - 队伍页:显示
group队伍成员摘要。 - 逻辑页:显示模块或职业逻辑返回的诊断信息(命中条件、动作技能、动作按键等)。
- 日志页:记录启动、停止、职业识别、模块匹配、逻辑状态变化、步骤变化和异常信息。
- 关于页:显示产品名、版本、运行目录、模块目录和配置文件路径。
触发键、发送模式的修改会立即重启运行循环。模块会保存到 module 文件夹,修改并保存后同样会重启运行循环以加载最新模块。窗口位置/大小、UI 状态(如规则表的列宽)会被缓存到 cache/window-state.json,下次启动时自动恢复。
运行环境
- Windows
- .NET 10 SDK
运行
在仓库根目录运行:
dotnet run --project .\Shigure.csproj
也可以传入启动参数:
dotnet run --project .\Shigure.csproj -- --window 魔兽世界 --toggle XBUTTON2 --mode switch --logic-ms 100 --render-ms 100
参数说明:
--window:目标窗口标题,默认魔兽世界。--toggle:触发键,默认XBUTTON2。--mode:发送模式,支持switch、click、hold。--logic-ms:逻辑循环间隔,默认100,最小50。--render-ms:UI 刷新间隔,默认100,最小100。
发送模式:
switch:按一次触发键开启逻辑,再按一次关闭。click:按一次触发键只执行一轮逻辑。hold:按住触发键时运行,松开后停止。
构建
dotnet build .\Shigure.csproj
应用图标来自:
Assets\shigure-emblem-arasaka.ico
项目结构
Shigure.csproj 项目文件,复制 Assets/config/keymap/module 到输出目录
App\ 程序入口与启动参数解析
UI\ WinForms 界面、编辑器、主题和 UI 缓存
Runtime\ 扫描、状态构建、逻辑运行和运行时快照
Modules\ 模块模型、存储、匹配、规则执行和字段目录
Input\ keymap 读取、按键发送和 Win32 API 互操作
Infrastructure\ 配置读取与 JSON 辅助方法
Assets\ 图标与品牌资源
keymap\ 各职业按键映射
module\ UI 可编辑模块
配置文件
config/*.json:状态扫描配置和职业 keymap 引用,common.json为公共配置,其余文件按职业名称命名。keymap/*.json:职业按键映射,运行时按职业 ID 选择。Assets/*.ico|*.png|*.svg:程序图标和品牌资源,构建时会复制到输出目录。cache/window-state.json:UI 缓存,保存置顶浮动条位置、设置窗口位置/大小和上次触发键。
config 结构
config 目录描述了如何把扫描到的像素数据翻译成状态字段。每个字段是一个对象:
step:在顶部行数据中的列索引,支持1~510;特殊值"bar"表示从左侧标记行数据读取,并配合bar字段指定段索引。type:字段类型,支持int、bool、string。
顶部状态行由 Fuyutsui 绘制为 510 个色块。Shigure 按两段颜色协议解码:1255 使用 (0, i / 255, b, 1),256510 使用 (1 / 255, (i - 255) / 255, b, 1);其中 b 会作为该 step 的原始值写入状态。左侧 "bar" 标记行仍按独立的计数条协议读取,不受顶部 510 色块数量影响。
common.json 包含 锚点、职业、专精 等基础字段和一个 state 公共状态块;其余职业文件如 战士.json、圣骑士.json 对应职业 ID,每个职业文件下:
keymap:该职业使用的 keymap 文件名。- 以专精 ID 为键(如
"1"、"2"、"3")的对象,包含该专精特有的字段、spells技能块和可选的group队伍块。
运行时 ConfigService 会把 锚点/职业/专精/state 与当前 职业/专精 对应的配置合并,再由 StateBuilder 构建出 GameState。group 块用 start(起始列)和 num(每个成员占用的列数)描述队伍成员数据的排布。
模块系统
模块用于把“识别到的角色环境”和“要执行的判断逻辑”拆成可编辑 JSON。运行时每轮识别到 职业、专精、队伍类型、英雄天赋 后,会在 module 文件夹中寻找匹配模块。
匹配字段:
ClassId:职业 ID,对应状态字段职业。SpecId:专精 ID,对应状态字段专精。PartyType:队伍类型,对应状态字段队伍类型。模块页使用下拉菜单:0表示单人,1-40表示团队,46表示队伍。HeroTalent:英雄天赋,对应状态字段英雄天赋。
字段留空(界面上选择 任意 (*))表示任意值。多个模块同时匹配时,程序会优先使用匹配字段更多的模块(Specificity 越大优先级越高),相同时按名称排序。
旧模块中 PartyType 如果保存为数字仍可读取;保存团队模块时会归一化写入 "1-40"。
模块以 模块名.json 的形式平铺保存在 module 文件夹(文件名取自模块名称,因此模块名称不能重复)。加载时会递归扫描 module 下的所有子目录,旧版本保存在嵌套子文件夹中的模块文件仍可正常读取。
模块文件示例:
{
"Id": "戒律-20260612100954681",
"Name": "戒律",
"Enabled": true,
"Match": {
"ClassId": 5,
"SpecId": 1,
"PartyType": "46",
"HeroTalent": 1
},
"Rules": [
{
"Enabled": true,
"Condition": "一键辅助 == 10",
"Unit": 0,
"Spell": "一键辅助",
"Hotkey": "",
"Step": ""
}
]
}
Id 由界面在新建时自动生成(名称-时间戳),用于唯一标识模块。
规则按顺序判断,第一条命中的规则会执行。Spell 会通过当前职业 keymap 查找按键;如果填写了 Hotkey,则直接发送该按键(优先于 Spell)。Unit 表示技能对应的单位(默认为 0,即自身/当前单位)。
模块页规则表中“技能”和“目标”列为下拉菜单,选项取自当前选中职业的 keymap:技能按名称去重(keymap 中同名技能的多个 unit 条目只显示一次)。“目标”下拉跟随该行所选技能联动——只列出该技能在 keymap 中实际配置过的 unit(例如治疗技能可能有 1-30,而形态/自身技能往往只有 0),切换技能后非法的旧目标会被清空。职业选“任意 (*)”时回退读取 keymap/keymap.json。旧模块中不在 keymap 里的技能,或自定义技能下的目标值,会保留为额外下拉选项,不会丢失。
判断条件支持:
- 状态字段:
生命值 < 50、战斗时间 > 0。 - 技能字段:
spells.圣疗术 == 0。 - 队伍字段:
group.1.生命值 < 60。 - 组合条件:
生命值 < 50 && spells.圣疗术 == 0、目标类型 == 1 || 首领战 > 0。 - 布尔简写:直接写字段名表示“为真”,前面加
!表示“为假”,例如战斗、!移动。 - 条件留空表示始终命中。
字符串字面量可用单引号或双引号包裹;true/yes/是、false/no/否、null/nil/空 会被识别为对应的布尔值或空值。
可视化条件编辑器
模块页规则表的“条件”列为只读,单击单元格会弹出条件编辑窗口(在新行占位符上点击并保存后会自动追加一条规则)。窗口中每行是一个比较项:
- 连接:第二行起可选
且(&&)或或(||),决定与上一行的组合方式。 - 字段:下拉菜单,内容来自
config目录并按模块当前选中的职业/专精过滤;技能字段以技能: 名称显示(保存为spells.名称)。原条件中不在目录里的字段(如group.1.生命值或手写字段)会保留为“自定义”项,不会丢失。 - 判断:数字字段提供
==、!=、>、>=、<、<=;布尔和字符串字段只提供==、!=。 - 值:按字段类型自适应——数字字段用数字输入框,布尔字段用
是/否下拉,字符串和自定义字段用文本框。 - 每行末尾有删除按钮,底部有“添加条件”按钮和生成表达式的实时预览。
注意:表达式中 && 的优先级高于 ||(先算“且”再算“或”),编辑器按此语义把行序列分组,不支持括号嵌套。布尔简写(如 战斗、!移动)在编辑器中会归一化为显式比较(战斗时间 > 0、移动 == false),含义不变。关系比较(>、< 等)遇到缺失或非数字的值(如未解析的动态单位字段)时视为“不命中”,不会报错中断。
动态单位与数量字段
模块页规则表上方有“动态单位 / 数量字段”面板。这些是按 group 队伍状态每帧实时解析的命名对象,逻辑移植自旧 Python 项目 utils.py,统一只统计 职责 != 0 的单位、生命值 0 视为死亡跳过、阈值表示只考虑 0 < 生命值 < 阈值。
- 动态单位(可作目标,也可在条件引用):解析为一个队伍槽位(
1~30)。选择器类型包括——生命值最低、按职责取首/末、按职责且不带某光环、带某光环(持续最久)、带某驱散类型。选择生命值最低后,可在新的“光环筛选”下拉里继续选择不筛选光环、带任一光环、不带某光环、带某光环或某光环值等于。参数(血量阈值、职责、光环、光环值、驱散类型等)按所选类型自适应显示,光环候选来自当前职业/专精的group字段,并排除生命值、职责、驱散这类基础字段。编辑弹窗在第二行显示“名称”,选择生命值最低时还会显示“值名称”:填了之后,该单位解析槽位的“生命值”会暴露成一个同名数值条件字段——如取名最低血量后条件可直接写最低血量 < 50(等价于单位名.生命值 < 50);单位未解析时该字段视为缺失(关系比较不命中)。 - 数量字段(仅条件可用):解析为一个整数。类型包括
低于阈值的人数、不带某光环且低血的人数、拥有某光环的人数。
定义后:
- 在规则表“目标”列的下拉里会出现动态单位名,选它即表示“对运行时解析出的那个槽位施法”。运行时若该选择器没选中任何单位(如没人掉血),该规则会被跳过,继续判断下一条。
- 在“条件”里可引用:裸
单位名(解析到槽位即为真,可用于存在性判断)、单位的“值名称”(数值,等于该单位的生命值)、以及数量名(如低血量人数 >= 3)。这些会出现在可视化条件编辑器的字段下拉中;单位名.字段(如最低血量单位.生命值 < 50)仍可手写,但不会展开进下拉列表。
模块 JSON 中以 Units、Counts 数组保存(单位的值名称存为 HealthName,未填则省略),规则用 UnitName 字段引用动态单位(与原有数字 Unit 互斥)。旧模块没有这些键也能正常加载。名称与值名称不能为纯数字、不能含 . 或 $,且不能与现有状态/队伍字段或其它单位/数量名重复。
默认逻辑
如果没有任何匹配的模块,程序会回退到 LogicRegistry.cs 中按职业 ID 注册的 C# 逻辑;若该职业也没有注册逻辑,则使用 DefaultClassLogic:当状态字段 一键辅助 == 10 且 keymap 中存在 一键辅助 时发送对应按键,否则提示“C# 职业逻辑尚未迁移”。
你可以在 module 文件夹中放置一个匹配字段全部留空的模块作为通配模块,让它在任何职业下都能命中,从而替代上述默认逻辑。
迁移职业逻辑
如果逻辑可以用简单条件表达式描述,优先在 UI 的 模块 页维护;如果需要复杂算法,再迁移为 C# 职业逻辑。
新增 C# 职业逻辑时,建议新建一个实现 IClassLogic 的类:
public sealed class PriestLogic : IClassLogic
{
public LogicDecision Run(GameState state, string? specName)
{
var health = state.GetInt("生命值");
return new LogicDecision(null, $"当前生命值: {health}", new Dictionary<string, object?>());
}
}
然后在 LogicRegistry 中按职业 ID 注册:
_logicByClass[5] = new PriestLogic();
逻辑内可以通过 GameState.GetInt(...)、GameState.GetBool(...)、state.Spells、state.Group 读取状态,并返回 LogicDecision:
Hotkey:需要发送的按键;为空则不发送。Step:当前逻辑步骤,会显示到 UI 和日志中。UnitInfo:诊断信息,会显示在逻辑页。ModuleName:命中的模块名(C# 逻辑通常留空,由模块逻辑填写)。