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_MAIN_HAND) || (*item_selection_ptr->cp >= INVEN_TOTAL)))
83 if (*prev_tag && command_cmd) {
86 item_use_flag use_flag = (*item_selection_ptr->cp >= INVEN_MAIN_HAND) ? USE_EQUIP : USE_INVEN;
88 flag |= !get_tag(owner_ptr, &item_selection_ptr->k, *prev_tag, use_flag, item_selection_ptr->tval);
89 flag |= !get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval);
91 if (item_selection_ptr->k < INVEN_MAIN_HAND)
92 flag |= !item_selection_ptr->inven;
94 flag |= !item_selection_ptr->equip;
101 *item_selection_ptr->cp = item_selection_ptr->k;
102 item_selection_ptr->tval = 0;
103 item_tester_hook = NULL;
108 if (!get_item_okay(owner_ptr, *item_selection_ptr->cp, item_selection_ptr->tval))
111 item_selection_ptr->tval = 0;
112 item_tester_hook = NULL;
118 * @brief アイテムにタグ付けがされているかの調査処理 (のはず)
119 * @param owner_ptr プレーヤーへの参照ポインタ
120 * @param item_selection_ptr アイテムへの参照ポインタ
121 * @param prev_tag 前回選択したアイテムのタグ (のはず)
122 * @return プレイヤーによりアイテムが選択されたならTRUEを返す
124 static bool check_item_tag(player_type *owner_ptr, item_selection_type *item_selection_ptr, char *prev_tag)
126 if (!repeat_pull(item_selection_ptr->cp))
129 if (item_selection_ptr->mode & USE_FORCE && (*item_selection_ptr->cp == INVEN_FORCE)) {
130 item_selection_ptr->tval = 0;
131 item_tester_hook = NULL;
136 if (check_item_tag_aux(owner_ptr, item_selection_ptr))
139 return check_item_tag_inventory(owner_ptr, item_selection_ptr, prev_tag);
143 * @brief インベントリ内のアイテムが妥当かを判定する
144 * @param owner_ptr プレーヤーへの参照ポインタ
145 * @param fis_ptr アイテム選択への参照ポインタ
148 static void test_inventory(player_type *owner_ptr, item_selection_type *item_selection_ptr)
150 if (!item_selection_ptr->inven) {
151 item_selection_ptr->i2 = -1;
158 for (int j = 0; j < INVEN_PACK; j++)
159 if (item_tester_okay(owner_ptr, &owner_ptr->inventory_list[j], item_selection_ptr->tval) || (item_selection_ptr->mode & USE_FULL))
160 item_selection_ptr->max_inven++;
164 * @brief 装備品が妥当かを判定する
165 * @param owner_ptr プレーヤーへの参照ポインタ
166 * @param fis_ptr アイテム選択への参照ポインタ
169 static void test_equipment(player_type *owner_ptr, item_selection_type *item_selection_ptr)
171 if (!item_selection_ptr->equip) {
172 item_selection_ptr->e2 = -1;
179 for (int j = INVEN_MAIN_HAND; j < INVEN_TOTAL; j++)
180 if (owner_ptr->select_ring_slot ? is_ring_slot(j)
181 : item_tester_okay(owner_ptr, &owner_ptr->inventory_list[j], item_selection_ptr->tval) || (item_selection_ptr->mode & USE_FULL))
182 item_selection_ptr->max_equip++;
184 if (has_two_handed_weapons(owner_ptr) && !(item_selection_ptr->mode & IGNORE_BOTHHAND_SLOT))
185 item_selection_ptr->max_equip++;
189 * @brief オブジェクト選択の汎用関数 / General function for the selection of item
190 * Let the user select an item, save its "index"
191 * @param owner_ptr プレーヤーへの参照ポインタ
192 * @param cp 選択したオブジェクトのID
193 * @param pmt 選択目的のメッセージ
194 * @param str 選択できるオブジェクトがない場合のキャンセルメッセージ
195 * @param mode オプションフラグ
196 * @return プレイヤーによりアイテムが選択されたならTRUEを返す
197 * Return TRUE only if an acceptable item was chosen by the user
199 bool get_item(player_type *owner_ptr, OBJECT_IDX *cp, concptr pmt, concptr str, BIT_FLAGS mode, tval_type tval)
201 static char prev_tag = '\0';
202 if (easy_floor || use_menu)
203 return get_item_floor(owner_ptr, cp, pmt, str, mode, tval);
205 item_selection_type tmp_selection;
206 item_selection_type *item_selection_ptr = initialize_item_selection_type(&tmp_selection, cp, mode, tval);
207 check_item_selection_mode(item_selection_ptr);
208 if (check_item_tag(owner_ptr, item_selection_ptr, &prev_tag))
212 item_selection_ptr->done = FALSE;
213 item_selection_ptr->item = FALSE;
214 item_selection_ptr->i1 = 0;
215 item_selection_ptr->i2 = INVEN_PACK - 1;
216 test_inventory(owner_ptr, item_selection_ptr);
217 while ((item_selection_ptr->i1 <= item_selection_ptr->i2) && (!get_item_okay(owner_ptr, item_selection_ptr->i1, item_selection_ptr->tval)))
218 item_selection_ptr->i1++;
220 while ((item_selection_ptr->i1 <= item_selection_ptr->i2) && (!get_item_okay(owner_ptr, item_selection_ptr->i2, item_selection_ptr->tval)))
221 item_selection_ptr->i2--;
223 item_selection_ptr->e1 = INVEN_MAIN_HAND;
224 item_selection_ptr->e2 = INVEN_TOTAL - 1;
225 test_equipment(owner_ptr, item_selection_ptr);
226 while ((item_selection_ptr->e1 <= item_selection_ptr->e2) && (!get_item_okay(owner_ptr, item_selection_ptr->e1, item_selection_ptr->tval)))
227 item_selection_ptr->e1++;
229 while ((item_selection_ptr->e1 <= item_selection_ptr->e2) && (!get_item_okay(owner_ptr, item_selection_ptr->e2, item_selection_ptr->tval)))
230 item_selection_ptr->e2--;
232 if (item_selection_ptr->equip && has_two_handed_weapons(owner_ptr) && !(item_selection_ptr->mode & IGNORE_BOTHHAND_SLOT)) {
233 if (has_right_hand_weapon(owner_ptr)) {
234 if (item_selection_ptr->e2 < INVEN_SUB_HAND)
235 item_selection_ptr->e2 = INVEN_SUB_HAND;
236 } else if (has_left_hand_weapon(owner_ptr))
237 item_selection_ptr->e1 = INVEN_MAIN_HAND;
240 if (item_selection_ptr->floor) {
241 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;
242 item_selection_ptr->this_o_idx = item_selection_ptr->next_o_idx) {
244 o_ptr = &owner_ptr->current_floor_ptr->o_list[item_selection_ptr->this_o_idx];
245 item_selection_ptr->next_o_idx = o_ptr->next_o_idx;
246 if ((item_tester_okay(owner_ptr, o_ptr, item_selection_ptr->tval) || (item_selection_ptr->mode & USE_FULL)) && (o_ptr->marked & OM_FOUND))
247 item_selection_ptr->allow_floor = TRUE;
251 if (!item_selection_ptr->allow_floor && (item_selection_ptr->i1 > item_selection_ptr->i2) && (item_selection_ptr->e1 > item_selection_ptr->e2)) {
253 item_selection_ptr->oops = TRUE;
254 item_selection_ptr->done = TRUE;
256 if (item_selection_ptr->mode & USE_FORCE) {
257 *item_selection_ptr->cp = INVEN_FORCE;
258 item_selection_ptr->item = TRUE;
261 if (command_see && command_wrk && item_selection_ptr->equip)
263 else if (item_selection_ptr->inven)
265 else if (item_selection_ptr->equip)
271 /* 追加オプション(always_show_list)が設定されている場合は常に一覧を表示する */
272 if ((always_show_list == TRUE) || use_menu)
278 while (!item_selection_ptr->done) {
279 COMMAND_CODE get_item_label = 0;
282 for (int j = 0; j < 8; j++) {
283 if (!angband_term[j])
286 if (window_flag[j] & (PW_INVEN))
289 if (window_flag[j] & (PW_EQUIP))
293 if ((command_wrk && ni && !ne) || (!command_wrk && !ni && ne)) {
294 toggle_inventory_equipment(owner_ptr);
295 item_selection_ptr->toggle = !item_selection_ptr->toggle;
298 owner_ptr->window |= (PW_INVEN | PW_EQUIP);
299 handle_stuff(owner_ptr);
303 get_item_label = show_inventory(owner_ptr, item_selection_ptr->menu_line, item_selection_ptr->mode, item_selection_ptr->tval);
306 get_item_label = show_equipment(owner_ptr, item_selection_ptr->menu_line, item_selection_ptr->mode, item_selection_ptr->tval);
310 sprintf(item_selection_ptr->out_val, _("持ち物:", "Inven:"));
311 if ((item_selection_ptr->i1 <= item_selection_ptr->i2) && !use_menu) {
312 sprintf(item_selection_ptr->tmp_val, _("%c-%c,'(',')',", " %c-%c,'(',')',"), index_to_label(item_selection_ptr->i1),
313 index_to_label(item_selection_ptr->i2));
314 strcat(item_selection_ptr->out_val, item_selection_ptr->tmp_val);
317 if (!command_see && !use_menu)
318 strcat(item_selection_ptr->out_val, _(" '*'一覧,", " * to see,"));
320 if (item_selection_ptr->equip)
321 strcat(item_selection_ptr->out_val, format(_(" %s 装備品,", " %s for Equip,"), use_menu ? _("'4'or'6'", "4 or 6") : _("'/'", "/")));
323 sprintf(item_selection_ptr->out_val, _("装備品:", "Equip:"));
324 if ((item_selection_ptr->e1 <= item_selection_ptr->e2) && !use_menu) {
325 sprintf(item_selection_ptr->tmp_val, _("%c-%c,'(',')',", " %c-%c,'(',')',"), index_to_label(item_selection_ptr->e1),
326 index_to_label(item_selection_ptr->e2));
327 strcat(item_selection_ptr->out_val, item_selection_ptr->tmp_val);
330 if (!command_see && !use_menu)
331 strcat(item_selection_ptr->out_val, _(" '*'一覧,", " * to see,"));
333 if (item_selection_ptr->inven)
334 strcat(item_selection_ptr->out_val, format(_(" %s 持ち物,", " %s for Inven,"), use_menu ? _("'4'or'6'", "4 or 6") : _("'/'", "'/'")));
337 if (item_selection_ptr->allow_floor)
338 strcat(item_selection_ptr->out_val, _(" '-'床上,", " - for item_selection_ptr->floor,"));
340 if (item_selection_ptr->mode & USE_FORCE)
341 strcat(item_selection_ptr->out_val, _(" 'w'練気術,", " w for the Force,"));
343 strcat(item_selection_ptr->out_val, " ESC");
344 sprintf(item_selection_ptr->tmp_val, "(%s) %s", item_selection_ptr->out_val, pmt);
345 prt(item_selection_ptr->tmp_val, 0, 0);
346 item_selection_ptr->which = inkey();
348 int max_line = (command_wrk ? item_selection_ptr->max_equip : item_selection_ptr->max_inven);
349 switch (item_selection_ptr->which) {
354 item_selection_ptr->done = TRUE;
361 item_selection_ptr->menu_line += (max_line - 1);
368 item_selection_ptr->menu_line++;
378 if (!item_selection_ptr->inven || !item_selection_ptr->equip) {
388 command_wrk = !command_wrk;
389 max_line = (command_wrk ? item_selection_ptr->max_equip : item_selection_ptr->max_inven);
390 if (item_selection_ptr->menu_line > max_line)
391 item_selection_ptr->menu_line = max_line;
400 if (command_wrk == USE_FLOOR) {
401 *item_selection_ptr->cp = -get_item_label;
403 if (!get_item_okay(owner_ptr, get_item_label, item_selection_ptr->tval)) {
408 if (!get_item_allow(owner_ptr, get_item_label)) {
409 item_selection_ptr->done = TRUE;
413 *item_selection_ptr->cp = get_item_label;
416 item_selection_ptr->item = TRUE;
417 item_selection_ptr->done = TRUE;
421 if (item_selection_ptr->mode & USE_FORCE) {
422 *item_selection_ptr->cp = INVEN_FORCE;
423 item_selection_ptr->item = TRUE;
424 item_selection_ptr->done = TRUE;
430 if (item_selection_ptr->menu_line > max_line)
431 item_selection_ptr->menu_line -= max_line;
436 switch (item_selection_ptr->which) {
438 item_selection_ptr->done = TRUE;
455 if (!item_selection_ptr->inven || !item_selection_ptr->equip) {
465 command_wrk = !command_wrk;
469 if (item_selection_ptr->allow_floor) {
470 for (item_selection_ptr->this_o_idx = owner_ptr->current_floor_ptr->grid_array[owner_ptr->y][owner_ptr->x].o_idx;
471 item_selection_ptr->this_o_idx; item_selection_ptr->this_o_idx = item_selection_ptr->next_o_idx) {
473 o_ptr = &owner_ptr->current_floor_ptr->o_list[item_selection_ptr->this_o_idx];
474 item_selection_ptr->next_o_idx = o_ptr->next_o_idx;
475 if (!item_tester_okay(owner_ptr, o_ptr, item_selection_ptr->tval) && !(item_selection_ptr->mode & USE_FULL))
478 item_selection_ptr->k = 0 - item_selection_ptr->this_o_idx;
479 if ((other_query_flag && !verify(owner_ptr, _("本当に", "Try"), item_selection_ptr->k))
480 || !get_item_allow(owner_ptr, item_selection_ptr->k))
483 *item_selection_ptr->cp = item_selection_ptr->k;
484 item_selection_ptr->item = TRUE;
485 item_selection_ptr->done = TRUE;
489 if (item_selection_ptr->done)
506 if (!get_tag(owner_ptr, &item_selection_ptr->k, item_selection_ptr->which, command_wrk ? USE_EQUIP : USE_INVEN, item_selection_ptr->tval)) {
511 if ((item_selection_ptr->k < INVEN_MAIN_HAND) ? !item_selection_ptr->inven : !item_selection_ptr->equip) {
516 if (!get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval)) {
521 if (!get_item_allow(owner_ptr, item_selection_ptr->k)) {
522 item_selection_ptr->done = TRUE;
526 *item_selection_ptr->cp = item_selection_ptr->k;
527 item_selection_ptr->item = TRUE;
528 item_selection_ptr->done = TRUE;
529 item_selection_ptr->cur_tag = item_selection_ptr->which;
533 if (item_selection_ptr->mode & USE_FORCE) {
534 *item_selection_ptr->cp = INVEN_FORCE;
535 item_selection_ptr->item = TRUE;
536 item_selection_ptr->done = TRUE;
543 bool not_found = FALSE;
544 if (!get_tag(owner_ptr, &item_selection_ptr->k, item_selection_ptr->which, command_wrk ? USE_EQUIP : USE_INVEN, item_selection_ptr->tval)) {
546 } else if ((item_selection_ptr->k < INVEN_MAIN_HAND) ? !item_selection_ptr->inven : !item_selection_ptr->equip) {
548 } else if (!get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval)) {
553 *item_selection_ptr->cp = item_selection_ptr->k;
554 item_selection_ptr->item = TRUE;
555 item_selection_ptr->done = TRUE;
556 item_selection_ptr->cur_tag = item_selection_ptr->which;
560 ver = isupper(item_selection_ptr->which);
561 item_selection_ptr->which = (char)tolower(item_selection_ptr->which);
563 if (item_selection_ptr->which == '(')
564 item_selection_ptr->k = item_selection_ptr->i1;
565 else if (item_selection_ptr->which == ')')
566 item_selection_ptr->k = item_selection_ptr->i2;
568 item_selection_ptr->k = label_to_inventory(owner_ptr, item_selection_ptr->which);
570 if (item_selection_ptr->which == '(')
571 item_selection_ptr->k = item_selection_ptr->e1;
572 else if (item_selection_ptr->which == ')')
573 item_selection_ptr->k = item_selection_ptr->e2;
575 item_selection_ptr->k = label_to_equipment(owner_ptr, item_selection_ptr->which);
578 if (!get_item_okay(owner_ptr, item_selection_ptr->k, item_selection_ptr->tval)) {
583 if (ver && !verify(owner_ptr, _("本当に", "Try"), item_selection_ptr->k)) {
584 item_selection_ptr->done = TRUE;
588 if (!get_item_allow(owner_ptr, item_selection_ptr->k)) {
589 item_selection_ptr->done = TRUE;
593 *item_selection_ptr->cp = item_selection_ptr->k;
594 item_selection_ptr->item = TRUE;
595 item_selection_ptr->done = TRUE;
606 item_selection_ptr->tval = 0;
607 item_tester_hook = NULL;
608 if (item_selection_ptr->toggle)
609 toggle_inventory_equipment(owner_ptr);
611 owner_ptr->window |= (PW_INVEN | PW_EQUIP);
612 handle_stuff(owner_ptr);
614 if (item_selection_ptr->oops && str)
617 if (item_selection_ptr->item) {
618 repeat_push(*item_selection_ptr->cp);
620 prev_tag = item_selection_ptr->cur_tag;
624 return item_selection_ptr->item;