Example #1
0
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
	);
}
Example #2
0
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;
}