工程参考/配置文件/Public/MonsterAITable.ini
MonsterAITable.ini 定义怪物 AI 类型的参数。 [INFO] 的 AINUMBER 决定有多少种 AI;每种 AI 一个 [AI<n>] 节,节内有 DESC 说明与 11 个 AIPARAM。怪物的基础 AI 编号(m_BaseAI)指向这里的下标,AI 行为在运行时按 AI_Monster::AIParam 取用。样本 AINUMBER=31,即 AI0 到 AI30 共 31 种。
这份表只调 AI 的行为参数,不决定怪物长什么样、刷在哪里、掉什么;那些由怪物属性表与场景刷怪配置决定。
文件位置与生效
| 项目 | 说明 |
|---|---|
| 运行文件 | ../Public/Config/MonsterAITable.ini,由 FileDef.h 的 FILE_MONSTER_AI 定义,相对于 Server 工作目录。Public 只是资源组织位置,本文件由服务端读取,不需要放进客户端。
|
| 读取程序 | Server 游戏进程:TableInit::InitMonsterAITable 用 Ini ini(FILE_MONSTER_AI) 打开 |
| 生效方法 | 正常保存并停服后,重启读取此文件的 Server。多份运行目录分别核对。当前检索未发现单独重载本文件的可用入口;不需要把本文件复制到玩家客户端。 |
| 样本格式 | GB18030-compatible,CRLF。保留原编码;源码读取器不会自动把中文转为 UTF-8。
|
加载流程是:先读 [INFO] AINUMBER 作为 AI 种类数,再双重循环 i 从 0 到 AINUMBER-1、j 从 0 到 AIPARAM_NUMBER-1,用 sprintf(szSection, "AI%d", i) 与 sprintf(szName, "AIPARAM%d", j) 拼出节名与键名逐个读整数。因此节名与键名里的数字必须连续:AI 编号断号会让后面所有种类的参数错位,AIPARAM 少一个键会让对应参数读成 -99999999。
| 参数与源码枚举 | 含义与修改要点 |
|---|---|
AIPARAM0AIPARAM_SCANTIME
|
扫描敌人的时间间隔(毫秒)。大于 0 表示主动攻击,值就是扫描间隔;小于等于 0 表示非主动攻击。 Obj_Monster.cpp 判断怪物是否主动攻击时读这一项。 |
AIPARAM1AIPARAM_RANDMOVETIME
|
随机移动位置的时间间隔(毫秒)。 |
AIPARAM2AIPARAM_CANNOTATTACK
|
无法攻击的对象。源码注释标注「已经废弃」:怪物是否无敌以 Public/MonsterAttrExTable.txt 为准。 不要再靠这一项配置无敌。 |
AIPARAM3AIPARAM_RETURN
|
距离出生地超过此值时放弃追赶。大于 0 才生效。 |
AIPARAM4AIPARAM_SCANENEMYDIST
|
扫描敌人的最大距离。 |
AIPARAM5AIPARAM_SCANTEAMMATEDIST
|
扫描队友的最大距离。 |
AIPARAM6AIPARAM_RESETTARGET_DIST
|
当前移动目标与敌人位置之间的距离大于此数值时,重新设定移动目标。 |
AIPARAM7AIPARAM_PATROLTIME
|
巡逻的时间间隔。小于等于 0 不进行巡逻。 |
AIPARAM8AIPARAM_STRIKEBACK
|
是否会还击。非 0 为会还击。 |
AIPARAM9AIPARAM_EXTEND_BY_LUA
|
是否由 Lua 脚本扩展怪物 AI。大于 0 时走脚本扩展分支。 Obj_Monster_AILuaExtand.cpp 按这一项判断是否交给 Lua。 |
AIPARAM10AIPARAM_CALL_NEARBY_MONSTER
|
是否召唤附近怪物协助作战。非 0 为会召唤。 |
| 检查项 | 结论 |
|---|---|
| AI 种类上限 | MAXAI_NUMBER = 256,AINUMBER 必须落在 0 到 255。 |
| 参数个数 | 固定 11 个(AIPARAM_NUMBER),由 enum MONSTER_AI_PRAM 决定,不能多写也不能少写。 |
| 缺失的键 | Ini::ReadInt 的返回版本在找不到时返回 ERROR_DATA,即 -99999999,不会被当成 0。
|
| 怪物的 AI 编号 | 刷怪配置里的 m_BaseAI 必须小于 AINUMBER,否则加载期断言。 |
| DESC 键 | 样本每个节都有,但加载函数不读它,纯粹是给维护者看的说明。 |
文件格式
使用 [节名] 与 Key=Value,节名和键名区分大小写,保持节标题位于行首。用单独一行分号写注释,保留原编码及 CRLF 换行;重复节或键取先匹配项,不依赖后写覆盖。缺项、空值与 0 分别按下表处理。
字段详解
模板 [n] 表示从 0 开始的序号,写入时应展开为实际数字;不是字面键名。
[INFO]
| 字段与类型 | 含义与修改要点 | 缺项或特殊值 |
|---|---|---|
AINUMBER整数,0 到 255 |
AI 种类的数量,决定读取 [AI0] 到 [AI<N-1>] 的循环次数。超出 MAXAI_NUMBER(256)会触发断言;为 0 时一个 AI 节都不读,所有怪物取到的参数都是 0。 | 必填。缺失时 Ini::ReadInt 返回 ERROR_DATA(-99999999),断言立即失败。 |
[AI[n]]
| 字段与类型 | 含义与修改要点 | 缺项或特殊值 |
|---|---|---|
DESC字符串,说明文字 |
该 AI 类型的人读说明。加载函数完全没有读取它,只作为维护备注存在。 | 可选。写错或删除不影响运行,但会让后续维护失去参考。 |
AIPARAM[n]整数,参数值 |
第 n 号 AI 的第 j 个参数(键名 AIPARAM0 到 AIPARAM10),含义见上表。怪物的 AI 类型就是这里的第一维下标,由怪物的基础 AI 编号决定,不是场景 ID 也不是怪物编号。 | 缺失时读到 ERROR_DATA(-99999999)而不是 0,通常意味着该参数被当成“极大/极小”的极端值使用,效果需要实测。 |
常用修改实例
示例为局部教学片段,先备份原运行文件,再修改对应行并保留其余配置。教学值不是程序默认值。
把 AI0 的巡逻间隔从 10000 毫秒改为 20000 毫秒
修改前:
[AI0] DESC=Sample AI for the teaching snippet. AIPARAM0=2000 AIPARAM7=10000
修改后:
[AI0] DESC=Sample AI for the teaching snippet. AIPARAM0=2000 AIPARAM7=20000
AIPARAM7 是巡逻时间间隔(AIPARAM_PATROLTIME),小于等于 0 表示不巡逻。这里只把 AI0 的这一项从 10000 改成 20000,让巡逻间隔加倍;其余 10 个参数、DESC 与 [INFO] 全部保留。
示例是局部片段,英文 DESC 只是为了让片段没有编码歧义;实际操作保留原文件的中文说明。改完需要重启 Server。
验证与排查
重启 Server 后查看启动日志的 “Load MonsterAITable.ini ... OK!”。再找一只使用目标 AI 编号的怪物,分别观察:是否主动攻击(AIPARAM0)、是否随机移动(AIPARAM1)、追出多远会返回(AIPARAM3)、是否巡逻与巡逻频率(AIPARAM7)、受击是否还击(AIPARAM8)。参数生效后才会体现在行为上,改 AIPARAM2 看不到无敌效果。失败时恢复备份并重启。
节名与键名的数字必须连续
节名与键名都由 sprintf 拼出,读取是靠拼名字去找,不是按文件顺序。删掉 AI5 会让原本的 AI6 变成新的 AI5,所有引用该编号的怪物行为都会改变。AIPARAM3 缺失则 AIPARAM4 不会顶上来,而是那一项读到 -99999999。
AIPARAM2 已经废弃
源码注释写明「无法攻击的对象(已经废弃,是否无敌是以 MonsterAttrExTable.txt 表中为主)」。配怪物无敌不要改这里。
取值单位是毫秒,不是秒
AIPARAM0、AIPARAM1、AIPARAM7 都是毫秒。把 10000 当 10 秒填成 10 会让怪物几乎每帧扫描。
这是服务端表,不要放进客户端
FILE_MONSTER_AI 指向 ../Public/Config,是服务端进程自己读的。修改不需要同步玩家客户端。
关联与依据
其他配置及整理状态 · 服务端外网设置 · Lua 接口索引
Common/ServerBase/Ini.cpp:实际加载、解析、字段使用或示例关联依据Common/ServerBase/Ini.h:实际加载、解析、字段使用或示例关联依据Common/ServerBase/FileDef.h:实际加载、解析、字段使用或示例关联依据Server/Server/GameServer/Server/Main/GameTable.cpp:实际加载、解析、字段使用或示例关联依据Server/Server/GameServer/Server/Main/GameTable.h:实际加载、解析、字段使用或示例关联依据Common/GameDefine.h:实际加载、解析、字段使用或示例关联依据Common/GameDefine2.h:实际加载、解析、字段使用或示例关联依据Server/Server/GameServer/Server/AI/AI_Monster.cpp:实际加载、解析、字段使用或示例关联依据Server/Server/GameServer/Server/Obj/Obj_Monster.cpp:实际加载、解析、字段使用或示例关联依据Server/Server/GameServer/Server/Obj/Obj_Monster_AILuaExtand.cpp:实际加载、解析、字段使用或示例关联依据Server/Server/GameServer/Server/Obj/MonsterManager.cpp:实际加载、解析、字段使用或示例关联依据resources/Public/Config/MonsterAITable.ini:实际加载、解析、字段使用或示例关联依据
本页核对源码读取、字段使用与样本格式,未启动游戏、服务端或数据库。解析验证不等于游戏实测;广播、权限、客户端交互等运行结果需要实测。