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
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
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
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)))
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
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))
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
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)))
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))
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)))
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
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
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)))
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
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
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
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
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
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
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)))
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
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
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
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