Exemplo n.º 1
0
/**
 * Allow one item to "absorb" another, assuming they are similar.
 *
 * The blending of the "note" field assumes that either (1) one has an
 * inscription and the other does not, or (2) neither has an inscription.
 * In both these cases, we can simply use the existing note, unless the
 * blending object has a note, in which case we use that note.
 *
* These assumptions are enforced by the "object_similar()" code.
 */
static void object_absorb_merge(struct object *obj1, const struct object *obj2)
{
	int total;

	/* Blend all knowledge */
	of_union(obj1->known_flags, obj2->known_flags);
	of_union(obj1->id_flags, obj2->id_flags);

	/* Merge inscriptions */
	if (obj2->note)
		obj1->note = obj2->note;

	/* Combine timeouts for rod stacking */
	if (tval_can_have_timeout(obj1))
		obj1->timeout += obj2->timeout;

	/* Combine pvals for wands and staves */
	if (tval_can_have_charges(obj1) || tval_is_money(obj1)) {
		total = obj1->pval + obj2->pval;
		obj1->pval = total >= MAX_PVAL ? MAX_PVAL : total;
	}

	/* Combine origin data as best we can */
	if (obj1->origin != obj2->origin ||
		obj1->origin_depth != obj2->origin_depth ||
		obj1->origin_xtra != obj2->origin_xtra) {
		int act = 2;

		if (obj1->origin_xtra && obj2->origin_xtra) {
			monster_race *r_ptr = &r_info[obj1->origin_xtra];
			monster_race *s_ptr = &r_info[obj2->origin_xtra];

			bool r_uniq = rf_has(r_ptr->flags, RF_UNIQUE) ? TRUE : FALSE;
			bool s_uniq = rf_has(s_ptr->flags, RF_UNIQUE) ? TRUE : FALSE;

			if (r_uniq && !s_uniq) act = 0;
			else if (s_uniq && !r_uniq) act = 1;
			else act = 2;
		}

		switch (act)
		{
				/* Overwrite with obj2 */
			case 1:
			{
				obj1->origin = obj2->origin;
				obj1->origin_depth = obj2->origin_depth;
				obj1->origin_xtra = obj2->origin_xtra;
			}

				/* Set as "mixed" */
			case 2:
			{
				obj1->origin = ORIGIN_MIXED;
			}
		}
	}
}
Exemplo n.º 2
0
/*
 * Notice the ego on an ego item.
 */
void object_notice_ego(object_type *o_ptr)
{
	ego_item_type *e_ptr;
	bitflag learned_flags[OF_SIZE];
	bitflag xtra_flags[OF_SIZE];

	if (!o_ptr->name2)
		return;

	e_ptr = &e_info[o_ptr->name2];


	/* XXX Eddie print a message on notice ego if not already noticed? */
	/* XXX Eddie should we do something about everseen of egos here? */

	/* Learn ego flags */
	of_union(o_ptr->known_flags, e_ptr->flags);

	/* Learn all flags except random abilities */
	of_setall(learned_flags);

	switch (e_ptr->xtra)
	{
		case OBJECT_XTRA_TYPE_NONE:
			break;
		case OBJECT_XTRA_TYPE_SUSTAIN:
			set_ego_xtra_sustain(xtra_flags);
			of_diff(learned_flags, xtra_flags);
			break;
		case OBJECT_XTRA_TYPE_RESIST:
			set_ego_xtra_resist(xtra_flags);
			of_diff(learned_flags, xtra_flags);
			break;
		case OBJECT_XTRA_TYPE_POWER:
			set_ego_xtra_power(xtra_flags);
			of_diff(learned_flags, xtra_flags);
			break;
		default:
			assert(0);
	}

	of_union(o_ptr->known_flags, learned_flags);

	if (object_add_ident_flags(o_ptr, IDENT_NAME))
	{
		/* if you know the ego, you know which it is of excellent or splendid */
		object_notice_sensing(o_ptr);

		object_check_for_ident(o_ptr);
	}
}
Exemplo n.º 3
0
/*
 * Create the artifact with the specified number
 */
static void wiz_create_artifact(int a_idx)
{
	object_type *i_ptr;
	object_type object_type_body;
	int k_idx;

	artifact_type *a_ptr = &a_info[a_idx];

	/* Ignore "empty" artifacts */
	if (!a_ptr->name) return;

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

	/* Wipe the object */
	object_wipe(i_ptr);

	/* Acquire the "kind" index */
	k_idx = lookup_kind(a_ptr->tval, a_ptr->sval);

	/* Oops */
	if (!k_idx) return;

	/* Create the artifact */
	object_prep(i_ptr, &k_info[k_idx], a_ptr->alloc_min, RANDOMISE);

	/* Save the name */
	i_ptr->name1 = a_idx;

	/* Extract the fields */
	i_ptr->pval = a_ptr->pval;
	i_ptr->ac = a_ptr->ac;
	i_ptr->dd = a_ptr->dd;
	i_ptr->ds = a_ptr->ds;
	i_ptr->to_a = a_ptr->to_a;
	i_ptr->to_h = a_ptr->to_h;
	i_ptr->to_d = a_ptr->to_d;
	i_ptr->weight = a_ptr->weight;

	/* Hack -- extract the "cursed" flags */
	if (cursed_p(a_ptr))
	{
		bitflag curse_flags[OF_SIZE];
		of_copy(curse_flags, a_ptr->flags);
		flags_mask(curse_flags, OF_SIZE, OF_CURSE_MASK, FLAG_END);
		of_union(i_ptr->flags, curse_flags);
	}

	/* Mark that the artifact has been created. */
	a_ptr->created = TRUE;

	/* Mark as cheat */
	i_ptr->origin = ORIGIN_CHEAT;

	/* Drop the artifact from heaven */
	drop_near(i_ptr, 0, p_ptr->py, p_ptr->px, TRUE);

	/* All done */
	msg_print("Allocated.");
}
Exemplo n.º 4
0
/**
 * Copy artifact data to a normal object, and set various slightly hacky
 * globals.
 */
static void copy_artifact_data(object_type *o_ptr, const artifact_type *a_ptr)
{
	/* Extract the other fields */
	o_ptr->pval = a_ptr->pval;
	o_ptr->ac = a_ptr->ac;
	o_ptr->dd = a_ptr->dd;
	o_ptr->ds = a_ptr->ds;
	o_ptr->to_a = a_ptr->to_a;
	o_ptr->to_h = a_ptr->to_h;
	o_ptr->to_d = a_ptr->to_d;
	o_ptr->weight = a_ptr->weight;

	/* Hack -- extract the "cursed" flags */
	if (cursed_p(a_ptr))
	{
		bitflag curse_flags[OF_SIZE];

		of_copy(curse_flags, a_ptr->flags);
		flags_mask(curse_flags, OF_SIZE, OF_CURSE_MASK, FLAG_END);
		of_union(o_ptr->flags, curse_flags);
	}

	/* Mega-Hack -- increase the rating */
	rating += 10;

	/* Mega-Hack -- increase the rating again */
	if (a_ptr->cost > 50000L) rating += 10;

	/* Set the good item flag */
	good_item_flag = TRUE;

	/* Cheat -- peek at the item */
	if (OPT(cheat_peek)) object_mention(o_ptr);
}
Exemplo n.º 5
0
/**
 * Copy artifact data to a normal object, and set various slightly hacky
 * globals.
 */
static void copy_artifact_data(object_type *o_ptr, const artifact_type *a_ptr)
{
	/* Extract the other fields */
	o_ptr->pval = a_ptr->pval;
	o_ptr->ac = a_ptr->ac;
	o_ptr->dd = a_ptr->dd;
	o_ptr->ds = a_ptr->ds;
	o_ptr->to_a = a_ptr->to_a;
	o_ptr->to_h = a_ptr->to_h;
	o_ptr->to_d = a_ptr->to_d;
	o_ptr->weight = a_ptr->weight;

	/* Hack -- extract the "cursed" flags */
	if (cursed_p(a_ptr))
	{
		bitflag curse_flags[OF_SIZE];

		of_copy(curse_flags, a_ptr->flags);
		flags_mask(curse_flags, OF_SIZE, OF_CURSE_MASK, FLAG_END);
		of_union(o_ptr->flags, curse_flags);
	}

	/* Mega-Hack -- increase the level rating
	 * - a sizeable increase for any artifact (c.f. up to 30 for ego items)
	 * - a bigger increase for more powerful artifacts
	 */
	rating += 30;
	rating += object_power(o_ptr, FALSE, NULL, TRUE) / 25;

	/* Set the good item flag */
	good_item_flag = TRUE;

	/* Cheat -- peek at the item */
	if (OPT(cheat_peek)) object_mention(o_ptr);
}
Exemplo n.º 6
0
/**
 * Copy artifact data to a normal object, and set various slightly hacky
 * globals.
 */
void copy_artifact_data(object_type *o_ptr, const artifact_type *a_ptr)
{
	int i;

	/* Extract the data */
	for (i = 0; i < a_ptr->num_pvals; i++)
		if (a_ptr->pval[i]) {
			o_ptr->pval[i] = a_ptr->pval[i];
			of_copy(o_ptr->pval_flags[i], a_ptr->pval_flags[i]);
		}
	o_ptr->num_pvals = a_ptr->num_pvals;
	o_ptr->ac = a_ptr->ac;
	o_ptr->dd = a_ptr->dd;
	o_ptr->ds = a_ptr->ds;
	o_ptr->to_a = a_ptr->to_a;
	o_ptr->to_h = a_ptr->to_h;
	o_ptr->to_d = a_ptr->to_d;
	o_ptr->weight = a_ptr->weight;
	of_union(o_ptr->flags, a_ptr->flags);

    /* Set the prefix or suffix, if the artifact has an affix */
	if (a_ptr->affix && affix_is_prefix(a_ptr->affix->eidx))
		o_ptr->prefix = a_ptr->affix;

	if (a_ptr->affix && affix_is_suffix(a_ptr->affix->eidx))
		o_ptr->suffix = a_ptr->affix;

	/* Set the theme, if it has one */
	if (a_ptr->theme)
		o_ptr->theme = a_ptr->theme;
}
Exemplo n.º 7
0
/**
 * Provide information on an ego-item type
 */
textblock *object_info_ego(struct ego_item * ego)
{
	object_kind *kind = NULL;
	object_type obj = { 0 };
	int i;

	for (i = 0; i < z_info->k_max; i++) {
		kind = &k_info[i];
		if (!kind->name)
			continue;
		if (kind->tval == ego->tval[0])
			break;
	}

	obj.kind = kind;
	obj.tval = kind->tval;
	obj.sval = kind->sval;
	obj.name2 = ego->eidx;
	of_union(obj.flags_obj, ego->flags_obj);
	cf_union(obj.flags_curse, ego->flags_curse);
	for (i = 0; i < MAX_P_RES; i++)
		obj.percent_res[i] = ego->percent_res[i];
	for (i = 0; i < A_MAX; i++)
		obj.bonus_stat[i] = ego->bonus_stat[i];
	for (i = 0; i < MAX_P_BONUS; i++)
		obj.bonus_other[i] = ego->bonus_other[i];
	for (i = 0; i < MAX_P_SLAY; i++)
		obj.multiple_slay[i] = ego->multiple_slay[i];
	for (i = 0; i < MAX_P_BRAND; i++)
		obj.multiple_brand[i] = ego->multiple_brand[i];

	return object_info_out(&obj, OINFO_FULL | OINFO_EGO | OINFO_DUMMY);
}
Exemplo n.º 8
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 (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);
}
Exemplo n.º 9
0
/**
 * Copy artifact data to a normal object, and set various slightly hacky
 * globals.
 */
void copy_artifact_data(struct object *obj, const struct artifact *art)
{
	int i;

	/* Extract the data */
	for (i = 0; i < OBJ_MOD_MAX; i++)
		obj->modifiers[i] = art->modifiers[i];
	obj->ac = art->ac;
	obj->dd = art->dd;
	obj->ds = art->ds;
	obj->to_a = art->to_a;
	obj->to_h = art->to_h;
	obj->to_d = art->to_d;
	obj->weight = art->weight;
	obj->activation = art->activation;
	if (art->time.base != 0)
		obj->time = art->time;
	of_union(obj->flags, art->flags);
	copy_slay(&obj->slays, art->slays);
	copy_brand(&obj->brands, art->brands);
	for (i = 0; i < ELEM_MAX; i++) {
		/* Take the larger of artifact and base object resist levels */
		obj->el_info[i].res_level =
			MAX(art->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 |= art->el_info[i].flags;
	}
}
Exemplo n.º 10
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;
}
Exemplo n.º 11
0
/** 
 * Label an item as an ego item if it has the required flags
 */
void label_as_ego(object_type * o_ptr, int item)
{
    char o_name[120];
    int j;
    int temp_flag;
    ego_item_type *e_ptr = &e_info[o_ptr->name2];

    /* All ego object flags now known */
    of_union(o_ptr->id_obj, e_ptr->flags_obj);

    /* All shown curses are now known */
    if (of_has(e_ptr->flags_obj, OF_SHOW_CURSE))
	cf_union(o_ptr->id_curse, e_ptr->flags_curse);

    /* Know all ego resists */
    for (j = 0; j < MAX_P_RES; j++) {
	temp_flag = OBJECT_ID_BASE_RESIST + j;
	if (e_ptr->percent_res[j] != RES_LEVEL_BASE)
	    if_on(o_ptr->id_other, temp_flag);
    }

    /* Know all ego slays */
    for (j = 0; j < MAX_P_SLAY; j++) {
	temp_flag = OBJECT_ID_BASE_SLAY + j;
	if (e_ptr->multiple_slay[j] != MULTIPLE_BASE)
	    if_on(o_ptr->id_other, temp_flag);
    }

    /* Know all ego brands */
    for (j = 0; j < MAX_P_BRAND; j++) {
	temp_flag = OBJECT_ID_BASE_BRAND + j;
	if (e_ptr->multiple_brand[j] != MULTIPLE_BASE)
	    if_on(o_ptr->id_other, temp_flag);
    }

    /* Combine / Reorder the pack (later) */
    p_ptr->notice |= (PN_COMBINE | PN_REORDER);

    /* Redraw stuff */
    p_ptr->redraw |= (PR_INVEN | PR_EQUIP | PR_BASIC | PR_EXTRA);

    /* Handle stuff */
    handle_stuff(p_ptr);

    /* Description */
    object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL);

    /* Describe */
    if (item - 1 >= INVEN_WIELD) {
	char *m = format("%s: %s (%c).", describe_use(item - 1), o_name, 
			 index_to_label(item - 1));
	my_strcap(m);
	msg(m);
    } else if (item - 1 >= 0) {
	msg("In your pack: %s (%c).", o_name, index_to_label(item));
    }
}
Exemplo n.º 12
0
/*
 * Notice a set of flags - returns TRUE if anything new was learned
 */
bool object_notice_flags(object_type *o_ptr, bitflag flags[OF_SIZE])
{
	if (!of_is_subset(o_ptr->known_flags, flags))
	{
		of_union(o_ptr->known_flags, flags);
		/* XXX Eddie don't want infinite recursion if object_check_for_ident sets more flags,
		 * but maybe this will interfere with savefile repair
		 */
		object_check_for_ident(o_ptr);
		event_signal(EVENT_INVENTORY);
		event_signal(EVENT_EQUIPMENT);

		return TRUE;
	}

	return FALSE;
}
Exemplo n.º 13
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;
}
Exemplo n.º 14
0
/**
 * Copy artifact data to a normal object, and set various slightly hacky
 * globals.
 */
void copy_artifact_data(object_type *o_ptr, const artifact_type *a_ptr)
{
	int i;

	/* Extract the data */
	for (i = 0; i < a_ptr->num_pvals; i++)
		if (a_ptr->pval[i]) {
			o_ptr->pval[i] = a_ptr->pval[i];
			of_copy(o_ptr->pval_flags[i], a_ptr->pval_flags[i]);
		}
	o_ptr->num_pvals = a_ptr->num_pvals;
	o_ptr->ac = a_ptr->ac;
	o_ptr->dd = a_ptr->dd;
	o_ptr->ds = a_ptr->ds;
	o_ptr->to_a = a_ptr->to_a;
	o_ptr->to_h = a_ptr->to_h;
	o_ptr->to_d = a_ptr->to_d;
	o_ptr->weight = a_ptr->weight;
	of_union(o_ptr->flags, a_ptr->flags);
}
Exemplo n.º 15
0
/**
 * Provide information on an ego-item type
 */
textblock *object_info_ego(struct ego_item *ego)
{
	object_kind *kind = NULL;
	object_type obj = { 0 };
	int i;

	for (i = 0; i < z_info->k_max; i++) {
		kind = &k_info[i];
		if (!kind->name)
			continue;
		if (kind->tval == ego->tval[0])
			break;
	}

	obj.kind = kind;
	obj.tval = kind->tval;
	obj.sval = kind->sval;
	obj.ego = ego;
	of_union(obj.flags, ego->flags);

	return object_info_out(&obj, OINFO_FULL | OINFO_EGO | OINFO_DUMMY);
}
Exemplo n.º 16
0
/*
 * Describe combat advantages.
 */
static bool describe_combat(textblock *tb, const object_type *o_ptr,
		oinfo_detail_t mode)
{
	bool full = mode & OINFO_FULL;

	const char *desc[SL_MAX] = { 0 };
	int i;
	int mult[SL_MAX];
	int cnt, dam, total_dam, plus = 0;
	int xtra_postcrit = 0, xtra_precrit = 0;
	int crit_mult, crit_div, crit_add;
	int str_plus, dex_plus, old_blows = 0, new_blows, extra_blows;
	int str_faster = -1, str_done = -1;
	object_type *bow = &p_ptr->inventory[INVEN_BOW];

	bitflag f[OF_SIZE], tmp_f[OF_SIZE], mask[OF_SIZE];

	bool weapon = (wield_slot(o_ptr) == INVEN_WIELD);
	bool ammo   = (p_ptr->state.ammo_tval == o_ptr->tval) &&
	              (bow->kind);
	int multiplier = 1;

	/* Create the "all slays" mask */
	create_mask(mask, FALSE, OFT_SLAY, OFT_KILL, OFT_BRAND, OFT_MAX);

	/* Abort if we've nothing to say */
	if (mode & OINFO_DUMMY) return FALSE;

	if (!weapon && !ammo)
	{
		/* Potions can have special text */
		if (o_ptr->tval != TV_POTION ||
				o_ptr->dd == 0 || o_ptr->ds == 0 ||
				!object_flavor_is_aware(o_ptr))
			return FALSE;

		textblock_append(tb, "It can be thrown at creatures with damaging effect.\n");
		return TRUE;
	}

	if (full) {
		object_flags(o_ptr, f);
	} else {
		object_flags_known(o_ptr, f);
	}

	textblock_append_c(tb, TERM_L_WHITE, "Combat info:\n");

	if (weapon)
	{
		/*
		 * Get the player's hypothetical state, were they to be
		 * wielding this item.
		 */
		player_state state;
		int dex_plus_bound;
		int str_plus_bound;

		object_type inven[INVEN_TOTAL];

		memcpy(inven, p_ptr->inventory, INVEN_TOTAL * sizeof(object_type));
		inven[INVEN_WIELD] = *o_ptr;

		if (full) object_know_all_flags(&inven[INVEN_WIELD]);

		calc_bonuses(inven, &state, TRUE);
		dex_plus_bound = STAT_RANGE - state.stat_ind[A_DEX];
		str_plus_bound = STAT_RANGE - state.stat_ind[A_STR];

		dam = ((o_ptr->ds + 1) * o_ptr->dd * 5);

		xtra_postcrit = state.dis_to_d * 10;
		if (object_attack_plusses_are_visible(o_ptr))
		{
			xtra_precrit += o_ptr->to_d * 10;
			plus += o_ptr->to_h;
		}

		calculate_melee_crits(&state, o_ptr->weight, plus,
				&crit_mult, &crit_add, &crit_div);

		/* Warn about heavy weapons */
		if (adj_str_hold[state.stat_ind[A_STR]] < o_ptr->weight / 10)
			textblock_append_c(tb, TERM_L_RED, "You are too weak to use this weapon.\n");

		textblock_append_c(tb, TERM_L_GREEN, "%d.%d ",
				state.num_blows / 100, (state.num_blows / 10) % 10);
		textblock_append(tb, "blow%s/round.\n",
				(state.num_blows > 100) ? "s" : "");

		/* Check to see if extra STR or DEX would yield extra blows */
		old_blows = state.num_blows;
		extra_blows = 0;

		/* First we need to look for extra blows on other items, as
		 * state does not track these */
		for (i = INVEN_BOW; i < INVEN_TOTAL; i++)
		{
			if (!p_ptr->inventory[i].kind)
				continue;
			object_flags_known(&p_ptr->inventory[i], tmp_f);

			if (of_has(tmp_f, OF_BLOWS))
				extra_blows += p_ptr->inventory[i].pval[which_pval(&p_ptr->inventory[i], OF_BLOWS)];
		}

		/* Then we add blows from the weapon being examined */
		if (of_has(f, OF_BLOWS))
			extra_blows += o_ptr->pval[which_pval(o_ptr, OF_BLOWS)];

		/* Then we check for extra "real" blows */
		for (dex_plus = 0; dex_plus < dex_plus_bound; dex_plus++)
		{
			for (str_plus = 0; str_plus < str_plus_bound; str_plus++)
	        {
				state.stat_ind[A_STR] += str_plus;
				state.stat_ind[A_DEX] += dex_plus;
				new_blows = calc_blows(o_ptr, &state, extra_blows);

				/* Test to make sure that this extra blow is a
				 * new str/dex combination, not a repeat
				 */
				if ((new_blows - new_blows % 10) > (old_blows - old_blows % 10) &&
					(str_plus < str_done ||
					str_done == -1))
				{
					textblock_append(tb, "With +%d STR and +%d DEX you would get %d.%d blows\n",
						str_plus, dex_plus, (new_blows / 100),
						(new_blows / 10) % 10);
					state.stat_ind[A_STR] -= str_plus;
					state.stat_ind[A_DEX] -= dex_plus;
					str_done = str_plus;
					break;
				}

				/* If the combination doesn't increment
				 * the displayed blows number, it might still
				 * take a little less energy
				 */
				if (new_blows > old_blows &&
					(str_plus < str_faster ||
					str_faster == -1) &&
					(str_plus < str_done ||
					str_done == -1))
				{
					textblock_append(tb, "With +%d STR and +%d DEX you would attack a bit faster\n",
						str_plus, dex_plus);
					state.stat_ind[A_STR] -= str_plus;
					state.stat_ind[A_DEX] -= dex_plus;
					str_faster = str_plus;
					continue;
				}

				state.stat_ind[A_STR] -= str_plus;
				state.stat_ind[A_DEX] -= dex_plus;
			}
		}
	}
	else
	{
		int tdis = 6 + 2 * p_ptr->state.ammo_mult;

		if (object_attack_plusses_are_visible(o_ptr))
			plus += o_ptr->to_h;

		calculate_missile_crits(&p_ptr->state, o_ptr->weight, plus,
				&crit_mult, &crit_add, &crit_div);

		/* Calculate damage */
		dam = ((o_ptr->ds + 1) * o_ptr->dd * 5);

		if (object_attack_plusses_are_visible(o_ptr))
			dam += (o_ptr->to_d * 10);
		if (object_attack_plusses_are_visible(bow))
			dam += (bow->to_d * 10);

		/* Apply brands/slays from the shooter to the ammo, but only if known
		 * Note that this is not dependent on mode, so that viewing shop-held
		 * ammo (fully known) does not leak information about launcher */
		object_flags_known(bow, tmp_f);
		of_union(f, tmp_f);

		textblock_append(tb, "Hits targets up to ");
		textblock_append_c(tb, TERM_L_GREEN, format("%d", tdis * 10));
		textblock_append(tb, " feet away.\n");
	}

	/* Collect slays */
	/* Melee weapons get slays and brands from other items now */
	if (weapon)
	{
		bool nonweap = FALSE;

		for (i = INVEN_LEFT; i < INVEN_TOTAL; i++)
		{
			if (!p_ptr->inventory[i].kind)
				continue;
			object_flags_known(&p_ptr->inventory[i], tmp_f);

			of_inter(tmp_f, mask); /* strip out non-slays */

			if (of_union(f, tmp_f))
				nonweap = TRUE;
		}

		if (nonweap)
			textblock_append(tb, "This weapon may benefit from one or more off-weapon brands or slays.\n");
	}

	textblock_append(tb, "Average damage/round: ");

	if (ammo) multiplier = p_ptr->state.ammo_mult;

	cnt = list_slays(f, mask, desc, NULL, mult, TRUE);
	for (i = 0; i < cnt; i++)
	{
		int melee_adj_mult = ammo ? 0 : 1; /* ammo mult adds fully, melee mult is times 1, so adds 1 less */
		/* Include bonus damage and slay in stated average */
		total_dam = dam * (multiplier + mult[i] - melee_adj_mult) + xtra_precrit;
		total_dam = (total_dam * crit_mult + crit_add) / crit_div;
		total_dam += xtra_postcrit;
		if (weapon) 
			total_dam = (total_dam * old_blows) / 100;
		else
			total_dam *= p_ptr->state.num_shots;
		

		if (total_dam <= 0)
			textblock_append_c(tb, TERM_L_RED, "%d", 0);
		else if (total_dam % 10)
			textblock_append_c(tb, TERM_L_GREEN, "%d.%d",
					total_dam / 10, total_dam % 10);
		else
			textblock_append_c(tb, TERM_L_GREEN, "%d", total_dam / 10);


		textblock_append(tb, " vs. %s, ", desc[i]);
	}

	if (cnt) textblock_append(tb, "and ");

	/* Include bonus damage in stated average */
	total_dam = dam * multiplier + xtra_precrit;
	total_dam = (total_dam * crit_mult + crit_add) / crit_div;
	total_dam += xtra_postcrit;
	if (weapon)
		total_dam = (total_dam * old_blows) / 100;
	else
		total_dam *= p_ptr->state.num_shots;

	if (total_dam <= 0)
		textblock_append_c(tb, TERM_L_RED, "%d", 0);
	else if (total_dam % 10)
		textblock_append_c(tb, TERM_L_GREEN, "%d.%d",
				total_dam / 10, total_dam % 10);
	else
		textblock_append_c(tb, TERM_L_GREEN, "%d", total_dam / 10);

	if (cnt) textblock_append(tb, " vs. others");
	textblock_append(tb, ".\n");

	/* Note the impact flag */
	if (of_has(f, OF_IMPACT))
		textblock_append(tb, "Sometimes creates earthquakes on impact.\n");

	/* Add breakage chance */
	if (ammo)
	{
		int chance = breakage_chance(o_ptr, TRUE);
		textblock_append_c(tb, TERM_L_GREEN, "%d%%", chance);
		textblock_append(tb, " chance of breaking upon contact.\n");
	}

	/* You always have something to say... */
	return TRUE;
}
Exemplo n.º 17
0
/*
 * Describe damage.
 */
static bool describe_damage(textblock *tb, const object_type *o_ptr,
		player_state state, bitflag f[OF_SIZE], oinfo_detail_t mode)
{
	const char *desc[SL_MAX] = { 0 };
	size_t i, cnt;
	int mult[SL_MAX];
	int dice, sides, dam, total_dam, plus = 0;
	int xtra_postcrit = 0, xtra_precrit = 0;
	int crit_mult, crit_div, crit_add;
	int old_blows = 0;
	object_type *bow = &p_ptr->inventory[INVEN_BOW];

	bitflag tmp_f[OF_SIZE], mask[OF_SIZE];

	bool weapon = (wield_slot(o_ptr) == INVEN_WIELD);
	bool ammo   = (p_ptr->state.ammo_tval == o_ptr->tval) &&
	              (bow->kind);
	int multiplier = 1;
	bool full = mode & OINFO_FULL;

	/* Create the "all slays" mask */
	create_mask(mask, FALSE, OFT_SLAY, OFT_KILL, OFT_BRAND, OFT_MAX);

	/* Use displayed dice if real dice not known */
	if (full || object_attack_plusses_are_visible(o_ptr)) {
		dice = o_ptr->dd;
		sides = o_ptr->ds;
	} else {
		dice = o_ptr->kind->dd;
		sides = o_ptr->kind->ds;
	}

	/* Calculate damage */
	dam = ((sides + 1) * dice * 5);

	if (weapon)	{
		xtra_postcrit = state.dis_to_d * 10;
		if (object_attack_plusses_are_visible(o_ptr) || full) {
			xtra_precrit += o_ptr->to_d * 10;
			plus += o_ptr->to_h;
		}

		calculate_melee_crits(&state, o_ptr->weight, plus,
				&crit_mult, &crit_add, &crit_div);

		old_blows = state.num_blows;
	} else { /* Ammo */
		if (object_attack_plusses_are_visible(o_ptr) || full)
			plus += o_ptr->to_h;

		calculate_missile_crits(&p_ptr->state, o_ptr->weight, plus,
				&crit_mult, &crit_add, &crit_div);

		if (object_attack_plusses_are_visible(o_ptr) || full)
			dam += (o_ptr->to_d * 10);
		if (object_attack_plusses_are_visible(bow))
			dam += (bow->to_d * 10);

		/* Apply brands/slays from the shooter to the ammo, but only if known
		 * Note that this is not dependent on mode, so that viewing shop-held
		 * ammo (fully known) does not leak information about launcher */
		object_flags_known(bow, tmp_f);
		of_union(f, tmp_f);
	}

	/* Collect slays */
	/* Melee weapons get slays and brands from other items now */
	if (weapon)	{
		bool nonweap_slay = FALSE;

		for (i = INVEN_LEFT; i < INVEN_TOTAL; i++) {
			if (!p_ptr->inventory[i].kind)
				continue;

			object_flags_known(&p_ptr->inventory[i], tmp_f);

			/* Strip out non-slays */
			of_inter(tmp_f, mask);

			if (of_union(f, tmp_f))
				nonweap_slay = TRUE;
		}

		if (nonweap_slay)
			textblock_append(tb, "This weapon may benefit from one or more off-weapon brands or slays.\n");
	}

	textblock_append(tb, "Average damage/round: ");

	if (ammo) multiplier = p_ptr->state.ammo_mult;

	/* Output damage for creatures effected by the brands or slays */
	cnt = list_slays(f, mask, desc, NULL, mult, TRUE);
	for (i = 0; i < cnt; i++) {
		/* ammo mult adds fully, melee mult is times 1, so adds 1 less */
		int melee_adj_mult = ammo ? 0 : 1;

		/* Include bonus damage and slay in stated average */
		total_dam = dam * (multiplier + mult[i] - melee_adj_mult) + xtra_precrit;
		total_dam = (total_dam * crit_mult + crit_add) / crit_div;
		total_dam += xtra_postcrit;

		if (weapon)
			total_dam = (total_dam * old_blows) / 100;
		else
			total_dam *= p_ptr->state.num_shots;

		if (total_dam <= 0)
			textblock_append_c(tb, TERM_L_RED, "%d", 0);
		else if (total_dam % 10)
			textblock_append_c(tb, TERM_L_GREEN, "%d.%d",
					total_dam / 10, total_dam % 10);
		else
			textblock_append_c(tb, TERM_L_GREEN, "%d", total_dam / 10);

		textblock_append(tb, " vs. %s, ", desc[i]);
	}

	if (cnt) textblock_append(tb, "and ");

	/* Include bonus damage in stated average */
	total_dam = dam * multiplier + xtra_precrit;
	total_dam = (total_dam * crit_mult + crit_add) / crit_div;
	total_dam += xtra_postcrit;

	/* Normal damage, not considering brands or slays */
	if (weapon)
		total_dam = (total_dam * old_blows) / 100;
	else
		total_dam *= p_ptr->state.num_shots;

	if (total_dam <= 0)
		textblock_append_c(tb, TERM_L_RED, "%d", 0);
	else if (total_dam % 10)
		textblock_append_c(tb, TERM_L_GREEN, "%d.%d",
				total_dam / 10, total_dam % 10);
	else
		textblock_append_c(tb, TERM_L_GREEN, "%d", total_dam / 10);

	if (cnt) textblock_append(tb, " vs. others");
	textblock_append(tb, ".\n");

	return TRUE;
}
Exemplo n.º 18
0
/* XXX Eddie should messages be adhoc all over the place?  perhaps the main
 * loop should check for change in inventory/wieldeds and all messages be
 * printed from one place
 */
void object_notice_on_wield(object_type *o_ptr)
{
	bitflag f[OF_SIZE], obvious_mask[OF_SIZE];
	bool obvious = FALSE;
	const slay_t *s_ptr;

	flags_init(obvious_mask, OF_SIZE, OF_OBVIOUS_MASK, FLAG_END);

	/* Save time of wield for later */
	object_last_wield = turn;

	/* Only deal with un-ID'd items */
	if (object_is_known(o_ptr)) return;

	/* Wear it */
	object_flavor_tried(o_ptr);
	if (object_add_ident_flags(o_ptr, IDENT_WORN))
		object_check_for_ident(o_ptr);

	if (obj_is_light(o_ptr) && ego_item_p(o_ptr))
		object_notice_ego(o_ptr);

	if (object_flavor_is_aware(o_ptr) && easy_know(o_ptr))
	{
		object_notice_everything(o_ptr);
		return;
	}

	/* Automatically sense artifacts upon wield */
	object_sense_artifact(o_ptr);

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

	/* special case FA, needed at least for mages wielding gloves */
	if (object_FA_would_be_obvious(o_ptr))
		of_on(obvious_mask, OF_FREE_ACT);

	/* Learn about obvious flags */
	of_union(o_ptr->known_flags, obvious_mask);

	/* Extract the flags */
	object_flags(o_ptr, f);

	/* Find obvious things (disregarding curses) */
	flags_clear(obvious_mask, OF_SIZE, OF_CURSE_MASK, FLAG_END);
	if (of_is_inter(f, obvious_mask)) obvious = TRUE;
	flags_init(obvious_mask, OF_SIZE, OF_OBVIOUS_MASK, FLAG_END);

	/* XXX Eddie should these next NOT call object_check_for_ident due to worries about repairing? */


	/* XXX Eddie this is a small hack, but jewelry with anything noticeable really is obvious */
	/* XXX Eddie learn =soulkeeping vs =bodykeeping when notice sustain_str */
	if (object_is_jewelry(o_ptr))
	{
		/* Learn the flavor of jewelry with obvious flags */
		if (EASY_LEARN && obvious)
			object_flavor_aware(o_ptr);

		/* Learn all flags on any aware non-artifact jewelry */
		if (object_flavor_is_aware(o_ptr) && !artifact_p(o_ptr))
			object_know_all_flags(o_ptr);
	}

	object_check_for_ident(o_ptr);

	if (!obvious) return;

	/* Messages */
	for (s_ptr = slay_table; s_ptr->slay_flag; s_ptr++)
	{
		if (of_has(f, s_ptr->slay_flag) && s_ptr->brand)
		{
			char o_name[40];
			object_desc(o_name, sizeof(o_name), o_ptr, ODESC_BASE);
			msg_format("Your %s %s!", o_name, s_ptr->active_verb);
		}
	}

	/* XXX Eddie need to add stealth here, also need to assert/double-check everything is covered */
	if (of_has(f, OF_STR))
		msg_format("You feel %s!", o_ptr->pval > 0 ? "stronger" : "weaker");
	if (of_has(f, OF_INT))
		msg_format("You feel %s!", o_ptr->pval > 0 ? "smarter" : "more stupid");
	if (of_has(f, OF_WIS))
		msg_format("You feel %s!", o_ptr->pval > 0 ? "wiser" : "more naive");
	if (of_has(f, OF_DEX))
		msg_format("You feel %s!", o_ptr->pval > 0 ? "more dextrous" : "clumsier");
	if (of_has(f, OF_CON))
		msg_format("You feel %s!", o_ptr->pval > 0 ? "healthier" : "sicklier");
	if (of_has(f, OF_CHR))
		msg_format("You feel %s!", o_ptr->pval > 0 ? "cuter" : "uglier");
	if (of_has(f, OF_SPEED))
		msg_format("You feel strangely %s.", o_ptr->pval > 0 ? "quick" : "sluggish");
	if (flags_test(f, OF_SIZE, OF_BLOWS, OF_SHOTS, FLAG_END))
		msg_format("Your hands %s", o_ptr->pval > 0 ? "tingle!" : "ache.");
	if (of_has(f, OF_INFRA))
		msg_format("Your eyes tingle.");
	if (of_has(f, OF_LIGHT))
		msg_print("It glows!");
	if (of_has(f, OF_TELEPATHY))
		msg_print("Your mind feels strangely sharper!");

	/* WARNING -- masking f by obvious mask -- this should be at the end of this function */
	flags_mask(f, OF_SIZE, OF_OBVIOUS_MASK, FLAG_END);

	/* learn the ego on any obvious brand or slay */
	if (EASY_LEARN && ego_item_p(o_ptr) && obvious &&
	    flags_test(f, OF_SIZE, OF_ALL_SLAY_MASK, FLAG_END))
		object_notice_ego(o_ptr);

	/* Remember the flags */
	object_notice_sensing(o_ptr);

	/* XXX Eddie should we check_for_ident here? */
}
Exemplo n.º 19
0
/**
 * Apply an affix to an ego-item, checking minima as we go.
 *
 * \param o_ptr is the object we're modifying
 * \param level is the generation level
 * \param affix is the affix we're applying
 */
void ego_apply_magic(object_type *o_ptr, int level, int affix)
{
	int i, j, flag, pval, amt;
	bitflag flags[OF_SIZE], f2[OF_SIZE];
	ego_item_type *ego;

	ego = &e_info[affix];

	/* Random powers */
	for (i = 0; i < ego->num_randlines; i++)
		for (j = 0; j < ego->num_randflags[i]; j++)
			of_on(o_ptr->flags,	get_new_attr(o_ptr->flags, ego->randmask[i]));

	/* Apply extra combat bonuses */
	amt = randcalc(ego->to_h, level, RANDOMISE);
	o_ptr->to_h += amt;
	if (ego->min_to_h != NO_MINIMUM) {
		if (amt < ego->min_to_h)
			o_ptr->to_h += ego->min_to_h - amt;
		if (o_ptr->to_h < ego->min_to_h)
			o_ptr->to_h = ego->min_to_h;
	}

	amt = randcalc(ego->to_d, level, RANDOMISE);
	o_ptr->to_d += amt;
	if (ego->min_to_d != NO_MINIMUM) {
		if (amt < ego->min_to_d)
			o_ptr->to_d += ego->min_to_d - amt;
		if (o_ptr->to_d < ego->min_to_d)
			o_ptr->to_d = ego->min_to_d;
	}

	amt = randcalc(ego->to_a, level, RANDOMISE);
	o_ptr->to_a += amt;
	if (ego->min_to_a != NO_MINIMUM) {
		if (amt < ego->min_to_a)
			o_ptr->to_a += ego->min_to_a - amt;
		if (o_ptr->to_a < ego->min_to_a)
			o_ptr->to_a = ego->min_to_a;
	}

	/* Apply pvals */
	of_copy(f2, ego->flags);
	for (i = 0; i < ego->num_pvals; i++) {
		of_copy(flags, ego->pval_flags[i]);
		pval = randcalc(ego->pval[i], level, RANDOMISE);
		if (ego->min_pval[i] != NO_MINIMUM && pval < ego->min_pval[i])
			pval = ego->min_pval[i];
		for (flag = of_next(flags, FLAG_START); flag != FLAG_END;
				flag = of_next(flags, flag + 1))
			/* Prevent phantom flags, and check minima after adding */
			if (pval) {
				object_add_pval(o_ptr, pval, flag);
				if (ego->min_pval[i] != NO_MINIMUM && of_has(o_ptr->flags,
						flag))
					if (o_ptr->pval[which_pval(o_ptr, flag)] < ego->min_pval[i])
						object_add_pval(o_ptr, ego->min_pval[i] -
							o_ptr->pval[which_pval(o_ptr, flag)], flag);
			} else
				of_off(f2, flag);
	}

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

	/* Adjust AC, weight, dice and sides */
	if (o_ptr->ac && ego->ac_mod)
		o_ptr->ac = ((100 + ego->ac_mod) * o_ptr->ac) / 100;

	o_ptr->weight = ((100 + ego->wgt_mod) * o_ptr->weight) / 100;

	o_ptr->dd += ego->dd;
	if (o_ptr->dd < 1)
		o_ptr->dd = 1;

	o_ptr->ds += ego->ds;
	if (o_ptr->ds < 1)
		o_ptr->ds = 1;

	/* Tidy up and de-duplicate flags, and set the correct prefix/suffix */
	check_flags(o_ptr);
	obj_affix_names(o_ptr);

	return;
}
Exemplo n.º 20
0
/**
 * 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);
}
Exemplo n.º 21
0
/**
 * Complete object creation by applying magic to it.
 *
 * Magic includes rolling for random bonuses, applying flags to ego-items,
 * charging charged items, fuelling lights, and trapping chests.
 *
 * 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.  See the function itself for the specifics of the
 * calculations involved.
 */
void apply_magic(object_type *o_ptr, int lev, bool allow_artifacts, bool good, bool great)
{
	int power = 0;
	/*u32b xtra = 0;*/
	/*bool new = FALSE;*/

	/* Chance of being `good` and `great` */
	int good_chance = (lev+2) * 3;
	int great_chance = MIN(lev/4 + lev, 50);


	/* Limit depth */
	if (lev > MAX_DEPTH - 1) lev = MAX_DEPTH - 1;

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

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

	/* Roll for "cursed" */
	else if (randint0(100) < good_chance)
	{
		/* Assume "cursed" */
		power = -1;

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


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

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

		/* Get four rolls if forced great */
		if (great) rolls = 4;

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


	/* Apply magic */
	switch (o_ptr->tval)
	{
		case TV_DIGGING:
		case TV_HAFTED:
		case TV_POLEARM:
		case TV_SWORD:
		case TV_BOW:
		case TV_SHOT:
		case TV_ARROW:
		case TV_BOLT:
		{
			if (power == 2 || power == -2)
			{
				int ego_power;

				ego_power = make_ego_item(o_ptr, lev, (bool)(power > 0));

				if (ego_power) power = ego_power;
			}

			if (power) a_m_aux_1(o_ptr, lev, power);

			break;
		}

		case TV_DRAG_ARMOR:
		case TV_HARD_ARMOR:
		case TV_SOFT_ARMOR:
		case TV_SHIELD:
		case TV_HELM:
		case TV_CROWN:
		case TV_CLOAK:
		case TV_GLOVES:
		case TV_BOOTS:
		{
			if (power == 2 || power == -2)
			{
				int ego_power;

				ego_power = make_ego_item(o_ptr, lev, (bool)(power > 0));

				if (ego_power) power = ego_power;
			}

			if (power) a_m_aux_2(o_ptr, lev, power);

			break;
		}

		case TV_RING:
		case TV_AMULET:
		{
			if (!power && (randint0(100) < 50)) power = -1;
			a_m_aux_3(o_ptr, lev, power);
			break;
		}

		case TV_LIGHT:
		{
			if (power == 2 || power == -2)
				make_ego_item(o_ptr, lev, (bool)(power > 0));

			/* Fuel it */
			a_m_aux_4(o_ptr, lev, power);
			break;
		}

		default:
		{
			a_m_aux_4(o_ptr, lev, power);
			break;
		}
	}


	/* Hack -- analyze ego-items */
	if (o_ptr->name2)
	{
		ego_item_type *e_ptr = &e_info[o_ptr->name2];
		bitflag flags[OF_SIZE];

		object_flags(o_ptr, flags);

		/* Extra powers */
		if (e_ptr->xtra == OBJECT_XTRA_TYPE_SUSTAIN)
			of_on(o_ptr->flags, get_new_attr(flags, ego_sustains,
											N_ELEMENTS(ego_sustains)));
		else if (e_ptr->xtra == OBJECT_XTRA_TYPE_RESIST)
			of_on(o_ptr->flags, get_new_attr(flags, ego_resists,
											N_ELEMENTS(ego_resists)));
		else if (e_ptr->xtra == OBJECT_XTRA_TYPE_POWER)
			of_on(o_ptr->flags, get_new_attr(flags, ego_powers,
											N_ELEMENTS(ego_powers)));

		/* Hack -- acquire "cursed" flags */
		if (cursed_p(e_ptr))
		{
			bitflag curse_flags[OF_SIZE];

			of_copy(curse_flags, e_ptr->flags);
			flags_mask(curse_flags, OF_SIZE, OF_CURSE_MASK, FLAG_END);
			of_union(o_ptr->flags, curse_flags);
		}

		/* Hack -- apply extra penalties if needed */
		if (cursed_p(o_ptr))
		{
			/* Apply extra ego bonuses */
			o_ptr->to_h -= randcalc(e_ptr->to_h, lev, RANDOMISE);
			o_ptr->to_d -= randcalc(e_ptr->to_d, lev, RANDOMISE);
			o_ptr->to_a -= randcalc(e_ptr->to_a, lev, RANDOMISE);

			/* Apply ego pval */
			o_ptr->pval -= randcalc(e_ptr->pval, lev, RANDOMISE);

			/* Apply minimums */
			if (o_ptr->to_h > -1 * e_ptr->min_to_h) o_ptr->to_h = -1 * e_ptr->min_to_h;
			if (o_ptr->to_d > -1 * e_ptr->min_to_d) o_ptr->to_d = -1 * e_ptr->min_to_d;
			if (o_ptr->to_a > -1 * e_ptr->min_to_a) o_ptr->to_a = -1 * e_ptr->min_to_a;
			if (o_ptr->pval > -1 * e_ptr->min_pval) o_ptr->pval = -1 * e_ptr->min_pval;
		}

		/* Hack -- apply extra bonuses if needed */
		else
		{
			/* Apply extra ego bonuses */
			o_ptr->to_h += randcalc(e_ptr->to_h, lev, RANDOMISE);
			o_ptr->to_d += randcalc(e_ptr->to_d, lev, RANDOMISE);
			o_ptr->to_a += randcalc(e_ptr->to_a, lev, RANDOMISE);

			/* Apply ego pval */
			o_ptr->pval += randcalc(e_ptr->pval, lev, RANDOMISE);

			/* Apply minimums */
			if (o_ptr->to_h < e_ptr->min_to_h) o_ptr->to_h = e_ptr->min_to_h;
			if (o_ptr->to_d < e_ptr->min_to_d) o_ptr->to_d = e_ptr->min_to_d;
			if (o_ptr->to_a < e_ptr->min_to_a) o_ptr->to_a = e_ptr->min_to_a;
			if (o_ptr->pval < e_ptr->min_pval) o_ptr->pval = e_ptr->min_pval;
		}

		/* Hack -- apply rating bonus */
		rating += e_ptr->rating;

		/* Cheat -- describe the item */
		if (OPT(cheat_peek)) object_mention(o_ptr);

		/* Done */
		return;
	}


	/* Examine real objects */
	if (o_ptr->k_idx)
	{
		object_kind *k_ptr = &k_info[o_ptr->k_idx];

		/* Hack -- acquire "cursed" flag */
		if (cursed_p(k_ptr))
		{
			bitflag curse_flags[OF_SIZE];

			of_copy(curse_flags, k_ptr->flags);
			flags_mask(curse_flags, OF_SIZE, OF_CURSE_MASK, FLAG_END);
			of_union(o_ptr->flags, curse_flags);
		}
	}
}
Exemplo n.º 22
0
/*
 * Calculate the players current "state", taking into account
 * not only race/class intrinsics, but also objects being worn
 * and temporary spell effects.
 *
 * See also calc_mana() and calc_hitpoints().
 *
 * Take note of the new "speed code", in particular, a very strong
 * player will start slowing down as soon as he reaches 150 pounds,
 * but not until he reaches 450 pounds will he be half as fast as
 * a normal kobold.  This both hurts and helps the player, hurts
 * because in the old days a player could just avoid 300 pounds,
 * and helps because now carrying 300 pounds is not very painful.
 *
 * The "weapon" and "bow" do *not* add to the bonuses to hit or to
 * damage, since that would affect non-combat things.  These values
 * are actually added in later, at the appropriate place.
 *
 * If id_only is true, calc_bonuses() will only use the known
 * information of objects; thus it returns what the player _knows_
 * the character state to be.
 */
void calc_bonuses(object_type inventory[], player_state *state, bool id_only)
{
	int i, j, hold;

	int extra_blows = 0;
	int extra_shots = 0;
	int extra_might = 0;

	object_type *o_ptr;

	bitflag f[OF_SIZE];
	bitflag collect_f[OF_SIZE];


	/*** Reset ***/

	memset(state, 0, sizeof *state);

	/* Set various defaults */
	state->speed = 110;
	state->num_blow = 1;


	/*** Extract race/class info ***/

	/* Base infravision (purely racial) */
	state->see_infra = rp_ptr->infra;

	/* Base skills */
	for (i = 0; i < SKILL_MAX; i++)
		state->skills[i] = rp_ptr->r_skills[i] + cp_ptr->c_skills[i];


	/*** Analyze player ***/

	/* Extract the player flags */
	player_flags(collect_f);


	/*** Analyze equipment ***/

	/* Scan the equipment */
	for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
	{
		o_ptr = &inventory[i];

		/* Skip non-objects */
		if (!o_ptr->k_idx) continue;

		/* Extract the item flags */
		if (id_only)
			object_flags_known(o_ptr, f);
		else
			object_flags(o_ptr, f);

		of_union(collect_f, f);

		/* Affect stats */
		if (of_has(f, OF_STR)) state->stat_add[A_STR] += o_ptr->pval;
		if (of_has(f, OF_INT)) state->stat_add[A_INT] += o_ptr->pval;
		if (of_has(f, OF_WIS)) state->stat_add[A_WIS] += o_ptr->pval;
		if (of_has(f, OF_DEX)) state->stat_add[A_DEX] += o_ptr->pval;
		if (of_has(f, OF_CON)) state->stat_add[A_CON] += o_ptr->pval;
		if (of_has(f, OF_CHR)) state->stat_add[A_CHR] += o_ptr->pval;

		/* Affect stealth */
		if (of_has(f, OF_STEALTH)) state->skills[SKILL_STEALTH] += o_ptr->pval;

		/* Affect searching ability (factor of five) */
		if (of_has(f, OF_SEARCH)) state->skills[SKILL_SEARCH] += (o_ptr->pval * 5);

		/* Affect searching frequency (factor of five) */
		if (of_has(f, OF_SEARCH)) state->skills[SKILL_SEARCH_FREQUENCY] += (o_ptr->pval * 5);

		/* Affect infravision */
		if (of_has(f, OF_INFRA)) state->see_infra += o_ptr->pval;

		/* Affect digging (factor of 20) */
		if (of_has(f, OF_TUNNEL)) state->skills[SKILL_DIGGING] += (o_ptr->pval * 20);

		/* Affect speed */
		if (of_has(f, OF_SPEED)) state->speed += o_ptr->pval;

		/* Affect blows */
		if (of_has(f, OF_BLOWS)) extra_blows += o_ptr->pval;

		/* Affect shots */
		if (of_has(f, OF_SHOTS)) extra_shots += o_ptr->pval;

		/* Affect Might */
		if (of_has(f, OF_MIGHT)) extra_might += o_ptr->pval;

		/* Modify the base armor class */
		state->ac += o_ptr->ac;

		/* The base armor class is always known */
		state->dis_ac += o_ptr->ac;

		/* Apply the bonuses to armor class */
		if (!id_only || object_is_known(o_ptr))
			state->to_a += o_ptr->to_a;

		/* Apply the mental bonuses to armor class, if known */
		if (object_defence_plusses_are_visible(o_ptr))
			state->dis_to_a += o_ptr->to_a;

		/* Hack -- do not apply "weapon" bonuses */
		if (i == INVEN_WIELD) continue;

		/* Hack -- do not apply "bow" bonuses */
		if (i == INVEN_BOW) continue;

		/* Apply the bonuses to hit/damage */
		if (!id_only || object_is_known(o_ptr))
		{
			state->to_h += o_ptr->to_h;
			state->to_d += o_ptr->to_d;
		}

		/* Apply the mental bonuses tp hit/damage, if known */
		if (object_attack_plusses_are_visible(o_ptr))
		{
			state->dis_to_h += o_ptr->to_h;
			state->dis_to_d += o_ptr->to_d;
		}
	}


	/*** Update all flags ***/

	/* Good flags */
	if (of_has(collect_f, OF_SLOW_DIGEST)) state->slow_digest = TRUE;
	if (of_has(collect_f, OF_FEATHER)) state->ffall = TRUE;
	if (of_has(collect_f, OF_REGEN)) state->regenerate = TRUE;
	if (of_has(collect_f, OF_TELEPATHY)) state->telepathy = TRUE;
	if (of_has(collect_f, OF_SEE_INVIS)) state->see_inv = TRUE;
	if (of_has(collect_f, OF_FREE_ACT)) state->free_act = TRUE;
	if (of_has(collect_f, OF_HOLD_LIFE)) state->hold_life = TRUE;

	/* Weird flags */
	if (of_has(collect_f, OF_BLESSED)) state->bless_blade = TRUE;

	/* Bad flags */
	if (of_has(collect_f, OF_IMPACT)) state->impact = TRUE;
	if (of_has(collect_f, OF_AGGRAVATE)) state->aggravate = TRUE;
	if (of_has(collect_f, OF_TELEPORT)) state->teleport = TRUE;
	if (of_has(collect_f, OF_DRAIN_EXP)) state->exp_drain = TRUE;
	if (of_has(collect_f, OF_IMPAIR_HP)) state->impair_hp = TRUE;
	if (of_has(collect_f, OF_IMPAIR_MANA)) state->impair_mana = TRUE;
	if (of_has(collect_f, OF_AFRAID)) state->afraid = TRUE;

	/* Vulnerability flags */
	if (of_has(collect_f, OF_VULN_FIRE)) state->vuln_fire = TRUE;
	if (of_has(collect_f, OF_VULN_ACID)) state->vuln_acid = TRUE;
	if (of_has(collect_f, OF_VULN_COLD)) state->vuln_cold = TRUE;
	if (of_has(collect_f, OF_VULN_ELEC)) state->vuln_elec = TRUE;

	/* Immunity flags */
	if (of_has(collect_f, OF_IM_FIRE)) state->immune_fire = TRUE;
	if (of_has(collect_f, OF_IM_ACID)) state->immune_acid = TRUE;
	if (of_has(collect_f, OF_IM_COLD)) state->immune_cold = TRUE;
	if (of_has(collect_f, OF_IM_ELEC)) state->immune_elec = TRUE;

	/* Resistance flags */
	if (of_has(collect_f, OF_RES_ACID)) state->resist_acid = TRUE;
	if (of_has(collect_f, OF_RES_ELEC)) state->resist_elec = TRUE;
	if (of_has(collect_f, OF_RES_FIRE)) state->resist_fire = TRUE;
	if (of_has(collect_f, OF_RES_COLD)) state->resist_cold = TRUE;
	if (of_has(collect_f, OF_RES_POIS)) state->resist_pois = TRUE;
	if (of_has(collect_f, OF_RES_FEAR)) state->resist_fear = TRUE;
	if (of_has(collect_f, OF_RES_LIGHT)) state->resist_light = TRUE;
	if (of_has(collect_f, OF_RES_DARK)) state->resist_dark = TRUE;
	if (of_has(collect_f, OF_RES_BLIND)) state->resist_blind = TRUE;
	if (of_has(collect_f, OF_RES_CONFU)) state->resist_confu = TRUE;
	if (of_has(collect_f, OF_RES_SOUND)) state->resist_sound = TRUE;
	if (of_has(collect_f, OF_RES_SHARD)) state->resist_shard = TRUE;
	if (of_has(collect_f, OF_RES_NEXUS)) state->resist_nexus = TRUE;
	if (of_has(collect_f, OF_RES_NETHR)) state->resist_nethr = TRUE;
	if (of_has(collect_f, OF_RES_CHAOS)) state->resist_chaos = TRUE;
	if (of_has(collect_f, OF_RES_DISEN)) state->resist_disen = TRUE;

	/* Sustain flags */
	if (of_has(collect_f, OF_SUST_STR)) state->sustain_str = TRUE;
	if (of_has(collect_f, OF_SUST_INT)) state->sustain_int = TRUE;
	if (of_has(collect_f, OF_SUST_WIS)) state->sustain_wis = TRUE;
	if (of_has(collect_f, OF_SUST_DEX)) state->sustain_dex = TRUE;
	if (of_has(collect_f, OF_SUST_CON)) state->sustain_con = TRUE;
	if (of_has(collect_f, OF_SUST_CHR)) state->sustain_chr = TRUE;



	/*** Handle stats ***/

	/* Calculate stats */
	for (i = 0; i < A_MAX; i++)
	{
		int add, top, use, ind;

		/* Extract modifier */
		add = state->stat_add[i];

		/* Maximize mode */
		if (OPT(adult_maximize))
		{
			/* Modify the stats for race/class */
			add += (rp_ptr->r_adj[i] + cp_ptr->c_adj[i]);
		}

		/* Extract the new "stat_top" value for the stat */
		top = modify_stat_value(p_ptr->stat_max[i], add);

		/* Save the new value */
		state->stat_top[i] = top;

		/* Extract the new "stat_use" value for the stat */
		use = modify_stat_value(p_ptr->stat_cur[i], add);

		/* Save the new value */
		state->stat_use[i] = use;

		/* Values: n/a */
		if (use <= 3) ind = 0;

		/* Values: 3, 4, ..., 18 */
		else if (use <= 18) ind = (use - 3);

		/* Ranges: 18/00-18/09, ..., 18/210-18/219 */
		else if (use <= 18+219) ind = (15 + (use - 18) / 10);

		/* Range: 18/220+ */
		else ind = (37);

		assert((0 <= ind) && (ind < STAT_RANGE));

		/* Save the new index */
		state->stat_ind[i] = ind;
	}


	/*** Temporary flags ***/

	/* Apply temporary "stun" */
	if (p_ptr->timed[TMD_STUN] > 50)
	{
		state->to_h -= 20;
		state->dis_to_h -= 20;
		state->to_d -= 20;
		state->dis_to_d -= 20;
		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE]
			* 8 / 10;
	}
	else if (p_ptr->timed[TMD_STUN])
	{
		state->to_h -= 5;
		state->dis_to_h -= 5;
		state->to_d -= 5;
		state->dis_to_d -= 5;
		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE]
			* 9 / 10;
	}

	/* Invulnerability */
	if (p_ptr->timed[TMD_INVULN])
	{
		state->to_a += 100;
		state->dis_to_a += 100;
	}

	/* Temporary blessing */
	if (p_ptr->timed[TMD_BLESSED])
	{
		state->to_a += 5;
		state->dis_to_a += 5;
		state->to_h += 10;
		state->dis_to_h += 10;
		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE]
			* 105 / 100;
	}

	/* Temporary shield */
	if (p_ptr->timed[TMD_SHIELD])
	{
		state->to_a += 50;
		state->dis_to_a += 50;
	}

	/* Temporary stoneskin */
	if (p_ptr->timed[TMD_STONESKIN])
	{
		state->to_a += 40;
		state->dis_to_a += 40;
		state->speed -= 5;
	}

	/* Temporary "Hero" */
	if (p_ptr->timed[TMD_HERO])
	{
		state->to_h += 12;
		state->dis_to_h += 12;
		state->resist_fear = TRUE;
		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE]
			* 105 / 100;
	}

	/* Temporary "Berserk" */
	if (p_ptr->timed[TMD_SHERO])
	{
		state->to_h += 24;
		state->dis_to_h += 24;
		state->to_a -= 10;
		state->dis_to_a -= 10;
		state->resist_fear = TRUE;
		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE]
			* 9 / 10;
	}

	/* Temporary "fast" */
	if (p_ptr->timed[TMD_FAST] || p_ptr->timed[TMD_SPRINT])
		state->speed += 10;

	/* Temporary "slow" */
	if (p_ptr->timed[TMD_SLOW])
		state->speed -= 10;

	/* Temporary see invisible */
	if (p_ptr->timed[TMD_SINVIS])
		state->see_inv = TRUE;

	/* Temporary infravision boost */
	if (p_ptr->timed[TMD_SINFRA])
		state->see_infra += 5;

	/* Temporary telepathy */
	if (p_ptr->timed[TMD_TELEPATHY])
		state->telepathy = TRUE;

	/* Temporary resist confusion */
	if (p_ptr->timed[TMD_OPP_CONF])
		state->resist_confu = TRUE;

	/* Fear */
	if (p_ptr->timed[TMD_AFRAID] || p_ptr->timed[TMD_TERROR])
		state->afraid = TRUE;

	if (p_ptr->timed[TMD_TERROR])
		state->speed += 5;

	/* Fear can come from item flags too */
	if (state->afraid)
	{
		state->to_h -= 20;
		state->dis_to_h -= 20;
		state->to_a += 8;
		state->dis_to_a += 8;
		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE]
			* 95 / 100;
	}

	/* Confusion */
	if (p_ptr->timed[TMD_CONFUSED])
		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE]
			* 75 / 100;

	/* Amnesia */
	if (p_ptr->timed[TMD_AMNESIA])
		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE]
			* 8 / 10;

	/* Poison */
	if (p_ptr->timed[TMD_POISONED])
		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE]
			* 95 / 100;

	/* Hallucination */
	if (p_ptr->timed[TMD_IMAGE])
		state->skills[SKILL_DEVICE] = state->skills[SKILL_DEVICE]
			* 8 / 10;

	/*** Analyze weight ***/

	/* Extract the current weight (in tenth pounds) */
	j = p_ptr->total_weight;

	/* Extract the "weight limit" (in tenth pounds) */
	i = weight_limit(state);

	/* Apply "encumbrance" from weight */
	if (j > i / 2) state->speed -= ((j - (i / 2)) / (i / 10));

	/* Bloating slows the player down (a little) */
	if (p_ptr->food >= PY_FOOD_MAX) state->speed -= 10;

	/* Searching slows the player down */
	if (p_ptr->searching) state->speed -= 10;

	/* Sanity check on extreme speeds */
	if (state->speed < 0) state->speed = 0;
	if (state->speed > 199) state->speed = 199;

	/*** Apply modifier bonuses ***/

	/* Actual Modifier Bonuses (Un-inflate stat bonuses) */
	state->to_a += ((int)(adj_dex_ta[state->stat_ind[A_DEX]]) - 128);
	state->to_d += ((int)(adj_str_td[state->stat_ind[A_STR]]) - 128);
	state->to_h += ((int)(adj_dex_th[state->stat_ind[A_DEX]]) - 128);
	state->to_h += ((int)(adj_str_th[state->stat_ind[A_STR]]) - 128);

	/* Displayed Modifier Bonuses (Un-inflate stat bonuses) */
	state->dis_to_a += ((int)(adj_dex_ta[state->stat_ind[A_DEX]]) - 128);
	state->dis_to_d += ((int)(adj_str_td[state->stat_ind[A_STR]]) - 128);
	state->dis_to_h += ((int)(adj_dex_th[state->stat_ind[A_DEX]]) - 128);
	state->dis_to_h += ((int)(adj_str_th[state->stat_ind[A_STR]]) - 128);


	/*** Modify skills ***/

	/* Affect Skill -- stealth (bonus one) */
	state->skills[SKILL_STEALTH] += 1;

	/* Affect Skill -- disarming (DEX and INT) */
	state->skills[SKILL_DISARM] += adj_dex_dis[state->stat_ind[A_DEX]];
	state->skills[SKILL_DISARM] += adj_int_dis[state->stat_ind[A_INT]];

	/* Affect Skill -- magic devices (INT) */
	state->skills[SKILL_DEVICE] += adj_int_dev[state->stat_ind[A_INT]];

	/* Affect Skill -- saving throw (WIS) */
	state->skills[SKILL_SAVE] += adj_wis_sav[state->stat_ind[A_WIS]];

	/* Affect Skill -- digging (STR) */
	state->skills[SKILL_DIGGING] += adj_str_dig[state->stat_ind[A_STR]];

	/* Affect Skills (Level, by Class) */
	for (i = 0; i < SKILL_MAX; i++)
		state->skills[i] += (cp_ptr->x_skills[i] * p_ptr->lev / 10);

	/* Limit Skill -- digging from 1 up */
	if (state->skills[SKILL_DIGGING] < 1) state->skills[SKILL_DIGGING] = 1;

	/* Limit Skill -- stealth from 0 to 30 */
	if (state->skills[SKILL_STEALTH] > 30) state->skills[SKILL_STEALTH] = 30;
	if (state->skills[SKILL_STEALTH] < 0) state->skills[SKILL_STEALTH] = 0;

	/* Apply Skill -- Extract noise from stealth */
	state->noise = (1L << (30 - state->skills[SKILL_STEALTH]));

	/* Obtain the "hold" value */
	hold = adj_str_hold[state->stat_ind[A_STR]];


	/*** Analyze current bow ***/

	/* Examine the "current bow" */
	o_ptr = &inventory[INVEN_BOW];

	/* Assume not heavy */
	state->heavy_shoot = FALSE;

	/* It is hard to carholdry a heavy bow */
	if (hold < o_ptr->weight / 10)
	{
		/* Hard to wield a heavy bow */
		state->to_h += 2 * (hold - o_ptr->weight / 10);
		state->dis_to_h += 2 * (hold - o_ptr->weight / 10);

		/* Heavy Bow */
		state->heavy_shoot = TRUE;
	}

	/* Analyze launcher */
	if (o_ptr->k_idx)
	{
		/* Get to shoot */
		state->num_fire = 1;

		/* Analyze the launcher */
		switch (o_ptr->sval)
		{
			/* Sling and ammo */
			case SV_SLING:
			{
				state->ammo_tval = TV_SHOT;
				state->ammo_mult = 2;
				break;
			}

			/* Short Bow and Arrow */
			case SV_SHORT_BOW:
			{
				state->ammo_tval = TV_ARROW;
				state->ammo_mult = 2;
				break;
			}

			/* Long Bow and Arrow */
			case SV_LONG_BOW:
			{
				state->ammo_tval = TV_ARROW;
				state->ammo_mult = 3;
				break;
			}

			/* Light Crossbow and Bolt */
			case SV_LIGHT_XBOW:
			{
				state->ammo_tval = TV_BOLT;
				state->ammo_mult = 3;
				break;
			}

			/* Heavy Crossbow and Bolt */
			case SV_HEAVY_XBOW:
			{
				state->ammo_tval = TV_BOLT;
				state->ammo_mult = 4;
				break;
			}
		}

		/* Apply special flags */
		if (o_ptr->k_idx && !state->heavy_shoot)
		{
			/* Extra shots */
			state->num_fire += extra_shots;

			/* Extra might */
			state->ammo_mult += extra_might;

			/* Hack -- Rangers love Bows */
			if (player_has(PF_EXTRA_SHOT) &&
			    (state->ammo_tval == TV_ARROW))
			{
				/* Extra shot at level 20 */
				if (p_ptr->lev >= 20) state->num_fire++;

				/* Extra shot at level 40 */
				if (p_ptr->lev >= 40) state->num_fire++;
			}
		}

		/* Require at least one shot */
		if (state->num_fire < 1) state->num_fire = 1;
	}


	/*** Analyze weapon ***/

	/* Examine the "current weapon" */
	o_ptr = &inventory[INVEN_WIELD];

	/* Assume not heavy */
	state->heavy_wield = FALSE;

	/* It is hard to hold a heavy weapon */
	if (hold < o_ptr->weight / 10)
	{
		/* Hard to wield a heavy weapon */
		state->to_h += 2 * (hold - o_ptr->weight / 10);
		state->dis_to_h += 2 * (hold - o_ptr->weight / 10);

		/* Heavy weapon */
		state->heavy_wield = TRUE;
	}

	/* Non-object means barehanded attacks */
	if (!o_ptr->k_idx)
		assert(o_ptr->weight == 0);

	/* Normal weapons */
	if (!state->heavy_wield)
	{
		/* Calculate number of blows */
		state->num_blow = calc_blows(o_ptr, state) + extra_blows;

		/* Boost digging skill by weapon weight */
		state->skills[SKILL_DIGGING] += (o_ptr->weight / 10);
	}


	/* Assume okay */
	state->icky_wield = FALSE;

	/* Priest weapon penalty for non-blessed edged weapons */
	if (player_has(PF_BLESS_WEAPON) && (!state->bless_blade) &&
	    ((o_ptr->tval == TV_SWORD) || (o_ptr->tval == TV_POLEARM)))
	{
		/* Reduce the real bonuses */
		state->to_h -= 2;
		state->to_d -= 2;

		/* Reduce the mental bonuses */
		state->dis_to_h -= 2;
		state->dis_to_d -= 2;

		/* Icky weapon */
		state->icky_wield = TRUE;
	}

	return;
}
Exemplo n.º 23
0
/**
 * Allow one item to "absorb" another, assuming they are similar.
 *
 * The blending of the "note" field assumes that either (1) one has an
 * inscription and the other does not, or (2) neither has an inscription.
 * In both these cases, we can simply use the existing note, unless the
 * blending object has a note, in which case we use that note.
 *
* These assumptions are enforced by the "object_similar()" code.
 */
static void object_absorb_merge(struct object *obj1, const struct object *obj2)
{
	int total;

	/* First object gains any extra knowledge from second */
	if (obj1->known && obj2->known) {
		of_union(obj1->known->flags, obj2->known->flags);
		if (obj2->known->ego)
			obj1->known->ego = (struct ego_item *)1;
		obj1->known->pval |= obj2->known->pval;
		obj1->known->dd |= obj2->known->dd;
		obj1->known->ds |= obj2->known->ds;
		obj1->known->ac |= obj2->known->ac;
		obj1->known->to_a |= obj2->known->to_a;
		obj1->known->to_h |= obj2->known->to_h;
		obj1->known->to_d |= obj2->known->to_d;
		if (obj2->known->effect)
			obj1->known->effect = (struct effect *)1;
	}

	/* Merge inscriptions */
	if (obj2->note)
		obj1->note = obj2->note;

	/* Combine timeouts for rod stacking */
	if (tval_can_have_timeout(obj1))
		obj1->timeout += obj2->timeout;

	/* Combine pvals for wands and staves */
	if (tval_can_have_charges(obj1) || tval_is_money(obj1)) {
		total = obj1->pval + obj2->pval;
		obj1->pval = total >= MAX_PVAL ? MAX_PVAL : total;
	}

	/* Combine origin data as best we can */
	if (obj1->origin != obj2->origin ||
		obj1->origin_depth != obj2->origin_depth ||
		obj1->origin_xtra != obj2->origin_xtra) {
		int act = 2;

		if (obj1->origin_xtra && obj2->origin_xtra) {
			struct monster_race *race1 = &r_info[obj1->origin_xtra];
			struct monster_race *race2 = &r_info[obj2->origin_xtra];

			bool r1_uniq = rf_has(race1->flags, RF_UNIQUE) ? true : false;
			bool r2_uniq = rf_has(race2->flags, RF_UNIQUE) ? true : false;

			if (r1_uniq && !r2_uniq) act = 0;
			else if (r2_uniq && !r1_uniq) act = 1;
			else act = 2;
		}

		switch (act)
		{
				/* Overwrite with obj2 */
			case 1:
			{
				obj1->origin = obj2->origin;
				obj1->origin_depth = obj2->origin_depth;
				obj1->origin_xtra = obj2->origin_xtra;
			}

				/* Set as "mixed" */
			case 2:
			{
				obj1->origin = ORIGIN_MIXED;
			}
		}
	}
}