Ejemplo n.º 1
0
/**
 * Check how many missiles can be put in the quiver without increasing the
 * number of pack slots used.
 *
 * Returns the quantity from a given stack of missiles that can be added.
 */
static int quiver_absorb_num(const struct object *obj)
{
	int i, quiver_count = 0, space_free = 0;

	/* Must be ammo */
	if (!tval_is_ammo(obj)) return 0;

	/* Count the current space this object could go into */
	for (i = 0; i < z_info->quiver_size; i++) {
		struct object *quiver_obj = player->upkeep->quiver[i];
		if (quiver_obj) {
			quiver_count += quiver_obj->number;
			if (object_stackable(quiver_obj, obj, OSTACK_PACK))
				space_free += z_info->stack_size - quiver_obj->number;
		} else {
			space_free += z_info->stack_size;
		}
	}

	/* No space */
	if (!space_free) return 0;

	/* Check we won't need another pack slot */
	quiver_count += z_info->stack_size;
	while (quiver_count > z_info->stack_size)
		quiver_count -= z_info->stack_size;

	/* Return the number, or the number that will fit */
	space_free = MIN(space_free, z_info->stack_size - quiver_count);
	return MIN(obj->number, space_free);
}
Ejemplo n.º 2
0
/**
 * Calculate the number of pack slots used by the current gear.
 *
 * Note that this function does not check that there are adequate slots in the
 * quiver, just the total quantity of missiles.
 */
int pack_slots_used(struct player *p)
{
	struct object *obj;
	int quiver_slots = 0, pack_slots = 0, quiver_ammo = 0;
	int maxsize = z_info->stack_size;

	for (obj = p->gear; obj; obj = obj->next) {
		/* Equipment doesn't count */
		if (object_is_equipped(p->body, obj)) continue;

		/* Check if it could be in the quiver */
		if (tval_is_ammo(obj))
			if (quiver_slots < z_info->quiver_size) {
				quiver_slots++;
				quiver_ammo += obj->number;
				continue;
			}

		/* Count regular slots */
		pack_slots++;
	}

	/* Full slots */
	pack_slots += quiver_ammo / maxsize;

	/* Plus one for any remainder */
	if (quiver_ammo % maxsize) pack_slots++;

	return pack_slots;
}
Ejemplo n.º 3
0
/**
 * Check if we have space to put an item in a new quiver slot without 
 * increasing the number of pack slots used 
 */
static bool new_quiver_slot_okay(const object_type *obj)
{
	int i, quiver_count = 0;
	bool empty_slot = FALSE;

	/* Must be ammo */
	if (!tval_is_ammo(obj)) return FALSE;

	/* Count the current space */
	for (i = 0; i < z_info->quiver_size; i++) {
		struct object *quiver_obj = player->upkeep->quiver[i];
		if (quiver_obj)
			quiver_count += quiver_obj->number;
		else
			empty_slot = TRUE;
	}

	/* Check for free quiver slots */
	if (!empty_slot) return FALSE;

	/* Check we won't need another pack slot */
	quiver_count = ((quiver_count - 1) % z_info->stack_size) + 1;
	if (quiver_count + obj->number > z_info->stack_size) return FALSE;

	/* Good to go */
	return TRUE;
}
Ejemplo n.º 4
0
/**
 * Calculate the number of pack slots used by the current gear.
 *
 * Note that this function does not check that there are adequate slots in the
 * quiver, just the total quantity of missiles.
 */
int pack_slots_used(struct player *p)
{
	struct object *obj;
	int quiver_slots = 0;
	int pack_slots = 0;
	int quiver_ammo = 0;

	for (obj = p->gear; obj; obj = obj->next) {
		/* Equipment doesn't count */
		if (!object_is_equipped(p->body, obj)) {
			/* Check if it could be in the quiver */
			if (tval_is_ammo(obj) && quiver_slots < z_info->quiver_size) {
				quiver_slots++;
				quiver_ammo += obj->number;
			} else {
				/* Count regular slots */
				pack_slots++;
			}
		}
	}

	/* Full slots */
	pack_slots += quiver_ammo / z_info->quiver_slot_size;

	/* Plus one for any remainder */
	if (quiver_ammo % z_info->quiver_slot_size) {
		pack_slots++;
	}

	return pack_slots;
}
Ejemplo n.º 5
0
/**
 * Describe the kind
 */
static void kind_info(char *buf, size_t buf_len, char *dam, size_t dam_len,
					  char *wgt, size_t wgt_len, int *lev, s32b *val, int k)
{
	struct object_kind *kind = &k_info[k];
	struct object *obj = object_new(), *known_obj = object_new();
	int i;

	/* Prepare a fake item */
	object_prep(obj, kind, 0, MAXIMISE);

	/* Cancel bonuses */
	for (i = 0; i < OBJ_MOD_MAX; i++)
		obj->modifiers[i] = 0;
	obj->to_a = 0;
	obj->to_h = 0;
	obj->to_d = 0;

	/* Level */
	(*lev) = kind->level;

	/* Make known */
	object_copy(known_obj, obj);
	obj->known = known_obj;

	/* Value */
	(*val) = object_value(obj, 1, false);

	/* Description (too brief) */
	if (buf)
		object_desc(buf, buf_len, obj, ODESC_BASE | ODESC_SPOIL);

	/* Weight */
	if (wgt)
		strnfmt(wgt, wgt_len, "%3d.%d", obj->weight / 10, obj->weight % 10);

	/* Hack */
	if (!dam)
		return;

	/* Misc info */
	dam[0] = '\0';

	/* Damage */
	if (tval_is_ammo(obj) || tval_is_melee_weapon(obj))
		strnfmt(dam, dam_len, "%dd%d", obj->dd, obj->ds);
	else if (tval_is_armor(obj))
		strnfmt(dam, dam_len, "%d", obj->ac);

	object_delete(&known_obj);
	object_delete(&obj);
}
Ejemplo n.º 6
0
/**
 * Add launcher bonus for ego ammo, multiply for launcher and rescale
 */
static int launcher_ammo_damage_power(const object_type *obj, int p)
{
	int ammo_type = 0;

	if (tval_is_ammo(obj)) {
		if (obj->tval == TV_ARROW) ammo_type = 1;
		if (obj->tval == TV_BOLT) ammo_type = 2;
		if (obj->ego)
			p += (archery[ammo_type].launch_dam * DAMAGE_POWER / 2);
		p = p * archery[ammo_type].launch_mult / (2 * MAX_BLOWS);
		log_obj(format("After multiplying ammo and rescaling, power is %d\n",
					   p));
	}
	return p;
}
Ejemplo n.º 7
0
/**
 * To damage power
 */
static int to_damage_power(const object_type *obj)
{
	int p;

	p = (obj->to_d * DAMAGE_POWER / 2);
	if (p) log_obj(format("%d power from to_dam\n", p));

	/* Add second lot of damage power for non-weapons */
	if ((wield_slot(obj) != slot_by_name(player, "shooting")) &&
		!tval_is_melee_weapon(obj) &&
		!tval_is_ammo(obj)) {
		int q = (obj->to_d * DAMAGE_POWER);
		p += q;
		if (q)
			log_obj(format("Add %d from non-weapon to_dam, total %d\n", q, p));
	}
	return p;
}
Ejemplo n.º 8
0
/**
 * Damage dice power or equivalent
 */
static int damage_dice_power(const object_type *obj)
{
	int dice = 0;

	/* Add damage from dice for any wieldable weapon or ammo */
	if (tval_is_melee_weapon(obj) || tval_is_ammo(obj)) {
		dice = (obj->dd * (obj->ds + 1) * DAMAGE_POWER / 4);
		log_obj(format("Add %d power for damage dice, ", dice));
	} else if (wield_slot(obj) != slot_by_name(player, "shooting")) {
		/* Add power boost for nonweapons with combat flags */
		if (obj->brands || obj->slays ||
			(obj->modifiers[OBJ_MOD_BLOWS] > 0) ||
			(obj->modifiers[OBJ_MOD_SHOTS] > 0) ||
			(obj->modifiers[OBJ_MOD_MIGHT] > 0)) {
			dice = (WEAP_DAMAGE * DAMAGE_POWER);
			log_obj(format("Add %d power for non-weapon combat bonuses, ",
						   dice));
		}
	}
	return dice;
}
Ejemplo n.º 9
0
/**
 * Apply magic to a weapon.
 */
static void apply_magic_weapon(struct object *obj, int level, int power)
{
	if (power <= 0)
		return;

	obj->to_h += randint1(5) + m_bonus(5, level);
	obj->to_d += randint1(5) + m_bonus(5, level);

	if (power > 1) {
		obj->to_h += m_bonus(10, level);
		obj->to_d += m_bonus(10, level);

		if (tval_is_melee_weapon(obj) || tval_is_ammo(obj)) {
			/* Super-charge the damage dice */
			while ((obj->dd * obj->ds > 0) &&
					one_in_(10L * obj->dd * obj->ds))
				obj->dd++;

			/* But not too high */
			if (obj->dd > 9) obj->dd = 9;
		}
	}
}
Ejemplo n.º 10
0
/**
 * Destroys a type of item on a given percent chance.
 * The chance 'cperc' is in hundredths of a percent (1-in-10000)
 * Note that missiles are no longer necessarily all destroyed
 *
 * Returns number of items destroyed.
 */
int inven_damage(struct player *p, int type, int cperc)
{
	int j, k, amt;
	struct object *obj = p->gear;
	char o_name[80];
	bool damage;

	/* No chance means no damage */
	if (cperc <= 0)
		return 0;

	/* Count the casualties */
	k = 0;

	/* Scan through the gear */
	while (obj) {
		struct object *next = obj->next;
		if (object_is_equipped(p->body, obj)) {
			obj = next;
			continue;
		}

		/* Hack -- for now, skip artifacts */
		if (obj->artifact) {
			obj = next;
			continue;
		}

		/* Give this item slot a shot at death if it is vulnerable */
		if ((obj->el_info[type].flags & EL_INFO_HATES) &&
			!(obj->el_info[type].flags & EL_INFO_IGNORE)) {
			/* Chance to destroy this item */
			int chance = cperc;

			/* Track if it is damaged instead of destroyed */
			damage = false;

			/* Analyze the type to see if we just damage it
			 * - we also check for rods to reduce chance */
			if (tval_is_weapon(obj) && !tval_is_ammo(obj)) {
				/* Chance to damage it */
				if (randint0(10000) < cperc) {
					/* Damage the item */
					obj->to_h--;
					if (p->obj_k->to_h)
						obj->known->to_h = obj->to_h;
					obj->to_d--;
					if (p->obj_k->to_d)
						obj->known->to_d = obj->to_d;

					/* Damaged! */
					damage = true;
				} else {
					obj = next;
					continue;
				}
			} else if (tval_is_armor(obj)) {
				/* Chance to damage it */
				if (randint0(10000) < cperc) {
					/* Damage the item */
					obj->to_a--;
					if (p->obj_k->to_a)
						obj->known->to_a = obj->to_a;

					/* Damaged! */
					damage = true;
				} else {
					obj = next;
					continue;
				}
			} else if (tval_is_rod(obj)) {
				chance = (chance / 4);
			}


			/* Damage instead of destroy */
			if (damage) {
				p->upkeep->update |= (PU_BONUS);
				p->upkeep->redraw |= (PR_EQUIP);

				/* Casualty count */
				amt = obj->number;
			} else
				/* ... or count the casualties */
				for (amt = j = 0; j < obj->number; ++j)
					if (randint0(10000) < chance) amt++;

			/* Some casualities */
			if (amt) {
				struct object *destroyed;
				bool none_left = false;

				/* Get a description */
				object_desc(o_name, sizeof(o_name), obj, ODESC_BASE);

				/* Message */
				msgt(MSG_DESTROY, "%sour %s (%c) %s %s!",
				           ((obj->number > 1) ?
				            ((amt == obj->number) ? "All of y" :
				             (amt > 1 ? "Some of y" : "One of y")) : "Y"),
				           o_name, gear_to_label(obj),
				           ((amt > 1) ? "were" : "was"),
					   (damage ? "damaged" : "destroyed"));

				/* Damage already done? */
				if (damage)
					continue;

				/* Destroy "amt" items */
				destroyed = gear_object_for_use(obj, amt, false, &none_left);
				if (destroyed->known)
					object_delete(&destroyed->known);
				object_delete(&destroyed);

				/* Count the casualties */
				k += amt;
			}
		}
		obj = next;
	}

	/* Return the casualty count */
	return (k);
}
Ejemplo n.º 11
0
/**
 * Return the real price of a known (or partly known) item.
 *
 * Wand and staffs get cost for each charge.
 *
 * Wearable items (weapons, launchers, jewelry, lights, armour) and ammo
 * are priced according to their power rating. All ammo, and normal (non-ego)
 * torches are scaled down by AMMO_RESCALER to reflect their impermanence.
 */
s32b object_value_real(const object_type *obj, int qty, int verbose,
					   bool known)
{
	s32b value, total_value;

	s32b power;
	int a = 1;
	int b = 5;
	static file_mode pricing_mode = MODE_WRITE;

	/* Wearables and ammo have prices that vary by individual item properties */
	if (tval_has_variable_power(obj))	{
		char buf[1024];
		ang_file *log_file = NULL;

		/* Logging */
		if (verbose) {
			path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "pricing.log");
			log_file = file_open(buf, pricing_mode, FTYPE_TEXT);
			if (!log_file) {
				msg("Error - can't open pricing.log for writing.");
				exit(1);
			}
			pricing_mode = MODE_APPEND;
		}

		file_putf(log_file, "object is %s\n", obj->kind->name);

		/* Calculate power and value */
		power = object_power(obj, verbose, log_file, known);
		value = SGN(power) * ((a * power * power) + (b * power));

		/* Rescale for expendables */
		if ((tval_is_light(obj) && of_has(obj->flags, OF_BURNS_OUT)
			 && !obj->ego) || tval_is_ammo(obj)) {
			value = value / AMMO_RESCALER;
			if (value < 1) value = 1;
		}

		/* More logging */
		file_putf(log_file, "a is %d and b is %d\n", a, b);
		file_putf(log_file, "value is %d\n", value);

		if (verbose) {
			if (!file_close(log_file)) {
				msg("Error - can't close pricing.log file.");
				exit(1);
			}
		}

		/* Get the total value */
		total_value = value * qty;
		if (total_value < 0) total_value = 0;
	} else {

		/* Worthless items */
		if (!obj->kind->cost) return (0L);

		/* Base cost */
		value = obj->kind->cost;

		/* Analyze the item type and quantity */
		if (tval_can_have_charges(obj)) {
			int charges;

			total_value = value * qty;

			/* Calculate number of charges, rounded up */
			charges = obj->pval * qty / obj->number;
			if ((obj->pval * qty) % obj->number != 0)
				charges++;

			/* Pay extra for charges, depending on standard number of charges */
			total_value += value * charges / 20;
		} else
			total_value = value * qty;

		/* No negative value */
		if (total_value < 0) total_value = 0;
	}

	/* Return the value */
	return (total_value);
}