コード例 #1
0
ファイル: obj-gear.c プロジェクト: fe051/angband
/**
 * Remove an object from the gear list, leaving it unattached
 * \param obj the object being tested
 * \return whether an object was removed
 */
static bool gear_excise_object(struct object *obj)
{
	int i;

	pile_excise(&player->gear_k, obj->known);
	pile_excise(&player->gear, obj);

	/* Change the weight */
	player->upkeep->total_weight -= (obj->number * obj->weight);

	/* Make sure it isn't still equipped */
	for (i = 0; i < player->body.count; i++) {
		if (slot_object(player, i) == obj) {
			player->body.slots[i].obj = NULL;
			player->upkeep->equip_cnt--;
		}
	}

	/* Update the gear */
	calc_inventory(player->upkeep, player->gear, player->body);

	/* Housekeeping */
	player->upkeep->update |= (PU_BONUS);
	player->upkeep->notice |= (PN_COMBINE);
	player->upkeep->redraw |= (PR_INVEN | PR_EQUIP);

	return true;
}
コード例 #2
0
ファイル: ui-input.c プロジェクト: pete-mack/angband
/**
 * Check no currently worn items are stopping the action 'c'
 */
bool key_confirm_command(unsigned char c)
{
    int i;

    /* Hack -- Scan equipment */
    for (i = 0; i < player->body.count; i++) {
        char verify_inscrip[] = "^*";
        unsigned n;

        struct object *obj = slot_object(player, i);
        if (!obj) continue;

        /* Set up string to look for, e.g. "^d" */
        verify_inscrip[1] = c;

        /* Verify command */
        n = check_for_inscrip(obj, "^*") +
            check_for_inscrip(obj, verify_inscrip);
        while (n--) {
            if (!get_check("Are you sure? "))
                return false;
        }
    }

    return true;
}
コード例 #3
0
/**
 * Melee effect handler: Absorb the player's light.
 */
static void melee_effect_handler_EAT_LIGHT(melee_effect_handler_context_t *context)
{
	int light_slot = slot_by_name(context->p, "light");
	struct object *obj = slot_object(context->p, light_slot);

	/* Take damage */
	take_hit(context->p, context->damage, context->ddesc);

	/* Player is dead */
	if (context->p->is_dead)
		return;

	/* Drain fuel where applicable */
	if (obj && !of_has(obj->flags, OF_NO_FUEL) && (obj->timeout > 0)) {
		/* Reduce fuel */
		obj->timeout -= (250 + randint1(250));
		if (obj->timeout < 1) obj->timeout = 1;

		/* Notice */
		if (!context->p->timed[TMD_BLIND]) {
			msg("Your light dims.");
			context->obvious = TRUE;
		}

		/* Redraw stuff */
		context->p->upkeep->redraw |= (PR_EQUIP);
	}
}
コード例 #4
0
ファイル: ui-player.c プロジェクト: angband/angband
/**
 * Equippy chars
 */
static void display_player_equippy(int y, int x)
{
	int i;

	byte a;
	wchar_t c;

	struct object *obj;

	/* Dump equippy chars */
	for (i = 0; i < player->body.count; ++i) {
		/* Object */
		obj = slot_object(player, i);

		/* Skip empty objects */
		if (!obj) continue;

		/* Get attr/char for display */
		a = object_attr(obj);
		c = object_char(obj);

		/* Dump */
		if ((tile_width == 1) && (tile_height == 1))
		        Term_putch(x + i, y, a, c);
	}
}
コード例 #5
0
ファイル: obj-info.c プロジェクト: pnd10/angband
/**
 * Returns information about objects that can be used for digging.
 *
 * `deciturns` will be filled in with the avg number of deciturns it will
 * take to dig through each type of diggable terrain, and must be at least 
 * [DIGGING_MAX].
 *
 * Returns FALSE if the object has no effect on digging, or if the specifics
 * are meaningless (i.e. the object is an ego template, not a real item).
 */
static bool obj_known_digging(struct object *obj, int deciturns[])
{
	player_state state;
	int i;
	int chances[DIGGING_MAX];
	int slot = wield_slot(obj);
	struct object *current = slot_object(player, slot);

	if (!tval_is_wearable(obj) || 
		(!tval_is_melee_weapon(obj) && 
		 (obj->modifiers[OBJ_MOD_TUNNEL] <= 0)))
		return FALSE;

	/* Pretend we're wielding the object */
	player->body.slots[slot].obj = obj;

	/* Calculate the player's hypothetical state */
	calc_bonuses(player->gear, &state, TRUE);

	/* Stop pretending */
	player->body.slots[slot].obj = current;

	calc_digging_chances(&state, chances);

	/* Digging chance is out of 1600 */
	for (i = DIGGING_RUBBLE; i < DIGGING_MAX; i++) {
		int chance = MIN(1600, chances[i]);
		deciturns[i] = chance ? (16000 / chance) : 0;
	}

	return TRUE;
}
コード例 #6
0
ファイル: obj-pile.c プロジェクト: fizzix/angband
/**
 * Get a list of "valid" objects.
 *
 * Fills item_list[] with items that are "okay" as defined by the
 * provided tester function, etc.  mode determines what combination of
 * inventory, equipment, quiver and player's floor location should be used
 * when drawing up the list.
 *
 * Returns the number of items placed into the list.
 *
 * Maximum space that can be used is
 * z_info->pack_size + z_info->quiver_size + player->body.count +
 * z_info->floor_size,
 * though practically speaking much smaller numbers are likely.
 */
int scan_items(struct object **item_list, size_t item_max, int mode,
			   item_tester tester)
{
	bool use_inven = ((mode & USE_INVEN) ? true : false);
	bool use_equip = ((mode & USE_EQUIP) ? true : false);
	bool use_quiver = ((mode & USE_QUIVER) ? true : false);
	bool use_floor = ((mode & USE_FLOOR) ? true : false);

	int floor_max = z_info->floor_size;
	struct object **floor_list = mem_zalloc(floor_max * sizeof(struct object *));
	int floor_num;

	int i;
	size_t item_num = 0;

	if (use_inven)
		for (i = 0; i < z_info->pack_size && item_num < item_max; i++) {
			if (object_test(tester, player->upkeep->inven[i]))
				item_list[item_num++] = player->upkeep->inven[i];
		}

	if (use_equip)
		for (i = 0; i < player->body.count && item_num < item_max; i++) {
			if (object_test(tester, slot_object(player, i)))
				item_list[item_num++] = slot_object(player, i);
		}

	if (use_quiver)
		for (i = 0; i < z_info->quiver_size && item_num < item_max; i++) {
			if (object_test(tester, player->upkeep->quiver[i]))
				item_list[item_num++] = player->upkeep->quiver[i];
		}

	/* Scan all non-gold objects in the grid */
	if (use_floor) {
		floor_num = scan_floor(floor_list, floor_max,
							   OFLOOR_TEST | OFLOOR_SENSE | OFLOOR_VISIBLE,
							   tester);

		for (i = 0; i < floor_num && item_num < item_max; i++)
			item_list[item_num++] = floor_list[i];
	}

	mem_free(floor_list);
	return item_num;
}
コード例 #7
0
ファイル: obj-gear.c プロジェクト: fe051/angband
struct object *equipped_item_by_slot_name(struct player *p, const char *name)
{
	/* Ensure a valid body */
	if (!p->body.slots)
		return NULL;

	return slot_object(p, slot_by_name(p, name));
}
コード例 #8
0
ファイル: ui-object.c プロジェクト: danaris/tgcangband
/**
 * Convert a label into an item in the equipment.
 *
 * Return NULL if the label does not indicate a real item.
 */
struct object *label_to_equip(int c)
{
	int i;

	/* Convert */
	i = (islower((unsigned char)c) ? A2I(c) : -1);

	/* Verify the index */
	if ((i < 0) || (i >= player->body.count))
		return NULL;

	/* Return the object */
	return slot_object(player, i);
}
コード例 #9
0
ファイル: ui-object.c プロジェクト: angband/angband
/**
 * Build the object list.
 */
static void build_obj_list(int last, struct object **list, item_tester tester,
						   olist_detail_t mode)
{
	int i;
	bool gold_ok = (mode & OLIST_GOLD) ? true : false;
	bool in_term = (mode & OLIST_WINDOW) ? true : false;
	bool dead = (mode & OLIST_DEATH) ? true : false;
	bool show_empty = (mode & OLIST_SEMPTY) ? true : false;
	bool equip = list ? false : true;
	bool quiver = list == player->upkeep->quiver ? true : false;

	/* Build the object list */
	for (i = 0; i <= last; i++) {
		char buf[80];
		struct object *obj = equip ? slot_object(player, i) : list[i];

		/* Acceptable items get a label */
		if (object_test(tester, obj) ||	(obj && tval_is_money(obj) && gold_ok))
			strnfmt(items[num_obj].label, sizeof(items[num_obj].label), "%c) ",
					quiver ? I2D(i) : I2A(i));

		/* Unacceptable items are still sometimes shown */
		else if ((!obj && show_empty) || in_term)
			my_strcpy(items[num_obj].label, "   ",
					  sizeof(items[num_obj].label));

		/* Unacceptable items are skipped in the main window */
		else continue;

		/* Show full slot labels for equipment (or quiver in subwindow) */
		if (equip) {
			strnfmt(buf, sizeof(buf), "%-14s: ", equip_mention(player, i));
			my_strcpy(items[num_obj].equip_label, buf,
					  sizeof(items[num_obj].equip_label));
		} else if ((in_term || dead) && quiver) {
			strnfmt(buf, sizeof(buf), "Slot %-9d: ", i);
			my_strcpy(items[num_obj].equip_label, buf,
					  sizeof(items[num_obj].equip_label));
		} else {
			strnfmt(items[num_obj].equip_label,
					sizeof(items[num_obj].equip_label), "");
		}

		/* Save the object */
		items[num_obj].object = obj;
		items[num_obj].key = (items[num_obj].label)[0];
		num_obj++;
	}
}
コード例 #10
0
ファイル: obj-gear.c プロジェクト: tingley/angband
/**
 * Remove an object from the gear list, leaving it unattached
 * \param obj the object being tested
 * \return whether an object was removed
 */
bool gear_excise_object(struct object *obj)
{
	int i;

	pile_excise(&player->gear, obj);

	/* Make sure it isn't still equipped */
	for (i = 0; i < player->body.count; i++) {
		if (slot_object(player, i) == obj)
			player->body.slots[i].obj = NULL;
	}

	/* Housekeeping */
	player->upkeep->update |= (PU_BONUS | PU_MANA | PU_INVEN);
	player->upkeep->notice |= (PN_COMBINE);
	player->upkeep->redraw |= (PR_INVEN | PR_EQUIP);

	return TRUE;
}
コード例 #11
0
ファイル: obj-info.c プロジェクト: lhz/angband
/**
 * Returns information about objects that can be used for digging.
 *
 * `deciturns` will be filled in with the avg number of deciturns it will
 * take to dig through each type of diggable terrain, and must be at least 
 * [DIGGING_MAX].
 *
 * Returns false if the object has no effect on digging, or if the specifics
 * are meaningless (i.e. the object is an ego template, not a real item).
 */
static bool obj_known_digging(struct object *obj, int deciturns[])
{
	struct player_state state;
	int i;
	int chances[DIGGING_MAX];
	int slot = wield_slot(obj);
	struct object *current = slot_object(player, slot);

	/* Doesn't remotely resemble a digger */
	if (!tval_is_wearable(obj) ||
		(!tval_is_melee_weapon(obj) && (obj->modifiers[OBJ_MOD_TUNNEL] <= 0)))
		return false;

	/* Player has no digging info */
	if (!tval_is_melee_weapon(obj) && !obj->known->modifiers[OBJ_MOD_TUNNEL])
		return false;

	/* Pretend we're wielding the object */
	player->body.slots[slot].obj = obj;

	/* Calculate the player's hypothetical state */
	memcpy(&state, &player->state, sizeof(state));
	state.stat_ind[STAT_STR] = 0; //Hack - NRM
	state.stat_ind[STAT_DEX] = 0; //Hack - NRM
	calc_bonuses(player, &state, true, false);

	/* Stop pretending */
	player->body.slots[slot].obj = current;

	calc_digging_chances(&state, chances);

	/* Digging chance is out of 1600 */
	for (i = DIGGING_RUBBLE; i < DIGGING_MAX; i++) {
		int chance = MIN(1600, chances[i]);
		deciturns[i] = chance ? (16000 / chance) : 0;
	}

	return true;
}
コード例 #12
0
ファイル: obj-info.c プロジェクト: Chillbon/angband
/**
 * Gets information about the average damage/turn that can be inflicted if
 * the player wields the given weapon.
 *
 * Fills in the damage against normal adversaries in `normal_damage`, as well
 * as the slays on the weapon in slay_list[] and corresponding damages in 
 * slay_damage[].  These must both be at least SL_MAX long to be safe.
 * `nonweap_slay` is set to whether other items being worn could add to the
 * damage done by branding attacks.
 *
 * Returns the number of slays populated in slay_list[] and slay_damage[].
 *
 * Note that the results are meaningless if called on a fake ego object as
 * the actual ego may have different properties.
 */
static bool obj_known_damage(const struct object *obj, int *normal_damage,
							struct brand **brand_list, struct slay **slay_list,
							bool *nonweap_slay)
{
	int i;
	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;
	struct brand *brand;
	struct slay *slay;

	struct object *bow = equipped_item_by_slot_name(player, "shooting");
	bool weapon = tval_is_melee_weapon(obj);
	bool ammo   = (player->state.ammo_tval == obj->tval) &&
	              (bow);
	int multiplier = 1;

	struct player_state state;
	int weapon_slot = slot_by_name(player, "weapon");
	struct object *current_weapon = slot_object(player, weapon_slot);

	/* Pretend we're wielding the object if it's a weapon */
	if (weapon)
		player->body.slots[weapon_slot].obj = (struct object *) obj;

	/* Calculate the player's hypothetical state */
	calc_bonuses(player, &state, true, false);

	/* Stop pretending */
	player->body.slots[weapon_slot].obj = current_weapon;

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

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

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

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

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

		calculate_missile_crits(&player->state, obj->weight, plus,
				&crit_mult, &crit_add, &crit_div);

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

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

	/* Get the brands */
	*brand_list = brand_collect(obj->known->brands, ammo ? bow->known : NULL);

	/* Get the slays */
	*slay_list = slay_collect(obj->known->slays, ammo ? bow->known : NULL);

	/* Melee weapons may get slays and brands from other items */
	*nonweap_slay = false;
	if (weapon)	{
		for (i = 2; i < player->body.count; i++) {
			struct object *slot_obj = slot_object(player, i);
			struct brand *new_brand;
			struct slay *new_slay;
			if (!slot_obj)
				continue;

			if (slot_obj->known->brands || slot_obj->known->slays)
				*nonweap_slay = true;
			else
				continue;

			/* Replace the old lists with new ones */
			new_brand = brand_collect(*brand_list, slot_obj->known);
			new_slay = slay_collect(*slay_list, slot_obj->known);
			free_brand(*brand_list);
			free_slay(*slay_list);
			*brand_list = new_brand;
			*slay_list = new_slay;
		}
	}

	/* Get damage for each brand on the objects */
	for (brand = *brand_list; brand; brand = brand->next) {
		/* 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 + brand->multiplier
						   - 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 *= player->state.num_shots;

		brand->damage = total_dam;
	}

	/* Get damage for each slay on the objects */
	for (slay = *slay_list; slay; slay = slay->next) {
		/* 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 + slay->multiplier
						   - 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 *= player->state.num_shots;

		slay->damage = total_dam;
	}

	/* 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 *= player->state.num_shots;

	*normal_damage = total_dam;

	return (*slay_list || *brand_list);
}
コード例 #13
0
ファイル: ui-player.c プロジェクト: angband/angband
/**
 * Special display, part 2c
 *
 * How to print out the modifications and sustains.
 * Positive mods with no sustain will be light green.
 * Positive mods with a sustain will be dark green.
 * Sustains (with no modification) will be a dark green 's'.
 * Negative mods (from a curse) will be red.
 * Huge mods (>9), like from MICoMorgoth, will be a '*'
 * No mod, no sustain, will be a slate '.'
 */
static void display_player_sust_info(void)
{
	int i, row, col, stat;

	struct object *obj;
	bitflag f[OF_SIZE];

	byte a;
	char c;


	/* Row */
	row = 2;

	/* Column */
	col = 26;

	/* Header */
	c_put_str(COLOUR_WHITE, "abcdefghijkl@", row-1, col);

	/* Process equipment */
	for (i = 0; i < player->body.count; ++i) {
		/* Get the object */
		obj = slot_object(player, i);

		if (!obj) {
			col++;
			continue;
		}

		/* Get the "known" flags */
		object_flags_known(obj, f);

		/* Initialize color based on sign of modifier. */
		for (stat = OBJ_MOD_MIN_STAT; stat < OBJ_MOD_MIN_STAT + STAT_MAX;
			 stat++) {
			/* Default */
			a = COLOUR_SLATE;
			c = '.';

			/* Boosted or reduced */
			if (obj->modifiers[stat] > 0) {
				/* Good */
				a = COLOUR_L_GREEN;

				/* Label boost */
				if (obj->modifiers[stat] < 10)
						c = I2D(obj->modifiers[stat]);
			} else if (obj->modifiers[stat] < 0) {
				/* Bad */
				a = COLOUR_RED;

				/* Label boost */
				if (obj->modifiers[stat] > -10)
					c = I2D(-(obj->modifiers[stat]));
			}

			/* Sustain */
			if (of_has(f, sustain_flag(stat))) {
				/* Dark green */
				a = COLOUR_GREEN;

				/* Convert '.' to 's' */
				if (c == '.') c = 's';
			}

			if ((c == '.') && obj && 
				!object_flag_is_known(obj, sustain_flag(stat)))
				c = '?';

			/* Dump proper character */
			Term_putch(col, row+stat, a, c);
		}

		/* Advance */
		col++;
	}

	/* Player flags */
	player_flags(player, f);

	/* Check stats */
	for (stat = 0; stat < STAT_MAX; ++stat) {
		/* Default */
		a = COLOUR_SLATE;
		c = '.';

		/* Sustain */
		if (of_has(f, sustain_flag(stat))) {
			/* Dark green "s" */
			a = COLOUR_GREEN;
			c = 's';
		}

		/* Dump */
		Term_putch(col, row+stat, a, c);
	}

	/* Column */
	col = 26;

	/* Footer */
	c_put_str(COLOUR_WHITE, "abcdefghijkl@", row+6, col);

	/* Equippy */
	display_player_equippy(row+7, col);
}
コード例 #14
0
ファイル: ui-player.c プロジェクト: angband/angband
/**
 * Write a character dump
 */
void write_character_dump(ang_file *fff)
{
	int i, x, y;

	int a;
	wchar_t c;

	struct store *home = &stores[STORE_HOME];
	struct object **home_list = mem_zalloc(sizeof(struct object *) *
										   z_info->store_inven_max);
	char o_name[80];

	char buf[1024];
	char *p;

	/* Begin dump */
	file_putf(fff, "  [%s Character Dump]\n\n", buildid);

	/* Display player */
	display_player(0);

	/* Dump part of the screen */
	for (y = 1; y < 23; y++) {
		p = buf;
		/* Dump each row */
		for (x = 0; x < 79; x++) {
			/* Get the attr/char */
			(void)(Term_what(x, y, &a, &c));

			/* Dump it */
			p += wctomb(p, c);
		}

		/* Back up over spaces */
		while ((p > buf) && (p[-1] == ' ')) --p;

		/* Terminate */
		*p = '\0';

		/* End the row */
		file_putf(fff, "%s\n", buf);
	}

	/* Skip a line */
	file_putf(fff, "\n");

	/* Display player */
	display_player(1);

	/* Dump part of the screen */
	for (y = 11; y < 20; y++) {
		p = buf;
		/* Dump each row */
		for (x = 0; x < 39; x++) {
			/* Get the attr/char */
			(void)(Term_what(x, y, &a, &c));

			/* Dump it */
			p += wctomb(p, c);
		}

		/* Back up over spaces */
		while ((p > buf) && (p[-1] == ' ')) --p;

		/* Terminate */
		*p = '\0';

		/* End the row */
		file_putf(fff, "%s\n", buf);
	}

	/* Skip a line */
	file_putf(fff, "\n");

	/* Dump part of the screen */
	for (y = 11; y < 20; y++) {
		p = buf;
		/* Dump each row */
		for (x = 0; x < 39; x++) {
			/* Get the attr/char */
			(void)(Term_what(x + 40, y, &a, &c));

			/* Dump it */
			p += wctomb(p, c);
		}

		/* Back up over spaces */
		while ((p > buf) && (p[-1] == ' ')) --p;

		/* Terminate */
		*p = '\0';

		/* End the row */
		file_putf(fff, "%s\n", buf);
	}

	/* Skip some lines */
	file_putf(fff, "\n\n");


	/* If dead, dump last messages -- Prfnoff */
	if (player->is_dead) {
		i = messages_num();
		if (i > 15) i = 15;
		file_putf(fff, "  [Last Messages]\n\n");
		while (i-- > 0)
		{
			file_putf(fff, "> %s\n", message_str((s16b)i));
		}
		file_putf(fff, "\nKilled by %s.\n\n", player->died_from);
	}


	/* Dump the equipment */
	file_putf(fff, "  [Character Equipment]\n\n");
	for (i = 0; i < player->body.count; i++) {
		struct object *obj = slot_object(player, i);
		if (!obj) continue;

		object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL);
		file_putf(fff, "%c) %s\n", gear_to_label(obj), o_name);
		object_info_chardump(fff, obj, 5, 72);
	}
	file_putf(fff, "\n\n");

	/* Dump the inventory */
	file_putf(fff, "\n\n  [Character Inventory]\n\n");
	for (i = 0; i < z_info->pack_size; i++) {
		struct object *obj = player->upkeep->inven[i];
		if (!obj) break;

		object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL);
		file_putf(fff, "%c) %s\n", gear_to_label(obj), o_name);
		object_info_chardump(fff, obj, 5, 72);
	}
	file_putf(fff, "\n\n");

	/* Dump the quiver */
	file_putf(fff, "\n\n  [Character Quiver]\n\n");
	for (i = 0; i < z_info->quiver_size; i++) {
		struct object *obj = player->upkeep->quiver[i];
		if (!obj) continue;

		object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL);
		file_putf(fff, "%c) %s\n", gear_to_label(obj), o_name);
		object_info_chardump(fff, obj, 5, 72);
	}
	file_putf(fff, "\n\n");

	/* Dump the Home -- if anything there */
	store_stock_list(home, home_list, z_info->store_inven_max);
	if (home->stock_num) {
		/* Header */
		file_putf(fff, "  [Home Inventory]\n\n");

		/* Dump all available items */
		for (i = 0; i < z_info->store_inven_max; i++) {
			struct object *obj = home_list[i];
			if (!obj) break;
			object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL);
			file_putf(fff, "%c) %s\n", I2A(i), o_name);

			object_info_chardump(fff, obj, 5, 72);
		}

		/* Add an empty line */
		file_putf(fff, "\n\n");
	}

	/* Dump character history */
	dump_history(fff);
	file_putf(fff, "\n\n");

	/* Dump options */
	file_putf(fff, "  [Options]\n\n");

	/* Dump options */
	for (i = 0; i < OP_MAX; i++) {
		int opt;
		const char *title = "";
		switch (i) {
			case OP_INTERFACE: title = "User interface"; break;
			case OP_BIRTH: title = "Birth"; break;
		    default: continue;
		}

		file_putf(fff, "  [%s]\n\n", title);
		for (opt = 0; opt < OPT_MAX; opt++) {
			if (option_type(opt) != i) continue;

			file_putf(fff, "%-45s: %s (%s)\n",
			        option_desc(opt),
			        player->opts.opt[opt] ? "yes" : "no ",
			        option_name(opt));
		}

		/* Skip some lines */
		file_putf(fff, "\n");
	}

	mem_free(home_list);
}
コード例 #15
0
ファイル: player-attack.c プロジェクト: ewert/angband
/**
 * Attack the monster at the given location with a single blow.
 */
static bool py_attack_real(int y, int x, bool *fear)
{
	size_t i;

	/* Information about the target of the attack */
	struct monster *mon = square_monster(cave, y, x);
	char m_name[80];
	bool stop = FALSE;

	/* The weapon used */
	struct object *obj = equipped_item_by_slot_name(player, "weapon");

	/* Information about the attack */
	int chance = py_attack_hit_chance(obj);
	bool do_quake = FALSE;
	bool success = FALSE;

	/* Default to punching for one damage */
	char verb[20];
	int dmg = 1;
	u32b msg_type = MSG_HIT;

	/* Default to punching for one damage */
	my_strcpy(verb, "punch", sizeof(verb));

	/* Extract monster name (or "it") */
	monster_desc(m_name, sizeof(m_name), mon, 
				 MDESC_OBJE | MDESC_IND_HID | MDESC_PRO_HID);

	/* Auto-Recall if possible and visible */
	if (mflag_has(mon->mflag, MFLAG_VISIBLE))
		monster_race_track(player->upkeep, mon->race);

	/* Track a new monster */
	if (mflag_has(mon->mflag, MFLAG_VISIBLE))
		health_track(player->upkeep, mon);

	/* Handle player fear (only for invisible monsters) */
	if (player_of_has(player, OF_AFRAID)) {
		msgt(MSG_AFRAID, "You are too afraid to attack %s!", m_name);
		return FALSE;
	}

	/* Disturb the monster */
	mon_clear_timed(mon, MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE, FALSE);

	/* See if the player hit */
	success = test_hit(chance, mon->race->ac,
					   mflag_has(mon->mflag, MFLAG_VISIBLE));

	/* If a miss, skip this hit */
	if (!success) {
		msgt(MSG_MISS, "You miss %s.", m_name);
		return FALSE;
	}

	/* Handle normal weapon */
	if (obj) {
		int j;
		const struct brand *b = NULL;
		const struct slay *s = NULL;

		my_strcpy(verb, "hit", sizeof(verb));

		/* Get the best attack from all slays or
		 * brands on all non-launcher equipment */
		for (j = 2; j < player->body.count; j++) {
			struct object *obj = slot_object(player, j);
			if (obj)
				improve_attack_modifier(obj, mon, &b, &s, verb, FALSE, TRUE,
										FALSE);
		}

		improve_attack_modifier(obj, mon, &b, &s, verb, FALSE, TRUE, FALSE);

		dmg = melee_damage(obj, b, s);
		dmg = critical_norm(obj->weight, obj->to_h, dmg, &msg_type);

		/* Learn by use for the weapon */
		object_notice_attack_plusses(obj);

		if (player_of_has(player, OF_IMPACT) && dmg > 50) {
			do_quake = TRUE;
			equip_notice_flag(player, OF_IMPACT);
		}
	}

	/* Learn by use for other equipped items */
	equip_notice_on_attack(player);

	/* Apply the player damage bonuses */
	dmg += player_damage_bonus(&player->state);

	/* No negative damage; change verb if no damage done */
	if (dmg <= 0) {
		dmg = 0;
		msg_type = MSG_MISS;
		my_strcpy(verb, "fail to harm", sizeof(verb));
	}

	for (i = 0; i < N_ELEMENTS(melee_hit_types); i++) {
		const char *dmg_text = "";

		if (msg_type != melee_hit_types[i].msg)
			continue;

		if (OPT(show_damage))
			dmg_text = format(" (%d)", dmg);

		if (melee_hit_types[i].text)
			msgt(msg_type, "You %s %s%s. %s", verb, m_name, dmg_text,
					melee_hit_types[i].text);
		else
			msgt(msg_type, "You %s %s%s.", verb, m_name, dmg_text);
	}

	/* Pre-damage side effects */
	blow_side_effects(player, mon);

	/* Damage, check for fear and death */
	stop = mon_take_hit(mon, dmg, fear, NULL);

	if (stop)
		(*fear) = FALSE;

	/* Post-damage effects */
	if (blow_after_effects(y, x, do_quake))
		stop = TRUE;

	return stop;
}
コード例 #16
0
ファイル: ui-player.c プロジェクト: angband/angband
static void display_resistance_panel(const struct player_flag_record *rec,
									size_t size, const region *bounds) 
{
	size_t i;
	int j;
	int col = bounds->col;
	int row = bounds->row;
	int res_cols = 5 + 2 + player->body.count;

	Term_putstr(col, row++, res_cols, COLOUR_WHITE, "      abcdefghijkl@");
	for (i = 0; i < size - 3; i++, row++) {
		byte name_attr = COLOUR_WHITE;
		Term_gotoxy(col + 6, row);

		/* Repeated extraction of flags is inefficient but more natural */
		for (j = 0; j <= player->body.count; j++) {
			bitflag f[OF_SIZE];
			byte attr = COLOUR_WHITE | (j % 2) * 8; /* alternating columns */
			char sym = '.';
			bool res = false, imm = false, vul = false, rune = false;
			bool timed = false;
			bool known = false;

			/* Object or player info? */
			if (j < player->body.count) {
				int index = 0;
				struct object *obj = slot_object(player, j);
				struct curse_data *curse = obj ? obj->curses : NULL;

				while (obj) {
					/* Wipe flagset */
					of_wipe(f);

					/* Get known properties */
					object_flags_known(obj, f);
					if (rec[i].element != -1) {
						known = object_element_is_known(obj, rec[i].element);
					} else if (rec[i].flag != -1) {
						known = object_flag_is_known(obj, rec[i].flag);
					} else {
						known = true;
					}

					/* Get resistance, immunity and vulnerability info */
					if (rec[i].mod != -1) {
						if (obj->modifiers[rec[i].mod] != 0) {
							res = true;
						}
						rune = (player->obj_k->modifiers[rec[i].mod] == 1);
					} else if (rec[i].flag != -1) {
						if (of_has(f, rec[i].flag)) {
							res = true;
						}
						rune = of_has(player->obj_k->flags, rec[i].flag);
					} else if (rec[i].element != -1) {
						if (known) {
							if (obj->el_info[rec[i].element].res_level == 3) {
								imm = true;
							}
							if (obj->el_info[rec[i].element].res_level == 1) {
								res = true;
							}
							if (obj->el_info[rec[i].element].res_level == -1) {
								vul = true;
							}
						}
						rune = (player->obj_k->el_info[rec[i].element].res_level == 1);
					}

					/* Move to any unprocessed curse object */
					if (curse) {
						index++;
						obj = NULL;
						while (index < z_info->curse_max) {
							if (curse[index].power) {
								obj = curses[index].obj;
								break;
							} else {
								index++;
							}
						}
					} else {
						obj = NULL;
					}
				}
			} else {
				player_flags(player, f);
				known = true;

				/* Timed flags only in the player column */
				if (rec[i].tmd_flag >= 0) {
	 				timed = player->timed[rec[i].tmd_flag] ? true : false;
					/* There has to be one special case... */
					if ((rec[i].tmd_flag == TMD_AFRAID) &&
						(player->timed[TMD_TERROR]))
						timed = true;
				}

				/* Set which (if any) symbol and color are used */
				if (rec[i].mod != -1) {
					int k;

					/* Shape modifiers */
					for (k = 0; k < OBJ_MOD_MAX; k++) {
						res = (player->shape->modifiers[i] > 0);
						vul = (player->shape->modifiers[i] > 0);
					}

					/* Messy special cases */
					if (rec[i].mod == OBJ_MOD_INFRA)
						res |= (player->race->infra > 0);
					if (rec[i].mod == OBJ_MOD_TUNNEL)
						res |= (player->race->r_skills[SKILL_DIGGING] > 0);
				} else if (rec[i].flag != -1) {
					res = of_has(f, rec[i].flag);
					res |= (of_has(player->shape->flags, rec[i].flag) &&
							of_has(player->obj_k->flags, rec[i].flag));
				} else if (rec[i].element != -1) {
					int el = rec[i].element;
					imm = (player->race->el_info[el].res_level == 3) ||
						((player->shape->el_info[el].res_level == 3) &&
						 (player->obj_k->el_info[el].res_level));
					res = (player->race->el_info[el].res_level == 1) ||
						((player->shape->el_info[el].res_level == 1) &&
						 (player->obj_k->el_info[el].res_level));
					vul = (player->race->el_info[el].res_level == -1) ||
						((player->shape->el_info[el].res_level == -1) &&
						 (player->obj_k->el_info[el].res_level));
				}
			}

			/* Colour the name appropriately */
			if (imm) {
				name_attr = COLOUR_GREEN;
			} else if (res && (name_attr != COLOUR_GREEN)) {
				name_attr = COLOUR_L_BLUE;
			} else if (vul && (name_attr != COLOUR_GREEN)) {
				name_attr = COLOUR_RED;
			}

			/* Set the symbols and print them */
			if (vul) {
				sym = '-';
			} else if (imm) {
				sym = '*';
			} else if (res) {
				sym = '+';
			} else if (timed) {
				sym = '!';
				attr = COLOUR_L_GREEN;
			} else if ((j < player->body.count) && slot_object(player, j) &&
					   !known && !rune) {
				sym = '?';
			}

			Term_addch(attr, sym);
		}

		/* Check if the rune is known */
		if (((rec[i].mod >= 0) &&
			 (player->obj_k->modifiers[rec[i].mod] == 0))
			|| ((rec[i].flag >= 0) &&
				!of_has(player->obj_k->flags, rec[i].flag))
			|| ((rec[i].element >= 0) &&
				(player->obj_k->el_info[rec[i].element].res_level == 0))) {
			name_attr = COLOUR_SLATE;
		}

		Term_putstr(col, row, 6, name_attr, format("%5s:", rec[i].name));
	}
	Term_putstr(col, row++, res_cols, COLOUR_WHITE, "      abcdefghijkl@");

	/* Equippy */
	display_player_equippy(row++, col + 6);
}
コード例 #17
0
ファイル: ui-object.c プロジェクト: angband/angband
/**
 * Let the user select an object, save its address
 *
 * Return true only if an acceptable item was chosen by the user.
 *
 * The user is allowed to choose acceptable items from the equipment,
 * inventory, quiver, or floor, respectively, if the proper flag was given,
 * and there are any acceptable items in that location.
 *
 * The equipment, inventory or quiver are displayed (even if no acceptable
 * items are in that location) if the proper flag was given.
 *
 * If there are no acceptable items available anywhere, and "str" is
 * not NULL, then it will be used as the text of a warning message
 * before the function returns.
 *
 * If a legal item is selected , we save it in "choice" and return true.
 *
 * If no item is available, we do nothing to "choice", and we display a
 * warning message, using "str" if available, and return false.
 *
 * If no item is selected, we do nothing to "choice", and return false.
 *
 * Global "player->upkeep->command_wrk" is used to choose between
 * equip/inven/quiver/floor listings.  It is equal to USE_INVEN or USE_EQUIP or
 * USE_QUIVER or USE_FLOOR, except when this function is first called, when it
 * is equal to zero, which will cause it to be set to USE_INVEN.
 *
 * We always erase the prompt when we are done, leaving a blank line,
 * or a warning message, if appropriate, if no items are available.
 *
 * Note that only "acceptable" floor objects get indexes, so between two
 * commands, the indexes of floor objects may change.  XXX XXX XXX
 */
bool textui_get_item(struct object **choice, const char *pmt, const char *str,
					 cmd_code cmd, item_tester tester, int mode)
{
	bool use_inven = ((mode & USE_INVEN) ? true : false);
	bool use_equip = ((mode & USE_EQUIP) ? true : false);
	bool use_quiver = ((mode & USE_QUIVER) ? true : false);
	bool use_floor = ((mode & USE_FLOOR) ? true : false);
	bool quiver_tags = ((mode & QUIVER_TAGS) ? true : false);

	bool allow_inven = false;
	bool allow_equip = false;
	bool allow_quiver = false;
	bool allow_floor = false;

	bool toggle = false;

	int floor_max = z_info->floor_size;
	int floor_num;

	floor_list = mem_zalloc(floor_max * sizeof(*floor_list));
	olist_mode = 0;
	item_mode = mode;
	item_cmd = cmd;
	tester_m = tester;
	prompt = pmt;
	allow_all = str ? false : true;

	/* Object list display modes */
	if (mode & SHOW_FAIL)
		olist_mode |= OLIST_FAIL;
	else
		olist_mode |= OLIST_WEIGHT;

	if (mode & SHOW_PRICES)
		olist_mode |= OLIST_PRICE;

	if (mode & SHOW_EMPTY)
		olist_mode |= OLIST_SEMPTY;

	if (mode & SHOW_QUIVER)
		olist_mode |= OLIST_QUIVER;

	if (mode & SHOW_RECHARGE)
		olist_mode |= OLIST_RECHARGE;

	/* Paranoia XXX XXX XXX */
	event_signal(EVENT_MESSAGE_FLUSH);

	/* Full inventory */
	i1 = 0;
	i2 = z_info->pack_size - 1;

	/* Forbid inventory */
	if (!use_inven) i2 = -1;

	/* Restrict inventory indexes */
	while ((i1 <= i2) && (!object_test(tester, player->upkeep->inven[i1])))
		i1++;
	while ((i1 <= i2) && (!object_test(tester, player->upkeep->inven[i2])))
		i2--;

	/* Accept inventory */
	if ((i1 <= i2) || allow_all)
		allow_inven = true;
	else if (item_mode & USE_INVEN)
		item_mode -= USE_INVEN;

	/* Full equipment */
	e1 = 0;
	e2 = player->body.count - 1;

	/* Forbid equipment */
	if (!use_equip) e2 = -1;

	/* Restrict equipment indexes unless starting with no command */
	if ((cmd != CMD_NULL) || (tester != NULL)) {
		while ((e1 <= e2) && (!object_test(tester, slot_object(player, e1))))
			e1++;
		while ((e1 <= e2) && (!object_test(tester, slot_object(player, e2))))
			e2--;
	}

	/* Accept equipment */
	if ((e1 <= e2) || allow_all)
		allow_equip = true;
	else if (item_mode & USE_EQUIP)
		item_mode -= USE_EQUIP;

	/* Restrict quiver indexes */
	q1 = 0;
	q2 = z_info->quiver_size - 1;

	/* Forbid quiver */
	if (!use_quiver) q2 = -1;

	/* Restrict quiver indexes */
	while ((q1 <= q2) && (!object_test(tester, player->upkeep->quiver[q1])))
		q1++;
	while ((q1 <= q2) && (!object_test(tester, player->upkeep->quiver[q2])))
		q2--;

	/* Accept quiver */
	if ((q1 <= q2) || allow_all)
		allow_quiver = true;
	else if (item_mode & USE_QUIVER)
		item_mode -= USE_QUIVER;

	/* Scan all non-gold objects in the grid */
	floor_num = scan_floor(floor_list, floor_max,
						   OFLOOR_TEST | OFLOOR_SENSE | OFLOOR_VISIBLE, tester);

	/* Full floor */
	f1 = 0;
	f2 = floor_num - 1;

	/* Forbid floor */
	if (!use_floor) f2 = -1;

	/* Restrict floor indexes */
	while ((f1 <= f2) && (!object_test(tester, floor_list[f1]))) f1++;
	while ((f1 <= f2) && (!object_test(tester, floor_list[f2]))) f2--;

	/* Accept floor */
	if ((f1 <= f2) || allow_all)
		allow_floor = true;
	else if (item_mode & USE_FLOOR)
		item_mode -= USE_FLOOR;

	/* Require at least one legal choice */
	if (allow_inven || allow_equip || allow_quiver || allow_floor) {
		/* Start where requested if possible */
		if ((player->upkeep->command_wrk == USE_EQUIP) && allow_equip)
			player->upkeep->command_wrk = USE_EQUIP;
		else if ((player->upkeep->command_wrk == USE_INVEN) && allow_inven)
			player->upkeep->command_wrk = USE_INVEN;
		else if ((player->upkeep->command_wrk == USE_QUIVER) && allow_quiver)
			player->upkeep->command_wrk = USE_QUIVER;
		else if ((player->upkeep->command_wrk == USE_FLOOR) && allow_floor)
			player->upkeep->command_wrk = USE_FLOOR;

		/* If we are obviously using the quiver then start on quiver */
		else if (quiver_tags && allow_quiver)
			player->upkeep->command_wrk = USE_QUIVER;

		/* Otherwise choose whatever is allowed */
		else if (use_inven && allow_inven)
			player->upkeep->command_wrk = USE_INVEN;
		else if (use_equip && allow_equip)
			player->upkeep->command_wrk = USE_EQUIP;
		else if (use_quiver && allow_quiver)
			player->upkeep->command_wrk = USE_QUIVER;
		else if (use_floor && allow_floor)
			player->upkeep->command_wrk = USE_FLOOR;

		/* If nothing to choose, use (empty) inventory */
		else
			player->upkeep->command_wrk = USE_INVEN;

		while (true) {
			int j;
			int ni = 0;
			int ne = 0;

			/* If inven or equip is on the main screen, and only one of them
			 * is slated for a subwindow, we should show the opposite there */
			for (j = 0; j < ANGBAND_TERM_MAX; j++) {
				/* Unused */
				if (!angband_term[j]) continue;

				/* Count windows displaying inven */
				if (window_flag[j] & (PW_INVEN)) ni++;

				/* Count windows displaying equip */
				if (window_flag[j] & (PW_EQUIP)) ne++;
			}

			/* Are we in the situation where toggling makes sense? */
			if ((ni && !ne) || (!ni && ne)) {
				if (player->upkeep->command_wrk == USE_EQUIP) {
					if ((ne && !toggle) || (ni && toggle)) {
						/* Main screen is equipment, so is subwindow */
						toggle_inven_equip();
						toggle = !toggle;
					}
				} else if (player->upkeep->command_wrk == USE_INVEN) {
					if ((ni && !toggle) || (ne && toggle)) {
						/* Main screen is inventory, so is subwindow */
						toggle_inven_equip();
						toggle = !toggle;
					}
				} else {
					/* Quiver or floor, go back to the original */
					if (toggle) {
						toggle_inven_equip();
						toggle = !toggle;
					}
				}
			}

			/* Redraw */
			player->upkeep->redraw |= (PR_INVEN | PR_EQUIP);

			/* Redraw windows */
			redraw_stuff(player);

			/* Save screen */
			screen_save();

			/* Build object list */
			wipe_obj_list();
			if (player->upkeep->command_wrk == USE_INVEN)
				build_obj_list(i2, player->upkeep->inven, tester_m, olist_mode);
			else if (player->upkeep->command_wrk == USE_EQUIP)
				build_obj_list(e2, NULL, tester_m, olist_mode);
			else if (player->upkeep->command_wrk == USE_QUIVER)
				build_obj_list(q2, player->upkeep->quiver, tester_m,olist_mode);
			else if (player->upkeep->command_wrk == USE_FLOOR)
				build_obj_list(f2, floor_list, tester_m, olist_mode);

			/* Show the prompt */
			menu_header();
			if (pmt) {
				prt(pmt, 0, 0);
				prt(header, 0, strlen(pmt) + 1);
			}

			/* No menu change request */
			newmenu = false;

			/* Get an item choice */
			*choice = item_menu(cmd, MAX(pmt ? strlen(pmt) : 0, 15), mode);

			/* Fix the screen */
			screen_load();

			/* Update */
			player->upkeep->redraw |= (PR_INVEN | PR_EQUIP);
			redraw_stuff(player);

			/* Clear the prompt line */
			prt("", 0, 0);

			/* We have a selection, or are backing out */
			if (*choice || !newmenu) {
				if (toggle) toggle_inven_equip();
				break;
			}
		}
	} else {
		/* Warning if needed */
		if (str) msg("%s", str);
		*choice = NULL;
	}

	/* Clean up */
	player->upkeep->command_wrk = 0;
	mem_free(floor_list);

	/* Result */
	return (*choice != NULL) ? true : false;
}
コード例 #18
0
ファイル: ui-player.c プロジェクト: bensemmler/angband
static void display_resistance_panel(const struct player_flag_record *rec,
									size_t size, const region *bounds) 
{
	size_t i;
	int j;
	int col = bounds->col;
	int row = bounds->row;
	int res_cols = 5 + 2 + player->body.count;

	Term_putstr(col, row++, res_cols, COLOUR_WHITE, "      abcdefghijkl@");
	for (i = 0; i < size - 3; i++, row++) {
		byte name_attr = COLOUR_WHITE;
		Term_gotoxy(col + 6, row);

		/* Repeated extraction of flags is inefficient but more natural */
		for (j = 0; j <= player->body.count; j++) {
			struct object *obj;
			bitflag f[OF_SIZE];

			byte attr = COLOUR_WHITE | (j % 2) * 8; /* alternating columns */
			char sym = '.';

			bool res = false, imm = false, vul = false, rune = false;
			bool timed = false;
			bool known = false;

			/* Wipe flagset */
			of_wipe(f);

			/* Get the object or player info */
			obj = j < player->body.count ? slot_object(player, j) : NULL;
			if (j < player->body.count && obj) {
				/* Get known properties */
				object_flags_known(obj, f);
				if (rec[i].element != -1)
					known = object_element_is_known(obj, rec[i].element);
				else if (rec[i].flag != -1)
					known = object_flag_is_known(obj, rec[i].flag);
				else
					known = true;
			} else if (j == player->body.count) {
				player_flags(player, f);
				known = true;

				/* Timed flags only in the player column */
				if (rec[i].tmd_flag >= 0) {
	 				timed = player->timed[rec[i].tmd_flag] ? true : false;
					/* There has to be one special case... */
					if ((rec[i].tmd_flag == TMD_AFRAID) &&
						(player->timed[TMD_TERROR]))
						timed = true;
				}
			}

			/* Set which (if any) symbol and color are used */
			if (rec[i].mod != -1) {
				if (j != player->body.count)
					res = (obj && (obj->modifiers[rec[i].mod] != 0));
				else {
					/* Messy special cases */
					if (rec[i].mod == OBJ_MOD_INFRA)
						res = (player->race->infra > 0);
					if (rec[i].mod == OBJ_MOD_TUNNEL)
						res = (player->race->r_skills[SKILL_DIGGING] > 0);
				}
				rune = (player->obj_k->modifiers[rec[i].mod] == 1);
			} else if (rec[i].flag != -1) {
				res = of_has(f, rec[i].flag);
				rune = of_has(player->obj_k->flags, rec[i].flag);
			} else if (rec[i].element != -1) {
				if (j != player->body.count) {
					imm = obj && known &&
						(obj->el_info[rec[i].element].res_level == 3);
					res = obj && known &&
						(obj->el_info[rec[i].element].res_level == 1);
					vul = obj && known &&
						(obj->el_info[rec[i].element].res_level == -1);
				} else {
					imm = player->race->el_info[rec[i].element].res_level == 3;
					res = player->race->el_info[rec[i].element].res_level == 1;
					vul = player->race->el_info[rec[i].element].res_level == -1;
				}
				rune = (player->obj_k->el_info[rec[i].element].res_level == 1);
			}

			/* Set the symbols and print them */
			if (imm) name_attr = COLOUR_GREEN;
			else if (!rune) name_attr = COLOUR_SLATE;
			else if (res && (name_attr != COLOUR_GREEN))
				name_attr = COLOUR_L_BLUE;

			if (vul) sym = '-';
			else if (imm) sym = '*';
			else if (res) sym = '+';
			else if (timed) { sym = '!'; attr = COLOUR_L_GREEN; }
			else if ((j < player->body.count) && obj && !known && !rune)
				sym = '?';

			Term_addch(attr, sym);
		}
		Term_putstr(col, row, 6, name_attr, format("%5s:", rec[i].name));
	}
	Term_putstr(col, row++, res_cols, COLOUR_WHITE, "      abcdefghijkl@");

	/* Equippy */
	display_player_equippy(row++, col + 6);
}
コード例 #19
0
void ResourceModel::fillMaterialInfo(Lumix::Material* material, Node& node)
{
	auto object = Object<Lumix::Material>(material, &node);
	node.m_getter = [material]() -> QVariant
	{
		return material->getPath().c_str();
	};
	node.m_name = "Material";
	object.getNode().onCreateEditor = [this, material](
		QWidget* parent, const QStyleOptionViewItem&) -> QWidget*
	{
		auto* widget = new QWidget(parent);
		auto* layout = new QHBoxLayout(widget);
		layout->setContentsMargins(0, 0, 0, 0);
		auto* label = new QLabel(material->getPath().c_str(), widget);
		layout->addWidget(label);
		layout->addStretch();

		QPushButton* button = new QPushButton("Save", widget);
		connect(button,
				&QPushButton::clicked,
				[this, material]()
				{
					saveMaterial(material);
				});
		layout->addWidget(button);

		return widget;
	};
	object.getNode().enablePeristentEditor();
	object.property("Alpha cutout",
					&Lumix::Material::isAlphaCutout,
					&Lumix::Material::enableAlphaCutout)
		.property("Backface culling",
				  &Lumix::Material::isBackfaceCulling,
				  &Lumix::Material::enableBackfaceCulling)
		.property("Shadow receiver",
				  &Lumix::Material::isShadowReceiver,
				  &Lumix::Material::enableShadowReceiving)
		.property("Shininess",
				  &Lumix::Material::getShininess,
				  &Lumix::Material::setShininess)
		.propertyColor("Specular",
					   &Lumix::Material::getSpecular,
					   &Lumix::Material::setSpecular)
		.property(
			"Z test", &Lumix::Material::isZTest, &Lumix::Material::enableZTest)
		.property("Shader",
				  [](Lumix::Material* material) -> QVariant
				  {
					  return material->getShader()
								 ? material->getShader()->getPath().c_str()
								 : "";
				  },
				  [this](Lumix::Material* material, QVariant value)
				  {
					  setMaterialShader(material, value.toString());
				  });
	auto shader_node = object.getNode().m_children.back();
	shader_node->enablePeristentEditor();
	shader_node->onCreateEditor = [shader_node](QWidget* parent,
												const QStyleOptionViewItem&)
	{
		auto input = new FileInput(parent);
		input->setValue(shader_node->m_getter().toString());
		input->connect(input,
					   &FileInput::valueChanged,
					   [shader_node, input]()
					   {
						   shader_node->m_setter(input->value());
					   });
		return input;
	};

	for (int i = 0; i < material->getUniformCount(); ++i)
	{
		auto& uniform = material->getUniform(i);
		QString name = uniform.m_name;
		object.property(uniform.m_name,
						[name](Lumix::Material* material) -> QVariant
						{
							Lumix::Material::Uniform* uniform =
								getMaterialUniform(material, name);
							if (uniform)
							{
								switch (uniform->m_type)
								{
									case Lumix::Material::Uniform::FLOAT:
										return uniform->m_float;
								}
							}
							return QVariant();
						},
						[name](Lumix::Material* material, const QVariant& value)
						{
							Lumix::Material::Uniform* uniform =
								getMaterialUniform(material, name);
							if (uniform)
							{
								switch (uniform->m_type)
								{
									case Lumix::Material::Uniform::FLOAT:
										uniform->m_float = value.toFloat();
										break;
								}
							}
						});
	}

	for (int i = 0; material->getShader() &&
					i < material->getShader()->getTextureSlotCount();
		 ++i)
	{
		const auto& slot = material->getShader()->getTextureSlot(i);
		Object<const Lumix::Shader::TextureSlot> slot_object(
			&slot, &object.getNode().addChild(slot.m_name));
		auto& node = slot_object.getNode();
		auto texture = material->getTexture(i);
		if (texture)
		{
			fillTextureInfo(texture, node);
		}
		node.m_name = slot.m_name;
		node.m_getter = [texture]() -> QVariant
		{
			return texture ? texture->getPath().c_str() : "";
		};
		node.onCreateEditor = [&node, i, texture, material](
			QWidget* parent, const QStyleOptionViewItem&) -> QWidget*
		{
			auto input = new FileInput(parent);
			input->setValue(texture ? texture->getPath().c_str() : "");
			input->connect(input,
						   &FileInput::valueChanged,
						   [&node, input]()
						   {
							   node.m_setter(input->value());
						   });
			return input;
		};
		node.m_setter = [material, i](const QVariant& value)
		{
			if (value.isValid())
			{
				material->setTexturePath(
					i, Lumix::Path(value.toString().toLatin1().data()));
			}
		};
		node.enablePeristentEditor();
	}
}
コード例 #20
0
ファイル: obj-info.c プロジェクト: lhz/angband
/**
 * Gets information about the average damage/turn that can be inflicted if
 * the player wields the given weapon.
 *
 * Fills in the damage against normal adversaries in `normal_damage`, as well
 * as the slays on the weapon in slay_list[] and corresponding damages in 
 * slay_damage[].  These must both be at least SL_MAX long to be safe.
 * `nonweap_slay` is set to whether other items being worn could add to the
 * damage done by branding attacks.
 *
 * Returns the number of slays populated in slay_list[] and slay_damage[].
 *
 * Note that the results are meaningless if called on a fake ego object as
 * the actual ego may have different properties.
 */
static bool obj_known_damage(const struct object *obj, int *normal_damage,
							 int *brand_damage, int *slay_damage,
							 bool *nonweap_slay)
{
	int i;
	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;
	bool *total_brands;
	bool *total_slays;
	bool has_brands_or_slays = false;

	struct object *bow = equipped_item_by_slot_name(player, "shooting");
	bool weapon = tval_is_melee_weapon(obj);
	bool ammo   = (player->state.ammo_tval == obj->tval) && (bow);
	int melee_adj_mult = ammo ? 0 : 1;
	int multiplier = 1;

	struct player_state state;
	int weapon_slot = slot_by_name(player, "weapon");
	struct object *current_weapon = slot_object(player, weapon_slot);

	/* Pretend we're wielding the object if it's a weapon */
	if (weapon)
		player->body.slots[weapon_slot].obj = (struct object *) obj;

	/* Calculate the player's hypothetical state */
	memcpy(&state, &player->state, sizeof(state));
	state.stat_ind[STAT_STR] = 0; //Hack - NRM
	state.stat_ind[STAT_DEX] = 0; //Hack - NRM
	calc_bonuses(player, &state, true, false);

	/* Stop pretending */
	player->body.slots[weapon_slot].obj = current_weapon;

	/* Finish if dice not known */
	dice = obj->known->dd;
	sides = obj->known->ds;
	if (!dice || !sides) return false;

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

	if (weapon)	{
		xtra_postcrit = state.to_d * 10;
		xtra_precrit += obj->known->to_d * 10;
		plus += obj->known->to_h;

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

		old_blows = state.num_blows;
	} else { /* Ammo */
		plus += obj->known->to_h;

		calculate_missile_crits(&player->state, obj->weight, plus, &crit_mult,
								&crit_add, &crit_div);

		dam += (obj->known->to_d * 10);
		dam += (bow->known->to_d * 10);
	}

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

	/* Get the brands */
	total_brands = mem_zalloc(z_info->brand_max * sizeof(bool));
	copy_brands(&total_brands, obj->known->brands);
	if (ammo && bow->known)
		copy_brands(&total_brands, bow->known->brands);

	/* Get the slays */
	total_slays = mem_zalloc(z_info->slay_max * sizeof(bool));
	copy_slays(&total_slays, obj->known->slays);
	if (ammo && bow->known)
		copy_slays(&total_slays, bow->known->slays);

	/* Melee weapons may get slays and brands from other items */
	*nonweap_slay = false;
	if (weapon)	{
		for (i = 2; i < player->body.count; i++) {
			struct object *slot_obj = slot_object(player, i);
			if (!slot_obj)
				continue;

			if (slot_obj->known->brands || slot_obj->known->slays)
				*nonweap_slay = true;
			else
				continue;

			/* Replace the old lists with new ones */
			copy_brands(&total_brands, slot_obj->known->brands);
			copy_slays(&total_slays, slot_obj->known->slays);
		}
	}

	/* Get damage for each brand on the objects */
	for (i = 1; i < z_info->brand_max; i++) {
		/* Must have the brand */
		if (total_brands[i])
			has_brands_or_slays = true;
		else
			continue;

		/* Include bonus damage and brand in stated average */
		total_dam = dam * (multiplier + brands[i].multiplier - 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 *= player->state.num_shots;

		brand_damage[i] = total_dam;
	}

	/* Get damage for each slay on the objects */
	for (i = 1; i < z_info->slay_max; i++) {
		/* Must have the slay */
		if (total_slays[i])
			has_brands_or_slays = true;
		else
			continue;

		/* Include bonus damage and slay in stated average */
		total_dam = dam * (multiplier + slays[i].multiplier - 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 *= player->state.num_shots;

		slay_damage[i] = total_dam;
	}

	/* 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 *= player->state.num_shots;

	*normal_damage = total_dam;

	mem_free(total_brands);
	mem_free(total_slays);
	return has_brands_or_slays;
}
コード例 #21
0
ファイル: obj-gear.c プロジェクト: fe051/angband
/**
 * Acid has hit the player, attempt to affect some armor.
 *
 * Note that the "base armor" of an object never changes.
 * If any armor is damaged (or resists), the player takes less damage.
 */
int minus_ac(struct player *p)
{
	int i, count = 0;
	struct object *obj = NULL;

	char o_name[80];

	/* Avoid crash during monster power calculations */
	if (!p->gear) return false;

	/* Count the armor slots */
	for (i = 0; i < player->body.count; i++) {
		/* Ignore non-armor */
		if (slot_type_is(i, EQUIP_WEAPON)) continue;
		if (slot_type_is(i, EQUIP_BOW)) continue;
		if (slot_type_is(i, EQUIP_RING)) continue;
		if (slot_type_is(i, EQUIP_AMULET)) continue;
		if (slot_type_is(i, EQUIP_LIGHT)) continue;

		/* Add */
		count++;
	}

	/* Pick one at random */
	for (i = player->body.count - 1; i >= 0; i--) {
		/* Ignore non-armor */
		if (slot_type_is(i, EQUIP_WEAPON)) continue;
		if (slot_type_is(i, EQUIP_BOW)) continue;
		if (slot_type_is(i, EQUIP_RING)) continue;
		if (slot_type_is(i, EQUIP_AMULET)) continue;
		if (slot_type_is(i, EQUIP_LIGHT)) continue;

		if (one_in_(count--)) break;
	}

	/* Get the item */
	obj = slot_object(player, i);

	/* Nothing to damage */
	if (!obj) return (false);

	/* No damage left to be done */
	if (obj->ac + obj->to_a <= 0) return (false);

	/* Describe */
	object_desc(o_name, sizeof(o_name), obj, ODESC_BASE);

	/* Object resists */
	if (obj->el_info[ELEM_ACID].flags & EL_INFO_IGNORE) {
		msg("Your %s is unaffected!", o_name);
		return (true);
	}

	/* Message */
	msg("Your %s is damaged!", o_name);

	/* Damage the item */
	obj->to_a--;
	if (p->obj_k->to_a)
		obj->known->to_a = obj->to_a;

	p->upkeep->update |= (PU_BONUS);
	p->upkeep->redraw |= (PR_EQUIP);

	/* Item was damaged */
	return (true);
}
コード例 #22
0
ファイル: obj-info.c プロジェクト: Chillbon/angband
/**
 * Gets information about the number of blows possible for the player with
 * the given object.
 *
 * Fills in whether the object is too_heavy to wield effectively,
 * and the possible_blows[] information of .str_plus and .dex_plus needed
 * to achieve the approximate number of blows in centiblows. 
 *
 * `max_blows` must be at least 1 to hold the current number of blows
 * `possible_blows` must be at least [`max_blows`] in size, and will be limited
 * to that number of entries.  The theoretical maximum is STAT_RANGE * 2 if
 * an extra blow/speed boost was given for each combination of STR and DEX.
 *
 * Returns the number of entries made in the possible_blows[] table, or 0
 * if the object is not a weapon.
 *
 * Note that the results are meaningless if called on a fake ego object as
 * the actual ego may have different properties.
 */
static int obj_known_blows(const struct object *obj, int max_num,
						   struct blow_info possible_blows[])
{
	int str_plus, dex_plus, old_blows = 0, new_blows, extra_blows;
	int str_faster = -1, str_done = -1;
	int dex_plus_bound;
	int str_plus_bound;
	int i;

	struct player_state state;

	int weapon_slot = slot_by_name(player, "weapon");
	struct object *current_weapon = slot_object(player, weapon_slot);
	int num = 0;

	/* Not a weapon - no blows! */
	if (!tval_is_melee_weapon(obj)) return 0;

	/* Pretend we're wielding the object */
	player->body.slots[weapon_slot].obj = (struct object *) obj;

	/* Calculate the player's hypothetical state */
	calc_bonuses(player, &state, true, false);

	/* Stop pretending */
	player->body.slots[weapon_slot].obj = current_weapon;

	/* First entry is always the current num of blows. */
	possible_blows[num].str_plus = 0;
	possible_blows[num].dex_plus = 0;
	possible_blows[num].centiblows = state.num_blows;
	num++;

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

	/* Start with blows from the weapon being examined */
	if (object_this_mod_is_visible(obj, OBJ_MOD_BLOWS))
		extra_blows += obj->modifiers[OBJ_MOD_BLOWS];

	/* Then we need to look for extra blows on other items, as
	 * state does not track these */
	for (i = 0; i < player->body.count; i++) {
		struct object *helper = slot_object(player, i);

		if ((i == slot_by_name(player, "weapon")) || !helper || !helper->kind)
			continue;

		if (object_this_mod_is_visible(helper, OBJ_MOD_BLOWS))
			extra_blows += helper->modifiers[OBJ_MOD_BLOWS];
	}

	dex_plus_bound = STAT_RANGE - state.stat_ind[STAT_DEX];
	str_plus_bound = STAT_RANGE - state.stat_ind[STAT_STR];

	/* 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++) {
			if (num == max_num)
				return num;

			state.stat_ind[STAT_STR] += str_plus;
			state.stat_ind[STAT_DEX] += dex_plus;
			new_blows = calc_blows(player, obj, &state, extra_blows);
			state.stat_ind[STAT_STR] -= str_plus;
			state.stat_ind[STAT_DEX] -= dex_plus;

			/* 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)) {
				possible_blows[num].str_plus = str_plus;
				possible_blows[num].dex_plus = dex_plus;
				possible_blows[num].centiblows = new_blows / 10;
				possible_blows[num].centiblows *= 10;
				num++;

				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)) {
				possible_blows[num].str_plus = str_plus;
				possible_blows[num].dex_plus = dex_plus;
				possible_blows[num].centiblows = new_blows;
				num++;

				str_faster = str_plus;
			}
		}
	}

	return num;
}
コード例 #23
0
ファイル: obj-info.c プロジェクト: lhz/angband
/**
 * Gets information about the number of blows possible for the player with
 * the given object.
 *
 * Fills in whether the object is too heavy to wield effectively,
 * and the possible_blows[] information of .str_plus and .dex_plus needed
 * to achieve the approximate number of blows in centiblows. 
 *
 * `max_blows` must be at least 1 to hold the current number of blows
 * `possible_blows` must be at least [`max_blows`] in size, and will be limited
 * to that number of entries.  The theoretical maximum is STAT_RANGE * 2 if
 * an extra blow/speed boost was given for each combination of STR and DEX.
 *
 * Returns the number of entries made in the possible_blows[] table, or 0
 * if the object is not a weapon.
 *
 * Note that the results are meaningless if called on a fake ego object as
 * the actual ego may have different properties.
 */
static int obj_known_blows(const struct object *obj, int max_num,
						   struct blow_info possible_blows[])
{
	int str_plus, dex_plus, old_blows = 0;
	int str_faster = -1, str_done = -1;
	int dex_plus_bound;
	int str_plus_bound;

	struct player_state state;

	int weapon_slot = slot_by_name(player, "weapon");
	struct object *current_weapon = slot_object(player, weapon_slot);
	int num = 0;

	/* Not a weapon - no blows! */
	if (!tval_is_melee_weapon(obj)) return 0;

	/* Pretend we're wielding the object */
	player->body.slots[weapon_slot].obj = (struct object *) obj;

	/* Calculate the player's hypothetical state */
	memcpy(&state, &player->state, sizeof(state));
	state.stat_ind[STAT_STR] = 0; //Hack - NRM
	state.stat_ind[STAT_DEX] = 0; //Hack - NRM
	calc_bonuses(player, &state, true, false);

	/* First entry is always the current num of blows. */
	possible_blows[num].str_plus = 0;
	possible_blows[num].dex_plus = 0;
	possible_blows[num].centiblows = state.num_blows;
	num++;

	/* Check to see if extra STR or DEX would yield extra blows */
	old_blows = state.num_blows;
	dex_plus_bound = STAT_RANGE - state.stat_ind[STAT_DEX];
	str_plus_bound = STAT_RANGE - state.stat_ind[STAT_STR];

	/* Re-calculate with increased stats */
	for (dex_plus = 0; dex_plus < dex_plus_bound; dex_plus++) {
		for (str_plus = 0; str_plus < str_plus_bound; str_plus++) {
			int new_blows = 0;

			/* Unlikely */
			if (num == max_num) {
				player->body.slots[weapon_slot].obj = current_weapon;
				return num;
			}

			state.stat_ind[STAT_STR] = str_plus; //Hack - NRM
			state.stat_ind[STAT_DEX] = dex_plus; //Hack - NRM
			calc_bonuses(player, &state, true, false);
			new_blows = state.num_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)) {
				possible_blows[num].str_plus = str_plus;
				possible_blows[num].dex_plus = dex_plus;
				possible_blows[num].centiblows = new_blows / 10;
				possible_blows[num].centiblows *= 10;
				num++;

				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)) {
				possible_blows[num].str_plus = str_plus;
				possible_blows[num].dex_plus = dex_plus;
				possible_blows[num].centiblows = new_blows;
				num++;

				str_faster = str_plus;
			}
		}
	}

	/* Stop pretending */
	player->body.slots[weapon_slot].obj = current_weapon;

	return num;
}