summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/item_use.cc
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-07-13 11:26:38 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-07-13 11:26:38 +0000
commit0eb7e87096f07509f3fed6a82fab696d505a2c18 (patch)
tree2b96ba1d50f34f5c3a9c83a22bf7f4dad4ecdd0f /crawl-ref/source/item_use.cc
parenta14e48e33b5e1eef0503fa426ff31e0c83628d73 (diff)
downloadcrawl-ref-0eb7e87096f07509f3fed6a82fab696d505a2c18.tar.gz
crawl-ref-0eb7e87096f07509f3fed6a82fab696d505a2c18.zip
[1746014] Added an implicit quiver when firing missiles:
- ^P/^N change the selected missile, but only within a fire_order slot. i.e., if you're wielding a launcher and have "launcher" first in your fire order, ^N and ^P will cycle only through suitable launcher ammo. - If you use ^P or ^N to change the default missiles offered, that choice gets saved as your quiver (unless you cancel targeting). - Fire always offers the quivered item first, if appropriate (so if you have darts quivered and try to shoot from a bow, the darts will not be offered). Breaks save compatibility (quiver is saved). git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1854 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/item_use.cc')
-rw-r--r--crawl-ref/source/item_use.cc204
1 files changed, 176 insertions, 28 deletions
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);
+ }
}
}