void CInventory::PutItem(const CInventoryItemPtr& item, const idStr& categoryName) { if (item == NULL) return; CInventoryCategoryPtr category; // Check if it is the default group or not. if (categoryName.IsEmpty()) { // category is empty, assign the item to the default group category = m_Category[0]; } else { // Try to find the category with the given name category = GetCategory(categoryName); // If not found, create it if (category == NULL) { category = CreateCategory(categoryName); } } // Pack the item into the category category->PutItemFront(item); // Objective callback for non-loot items: // non-loot item passes in inv_name and individual item count, SuperGroupVal of 1 gameLocal.m_MissionData->InventoryCallback( item->GetItemEntity(), item->GetName(), item->GetCount(), 1, true ); }
CInventoryItemPtr CInventory::PutItem(idEntity *ent, idEntity *owner) { // Sanity checks if (ent == NULL || owner == NULL) return CInventoryItemPtr(); // grayman (#2376) - If there's a shop with this item in it, // and this is an inv_map_start item, we won't put it into the // inventory because the player already has it. const ShopItemList& startingItems = gameLocal.m_Shop->GetPlayerStartingEquipment(); bool gotFromShop = ((startingItems.Num() > 0) && (ent->spawnArgs.GetBool("inv_map_start", "0"))); // Check for loot items CInventoryItemPtr returnValue = ValidateLoot(ent,gotFromShop); // grayman (#2376) if (ent->GetAbsenceNoticeability() > 0) { ent->SpawnAbsenceMarker(); } if (returnValue != NULL) { // The item is a valid loot item, remove the entity and return DM_LOG(LC_INVENTORY, LT_DEBUG)LOGSTRING("Added loot item to inventory: %s\r", ent->name.c_str()); // Remove the entity, it is a loot item (which vanishes when added to the inventory) RemoveEntityFromMap(ent, true); return returnValue; } // Let's see if this is an ammunition item returnValue = ValidateAmmo(ent,gotFromShop); // grayman (#2376) if (returnValue != NULL) { DM_LOG(LC_INVENTORY, LT_DEBUG)LOGSTRING("Added ammo item to inventory, removing from map: %s\r", ent->name.c_str()); // Remove the entity from the game, the ammunition is added RemoveEntityFromMap(ent, true); return returnValue; } // Check for a weapon item returnValue = ValidateWeapon(ent,gotFromShop); // grayman (#2376) if (returnValue != NULL) { DM_LOG(LC_INVENTORY, LT_DEBUG)LOGSTRING("Added weapon item to inventory, removing from map: %s\r", ent->name.c_str()); // Remove the entity from the game, the ammunition is added RemoveEntityFromMap(ent, true); return returnValue; } // Not a loot or ammo item, determine name and category to check for existing item of same name/category idStr name = ent->spawnArgs.GetString("inv_name", ""); idStr category = ent->spawnArgs.GetString("inv_category", ""); // Tels: Replace "\n" with \x0a, otherwise multiline spawnargs set inside DR do not work name.Replace( "\\n", "\n" ); category.Replace( "\\n", "\n" ); if (name.IsEmpty() || category.IsEmpty()) { // Invalid inv_name or inv_category DM_LOG(LC_INVENTORY, LT_ERROR)LOGSTRING("Cannot put %s in inventory: inv_name or inv_category not specified.\r", ent->name.c_str()); return returnValue; } // Check for existing items (create the category if necessary (hence the TRUE)) CInventoryItemPtr existing = GetItem(name, category, true); if (existing != NULL) { // Item must be stackable, if items of the same name/category already exist if (!ent->spawnArgs.GetBool("inv_stackable", "0")) { DM_LOG(LC_INVENTORY, LT_ERROR)LOGSTRING("Cannot put %s in inventory: not stackable.\r", ent->name.c_str()); // grayman #2467 - Remove the entity from the game if it was already put into the inventory by the shop code. if (gotFromShop) { RemoveEntityFromMap(ent, true); } return returnValue; } // Item is stackable, determine how many items should be added to the stack int count = ent->spawnArgs.GetInt("inv_count", "1"); // grayman (#2376) - If there's a shop in this mission, all stackable inv_map_start items were shown in // the shop's startingItems list, and have already been given to the player. Check if this // entity is an inv_map_start entity. If it is, check the size of the startingItems list. // If it's 0, then there's no shop and we have to give the player the count from this // entity. If > 0, zero the count because the player already has it. if (gotFromShop) { count = 0; // Item count already given, so clear it. } // Increase the stack count existing->SetCount(existing->GetCount() + count); // Persistent flags are latched - once a inv_persistent item is added to a stack, the whole stack // snaps into persistent mode. if (ent->spawnArgs.GetBool("inv_persistent") && !existing->IsPersistent()) { DM_LOG(LC_INVENTORY, LT_DEBUG)LOGSTRING("Marking stackable items as persistent after picking up one persistent item: %s\r", existing->GetName().c_str()); existing->SetPersistent(true); } // We added a stackable item that was already in the inventory // grayman #3315 - Solution from Zbyl. InventoryCallback() looks at // the existing entity to retrieve a bindmaster, and that's already // been NULLed. So we need to look at the new entity instead. gameLocal.m_MissionData->InventoryCallback( ent, existing->GetName(), existing->GetCount(), 1, true ); // Notify the player, if appropriate // grayman #3316 - correct pickup message, courtesy Zbyl if ( !ent->spawnArgs.GetBool("inv_map_start", "0") && !ent->spawnArgs.GetBool("inv_no_pickup_message", "0") ) { idStr msg = common->Translate(name); if ( count > 1 ) { msg += " x" + idStr(count); } NotifyOwnerAboutPickup(msg, existing); } DM_LOG(LC_INVENTORY, LT_DEBUG)LOGSTRING("Added stackable item to inventory: %s\r", ent->name.c_str()); DM_LOG(LC_INVENTORY, LT_DEBUG)LOGSTRING("New inventory item stack count is: %d\r", existing->GetCount()); // Remove the entity, it has been stacked RemoveEntityFromMap(ent, true); // Return the existing value instead of a newly created one returnValue = existing; } else { // Item doesn't exist, create a new InventoryItem // grayman (#2376) - if we got here, the item isn't already in the inventory, // so it wasn't given by the shop. No code changes needed. CInventoryItemPtr item(new CInventoryItem(ent, owner)); if (item != NULL) { DM_LOG(LC_INVENTORY, LT_DEBUG)LOGSTRING("Adding new inventory item %s to category %s...\r", common->Translate(name.c_str()), common->Translate(category.c_str())); // Put the item into its category PutItem(item, category); // grayman #3313 - Solution is from Zbyl. InventoryCallback() is called from PutItem(), so it's already been done. /* // We added a new inventory item gameLocal.m_MissionData->InventoryCallback( item->GetItemEntity(), item->GetName(), 1, 1, true ); */ // grayman #3316 - correct pickup message, courtesy Zbyl if ( !ent->spawnArgs.GetBool("inv_map_start", "0") && !ent->spawnArgs.GetBool("inv_no_pickup_message", "0") ) { idStr msg = common->Translate(name); if ( item->GetCount() > 1 ) { msg += " x" + idStr(item->GetCount()); } NotifyOwnerAboutPickup(msg, item); } // Hide the entity from the map (don't delete the entity) RemoveEntityFromMap(ent, false); } else { DM_LOG(LC_INVENTORY, LT_ERROR)LOGSTRING("Cannot put item into category: %s.\r", ent->name.c_str()); } returnValue = item; } return returnValue; }