☰
AzerothCore 自定义模块实战:为单人带机器人 WotLK 服务器实现离线采集、拍卖行经济与进度修复
2026/10/9 11:06:01 网站建设 项目流程

【免费下载链接】universal-modder

Point Claude at any game. Skills, tools and the fal MCP that let Claude Code mod almost any PC game you own: recon, reverse engineering, fal-generated art/3D/audio, in-game testing, showcase videos.

项目地址:https://gitcode.com/gh_mirrors/un/universal-modder
点击查看免费下载

本文基于 universal-modder 知识库中的实战笔记 azerothcore-custom-modules.md 展开,完整记录了一套为「一名真人玩家 + 大量服务器端机器人」的 WotLK(3.3.5a)私人服务器编写自定义 AzerothCore 模块与核心补丁的全过程:由 NPC 雇佣「农场工人」在你离线时采集并邮寄货箱、拍卖行成交金直接入账并自动补货、邮件未读计数修复、手动团队进度控制(含 mod-individual-progression 的 Ahn'Qiraj 战争机制解密)、NPC 同伴的恶魔宠物,以及通过 DBC 覆盖表改数据。读完本文,你将掌握 AzerothCore 模块的标准骨架、脚本钩子选型、掉落表与邮件系统的底层行为,以及一套可复现的「症状 → 原因 → 修复」排障方法论,足以在自己的服务器上复刻或扩展同类玩法。

适用前提与版本基线

本笔记描述的环境与版本(来自笔记 front matter):

  • 核心:AzerothCore WotLK(3.3.5a)Playerbot 分支,2026-09 源码;
  • 进度模块:mod-individual-progression;
  • 客户端:3.3.5a build 12340;
  • 平台:Linux(服务器端);
  • 工具链:AzerothCore 模块 API(C++)、MySQL 8.4、TradeSkillMaster 价格数据;
  • 反作弊:不适用——这是用户自己运行的私人服务器;
  • 参与方:Claude Code (Opus 5.5) + 人类玩家 RedSuper;
  • 状态:working(全部模块已上线运行)。

服务器运行环境的更多细节可参考姊妹篇笔记 azerothcore-playerbots-server-ops.md:Playerbot 分支、MySQL 8.4(Oracle 仓库,而非 MariaDB)、Debian 13 下的 tmux 进程管理、构建与崩溃排查。这篇笔记专注「模块与补丁本身怎么写」,而运维篇专注「服务器怎么跑起来」,两篇配合阅读可以完整覆盖从编译到玩法落地。

路线选择:模块 API 优先,核心补丁兜底

笔记给出的核心原则只有一句话,但决定了整个工程的架构走向:

模块 API 只要存在对应钩子就用它;只有当 bug 出在核心(邮件计数、威胁 bug、进度守卫)时,才改核心补丁。

对应到 universal-modder 的路线框架(见 mod-any-game 技能 的路线表),这属于Loader API路线:服务器本身(AzerothCore)就是最完整的「加载器」,模块是它官方支持的扩展单元,天然避开了对二进制打补丁、签名扫描等重活。只有当缺陷位于核心代码、模块钩子无法触达时,才降级为核心补丁——这也正是「cheapest route that reaches the idea」的取舍逻辑:能用钩子解决的,绝不动核心。

模块骨架:三件套即可上线

  • 模块文件布局:src/mod_<name>.cpp,内含Addmod_<name>Scripts()作为脚本注册入口;
  • 配置模板:conf/<Name>.conf.dist(AzerothCore 约定,供玩家复制为.conf使用);
  • 无需修改 CMake:模块目录会被自动发现(auto-discovered)。

注意一个构建层面的代价:虽然不需要改 CMake,但每新增一个模块文件夹,就会重新生成模块加载器并触发近乎全量的重编译。运维篇 azerothcore-playerbots-server-ops.md 给出了具体数字佐证——添加一个模块目录会重新编译全部约 700 个模块对象,因此在规划功能时要尽量「一次建好,后续在既有模块内迭代」,避免反复触发全量构建。

用到的脚本类型

脚本类型用途
CreatureScript对话(gossip):农场工人合同 NPC、拍卖行相关 NPC
WorldScript启动时种子数据、世界更新 tick、配置读取
PlayerScript玩家侧行为挂钩
AuctionHouseScript拍卖成交、上架钩子(拍卖支付/补货的核心)

核心机制:服务器到底怎么读数据(必须掌握的知识)

笔记以「How the game works」为章节名,罗列了实现六个功能前必须摸清的引擎与数据库行为。这些是整篇文章的「底层原理」部分,也是踩坑清单的直接来源。

掉落表(Loot tables)的真实语义

AzerothCore 读取掉落表时遵循的规则与直觉相反,理解错误会直接导致「绝大多数采集点什么都不掉」:

  • GroupId 分组语义:同一组(GroupId)内的掉落行,恰好只掉其中一件物品;
  • Chance = 0 行的含义:Chance = 0的行并非「永不掉落」,而是与其他 Chance = 0 的行均分组内剩余概率。笔记指出全部 18,025 行 gameobject 掉落中,有 8,579 行依赖这一语义——即近半数采集掉落是靠「零概率均分」机制工作的;
  • Reference 递归展开:Reference行会递归展开到reference_loot_template表(宝石类掉落存放在那里)。不做递归展开,宝石就永远不会出现在产出里;
  • 剥皮掉落(skinning loot):由creature_template.skinloot字段指定,不是按生物 entry 直接查表;
  • 物品 class 12(任务物品):会出现在采集掉落表中,凡是要发放给玩家的产出都必须过滤掉它。

货箱与邮件:存储掉落与邮件系统的边界

  • 货箱机制:按物品存储的掉落(item_loot_storage)能让一件物品充当「货箱」,但LoadStoredLoot只有在该物品存在item_loot_template行时才会运行——需要给每件货箱物品补一行「近零概率」的掉落行(注意:chance 0 + group 0 的组合会被拒绝);
  • 掉落窗口上限:最多显示 18 个物品(MAX_NR_LOOT_ITEMS),且堆叠计数是 8 位(最大 255);
  • 邮件上限:MAX_MAIL_ITEMS为 12 件/封,更大的交付必须拆成多封;
  • 邮件送达通知陷阱:只传 guid 的MailReceiver(guid)版本硬编码为「无玩家」,在线收件人永远不会收到通知——必须使用MailReceiver(player, guid)玩家版本;
  • 未读邮件计数:只在「标记为已读」时递减。如果玩家用「全部打开」类插件直接取走或删除了未读邮件,就会留下一个幽灵邮件图标。修复方式是核心补丁:删除/退回未读邮件时递减计数,并在重新统计时跳过已删除邮件;
  • 客户端收件箱:只显示 50 封邮件。

数据库:异步陷阱与 DBC 覆盖表

  • CharacterDatabase.Execute()是异步的:紧接着执行 SELECT 读取刚插入行的 id,会读到 0。需要立即拿到行时必须用DirectExecute();
  • DBC 覆盖表(spell_dbc、skillraceclassinfo_dbc、charstartoutfit_dbc、creaturefamily_dbc等):启动时按 id 向服务器内存中的 DBC追加或替换行。但客户端读取这些数据时,仍然需要 patch MPQ 里有对应的 DBC 行——例如新的种族/职业组合所需的CharBaseInfo就存放在 locale 归档里。这解释了为什么「服务端加了行、客户端却看不到」:两边各有一份 DBC。运维篇补充了同族事实:服务器会校验生物外观(creature display)只认自己的 DBC 副本,新增坐骑时需要在creaturedisplayinfo_dbc/creaturemodeldata_dbc中补对应行并重启(物品外观则不校验)。

拍卖行:内存态与直付直补

  • AuctionHouseScript钩子:可以抑制「待成交 / 成交成功 / 竞拍成功」三类邮件(sendMail = false),而OnAuctionSuccessful紧随其后触发——足够在成交时直接把金币付给卖家,避免塞满 50 封邮件的收件箱;
  • 拍卖行是内存态:拍卖数据常驻服务器内存,关机时才回写数据库。在运行中的服务器上直接改拍卖表,会被静默还原。要在运行中添加上架,必须模仿核心的做法,且放在同一个事务里:
    1. Item::CreateItem(clone 模式可避免随机后缀);
    2. SaveToDB;
    3. sAuctionMgr->AddAItem;
    4. AuctionHouseObject::AddAuction;
    5. 物品 entry 的SaveToDB。
  • 双价格表漂移陷阱:库存来自启动时种子的「花名册表」(物品、堆叠、数量),而买家机器人按另一张「市场价表」的一定百分比出价。两张价格表一旦漂移,玩家按种子价上架的物品就永远卖不出去。

宠物:种族 → 技能线 → 技能

  • 生物种族(CreatureFamily)映射到宠物法术(skill lines → abilities);术士召唤走召唤宠物效果,观赏宠物(vanity pets)走另一套;
  • 宠物名牌来自生物查询结果(creature_template.name),与种族无关——改creature_template行即可重命名;
  • Pet::InitStatsForLevel按生物 entry 分支:未知 entry 不会获得属性缩放光环——所以克隆新宠物时必须为新 entry 添加属性缩放 case。

进度模块(mod-individual-progression)的 AQ 战争解密

笔记花了最大篇幅剖析这个模块,因为「单人带机器人」的服务器必须把进度牢牢抓在自己手里:

  • 层级存储:层数(tiers)以已奖励的隐藏任务 66001–66018 存储;提升某层会自动回填所有更低层级;
  • 默认进度守卫失效:所用构建中,即使DisableDefaultProgression = 1,boss 击杀仍会推进层级(守卫被注释掉了)。补丁内容:仅在默认进度开启时击杀才推进层级;.ip set修复后可将层级设为 0(清空所有层级);
  • 逐玩家 AQ 战争努力:一个「Complete the War Effort」任务(1,000 枚嘉奖徽记,且每个收集任务完成一次后)同时门控「权杖任务线」的起始与模块自己的锣任务;
  • 敲锣("Bang a Gong!"):仅在默认进度开启时把玩家推到 tier 4;DisableDefaultProgression = 1时敲锣什么都不动,层级保持手动;
  • 锣的动画细节:播放开门动画(树根、符文、门),但约五分钟后会再次关门,因此可以反复重放;模块的「战争」步骤其实是一个空等待;再次点击锣会重新开门;门的对象展示给 tier 5 以下的角色;
  • 室外 AQ 战争被 phase 到 tier 4 专属:一个相位光环作用于 Silithus、Darkshore 与 Scarab Wall。三座巨像(Zora、Regal、Ashi,其击杀任务由锣旁 NPC 发放)、Nokhor 中将与 Supreme Anubisath Warbringers、Colossal Anubisath Warbringers、一个低等级 Darkshore 部分以及水晶构造体都依赖相位掩码放置——只数带脚本名的刷怪点会几乎什么都找不到;
  • 巨像的机制(约 200 万生命,免疫打断与眩晕):开战 60 秒后施放 Colossal Smash,此后每分钟一次——5 秒施法,对 100 码内所有人造成 3,125 点物理伤害,外加 50 码/秒向外、50 向上的击退。在平地会把玩家抛出约 260 码、向上 65 码,落地伤害约为最大生命值的 92%;而巨像只攻击 200 码可见性覆盖内的目标,当所有人被击退到范围之外时,巨像会在满血状态下脱战(evade);
  • 战争 Boss 掉落表:该构建中这些 Boss 的掉落表存的是 70 级物品(一把 TBC 剑、Living Ruby 宝石)——原版数值迁移不完整。

六个构建步骤详解

笔记的 Build steps 共六步,覆盖全部功能。下面逐条展开,并补充可验证依据。

1. 离线采集(「FarmSim」)

  • 入口:一个 NPC 按种族与层级出售「农场工人合同」;
  • 产出计算:世界更新 tick(WorldScript)根据真实掉落表计算每位农场工人在已流逝时间内的产出——按组(GroupId)、引用(reference)、剥皮掉落(skinning loot)语义展开,种族加成按小数概率随机化;
  • 交付:以「存储掉落」货箱形式邮寄,按 12 件/封拆成多封;
  • 定价锚定:产出速率锚定到人类采集速度,价格参考拍卖数据(TradeSkillMaster 价格数据)。
  • 验证方式:时间跳跃测试(模拟 6 小时 → 分层产出、真实宝石稀有度、无任务物品),见下文「验证」节。

2. 拍卖直付

  • 抑制拍卖三类邮件(sendMail = false);
  • 在OnAuctionSuccessful中直接支付金币;
  • 注意边界:先支付、且绝不能因为金币上限(2^31 铜币数量级)而吞钱。

3. 邮件未读计数修复

  • 两个核心函数修复(删除/退回未读邮件时递减计数、重数时跳过已删除邮件);
  • 笔记强调:无头文件改动,约一分钟构建——属于「核心小补丁」的典型,改动面最小。

4. 进度控制

  • 恢复模块中两处守卫(击杀推进、敲锣推进的门控);
  • 配套一个可逆 SQL 用于层级变更(.ip set0 清空全部层级)。

5. 同伴恶魔宠物

  • 克隆一个术士召唤物但去掉其材料需求(灵魂碎片试剂);
  • 为新 entry 添加宠物属性缩放 case(对应Pet::InitStatsForLevel);
  • 通过creature_template行重命名(名牌来自生物行而非种族)。

6. 拍卖自动补货

  • 在市场模块内放一个定时器:每 30 分钟、每轮最多 500 个上架、首轮在启动后一个间隔才执行;
  • 统计机器人每个(物品 × 堆叠)组合的存活上架数,按与启动种子相同的规则在内存中补齐缺失项:
    • 价格 × 堆叠,上限 20 亿铜币(2 billion copper);
    • 一口价(buyout)为出价的 80%(bid 80%);
    • 有效期一年。
  • 注意与「双价格表」陷阱联动:买家机器人的出价上限必须与种子价格表同步(见 Gotcha 11)。

验证:每一环都要有可复核的证据

笔记的 Verification 段落本身就是一套「oracle」方法论(与 oracles-how-agents-know-a-mod-works.md 的验证思想一脉相承):

  • 时间跳跃测试:采集模块模拟 6 个小时 → 验证分层产出、真实宝石稀有度、无任务物品混入;
  • 人工在游戏内复核:每一次线上变更都由人类玩家在游戏内确认;
  • 数据库行检查:货箱、邮件、进度变更均回到 DB 行核对;
  • 补货验证:启动后的上架数与花名册一致;一次线上补货轮精确重发了已售出的物品(4 个上架,一个不少)——这是「线上行为 + 数字对账」的实证;
  • 诚实标注证据边界(知识库贡献规则要求,见 CONTRIBUTING.md):
    • AQ 战争事实来自模块代码与数据 + 人类玩家的实际游玩(关门、巨像重置);
    • 击退距离与坠落伤害是由法术数据计算得出的,未在游戏中实测;
    • 战争 Boss 的掉落是从掉落表读出的,未亲眼见过掉落。

这种「哪些是实测、哪些是推算」的边界标注,正是知识库笔记区别于普通博客的关键——后续 Agent 知道哪些结论可以无条件信任、哪些需要重新验证。

十三条坑:症状 → 原因 → 修复

笔记的 Gotchas 是全篇最可复用的部分,完整收录如下:

  1. 付费升级从未保存。原因:异步 INSERT 后 SELECT id 读到 0,导致每次保存都执行WHERE id=0。修复:改用DirectExecute,加一个拒绝 id 0 的守卫并退款。
  2. 货箱打开是空的还销毁了内容。原因:缺少item_loot_template行,存储掉落从未被加载。修复:每件货箱物品补一行近零概率掉落行。
  3. 产出里从来不出宝石。原因:引用掉落未展开。修复:递归展开 reference 掉落。
  4. 大多数采集点什么都不掉。原因:把Chance = 0行当成了「永不掉落」。修复:采用核心的组语义(Chance = 0 均分组内剩余概率)。
  5. 交付悄悄变少。原因:12 件/封的邮件上限。修复:拆成多封邮件。
  6. 邮件到了但玩家没被通知。原因:只传 guid 的MailReceiver硬编码无玩家。修复:改用带 player 参数的版本。
  7. 幽灵未读邮件图标。原因:计数器只在标记已读时递减。修复:上文的核心补丁(删除/退回未读邮件时递减、重数跳过已删)。
  8. 团队进度自己动。原因:模块的击杀守卫被注释掉了。修复:恢复守卫。
  9. 克隆宠物法术报「缺少材料」。原因:原法术的灵魂碎片试剂被一起带过来了。修复:在覆盖行(DBC override row)中清空试剂。
  10. 直接在数据库加的拍卖上架消失了。原因:拍卖在内存中、关机时重写。修复:在世界服务器启动前种子化,或通过拍卖管理器在内存中创建(见「拍卖行」一节的五步事务)。
  11. 玩家自己的拍卖永远卖不出去。原因:买家机器人用与种子不同的表定价,615 件物品标价高于其上限。修复:让买家价格从种子表同步(模块可在配置重载时重新读取)。
  12. 「AQ 的门一直关着。」原因:进度模块在敲锣五分钟后重置门。修复:再点一次锣,或把门对象改为从 tier 5 改为 tier 4 起隐藏。
  13. 机器人团打不过巨像。原因:Colossal Smash 的击退每分钟把所有人送出 Boss 攻击范围(见上文机制计算)。修复:模块内无解;通过服务器法术覆盖(spell override)调小击退距离才能让这场战斗打得起来。

未解决问题与延伸阅读

  • 待修复:AoE 拾取模块对任务物品与条件掉落处理不当,尚未修复。

这些模块的玩法改动与客户端侧同样深度相关:邮件计数、拍卖邮件、收件箱 50 封限制等,客户端行为细节可对照 addon-development-335a.md(例如 3.3.5a 客户端的插件生态、宏与公会银行等 UI 行为);而拍卖直付、机器人经济这类「服务器内部经济」问题,往往与客户端插件(如「全部打开」类邮件插件)交互产生,值得两篇笔记对照排查。

最后,本笔记本身即遵循知识库的 field note 规范(结构:Setup / Route and why / How the game works / Build steps / Verification / Gotchas),详见 knowledge/README.md:精确版本、真实路线、引擎真实行为、验证方式、编号坑,五要素齐全才是一篇可被下一个 Agent 直接接手的笔记。本文的所有事实均直接来源于该笔记及其姊妹篇,未作任何性能或效果的夸大。

【免费下载链接】universal-modder

Point Claude at any game. Skills, tools and the fal MCP that let Claude Code mod almost any PC game you own: recon, reverse engineering, fal-generated art/3D/audio, in-game testing, showcase videos.

项目地址:https://gitcode.com/gh_mirrors/un/universal-modder
点击查看免费下载

相关推荐

上一篇:探秘Theia Sticky Sidebar:一款强大的侧边栏固定工具
下一篇:终极指南:如何快速掌握NLP研究代码编写——EMNLP 2018教程完整解析

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询