1 #include "inventory/item-getter.h"
2 #include "core/stuff-handler.h"
3 #include "core/window-redrawer.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-slot-types.h"
10 #include "inventory/inventory-util.h"
11 #include "inventory/item-selection-util.h"
12 #include "io/command-repeater.h"
13 #include "io/input-key-acceptor.h"
14 #include "io/input-key-requester.h"
15 #include "main/sound-of-music.h"
16 #include "object/item-tester-hooker.h"
17 #include "object/item-use-flags.h"
18 #include "object/object-info.h"
19 #include "object/object-mark-types.h"
20 #include "player/player-status-flags.h"
21 #include "system/floor-type-definition.h"
22 #include "term/gameterm.h"
23 #include "term/screen-processor.h"
24 #include "util/int-char-converter.h"
25 #include "view/display-inventory.h"
26 #include "view/display-messages.h"
27 #include "window/display-sub-windows.h"
30 * @brief オブジェクト選択のモード設定
31 * @param item_selection_ptr アイテム選択への参照ポインタ
34 static void check_item_selection_mode(item_selection_type *item_selection_ptr)
36 if (item_selection_ptr->mode & USE_EQUIP)
37 item_selection_ptr->equip = TRUE;
39 if (item_selection_ptr->mode & USE_INVEN)
40 item_selection_ptr->inven = TRUE;
42 if (item_selection_ptr->mode & USE_FLOOR)
43 item_selection_ptr->floor = TRUE;
47 * todo 適切な関数名をどうしても付けられなかったので暫定でauxとした
48 * @brief アイテムへにタグ付けがされているかの調査処理 (のはず)
49 * @param owner_ptr プレーヤーへの参照ポインタ
50 * @param item_selection_ptr アイテムへの参照ポインタ
51 * @return プレイヤーによりアイテムが選択されたならTRUEを返す
53 static bool check_item_tag_aux(player_type *owner_ptr, item_selection_type *item_selection_ptr)
55 if (!item_selection_ptr->floor || (*item_selection_ptr->cp >= 0))
59 item_selection_ptr->k = 0 - (*item_selection_ptr->cp);
60 o_ptr = &owner_ptr->current_floor_ptr->o_list[item_selection_ptr->k];
61 if (!item_tester_okay(owner_ptr, o_ptr, item_selection_ptr->tval) && ((item_selection_ptr->mode & USE_FULL) == 0))
64 item_selection_ptr->tval = 0;
65 item_tester_hook = NULL;
71 * @brief インベントリのアイテムにタグ付けがされているかの調査処理 (のはず)
72 * @param owner_ptr プレーヤーへの参照ポインタ
73 * @param fis_ptr 床上アイテムへの参照ポインタ
74 * @param prev_tag 前回選択したアイテムのタグ (のはず)
75 * @return プレイヤーによりアイテムが選択されたならTRUEを返す
77 static bool check_item_tag_inventory(player_type *owner_ptr, item_selection_type *item_selection_ptr, char *prev_tag)
79 if ((!item_selection_ptr->inven || (*item_selection_ptr->cp < 0) || (*item_selection_ptr->cp >= INVEN_PACK))
80 && (!item_selection_ptr->equip || (*item_selection_ptr->cp < INVEN_RARM) || (*item_selection_ptr->cp >= INVEN_TOTAL)))
83 if (*prev_tag && command_cmd) {
84 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)
85 || (item_selection_ptr->k < INVEN_RARM)
86 ? !item_selection_ptr->inven
87 : !item_selection_ptr->equip || !get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval)) {
92 *item_selection_ptr->cp = item_selection_ptr->k;
93 item_selection_ptr->tval = 0;
94 item_tester_hook = NULL;
99 if (!get_item_okay(owner_ptr, *item_selection_ptr->cp, item_selection_ptr->tval))
102 item_selection_ptr->tval = 0;
103 item_tester_hook = NULL;
109 * @brief アイテムにタグ付けがされているかの調査処理 (のはず)
110 * @param owner_ptr プレーヤーへの参照ポインタ
111 * @param item_selection_ptr アイテムへの参照ポインタ
112 * @param prev_tag 前回選択したアイテムのタグ (のはず)
113 * @return プレイヤーによりアイテムが選択されたならTRUEを返す
115 static bool check_item_tag(player_type *owner_ptr, item_selection_type *item_selection_ptr, char *prev_tag)
117 if (!repeat_pull(item_selection_ptr->cp))
120 if (item_selection_ptr->mode & USE_FORCE && (*item_selection_ptr->cp == INVEN_FORCE)) {
121 item_selection_ptr->tval = 0;
122 item_tester_hook = NULL;
127 if (check_item_tag_aux(owner_ptr, item_selection_ptr))
130 return check_item_tag_inventory(owner_ptr, item_selection_ptr, prev_tag);
134 * @brief インベントリ内のアイテムが妥当かを判定する
135 * @param owner_ptr プレーヤーへの参照ポインタ
136 * @param fis_ptr アイテム選択への参照ポインタ
139 static void test_inventory(player_type *owner_ptr, item_selection_type *item_selection_ptr)
141 if (!item_selection_ptr->inven) {
142 item_selection_ptr->i2 = -1;
149 for (int j = 0; j < INVEN_PACK; j++)
150 if (item_tester_okay(owner_ptr, &owner_ptr->inventory_list[j], item_selection_ptr->tval) || (item_selection_ptr->mode & USE_FULL))
151 item_selection_ptr->max_inven++;
155 * @brief 装備品が妥当かを判定する
156 * @param owner_ptr プレーヤーへの参照ポインタ
157 * @param fis_ptr アイテム選択への参照ポインタ
160 static void test_equipment(player_type *owner_ptr, item_selection_type *item_selection_ptr)
162 if (!item_selection_ptr->equip) {
163 item_selection_ptr->e2 = -1;
170 for (int j = INVEN_RARM; j < INVEN_TOTAL; j++)
171 if (select_ring_slot ? is_ring_slot(j)
172 : item_tester_okay(owner_ptr, &owner_ptr->inventory_list[j], item_selection_ptr->tval) || (item_selection_ptr->mode & USE_FULL))
173 item_selection_ptr->max_equip++;
175 if (have_two_handed_weapons(owner_ptr) && !(item_selection_ptr->mode & IGNORE_BOTHHAND_SLOT))
176 item_selection_ptr->max_equip++;
180 * @brief オブジェクト選択の汎用関数 / General function for the selection of item
181 * Let the user select an item, save its "index"
182 * @param owner_ptr プレーヤーへの参照ポインタ
183 * @param cp 選択したオブジェクトのID
184 * @param pmt 選択目的のメッセージ
185 * @param str 選択できるオブジェクトがない場合のキャンセルメッセージ
186 * @param mode オプションフラグ
187 * @return プレイヤーによりアイテムが選択されたならTRUEを返す
188 * Return TRUE only if an acceptable item was chosen by the user
190 bool get_item(player_type *owner_ptr, OBJECT_IDX *cp, concptr pmt, concptr str, BIT_FLAGS mode, tval_type tval)
192 static char prev_tag = '\0';
193 if (easy_floor || use_menu)
194 return get_item_floor(owner_ptr, cp, pmt, str, mode, tval);
196 item_selection_type tmp_selection;
197 item_selection_type *item_selection_ptr = initialize_item_selection_type(&tmp_selection, cp, mode, tval);
198 check_item_selection_mode(item_selection_ptr);
199 if (check_item_tag(owner_ptr, item_selection_ptr, &prev_tag))
203 item_selection_ptr->done = FALSE;
204 item_selection_ptr->item = FALSE;
205 item_selection_ptr->i1 = 0;
206 item_selection_ptr->i2 = INVEN_PACK - 1;
207 test_inventory(owner_ptr, item_selection_ptr);
208 while ((item_selection_ptr->i1 <= item_selection_ptr->i2) && (!get_item_okay(owner_ptr, item_selection_ptr->i1, item_selection_ptr->tval)))
209 item_selection_ptr->i1++;
211 while ((item_selection_ptr->i1 <= item_selection_ptr->i2) && (!get_item_okay(owner_ptr, item_selection_ptr->i2, item_selection_ptr->tval)))
212 item_selection_ptr->i2--;
214 item_selection_ptr->e1 = INVEN_RARM;
215 item_selection_ptr->e2 = INVEN_TOTAL - 1;
216 test_equipment(owner_ptr, item_selection_ptr);
217 while ((item_selection_ptr->e1 <= item_selection_ptr->e2) && (!get_item_okay(owner_ptr, item_selection_ptr->e1, item_selection_ptr->tval)))
218 item_selection_ptr->e1++;
220 while ((item_selection_ptr->e1 <= item_selection_ptr->e2) && (!get_item_okay(owner_ptr, item_selection_ptr->e2, item_selection_ptr->tval)))
221 item_selection_ptr->e2--;
223 if (item_selection_ptr->equip && have_two_handed_weapons(owner_ptr) && !(item_selection_ptr->mode & IGNORE_BOTHHAND_SLOT)) {
224 if (have_right_hand_weapon(owner_ptr)) {
225 if (item_selection_ptr->e2 < INVEN_LARM)
226 item_selection_ptr->e2 = INVEN_LARM;
227 } else if (have_left_hand_weapon(owner_ptr))
228 item_selection_ptr->e1 = INVEN_RARM;
231 if (item_selection_ptr->floor) {
232 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;
233 item_selection_ptr->this_o_idx = item_selection_ptr->next_o_idx) {
235 o_ptr = &owner_ptr->current_floor_ptr->o_list[item_selection_ptr->this_o_idx];
236 item_selection_ptr->next_o_idx = o_ptr->next_o_idx;
237 if ((item_tester_okay(owner_ptr, o_ptr, item_selection_ptr->tval) || (item_selection_ptr->mode & USE_FULL)) && (o_ptr->marked & OM_FOUND))
238 item_selection_ptr->allow_floor = TRUE;
242 if (!item_selection_ptr->allow_floor && (item_selection_ptr->i1 > item_selection_ptr->i2) && (item_selection_ptr->e1 > item_selection_ptr->e2)) {
244 item_selection_ptr->oops = TRUE;
245 item_selection_ptr->done = TRUE;
247 if (item_selection_ptr->mode & USE_FORCE) {
248 *item_selection_ptr->cp = INVEN_FORCE;
249 item_selection_ptr->item = TRUE;
252 if (command_see && command_wrk && item_selection_ptr->equip)
254 else if (item_selection_ptr->inven)
256 else if (item_selection_ptr->equip)
262 /* 追加オプション(always_show_list)が設定されている場合は常に一覧を表示する */
263 if ((always_show_list == TRUE) || use_menu)
269 while (!item_selection_ptr->done) {
270 COMMAND_CODE get_item_label = 0;
273 for (int j = 0; j < 8; j++) {
274 if (!angband_term[j])
277 if (window_flag[j] & (PW_INVEN))
280 if (window_flag[j] & (PW_EQUIP))
284 if ((command_wrk && ni && !ne) || (!command_wrk && !ni && ne)) {
285 toggle_inventory_equipment(owner_ptr);
286 item_selection_ptr->toggle = !item_selection_ptr->toggle;
289 owner_ptr->window |= (PW_INVEN | PW_EQUIP);
290 handle_stuff(owner_ptr);
294 get_item_label = show_inventory(owner_ptr, item_selection_ptr->menu_line, item_selection_ptr->mode, item_selection_ptr->tval);
297 get_item_label = show_equipment(owner_ptr, item_selection_ptr->menu_line, item_selection_ptr->mode, item_selection_ptr->tval);
301 sprintf(item_selection_ptr->out_val, _("持ち物:", "Inven:"));
302 if ((item_selection_ptr->i1 <= item_selection_ptr->i2) && !use_menu) {
303 sprintf(item_selection_ptr->tmp_val, _("%c-%c,'(',')',", " %c-%c,'(',')',"), index_to_label(item_selection_ptr->i1),
304 index_to_label(item_selection_ptr->i2));
305 strcat(item_selection_ptr->out_val, item_selection_ptr->tmp_val);
308 if (!command_see && !use_menu)
309 strcat(item_selection_ptr->out_val, _(" '*'一覧,", " * to see,"));
311 if (item_selection_ptr->equip)
312 strcat(item_selection_ptr->out_val, format(_(" %s 装備品,", " %s for Equip,"), use_menu ? _("'4'or'6'", "4 or 6") : _("'/'", "/")));
314 sprintf(item_selection_ptr->out_val, _("装備品:", "Equip:"));
315 if ((item_selection_ptr->e1 <= item_selection_ptr->e2) && !use_menu) {
316 sprintf(item_selection_ptr->tmp_val, _("%c-%c,'(',')',", " %c-%c,'(',')',"), index_to_label(item_selection_ptr->e1),
317 index_to_label(item_selection_ptr->e2));
318 strcat(item_selection_ptr->out_val, item_selection_ptr->tmp_val);
321 if (!command_see && !use_menu)
322 strcat(item_selection_ptr->out_val, _(" '*'一覧,", " * to see,"));
324 if (item_selection_ptr->inven)
325 strcat(item_selection_ptr->out_val, format(_(" %s 持ち物,", " %s for Inven,"), use_menu ? _("'4'or'6'", "4 or 6") : _("'/'", "'/'")));
328 if (item_selection_ptr->allow_floor)
329 strcat(item_selection_ptr->out_val, _(" '-'床上,", " - for item_selection_ptr->floor,"));
331 if (item_selection_ptr->mode & USE_FORCE)
332 strcat(item_selection_ptr->out_val, _(" 'w'練気術,", " w for the Force,"));
334 strcat(item_selection_ptr->out_val, " ESC");
335 sprintf(item_selection_ptr->tmp_val, "(%s) %s", item_selection_ptr->out_val, pmt);
336 prt(item_selection_ptr->tmp_val, 0, 0);
337 item_selection_ptr->which = inkey();
339 int max_line = (command_wrk ? item_selection_ptr->max_equip : item_selection_ptr->max_inven);
340 switch (item_selection_ptr->which) {
345 item_selection_ptr->done = TRUE;
352 item_selection_ptr->menu_line += (max_line - 1);
359 item_selection_ptr->menu_line++;
369 if (!item_selection_ptr->inven || !item_selection_ptr->equip) {
379 command_wrk = !command_wrk;
380 max_line = (command_wrk ? item_selection_ptr->max_equip : item_selection_ptr->max_inven);
381 if (item_selection_ptr->menu_line > max_line)
382 item_selection_ptr->menu_line = max_line;
391 if (command_wrk == USE_FLOOR) {
392 *item_selection_ptr->cp = -get_item_label;
394 if (!get_item_okay(owner_ptr, get_item_label, item_selection_ptr->tval)) {
399 if (!get_item_allow(owner_ptr, get_item_label)) {
400 item_selection_ptr->done = TRUE;
404 *item_selection_ptr->cp = get_item_label;
407 item_selection_ptr->item = TRUE;
408 item_selection_ptr->done = TRUE;
412 if (item_selection_ptr->mode & USE_FORCE) {
413 *item_selection_ptr->cp = INVEN_FORCE;
414 item_selection_ptr->item = TRUE;
415 item_selection_ptr->done = TRUE;
421 if (item_selection_ptr->menu_line > max_line)
422 item_selection_ptr->menu_line -= max_line;
427 switch (item_selection_ptr->which) {
429 item_selection_ptr->done = TRUE;
446 if (!item_selection_ptr->inven || !item_selection_ptr->equip) {
456 command_wrk = !command_wrk;
460 if (item_selection_ptr->allow_floor) {
461 for (item_selection_ptr->this_o_idx = owner_ptr->current_floor_ptr->grid_array[owner_ptr->y][owner_ptr->x].o_idx;
462 item_selection_ptr->this_o_idx; item_selection_ptr->this_o_idx = item_selection_ptr->next_o_idx) {
464 o_ptr = &owner_ptr->current_floor_ptr->o_list[item_selection_ptr->this_o_idx];
465 item_selection_ptr->next_o_idx = o_ptr->next_o_idx;
466 if (!item_tester_okay(owner_ptr, o_ptr, item_selection_ptr->tval) && !(item_selection_ptr->mode & USE_FULL))
469 item_selection_ptr->k = 0 - item_selection_ptr->this_o_idx;
470 if (other_query_flag && !verify(owner_ptr, _("本当に", "Try"), item_selection_ptr->k) || !get_item_allow(owner_ptr, item_selection_ptr->k))
473 *item_selection_ptr->cp = item_selection_ptr->k;
474 item_selection_ptr->item = TRUE;
475 item_selection_ptr->done = TRUE;
479 if (item_selection_ptr->done)
496 if (!get_tag(owner_ptr, &item_selection_ptr->k, item_selection_ptr->which, command_wrk ? USE_EQUIP : USE_INVEN, item_selection_ptr->tval)) {
501 if ((item_selection_ptr->k < INVEN_RARM) ? !item_selection_ptr->inven : !item_selection_ptr->equip) {
506 if (!get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval)) {
511 if (!get_item_allow(owner_ptr, item_selection_ptr->k)) {
512 item_selection_ptr->done = TRUE;
516 *item_selection_ptr->cp = item_selection_ptr->k;
517 item_selection_ptr->item = TRUE;
518 item_selection_ptr->done = TRUE;
519 item_selection_ptr->cur_tag = item_selection_ptr->which;
523 if (item_selection_ptr->mode & USE_FORCE) {
524 *item_selection_ptr->cp = INVEN_FORCE;
525 item_selection_ptr->item = TRUE;
526 item_selection_ptr->done = TRUE;
533 bool not_found = FALSE;
534 if (!get_tag(owner_ptr, &item_selection_ptr->k, item_selection_ptr->which, command_wrk ? USE_EQUIP : USE_INVEN, item_selection_ptr->tval)) {
536 } else if ((item_selection_ptr->k < INVEN_RARM) ? !item_selection_ptr->inven : !item_selection_ptr->equip) {
538 } else if (!get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval)) {
543 *item_selection_ptr->cp = item_selection_ptr->k;
544 item_selection_ptr->item = TRUE;
545 item_selection_ptr->done = TRUE;
546 item_selection_ptr->cur_tag = item_selection_ptr->which;
550 ver = isupper(item_selection_ptr->which);
551 item_selection_ptr->which = (char)tolower(item_selection_ptr->which);
553 if (item_selection_ptr->which == '(')
554 item_selection_ptr->k = item_selection_ptr->i1;
555 else if (item_selection_ptr->which == ')')
556 item_selection_ptr->k = item_selection_ptr->i2;
558 item_selection_ptr->k = label_to_inventory(owner_ptr, item_selection_ptr->which);
560 if (item_selection_ptr->which == '(')
561 item_selection_ptr->k = item_selection_ptr->e1;
562 else if (item_selection_ptr->which == ')')
563 item_selection_ptr->k = item_selection_ptr->e2;
565 item_selection_ptr->k = label_to_equipment(owner_ptr, item_selection_ptr->which);
568 if (!get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval)) {
573 if (ver && !verify(owner_ptr, _("本当に", "Try"), item_selection_ptr->k)) {
574 item_selection_ptr->done = TRUE;
578 if (!get_item_allow(owner_ptr, item_selection_ptr->k)) {
579 item_selection_ptr->done = TRUE;
583 *item_selection_ptr->cp = item_selection_ptr->k;
584 item_selection_ptr->item = TRUE;
585 item_selection_ptr->done = TRUE;
596 item_selection_ptr->tval = 0;
597 item_tester_hook = NULL;
598 if (item_selection_ptr->toggle)
599 toggle_inventory_equipment(owner_ptr);
601 owner_ptr->window |= (PW_INVEN | PW_EQUIP);
602 handle_stuff(owner_ptr);
604 if (item_selection_ptr->oops && str)
607 if (item_selection_ptr->item) {
608 repeat_push(*item_selection_ptr->cp);
610 prev_tag = item_selection_ptr->cur_tag;
614 return item_selection_ptr->item;