diff options
-rw-r--r-- | crawl-ref/docs/crawl_manual.txt | 3 | ||||
-rw-r--r-- | crawl-ref/source/command.cc | 3 | ||||
-rw-r--r-- | crawl-ref/source/directn.cc | 136 | ||||
-rw-r--r-- | crawl-ref/source/enum.h | 12 | ||||
-rw-r--r-- | crawl-ref/source/externs.h | 1 | ||||
-rw-r--r-- | crawl-ref/source/initfile.cc | 1 | ||||
-rw-r--r-- | crawl-ref/source/output.cc | 120 | ||||
-rw-r--r-- | crawl-ref/source/output.h | 25 | ||||
-rw-r--r-- | crawl-ref/source/view.cc | 3 |
9 files changed, 237 insertions, 67 deletions
diff --git a/crawl-ref/docs/crawl_manual.txt b/crawl-ref/docs/crawl_manual.txt index b9a2ca99db..1efc4ac2fa 100644 --- a/crawl-ref/docs/crawl_manual.txt +++ b/crawl-ref/docs/crawl_manual.txt @@ -250,7 +250,8 @@ can be subtle, and a full list with explanations is given in Appendix 5. Monsters within your field of vision are listed on a special panel, the monster list. Single monsters also get indicators of their health status in the form of a coloured box, and also on effects they enjoy or suffer -from. +from. Within target mode you can directly target single monsters by use +of the monster list. Use Ctrl-L to toggle this on or off. Sometimes characters will be able to use special abilities, e.g. the Naga's ability to spit poison, or the magical power to turn invisible diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index 24a11729ec..0365448d36 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -729,6 +729,9 @@ static const char *targeting_help_1 = "<w><<</w>/<w>></w> : cycle through up/down stairs\n" "<w>Tab</w> : cycle through shops and portals\n" "<w>Ctrl-F</w> : change monster targeting mode\n" +#ifndef USE_TILE + "<w>Ctrl-L</w> : toggle targetting via monster list\n" +#endif "<w>Ctrl-P</w> : repeat prompt\n" " \n" "<h>Targeting (zapping wands, casting spells, etc.):\n" diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index 2f86f47638..69f547e24f 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -58,6 +58,7 @@ #include "travel.h" #include "tutorial.h" #include "view.h" +#include "output.h" #include "macro.h" @@ -91,6 +92,10 @@ static bool _find_object( int x, int y, int mode, bool need_path, int range ); static bool _find_monster( int x, int y, int mode, bool need_path, int range ); static bool _find_feature( int x, int y, int mode, bool need_path, int range ); +#ifndef USE_TILE +static bool _find_mlist( int x, int y, int mode, bool need_path, int range ); +#endif + static char _find_square_wrapper( int tx, int ty, FixedVector<char, 2> &mfp, char direction, bool (*targ)(int, int, int, bool, int), @@ -433,7 +438,31 @@ static void direction_again(dist& moves, targeting_type restricts, // tx,ty target x,y // dx,dy direction delta for DIR_DIR // -//--------------------------------------------------------------- +//-------------------------------------------------------------- + +#ifndef USE_TILE +// XXX: Hack - can't pass mlist entries into _find_mlist(). +std::vector<monster_pane_info> mlist; +static void _fill_monster_list(void) +{ + std::vector<monster_pane_info> temp; + get_monster_pane_info(temp); + + // Get the unique entries. + mlist.clear(); + int start = 0, end = 1; + while (start < (int) temp.size()) + { + mlist.push_back(temp[start]); + for (end = start + 1; end < (int) temp.size(); ++end) + if (monster_pane_info::less_than(temp[start], temp[end])) + break; + + start = end; + } +} +#endif + void direction(dist& moves, targeting_type restricts, targ_mode_type mode, int range, bool just_looking, bool needs_path, const char *prompt, @@ -445,6 +474,14 @@ void direction(dist& moves, targeting_type restricts, beh->just_looking = just_looking; +#ifndef USE_TILE + if (!just_looking && Options.mlist_targetting == MLIST_TARGET_HIDDEN) + { + Options.mlist_targetting = MLIST_TARGET_ON; + _fill_monster_list(); + } +#endif + if (crawl_state.is_replaying_keys() && restricts != DIR_DIR) { direction_again(moves, restricts, mode, range, just_looking, @@ -502,6 +539,7 @@ void direction(dist& moves, targeting_type restricts, } bool show_prompt = true; + while (true) { // Prompts might get scrolled off if you have too few lines available. @@ -602,6 +640,23 @@ void direction(dist& moves, targeting_type restricts, int i, mid; +#ifndef USE_TILE + if (key_command >= CMD_TARGET_CYCLE_MLIST + && key_command <= CMD_TARGET_CYCLE_MLIST_END) + { + const int idx = key_command - CMD_TARGET_CYCLE_MLIST; + if (_find_square_wrapper(moves.tx, moves.ty, monsfind_pos, 1, + _find_mlist, needs_path, idx, range, + Options.target_wrap)) + { + moves.tx = monsfind_pos[0]; + moves.ty = monsfind_pos[1]; + } + else if (!skip_iter) + flush_input_buffer(FLUSH_ON_FAILURE); + } +#endif + switch (key_command) { // standard movement @@ -664,6 +719,20 @@ void direction(dist& moves, targeting_type restricts, target_mode_help_text(restricts)); break; +#ifndef USE_TILE + case CMD_TARGET_TOGGLE_MLIST: + if (Options.mlist_targetting == MLIST_TARGET_ON) + Options.mlist_targetting = MLIST_TARGET_OFF; + else + Options.mlist_targetting = MLIST_TARGET_ON; + + update_monster_pane(); + + if (Options.mlist_targetting == MLIST_TARGET_ON) + _fill_monster_list(); + break; +#endif + #ifdef WIZARD case CMD_TARGET_CYCLE_BEAM: show_beam = find_ray(you.x_pos, you.y_pos, moves.tx, moves.ty, @@ -796,6 +865,11 @@ void direction(dist& moves, targeting_type restricts, you.prev_targ = MHITYOU; else you.prev_grd_targ = coord_def(moves.tx, moves.ty); + +#ifndef USE_TILE + if (Options.mlist_targetting == MLIST_TARGET_ON) + Options.mlist_targetting = MLIST_TARGET_HIDDEN; +#endif break; case CMD_TARGET_OBJ_CYCLE_BACK: @@ -833,6 +907,11 @@ void direction(dist& moves, targeting_type restricts, loop_done = true; moves.isCancel = true; beh->mark_ammo_nonchosen(); + +#ifndef USE_TILE + if (Options.mlist_targetting == MLIST_TARGET_ON) + Options.mlist_targetting = MLIST_TARGET_HIDDEN; +#endif break; #ifdef WIZARD @@ -1022,7 +1101,7 @@ void direction(dist& moves, targeting_type restricts, true, ray, 0, true) ) { #else - if ( need_beam_redraw ) + if (need_beam_redraw) { viewwindow(true, false); #endif @@ -1164,6 +1243,46 @@ bool in_los(int x, int y) return (in_vlos(grid2view(coord_def(x, y)))); } +#ifndef USE_TILE +static bool _find_mlist( int x, int y, int idx, bool need_path, int range = -1) +{ + if ((int) mlist.size() <= idx) + return (false); + + if (!_is_target_in_range(x, y, range) || !in_los(x,y)) + return (false); + + const int targ_mon = mgrd[ x ][ y ]; + if (targ_mon == NON_MONSTER) + return (false); + + int real_idx = 0; + for (unsigned int i = 0; i < mlist.size()-1; i++) + { + if (real_idx == idx) + { + real_idx = i; + break; + } + + // While the monsters are identical, don't increase real_idx. + if (mlist[i].m_mon->type == mlist[i+1].m_mon->type + && mlist[i].m_attitude == mlist[i+1].m_attitude) + { + continue; + } + real_idx++; + } + + monsters *mon = &menv[targ_mon]; + const monsters *monl = mlist[real_idx].m_mon; + extern mon_attitude_type mons_attitude(const monsters *m); + + return (mons_attitude(mon) == mlist[idx].m_attitude + && mon->type == monl->type); +} +#endif + static bool _find_monster( int x, int y, int mode, bool need_path, int range = -1) { @@ -1556,8 +1675,8 @@ static char _find_square_wrapper( int tx, int ty, FixedVector<char, 2> &mfp, char direction, bool (*find_targ)(int x, int y, int mode, bool need_path, int range), - bool need_path, int mode, int range, bool wrap, - int los ) + bool need_path, int mode, int range, + bool wrap, int los ) { const char r = _find_square(grid2viewX(tx), grid2viewY(ty), mfp, direction, find_targ, need_path, mode, range, @@ -2500,7 +2619,13 @@ command_type targeting_behaviour::get_command(int key) if (key == -1) key = get_key(); - switch ( key ) +#ifndef USE_TILE + // Overrides the movement keys while mlist_targetting is active. + if (Options.mlist_targetting == MLIST_TARGET_ON && islower(key)) + return static_cast<command_type> (CMD_TARGET_CYCLE_MLIST + (key - 'a')); +#endif + + switch (key) { case ESCAPE: case 'x': return CMD_TARGET_CANCEL; @@ -2539,6 +2664,7 @@ command_type targeting_behaviour::get_command(int key) case '>': return CMD_TARGET_FIND_DOWNSTAIR; case CONTROL('F'): return CMD_TARGET_CYCLE_TARGET_MODE; + case CONTROL('L'): return CMD_TARGET_TOGGLE_MLIST; case 'p': return CMD_TARGET_PREV_TARGET; case 'f': return CMD_TARGET_MAYBE_PREV_TARGET; case 't': return CMD_TARGET_MAYBE_PREV_TARGET; // for the 0.3.4 keys diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index 9bc7585319..f9b3878b13 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -586,6 +586,9 @@ enum command_type CMD_TARGET_CYCLE_FORWARD, CMD_TARGET_CYCLE_BACK, CMD_TARGET_CYCLE_BEAM, + CMD_TARGET_CYCLE_MLIST = 2000, // for indices a-z in the monster list + CMD_TARGET_CYCLE_MLIST_END = 2025, + CMD_TARGET_TOGGLE_MLIST, CMD_TARGET_HIDE_BEAM, CMD_TARGET_CENTER, CMD_TARGET_CANCEL, @@ -2796,6 +2799,15 @@ enum montravel_target_type MTRAV_SUBMERSIBLE // Travelling to reach a submersible place. }; +#ifndef USE_TILE +enum mlist_targetting_type +{ + MLIST_TARGET_OFF = 0, + MLIST_TARGET_HIDDEN, + MLIST_TARGET_ON +}; +#endif + #ifdef WIZARD enum wizard_option_type diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h index 8603111f87..579cf5e74a 100644 --- a/crawl-ref/source/externs.h +++ b/crawl-ref/source/externs.h @@ -1614,6 +1614,7 @@ public: int mlist_min_height; int msg_max_height; bool mlist_allow_alternate_layout; + int mlist_targetting; // not actually a real option bool classic_hud; bool msg_condense_repeats; diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 9b437a83b3..b69e653cf9 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -615,6 +615,7 @@ void game_options::reset_options() mlist_min_height = 5; msg_max_height = 10; mlist_allow_alternate_layout = false; + mlist_targetting = 0; classic_hud = false; msg_condense_repeats = true; diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index ad0e9a284b..b769206e7c 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -1170,42 +1170,25 @@ std::string mpr_monster_list(bool past) } #ifndef USE_TILE - -// Monster info used by the pane; precomputes some data -// to help with sorting and rendering. -class monster_pane_info +monster_pane_info::monster_pane_info(const monsters *m) + : m_mon(m) { - public: - static bool less_than(const monster_pane_info& m1, - const monster_pane_info& m2, bool zombified = true); - - monster_pane_info(const monsters* m) - : m_mon(m) - { - m_attitude = mons_attitude(m); - - // Currently, difficulty is defined as "average hp". Leaks too - // much info? - const monsterentry* me = get_monster_data(m->type); - m_difficulty = me->hpdice[0] * (me->hpdice[1] + (me->hpdice[2]>>1)) - + me->hpdice[3]; - - m_brands = 0; - if (mons_looks_stabbable(m)) m_brands |= 1; - if (mons_looks_distracted(m)) m_brands |= 2; - if (m->has_ench(ENCH_BERSERK)) m_brands |= 4; - - m_fullname = true; - } - - void to_string(int count, std::string& desc, int& desc_color) const; - - const monsters* m_mon; - mon_attitude_type m_attitude; - int m_difficulty; - int m_brands; - bool m_fullname; -}; + // XXX: this doesn't take into account ENCH_NEUTRAL, but that's probably + // a bug for mons_attitude, not this. + // XXX: also, mons_attitude_type should be sorted hostile/neutral/friendly; + // will break saves a little bit though. + m_attitude = mons_attitude(m); + + // Currently, difficulty is defined as "average hp". Leaks too much info? + const monsterentry* me = get_monster_data(m->type); + m_difficulty = me->hpdice[0] * (me->hpdice[1] + (me->hpdice[2]>>1)) + + me->hpdice[3]; + + m_brands = 0; + if (mons_looks_stabbable(m)) m_brands |= 1; + if (mons_looks_distracted(m)) m_brands |= 2; + if (m->has_ench(ENCH_BERSERK)) m_brands |= 4; +} // Sort monsters by: // attitude @@ -1344,9 +1327,9 @@ void monster_pane_info::to_string( int count, std::string& desc, desc = out.str(); } -static void _print_next_monster_desc( - const std::vector<monster_pane_info>& mons, int& start, - bool zombified = false) +static void _print_next_monster_desc(const std::vector<monster_pane_info>& mons, + int& start, bool zombified = false, + int idx = -1) { // Skip forward to past the end of the range of identical monsters. unsigned int end; @@ -1362,6 +1345,15 @@ static void _print_next_monster_desc( { int printed = 0; + // for targeting + if (idx >= 0) + { + textcolor(WHITE); + cprintf( stringize_glyph('a' + idx).c_str() ); + cprintf(" - "); + printed += 4; + } + // One glyph for each monster. for (unsigned int i_mon = start; i_mon < end; i_mon++) { @@ -1442,6 +1434,21 @@ static void _print_next_monster_desc( textcolor(LIGHTGREY); } +void get_monster_pane_info(std::vector<monster_pane_info>& mons) +{ + std::vector<monsters*> visible; + get_playervisible_monsters(visible); + for (unsigned int i = 0; i < visible.size(); i++) + { + if (Options.target_zero_exp + || !mons_class_flag( visible[i]->type, M_NO_EXP_GAIN )) + { + mons.push_back(monster_pane_info(visible[i])); + } + } + std::sort(mons.begin(), mons.end(), monster_pane_info::less_than); +} + #define BOTTOM_JUSTIFY_MONSTER_LIST 0 void update_monster_pane() { @@ -1452,19 +1459,7 @@ void update_monster_pane() return; std::vector<monster_pane_info> mons; - { - std::vector<monsters*> visible; - get_playervisible_monsters(visible); - for (unsigned int i = 0; i < visible.size(); i++) - { - if (Options.target_zero_exp - || !mons_class_flag( visible[i]->type, M_NO_EXP_GAIN )) - { - mons.push_back(monster_pane_info(visible[i])); - } - } - } - + get_monster_pane_info(mons); std::sort(mons.begin(), mons.end(), monster_pane_info::less_than); // Count how many groups of monsters there are @@ -1497,15 +1492,18 @@ void update_monster_pane() #endif // Print the monsters! - std::string blank; blank.resize(crawl_view.mlistsz.x, ' '); int i_mons = 0; for (int i_print = 0; i_print < max_print; ++i_print) { - cgotoxy(1, 1+i_print, GOTO_MLIST); + cgotoxy(1, 1 + i_print, GOTO_MLIST); // i_mons is incremented by _print_next_monster_desc - if ((i_print >= skip_lines) && (i_mons < (int)mons.size())) - _print_next_monster_desc(mons, i_mons, zombified); + if (i_print >= skip_lines && i_mons < (int) mons.size()) + { + _print_next_monster_desc(mons, i_mons, zombified, + Options.mlist_targetting == MLIST_TARGET_ON ? i_print + : -1); + } else cprintf("%s", blank.c_str()); } @@ -1513,7 +1511,7 @@ void update_monster_pane() if (i_mons < (int) mons.size()) { // Didn't get to all of them. - cgotoxy(crawl_view.mlistsz.x-4, crawl_view.mlistsz.y, GOTO_MLIST); + cgotoxy(crawl_view.mlistsz.x - 4, crawl_view.mlistsz.y, GOTO_MLIST); cprintf(" ... "); } } @@ -1564,10 +1562,9 @@ const char *equip_slot_to_name(int equip) int equip_name_to_slot(const char *s) { for (int i = 0; i < NUM_EQUIP; ++i) - { if (!stricmp(s_equip_slot_names[i], s)) return i; - } + return -1; } @@ -2122,10 +2119,15 @@ std::string _status_mut_abilities() if (you.duration[DUR_CONF]) text += "confused, "; - // how exactly did you get to show the status? + // How exactly did you get to show the status? + // It's not so unreasonable anymore now that the new overview screen is + // dumped. When the player dies while paralysed it's important information. if (you.duration[DUR_PARALYSIS]) text += "paralysed, "; + if (you.duration[DUR_PETRIFIED]) + text += "petrified, "; + if (you.duration[DUR_SLEEP]) text += "sleeping, "; diff --git a/crawl-ref/source/output.h b/crawl-ref/source/output.h index c8f1aa9312..073879a2a7 100644 --- a/crawl-ref/source/output.h +++ b/crawl-ref/source/output.h @@ -53,7 +53,7 @@ void print_stats_level(void); void draw_border(void); std::string mpr_monster_list(bool past = false); void redraw_skill(const std::string &your_name, const std::string &class_name); -void update_monster_pane(void); +void update_monster_pane(); const char *equip_slot_to_name(int equip); @@ -65,4 +65,27 @@ void print_overview_screen(void); std::string dump_overview_screen(bool full_id); +#ifndef USE_TILE +// Monster info used by the pane; precomputes some data +// to help with sorting and rendering. +class monster_pane_info +{ + public: + static bool less_than(const monster_pane_info& m1, + const monster_pane_info& m2, bool zombified = true); + + monster_pane_info(const monsters* m); + + void to_string(int count, std::string& desc, int& desc_color) const; + + const monsters* m_mon; + mon_attitude_type m_attitude; + int m_difficulty; + int m_brands; + bool m_fullname; +}; + +void get_monster_pane_info(std::vector<monster_pane_info>& mons); +#endif + #endif diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 8bed707e4d..776504af6b 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -5028,8 +5028,9 @@ void viewwindow(bool draw_it, bool do_updates) crawl_view.viewp.x + crawl_view.viewsz.x - 1, crawl_view.viewp.y + crawl_view.viewsz.y - 1, buffy); -#endif + update_monster_pane(); +#endif } } |