diff options
-rw-r--r-- | crawl-ref/source/command.cc | 16 | ||||
-rw-r--r-- | crawl-ref/source/direct.cc | 170 | ||||
-rw-r--r-- | crawl-ref/source/direct.h | 19 | ||||
-rw-r--r-- | crawl-ref/source/externs.h | 1 | ||||
-rw-r--r-- | crawl-ref/source/item_use.cc | 204 | ||||
-rw-r--r-- | crawl-ref/source/item_use.h | 6 | ||||
-rw-r--r-- | crawl-ref/source/player.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/tags.cc | 4 |
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); |