git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@4191 c06c8d41-db1a-0410-9941-cceddc491573
ENI6P5WUO7DS4Y7EUDCYB4PSNT7CXH2L5JIB5BLZHNMWN4QDXMWQC TX3LTXGB7TJ2QHLW2TEW6XTCTOW5A3KTZGBPBRTDTUYOZFFT3NLAC TRCCLE5RJ4VJULBOWOI2WC3RJU7WTEGS7RRQTDQL6W5UU246LKTQC TM35IHKZZNBCMR3ERBS4EYHGUK5IVCPUT2JUITMT74AYAIUZSYFQC CWPA3Q5BG7KTTY6GX7CCS26PWC4UHJ47PUCMJX5BOJIP3FSTP2BQC COLMJH3UIQFF4R5AV642OJK4HHGUIIPLNP5WGKLWWYNJV7ZGPI7AC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC EAAACIJUVSBDOB6S73O4NFSMRDLFLQTFO7SXWWALGMVDZTQTHQBQC RPGERJQMO2J4ZDYTRHJCLZMXDVSTUOOJURSZ7FPWOUFHTXIV5VIAC GT7BSR54BVJKHUCLEBTELGBMNBFFDQW52EVC4XKVEMUVG2UGZMDAC NQIXUYGUIQTKZUB2IQDII7BBDMZ4VN4NUUTGT2ARQBZTDJUMPKRQC FVT2J6IVMSQZYKQGUHQVGT4ADYM7AWUQ4U7766GBRRFMSR2WBMLAC AVCMVFA3MKCXHO6H44UK5KJNIHTGQV7UA7GYXM26VI6TXXU5ZN6QC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC DOZORMA366M4HB5JKSS27BMCR6ET7QNZNND2B7KV3NVEEPR5H7EAC CE6FLTWU5PYFBSGVTIJXQXRMHOIHQ3VJCKHQVIMUUAIFHQ73X7NAC 25CH7HH4LKXFIZ75YNMXS3TSXO6O27DYSOPLOD45K4OCNFWLS4LQC LZB2MLE66DKPQPG3BE6IU77HLHYMBQFJTKFJSPKEKZSOSXPXESJQC 4GFCF6N3MZSCHUB77Z3SQYJ3FYR5N3VBW2CGWANLJ74O5FEQH3CQC YPALSPBPRHBZ6AA7Q2JVYWM53XIPB536EJGHUMESY4GKF4XFILZQC 5HBRQ2QZTFBQE2Z2CFADUI2D52LO5Z5CNHXHA7BJP3LGO7FJPUCQC 45MYNXZEG5E2GIOGVN2JXQFLHC56WTCXPD2SW6S6LZJ643G24JHQC WL5WZXFJ6TONUQRSHUY4GQ5USU47ILWNN5X2JDQZO4CRJJZSRQIAC QFM6WJTFHB4KCQYVROAQD4KRAYV2FZKDL5PJZQN5MS7WDYSLJBIAC HSRRNAU5UAYC6B6IQWGJPFROMZBTJICPCH6DJVZDHDTAGOQ6IOYAC RQFPW4BTIVE72VTJJAPQ6SA67IRSNUEAB3CBWN5RXPEDSYWM5ROAC 5V47S4NNTHWTSAHV3YLO2VGH7JTUIYJ3GBPDN5ZM4UQALT2ZEXDQC 6K4SRFJRW7762C4M7GOP2J3ZX6UZOAN5ZAOSS6QALFFG4SXRXJKAC 3GLHLYH34NUBL2C5HSECKNVAO4ZFAAYXCW3Q5VZ2PXDDZ4SDD7LQC ACDPN464TK2LKLHSDN3YVRHAPF7WLSLLU3UHIYEXKFDEZPEU3XSQC 7V6TZHBSKK7AKY3SCYSP27QR2HP5N7HI3FI7V2QL7Y44OKKNI6IAC E3X5HVN5UN75OMTJA6JFQBNZ54P37NDZLZZF7EFBZZC45KR73YGAC 4MPLCIJZL4YNUWK2RTKNE6N4UWNBMO5WDRKW737ENVE3RKV5LCRAC R22TTMI6WXWULC7ODKFF3QCB7MOTETQQ6IR4BUCUPOCQKQNCTT5AC 3PY3L3A4QRW3Z5Y7SHO4TMVOOP2VNCO27X2MX4DTOP2SADLBQUOAC DLVXY6DBP65B3RGWW4PNBEBPBNHNM3LSRYD36F3XDARFY7SPSJYAC W2KRIXSCRJPS6WDIYTHVF5IRMF3V5DWECRAWUPVTB7VZ6A2BLD4QC 3D6NWJ44UYHLZMD3BOQIWXJUEGITAVCHK6Z2WWDQONVQC4HSBRXQC XRZPPYWPWUOM4SFNI6BHKH2UKJQNLKOV6Y7XIEPEZXE5QYRT26PAC 2PAHDAPDO6PN4FNGB5N7CQNEGHSE3NOGPXYZMIAOJC4VW34FRVOAC TRZAZJJA5VQBJ65SO5H5DNSILIZEJHIZCBYEBHEATCT6ZSMWIFKQC // Returns an item, or a reason why we returned an invalid itemint get_default_slot(std::string& no_item_reason) const;void get_fire_order(std::vector<int>& v) const { _get_fire_order(v, false); }
int get_fire_item(std::string* no_item_reason=0) const;void get_fire_order(std::vector<int>& v) const;
static ammo_t _get_weapon_ammo_type();static bool _item_matches(const item_def &item, fire_type types);
static ammo_t _get_weapon_ammo_type(const item_def*);static bool _item_matches(const item_def &item, fire_type types, const item_def* launcher);static bool _items_similar(const item_def& a, const item_def& b);
// This is the first item displayed in the fire interface.int player_quiver::get_default_slot(std::string& no_item_reason) const
// This differs from get_desired_item; that method can return// an item that is not in inventory, while this one cannot.// If no item can be found, return the reason why.int player_quiver::get_fire_item(std::string* no_item_reason) const
m_last_used_type = _get_weapon_ammo_type();
// Only switch m_last_used_type if weapon really changedconst item_def* weapon = you.weapon();if (weapon == NULL){if (m_last_weapon.base_type != OBJ_UNASSIGNED){m_last_weapon.base_type = OBJ_UNASSIGNED;m_last_used_type = AMMO_THROW;}}else{if (! _items_similar(*weapon, m_last_weapon)){m_last_weapon = *weapon;m_last_used_type = _get_weapon_ammo_type(weapon);}}_maybe_fill_empty_slot();
void player_quiver::_get_fire_order(std::vector<int>& order, bool ignore_inscription_etc) const
void player_quiver::on_inv_quantity_change(int slot, int amt){if (m_last_used_of_type[m_last_used_type].base_type == OBJ_UNASSIGNED){// Empty quiver. Maybe we can fill it now?_maybe_fill_empty_slot();you.quiver_change = true;}else if (m_last_used_of_type[m_last_used_type].base_type !=you.inv[slot].base_type){// Not our current stack; don't bother}else{// Maybe matches current stack. Redraw if so.int qv_slot; get_desired_item(NULL, &qv_slot);if (qv_slot == slot)you.quiver_change = true;}}// If current quiver slot is empty, fill it with something useful.void player_quiver::_maybe_fill_empty_slot(){const item_def* weapon = you.weapon();const ammo_t slot = _get_weapon_ammo_type(weapon);if (! is_valid_item(m_last_used_of_type[slot])){// const launch_retval desired_ret =// (weapon && is_range_weapon(*weapon)) ? LRET_LAUNCHED : LRET_THROWN;const launch_retval desired_ret =(slot == AMMO_THROW ? LRET_THROWN : LRET_LAUNCHED);std::vector<int> order; _get_fire_order(order, false, weapon);for (unsigned int i=0; i<order.size(); i++){if (is_launched(&you, weapon, you.inv[order[i]]) == desired_ret){m_last_used_of_type[slot] = you.inv[order[i]];m_last_used_of_type[slot].quantity = 1;break;}}}}void player_quiver::get_fire_order(std::vector<int>& v) const{_get_fire_order(v, false, you.weapon());}// Get a sorted list of items to show in the fire interface.//// If ignore_inscription_etc, ignore =f and Options.fire_items_start.// This is used for generating informational error messages, when the// fire order is empty.//// launcher determines what items match the 'launcher' fire_order type.void player_quiver::_get_fire_order(std::vector<int>& order,bool ignore_inscription_etc,const item_def* launcher) const
const int wielded = you.equip[EQ_WEAPON];if (wielded == -1)return (AMMO_THROW);item_def &weapon = you.inv[wielded];if (weapon.base_type != OBJ_WEAPONS)return (AMMO_THROW);
if (weapon == NULL)return AMMO_THROW;if (weapon->base_type != OBJ_WEAPONS)return AMMO_THROW;
// Helper for _get_fire_orderstatic bool _fire_item_matches(const item_def &item, unsigned fire_type){if (!is_valid_item(item))return (false);if (you.attribute[ATTR_HELD]){if (item.base_type == OBJ_MISSILES){const item_def *weapon = you.weapon();if (weapon && weapon->sub_type == WPN_BLOWGUN&& item.launched_by(*weapon)){return (true);}}return (false);}if (fire_type & FIRE_INSCRIBED)if (item.inscription.find("+f", 0) != std::string::npos)return true;if (item.base_type == OBJ_MISSILES){if ((fire_type & FIRE_DART) && item.sub_type == MI_DART)return (true);if ((fire_type & FIRE_STONE) && item.sub_type == MI_STONE)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);if ((fire_type & FIRE_NET) && item.sub_type == MI_THROWING_NET)return (true);if (fire_type & FIRE_LAUNCHER){const item_def *weapon = you.weapon();if (weapon && item.launched_by(*weapon))return (true);}}else if (item.base_type == OBJ_WEAPONS&& is_throwable(item, you.body_size())){if ((fire_type & FIRE_RETURNING) && item.special == SPWPN_RETURNING&& item_ident(item, ISFLAG_KNOW_TYPE)){return (true);}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);}
quiver_type get_quiver_type(){const int wielded = you.equip[EQ_WEAPON];if (wielded == -1)return (QUIVER_THROW);item_def &weapon = you.inv[wielded];if (weapon.base_type != OBJ_WEAPONS)return (QUIVER_THROW);switch (weapon.sub_type){case WPN_BLOWGUN:return (QUIVER_BLOWGUN);case WPN_SLING:return (QUIVER_SLING);case WPN_BOW:case WPN_LONGBOW:return (QUIVER_BOW);case WPN_CROSSBOW:return (QUIVER_CROSSBOW);case WPN_HAND_CROSSBOW:return (QUIVER_HAND_CROSSBOW);default:return (QUIVER_THROW);}}// Not free, but not a performance issue either.static bool Hack_Ignore_F_Inscription = false; // only for "why can't I fire" feedbackstatic void _get_fire_order(std::vector<int>& fire_order){for (int i_inv=Options.fire_items_start; i_inv<ENDOFPACK; i_inv++){const item_def& item = you.inv[i_inv];if (!is_valid_item(item))continue;if (you.equip[EQ_WEAPON] == i_inv)continue;// =f prevents item from being in fire orderif (!Hack_Ignore_F_Inscription &&strstr(item.inscription.c_str(), "=f"))continue;for (unsigned int i_flags=0;i_flags<Options.fire_order.size();i_flags++){if (_fire_item_matches(item, Options.fire_order[i_flags])){fire_order.push_back( (i_flags<<16) | (i_inv & 0xffff) );break;}}}std::sort(fire_order.begin(), fire_order.end());for (unsigned int i=0; i<fire_order.size(); i++){fire_order[i] &= 0xffff;}}
int get_current_fire_item(){std::vector<int> fire_order;_get_fire_order(fire_order);if (fire_order.size() == 0)return ENDOFPACK;if (! Options.fire_quiver_best){const int q = you.quiver[get_quiver_type()];for (unsigned i = 0; i < fire_order.size(); i++)if (q == fire_order[i])return q;}return fire_order[0];}
const int next_item = get_next_fire_item(item, +1);bool no_other_items = (next_item == ENDOFPACK || next_item == item);
const int next_item = get_next_fire_item(m_slot, +1);bool no_other_items = (next_item == -1 || next_item == m_slot);
const int next = get_next_fire_item(item, direction);if (next != item && next != ENDOFPACK)
const int next = get_next_fire_item(m_slot, direction);if (next != m_slot && next != -1)
item = beh.item;if (! beh.selected_from_inventory){you.quiver[get_quiver_type()] = beh.item;you.quiver_change = true;}
you.m_quiver->on_item_fired(you.inv[beh.m_slot]);}else{you.m_quiver->on_item_fired_fi(you.inv[beh.m_slot]);
}static std::string _fire_get_noitem_reason(){const int cur_item = get_current_fire_item();if (cur_item != ENDOFPACK){// Shouldn't be calling this if there is a good default item!return std::string("Buggy.");}// Tell the user why we might have skipped their missileunwind_var<int> unwind_festart(Options.fire_items_start, 0);unwind_var<bool> unwind_inscription(Hack_Ignore_F_Inscription, true);const int skipped_item = get_current_fire_item();char buf[200];if (skipped_item == ENDOFPACK){return std::string("No suitable missiles.");}else if (skipped_item < unwind_festart.original_value()){// no room for showing index_to_letter(skipped_item);snprintf(buf, 200,"Nothing suitable (fire_items_start = '%c').",index_to_letter(unwind_festart.original_value()));return std::string(buf);}else{snprintf(buf, 200,"Nothing suitable (ignored '=f'-inscribed item on '%c').",index_to_letter(skipped_item));return std::string(buf);}
if (Options.fire_quiver_best){mpr("Use fire_quiver_best=false if you want manual quiver control.");break;}const int cur = you.quiver[get_quiver_type()];if (cur != ENDOFPACK)
int cur;you.m_quiver->get_desired_item(NULL, &cur);const int next = get_next_fire_item(cur, +1);if (next != -1)