コード例 #1
0
ファイル: obj-gear.c プロジェクト: Daedelus01/angband
/**
 * 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;
}
コード例 #2
0
ファイル: cmd-obj.c プロジェクト: non/angband
void textui_obj_wield(object_type *o_ptr, int item)
{
    int slot = wield_slot(o_ptr);

    /* Usually if the slot is taken we'll just replace the item in the slot,
     * but in some cases we need to ask the user which slot they actually
     * want to replace */
    if (p_ptr->inventory[slot].k_idx)
    {
        if (o_ptr->tval == TV_RING)
        {
            cptr q = "Replace which ring? ";
            cptr s = "Error in obj_wield, please report";
            item_tester_hook = obj_is_ring;
            if (!get_item(&slot, q, s, CMD_WIELD, USE_EQUIP)) return;
        }

        if (obj_is_ammo(o_ptr) && !object_similar(&p_ptr->inventory[slot],
                o_ptr, OSTACK_QUIVER))
        {
            cptr q = "Replace which ammunition? ";
            cptr s = "Error in obj_wield, please report";
            item_tester_hook = obj_is_ammo;
            if (!get_item(&slot, q, s, CMD_WIELD, USE_EQUIP)) return;
        }
    }

    cmd_insert(CMD_WIELD);
    cmd_set_arg_item(cmd_get_top(), 0, item);
    cmd_set_arg_number(cmd_get_top(), 1, slot);
}
コード例 #3
0
ファイル: cmd1.c プロジェクト: eddiegrove/angband
/*
 * Carry an object and delete it.
 */
static void py_pickup_aux(int o_idx, bool domsg)
{
	int slot, quiver_slot = 0;

	char o_name[80];
	object_type *o_ptr = object_byid(o_idx);

	/* Carry the object */
	slot = inven_carry(p_ptr, o_ptr);

	/* Handle errors (paranoia) */
	if (slot < 0) return;

	/* If we have picked up ammo which matches something in the quiver, note
	 * that it so that we can wield it later (and suppress pick up message) */
	if (obj_is_ammo(o_ptr)) 
	{
		int i;
		for (i = QUIVER_START; i < QUIVER_END; i++) 
		{
			if (!p_ptr->inventory[i].kind) continue;
			if (!object_similar(&p_ptr->inventory[i], o_ptr,
				OSTACK_QUIVER)) continue;
			quiver_slot = i;
			break;
		}
	}

	/* Get the new object */
	o_ptr = &p_ptr->inventory[slot];

	/* Set squelch status */
	p_ptr->notice |= PN_SQUELCH;

	/* Automatically sense artifacts */
	object_notice_artifact(o_ptr);

	/* Optionally, display a message */
	if (domsg && !quiver_slot)
	{
		/* Describe the object */
		object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL);

		/* Message */
		msg("You have %s (%c).", o_name, index_to_label(slot));
	}

	/* Update object_idx if necessary */
	if (p_ptr->object_idx == (0 - o_idx))
	{
		track_object(slot);
	}

	/* Delete the object */
	delete_object_idx(o_idx);

	/* If we have a quiver slot that this ammo matches, use it */
	if (quiver_slot) wield_item(o_ptr, slot, quiver_slot);
}
コード例 #4
0
ファイル: obj-pile.c プロジェクト: fizzix/angband
/**
 * Let the floor carry an object, deleting old ignored items if necessary.
 * The calling function must deal with the dropped object on failure.
 *
 * Optionally put the object at the top or bottom of the pile
 */
bool floor_carry(struct chunk *c, int y, int x, struct object *drop, bool last)
{
	int n = 0;
	struct object *obj, *ignore = floor_get_oldest_ignored(y, x);

	/* Fail if the square can't hold objects */
	if (!square_isobjectholding(c, y, x))
		return false;

	/* Scan objects in that grid for combination */
	for (obj = square_object(c, y, x); obj; obj = obj->next) {
		/* Check for combination */
		if (object_similar(obj, drop, OSTACK_FLOOR)) {
			/* Combine the items */
			object_absorb(obj, drop);

			/* Result */
			return true;
		}

		/* Count objects */
		n++;
	}

	/* The stack is already too large */
	if (n >= z_info->floor_size || (!OPT(player, birth_stacking) && n)) {
		/* Delete the oldest ignored object */
		if (ignore) {
			square_excise_object(c, y, x, ignore);
			delist_object(c, ignore);
			object_delete(&ignore);
		} else
			return false;
	}

	/* Location */
	drop->iy = y;
	drop->ix = x;

	/* Forget monster */
	drop->held_m_idx = 0;

	/* Link to the first or last object in the pile */
	if (last)
		pile_insert_end(&c->squares[y][x].obj, drop);
	else
		pile_insert(&c->squares[y][x].obj, drop);

	/* Record in the level list */
	list_object(c, drop);

	/* Redraw */
	square_note_spot(c, y, x);
	square_light_spot(c, y, x);

	/* Result */
	return true;
}
コード例 #5
0
ファイル: obj-gear.c プロジェクト: fe051/angband
/**
 * 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();
	}
}
コード例 #6
0
ファイル: obj-gear.c プロジェクト: Daedelus01/angband
/**
 * 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();
	}
}
コード例 #7
0
ファイル: object2.c プロジェクト: jcubic/ToME
/*
 * Check if we have space for an item in the pack without overflow
 */
bool inven_carry_okay(object_type *o_ptr)
{
	if (has_flag(o_ptr, FLAG_GOLD_VALUE)) return FALSE;

	/* Empty slot? */
	if (inventory_limit(INVEN_INVEN) > flag_max_key(get_inven(p_ptr, INVEN_INVEN))) return (TRUE);

	/* Similar slot? */
	for_inventory(p_ptr, j_ptr, INVEN_INVEN, INVEN_PACK);
	{
		/* Check if the two items can be combined */
		if (object_similar(j_ptr, o_ptr)) return (TRUE);
	}
	end_inventory();

	/* Nope */
	return (FALSE);
} /* inven_carry_okay() */
コード例 #8
0
ファイル: cmd-obj.c プロジェクト: Hrrunstar/angband
/* Wield or wear an item */
void do_cmd_wield(cmd_code code, cmd_arg args[])
{
	object_type *equip_o_ptr;
	char o_name[80];

	unsigned n;

	int item = args[0].item;
	int slot = args[1].number;
	object_type *o_ptr = object_from_item_idx(item);

	if (!item_is_available(item, NULL, USE_INVEN | USE_FLOOR))
	{
		msg("You do not have that item to wield.");
		return;
	}

	/* Check the slot */
	if (!slot_can_wield_item(slot, o_ptr))
	{
		msg("You cannot wield that item there.");
		return;
	}

	equip_o_ptr = &p_ptr->inventory[slot];

	/* If the slot is open, wield and be done */
	if (!equip_o_ptr->kind)
	{
		wield_item(o_ptr, item, slot);
		return;
	}

	/* If the slot is in the quiver and objects can be combined */
	if (obj_is_ammo(equip_o_ptr) && object_similar(equip_o_ptr, o_ptr,
		OSTACK_QUIVER))
	{
		wield_item(o_ptr, item, slot);
		return;
	}

	/* Prevent wielding into a cursed slot */
	if (cursed_p(equip_o_ptr->flags))
	{
		object_desc(o_name, sizeof(o_name), equip_o_ptr, ODESC_BASE);
		msg("The %s you are %s appears to be cursed.", o_name,
				   describe_use(slot));
		return;
	}

	/* "!t" checks for taking off */
	n = check_for_inscrip(equip_o_ptr, "!t");
	while (n--)
	{
		/* Prompt */
		object_desc(o_name, sizeof(o_name), equip_o_ptr,
					ODESC_PREFIX | ODESC_FULL);
		
		/* Forget it */
		if (!get_check(format("Really take off %s? ", o_name))) return;
	}

	wield_item(o_ptr, item, slot);
}
コード例 #9
0
ファイル: cmd-obj.c プロジェクト: Hrrunstar/angband
/*
 * Wield or wear a single item from the pack or floor
 */
void wield_item(object_type *o_ptr, int item, int slot)
{
	object_type object_type_body;
	object_type *i_ptr = &object_type_body;

	const char *fmt;
	char o_name[80];

	bool combined_ammo = FALSE;
	bool track_wielded_item = FALSE;
	int num = 1;

	/* If we are stacking ammo in the quiver */
	if (obj_is_ammo(o_ptr))
	{
		num = o_ptr->number;
		combined_ammo = object_similar(o_ptr, &p_ptr->inventory[slot],
			OSTACK_QUIVER);
	}

	/* Take a turn */
	p_ptr->energy_use = 100;

	/* Obtain local object */
	object_copy(i_ptr, o_ptr);

	/* Modify quantity */
	i_ptr->number = num;

	/* Update object_idx if necessary, once object is in slot */
	if (p_ptr->object_idx == item)
	{
		track_wielded_item = TRUE;
	}

	/* Decrease the item (from the pack) */
	if (item >= 0)
	{
		inven_item_increase(item, -num);
		inven_item_optimize(item);
	}

	/* Decrease the item (from the floor) */
	else
	{
		floor_item_increase(0 - item, -num);
		floor_item_optimize(0 - item);
	}

	/* Get the wield slot */
	o_ptr = &p_ptr->inventory[slot];

	if (combined_ammo)
	{
		/* Add the new ammo to the already-quiver-ed ammo */
		object_absorb(o_ptr, i_ptr);
	}
	else 
	{
		/* Take off existing item */
		if (o_ptr->kind)
			(void)inven_takeoff(slot, 255);

		/* If we are wielding ammo we may need to "open" the slot by shifting
		 * later ammo up the quiver; this is because we already called the
		 * inven_item_optimize() function. */
		if (slot >= QUIVER_START)
			open_quiver_slot(slot);
	
		/* Wear the new stuff */
		object_copy(o_ptr, i_ptr);

		/* Increment the equip counter by hand */
		p_ptr->equip_cnt++;
	}

	/* Increase the weight */
	p_ptr->total_weight += i_ptr->weight * num;

	/* Track object if necessary */
	if (track_wielded_item)
	{
		track_object(slot);
	}

	/* Do any ID-on-wield */
	object_notice_on_wield(o_ptr);

	/* Where is the item now */
	if (slot == INVEN_WIELD)
		fmt = "You are wielding %s (%c).";
	else if (slot == INVEN_BOW)
		fmt = "You are shooting with %s (%c).";
	else if (slot == INVEN_LIGHT)
		fmt = "Your light source is %s (%c).";
	else if (combined_ammo)
		fmt = "You combine %s in your quiver (%c).";
	else if (slot >= QUIVER_START && slot < QUIVER_END)
		fmt = "You add %s to your quiver (%c).";
	else
		fmt = "You are wearing %s (%c).";

	/* Describe the result */
	object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL);

	/* Message */
	msgt(MSG_WIELD, fmt, o_name, index_to_label(slot));

	/* Cursed! */
	if (cursed_p(o_ptr->flags))
	{
		/* Warn the player */
		msgt(MSG_CURSED, "Oops! It feels deathly cold!");

		/* Sense the object */
		object_notice_curses(o_ptr);
	}

	/* Save quiver size */
	save_quiver_size(p_ptr);

	/* See if we have to overflow the pack */
	pack_overflow();

	/* Recalculate bonuses, torch, mana */
	p_ptr->notice |= PN_SORT_QUIVER;
	p_ptr->update |= (PU_BONUS | PU_TORCH | PU_MANA);
	p_ptr->redraw |= (PR_INVEN | PR_EQUIP);
}
コード例 #10
0
ファイル: obj-pile.c プロジェクト: fizzix/angband
/**
 * Find a grid near the given one for an object to fall on
 *
 * We check several locations to see if we can find a location at which
 * the object can combine, stack, or be placed.  Artifacts will try very
 * hard to be placed, including "teleporting" to a useful grid if needed.
 *
 * If no appropriate grid is found, the given grid is unchanged
 */
static void drop_find_grid(struct object *drop, int *y, int *x)
{
	int best_score = -1;
	int best_y = *y;
	int best_x = *x;
	int i, dy, dx;
	struct object *obj;

	/* Scan local grids */
	for (dy = -3; dy <= 3; dy++) {
		for (dx = -3; dx <= 3; dx++) {
			bool combine = false;
			int dist = (dy * dy) + (dx * dx);
			int ty = *y + dy;
			int tx = *x + dx;
			int num_shown = 0;
			int num_ignored = 0;
			int score;

			/* Lots of reasons to say no */
			if ((dist > 10) ||
				!square_in_bounds_fully(cave, ty, tx) ||
				!los(cave, *y, *x, ty, tx) ||
				!square_isfloor(cave, ty, tx) ||
				square_isplayertrap(cave, ty, tx) ||
				square_iswarded(cave, ty, tx))
				continue;

			/* Analyse the grid for carrying the new object */
			for (obj = square_object(cave, ty, tx); obj; obj = obj->next) {
				/* Check for possible combination */
				if (object_similar(obj, drop, OSTACK_FLOOR))
					combine = true;

				/* Count objects */
				if (!ignore_item_ok(obj))
					num_shown++;
				else
					num_ignored++;
			}
			if (!combine)
				num_shown++;

			/* Disallow if the stack size is too big */
			if ((OPT(player, birth_stacking) && (num_shown > 1)) ||
				((num_shown + num_ignored) > z_info->floor_size &&
				 !floor_get_oldest_ignored(ty, tx)))
				continue;

			/* Score the location based on how close and how full the grid is */
			score = 1000 - (dist + num_shown * 5);

			if ((score < best_score) || ((score == best_score) && one_in_(2)))
				continue;

			best_score = score;
			best_y = ty;
			best_x = tx;
		}
	}

	/* Return if we have a score, otherwise fail or try harder for artifacts */
	if (best_score >= 0) {
		*y = best_y;
		*x = best_x;
		return;
	} else if (!drop->artifact) {
		return;
	}
	for (i = 0; i < 2000; i++) {
		/* Start bouncing from grid to grid, stopping if we find an empty one */
		if (i < 1000) {
			best_y = rand_spread(best_y, 1);
			best_x = rand_spread(best_x, 1);
		} else {
			/* Now go to purely random locations */
			best_y = randint0(cave->height);
			best_x = randint0(cave->width);
		}
		if (square_canputitem(cave, best_y, best_x)) {
			*y = best_y;
			*x = best_x;
			return;
		}
	}
}
コード例 #11
0
ファイル: obj-pile.c プロジェクト: awalding/angband
/**
 * Let an object fall to the ground at or near a location.
 *
 * The initial location is assumed to be "square_in_bounds_fully(cave, )".
 *
 * This function takes a parameter "chance".  This is the percentage
 * chance that the item will "disappear" instead of drop.  If the object
 * has been thrown, then this is the chance of disappearance on contact.
 *
 * This function will produce a description of a drop event under the player
 * when "verbose" is true.
 *
 * We check several locations to see if we can find a location at which
 * the object can combine, stack, or be placed.  Artifacts will try very
 * hard to be placed, including "teleporting" to a useful grid if needed.
 *
 * Objects which fail to be carried by the floor are deleted.  This function
 * attempts to add successfully dropped objects to, and to remove failures
 * from, the object list (as dropped items may or may not be already listed).
 */
void drop_near(struct chunk *c, struct object *dropped, int chance, int y,
			   int x, bool verbose)
{
	int i, k, n, d, s;

	int bs, bn;
	int by, bx;
	int dy, dx;
	int ty, tx;

	struct object *obj;

	char o_name[80];

	bool flag = false;

	/* Only called in the current level */
	assert(c == cave);

	/* Describe object */
	object_desc(o_name, sizeof(o_name), dropped, ODESC_BASE);

	/* Handle normal "breakage" */
	if (!dropped->artifact && (randint0(100) < chance)) {
		/* Message */
		msg("The %s %s.", o_name,
			VERB_AGREEMENT(dropped->number, "breaks", "break"));

		/* Failure */
		if (dropped->known) {
			delist_object(cave_k, dropped->known);
			object_delete(&dropped->known);
		}
		delist_object(c, dropped);
		object_delete(&dropped);
		return;
	}

	/* Score */
	bs = -1;

	/* Picker */
	bn = 0;

	/* Default */
	by = y;
	bx = x;

	/* Scan local grids */
	for (dy = -3; dy <= 3; dy++) {
		for (dx = -3; dx <= 3; dx++) {
			bool comb = false;

			/* Calculate actual distance */
			d = (dy * dy) + (dx * dx);

			/* Ignore distant grids */
			if (d > 10) continue;

			/* Location */
			ty = y + dy;
			tx = x + dx;

			/* Skip illegal grids */
			if (!square_in_bounds_fully(c, ty, tx)) continue;

			/* Require line of sight */
			if (!los(c, y, x, ty, tx)) continue;

			/* Require floor space */
			if (!square_isfloor(c, ty, tx)) continue;

			/* Require no trap or rune */
			if (square_isplayertrap(c, ty, tx) ||
				square_iswarded(c, ty, tx))
				continue;

			/* No objects */
			k = 0;
			n = 0;

			/* Scan objects in that grid */
			for (obj = square_object(c, ty, tx); obj; obj = obj->next) {
				/* Check for possible combination */
				if (object_similar(obj, dropped, OSTACK_FLOOR))
					comb = true;

				/* Count objects */
				if (!ignore_item_ok(obj))
					k++;
				else
					n++;
			}

			/* Add new object */
			if (!comb) k++;

			/* Option -- disallow stacking */
			if (OPT(birth_no_stacking) && (k > 1)) continue;

			/* Paranoia? */
			if ((k + n) > z_info->floor_size &&
				!floor_get_oldest_ignored(ty, tx)) continue;

			/* Calculate score */
			s = 1000 - (d + k * 5);

			/* Skip bad values */
			if (s < bs) continue;

			/* New best value */
			if (s > bs) bn = 0;

			/* Apply the randomizer to equivalent values */
			if ((++bn >= 2) && (randint0(bn) != 0)) continue;

			/* Keep score */
			bs = s;

			/* Track it */
			by = ty;
			bx = tx;

			/* Okay */
			flag = true;
		}
	}

	/* Handle lack of space */
	if (!flag && !dropped->artifact) {
		/* Message */
		msg("The %s %s.", o_name,
			VERB_AGREEMENT(dropped->number, "disappears", "disappear"));

		/* Debug */
		if (player->wizard) msg("Breakage (no floor space).");

		/* Failure */
		if (dropped->known) {
			delist_object(cave_k, dropped->known);
			object_delete(&dropped->known);
		}
		delist_object(c, dropped);
		object_delete(&dropped);
		return;
	}

	/* Find a grid */
	for (i = 0; !flag; i++) {
		/* Bounce around */
		if (i < 1000) {
			ty = rand_spread(by, 1);
			tx = rand_spread(bx, 1);
		} else {
			/* Random locations */
			ty = randint0(c->height);
			tx = randint0(c->width);
		}

		/* Require floor space */
		if (!square_canputitem(c, ty, tx)) continue;

		/* Bounce to that location */
		by = ty;
		bx = tx;

		/* Okay */
		flag = true;
	}

	/* Give it to the floor */
	if (!floor_carry(c, by, bx, dropped, false)) {
		/* Message */
		msg("The %s %s.", o_name,
			VERB_AGREEMENT(dropped->number, "disappears", "disappear"));

		/* Debug */
		if (player->wizard) msg("Breakage (too many objects).");

		if (dropped->artifact) dropped->artifact->created = false;

		/* Failure */
		if (dropped->known) {
			delist_object(cave_k, dropped->known);
			object_delete(&dropped->known);
		}
		delist_object(c, dropped);
		object_delete(&dropped);
		return;
	}

	/* Sound */
	sound(MSG_DROP);

	/* Message when an object falls under the player */
	if (verbose && (c->squares[by][bx].mon < 0))
		/* Check the item still exists and isn't ignored */
		if (c->objects[dropped->oidx] && !ignore_item_ok(dropped))
			msg("You feel something roll beneath your feet.");
}
コード例 #12
0
ファイル: cmd3.c プロジェクト: fph/mortsil
/*
 * Wield or wear a single item from the pack or floor
 */
void do_cmd_wield(object_type *default_o_ptr, int default_item)
{
	int item, slot;
	
	object_type *o_ptr;
	
	object_type *i_ptr;
	object_type object_type_body;
	
	cptr act;
	
	cptr q, s;
	
	int i, quantity, original_quantity;
	
	bool weapon_less_effective = FALSE;
	
	bool grants_two_weapon = FALSE;
	
	char o_name[80];
	
	bool combine = FALSE;
	
	// use specified item if possible
	if (default_o_ptr != NULL)
	{
		o_ptr = default_o_ptr;
		item = default_item;
	}
	/* Get an item */
	else
	{
		/* Restrict the choices */
		item_tester_hook = item_tester_hook_wear;
		
		/* Get an item */
		q = "Wear/Wield which item? ";
		s = "You have nothing you can wear or wield.";
		if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
		
		/* Get the item (in the pack) */
		if (item >= 0)
		{
			o_ptr = &inventory[item];
		}
		else
		{
			o_ptr = &o_list[0 - item];
		}
	}
	
	// remember how many there were
	original_quantity = o_ptr->number;
	
	// Check whether it would be too heavy
	if ((item < 0) && (p_ptr->total_weight + o_ptr->weight > weight_limit()*3/2))
	{
		/* Describe it */
		object_desc(o_name, sizeof(o_name), o_ptr, TRUE, 3);
		
		if (o_ptr->k_idx) msg_format("You cannot lift %s.", o_name);
		
		/* Abort */
		return;
	}
	
	
	/* Check the slot */
	slot = wield_slot(o_ptr);
	
	/* Ask for ring to replace */
	if ((o_ptr->tval == TV_RING) &&
		inventory[INVEN_LEFT].k_idx &&
		inventory[INVEN_RIGHT].k_idx)
	{
		/* Restrict the choices */
		item_tester_tval = TV_RING;
		
		/* Choose a ring from the equipment only */
		q = "Replace which ring? ";
		s = "Oops.";
		if (!get_item(&slot, q, s, USE_EQUIP)) return;
	}

	// Special cases for merging arrows
	if (object_similar(&inventory[INVEN_QUIVER1], o_ptr))
	{
		slot = INVEN_QUIVER1;
		combine = TRUE;
	}
	else if (object_similar(&inventory[INVEN_QUIVER2], o_ptr))
	{
		slot = INVEN_QUIVER2;
		combine = TRUE;
	}
	/* Ask for arrow set to replace */
	else if ((o_ptr->tval == TV_ARROW) && inventory[INVEN_QUIVER1].k_idx && inventory[INVEN_QUIVER2].k_idx)
	{
		/* Restrict the choices */
		item_tester_tval = TV_ARROW;
		
		/* Choose a set of arrows from the equipment only */
		q = "Replace which set of arrows? ";
		s = "Oops.";
		if (!get_item(&slot, q, s, USE_EQUIP)) return;
	}
	
	// Ask about two weapon fighting if necessary
	for (i = 0; i < o_ptr->abilities; i++)
	{
		if ((o_ptr->skilltype[i] == S_MEL) && (o_ptr->abilitynum[i] == MEL_TWO_WEAPON) && object_known_p(o_ptr))
		{
			grants_two_weapon = TRUE;
		}
	}
	if ((p_ptr->active_ability[S_MEL][MEL_TWO_WEAPON] || grants_two_weapon) && 
	    ((o_ptr->tval == TV_SWORD) || (o_ptr->tval == TV_POLEARM) || (o_ptr->tval == TV_HAFTED) || (o_ptr->tval == TV_DIGGING)))
	{
		if (!(k_info[o_ptr->k_idx].flags3 & (TR3_TWO_HANDED)))
		{
			if (get_check("Do you wish to wield it in your off-hand? "))
			{
				slot = INVEN_ARM;
			}
		}
	}
	
	/* Prevent wielding into a cursed slot */
	if (cursed_p(&inventory[slot]))
	{
		/* Describe it */
		object_desc(o_name, sizeof(o_name), &inventory[slot], FALSE, 0);
		
		/* Message */
		msg_format("The %s you are %s appears to be cursed.",
		           o_name, describe_use(slot));
		
		/* Cancel the command */
		return;
	}
	
	/* Deal with wielding of two-handed weapons when already using a shield */
	if ((k_info[o_ptr->k_idx].flags3 & (TR3_TWO_HANDED)) && (inventory[INVEN_ARM].k_idx))
	{
		if (cursed_p(&inventory[INVEN_ARM]))
		{
			if (inventory[INVEN_ARM].tval == TV_SHIELD)
			{
				msg_print("You would need to remove your shield, but it appears to be cursed.");
			}
			else
			{
				msg_print("You would need to put down your off-hand weapon, but it appears to be cursed.");
			}
			
			/* Cancel the command */
			return;			
		}
		
		// warn about dropping item in left hand
		if ((item < 0) && (&inventory[INVEN_PACK-1])->tval)
		{
			/* Flush input */
			flush();
			
			if (inventory[INVEN_ARM].tval == TV_SHIELD)
			{
				if (!get_check("This would require removing (and dropping) your shield. Proceed? "))
				{
					/* Cancel the command */
					return;
				}
			}
			else
			{
				msg_print("This would require removing (and dropping) your off-hand weapon.");
				if (!get_check("Proceed? "))
				{
					/* Cancel the command */
					return;
				}
			}
		}
	}
	
	/* Deal with wielding of shield or second weapon when already wielding a two handed weapon */
	if ((slot == INVEN_ARM) && (k_info[inventory[INVEN_WIELD].k_idx].flags3 & (TR3_TWO_HANDED)))	     
	{
		if (cursed_p(&inventory[INVEN_WIELD]))
		{
			msg_print("You would need to put down your weapon, but it appears to be cursed.");
			
			/* Cancel the command */
			return;
		}

		// warn about dropping item in left hand
		if ((item < 0) && (&inventory[INVEN_PACK-1])->tval)
		{
			/* Flush input */
			flush();
			
			if (inventory[INVEN_ARM].tval == TV_SHIELD)
			{
				if (!get_check("This would require removing (and dropping) your weapon. Proceed? "))
				{
					/* Cancel the command */
					return;
				}
			}
			else
			{
				msg_print("This would require removing (and dropping) your weapon.");
				if (!get_check("Proceed? "))
				{
					/* Cancel the command */
					return;
				}
			}
		}
	}
	
	/* Deal with wielding of shield or second weapon when already wielding a hand and a half weapon */
	if ((slot == INVEN_ARM) && (k_info[inventory[INVEN_WIELD].k_idx].flags3 & (TR3_HAND_AND_A_HALF))
	    && (!inventory[INVEN_ARM].k_idx))
	{
		weapon_less_effective = TRUE;
	}
	
	/* Take a turn */
	p_ptr->energy_use = 100;
	
	// store the action type
	p_ptr->previous_action[0] = ACTION_MISC;
	
	/* Get local object */
	i_ptr = &object_type_body;
	
	/* Obtain local object */
	object_copy(i_ptr, o_ptr);
	
	// Handle quantity differently for arrows
	if (i_ptr->tval == TV_ARROW)
	{
		if (combine)	quantity = MIN(o_ptr->number, MAX_STACK_SIZE - 1 - (&inventory[slot])->number);
		else			quantity = o_ptr->number;
	}
	else
	{
		quantity = 1;
	}
	
	/* Modify quantity */
	i_ptr->number = quantity;
	
	/* Decrease the item (from the pack) */
	if (item >= 0)
	{
		inven_item_increase(item, -quantity);
		inven_item_optimize(item);
	}
	
	/* Decrease the item (from the floor) */
	else
	{
		floor_item_increase(0 - item, -quantity);
		floor_item_optimize(0 - item);
	}
	
	/* Get the wield slot */
	o_ptr = &inventory[slot];
	
	/* Take off existing item */
	if (o_ptr->k_idx && !combine)
	{
		/* Take off existing item */
		(void)inven_takeoff(slot, 255);
	}
	
	/* Deal with wielding of two-handed weapons when already using a shield */
	if ((k_info[i_ptr->k_idx].flags3 & (TR3_TWO_HANDED)) && (inventory[INVEN_ARM].k_idx))
	{
		/* Take off shield */
		check_pack_overflow();
		(void)inven_takeoff(INVEN_ARM, 255);
	}
	
	/* Deal with wielding of shield or second weapon when already wielding a two handed weapon */
	if ((slot == INVEN_ARM) && (k_info[inventory[INVEN_WIELD].k_idx].flags3 & (TR3_TWO_HANDED)))
	{
		/* Stop wielding two handed weapon */
		(void)inven_takeoff(INVEN_WIELD, 255);
	}
	
	/* Combine the new stuff into the equipment */
	if (combine)
	{
		msg_print("You combine them with some that are already in your quiver.");
		object_absorb(o_ptr, i_ptr);
	}
	/* Wear the new stuff */
	else
	{
		object_copy(o_ptr, i_ptr);
	}
	
	/* Increment the equip counter by hand */
	if (!combine) p_ptr->equip_cnt++;
	
	/* Where is the item now */
	if ((slot == INVEN_WIELD) || ((slot == INVEN_ARM) && (o_ptr->tval != TV_SHIELD)))
	{
		act = "You are wielding";
	}
	else if (slot == INVEN_BOW)
	{
		act = "You are shooting with";
	}
	else if (slot == INVEN_LITE)
	{
		act = "Your light source is";
	}
	else if ((slot == INVEN_QUIVER1) || (slot == INVEN_QUIVER2))
	{
		act = "In your quiver you have";
	}
	else
	{
		act = "You are wearing";
	}
	
	/* Describe the result */
	object_desc(o_name, sizeof(o_name), o_ptr, TRUE, 3);
	
	/* Message */
	msg_format("%s %s (%c).", act, o_name, index_to_label(slot));
	
	// Deal with wielding from the floor
	if (item < 0)
	{
		/* Forget monster */
		o_ptr->held_m_idx = 0;
		
		/* Forget location */
		o_ptr->iy = o_ptr->ix = 0;
		
		// Break the truce if picking up an item from the floor
		break_truce(FALSE);

		// Special effects when picking up all the items from the floor
		if (i_ptr->number == original_quantity)
		{
			/* No longer marked */
			o_ptr->marked = FALSE;
		}
	}
	
	/* Cursed! */
	if (cursed_p(o_ptr))
	{
		/* Warn the player */
		msg_print("You have a very bad feeling about this...");
		
		/* Remove special inscription, if any */
		if (o_ptr->discount >= INSCRIP_NULL) o_ptr->discount = 0;
		
		/* Sense the object if allowed */
		if (o_ptr->discount == 0) o_ptr->discount = INSCRIP_CURSED;
		
		/* The object has been "sensed" */
		o_ptr->ident |= (IDENT_SENSE);
	}
	
	if (weapon_less_effective)
	{
		/* Describe it */
		object_desc(o_name, sizeof(o_name), &inventory[INVEN_WIELD], FALSE, 0);
		
		/* Message */
		msg_format("You are no longer able to wield your %s as effectively.",
				   o_name);
	}
	
	ident_on_wield(o_ptr);
	
	// activate all of its new abilities
	for (i = 0; i < o_ptr->abilities; i++)
	{
		if (!p_ptr->have_ability[o_ptr->skilltype[i]][o_ptr->abilitynum[i]])
		{
			p_ptr->have_ability[o_ptr->skilltype[i]][o_ptr->abilitynum[i]] = TRUE;
			p_ptr->active_ability[o_ptr->skilltype[i]][o_ptr->abilitynum[i]] = TRUE;
		}
	}
	
	/* Recalculate bonuses */
	p_ptr->update |= (PU_BONUS);
	
	/* Recalculate mana */
	p_ptr->update |= (PU_MANA);
	
	/* Window stuff */
	p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER_0);
	
	p_ptr->redraw |= (PR_EQUIPPY | PR_RESIST);
}
コード例 #13
0
ファイル: attack.c プロジェクト: simongre/RePosBand
/*
 * Throw an object from the pack or floor.
 *
 * Note: "unseen" monsters are very hard to hit.
 *
 * Should throwing a weapon do full damage?  Should it allow the magic
 * to hit bonus of the weapon to have an effect?  Should it ever cause
 * the item to be destroyed?  Should it do any damage at all?
 */
void do_cmd_throw(cmd_code code, cmd_arg args[])
{
	int dir, item;
	int i, j, y, x;
	s16b ty, tx;
	int chance, tdam, tdis;
	int weight;

	object_type *o_ptr;

	object_type *i_ptr;
	object_type object_type_body;

	bool hit_body = FALSE;

	byte missile_attr;
	char missile_char;

	char o_name[80];

	u32b msg_type = 0;

	int path_n;
	u16b path_g[256];

	int msec = op_ptr->delay_factor * op_ptr->delay_factor;

	/* Get item to throw and direction in which to throw it. */
	item = args[0].item;
	dir = args[1].direction;

	/* Make sure the player isn't throwing wielded items */
	if (item >= INVEN_WIELD && item < QUIVER_START)
	{
		msg_print("You have cannot throw wielded items.");
		return;
	}

	/* Check the item being thrown is usable by the player. */
	if (!item_is_available(item, NULL, (USE_EQUIP | USE_INVEN | USE_FLOOR)))
	{
		msg_format("That item is not within your reach.");
		return;
	}

	/* Get the object */
	o_ptr = object_from_item_idx(item);
	object_notice_on_firing(o_ptr);

	/* Get local object */
	i_ptr = &object_type_body;

	/* Obtain a local object */
	object_copy(i_ptr, o_ptr);

	/* Distribute the charges of rods/wands/staves between the stacks */
	distribute_charges(o_ptr, i_ptr, 1);

	/* Single object */
	i_ptr->number = 1;

	/* Reduce and describe inventory */
	if (item >= 0)
	{
		inven_item_increase(item, -1);
		inven_item_describe(item);
		inven_item_optimize(item);
	}

	/* Reduce and describe floor item */
	else
	{
		floor_item_increase(0 - item, -1);
		floor_item_optimize(0 - item);
	}


	/* Description */
	object_desc(o_name, sizeof(o_name), i_ptr, ODESC_FULL);

	/* Find the color and symbol for the object for throwing */
	missile_attr = object_attr(i_ptr);
	missile_char = object_char(i_ptr);


	/* Enforce a minimum "weight" of one pound */
	weight = ((i_ptr->weight > 10) ? i_ptr->weight : 10);

	/* Hack -- Distance -- Reward strength, penalize weight */
	tdis = (adj_str_blow[p_ptr->state.stat_ind[A_STR]] + 20) * 10 / weight;

	/* Max distance of 10 */
	if (tdis > 10) tdis = 10;

	/* Hack -- Base damage from thrown object */
	tdam = damroll(i_ptr->dd, i_ptr->ds);
	if (!tdam) tdam = 1;
	tdam += i_ptr->to_d;

	/* Chance of hitting */
	chance = (p_ptr->state.skills[SKILL_TO_HIT_THROW] + (p_ptr->state.to_h * BTH_PLUS_ADJ));


	/* Take a turn */
	p_ptr->energy_use = 100;


	/* Start at the player */
	y = p_ptr->py;
	x = p_ptr->px;

	/* Predict the "target" location */
	ty = p_ptr->py + 99 * ddy[dir];
	tx = p_ptr->px + 99 * ddx[dir];

	/* Check for "target request" */
	if ((dir == 5) && target_okay())
	{
		target_get(&tx, &ty);
	}

	/* Calculate the path */
	path_n = project_path(path_g, tdis, p_ptr->py, p_ptr->px, ty, tx, 0);


	/* Hack -- Handle stuff */
	handle_stuff();

	/* Project along the path */
	for (i = 0; i < path_n; ++i)
	{
		int ny = GRID_Y(path_g[i]);
		int nx = GRID_X(path_g[i]);

		/* Hack -- Stop before hitting walls */
		if (!cave_floor_bold(ny, nx)) break;

		/* Advance */
		x = nx;
		y = ny;

		/* Only do visuals if the player can "see" the missile */
		if (player_can_see_bold(y, x))
		{
			/* Visual effects */
			print_rel(missile_char, missile_attr, y, x);
			move_cursor_relative(y, x);

			Term_fresh();
			if (p_ptr->redraw) redraw_stuff();

			Term_xtra(TERM_XTRA_DELAY, msec);
			light_spot(y, x);

			Term_fresh();
			if (p_ptr->redraw) redraw_stuff();
		}

		/* Delay anyway for consistency */
		else
		{
			/* Pause anyway, for consistancy */
			Term_xtra(TERM_XTRA_DELAY, msec);
		}

		/* Handle monster */
		if (cave_m_idx[y][x] > 0)
		{
			monster_type *m_ptr = &mon_list[cave_m_idx[y][x]];
			monster_race *r_ptr = &r_info[m_ptr->r_idx];

			int chance2 = chance - distance(p_ptr->py, p_ptr->px, y, x);

			int visible = m_ptr->ml;

			/* Note the collision */
			hit_body = TRUE;

			/* Did we hit it (penalize range) */
			if (test_hit(chance2, r_ptr->ac, m_ptr->ml))
			{
				const char *hit_verb = "hits";
				bool fear = FALSE;
				const slay_t *best_s_ptr = NULL;

				/* Assume a default death */
				cptr note_dies = " dies.";

				/* Some monsters get "destroyed" */
				if (monster_is_unusual(r_ptr))
				{
					/* Special note at death */
					note_dies = " is destroyed.";
				}

				/* Apply special damage  - brought forward to fill in hit_verb XXX XXX XXX */
				improve_attack_modifier(i_ptr, m_ptr, &best_s_ptr);
				if (best_s_ptr != NULL)
				{
					tdam *= best_s_ptr->mult;
					hit_verb = best_s_ptr->range_verb;
				}
				/* Apply special damage XXX XXX XXX */
				tdam = critical_shot(i_ptr->weight, i_ptr->to_h, tdam, &msg_type);

				/* No negative damage; change verb if no damage done */
				if (tdam <= 0)
				{
					tdam = 0;
					hit_verb = "fail to harm";
				}

				/* Handle unseen monster */
				if (!visible)
				{
					/* Invisible monster */
					msg_format("The %s finds a mark.", o_name);
				}

				/* Handle visible monster */
				else
				{
					char m_name[80];

					/* Get "the monster" or "it" */
					monster_desc(m_name, sizeof(m_name), m_ptr, 0);

					/* Tell the player what happened */
					if (msg_type == MSG_SHOOT_HIT)
						message_format(MSG_SHOOT_HIT, 0, "The %s %s %s.", o_name, hit_verb, m_name);
					else
					{
						if (msg_type == MSG_HIT_GOOD)
						{
							message_format(MSG_HIT_GOOD, 0, "The %s %s %s. %s", o_name, hit_verb, m_name,
										   "It was a good hit!");
						}
						else if (msg_type == MSG_HIT_GREAT)
						{
							message_format(MSG_HIT_GREAT, 0, "The %s %s %s. %s", o_name, hit_verb, m_name,
										   "It was a great hit!");
						}
						else if (msg_type == MSG_HIT_SUPERB)
						{
							message_format(MSG_HIT_SUPERB, 0, "The %s %s %s. %s", o_name, hit_verb, m_name,
										   "It was a superb hit!");
						}
					}
					/* Hack -- Track this monster race */
					if (m_ptr->ml) monster_race_track(m_ptr->r_idx);

					/* Hack -- Track this monster */
					if (m_ptr->ml) health_track(cave_m_idx[y][x]);
				}

				/* Learn the bonuses */
				/* XXX Eddie This is messed up, better done for firing, */
				/* should use that method [split last] instead */
				/* check if inven_optimize removed what o_ptr referenced */
				if (object_similar(i_ptr, o_ptr, OSTACK_PACK))
					object_notice_attack_plusses(o_ptr);
				object_notice_attack_plusses(i_ptr);

				/* Complex message */
				if (p_ptr->wizard)
					msg_format("You do %d (out of %d) damage.",
							   tdam, m_ptr->hp);

				/* Hit the monster, check for death */
				if (mon_take_hit(cave_m_idx[y][x], tdam, &fear, note_dies))
				{
					/* Dead monster */
				}

				/* No death */
				else
				{
					/* Message */
					message_pain(cave_m_idx[y][x], tdam);

					/* Take note */
					if (fear && m_ptr->ml)
					{
						char m_name[80];

						/* Get the monster name (or "it") */
						monster_desc(m_name, sizeof(m_name), m_ptr, 0);

						/* Message */
						message_format(MSG_FLEE, m_ptr->r_idx,
						               "%^s flees in terror!", m_name);
					}
				}
			}

			/* Stop looking */
			break;
		}
	}

	/* Chance of breakage (during attacks) */
	j = (hit_body ? breakage_chance(i_ptr) : 0);

	/* Drop (or break) near that location */
	drop_near(i_ptr, j, y, x, TRUE);
}
コード例 #14
0
ファイル: object2.c プロジェクト: jcubic/ToME
/*
 * Let an object fall to the ground at or near a location.
 *
 * The initial location is assumed to be "in_bounds()".
 *
 * This function takes a parameter "chance".  This is the percentage
 * chance that the item will "disappear" instead of drop.  If the object
 * has been thrown, then this is the chance of disappearance on contact.
 *
 * Hack -- this function uses "chance" to determine if it should produce
 * some form of "description" of the drop event (under the player).
 *
 * We check several locations to see if we can find a location at which
 * the object can combine, stack, or be placed.  Artifacts will try very
 * hard to be placed, including "teleporting" to a useful grid if needed.
 */
s16b drop_near(object_type *j_ptr, s32b chance, s32b y, s32b x)
{
	s32b i, k, d, s;

	s32b bs, bn;
	s32b by, bx;
	s32b dy, dx;
	s32b ty, tx;

	s16b o_idx = 0;

	cave_type *c_ptr;

	char o_name[80];

	bool flag = FALSE;

	bool plural = FALSE;


	/* Extract plural */
	if (j_ptr->number != 1) plural = TRUE;

	/* Describe object */
	object_desc(o_name, j_ptr, FALSE, 0);


	/* Handle normal "breakage" */
	if (!(j_ptr->art_name || artifact_p(j_ptr)) && (rand_int(100) < chance))
	{
		/* Message */
		msg_format("The %s disappear%s.",
		           o_name, (plural ? "" : "s"));

		/* Debug */
		if (wizard) msg_print("(breakage)");

		delete_object(j_ptr);

		/* Failure */
		return (0);
	}


	/* Score */
	bs = -1;

	/* Picker */
	bn = 0;

	/* Default */
	by = y;
	bx = x;

	/* Scan local grids */
	for (dy = -3; dy <= 3; dy++)
	{
		/* Scan local grids */
		for (dx = -3; dx <= 3; dx++)
		{
			bool comb = FALSE;

			/* Calculate actual distance */
			d = (dy * dy) + (dx * dx);

			/* Ignore distant grids */
			if (d > 10) continue;

			/* Location */
			ty = y + dy;
			tx = x + dx;

			/* Skip illegal grids */
			if (!in_bounds(ty, tx)) continue;

			/* Require line of sight */
			if (!los(y, x, ty, tx)) continue;

			/* Obtain grid */
			c_ptr = &cave[ty][tx];

			/* Require floor space (or shallow terrain) -KMW- */
			if (!has_flag(&f_info[c_ptr->feat], FLAG_FLOOR)) continue;

			/* No traps */
			if (flag_used(&c_ptr->activations)) continue;

			/* No objects */
			k = 0;

			/* Scan objects in that grid */
			for_inventory_slot(&c_ptr->inventory, o_ptr);
			{
				/* Check for possible combination */
				if (object_similar(o_ptr, j_ptr)) comb = TRUE;

				/* Count objects */
				k++;
			}
			end_inventory_slot();

			/* Add new object */
			if (!comb) k++;

			/* Paranoia */
			if (k >= inventory_limit_inven(&c_ptr->inventory)) continue;

			/* Calculate score */
			s = 1000 - (d + k * 5);

			/* Skip bad values */
			if (s < bs) continue;

			/* New best value */
			if (s > bs) bn = 0;

			/* Apply the randomizer to equivalent values */
			if ((++bn >= 2) && (rand_int(bn) != 0)) continue;

			/* Keep score */
			bs = s;

			/* Track it */
			by = ty;
			bx = tx;

			/* Okay */
			flag = TRUE;
		}
	}


	/* Handle lack of space */
	if (!flag && !(artifact_p(j_ptr) || j_ptr->art_name))
	{
		/* Message */
		msg_format("The %s disappear%s.",
		           o_name, (plural ? "" : "s"));

		/* Debug */
		if (wizard) msg_print("(no floor space)");

		delete_object(j_ptr);

		/* Failure */
		return (0);
	}


	/* Find a grid */
	for (i = 0; !flag; i++)
	{
		/* Bounce around */
		if (i < 1000)
		{
			ty = rand_spread(by, 1);
			tx = rand_spread(bx, 1);
		}

		/* Random locations */
		else
		{
			ty = rand_int(cur_hgt);
			tx = rand_int(cur_wid);
		}

		/* Grid */
		c_ptr = &cave[ty][tx];

		/* Require floor space */
		if (!has_flag(&f_info[c_ptr->feat], FLAG_FLOOR) || has_flag(&f_info[c_ptr->feat], FLAG_NO_WALK)) continue;

		/* Bounce to that location */
		by = ty;
		bx = tx;

		/* Require floor space */
		if (!cave_clean_bold(by, bx)) continue;

		/* Okay */
		flag = TRUE;
	}

	j_ptr->iy         = by;
	j_ptr->ix         = bx;
	j_ptr->held_m_idx = 0;

	/* Grid */
	c_ptr = &cave[by][bx];

	/* Carry */
	o_idx = inven_carry_inven(&c_ptr->inventory, j_ptr, FALSE);

	/*
	 * j_ptr might have been merged into an existing object and then
	 * deleted, so re-get the object.
	 */
	j_ptr = get_object(item_slot_to_item(o_idx));

	/* Note the spot */
	note_spot(by, bx);

	/* Draw the spot */
	lite_spot(by, bx);

	/* Mega-Hack -- no message if "dropped" by player */
	/* Message when an object falls under the player */
	if (chance && (by == p_ptr->py) && (bx == p_ptr->px))
	{
		msg_print("You feel something roll beneath your feet.");
		/* Sound */
		sound(SOUND_DROP);
	}

	process_hooks(HOOK_DROPPED_NEAR, "(O,b,d,d,d,d)", j_ptr, chance,
				  y, x, by, bx);

	/* XXX XXX XXX */

	/* Result */
	return (o_idx);
}
コード例 #15
0
ファイル: obj-gear.c プロジェクト: fe051/angband
/**
 * 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);
}
コード例 #16
0
ファイル: cmd1.c プロジェクト: artes-liberales/FAangband
/**
 * Carry an object and delete it.
 */
extern void py_pickup_aux(int o_idx, bool msg)
{
    int slot, quiver_slot = 0;

    char o_name[120];
    object_type *o_ptr = &o_list[o_idx];
    object_type *i_ptr = &p_ptr->inventory[INVEN_LIGHT];
    bitflag f[OF_SIZE], obvious_mask[OF_SIZE];


    flags_init(obvious_mask, OF_SIZE, OF_OBVIOUS_MASK, FLAG_END);
    of_copy(f, o_ptr->flags_obj);
    
    /* Carry the object */
    slot = inven_carry(p_ptr, o_ptr);

    /* Handle errors (paranoia) */
    if (slot < 0) return;

    /* If we have picked up ammo which matches something in the quiver, note
     * that it so that we can wield it later (and suppress pick up message) */
    if (obj_is_quiver_obj(o_ptr)) 
    {
	int i;
	for (i = QUIVER_START; i < QUIVER_END; i++) 
	{
	    if (!p_ptr->inventory[i].k_idx) continue;
	    if (!object_similar(&p_ptr->inventory[i], o_ptr,
				OSTACK_QUIVER)) continue;
	    quiver_slot = i;
	    break;
	}
    }

    /* Get the object again */
    o_ptr = &p_ptr->inventory[slot];

    /* Set squelch status */
    p_ptr->notice |= PN_SQUELCH;

    /* Stone of Lore gives id on pickup */
    if (!object_known_p(o_ptr)) {
	if (i_ptr->sval == SV_STONE_LORE)
	    identify_object(o_ptr);

	/* Otherwise pseudo-ID */
	else {
	    bool heavy = FALSE;
	    int feel;

	    /* Heavy sensing */
	    heavy = (player_has(PF_PSEUDO_ID_HEAVY));

	    /* Type of feeling */
	    feel = (heavy ? value_check_aux1(o_ptr) : value_check_aux2(o_ptr));

	    /* We have "felt" it */
	    o_ptr->ident |= (IDENT_SENSE);

	    /* Inscribe it textually */
	    o_ptr->feel = feel;

	    /* Set squelch flag as appropriate */
	    p_ptr->notice |= PN_SQUELCH;
	}
    }

    /* Log artifacts if found */
    if (artifact_p(o_ptr))
	history_add_artifact(o_ptr->name1, object_is_known(o_ptr), TRUE);

    /* Notice dice and other obvious stuff */
    notice_other(IF_DD_DS, slot + 1);
    (void) of_inter(f, obvious_mask);
    of_union(o_ptr->id_obj, f);

    /* Average things are average */
    if ((o_ptr->feel == FEEL_AVERAGE) && (is_weapon(o_ptr) || is_armour(o_ptr))){
	notice_other(IF_AC, slot + 1);
	notice_other(IF_TO_A, slot + 1);
	notice_other(IF_TO_H, slot + 1);
	notice_other(IF_TO_D, slot + 1);
    }

    /* Recalculate the bonuses */
    p_ptr->update |= (PU_BONUS);

    /* Optionally, display a message */
    if (msg && !quiver_slot)
    {
	/* Describe the object */
	object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL);

	/* Message */
	msg_format("You have %s (%c).", o_name, index_to_label(slot));
    }


    /* Delete the object */
    delete_object_idx(o_idx);

    /* If we have a quiver slot that this item matches, use it */
    if (quiver_slot) wield_item(o_ptr, slot, quiver_slot);
}
コード例 #17
0
ファイル: obj-gear.c プロジェクト: NickMcConnell/angband
/**
 * 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);
}