summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/command.cc16
-rw-r--r--crawl-ref/source/direct.cc170
-rw-r--r--crawl-ref/source/direct.h19
-rw-r--r--crawl-ref/source/externs.h1
-rw-r--r--crawl-ref/source/item_use.cc204
-rw-r--r--crawl-ref/source/item_use.h6
-rw-r--r--crawl-ref/source/player.cc2
-rw-r--r--crawl-ref/source/tags.cc4
8 files changed, 319 insertions, 103 deletions
diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc
index 812a47266a..cd6955ec0a 100644
--- a/crawl-ref/source/command.cc
+++ b/crawl-ref/source/command.cc
@@ -538,7 +538,7 @@ static const char *level_map_help =
"<w>Ctrl-W</w> : set Waypoint\n"
"<w>Ctrl-C</w> : Clear level and main maps\n";
-static const char *targeting_help =
+static const char *targeting_help_1 =
"<h>Examine surroundings ('<w>x</w><h>' in main):\n"
"<w>Esc</w> : cancel (also <w>Space</w>)\n"
"<w>Dir.</w>: move cursor in that direction\n"
@@ -563,6 +563,12 @@ static const char *targeting_help =
"<w>:</w> : show/hide beam path\n"
"<w>Shift-Dir</w> : shoot straight-line beam\n";
+static const char *targeting_help_2 =
+ "<h>Firing or throwing a missile:\n"
+ "<w>Ctrl-P</w> : cycle to previous missile.\n"
+ "<w>Ctrl-N</w> : cycle to next missile.\n";
+
+
static const char *interlevel_travel_branch_help =
"<h>Interlevel Travel (choose a branch):\n"
" Use the shortcut letter for a branch to select the branch for travel.\n"
@@ -796,7 +802,13 @@ void show_levelmap_help()
void show_targeting_help()
{
- show_specific_help( targeting_help );
+ column_composer cols(2, 41);
+ // Page size is number of lines - one line for --more-- prompt.
+ cols.set_pagesize(get_number_of_lines() - 1);
+
+ cols.add_formatted(0, targeting_help_1, true, true);
+ cols.add_formatted(1, targeting_help_2, true, true);
+ show_keyhelp_menu(cols.formatted_lines(), false, true);
}
void show_interlevel_travel_branch_help()
diff --git a/crawl-ref/source/direct.cc b/crawl-ref/source/direct.cc
index 214d88d808..b84ca81e1f 100644
--- a/crawl-ref/source/direct.cc
+++ b/crawl-ref/source/direct.cc
@@ -98,71 +98,7 @@ static int targeting_cmd_to_compass( command_type command );
static void describe_oos_square(int x, int y);
static void extend_move_to_edge(dist &moves);
-static command_type read_direction_key(bool just_looking = false)
-{
- flush_input_buffer( FLUSH_BEFORE_COMMAND );
-
- const int key =
- unmangle_direction_keys(
- getchm(KC_TARGETING), KC_TARGETING, false, false);
-
- switch ( key )
- {
- case ESCAPE: case 'x': return CMD_TARGET_CANCEL;
-
-#ifdef WIZARD
- case 'F': return CMD_TARGET_WIZARD_MAKE_FRIENDLY;
-#endif
- case 'v': return CMD_TARGET_DESCRIBE;
- case '?': return CMD_TARGET_HELP;
- case ' ': return just_looking? CMD_TARGET_CANCEL : CMD_TARGET_SELECT;
-#ifdef WIZARD
- case CONTROL('C'): return CMD_TARGET_CYCLE_BEAM;
-#endif
- case ':': return CMD_TARGET_HIDE_BEAM;
- case '\r': return CMD_TARGET_SELECT;
- case '.': return CMD_TARGET_SELECT;
- case '5': return CMD_TARGET_SELECT;
- case '!': return CMD_TARGET_SELECT_ENDPOINT;
-
- case '\\': case '\t': return CMD_TARGET_FIND_PORTAL;
- case '^': return CMD_TARGET_FIND_TRAP;
- case '_': return CMD_TARGET_FIND_ALTAR;
- case '<': return CMD_TARGET_FIND_UPSTAIR;
- case '>': return CMD_TARGET_FIND_DOWNSTAIR;
-
- case CONTROL('F'): return CMD_TARGET_CYCLE_TARGET_MODE;
- case 'p': return CMD_TARGET_PREV_TARGET;
- case 'f': case 't': return CMD_TARGET_MAYBE_PREV_TARGET;
-
- case '-': return CMD_TARGET_CYCLE_BACK;
- case '+': case '=': return CMD_TARGET_CYCLE_FORWARD;
- case ';': case '/': return CMD_TARGET_OBJ_CYCLE_BACK;
- case '*': case '\'': return CMD_TARGET_OBJ_CYCLE_FORWARD;
-
- case 'b': return CMD_TARGET_DOWN_LEFT;
- case 'h': return CMD_TARGET_LEFT;
- case 'j': return CMD_TARGET_DOWN;
- case 'k': return CMD_TARGET_UP;
- case 'l': return CMD_TARGET_RIGHT;
- case 'n': return CMD_TARGET_DOWN_RIGHT;
- case 'u': return CMD_TARGET_UP_RIGHT;
- case 'y': return CMD_TARGET_UP_LEFT;
-
- case 'B': return CMD_TARGET_DIR_DOWN_LEFT;
- case 'H': return CMD_TARGET_DIR_LEFT;
- case 'J': return CMD_TARGET_DIR_DOWN;
- case 'K': return CMD_TARGET_DIR_UP;
- case 'L': return CMD_TARGET_DIR_RIGHT;
- case 'N': return CMD_TARGET_DIR_DOWN_RIGHT;
- case 'U': return CMD_TARGET_DIR_UP_RIGHT;
- case 'Y': return CMD_TARGET_DIR_UP_LEFT;
-
- default: return CMD_NO_CMD;
- }
-}
-
-void direction_choose_compass( struct dist& moves )
+void direction_choose_compass( dist& moves, targeting_behaviour *beh)
{
moves.isValid = true;
moves.isTarget = false;
@@ -170,8 +106,10 @@ void direction_choose_compass( struct dist& moves )
moves.isCancel = false;
moves.dx = moves.dy = 0;
+ beh->compass = true;
+
do {
- const command_type key_command = read_direction_key();
+ const command_type key_command = beh->get_command();
if (key_command == CMD_TARGET_SELECT)
{
@@ -310,14 +248,21 @@ static void draw_ray_glyph(const coord_def &pos, int colour,
//
//---------------------------------------------------------------
void direction(dist& moves, targeting_type restricts,
- targ_mode_type mode, bool just_looking, const char *prompt)
+ targ_mode_type mode, bool just_looking,
+ const char *prompt, targeting_behaviour *beh)
{
+ static targeting_behaviour stock_behaviour;
+ if (!beh)
+ beh = &stock_behaviour;
+
+ beh->just_looking = just_looking;
+
// NOTE: Even if just_looking is set, moves is still interesting,
// because we can travel there!
if ( restricts == DIR_DIR )
{
- direction_choose_compass( moves );
+ direction_choose_compass( moves, beh );
return;
}
@@ -360,7 +305,7 @@ void direction(dist& moves, targeting_type restricts,
{
// Prompts might get scrolled off if you have too few lines available.
// We'll live with that.
- if ( !just_looking && show_prompt )
+ if ( !just_looking && (show_prompt || beh->should_redraw()) )
{
mprf(MSGCH_PROMPT, "%s (%s)", prompt? prompt : "Aim",
target_mode_help_text(restricts));
@@ -388,7 +333,7 @@ void direction(dist& moves, targeting_type restricts,
key_command = CMD_TARGET_CYCLE_FORWARD; // find closest enemy
}
else
- key_command = read_direction_key(just_looking);
+ key_command = beh->get_command();
if (target_unshifted && moves.tx == you.x_pos && moves.ty == you.y_pos
&& restricts != DIR_TARGET)
@@ -1712,3 +1657,88 @@ static void describe_cell(int mx, int my)
mpr(feature_desc.c_str());
#endif
}
+
+///////////////////////////////////////////////////////////////////////////
+// targeting_behaviour
+
+targeting_behaviour::targeting_behaviour(bool look_around)
+ : just_looking(look_around), compass(false)
+{
+}
+
+targeting_behaviour::~targeting_behaviour()
+{
+}
+
+int targeting_behaviour::get_key()
+{
+ flush_input_buffer(FLUSH_BEFORE_COMMAND);
+ return unmangle_direction_keys(
+ getchm(KC_TARGETING), KC_TARGETING, false, false);
+}
+
+command_type targeting_behaviour::get_command(int key)
+{
+ if (key == -1)
+ key = get_key();
+
+ switch ( key )
+ {
+ case ESCAPE: case 'x': return CMD_TARGET_CANCEL;
+
+#ifdef WIZARD
+ case 'F': return CMD_TARGET_WIZARD_MAKE_FRIENDLY;
+#endif
+ case 'v': return CMD_TARGET_DESCRIBE;
+ case '?': return CMD_TARGET_HELP;
+ case ' ': return just_looking? CMD_TARGET_CANCEL : CMD_TARGET_SELECT;
+#ifdef WIZARD
+ case CONTROL('C'): return CMD_TARGET_CYCLE_BEAM;
+#endif
+ case ':': return CMD_TARGET_HIDE_BEAM;
+ case '\r': return CMD_TARGET_SELECT;
+ case '.': return CMD_TARGET_SELECT;
+ case '5': return CMD_TARGET_SELECT;
+ case '!': return CMD_TARGET_SELECT_ENDPOINT;
+
+ case '\\': case '\t': return CMD_TARGET_FIND_PORTAL;
+ case '^': return CMD_TARGET_FIND_TRAP;
+ case '_': return CMD_TARGET_FIND_ALTAR;
+ case '<': return CMD_TARGET_FIND_UPSTAIR;
+ case '>': return CMD_TARGET_FIND_DOWNSTAIR;
+
+ case CONTROL('F'): return CMD_TARGET_CYCLE_TARGET_MODE;
+ case 'p': return CMD_TARGET_PREV_TARGET;
+ case 'f': case 't': return CMD_TARGET_MAYBE_PREV_TARGET;
+
+ case '-': return CMD_TARGET_CYCLE_BACK;
+ case '+': case '=': return CMD_TARGET_CYCLE_FORWARD;
+ case ';': case '/': return CMD_TARGET_OBJ_CYCLE_BACK;
+ case '*': case '\'': return CMD_TARGET_OBJ_CYCLE_FORWARD;
+
+ case 'b': return CMD_TARGET_DOWN_LEFT;
+ case 'h': return CMD_TARGET_LEFT;
+ case 'j': return CMD_TARGET_DOWN;
+ case 'k': return CMD_TARGET_UP;
+ case 'l': return CMD_TARGET_RIGHT;
+ case 'n': return CMD_TARGET_DOWN_RIGHT;
+ case 'u': return CMD_TARGET_UP_RIGHT;
+ case 'y': return CMD_TARGET_UP_LEFT;
+
+ case 'B': return CMD_TARGET_DIR_DOWN_LEFT;
+ case 'H': return CMD_TARGET_DIR_LEFT;
+ case 'J': return CMD_TARGET_DIR_DOWN;
+ case 'K': return CMD_TARGET_DIR_UP;
+ case 'L': return CMD_TARGET_DIR_RIGHT;
+ case 'N': return CMD_TARGET_DIR_DOWN_RIGHT;
+ case 'U': return CMD_TARGET_DIR_UP_RIGHT;
+ case 'Y': return CMD_TARGET_DIR_UP_LEFT;
+
+ default: return CMD_NO_CMD;
+ }
+}
+
+bool targeting_behaviour::should_redraw()
+{
+ return (false);
+}
diff --git a/crawl-ref/source/direct.h b/crawl-ref/source/direct.h
index f8be4357a7..9541e23825 100644
--- a/crawl-ref/source/direct.h
+++ b/crawl-ref/source/direct.h
@@ -23,9 +23,26 @@
* spells2 - spells3 - spells4
* *********************************************************************** */
+// An object that modifies the behaviour of the direction prompt.
+class targeting_behaviour
+{
+public:
+ targeting_behaviour(bool just_looking = false);
+ virtual ~targeting_behaviour();
+
+ // Returns a keystroke for the prompt.
+ virtual int get_key();
+ virtual command_type get_command(int key = -1);
+ virtual bool should_redraw();
+
+public:
+ bool just_looking;
+ bool compass;
+};
+
void direction( dist &moves, targeting_type restricts = DIR_NONE,
targ_mode_type mode = TARG_ANY, bool just_looking = false,
- const char *prompt = NULL );
+ const char *prompt = NULL, targeting_behaviour *mod = NULL );
bool in_los_bounds(int x, int y);
bool in_viewport_bounds(int x, int y);
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 90a73f833d..330c3fe0a8 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -695,6 +695,7 @@ public:
char shield_blocks; // number of shield blocks since last action
FixedVector< item_def, ENDOFPACK > inv;
+ int quiver; // default item for (f)ire.
int burden;
burden_state_type burden_state;
diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc
index 183c7d3d14..a27ec3ae27 100644
--- a/crawl-ref/source/item_use.cc
+++ b/crawl-ref/source/item_use.cc
@@ -36,6 +36,7 @@
#include "beam.h"
#include "cio.h"
+#include "command.h"
#include "debug.h"
#include "delay.h"
#include "describe.h"
@@ -1155,40 +1156,63 @@ static bool fire_item_matches(const item_def &item, unsigned fire_type)
return (false);
}
-static int find_fire_item_matching(unsigned fire_type_flags, int start = 0)
+static bool fire_item_okay(const item_def &item, unsigned flags)
{
- for (int i = start; i < ENDOFPACK; ++i)
+ return (fire_item_matches(item, flags)
+ && check_warning_inscriptions(item, OPER_FIRE));
+}
+
+static int find_fire_item_matching(unsigned fire_type, int start,
+ bool forward, bool check_quiver)
+{
+ if (check_quiver)
{
- if (i < Options.fire_items_start)
- continue;
- if (fire_item_matches(you.inv[i], fire_type_flags)
- && check_warning_inscriptions(you.inv[i], OPER_FIRE))
- return (i);
+ const int q = you.quiver;
+ if (q >= 0 && q < ENDOFPACK && fire_item_okay(you.inv[q], fire_type))
+ return (q);
}
- for (int i = 0; i < start; ++i)
+ const int dir = forward? 1 : -1;
+ int end = forward? ENDOFPACK : -1;
+
+ for (int i = start; i != end; )
{
- if (i < Options.fire_items_start)
- continue;
- if (fire_item_matches(you.inv[i], fire_type_flags)
- && check_warning_inscriptions(you.inv[i], OPER_FIRE))
+ if (i >= Options.fire_items_start
+ && fire_item_okay(you.inv[i], fire_type))
+ {
return (i);
+ }
+
+ i += dir;
+ if (i == -1)
+ {
+ i += ENDOFPACK;
+ end = start;
+ }
+ else if (i == ENDOFPACK)
+ {
+ i = 0;
+ end = start;
+ }
}
-
return (ENDOFPACK);
}
// Note: This is a simple implementation, not an efficient one. -- bwr
//
// Returns item index or ENDOFPACK if no item found for auto-firing
-int get_fire_item_index( void )
+int get_fire_item_index(int start_from, bool forward, bool check_quiver)
{
int item = ENDOFPACK;
for (unsigned i = 0; i < Options.fire_order.size(); i++)
{
const unsigned fire_flags = Options.fire_order[i];
- if ((item = find_fire_item_matching(fire_flags)) != ENDOFPACK)
+ if ((item =
+ find_fire_item_matching(fire_flags,
+ start_from,
+ forward,
+ check_quiver)) != ENDOFPACK)
break;
}
@@ -1196,6 +1220,124 @@ int get_fire_item_index( void )
return (item);
}
+static void announce_ammo(int item)
+{
+ mesclr();
+ mprf("Firing%s: %s",
+ get_fire_item_index((item + 1) % ENDOFPACK, true, false) != item?
+ " (^N/^P - change)" : "",
+ you.inv[item].name(DESC_INVENTORY_EQUIP).c_str());
+}
+
+class fire_target_behaviour : public targeting_behaviour
+{
+public:
+ fire_target_behaviour(int it) : item(it), need_prompt(false) { }
+ command_type get_command(int key = -1);
+ bool should_redraw();
+ void announce_new_ammo(bool redraw = true);
+
+public:
+ int item;
+ bool need_prompt;
+
+private:
+ void find_next_ammo();
+ void find_prev_ammo();
+};
+
+bool fire_target_behaviour::should_redraw()
+{
+ if (need_prompt)
+ {
+ need_prompt = false;
+ return (true);
+ }
+ return (false);
+}
+
+command_type fire_target_behaviour::get_command(int key)
+{
+ if (key == -1)
+ key = get_key();
+
+ switch (key)
+ {
+ case CONTROL('N'):
+ find_next_ammo();
+ break;
+ case CONTROL('P'):
+ find_prev_ammo();
+ break;
+ case '?':
+ show_targeting_help();
+ redraw_screen();
+ announce_new_ammo(item);
+ need_prompt = true;
+ return (CMD_NO_CMD);
+ }
+
+ return targeting_behaviour::get_command(key);
+}
+
+void fire_target_behaviour::announce_new_ammo(bool redraw)
+{
+ announce_ammo(item);
+ need_prompt = redraw;
+}
+
+void fire_target_behaviour::find_next_ammo()
+{
+ const int start = item == ENDOFPACK - 1? 0 : item + 1;
+ const int next = get_fire_item_index(start, true, false);
+
+ // We should never get back ENDOFPACK.
+ if (next != item)
+ {
+ item = next;
+ announce_new_ammo();
+ }
+}
+
+void fire_target_behaviour::find_prev_ammo()
+{
+ const int start = item == 0? ENDOFPACK - 1 : item - 1;
+ const int next = get_fire_item_index(start, false, false);
+
+ // We should never get back ENDOFPACK.
+ if (next != item)
+ {
+ item = next;
+ announce_new_ammo();
+ }
+}
+
+static bool choose_fire_target(dist &target, int &item)
+{
+ announce_ammo(item);
+ message_current_target();
+
+ fire_target_behaviour beh(item);
+ direction( target, DIR_NONE, TARG_ENEMY, false, NULL, &beh );
+
+ if (!target.isValid)
+ {
+ if (target.isCancel)
+ canned_msg(MSG_OK);
+ return (false);
+ }
+
+ // Okay, valid target; if the user chose different ammo, quiver it.
+ if (beh.item != item)
+ {
+ item = beh.item;
+ if (you.inv[beh.item].quantity > 1)
+ you.quiver = beh.item;
+ }
+
+ return (true);
+}
+
void shoot_thing(void)
{
struct bolt beam; // passed in by reference, but never used here
@@ -1207,7 +1349,7 @@ void shoot_thing(void)
return;
}
- const int item = get_fire_item_index();
+ int item = get_fire_item_index();
if (item == ENDOFPACK)
{
@@ -1216,9 +1358,9 @@ void shoot_thing(void)
return;
}
- mprf("Firing: %s", you.inv[item].name(DESC_INVENTORY_EQUIP).c_str());
-
- throw_it( beam, item );
+ dist target;
+ if (choose_fire_target(target, item))
+ throw_it( beam, item, false, 0, &target );
} // end shoot_thing()
// Returns delay multiplier numerator (denominator should be 100) for the
@@ -1359,9 +1501,10 @@ static int dex_adjust_thrown_tohit(int hit)
//
// Return value is only relevant if dummy_target is non-NULL, and returns
// true if dummy_target is hit.
-bool throw_it(bolt &pbolt, int throw_2, bool teleport, int acc_bonus)
+bool throw_it(bolt &pbolt, int throw_2, bool teleport, int acc_bonus,
+ dist *target)
{
- struct dist thr;
+ dist thr;
char shoot_skill = 0;
char lnchClass, lnchType; // launcher class and type
@@ -1377,15 +1520,20 @@ bool throw_it(bolt &pbolt, int throw_2, bool teleport, int acc_bonus)
if (!teleport)
{
- message_current_target();
- direction( thr, DIR_NONE, TARG_ENEMY );
-
- if (!thr.isValid)
+ if (target)
+ thr = *target;
+ else
{
- if (thr.isCancel)
- canned_msg(MSG_OK);
+ message_current_target();
+ direction( thr, DIR_NONE, TARG_ENEMY );
+
+ if (!thr.isValid)
+ {
+ if (thr.isCancel)
+ canned_msg(MSG_OK);
- return (false);
+ return (false);
+ }
}
}
diff --git a/crawl-ref/source/item_use.h b/crawl-ref/source/item_use.h
index 3ba4d11a00..d0ccb961c9 100644
--- a/crawl-ref/source/item_use.h
+++ b/crawl-ref/source/item_use.h
@@ -76,7 +76,8 @@ bool remove_ring(int slot = -1, bool announce = false);
/* ***********************************************************************
* called from: acr
* *********************************************************************** */
-int get_fire_item_index(void);
+int get_fire_item_index(int start_from = 0, bool forward = true,
+ bool check_quiver = true);
void shoot_thing(void);
@@ -138,7 +139,8 @@ bool puton_item(int slot, bool prompt_finger = true);
bool enchant_weapon( int which_stat, bool quiet = false );
-bool throw_it(bolt &pbolt, int throw_2, bool teleport=false, int acc_bonus=0);
+bool throw_it(bolt &pbolt, int throw_2, bool teleport=false, int acc_bonus=0,
+ dist *target = NULL);
void inscribe_item();
int launcher_shield_slowdown(const item_def &launcher,
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index d785552489..0c373c2690 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -4617,6 +4617,8 @@ void player::init()
inv[i].link = i;
}
+ quiver = -1;
+
duration.init(0);
exp_available = 25;
diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc
index c4d039134f..0c9d0fc0a5 100644
--- a/crawl-ref/source/tags.cc
+++ b/crawl-ref/source/tags.cc
@@ -875,6 +875,8 @@ static void tag_construct_you_items(struct tagHeader &th)
marshallString(th, you.inv[i].inscription.c_str(), 80);
}
+ marshallByte(th, you.quiver);
+
// item descrip for each type & subtype
// how many types?
marshallByte(th, 5);
@@ -1179,6 +1181,8 @@ static void tag_read_you_items(struct tagHeader &th, char minorVersion)
you.inv[i].slot = index_to_letter(i);
}
+ you.quiver = unmarshallByte(th);
+
// item descrip for each type & subtype
// how many types?
count_c = unmarshallByte(th);