AzerothCore学习笔记·数据库09:物品系统——模板表与背包结构
有一把剑,WoW 老玩家没有不知道的。
“灰烬使者”(Ashbringer)。提米手里那把黑色的剑,暗影领主提里斯管理着它,无数玩家在纳克萨玛斯里刷过这把刀。它掉落的概率低到离谱,而且——每次掉落的"灰烬使者",随机属性还不一样。
这就是 AzerothCore 物品系统要处理的核心场景之一:同一把剑,不同实例,随机词缀。
两套模板:item_template 与 item_instance
物品系统的核心,和怪物一样,是模板与实例的分离。
item_template:物品的类型定义,全服同一类物品共用一份模板,记录名称、属性、品质、图标、绑定规则等全服统一的配置item_instance:物品的具体实例,每个玩家背包里的每一个具体物品,记录随机属性、耐久度、持有者
模板可以共享,不需要为每个玩家的物品单独存类型信息;实例存每件物品独享的数据。
item_template 的字段
两百多个字段,拆开看分几类:
类型标识:物品类别、子类别、材质、模型 ID
名称与描述:name、description、displayid
属性配置:基础数值(armor、damage、block、spellcharges)、随机属性池(RandomProperty / RandomSuffix)
行为规则:bonding(绑定规则:拾取绑定/装备绑定/使用绑定)、商店价格、职业/种族限制
背包规则:bagfamily(背包家族:矿石袋、草药袋)、ContainerSlots(如果是背包,记录格子数)
两百多个字段里,最核心的是前几类。后面很多字段是为特殊物品准备的,常规武器装备大量字段为空。
随机属性机制:为什么同一把剑属性不一样
WoW 里有一类装备,叫随机属性装备——同一个物品模板,每次掉落属性不同。
拿灰烬使者来说,item_template定义了它"是一把传奇品质的双手剑",但"提供 +30 暗影伤害"还是"+40 耐力",每次掉落时从词缀池里抽取。
AzerothCore 用两张表处理这个:
item_template.RandomProperty:随机的固定词缀(“+XX 敏捷”)item_template.RandomSuffix:随机的百分比词缀(“+15% 敏捷”)
随机属性在物品生成时(掉落、购买、制造)完成抽取,结果写入item_instance.randomPropertyId——生成后属性就固定了,后续不再变化。服务器不需要在运行时重新计算随机属性,只需要存一个 ID。
这个设计和.game_event_save 恰好相反:活动叠加层里的进度需要保留,玩家背包里的随机属性一旦确定就不该再变——否则今天刷出的灰烬使者是力敏双加,明天上线变成智精耐加,这个游戏就没法玩了。
item_instance:物品的生命周期
item_instance是物品在服务器内存中的持久化快照。角色下线时背包状态写进去,上线时从这里读回来。
| 字段 | 说什么 |
|---|---|
itemguid | 物品实例唯一 ID |
owner_guid | 当前持有者角色 ID |
itemEntry | 关联的物品模板 ID |
creatorGuid | 制造者 ID(如果是制造的) |
randomPropertyId | 抽取到的随机词缀 ID |
durability | 当前耐久度 |
flags | 状态标志(灵魂绑定、已交易、已锁定) |
注意耐久度在item_instance里,而不是item_template里——这是对的。耐久度是实例级数据,同一种物品,持有时间越长,耐久越低。不可能存在一个"模板级"的耐久度。
character_inventory:物品放在哪里
item_instance存物品本身,character_inventory存物品放在哪里:
character_guid, bag, slot, itemguid说的是:角色 X 的背包 Y 格子 Z 里,放着物品实例 M。
把这两张表联合起来,能完整还原一个角色背包的状态:每个位置放的是什么物品,物品当前的耐久度和随机属性是什么。
character_inventory里用bag字段区分普通槽位和背包内部格子:bag=0是普通背包槽位,bag=物品实例ID表示这个格子在某个背包内部。这套设计让背包本身也是一个物品实例——放进背包槽位的是一个item_instance,这个实例内部的格子由character_inventory里的bag字段指向这个实例的 ID。
绑定规则:灵魂绑定是怎么回事
item_template里的bonding字段,控制物品能否流通:
NO_BODY:不绑定,任何人都可以交易ON_PICKUP:拾取时绑定,捡起来就变成灵魂绑定ON_EQUIP:装备时绑定,穿上后变成灵魂绑定ON_USE:使用时绑定QUEST ITEM:任务物品,不可丢弃、不可交易
绑定信息在物品生成时写入item_instance.flags。一旦绑定,服务器在交易时检查这个标志,拒绝绑定物品的交易请求。
还有一个边缘情况:团队掉落被分配后 2 小时内可以交易——团队散了玩家可以把刚拿到的装备交易给队友。item_soulbound_trade_data表记录这个临时交易窗口的截止时间。
物品外观:displayid 的作用
item_template.displayid是物品在客户端显示的模型 ID。
不同的displayid对应不同的图标和 3D 模型。服务器只存一个 ID,客户端负责渲染。
有趣的是,AzerothCore 通过修改displayid,可以让同一个物品模板在不改变数值的情况下呈现完全不同的外观——外观和数值解耦,开发者可以自由组合。这在自定义服务器里是常见的修改手段。
回头看 AzerothCore 的物品系统,有一条主线贯穿始终:模板定义"应该有什么属性",实例记录"这个具体的物品现在是什么状态"。这两层分离让物品系统能够同时处理两种场景——全服统一的物品类型配置,和每个玩家背包里独一份的物品实例。系列一到这里,四个核心库全部聊完。模板模式、实例模式、条件系统、叠加层……这些反复出现的核心概念,构成了 AzerothCore 数据设计的骨架。系列二会从代码层深入聊这些系统的具体实现。
