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