Пример #1
0
    def load_items(self):
        # Add backpack
        self.containers[InventorySlots.SLOT_INBACKPACK] = ContainerManager(
            is_backpack=True, owner=self.owner.guid)

        character_inventory = RealmDatabaseManager.character_get_inventory(
            self.owner.guid)

        # First load bags
        for item_instance in character_inventory:
            item_template = WorldDatabaseManager.item_template_get_by_entry(
                item_instance.item_template)
            if item_template and item_template.inventory_type == InventoryTypes.BAG:
                container_mgr = ContainerManager(owner=self.owner.guid,
                                                 item_template=item_template,
                                                 item_instance=item_instance)
                if self.is_bag_pos(container_mgr.current_slot):
                    self.containers[item_instance.bag].sorted_slots[
                        container_mgr.current_slot] = container_mgr
                    self.containers[container_mgr.current_slot] = container_mgr

        # Then load items
        for item_instance in character_inventory:
            item_template = WorldDatabaseManager.item_template_get_by_entry(
                item_instance.item_template)
            if item_template:
                item_mgr = ItemManager(item_template=item_template,
                                       item_instance=item_instance)
                if item_mgr.is_container() and self.is_bag_pos(
                        item_mgr.current_slot):
                    continue
                if item_instance.bag in self.containers:
                    self.containers[item_instance.bag].sorted_slots[
                        item_mgr.current_slot] = item_mgr
Пример #2
0
    def handle(world_session, socket, reader):
        if len(reader.data) >= 4:  # Avoid handling empty item query packet.
            entry = unpack('<I', reader.data[:4])[0]
            if entry > 0:
                item_template = WorldDatabaseManager.ItemTemplateHolder.item_template_get_by_entry(
                    entry)
                if item_template:
                    item_mgr = ItemManager(item_template=item_template)
                    world_session.enqueue_packet(item_mgr.query_details())

        return 0
Пример #3
0
    def _gen_item_struct(self, item_entry, count):
        item_template = WorldDatabaseManager.ItemTemplateHolder.item_template_get_by_entry(
            item_entry)
        display_id = 0
        if item_template:
            item_mgr = ItemManager(item_template=item_template)
            self.player_mgr.enqueue_packet(item_mgr.query_details())
            display_id = item_template.display_id

        item_data = pack('<3I', item_entry, count, display_id)

        return item_data
Пример #4
0
    def generate_loot(self, requester):
        # Circular refs.
        from game.world.managers.objects.units.LootHolder import LootHolder
        from game.world.managers.objects.item.ItemManager import ItemManager
        self.clear()

        for loot_item in choices(self.loot_template, k=randint(min(3, len(self.loot_template)),
                                                               min(7, len(self.loot_template)))):
            chance = float(round(uniform(0.0, 1.0), 2) * 100)
            item_template = WorldDatabaseManager.ItemTemplateHolder.item_template_get_by_entry(loot_item.item)
            if item_template:
                # Check if this is a quest item and if the player needs it.
                if requester and item_template.class_ == ItemClasses.ITEM_CLASS_QUEST:  # Quest item.
                    if not requester.player_or_group_require_quest_item(item_template.entry, only_self=True):
                        continue  # Move on to next item.

                item_chance = loot_item.ChanceOrQuestChance
                item_chance = item_chance if item_chance > 0 else item_chance * -1

                # TODO: ChanceOrQuestChance = 0 on Items equals 100% chance?
                if item_chance >= 100 or chance - item_chance < 0 or loot_item.ChanceOrQuestChance == 0:
                    item = ItemManager.generate_item_from_entry(item_template.entry)
                    if item:
                        # TODO Not handling references to other templates at this moment (mincountOrRef < 0), ignore.
                        if loot_item.mincountOrRef < 0:
                            continue
                        self.current_loot.append(LootHolder(item, randint(loot_item.mincountOrRef, loot_item.maxcount)))
Пример #5
0
    def set_item(self,
                 item,
                 slot,
                 count=1,
                 is_swap=False,
                 perm_enchant=0,
                 created_by=None):
        if self.can_set_item(item, slot, is_swap=is_swap):
            if isinstance(item, ItemManager):
                item_mgr = item
                if item_mgr == self:
                    return None
            else:
                item_creator = 0 if not created_by else created_by.guid
                item_mgr = ItemManager.generate_item(item,
                                                     self.owner,
                                                     self.current_slot,
                                                     slot,
                                                     stack_count=count,
                                                     perm_enchant=perm_enchant,
                                                     creator=item_creator)

            if item_mgr:
                item_mgr.current_slot = slot
                self.sorted_slots[slot] = item_mgr
                # Update slot fields.
                if not self.is_backpack:
                    self.build_container_update_packet()

            if item_mgr.item_template.bonding == ItemBondingTypes.BIND_WHEN_PICKED_UP:
                item_mgr.set_binding(True)
            return item_mgr
        return None
Пример #6
0
    def send_inventory_list(self, world_session):
        vendor_data, session = WorldDatabaseManager.creature_get_vendor_data(self.entry)
        item_count = len(vendor_data) if vendor_data else 0

        data = pack(
            '<QB',
            self.guid,
            item_count
        )

        if item_count == 0:
            data += pack('<B', 0)
        else:
            for count, vendor_data_entry in enumerate(vendor_data):
                data += pack(
                    '<7I',
                    count + 1,  # m_muid, acts as slot counter.
                    vendor_data_entry.item,
                    vendor_data_entry.item_template.display_id,
                    0xFFFFFFFF if vendor_data_entry.maxcount <= 0 else vendor_data_entry.maxcount,
                    vendor_data_entry.item_template.buy_price,
                    vendor_data_entry.item_template.max_durability,  # Max durability (not implemented in 0.5.3).
                    vendor_data_entry.item_template.buy_count  # Stack count.
                )
                world_session.enqueue_packet(ItemManager(item_template=vendor_data_entry.item_template).query_details())

        session.close()
        world_session.enqueue_packet(PacketWriter.get_packet(OpCode.SMSG_LIST_INVENTORY, data))
Пример #7
0
    def get_next_available_slot_for_inv_type(self, inventory_type):
        if inventory_type == InventoryTypes.BAG:
            for container_slot, container in list(self.containers.items()):
                if not container:
                    return container_slot.value

        # Inventory types that can target multiple slots (bags handled separately)

        if inventory_type == InventoryTypes.FINGER:
            target_slots = (InventorySlots.SLOT_FINGERL.value,
                            InventorySlots.SLOT_FINGERR.value)
        elif inventory_type == InventoryTypes.TRINKET:
            target_slots = (InventorySlots.SLOT_TRINKETL.value,
                            InventorySlots.SLOT_TRINKETR.value)
        elif inventory_type == InventoryTypes.WEAPON and \
                self.owner.skill_manager.can_dual_wield() and not self.has_two_handed_weapon():
            target_slots = (
                InventorySlots.SLOT_MAINHAND.value,
                InventorySlots.SLOT_OFFHAND.value
            )  # Offhand option is only valid when player can dual wield and doesn't have a 2H weapon (autoequip 1H weapon should replace 2H)
        else:
            target_slots = (ItemManager.get_inv_slot_by_type(inventory_type), )

        for slot in target_slots:
            if not self.get_backpack().get_item(slot):
                return slot

        return -1
Пример #8
0
    def generate_loot(self, requester):
        self.clear()

        money = randint(self.world_object.creature_template.gold_min, self.world_object.creature_template.gold_max)
        self.current_money = money

        for loot_item in self.loot_template:
            chance = float(round(uniform(0.0, 1.0), 2) * 100)
            item_template = WorldDatabaseManager.ItemTemplateHolder.item_template_get_by_entry(loot_item.item)
            if item_template:

                # Check if this is a quest item and if the player or group needs it.
                if requester and item_template.class_ == ItemClasses.ITEM_CLASS_QUEST:  # Quest item
                    if not requester.player_or_group_require_quest_item(item_template.entry):
                        continue  # Move on to next item.

                item_chance = loot_item.ChanceOrQuestChance
                item_chance = item_chance if item_chance > 0 else item_chance * -1

                if item_chance >= 100 or chance - item_chance < 0:
                    item = ItemManager.generate_item_from_entry(item_template.entry)
                    if item:
                        # TODO Not handling references to other templates at this moment (mincountOrRef < 0), ignore.
                        if loot_item.mincountOrRef < 0:
                            continue
                        self.current_loot.append(LootHolder(item, randint(loot_item.mincountOrRef, loot_item.maxcount)))
Пример #9
0
    def send_inventory_list(self, world_session):
        vendor_data, session = WorldDatabaseManager.creature_get_vendor_data(self.entry)
        item_count = len(vendor_data) if vendor_data else 0

        data = pack(
            '<QB',
            self.guid,
            item_count
        )

        if item_count == 0:
            data += pack('<B', 0)
        else:
            for vendor_data_entry in vendor_data:
                data += pack(
                    '<7I',
                    1,  # mui
                    vendor_data_entry.item,
                    vendor_data_entry.item_template.display_id,
                    0xFFFFFFFF if vendor_data_entry.maxcount <= 0 else vendor_data_entry.maxcount,
                    vendor_data_entry.item_template.buy_price,
                    0,  # durability
                    0,  # stack count
                )
                world_session.enqueue_packet(ItemManager(item_template=vendor_data_entry.item_template).query_details())

        session.close()
        world_session.enqueue_packet(PacketWriter.get_packet(OpCode.SMSG_LIST_INVENTORY, data))
Пример #10
0
 def add_loot(self, loot_item):
     from game.world.managers.objects.loot.LootHolder import LootHolder
     from game.world.managers.objects.item.ItemManager import ItemManager
     item = ItemManager.generate_item_from_entry(loot_item.item)
     if item:
         self.current_loot.append(
             LootHolder(
                 item, randint(loot_item.mincountOrRef,
                               loot_item.maxcount)))
Пример #11
0
    def handle(world_session, socket, reader):
        if len(reader.data) >= 4:  # Avoid handling empty item query packet.
            entry = unpack('<I', reader.data[:4])[0]
            if entry > 0:
                item_template = WorldDatabaseManager.ItemTemplateHolder.item_template_get_by_entry(entry)
                if item_template:
                    query_data = ItemManager.generate_query_details_data(item_template)
                    query_packet = PacketWriter.get_packet(OpCode.SMSG_ITEM_QUERY_SINGLE_RESPONSE, query_data)
                    world_session.enqueue_packet(query_packet)

        return 0
Пример #12
0
    def load_items(self):
        character_inventory = RealmDatabaseManager.character_get_inventory(
            self.owner.guid)

        # First load bags
        for item_instance in character_inventory:
            item_template = WorldDatabaseManager.ItemTemplateHolder.item_template_get_by_entry(
                item_instance.item_template)
            if item_template and item_template.inventory_type == InventoryTypes.BAG:
                container_mgr = ContainerManager(owner=self.owner.guid,
                                                 item_template=item_template,
                                                 item_instance=item_instance)
                if self.is_bag_pos(container_mgr.current_slot):
                    if item_instance.bag > 23:
                        low_guid = container_mgr.guid & ~HighGuid.HIGHGUID_CONTAINER
                        Logger.warning(
                            f'Invalid bag slot {item_instance.bag} for guid {low_guid} owner {self.owner.guid}'
                        )
                        continue
                    self.containers[item_instance.bag].sorted_slots[
                        container_mgr.current_slot] = container_mgr
                    self.containers[container_mgr.current_slot] = container_mgr

        # Then load items
        for item_instance in character_inventory:
            item_template = WorldDatabaseManager.ItemTemplateHolder.item_template_get_by_entry(
                item_instance.item_template)
            if item_template:
                if item_template.display_id > MAX_3368_ITEM_DISPLAY_ID and \
                        self.is_equipment_pos(item_instance.bag, item_instance.slot):
                    Logger.error(
                        f'Character {self.owner.player.name} has an equipped item ({item_template.entry} - {item_template.name}) '
                        f'with out of bounds display_id ({item_template.display_id}), '
                        f'deleting in order to prevent crashes.')
                    RealmDatabaseManager.character_inventory_delete(
                        item_instance)
                    continue

                if item_template.inventory_type == InventoryTypes.BAG:
                    if self.is_bag_pos(item_instance.slot):
                        continue

                    item_mgr = ContainerManager(owner=self.owner.guid,
                                                item_template=item_template,
                                                item_instance=item_instance)
                else:
                    item_mgr = ItemManager(item_template=item_template,
                                           item_instance=item_instance)

                if item_instance.bag in self.containers and self.containers[
                        item_instance.bag]:
                    self.containers[item_instance.bag].sorted_slots[
                        item_mgr.current_slot] = item_mgr
Пример #13
0
    def load_items(self):
        # Add backpack
        self.containers[InventorySlots.SLOT_INBACKPACK] = ContainerManager(
            is_backpack=True, owner=self.owner.guid)

        character_inventory = RealmDatabaseManager.character_get_inventory(
            self.owner.guid)

        # First load bags
        for item_instance in character_inventory:
            item_template = WorldDatabaseManager.item_template_get_by_entry(
                item_instance.item_template)
            if item_template and item_template.inventory_type == InventoryTypes.BAG:
                container_mgr = ContainerManager(owner=self.owner.guid,
                                                 item_template=item_template,
                                                 item_instance=item_instance)
                if self.is_bag_pos(container_mgr.current_slot):
                    self.containers[item_instance.bag].sorted_slots[
                        container_mgr.current_slot] = container_mgr
                    self.containers[container_mgr.current_slot] = container_mgr

        # Then load items
        for item_instance in character_inventory:
            item_template = WorldDatabaseManager.item_template_get_by_entry(
                item_instance.item_template)
            if item_template:
                if item_template.display_id > MAX_3368_ITEM_DISPLAY_ID and \
                        self.is_equipment_pos(item_instance.bag, item_instance.slot):
                    Logger.error(
                        'Character %s has an equipped item (%u - %s) with out of bounds display_id (%u), '
                        'deleting in order to prevent crashes.' %
                        (self.owner.player.name, item_template.entry,
                         item_template.name, item_template.display_id))
                    RealmDatabaseManager.character_inventory_delete(
                        item_instance)
                    continue

                if item_template.inventory_type == InventoryTypes.BAG:
                    if self.is_bag_pos(item_instance.slot):
                        continue

                    item_mgr = ContainerManager(owner=self.owner.guid,
                                                item_template=item_template,
                                                item_instance=item_instance)
                else:
                    item_mgr = ItemManager(item_template=item_template,
                                           item_instance=item_instance)
                if item_instance.bag in self.containers:
                    self.containers[item_instance.bag].sorted_slots[
                        item_mgr.current_slot] = item_mgr

        self.set_base_attack_time()
    def generate_loot(self):
        # TODO: Implement loot group handling
        money = randint(self.world_obj.creature_template.gold_min, self.world_obj.creature_template.gold_max)
        self.current_money = money

        for loot_item in self.loot_template:
            chance = float(round(uniform(0.0, 1.0), 2) * 100)
            item_template = WorldDatabaseManager.item_template_get_by_entry(loot_item.item)
            if item_template:
                item_chance = loot_item.ChanceOrQuestChance
                item_chance = item_chance if item_chance > 0 else item_chance * -1

                if item_chance >= 100 or chance - item_chance < 0:
                    item = ItemManager.generate_item_from_entry(item_template.entry)
                    if item:
                        self.current_loot.append(LootHolder(item, randint(loot_item.mincountOrRef, loot_item.maxcount)))
Пример #15
0
    def _gen_item_struct(self, item_entry, count):
        item_template = WorldDatabaseManager.ItemTemplateHolder.item_template_get_by_entry(item_entry)
        display_id = 0
        if item_template:
            display_id = item_template.display_id
            query_data = ItemManager.generate_query_details_data(item_template)
            self.player_mgr.enqueue_packet(PacketWriter.get_packet(OpCode.SMSG_ITEM_QUERY_SINGLE_RESPONSE, query_data))

        item_data = pack(
            '<3I',
            item_entry,
            count,
            display_id
        )

        return item_data
Пример #16
0
 def generate_starting_items(guid, race, class_, gender):
     start_items = DbcDatabaseManager.char_start_outfit_get(
         race, class_, gender)
     items_to_add = [
         start_items.ItemID_1, start_items.ItemID_2, start_items.ItemID_3,
         start_items.ItemID_4, start_items.ItemID_5, start_items.ItemID_6,
         start_items.ItemID_7, start_items.ItemID_8, start_items.ItemID_9,
         start_items.ItemID_10, start_items.ItemID_11, start_items.ItemID_12
     ]
     last_bag_slot = InventorySlots.SLOT_INBACKPACK.value
     for entry in items_to_add:
         item = ItemManager.generate_starting_item(guid, entry,
                                                   last_bag_slot)
         if item and item.item_instance:
             RealmDatabaseManager.character_inventory_add_item(
                 item.item_instance)
             if item.current_slot >= InventorySlots.SLOT_INBACKPACK:
                 last_bag_slot += 1
Пример #17
0
    def set_item(self, item, slot, count=1):
        if self.can_set_item(item, slot):
            if isinstance(item, ItemManager):
                item_mgr = item
                if item_mgr == self:
                    return None
            else:
                item_mgr = ItemManager.generate_item(item, self.owner, self.current_slot, slot, count=count)

            if item_mgr:
                item_mgr.current_slot = slot
                self.sorted_slots[slot] = item_mgr
                RealmDatabaseManager.character_inventory_update_item(item_mgr.item_instance)

            if item_mgr.item_template.bonding == ItemBondingTypes.BIND_WHEN_PICKED_UP:
                item_mgr.set_binding(True)
            return item_mgr
        return None
Пример #18
0
    def set_item(self, item, slot, count=1):
        if self.can_set_item(item, slot):
            if isinstance(item, ItemManager):
                item_mgr = item
                if item_mgr == self:
                    return None
            else:
                item_mgr = ItemManager.generate_item(item,
                                                     self.owner,
                                                     self.current_slot,
                                                     slot,
                                                     count=count)

            if item_mgr:
                item_mgr.current_slot = slot
                self.sorted_slots[slot] = item_mgr

            return item_mgr
        return None
Пример #19
0
    def set_item(self, item, slot, count=1):
        if self.can_set_item(item, slot):
            if isinstance(item, ItemManager):
                item_mgr = item
                if item_mgr == self:
                    return None
            else:
                item_mgr = ItemManager.generate_item(item,
                                                     self.owner,
                                                     self.current_slot,
                                                     slot,
                                                     count=count)

            if item_mgr:
                item_mgr.current_slot = slot
                self.sorted_slots[slot] = item_mgr
                RealmDatabaseManager.character_inventory_update_item(
                    item_mgr.item_instance)
            return item_mgr
        return None
Пример #20
0
    def set_item(self, item, slot, count=1):
        if not item or len(self.sorted_slots
                           ) == self.total_slots or slot > self.total_slots:
            return None

        if isinstance(item, ItemManager):
            item_mgr = item
            if item_mgr == self:
                return None
        else:
            item_mgr = ItemManager.generate_item(item,
                                                 self.owner,
                                                 self.current_slot,
                                                 slot,
                                                 count=count)
        if item_mgr:
            item_mgr.current_slot = slot
            self.sorted_slots[slot] = item_mgr

        return item_mgr
Пример #21
0
    def generate_loot(self, requester):
        # TODO: Even if called on parent, this is not properly set as with CreatureLootManager.
        if len(self.loot_template) == 0:
            self.loot_template = self.populate_loot_template()

        # For now, randomly pick 3..7 items.
        for loot_item in choices(self.loot_template, k=randint(min(3, len(self.loot_template)), min(7, len(self.loot_template)))):
            chance = float(round(uniform(0.0, 1.0), 2) * 100)
            item_template = WorldDatabaseManager.ItemTemplateHolder.item_template_get_by_entry(loot_item.item)
            if item_template:
                # Check if this is a quest item and if the player or group needs it.
                if requester and item_template.class_ == ItemClasses.ITEM_CLASS_QUEST:  # Quest item
                    if not requester.player_or_group_require_quest_item(item_template.entry):
                        continue  # Move on to next item.

                item_chance = loot_item.ChanceOrQuestChance
                item_chance = item_chance if item_chance > 0 else item_chance * -1

                # TODO: ChanceOrQuestChance = 0 on Gameobjects equals 100% chance?
                if item_chance >= 100 or chance - item_chance < 0 or loot_item.ChanceOrQuestChance == 0:
                    item = ItemManager.generate_item_from_entry(item_template.entry)
                    if item:
                        self.current_loot.append(LootHolder(item, randint(loot_item.mincountOrRef, loot_item.maxcount)))
Пример #22
0
    def handle(world_session, socket, reader):
        if len(reader.data
               ) >= 4:  # Avoid handling empty multiple item query packet.
            requested_item_count = unpack('<I', reader.data[:4])[0]
            if requested_item_count:
                found_items = 0
                item_query_data = b''
                for requested_item in range(requested_item_count):
                    entry = unpack(
                        '<I', reader.data[4 + (requested_item_count * 4):4])[0]
                    item_template = WorldDatabaseManager.ItemTemplateHolder.item_template_get_by_entry(
                        entry)
                    if item_template:
                        found_items += 1
                        item_query_data += ItemManager.generate_query_details_data(
                            item_template)

                if found_items:
                    data = pack(f'<I{len(item_query_data)}s', found_items,
                                item_query_data)
                    packet = PacketWriter.get_packet(
                        OpCode.SMSG_ITEM_QUERY_MULTIPLE_RESPONSE, data)
                    world_session.enqueue_packet(packet)
        return 0
Пример #23
0
    def add_item_to_slot(self,
                         dest_bag_slot,
                         dest_slot,
                         entry=0,
                         item_template=None,
                         count=1,
                         handle_error=True):
        if not self.containers[dest_bag_slot]:
            if handle_error:
                self.send_equip_error(InventoryError.BAG_ITEM_NOT_FOUND)
            return
        if entry != 0 and not item_template:
            item_template = WorldDatabaseManager.item_template_get_by_entry(
                entry)
        if not item_template:
            if handle_error:
                self.send_equip_error(InventoryError.BAG_ITEM_NOT_FOUND)
            return

        dest_container = self.containers[dest_bag_slot]
        dest_item = dest_container.get_item(dest_slot)

        # Bag family check
        if self.is_inventory_pos(dest_bag_slot, dest_slot) and \
                not dest_container.can_contain_item(item_template):
            self.send_equip_error(InventoryError.BAG_ITEM_CLASS_MISMATCH, None,
                                  dest_item)
            return

        if not self.can_store_item(item_template, count):
            if handle_error:
                self.send_equip_error(InventoryError.BAG_INV_FULL)
            return

        if not self.owner.is_alive:
            if handle_error:
                self.send_equip_error(InventoryError.BAG_NOT_WHILE_DEAD, None,
                                      dest_item)
            return

        # Destination slot checks
        if dest_container.is_backpack:
            template_equip_slot = ItemManager.get_inv_slot_by_type(
                item_template.inventory_type)
            if self.is_equipment_pos(dest_bag_slot, dest_slot) and dest_slot != template_equip_slot or \
                    self.is_bag_pos(dest_slot) and item_template.inventory_type != InventoryTypes.BAG or \
                    dest_slot == 255:  # slot 255 is the backpack slot
                if handle_error:
                    self.send_equip_error(InventoryError.BAG_SLOT_MISMATCH,
                                          None, dest_item)
                return

        # Check backpack / paperdoll placement
        if item_template.required_level > self.owner.level and \
                self.is_equipment_pos(dest_bag_slot, dest_slot):
            # Not enough level
            if handle_error:
                self.send_equip_error(InventoryError.BAG_LEVEL_MISMATCH, None,
                                      dest_item, item_template.required_level)
            return

        # Stack handling
        if dest_item:
            if self.is_inventory_pos(dest_bag_slot, dest_slot):
                if item_template.entry == dest_item.item_template.entry:
                    diff = dest_item.item_template.stackable - dest_item.item_instance.stackcount
                    if diff >= count:
                        dest_item.item_instance.stackcount += count
                    else:
                        # Update stack values
                        # Case where an item is dragged to stack but there's no space.
                        # Test on later version shows that the items will go to another stack if there's space
                        dest_item.item_instance.stackcount += diff
                        self.add_item(item_template=item_template,
                                      count=count - diff,
                                      handle_error=False)

                    self.owner.send_update_self()
                    RealmDatabaseManager.character_inventory_update_item(
                        dest_item.item_instance)
                    return True
                else:
                    if handle_error:
                        self.send_equip_error(InventoryError.BAG_CANT_STACK,
                                              None, dest_item)
                    return
            else:
                if handle_error:
                    self.send_equip_error(InventoryError.BAG_NOT_EQUIPPABLE,
                                          None, dest_item)
                return

        generated_item = dest_container.set_item(item_template, dest_slot,
                                                 count)
        # Add to containers if a bag was dragged to bag slots
        if self.is_bag_pos(dest_slot):
            if item_template.inventory_type == InventoryTypes.BAG:
                self.add_bag(dest_slot, generated_item)
            else:
                if handle_error:
                    self.send_equip_error(InventoryError.BAG_SLOT_MISMATCH,
                                          None, dest_item)
                return

        # Update attack time
        if dest_slot == InventorySlots.SLOT_MAINHAND:
            self.set_base_attack_time()

        if self.is_equipment_pos(dest_bag_slot, dest_slot):
            self.owner.flagged_for_update = True
        else:
            self.owner.send_update_self()
        return True
Пример #24
0
    def add_item_to_slot(self, dest_bag_slot, dest_slot, entry=0, item=None, item_template=None, count=1,
                         handle_error=True):
        if not self.containers[dest_bag_slot]:
            if handle_error:
                self.send_equip_error(InventoryError.BAG_ITEM_NOT_FOUND)
            return
        if entry != 0 and not item_template:
            item_template = WorldDatabaseManager.item_template_get_by_entry(entry)
        if not item_template:
            if handle_error:
                self.send_equip_error(InventoryError.BAG_ITEM_NOT_FOUND)
            return

        dest_container = self.containers[dest_bag_slot]
        dest_item = dest_container.get_item(dest_slot)

        # Bag family check
        if self.is_inventory_pos(dest_bag_slot, dest_slot) and \
                not dest_container.can_contain_item(item_template):
            self.send_equip_error(InventoryError.BAG_ITEM_CLASS_MISMATCH, item, dest_item)
            return

        if not self.can_store_item(item_template, count):
            if handle_error:
                self.send_equip_error(InventoryError.BAG_INV_FULL)
            return

        if not self.owner.is_alive:
            if handle_error:
                self.send_equip_error(InventoryError.BAG_NOT_WHILE_DEAD, item, dest_item)
            return

        # Destination slot checks
        if dest_container.is_backpack:
            # Set equip slot as offhand if trying to equip a one handed weapon in the offhand slot
            if dest_slot == InventorySlots.SLOT_OFFHAND and item_template.inventory_type == InventoryTypes.WEAPON:
                template_equip_slot = InventorySlots.SLOT_OFFHAND.value
            else:
                template_equip_slot = ItemManager.get_inv_slot_by_type(item_template.inventory_type)
            if self.is_equipment_pos(dest_bag_slot, dest_slot) and dest_slot != template_equip_slot or \
                    self.is_bag_pos(dest_slot) and item_template.inventory_type != InventoryTypes.BAG:
                if handle_error:
                    self.send_equip_error(InventoryError.BAG_SLOT_MISMATCH, item, dest_item)
                return

        if dest_slot == 0xFF:  # Dragging an item to bag bar. Acts like adding item but with container priority
            if not self.can_store_item(item_template, count):
                if handle_error:
                    self.send_equip_error(InventoryError.BAG_INV_FULL, item, dest_item)
                return

            dest_slot = dest_container.next_available_slot()
            remaining = count
            if dest_slot == -1:
                dest_slot, dest_container = self.get_next_available_inventory_slot()

            if not dest_slot == -1:  # If the target container has a slot open
                remaining = dest_container.add_item(item_template, count)  # Add items to target container
            if remaining > 0:
                self.add_item(item_template=item_template, count=remaining)  # Overflow to inventory
            else:
                # Update if container is modified self.add_item isn't called
                self.owner.send_update_self(force_inventory_update=True)
            return

        # Check backpack / paperdoll placement
        if item_template.required_level > self.owner.level and \
                self.is_equipment_pos(dest_bag_slot, dest_slot):
            # Not enough level
            if handle_error:
                self.send_equip_error(InventoryError.BAG_LEVEL_MISMATCH, item, dest_item, item_template.required_level)
            return

        # Stack handling
        if dest_item:
            if self.is_inventory_pos(dest_bag_slot, dest_slot):
                if item_template.entry == dest_item.item_template.entry:
                    diff = dest_item.item_template.stackable - dest_item.item_instance.stackcount
                    if diff >= count:
                        dest_item.item_instance.stackcount += count
                    else:
                        # Update stack values
                        # Case where an item is dragged to stack but there's no space.
                        # Test on later version shows that the items will go to another stack if there's space
                        dest_item.item_instance.stackcount += diff
                        self.add_item(item_template=item_template, count=count-diff, handle_error=False)

                    self.owner.send_update_self(force_inventory_update=True)
                    RealmDatabaseManager.character_inventory_update_item(dest_item.item_instance)
                    return True
                else:
                    if handle_error:
                        self.send_equip_error(InventoryError.BAG_CANT_STACK, item, dest_item)
                    return
            else:
                if handle_error:
                    self.send_equip_error(InventoryError.BAG_NOT_EQUIPPABLE, item, dest_item)
                return

        generated_item = dest_container.set_item(item_template, dest_slot, count)
        # Add to containers if a bag was dragged to bag slots
        if self.is_bag_pos(dest_slot):
            if item_template.inventory_type == InventoryTypes.BAG:
                self.add_bag(dest_slot, generated_item)
            else:
                if handle_error:
                    self.send_equip_error(InventoryError.BAG_SLOT_MISMATCH, item, dest_item)
                return

        if self.is_equipment_pos(dest_bag_slot, dest_slot):
            self.owner.stat_manager.apply_bonuses()
            self.owner.set_dirty(dirty_inventory=True)
        else:
            self.owner.send_update_self(force_inventory_update=True)

        return True
Пример #25
0
    def item_can_be_moved_to_slot(self,
                                  source_template,
                                  dest_slot,
                                  dest_bag,
                                  source_item=None,
                                  source_container=None):
        dest_container = self.get_container(dest_bag)
        if not dest_container:
            self.send_equip_error(InventoryError.BAG_ITEM_NOT_FOUND)
            return False

        dest_item = dest_container.get_item(dest_slot)

        if not source_template:
            return False

        if not self.owner.is_alive:
            self.send_equip_error(InventoryError.BAG_NOT_WHILE_DEAD,
                                  source_item, dest_item)
            return False

        # Check equipment skill and level requirement
        if self.is_equipment_pos(dest_bag, dest_slot):
            if source_template.required_level > self.owner.level:
                self.send_equip_error(InventoryError.BAG_LEVEL_MISMATCH,
                                      source_item, dest_item)
                return False
            if not self.owner.skill_manager.can_use_equipment(
                    source_template.class_, source_template.subclass):
                self.send_equip_error(InventoryError.BAG_PROFICIENCY_NEEDED,
                                      source_item, dest_item)
                return False

        # Destination slot (item type) check for paper doll and bag slots
        if dest_container.is_backpack:
            if (self.is_equipment_pos(dest_bag, dest_slot) and not ItemManager.item_can_go_in_paperdoll_slot(source_template, dest_slot)) or \
                    (self.is_bag_pos(dest_slot) and source_template.inventory_type != InventoryTypes.BAG):  # dest is paperdoll/bag slots but item isn't equipment/bag
                self.send_equip_error(InventoryError.BAG_SLOT_MISMATCH,
                                      source_item, dest_item)
                return False

        # Bag item family checks
        if self.is_inventory_pos(
                dest_bag, dest_slot
        ) and not dest_container.can_contain_item(source_template):
            self.send_equip_error(InventoryError.BAG_ITEM_CLASS_MISMATCH,
                                  source_item, dest_item)
            return False

        # Moving a container, excluding case where source and destination are bag slots
        # These cases are only relevant if the source item and source container exist
        if source_item and source_item.is_container() and source_container and not \
                (source_container.is_backpack and dest_container.is_backpack and self.is_bag_pos(
                    source_item.current_slot) and self.is_bag_pos(dest_slot)):
            if source_item.guid == dest_container.guid:  # Moving bag inside itself
                self.send_equip_error(InventoryError.BAG_NO_BAGS_IN_BAGS,
                                      source_item, dest_item)
                return False

            if source_container.is_backpack and self.is_bag_pos(
                    source_item.current_slot) and not source_item.is_empty(
                    ):  # Moving non-empty bag from bag slots
                self.send_equip_error(InventoryError.BAG_NOT_EMPTY,
                                      source_item, dest_item)
                return False

        source_is_weapon = source_template.inventory_type == InventoryTypes.WEAPON or \
            source_template.inventory_type == InventoryTypes.WEAPONOFFHAND

        # Dual wield check
        if source_is_weapon and dest_slot == InventorySlots.SLOT_OFFHAND and not \
                self.owner.skill_manager.can_dual_wield():  # Equipping weapon in OH without DW skill
            if dest_slot == InventorySlots.SLOT_OFFHAND and not \
                    self.owner.skill_manager.can_dual_wield():
                self.send_equip_error(InventoryError.BAG_NOT_EQUIPPABLE,
                                      source_item, dest_item)
                return False

        if dest_container.is_backpack and dest_slot == InventorySlots.SLOT_MAINHAND:
            current_oh = self.get_offhand()
            source_is_2h = source_template.inventory_type == InventoryTypes.TWOHANDEDWEAPON
            if current_oh and source_is_2h and not \
                    self.can_store_item(current_oh.item_template,
                                        current_oh.item_instance.stackcount):  # Equipping 2H with OH equipped but inv is full
                self.send_equip_error(InventoryError.BAG_CANT_SWAP,
                                      source_item, dest_item)
                return False

        # Offhand equip
        if dest_container.is_backpack and dest_slot == InventorySlots.SLOT_OFFHAND and self.has_two_handed_weapon(
        ):
            self.send_equip_error(InventoryError.BAG_2HWEAPONBEINGWIELDED,
                                  source_item, dest_item)
            return False

        return True