Loot模板系统
1. Loot模板表定义
TrinityCore中的Loot系统通过一系列数据库表来定义和管理战利品掉落,这些表构成了完整的Loot模板系统。
1.1 核心掉落表
-
creature_loot_template:定义生物掉落物品
-
gameobject_loot_template:定义游戏对象掉落物品
-
item_loot_template:定义物品包含的其他物品
-
quest_mail_loot_template:定义任务邮件附件物品
-
disenchant_loot_template:定义分解物品获得的材料(附魔)
-
fishing_loot_template:定义钓鱼获得的物品
-
skinning_loot_template:定义剥皮获得的材料
-
pickpocketing_loot_template:定义偷窃获得的物品
-
prospecting_loot_template:定义勘探获得的宝石(选矿)
-
milling_loot_template:定义研磨获得的物品(铭文)
-
spell_loot_template:定义当玩家施放特定法术或技能时可能获得的物品列表,主要包括以下情况
- 采集技能(如采矿、采药)时通过法术获得的额外物品
- 特定职业技能(如术士的“灵魂碎片”采集)
- 任务相关法术可能触发的物品掉落
- 某些物品使用后触发的法术可能产生的战利品
1.2 参考引用表
reference_loot_template:定义可重复引用的Loot模板
2. Loot模板字段详解
2.1 基本字段
2.1.1 Entry
- 含义:Loot模板的ID,对应生物、物品或游戏对象的Entry
- 用途:作为Loot模板的唯一标识符
- 示例:生物Entry为10000的生物,其Loot模板Entry也为10000
2.1.2 Itemtype
- 含义:Loot掉落类型
- 0:掉落类型为物品,Item栏应填写物品ID
- 1:掉落类型为引用,Reference栏应填写Reference ID
- 2:掉落类型为货币,Item栏应填写货币ID
- 用途:指定可能掉落的物品的类型
- 示例:Item为25表示掉落物品ID为25的物品
2.1.3 Item
- 含义:掉落物品的Entry
- 用途:指定可能掉落的物品
- 示例:Item为25表示掉落物品ID为25的物品
2.1.4 Reference
- 含义:引用其他Loot模板的ID
- 用途:当需要引用其他Loot模板时使用(Item和Reference不能同时非零)
- 示例:Reference为10000时,表示引用Entry为10000的reference_loot_template
2.1.5 Chance
- 含义:物品掉落概率(0-100之间的浮点数)
- 用途:表示掉落百分比
- 特殊值:0表示物品不会掉落,100表示物品必定掉落,仅允许分组条目(相同的GroupId)的Chance值为零
- 示例:Chance为50.0表示50%的掉落概率
2.1.6 QuestRequired
- 含义:物品是否需要任务才能拾取
- 用途:0表示不需要任务,非0表示需要特定任务
- 只有在接到任务且该任务 quest_template.RequiredItemId[1-6] 字段(高版本为 quest_objectives.ObjectID 字段,quest_objectives.type=1)里包含该任务物品的编号,且已收集的物品数量比任务目标数量少时,掉落才会生效
- 示例:QuestRequired为12345表示需要接到ID为12345的任务才能触发掉落事件
2.1.7 LootMode
- 含义:Loot模式标志位
- 用途:控制不同条件下的掉落行为
- 示例:1为普通模式,2为英雄模式,4为10人模式,8为25人模式
2.1.8 GroupId
- 含义:物品分组ID
- 使用:决定物品的掉落方式
- 同一个组(所有条目的GroupId相同且均非零,下同)中最多只能有一个项目掉落
- 同一个组的掉落Chance合计不超过100时,则组条目中定义的每个项目都有机会按照设置的Chance掉落
- 同一个组的掉落Chance合计超过100时,那么该组内的一些条目将失去一部分掉落的机会(同一个组的掉落Chance合计不应超过100)
- 不建议将非任务和任务掉落混合在同一个组中
- 只有16个非任务物品(为任务添加到战利品中的金钱和物品不计入此“16”)可以进入战利品。由于大多数掉落都有超过16个可能的物品(有时是数百个),因此如果没有分组,给定的战利品有可能滚动超过16个物品,但玩家只能看到(并拿走)其中的前16个
- 核心对组的数量没有限制,但根据前面的说明,不要使用大于16的值
- 示例:GroupId为0的条目会从该条目中按预设的chance掉落,所有GroupId为非零的条目只会从该组中随机掉落一个
2.1.9 MinCount和MaxCount
- 含义:物品掉落数量的最小值和最大值
- 使用:控制每次掉落的物品数量范围
- MinCount不应该使用0值
- 如果参考引用模板表(Reference)的MinCount和MaxCount的值分别为3和10,掉落模板表LootMaxCount的值为5,那么在处理该引用后,将会有15到50个物品被添加到掉落中。
INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES (30001, 4001, 50.0, 1, 0, 3, 10, 'Reference item 1');INSERT INTO `creature_loot_template` (`Entry`, `Reference`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES (12345, 30001, 100.0, 1, 0, 1, 5, 'Reference to template 30001');
-
自引用(战利品模板包括对自身的引用)和循环引用(战利品模版A包括对整个模版B的引用,战利品模版B包括对整个样板A的引用)与内部引用完全不同。如下例,在第一次尝试战利品21215处理时,核心将由于堆栈溢出而崩溃。严格禁止自引用和循环引用!
-- 错误的用法 INSERT INTO `reference_loot_template` (`Entry`,`Item`,`Reference`) VALUES (21215, 0, 21215);
- 示例:MinCount为1,MaxCount为3表示掉落数量为1-3个
2.1.10 Comment
- 含义:注释字段
- 使用:用于描述该条Loot记录的用途
- 示例:"Rare drop"表示这是一个稀有掉落
3. Loot模板使用方法
3.1 基本使用流程
3.1.1 创建Loot模板
- 确定Loot类型(生物、游戏对象、物品等)
- 选择对应的Loot表
- 填写Entry、Item等字段
- 设置掉落概率和数量
3.1.2 引用Loot模板
- 创建reference_loot_template记录
- 在其他Loot模板中通过Reference字段引用
- 可以多层嵌套引用
3.1.3 分组Loot
- 设置GroupId为相同值的物品
- 系统会从每组中随机选择一个物品掉落
- 不同组之间的物品独立计算
3.2 高级使用技巧
3.2.1 条件掉落
-- 只有特定职业才能拾取的物品(需结合conditions表来实现)
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(12345, 67890, 10.0, 1, 0, 1, 1, 'Warrior only item');
3.2.2 多模式掉落
-- 不同难度模式下的不同掉落
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(12345, 1001, 20.0, 1, 0, 1, 1, 'Normal mode drop'),
(12345, 1002, 30.0, 2, 0, 1, 1, 'Heroic mode drop');
3.2.3 分组掉落
-- 从一组物品中随机掉落一个
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(12345, 2001, 33.3, 1, 1, 1, 1, 'Group 1 item 1'),
(12345, 2002, 33.3, 1, 1, 1, 1, 'Group 1 item 2'),
(12345, 2003, 33.3, 1, 1, 1, 1, 'Group 1 item 3');
3.2.4 引用模板
-- 创建引用模板
INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(30001, 4001, 50.0, 1, 0, 1, 1, 'Reference item 1'),
(30001, 4002, 50.0, 1, 0, 1, 1, 'Reference item 2');-- 引用模板
INSERT INTO `creature_loot_template` (`Entry`, `Reference`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
(12345, 30001, 100.0, 1, 0, 1, 1, 'Reference to template 30001');
4. Loot模板与代码的交互
4.1 Loot生成流程
4.1.1 服务器端Loot生成
// 伪代码示例
void GenerateLoot(Player* killer, Creature* victim) {// 1. 获取Loot模板LootTemplate const* lootTemplate = GetLootTemplate(victim->GetEntry());// 2. 应用Loot模式uint32 lootMode = CalculateLootMode(killer, victim);// 3. 生成Loot物品lootTemplate->Process(loot, lootMode, killer);// 4. 应用条件检查ApplyConditions(loot, killer, victim);// 5. 通知客户端SendLootToClient(killer, victim, loot);
}
4.1.2 条件检查
// 条件检查示例
bool IsLootAllowed(Player* player, LootItem const& item) {// 1. 检查基本条件if (!sConditionMgr->IsObjectMeetToConditions(player, item.conditions))return false;// 2. 检查职业限制if (item.classMask && !(item.classMask & player->getClassMask()))return false;// 3. 检查等级要求if (player->getLevel() < item.requiredLevel)return false;return true;
}
4.2 Loot模式控制
4.2.1 Loot模式枚举
enum LootModes {LOOT_MODE_DEFAULT = 1,LOOT_MODE_HARD_MODE_1 = 2,LOOT_MODE_HARD_MODE_2 = 4,LOOT_MODE_HARD_MODE_3 = 8
};
4.2.2 应用Loot模式
void ApplyLootMode(Loot& loot, uint32 mode) {loot.lootMode |= mode;
}
4.3 实际应用示例
4.3.1 奥杜尔副本Loot模式
void AddHardModeLoot()
{if (me->HasLootMode(LOOT_MODE_HARD_MODE_2)) // 已有两个困难模式me->AddLootMode(LOOT_MODE_HARD_MODE_3); // 添加第三个困难模式else if (me->HasLootMode(LOOT_MODE_HARD_MODE_1)) // 有一个困难模式me->AddLootMode(LOOT_MODE_HARD_MODE_2); // 添加第二个困难模式else // 没有困难模式me->AddLootMode(LOOT_MODE_HARD_MODE_1); // 添加第一个困难模式
}
5. 最佳实践
5.1 设计原则
- 模块化设计:使用reference_loot_template创建可重用的Loot模板
- 合理分组:使用GroupId确保互斥物品的正确掉落
- 概率平衡:确保掉落概率总和合理,避免过高或过低
- 条件明确:清晰定义物品的掉落条件和限制
5.2 性能优化
- 减少引用层级:避免过深的Loot模板引用嵌套
- 合理使用分组:减少不必要的分组计算
- 缓存常用模板:对高频使用的Loot模板进行缓存
- 批量处理:对多个Loot项进行批量处理而非逐个处理
5.3 调试技巧
- 使用注释:为每个Loot项添加清晰的注释
- 测试概率:使用大量测试验证掉落概率的准确性
- 检查条件:确保所有条件都能正确应用
- 日志记录:添加详细的Loot生成日志以便调试
6.附录
Loot table | Field | Relation | Related table | Field | Comment |
---|---|---|---|---|---|
fishing_loot_template | no relation | entry is linked with ID of the fishing zone or area | |||
creature_loot_template | entry | many <- many | creature_template | lootid | |
gameobject_loot_template | entry | many <- many | gameobject_template | Data1 | Only gameobject type 3 (GAMEOBJECT_TYPE_CHEST) or 25 (GAMEOBJECT_TYPE_FISHINGHOLE) use data1 as loot ID, for other types data1 is used in other ways |
item_loot_template | entry | many <- many | ItemSparse.db2 (wago.tools) | ID | |
disenchant_loot_template | entry | many <- many | ItemSparse.db2 (wago.tools) | ||
prospecting_loot_template | entry | many <- many | ItemSparse.db2 (wago.tools) | ID | |
milling_loot_template | entry | many <- many | ItemSparse.db2 (wago.tools) | ID | |
pickpocketing_loot_template | entry | many <- many | creature_template | pickpocketloot | |
skinning_loot_template | entry | many <- many | creature_template | skinloot | |
quest_mail_loot_template | entry | quest_template_addon | RewardMailTemplateID | ||
reference_loot_template | entry | many <- many | *_loot_template | Item (if ItemType = 1) | |
spell_loot_template | entry | many <- many | Spell.db2 (wago.tools) or SpellName.db2 (wago.tools) | ID |