bool target_set_closest(int mode) { int y, x, m_idx; monster_type *m_ptr; char m_name[80]; bool visibility; struct point_set *targets; /* Cancel old target */ target_set_monster(0); /* Get ready to do targetting */ targets = target_set_interactive_prepare(mode); /* If nothing was prepared, then return */ if (point_set_size(targets) < 1) { msg("No Available Target."); point_set_dispose(targets); return FALSE; } /* Find the first monster in the queue */ y = targets->pts[0].y; x = targets->pts[0].x; m_idx = cave->m_idx[y][x]; /* Target the monster, if possible */ if ((m_idx <= 0) || !target_able(m_idx)) { msg("No Available Target."); point_set_dispose(targets); return FALSE; } /* Target the monster */ m_ptr = cave_monster(cave, m_idx); monster_desc(m_name, sizeof(m_name), m_ptr, 0x00); if (!(mode & TARGET_QUIET)) msg("%^s is targeted.", m_name); Term_fresh(); /* Set up target information */ monster_race_track(m_ptr->r_idx); health_track(p_ptr, cave->m_idx[y][x]); target_set_monster(m_idx); /* Visual cue */ Term_get_cursor(&visibility); (void)Term_set_cursor(TRUE); move_cursor_relative(y, x); Term_redraw_section(x, y, x, y); /* TODO: what's an appropriate amount of time to spend highlighting */ Term_xtra(TERM_XTRA_DELAY, 150); (void)Term_set_cursor(visibility); point_set_dispose(targets); return TRUE; }
/** * Set target to closest monster. */ bool target_set_closest(int mode) { int y, x; struct monster *mon; char m_name[80]; struct point_set *targets; /* Cancel old target */ target_set_monster(0); /* Get ready to do targetting */ targets = target_get_monsters(mode); /* If nothing was prepared, then return */ if (point_set_size(targets) < 1) { msg("No Available Target."); point_set_dispose(targets); return false; } /* Find the first monster in the queue */ y = targets->pts[0].y; x = targets->pts[0].x; mon = square_monster(cave, y, x); /* Target the monster, if possible */ if (!target_able(mon)) { msg("No Available Target."); point_set_dispose(targets); return false; } /* Target the monster */ monster_desc(m_name, sizeof(m_name), mon, MDESC_CAPITAL); if (!(mode & TARGET_QUIET)) msg("%s is targeted.", m_name); /* Set up target information */ monster_race_track(player->upkeep, mon->race); health_track(player->upkeep, mon); target_set_monster(mon); point_set_dispose(targets); return true; }
/** * Deletes all the monsters when the player leaves the level. * * This is an efficient method of simulating multiple calls to the * "delete_monster()" function, with no visual effects. * * Note that we must delete the objects the monsters are carrying, but we * do nothing with mimicked objects. */ void wipe_mon_list(struct chunk *c, struct player *p) { int m_idx; /* Delete all the monsters */ for (m_idx = cave_monster_max(c) - 1; m_idx >= 1; m_idx--) { struct monster *mon = cave_monster(c, m_idx); struct object *held_obj = mon ? mon->held_obj : NULL; /* Skip dead monsters */ if (!mon->race) continue; /* Delete all the objects */ if (held_obj) { /* Go through all held objects and check for artifacts */ struct object *obj = held_obj; while (obj) { if (obj->artifact && !(obj->known && obj->known->artifact)) obj->artifact->created = false; obj = obj->next; } object_pile_free(held_obj); } /* Reduce the racial counter */ mon->race->cur_num--; /* Monster is gone */ c->squares[mon->fy][mon->fx].mon = 0; /* Wipe the Monster */ memset(mon, 0, sizeof(struct monster)); } /* Reset "cave->mon_max" */ c->mon_max = 1; /* Reset "mon_cnt" */ c->mon_cnt = 0; /* Hack -- reset "reproducer" count */ num_repro = 0; /* Hack -- no more target */ target_set_monster(0); /* Hack -- no more tracking */ health_track(p->upkeep, 0); }
/** * Housekeeping on arriving on a new level */ void on_new_level(void) { /* Play ambient sound on change of level. */ play_ambient_sound(); /* Cancel the target */ target_set_monster(0); /* Cancel the health bar */ health_track(player->upkeep, NULL); /* Disturb */ disturb(player, 1); /* Track maximum player level */ if (player->max_lev < player->lev) player->max_lev = player->lev; /* Track maximum dungeon level */ if (player->max_depth < player->depth) player->max_depth = player->depth; /* Flush messages */ event_signal(EVENT_MESSAGE_FLUSH); /* Update display */ event_signal(EVENT_NEW_LEVEL_DISPLAY); /* Update player */ update_player_object_knowledge(player); player->upkeep->update |= (PU_BONUS | PU_HP | PU_SPELLS | PU_INVEN); player->upkeep->notice |= (PN_COMBINE | PN_SEARCH); notice_stuff(player); update_stuff(player); redraw_stuff(player); /* Refresh */ event_signal(EVENT_REFRESH); /* Announce (or repeat) the feeling */ if (player->depth) display_feeling(false); /* Give player minimum energy to start a new level, but do not reduce * higher value from savefile for level in progress */ if (player->energy < z_info->move_energy) player->energy = z_info->move_energy; }
/** * Move a monster from index i1 to index i2 in the monster list. */ static void compact_monsters_aux(int i1, int i2) { int y, x; struct monster *mon; struct object *obj; /* Do nothing */ if (i1 == i2) return; /* Old monster */ mon = cave_monster(cave, i1); y = mon->fy; x = mon->fx; /* Update the cave */ cave->squares[y][x].mon = i2; /* Update midx */ mon->midx = i2; /* Repair objects being carried by monster */ for (obj = mon->held_obj; obj; obj = obj->next) obj->held_m_idx = i2; /* Move mimicked objects (heh) */ if (mon->mimicked_obj) mon->mimicked_obj->mimicking_m_idx = i2; /* Hack -- Update the target */ if (target_get_monster() == mon) target_set_monster(cave_monster(cave, i2)); /* Hack -- Update the health bar */ if (player->upkeep->health_who == mon) player->upkeep->health_who = cave_monster(cave, i2); /* Hack -- move monster */ memcpy(cave_monster(cave, i2), cave_monster(cave, i1), sizeof(struct monster)); /* Hack -- wipe hole */ memset(cave_monster(cave, i1), 0, sizeof(struct monster)); }
/* checks if there is a visible monster in line-of-sight */ bool valid_target_exists(int mode) { int y, x, m_idx; /* Save target info */ s16b old_target_set = p_ptr->target_set; s16b old_target_who = p_ptr->target_who; s16b old_target_row = p_ptr->target_row; s16b old_target_col = p_ptr->target_col; /* Cancel old target */ target_set_monster(0); /* Get ready to do targetting */ target_set_interactive_prepare(mode); /* Find the first monster in the queue */ y = temp_y[0]; x = temp_x[0]; m_idx = cave_m_idx[y][x]; /* restore old target into */ p_ptr->target_set = old_target_set; p_ptr->target_who = old_target_who; p_ptr->target_row = old_target_row; p_ptr->target_col = old_target_col ; /* If nothing was prepared, then return */ if (temp_n < 1) { return FALSE; } /* Target the monster, if possible */ if ((m_idx <= 0) || !target_able(m_idx)) { return FALSE; } return (TRUE); }
/** * Deletes all the monsters when the player leaves the level. * * This is an efficient method of simulating multiple calls to the * "delete_monster()" function, with no visual effects. * * Note that we do not delete the objects the monsters are carrying; * that must be taken care of separately via wipe_o_list(). */ void wipe_mon_list(struct cave *c, struct player *p) { int m_idx; /* Delete all the monsters */ for (m_idx = cave_monster_max(cave) - 1; m_idx >= 1; m_idx--) { monster_type *m_ptr = cave_monster(cave, m_idx); monster_race *r_ptr = &r_info[m_ptr->r_idx]; /* Skip dead monsters */ if (!m_ptr->r_idx) continue; /* Hack -- Reduce the racial counter */ r_ptr->cur_num--; /* Monster is gone */ c->m_idx[m_ptr->fy][m_ptr->fx] = 0; /* Wipe the Monster */ (void)WIPE(m_ptr, monster_type); } /* Reset "cave->mon_max" */ cave->mon_max = 1; /* Reset "mon_cnt" */ cave->mon_cnt = 0; /* Hack -- reset "reproducer" count */ num_repro = 0; /* Hack -- no more target */ target_set_monster(0); /* Hack -- no more tracking */ health_track(p, 0); }
// Try to pick the most sensible target mode based on the mode static bool set_selected_target(int mode, int y, int x) { int m_idx = dungeon_info[y][x].monster_idx; if (mode & (TARGET_KILL | TARGET_PROBE)) { bool probing = (mode & (TARGET_PROBE)); if ((m_idx > 0) && target_able(m_idx, probing)) { health_track(m_idx); target_set_monster(m_idx, probing); } else target_set_location(y, x); return (TRUE); } if ((mode & (TARGET_TRAP)) && target_able_trap(y, x)) { target_set_location(y, x); return (TRUE); } // Always set location for target grid if (mode & (TARGET_GRID)) { target_set_location(y, x); return (TRUE); } if (!(mode & (TARGET_QUIET))) { message(QString("Illegal target!")); } return (FALSE); }
/** * Handle a textui mouseclick. */ static void textui_process_click(ui_event e) { int x, y; if (!OPT(mouse_movement)) return; y = KEY_GRID_Y(e); x = KEY_GRID_X(e); /* Check for a valid location */ if (!cave_in_bounds_fully(cave, y, x)) return; /* XXX show context menu here */ if ((p_ptr->py == y) && (p_ptr->px == x)) { if (e.mouse.mods & KC_MOD_SHIFT) { /* shift-click - cast magic */ if (e.mouse.button == 1) { textui_obj_cast(); } else if (e.mouse.button == 2) { Term_keypress('i',0); } } else if (e.mouse.mods & KC_MOD_CONTROL) { /* ctrl-click - use feature / use inventory item */ /* switch with default */ if (e.mouse.button == 1) { if (cave_isupstairs(cave, p_ptr->py, p_ptr->px)) cmd_insert(CMD_GO_UP); else if (cave_isdownstairs(cave, p_ptr->py, p_ptr->px)) cmd_insert(CMD_GO_DOWN); } else if (e.mouse.button == 2) { cmd_insert(CMD_USE_UNAIMED); } } else if (e.mouse.mods & KC_MOD_ALT) { /* alt-click - Search or show char screen */ /* XXX call a platform specific hook */ if (e.mouse.button == 1) { cmd_insert(CMD_SEARCH); } else if (e.mouse.button == 2) { Term_keypress('C',0); } } else { if (e.mouse.button == 1) { if (cave->o_idx[y][x]) { cmd_insert(CMD_PICKUP); } else { cmd_insert(CMD_HOLD); } } else if (e.mouse.button == 2) { // show a context menu context_menu_player(e.mouse.x, e.mouse.y); } } } else if (e.mouse.button == 1) { if (p_ptr->timed[TMD_CONFUSED]) { cmd_insert(CMD_WALK); } else { if (e.mouse.mods & KC_MOD_SHIFT) { /* shift-click - run */ cmd_insert(CMD_RUN); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(y,x)); /*if ((y-p_ptr->py >= -1) && (y-p_ptr->py <= 1) && (x-p_ptr->px >= -1) && (x-p_ptr->px <= 1)) { cmd_insert(CMD_JUMP); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(y,x)); } else { cmd_insert(CMD_RUN); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(y,x)); }*/ } else if (e.mouse.mods & KC_MOD_CONTROL) { /* control-click - alter */ cmd_insert(CMD_ALTER); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(y,x)); } else if (e.mouse.mods & KC_MOD_ALT) { /* alt-click - look */ if (target_set_interactive(TARGET_LOOK, x, y)) { msg("Target Selected."); } //cmd_insert(CMD_LOOK); //cmd_set_arg_point(cmd_get_top(), 0, y, x); } else { /* pathfind does not work well on trap detection borders, * so if the click is next to the player, force a walk step */ if ((y-p_ptr->py >= -1) && (y-p_ptr->py <= 1) && (x-p_ptr->px >= -1) && (x-p_ptr->px <= 1)) { cmd_insert(CMD_WALK); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(y,x)); } else { cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); } } } } else if (e.mouse.button == 2) { struct monster *m = cave_monster_at(cave, y, x); if (m && target_able(m)) { /* Set up target information */ monster_race_track(m->race); health_track(p_ptr, m); target_set_monster(m); } else { target_set_location(y,x); } if (e.mouse.mods & KC_MOD_SHIFT) { /* shift-click - cast spell at target */ if (textui_obj_cast_ret() >= 0) { cmd_set_arg_target(cmd_get_top(), 1, DIR_TARGET); } } else if (e.mouse.mods & KC_MOD_CONTROL) { /* control-click - fire at target */ cmd_insert(CMD_USE_AIMED); cmd_set_arg_target(cmd_get_top(), 1, DIR_TARGET); } else if (e.mouse.mods & KC_MOD_ALT) { /* alt-click - throw at target */ cmd_insert(CMD_THROW); cmd_set_arg_target(cmd_get_top(), 1, DIR_TARGET); } else { //msg("Target set."); /* see if the click was adjacent to the player */ if ((y-p_ptr->py >= -1) && (y-p_ptr->py <= 1) && (x-p_ptr->px >= -1) && (x-p_ptr->px <= 1)) { context_menu_cave(cave,y,x,1,e.mouse.x, e.mouse.y); } else { context_menu_cave(cave,y,x,0,e.mouse.x, e.mouse.y); } } } }
/* * Handle "target" and "look". * * Note that this code can be called from "get_aim_dir()". * * Currently, when "flag" is true, that is, when * "interesting" grids are being used, and a directional key is used, we * only scroll by a single panel, in the direction requested, and check * for any interesting grids on that panel. The "correct" solution would * actually involve scanning a larger set of grids, including ones in * panels which are adjacent to the one currently scanned, but this is * overkill for this function. XXX XXX * * Hack -- targetting/observing an "outer border grid" may induce * problems, so this is not currently allowed. * * The player can use the direction keys to move among "interesting" * grids in a heuristic manner, or the "space", "+", and "-" keys to * move through the "interesting" grids in a sequential manner, or * can enter "location" mode, and use the direction keys to move one * grid at a time in any direction. The "t" (set target) command will * only target a monster (as opposed to a location) if the monster is * target_able and the "interesting" mode is being used. * * The current grid is described using the "look" method above, and * a new command may be entered at any time, but note that if the * "TARGET_LOOK" bit flag is set (or if we are in "location" mode, * where "space" has no obvious meaning) then "space" will scan * through the description of the current grid until done, instead * of immediately jumping to the next "interesting" grid. This * allows the "target" command to retain its old semantics. * * The "*", "+", and "-" keys may always be used to jump immediately * to the next (or previous) interesting grid, in the proper mode. * * The "return" key may always be used to scan through a complete * grid description (forever). * * This command will cancel any old target, even if used from * inside the "look" command. * * * 'mode' is one of TARGET_LOOK or TARGET_KILL. * 'x' and 'y' are the initial position of the target to be highlighted, * or -1 if no location is specified. * Returns TRUE if a target has been successfully set, FALSE otherwise. */ bool target_set_interactive(int mode, int x, int y) { int i, d, m, t, bd; int wid, hgt, help_prompt_loc; bool done = FALSE; bool flag = TRUE; bool help = FALSE; ui_event_data query; /* If we haven't been given an initial location, start on the player. */ if (x == -1 || y == -1) { x = p_ptr->px; y = p_ptr->py; } /* If we /have/ been given an initial location, make sure we honour it by going into "free targetting" mode. */ else { flag = FALSE; } /* Cancel target */ target_set_monster(0); /* Cancel tracking */ /* health_track(0); */ /* Calculate the window location for the help prompt */ Term_get_size(&wid, &hgt); help_prompt_loc = hgt - 1; /* Display the help prompt */ prt("Press '?' for help.", help_prompt_loc, 0); /* Prepare the "temp" array */ target_set_interactive_prepare(mode); /* Start near the player */ m = 0; /* Interact */ while (!done) { /* Interesting grids */ if (flag && temp_n) { y = temp_y[m]; x = temp_x[m]; /* Adjust panel if needed */ if (adjust_panel_help(y, x, help)) { /* Handle stuff */ handle_stuff(); } /* Update help */ if (help) { bool good_target = ((cave_m_idx[y][x] > 0) && target_able(cave_m_idx[y][x])); target_display_help(good_target, !(flag && temp_n)); } /* Describe and Prompt */ query = target_set_interactive_aux(y, x, mode); /* Cancel tracking */ /* health_track(0); */ /* Assume no "direction" */ d = 0; /* If we click, move the target location to the click and switch to "free targetting" mode by unsetting 'flag'. This means we get some info about wherever we've picked. */ if (query.type == EVT_MOUSE) { x = KEY_GRID_X(query); y = KEY_GRID_Y(query); flag = FALSE; break; } else { /* Analyze */ switch (query.key) { case ESCAPE: case 'q': { done = TRUE; break; } case ' ': case '*': case '+': { if (++m == temp_n) m = 0; break; } case '-': { if (m-- == 0) m = temp_n - 1; break; } case 'p': { /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(); y = p_ptr->py; x = p_ptr->px; } case 'o': { flag = FALSE; break; } case 'm': { break; } case 't': case '5': case '0': case '.': { int m_idx = cave_m_idx[y][x]; if ((m_idx > 0) && target_able(m_idx)) { health_track(m_idx); target_set_monster(m_idx); done = TRUE; } else { bell("Illegal target!"); } break; } case 'g': { cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); done = TRUE; break; } case '?': { help = !help; /* Redraw main window */ p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); handle_stuff(); if (!help) prt("Press '?' for help.", help_prompt_loc, 0); break; } default: { /* Extract direction */ d = target_dir(query.key); /* Oops */ if (!d) bell("Illegal command for target mode!"); break; } } } /* Hack -- move around */ if (d) { int old_y = temp_y[m]; int old_x = temp_x[m]; /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d]); /* Scroll to find interesting grid */ if (i < 0) { int old_wy = Term->offset_y; int old_wx = Term->offset_x; /* Change if legal */ if (change_panel(d)) { /* Recalculate interesting grids */ target_set_interactive_prepare(mode); /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d]); /* Restore panel if needed */ if ((i < 0) && modify_panel(Term, old_wy, old_wx)) { /* Recalculate interesting grids */ target_set_interactive_prepare(mode); } /* Handle stuff */ handle_stuff(); } } /* Use interesting grid if found */ if (i >= 0) m = i; } } /* Arbitrary grids */ else { /* Update help */ if (help) { bool good_target = ((cave_m_idx[y][x] > 0) && target_able(cave_m_idx[y][x])); target_display_help(good_target, !(flag && temp_n)); } /* Describe and Prompt (enable "TARGET_LOOK") */ query = target_set_interactive_aux(y, x, mode | TARGET_LOOK); /* Cancel tracking */ /* health_track(0); */ /* Assume no direction */ d = 0; if (query.type == EVT_MOUSE) { /* We only target if we click somewhere where the cursor is already (i.e. a double-click without a time limit) */ if (KEY_GRID_X(query) == x && KEY_GRID_Y(query) == y) { /* Make an attempt to target the monster on the given square rather than the square itself (it seems this is the more likely intention of clicking on a monster). */ int m_idx = cave_m_idx[y][x]; if ((m_idx > 0) && target_able(m_idx)) { health_track(m_idx); target_set_monster(m_idx); } else { /* There is no monster, or it isn't targettable, so target the location instead. */ target_set_location(y, x); } done = TRUE; } else { /* Just move the cursor for now - another click will target. */ x = KEY_GRID_X(query); y = KEY_GRID_Y(query); } break; } else { /* Analyze the keypress */ switch (query.key) { case ESCAPE: case 'q': { done = TRUE; break; } case ' ': case '*': case '+': case '-': { break; } case 'p': { /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(); y = p_ptr->py; x = p_ptr->px; } case 'o': { break; } case 'm': { flag = TRUE; m = 0; bd = 999; /* Pick a nearby monster */ for (i = 0; i < temp_n; i++) { t = distance(y, x, temp_y[i], temp_x[i]); /* Pick closest */ if (t < bd) { m = i; bd = t; } } /* Nothing interesting */ if (bd == 999) flag = FALSE; break; } case 't': case '5': case '0': case '.': { target_set_location(y, x); done = TRUE; break; } case 'g': { cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); done = TRUE; break; } case '?': { help = !help; /* Redraw main window */ p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); handle_stuff(); if (!help) prt("Press '?' for help.", help_prompt_loc, 0); break; } default: { /* Extract a direction */ d = target_dir(query.key); /* Oops */ if (!d) bell("Illegal command for target mode!"); break; } } } /* Handle "direction" */ if (d) { int dungeon_hgt = (p_ptr->depth == 0) ? TOWN_HGT : DUNGEON_HGT; int dungeon_wid = (p_ptr->depth == 0) ? TOWN_WID : DUNGEON_WID; /* Move */ x += ddx[d]; y += ddy[d]; /* Slide into legality */ if (x >= dungeon_wid - 1) x--; else if (x <= 0) x++; /* Slide into legality */ if (y >= dungeon_hgt - 1) y--; else if (y <= 0) y++; /* Adjust panel if needed */ if (adjust_panel_help(y, x, help)) { /* Handle stuff */ handle_stuff(); /* Recalculate interesting grids */ target_set_interactive_prepare(mode); } } } } /* Forget */ temp_n = 0; /* Redraw as necessary */ if (help) { p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); } else { prt("", 0, 0); prt("", help_prompt_loc, 0); p_ptr->redraw |= (PR_DEPTH | PR_STATUS); } /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(); /* Failure to set target */ if (!target_set) return (FALSE); /* Success */ return (TRUE); }
/* * Handle "target" and "look". * * Note that this code can be called from "get_aim_dir()". * * Currently, when "flag" is true, that is, when * "interesting" grids are being used, and a directional key is used, we * only scroll by a single panel, in the direction requested, and check * for any interesting grids on that panel. The "correct" solution would * actually involve scanning a larger set of grids, including ones in * panels which are adjacent to the one currently scanned, but this is * overkill for this function. XXX XXX * * Hack -- targetting/observing an "outer border grid" may induce * problems, so this is not currently allowed. * * The player can use the direction keys to move among "interesting" * grids in a heuristic manner, or the "space", "+", and "-" keys to * move through the "interesting" grids in a sequential manner, or * can enter "location" mode, and use the direction keys to move one * grid at a time in any direction. The "t" (set target) command will * only target a monster (as opposed to a location) if the monster is * target_able and the "interesting" mode is being used. * * The current grid is described using the "look" method above, and * a new command may be entered at any time, but note that if the * "TARGET_LOOK" bit flag is set (or if we are in "location" mode, * where "space" has no obvious meaning) then "space" will scan * through the description of the current grid until done, instead * of immediately jumping to the next "interesting" grid. This * allows the "target" command to retain its old semantics. * * The "*", "+", and "-" keys may always be used to jump immediately * to the next (or previous) interesting grid, in the proper mode. * * The "return" key may always be used to scan through a complete * grid description (forever). * * This command will cancel any old target, even if used from * inside the "look" command. * * * 'mode' is one of TARGET_LOOK or TARGET_KILL. * 'x' and 'y' are the initial position of the target to be highlighted, * or -1 if no location is specified. * Returns TRUE if a target has been successfully set, FALSE otherwise. */ bool target_set_interactive(int mode, int x, int y) { int py = p_ptr->py; int px = p_ptr->px; int path_n; u16b path_g[256]; int i, d, m, t, bd; int wid, hgt, help_prompt_loc; bool done = FALSE; bool flag = TRUE; bool help = FALSE; struct keypress query; /* These are used for displaying the path to the target */ char path_char[MAX_RANGE]; byte path_attr[MAX_RANGE]; /* If we haven't been given an initial location, start on the player. */ if (x == -1 || y == -1) { x = p_ptr->px; y = p_ptr->py; } /* If we /have/ been given an initial location, make sure we honour it by going into "free targetting" mode. */ else { flag = FALSE; } /* Cancel target */ target_set_monster(0); /* Cancel tracking */ /* health_track(0); */ /* Calculate the window location for the help prompt */ Term_get_size(&wid, &hgt); help_prompt_loc = hgt - 1; /* Display the help prompt */ prt("Press '?' for help.", help_prompt_loc, 0); /* Prepare the "temp" array */ target_set_interactive_prepare(mode); /* Start near the player */ m = 0; /* Interact */ while (!done) { bool path_drawn = FALSE; /* Interesting grids */ if (flag && temp_n) { y = temp_y[m]; x = temp_x[m]; /* Adjust panel if needed */ if (adjust_panel_help(y, x, help)) handle_stuff(); /* Update help */ if (help) { bool good_target = (cave->m_idx[y][x] > 0) && target_able(cave->m_idx[y][x]); target_display_help(good_target, !(flag && temp_n)); } /* Find the path. */ path_n = project_path(path_g, MAX_RANGE, py, px, y, x, PROJECT_THRU); /* Draw the path in "target" mode. If there is one */ if (mode & (TARGET_KILL)) path_drawn = draw_path(path_n, path_g, path_char, path_attr, py, px); /* Describe and Prompt */ query = target_set_interactive_aux(y, x, mode); /* Remove the path */ if (path_drawn) load_path(path_n, path_g, path_char, path_attr); /* Cancel tracking */ /* health_track(0); */ /* Assume no "direction" */ d = 0; /* Analyze */ switch (query.code) { case ESCAPE: case 'q': { done = TRUE; break; } case ' ': case '*': case '+': { if (++m == temp_n) m = 0; break; } case '-': { if (m-- == 0) m = temp_n - 1; break; } case 'p': { /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(); y = p_ptr->py; x = p_ptr->px; } case 'o': { flag = FALSE; break; } case 'm': { break; } case 't': case '5': case '0': case '.': { int m_idx = cave->m_idx[y][x]; if ((m_idx > 0) && target_able(m_idx)) { health_track(p_ptr, m_idx); target_set_monster(m_idx); done = TRUE; } else { bell("Illegal target!"); } break; } case 'g': { cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); done = TRUE; break; } case '?': { help = !help; /* Redraw main window */ p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); handle_stuff(); if (!help) prt("Press '?' for help.", help_prompt_loc, 0); break; } default: { /* Extract direction */ d = target_dir(query); /* Oops */ if (!d) bell("Illegal command for target mode!"); break; } } /* Hack -- move around */ if (d) { int old_y = temp_y[m]; int old_x = temp_x[m]; /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d]); /* Scroll to find interesting grid */ if (i < 0) { int old_wy = Term->offset_y; int old_wx = Term->offset_x; /* Change if legal */ if (change_panel(d)) { /* Recalculate interesting grids */ target_set_interactive_prepare(mode); /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d]); /* Restore panel if needed */ if ((i < 0) && modify_panel(Term, old_wy, old_wx)) { /* Recalculate interesting grids */ target_set_interactive_prepare(mode); } /* Handle stuff */ handle_stuff(); } } /* Use interesting grid if found */ if (i >= 0) m = i; } } /* Arbitrary grids */ else { /* Update help */ if (help) { bool good_target = ((cave->m_idx[y][x] > 0) && target_able(cave->m_idx[y][x])); target_display_help(good_target, !(flag && temp_n)); } /* Find the path. */ path_n = project_path(path_g, MAX_RANGE, py, px, y, x, PROJECT_THRU); /* Draw the path in "target" mode. If there is one */ if (mode & (TARGET_KILL)) path_drawn = draw_path (path_n, path_g, path_char, path_attr, py, px); /* Describe and Prompt (enable "TARGET_LOOK") */ query = target_set_interactive_aux(y, x, mode | TARGET_LOOK); /* Remove the path */ if (path_drawn) load_path(path_n, path_g, path_char, path_attr); /* Cancel tracking */ /* health_track(0); */ /* Assume no direction */ d = 0; /* Analyze the keypress */ switch (query.code) { case ESCAPE: case 'q': { done = TRUE; break; } case ' ': case '*': case '+': case '-': { break; } case 'p': { /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(); y = p_ptr->py; x = p_ptr->px; } case 'o': { break; } case 'm': { flag = TRUE; m = 0; bd = 999; /* Pick a nearby monster */ for (i = 0; i < temp_n; i++) { t = distance(y, x, temp_y[i], temp_x[i]); /* Pick closest */ if (t < bd) { m = i; bd = t; } } /* Nothing interesting */ if (bd == 999) flag = FALSE; break; } case 't': case '5': case '0': case '.': { target_set_location(y, x); done = TRUE; break; } case 'g': { cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); done = TRUE; break; } case '?': { help = !help; /* Redraw main window */ p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); handle_stuff(); if (!help) prt("Press '?' for help.", help_prompt_loc, 0); break; } default: { /* Extract a direction */ d = target_dir(query); /* Oops */ if (!d) bell("Illegal command for target mode!"); break; } } /* Handle "direction" */ if (d) { int dungeon_hgt = (p_ptr->depth == 0) ? TOWN_HGT : DUNGEON_HGT; int dungeon_wid = (p_ptr->depth == 0) ? TOWN_WID : DUNGEON_WID; /* Move */ x += ddx[d]; y += ddy[d]; /* Slide into legality */ if (x >= dungeon_wid - 1) x--; else if (x <= 0) x++; /* Slide into legality */ if (y >= dungeon_hgt - 1) y--; else if (y <= 0) y++; /* Adjust panel if needed */ if (adjust_panel_help(y, x, help)) { /* Handle stuff */ handle_stuff(); /* Recalculate interesting grids */ target_set_interactive_prepare(mode); } } } } /* Forget */ temp_n = 0; /* Redraw as necessary */ if (help) { p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); } else { prt("", 0, 0); prt("", help_prompt_loc, 0); p_ptr->redraw |= (PR_DEPTH | PR_STATUS); } /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(); /* Failure to set target */ if (!target_set) return (FALSE); /* Success */ return (TRUE); }
/* * Handle "target" and "look". * * Note that this code can be called from "get_aim_dir()". * * Currently, when "flag" is true, that is, when * "interesting" grids are being used, and a directional key is used, we * only scroll by a single panel, in the direction requested, and check * for any interesting grids on that panel. The "correct" solution would * actually involve scanning a larger set of grids, including ones in * panels which are adjacent to the one currently scanned, but this is * overkill for this function. XXX XXX * * Hack -- targetting/observing an "outer border grid" may induce * problems, so this is not currently allowed. * * The player can use the direction keys to move among "interesting" * grids in a heuristic manner, or the "space", "+", and "-" keys to * move through the "interesting" grids in a sequential manner, or * can enter "location" mode, and use the direction keys to move one * grid at a time in any direction. The "t" (set target) command will * only target a monster (as opposed to a location) if the monster is * target_able and the "interesting" mode is being used. * * The current grid is described using the "look" method above, and * a new command may be entered at any time, but note that if the * "TARGET_LOOK" bit flag is set (or if we are in "location" mode, * where "space" has no obvious meaning) then "space" will scan * through the description of the current grid until done, instead * of immediately jumping to the next "interesting" grid. This * allows the "target" command to retain its old semantics. * * The "*", "+", and "-" keys may always be used to jump immediately * to the next (or previous) interesting grid, in the proper mode. * * The "return" key may always be used to scan through a complete * grid description (forever). * * This command will cancel any old target, even if used from * inside the "look" command. * * * 'mode' is one of TARGET_LOOK or TARGET_KILL. * 'x' and 'y' are the initial position of the target to be highlighted, * or -1 if no location is specified. * Returns TRUE if a target has been successfully set, FALSE otherwise. */ bool target_set_interactive(int mode, int x, int y) { int py = p_ptr->py; int px = p_ptr->px; int path_n; u16b path_g[256]; int i, d, m, t, bd; int wid, hgt, help_prompt_loc; bool done = FALSE; bool flag = TRUE; bool help = FALSE; //struct keypress query; ui_event press; /* These are used for displaying the path to the target */ wchar_t path_char[MAX_RANGE_LGE]; int path_attr[MAX_RANGE_LGE]; struct point_set *targets; /* If we haven't been given an initial location, start on the player. */ if (x == -1 || y == -1) { x = p_ptr->px; y = p_ptr->py; } /* If we /have/ been given an initial location, make sure we honour it by going into "free targetting" mode. */ else { flag = FALSE; } /* Cancel target */ target_set_monster(0); /* Cancel tracking */ /* health_track(NULL); */ /* Calculate the window location for the help prompt */ Term_get_size(&wid, &hgt); help_prompt_loc = hgt - 1; /* Display the help prompt */ prt("Press '?' for help.", help_prompt_loc, 0); /* Prepare the target set */ targets = target_set_interactive_prepare(mode); /* Start near the player */ m = 0; /* Interact */ while (!done) { bool path_drawn = FALSE; /* Interesting grids */ if (flag && point_set_size(targets)) { y = targets->pts[m].y; x = targets->pts[m].x; /* Adjust panel if needed */ if (adjust_panel_help(y, x, help)) handle_stuff(p_ptr); /* Update help */ if (help) { bool good_target = target_able(cave_monster_at(cave, y, x)); target_display_help(good_target, !(flag && point_set_size(targets))); } /* Find the path. */ path_n = project_path(path_g, MAX_RANGE, py, px, y, x, PROJECT_THRU); /* Draw the path in "target" mode. If there is one */ if (mode & (TARGET_KILL)) path_drawn = draw_path(path_n, path_g, path_char, path_attr, py, px); /* Describe and Prompt */ press = target_set_interactive_aux(y, x, mode); /* Remove the path */ if (path_drawn) load_path(path_n, path_g, path_char, path_attr); /* Cancel tracking */ /* health_track(NULL); */ /* Assume no "direction" */ d = 0; /* Analyze */ if (press.type == EVT_MOUSE) { if (press.mouse.button == 3) { /* give the target selection command */ press.mouse.button = 2; press.mouse.mods = KC_MOD_CONTROL; } if (press.mouse.button == 2) { y = KEY_GRID_Y(press);//.mouse.y; x = KEY_GRID_X(press);//.mouse.x; if (press.mouse.mods & KC_MOD_CONTROL) { /* same as keyboard target selection command below */ struct monster *m = cave_monster_at(cave, y, x); if (target_able(m)) { /* Set up target information */ monster_race_track(m->race); health_track(p_ptr, m); target_set_monster(m); done = TRUE; } else { bell("Illegal target!"); } } else if (press.mouse.mods & KC_MOD_ALT) { /* go to spot - same as 'g' command below */ cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); done = TRUE; } else { /* cancel look mode */ done = TRUE; } } else /*if (press.mouse.button == 3) { } else*/ { y = KEY_GRID_Y(press);//.mouse.y; x = KEY_GRID_X(press);//.mouse.x; if (cave->m_idx[y][x] || cave->o_idx[y][x]){// || cave->feat[y][x]&) { /* reset the flag, to make sure we stay in this mode if * something is actually there */ flag = FALSE; /* scan the interesting list and see if there in anything here */ for (i = 0; i < point_set_size(targets); i++) { if ((y == targets->pts[i].y) && (x == targets->pts[i].x)) { m = i; flag = TRUE; break; } } } else { flag = FALSE; } } } else switch (press.key.code) { case ESCAPE: case 'q': { done = TRUE; break; } case ' ': case '*': case '+': { if (++m == point_set_size(targets)) m = 0; break; } case '-': { if (m-- == 0) m = point_set_size(targets) - 1; break; } case 'p': { /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(p_ptr); y = p_ptr->py; x = p_ptr->px; } case 'o': { flag = FALSE; break; } case 'm': { break; } case 't': case '5': case '0': case '.': { struct monster *m = cave_monster_at(cave, y, x); if (target_able(m)) { health_track(p_ptr, m); target_set_monster(m); done = TRUE; } else { bell("Illegal target!"); } break; } case 'g': { cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); done = TRUE; break; } case '?': { help = !help; /* Redraw main window */ p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); handle_stuff(p_ptr); if (!help) prt("Press '?' for help.", help_prompt_loc, 0); break; } default: { /* Extract direction */ d = target_dir(press.key); /* Oops */ if (!d) bell("Illegal command for target mode!"); break; } } /* Hack -- move around */ if (d) { int old_y = targets->pts[m].y; int old_x = targets->pts[m].x; /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d], targets); /* Scroll to find interesting grid */ if (i < 0) { int old_wy = Term->offset_y; int old_wx = Term->offset_x; /* Change if legal */ if (change_panel(d)) { /* Recalculate interesting grids */ point_set_dispose(targets); targets = target_set_interactive_prepare(mode); /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d], targets); /* Restore panel if needed */ if ((i < 0) && modify_panel(Term, old_wy, old_wx)) { /* Recalculate interesting grids */ point_set_dispose(targets); targets = target_set_interactive_prepare(mode); } /* Handle stuff */ handle_stuff(p_ptr); } } /* Use interesting grid if found */ if (i >= 0) m = i; } } /* Arbitrary grids */ else { /* Update help */ if (help) { bool good_target = target_able(cave_monster_at(cave, y, x)); target_display_help(good_target, !(flag && point_set_size(targets))); } /* Find the path. */ path_n = project_path(path_g, MAX_RANGE, py, px, y, x, PROJECT_THRU); /* Draw the path in "target" mode. If there is one */ if (mode & (TARGET_KILL)) path_drawn = draw_path (path_n, path_g, path_char, path_attr, py, px); /* Describe and Prompt (enable "TARGET_LOOK") */ press = target_set_interactive_aux(y, x, mode | TARGET_LOOK); /* Remove the path */ if (path_drawn) load_path(path_n, path_g, path_char, path_attr); /* Cancel tracking */ /* health_track(0); */ /* Assume no direction */ d = 0; /* Analyze the keypress */ if (press.type == EVT_MOUSE) { if (press.mouse.button == 3) { /* give the target selection command */ press.mouse.button = 2; press.mouse.mods = KC_MOD_CONTROL; } if (press.mouse.button == 2) { if (mode & (TARGET_KILL)) { if ((y == KEY_GRID_Y(press)) && (x == KEY_GRID_X(press))) { d = -1; } } y = KEY_GRID_Y(press);//.mouse.y; x = KEY_GRID_X(press);//.mouse.x; if (press.mouse.mods & KC_MOD_CONTROL) { /* same as keyboard target selection command below */ target_set_location(y, x); done = TRUE; } else if (press.mouse.mods & KC_MOD_ALT) { /* go to spot - same as 'g' command below */ cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); done = TRUE; } else { /* cancel look mode */ done = TRUE; if (d == -1) { target_set_location(y, x); d = 0; } } } else /*if (press.mouse.button == 3) { } else*/ { int dungeon_hgt = cave->height; int dungeon_wid = cave->width; y = KEY_GRID_Y(press);//.mouse.y; x = KEY_GRID_X(press);//.mouse.x; if (Term) { if (press.mouse.y <= 1) { /* move the screen north */ y--; } else if (press.mouse.y >= (Term->hgt - 2)) { /* move the screen south */ y++; } else if (press.mouse.x <= COL_MAP) { /* move the screen in west */ x--; } else if (press.mouse.x >= (Term->wid - 2)) { /* move the screen east */ x++; } } if (y < 0) y = 0; if (x < 0) x = 0; if (y >= dungeon_hgt-1) y = dungeon_hgt-1; if (x >= dungeon_wid-1) x = dungeon_wid-1; /* Adjust panel if needed */ if (adjust_panel_help(y, x, help)) { /* Handle stuff */ handle_stuff(p_ptr); /* Recalculate interesting grids */ point_set_dispose(targets); targets = target_set_interactive_prepare(mode); } if (cave->m_idx[y][x] || cave->o_idx[y][x]) { /* scan the interesting list and see if there in anything here */ for (i = 0; i < point_set_size(targets); i++) { if ((y == targets->pts[i].y) && (x == targets->pts[i].x)) { m = i; flag = TRUE; break; } } } else { flag = FALSE; } } } else switch (press.key.code) { case ESCAPE: case 'q': { done = TRUE; break; } case ' ': case '*': case '+': case '-': { break; } case 'p': { /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(p_ptr); y = p_ptr->py; x = p_ptr->px; } case 'o': { break; } case 'm': { flag = TRUE; m = 0; bd = 999; /* Pick a nearby monster */ for (i = 0; i < point_set_size(targets); i++) { t = distance(y, x, targets->pts[i].y, targets->pts[i].x); /* Pick closest */ if (t < bd) { m = i; bd = t; } } /* Nothing interesting */ if (bd == 999) flag = FALSE; break; } case 't': case '5': case '0': case '.': { target_set_location(y, x); done = TRUE; break; } case 'g': { cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); done = TRUE; break; } case '?': { help = !help; /* Redraw main window */ p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); handle_stuff(p_ptr); if (!help) prt("Press '?' for help.", help_prompt_loc, 0); break; } default: { /* Extract a direction */ d = target_dir(press.key); /* Oops */ if (!d) bell("Illegal command for target mode!"); break; } } /* Handle "direction" */ if (d) { int dungeon_hgt = cave->height; int dungeon_wid = cave->width; /* Move */ x += ddx[d]; y += ddy[d]; /* Slide into legality */ if (x >= dungeon_wid - 1) x--; else if (x <= 0) x++; /* Slide into legality */ if (y >= dungeon_hgt - 1) y--; else if (y <= 0) y++; /* Adjust panel if needed */ if (adjust_panel_help(y, x, help)) { /* Handle stuff */ handle_stuff(p_ptr); /* Recalculate interesting grids */ point_set_dispose(targets); targets = target_set_interactive_prepare(mode); } } } } /* Forget */ point_set_dispose(targets); /* Redraw as necessary */ if (help) { p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); } else { prt("", 0, 0); prt("", help_prompt_loc, 0); p_ptr->redraw |= (PR_DEPTH | PR_STATUS); } /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(p_ptr); /* Failure to set target */ if (!target_set) return (FALSE); /* Success */ return (TRUE); }
bool target_set_closest(int mode) { /* Cancel old target */ target_set_monster(0, FALSE); target_grids.clear(); // if (mode & (TARGET_KILL | TARGET_PROBE)) { monster_type *m_ptr; int m_idx; bool probing = (mode & (TARGET_PROBE)); for (int i = 1; i < mon_max; i++) { if (!target_able(i, probing)) continue; m_ptr = &mon_list[i]; target_grids.append(make_coords(m_ptr->fy, m_ptr->fx)); } if (!target_grids.size()) { if (!(mode & TARGET_QUIET)) message(QString("No Available Target.")); return FALSE; } // Sort by distance qSort(target_grids.begin(), target_grids.end(), coords_sort_distance); /* Find the first monster in the queue */ int y = target_grids.at(0).y; int x = target_grids.at(0).x; m_idx = dungeon_info[y][x].monster_idx; /* Target the monster */ m_ptr = &mon_list[m_idx]; if (!(mode & TARGET_QUIET)) { QString m_name = monster_desc(m_ptr, 0x00); message(QString("%1 is targeted.").arg(capitalize_first(m_name))); } /* Set up target */ monster_race_track(m_ptr->r_idx); health_track(m_idx); target_set_monster(m_idx, probing); return (TRUE); } else if (mode & (TARGET_TRAP)) { // GO through all effects for (int i = x_max - 1; i >= 1; i--) { effect_type *x_ptr = &x_list[i]; /* Skip dead effects */ if (!x_ptr->x_type) continue; // Use only the targetable traps if (!target_able_trap(x_ptr->x_cur_y, x_ptr->x_cur_x)) continue; target_grids.append(make_coords(x_ptr->x_cur_y, x_ptr->x_cur_x)); } // Sort by distance qSort(target_grids.begin(), target_grids.end(), coords_sort_distance); if (!target_grids.size()) { if (!(mode & TARGET_QUIET)) message(QString("No Available Target.")); return FALSE; } /* Find the first monster in the queue */ int y = target_grids.at(0).y; int x = target_grids.at(0).x; { // Use this location target_set_location(y, x); return (TRUE); } } return (TRUE); }
/* * Handle "target" and "look". * * Note that this code can be called from "get_aim_dir()". * * Currently, when "flag" is true, that is, when * "interesting" grids are being used, and a directional key is used, we * only scroll by a single panel, in the direction requested, and check * for any interesting grids on that panel. The "correct" solution would * actually involve scanning a larger set of grids, including ones in * panels which are adjacent to the one currently scanned, but this is * overkill for this function. XXX XXX * * Hack -- targeting/observing an "outer border grid" may induce * problems, so this is not currently allowed. * * The player can use the direction keys to move among "interesting" * grids in a heuristic manner, or the "space", "+", and "-" keys to * move through the "interesting" grids in a sequential manner, or * can enter "location" mode, and use the direction keys to move one * grid at a time in any direction. The "t" (set target) command will * only target a monster (as opposed to a location) if the monster is * target_able and the "interesting" mode is being used. * * The current grid is described using the "look" method above, and * a new command may be entered at any time, but note that if the * "TARGET_LOOK" bit flag is set (or if we are in "location" mode, * where "space" has no obvious meaning) then "space" will scan * through the description of the current grid until done, instead * of immediately jumping to the next "interesting" grid. This * allows the "target" command to retain its old semantics. * * The "*", "+", and "-" keys may always be used to jump immediately * to the next (or previous) interesting grid, in the proper mode. * * The "return" key may always be used to scan through a complete * grid description (forever). * * This command will cancel any old target, even if used from * inside the "look" command. * * 'mode' is one of TARGET_LOOK or TARGET_KILL. * 'x' and 'y' are the initial position of the target to be highlighted, * or -1 if no location is specified. * Returns TRUE if a target has been successfully set, FALSE otherwise. */ bool target_set_interactive(int mode, int x, int y) { int py = p_ptr->py; int px = p_ptr->px; int i, d, target_count; bool done = FALSE; bool interactive = TRUE; u16b path_n; u16b path_g[PATH_SIZE]; u16b path_gx[PATH_SIZE]; /* Cancel target */ target_set_monster(0, FALSE); /* All grids are selectable */ if (mode & (TARGET_GRID)) { /* Disable other modes */ mode &= ~(TARGET_LOOK | TARGET_KILL | TARGET_TRAP); /* Disable interesting grids */ interactive = FALSE; } /* Prepare the "temp" array */ target_set_interactive_prepare(mode); /* If we haven't been given an initial location, start on the player. */ if ((x == -1 || y == -1) && target_grids.size()) { x = p_ptr->px; y = p_ptr->py; ui_targeting_show(MODE_TARGETING_INTERACTIVE); ui_update_message_label(color_string("Interactive Target Mode", TERM_L_RED)); } /* * If we /have/ been given an initial location, make sure we * honour it by going into "free targeting" mode. */ else { if (x == -1 || y == -1) { x = p_ptr->px; y = p_ptr->py; } interactive = FALSE; ui_targeting_show(MODE_TARGETING_MANUAL); ui_update_message_label(color_string("Manual Target Mode", TERM_L_RED)); } /* Start near the player */ target_count = 0; /* Interact */ while (!done) { /* Interesting grids */ if (interactive && target_grids.size()) { bool path_drawn = FALSE; int yy, xx; y = target_grids[target_count].y; x = target_grids[target_count].x; /* Dummy pointers to send to project_path */ yy = y; xx = x; /* Adjust panel if needed */ ui_ensure(y, x); /* Find the path. */ path_n = project_path(path_g, path_gx, MAX_RANGE, py, px, &yy, &xx, PROJECT_THRU); /* Draw the path in "target" mode. If there is one */ if ((mode & (TARGET_KILL)) && (dungeon_info[y][x].projectable())) { path_drawn = ui_draw_path(path_n, path_g, y, x); } ui_show_cursor(y, x); /* Describe and Prompt */ describe_grid_brief(y, x); UserInput input = ui_get_input(); /* Remove the path */ if (path_drawn) ui_destroy_path(); ui_show_cursor(-1, -1); /* Assume no "direction" */ d = 0; // Use the mouse wheel to go through targets if (input.mode == INPUT_MODE_MOUSE_WHEEL) { if (input.key == Qt::Key_Plus) { if (++target_count == target_grids.size()) target_count = 0; } else if (input.key == Qt::Key_Minus) { if (target_count-- == 0) target_count = target_grids.size() - 1; } continue; } // double-click - automatically target if appropriate if (input.mode == INPUT_MODE_MOUSE_DOUBLE_CLICK) { if (!set_selected_target(mode, y, x)) { target_set_location(y, x); } done = TRUE; continue; } /* * If we click, move the target location to the click and * switch to "free targeting" mode by unsetting 'flag'. * This means we get some info about wherever we've picked. */ if (input.mode == INPUT_MODE_MOUSE_SINGLE_CLICK) { // If clicking twice on the same square, accept if (input.x == x && input.y == y) { if (set_selected_target(mode, y, x)) done = TRUE; continue; } x = input.x; y = input.y; ui_update_message_label(color_string("Interactive Target Mode", TERM_L_RED)); ui_targeting_show(MODE_TARGETING_MANUAL); interactive = FALSE; continue; } /* Analyze */ switch (input.key) { case Qt::Key_Escape: case Qt::Key_X: { done = TRUE; break; } case Qt::Key_C: case Qt::Key_Comma: { /* Set to closest target */ if (target_set_closest(TARGET_KILL)) done = TRUE; break; } case Qt::Key_Space: case Qt::Key_Plus: { if (++target_count == target_grids.size()) target_count = 0; break; } case Qt::Key_Minus: { if (target_count-- == 0) target_count = target_grids.size() - 1; break; } case Qt::Key_Exclam: case Qt::Key_L: { GridDialog(y, x); break; } case Qt::Key_Asterisk: case Qt::Key_M: { ui_update_message_label(color_string("Manual Target Mode", TERM_L_RED)); ui_targeting_show(MODE_TARGETING_MANUAL); interactive = FALSE; break; } case Qt::Key_Question: { do_cmd_list_targeting_commands(); break; } case Qt::Key_H: case Qt::Key_5: case Qt::Key_Period: case Qt::Key_Clear: { if (set_selected_target(mode, y, x)) done = TRUE; break; } default: { /* Extract direction */ d = target_dir(input); /* Oops */ if (!d) message("Illegal command for target mode!"); break; } } /* Hack -- move around */ if (d) { int old_y = target_grids[target_count].y; int old_x = target_grids[target_count].x; /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d]); /* Scroll to find interesting grid */ if (i < 0) { QRect vis = visible_dungeon(); int old_wy = vis.y(); int old_wx = vis.x(); /* Change if legal */ if (ui_change_panel(d)) { /* Recalculate interesting grids */ target_set_interactive_prepare(mode); /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d]); /* Restore panel if needed */ if ((i < 0) && ui_modify_panel(old_wy, old_wx)) { /* Recalculate interesting grids */ target_set_interactive_prepare(mode); } } } /* Use interesting grid if found */ if (i >= 0) target_count = i; } } /* Arbitrary grids */ else { bool path_drawn = FALSE; /* Dummy pointers to send to project_path */ int yy = y; int xx = x; /* Find the path. */ path_n = project_path(path_g, path_gx, MAX_RANGE, py, px, &yy, &xx, PROJECT_THRU); /* Draw the path in "target" mode. If there is one */ if ((mode & (TARGET_KILL)) && (dungeon_info[y][x].projectable())) { /* Save target info */ path_drawn = ui_draw_path(path_n, path_g, y, x); } describe_grid_brief(y, x); ui_show_cursor(y, x); UserInput input = ui_get_input(); /* Remove the path */ if (path_drawn) ui_destroy_path(); ui_show_cursor(y, x); /* Assume no direction */ d = 0; if (input.mode == INPUT_MODE_MOUSE_WHEEL) continue; // double-click - automatically target if appropriate if (input.mode == INPUT_MODE_MOUSE_DOUBLE_CLICK) { if (set_selected_target(mode, y, x)) done = TRUE; else { message(QString("Illegal target!")); } break; } if (input.mode == INPUT_MODE_MOUSE_SINGLE_CLICK) { /* We only target if we click somewhere where the cursor is already (i.e. a double-click without a time limit) */ if (input.x == x && input.y == y) { target_set_location(y, x); done = TRUE; } else { /* Just move the cursor for now - another click will target. */ x = input.x; y = input.y; } continue; } /* Analyze the keypress */ switch (input.key) { case Qt::Key_Escape: case Qt::Key_X: { done = TRUE; continue; } case Qt::Key_Asterisk: case Qt::Key_M: { if (((mode & (TARGET_GRID)) != TARGET_GRID) && target_grids.size()) { ui_update_message_label(color_string("Interactive Target Mode", TERM_L_RED)); ui_targeting_show(MODE_TARGETING_INTERACTIVE); interactive = TRUE; } break; } case Qt::Key_copyright: case Qt::Key_C: case Qt::Key_Comma: { /* Set to closest target */ if (target_set_closest(TARGET_KILL)) done = TRUE; break; } case Qt::Key_Exclam: case Qt::Key_L: { GridDialog(y, x); break; } case Qt::Key_Ampersand: case Qt::Key_P: { /* Recenter around player */ ui_center(py, px); y = py; x = px; break; } case Qt::Key_H: case Qt::Key_5: case Qt::Key_Period: case Qt::Key_Clear: { target_set_location(y, x); done = TRUE; break; } case Qt::Key_Question: { do_cmd_list_targeting_commands(); break; } default: { /* Extract a direction */ d = target_dir(input); /* Oops */ if (!d) message("Illegal command for target mode!"); break; } } /* Handle "direction" */ if (d) { int dungeon_hgt = p_ptr->cur_map_hgt; int dungeon_wid = p_ptr->cur_map_wid; /* Move */ x += ddx[d]; y += ddy[d]; /* Slide into legality */ if (x >= dungeon_wid - 1) x--; else if (x <= 0) x++; /* Slide into legality */ if (y >= dungeon_hgt - 1) y--; else if (y <= 0) y++; /* Adjust panel if needed */ if (ui_adjust_panel(y, x)) { /* Recalculate interesting grids */ target_set_interactive_prepare(mode); } } } } /* Forget */ target_grids.clear(); ui_targeting_hide(); /* Recenter around player */ ui_ensure(py, px); /* Failure to set target */ if (!p_ptr->target_set) return (FALSE); /* Success */ return (TRUE); }
/* * Handle "target" and "look". * * Note that this code can be called from "get_aim_dir()". * * Currently, when "flag" is true, that is, when * "interesting" grids are being used, and a directional key is used, we * only scroll by a single panel, in the direction requested, and check * for any interesting grids on that panel. The "correct" solution would * actually involve scanning a larger set of grids, including ones in * panels which are adjacent to the one currently scanned, but this is * overkill for this function. XXX XXX * * Hack -- targetting/observing an "outer border grid" may induce * problems, so this is not currently allowed. * * The player can use the direction keys to move among "interesting" * grids in a heuristic manner, or the "space", "+", and "-" keys to * move through the "interesting" grids in a sequential manner, or * can enter "location" mode, and use the direction keys to move one * grid at a time in any direction. The "t" (set target) command will * only target a monster (as opposed to a location) if the monster is * target_able and the "interesting" mode is being used. * * The current grid is described using the "look" method above, and * a new command may be entered at any time, but note that if the * "TARGET_LOOK" bit flag is set (or if we are in "location" mode, * where "space" has no obvious meaning) then "space" will scan * through the description of the current grid until done, instead * of immediately jumping to the next "interesting" grid. This * allows the "target" command to retain its old semantics. * * The "*", "+", and "-" keys may always be used to jump immediately * to the next (or previous) interesting grid, in the proper mode. * * The "return" key may always be used to scan through a complete * grid description (forever). * * This command will cancel any old target, even if used from * inside the "look" command. * * 'mode' is one of TARGET_LOOK or TARGET_KILL. * 'x' and 'y' are the initial position of the target to be highlighted, * or -1 if no location is specified. * Returns TRUE if a target has been successfully set, FALSE otherwise. */ bool target_set_interactive(int mode, int x, int y) { int py = p_ptr->py; int px = p_ptr->px; int i, d, m, t, bd; int wid, hgt, help_prompt_loc; bool done = FALSE; bool flag = TRUE; bool help = FALSE; bool list_floor_objects = auto_display_lists; u16b path_n; u16b path_g[PATH_SIZE]; u16b path_gx[PATH_SIZE]; ui_event_data query; char info[80]; /* These are used for displaying the path to the target */ char path_char[MAX_RANGE]; byte path_attr[MAX_RANGE]; /* If we haven't been given an initial location, start on the player. */ if (x == -1 || y == -1) { x = p_ptr->px; y = p_ptr->py; } /* If we /have/ been given an initial location, make sure we honour it by going into "free targeting" mode. */ else { flag = FALSE; } /* Cancel target */ target_set_monster(0); /* make some buttons */ button_backup_all(); button_kill_all(); button_add("[ESCAPE]", ESCAPE); button_add("[NEXT]", '+'); button_add("[PREV]", '-'); button_add("[PLAYER]", 'p'); button_add("[PATHFIND]", 'g'); button_add("[TARGET]", 't'); /* health_track(0); */ /* All grids are selectable */ if (mode & (TARGET_GRID)) { /* Disable other modes */ mode &= ~(TARGET_LOOK | TARGET_KILL | TARGET_TRAP); /* Disable interesting grids */ flag = FALSE; } /* Calculate the window location for the help prompt */ Term_get_size(&wid, &hgt); help_prompt_loc = hgt - (mouse_buttons ? 2 : 1); /* Display the help prompt */ prt("'?' - help", help_prompt_loc, 0); /* Prepare the "temp" array */ target_set_interactive_prepare(mode); /* Start near the player */ m = 0; /* Interact */ while (!done) { button_kill('l'); button_kill('?'); if (list_floor_objects) { button_add("[HIDE_OBJLIST]", 'l'); } else button_add("[SHOW_OBJLIST]", 'l'); if (help) { button_add("[HIDE_HELP]", '?'); } else button_add("[SHOW_HELP]",'?'); /* Interesting grids */ if (flag && temp_n) { bool path_drawn = FALSE; int yy, xx; y = temp_y[m]; x = temp_x[m]; button_add("[SCAN]",'o'); /* Update help */ if (help) { bool good_target = ((cave_m_idx[y][x] > 0) && target_able(cave_m_idx[y][x])); target_display_help(good_target, !(flag && temp_n)); } /* Dummy pointers to send to project_path */ yy = y; xx = x; /* Allow targets for monsters....or traps, if applicable */ if (((cave_m_idx[y][x] > 0) && target_able(cave_m_idx[y][x])) || ((mode & (TARGET_TRAP)) && target_able_trap(y, x))) { strcpy(info, "q,t,r,l,p,o,+,-,<dir>"); } /* Dis-allow target */ else { strcpy(info, "q,p,l,o,+,-,<dir>"); } /* Adjust panel if needed */ if (adjust_panel(y, x)) { /* Handle stuff */ handle_stuff(); } /* Find the path. */ path_n = project_path(path_g, path_gx, MAX_RANGE, py, px, &yy, &xx, PROJECT_THRU); /* Draw the path in "target" mode. If there is one */ if ((mode & (TARGET_KILL)) && (cave_info[y][x] & (CAVE_FIRE))) { path_drawn = draw_path(path_n, path_g, path_char, path_attr, py, px, y, x); } event_signal(EVENT_MOUSEBUTTONS); /* Describe and Prompt */ query = target_set_interactive_aux(y, x, mode, info, list_floor_objects); /* Remove the path */ if (path_drawn) load_path(path_n, path_g, path_char, path_attr); /* Cancel tracking */ /* health_track(0); */ /* Assume no "direction" */ d = 0; /* Analyze */ switch (query.key) { case ESCAPE: case 'q': { done = TRUE; break; } case ' ': case '*': case '+': { if (++m == temp_n) m = 0; break; } case '-': { if (m-- == 0) m = temp_n - 1; break; } case 'p': { /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(); y = py; x = px; } case 'o': { flag = FALSE; break; } case 'm': { break; } /* If we click, move the target location to the click and switch to "free targetting" mode by unsetting 'flag'. This means we get some info about wherever we've picked. */ case DEFINED_XFF: { x = KEY_GRID_X(query); y = KEY_GRID_Y(query); flag = FALSE; break; } case 't': case '5': case '0': case '.': { int m_idx = cave_m_idx[y][x]; if ((m_idx > 0) && target_able(m_idx)) { health_track(m_idx); target_set_monster(m_idx); done = TRUE; } else if ((mode & (TARGET_TRAP)) && target_able_trap(y, x)) { target_set_location(y, x); done = TRUE; } else if (mode & (TARGET_PROBE)) { target_set_location(y, x); done = TRUE; } else { bell("Illegal target!"); } break; } case 'g': { cmd_insert(CMD_PATHFIND, y, x); done = TRUE; break; } case 'l': { list_floor_objects = (!list_floor_objects); } case '?': { help = !help; /* Redraw main window */ p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); handle_stuff(); if (!help) prt("'?' - help", help_prompt_loc, 0); break; } default: { /* Extract direction */ d = target_dir(query.key); /* Oops */ if (!d) bell("Illegal command for target mode!"); break; } } /* Hack -- move around */ if (d) { int old_y = temp_y[m]; int old_x = temp_x[m]; /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d]); /* Scroll to find interesting grid */ if (i < 0) { int old_wy = Term->offset_y; int old_wx = Term->offset_x; /* Change if legal */ if (change_panel(d)) { /* Recalculate interesting grids */ target_set_interactive_prepare(mode); /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d]); /* Restore panel if needed */ if ((i < 0) && modify_panel(Term, old_wy, old_wx)) { /* Recalculate interesting grids */ target_set_interactive_prepare(mode); } /* Handle stuff */ handle_stuff(); } } /* Use interesting grid if found */ if (i >= 0) m = i; } } /* Arbitrary grids */ else { bool path_drawn = FALSE; /* Dummy pointers to send to project_path */ int yy = y; int xx = x; /* Don't need this button any more */ button_kill('o'); /* Update help */ if (help) { bool good_target = ((cave_m_idx[y][x] > 0) && target_able(cave_m_idx[y][x])); target_display_help(good_target, !(flag && temp_n)); } /* Default prompt */ if (!(mode & (TARGET_GRID))) { strcpy(info, "q,t,l,p,m,+,-,<dir>"); } /* Disable monster selection */ else { strcpy(info, "q,t,l.p,+,-,<dir>"); } /* Find the path. */ path_n = project_path(path_g, path_gx, MAX_RANGE, py, px, &yy, &xx, PROJECT_THRU); /* Draw the path in "target" mode. If there is one */ if ((mode & (TARGET_KILL)) && (cave_info[y][x] & (CAVE_FIRE))) { /* Save target info */ path_drawn = draw_path(path_n, path_g, path_char, path_attr, py, px, y, x); } event_signal(EVENT_MOUSEBUTTONS); /* Describe and Prompt (enable "TARGET_LOOK") */ query = target_set_interactive_aux(y, x, (mode | TARGET_LOOK), info, list_floor_objects); /* Remove the path */ if (path_drawn) load_path(path_n, path_g, path_char, path_attr); /* Cancel tracking */ /* health_track(0); */ /* Assume no direction */ d = 0; /* Analyze the keypress */ switch (query.key) { case ESCAPE: case 'q': { done = TRUE; break; } case ' ': case '*': case '+': case '-': { break; } case 'p': { /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(); y = py; x = px; } case 'o': { break; } case 'm': { /* Monster selection is disabled */ if (mode & (TARGET_GRID)) break; flag = TRUE; m = 0; bd = 999; /* Pick a nearby monster */ for (i = 0; i < temp_n; i++) { t = distance(y, x, temp_y[i], temp_x[i]); /* Pick closest */ if (t < bd) { m = i; bd = t; } } /* Nothing interesting */ if (bd == 999) flag = FALSE; break; } case '\xff': { /* We only target if we click somewhere where the cursor is already (i.e. a double-click without a time limit) */ if (KEY_GRID_X(query) == x && KEY_GRID_Y(query) == y) { /* Make an attempt to target the monster on the given square rather than the square itself (it seems this is the more likely intention of clicking on a monster). */ int m_idx = cave_m_idx[y][x]; if ((m_idx > 0) && target_able(m_idx)) { health_track(m_idx); target_set_monster(m_idx); } else { /* There is no monster, or it isn't targettable, so target the location instead. */ target_set_location(y, x); } done = TRUE; } else { /* Just move the cursor for now - another click will target. */ x = KEY_GRID_X(query); y = KEY_GRID_Y(query); } break; } case 't': case '5': case '0': case '.': { target_set_location(y, x); done = TRUE; break; } case 'g': { cmd_insert(CMD_PATHFIND, y, x); done = TRUE; break; } case 'l': { list_floor_objects = (!list_floor_objects); } case '?': { help = !help; /* Redraw main window */ p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); handle_stuff(); if (!help) prt("'?' - help.", help_prompt_loc, 0); break; } default: { /* Extract a direction */ d = target_dir(query.key); /* Oops */ if (!d) bell("Illegal command for target mode!"); break; } } /* Handle "direction" */ if (d) { int dungeon_hgt = p_ptr->cur_map_hgt; int dungeon_wid = p_ptr->cur_map_wid; /* Move */ x += ddx[d]; y += ddy[d]; /* Slide into legality */ if (x >= dungeon_wid - 1) x--; else if (x <= 0) x++; /* Slide into legality */ if (y >= dungeon_hgt - 1) y--; else if (y <= 0) y++; /* Adjust panel if needed */ if (adjust_panel(y, x)) { /* Handle stuff */ handle_stuff(); /* Recalculate interesting grids */ target_set_interactive_prepare(mode); } } } } /* Forget */ temp_n = 0; /* Redraw as necessary */ if (help) { p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); } else { prt("", 0, 0); prt("", help_prompt_loc, 0); p_ptr->redraw |= (PR_DEPTH | PR_STATUS); } /* Recenter around player */ verify_panel(); /* Restore buttons */ button_restore(); /* Handle stuff */ handle_stuff(); /* Failure to set target */ if (!p_ptr->target_set) return (FALSE); /* Success */ return (TRUE); }
/* * Become unaware of objects, monster memory, and the map */ static void do_cmd_wiz_forget(void) { int i; /* Forget info about objects on the map */ for (i = 1; i < o_max; i++) { object_type *o_ptr = &o_list[i]; object_kind *k_ptr = &k_info[o_ptr->k_idx]; /* Skip non-objects */ if (!o_ptr->k_idx) continue; // identify non-special non-artefact weapons/armour switch (o_ptr->tval) { case TV_DIGGING: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: case TV_BOW: case TV_ARROW: case TV_MAIL: case TV_SOFT_ARMOR: case TV_SHIELD: case TV_HELM: case TV_CROWN: case TV_CLOAK: case TV_GLOVES: case TV_BOOTS: case TV_LIGHT: { if (!o_ptr->name1 && !o_ptr->name2) { /* Identify it */ object_aware(o_ptr); object_known(o_ptr); break; } } default: { if (!(k_ptr->flags3 & (TR3_EASY_KNOW))) { o_ptr->ident &= ~(IDENT_KNOWN); } } } /* Hack -- Clear the "empty" flag */ o_ptr->ident &= ~(IDENT_EMPTY); // re pseudo id pseudo_id(o_ptr); } /* Forget info about carried objects */ for (i = 0; i < INVEN_TOTAL; i++) { object_type *o_ptr = &inventory[i]; object_kind *k_ptr = &k_info[o_ptr->k_idx]; /* Skip non-objects */ if (!o_ptr->k_idx) continue; // identify non-special non-artefact weapons/armour switch (o_ptr->tval) { case TV_DIGGING: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: case TV_BOW: case TV_ARROW: case TV_MAIL: case TV_SOFT_ARMOR: case TV_SHIELD: case TV_HELM: case TV_CROWN: case TV_CLOAK: case TV_GLOVES: case TV_BOOTS: case TV_LIGHT: { if (!o_ptr->name1 && !o_ptr->name2) { /* Identify it */ object_aware(o_ptr); object_known(o_ptr); break; } } default: { if (!(k_ptr->flags3 & (TR3_EASY_KNOW))) { o_ptr->ident &= ~(IDENT_KNOWN); } } } /* Hack -- Clear the "empty" flag */ o_ptr->ident &= ~(IDENT_EMPTY); // re pseudo id pseudo_id(o_ptr); } /* Reset the object kinds */ for (i = 1; i < z_info->k_max; i++) { object_kind *k_ptr = &k_info[i]; /* Reset "tried" */ k_ptr->tried = FALSE; /* Reset "aware" */ k_ptr->aware = FALSE; } /* Reset the special objects */ for (i = 1; i < z_info->e_max; i++) { ego_item_type *e_ptr = &e_info[i]; /* Reset "aware" */ e_ptr->aware = FALSE; } /* Forget encountered monsters */ for (i = 1; i < mon_max; i++) { monster_type *m_ptr = &mon_list[i]; m_ptr->encountered = FALSE; } /* Reset the monster memory */ for (i = 1; i < z_info->r_max; i++) { monster_lore *l_ptr = &l_list[i]; WIPE(l_ptr, monster_lore); } /* Mega-Hack -- Forget the map */ wiz_dark(); // lose all spare experience //lose_exp(10000); // clear the cheat flags p_ptr->noscore = 0x0000; /* Forget turns */ turn = 1; playerturn = 1; // forget all messages -- currently a bit buggy messages_init(); // clear target target_set_monster(0); /* Recalculate bonuses */ p_ptr->update |= (PU_BONUS); /* Combine / Reorder the pack (later) */ p_ptr->notice |= (PN_COMBINE | PN_REORDER); /* Window stuff */ p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER_0); }
/** * Move a monster from index i1 to index i2 in the monster list. */ static void compact_monsters_aux(int i1, int i2) { int y, x; monster_type *m_ptr; s16b this_o_idx, next_o_idx = 0; /* Do nothing */ if (i1 == i2) return; /* Old monster */ m_ptr = cave_monster(cave, i1); y = m_ptr->fy; x = m_ptr->fx; /* Update the cave */ cave->m_idx[y][x] = i2; /* Update midx */ m_ptr->midx = i2; /* Repair objects being carried by monster */ for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx) { object_type *o_ptr; /* Get the object */ o_ptr = object_byid(this_o_idx); /* Get the next object */ next_o_idx = o_ptr->next_o_idx; /* Reset monster pointer */ o_ptr->held_m_idx = i2; } /* Move mimicked objects */ if (m_ptr->mimicked_o_idx > 0) { object_type *o_ptr; /* Get the object */ o_ptr = object_byid(m_ptr->mimicked_o_idx); /* Reset monster pointer */ o_ptr->mimicking_m_idx = i2; } /* Hack -- Update the target */ if (target_get_monster() == m_ptr) target_set_monster(cave_monster(cave, i2)); /* Hack -- Update the health bar */ if (p_ptr->health_who == m_ptr) p_ptr->health_who = cave_monster(cave, i2); /* Hack -- move monster */ COPY(cave_monster(cave, i2), cave_monster(cave, i1), struct monster); /* Hack -- wipe hole */ (void)WIPE(cave_monster(cave, i1), monster_type); }
/** * Deletes a monster by index. * * When a monster is deleted, all of its objects are deleted. */ void delete_monster_idx(int m_idx) { int x, y; s16b this_o_idx, next_o_idx = 0; monster_type *m_ptr; assert(m_idx > 0); m_ptr = cave_monster(cave, m_idx); /* Monster location */ y = m_ptr->fy; x = m_ptr->fx; /* Hack -- Reduce the racial counter */ m_ptr->race->cur_num--; /* Hack -- count the number of "reproducers" */ if (rf_has(m_ptr->race->flags, RF_MULTIPLY)) num_repro--; /* Hack -- remove target monster */ if (target_get_monster() == m_ptr) target_set_monster(NULL); /* Hack -- remove tracked monster */ if (p_ptr->health_who == m_ptr) health_track(p_ptr, NULL); /* Monster is gone */ cave->m_idx[y][x] = 0; /* Delete objects */ for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx) { object_type *o_ptr; /* Get the object */ o_ptr = object_byid(this_o_idx); /* Get the next object */ next_o_idx = o_ptr->next_o_idx; /* Preserve unseen artifacts (we assume they were created as this * monster's drop) - this will cause unintended behaviour in preserve * off mode if monsters can pick up artifacts */ if (o_ptr->artifact && !object_was_sensed(o_ptr)) o_ptr->artifact->created = FALSE; /* Clear held_m_idx now to avoid wasting time in delete_object_idx */ o_ptr->held_m_idx = 0; /* Delete the object */ delete_object_idx(this_o_idx); } /* Delete mimicked objects */ if (m_ptr->mimicked_o_idx > 0) delete_object_idx(m_ptr->mimicked_o_idx); /* Wipe the Monster */ (void)WIPE(m_ptr, monster_type); /* Count monsters */ cave->mon_cnt--; /* Visual update */ cave_light_spot(cave, y, x); }
bool find_enemy_to_kill(int *ty, int *tx) { int i; int dist; int best_dist = 4; // target to beat bool can_fire = FALSE; monster_type *m_ptr; monster_race *r_ptr; for (i = 1; i < mon_max; i++) { m_ptr = &mon_list[i]; r_ptr = &r_info[m_ptr->r_idx]; // Skip dead monsters if (!m_ptr->r_idx) continue; // Skip unseen monsters if (!m_ptr->ml) continue; // Skip unalert monsters if (m_ptr->alertness < ALERTNESS_ALERT) continue; // Skip unmoving monsters if (r_ptr->flags1 & (RF1_NEVER_MOVE)) continue; dist = flow_dist(FLOW_AUTOMATON, m_ptr->fy, m_ptr->fx); if (dist < best_dist) { best_dist = dist; can_fire = (dist > 1) && (cave_info[m_ptr->fy][m_ptr->fx] & (CAVE_FIRE)); // wait for melee opponents to come to you if ((best_dist == 2) && (r_ptr->freq_ranged == 0)) { *ty = p_ptr->py; *tx = p_ptr->px; } // charge at the others else { *ty = m_ptr->fy; *tx = m_ptr->fx; } } } if (can_fire && inventory[INVEN_BOW].tval && ((inventory[INVEN_QUIVER1].number >= 1) || (inventory[INVEN_QUIVER2].number >= 1))) { // clear the target target_set_monster(0); // queue the commands automaton_keypresses("ff"); // bug: occasionally shoots at a mold instead of the mobile target... return (TRUE); } return (FALSE); }
/** * Deletes a monster by index. * * When a monster is deleted, all of its objects are deleted. */ void delete_monster_idx(int m_idx) { assert(m_idx > 0); struct monster *mon = cave_monster(cave, m_idx); int y = mon->fy; int x = mon->fx; assert(square_in_bounds(cave, y, x)); /* Hack -- Reduce the racial counter */ mon->race->cur_num--; /* Hack -- count the number of "reproducers" */ if (rf_has(mon->race->flags, RF_MULTIPLY)) num_repro--; /* Hack -- remove target monster */ if (target_get_monster() == mon) target_set_monster(NULL); /* Hack -- remove tracked monster */ if (player->upkeep->health_who == mon) health_track(player->upkeep, NULL); /* Monster is gone */ cave->squares[y][x].mon = 0; /* Delete objects */ struct object *obj = mon->held_obj; while (obj) { struct object *next = obj->next; /* Preserve unseen artifacts (we assume they were created as this * monster's drop) - this will cause unintended behaviour in preserve * off mode if monsters can pick up artifacts */ if (obj->artifact && !(obj->known && obj->known->artifact)) obj->artifact->created = false; /* Delete the object */ delist_object(cave, obj); object_delete(&obj); obj = next; } /* Delete mimicked objects */ if (mon->mimicked_obj) { square_excise_object(cave, y, x, mon->mimicked_obj); delist_object(cave, mon->mimicked_obj); object_delete(&mon->mimicked_obj); } /* Wipe the Monster */ memset(mon, 0, sizeof(struct monster)); /* Count monsters */ cave->mon_cnt--; /* Visual update */ square_light_spot(cave, y, x); }