1 /**
2  * @file
3  * @brief Functions for inventory related commands.
4 **/
5 
6 #pragma once
7 
8 #include <cstddef>
9 #include <functional>
10 #include <vector>
11 
12 #include "enum.h"
13 #include "equipment-type.h"
14 #include "item-name.h"
15 #include "item-prop-enum.h"
16 #include "menu.h"
17 #include "operation-types.h"
18 #include "tag-version.h"
19 
20 enum object_selector
21 {
22     OSEL_ANY                     =  -1,
23     OSEL_WIELD                   =  -2,
24     OSEL_UNIDENT                 =  -3,
25 #if TAG_MAJOR_VERSION == 34
26     OSEL_RECHARGE                =  -4,
27 #endif
28     OSEL_ENCHANTABLE_ARMOUR      =  -5,
29     OSEL_BEOGH_GIFT              =  -6,
30 #if TAG_MAJOR_VERSION == 34
31     OSEL_DRAW_DECK               =  -7,
32 #endif
33     OSEL_THROWABLE               =  -8,
34     OSEL_EVOKABLE                =  -9,
35     OSEL_WORN_ARMOUR             = -10,
36     OSEL_CURSED_WORN             = -11,
37 #if TAG_MAJOR_VERSION == 34
38     OSEL_UNCURSED_WORN_ARMOUR    = -12,
39     OSEL_UNCURSED_WORN_JEWELLERY = -13,
40 #endif
41     OSEL_BRANDABLE_WEAPON        = -14,
42     OSEL_ENCHANTABLE_WEAPON      = -15,
43     OSEL_BLESSABLE_WEAPON        = -16,
44     OSEL_CURSABLE                = -17, // Items that are worn and cursable
45 #if TAG_MAJOR_VERSION == 34
46     OSEL_DIVINE_RECHARGE         = -18,
47 #endif
48     OSEL_UNCURSED_WORN_RINGS     = -19,
49     OSEL_QUIVER_ACTION           = -20,
50     OSEL_QUIVER_ACTION_FORCE     = -21,
51 };
52 
53 /// Behaviour flags for prompt_invent_item().
54 enum class invprompt_flag
55 {
56     none               = 0,
57     /// Warning inscriptions are not checked & the player will not be warned.
58     no_warning         = 1 << 0,
59     /// '\' will be ignored, instead of switching to the known item list.
60     hide_known         = 1 << 1,
61     /// Allow selecting items that do not exist.
62     unthings_ok        = 1 << 2,
63     /// Don't start in the '?' list InvMenu.
64     manual_list        = 1 << 3,
65     /// Only allow exiting with escape, not also space.
66     escape_only        = 1 << 4,
67 };
68 DEF_BITFIELD(invent_prompt_flags, invprompt_flag);
69 
70 #define PROMPT_ABORT         -1
71 #define PROMPT_GOT_SPECIAL   -2
72 #define PROMPT_NOTHING       -3
73 
74 #define SLOT_BARE_HANDS      PROMPT_GOT_SPECIAL
75 
76 extern FixedVector<int, NUM_OBJECT_CLASSES> inv_order;
77 
78 struct SelItem
79 {
80     int slot;
81     int quantity;
82     const item_def *item;
83     bool has_star;
SelItemSelItem84     SelItem() : slot(0), quantity(0), item(nullptr), has_star(false) { }
85     SelItem(int s, int q, const item_def *it = nullptr, bool do_star = false)
slotSelItem86         : slot(s), quantity(q), item(it), has_star(do_star)
87     {
88     }
89 };
90 
91 typedef string (*invtitle_annotator)(const Menu *m, const string &oldtitle);
92 
93 class InvTitle : public MenuEntry
94 {
95 public:
96     InvTitle(Menu *mn, const string &title, invtitle_annotator tfn);
97 
98     string get_text(const bool = false) const override;
99 
100 private:
101     Menu *m;
102     invtitle_annotator titlefn;
103 };
104 
105 class InvEntry : public MenuEntry
106 {
107 private:
108     static bool show_glyph;
109     static bool show_coordinates;
110 
111     mutable string basename;
112     mutable string qualname;
113     mutable string dbname;
114 
115 protected:
116     static bool show_cursor;
117     // Should we show the floor tile, etc?
118     bool show_background = true;
119 
120 public:
121     const item_def *item;
122 
123     InvEntry(const item_def &i);
124     string get_text(const bool need_cursor = false) const override;
125     void set_show_glyph(bool doshow);
126     void set_show_coordinates(bool doshow);
127     static void set_show_cursor(bool doshow);
128 
129     const string &get_basename() const;
130     const string &get_qualname() const;
131     const string &get_fullname() const;
132     const string &get_dbname() const;
133     bool         is_cursed() const;
134     bool         is_glowing() const;
135     bool         is_ego() const;
136     bool         is_art() const;
137     bool         is_equipped() const;
138 
highlight_colour()139     virtual int highlight_colour() const override
140     {
141         return menu_colour(get_text(), item_prefix(*item), tag);
142     }
143 
144     virtual void select(int qty = -1) override;
145     void set_star(bool);
146     bool has_star() const;
147 
148     virtual string get_filter_text() const override;
149 
150     // returns const false and leaves arg unchanged unless USE_TILES is defined
151     virtual bool get_tiles(vector<tile_def>& tiles) const override;
152 
153 private:
154     void add_class_hotkeys(const item_def &i);
155     bool _has_star;
156 };
157 
158 class InvMenu : public Menu
159 {
160 public:
161     InvMenu(int mflags = MF_MULTISELECT);
162 
163 public:
164     int getkey() const override;
165 
166     void set_preselect(const vector<SelItem> *pre);
167     void set_type(menu_type t);
168 
169     // Sets function to annotate the title with meta-information if needed.
170     // If you set this, do so *before* calling set_title, or it won't take
171     // effect.
172     void set_title_annotator(invtitle_annotator fn);
173 
174     // Not an override, but an overload. Not virtual!
175     void set_title(MenuEntry *title, bool first = true);
176     void set_title(const string &s);
177 
178     // Loads items into the menu. If "procfn" is provided, it'll be called
179     // for each MenuEntry added.
180     // NOTE: Does not set menu title, ever! You *must* set the title explicitly
181     menu_letter load_items(const vector<const item_def*> &items,
182                            function<MenuEntry* (MenuEntry*)> procfn = nullptr,
183                            menu_letter ckey = 'a', bool sort = true);
184 
185     // Make sure this menu does not outlive items, or mayhem will ensue!
186     menu_letter load_items(const vector<item_def>& items,
187                            function<MenuEntry* (MenuEntry*)> procfn = nullptr,
188                            menu_letter ckey = 'a', bool sort = true);
189 
190     // Loads items from the player's inventory into the menu, and sets the
191     // title to the stock title. If "procfn" is provided, it'll be called for
192     // each MenuEntry added, *excluding the title*.
193     void load_inv_items(int item_selector = OSEL_ANY, int excluded_slot = -1,
194                         function<MenuEntry* (MenuEntry*)> procfn = nullptr);
195 
196     vector<SelItem> get_selitems() const;
197 
198     const menu_sort_condition *find_menu_sort_condition() const;
199     void sort_menu(vector<InvEntry*> &items, const menu_sort_condition *cond);
200 
201     // Drop menu only: if true, dropped items are removed from autopickup.
202     bool mode_special_drop() const;
203 
204 protected:
205     void do_preselect(InvEntry *ie);
206     void select_item_index(int idx, int qty, bool draw_cursor = true) override;
207     int pre_process(int key) override;
208     virtual bool is_selectable(int index) const override;
209     virtual string help_key() const override;
210 
211 protected:
212     menu_type type;
213     const vector<SelItem> *pre_select;
214 
215     invtitle_annotator title_annotate;
216     string temp_title;
217 
218 private:
219     bool _mode_special_drop;
220 };
221 
222 void get_class_hotkeys(const int type, vector<char> &glyphs);
223 
224 bool item_is_selected(const item_def &item, int selector);
225 bool any_items_of_type(int type_expect, int excluded_slot = -1, bool inspect_floor = false);
226 string no_selectables_message(int item_selector);
227 
228 string slot_description();
229 
230 int prompt_invent_item(const char *prompt,
231                        menu_type type,
232                        int type_expect,
233                        operation_types oper = OPER_ANY,
234                        invent_prompt_flags flags = invprompt_flag::none,
235                        const char other_valid_char = '\0');
236 
237 vector<SelItem> select_items(
238                         const vector<const item_def*> &items,
239                         const char *title, bool noselect = false,
240                         menu_type mtype = menu_type::pickup);
241 
242 vector<SelItem> prompt_drop_items(const vector<SelItem> &preselected_items);
243 
244 void display_inventory();
245 
246 bool in_inventory(const item_def &i);
247 void identify_inventory();
248 
249 const char *item_class_name(int type, bool terse = false);
250 const char *item_slot_name(equipment_type type);
251 
252 bool get_tiles_for_item(const item_def &item, vector<tile_def>& tileset, bool show_background);
253 
254 bool check_old_item_warning(const item_def& item, operation_types oper,
255                             bool check_melded = false);
256 bool check_warning_inscriptions(const item_def& item, operation_types oper);
257 
258 void init_item_sort_comparators(item_sort_comparators &list,
259                                 const string &set);
260 
261 bool prompt_failed(int retval);
262 
263 void list_charging_evokers(FixedVector<item_def*, NUM_MISCELLANY> &evokers);
264 
265 bool item_is_wieldable(const item_def &item);
266 bool item_is_evokable(const item_def &item, bool reach = true,
267                       bool msg = false, bool equip = true);
268 bool needs_notele_warning(const item_def &item, operation_types oper);
269 bool needs_handle_warning(const item_def &item, operation_types oper,
270                           bool &penance);
271 item_def *digit_inscription_to_item(char digit, operation_types oper);
272