void inventory::restack(player *p) { // tasks that the old restack seemed to do: // 1. reassign inventory letters // 2. remove items from non-matching stacks // 3. combine matching stacks if (!p) { return; } std::list<item> to_restack; for (invstack::iterator iter = items.begin(); iter != items.end(); ++iter) { if (!iter->front().invlet_is_okay() || p->has_weapon_or_armor(iter->front().invlet)) { assign_empty_invlet(iter->front(), p); for (std::list<item>::iterator stack_iter = iter->begin(); stack_iter != iter->end(); ++stack_iter) { stack_iter->invlet = iter->front().invlet; } } // remove non-matching items while (iter->size() > 0 && !iter->front().stacks_with(iter->back())) { to_restack.splice(to_restack.begin(), *iter, iter->begin()); } if (iter->size() <= 0) { iter = items.erase(iter); --iter; continue; } } // combine matching stacks // separate loop to ensure that ALL stacks are homogeneous for (invstack::iterator iter = items.begin(); iter != items.end(); ++iter) { for (invstack::iterator other = iter; other != items.end(); ++other) { if (iter != other && iter->front().type->id == other->front().type->id) { if (other->front().charges != -1 && (other->front().is_food() || other->front().is_ammo())) { iter->front().charges += other->front().charges; } else if (iter->front().stacks_with(other->front())) { iter->splice(iter->begin(), *other); } else { continue; } other = items.erase(other); --other; } } } //re-add non-matching items for (std::list<item>::iterator iter = to_restack.begin(); iter != to_restack.end(); ++iter) { add_item(*iter); } }
void inventory::restack( player &p ) { // tasks that the old restack seemed to do: // 1. reassign inventory letters // 2. remove items from non-matching stacks // 3. combine matching stacks binned = false; std::list<item> to_restack; int idx = 0; for( invstack::iterator iter = items.begin(); iter != items.end(); ++iter, ++idx ) { std::list<item> &stack = *iter; item &topmost = stack.front(); const int ipos = p.invlet_to_position( topmost.invlet ); if( !inv_chars.valid( topmost.invlet ) || ( ipos != INT_MIN && ipos != idx ) ) { assign_empty_invlet( topmost, p ); for( auto &stack_iter : stack ) { stack_iter.invlet = topmost.invlet; } } // remove non-matching items, stripping off end of stack so the first item keeps the invlet. while( stack.size() > 1 && !topmost.stacks_with( stack.back() ) ) { to_restack.splice( to_restack.begin(), *iter, --stack.end() ); } } // combine matching stacks // separate loop to ensure that ALL stacks are homogeneous for( invstack::iterator iter = items.begin(); iter != items.end(); ++iter ) { for( invstack::iterator other = iter; other != items.end(); ++other ) { if( iter != other && iter->front().stacks_with( other->front() ) ) { if( other->front().count_by_charges() ) { iter->front().charges += other->front().charges; } else { iter->splice( iter->begin(), *other ); } other = items.erase( other ); --other; } } } //re-add non-matching items for( auto &elem : to_restack ) { add_item( elem ); } //Ensure that all items in the same stack have the same invlet. for( std::list< item > &outer : items ) { for( item &inner : outer ) { inner.invlet = outer.front().invlet; } } items.sort( stack_compare ); #if defined(__ANDROID__) remove_stale_inventory_quick_shortcuts(); #endif }
item& inventory::add_item(item newit, bool keep_invlet, bool assign_invlet) { //dprint("inv.add_item(%d): [%c] %s", keep_invlet, newit.invlet, newit.typeId().c_str() ); bool reuse_cached_letter = false; // Check how many stacks of this type already are in our inventory. if(!keep_invlet && assign_invlet) { // Do we have this item in our inventory favourites cache? char temp_invlet = get_invlet_for_item( newit.typeId() ); if( temp_invlet != 0 ) { newit.invlet = temp_invlet; reuse_cached_letter = true; } // If it's not in our cache and not a lowercase letter, try to give it a low letter. if(!reuse_cached_letter && (newit.invlet < 'a' || newit.invlet > 'z')) { assign_empty_invlet(newit); } // Make sure the assigned invlet doesn't exist already. if(g->u.has_item(newit.invlet)) { assign_empty_invlet(newit); } } // See if we can't stack this item. for (invstack::iterator iter = items.begin(); iter != items.end(); ++iter) { std::list<item>::iterator it_ref = iter->begin(); if (it_ref->type->id == newit.type->id) { if (newit.charges != -1 && (newit.is_food() || newit.is_ammo())) { it_ref->charges += newit.charges; return *it_ref; } else if (it_ref->stacks_with(newit)) { if (it_ref->is_food() && it_ref->has_flag("HOT")) { int tmpcounter = (it_ref->item_counter + newit.item_counter) / 2; it_ref->item_counter = tmpcounter; newit.item_counter = tmpcounter; } newit.invlet = it_ref->invlet; iter->push_back(newit); return iter->back(); } else if (keep_invlet && assign_invlet && it_ref->invlet == newit.invlet) { assign_empty_invlet(*it_ref); } } // If keep_invlet is true, we'll be forcing other items out of their current invlet. else if (keep_invlet && assign_invlet && it_ref->invlet == newit.invlet) { assign_empty_invlet(*it_ref); } } // Couldn't stack the item, proceed. if(!reuse_cached_letter) { update_cache_with_item(newit); } std::list<item> newstack; newstack.push_back(newit); items.push_back(newstack); return items.back().back(); }