Beispiel #1
0
/**
 * Apply generation magic to an ego-item.
 */
void ego_apply_magic(struct object *obj, int level)
{
    int i, x, resist = 0;
    bitflag newf[OF_SIZE];

    /* Extra powers */
    if (kf_has(obj->ego->kind_flags, KF_RAND_SUSTAIN)) {
        create_mask(newf, false, OFT_SUST, OFT_MAX);
        of_on(obj->flags, get_new_attr(obj->flags, newf));
    }
    else if (kf_has(obj->ego->kind_flags, KF_RAND_POWER)) {
        create_mask(newf, false, OFT_PROT, OFT_MISC, OFT_MAX);
        of_on(obj->flags, get_new_attr(obj->flags, newf));
    }
    else if (kf_has(obj->ego->kind_flags, KF_RAND_HI_RES))
        /* Get a high resist if available, mark it as random */
        if (random_high_resist(obj, &resist)) {
            obj->el_info[resist].res_level = 1;
            obj->el_info[resist].flags |= EL_INFO_RANDOM;
        }

    /* Apply extra obj->ego bonuses */
    obj->to_h += randcalc(obj->ego->to_h, level, RANDOMISE);
    obj->to_d += randcalc(obj->ego->to_d, level, RANDOMISE);
    obj->to_a += randcalc(obj->ego->to_a, level, RANDOMISE);

    /* Apply modifiers */
    for (i = 0; i < OBJ_MOD_MAX; i++) {
        x = randcalc(obj->ego->modifiers[i], level, RANDOMISE);
        obj->modifiers[i] += x;
    }

    /* Apply flags */
    of_union(obj->flags, obj->ego->flags);
    of_diff(obj->flags, obj->ego->flags_off);

    /* Add slays and brands */
    copy_slay(&obj->slays, obj->ego->slays);
    copy_brand(&obj->brands, obj->ego->brands);

    /* Add resists */
    for (i = 0; i < ELEM_MAX; i++) {
        /* Take the larger of ego and base object resist levels */
        obj->el_info[i].res_level =
            MAX(obj->ego->el_info[i].res_level, obj->el_info[i].res_level);

        /* Union of flags so as to know when ignoring is notable */
        obj->el_info[i].flags |= obj->ego->el_info[i].flags;
    }

    /* Add effect (ego effect will trump object effect, when there are any) */
    if (obj->ego->effect) {
        obj->effect = obj->ego->effect;
        obj->time = obj->ego->time;
    }

    return;
}
Beispiel #2
0
/**
 * Prepare an object based on an object kind.
 */
void object_prep(object_type * o_ptr, int k_idx, aspect rand_aspect)
{
    int i;

    object_kind *k_ptr = &k_info[k_idx];

    /* Clear the record */
    (void) WIPE(o_ptr, object_type);

    /* Save the kind  */
    o_ptr->k_idx = k_idx;
    o_ptr->kind = k_ptr;

    /* Efficiency -- tval/sval */
    o_ptr->tval = k_ptr->tval;
    o_ptr->sval = k_ptr->sval;

    /* Default "pval" */
    o_ptr->pval = randcalc(k_ptr->pval, k_ptr->level, rand_aspect);

    /* Default number */
    o_ptr->number = 1;

    /* Default weight */
    o_ptr->weight = k_ptr->weight;

    /* Default magic */
    o_ptr->to_h = randcalc(k_ptr->to_h, k_ptr->level, rand_aspect);
    o_ptr->to_d = randcalc(k_ptr->to_d, k_ptr->level, rand_aspect);
    o_ptr->to_a = randcalc(k_ptr->to_a, k_ptr->level, rand_aspect);

    /* Default power */
    o_ptr->ac = k_ptr->ac;
    o_ptr->dd = k_ptr->dd;
    o_ptr->ds = k_ptr->ds;

    /* Default effect and time */
    o_ptr->effect = k_ptr->effect;
    o_ptr->time = k_ptr->time;

    /* Default flags */
    of_copy(o_ptr->flags_obj, k_ptr->flags_obj);
    cf_copy(o_ptr->flags_curse, k_ptr->flags_curse);

    /* Default resists, bonuses, multiples */
    for (i = 0; i < MAX_P_RES; i++)
	o_ptr->percent_res[i] = k_ptr->percent_res[i];
    for (i = 0; i < A_MAX; i++)
	o_ptr->bonus_stat[i] = k_ptr->bonus_stat[i];
    for (i = 0; i < MAX_P_BONUS; i++)
	o_ptr->bonus_other[i] = k_ptr->bonus_other[i];
    for (i = 0; i < MAX_P_SLAY; i++)
	o_ptr->multiple_slay[i] = k_ptr->multiple_slay[i];
    for (i = 0; i < MAX_P_BRAND; i++)
	o_ptr->multiple_brand[i] = k_ptr->multiple_brand[i];
}
Beispiel #3
0
/**
 * Test whether an object is intrinsically good.
 *
 * Note that this test only applies to the object *kind*, so it is
 * possible to choose a kind which is good, and then later cause
 * the actual object to be cursed.  We do explicitly forbid objects
 * which are known to be boring or which start out somewhat damaged.
 */
static bool kind_is_good(const object_kind *kind)
{
		if (of_has(kind->flags, OF_GOOD) ||
				of_has(kind->base->flags, OF_GOOD)) return TRUE;
		if (randcalc(kind->to_a, 0, MINIMISE) < 0) return FALSE;
		if (randcalc(kind->to_d, 0, MINIMISE) < 0) return FALSE;
		if (kind_is_armour(kind->tval)) return TRUE;
		if (randcalc(kind->to_h, 0, MINIMISE) < 0) return FALSE;
		if (kind_is_weapon(kind->tval) || kind_is_ammo(kind->tval)) return TRUE;
		return FALSE;
}
Beispiel #4
0
/**
 * Wipe an object clean and make it a standard object of the specified kind.
 */
void object_prep(object_type *o_ptr, struct object_kind *k, int lev,
		aspect rand_aspect)
{
	int i, flag, pval;
	bitflag flags[OF_SIZE], f2[OF_SIZE];

	/* Clean slate */
	WIPE(o_ptr, object_type);

	/* Assign the kind and copy across data */
	o_ptr->kind = k;
	o_ptr->tval = k->tval;
	o_ptr->sval = k->sval;
	o_ptr->ac = k->ac;
	o_ptr->dd = k->dd;
	o_ptr->ds = k->ds;
	o_ptr->weight = k->weight;

	/* Default number */
	o_ptr->number = 1;

	/* Apply pvals and then copy flags */
	of_copy(f2, k->flags);
    for (i = 0; i < k->num_pvals; i++) {
        of_copy(flags, k->pval_flags[i]);
        pval = randcalc(k->pval[i], lev, rand_aspect);
        for (flag = of_next(flags, FLAG_START); flag != FLAG_END;
                flag = of_next(flags, flag + 1))
			/* Prevent phantom flags */
			if (pval)
				object_add_pval(o_ptr, pval, flag);
			else
				of_off(f2, flag);
    }
	of_copy(o_ptr->flags, k->base->flags);
	of_union(o_ptr->flags, f2);

	/* Assign charges/food/fuel value (wands/staves/food/oil) */
	o_ptr->extent = randcalc(k->extent, lev, rand_aspect);

	/* Default fuel for lamps */
	if (o_ptr->tval == TV_LIGHT) {
		if (o_ptr->sval == SV_LIGHT_TORCH)
			o_ptr->timeout = DEFAULT_TORCH;
		else if (o_ptr->sval == SV_LIGHT_LANTERN)
			o_ptr->timeout = DEFAULT_LAMP;
	}

	/* Default magic */
	o_ptr->to_h = randcalc(k->to_h, lev, rand_aspect);
	o_ptr->to_d = randcalc(k->to_d, lev, rand_aspect);
	o_ptr->to_a = randcalc(k->to_a, lev, rand_aspect);
}
Beispiel #5
0
/**
 * Adjust damage according to resistance or vulnerability.
 *
 * \param p is the player
 * \param type is the attack type we are checking.
 * \param dam is the unadjusted damage.
 * \param dam_aspect is the calc we want (min, avg, max, random).
 * \param resist is the degree of resistance (-1 = vuln, 3 = immune).
 */
int adjust_dam(struct player *p, int type, int dam, aspect dam_aspect,
			   int resist, bool actual)
{
	int i, denom = 0;

	/* If an actual player exists, get their actual resist */
	if (p && p->race) {
		/* Ice is a special case */
		int res_type = (type == PROJ_ICE) ? PROJ_COLD: type;
		resist = p->state.el_info[res_type].res_level;

		/* Notice element stuff */
		if (actual) {
			equip_learn_element(p, res_type);
		}
	}

	if (resist == 3) /* immune */
		return 0;

	/* Hack - acid damage is halved by armour, holy orb is halved */
	if ((type == PROJ_ACID && p && minus_ac(p)) || type == PROJ_HOLY_ORB)
		dam = (dam + 1) / 2;

	if (resist == -1) /* vulnerable */
		return (dam * 4 / 3);

	/* Variable resists vary the denominator, so we need to invert the logic
	 * of dam_aspect. (m_bonus is unused) */
	switch (dam_aspect) {
		case MINIMISE:
			denom = randcalc(projections[type].denominator, 0, MAXIMISE);
			break;
		case MAXIMISE:
			denom = randcalc(projections[type].denominator, 0, MINIMISE);
			break;
		case AVERAGE:
		case EXTREMIFY:
		case RANDOMISE:
			denom = randcalc(projections[type].denominator, 0, dam_aspect);
			break;
		default:
			assert(0);
	}

	for (i = resist; i > 0; i--)
		if (denom)
			dam = dam * projections[type].numerator / denom;

	return dam;
}
Beispiel #6
0
/**
 * Prepare an object `dst` representing `amt` objects,  based on an existing
 * object `src` representing at least `amt` objects.
 *
 * Takes care of the charge redistribution concerns of stacked items.
 */
void object_copy_amt(struct object *dest, struct object *src, int amt)
{
	int charge_time = randcalc(src->time, 0, AVERAGE), max_time;

	/* Get a copy of the object */
	object_copy(dest, src);

	/* Modify quantity */
	dest->number = amt;
	dest->note = src->note;

	/*
	 * If the item has charges/timeouts, set them to the correct level
	 * too. We split off the same amount as distribute_charges.
	 */
	if (tval_can_have_charges(src))
		dest->pval = src->pval * amt / src->number;

	if (tval_can_have_timeout(src)) {
		max_time = charge_time * amt;

		if (src->timeout > max_time)
			dest->timeout = max_time;
		else
			dest->timeout = src->timeout;
	}
}
Beispiel #7
0
/**
 * Critical blow.  All hits that do 95% of total possible damage,
 * and which also do at least 20 damage, or, sometimes, N damage.
 * This is used only to determine "cuts" and "stuns".
 */
static int monster_critical(random_value dice, int rlev, int dam)
{
	int max = 0;
	int total = randcalc(dice, rlev, MAXIMISE);

	/* Must do at least 95% of perfect */
	if (dam < total * 19 / 20) return (0);

	/* Weak blows rarely work */
	if ((dam < 20) && (randint0(100) >= dam)) return (0);

	/* Perfect damage */
	if (dam == total) max++;

	/* Super-charge */
	if (dam >= 20)
		while (randint0(100) < 2) max++;

	/* Critical damage */
	if (dam > 45) return (6 + max);
	if (dam > 33) return (5 + max);
	if (dam > 25) return (4 + max);
	if (dam > 18) return (3 + max);
	if (dam > 11) return (2 + max);
	return (1 + max);
}
Beispiel #8
0
/**
 * Make a new trap of the given type.  Return true if successful.
 *
 * We choose a player trap at random if the index is not legal. This means that
 * things which are not player traps must be picked by passing a valid index.
 *
 * This should be the only function that places traps in the dungeon
 * except the savefile loading code.
 */
void place_trap(struct chunk *c, int y, int x, int t_idx, int trap_level)
{
	struct trap *new_trap;

    /* We've been called with an illegal index; choose a random trap */
    if ((t_idx <= 0) || (t_idx >= z_info->trap_max)) {
		/* Require the correct terrain */
		if (!square_player_trap_allowed(c, y, x)) return;

		t_idx = pick_trap(c, c->squares[y][x].feat, trap_level);
    }

    /* Failure */
    if (t_idx < 0) return;

	/* Allocate a new trap for this grid (at the front of the list) */
	new_trap = mem_zalloc(sizeof(*new_trap));
	new_trap->next = square_trap(c, y, x);
	c->squares[y][x].trap = new_trap;

	/* Set the details */
	new_trap->t_idx = t_idx;
	new_trap->kind = &trap_info[t_idx];
	new_trap->fy = y;
	new_trap->fx = x;
	new_trap->power = randcalc(new_trap->kind->power, trap_level, RANDOMISE);
	trf_copy(new_trap->flags, trap_info[t_idx].flags);

	/* Toggle on the trap marker */
	sqinfo_on(c->squares[y][x].info, SQUARE_TRAP);

	/* Redraw the grid */
	square_light_spot(c, y, x);
}
Beispiel #9
0
/**
 * Hack -- determine if a template is "good".
 *
 * Note that this test only applies to the object *kind*, so it is
 * possible to choose a kind which is "good", and then later cause
 * the actual object to be cursed.  We do explicitly forbid objects
 * which are known to be boring or which start out somewhat damaged.
 */
bool kind_is_good(const struct object_kind *kind)
{
	/* Some item types are (almost) always good */
	switch (kind->tval)
	{
		/* Armor -- Good unless damaged */
		case TV_HARD_ARMOR:
		case TV_SOFT_ARMOR:
		case TV_DRAG_ARMOR:
		case TV_SHIELD:
		case TV_CLOAK:
		case TV_BOOTS:
		case TV_GLOVES:
		case TV_HELM:
		case TV_CROWN:
		{
			if (randcalc(kind->to_a, 0, MINIMISE) < 0) return (false);
			return true;
		}

		/* Weapons -- Good unless damaged */
		case TV_BOW:
		case TV_SWORD:
		case TV_HAFTED:
		case TV_POLEARM:
		case TV_DIGGING:
		{
			if (randcalc(kind->to_h, 0, MINIMISE) < 0) return (false);
			if (randcalc(kind->to_d, 0, MINIMISE) < 0) return (false);
			return true;
		}

		/* Ammo -- Arrows/Bolts are good */
		case TV_BOLT:
		case TV_ARROW:
		{
			return true;
		}
	}

	/* Anything with the GOOD flag */
	if (kf_has(kind->kind_flags, KF_GOOD))
		return true;

	/* Assume not good */
	return (false);
}
Beispiel #10
0
/**
 * Gives the known effects of using the given item.
 *
 * Fills in:
 *  - the effect
 *  - whether the effect can be aimed
 *  -  the minimum and maximum time in game turns for the item to recharge 
 *     (or zero if it does not recharge)
 *  - the percentage chance of the effect failing when used
 *
 * Return false if the object has no effect.
 */
static bool obj_known_effect(const struct object *obj, struct effect **effect,
								 bool *aimed, int *min_recharge,
								 int *max_recharge, int *failure_chance)
{
	random_value timeout = {0, 0, 0, 0};

	*effect = 0;
	*min_recharge = 0;
	*max_recharge = 0;
	*failure_chance = 0;
	*aimed = false;

	if (object_effect_is_known(obj)) {
		*effect = object_effect(obj);
		timeout = obj->time;
		if (effect_aim(*effect))
			*aimed = true;;
	} else if (object_effect(obj)) {
		/* Don't know much - be vague */
		*effect = NULL;

		if (!obj->artifact && effect_aim(object_effect(obj)))
			*aimed = true;

		return true;
	} else {
		/* No effect - no info */
		return false;
	}

	if (randcalc(timeout, 0, MAXIMISE) > 0)	{
		*min_recharge = randcalc(timeout, 0, MINIMISE);
		*max_recharge = randcalc(timeout, 0, MAXIMISE);
	}

	if (tval_is_edible(obj) || tval_is_potion(obj) || tval_is_scroll(obj)) {
		*failure_chance = 0;
	} else {
		*failure_chance = get_use_device_chance(obj);
	}

	return true;
}
Beispiel #11
0
/**
 * Attempt to make an object
 *
 * \param c is the current dungeon level.
 * \param j_ptr is the object struct to be populated.
 * \param lev is the creation level of the object (not necessarily == depth).
 * \param good is whether the object is to be good
 * \param great is whether the object is to be great
 * \param value is the value to be returned to the calling function
 *
 * Returns the whether or not creation worked.
 */
bool make_object(struct cave *c, object_type *j_ptr, int lev, bool good,
	bool great, s32b *value)
{
	int base, art, div;
	object_kind *kind;

	/* Base level and artifact chance for the object */
	if (great) {
		art = ART_GREAT;
		base = lev + 10 + m_bonus(5, lev);
	} else if (good) {
		art = ART_GOOD;
		base = lev + 5 + m_bonus(5, lev);
	} else {
		art = ART_NORMAL;
		base = lev;
	}

	/* Small hack to bring artifact frequencies at low depths in line with V */
	div = 9 - p_ptr->depth;
	if (div < 1)
		div = 1;

	/* Try to make an artifact */
	if (one_in_(art * div)) {
		if (make_artifact(j_ptr, lev)) {
			if (value)
				*value = object_value_real(j_ptr, 1, FALSE, TRUE);
			return TRUE;
		}
	}

	/* Get the object, prep it and apply magic */
	kind = get_obj_num(base, good || great);
	if (!kind) return FALSE;
	object_prep(j_ptr, kind, base, RANDOMISE);
	apply_magic(j_ptr, base, FALSE, good, great);

	/* Generate multiple items */
	if (kind->gen_mult_prob >= randint1(100))
		j_ptr->number = randcalc(kind->stack_size, lev, RANDOMISE);

	if (j_ptr->number >= MAX_STACK_SIZE)
		j_ptr->number = MAX_STACK_SIZE - 1;

	/* Return value, increased for uncursed out-of-depth objects */
	if (value)
		*value = object_value_real(j_ptr, j_ptr->number, FALSE, TRUE);

	if (!cursed_p(j_ptr->flags) && (kind->alloc_min > c->depth)) {
		if (value) *value = (kind->alloc_min - c->depth) * (*value / 5);
	}

	return TRUE;
}
Beispiel #12
0
/**
 * Apply generation magic to an ego-item.
 */
void ego_apply_magic(object_type *o_ptr, int level)
{
	int i, flag, x;

	bitflag flags[OF_SIZE], newf[OF_SIZE], f2[OF_SIZE];
	object_flags(o_ptr, flags);

	/* Extra powers */
	if (o_ptr->ego->xtra == OBJECT_XTRA_TYPE_SUSTAIN)
		create_mask(newf, FALSE, OFT_SUST, OFT_MAX);
	else if (o_ptr->ego->xtra == OBJECT_XTRA_TYPE_RESIST)
		create_mask(newf, FALSE, OFT_HRES, OFT_MAX);
	else if (o_ptr->ego->xtra == OBJECT_XTRA_TYPE_POWER)
		create_mask(newf, FALSE, OFT_PROT, OFT_MISC, OFT_MAX);

	if (o_ptr->ego->xtra)
		of_on(o_ptr->flags, get_new_attr(flags, newf));

	/* Apply extra o_ptr->ego bonuses */
	o_ptr->to_h += randcalc(o_ptr->ego->to_h, level, RANDOMISE);
	o_ptr->to_d += randcalc(o_ptr->ego->to_d, level, RANDOMISE);
	o_ptr->to_a += randcalc(o_ptr->ego->to_a, level, RANDOMISE);

	/* Apply pvals */
	of_copy(f2, o_ptr->ego->flags);
	for (i = 0; i < o_ptr->ego->num_pvals; i++) {
		of_copy(flags, o_ptr->ego->pval_flags[i]);
		x = randcalc(o_ptr->ego->pval[i], level, RANDOMISE);
		for (flag = of_next(flags, FLAG_START); flag != FLAG_END;
				flag = of_next(flags, flag + 1))
			/* Prevent phantom flags */
			if (x)
				object_add_pval(o_ptr, x, flag);
			else
				of_off(f2, flag);
	}

	/* Apply remaining flags */
	of_union(o_ptr->flags, f2);

	return;
}
Beispiel #13
0
/**
 * Attempt to make an object
 *
 * \param c is the current dungeon level.
 * \param lev is the creation level of the object (not necessarily == depth).
 * \param good is whether the object is to be good
 * \param great is whether the object is to be great
 * \param extra_roll is whether we get an extra roll in apply_magic()
 * \param value is the value to be returned to the calling function
 * \param tval is the desired tval, or 0 if we allow any tval
 *
 * \return a pointer to the newly allocated object, or NULL on failure.
 */
struct object *make_object(struct chunk *c, int lev, bool good, bool great,
						   bool extra_roll, s32b *value, int tval)
{
	int base;
	struct object_kind *kind;
	struct object *new_obj;

	/* Try to make a special artifact */
	if (one_in_(good ? 10 : 1000)) {
		new_obj = make_artifact_special(lev);
		if (new_obj) {
			if (value) *value = object_value_real(new_obj, 1, false);
			return new_obj;
		}

		/* If we failed to make an artifact, the player gets a good item */
		good = true;
	}

	/* Base level for the object */
	base = (good ? (lev + 10) : lev);

	/* Try to choose an object kind */
	kind = get_obj_num(base, good || great, tval);
	if (!kind)
		return NULL;

	/* Make the object, prep it and apply magic */
	new_obj = object_new();
	object_prep(new_obj, kind, lev, RANDOMISE);
	if (one_in_(20) && tval_is_wearable(new_obj)) {
		apply_curse(new_obj, &lev);
	}
	apply_magic(new_obj, lev, true, good, great, extra_roll);
	apply_curse_knowledge(new_obj);

	/* Generate multiple items */
	if (kind->gen_mult_prob >= randint1(100))
		new_obj->number = randcalc(kind->stack_size, lev, RANDOMISE);

	if (new_obj->number > z_info->stack_size)
		new_obj->number = z_info->stack_size;

	/* Get the value */
	if (value)
		*value = object_value_real(new_obj, new_obj->number, false);

	/* Boost of 20% per level OOD for uncursed objects */
	if ((!new_obj->curses) && (kind->alloc_min > c->depth)) {
		if (value) *value += (kind->alloc_min - c->depth) * (*value / 5);
	}

	return new_obj;
}
Beispiel #14
0
/*
 * Prepare an object based on an object kind.
 * Use the specified randomization aspect
 */
void object_prep(object_type *o_ptr, int k_idx, int lev, aspect rand_aspect)
{
	object_kind *k_ptr = &k_info[k_idx];

	/* Clear the record */
	(void)WIPE(o_ptr, object_type);

	/* Save the kind index */
	o_ptr->k_idx = k_idx;

	/* Efficiency -- tval/sval */
	o_ptr->tval = k_ptr->tval;
	o_ptr->sval = k_ptr->sval;

	/* Default number */
	o_ptr->number = 1;

	/* Default "pval" */
	o_ptr->pval = randcalc(k_ptr->pval, lev, rand_aspect);

	/* Default weight */
	o_ptr->weight = k_ptr->weight;
	
	/* Assign charges (wands/staves only) */
	if (o_ptr->tval == TV_WAND || o_ptr->tval == TV_STAFF)
		o_ptr->pval = randcalc(k_ptr->charge, lev, rand_aspect);

	/* Default magic */
	o_ptr->to_h = randcalc(k_ptr->to_h, lev, rand_aspect);
	o_ptr->to_d = randcalc(k_ptr->to_d, lev, rand_aspect);
	o_ptr->to_a = randcalc(k_ptr->to_a, lev, rand_aspect);

	/* Default power */
	o_ptr->ac = k_ptr->ac;
	o_ptr->dd = k_ptr->dd;
	o_ptr->ds = k_ptr->ds;

	/* Hack -- cursed items are always "cursed" */
	if (of_has(k_ptr->flags, OF_LIGHT_CURSE))
	    of_on(o_ptr->flags, OF_LIGHT_CURSE);
}
Beispiel #15
0
/**
 * Gives the known effects of using the given item.
 *
 * Fills in:
 *  - the effect id, or OBJ_KNOWN_PRESENT if there is an effect but details
 *    are unknown
 *  - whether the effect can be aimed
 *  -  the minimum and maximum time in game turns for the item to recharge 
 *     (or zero if it does not recharge)
 *  - the percentage chance of the effect failing when used
 *
 * Return FALSE if the object has no effect.
 */
static bool obj_known_effect(const struct object *obj, int *effect, bool *aimed, int *min_recharge, int *max_recharge, int *failure_chance)
{
	random_value timeout = {0, 0, 0, 0};

	*effect = 0;
	*min_recharge = 0;
	*max_recharge = 0;
	*failure_chance = 0;
	*aimed = FALSE;

	if (object_effect_is_known(obj)) {
		*effect = object_effect(obj);
		timeout = obj->time;
	} else if (object_effect(obj)) {
		/* Don't know much - be vague */
		*effect = OBJ_KNOWN_PRESENT;

		if (!obj->artifact && effect_aim(obj->effect))
			*aimed = TRUE;
					
		return TRUE;
	} else {
		/* No effect - no info */
		return FALSE;
	}
	
	if (randcalc(timeout, 0, MAXIMISE) > 0)	{
		*min_recharge = randcalc(timeout, 0, MINIMISE);
		*max_recharge = randcalc(timeout, 0, MAXIMISE);
	}

	if (tval_is_food(obj) || tval_is_potion(obj) || tval_is_scroll(obj)) {
		*failure_chance = 0;
	} else {
		*failure_chance = get_use_device_chance(obj);
	}

	return TRUE;
}
Beispiel #16
0
/**
 * Attempt to make an object
 *
 * \param c is the current dungeon level.
 * \param lev is the creation level of the object (not necessarily == depth).
 * \param good is whether the object is to be good
 * \param great is whether the object is to be great
 * \param extra_roll is whether we get an extra roll in apply_magic()
 * \param value is the value to be returned to the calling function
 * \param tval is the desired tval, or 0 if we allow any tval
 *
 * \return a pointer to the newly allocated object, or NULL on failure.
 */
struct object *make_object(struct chunk *c, int lev, bool good, bool great,
						   bool extra_roll, s32b *value, int tval)
{
	int base;
	object_kind *kind;
	struct object *new_obj;

	/* Try to make a special artifact */
	if (one_in_(good ? 10 : 1000)) {
		new_obj = make_artifact_special(lev);
		if (new_obj) {
			if (value) *value = object_value_real(new_obj, 1, FALSE, TRUE);
			return new_obj;
		}

		/* If we failed to make an artifact, the player gets a good item */
		good = TRUE;
	}

	/* Base level for the object */
	base = (good ? (lev + 10) : lev);

	/* Try to choose an object kind */
	kind = get_obj_num(base, good || great, tval);
	if (!kind)
		return NULL;

	/* Make the object, prep it and apply magic */
	new_obj = object_new();
	object_prep(new_obj, kind, lev, RANDOMISE);
	apply_magic(new_obj, lev, TRUE, good, great, extra_roll);

	/* Generate multiple items */
	if (kind->gen_mult_prob >= randint1(100))
		new_obj->number = randcalc(kind->stack_size, lev, RANDOMISE);

	if (new_obj->number > z_info->stack_size)
		new_obj->number = z_info->stack_size;

	/* Return value, increased for uncursed out-of-depth objects */
	if (value)
		*value = object_value_real(new_obj, new_obj->number, FALSE, TRUE);

	/* This seems to imply objects get less value from being > 1 but < 5
	 * levels out of depth - should it be *value +=... - NRM */
	if (!cursed_p(new_obj->flags) && (kind->alloc_min > c->depth)) {
		if (value) *value = (kind->alloc_min - c->depth) * (*value / 5);
	}

	return new_obj;
}
Beispiel #17
0
/*
 * Attempt to make an object (normal or good/great)
 *
 * This routine plays nasty games to generate the "special artifacts".
 *
 * We assume that the given object has been "wiped".
 */
bool make_object(object_type *j_ptr, int lev, bool good, bool great)
{
	int k_idx, base;
	object_kind *k_ptr;

	/* Try to make a special artifact */
	if (one_in_(good ? 10 : 1000))
	{
		if (make_artifact_special(j_ptr, lev)) return TRUE;
		/* If we failed to make an artifact, the player gets a great item */
		good = great = TRUE;
	}

	/* Base level for the object */
	base = (good ? (lev + 10) : lev);

	/* Get the object */
	k_idx = get_obj_num(base, good || great);
	if (!k_idx) return FALSE;

	/* Prepare the object */
	object_prep(j_ptr, &k_info[k_idx], lev, RANDOMISE);

	/* Apply magic (allow artifacts) */
	apply_magic(j_ptr, lev, TRUE, good, great);


	/* Generate multiple items */
	k_ptr = &k_info[j_ptr->k_idx];

	if (k_ptr->gen_mult_prob >= 100 ||
	    k_ptr->gen_mult_prob >= randint1(100))
	{
		j_ptr->number = randcalc(k_ptr->stack_size, lev, RANDOMISE);
	}


	/* Notice "okay" out-of-depth objects */
	if (!cursed_p(j_ptr) && (k_info[j_ptr->k_idx].level > p_ptr->depth))
	{
		/* Rating increase */
		rating += (k_info[j_ptr->k_idx].alloc_min - p_ptr->depth);

		/* Cheat -- peek at items */
		if (OPT(cheat_peek)) object_mention(j_ptr);
	}

	return TRUE;
}
Beispiel #18
0
static long eval_blow_effect(int effect, random_value atk_dam, int rlev)
{
	int adjustment = monster_blow_effect_eval(effect);
	int power = randcalc(atk_dam, rlev, MAXIMISE);

	if (effect == RBE_POISON) {
		power *= 5;
		power /= 4;
		power += rlev;
	} else {
		power += adjustment;
	}

	return power;
}
Beispiel #19
0
/**
 * Wipe an object clean and make it a standard object of the specified kind.
 */
void object_prep(object_type *o_ptr, struct object_kind *k, int lev,
		aspect rand_aspect)
{
	int i, flag, x;
	bitflag flags[OF_SIZE];

	/* Clean slate */
	WIPE(o_ptr, object_type);

	/* Assign the kind and copy across data */
	o_ptr->kind = k;
	o_ptr->tval = k->tval;
	o_ptr->sval = k->sval;
	o_ptr->ac = k->ac;
	o_ptr->dd = k->dd;
	o_ptr->ds = k->ds;
	o_ptr->weight = k->weight;

	/* Default number */
	o_ptr->number = 1;

	/* Apply pvals and then copy flags */
    for (i = 0; i < k->num_pvals; i++) {
        of_copy(flags, k->pval_flags[i]);
        x = randcalc(k->pval[i], lev, rand_aspect);
        for (flag = of_next(flags, FLAG_START); flag != FLAG_END;
                flag = of_next(flags, flag + 1))
            object_add_pval(o_ptr, x, flag);
    }
	of_copy(o_ptr->flags, k->base->flags);
	of_union(o_ptr->flags, k->flags);

	/* Assign charges (wands/staves only) */
	if (o_ptr->tval == TV_WAND || o_ptr->tval == TV_STAFF)
		o_ptr->pval[DEFAULT_PVAL] = randcalc(k->charge, lev, rand_aspect);

	/* Assign flagless pval for food or oil */
	if (o_ptr->tval == TV_FOOD || o_ptr->tval == TV_POTION ||
			o_ptr->tval == TV_FLASK)
		o_ptr->pval[DEFAULT_PVAL]
			= randcalc(k->pval[DEFAULT_PVAL], lev, rand_aspect);

	/* Default fuel for lamps */
	if (o_ptr->tval == TV_LIGHT) {
		if (o_ptr->sval == SV_LIGHT_TORCH)
			o_ptr->timeout = DEFAULT_TORCH;
		else if (o_ptr->sval == SV_LIGHT_LANTERN)
			o_ptr->timeout = DEFAULT_LAMP;
	}

	/* Default magic */
	o_ptr->to_h = randcalc(k->to_h, lev, rand_aspect);
	o_ptr->to_d = randcalc(k->to_d, lev, rand_aspect);
	o_ptr->to_a = randcalc(k->to_a, lev, rand_aspect);
}
Beispiel #20
0
static size_t obj_desc_charges(const object_type * o_ptr, char *buf, size_t max,
			       size_t end)
{
    object_kind *k_ptr = &k_info[o_ptr->k_idx];

    bool aware = object_aware_p(o_ptr);

    /* Wands and Staffs have charges */
    if (aware && (o_ptr->tval == TV_STAFF || o_ptr->tval == TV_WAND))
	strnfcat(buf, max, &end, " (%d charge%s)", o_ptr->pval,
		 PLURAL(o_ptr->pval));

    /* Charging things */
    else if (o_ptr->timeout > 0) {
	if (o_ptr->tval == TV_ROD && o_ptr->number > 1) {
	    int power;
	    int time_base = randcalc(k_ptr->time, 0, MINIMISE);

	    if (!time_base)
		time_base = 1;

	    /* 
	     * Find out how many rods are charging, by dividing
	     * current timeout by each rod's maximum timeout.
	     * Ensure that any remainder is rounded up.  Display
	     * very discharged stacks as merely fully discharged.
	     */
	    power = (o_ptr->timeout + (time_base - 1)) / time_base;
	    if (power > o_ptr->number)
		power = o_ptr->number;

	    /* Display prettily */
	    strnfcat(buf, max, &end, " (%d charging)", power);
	}

	/* Artifacts, single rods */
	else if (!(o_ptr->tval == TV_LIGHT && !artifact_p(o_ptr))) {
	    strnfcat(buf, max, &end, " (charging)");
	}
    }

    return end;
}
Beispiel #21
0
/**
 * Attempt to make an object
 *
 * \param c is the current dungeon level.
 * \param j_ptr is the object struct to be populated.
 * \param lev is the creation level of the object (not necessarily == depth).
 * \param good is whether the object is to be good
 * \param great is whether the object is to be great
 * \param value is the value to be returned to the calling function
 * \param tval is the desired tval, or 0 if we allow any tval
 *
 * Returns the whether or not creation worked.
 */
bool make_object(struct cave *c, object_type *j_ptr, int lev, bool good,
	bool great, bool extra_roll, s32b *value, int tval)
{
	int base;
	object_kind *kind;

	/* Try to make a special artifact */
	if (one_in_(good ? 10 : 1000)) {
		if (make_artifact_special(j_ptr, lev)) {
			if (value) *value = object_value_real(j_ptr, 1, FALSE, TRUE);
			return TRUE;
		}

		/* If we failed to make an artifact, the player gets a good item */
		good = TRUE;
	}

	/* Base level for the object */
	base = (good ? (lev + 10) : lev);

	/* Get the object, prep it and apply magic */
	kind = get_obj_num(base, good || great, tval);
	if (!kind) return FALSE;
	object_prep(j_ptr, kind, lev, RANDOMISE);
	apply_magic(j_ptr, lev, TRUE, good, great, extra_roll);

	/* Generate multiple items */
	if (kind->gen_mult_prob >= randint1(100))
		j_ptr->number = randcalc(kind->stack_size, lev, RANDOMISE);

	if (j_ptr->number >= MAX_STACK_SIZE)
		j_ptr->number = MAX_STACK_SIZE - 1;

	/* Return value, increased for uncursed out-of-depth objects */
	if (value)
		*value = object_value_real(j_ptr, j_ptr->number, FALSE, TRUE);

	if (!cursed_p(j_ptr->flags) && (kind->alloc_min > c->depth)) {
		if (value) *value = (kind->alloc_min - c->depth) * (*value / 5);
	}

	return TRUE;
}
Beispiel #22
0
/**
 * Determine the damage of a spell attack which ignores monster hp
 * (i.e. bolts and balls, including arrows/boulders/storms/etc.)
 *
 * \param spell is the attack type
 * \param rlev is the monster level of the attacker
 * \param aspect is the damage calc required (min, avg, max, random)
 */
static int nonhp_dam(int spell, int rlev, aspect dam_aspect)
{
	const struct mon_spell *rs_ptr = &mon_spell_table[spell];
	int dam;

	/* base damage is X + YdZ (m_bonus is not used) */
	dam = randcalc(rs_ptr->base_dam, 0, dam_aspect);

	/* rlev-dependent damage (m_bonus is used as a switch) */
	dam += (rlev * rs_ptr->rlev_dam.base / 100);

	if (rs_ptr->rlev_dam.m_bonus == 1) /* then rlev affects dice */
		dam += damcalc(MIN(1, rs_ptr->rlev_dam.dice * rlev / 100), 
				rs_ptr->rlev_dam.sides, dam_aspect);
	else /* rlev affects sides */
		dam += damcalc(rs_ptr->rlev_dam.dice, rs_ptr->rlev_dam.sides *
				rlev / 100, dam_aspect);

	return dam;
}
Beispiel #23
0
/**
 * Determine the damage of a spell attack which ignores monster hp
 * (i.e. bolts and balls, including arrows/boulders/storms/etc.)
 *
 * \param spell is the attack type
 * \param race is the monster race of the attacker
 * \param dam_aspect is the damage calc required (min, avg, max, random)
 */
static int nonhp_dam(const struct monster_spell *spell,
					 const struct monster_race *race, aspect dam_aspect)
{
	int dam = 0;
	struct effect *effect = spell->effect;

	/* Set the reference race for calculations */
	ref_race = race;

	/* Now add the damage for each effect */
	while (effect) {
		random_value rand;
		if (effect->dice) {
			dice_roll(effect->dice, &rand);
			dam += randcalc(rand, 0, dam_aspect);
		}
		effect = effect->next;
	}

	ref_race = NULL;

	return dam;
}
Beispiel #24
0
/*
 * Read an object
 *
 * This function attempts to "repair" old savefiles, and to extract
 * the most up to date values for various object fields.
 */
static int rd_item(object_type *o_ptr)
{
	byte old_dd;
	byte old_ds;
	byte tmp8u;

	size_t i;

	object_kind *k_ptr;

	char buf[128];


	/* Kind */
	rd_s16b(&o_ptr->k_idx);

	/* Paranoia */
	if ((o_ptr->k_idx < 0) || (o_ptr->k_idx >= z_info->k_max))
		return (-1);

	/* Location */
	rd_byte(&o_ptr->iy);
	rd_byte(&o_ptr->ix);

	/* Type/Subtype */
	rd_byte(&o_ptr->tval);
	rd_byte(&o_ptr->sval);
	rd_s16b(&o_ptr->pval);

	/* Pseudo-ID bit */
	rd_byte(&tmp8u);

	rd_byte(&o_ptr->number);
	rd_s16b(&o_ptr->weight);

	rd_byte(&o_ptr->name1);
	rd_byte(&o_ptr->name2);

	rd_s16b(&o_ptr->timeout);

	rd_s16b(&o_ptr->to_h);
	rd_s16b(&o_ptr->to_d);
	rd_s16b(&o_ptr->to_a);

	rd_s16b(&o_ptr->ac);

	rd_byte(&old_dd);
	rd_byte(&old_ds);

	rd_byte(&tmp8u);

	rd_byte(&o_ptr->marked);

	rd_byte(&o_ptr->origin);
	rd_byte(&o_ptr->origin_depth);
	rd_u16b(&o_ptr->origin_xtra);

	/* Hack - XXX - MarbleDice - Maximum saveable flags = 96 */
	for (i = 0; i < 12 && i < OF_SIZE; i++)
		rd_byte(&o_ptr->flags[i]);
	if (i < 12) strip_bytes(OF_SIZE - i);

	/* Monster holding object */
	rd_s16b(&o_ptr->held_m_idx);

	rd_string(buf, sizeof(buf));

	/* Save the inscription */
	if (buf[0]) o_ptr->note = quark_add(buf);


	/* Lookup item kind */
	o_ptr->k_idx = lookup_kind(o_ptr->tval, o_ptr->sval);

	k_ptr = &k_info[o_ptr->k_idx];

	/* Return now in case of "blank" or "empty" objects */
	if (!k_ptr->name || !o_ptr->k_idx)
	{
		o_ptr->k_idx = 0;
		return 0;
	}



	/* Repair non "wearable" items */
	if (!wearable_p(o_ptr))
	{
		/* Get the correct fields */
		if (!randcalc_valid(k_ptr->to_h, o_ptr->to_h))
			o_ptr->to_h = randcalc(k_ptr->to_h, o_ptr->origin_depth, RANDOMISE);
		if (!randcalc_valid(k_ptr->to_d, o_ptr->to_d))
			o_ptr->to_d = randcalc(k_ptr->to_d, o_ptr->origin_depth, RANDOMISE);
		if (!randcalc_valid(k_ptr->to_a, o_ptr->to_a))
			o_ptr->to_a = randcalc(k_ptr->to_a, o_ptr->origin_depth, RANDOMISE);

		/* Get the correct fields */
		o_ptr->ac = k_ptr->ac;
		o_ptr->dd = k_ptr->dd;
		o_ptr->ds = k_ptr->ds;

		/* Get the correct weight */
		o_ptr->weight = k_ptr->weight;

		/* Paranoia */
		o_ptr->name1 = o_ptr->name2 = 0;

		/* All done */
		return (0);
	}



	/* Paranoia */
	if (o_ptr->name1)
	{
		artifact_type *a_ptr;

		/* Paranoia */
		if (o_ptr->name1 >= z_info->a_max) return (-1);

		/* Obtain the artifact info */
		a_ptr = &a_info[o_ptr->name1];

		/* Verify that artifact */
		if (!a_ptr->name) o_ptr->name1 = 0;
	}

	/* Paranoia */
	if (o_ptr->name2)
	{
		ego_item_type *e_ptr;

		/* Paranoia */
		if (o_ptr->name2 >= z_info->e_max) return (-1);

		/* Obtain the ego-item info */
		e_ptr = &e_info[o_ptr->name2];

		/* Verify that ego-item */
		if (!e_ptr->name) o_ptr->name2 = 0;
	}


	/* Get the standard fields */
	o_ptr->ac = k_ptr->ac;
	o_ptr->dd = k_ptr->dd;
	o_ptr->ds = k_ptr->ds;

	/* Get the standard weight */
	o_ptr->weight = k_ptr->weight;


	/* Artifacts */
	if (o_ptr->name1)
	{
		artifact_type *a_ptr;

		/* Obtain the artifact info */
		a_ptr = &a_info[o_ptr->name1];

		/* Get the new artifact "pval" */
		o_ptr->pval = a_ptr->pval;

		/* Get the new artifact fields */
		o_ptr->ac = a_ptr->ac;
		o_ptr->dd = a_ptr->dd;
		o_ptr->ds = a_ptr->ds;

		/* Get the new artifact weight */
		o_ptr->weight = a_ptr->weight;
	}

	/* Ego items */
	if (o_ptr->name2)
	{
		ego_item_type *e_ptr;

		/* Obtain the ego-item info */
		e_ptr = &e_info[o_ptr->name2];

		/* Hack -- keep some old fields */
		if ((o_ptr->dd < old_dd) && (o_ptr->ds == old_ds))
		{
			/* Keep old boosted damage dice */
			o_ptr->dd = old_dd;
		}

		/* Hack -- enforce legal pval */
		if (flags_test(e_ptr->flags, OF_SIZE, OF_PVAL_MASK, FLAG_END))
		{
			/* Force a meaningful pval */
			if (!o_ptr->pval) o_ptr->pval = 1;
		}
	}


	/* Success */
	return (0);
}
Beispiel #25
0
/*
 * Describe an object's effect, if any.
 */
static bool describe_effect(textblock *tb, const object_type *o_ptr, bool full,
		bool only_artifacts, bool subjective)
{
	const char *desc;
	random_value timeout = {0, 0, 0, 0};

	int effect = 0, fail;

	if (o_ptr->artifact)
	{
		if (object_effect_is_known(o_ptr) || full)
		{
			effect = o_ptr->artifact->effect;
			timeout = o_ptr->artifact->time;
		}
		else if (object_effect(o_ptr))
		{
			textblock_append(tb, "It can be activated.\n");
			return TRUE;
		}
	}
	else
	{
		/* Sometimes only print artifact activation info */
		if (only_artifacts == TRUE) return FALSE;

		if (object_effect_is_known(o_ptr) || full)
		{
			effect = o_ptr->kind->effect;
			timeout = o_ptr->kind->time;
		}
		else if (object_effect(o_ptr) != 0)
		{
			if (effect_aim(o_ptr->kind->effect))
				textblock_append(tb, "It can be aimed.\n");
			else if (o_ptr->tval == TV_FOOD)
				textblock_append(tb, "It can be eaten.\n");
			else if (o_ptr->tval == TV_POTION)
				textblock_append(tb, "It can be drunk.\n");
			else if (o_ptr->tval == TV_SCROLL)
				textblock_append(tb, "It can be read.\n");
			else textblock_append(tb, "It can be activated.\n");

			return TRUE;
		}
	}

	/* Forget it without an effect */
	if (!effect) return FALSE;

	/* Obtain the description */
	desc = effect_desc(effect);
	if (!desc) return FALSE;

	if (effect_aim(effect))
		textblock_append(tb, "When aimed, it ");
	else if (o_ptr->tval == TV_FOOD)
		textblock_append(tb, "When eaten, it ");
	else if (o_ptr->tval == TV_POTION)
		textblock_append(tb, "When drunk, it ");
	else if (o_ptr->tval == TV_SCROLL)
	    textblock_append(tb, "When read, it ");
	else
	    textblock_append(tb, "When activated, it ");

	/* Print a colourised description */
	do
	{
		if (isdigit((unsigned char) *desc))
			textblock_append_c(tb, TERM_L_GREEN, "%c", *desc);
		else
			textblock_append(tb, "%c", *desc);
	} while (*desc++);

	textblock_append(tb, ".\n");

	if (randcalc(timeout, 0, MAXIMISE) > 0)
	{
		int min_time, max_time;

		/* Sometimes adjust for player speed */
		int multiplier = extract_energy[p_ptr->state.speed];
		if (!subjective) multiplier = 10;

		textblock_append(tb, "Takes ");

		/* Correct for player speed */
		min_time = randcalc(timeout, 0, MINIMISE) * multiplier / 10;
		max_time = randcalc(timeout, 0, MAXIMISE) * multiplier / 10;

		textblock_append_c(tb, TERM_L_GREEN, "%d", min_time);

		if (min_time != max_time)
		{
			textblock_append(tb, " to ");
			textblock_append_c(tb, TERM_L_GREEN, "%d", max_time);
		}

		textblock_append(tb, " turns to recharge");
		if (subjective && p_ptr->state.speed != 110)
			textblock_append(tb, " at your current speed");

		textblock_append(tb, ".\n");
	}

	if (!subjective || o_ptr->tval == TV_FOOD || o_ptr->tval == TV_POTION ||
		o_ptr->tval == TV_SCROLL)
	{
		return TRUE;
	}
	else
	{
		fail = get_use_device_chance(o_ptr);
		textblock_append(tb, "Your chance of success is %d.%d%%\n", (1000 - fail) /
			10, (1000 - fail) % 10);
	}

	return TRUE;
}
Beispiel #26
0
/**
 * Small helper function to see how an object trait compares to the one
 * in its base type.
 *
 * If the base type provides a positive bonus, we'll use that. Otherwise, we'll
 * use zero (players don't consider an item with a positive bonus to be bad
 * even if the base kind has a higher positive bonus).
 */
static int cmp_object_trait(int bonus, random_value base)
{
	int amt = randcalc(base, 0, MINIMISE);
	if (amt > 0) amt = 0;
	return CMP(bonus, amt);
}
Beispiel #27
0
/*
 * Use an object the right way.
 *
 * There may be a BIG problem with any "effect" that can cause "changes"
 * to the inventory.  For example, a "scroll of recharging" can cause
 * a wand/staff to "disappear", moving the inventory up.  Luckily, the
 * scrolls all appear BEFORE the staffs/wands, so this is not a problem.
 * But, for example, a "staff of recharging" could cause MAJOR problems.
 * In such a case, it will be best to either (1) "postpone" the effect
 * until the end of the function, or (2) "change" the effect, say, into
 * giving a staff "negative" charges, or "turning a staff into a stick".
 * It seems as though a "rod of recharging" might in fact cause problems.
 * The basic problem is that the act of recharging (and destroying) an
 * item causes the inducer of that action to "move", causing "o_ptr" to
 * no longer point at the correct item, with horrifying results.
 */
void do_cmd_use(cmd_code code, cmd_arg args[])
{
	int item = args[0].item;
	object_type *o_ptr = object_from_item_idx(item);
	int effect;
	bool ident = FALSE, used = FALSE;
	bool was_aware = object_flavor_is_aware(o_ptr);
	int dir = 5;
	int px = p_ptr->px, py = p_ptr->py;
	int snd, boost, level;
	use_type use;
	int items_allowed = 0;

	/* Determine how this item is used. */
	if (obj_is_rod(o_ptr))
	{
		if (!obj_can_zap(o_ptr))
		{
			msg("That rod is still charging.");
			return;
		}

		use = USE_TIMEOUT;
		snd = MSG_ZAP_ROD;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_wand(o_ptr))
	{
		if (!obj_has_charges(o_ptr))
		{
			msg("That wand has no charges.");
			return;
		}

		use = USE_CHARGE;
		snd = MSG_ZAP_ROD;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_staff(o_ptr))
	{
		if (!obj_has_charges(o_ptr))
		{
			msg("That staff has no charges.");
			return;
		}

		use = USE_CHARGE;
		snd = MSG_USE_STAFF;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_food(o_ptr))
	{
		use = USE_SINGLE;
		snd = MSG_EAT;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_potion(o_ptr))
	{
		use = USE_SINGLE;
		snd = MSG_QUAFF;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_scroll(o_ptr))
	{
		/* Check player can use scroll */
		if (!player_can_read())
			return;

		use = USE_SINGLE;
		snd = MSG_GENERIC;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_activatable(o_ptr))
	{
		if (!obj_can_activate(o_ptr))
		{
			msg("That item is still charging.");
			return;
		}

		use = USE_TIMEOUT;
		snd = MSG_ACT_ARTIFACT;
		items_allowed = USE_EQUIP;
	}
	else
	{
		msg("The item cannot be used at the moment");
	}

	/* Check if item is within player's reach. */
	if (items_allowed == 0 || !item_is_available(item, NULL, items_allowed))
	{
		msg("You cannot use that item from its current location.");
		return;
	}

	/* track the object used */
	track_object(item);

	/* Figure out effect to use */
	effect = object_effect(o_ptr);

	/* If the item requires a direction, get one (allow cancelling) */
	if (obj_needs_aim(o_ptr))
		dir = args[1].direction;

	/* Check for use if necessary, and execute the effect */
	if ((use != USE_CHARGE && use != USE_TIMEOUT) || check_devices(o_ptr))
	{
		int beam = beam_chance(o_ptr->tval);

		/* Special message for artifacts */
		if (o_ptr->artifact)
		{
			msgt(snd, "You activate it.");
			if (o_ptr->artifact->effect_msg)
				activation_message(o_ptr, o_ptr->artifact->effect_msg);
			level = o_ptr->artifact->level;
		}
		else
		{
			/* Make a noise! */
			sound(snd);
			level = o_ptr->kind->level;
		}

		/* A bit of a hack to make ID work better.
			-- Check for "obvious" effects beforehand. */
		if (effect_obvious(effect)) object_flavor_aware(o_ptr);

		/* Boost damage effects if skill > difficulty */
		boost = MAX(p_ptr->state.skills[SKILL_DEVICE] - level, 0);

		/* Do effect */
		used = effect_do(effect, &ident, was_aware, dir, beam, boost);

		/* Quit if the item wasn't used and no knowledge was gained */
		if (!used && (was_aware || !ident)) return;
	}

	/* If the item is a null pointer or has been wiped, be done now */
	if (!o_ptr || !o_ptr->kind) return;

	if (ident) object_notice_effect(o_ptr);

	/* Food feeds the player */
	if (o_ptr->tval == TV_FOOD || o_ptr->tval == TV_POTION)
		(void)set_food(p_ptr->food + o_ptr->pval[DEFAULT_PVAL]);

	/* Use the turn */
	p_ptr->energy_use = 100;

	/* Mark as tried and redisplay */
	p_ptr->notice |= (PN_COMBINE | PN_REORDER);
	p_ptr->redraw |= (PR_INVEN | PR_EQUIP | PR_OBJECT);

	/*
	 * If the player becomes aware of the item's function, then mark it as
	 * aware and reward the player with some experience.  Otherwise, mark
	 * it as "tried".
	 */
	if (ident && !was_aware)
	{
		/* Object level */
		int lev = o_ptr->kind->level;

		object_flavor_aware(o_ptr);
		if (o_ptr->tval == TV_ROD) object_notice_everything(o_ptr);
		player_exp_gain(p_ptr, (lev + (p_ptr->lev / 2)) / p_ptr->lev);
		p_ptr->notice |= PN_SQUELCH;
	}
	else if (used)
	{
		object_flavor_tried(o_ptr);
	}

	/* If there are no more of the item left, then we're done. */
	if (!o_ptr->number) return;

	/* Chargeables act differently to single-used items when not used up */
	if (used && use == USE_CHARGE)
	{
		/* Use a single charge */
		o_ptr->pval[DEFAULT_PVAL]--;

		/* Describe charges */
		if (item >= 0)
			inven_item_charges(item);
		else
			floor_item_charges(0 - item);
	}
	else if (used && use == USE_TIMEOUT)
	{
		/* Artifacts use their own special field */
		if (o_ptr->artifact)
			o_ptr->timeout = randcalc(o_ptr->artifact->time, 0, RANDOMISE);
		else
			o_ptr->timeout += randcalc(o_ptr->kind->time, 0, RANDOMISE);
	}
	else if (used && use == USE_SINGLE)
	{
		/* Destroy a potion in the pack */
		if (item >= 0)
		{
			inven_item_increase(item, -1);
			inven_item_describe(item);
			inven_item_optimize(item);
		}

		/* Destroy a potion on the floor */
		else
		{
			floor_item_increase(0 - item, -1);
			floor_item_describe(0 - item);
			floor_item_optimize(0 - item);
		}
	}
	
	/* Hack to make Glyph of Warding work properly */
	if (cave->feat[py][px] == FEAT_GLYPH)
	{
		/* Push objects off the grid */
		if (cave->o_idx[py][px]) push_object(py, px);
	}


}
Beispiel #28
0
/**
 * Wipe an object clean and make it a standard object of the specified kind.
 */
void object_prep(struct object *obj, struct object_kind *k, int lev,
				 aspect rand_aspect)
{
	int i;

	/* Clean slate */
	memset(obj, 0, sizeof(*obj));

	/* Assign the kind and copy across data */
	obj->kind = k;
	obj->tval = k->tval;
	obj->sval = k->sval;
	obj->ac = k->ac;
	obj->dd = k->dd;
	obj->ds = k->ds;
	obj->weight = k->weight;
	obj->effect = k->effect;
	obj->time = k->time;

	/* Default number */
	obj->number = 1;

	/* Copy flags */
	of_copy(obj->flags, k->base->flags);
	of_copy(obj->flags, k->flags);

	/* Assign modifiers */
	for (i = 0; i < OBJ_MOD_MAX; i++)
		obj->modifiers[i] = randcalc(k->modifiers[i], lev, rand_aspect);

	/* Assign charges (wands/staves only) */
	if (tval_can_have_charges(obj))
		obj->pval = randcalc(k->charge, lev, rand_aspect);

	/* Assign pval for food, oil and launchers */
	if (tval_is_edible(obj) || tval_is_potion(obj) || tval_is_fuel(obj) ||
		tval_is_launcher(obj))
		obj->pval
			= randcalc(k->pval, lev, rand_aspect);

	/* Default fuel */
	if (tval_is_light(obj)) {
		if (of_has(obj->flags, OF_BURNS_OUT))
			obj->timeout = z_info->fuel_torch;
		else if (of_has(obj->flags, OF_TAKES_FUEL))
			obj->timeout = z_info->default_lamp;
	}

	/* Default magic */
	obj->to_h = randcalc(k->to_h, lev, rand_aspect);
	obj->to_d = randcalc(k->to_d, lev, rand_aspect);
	obj->to_a = randcalc(k->to_a, lev, rand_aspect);

	/* Default slays and brands */
	copy_slay(&obj->slays, k->slays);
	copy_brand(&obj->brands, k->brands);

	/* Default resists */
	for (i = 0; i < ELEM_MAX; i++) {
		obj->el_info[i].res_level = k->el_info[i].res_level;
		obj->el_info[i].flags = k->el_info[i].flags;
		obj->el_info[i].flags |= k->base->el_info[i].flags;
	}
}
Beispiel #29
0
/**
 * Apply magic to miscellanious items
 *
 * Hack -- note the special code for various items
 */
static void a_m_aux_4(object_type * o_ptr, int level, int power)
{
    object_kind *k_ptr = &k_info[o_ptr->k_idx];

    /* Apply magic (good or bad) according to type */
    switch (o_ptr->tval) {
    case TV_LIGHT:
	{
	    /* Hack -- Torches -- random fuel */
	    if (o_ptr->sval == SV_LIGHT_TORCH) {
		if (o_ptr->pval > 0)
		    o_ptr->pval = randint1(o_ptr->pval);
	    }

	    /* Hack -- Lanterns -- random fuel */
	    if (o_ptr->sval == SV_LIGHT_LANTERN) {
		if (o_ptr->pval > 0)
		    o_ptr->pval = randint1(o_ptr->pval);
	    }

	    break;
	}

    case TV_WAND:
    case TV_STAFF:
	{
	    int temp_pval = randcalc(k_ptr->pval, level, RANDOMISE);
	    /* The wand or staff gets a number of initial charges equal to
	     * between 1/2 (+1) and the full object kind's pval. */
	    o_ptr->pval = temp_pval / 2 + randint1((temp_pval + 1) / 2);
	    break;
	}

    case TV_ROD:
	{
	    /* Transfer the pval. */
	    o_ptr->pval = randcalc(k_ptr->pval, level, RANDOMISE);
	    break;
	}

    case TV_CHEST:		/* changed by LM */
	{
	    /* Hack -- pick a "value/difficulty", capable of being as little as 
	     * chest level - 16... */
	    o_ptr->pval = (k_info[o_ptr->k_idx].level) + 20 - damroll(4, 9);

	    /* ...and never exceeding chest level + 4. */
	    if (o_ptr->pval > k_info[o_ptr->k_idx].level)
		o_ptr->pval = k_info[o_ptr->k_idx].level + randint1(4);

	    /* Value/difficulty cannot be less than 5. */
	    if (o_ptr->pval < 5)
		o_ptr->pval = 5;

	    /* Never exceed "value/difficulty" of 99. */
	    if (o_ptr->pval > 99)
		o_ptr->pval = 99;

	    break;
	}
    }
}
Beispiel #30
0
/*
 * Hack -- determine if a template is "good".
 *
 * Note that this test only applies to the object *kind*, so it is
 * possible to choose a kind which is "good", and then later cause
 * the actual object to be cursed.  We do explicitly forbid objects
 * which are known to be boring or which start out somewhat damaged.
 */
static bool kind_is_good(const object_kind *kind)
{
	/* Analyze the item type */
	switch (kind->tval)
	{
		/* Armor -- Good unless damaged */
		case TV_HARD_ARMOR:
		case TV_SOFT_ARMOR:
		case TV_DRAG_ARMOR:
		case TV_SHIELD:
		case TV_CLOAK:
		case TV_BOOTS:
		case TV_GLOVES:
		case TV_HELM:
		case TV_CROWN:
		{
			if (randcalc(kind->to_a, 0, MINIMISE) < 0) return (FALSE);
			return (TRUE);
		}

		/* Weapons -- Good unless damaged */
		case TV_BOW:
		case TV_SWORD:
		case TV_HAFTED:
		case TV_POLEARM:
		case TV_DIGGING:
		{
			if (randcalc(kind->to_h, 0, MINIMISE) < 0) return (FALSE);
			if (randcalc(kind->to_d, 0, MINIMISE) < 0) return (FALSE);
			return (TRUE);
		}

		/* Ammo -- Arrows/Bolts are good */
		case TV_BOLT:
		case TV_ARROW:
		{
			return (TRUE);
		}

		/* Books -- High level books are good */
		case TV_MAGIC_BOOK:
		case TV_PRAYER_BOOK:
		{
			if (kind->sval >= SV_BOOK_MIN_GOOD) return (TRUE);
			return (FALSE);
		}

		/* Rings -- Rings of Speed are good */
		case TV_RING:
		{
			if (kind->sval == SV_RING_SPEED) return (TRUE);
			return (FALSE);
		}

		/* Amulets -- Amulets of the Magi are good */
		case TV_AMULET:
		{
			if (kind->sval == SV_AMULET_THE_MAGI) return (TRUE);
			if (kind->sval == SV_AMULET_DEVOTION) return (TRUE);
			if (kind->sval == SV_AMULET_WEAPONMASTERY) return (TRUE);
			if (kind->sval == SV_AMULET_TRICKERY) return (TRUE);
			return (FALSE);
		}
	}

	/* Assume not good */
	return (FALSE);
}