Beispiel #1
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 #2
0
/**
 * Describe an object's effect, if any.
 */
static bool describe_effect(textblock *tb, const struct object *obj,
		bool only_artifacts, bool subjective)
{
	char desc[200];
	struct effect *effect = NULL;
	bool aimed = false;
	int min_time, max_time, failure_chance;

	/* Sometimes we only print artifact activation info */
	if (only_artifacts && !obj->artifact)
		return false;

	if (obj_known_effect(obj, &effect, &aimed, &min_time, &max_time,
							 &failure_chance) == false)
		return false;

	/* Effect not known, mouth platitudes */
	if (!effect && object_effect(obj)) {
		if (aimed)
			textblock_append(tb, "It can be aimed.\n");
		else if (tval_is_edible(obj))
			textblock_append(tb, "It can be eaten.\n");
		else if (tval_is_potion(obj))
			textblock_append(tb, "It can be drunk.\n");
		else if (tval_is_scroll(obj))
			textblock_append(tb, "It can be read.\n");
		else textblock_append(tb, "It can be activated.\n");

		return true;
	}

	/* Activations get a special message */
	if (obj->activation && obj->activation->desc) {
		textblock_append(tb, "When activated, it ");
		textblock_append(tb, obj->activation->desc);
	} else {
		int random_choices = 0;

		/* Get descriptions for all the effects */
		effect = object_effect(obj);
		if (!effect_desc(effect)) return false;

		if (aimed)
			textblock_append(tb, "When aimed, it ");
		else if (tval_is_edible(obj))
			textblock_append(tb, "When eaten, it ");
		else if (tval_is_potion(obj))
			textblock_append(tb, "When quaffed, it ");
		else if (tval_is_scroll(obj))
			textblock_append(tb, "When read, it ");
		else
			textblock_append(tb, "When activated, it ");

		/* Print a colourised description */
		while (effect) {
			char *next_char = desc;
			int roll = 0;
			random_value value = { 0, 0, 0, 0 };
			char dice_string[20];
			int boost, level = obj->kind->level;

			/* Get the level */
			if (obj->artifact)
				level = obj->artifact->level;
			else if (obj->ego)
				level = obj->ego->level;

			/* Get the boost */
			boost = MAX(player->state.skills[SKILL_DEVICE] - level, 0);			

			if (effect->dice != NULL)
				roll = dice_roll(effect->dice, &value);

			/* Deal with special random effect */
			if (effect->index == EF_RANDOM)
				random_choices = roll + 1;

			/* Get the possible dice strings */
			if (value.dice && value.base)
				strnfmt(dice_string, sizeof(dice_string), "%d+%dd%d",
						value.base, value.dice, value.sides);
			else if (value.dice)
				strnfmt(dice_string, sizeof(dice_string), "%dd%d",
						value.dice, value.sides);
			else
				strnfmt(dice_string, sizeof(dice_string), "%d", value.base);

			/* Check all the possible types of description format */
			switch (base_descs[effect->index].efinfo_flag) {
				/* Healing sometimes has a minimum percentage */
			case EFINFO_HEAL: {
				char min_string[50];
				if (value.m_bonus)
					strnfmt(min_string, sizeof(min_string),
							" (or %d%%, whichever is greater)", value.m_bonus);
				else
					strnfmt(min_string, sizeof(min_string), "");
				strnfmt(desc, sizeof(desc), effect_desc(effect), dice_string,
						min_string);
				break;
			}

			/* Nourishment is just a flat amount */
			case EFINFO_CONST: {
				strnfmt(desc, sizeof(desc), effect_desc(effect), value.base/2);
				break;
			}
			case EFINFO_CURE: {
				strnfmt(desc, sizeof(desc), effect_desc(effect),
							timed_idx_to_desc(effect->params[0]));
				break;
			}
			case EFINFO_TIMED: {
				strnfmt(desc, sizeof(desc), effect_desc(effect),
							timed_idx_to_desc(effect->params[0]), dice_string);
				break;
			}
			case EFINFO_STAT: {
				strnfmt(desc, sizeof(desc), effect_desc(effect),
							mod_flags[effect->params[0]].name);
				break;
			}
			case EFINFO_SEEN: {
				strnfmt(desc, sizeof(desc), effect_desc(effect),
						gf_desc(effect->params[0]));
				break;
			}
			case EFINFO_SUMM: {
				strnfmt(desc, sizeof(desc), effect_desc(effect),
						summon_desc(effect->params[0]));
				break;
			}

			/* Only currently used for the player, but can handle monsters */
			case EFINFO_TELE: {
				if (effect->params[0])
					strnfmt(desc, sizeof(desc), effect_desc(effect),
							"a monster", value.base);
				else
					strnfmt(desc, sizeof(desc), effect_desc(effect), "you",
							value.base);
				break;
			}
			case EFINFO_QUAKE: {
				strnfmt(desc, sizeof(desc), effect_desc(effect),
						effect->params[1]);
				break;
			}
			case EFINFO_LIGHT: {
				strnfmt(desc, sizeof(desc), effect_desc(effect), dice_string,
						effect->params[1]);
				break;
			}

			/* Object generated balls are elemental */
			case EFINFO_BALL: {
				strnfmt(desc, sizeof(desc), effect_desc(effect),
						elements[effect->params[0]].name, effect->params[1],
						dice_string);
				if (boost)
					my_strcat(desc, format(", which your device skill increases by %d per cent", boost),
							  sizeof(desc));
				break;
			}

			/* Bolts that inflict status */
			case EFINFO_BOLT: {
				strnfmt(desc, sizeof(desc), effect_desc(effect),
						gf_desc(effect->params[0]));
				break;
			}
			/* Bolts and beams that damage */
			case EFINFO_BOLTD: {
				strnfmt(desc, sizeof(desc), effect_desc(effect),
						gf_desc(effect->params[0]), dice_string);
				if (boost)
					my_strcat(desc, format(", which your device skill increases by %d per cent", boost),
							  sizeof(desc));
				break;
			}
			case EFINFO_TOUCH: {
				strnfmt(desc, sizeof(desc), effect_desc(effect),
						gf_desc(effect->params[0]));
				break;
			}
			case EFINFO_NONE: {
				strnfmt(desc, sizeof(desc), effect_desc(effect));
				break;
			}
			default: {
				msg("Bad effect description passed to describe_effect(). Please report this bug.");
				return false;
			}
			}

			do {
				if (isdigit((unsigned char) *next_char))
					textblock_append_c(tb, COLOUR_L_GREEN, "%c", *next_char);
				else
					textblock_append(tb, "%c", *next_char);
			} while (*next_char++);

			/* Random choices need special treatment - note that this code
			 * assumes that RANDOM and the random choices will be the last
			 * effect in the object/activation description */
			if (random_choices >= 1) {
				if (effect->index == EF_RANDOM)
					;
				else if (random_choices > 2)
					textblock_append(tb, ", ");
				else if (random_choices == 2)
					textblock_append(tb, " or ");
				random_choices--;
			} else if (effect->next) {
				if (effect->next->next && (effect->next->index != EF_RANDOM))
					textblock_append(tb, ", ");
				else
					textblock_append(tb, " and ");
			}
			effect = effect->next;
		}
	}

	textblock_append(tb, ".\n");

	if (min_time || max_time) {
		/* Sometimes adjust for player speed */
		int multiplier = turn_energy(player->state.speed);
		if (!subjective) multiplier = 10;

		textblock_append(tb, "Takes ");

		/* Correct for player speed */
		min_time = (min_time * multiplier) / 10;
		max_time = (max_time * multiplier) / 10;

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

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

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

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

	if (failure_chance > 0) {
		textblock_append(tb, "Your chance of success is %d.%d%%\n", 
			(1000 - failure_chance) / 10, (1000 - failure_chance) % 10);
	}

	return true;
}
Beispiel #3
0
/*
 * Describe an object's effect, if any.
 */
static bool describe_effect(textblock * tb, const object_type * o_ptr,
							oinfo_detail_t mode)
{
	const object_kind *k_ptr = &k_info[o_ptr->k_idx];
	const char *desc;
	random_value timeout = { 0, 0, 0, 0 };
	bool full = mode & OINFO_FULL;
	bool subjective = mode & OINFO_SUBJ;
	bool terse = mode & OINFO_TERSE;

	int effect = 0, fail;

	if (wearable_p(o_ptr)) {
		/* Wearable + effect <=> activates */
		if ((o_ptr->ident & IDENT_WORN) || full) {
			effect = o_ptr->effect;
			timeout = o_ptr->time;
		} else if (object_effect(o_ptr)) {
			textblock_append(tb, "It can be activated.\n");
			return TRUE;
		}
	} else {
		/* Sometimes only print activation info */
		if (terse)
			return FALSE;

		if ((object_aware_p(o_ptr)
			 && kf_has(k_ptr->flags_kind, KF_EASY_KNOW))
			|| full) {
			effect = o_ptr->effect;
			timeout = o_ptr->time;
		} else if (object_effect(o_ptr)) {
			if (effect_aim(k_ptr->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.pspeed];
		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.pspeed != 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 #4
0
/**
 * Describe an object's effect, if any.
 */
static bool describe_effect(textblock *tb, const struct object *obj,
		bool only_artifacts, bool subjective)
{
	char desc[200];
	struct effect *e;

	int effect = 0;
	bool aimed = FALSE;
	int min_time, max_time, failure_chance;

	/* Sometimes we only print artifact activation info */
	if (only_artifacts && !obj->artifact)
		return FALSE;

	if (obj_known_effect(obj, &effect, &aimed, &min_time, &max_time, &failure_chance) == FALSE)
		return FALSE;

	/* We don't know much */
	if (effect == OBJ_KNOWN_PRESENT) {
		if (aimed)
			textblock_append(tb, "It can be aimed.\n");
		else if (tval_is_edible(obj))
			textblock_append(tb, "It can be eaten.\n");
		else if (tval_is_potion(obj))
			textblock_append(tb, "It can be drunk.\n");
		else if (tval_is_scroll(obj))
			textblock_append(tb, "It can be read.\n");
		else textblock_append(tb, "It can be activated.\n");

		return TRUE;
	}

	/* Obtain the description */
	e = obj->effect;
	if (!effect_desc(e)) return FALSE;

	if (aimed)
		textblock_append(tb, "When aimed, it ");
	else if (tval_is_edible(obj))
		textblock_append(tb, "When eaten, it ");
	else if (tval_is_potion(obj))
		textblock_append(tb, "When quaffed, it ");
	else if (tval_is_scroll(obj))
	    textblock_append(tb, "When read, it ");
	else
	    textblock_append(tb, "When activated, it ");

	/* Print a colourised description */
	while (e) {
		char *next_char = desc;
		random_value value = { 0, 0, 0, 0 };
		char dice_string[20];
		if (e->dice != NULL)
			(void) dice_roll(e->dice, &value);

		/* Get the possible dice strings */
		if (value.dice && value.base)
			strnfmt(dice_string, sizeof(dice_string), "%d+%dd%d",
					value.base, value.dice, value.sides);
		else if (value.dice)
			strnfmt(dice_string, sizeof(dice_string), "%dd%d",
					value.dice, value.sides);
		else
			strnfmt(dice_string, sizeof(dice_string), "%d", value.base);

		/* Check all the possible types of description format */
		switch (base_descs[e->index].efinfo_flag) {
			/* Healing sometimes has a minimum percentage */
			case EFINFO_HEAL: {
				char min_string[50];
				if (value.m_bonus)
					strnfmt(min_string, sizeof(min_string),
							" (or %d%%, whichever is greater)", value.m_bonus);
				else
					strnfmt(min_string, sizeof(min_string), "");
				strnfmt(desc, sizeof(desc), effect_desc(e), dice_string,
						min_string);
				break;
			}

			/* Nourishment is just a flat amount */
			case EFINFO_FEED: {
				strnfmt(desc, sizeof(desc), effect_desc(e), value.base);
				break;
			}
			case EFINFO_CURE: {
				strnfmt(desc, sizeof(desc), effect_desc(e),
							timed_idx_to_desc(e->params[0]));
				break;
			}
			case EFINFO_TIMED: {
				strnfmt(desc, sizeof(desc), effect_desc(e),
							timed_idx_to_desc(e->params[0]), dice_string);
				break;
			}
			case EFINFO_STAT: {
				strnfmt(desc, sizeof(desc), effect_desc(e),
							mod_flags[e->params[0]].name);
				break;
			}
			case EFINFO_SEEN: {
				strnfmt(desc, sizeof(desc), effect_desc(e),
						gf_desc(e->params[0]));
				break;
			}
			case EFINFO_SUMM: {
				strnfmt(desc, sizeof(desc), effect_desc(e),
						summon_desc(e->params[0]));
				break;
			}

			/* Only currently used for the player, but can handle monsters */
			case EFINFO_TELE: {
				if (e->params[0])
					strnfmt(desc, sizeof(desc), effect_desc(e), "a monster", 
						value.base);
				else
					strnfmt(desc, sizeof(desc), effect_desc(e), "you",
							value.base);
				break;
			}
			case EFINFO_QUAKE: {
				strnfmt(desc, sizeof(desc), effect_desc(e), e->params[1]);
				break;
			}
			case EFINFO_LIGHT: {
				strnfmt(desc, sizeof(desc), effect_desc(e), dice_string,
						e->params[1]);
				break;
			}

			/* Object generated balls are elemental */
			case EFINFO_BALL: {
				strnfmt(desc, sizeof(desc), effect_desc(e),
						elements[e->params[0]].name, e->params[1], dice_string);
				break;
			}

			/* Bolts that inflict status */
			case EFINFO_BOLT: {
				strnfmt(desc, sizeof(desc), effect_desc(e),
						gf_desc(e->params[0]));
				break;
			}
			/* Bolts and beams that damage */
			case EFINFO_BOLTD: {
				strnfmt(desc, sizeof(desc), effect_desc(e),
						gf_desc(e->params[0]), dice_string);
				break;
			}
			case EFINFO_TOUCH: {
				strnfmt(desc, sizeof(desc), effect_desc(e),
						gf_desc(e->params[0]));
				break;
			}
			default:strnfmt(desc, sizeof(desc), effect_desc(e)); break;
		}
		do {
			if (isdigit((unsigned char) *next_char))
				textblock_append_c(tb, COLOUR_L_GREEN, "%c", *next_char);
			else
				textblock_append(tb, "%c", *next_char);
		} while (*next_char++);
		if (e->next) {
			if (e->next->next)
				textblock_append(tb, ", ");
			else
				textblock_append(tb, " and ");
		}
		e = e->next;
	}

	textblock_append(tb, ".\n");

	if (min_time || max_time) {
		/* Sometimes adjust for player speed */
		int multiplier = turn_energy(player->state.speed);
		if (!subjective) multiplier = 10;

		textblock_append(tb, "Takes ");

		/* Correct for player speed */
		min_time *= multiplier / 10;
		max_time *= multiplier / 10;

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

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

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

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

	if (failure_chance > 0) {
		textblock_append(tb, "Your chance of success is %d.%d%%\n", 
			(1000 - failure_chance) / 10, (1000 - failure_chance) % 10);
	}

	return TRUE;
}