1 #include "inventory/item-getter.h"
2 #include "core/stuff-handler.h"
3 #include "floor/floor.h"
4 #include "game-option/input-options.h"
5 #include "game-option/option-flags.h"
6 #include "game-option/text-display-options.h"
8 #include "inventory/floor-item-getter.h"
9 #include "inventory/inventory-util.h"
10 #include "inventory/item-selection-util.h"
11 #include "io/command-repeater.h"
12 #include "io/input-key-acceptor.h"
13 #include "io/input-key-requester.h"
14 #include "main/sound-of-music.h"
15 #include "object/item-tester-hooker.h"
16 #include "object/item-use-flags.h"
17 #include "object/object-info.h"
18 #include "object/object-mark-types.h"
19 #include "term/gameterm.h"
20 #include "term/screen-processor.h"
21 #include "util/int-char-converter.h"
22 #include "view/display-inventory.h"
23 #include "view/display-messages.h"
24 #include "view/display-sub-windows.h"
27 * @brief オブジェクト選択のモード設定
28 * @param item_selection_ptr アイテム選択への参照ポインタ
31 static void check_item_selection_mode(item_selection_type *item_selection_ptr)
33 if (item_selection_ptr->mode & USE_EQUIP)
34 item_selection_ptr->equip = TRUE;
36 if (item_selection_ptr->mode & USE_INVEN)
37 item_selection_ptr->inven = TRUE;
39 if (item_selection_ptr->mode & USE_FLOOR)
40 item_selection_ptr->floor = TRUE;
44 * todo 適切な関数名をどうしても付けられなかったので暫定でauxとした
45 * @brief アイテムへにタグ付けがされているかの調査処理 (のはず)
46 * @param owner_ptr プレーヤーへの参照ポインタ
47 * @param item_selection_ptr アイテムへの参照ポインタ
48 * @return プレイヤーによりアイテムが選択されたならTRUEを返す
50 static bool check_item_tag_aux(player_type *owner_ptr, item_selection_type *item_selection_ptr)
52 if (!item_selection_ptr->floor || (*item_selection_ptr->cp >= 0))
56 item_selection_ptr->k = 0 - (*item_selection_ptr->cp);
57 o_ptr = &owner_ptr->current_floor_ptr->o_list[item_selection_ptr->k];
58 if (!item_tester_okay(owner_ptr, o_ptr, item_selection_ptr->tval) && ((item_selection_ptr->mode & USE_FULL) == 0))
61 item_selection_ptr->tval = 0;
62 item_tester_hook = NULL;
68 * @brief インベントリのアイテムにタグ付けがされているかの調査処理 (のはず)
69 * @param owner_ptr プレーヤーへの参照ポインタ
70 * @param fis_ptr 床上アイテムへの参照ポインタ
71 * @param prev_tag 前回選択したアイテムのタグ (のはず)
72 * @return プレイヤーによりアイテムが選択されたならTRUEを返す
74 static bool check_item_tag_inventory(player_type *owner_ptr, item_selection_type *item_selection_ptr, char *prev_tag)
76 if ((!item_selection_ptr->inven || (*item_selection_ptr->cp < 0) || (*item_selection_ptr->cp >= INVEN_PACK))
77 && (!item_selection_ptr->equip || (*item_selection_ptr->cp < INVEN_RARM) || (*item_selection_ptr->cp >= INVEN_TOTAL)))
80 if (*prev_tag && command_cmd) {
81 if (!get_tag(owner_ptr, &item_selection_ptr->k, *prev_tag, (*item_selection_ptr->cp >= INVEN_RARM) ? USE_EQUIP : USE_INVEN, item_selection_ptr->tval)
82 || (item_selection_ptr->k < INVEN_RARM)
83 ? !item_selection_ptr->inven
84 : !item_selection_ptr->equip || !get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval)) {
89 *item_selection_ptr->cp = item_selection_ptr->k;
90 item_selection_ptr->tval = 0;
91 item_tester_hook = NULL;
96 if (!get_item_okay(owner_ptr, *item_selection_ptr->cp, item_selection_ptr->tval))
99 item_selection_ptr->tval = 0;
100 item_tester_hook = NULL;
106 * @brief アイテムにタグ付けがされているかの調査処理 (のはず)
107 * @param owner_ptr プレーヤーへの参照ポインタ
108 * @param item_selection_ptr アイテムへの参照ポインタ
109 * @param prev_tag 前回選択したアイテムのタグ (のはず)
110 * @return プレイヤーによりアイテムが選択されたならTRUEを返す
112 static bool check_item_tag(player_type *owner_ptr, item_selection_type *item_selection_ptr, char *prev_tag)
114 if (!repeat_pull(item_selection_ptr->cp))
117 if (item_selection_ptr->mode & USE_FORCE && (*item_selection_ptr->cp == INVEN_FORCE)) {
118 item_selection_ptr->tval = 0;
119 item_tester_hook = NULL;
124 if (check_item_tag_aux(owner_ptr, item_selection_ptr))
127 return check_item_tag_inventory(owner_ptr, item_selection_ptr, prev_tag);
131 * @brief インベントリ内のアイテムが妥当かを判定する
132 * @param owner_ptr プレーヤーへの参照ポインタ
133 * @param fis_ptr アイテム選択への参照ポインタ
136 static void test_inventory(player_type *owner_ptr, item_selection_type *item_selection_ptr)
138 if (!item_selection_ptr->inven) {
139 item_selection_ptr->i2 = -1;
146 for (int j = 0; j < INVEN_PACK; j++)
147 if (item_tester_okay(owner_ptr, &owner_ptr->inventory_list[j], item_selection_ptr->tval) || (item_selection_ptr->mode & USE_FULL))
148 item_selection_ptr->max_inven++;
152 * @brief 装備品が妥当かを判定する
153 * @param owner_ptr プレーヤーへの参照ポインタ
154 * @param fis_ptr アイテム選択への参照ポインタ
157 static void test_equipment(player_type *owner_ptr, item_selection_type *item_selection_ptr)
159 if (!item_selection_ptr->equip) {
160 item_selection_ptr->e2 = -1;
167 for (int j = INVEN_RARM; j < INVEN_TOTAL; j++)
168 if (select_ring_slot ? is_ring_slot(j)
169 : item_tester_okay(owner_ptr, &owner_ptr->inventory_list[j], item_selection_ptr->tval) || (item_selection_ptr->mode & USE_FULL))
170 item_selection_ptr->max_equip++;
172 if (owner_ptr->ryoute && !(item_selection_ptr->mode & IGNORE_BOTHHAND_SLOT))
173 item_selection_ptr->max_equip++;
177 * @brief オブジェクト選択の汎用関数 / General function for the selection of item
178 * Let the user select an item, save its "index"
179 * @param owner_ptr プレーヤーへの参照ポインタ
180 * @param cp 選択したオブジェクトのID
181 * @param pmt 選択目的のメッセージ
182 * @param str 選択できるオブジェクトがない場合のキャンセルメッセージ
183 * @param mode オプションフラグ
184 * @return プレイヤーによりアイテムが選択されたならTRUEを返す
185 * Return TRUE only if an acceptable item was chosen by the user
187 bool get_item(player_type *owner_ptr, OBJECT_IDX *cp, concptr pmt, concptr str, BIT_FLAGS mode, tval_type tval)
189 static char prev_tag = '\0';
190 if (easy_floor || use_menu)
191 return get_item_floor(owner_ptr, cp, pmt, str, mode, tval);
193 item_selection_type tmp_selection;
194 item_selection_type *item_selection_ptr = initialize_item_selection_type(&tmp_selection, cp, mode, tval);
195 check_item_selection_mode(item_selection_ptr);
196 if (check_item_tag(owner_ptr, item_selection_ptr, &prev_tag))
200 item_selection_ptr->done = FALSE;
201 item_selection_ptr->item = FALSE;
202 item_selection_ptr->i1 = 0;
203 item_selection_ptr->i2 = INVEN_PACK - 1;
204 test_inventory(owner_ptr, item_selection_ptr);
205 while ((item_selection_ptr->i1 <= item_selection_ptr->i2) && (!get_item_okay(owner_ptr, item_selection_ptr->i1, item_selection_ptr->tval)))
206 item_selection_ptr->i1++;
208 while ((item_selection_ptr->i1 <= item_selection_ptr->i2) && (!get_item_okay(owner_ptr, item_selection_ptr->i2, item_selection_ptr->tval)))
209 item_selection_ptr->i2--;
211 item_selection_ptr->e1 = INVEN_RARM;
212 item_selection_ptr->e2 = INVEN_TOTAL - 1;
213 test_equipment(owner_ptr, item_selection_ptr);
214 while ((item_selection_ptr->e1 <= item_selection_ptr->e2) && (!get_item_okay(owner_ptr, item_selection_ptr->e1, item_selection_ptr->tval)))
215 item_selection_ptr->e1++;
217 while ((item_selection_ptr->e1 <= item_selection_ptr->e2) && (!get_item_okay(owner_ptr, item_selection_ptr->e2, item_selection_ptr->tval)))
218 item_selection_ptr->e2--;
220 if (item_selection_ptr->equip && owner_ptr->ryoute && !(item_selection_ptr->mode & IGNORE_BOTHHAND_SLOT)) {
221 if (owner_ptr->migite) {
222 if (item_selection_ptr->e2 < INVEN_LARM)
223 item_selection_ptr->e2 = INVEN_LARM;
224 } else if (owner_ptr->hidarite)
225 item_selection_ptr->e1 = INVEN_RARM;
228 if (item_selection_ptr->floor) {
229 for (item_selection_ptr->this_o_idx = owner_ptr->current_floor_ptr->grid_array[owner_ptr->y][owner_ptr->x].o_idx; item_selection_ptr->this_o_idx;
230 item_selection_ptr->this_o_idx = item_selection_ptr->next_o_idx) {
232 o_ptr = &owner_ptr->current_floor_ptr->o_list[item_selection_ptr->this_o_idx];
233 item_selection_ptr->next_o_idx = o_ptr->next_o_idx;
234 if ((item_tester_okay(owner_ptr, o_ptr, item_selection_ptr->tval) || (item_selection_ptr->mode & USE_FULL)) && (o_ptr->marked & OM_FOUND))
235 item_selection_ptr->allow_floor = TRUE;
239 if (!item_selection_ptr->allow_floor && (item_selection_ptr->i1 > item_selection_ptr->i2) && (item_selection_ptr->e1 > item_selection_ptr->e2)) {
241 item_selection_ptr->oops = TRUE;
242 item_selection_ptr->done = TRUE;
244 if (item_selection_ptr->mode & USE_FORCE) {
245 *item_selection_ptr->cp = INVEN_FORCE;
246 item_selection_ptr->item = TRUE;
249 if (command_see && command_wrk && item_selection_ptr->equip)
251 else if (item_selection_ptr->inven)
253 else if (item_selection_ptr->equip)
259 /* 追加オプション(always_show_list)が設定されている場合は常に一覧を表示する */
260 if ((always_show_list == TRUE) || use_menu)
266 while (!item_selection_ptr->done) {
267 COMMAND_CODE get_item_label = 0;
270 for (int j = 0; j < 8; j++) {
271 if (!angband_term[j])
274 if (window_flag[j] & (PW_INVEN))
277 if (window_flag[j] & (PW_EQUIP))
281 if ((command_wrk && ni && !ne) || (!command_wrk && !ni && ne)) {
282 toggle_inventory_equipment(owner_ptr);
283 item_selection_ptr->toggle = !item_selection_ptr->toggle;
286 owner_ptr->window |= (PW_INVEN | PW_EQUIP);
287 handle_stuff(owner_ptr);
291 get_item_label = show_inventory(owner_ptr, item_selection_ptr->menu_line, item_selection_ptr->mode, item_selection_ptr->tval);
294 get_item_label = show_equipment(owner_ptr, item_selection_ptr->menu_line, item_selection_ptr->mode, item_selection_ptr->tval);
298 sprintf(item_selection_ptr->out_val, _("持ち物:", "Inven:"));
299 if ((item_selection_ptr->i1 <= item_selection_ptr->i2) && !use_menu) {
300 sprintf(item_selection_ptr->tmp_val, _("%c-%c,'(',')',", " %c-%c,'(',')',"), index_to_label(item_selection_ptr->i1),
301 index_to_label(item_selection_ptr->i2));
302 strcat(item_selection_ptr->out_val, item_selection_ptr->tmp_val);
305 if (!command_see && !use_menu)
306 strcat(item_selection_ptr->out_val, _(" '*'一覧,", " * to see,"));
308 if (item_selection_ptr->equip)
309 strcat(item_selection_ptr->out_val, format(_(" %s 装備品,", " %s for Equip,"), use_menu ? _("'4'or'6'", "4 or 6") : _("'/'", "/")));
311 sprintf(item_selection_ptr->out_val, _("装備品:", "Equip:"));
312 if ((item_selection_ptr->e1 <= item_selection_ptr->e2) && !use_menu) {
313 sprintf(item_selection_ptr->tmp_val, _("%c-%c,'(',')',", " %c-%c,'(',')',"), index_to_label(item_selection_ptr->e1),
314 index_to_label(item_selection_ptr->e2));
315 strcat(item_selection_ptr->out_val, item_selection_ptr->tmp_val);
318 if (!command_see && !use_menu)
319 strcat(item_selection_ptr->out_val, _(" '*'一覧,", " * to see,"));
321 if (item_selection_ptr->inven)
322 strcat(item_selection_ptr->out_val, format(_(" %s 持ち物,", " %s for Inven,"), use_menu ? _("'4'or'6'", "4 or 6") : _("'/'", "'/'")));
325 if (item_selection_ptr->allow_floor)
326 strcat(item_selection_ptr->out_val, _(" '-'床上,", " - for item_selection_ptr->floor,"));
328 if (item_selection_ptr->mode & USE_FORCE)
329 strcat(item_selection_ptr->out_val, _(" 'w'練気術,", " w for the Force,"));
331 strcat(item_selection_ptr->out_val, " ESC");
332 sprintf(item_selection_ptr->tmp_val, "(%s) %s", item_selection_ptr->out_val, pmt);
333 prt(item_selection_ptr->tmp_val, 0, 0);
334 item_selection_ptr->which = inkey();
336 int max_line = (command_wrk ? item_selection_ptr->max_equip : item_selection_ptr->max_inven);
337 switch (item_selection_ptr->which) {
342 item_selection_ptr->done = TRUE;
349 item_selection_ptr->menu_line += (max_line - 1);
356 item_selection_ptr->menu_line++;
366 if (!item_selection_ptr->inven || !item_selection_ptr->equip) {
376 command_wrk = !command_wrk;
377 max_line = (command_wrk ? item_selection_ptr->max_equip : item_selection_ptr->max_inven);
378 if (item_selection_ptr->menu_line > max_line)
379 item_selection_ptr->menu_line = max_line;
388 if (command_wrk == USE_FLOOR) {
389 *item_selection_ptr->cp = -get_item_label;
391 if (!get_item_okay(owner_ptr, get_item_label, item_selection_ptr->tval)) {
396 if (!get_item_allow(owner_ptr, get_item_label)) {
397 item_selection_ptr->done = TRUE;
401 *item_selection_ptr->cp = get_item_label;
404 item_selection_ptr->item = TRUE;
405 item_selection_ptr->done = TRUE;
409 if (item_selection_ptr->mode & USE_FORCE) {
410 *item_selection_ptr->cp = INVEN_FORCE;
411 item_selection_ptr->item = TRUE;
412 item_selection_ptr->done = TRUE;
418 if (item_selection_ptr->menu_line > max_line)
419 item_selection_ptr->menu_line -= max_line;
424 switch (item_selection_ptr->which) {
426 item_selection_ptr->done = TRUE;
443 if (!item_selection_ptr->inven || !item_selection_ptr->equip) {
453 command_wrk = !command_wrk;
457 if (item_selection_ptr->allow_floor) {
458 for (item_selection_ptr->this_o_idx = owner_ptr->current_floor_ptr->grid_array[owner_ptr->y][owner_ptr->x].o_idx;
459 item_selection_ptr->this_o_idx; item_selection_ptr->this_o_idx = item_selection_ptr->next_o_idx) {
461 o_ptr = &owner_ptr->current_floor_ptr->o_list[item_selection_ptr->this_o_idx];
462 item_selection_ptr->next_o_idx = o_ptr->next_o_idx;
463 if (!item_tester_okay(owner_ptr, o_ptr, item_selection_ptr->tval) && !(item_selection_ptr->mode & USE_FULL))
466 item_selection_ptr->k = 0 - item_selection_ptr->this_o_idx;
467 if (other_query_flag && !verify(owner_ptr, _("本当に", "Try"), item_selection_ptr->k) || !get_item_allow(owner_ptr, item_selection_ptr->k))
470 *item_selection_ptr->cp = item_selection_ptr->k;
471 item_selection_ptr->item = TRUE;
472 item_selection_ptr->done = TRUE;
476 if (item_selection_ptr->done)
493 if (!get_tag(owner_ptr, &item_selection_ptr->k, item_selection_ptr->which, command_wrk ? USE_EQUIP : USE_INVEN, item_selection_ptr->tval)) {
498 if ((item_selection_ptr->k < INVEN_RARM) ? !item_selection_ptr->inven : !item_selection_ptr->equip) {
503 if (!get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval)) {
508 if (!get_item_allow(owner_ptr, item_selection_ptr->k)) {
509 item_selection_ptr->done = TRUE;
513 *item_selection_ptr->cp = item_selection_ptr->k;
514 item_selection_ptr->item = TRUE;
515 item_selection_ptr->done = TRUE;
516 item_selection_ptr->cur_tag = item_selection_ptr->which;
520 if (item_selection_ptr->mode & USE_FORCE) {
521 *item_selection_ptr->cp = INVEN_FORCE;
522 item_selection_ptr->item = TRUE;
523 item_selection_ptr->done = TRUE;
530 bool not_found = FALSE;
531 if (!get_tag(owner_ptr, &item_selection_ptr->k, item_selection_ptr->which, command_wrk ? USE_EQUIP : USE_INVEN, item_selection_ptr->tval)) {
533 } else if ((item_selection_ptr->k < INVEN_RARM) ? !item_selection_ptr->inven : !item_selection_ptr->equip) {
535 } else if (!get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval)) {
540 *item_selection_ptr->cp = item_selection_ptr->k;
541 item_selection_ptr->item = TRUE;
542 item_selection_ptr->done = TRUE;
543 item_selection_ptr->cur_tag = item_selection_ptr->which;
547 ver = isupper(item_selection_ptr->which);
548 item_selection_ptr->which = (char)tolower(item_selection_ptr->which);
550 if (item_selection_ptr->which == '(')
551 item_selection_ptr->k = item_selection_ptr->i1;
552 else if (item_selection_ptr->which == ')')
553 item_selection_ptr->k = item_selection_ptr->i2;
555 item_selection_ptr->k = label_to_inventory(owner_ptr, item_selection_ptr->which);
557 if (item_selection_ptr->which == '(')
558 item_selection_ptr->k = item_selection_ptr->e1;
559 else if (item_selection_ptr->which == ')')
560 item_selection_ptr->k = item_selection_ptr->e2;
562 item_selection_ptr->k = label_to_equipment(owner_ptr, item_selection_ptr->which);
565 if (!get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval)) {
570 if (ver && !verify(owner_ptr, _("本当に", "Try"), item_selection_ptr->k)) {
571 item_selection_ptr->done = TRUE;
575 if (!get_item_allow(owner_ptr, item_selection_ptr->k)) {
576 item_selection_ptr->done = TRUE;
580 *item_selection_ptr->cp = item_selection_ptr->k;
581 item_selection_ptr->item = TRUE;
582 item_selection_ptr->done = TRUE;
593 item_selection_ptr->tval = 0;
594 item_tester_hook = NULL;
595 if (item_selection_ptr->toggle)
596 toggle_inventory_equipment(owner_ptr);
598 owner_ptr->window |= (PW_INVEN | PW_EQUIP);
599 handle_stuff(owner_ptr);
601 if (item_selection_ptr->oops && str)
604 if (item_selection_ptr->item) {
605 repeat_push(*item_selection_ptr->cp);
607 prev_tag = item_selection_ptr->cur_tag;
611 return item_selection_ptr->item;