Loot模板系统

发布于:2025-09-04 ⋅ 阅读:(18) ⋅ 点赞:(0)

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模板
  1. 确定Loot类型(生物、游戏对象、物品等)
  2. 选择对应的Loot表
  3. 填写Entry、Item等字段
  4. 设置掉落概率和数量
3.1.2 引用Loot模板
  1. 创建reference_loot_template记录
  2. 在其他Loot模板中通过Reference字段引用
  3. 可以多层嵌套引用
3.1.3 分组Loot
  1. 设置GroupId为相同值的物品
  2. 系统会从每组中随机选择一个物品掉落
  3. 不同组之间的物品独立计算

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 设计原则

  1. 模块化设计:使用reference_loot_template创建可重用的Loot模板
  2. 合理分组:使用GroupId确保互斥物品的正确掉落
  3. 概率平衡:确保掉落概率总和合理,避免过高或过低
  4. 条件明确:清晰定义物品的掉落条件和限制

5.2 性能优化

  1. 减少引用层级:避免过深的Loot模板引用嵌套
  2. 合理使用分组:减少不必要的分组计算
  3. 缓存常用模板:对高频使用的Loot模板进行缓存
  4. 批量处理:对多个Loot项进行批量处理而非逐个处理

5.3 调试技巧

  1. 使用注释:为每个Loot项添加清晰的注释
  2. 测试概率:使用大量测试验证掉落概率的准确性
  3. 检查条件:确保所有条件都能正确应用
  4. 日志记录:添加详细的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

网站公告

今日签到

点亮在社区的每一天
去签到