找回密码
 注册/Sign up
搜索
查看: 72|回复: 4

[LUA] GM 命令 + 对话框菜单 + 自动战斗

[复制链接]

发表于 昨天 13:20 | 显示全部楼层 |阅读模式
用claude写的脚本,常用的功能都加上了,支持各种中文检索。自动战斗根据不同职业技能定制了策略,特别是法师,可以根据敌人的数量/属性/种族智能选择合适的魔法和攻击对象。还添加了智能补血和宠物策略,应该是做过的最智能的自动战斗了。

适用:cgmsv(CrossGate 服务端)。开发和测试的版本是 **26.8d**(整合包里 `更新说明.txt` 记载的最新版本)。
自动战斗用到的事件 `AutoBattleCommandEvent` 是 cgmsv 25.9i 加入的,比这更老的版本肯定不能用;更老的版本里别的功能(比如 `Char.SwitchBag` 是 24.10e 加入的)也可能缺,我只在 26.8d 上测过。

---

## 目录

1. 包里有什么
2. 【先看】警告与权限
3. 安装
4. 依赖的配置和数据
5. gmTools 命令大全
6. /menu 对话框菜单
7. 自动战斗
8. 测试情况和已知限制
9. 常见问题
10. 附录

---

## 1. 包里有什么

| 文件(放在服务端的 `gmsv/lua/Modules/` 下) | 作用 |
|---|---|
| `gmTools.lua` | 一组 GM 快捷命令(给物品、改等级、传送、卖东西、改宠物……)和 `/menu` 对话框菜单 |
| `autoBattle.lua` | 自动战斗的核心:事件、下指令、重试、`/auto` 命令 |
| `autoBattleTactics.lua` | 自动战斗的各职业技能策略、补血、魔法选法。**必须和 `autoBattle.lua` 一起用** |

- `gmTools.lua` 可以单独用。
- `autoBattle.lua` 和 `autoBattleTactics.lua` 是一对,更新时两个文件一起换。缺了后者,自动战斗只剩"重复上回合",日志里会有 tactics 加载失败的错误。
- 菜单里的"自动战斗"那一页依赖 `autoBattle` 已经加载,没加载就不显示。

## 2. 【先看】警告与权限

1. **gmTools 没有任何权限检查**:只要模块加载了,**所有玩家**都能用所有命令(`/item`、`/gold`、`/lv`、`/pet make`……)。它是为单机、自己一个人玩的私服写的。**多人服务器不要直接用**,要么不装,要么按下面 2.1 加上管理员检查。
2. 这些命令会直接改角色数据(金币、等级、背包、宠物、技能、职业)。用之前先备份服务端目录(至少备份 `gmsv/` 整个目录)。
3. 三个文件的编码是 **GBK + CRLF 换行**,和引擎自带的 Lua 文件一样。**不要用 UTF-8 保存**,也不要让编辑器改换行。用记事本、VS Code 等直接打开保存可能改掉编码,建议用能保持 GBK 的编辑器(比如 Notepad++,编码选"ANSI"),或者只复制不修改。

### 2.1 给 gmTools 加管理员检查(可选)

打开 `gmTools.lua`,找到 `function GM:onTalk`,在 `if not fn then return 1 end` 后面加三行:

```lua
function GM:onTalk(charIndex, msg, color, range, size)
  local command = msg:match('^/(%w+)')
  local fn = command and commands[command]
  if not fn then
    return 1
  end
  -- 下面三行是新加的: 不是管理员的玩家, 命令当普通聊天处理
  local admin = getModule('admin')
  if not (admin and admin:isAdmin(charIndex)) then
    return 1
  end
  ...
```

- 这用的是整合包自带的 `admin` 模块的 `isAdmin`(`admin.lua` 里 `gmList` 里的账号、或带 GM 标记的角色)。
- 没装 `admin` 模块时,这样改以后**谁都不能用** gmTools(宁可不能用,也不放开)。
- 我在模拟环境里验证过这个改法:管理员正常使用,非管理员的命令被放行成普通聊天,原有功能不受影响。没有在真服务端上测。
- `/auto`(自动战斗)只改玩家自己的设置,没有加检查。

## 3. 安装

1. 把三个 `.lua` 文件复制到 `gmsv/lua/Modules/`。
2. 编辑 `gmsv/lua/ModuleConfig.lua`,在末尾加两行:
   ```lua
   loadModule('autoBattle')
   loadModule('gmTools')
   ```
   `autoBattleTactics.lua` 不用写进去,`autoBattle` 启动时自己读它。
3. 重启服务端。也可以不重启,用管理员命令热重载:`/module reload autoBattle`、`/module reload gmTools`。
4. 进游戏验证:
   - `/me` → 聊天框显示自己的 charIndex、账号、位置;
   - `/menu` → 弹出"菜单"窗口;
   - `/auto status` → 显示自动战斗当前状态。

## 4. 依赖的配置和数据

gmTools 会读 `gmsv/cgmsv.cf` 里的这几项来给出上限:

| 配置项 | 含义 | gmTools 怎么用 |
|---|---|---|
| `fevermax` | 最大卡时(小时) | `/clock add` 加到这个值为止 |
| `maxgoldhave` | 最大持有金币(单位:万) | `/gold` 写多了设成上限 |
| `extbagpage` | 扩展背包页数,0 = 只有一页 | 开了就一页一页处理背包 |
| `maxskilllevel` | 技能等级上限 | 本包按 15 级设计(整合包默认 15) |

数据文件用的都是整合包自带的(`data/` 下的地图名、传送点、宠物、技能、职业、配方等),没有另外的数据依赖,**只有一个例外**:

**`data/skillexp.txt` 必须有 15 级的经验**。每行是:表号 + Lv1…Lv15 的累计经验 + 末尾一个 `9999999`,一共 17 个数字,用制表符分隔。我拿到的整合包里每行只有 13 级,`maxskilllevel=15` 时引擎启动会报:

```
[错误]skill/skill.c:999 数据不足 所在文件:./data/skillexp.txt 所在行1…7
```

`/skill` 设等级时也要读这张表来算对应的经验。补全后的整张表在附录 A,**Lv14、Lv15 是我按前面的增长曲线推算的,不是官方数据**。

## 5. gmTools 命令大全

**通用约定**
- 宠物栏、技能位置一律**从 0 数起**(和游戏原生命令一致)。技能位置是界面上从上到下的名次。
- 写名字的地方,名字里含这几个字就能匹配;匹配到多种东西时不会乱选,会列出来让你写完整名字或 id。匹配按"字"的边界,不会把相邻两个汉字的字节拼成第三个字(GBK 的坑)。
- 命令名避开了整合包里 `admin`、`adminCommands` 已有的聊天命令(它们在 gmTools 之前处理聊天,同名会被它们吞掉)。如果你装了别的模块,注意别重名。
- 出错时聊天框会说"命令出错,见服务端日志",日志里有详细错误。

### 5.1 自己的信息、卡时、金币、回血

| 命令 | 作用 |
|---|---|
| `/me` | 显示游戏里看不到的信息:charIndex、账号、宠物 index、位置(mapType floor x y) |
| `/clock` | 打卡开/关切换,并显示剩余卡时 |
| `/clock add <小时>` | 加卡时(可以写小数),最多加到 `fevermax`。加完要重新打卡或重新登录,界面才显示新值 |
| `/gold [数字]` | 不写看金币;写了就把金币设成这个数,最多到 `maxgoldhave`。最后读回实际值告诉你 |
| `/heal` | 人和宠物回满血魔,并清除受伤 |

### 5.2 等级、属性、技能、职业、形象

| 命令 | 作用 |
|---|---|
| `/lv [等级]` | 显示/改等级(只做人):经验设成这一级需要的最少总经验,升级点按每级 4 点加减 |
| `/stat [属性 值 …]` | 显示/直接设:体力、力量、强度、速度、魔法(界面数值,内部乘 100)、耐力、灵巧、智力、升级点。例:`/stat 体力 100 力量 50` |
| `/skill` | 列出自己的技能:位置、名字、等级、经验 |
| `/skill <id或名字> [等级1-15]` | 学新技能,默认 1 级、经验 0(界面显示 0/1800 这样)。已经有了:不写等级只提示;写了等级就把等级和对应经验一起改 |
| `/skill del <位置或名字>…` | 删技能,可以写多个 |
| `/job` | 显示当前职业(名字、id、职类、职阶) |
| `/job <职业id>` | 换职业(id 里已带阶,11-17 是士系从见习剑士到剑圣,481 是超级职;id 见 `data/jobs.txt` 第 3 列),自动改职类和职阶 |
| `/job <中文名> [阶0-6]` | 按名字换:名字和职业名完全一样就是它;否则当基础职业取这个职系的第 0 阶;写了阶(从 0 数起)取对应阶。例:`/job 剑士 3` |
| `/image <形象编号\|宠物中文名\|reset>` | 改自己的形象,reset 还原 |

注意:
- 换成别的职业后,该职业上限为 0 的技能会显示 0 级(比如牧师、魔导士的气功弹、崩击、连击),这是引擎按职业上限算的,不是 bug。
- `/lv`、`/stat` 只做人;宠物的成长引擎自己算,没法精确模拟,所以不做。
- `/skill` 的经验按技能自己的经验表算(`data/skill.txt` 第 10 列决定用 `skillexp.txt` 的哪一行:标准、减半、3/4……)。

### 5.3 宠物

| 命令 | 作用 |
|---|---|
| `/pet` | 列出身上的宠物:栏号 0-4、名字、等级、每项掉几档 |
| `/pet <栏>` | 这只宠物的详细资料:种类 id、地水火风属性、每项成长值/满档值、形象 |
| `/pet <栏> skill` | 列出这只宠物的技能 |
| `/pet <栏> skill <techId或名字>` | 加技能(名字见 `data/tech.txt`) |
| `/pet <栏> skill del <技能栏>…` | 按技能栏号删,可写多个 |
| `/pet <栏> image <形象编号\|宠物中文名\|reset>` | 改宠物形象 |
| `/pet del <栏…\|all>` | 删除宠物,可写多个栏,`all` 是全部 |
| `/pet roll <栏…\|all>` | 重新随机成长:删掉这只,再给一只同种类的 1 级新宠物(栏的写法和 `del` 一样) |
| `/pet find <中文名>` | 按名字查宠物。3 种以内列全部资料(形象、种族、技能栏、五项数值、命中/必杀/闪躲/反击、属性、抗性、出生技能、宠物 id),多了只列数值和 id;只收最低等级是 1 的,同名里有可捕捉的就只列可捕捉的 |
| `/pet make <宠物id或名字>` | 给一只宠物。id 就是 `/pet find` 列出的 id(`data/enemy.txt` 第 3 列);写名字时只认完全相同的,刚好一种就直接给,多种要先 find 再写 id |

`/pet roll` 是"删掉再给",所以不用管宠物栏满没满。

### 5.4 背包、物品、金币相关

| 命令 | 作用 |
|---|---|
| `/item <id或名字> [数量]` | 给物品,数量默认 1。一组放不下引擎自己堆到上限。名字完全相同且只有一个就直接给,否则列出选项让你写 id |
| `/item find <中文名>` | 查物品:名字、id、类型、等级、价格,最多列 10 个;匹配到 3 个以内再列各项修正(攻击/防御/…/抗性)、耐久、水晶属性、说明 |
| `/item del <名字或id> [数量]` | 删背包里这个东西:不写数量 = 所有同名的堆全删;写了数量就只删这么多。名字不完全相同时,含这几个字的刚好是同一种才删。装备栏不动 |
| `/item del all` | 删背包里的全部东西(装备栏不动) |
| `/material <配方名\|配方id> [套数]` | 给做这个东西(装备、料理、药品……)的全部材料,数量 = 一套的数量 × 套数;同名配方多就列出来让你写配方 id |
| `/sort` | 整理背包(引擎自带的 `NLG.SortItem`:合并同名堆叠、排序、集中放到前面) |
| `/sort on\|off` | 战斗结束后自动整理的开关,默认开,每个角色单独记 |
| `/identify [名字或id]` | 鉴定所有没鉴定的东西,写了名字就只鉴定这个。免费:直接把"已鉴定"标记置 1(引擎自己的鉴定函数 Lua 调用不了) |
| `/sell` | 卖掉魔石和怪物卡片(名字以"的卡片"结尾的宠物图鉴卡) |
| `/sell all` | 把背包里所有能卖的都卖了(装备栏不动) |
| `/sell <名字或id>` | 卖这个东西(同名的所有堆) |

**`/sell` 的规矩**(按引擎里这件东西的"贩卖单位"算,不先鉴定,没鉴定的卡片就按现在显示的价格卖):
- 单位是 1 的(魔石):一个一个卖,价格 × 个数。
- 单位是 N 的(印度轻木是 20):一组 N 个、一组一个价格,每一**堆**能凑几组就卖几组,零头留着(38 个卖 20 个,剩 18 个);不满一组不能卖。
- 单位是 0 的(铜条):整堆(满堆叠数)一个价格,不满一堆不能卖。
- 商店不收的(`itemset` 的"可出售"标记是 0)和价格是 0 的不卖。不能卖的都会列出来并说明原因。
- **每一堆单独算,不跨堆合并**。比如印度轻木有 12、28、10、35 四堆,`/sell 印度轻木` 只卖 28 和 35 各 20 个,剩 12、8、10、15。
- 卖零头、删一部分数量时,只改**你选的那一堆**的堆叠数(不用 `Char.DelItem`——它按物品 id 扣,同一种东西有两堆时扣哪一堆是引擎定的,实测会扣到别的堆上)。

`/sort`、`/sell`、`/identify`、`/item del` 会处理所有页的背包:开了扩展背包(`extbagpage`)就一页一页切过去处理,最后切回原来那页。战斗后自动整理只整理当前页。

### 5.5 传送、迷宫、遇敌

| 命令 | 作用 |
|---|---|
| `/goto <中文地名或floor>` | 传到这个地图的入口落点(`warp.txt` 里进入它的记录:优先来源 floor 比它小的城镇外入口;没有就取第一条)。名字完全相同就去,重名会列出选项 |
| `/goto <地名或floor> <x> <y>` | 传到指定坐标;引擎拒绝(坐标不能走)时如实说传送失败 |
| `/goto <x> <y>` | 在当前地图里传到这个坐标(迷宫里也能用)。只写一个数字会被当成 floor,要写就写两个 |
| `/dungeon <迷宫id或名字>` | 传到迷宫入口。入口由引擎 `Map.FindDungeonEntry` 告诉我们,迷宫现在没有生成就找不到;迷宫 id 见 `data/dungeonconf.txt` 第 4 列(例:104 = 奇怪的洞窟) |
| `/encounter` | 原地遇敌(这里不能遇敌会说一声) |
| `/encounter always` | 步步遇敌:每走一步都遇敌(用的是"香"的步数,设成 999 步) |
| `/encounter never` | 步步不遇敌 |
| `/encounter normal` | 恢复正常遇敌(always 和 never 互斥) |

地名例子:`/goto 法兰城医院`("来源 + 地名",来源名字里含"法兰城"的医院)、`/goto 1000 94 78`。

## 6. /menu 对话框菜单

`/menu` 打开主菜单,也可以直达某个分类:`/menu char | pet | item | map | misc | auto`。

菜单是用一个 NPC 弹窗实现的:模块加载时会在 **777 号地图 (0,0)** 创建一个叫 gmTools 的 NPC,所有窗口都从它发出。创建失败时 `/menu` 会提示"界面用的 NPC 没建成,见服务端日志"。

| 分类 | 里面有什么 |
|---|---|
| 人物 | 等级、升级点、属性(体力、力量、强度、速度、魔法、耐力、灵巧、智力八项,直接填数字)、技能(列表,添加、改等级、删除)、职业(先选职系再选阶,也能搜索)、形象 |
| 宠物 | + 获得宠物(搜名字,点结果先看详细资料再确定)、宠物列表;每只宠物:详细、形象、技能、roll、删除 |
| 物品 | + 获得物品(搜名字,看详细 + 输入数量)、+ 配方材料、金币、整理背包(现在整理/战斗后自动整理开关)、鉴定、卖物品、删除物品 |
| 地图 | + 传送到地图(搜地名,确定传入口,或填坐标)、+ 去迷宫、当前地图传到坐标、原地遇敌、步步遇敌、步步不遇敌 |
| 其他 | 回满血魔、打卡、加卡时、我的信息 |
| 自动战斗 | 见第 7 章 |

操作约定:
- 点选项进去;**关闭按钮 = 退回上一级**,一直退到主菜单再关闭就是退出。
- 点列表里的某一项,**只动你点的这一堆/这一个**(卖、鉴定、删除都是这样)。
- 详情窗口:确定 = 执行,关闭 = 离开。带数量的输入框,不写就用默认值(获得物品默认 1 个,删物品默认整堆,配方默认 1 套)。
- 命令和菜单互相独立:菜单是把命令重新组合的界面,没有把每条命令都照搬进去。
- 如果你的客户端支持把快捷键绑到一句话(聊天宏),可以把 `/menu` 绑上去。

**界面的限制**(都是在游戏客户端里实测的):
- **战斗中客户端不显示这个窗口**,战斗里改设置用命令(比如 `/auto`)。
- 窗口是服务端发出的一次性快照,**不会实时刷新**:窗口开着时用命令改了数据,窗口里还是旧值,要点一下任意一项(会重画)或重新 `/menu`。
- 选择框一页最多 8 项,每行最多 44 列(22 个汉字),超出的文字会被截断成 `..`;信息框约 10 行(代码按 9 行用),不能滚动;同一个窗口只能有一个输入框。

## 7. 自动战斗

开了以后,每回合开始等待指令时,脚本替玩家下指令。每个回合的决定顺序:

**补血(魔法优先,其次血瓶,所有角色通用,永远开着) > 当前策略的技能 > 普通攻击**

### 7.1 命令

| 命令 | 作用 |
|---|---|
| `/auto` | 开/关切换 |
| `/auto on`、`/auto off` | 开、关 |
| `/auto <策略id> [模式]` | 选策略并**同时开启**。例:`/auto mage eco`、`/auto fist` |
| `/auto default` | 改回按职业默认的策略(同样开启) |
| `/auto list` | 列出所有人物策略(`*` 是当前的) |
| `/auto status` | 当前状态:开关、策略、补血线、宠物策略 |
| `/auto heal [1-99]` | 看/设补血触发线(血量百分比),默认 60 |
| `/auto pet` | 列出宠物策略 |
| `/auto pet <策略id>` | 选宠物策略;`/auto pet default` 改回默认 |
| `/auto log on\|off` | 诊断日志开关(排查问题用,整个服务端共用,重新加载模块后恢复为关) |

- 设置存在角色自己的扩展数据里,下线也保留。**登录时自动战斗开关会被关掉**,避免带着旧状态进游戏。
- 战斗中窗口弹不出来,所以战斗里改设置用 `/auto` 命令。可以用游戏的快捷键绑定。

### 7.2 人物策略

没有手动选过策略的角色,按职业给默认(职业对了还要**至少学会一个相关技能**,等级大于 0),否则就是"重复上回合"。

| 策略 id | 名字 | 默认给谁(`jobs.txt` 的职业 id) | 技能 | 规则 |
|---|---|---|---|---|
| `repeat` | 重复上回合 | 其他所有人 | 你手动下过的指令 | 回放你手动下的上一回合指令(官方自动战斗的做法)。补血和范围技能每回合重新选最佳目标,其余延续上回合的目标 |
| `mage` | 法师:智能魔法 | 71-77 | 单体/强力/超强陨石、冰冻、火焰、风刃 | 见 7.3 |
| `fist` | 格斗:气功弹 | 141-147 | 气功弹 | 敌人 3 个以上才放;等级按平均打到的个数取刚好够的,不够就取最高级;否则普通攻击 |
| `bow` | 弓箭手:乱射 | 41-47 | 乱射 | 敌人 3 个以上才放;等级取箭数够每个敌人 2 支的最低级(6 个以上用 10 级);否则普通攻击 |
| `heavy` | 重装(剑士/战斧/骑士):追月 | 11-17、21-27、31-37 | 追月 | 敌人 3 个以上才放,点范围内敌人最多的位置(点一个位置打左中右三列 × 前后两排),等级按平均打到的个数取刚好够的;否则普通攻击 |
| `karma` | 饲养师:因果报应 | 101-107 | 因果报应 | 敌人 3 个以上才放,点敌人多的一排,等级用能放的最高级;否则普通攻击 |
| `missile` | 传教/巫师:精神冲击波 | 61-67、131-137 | 精神冲击波 | 同上,点敌人多的一排 |

通用规则:
- **技能等级**:没练到职业上限的技能一律用最高级(要积累经验)。可用等级 = 取下面几个里最小的:技能等级、职业对这个技能的上限(`skilllv.txt`)、人物等级限制(**等级 ÷ 10 取整 + 1**,这是游戏里的规矩,超过的在客户端里是灰的)、魔法最高 10 级。
- **引擎拒绝了某个等级**(比如魔攻不够等没有数据的限制):记下"这场战斗里这个等级及以上放不了",立刻换低一级再下,直到被收下;战斗结束后清掉。
- **选目标**:补血、追月、一排技能、攻击魔法有各自的算法,每回合按场面重选最佳目标;其余指令(普通攻击、气功弹、乱射……)一律"延续上回合的目标,没有或已倒下就选血最少的"。
- 方向(敌方还是己方)看上回合目标在哪一边;只能对自己的技能(防御、圣盾、明镜止水……)和没有目标的原样不动;不能选自己的(护卫、气绝回复……)在己方候选里排除自己。
- 武器不对(技能要求装备)、魔力不够、背包里药没了,都退回普通攻击,每回合重新判断。
- **不带宠物时每回合动 2 次**:脚本决定第 1 个动作,第 2 个动作是普通攻击;只有"重复上回合"原样回放两个动作。带宠物时人 1 次、宠 1 次。

### 7.3 法师的智能魔法和三种模式

候选:单体(技能 19-22)、强力(23-26,十字范围,最多打 4 个)、超强(27-30,打全体),各自的四个元素(地水火风),每个取买得起的最高等级。每个候选估算**总伤害 = 伤害率 × 打到的每个敌人的属性/种族倍率之和**。

数据里三档的关系(每一级都是):伤害率 单体 : 强力 : 超强 = 1 : 0.6 : 0.4(每个敌人),耗魔 1 : 2 : 4。

选法(三种模式用同一个规则,只是"保留率"不同):
1. 基准 = **耗魔最低的那个魔法**(通常是单体;同耗魔取伤害高的)。
2. 每个魔法的门槛 = 基准伤害 × max(1, 保留率 × 该魔法耗魔 ÷ 基准耗魔)。
3. 过了门槛的魔法里,**总伤害最高的**用;一样高用便宜的。基准自己一定过。

| 模式 | 保留率 | 含义 | 强力从几个敌人起 | 超强从几个敌人起 |
|---|---|---|---|---|
| `fast` | 0 | 伤害优先,不管耗魔 | 十字打到 2 个 | 3 个 |
| `normal`(默认) | 0.65 | 均衡:耗魔 2 倍要多打 30%,4 倍要多打 160% | 十字打到 3 个 | 7 个 |
| `eco` | 0.75 | 省魔力:耗魔 2 倍要多打 50%,4 倍要多打 200% | 十字打到 3 个 | 8 个 |

- 表里的数字是**不考虑属性克制、三档都是 10 级**时的结果,有属性克制时只是各魔法的总伤害变了,门槛规则不变。
- 以单体 10 级、强力、超强都有为例:7 个敌人、十字打 4 个时,强力 1732、超强 2023、单体 722;normal 的超强门槛是 722 × 2.6 = 1877,达标且伤害最高,所以放超强;eco 的门槛 722 × 3 = 2166,超强不达标,所以放强力。
- 没学强力时,单体直接到超强(耗魔差 4 倍):normal 7 个敌人起放超强,eco 8 个起;3 到 6 个敌人时用单体。
- 如果耗魔最低的是一个很低级的魔法(比如单体只有 1 级),它每点魔力的伤害更高(1 级 9.5,10 级 7.2),别的魔法要多打一点才达标,超强的起用点会往后推。单体用得多,等级自然会上去。
- 保留率是固定值,不让用户调,用户只选模式。想改的话,在 `autoBattleTactics.lua` 开头的 `MAGIC_KEEP` 表里改:强力要在十字打到 n 个时才放 → 保留率取 `[0.3×(n-1), 0.3×n)`;超强要在 m 个敌人时才放 → 取 `[0.1×(m-1), 0.1×m)`,两个范围要同时满足。

### 7.4 补血

- 触发:有人的血量(加上前面的人已经打算补的)低于补血线(默认 60%,`/auto heal` 改)。
- 补血量 = 角色"回复"属性 × 技能的伤害率 ÷ 100;血瓶 = 回复 × 药的数值 ÷ 100(药名括号里的数,如"生命力回复药(500)")。
- 怎么补:补血魔法优先,其次血瓶。在所有(档位、等级、中心)里选"**实际补上的血最多**"的:每个被盖到的人按 min(补血量, 缺的血) 算;一样多取耗魔少的;方案至少要盖到一个低于补血线的人。补血魔法没练到职业上限的档位只用最高级。
- 血瓶:背包里战斗中可用、对单个我方使用、效果是纯"LP 数字"的药。
- 多人同时开了自动战斗:每回合第一个来问的角色触发,一次给所有开了自动战斗的玩家排好:会补血魔法的先(传教最先,补血耗魔减半),其次只有血瓶的;后面的人先扣掉前面的人打算补的量,前面已经把大家补过线,后面的人就不会触发。这是"决定指令"的顺序,不是战斗里出手的顺序(脚本拿不到出手顺序)。

### 7.5 宠物策略

按玩家存一份,不分宠物,和人物策略互相独立。没选过的按宠物默认:会攻击魔法就走魔法,否则重复上回合。

| 策略 id | 规则 |
|---|---|
| `repeat` | 重复你手动给这只宠物下过的上一回合指令;没有记录就普通攻击(没有"攻击"技能就防御) |
| `guardbreak` | 每回合用宠物会的最高级崩击(魔力够的),打延续上回合的目标,没有就打血最少的;没有魔力或不会崩击就普通攻击 |
| `magic` | 用宠物会的攻击魔法(单体/强力,固定等级),按敌人的位置、属性、种族选伤害最划算的;规则和人物魔法的 `normal` 一样(同一个函数);没有魔力就普通攻击 |

宠物没有模式可选,魔法一直按 `normal`。

### 7.6 菜单里的自动战斗页面

`/menu auto`:每行直接显示当前值,点一下就改。

```
自动战斗: 开              ← 点一下开/关
策略: 法师: 智能魔法(normal) 按职业默认   → 策略列表 → 点一个先看说明,确定才使用;法师再选模式
补血线: 60%              → 输入 1-99
宠物策略: 按宠物默认      → 宠物策略列表
```

选策略(包括"按职业默认")会同时开启自动战斗,选宠物策略不会改开关。模式在菜单里是中文说明:伤害优先(不管耗魔)/ 均衡(默认)/ 省魔力(群攻要更划算才用);命令里仍是 `fast` / `normal` / `eco`。

### 7.7 诊断日志

`/auto log on` 后,每回合的魔法选择会写日志,格式类似:

```
magic mode= normal enemies= 7 mp= ... options= 单体火LV10(耗100,伤害722,打1个) 强力火LV10(耗200,伤害1732,打4个) 超强火LV10(耗400,伤害2023,打7个) pick= 超强火LV10 ...
```

选择和预期不符时,把这几行发给作者最快。另外还有几个只写日志的诊断钩子(攻击目标、伤害、补血量),它们**只读不改**,原样返回引擎的值。

## 8. 测试情况和已知限制

**测试**
- 开发过程中,大部分命令和界面页面在 cgmsv 26.8d 的真实服务端里逐项测试过。
- 另外有一套模拟引擎的自动测试(gmTools 约 580 项检查、自动战斗约 440 项),用真的 Lua 代码跑,但**引擎接口是模拟的**,只能证明逻辑在那些假设下成立,不等于引擎真的这样。
- **最近的几处改动我只在模拟里验证过,没有在游戏里充分验证,请自己多测**(有问题请反馈):
  - 卖物品/删物品"只扣选中那一堆"(直接改这件东西的堆叠数再通知客户端,改完读回核对;引擎不接受就会回滚并提示);
  - `/skill` 学新技能的初始等级和经验;
  - 菜单里的"自动战斗"页面;
  - 法师魔法选法按实际耗魔比算(三种模式的新规则)。

**已知限制**
- 战斗中弹不出对话框(客户端的限制);窗口不会实时刷新。
- `/encounter always` 用的是"香"的步数 999,步数用完会自动停;我没有在游戏里确认走满 999 步以后的表现。
- 扩展背包(`extbagpage` > 0)的多页处理没有在游戏里测过;战斗后自动整理只整理当前页。
- 11 到 15 级的技能:`tech.txt` 里有它们的条目(名字是"-Ⅰ"到"-Ⅴ"),但我没有验证实际效果。
- 魔法的魔攻门槛(魔攻不够放不了高级魔法)没有可读的数据,脚本不考虑;引擎拒绝了会记下并降级。
- `/lv`、`/stat` 不做宠物。
- 技能经验表 Lv14、Lv15 是推算值,不是官方数据。
- 自动战斗里"人物等级 ÷ 10 + 1"这条规则来自游戏经验,不是数据文件里读到的。

## 9. 常见问题

**`/menu` 没反应或提示 NPC 没建成**:看服务端日志。NPC 建在 777 号地图 (0,0),地图或坐标有问题会建不成。

**输入命令没反应(连"命令出错"都没有)**:
- 命令被别的模块抢先处理了(同名);
- 模块没加载成功:看日志里有没有 gmTools 的加载错误;
- 编码被改了:文件被保存成 UTF-8 会读不进去,日志里会有语法错误。

**聊天框里是乱码**:文件编码被改了。用原来的 GBK 文件覆盖。

**`/auto` 提示补血功能没加载**:`autoBattleTactics.lua` 没复制过去,或者读入出错。日志里搜 `tactics`。

**自动战斗开着,但每回合还是要自己点**:确认已经 `/auto on`(登录会关);`/auto status` 看开关;`/auto log on` 打一场看日志。

**启动报 `skillexp.txt 数据不足`**:见第 4 章和附录 A。

**怎么卸载**:从 `ModuleConfig.lua` 删掉那两行,删掉三个文件,重启。设置保存在角色扩展数据里,不删也没关系。

## 10. 附录

### 附录 A:`data/skillexp.txt`(15 级,制表符分隔)

每行:表号、Lv1 到 Lv15 的累计经验、末尾 `9999999`。以下显示时用空格代替制表符,**写文件时要用制表符**。**Lv14、Lv15 两列是推算值。**

```
0 0 1000 2500 4500 7000 10000 13500 17500 22000 27000 32000 42000 62000 102000 182000 9999999
1 0 1000 2500 4500 7000 10000 13500 17500 22000 27000 32000 42000 62000 102000 182000 9999999
2 0 1800 7200 19800 45000 82800 133200 183600 246600 322200 397800 700200 1305000 2514600 4933800 9999999
3 0 900 3600 9900 22500 41400 66600 91800 123300 161100 198900 350100 652500 1257300 2466900 9999999
4 0 1350 5400 14850 33750 62100 99900 137700 184950 241650 298350 525150 978750 1885950 3700350 9999999
5 0 500 2000 5500 12500 23000 37000 51000 68500 89500 110500 194500 292500 488500 880500 9999999
6 0 450 1800 4950 11250 20700 33300 45900 61650 80550 99450 175050 263250 439650 792450 9999999
```

### 附录 B:版本

- v1.0(2026-11-08):首次发布。

### 声明

- cgmsv 引擎、整合包和游戏数据都不是我写的,这个包只是三个 Lua 模块。
- 可以自由使用、修改和转载,请保留出处;不提供任何担保,使用风险自负。


gmTools_autoBattle_v1.0.zip

83.39 KB, 下载次数: 0, 下载积分: 金币 -1

发表于 昨天 14:45 | 显示全部楼层
本帖最后由 dinghai612 于 2026-11-8 14:52 编辑

看起来好高级。可惜没有金币!

发表于 昨天 16:35 | 显示全部楼层
666666666666

 楼主| 发表于 昨天 23:16 | 显示全部楼层
发现个小bug,gmTools.lua找到这一行:
local ITEM_ELEMENTS = { [0] = '地', '水', '火', '风' }
改成:
local ITEM_ELEMENTS = { '地', '水', '火', '风' }
不然物品描述里的水晶属性是错误的。
您需要登录后才可以回帖 登录 | 注册/Sign up

本版积分规则

手机版|cgmsv引擎论坛

GMT+8, 2026-11-9 00:00 , Processed in 0.032743 second(s), 4 queries , Gzip On, Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表