bool CInventory::ReplaceItem(idEntity* oldItemEnt, idEntity* newItemEnt) { if (oldItemEnt == NULL) return false; idStr oldInvName = oldItemEnt->spawnArgs.GetString("inv_name"); CInventoryItemPtr oldItem = GetItem(oldInvName); if (oldItem == NULL) { gameLocal.Warning("Could not find old inventory item for %s", oldItemEnt->name.c_str()); DM_LOG(LC_INVENTORY, LT_DEBUG)LOGSTRING("Could not find old inventory item for %s\n", oldItemEnt->name.c_str()); return false; } // greebo: Let's call PutItem on the new entity first to see what kind of item this is // PutItem will also take care of the mission data callbacks for the objectives CInventoryItemPtr newItem = PutItem(newItemEnt, m_Owner.GetEntity()); if (newItem != NULL && newItem->Category() == oldItem->Category()) { // New item has been added, swap the old and the new one to fulfil the inventory position guarantee oldItem->Category()->SwapItemPosition(oldItem, newItem); } // If SwapItemPosition has been called, newItem now takes the place of oldItem before the operation. // Remove the old item in any case, but only if the items are actually different. // In case anybody wonder, newItem might be the same as oldItem in the case of stackable items or loot. if (oldItem != newItem) { RemoveItem(oldItem); } return true; }
bool CFrobLock::CanBeUsedBy(const CInventoryItemPtr& item, const bool isFrobUse) { // First, check if the frob master can be used // If this doesn't succeed, perform additional checks idEntity* master = GetFrobMaster(); if( master != NULL && master->CanBeUsedBy(item, isFrobUse) ) { return true; } if (item == NULL) return false; assert(item->Category() != NULL); const idStr& categoryName = item->Category()->GetName(); if (categoryName == "#str_02392" ) // Keys { // Keys can always be used on doors // Exception: for "frob use" this only applies when the mover is locked return (isFrobUse) ? IsLocked() : true; } else if (categoryName == "#str_02389" ) // Lockpicks { if (!m_Lock->IsPickable()) { // Lock is not pickable DM_LOG(LC_LOCKPICK, LT_DEBUG)LOGSTRING("FrobLock %s is not pickable\r", name.c_str()); return false; } // Lockpicks behave similar to keys return (isFrobUse) ? IsLocked() : true; } return false; }
void CInventory::RemoveItem(const CInventoryItemPtr& item) { if (item == NULL) return; // Update the cursors first for (int i = 0; i < m_Cursor.Num(); i++) { if (m_Cursor[i]->GetCurrentItem() == item) { // Advance the cursor, this should be enough m_Cursor[i]->GetNextItem(); } } // Now remove the item, the cursors are updated. item->Category()->RemoveItem(item); }
bool CFrobLock::UseBy(EImpulseState impulseState, const CInventoryItemPtr& item) { if (item == NULL) return false; // Pass the call on to the master, if we have one if (GetFrobMaster() != NULL) { return GetFrobMaster()->UseBy(impulseState, item); } assert(item->Category() != NULL); // Retrieve the entity behind that item and reject NULL entities idEntity* itemEntity = item->GetItemEntity(); if (itemEntity == NULL) return false; // Get the name of this inventory category const idStr& categoryName = item->Category()->GetName(); if (categoryName == "#str_02392" && impulseState == EPressed ) // Keys { // Keys can be used on button PRESS event, let's see if the key matches if (m_UsedByName.FindIndex(itemEntity->name) != -1) { // just toggle the lock. ToggleLock(); return true; } else { FrobLockStartSound("snd_wrong_key"); return false; } } else if (categoryName == "#str_02389" ) // Lockpicks { if (!m_Lock->IsPickable()) { // Lock is not pickable DM_LOG(LC_LOCKPICK, LT_DEBUG)LOGSTRING("FrobLock %s is not pickable\r", name.c_str()); return false; } // First we check if this item is a lockpick. It has to be of correct type idStr str = itemEntity->spawnArgs.GetString("lockpick_type", ""); if (str.Length() == 1) { // greebo: Check if the item owner is a player, and if yes, // update the immobilization flags. idEntity* itemOwner = item->GetOwner(); if (itemOwner->IsType(idPlayer::Type)) { idPlayer* playerOwner = static_cast<idPlayer*>(itemOwner); playerOwner->SetImmobilization("Lockpicking", EIM_ATTACK); // Schedule an event 1/3 sec. from now, to enable weapons again after this time CancelEvents(&EV_TDM_FrobLock_ClearPlayerImmobilization); PostEventMS(&EV_TDM_FrobLock_ClearPlayerImmobilization, 300, playerOwner); } // Pass the call to the lockpick routine return m_Lock->ProcessLockpickImpulse(impulseState, static_cast<int>(str[0])); } else { gameLocal.Warning("Wrong 'lockpick_type' spawnarg for lockpicking on item %s, must be a single character.", itemEntity->name.c_str()); return false; } } return false; }