void CShop::AddPersistentStartingEquipment() { const CInventory &sourceInventory = *gameLocal.persistentPlayerInventory; // Cycle through all categories to add them for( int c = 0; c < sourceInventory.GetNumCategories(); ++c ) { const CInventoryCategoryPtr &category = sourceInventory.GetCategory( c ); for( int itemIdx = 0; itemIdx < category->GetNumItems(); ++itemIdx ) { const CInventoryItemPtr &item = category->GetItem( itemIdx ); if( item->GetPersistentCount() <= 0 ) { DM_LOG( LC_MAINMENU, LT_DEBUG )LOGSTRING( "Item %s is not marked as persistent, won't add to shop.\r", item->GetName().c_str() ); continue; // not marked as persistent } const idDict *itemDict = item->GetSavedItemEntityDict(); if( itemDict == NULL ) { DM_LOG( LC_MAINMENU, LT_WARNING )LOGSTRING( "Item %s is marked as persistent, but has no saved item dictionary.\r", item->GetName().c_str() ); continue; } idStr className = itemDict->GetString( "classname" ); // Try to look up the corresponding shop item definition for this item's classname CShopItemPtr found = FindShopItemDefByClassName( className ); if( found == NULL ) { DM_LOG( LC_MAINMENU, LT_DEBUG )LOGSTRING( "Can't find shopitem definition for classname %s, skipping.\r", className.c_str() ); continue; } int quantity = GetQuantityForItem( item ); // Don't attempt to merge if we don't have anything to merge in the first place if( quantity == 0 ) { DM_LOG( LC_MAINMENU, LT_DEBUG )LOGSTRING( "Persistent weapon doesn't have ammo, skipping.\r", className.c_str() ); continue; } // Check if this is a weapon CInventoryWeaponItemPtr weaponItem = boost::dynamic_pointer_cast<CInventoryWeaponItem>( item ); bool isWeapon = ( weaponItem != NULL ); bool weaponIsAllowedEmpty = weaponItem ? weaponItem->IsAllowedEmpty() : false; bool itemMerged = MergeIntoStartingEquipment( className, quantity, isWeapon, weaponIsAllowedEmpty ); // Append the item to the list if it didn't contribute quantity to // an existing list item. if( !itemMerged ) { CShopItemPtr anItem( new CShopItem( *found, quantity, 0, false ) ); bool canDrop = itemDict->GetBool( "inv_droppable", "1" ); anItem->SetCanDrop( canDrop ); _startingItems.Append( anItem ); } } } }
void CShop::AddMapItems(idMapFile* mapFile) { // get the difficulty level idStr diffString = "diff_" + idStr(gameLocal.m_DifficultyManager.GetDifficultyLevel()) + "_nospawn"; // Cycle through map entities. Since the number of entities can change in the loop, // always refresh the entity count used to terminate the loop. // Skip entity 0, which is the world. for (int i = 1; i < mapFile->GetNumEntities(); i++) { idMapEntity* mapEnt = mapFile->GetEntity(i); // does this entity have an inv_map_start spawnflag set to 1? if (mapEnt->epairs.GetBool("inv_map_start", "0")) { // does this entity exist in the chosen difficulty level? if (idStr::Icmp(mapEnt->epairs.GetString(diffString, "0"), "0") == 0) { idStr className = mapEnt->epairs.GetString("classname"); int quantity; bool isWeapon = false; // is this an arrow? int max_ammo = 1; // in case this is a weapon // Special handling for arrows. The shop definitions allow for // atdm:weapon_*, but not atdm:ammo_*. The latter form is used on // map entities. If this is an atdm:ammo_* entity, change its ID (itemName) // to the allowable atdm:weapon_* form. if (className.Find("atdm:ammo_") >= 0) { isWeapon = true; className.Replace( "atdm:ammo_", "atdm:weapon_" ); // An arrow's quantity is defined by "inv_ammo_amount" instead // of "inv_count". Look for that. quantity = mapEnt->epairs.GetInt("inv_ammo_amount", "0"); // Arrow quantities have limits. See if you can find the limit // for this weapon. if (quantity > 0) { max_ammo = GetMaxAmmo(className); quantity = (quantity > max_ammo) ? max_ammo : quantity; } } else { quantity = mapEnt->epairs.GetInt("inv_count", "1"); } if (quantity > 0) { CShopItemPtr found = FindShopItemDefByClassName(className); if (found != NULL) { // We don't have much info about the weapon item at this point and FindEntityDefDict() is lagging // so let's assume there is only a shortsword and blackjack as possible melee items for now bool isMeleeWeapon = (className.Cmp("atdm:weapon_shortsword") == 0 || className.Cmp("atdm:weapon_blackjack") == 0); // If this item is stackable, and already exists in the _startingItems list, // bump up the quantity there instead of appending the item to the list. // If the item is not stackable, and we already have it, ignore it. bool itemMerged = MergeIntoStartingEquipment(className, quantity, isWeapon, isMeleeWeapon); // Append the item to the list if it didn't contribute quantity to // an existing list item. if (!itemMerged) { CShopItemPtr anItem(new CShopItem(*found, quantity, 0, false)); bool canDrop = mapEnt->epairs.GetBool("inv_droppable", "1"); anItem->SetCanDrop(canDrop); _startingItems.Append(anItem); } } else { gameLocal.Warning("Map entity is not a valid shop item: %s", className.c_str()); } } } } } }