//----[  eraseItems  ]---------------------------------------------------------
int ClientItemsInterface::eraseItems(unsigned int item_type, int quantity) {
  for (unsigned int i = 0; (quantity > 0) && (i < items_in_inventory_);) {
    ItemInstance* item = inventory_[i].item.dereference();
    if (!item) {
      repackInventory();
      break;
    } else {
      if (item->getDescription()->type_index == item_type) {
        quantity = item->removeQuantity(quantity);
        update_inventory_ = true;
        equipment_changed_ = equipment_changed_ || inventory_[i].equipped;
        inventory_dirty_bits_.set(i);

        // check to see if this item was destroyed by removing
        // the given quantity.
        if (quantity >= 0) {
          GlobalDatabaseManager::singleton()
              ->itemOnAvatarErased(item->getUniqueID());
          GlobalItemManager::singleton()->releaseItem(&inventory_[i].item);
          shiftDownToEraseInInventory(i);
        }

        // If the quantity has been consumed, we're done!
        if (quantity <= 0) return 0;
      } else {
        ++i;
      }
    }
  }

  return quantity;
}
//----[  onDeath  ]------------------------------------------------------------
bool ClientItemsInterface::onDeath(Magic::MagicIndex* on_death_magic,
                                   int* wishing_percent) {
  assert(on_death_magic);
  assert(wishing_percent);
  bool found_on_death_magic = false;
  int wishing_percent_sum = 0;

  // iterate backward because we might remove an element
  for (int i = items_in_inventory_; i > 0;) {
    --i;
    if (!inventory_[i].equipped) continue;
    ItemInstance* item = inventory_[i].item.dereference();
    assert(item);
    Magic::MagicIndex death_magic = item->getDescription()->on_death_magic;
    wishing_percent_sum += item->getDescription()->wishing_percent;
    if (!found_on_death_magic &&
        (death_magic != Magic::INVALID_MAGIC_INDEX)) {
      found_on_death_magic = true;
      *on_death_magic = death_magic;
      update_inventory_ = true;
      GlobalDatabaseManager::singleton()
        ->itemOnAvatarErased(item->getUniqueID());
      GlobalItemManager::singleton()
        ->releaseItem(&inventory_[i].item);
      shiftDownToEraseInInventory(i);
    }
  }
  *wishing_percent = wishing_percent_sum;
  return found_on_death_magic;
}
Beispiel #3
0
Void Inventory::SortBufferBagItems()
{
    if ( m_arrBags[INVENTORYBAGID_BUFFER].iFreeSlots == INVENTORY_BAG_SIZE )
        return;

    for( UInt i = 0; i < INVENTORY_BAG_SIZE; ++i ) {
        ItemInstance * pItemInstance = m_arrBags[INVENTORYBAGID_BUFFER].arrSlots[i];
        if ( pItemInstance == NULL )
            continue;

        InventoryBagID idTargetBag = INVENTORYBAGID_COUNT;
        switch( pItemInstance->GetType() ) {
            case ITEMTYPE_BLOCK:      idTargetBag = INVENTORYBAGID_BLOCK;       break;
            case ITEMTYPE_EQUIPMENT:  idTargetBag = INVENTORYBAGID_EQUIPMENT;   break;
            case ITEMTYPE_CONSUMABLE: idTargetBag = INVENTORYBAGID_CONSUMABLE; break;
            case ITEMTYPE_QUEST:      idTargetBag = INVENTORYBAGID_QUEST;       break;
            default: Assert(false); break;
        }
        if ( m_arrBags[idTargetBag].iFreeSlots == 0 )
            continue;

        UInt iFreeSlot = _Bag_GetFreeSlot( idTargetBag );
        Assert( m_arrBags[idTargetBag].arrSlots[iFreeSlot] == NULL );

        m_arrBags[INVENTORYBAGID_BUFFER].arrSlots[i] = NULL;
        m_arrBags[idTargetBag].arrSlots[iFreeSlot] = pItemInstance;

        ++(m_arrBags[INVENTORYBAGID_BUFFER].iFreeSlots);
        --(m_arrBags[idTargetBag].iFreeSlots);
    }
    SortBag( INVENTORYBAGID_BUFFER );
}
//----[  findStackableItemInInventory  ]---------------------------------------
bool ClientItemsInterface::findStackableItemInInventory(
    ItemInstance* find_match_for,
    unsigned int start_search_index,
    unsigned int* found_index,
    ItemInstance** current_item) {
  if (!find_match_for) return false; // no item?
  const Evidyon::Item::ItemServerDescription* description
    = find_match_for->getDescription();
  if (description->max_stack_size <= 1) return false; // not stackable?

  unsigned int i = start_search_index;
  while (i < items_in_inventory_) {
    ItemInstance* item = inventory_[i].item.dereference();
    if (!item) {
      // This item is invalid, but is listed as valid--fix the problem,
      // then try again.  This will loop until no problems are found
      // or the list is emptied because all are bugged.
      repackInventory();
    } else {
      if (item->getDescription() == description &&
          !inventory_[i].equipped) { // don't stack equipped items
        *found_index = start_search_index;
        *current_item = item;
        return true;
      } else {
        ++i;
      }
    }
  }
  return false;
}
//----[  splitItem  ]----------------------------------------------------------
bool ClientItemsInterface::splitItem(unsigned int index) {
  if (!inventoryItemIsValid(index)) return false;
  AvatarInventoryItem* inventory_item = &inventory_[index];
  if (!inventory_item->stackable || // item must be stackable...
      inventory_item->equipped) return false; // ...and in the inventory
  ItemInstance* item = inventory_item->item.dereferenceAssumingValid(); // justified by validity check
  if (canHoldItems(1) == false) return false; // 
  const int original_quantity = item->getQuantity();
  if (original_quantity <= 1) return false; // can't split a stack of 1
  int new_quantity = original_quantity >> 1; // divide in half
  int quantity_remaining = original_quantity - new_quantity;

  // Create the new item
  ItemPointer new_item;
  if (!GlobalItemManager::singleton()->acquireNewItem(new_quantity,
                                                      item->getDescription()->type_index,
                                                     &new_item)) {
    return false;
  }

  // Put the new item in the inventory
  if (!addToInventory(new_item, NULL)) {
    GlobalItemManager::singleton()->releaseItem(&new_item);
  }

  // Adjust the quantity of the original item
  item->setQuantity(quantity_remaining);
  return true;
}
Beispiel #6
0
uint32 EQEmu::ItemInstance::GetItemID(uint8 slot) const
{
	ItemInstance *item = GetItem(slot);
	if (item)
		return item->GetID();

	return 0;
}
//----[  setStorageItem  ]-----------------------------------------------------
void ClientItemsInterface::setStorageItem(unsigned int index,
                                          ItemPointer* item_pointer) {
  ItemInstance* item = item_pointer->dereferenceAssumingValid();
  storage_[index].id = item->getUniqueID();
  storage_[index].quantity = item->getQuantity();
  storage_[index].type = item->getDescription()->type_index;
  GlobalItemManager::singleton()->releaseItem(item_pointer);
  storage_dirty_bits_.set(index);
  update_storage_ = true;
}
//----[  geosidSacrificeItem  ]------------------------------------------------
bool ClientItemsInterface::geosidSacrificeItem(unsigned int index,
                                               Geosid::Geonite* geonite_value) {
  if (!inventoryItemIsValid(index)) return false;
  AvatarInventoryItem* inventory_item = &inventory_[index];
  if (inventory_item->equipped) return false; // can't sacrifice equipped items
  ItemInstance* item = inventory_item->item.dereferenceAssumingValid();
  *geonite_value = item->getDescription()->geonite_value;
  GlobalItemManager::singleton()->releaseItem(&inventory_item->item);
  shiftDownToEraseInInventory(index);
  return true;
}
Beispiel #9
0
bool BarrelBlock::use(Player& player, const BlockPos& pos)
{
	BarrelEntity* container = (BarrelEntity*)player.region.getBlockEntity(pos);
	if(container == nullptr)
		return false;

	Inventory* playerInventory = *(Inventory**) (((uintptr_t) &player) + 0xD78); // TODO: Do the f*** header of Entity, Mob, Player.
	ItemInstance* instance = player.getSelectedItem();
	if(container->itemInstance == nullptr && instance != nullptr) 
	{
	 	container->maxItems =  instance->getMaxStackSize() * 64;
		container->itemCount = instance->count;
		container->itemInstance = ItemInstance::clone(instance);

		playerInventory->clearSlot(playerInventory->getSelectedSlot());
	} 
	else if((instance == nullptr || instance->getId() != container->itemInstance->getId()) && container->itemCount > 0)
	{
		ItemInstance temp(container->itemInstance->getId(), 1, container->itemInstance->getAuxValue());
		if(!playerInventory->add(temp)) // This function clone the ItemInstance
		{
			//If the player does not have space, drop the item to the floor.
			player.region.getLevel()->addEntity(std::unique_ptr<Entity>(new ItemEntity(player.region, Vec3(pos), temp, 1)));
		} 
		container->itemCount -= 1;
	} 
	else if(container->itemInstance->sameItemAndAux(instance) && (container->itemCount > 0) && (container->itemCount < container->maxItems))
	{

		if((container->itemCount + instance->count) > container->maxItems) 
		{
			instance->count = (container->itemCount + instance->count) - container->maxItems;
			container->itemCount = container->maxItems;
		} 
		else 
		{
			container->itemCount += instance->count;
			playerInventory->clearSlot(playerInventory->getSelectedSlot());
		}
	}

	container->setChanged();
	if(container->itemCount <= 0)
		container->clear();

	if(instance == nullptr)
		return false;

	return true;
}
//----[  isCarrying  ]---------------------------------------------------------
bool ClientItemsInterface::isCarrying(unsigned int item_type, int quantity) {
  for (unsigned int i = 0; i < items_in_inventory_; ++i) {
    ItemInstance* item = inventory_[i].item.dereference();
    if (!item) {
      repackInventory();
      return false;
    } else {
      if (item->getDescription()->type_index == item_type) {
        quantity -= item->getQuantity();
        if (quantity <= 0) return true;
      }
    }
  }
  return false;
}
//----[  setInventoryItem  ]---------------------------------------------------
void ClientItemsInterface::setInventoryItem(unsigned int index,
                                            ItemPointer& item_pointer) {
  ItemInstance* item = item_pointer.dereferenceAssumingValid();
  inventory_[index].item.copy(item_pointer);
  inventory_[index].stackable = item->isStackable();
  inventory_[index].equipped = false;
  inventory_dirty_bits_.set(index);
  update_inventory_ = true;

  { // become the owner of this item
    //inventory_[index].item.becomeUniquePointer();
    GlobalDatabaseManager::singleton()->itemChangeOwner(item->getUniqueID(),
                                                        account_id_,
                                                        character_id_,
                                                        session_id_);
  }
}
Beispiel #12
0
void EQEmu::ItemInstance::PutItem(uint8 index, const ItemInstance& inst)
{
	// Clean up item already in slot (if exists)
	DeleteItem(index);

	// Delegate to internal method
	_PutItem(index, inst.Clone());
}
//----[  isCarryingNew  ]------------------------------------------------------
bool ClientItemsInterface::isCarryingNew(unsigned int item_type,
                                         int quantity,
                                         ItemIDType oldest_id) {
  for (unsigned int i = 0; i < items_in_inventory_; ++i) {
    ItemInstance* item = inventory_[i].item.dereference();
    if (!item) {
      repackInventory();
      return false;
    } else {
      if (item->getDescription()->type_index == item_type &&
          item->getUniqueID() >= oldest_id) { // consider only new items
        quantity -= item->getQuantity();
        if (quantity <= 0) return true;
      }
    }
  }
  return false;
}
int QualityBasedMiningToolItemTypeComponent::getPower(const ItemInstance& itemInstance) const
{
    if(_strengths.size() == 0)
    {
        return 0;
    }
    ItemInstanceComponent* comp = itemInstance.getComponent(ItemInstanceComponent::QualityItemInstanceComponent);
    int quality = comp == 0 ? 0 : static_cast<QualityItemInstanceComponent*>(comp)->getQualityValue();
    return quality < 0 ? _strengths.front() : quality >= _strengths.size() ? _strengths.back() : _strengths[quality];
}
Beispiel #15
0
void Room::initializeFromFile(std::ifstream& fin, std::vector<Monster>& temp, std::vector<Items>& temp2, int level) {
	initialized = true;
	fin >> width;
	fin >> height;

	int nMonsters;
	fin >> nMonsters;
	for (int i = 0; i < nMonsters; i++) {
		std::string name;
		fin >> name;
		MonsterInstance* m = 0;
		for (int i = 0; i < temp.size(); i++) {
			if (!name.compare(temp[i].getName()))
				m = new MonsterInstance(temp[i]);
		}
		if (m == 0) throw "bad monster name";
		int x, y;
		fin >> x;
		fin >> y;
		m->setCoords(x, y);
		monsters.push_back(*m);
	}

	int nItems;
	fin >> nItems;
	for (int i = 0; i < nItems; i++) {
		std::string name;
		fin >> name;
		ItemInstance* m = 0;
		for (int i = 0; i < temp2.size(); i++) {
			if (!name.compare(temp2[i].getName()))
				m = new ItemInstance(temp2[i]);
		}
		if (m == 0) throw "bad item name";
		int x, y;
		fin >> x;
		fin >> y;
		m->setCoords(x, y);
		items.push_back(*m);
	}
}
//----[  giveItem  ]-----------------------------------------------------------
bool ClientItemsInterface::giveItem(ItemPointer* item_pointer,
                                    unsigned int* assigned_index) {
  if (!item_pointer || item_pointer->invalid()) return false;
  ItemInstance* item = item_pointer->dereferenceAssumingValid(); // justified by prev. line

  int source_quantity = item->getQuantity();
  if (source_quantity < 0) return false;

  // stack with existing items
  if (item->isStackable()) {
    unsigned int start_search_index = 0;
    while (item &&
           start_search_index < items_in_inventory_) { // keep the index safe!
      ItemInstance* stackable_item = NULL;
      if (!findStackableItemInInventory(item,
                                       start_search_index,
                                      &start_search_index,
                                      &stackable_item)) break;
      inventory_dirty_bits_.set(start_search_index);
      update_inventory_ = true;
      ++start_search_index;
      item->setQuantity(stackable_item->addQuantity(item->getQuantity()));
      if (item->getQuantity() <= 0) {
        GlobalItemManager::singleton()->releaseItem(item_pointer);
        item = NULL;
      }
    }
  }

  // add to the inventory
  return item ? addToInventory(*item_pointer, assigned_index) : true;
}
//----[  consumeItem  ]--------------------------------------------------------
bool ClientItemsInterface::consumeItem(unsigned int index,
                                       Magic::MagicIndex* magic_index) {
  assert(magic_index);
  if (!inventoryItemIsValid(index)) return false;
  ItemInstance* item = inventory_[index].item.dereferenceAssumingValid(); // guaranteed OK
  const Item::ItemServerDescription* description
    = item->getDescription();
  if (description->consumable_magic ==
        Magic::INVALID_MAGIC_INDEX) return false;
  *magic_index = description->consumable_magic;
  if (item->removeQuantity(1) >= 0) {
    // this item has been fully consumed
    GlobalDatabaseManager::singleton()->itemOnAvatarErased(item->getUniqueID());
    GlobalItemManager::singleton()->releaseItem(&inventory_[index].item);
    shiftDownToEraseInInventory(index);
  } else {
    // item is still available
    update_inventory_ = true;
    inventory_dirty_bits_.set(index);
  }
  todo("karl","if equipped consumable and consumed, change equipment");
  return true;
}
Beispiel #18
0
void Room::initializeRandom(std::vector<Monster>& tempM, std::vector<Items>& tempI, int level) {
	initialized = true;
	width = 5 + rand() % 5;
	height = 5 + rand() % 5;

	int nMonsters = maxMonsters != 0?rand() % maxMonsters:0;
	std::vector<Monster> vm;
	for (int i = 0; i < tempM.size(); i++) {
		if (tempM[i].getScale() <= level) vm.push_back(tempM[i]);
	}

	for (int i = 0; i < nMonsters; i++) {
		MonsterInstance m(vm[rand() % vm.size()]);
		m.setCoords(rand() % width, rand() % height);
		monsters.push_back(m);
	}

	int nItems = rand() % maxItems;
	std::vector<Items> wal;
	std::vector<Items> ol;
	for (int i = 1; i < tempI.size(); i++) {
		if (tempI[i].getType() == 2) {
			if (tempI[i].getScale() <= level) ol.push_back(tempI[i]);
		} else if (tempI[i].getScale() <= level) wal.push_back(tempI[i]);
	}

	for (int i = 0; i < nItems; i++) {
		ItemInstance* m;
		if (rand() % 100 < 20) {
			m = new ItemInstance(wal[rand() % wal.size()]);
		} else  {
			m = new ItemInstance(ol[rand() % ol.size()]);
		}
		m->setCoords(rand() % width, rand() % height);
		items.push_back(*m);
	}
}
//----[  changeEquipped  ]-----------------------------------------------------
bool ClientItemsInterface::changeEquipped(unsigned int item_index) {
  if (!inventoryItemIsValid(item_index)) return false;

  ItemInstance* item = inventory_[item_index].item.dereference();
  int quantity = item->getQuantity();
  if (!canHoldItems(1) && quantity > 1) return false;

  equipment_changed_ = true;
  inventory_[item_index].equipped = !inventory_[item_index].equipped;
  update_inventory_ = true;
  inventory_dirty_bits_.set(item_index);

  if (quantity > 1) {
    int quantity_to_remove = quantity - 1;
    item->removeQuantity(quantity_to_remove);
    ItemPointer new_item;
    bool succeeded = false;
    if (GlobalItemManager::singleton()->acquireNewItem(
          quantity_to_remove,
          item->getDescription()->type_index,
          &new_item)) {
      unsigned int new_index;
      if (giveItem(&new_item, &new_index)) {
        succeeded = true;
      }
    }
    if (!succeeded) {
      // put the quantity back since this new item doesn't exist
      item->addQuantity(quantity_to_remove);
      // make the item unequipped
      inventory_[item_index].equipped = false;
    }
  }

  return true;
}
Beispiel #20
0
Void CharStatPackage::_ComputePersistentStatModifiers()
{
    // Modifiers from passives
    for( UInt i = 0; i < CHARSTAT_COUNT; ++i )
        m_arrPassiveStatModifier[i] = 0.0f;

    m_pOwner->EnumSkills();
    SkillInstance * pSkillInstance = m_pOwner->EnumNextSkill();
    while( pSkillInstance != NULL ) {
        if ( pSkillInstance->IsPassive() ) {
            const Scalar * arrBonus = ( (PassiveSkill*)(pSkillInstance->GetSkill()) )->GetStatBonus();
            for( UInt i = 0; i < CHARSTAT_COUNT; ++i )
                m_arrPassiveStatModifier[i] += arrBonus[i];
        }
        pSkillInstance = m_pOwner->EnumNextSkill();
    }

    // Modifiers from items
    for( UInt i = 0; i < CHARSTAT_COUNT; ++i )
        m_arrItemStatModifier[i] = 0.0f;

    for( UInt i = 0; i < EQUIPSLOTID_COUNT; ++i ) {
        ItemInstance * pItemInstance = m_pOwner->GetItem( (EquipmentSoltID)i );
        if ( pItemInstance->IsEmpty() )
            continue;
        Assert( pItemInstance->GetItem()->GetType() == ITEMTYPE_EQUIPMENT );
        EquipmentItem * pItem = (EquipmentItem*)( pItemInstance->GetItem() );
        const Scalar * arrBonus = pItem->GetStatBonus();
        for( UInt j = 0; j < CHARSTAT_COUNT; ++j )
            m_arrItemStatModifier[j] += arrBonus[j];
    }

    // Final stats
    for( UInt i = 0; i < CHARSTAT_COUNT; ++i )
        m_arrFinalStat[i] = ( m_arrModdedStat[i] + m_arrPassiveStatModifier[i] + m_arrItemStatModifier[i] );
}
void PickaxeItem::hurtEnemy(ItemInstance &item, Mob*, Mob *victim) const
{
	item.hurtAndBreak(2, victim);
}
Beispiel #22
0
// Remove all items from container
void EQEmu::ItemInstance::ClearByFlags(byFlagSetting is_nodrop, byFlagSetting is_norent)
{
	// TODO: This needs work...

	// Destroy container contents
	std::map<uint8, ItemInstance*>::const_iterator cur, end, del;
	cur = m_contents.begin();
	end = m_contents.end();
	for (; cur != end;) {
		ItemInstance* inst = cur->second;
		if (inst == nullptr) {
			cur = m_contents.erase(cur);
			continue;
		}

		const ItemData* item = inst->GetItem();
		if (item == nullptr) {
			cur = m_contents.erase(cur);
			continue;
		}

		del = cur;
		++cur;

		switch (is_nodrop) {
		case byFlagSet:
			if (item->NoDrop == 0) {
				safe_delete(inst);
				m_contents.erase(del->first);
				continue;
			}
			// no 'break;' deletes 'byFlagNotSet' type - can't add at the moment because it really *breaks* the process somewhere
		case byFlagNotSet:
			if (item->NoDrop != 0) {
				safe_delete(inst);
				m_contents.erase(del->first);
				continue;
			}
		default:
			break;
		}

		switch (is_norent) {
		case byFlagSet:
			if (item->NoRent == 0) {
				safe_delete(inst);
				m_contents.erase(del->first);
				continue;
			}
			// no 'break;' deletes 'byFlagNotSet' type - can't add at the moment because it really *breaks* the process somewhere
		case byFlagNotSet:
			if (item->NoRent != 0) {
				safe_delete(inst);
				m_contents.erase(del->first);
				continue;
			}
		default:
			break;
		}
	}
}
bool PickaxeItem::mineBlock(ItemInstance &item, BlockID, int, int, int, Entity *entity) const
{
	item.hurtAndBreak(1, entity);
}
Beispiel #24
0
ItemInstance * Inventory::EquipItem( EquipmentSoltID idEquipSlot, InventoryBagID idBag, UInt iSlot )
{
    Assert( idBag < INVENTORYBAGID_COUNT && iSlot < INVENTORY_BAG_SIZE );

    ItemInstance * pSwap = m_arrBags[idBag].arrSlots[iSlot];
    if ( pSwap == NULL )
        return NULL;

    switch( idEquipSlot ) {
        case EQUIPSLOTID_HEAD:            if ( pSwap->GetClass() != ITEMCLASS_HEAD ) return NULL; break;
        case EQUIPSLOTID_CHEST:           if ( pSwap->GetClass() != ITEMCLASS_CHEST ) return NULL; break;
        case EQUIPSLOTID_SHOULDERS:       if ( pSwap->GetClass() != ITEMCLASS_SHOULDERS ) return NULL; break;
        case EQUIPSLOTID_ARMS:            if ( pSwap->GetClass() != ITEMCLASS_ARMS ) return NULL; break;
        case EQUIPSLOTID_WRISTS:          if ( pSwap->GetClass() != ITEMCLASS_WRISTS ) return NULL; break;
        case EQUIPSLOTID_HANDS:           if ( pSwap->GetClass() != ITEMCLASS_HANDS ) return NULL; break;
        case EQUIPSLOTID_LEGS:            if ( pSwap->GetClass() != ITEMCLASS_LEGS ) return NULL; break;
        case EQUIPSLOTID_FEET:            if ( pSwap->GetClass() != ITEMCLASS_FEET ) return NULL; break;
        case EQUIPSLOTID_NECK:            if ( pSwap->GetClass() != ITEMCLASS_NECK ) return NULL; break;
        case EQUIPSLOTID_BELT:            if ( pSwap->GetClass() != ITEMCLASS_BELT ) return NULL; break;
        case EQUIPSLOTID_RING_1:
        case EQUIPSLOTID_RING_2:          if ( pSwap->GetClass() != ITEMCLASS_RING ) return NULL; break;
        case EQUIPSLOTID_TRINKET_1:
        case EQUIPSLOTID_TRINKET_2:       if ( pSwap->GetClass() != ITEMCLASS_TRINKET ) return NULL; break;
        case EQUIPSLOTID_TOOL_RIGHT:      if ( pSwap->GetClass() != ITEMCLASS_TOOL_RIGHT ) return NULL; break;
        case EQUIPSLOTID_TOOL_LEFT:       if ( pSwap->GetClass() != ITEMCLASS_TOOL_LEFT ) return NULL; break;
        case EQUIPSLOTID_TOOL_DISTANCE:   if ( pSwap->GetClass() != ITEMCLASS_TOOL_DISTANCE ) return NULL; break;
        case EQUIPSLOTID_WEAPON_RIGHT:    if ( pSwap->GetClass() != ITEMCLASS_WEAPON_RIGHT ) return NULL; break;
        case EQUIPSLOTID_WEAPON_LEFT:     if ( pSwap->GetClass() != ITEMCLASS_WEAPON_LEFT ) return NULL; break;
        case EQUIPSLOTID_WEAPON_DISTANCE: if ( pSwap->GetClass() != ITEMCLASS_WEAPON_DISTANCE ) return NULL; break;
        default: Assert(false); break;
    }

    if ( pSwap->GetBindType() == ITEMBIND_ON_EQUIP )
        pSwap->Bind();

    m_arrBags[idBag].arrSlots[iSlot] = m_arrEquipmentSlots[idEquipSlot];
    m_arrEquipmentSlots[idEquipSlot] = pSwap;

    return pSwap;
}
//----[  dropItemsOnDeath  ]---------------------------------------------------
void ClientItemsInterface::dropItemsOnDeath(int equipped_items_to_drop,
                                            Map* map,
                                            int x,
                                            int y) {
  WorldRegion* region = map->acquireRegionFromPoint(x, y);
  if (!region || (items_in_inventory_ == 0)) return;

  // equipped items are temporarily listed here
  kg::Array<AvatarInventoryItem,AVATAR_INVENTORY_SIZE> items_not_dropped;

  // drop all inventory items and count the equipped items
  for (unsigned int i = 0; i < items_in_inventory_; ++i) {
    ItemInstance* item = inventory_[i].item.dereference();
    confirm(item) else continue;
    if (!item->getDescription()->drop_on_death ||
        inventory_[i].equipped) {
      items_not_dropped.add(inventory_[i]);
    } else {
      region->addItemOnGround(true, x, y, inventory_[i].item);
    }
    inventory_[i].item.reset();
    inventory_[i].stackable = false;
    inventory_[i].equipped = false;
  }

  // NOTE: items_in_inventory_ (the private member variable) will hold
  //       the OLD number of items until the end of this method--so
  //       don't touch it!  this is so that we can tell if the # of items
  //       changed.

  // move non-drop items back into the inventory
  unsigned int items_in_inventory = 0;
  for (unsigned int i = 0; i < items_not_dropped.count;) {
    ItemInstance* item = items_not_dropped[i].item.dereference();
    if (!item->getDescription()->drop_on_death) {
      memcpy(&inventory_[items_in_inventory],
             &items_not_dropped[i],
             sizeof(AvatarInventoryItem));
      ++items_in_inventory;
      items_not_dropped[i].item.reset();
      items_not_dropped.swapRemoveMemcpy(i);
    } else {
      ++i;
    }
  }

  // drop equipped items
  if (equipped_items_to_drop >= items_not_dropped.count) { 

    // drop everything
    for (unsigned int i = 0; i < items_not_dropped.count;) {
      ItemInstance* item = items_not_dropped[i].item.dereference();
      region->addItemOnGround(true, x, y, items_not_dropped[i].item);
      items_not_dropped[i].item.reset();
      items_not_dropped.swapRemoveMemcpy(i);
    }

  } else {

    // randomly pick items to drop
    int number_of_items_dropped = 0;
    while (number_of_items_dropped < equipped_items_to_drop) {
      confirm(items_not_dropped.count > 0) else break;
      int slot = rand()%items_not_dropped.count;

      ItemInstance* item = items_not_dropped[slot].item.dereference();
      region->addItemOnGround(true, x, y, items_not_dropped[slot].item);
      items_not_dropped[slot].item.reset();
      items_not_dropped.swapRemoveMemcpy(slot);

      ++number_of_items_dropped;
    }

  }

  // move items that weren't dropped back into the inventory
  for (unsigned int i = 0; i < items_not_dropped.count; ++i) {
    ItemInstance* item = items_not_dropped[i].item.dereference();
    memcpy(&inventory_[items_in_inventory],
           &items_not_dropped[i],
           sizeof(AvatarInventoryItem));
    // If the item provides on-death magic, ensure it is no longer
    // equipped.  This causes Valtus Mederi Charms and the like to
    // only prevent death once (until the user can get back up and
    // re-equip one) even if multiple are equipped.
    if (item->getDescription()->on_death_magic
          != Magic::INVALID_MAGIC_INDEX) {
      inventory_[items_in_inventory].equipped = false;
    }

    ++items_in_inventory;
  }

  /*

  // drop all inventory items and count the equipped items
  unsigned int first_remaining_item = AVATAR_INVENTORY_SIZE,
               last_remaining_item = 0;
  for (unsigned int i = 0; i < items_in_inventory_; ++i) {
    ItemInstance* item = inventory_[i].item.dereference();
    assert(item);
    if (!item->getDescription()->drop_on_death ||
        inventory_[i].equipped) {
      if (i < first_remaining_item) first_remaining_item = i;
      last_remaining_item = i;
    } else {
      region->addItemOnGround(true, x, y, inventory_[i].item);
      inventory_[i].item.reset();
      inventory_[i].stackable = false;
    }
  }

  // will hold the number of items left in the inventory
  int items_in_inventory = 0;

  // copy down remaining equipped items
  for (unsigned int i = first_remaining_item;
                    i <= last_remaining_item;
                  ++i) {
    if (inventory_[i].item.invalid()) continue;
    assert(inventory_[i].equipped ||
          !inventory_[i].item.dereference()->getDescription()->drop_on_death);
    if (i != items_in_inventory) {
      memcpy(&inventory_[items_in_inventory],
             &inventory_[i],
             sizeof(AvatarInventoryItem));
    }
    ++items_in_inventory;
  }

  if (equipped_items_to_drop >= items_in_inventory) {

    int items_remaining = 0;

    // drop everything; leave nothing (except non-drop items)
    for (unsigned int i = 0;
                      i < items_in_inventory;
                    ++i) {
      ItemInstance* item = inventory_[i].item.dereference();
      assert(item);
      if (item->getDescription()->drop_on_death) {
        equipment_changed_ = true;
        region->addItemOnGround(true, x, y, inventory_[i].item);
        inventory_[i].item.reset();
        inventory_[i].stackable = false;
        inventory_[i].equipped = false;
      } else {
        if (i != items_remaining) {
          memcpy(&inventory_[items_remaining],
                 &inventory_[i],
                 sizeof(AvatarInventoryItem));
        }
        ++items_remaining;
      }
    }

    items_in_inventory = items_remaining;

  } else {
    // go in a loop
    assert(items_in_inventory > 0);
    int first_item = rand()%items_in_inventory;
    int i = first_item;
    int number_of_items_dropped = 0;
    do {
      ItemInstance* item = inventory_[i].item.dereference();
      assert(item);
      if (item->getDescription()->drop_on_death) {
        assert(inventory_[i].equipped);
        region->addItemOnGround(true, x, y, inventory_[i].item);
        inventory_[i].item.reset();
        inventory_[i].stackable = false;
        inventory_[i].equipped = false;
        ++number_of_items_dropped;
      }
      i = (i + 1) % items_in_inventory;
    } while (i != first_item &&
             (number_of_items_dropped < equipped_items_to_drop));

    // copy down all remaining valid items, but unequip them
    // if they gave on-death magic
    int remaining_items = 0;
    for (int j = 0; j < items_in_inventory; ++j) {
      if (inventory_[j].item.invalid() == false) {
        if (inventory_[j].item.dereference()->getDescription()->on_death_magic
              != Magic::INVALID_MAGIC_INDEX) {
          // this should cause Valtus Mederi Charms and other special
          // items to unequip themselves when a character dies, but
          // it will leave all non-dropped equipment on the character
          inventory_[j].equipped = false;
        }
        if (j != remaining_items) {
          memcpy(&inventory_[remaining_items],
                 &inventory_[j],
                 sizeof(AvatarInventoryItem));
          ++remaining_items;
        }
      }
    }

    items_in_inventory_ = remaining_items;
  }
*/
  // did anything change?
  if (items_in_inventory != items_in_inventory_) {
    equipment_changed_ = true;
    region->broadcastUpdateItemsOnLocation(x, y);
    inventory_dirty_bits_.setRange(0, items_in_inventory_);
    items_in_inventory_ = items_in_inventory;
    commit();
  }
}