コード例 #1
0
ファイル: attack.c プロジェクト: SinorKirby/Anquestria
/**
 * This is a helper function used by do_cmd_throw and do_cmd_fire.
 *
 * It abstracts out the projectile path, display code, identify and clean up
 * logic, while using the 'attack' parameter to do work particular to each
 * kind of attack.
 */
static void ranged_helper(int item, int dir, int range, int shots, ranged_attack attack) {
	/* Get the ammo */
	object_type *o_ptr = object_from_item_idx(item);

	int i, j;
	byte missile_attr = object_attr(o_ptr);
	char missile_char = object_char(o_ptr);

	object_type object_type_body;
	object_type *i_ptr = &object_type_body;

	char o_name[80];

	int path_n;
	u16b path_g[256];

	int msec = op_ptr->delay_factor;

	/* Start at the player */
	int x = p_ptr->px;
	int y = p_ptr->py;

	/* Predict the "target" location */
	s16b ty = y + 99 * ddy[dir];
	s16b tx = x + 99 * ddx[dir];

	bool hit_target = FALSE;

	/* Check for target validity */
	if ((dir == 5) && target_okay()) {
		int taim;
		char msg[80];
		target_get(&tx, &ty);
		taim = distance(y, x, ty, tx);
		if (taim > range) {
			sprintf (msg, "Target out of range by %d squares. Fire anyway? ",
				taim - range);
			if (!get_check(msg)) return;
		}
	}

	/* Sound */
	sound(MSG_SHOOT);

	object_notice_on_firing(o_ptr);

	/* Describe the object */
	object_desc(o_name, sizeof(o_name), o_ptr, ODESC_FULL | ODESC_SINGULAR);

	/* Actually "fire" the object -- Take a partial turn */
	p_ptr->energy_use = (100 / shots);

	/* Calculate the path */
	path_n = project_path(path_g, range, y, x, ty, tx, 0);

	/* Hack -- Handle stuff */
	handle_stuff(p_ptr);

	/* Start at the player */
	x = p_ptr->px;
	y = p_ptr->py;

	/* Project along the path */
	for (i = 0; i < path_n; ++i) {
		int ny = GRID_Y(path_g[i]);
		int nx = GRID_X(path_g[i]);

		/* Hack -- Stop before hitting walls */
		if (!cave_floor_bold(ny, nx)) break;

		/* Advance */
		x = nx;
		y = ny;

		/* Only do visuals if the player can "see" the missile */
		if (player_can_see_bold(y, x)) {
			print_rel(missile_char, missile_attr, y, x);
			move_cursor_relative(y, x);

			Term_fresh();
			if (p_ptr->redraw) redraw_stuff(p_ptr);

			Term_xtra(TERM_XTRA_DELAY, msec);
			cave_light_spot(cave, y, x);

			Term_fresh();
			if (p_ptr->redraw) redraw_stuff(p_ptr);
		} else {
			/* Delay anyway for consistency */
			Term_xtra(TERM_XTRA_DELAY, msec);
		}

		/* Handle monster */
		if (cave->m_idx[y][x] > 0) break;
	}

	/* Try the attack on the monster at (x, y) if any */
	if (cave->m_idx[y][x] > 0) {
		monster_type *m_ptr = cave_monster(cave, cave->m_idx[y][x]);
		monster_race *r_ptr = &r_info[m_ptr->r_idx];
		int visible = m_ptr->ml;

		bool fear = FALSE;
		char m_name[80];
		const char *note_dies = monster_is_unusual(r_ptr) ? " is destroyed." : " dies.";

		struct attack_result result = attack(o_ptr, y, x);
		int dmg = result.dmg;
		u32b msg_type = result.msg_type;
		const char *hit_verb = result.hit_verb;

		if (result.success) {
			hit_target = TRUE;

			/* Get "the monster" or "it" */
			monster_desc(m_name, sizeof(m_name), m_ptr, 0);
		
			object_notice_attack_plusses(o_ptr);
		
			/* No negative damage; change verb if no damage done */
			if (dmg <= 0) {
				dmg = 0;
				hit_verb = "fail to harm";
			}
		
			if (!visible) {
				/* Invisible monster */
				msgt(MSG_SHOOT_HIT, "The %s finds a mark.", o_name);
			} else {
				/* Visible monster */
				if (msg_type == MSG_SHOOT_HIT)
					msgt(MSG_SHOOT_HIT, "The %s %s %s.", o_name, hit_verb, m_name);
				else if (msg_type == MSG_HIT_GOOD) {
					msgt(MSG_HIT_GOOD, "The %s %s %s. %s", o_name, hit_verb, m_name, "It was a good hit!");
				} else if (msg_type == MSG_HIT_GREAT) {
					msgt(MSG_HIT_GREAT, "The %s %s %s. %s", o_name, hit_verb, m_name,
						 "It was a great hit!");
				} else if (msg_type == MSG_HIT_SUPERB) {
					msgt(MSG_HIT_SUPERB, "The %s %s %s. %s", o_name, hit_verb, m_name,
						 "It was a superb hit!");
				}
		
				/* Track this monster */
				if (m_ptr->ml) monster_race_track(m_ptr->r_idx);
				if (m_ptr->ml) health_track(p_ptr, cave->m_idx[y][x]);
			}
		
			/* Complex message */
			if (p_ptr->wizard)
				msg("You do %d (out of %d) damage.", dmg, m_ptr->hp);
		
			/* Hit the monster, check for death */
			if (!mon_take_hit(cave->m_idx[y][x], dmg, &fear, note_dies)) {
				message_pain(cave->m_idx[y][x], dmg);
				if (fear && m_ptr->ml)
					add_monster_message(m_name, cave->m_idx[y][x], MON_MSG_FLEE_IN_TERROR, TRUE);
			}
		}
	}

	/* Obtain a local object */
	object_copy(i_ptr, o_ptr);
	object_split(i_ptr, o_ptr, 1);

	/* See if the ammunition broke or not */
	j = breakage_chance(i_ptr, hit_target);

	/* Drop (or break) near that location */
	drop_near(cave, i_ptr, j, y, x, TRUE);

	if (item >= 0) {
		/* The ammo is from the inventory */
		inven_item_increase(item, -1);
		inven_item_describe(item);
		inven_item_optimize(item);
	} else {
		/* The ammo is from the floor */
		floor_item_increase(0 - item, -1);
		floor_item_optimize(0 - item);
	}
}
コード例 #2
0
ファイル: wizard2.c プロジェクト: mjdrinen/FAangband
/**
 * Query the dungeon
 */
static void do_cmd_wiz_query(void)
{
    int py = p_ptr->py;
    int px = p_ptr->px;

    int y, x;

    char cmd;

    u16b mask = 0x00;


    /* Get a "debug command" */
    if (!get_com("Debug Command Query: ", &cmd))
        return;

    /* Extract a flag */
    switch (cmd) {
    case '0':
        mask = (1 << 0);
        break;
    case '1':
        mask = (1 << 1);
        break;
    case '2':
        mask = (1 << 2);
        break;
    case '3':
        mask = (1 << 3);
        break;
    case '4':
        mask = (1 << 4);
        break;
    case '5':
        mask = (1 << 5);
        break;
    case '6':
        mask = (1 << 6);
        break;
    case '7':
        mask = (1 << 7);
        break;

    case 'm':
        mask |= (CAVE_MARK);
        break;
    case 'g':
        mask |= (CAVE_GLOW);
        break;
    case 'r':
        mask |= (CAVE_ROOM);
        break;
    case 'i':
        mask |= (CAVE_ICKY);
        break;
    case 's':
        mask |= (CAVE_SEEN);
        break;
    case 'v':
        mask |= (CAVE_VIEW);
        break;
    case 't':
        mask |= (CAVE_TEMP);
        break;
    case 'w':
        mask |= (CAVE_WALL);
        break;
    }

    /* Scan map */
    for (y = Term->offset_y; y <= Term->offset_y + SCREEN_HGT; y++) {
        for (x = Term->offset_x; x <= Term->offset_x + SCREEN_WID; x++) {
            byte a = TERM_RED;

            /* Given mask, show only those grids */
            if (mask && !(cave_info[y][x][0] & mask))
                continue;

            /* Given no mask, show unknown grids */
            if (!mask && (cave_info[y][x][0] & (CAVE_MARK)))
                continue;

            /* Color */
            if (cave_floor_bold(y, x))
                a = TERM_YELLOW;

            /* Display player/floors/walls */
            if ((y == py) && (x == px)) {
                print_rel('@', a, y, x);
            } else if (cave_floor_bold(y, x)) {
                print_rel('*', a, y, x);
            } else {
                print_rel('#', a, y, x);
            }
        }
    }

    /* Get keypress */
    msg_print("Press any key.");
    msg_print(NULL);

    /* Redraw map */
    prt_map();
}
コード例 #3
0
ファイル: wizard2.c プロジェクト: mjdrinen/FAangband
/**
 * Debug scent trails and noise bursts.
 */
static void do_cmd_wiz_hack_ben(void)
{

#ifdef MONSTER_FLOW

    char cmd;

    int py = p_ptr->py;
    int px = p_ptr->px;

    int i, y, x, y2, x2;

    /* Get a "debug command" */
    if (!get_com("Press 'S' for scent, 'N' for noise info: ", &cmd))
        return;


    /* Analyze the command */
    switch (cmd) {
    case 'S':
    case 's':
    {
        /* Update map */
        for (y = Term->offset_y; y <= Term->offset_y + SCREEN_HGT; y++) {
            for (x = Term->offset_x; x <= Term->offset_x + SCREEN_WID; x++) {
                byte a;

                int age = get_scent(y, x);

                /* Must have scent */
                if (age == -1)
                    continue;

                /* Pretty colors by age */
                if (age > SMELL_STRENGTH)
                    a = TERM_L_DARK;

                else if (age < 10)
                    a = TERM_BLUE;
                else if (age < 20)
                    a = TERM_L_BLUE;
                else if (age < 30)
                    a = TERM_GREEN;
                else if (age < 40)
                    a = TERM_L_GREEN;
                else if (age < 50)
                    a = TERM_YELLOW;
                else if (age < 60)
                    a = TERM_ORANGE;
                else if (age < 70)
                    a = TERM_L_RED;
                else
                    a = TERM_RED;


                /* Display player/floors/walls */
                if ((y == py) && (x == px)) {
                    print_rel('@', a, y, x);
                } else {
                    print_rel('0' + (age % 10), a, y, x);
                }
            }
        }

        /* Prompt */
        prt("Scent ages", 0, 0);

        /* Wait for a keypress */
        (void) inkey();

        /* Redraw map */
        prt_map();

        break;

    }

    case 'N':
    case 'n':
    {

        /* Get a "debug command" */
        if (!get_com
                ("Press 'D' for direction of flow, 'C' for actual cost values: ",
                 &cmd))
            return;

        if ((cmd == 'D') || (cmd == 'd')) {
            /* Update map */
            for (y = Term->offset_y; y <= Term->offset_y + SCREEN_HGT; y++) {
                for (x = Term->offset_x; x <= Term->offset_x + SCREEN_WID; x++) {
                    int lowest_cost = cave_cost[y][x];
                    int dir = -1;
                    int cost;

                    if (lowest_cost == 0)
                        continue;

                    for (i = 0; i < 8; i++) {
                        /* Get the location */
                        y2 = y + ddy_ddd[i];
                        x2 = x + ddx_ddd[i];

                        cost = cave_cost[y2][x2];
                        if (!cost)
                            continue;

                        /* If this grid's scent is younger, save it */
                        if (lowest_cost > cost)
                            lowest_cost = cost;

                        /* If it isn't, look elsewhere */
                        else
                            continue;

                        /* Save this direction */
                        dir = i;
                    }

                    /* If we didn't find any younger scent, print a '5' */
                    if (dir == -1)
                        print_rel('5', TERM_YELLOW, y, x);

                    /* Otherwise, convert to true direction and print */
                    else {
                        i = ddd[dir];
                        print_rel('0' + i, TERM_L_BLUE, y, x);
                    }
                }
            }

            /* Prompt */
            prt("Directions given to advancing monsters using noise info",
                0, 0);

            /* Wait for a keypress */
            (void) inkey();

            /* Redraw map */
            prt_map();
        }

        /* Actual cost values */
        else {
            int j;

            for (i = cost_at_center - 2; i <= 100 + NOISE_STRENGTH; ++i) {
                /* First show grids with no scent */
                if (i == cost_at_center - 2)
                    j = 0;

                /* Then show specially marked grids (bug-checking) */
                else if (i == cost_at_center - 1)
                    j = 255;

                /* Then show standard grids */
                else
                    j = i;

                /* Update map */
                for (y = Term->offset_y; y <= Term->offset_y + SCREEN_HGT; y++) {
                    for (x = Term->offset_x; x <= Term->offset_x + SCREEN_WID; x++) {
                        byte a = TERM_YELLOW;

                        /* Display proper cost */
                        if (cave_cost[y][x] != j)
                            continue;

                        /* Display player/floors/walls */
                        if ((y == py) && (x == px)) {
                            print_rel('@', a, y, x);
                        } else if (cave_floor_bold(y, x)) {
                            print_rel('*', a, y, x);
                        } else {
                            print_rel('#', a, y, x);
                        }
                    }
                }

                /* Prompt */
                if (j == 0) {
                    prt("Grids with no scent", 0, 0);
                } else if (j == 255) {
                    prt("Specially marked grids", 0, 0);
                } else {
                    prt(format("Depth %d: ", j), 0, 0);
                }

                /* Get key */
                if (inkey() == ESCAPE)
                    break;

                /* Redraw map */
                prt_map();
            }
        }

        break;
    }

    default:
    {
        break;
    }
    }

    /* Done */
    prt("", 0, 0);

    /* Redraw map */
    prt_map();

#else				/* MONSTER_FLOW */

    /* Oops */
    msg_print("Monster flow is not included in this copy of the game.");

#endif				/* MONSTER_FLOW */

}
コード例 #4
0
ファイル: scout.c プロジェクト: poschengband/poschengband
static void _greater_whirlwind_attack_spell(int cmd, variant *res)
{
    switch (cmd)
    {
    case SPELL_NAME:
        var_set_string(res, "Greater Ambush");
        break;
    case SPELL_DESC:
        var_set_string(res, "Perform a massive ambush on nearby monsters.");
        break;
    case SPELL_CAST:
    {
        int              i, x, y;
        cave_type       *c_ptr;
        monster_type    *m_ptr;

/*       cba
        d218l
        e3@7k
        f456j
         ghi  */

        typedef struct _offset_t { int dx; int dy; } _offset;
        static _offset offsets[] = {
            { 0, -1},
            {-1, -1},
            {-1,  0},
            {-1,  1},
            { 0,  1},
            { 1,  1},
            { 1,  0},
            { 1, -1},
            { 1, -2},
            { 0, -2},
            {-1, -2},
            {-2, -1},
            {-2,  0},
            {-2,  1},
            {-1,  2},
            { 0,  2},
            { 1,  2},
            { 2,  1},
            { 2,  0},
            { 2, -1},
            { 0,  0}, /* sentinel */
        };

        for (i = 0;; i++)
        {
            _offset offset = offsets[i];
            if (offset.dx == 0 && offset.dy == 0) break;

            y = py + offset.dy;
            x = px + offset.dx;

            if (!in_bounds(y, x)) continue;
            if (!projectable(py, px, y, x)) continue;

            c_ptr = &cave[y][x];

            if (!c_ptr->m_idx) continue;

            m_ptr = &m_list[c_ptr->m_idx];

            if (m_ptr->ml || cave_have_flag_bold(y, x, FF_PROJECT))
            {
                int msec = delay_factor * delay_factor * delay_factor;

                if (panel_contains(y, x) && player_can_see_bold(y, x))
                {
                    char c = 0x30;
                    byte a = TERM_WHITE;

                    print_rel(c, a, y, x);
                    move_cursor_relative(y, x);
                    Term_fresh();
                    Term_xtra(TERM_XTRA_DELAY, msec);
                    lite_spot(y, x);
                    Term_fresh();
                }
                else
                    Term_xtra(TERM_XTRA_DELAY, msec);

                py_attack(y, x, 0);
            }
        }
        var_set_bool(res, TRUE);
        break;
    }
    default:
        default_spell(cmd, res);
        break;
    }
}