summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/docs/crawl_manual.txt3
-rw-r--r--crawl-ref/source/command.cc3
-rw-r--r--crawl-ref/source/directn.cc136
-rw-r--r--crawl-ref/source/enum.h12
-rw-r--r--crawl-ref/source/externs.h1
-rw-r--r--crawl-ref/source/initfile.cc1
-rw-r--r--crawl-ref/source/output.cc120
-rw-r--r--crawl-ref/source/output.h25
-rw-r--r--crawl-ref/source/view.cc3
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
}
}