summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-06-24 14:06:28 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-06-24 14:06:28 +0000
commita117fb1baf5f81a56014a174f0400622cdf2ab5d (patch)
treeebe42721a9dad967d0c1a000a29c1a01920a19f6 /crawl-ref
parent33b1249af4f983197d5af346199c5d0a4061835a (diff)
downloadcrawl-ref-a117fb1baf5f81a56014a174f0400622cdf2ab5d.tar.gz
crawl-ref-a117fb1baf5f81a56014a174f0400622cdf2ab5d.zip
Modify quiver to only quiver ammunition explicitly chosen by the player
(via (,) or i, or by the new quivering command). Ammo that just happens to come next in the fire order is not quivered anymore even if you continue firing. Add a new quiver command on Q, and while I was at it, restrict the items offered when firing (fi) or quivering to actual throwables. (This was a long outstanding FR.) I think that's it... git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@6112 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/acr.cc2
-rw-r--r--crawl-ref/source/describe.cc13
-rw-r--r--crawl-ref/source/directn.cc13
-rw-r--r--crawl-ref/source/directn.h1
-rw-r--r--crawl-ref/source/invent.cc26
-rw-r--r--crawl-ref/source/invent.h19
-rw-r--r--crawl-ref/source/item_use.cc92
-rw-r--r--crawl-ref/source/makeitem.cc8
-rw-r--r--crawl-ref/source/output.cc20
-rw-r--r--crawl-ref/source/quiver.cc64
-rw-r--r--crawl-ref/source/quiver.h10
-rw-r--r--crawl-ref/source/randart.cc6
12 files changed, 185 insertions, 89 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index fa2a47c612..f6b290e344 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -2080,7 +2080,7 @@ void process_command( command_type cmd )
break;
case CMD_QUIVER_ITEM:
- mpr("Sorry, this command has not yet been implemented.");
+ choose_item_for_quiver();
break;
case CMD_WEAR_ARMOUR:
diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc
index 42cd0de8da..90f5b2c6f4 100644
--- a/crawl-ref/source/describe.cc
+++ b/crawl-ref/source/describe.cc
@@ -1344,19 +1344,26 @@ static std::string _describe_jewellery( const item_def &item, bool verbose)
break;
case RING_SLAYING:
- if (item.plus != 0 || is_random_artefact( item ))
+ if (item.plus != 0)
{
description += "$It affects your accuracy (";
_append_value( description, item.plus, true );
description += ").";
}
- if (item.plus2 != 0 || is_random_artefact( item ))
+ if (item.plus2 != 0)
{
description += "$It affects your damage-dealing abilities (";
_append_value( description, item.plus2, true );
description += ").";
}
+
+ if (item.plus == 0 && item.plus2 == 0)
+ {
+ description += "This buggy ring affects neither your "
+ "accuracy nor your damage-dealing "
+ "abilities.";
+ }
break;
default:
@@ -1365,7 +1372,7 @@ static std::string _describe_jewellery( const item_def &item, bool verbose)
}
}
- // randart properties
+ // Randart properties.
if (is_random_artefact( item ))
{
description += "$";
diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc
index e84c8d8319..2f86f47638 100644
--- a/crawl-ref/source/directn.cc
+++ b/crawl-ref/source/directn.cc
@@ -134,18 +134,18 @@ void direction_choose_compass( dist& moves, targeting_behaviour *beh)
}
const int i = _targeting_cmd_to_compass(key_command);
- if ( i != -1 )
+ if (i != -1)
{
moves.dx = Compass[i].x;
moves.dy = Compass[i].y;
}
- else if ( key_command == CMD_TARGET_CANCEL )
+ else if (key_command == CMD_TARGET_CANCEL)
{
moves.isCancel = true;
moves.isValid = false;
}
}
- while ( !moves.isCancel && moves.dx == 0 && moves.dy == 0 );
+ while (!moves.isCancel && moves.dx == 0 && moves.dy == 0);
}
static int _targeting_cmd_to_compass( command_type command )
@@ -832,6 +832,7 @@ void direction(dist& moves, targeting_type restricts,
case CMD_TARGET_CANCEL:
loop_done = true;
moves.isCancel = true;
+ beh->mark_ammo_nonchosen();
break;
#ifdef WIZARD
@@ -839,6 +840,7 @@ void direction(dist& moves, targeting_type restricts,
// Maybe we can skip this check...but it can't hurt
if (!you.wizard || !in_bounds(moves.tx, moves.ty))
break;
+
mid = mgrd[moves.tx][moves.ty];
if (mid == NON_MONSTER) // can put in terrain description here
break;
@@ -2575,3 +2577,8 @@ bool targeting_behaviour::should_redraw()
{
return (false);
}
+
+void targeting_behaviour::mark_ammo_nonchosen()
+{
+ // Nothing to be done.
+}
diff --git a/crawl-ref/source/directn.h b/crawl-ref/source/directn.h
index a4cc637df2..b6cbd52bed 100644
--- a/crawl-ref/source/directn.h
+++ b/crawl-ref/source/directn.h
@@ -116,6 +116,7 @@ public:
virtual int get_key();
virtual command_type get_command(int key = -1);
virtual bool should_redraw();
+ virtual void mark_ammo_nonchosen();
public:
bool just_looking;
diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc
index b623a73411..e2955ca7db 100644
--- a/crawl-ref/source/invent.cc
+++ b/crawl-ref/source/invent.cc
@@ -357,6 +357,8 @@ static std::string _no_selectables_message(int item_selector)
return("You aren't carrying any books or scrolls.");
case OBJ_WANDS:
return("You aren't carrying any wands.");
+ case OSEL_THROWABLE:
+ return("You aren't carrying any items that might be thrown or fired.");
}
return("You aren't carrying any such object.");
@@ -804,33 +806,55 @@ static bool _item_class_selected(const item_def &i, int selector)
{
case OSEL_UNIDENT:
return !fully_identified(i);
+
case OBJ_MISSILES:
return (itype == OBJ_MISSILES || itype == OBJ_WEAPONS);
+
+ case OSEL_THROWABLE:
+ {
+ if (i.base_type != OBJ_WEAPONS && i.base_type != OBJ_MISSILES)
+ return (false);
+
+ const launch_retval projected = is_launched(&you, you.weapon(), i);
+
+ if (projected == LRET_FUMBLED)
+ return (false);
+
+ return (true);
+ }
case OBJ_WEAPONS:
case OSEL_WIELD:
return (itype == OBJ_WEAPONS || itype == OBJ_STAVES
|| itype == OBJ_MISCELLANY);
+
case OSEL_MEMORISE:
return (itype == OBJ_BOOKS && i.sub_type != BOOK_MANUAL
&& (i.sub_type != BOOK_DESTRUCTION || !item_type_known(i)));
+
case OBJ_SCROLLS:
return (itype == OBJ_SCROLLS || itype == OBJ_BOOKS);
+
case OSEL_RECHARGE:
return (item_is_rechargable(i, true));
+
case OSEL_ENCH_ARM:
return (is_enchantable_armour(i, true));
+
case OSEL_VAMP_EAT:
return (itype == OBJ_CORPSES && i.sub_type == CORPSE_BODY
&& !food_is_rotten(i) && mons_has_blood(i.plus));
+
case OSEL_DRAW_DECK:
return (is_deck(i));
+
case OSEL_EQUIP:
for (int eq = 0; eq < NUM_EQUIP; eq++)
{
if (you.equip[eq] == i.link)
return (true);
}
- // fall through
+ return (false);
+
default:
return (false);
}
diff --git a/crawl-ref/source/invent.h b/crawl-ref/source/invent.h
index f11916107e..8ff0a75e35 100644
--- a/crawl-ref/source/invent.h
+++ b/crawl-ref/source/invent.h
@@ -22,15 +22,16 @@
enum object_selector
{
- OSEL_ANY = -1,
- OSEL_WIELD = -2,
- OSEL_UNIDENT = -3,
- OSEL_EQUIP = -4,
- OSEL_MEMORISE = -5,
- OSEL_RECHARGE = -6,
- OSEL_ENCH_ARM = -7,
- OSEL_VAMP_EAT = -8,
- OSEL_DRAW_DECK = -9
+ OSEL_ANY = -1,
+ OSEL_WIELD = -2,
+ OSEL_UNIDENT = -3,
+ OSEL_EQUIP = -4,
+ OSEL_MEMORISE = -5,
+ OSEL_RECHARGE = -6,
+ OSEL_ENCH_ARM = -7,
+ OSEL_VAMP_EAT = -8,
+ OSEL_DRAW_DECK = -9,
+ OSEL_THROWABLE = -10
};
#define PROMPT_ABORT -1
diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc
index 3ec29799a1..392a37016f 100644
--- a/crawl-ref/source/item_use.cc
+++ b/crawl-ref/source/item_use.cc
@@ -1292,7 +1292,8 @@ class fire_target_behaviour : public targeting_behaviour
{
public:
fire_target_behaviour()
- : m_slot(-1), selected_from_inventory(false), need_prompt(false)
+ : m_slot(-1), selected_from_inventory(false), need_prompt(false),
+ chosen_ammo(false)
{
m_slot = you.m_quiver->get_fire_item(&m_noitem_reason);
}
@@ -1300,6 +1301,7 @@ public:
// targeting_behaviour API
virtual command_type get_command(int key = -1);
virtual bool should_redraw();
+ virtual void mark_ammo_nonchosen();
void message_ammo_prompt(const std::string* pre_text = 0);
@@ -1308,6 +1310,7 @@ public:
std::string m_noitem_reason;
bool selected_from_inventory;
bool need_prompt;
+ bool chosen_ammo;
};
void fire_target_behaviour::message_ammo_prompt(const std::string* pre_text)
@@ -1381,6 +1384,11 @@ bool fire_target_behaviour::should_redraw()
return (false);
}
+void fire_target_behaviour::mark_ammo_nonchosen()
+{
+ chosen_ammo = false;
+}
+
command_type fire_target_behaviour::get_command(int key)
{
if (key == -1)
@@ -1388,42 +1396,44 @@ command_type fire_target_behaviour::get_command(int key)
switch (key)
{
- case '(':
- case CONTROL('N'):
- case ')':
- case CONTROL('P'):
- {
- const int direction = (key == CONTROL('P') || key == ')') ? -1 : +1;
- const int next = get_next_fire_item(m_slot, direction);
- if (next != m_slot && next != -1)
- {
- m_slot = next;
- selected_from_inventory = false;
- }
- // Do this stuff unconditionally to make the prompt redraw.
- message_ammo_prompt();
- need_prompt = true;
- break;
- }
- case 'i':
- {
- std::string err;
- const int selected = _fire_prompt_for_item(err);
- if (selected >= 0 && _fire_validate_item(selected, err))
- {
- m_slot = selected;
- selected_from_inventory = true;
- }
- message_ammo_prompt( err.length() ? &err : NULL );
- need_prompt = true;
- return (CMD_NO_CMD);
- }
- case '?':
- show_targeting_help();
- redraw_screen();
- message_ammo_prompt();
- need_prompt = true;
- return (CMD_NO_CMD);
+ case '(':
+ case CONTROL('N'):
+ case ')':
+ case CONTROL('P'):
+ {
+ const int direction = (key == CONTROL('P') || key == ')') ? -1 : +1;
+ const int next = get_next_fire_item(m_slot, direction);
+ if (next != m_slot && next != -1)
+ {
+ m_slot = next;
+ selected_from_inventory = false;
+ chosen_ammo = true;
+ }
+ // Do this stuff unconditionally to make the prompt redraw.
+ message_ammo_prompt();
+ need_prompt = true;
+ break;
+ }
+ case 'i':
+ {
+ std::string err;
+ const int selected = _fire_prompt_for_item(err);
+ if (selected >= 0 && _fire_validate_item(selected, err))
+ {
+ m_slot = selected;
+ selected_from_inventory = true;
+ chosen_ammo = true;
+ }
+ message_ammo_prompt( err.length() ? &err : NULL );
+ need_prompt = true;
+ return (CMD_NO_CMD);
+ }
+ case '?':
+ show_targeting_help();
+ redraw_screen();
+ message_ammo_prompt();
+ need_prompt = true;
+ return (CMD_NO_CMD);
}
return targeting_behaviour::get_command(key);
@@ -1462,17 +1472,20 @@ static bool _fire_choose_item_and_target(int& slot, dist& target,
return (false);
}
+ you.m_quiver->on_item_fired(you.inv[beh.m_slot], beh.chosen_ammo);
+/*
// If ammo was chosen via 'fi', it's not supposed to get quivered.
// Otherwise, if the user chose different ammo, quiver it.
// Same for items selected in tile mode.
if (was_chosen || !beh.selected_from_inventory)
{
- you.m_quiver->on_item_fired(you.inv[beh.m_slot]);
+ you.m_quiver->on_item_fired(you.inv[beh.m_slot], beh.chosen_ammo);
}
else
{
you.m_quiver->on_item_fired_fi(you.inv[beh.m_slot]);
}
+*/
you.redraw_quiver = true;
slot = beh.m_slot;
@@ -1493,8 +1506,9 @@ static int _fire_prompt_for_item(std::string& err)
int slot = prompt_invent_item( "Fire/throw which item? (* to show all)",
MT_INVLIST,
- OBJ_MISSILES, true, true, true, 0, NULL,
+ OSEL_THROWABLE, true, true, true, 0, NULL,
OPER_FIRE );
+
if (slot == PROMPT_ABORT || slot == PROMPT_NOTHING)
{
err = "Nothing selected.";
diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc
index b885d764f8..52989e4462 100644
--- a/crawl-ref/source/makeitem.cc
+++ b/crawl-ref/source/makeitem.cc
@@ -2596,17 +2596,17 @@ static void _generate_jewellery_item(item_def& item, bool allow_uniques,
: get_random_ring_type());
}
- // everything begins as uncursed, unenchanted jewellery {dlb}:
+ // Everything begins as uncursed, unenchanted jewellery {dlb}:
item.plus = 0;
item.plus2 = 0;
item.plus = _determine_ring_plus(item.sub_type);
- if ( item.plus < 0 )
+ if (item.plus < 0)
do_curse_item(item);
if (item.sub_type == RING_SLAYING ) // requires plus2 too
{
- if (item_cursed( item ) && !one_chance_in(20))
+ if (item_cursed(item) && !one_chance_in(20))
item.plus2 = -1 - random2avg(6, 2);
else
{
@@ -2615,7 +2615,7 @@ static void _generate_jewellery_item(item_def& item, bool allow_uniques,
if (random2(25) < 9) // 36% of such rings {dlb}
{
// make "ring of damage"
- do_uncurse_item( item );
+ do_uncurse_item(item);
item.plus = 0;
item.plus2 += 2;
}
diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc
index c1dca948a5..ad0e9a284b 100644
--- a/crawl-ref/source/output.cc
+++ b/crawl-ref/source/output.cc
@@ -507,6 +507,7 @@ static void _print_stats_qv(int y)
const std::string prefix = menu_colour_item_prefix(quiver);
const int prefcol =
menu_colour(quiver.name(DESC_INVENTORY), prefix);
+
if (prefcol != -1)
textcolor(prefcol);
@@ -519,25 +520,6 @@ static void _print_stats_qv(int y)
{
textcolor(LIGHTGREY);
cprintf("Nothing quivered");
-
-/*
- const item_def* item;
- you.m_quiver->get_desired_item(&item, &q);
-
- if (item != NULL && is_valid_item(*item))
- {
- textcolor(item->colour);
- cprintf("-) %s", item->name(DESC_PLAIN, true)
- .substr(0, crawl_view.hudsz.x - 15).c_str());
- textcolor(RED);
- cprintf(" (empty)");
- }
- else
- {
- textcolor(LIGHTGREY);
- cprintf("Nothing quivered");
- }
-*/
}
textcolor(LIGHTGREY);
diff --git a/crawl-ref/source/quiver.cc b/crawl-ref/source/quiver.cc
index 6ecf4c8661..e22f5097c3 100644
--- a/crawl-ref/source/quiver.cc
+++ b/crawl-ref/source/quiver.cc
@@ -12,6 +12,7 @@
#include "AppHdr.h"
#include "quiver.h"
+#include "invent.h"
#include "item_use.h"
#include "itemprop.h"
#include "items.h"
@@ -122,9 +123,60 @@ int player_quiver::get_fire_item(std::string* no_item_reason) const
return slot;
}
+void player_quiver::set_quiver(const item_def &item, ammo_t ammo_type)
+{
+ m_last_used_of_type[ammo_type] = item;
+ m_last_used_of_type[ammo_type].quantity = 1;
+ m_last_used_type = ammo_type;
+ you.redraw_quiver = true;
+}
+
+void choose_item_for_quiver()
+{
+ int slot = prompt_invent_item( "Quiver which item? (* to show all)",
+ MT_INVLIST,
+ OSEL_THROWABLE, true, true, true, 0, NULL,
+ OPER_FIRE );
+
+ if (slot == PROMPT_ABORT)
+ {
+ canned_msg(MSG_OK);
+ return;
+ }
+ else if (slot == PROMPT_NOTHING)
+ return;
+
+ const item_def item = you.inv[slot];
+
+ if (!is_valid_item(item))
+ return;
+
+ ammo_t t = AMMO_THROW;
+
+ const item_def *weapon = you.weapon();
+ if (weapon && item.launched_by(*weapon))
+ t = _get_weapon_ammo_type(weapon);
+
+ you.m_quiver->set_quiver(you.inv[slot], t);
+ mprf("Quivering %s %s.", you.inv[slot].name(DESC_INVENTORY).c_str(),
+ t == AMMO_THROW ? "as throwing weapon" :
+ t == AMMO_BLOWGUN ? "for blowguns" :
+ t == AMMO_SLING ? "for slings" :
+ t == AMMO_BOW ? "for bows" :
+ t == AMMO_CROSSBOW ? "for crossbows"
+ : "for hand crossbows");
+}
+
// Notification that item was fired with 'f'.
-void player_quiver::on_item_fired(const item_def& item)
+void player_quiver::on_item_fired(const item_def& item, bool explicitly_chosen)
{
+ if (!explicitly_chosen)
+ {
+ // If the item was not actively chosen, i.e. just automatically
+ // passed into the quiver, don't change any of the quiver settings.
+ you.redraw_quiver = true;
+ return;
+ }
// If item matches the launcher, put it in that launcher's last-used item.
// Otherwise, it goes into last hand-thrown item.
@@ -376,9 +428,12 @@ void player_quiver::load(reader& inf)
preserve_quiver_slots::preserve_quiver_slots()
{
- if (!you.m_quiver) return;
+ if (!you.m_quiver)
+ return;
+
COMPILE_CHECK(ARRAYSZ(m_last_used_of_type) ==
ARRAYSZ(you.m_quiver->m_last_used_of_type), a);
+
for (unsigned int i = 0; i < ARRAYSZ(m_last_used_of_type); i++)
{
m_last_used_of_type[i] =
@@ -388,7 +443,9 @@ preserve_quiver_slots::preserve_quiver_slots()
preserve_quiver_slots::~preserve_quiver_slots()
{
- if (! you.m_quiver) return;
+ if (!you.m_quiver)
+ return;
+
for (unsigned int i = 0; i < ARRAYSZ(m_last_used_of_type); i++)
{
const int slot = m_last_used_of_type[i];
@@ -473,7 +530,6 @@ static int _get_pack_slot(const item_def& item)
return -1;
}
-
// Returns the type of ammo used by the player's equipped weapon,
// or AMMO_THROW if it's not a launcher.
static ammo_t _get_weapon_ammo_type(const item_def* weapon)
diff --git a/crawl-ref/source/quiver.h b/crawl-ref/source/quiver.h
index 04366051d2..5014cc1a8f 100644
--- a/crawl-ref/source/quiver.h
+++ b/crawl-ref/source/quiver.h
@@ -34,12 +34,13 @@ class player_quiver
// Queries from engine -- don't affect state
void get_desired_item(const item_def** item_out, int* slot_out) const;
- int get_fire_item(std::string* no_item_reason=0) const;
+ int get_fire_item(std::string* no_item_reason = 0) const;
void get_fire_order(std::vector<int>& v) const;
// Callbacks from engine
- void on_item_fired(const item_def&);
- void on_item_fired_fi(const item_def&);
+ void set_quiver(const item_def &item, ammo_t ammo_type);
+ void on_item_fired(const item_def &item, bool explicitly_chosen = false);
+ void on_item_fired_fi(const item_def &item);
void on_inv_quantity_changed(int slot, int amt);
void on_weapon_changed();
@@ -77,4 +78,7 @@ class preserve_quiver_slots
int m_last_used_of_type[NUM_AMMO];
};
+
+void choose_item_for_quiver(void);
+
#endif
diff --git a/crawl-ref/source/randart.cc b/crawl-ref/source/randart.cc
index 9471d21190..ecbca074da 100644
--- a/crawl-ref/source/randart.cc
+++ b/crawl-ref/source/randart.cc
@@ -470,7 +470,7 @@ void randart_desc_properties( const item_def &item,
break;
case RING_STRENGTH:
- fake_rap = RAP_STRENGTH;
+ fake_rap = RAP_STRENGTH;
fake_plus = item.plus;
break;
@@ -510,10 +510,10 @@ void randart_desc_properties( const item_def &item,
break;
}
- if (fake_rap != RAP_NUM_PROPERTIES)
+ if (fake_rap != RAP_NUM_PROPERTIES && fake_plus != 0)
proprt[fake_rap] += fake_plus;
- if (fake_rap2 != RAP_NUM_PROPERTIES)
+ if (fake_rap2 != RAP_NUM_PROPERTIES && fake_plus2 != 0)
proprt[fake_rap2] += fake_plus2;
if (item_ident( item, ISFLAG_KNOW_PROPERTIES )