git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1847 c06c8d41-db1a-0410-9941-cceddc491573
4GFCF6N3MZSCHUB77Z3SQYJ3FYR5N3VBW2CGWANLJ74O5FEQH3CQC
2CKTZRWEVA5INSOXZ6H7675TAAA55TPNWYIVVUQWSCS5DYCANSFQC
5V47S4NNTHWTSAHV3YLO2VGH7JTUIYJ3GBPDN5ZM4UQALT2ZEXDQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
IPB47Q5V3UZIUXP4CHHLYXA5UA4ETTNXJACUBD6YWVIYQDMCZNAAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
GT7BSR54BVJKHUCLEBTELGBMNBFFDQW52EVC4XKVEMUVG2UGZMDAC
2WNUWTZNE66IUUTQ4NW3RN7P2MFUKBXPD265M5CTZCDKC56VQONQC
VNIAJEGE3PYE6F6EAMCQDWMAS52EQTKJUPAFXK7ARCITZ326WTTQC
V4WGXVERZ34B7CEINV4D3ZYEKKT2TUIUYTOX5FSOX6B26U3DPVLQC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
KU6YUIJWXZSNTABFB36HDEEZ6LTY7O4VKI3RNFBQE3LEYZCT3XQQC
BWAQ3FHBBM6G3K3KYP75CRTR343RDQZJRYX5ZGYUEXYBAC3APDLAC
H3552BCIAVBLKAYKE4DHFLBLFW5RGRMYBMRRYHYEB5IPIJRUVU5QC
2ZFV5PKZU3HDHMLJWVWPPFV43NUNUON6YSAITHB26D7L4XIVWUHQC
EHSY6DVGUMI6C67WKET3GDJVLWJWGYBYQONNDK5JVT7BCTHBEZVAC
RVST2QHYJ757ZHK4AUJ5NGPDZ44AD6RVFVXYPKQIBJXZBDNUCHXQC
XPCGZBHHSL6MB3ORMUJI64BAERU6AZTIY6RK56BBW7SNB3IK24IAC
// skip invalid objects, wielded object
if (!is_valid_item( you.inv[i] ) || you.equip[EQ_WEAPON] == i)
continue;
if ((fire_type & FIRE_DART) && item.sub_type == MI_DART)
return (true);
if ((fire_type & FIRE_STONE)
&& (item.sub_type == MI_STONE || item.sub_type == MI_SLING_BULLET))
return (true);
if ((fire_type & FIRE_JAVELIN) && item.sub_type == MI_JAVELIN)
return (true);
if ((fire_type & FIRE_ROCK) && item.sub_type == MI_LARGE_ROCK)
return (true);
return (i);
else if (item.base_type == OBJ_WEAPONS
&& is_throwable(item, you.body_size()))
{
if ((fire_type & FIRE_DAGGER) && item.sub_type == WPN_DAGGER)
return (true);
if ((fire_type & FIRE_SPEAR) && item.sub_type == WPN_SPEAR)
return (true);
if ((fire_type & FIRE_HAND_AXE) && item.sub_type == WPN_HAND_AXE)
return (true);
if ((fire_type & FIRE_CLUB) && item.sub_type == WPN_CLUB)
return (true);
}
return (false);
// Return index of first missile of sub_type or ENDOFPACK
static int try_finding_missile( int sub_type, const item_def *launcher = NULL )
static int find_fire_item_matching(unsigned fire_type_flags, int start = 0)
const item_def &item = you.inv[i];
// In theory, we should do two passes, first trying
// to find a non-warning-inscribed item, then looping
// through the warning-inscribed ones. Seems unlikely
// to matter much.
if (launcher && item.launched_by(*launcher))
break;
// consider melee weapons that can also be thrown
if (item.base_type == OBJ_MISSILES
&& (item.sub_type == sub_type
|| (sub_type == MI_STONE && item.sub_type == MI_SLING_BULLET))
if (fire_item_matches(you.inv[i], fire_type_flags)
// look for next type on list... if found item is set != ENDOFPACK
switch (Options.fire_order[i])
{
case FIRE_LAUNCHER:
// check if we have ammo for a wielded launcher:
if (weapon != -1
&& you.inv[ weapon ].base_type == OBJ_WEAPONS
&& is_range_weapon( you.inv[ weapon ] ))
{
item = try_finding_missile( MI_NONE, &you.inv[weapon] );
}
const unsigned fire_flags = Options.fire_order[i];
if ((item = find_fire_item_matching(fire_flags)) != ENDOFPACK)
case FIRE_DART:
item = try_finding_missile( MI_DART );
break;
case FIRE_STONE:
item = try_finding_missile( MI_STONE );
break;
case FIRE_JAVELIN:
item = try_finding_missile( MI_JAVELIN );
break;
case FIRE_DAGGER:
item = try_finding_throwing_weapon( WPN_DAGGER );
break;
case FIRE_SPEAR:
item = try_finding_throwing_weapon( WPN_SPEAR );
break;
case FIRE_HAND_AXE:
item = try_finding_throwing_weapon( WPN_HAND_AXE );
break;
case FIRE_CLUB:
item = try_finding_throwing_weapon( WPN_CLUB );
break;
case FIRE_NONE:
default:
break;
}
// if successful break
if (item != ENDOFPACK)
break;
}
static void str_to_fire_order( const std::string &str,
FixedVector< fire_type, NUM_FIRE_TYPES > &list )
{
int i;
size_t pos = 0;
std::string item = "";
for (i = 0; i < NUM_FIRE_TYPES; i++)
{
// get next item from comma delimited list
const size_t end = str.find( ',', pos );
item = str.substr( pos, end - pos );
trim_string( item );
list[i] = str_to_fire_types( item );
if (end == std::string::npos)
break;
else
pos = end + 1;
}
for (int i = 0; i < NUM_FIRE_TYPES; i++)
fire_order[i] = FIRE_NONE;
fire_order[0] = FIRE_LAUNCHER; // fire first from bow...
fire_order[1] = FIRE_JAVELIN;
fire_order[2] = FIRE_DART; // then only consider darts
fire_order[3] = FIRE_STONE; // and then chuck stones
set_fire_order("launcher, javelin / dart / stone");
}
void game_options::set_fire_order(const std::string &s)
{
fire_order.clear();
std::vector<std::string> slots = split_string(",", s);
for (int i = 0, size = slots.size(); i < size; ++i)
add_fire_order_slot(slots[i]);
}
void game_options::add_fire_order_slot(const std::string &s)
{
unsigned flags = 0;
std::vector<std::string> alts = split_string("/", s);
for (int i = 0, size = alts.size(); i < size; ++i)
flags |= str_to_fire_types(alts[i]);
if (flags)
fire_order.push_back(flags);
int fire_items_start; // index of first item for fire command
FixedVector<fire_type, NUM_FIRE_TYPES> fire_order; // order for 'f' command
int fire_items_start; // index of first item for fire command
std::vector<unsigned> fire_order; // missile search order for 'f' command
FIRE_NONE,
FIRE_LAUNCHER,
FIRE_DART,
FIRE_STONE,
FIRE_DAGGER,
FIRE_JAVELIN,
FIRE_SPEAR,
FIRE_HAND_AXE,
FIRE_CLUB,
FIRE_ROCK,
NUM_FIRE_TYPES
FIRE_NONE = 0x0000,
FIRE_LAUNCHER = 0x0001,
FIRE_DART = 0x0002,
FIRE_STONE = 0x0004,
FIRE_DAGGER = 0x0008,
FIRE_JAVELIN = 0x0010,
FIRE_SPEAR = 0x0020,
FIRE_HAND_AXE = 0x0040,
FIRE_CLUB = 0x0080,
FIRE_ROCK = 0x0100
Items that appear first get higher priority.
Items in any position may be slash-separated to indicate that these
are of equal priority. In the example, darts, stones and daggers are
at the same priority, so the first item in your inventory that is
one of these will be picked for firing.