Example #1
0
/**
 * 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;
}
Example #2
0
/**
 * 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;
}
Example #3
0
/**
 * 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();
	}
}
Example #4
0
/**
 * 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();
	}
}
Example #5
0
/**
 * 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();
}
Example #6
0
/**
 * 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();
}