/** * Check to see if an item is stackable in the inventory */ bool inven_stack_okay(const object_type *o_ptr) { struct object *gear_obj; int new_number; bool extra_slot; /* Check for similarity */ for (gear_obj = player->gear; gear_obj; gear_obj = gear_obj->next) { /* Skip equipped items and non-objects */ if (object_is_equipped(player->body, gear_obj)) continue; if (!gear_obj) continue; /* Check if the two items can be combined */ if (object_similar(gear_obj, o_ptr, OSTACK_PACK)) break; } /* Definite no */ if (!gear_obj) return FALSE; /* Add it and see what happens */ gear_obj->number += o_ptr->number; extra_slot = (gear_obj->number > z_info->stack_size); new_number = pack_slots_used(player); gear_obj->number -= o_ptr->number; /* Analyse the results */ if (new_number + (extra_slot ? 1 : 0) > z_info->pack_size) return FALSE; return TRUE; }
/** * Check if we have space for an item in the pack without overflow */ bool inven_carry_okay(const object_type *obj) { /* Empty slot? */ if (pack_slots_used(player) < z_info->pack_size) return TRUE; /* Check if it can stack */ if (inven_stack_okay(obj)) return TRUE; /* Nope */ return FALSE; }
/** * Calculate how much of an item is can be carried in the inventory or quiver. * * Optionally only return a positive value if there is already a similar object. */ int inven_carry_num(const struct object *obj, bool stack) { struct object *gear_obj; int i, num_left = obj->number; /* Check for similarity */ if (stack) { for (gear_obj = player->gear; gear_obj; gear_obj = gear_obj->next) { /* Skip equipped items and non-objects */ if (object_is_equipped(player->body, gear_obj)) continue; if (!gear_obj) continue; /* Check if the two items can be combined */ if (object_stackable(gear_obj, obj, OSTACK_PACK)) break; } /* No similar object, so no stacking */ if (!gear_obj) return 0; } /* Free inventory slots, so there is definitely room */ if (pack_slots_used(player) < z_info->pack_size) return obj->number; /* Absorb as many as we can in the quiver */ num_left -= quiver_absorb_num(obj); /* See if we can add to a part full inventory slot */ for (i = 0; i < z_info->pack_size; i++) { struct object *inven_obj = player->upkeep->inven[i]; if (!inven_obj) continue; if (!object_stackable(inven_obj, obj, OSTACK_PACK)) continue; num_left -= z_info->stack_size - inven_obj->number; } /* Return the number we can absorb */ num_left = MAX(num_left, 0); return obj->number - num_left; }
/** * Calculate how much of an item is can be carried in the inventory or quiver. * * Optionally only return a positive value if there is already a similar object. */ int inven_carry_num(const struct object *obj, bool stack) { /* Check for similarity */ if (stack) { struct object *gear_obj; for (gear_obj = player->gear; gear_obj; gear_obj = gear_obj->next) { if (!object_is_equipped(player->body, gear_obj) && object_stackable(gear_obj, obj, OSTACK_PACK)) { break; } } /* No similar object, so no stacking */ if (!gear_obj) { return 0; } } /* Free inventory slots, so there is definitely room */ if (pack_slots_used(player) < z_info->pack_size) { return obj->number; } else { int i; /* Absorb as many as we can in the quiver */ int num_left = obj->number - quiver_absorb_num(obj); /* See if we can add to a part full inventory slot */ for (i = 0; i < z_info->pack_size; i++) { struct object *inven_obj = player->upkeep->inven[i]; if (inven_obj && object_stackable(inven_obj, obj, OSTACK_PACK)) { num_left -= inven_obj->kind->base->max_stack - inven_obj->number; } } /* Return the number we can absorb */ return obj->number - MAX(num_left, 0); } }
/** * Returns whether the pack is holding the maximum number of items. */ bool pack_is_full(void) { return pack_slots_used(player) == z_info->pack_size ? true : false; }
/** * Add an item to the players inventory. * * If the new item can combine with an existing item in the inventory, * it will do so, using object_similar() and object_absorb(), else, * the item will be placed into the first available gear array index. * * This function can be used to "over-fill" the player's pack, but only * once, and such an action must trigger the "overflow" code immediately. * Note that when the pack is being "over-filled", the new item must be * placed into the "overflow" slot, and the "overflow" must take place * before the pack is reordered, but (optionally) after the pack is * combined. This may be tricky. See "dungeon.c" for info. * * Note that this code removes any location information from the object once * it is placed into the inventory, but takes no responsibility for removing * the object from any other pile it was in. */ void inven_carry(struct player *p, struct object *obj, bool absorb, bool message) { struct object *gear_obj; char o_name[80]; /* Check for combining, if appropriate */ if (absorb) { for (gear_obj = p->gear; gear_obj; gear_obj = gear_obj->next) { /* Can't stack equipment */ if (object_is_equipped(p->body, gear_obj)) continue; /* Check if the two items can be combined */ if (object_similar(gear_obj, obj, OSTACK_PACK)) { /* Increase the weight */ p->upkeep->total_weight += (obj->number * obj->weight); /* Combine the items, and their known versions */ object_absorb(gear_obj->known, obj->known); obj->known = NULL; object_absorb(gear_obj, obj); /* Describe the combined object */ object_desc(o_name, sizeof(o_name), gear_obj, ODESC_PREFIX | ODESC_FULL); /* Recalculate bonuses */ p->upkeep->update |= (PU_BONUS | PU_INVEN); /* Redraw stuff */ p->upkeep->redraw |= (PR_INVEN); /* Inventory will need updating */ update_stuff(player); /* Optionally, display a message */ if (message) msg("You have %s (%c).", o_name, gear_to_label(gear_obj)); /* Sound for quiver objects */ if (object_is_in_quiver(p, gear_obj)) sound(MSG_QUIVER); /* Success */ return; } } } /* Paranoia */ assert(pack_slots_used(p) <= z_info->pack_size); /* Add to the end of the list */ gear_insert_end(obj); /* Apply an autoinscription */ apply_autoinscription(obj); /* Remove cave object details */ obj->held_m_idx = 0; obj->iy = obj->ix = 0; obj->known->iy = obj->known->ix = 0; /* Update the inventory */ p->upkeep->total_weight += (obj->number * obj->weight); p->upkeep->update |= (PU_BONUS | PU_INVEN); p->upkeep->notice |= (PN_COMBINE); p->upkeep->redraw |= (PR_INVEN); /* Inventory will need updating */ update_stuff(player); /* Hobbits ID mushrooms on pickup, gnomes ID wands and staffs on pickup */ if (!object_flavor_is_aware(obj)) { if (player_has(player, PF_KNOW_MUSHROOM) && tval_is_mushroom(obj)) { object_flavor_aware(obj); msg("Mushrooms for breakfast!"); } else if (player_has(player, PF_KNOW_ZAPPER) && tval_is_zapper(obj)) object_flavor_aware(obj); } /* Optionally, display a message */ if (message) { /* Describe the object */ object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL); /* Message */ msg("You have %s (%c).", o_name, gear_to_label(obj)); } /* Sound for quiver objects */ if (object_is_in_quiver(p, obj)) sound(MSG_QUIVER); }
/** * Returns whether the pack is holding the more than the maximum number of * items. If this is true, calling pack_overflow() will trigger a pack overflow. */ bool pack_is_overfull(void) { return pack_slots_used(player) > z_info->pack_size ? TRUE : FALSE; }
/** * Add an item to the players inventory. * * If the new item can combine with an existing item in the inventory, * it will do so, using object_similar() and object_absorb(), else, * the item will be placed into the first available gear array index. * * This function can be used to "over-fill" the player's pack, but only * once, and such an action must trigger the "overflow" code immediately. * Note that when the pack is being "over-filled", the new item must be * placed into the "overflow" slot, and the "overflow" must take place * before the pack is reordered, but (optionally) after the pack is * combined. This may be tricky. See "dungeon.c" for info. * * Note that this code removes any location information from the object once * it is placed into the inventory, but takes no responsibility for removing * the object from any other pile it was in. */ void inven_carry(struct player *p, struct object *obj, bool absorb, bool message) { bool combining = false; /* Check for combining, if appropriate */ if (absorb) { struct object *combine_item = NULL; struct object *gear_obj = p->gear; while (combine_item == false && gear_obj) { if (!object_is_equipped(p->body, gear_obj) && object_similar(gear_obj, obj, OSTACK_PACK)) { combine_item = gear_obj; } gear_obj = gear_obj->next; } if (combine_item) { /* Increase the weight */ p->upkeep->total_weight += (obj->number * obj->weight); /* Combine the items, and their known versions */ object_absorb(combine_item->known, obj->known); obj->known = NULL; object_absorb(combine_item, obj); obj = combine_item; combining = true; } } /* We didn't manage the find an object to combine with */ if (!combining) { /* Paranoia */ assert(pack_slots_used(p) <= z_info->pack_size); gear_insert_end(obj); apply_autoinscription(obj); /* Remove cave object details */ obj->held_m_idx = 0; obj->grid = loc(0, 0); obj->known->grid = loc(0, 0); /* Update the inventory */ p->upkeep->total_weight += (obj->number * obj->weight); p->upkeep->notice |= (PN_COMBINE); /* Hobbits ID mushrooms on pickup, gnomes ID wands and staffs on pickup */ if (!object_flavor_is_aware(obj)) { if (player_has(player, PF_KNOW_MUSHROOM) && tval_is_mushroom(obj)) { object_flavor_aware(obj); msg("Mushrooms for breakfast!"); } else if (player_has(player, PF_KNOW_ZAPPER) && tval_is_zapper(obj)) object_flavor_aware(obj); } } p->upkeep->update |= (PU_BONUS | PU_INVEN); p->upkeep->redraw |= (PR_INVEN); update_stuff(player); if (message) { char o_name[80]; object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL); msg("You have %s (%c).", o_name, gear_to_label(obj)); } if (object_is_in_quiver(p, obj)) sound(MSG_QUIVER); }