类型定义:
主要在ItemPrototype.h中,是各种道具相关的宏定义和枚举定义。
物品类型(INVENTORY_TYPES):
道具分类(ITEM_CLASS)
道具子类(Item_Subclass)
道具:
所有放在包里的东西都视为道具,包括装备、任务物品、药水等等。道具属性集是各种物品的属性并集。
道具定义:
ItemPrototype 道具原型模板,记录了某个物品的不变属性,由ItemPrototypeStorage统一维护,游戏中不能修改。同一模板的多个实例共用一个ItemPrototype。
Item 道具的实例,记录了同一物品不同实例的差异属性(如附魔、插槽、随机属性等)并引用一个ItemPrototype。
道具存储:
ItemPrototype与Item分别存储,ItemPrototype在world DB 表items中,服务器启动时加载入内存,运行期间内容不变。Item在服务器运行期动态生成(如掉落),然后存入Charactor Db的表PlayerItems中,其entry也是ItemPrototype的entry。
物品掉落:
生成物品的途径很多,主要有:怪物掉落,开箱子,盗窃,采矿,采药,剥皮,分解,钓鱼,打开包裹。
物品掉落由LootMgr负责管理,其中加载了各种类型的掉落表LootStore,即掉落各种东西的几率表。当触发掉落时(如怪物死亡、箱子打开),为目标对象填充loot,其中只是引用了掉落物品的 ItemPrototype,当玩家拾取的时候再生成Item放入玩家背包。
以怪物掉落为例(其他掉落均是此种的简化版,只是稍有不同):
当怪物死亡(Object::HandleDeath)时,死者生成掉落物品(victim->generateLoot()),其中
void LootMgr::FillCreatureLoot(Loot * loot,uint32 loot_id, bool heroic)
根据掉落几率生成__LootItem(最多16个)及item的随机属性(如前缀、随机值),并加入怪物的loot中。
玩家搜索搜索尸体
void WorldSession::HandleLootOpcode( WorldPacket & recv_data )
服务器则读出loot中的道具,根据分配方式和需求将掉落道具列表发给客户端(比如没有相关任务就不能看到任务物品),
如果需要Roll,则创建一个LootRoll对象,并通知客户端
void Player::SendLoot(uint64 guid,uint8 loot_type)
客户端分别以物品ID向服务器索取进一步的详细物品信息
void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
玩家没有放弃该物品,选择roll,服务器在处理时由
void WorldSession::HandleLootRollOpcode(WorldPacket& recv_data)
调用
void LootRoll::PlayerRolled(shared_ptr<Player> player, uint8 choice)
当所有的玩家roll完(或者时间到)之后,由
void LootRoll::Finalize()
创建出Item并分配给roll点最高的玩家,否则不能拾取。
不需要roll的物品则直接拾取,拾取时创建出Item并放入玩家物品栏空位。
void WorldSession::HandleAutostoreLootItemOpcode( WorldPacket & recv_data )
道具管理:
每个Player有一个ItemInterface,ItemInterface主要管理玩家的各种物品栏,包括包裹、银行、售卖列表的回购栏、装备栏。它记录了玩家的每一个道具和道具的位置。拾取道具、穿脱装备、买卖物品等操作的道具位置变化都是通过ItemInterface进行。
装备:
装备也是一种道具,定义参照struct ItemPrototype,一件装备可以附带最多10种状态,5种伤害,5种技能和3个插槽。
当装备通过ItemInterface移动到装备栏时,通过
void _ApplyItemMods( shared_ptr<Item> item, int8 slot, bool apply, bool justdrokedown = false, bool skip_stat_apply = false );
将装备效果附加到角色身上,并重新计算修正的相关属性。
套装:
定义(DBC文件):
struct ItemSetEntry
{
uint32 id; //1
char* name; //2
//uint32 unused_shit[15]; //3 - 9
uint32 flag; //10 constant
uint32 itemid[8]; //11 - 18
//uint32 more_unused_shit[9]; //19 - 27
uint32 SpellID[8]; //28 - 35
uint32 itemscount[8]; //36 - 43
uint32 RequiredSkillID; //44
uint32 RequiredSkillAmt; //45
}
一个套装最多有8件装备, SpellID[x]是指装备x件装备后能得到的套装属性。而套装属性的实现是以Aura的形式(就像Buff一样)
所以这里提供了一个SpellID,当装备第X件套装装备时,如果有对应的spellid,则为自己加上此spell效果,当脱下时则取消该Aura.