Exemple #1
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);
}
Exemple #2
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);
}
Exemple #3
0
/**
 * Applying magic to an object, which includes creating ego-items, and applying
 * random bonuses,
 *
 * The `good` argument forces the item to be at least `good`, and the `great`
 * argument does likewise.  Setting `allow_artifacts` to true allows artifacts
 * to be created here.
 *
 * If `good` or `great` are not set, then the `lev` argument controls the
 * quality of item.
 *
 * Returns 0 if a normal object, 1 if a good object, 2 if an ego item, 3 if an
 * artifact.
 */
int apply_magic(struct object *obj, int lev, bool allow_artifacts, bool good,
				bool great, bool extra_roll)
{
	int i;
	s16b power = 0;

	/* Chance of being `good` and `great` */
	/* This has changed over the years:
	 * 3.0.0:   good = MIN(75, lev + 10);      great = MIN(20, lev / 2); 
	 * 3.3.0:	good = (lev + 2) * 3;          great = MIN(lev / 4 + lev, 50);
     * 3.4.0:   good = (2 * lev) + 5
     * 3.4 was in between 3.0 and 3.3, 3.5 attempts to keep the same
     * area under the curve as 3.4, but make the generation chances
     * flatter.  This depresses good items overall since more items
     * are created deeper. 
     * This change is meant to go in conjunction with the changes
     * to ego item allocation levels. (-fizzix)
	 */
	int good_chance = (33 + lev);
	int great_chance = 30;

	/* Roll for "good" */
	if (good || (randint0(100) < good_chance)) {
		power = 1;

		/* Roll for "great" */
		if (great || (randint0(100) < great_chance))
			power = 2;
	}

	/* Roll for artifact creation */
	if (allow_artifacts) {
		int rolls = 0;

		/* Get one roll if excellent */
		if (power >= 2) rolls = 1;

		/* Get two rolls if forced great */
		if (great) rolls = 2;
        
        /* Give some extra rolls for uniques and acq scrolls */
        if (extra_roll) rolls += 2;

		/* Roll for artifacts if allowed */
		for (i = 0; i < rolls; i++)
			if (make_artifact(obj)) return 3;
	}

	/* Try to make an ego item */
	if (power == 2)
		make_ego_item(obj, lev);

	/* Apply magic */
	if (tval_is_weapon(obj)) {
		apply_magic_weapon(obj, lev, power);
	} else if (tval_is_armor(obj)) {
		apply_magic_armour(obj, lev, power);
	} else if (tval_is_ring(obj)) {
		if (obj->sval == lookup_sval(obj->tval, "Speed")) {
			/* Super-charge the ring */
			while (one_in_(2))
				obj->modifiers[OBJ_MOD_SPEED]++;
		}
	} else if (tval_is_chest(obj)) {
		/* Hack -- skip ruined chests */
		if (obj->kind->level > 0) {
			/* Hack -- pick a "difficulty" */
			obj->pval = randint1(obj->kind->level);

			/* Never exceed "difficulty" of 55 to 59 */
			if (obj->pval > 55)
				obj->pval = (s16b)(55 + randint0(5));
		}
	}

	/* Apply minima from ego items if necessary */
	ego_apply_minima(obj);

	return power;
}
Exemple #4
0
/**
 * Determine if an item can "absorb" a second item
 *
 * See "object_absorb()" for the actual "absorption" code.
 *
 * If permitted, we allow weapons/armor to stack, if "known".
 *
 * Missiles will combine if both stacks have the same "known" status.
 * This is done to make unidentified stacks of missiles useful.
 *
 * Food, potions, scrolls, and "easy know" items always stack.
 *
 * Chests, and activatable items, except rods, never stack (for various
 * reasons).
 */
bool object_stackable(const struct object *obj1, const struct object *obj2,
					  object_stack_t mode)
{
	int i;

	/* Equipment items don't stack */
	if (object_is_equipped(player->body, obj1))
		return false;
	if (object_is_equipped(player->body, obj2))
		return false;

	/* If either item is unknown, do not stack */
	if (mode & OSTACK_LIST && obj1->kind != obj1->known->kind) return false;
	if (mode & OSTACK_LIST && obj2->kind != obj2->known->kind) return false;

	/* Hack -- identical items cannot be stacked */
	if (obj1 == obj2) return false;

	/* Require identical object kinds */
	if (obj1->kind != obj2->kind) return false;

	/* Different flags don't stack */
	if (!of_is_equal(obj1->flags, obj2->flags)) return false;

	/* Different elements don't stack */
	for (i = 0; i < ELEM_MAX; i++) {
		if (obj1->el_info[i].res_level != obj2->el_info[i].res_level)
			return false;
		if ((obj1->el_info[i].flags & (EL_INFO_HATES | EL_INFO_IGNORE)) !=
			(obj2->el_info[i].flags & (EL_INFO_HATES | EL_INFO_IGNORE)))
			return false;
	}

	/* Artifacts never stack */
	if (obj1->artifact || obj2->artifact) return false;

	/* Analyze the items */
	if (tval_is_chest(obj1)) {
		/* Chests never stack */
		return false;
	}
	else if (tval_is_edible(obj1) || tval_is_potion(obj1) ||
		tval_is_scroll(obj1) || tval_is_rod(obj1)) {
		/* Food, potions, scrolls and rods all stack nicely,
		   since the kinds are identical, either both will be
		   aware or both will be unaware */
	} else if (tval_can_have_charges(obj1) || tval_is_money(obj1)) {
		/* Gold, staves and wands stack most of the time */
		/* Too much gold or too many charges */
		if (obj1->pval + obj2->pval > MAX_PVAL)
			return false;

		/* ... otherwise ok */
	} else if (tval_is_weapon(obj1) || tval_is_armor(obj1) ||
		tval_is_jewelry(obj1) || tval_is_light(obj1)) {
		bool obj1_is_known = object_fully_known((struct object *)obj1);
		bool obj2_is_known = object_fully_known((struct object *)obj2);

		/* Require identical values */
		if (obj1->ac != obj2->ac) return false;
		if (obj1->dd != obj2->dd) return false;
		if (obj1->ds != obj2->ds) return false;

		/* Require identical bonuses */
		if (obj1->to_h != obj2->to_h) return false;
		if (obj1->to_d != obj2->to_d) return false;
		if (obj1->to_a != obj2->to_a) return false;

		/* Require all identical modifiers */
		for (i = 0; i < OBJ_MOD_MAX; i++)
			if (obj1->modifiers[i] != obj2->modifiers[i])
				return (false);

		/* Require identical ego-item types */
		if (obj1->ego != obj2->ego) return false;

		/* Require identical curses */
		if (!curses_are_equal(obj1->curses, obj2->curses)) return false;

		/* Hack - Never stack recharging wearables ... */
		if ((obj1->timeout || obj2->timeout) &&
			!tval_is_light(obj1)) return false;

		/* ... and lights must have same amount of fuel */
		else if ((obj1->timeout != obj2->timeout) &&
				 tval_is_light(obj1)) return false;

		/* Prevent unIDd items stacking with IDd items in the object list */
		if (mode & OSTACK_LIST && (obj1_is_known != obj2_is_known))
			return false;
	} else {
		/* Anything else probably okay */
	}

	/* Require compatible inscriptions */
	if (obj1->note && obj2->note && (obj1->note != obj2->note))
		return false;

	/* They must be similar enough */
	return true;
}
/**
 * Is obj armor?
 */
static bool obj_desc_show_armor(const struct object *obj)
{
	if (obj->ac || tval_is_armor(obj)) return TRUE;

	return FALSE;
}