/** * Remove an amount of an object from the inventory or quiver, returning * a detached object which can be used. * * Optionally describe what remains. */ struct object *gear_object_for_use(struct object *obj, int num, bool message) { struct object *usable; char name[80]; char label = gear_to_label(obj); bool artifact = obj->artifact && (object_is_known(obj) || object_name_is_visible(obj)); /* Bounds check */ num = MIN(num, obj->number); /* Prepare a name if necessary */ if (message) { /* Artifacts */ if (artifact) object_desc(name, sizeof(name), obj, ODESC_FULL | ODESC_SINGULAR); else { /* Describe as if it's already reduced */ obj->number -= num; object_desc(name, sizeof(name), obj, ODESC_PREFIX | ODESC_FULL); obj->number += num; } } /* Split off a usable object if necessary */ if (obj->number > num) { usable = object_split(obj, num); } else { /* We're using the entire stack */ usable = obj; gear_excise_object(usable); /* Stop tracking item */ if (tracked_object_is(player->upkeep, obj)) track_object(player->upkeep, NULL); /* Inventory has changed, so disable repeat command */ cmd_disable_repeat(); } /* Change the weight */ player->upkeep->total_weight -= (num * obj->weight); /* Housekeeping */ player->upkeep->update |= (PU_BONUS); player->upkeep->notice |= (PN_COMBINE); player->upkeep->redraw |= (PR_INVEN | PR_EQUIP); /* Print a message if desired */ if (message) { if (artifact) msg("You no longer have the %s (%c).", name, label); else msg("You have %s (%c).", name, label); } return usable; }
/** * Remove an amount of an object from the floor, returning a detached object * which can be used - it is assumed that the object is on the player grid. * * Optionally describe what remains. */ struct object *floor_object_for_use(struct object *obj, int num, bool message, bool *none_left) { struct object *usable; char name[80]; /* Bounds check */ num = MIN(num, obj->number); /* Split off a usable object if necessary */ if (obj->number > num) { usable = object_split(obj, num); } else { usable = obj; square_excise_object(player->cave, usable->iy, usable->ix, usable->known); delist_object(player->cave, usable->known); square_excise_object(cave, usable->iy, usable->ix, usable); delist_object(cave, usable); *none_left = true; /* Stop tracking item */ if (tracked_object_is(player->upkeep, obj)) track_object(player->upkeep, NULL); /* Inventory has changed, so disable repeat command */ cmd_disable_repeat(); } /* Object no longer has a location */ usable->known->iy = 0; usable->known->ix = 0; usable->iy = 0; usable->ix = 0; /* Housekeeping */ player->upkeep->update |= (PU_BONUS | PU_INVEN); player->upkeep->notice |= (PN_COMBINE); player->upkeep->redraw |= (PR_INVEN | PR_EQUIP); /* Print a message if requested and there is anything left */ if (message) { if (usable == obj) obj->number = 0; /* Get a description */ object_desc(name, sizeof(name), obj, ODESC_PREFIX | ODESC_FULL); if (usable == obj) obj->number = num; /* Print a message */ msg("You see %s.", name); } return usable; }
/** * Combine items in the pack, confirming no blank objects or gold */ void combine_pack(void) { struct object *obj1, *obj2, *prev; bool display_message = false; /* Combine the pack (backwards) */ obj1 = gear_last_item(); while (obj1) { assert(obj1->kind); assert(!tval_is_money(obj1)); prev = obj1->prev; /* Scan the items above that item */ for (obj2 = player->gear; obj2 && obj2 != obj1; obj2 = obj2->next) { assert(obj2->kind); /* Can we drop "obj1" onto "obj2"? */ if (object_similar(obj2, obj1, OSTACK_PACK)) { display_message = true; object_absorb(obj2->known, obj1->known); obj1->known = NULL; object_absorb(obj2, obj1); break; } else if (inven_can_stack_partial(obj2, obj1, OSTACK_PACK)) { /* Setting this to true spams the combine message. */ display_message = false; object_absorb_partial(obj2->known, obj1->known); object_absorb_partial(obj2, obj1); break; } } obj1 = prev; } calc_inventory(player->upkeep, player->gear, player->body); /* Redraw gear */ event_signal(EVENT_INVENTORY); event_signal(EVENT_EQUIPMENT); /* Message */ if (display_message) { msg("You combine some items in your pack."); /* Stop "repeat last command" from working. */ cmd_disable_repeat(); } }
/** * Combine items in the pack, confirming no blank objects or gold */ void combine_pack(void) { struct object *obj1, *obj2; bool display_message = FALSE; bool redraw = FALSE; /* Combine the pack (backwards) */ for (obj1 = gear_last_item(); obj1; obj1 = obj1->prev) { assert(obj1->kind); assert(!tval_is_money(obj1)); /* Scan the items above that item */ for (obj2 = player->gear; obj2 && obj2 != obj1; obj2 = obj2->next) { assert(obj2->kind); /* Can we drop "obj1" onto "obj2"? */ if (object_similar(obj2, obj1, OSTACK_PACK)) { display_message = TRUE; redraw = TRUE; object_absorb(obj2, obj1); } else if (inven_can_stack_partial(obj2, obj1, OSTACK_PACK)) { /* Setting this to TRUE spams the combine message. */ display_message = FALSE; redraw = TRUE; object_absorb_partial(obj2, obj1); break; } } } calc_inventory(player->upkeep, player->gear, player->body); /* Redraw stuff */ if (redraw) { player->upkeep->redraw |= (PR_INVEN | PR_EQUIP); player->upkeep->update |= (PU_INVEN); } /* Message */ if (display_message) { msg("You combine some items in your pack."); /* Stop "repeat last command" from working. */ cmd_disable_repeat(); } }
/** * Wield or wear a single item from the pack or floor */ void inven_wield(struct object *obj, int slot) { struct object *wielded, *old = player->body.slots[slot].obj; const char *fmt; char o_name[80]; bool dummy = false; /* Increase equipment counter if empty slot */ if (old == NULL) player->upkeep->equip_cnt++; /* Take a turn */ player->upkeep->energy_use = z_info->move_energy; /* It's either a gear object or a floor object */ if (object_is_carried(player, obj)) { /* Split off a new object if necessary */ if (obj->number > 1) { wielded = gear_object_for_use(obj, 1, false, &dummy); /* The new item needs new gear and known gear entries */ wielded->next = obj->next; obj->next = wielded; wielded->prev = obj; if (wielded->next) (wielded->next)->prev = wielded; wielded->known->next = obj->known->next; obj->known->next = wielded->known; wielded->known->prev = obj->known; if (wielded->known->next) (wielded->known->next)->prev = wielded->known; } else { /* Just use the object directly */ wielded = obj; } } else { /* Get a floor item and carry it */ wielded = floor_object_for_use(obj, 1, false, &dummy); inven_carry(player, wielded, false, false); } /* Wear the new stuff */ player->body.slots[slot].obj = wielded; /* Do any ID-on-wield */ object_learn_on_wield(player, wielded); /* Where is the item now */ if (tval_is_melee_weapon(wielded)) fmt = "You are wielding %s (%c)."; else if (wielded->tval == TV_BOW) fmt = "You are shooting with %s (%c)."; else if (tval_is_light(wielded)) fmt = "Your light source is %s (%c)."; else fmt = "You are wearing %s (%c)."; /* Describe the result */ object_desc(o_name, sizeof(o_name), wielded, ODESC_PREFIX | ODESC_FULL); /* Message */ msgt(MSG_WIELD, fmt, o_name, I2A(slot)); /* Cursed! */ if (wielded->curses) { /* Warn the player */ msgt(MSG_CURSED, "Oops! It feels deathly cold!"); } /* See if we have to overflow the pack */ combine_pack(); pack_overflow(old); /* Recalculate bonuses, torch, mana, gear */ player->upkeep->notice |= (PN_IGNORE); player->upkeep->update |= (PU_BONUS | PU_INVEN); player->upkeep->redraw |= (PR_INVEN | PR_EQUIP | PR_ARMOR); player->upkeep->redraw |= (PR_STATS | PR_HP | PR_MANA | PR_SPEED); /* Disable repeats */ cmd_disable_repeat(); }
/** * Wield or wear a single item from the pack or floor */ void inven_wield(struct object *obj, int slot) { struct object *wielded, *old = player->body.slots[slot].obj; const char *fmt; char o_name[80]; /* Increase equipment counter if empty slot */ if (old == NULL) player->upkeep->equip_cnt++; /* Take a turn */ player->upkeep->energy_use = z_info->move_energy; /* Split off a new object if necessary */ if (obj->number > 1) { /* Split off a new single object */ wielded = object_split(obj, 1); /* If it's a gear object, give the split item a list entry */ if (pile_contains(player->gear, obj)) { wielded->next = obj->next; obj->next = wielded; wielded->prev = obj; if (wielded->next) (wielded->next)->prev = wielded; } } else wielded = obj; /* Carry floor items, don't allow combining */ if (square_holds_object(cave, player->py, player->px, wielded)) { square_excise_object(cave, player->py, player->px, wielded); inven_carry(player, wielded, FALSE, FALSE); } /* Wear the new stuff */ player->body.slots[slot].obj = wielded; /* Do any ID-on-wield */ object_notice_on_wield(wielded); /* Where is the item now */ if (tval_is_melee_weapon(wielded)) fmt = "You are wielding %s (%c)."; else if (wielded->tval == TV_BOW) fmt = "You are shooting with %s (%c)."; else if (tval_is_light(wielded)) fmt = "Your light source is %s (%c)."; else fmt = "You are wearing %s (%c)."; /* Describe the result */ object_desc(o_name, sizeof(o_name), wielded, ODESC_PREFIX | ODESC_FULL); /* Message */ msgt(MSG_WIELD, fmt, o_name, I2A(slot)); /* Cursed! */ if (cursed_p(wielded->flags)) { /* Warn the player */ msgt(MSG_CURSED, "Oops! It feels deathly cold!"); /* Sense the object */ object_notice_curses(wielded); } /* See if we have to overflow the pack */ combine_pack(); pack_overflow(old); /* Recalculate bonuses, torch, mana, gear */ player->upkeep->notice |= (PN_IGNORE); player->upkeep->update |= (PU_BONUS | PU_INVEN); player->upkeep->redraw |= (PR_INVEN | PR_EQUIP | PR_ARMOR); player->upkeep->redraw |= (PR_STATS | PR_HP | PR_MANA | PR_SPEED); /* Disable repeats */ cmd_disable_repeat(); }