int32_t PListViewInvoke(void *pobject, void *in, void *out, void *extraData) { if (!pobject || !in || !out) return B_ERROR; PView *parent = static_cast<PView*>(pobject); if (!parent) return B_BAD_TYPE; BListView *backend = (BListView*)parent->GetView(); PArgs *args = static_cast<PArgs*>(in); int32 what; if (args->FindInt32("message", &what) != B_OK) what = -1; if (backend->Window()) backend->Window()->Lock(); if (what >= 0) { BMessage invMsg(what); backend->Invoke(&invMsg); } else backend->Invoke(); if (backend->Window()) backend->Window()->Unlock(); return B_OK; }
status_t PListView::SetProperty(const char *name, PValue *value, const int32 &index) { if (!name || !value) return B_ERROR; BString str(name); PProperty *prop = FindProperty(name,index); if (!prop) return B_NAME_NOT_FOUND; if (FlagsForProperty(prop) & PROPERTY_READ_ONLY) return B_READ_ONLY; BListView *backend = (BListView*)fView; BoolValue boolval; CharValue charval; ColorValue colorval; FloatValue floatval; IntValue intval; PointValue pointval; RectValue rectval; StringValue stringval; status_t status = prop->SetValue(value); if (status != B_OK) return status; if (backend->Window()) backend->Window()->Lock(); else if (str.ICompare("SelectionMessage") == 0) { BMessage selMsg(*intval.value); backend->SetSelectionMessage(&selMsg); } else if (str.ICompare("InvocationMessage") == 0) { BMessage invMsg(*intval.value); backend->SetInvocationMessage(&invMsg); } else if (str.ICompare("SelectionType") == 0) { prop->GetValue(&intval); backend->SetListType((list_view_type)*intval.value); } else { if (backend->Window()) backend->Window()->Unlock(); return PView::SetProperty(name, value, index); } if (backend->Window()) backend->Window()->Unlock(); return prop->GetValue(value); }
unsigned Inventory::removeFromSlot(unsigned slot, unsigned amount) { InventoryData::iterator it = mPoss->inventory.find(slot); // When the given slot doesn't exist, we can't remove anything if (it == mPoss->inventory.end()) return amount; LOG_DEBUG("Inventory: Request Removal of " << amount << " item(s) in slot: " << slot << " for character: '" << mCharacter->getComponent<BeingComponent>()->getName() << "'."); MessageOut invMsg(GPMSG_INVENTORY); // Check if an item of the same id exists elsewhere in the inventory bool exists = false; for (InventoryData::const_iterator it2 = mPoss->inventory.begin(), it2_end = mPoss->inventory.end(); it2 != it2_end; ++it2) { if (it2->second.itemId == it->second.itemId && it->first != it2->first) { exists = true; break; } } // We check whether it's the last slot where we can find that item id. bool lastSlotOfItemRemaining = false; if (!exists && it->second.itemId) lastSlotOfItemRemaining = true; unsigned sub = std::min(amount, it->second.amount); amount -= sub; it->second.amount -= sub; invMsg.writeInt16(it->first); if (it->second.amount) { invMsg.writeInt16(it->second.itemId); invMsg.writeInt16(it->second.amount); } else { invMsg.writeInt16(0); // The item(s) was(were) the last one(s) in the inventory. if (lastSlotOfItemRemaining) { if (ItemClass *ic = itemManager->getItem(it->second.itemId)) ic->useTrigger(mCharacter, ITT_LEAVE_INVY); } mPoss->inventory.erase(it); } if (invMsg.getLength() > 2) gameHandler->sendTo(mCharacter, invMsg); return amount; }
unsigned Inventory::move(unsigned slot1, unsigned slot2, unsigned amount) { LOG_DEBUG(amount << " item(s) requested to move from: " << slot1 << " to " << slot2 << " for character: '" << mCharacter->getComponent<BeingComponent>()->getName() << "'."); if (!amount || slot1 == slot2 || slot2 >= INVENTORY_SLOTS) return amount; InventoryData::iterator it1 = mPoss->inventory.find(slot1), it2 = mPoss->inventory.find(slot2), inv_end = mPoss->inventory.end(); if (it1 == inv_end) return amount; MessageOut invMsg(GPMSG_INVENTORY); unsigned nb = std::min(amount, it1->second.amount); if (it2 == inv_end) { // Slot2 does not yet exist. mPoss->inventory[slot2].itemId = it1->second.itemId; nb = std::min(itemManager->getItem(it1->second.itemId)->getMaxPerSlot(), nb); mPoss->inventory[slot2].amount = nb; it1->second.amount -= nb; amount -= nb; //Save the itemId in case of deletion of the iterator unsigned itemId = it1->second.itemId; invMsg.writeInt16(slot1); // Slot if (it1->second.amount) { invMsg.writeInt16(it1->second.itemId); // Item Id invMsg.writeInt16(it1->second.amount); // Amount LOG_DEBUG("Left " << amount << " item(s) id:" << it1->second.itemId << " into slot: " << slot1); } else { invMsg.writeInt16(0); mPoss->inventory.erase(it1); LOG_DEBUG("Slot: " << slot1 << " is now empty."); } invMsg.writeInt16(slot2); // Slot invMsg.writeInt16(itemId); // Item Id (same as slot 1) invMsg.writeInt16(nb); // Amount LOG_DEBUG("Slot: " << slot2 << " has now " << nb << " of item id: " << itemId); } else { // Slot2 exists. if (it2->second.itemId != it1->second.itemId) { // Swap items when they are of a different type // and when all the amount of slot 1 is moving onto slot 2. if (amount >= it1->second.amount) { unsigned itemId = it1->second.itemId; unsigned amount = it1->second.amount; it1->second.itemId = it2->second.itemId; it1->second.amount = it2->second.amount; it2->second.itemId = itemId; it2->second.amount = amount; // Sending swapped slots. invMsg.writeInt16(slot1); invMsg.writeInt16(it1->second.itemId); invMsg.writeInt16(it1->second.amount); invMsg.writeInt16(slot2); invMsg.writeInt16(it2->second.itemId); invMsg.writeInt16(it2->second.amount); LOG_DEBUG("Swapping items in slots " << slot1 << " and " << slot2); } else { // Cannot partially stack items of a different type. LOG_DEBUG("Cannot move " << amount << " item(s) from slot " << slot1 << " to " << slot2); return amount; } } else // Same item type on slot 2. { // Number of items moving nb = std::min(itemManager->getItem( it1->second.itemId)->getMaxPerSlot() - it2->second.amount, nb); // If nothing can move, we can abort if (!nb) return amount; it1->second.amount -= nb; it2->second.amount += nb; amount -= nb; invMsg.writeInt16(slot1); // Slot if (it1->second.amount) { invMsg.writeInt16(it1->second.itemId); // Item Id invMsg.writeInt16(it1->second.amount); // Amount } else { invMsg.writeInt16(0); mPoss->inventory.erase(it1); } invMsg.writeInt16(slot2); // Slot invMsg.writeInt16(it2->second.itemId); // Item Id invMsg.writeInt16(it2->second.amount); // Amount } } if (invMsg.getLength() > 2) gameHandler->sendTo(mCharacter, invMsg); return amount; }
unsigned Inventory::remove(unsigned itemId, unsigned amount) { if (!itemId || !amount) return amount; LOG_DEBUG("Inventory: Request remove of " << amount << " item(s) id: " << itemId << " for character: '" << mCharacter->getComponent<BeingComponent>()->getName() << "'."); MessageOut invMsg(GPMSG_INVENTORY); bool triggerLeaveInventory = true; for (InventoryData::iterator it = mPoss->inventory.begin(); it != mPoss->inventory.end();) { LOG_DEBUG("Remove: Treating slot id: " << it->first); if (it->second.itemId == itemId) { if (amount) { unsigned sub = std::min(amount, it->second.amount); amount -= sub; it->second.amount -= sub; invMsg.writeInt16(it->first); if (it->second.amount) { invMsg.writeInt16(it->second.itemId); invMsg.writeInt16(it->second.amount); // Some still exist, and we have none left to remove, so // no need to run leave invy triggers. if (!amount) triggerLeaveInventory = false; LOG_DEBUG("Slot id: " << it->first << " has now " << it->second.amount << "item(s)."); } else { invMsg.writeInt16(0); // Ensure the slot is set empty. LOG_DEBUG("Slot id: " << it->first << " is now empty."); mPoss->inventory.erase(it++); continue; } } else { // We found an instance of them existing and have none left to // remove, so no need to run leave invy triggers. triggerLeaveInventory = false; } } ++it; } if (triggerLeaveInventory) itemManager->getItem(itemId)->useTrigger(mCharacter, ITT_LEAVE_INVY); if (invMsg.getLength() > 2) gameHandler->sendTo(mCharacter, invMsg); return amount; }
unsigned Inventory::insert(unsigned itemId, unsigned amount) { if (!itemId || !amount) return 0; MessageOut invMsg(GPMSG_INVENTORY); ItemClass *item = itemManager->getItem(itemId); if (!item) { LOG_ERROR("Inventory: Trying to insert invalid item id " << itemId << " (amount: " << amount << ")"); return amount; } unsigned maxPerSlot = item->getMaxPerSlot(); LOG_DEBUG("Inventory: Inserting " << amount << " item(s) Id: " << itemId << " for character '" << mCharacter->getComponent<BeingComponent>()->getName() << "'."); InventoryData::iterator it, it_end = mPoss->inventory.end(); // Add to slots with existing items of this type first. for (it = mPoss->inventory.begin(); it != it_end; ++it) { if (it->second.itemId == itemId) { // If the slot is full, try the next slot if (it->second.amount >= maxPerSlot) continue; // Add everything that'll fit to the stack unsigned short spaceLeft = maxPerSlot - it->second.amount; if (spaceLeft >= amount) { it->second.amount += amount; amount = 0; LOG_DEBUG("Everything inserted at slot id: " << it->first); } else { it->second.amount += spaceLeft; amount -= spaceLeft; LOG_DEBUG(spaceLeft << " item(s) inserted at slot id: " << it->first); } invMsg.writeInt16(it->first); invMsg.writeInt16(itemId); invMsg.writeInt16(it->second.amount); if (!amount) break; } } int slot = 0; // We still have some left, so add to blank slots. for (it = mPoss->inventory.begin();; ++it) { if (!amount) break; int lim = (it == it_end) ? INVENTORY_SLOTS : it->first; while (amount && slot < lim) { int additions = std::min(amount, maxPerSlot); mPoss->inventory[slot].itemId = itemId; mPoss->inventory[slot].amount = additions; amount -= additions; LOG_DEBUG(additions << " item(s) inserted at slot id: " << slot); invMsg.writeInt16(slot++); // Last read, so also increment invMsg.writeInt16(itemId); invMsg.writeInt16(additions); } ++slot; // Skip the slot that the iterator points to if (it == it_end) break; } item->useTrigger(mCharacter, ITT_IN_INVY); // Send that first, before checking potential removals if (invMsg.getLength() > 2) gameHandler->sendTo(mCharacter, invMsg); return amount; }