mirror of
https://github.com/waynebian01/Shigure.git
synced 2026-09-02 22:39:01 +08:00
295 lines
22 KiB
Markdown
295 lines
22 KiB
Markdown
# Shigure
|
||
|
||
Shigure 是荒坂公司(Arasaka Corporation)开发的冲锋枪。有时人们只想把子弹全打出去,在硝烟过后品味眼前的一片狼藉。
|
||
|
||
### 仓库已内置冬月电子(Fuyutsuki Electronics)的 Fuyutsui 插件源码,无需另行下载或手动安装。
|
||
|
||
# 免责声明 (Disclaimer)
|
||
|
||
1. **合规责任**
|
||
|
||
Shigure 仅供技术研究、学习交流和个人实验使用。下载、安装、复制、修改、分发或使用本软件前,用户应自行确认相关行为符合所在地法律法规,以及目标软件、游戏平台或服务提供商的用户协议、服务条款和社区规则。
|
||
|
||
2. **账号与处罚风险**
|
||
|
||
本软件可能涉及窗口状态读取、按键发送或自动化辅助流程。此类行为可能被游戏运营商、反作弊系统或相关服务提供商认定为违规,并导致账号限制、角色封禁、数据丢失、收益回收或其他处罚。用户应充分了解并自行承担全部风险,开发者不对由此产生的任何后果负责。
|
||
|
||
3. **无担保声明**
|
||
|
||
本项目基于 MIT License 开源发布,详见 [LICENSE](LICENSE)。软件按“原样”(AS IS)提供,不对稳定性、准确性、完整性、安全性、兼容性、持续可用性或特定用途适用性作出任何明示或暗示保证。因使用或无法使用本软件导致的直接、间接、偶然、特殊或后续损失,均由用户自行承担。
|
||
|
||
4. **商业使用与衍生版本**
|
||
|
||
MIT License 允许在遵守许可证条件的前提下复制、修改、分发和商业使用本软件。任何第三方对本软件或其衍生版本的运营、销售、推广、技术支持或其他商业利用,均由该第三方独立负责。开发者不代表、不授权或保证任何第三方产品、服务或运营活动,也不对第三方的违法行为、违反平台规则的行为或由此产生的后果负责。
|
||
但本声明不限制适用法律所规定的责任,也不构成对任何具体行为合法性的保证。
|
||
5. **使用即表示接受**
|
||
|
||
使用者应在使用前阅读并理解本免责声明及 MIT License。开始使用本软件,表示使用者已获得必要授权,并将自行承担使用本软件产生的风险;但仅通过使用行为是否构成法律上的合同接受,应以适用法律及实际使用场景为准。
|
||
|
||
## 项目简介
|
||
|
||
Shigure 是一个 Windows WinForms 桌面程序。它从目标窗口读取 Fuyutsui 绘制的像素状态,按职业 keymap 和模块规则选择按键,并在界面中展示状态、光环、技能、队伍、动态单位、逻辑结果和运行日志。
|
||
|
||
程序采用单实例运行;再次启动时会提示“Shigure 已经在运行”,随后退出新实例。
|
||
|
||
当前版本:`1.2.1.20`
|
||
|
||
## 主要功能
|
||
|
||
- 扫描 510 格顶部状态行、左侧计数条和队伍治疗吸收数据。
|
||
- 按职业、专精、队伍类型和英雄天赋自动匹配模块,也可手动锁定符合条件的模块。
|
||
- 使用可视化编辑器维护规则、主/子条件、动态单位、数量字段、条件动态数值和公式动态数值。
|
||
- 以内置 `Fuyutsui/` 为权威源编辑职业配置与宏,并按 SHA-256 将插件部署到已运行游戏的 `Interface\AddOns\Fuyutsui`。
|
||
- 支持 `switch`、`click`、`hold` 三种触发模式,以及除 `ALT` 外的键盘按键、`XBUTTON1`、`XBUTTON2`。
|
||
|
||
## 界面
|
||
|
||
- 置顶浮动条:显示程序名、当前职业图标颜色和逻辑状态,提供 `开启/关闭`、`设置`、`✕` 按钮。窗口可拖动和缩放,显示后自动启动运行循环。
|
||
- `通用`:设置触发键和发送模式;从项目 Fuyutsui 更新配置并同步游戏插件;按实时环境选择模块,或按职业、专精、英雄天赋和队伍类型指定默认模块;从 GitHub 按需下载或更新技能/物品图标数据包。
|
||
- `配置`:直接编辑项目 `Fuyutsui/class/*.lua` 中的 `ClassBlocks`,包括状态、光环、冷却(技能冷却与当前专精物品冷却)和队伍字段;技能列表页可编辑 `Fuyutsui.spellsList` 中索引 1–100 的法术 ID、索引和名称,也可从技能数据库添加;物品列表页编辑职业级 `Fuyutsui.itemsList`(`[itemId] = { index, name }`,允许同名、禁止同 ID),并可从全量物品数据库添加。旧版稀疏索引格式只读,需先迁移到 `states/auras/spells/items/group` 格式。
|
||
- `宏`:编辑项目 `Fuyutsui/core/classmacros.lua` 中各职业的动态宏、静态宏和特殊宏。动态宏每项占用 30 个团队点名槽位;特殊宏的技能名必须手工填写,不从宏正文解析,生成映射时固定为无目标、无宏条件。
|
||
- `模块`:新建、编辑、删除本地模块,维护作者、推荐天赋、匹配条件、动态字段和有序规则。规则支持拖拽、上移、下移、复制与插入。
|
||
- `状态`:分栏显示基础状态、`auras`、`spells` 和模块计算出的动态单位/数值。
|
||
- `队伍`:显示 `group` 中当前队伍成员及扫描字段摘要。
|
||
- `逻辑`:显示命中模块、目标、按键和调试值。
|
||
- `日志`:记录启动、停止、职业识别、模块匹配、逻辑状态、施放步骤、配置同步和异常。
|
||
- `关于`:显示产品、公司、版本、模块目录、配置目录、免责声明和 MIT 许可证。
|
||
|
||
触发键、发送模式、模块选择、默认模块、模块保存以及配置同步都会按需重启运行循环。窗口位置、大小、主界面横纵布局(两个方向分别保存窗口位置)、模块选择、按筛选条件保存的默认模块和表格列宽等 UI 状态保存在我的文档目录 `{MyDocuments}/Shigure/cache/window-state.json`;模块保存在 `{MyDocuments}/Shigure/module`。`cache/` 与模块数据都是本地数据,默认不提交到 Git。
|
||
|
||
## 环境要求
|
||
|
||
- Windows
|
||
- .NET 10 SDK
|
||
- 使用运行和插件部署功能时需要打开目标游戏窗口;Fuyutsui 无需手动安装,Shigure 会在启动或“更新配置”时部署项目内版本
|
||
|
||
## 运行
|
||
|
||
在仓库根目录执行:
|
||
|
||
```powershell
|
||
dotnet run --project .\Shigure.csproj
|
||
```
|
||
|
||
可选启动参数:
|
||
|
||
```powershell
|
||
dotnet run --project .\Shigure.csproj -- --toggle XBUTTON2 --mode switch --logic-ms 100 --render-ms 100
|
||
```
|
||
|
||
- `wow_process.txt`:每行一个目标进程名(可带或不带 `.exe`)。程序使用 Windows Z 顺序中最靠前的候选进程可见顶层窗口,切换窗口后会自动跟随。
|
||
- `--toggle`:触发键,默认 `XBUTTON2`。
|
||
- `--mode`:发送模式,支持 `switch`、`click`、`hold`。
|
||
- `--logic-ms`:逻辑循环间隔,默认 `100` ms,最小 `50` ms。
|
||
- `--render-ms`:UI 刷新间隔,默认 `100` ms,最小 `100` ms。
|
||
|
||
发送模式:
|
||
|
||
- `switch`:按一次开启,再按一次关闭。
|
||
- `click`:每次按下只执行一轮逻辑。
|
||
- `hold`:按住时运行,松开后停止。
|
||
|
||
程序会直接从当前 EXE 所在目录运行,并从该目录读取 `Fuyutsui/`、`config/`、`keymap/` 和 `wow_process.txt`;模块从我的文档目录 `{MyDocuments}/Shigure/module` 读取,UI 缓存写入 `{MyDocuments}/Shigure/cache`。
|
||
|
||
## 构建
|
||
|
||
```powershell
|
||
dotnet build .\Shigure.csproj
|
||
```
|
||
|
||
应用图标为 `Assets\arasaka-icon.ico`。项目会把 `Fuyutsui/**`、`config/*.json`、`keymap/*.json` 和 `wow_process.txt` 复制到输出/发布目录;应用、职业、专精和少量程序专用图标作为嵌入资源打包。完整技能/物品图标库不随发布版分发,用户可在“设置 → 通用 → 下载数据包”中从 GitHub 最新正式 Release 下载到 `data\SpellIcons.shgpack`。缺少数据包时技能图标与添加技能的 spellId 联想保持关闭,但仍可手工编辑技能。仅技能旧包仍可加载技能;物品搜索库关闭,手工编辑物品保持可用。
|
||
|
||
## 项目结构
|
||
|
||
```text
|
||
Shigure.csproj 项目文件与构建资源配置
|
||
App\ 程序入口、启动参数和依赖组装
|
||
UI\ WinForms 主界面、配置/宏/模块编辑器和主题
|
||
Runtime\ 像素扫描、状态构建、运行循环和快照
|
||
Modules\ 模块模型、匹配、条件、公式和动态字段
|
||
Input\ keymap 读取、按键发送和 Win32 API
|
||
Infrastructure\ 配置服务、Lua 读写、Fuyutsui 转换和路径定位
|
||
Assets\ 应用图标、品牌资源、职业图和专精图
|
||
Fuyutsui\ 权威插件源码、配置/宏编辑源及游戏部署源
|
||
config\ 由 Fuyutsui 职业配置生成的扫描映射
|
||
keymap\ 由 Fuyutsui 职业宏生成的按键映射
|
||
module\ 模块示例模板(运行时模块保存在我的文档目录 `{MyDocuments}/Shigure/module`)
|
||
SpellIconPackage\ 本地技能/物品图标数据包清单、构建与修复工具(Git 忽略)
|
||
Tools\ 辅助脚本
|
||
```
|
||
|
||
`SpellIconPackage/` 中保存数据包源清单、本地构建工具和生成的
|
||
`SpellIcons.shgpack`;整个目录由 `.gitignore` 排除,不提交到仓库。完整包在 v1 技能索引后追加物品扩展段;仅技能旧包可被新版读取,此时只禁用物品搜索库。
|
||
|
||
## Fuyutsui 配置同步
|
||
|
||
项目目录中的 `Fuyutsui/` 是唯一权威源。`通用` 页的“更新配置”会读取:
|
||
|
||
- `Fuyutsui\class\*.lua` → `config/*.json`
|
||
- `Fuyutsui\core\classmacros.lua` → `keymap/*.json`
|
||
|
||
如果 EXE 所在目录的 `config/` 或 `keymap/` 缺失或文件不完整,启动 Shigure 时会先从上述 Fuyutsui 源文件自动补齐;新建 `config/` 时也会生成运行时必需的 `common.json`。转换完成后会刷新模块编辑器的字段/keymap 目录并重启运行循环,同时递归同步整个插件到当前游戏的 `Interface\AddOns\Fuyutsui`。启动 Shigure 时也会执行同一全量同步:缺失文件会创建,SHA-256 不同的文件会覆盖,相同文件会跳过,游戏目录中的额外文件会保留。
|
||
|
||
`配置` 页和 `宏` 页保存时先写入项目内 Lua、重新生成 config/keymap,再只把当前修改的 Lua 文件部署到游戏目录。找不到游戏或目标文件不可写时,本地保存不会回滚;界面和日志会提示游戏同步未完成,可在游戏启动后再次点击“更新配置”。
|
||
|
||
### 插入法术与插入物品命令
|
||
|
||
游戏内可使用 `/fu i 技能名称或spellId` 临时写入“插入法术”状态。例如 `/fu i 奥术洪流` 保留按名称查询,`/fu i 232633` 则直接按 spellId 精确读取当前 `Fuyutsui.spellsList` 中的本地序号。该命令只检查 `spellsList`,不检查 `ClassMacros`,也不接受 `target`、`player` 等单位参数;成功后聊天框会显示技能名称、spellId 和本地序号。
|
||
|
||
同样可用 `/fu t 物品名称或itemId` 临时写入“插入物品”状态。例如 `/fu t 鲁莽药水` 按名称查询,`/fu t 241288` 则按 itemId 精确读取当前 `Fuyutsui.itemsList` 中的本地序号。该命令只检查 `itemsList`,不检查 `ClassMacros`;成功后聊天框会显示物品名称、itemId 和本地序号。模块规则中的 `自动插入物品` 会读取该状态并映射到 keymap 中的物品宏。
|
||
|
||
### `config` 结构
|
||
|
||
`config` 描述如何把像素数据翻译成运行时状态。字段对象包含:
|
||
|
||
- `step`:顶部状态行的列索引,支持 `1`~`510`;特殊值 `"bar"` 表示读取左侧计数条,并由 `bar` 指定段索引。
|
||
- `type`:字段类型,支持 `int`、`bool`、`string`。
|
||
|
||
顶部状态行由 Fuyutsui 绘制为 510 个色块。Shigure 按两段颜色协议解码:`1`~`255` 使用 `(0, i / 255, b, 1)`,`256`~`510` 使用 `(1 / 255, (i - 255) / 255, b, 1)`,蓝色通道 `b` 是该 `step` 的原始值。左侧 `"bar"` 标记行使用独立计数条协议。
|
||
|
||
`common.json` 保存固定启动字段 `锚点`、`职业`、`专精`。其余文件按英文职业名命名,例如 `Warrior.json`、`Priest.json`,每个文件包含:
|
||
|
||
- `keymap`:该职业使用的 keymap 文件名。
|
||
- `一键法术`:状态中的本地技能索引到 spellId 的映射。
|
||
- `一键物品`:状态中的本地物品索引到 itemId 的映射。
|
||
- 以专精 ID 为键的对象,包含普通状态与物品字段,以及可选的 `auras`、`spells`、`group`。
|
||
|
||
运行时先读取 `common.json` 确定职业和专精,再合并对应专精配置。`group.start` 是队伍数据起始列,`group.num` 是每名成员占用的列数;组内字段的 `step` 是相对偏移。
|
||
|
||
### `keymap` 与单位编号
|
||
|
||
每条 keymap 记录包含 `unit`、`技能`、`热键` 和可选的 `宏条件`。模块和 keymap 共用以下单位编号:
|
||
|
||
- `0`:无目标。
|
||
- `1`~`30`:队伍/团队槽位。
|
||
- `31`:玩家。
|
||
- `32`:当前目标。
|
||
- `33`:焦点。
|
||
- `34`:地面。
|
||
- `35`:鼠标指向。
|
||
|
||
当前映射版本为 `UnitMappingVersion = 3`。版本 1 模块会迁移旧的 `31/34` 含义;版本 2 模块中的 `36/37` 会迁移为 unit 0,并分别补成 `channeling` / `nochanneling` 宏条件。
|
||
|
||
## 模块系统
|
||
|
||
模块以 `模块名.json` 保存在我的文档目录 `{MyDocuments}/Shigure/module`。名称不能重复;加载时会递归扫描子目录,以兼容旧版布局。模块页保存时会写入当前 Shigure 版本。模块的 `Version` 必须与当前软件版本完整一致才会参与依赖导入、模块选择和运行;版本不一致或为空的模块仍在编辑器列表中显示为红色,可在检查并显式保存后升级到当前版本。职业和专精均已指定时,模块还会携带该专精的 `ClassBlocks`、职业 `spellsList`,以及该职业的通用/专精动态宏、静态宏和特殊宏。
|
||
|
||
启动和“刷新模块”会把模块携带而本地缺少的配置与宏追加到项目 `Fuyutsui/`。光环、法术和技能列表都以 `spellId` 判断同一条目,不再按名称回退:光环任一 ID 重合即合并 ID 集合,`maxApps` 仅补本地空值;法术的布尔属性采用 true 补齐 false,最大充能和施法次数仅补本地空值;双方都有不同值时保留本地并提示冲突。技能列表同一 spellId 保留本地索引和名称,缺失 spellId 按模块快照追加,允许多个 spellId 共用同一索引。队伍依赖快照只为模块文件兼容保留,读取时不比较、不导入,也不修改本地队伍配置。发生新增后会自动重建 `config/keymap`、同步游戏插件并按需重启运行。导入前会按每项动态宏 30 个槽位、静态/特殊宏各 1 个槽位检查该职业所有受影响专精;合并结果超过 350 个槽位时,整个模块不会进入模块列表或运行时,本地 Lua 也不会被修改。模块文件仍保留在模块目录,清理宏后可刷新重试。
|
||
|
||
模块匹配字段:
|
||
|
||
- `ClassId`:职业 ID。
|
||
- `SpecId`:专精 ID。
|
||
- `PartyType`:`0` 为单人、`1-40` 为团队、`46` 为队伍。
|
||
- `HeroTalent`:英雄天赋 ID。
|
||
|
||
任一字段留空(界面显示 `任意 (*)`)即为通配。多个模块同时匹配时,优先选择具体匹配字段更多的模块,相同则按名称排序。`RecommendedTalent` 仅用于说明,不参与匹配。
|
||
|
||
模块文件示例:
|
||
|
||
```json
|
||
{
|
||
"Id": "戒律-20260730120000000",
|
||
"Name": "戒律",
|
||
"Author": "模块作者",
|
||
"RecommendedTalent": "推荐天赋代码或说明",
|
||
"Version": "1.2.1.17",
|
||
"UnitMappingVersion": 3,
|
||
"Enabled": true,
|
||
"Match": {
|
||
"ClassId": 5,
|
||
"SpecId": 1,
|
||
"PartyType": "46",
|
||
"HeroTalent": 1
|
||
},
|
||
"Units": [],
|
||
"Counts": [],
|
||
"ValueAdjustments": [],
|
||
"Rules": [
|
||
{
|
||
"Enabled": true,
|
||
"Condition": "生命值 < 50 && spells.17.cooldown == 0",
|
||
"Unit": 31,
|
||
"Spell": "真言术:盾",
|
||
"Hotkey": "",
|
||
"Step": "自保"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
规则按顺序判断,第一条命中的规则会执行。普通动作的 `Spell` 保存并使用“技能”列中的技能或宏名称,不用 spellId 判断;运行时按名称、目标单位和宏条件查找 keymap 热键。填写 `Hotkey` 时会直接发送该键。技能下拉还包含以下特殊动作:
|
||
|
||
- `暂停`:命中后不发送按键,并停止继续匹配本轮后续规则。
|
||
- `自动插入法术`:读取状态字段 `插入法术`,按职业配置映射到当前可用技能。
|
||
- `自动插入物品`:读取状态字段 `插入物品`,按职业 `itemsList` 映射到当前可用物品宏。
|
||
- `一键法术`:读取状态字段 `一键辅助`,按职业配置映射到技能。
|
||
|
||
### 条件
|
||
|
||
支持的常见表达式:
|
||
|
||
- 状态:`生命值 < 50`、`战斗时间 > 0`。
|
||
- 玩家光环:`auras.player.114255.value > 0`;层数使用 `.apps`。
|
||
- 目标/焦点光环:`auras.target.harmful.55078.value > 0`、`auras.focus.helpful.12345.value > 0`。
|
||
- 技能:`spells.633.cooldown == 0`;充能冷却和层数分别使用 `.chargeCooldown`、`.count`。
|
||
- 队伍:`group.1.生命值 < 60`。
|
||
- 列表:`目标类型 in (1, 2)`、`职业 not in (4, 9)`。
|
||
- 组合:`生命值 < 50 && spells.633.cooldown == 0`、`目标类型 == 1 || 首领战 > 0`。
|
||
- 布尔简写:`移动` 表示为真,`!移动` 表示为假。
|
||
- 空条件:始终命中。
|
||
|
||
`一键辅助`、`插入法术`、`施法技能`、`上个技能` 是技能列表索引状态。可视化编辑器为这些字段提供“技能图标 / 技能名称 / spellId”下拉,并且只允许 `==`、`!=`;模块条件保存 spellId,运行时按当前职业的 `spellsList` 把 spellId 转换为本地索引后再比较,因此模块不依赖来源职业文件中的索引分配。找不到 spellId 时,该条件行和所属规则行显示为红色,条件按不命中处理。
|
||
|
||
`插入物品` 是物品列表索引状态。可视化编辑器提供“物品图标 / 物品名称 / itemId”下拉,并且只允许 `==`、`!=`;模块条件保存 itemId,运行时按当前职业的 `itemsList` 把 itemId 转换为本地索引后再比较。找不到 itemId 时同样显示为红色,条件按不命中处理。
|
||
|
||
生成的 `config/*.json` 和运行时状态使用“范围 + spellId + 数值类型”的结构化键;字段节点中的 `displayName`、`spellId`、`scope`、`metric` 和 `spellIds` 仅用于显示及别名解析。多 ID 光环优先使用单值 `spellId`,否则使用最小有效 ID 作为规范键,其余 ID 映射到同一运行时值。普通条件、子条件、动态数值、公式、动态单位和人数统计均持久化 spellId;缺失引用会保留原 ID、显示红色并按不命中处理。
|
||
|
||
字符串可以使用单引号或双引号。`true/yes/是`、`false/no/否`、`null/nil/空` 会转换为对应字面量。`&&` 的优先级高于 `||`,主表达式不支持括号嵌套。
|
||
|
||
规则还可添加多个“子条件”:主条件与子条件组是“且”关系,子条件之间是“或”关系,即 `主条件 && (子条件 1 || 子条件 2)`。这用于表达主编辑器无法用括号表示的逻辑。
|
||
|
||
可视化条件编辑器会按当前职业/专精提供状态、光环、冷却(技能/物品)和动态单位字段,并支持:
|
||
|
||
- 数字比较 `==`、`!=`、`>`、`>=`、`<`、`<=`。
|
||
- 文本/数字列表比较 `in`、`not in`。
|
||
- `延迟 (ms)`:限制同一规则两次实际发送的最小间隔。
|
||
- `逻辑延迟 (ms)`:发送后暂停逻辑扫描指定时间;触发键检测和界面刷新仍继续。
|
||
|
||
缺失或非数字字段参与大小比较时视为不命中,不会中断运行。
|
||
|
||
### 动态单位、数量与动态数值
|
||
|
||
这些字段按 `group` 状态每帧重新计算。多数动态选择与数量统计会跳过 `职责 == 0` 的单位;具体生命值过滤取决于字段类别。
|
||
|
||
- 动态单位:可按最低生命值、最高治疗吸收、职责、光环、光环值或驱散类型选择 `1`~`30` 的队伍槽位。最低生命值使用“扫描生命值减去治疗吸收”的结果,允许结果为 0 或负数,并在所有 `生命值 < 阈值` 的候选中取最低值。动态单位可在规则目标中直接使用,也可用裸名称判断是否成功解析。
|
||
- 数量字段:统计低于生命值阈值、高于治疗吸收阈值或带/不带指定光环的单位数,只能用于条件。其中低生命数量仍只统计 `0 < 生命值 < 阈值` 的单位。
|
||
- 条件动态数值:条件成立时对已有状态、光环、技能或动态字段加减一个整数。
|
||
- 公式动态数值:使用字段和算术表达式生成命名数值,支持 `+ - * /`、括号、一元正负号和 `int`、`round`、`floor`、`ceil`、`min`、`max`。
|
||
|
||
动态单位和数量阈值既可使用固定值,也可引用其它动态数值。规则引用未解析出的动态目标时会跳过该规则,继续判断下一条。
|
||
|
||
模块 JSON 使用 `Units`、`Counts`、`ValueAdjustments` 保存这些定义;规则使用 `UnitName` 引用动态单位。名称不能是纯数字,不能包含 `.` 或 `$`,也不能与已有状态字段或其它动态名称冲突。
|
||
|
||
## 默认逻辑与 C# 扩展
|
||
|
||
如果没有匹配模块,`LogicRegistry` 会尝试使用按职业注册的 `IClassLogic`。当前没有注册项时会进入 `DefaultClassLogic`:仅当 `一键辅助 == 10` 且 keymap 中存在 `一键辅助` 时发送按键,否则显示“C# 职业逻辑尚未迁移”。
|
||
|
||
通常应优先在 `模块` 页维护逻辑。确实需要复杂算法时,可实现 `IClassLogic` 并在 `LogicRegistry` 中按职业 ID 注册:
|
||
|
||
```csharp
|
||
public sealed class PriestLogic : IClassLogic
|
||
{
|
||
public LogicDecision Run(GameState state, string? specName)
|
||
{
|
||
var health = state.GetInt("生命值");
|
||
return new LogicDecision(
|
||
Hotkey: null,
|
||
Step: $"当前生命值: {health}",
|
||
UnitInfo: new Dictionary<string, object?>());
|
||
}
|
||
}
|
||
```
|
||
|
||
职业逻辑可通过 `GameState.GetInt(...)`、`GameState.GetBool(...)`、`state.Auras`、`state.Spells`、`state.Group` 读取数据,并返回 `LogicDecision`。也可以创建匹配字段全部留空的通配模块,覆盖默认逻辑。
|