当前位置: 首页 > 工具软件 > Arcemu > 使用案例 >

Ascent/Arcemu代码分析7- 物品及装备

盖嘉珍
2023-12-01

 

类型定义:

                   主要在ItemPrototype.h中,是各种道具相关的宏定义和枚举定义。

                            物品类型(INVENTORY_TYPES):

                            道具分类(ITEM_CLASS

                            道具子类(Item_Subclass

 

道具:

          所有放在包里的东西都视为道具,包括装备、任务物品、药水等等。道具属性集是各种物品的属性并集。

 

道具定义:

ItemPrototype 道具原型模板,记录了某个物品的不变属性,由ItemPrototypeStorage统一维护,游戏中不能修改。同一模板的多个实例共用一个ItemPrototype

Item 道具的实例,记录了同一物品不同实例的差异属性(如附魔、插槽、随机属性等)并引用一个ItemPrototype

 

道具存储:

        ItemPrototypeItem分别存储,ItemPrototypeworld DB items中,服务器启动时加载入内存,运行期间内容不变。Item在服务器运行期动态生成(如掉落),然后存入Charactor Db的表PlayerItems中,其entry也是ItemPrototypeentry

 

物品掉落:

         生成物品的途径很多,主要有:怪物掉落,开箱子,盗窃,采矿,采药,剥皮,分解,钓鱼,打开包裹。

        物品掉落由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有一个ItemInterfaceItemInterface主要管理玩家的各种物品栏,包括包裹、银行、售卖列表的回购栏、装备栏。它记录了玩家的每一个道具和道具的位置。拾取道具、穿脱装备、买卖物品等操作的道具位置变化都是通过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.

 

 类似资料: