1 #include "inventory/inventory-object.h"
2 #include "object/object-flavor.h"
3 #include "object/object-mark-types.h"
4 #include "object/object-value.h"
5 #include "object/object2.h" // 暫定、相互参照している.
6 #include "player/player-effects.h" // 暫定、相互参照している.
7 #include "view/object-describer.h"
9 void vary_item(player_type *owner_ptr, INVENTORY_IDX item, ITEM_NUMBER num)
12 inven_item_increase(owner_ptr, item, num);
13 inven_item_describe(owner_ptr, item);
14 inven_item_optimize(owner_ptr, item);
18 floor_type *floor_ptr = owner_ptr->current_floor_ptr;
19 floor_item_increase(floor_ptr, 0 - item, num);
20 floor_item_describe(owner_ptr, 0 - item);
21 floor_item_optimize(owner_ptr, 0 - item);
25 * @brief アイテムを増減させ残り所持数メッセージを表示する /
26 * Increase the "number" of an item in the inventory
27 * @param owner_ptr プレーヤーへの参照ポインタ
28 * @param item 所持数を増やしたいプレイヤーのアイテム所持スロット
32 void inven_item_increase(player_type *owner_ptr, INVENTORY_IDX item, ITEM_NUMBER num)
34 object_type *o_ptr = &owner_ptr->inventory_list[item];
46 owner_ptr->total_weight += (num * o_ptr->weight);
47 owner_ptr->update |= (PU_BONUS);
48 owner_ptr->update |= (PU_MANA);
49 owner_ptr->update |= (PU_COMBINE);
50 owner_ptr->window |= (PW_INVEN | PW_EQUIP);
52 if (o_ptr->number || !owner_ptr->ele_attack)
54 if (!(item == INVEN_RARM) && !(item == INVEN_LARM))
56 if (has_melee_weapon(owner_ptr, INVEN_RARM + INVEN_LARM - item))
59 set_ele_attack(owner_ptr, 0, 0);
63 * @brief 所持アイテムスロットから所持数のなくなったアイテムを消去する /
64 * Erase an inventory slot if it has no more items
65 * @param owner_ptr プレーヤーへの参照ポインタ
66 * @param item 消去したいプレイヤーのアイテム所持スロット
69 void inven_item_optimize(player_type *owner_ptr, INVENTORY_IDX item)
71 object_type *o_ptr = &owner_ptr->inventory_list[item];
77 if (item >= INVEN_RARM) {
78 owner_ptr->equip_cnt--;
79 object_wipe(&owner_ptr->inventory_list[item]);
80 owner_ptr->update |= PU_BONUS;
81 owner_ptr->update |= PU_TORCH;
82 owner_ptr->update |= PU_MANA;
84 owner_ptr->window |= PW_EQUIP;
85 owner_ptr->window |= PW_SPELL;
89 owner_ptr->inven_cnt--;
91 for (i = item; i < INVEN_PACK; i++) {
92 owner_ptr->inventory_list[i] = owner_ptr->inventory_list[i + 1];
95 object_wipe(&owner_ptr->inventory_list[i]);
96 owner_ptr->window |= PW_INVEN;
97 owner_ptr->window |= PW_SPELL;
101 * @brief 所持スロットから床下にオブジェクトを落とすメインルーチン /
102 * Drop (some of) a non-cursed inventory/equipment item
103 * @param owner_ptr プレーヤーへの参照ポインタ
104 * @param item 所持テーブルのID
108 * The object will be dropped "near" the current location
110 void drop_from_inventory(player_type *owner_ptr, INVENTORY_IDX item, ITEM_NUMBER amt)
115 GAME_TEXT o_name[MAX_NLEN];
116 o_ptr = &owner_ptr->inventory_list[item];
120 if (amt > o_ptr->number)
123 if (item >= INVEN_RARM) {
124 item = inven_takeoff(owner_ptr, item, amt);
125 o_ptr = &owner_ptr->inventory_list[item];
129 object_copy(q_ptr, o_ptr);
130 distribute_charges(o_ptr, q_ptr, amt);
133 object_desc(owner_ptr, o_name, q_ptr, 0);
134 msg_format(_("%s(%c)を落とした。", "You drop %s (%c)."), o_name, index_to_label(item));
135 (void)drop_near(owner_ptr, q_ptr, 0, owner_ptr->y, owner_ptr->x);
136 vary_item(owner_ptr, item, -amt);
140 * @brief プレイヤーの所持スロットに存在するオブジェクトをまとめなおす /
141 * Combine items in the pack
144 * Note special handling of the "overflow" slot
146 void combine_pack(player_type *owner_ptr)
149 bool is_first_combination = TRUE;
150 bool combined = TRUE;
151 while (is_first_combination || combined) {
152 is_first_combination = FALSE;
155 for (int i = INVEN_PACK; i > 0; i--) {
157 o_ptr = &owner_ptr->inventory_list[i];
160 for (int j = 0; j < i; j++) {
162 j_ptr = &owner_ptr->inventory_list[j];
167 * Get maximum number of the stack if these
168 * are similar, get zero otherwise.
170 int max_num = object_similar_part(j_ptr, o_ptr);
172 bool is_max = (max_num != 0) && (j_ptr->number < max_num);
176 if (o_ptr->number + j_ptr->number <= max_num) {
178 object_absorb(j_ptr, o_ptr);
179 owner_ptr->inven_cnt--;
181 for (k = i; k < INVEN_PACK; k++) {
182 owner_ptr->inventory_list[k] = owner_ptr->inventory_list[k + 1];
185 object_wipe(&owner_ptr->inventory_list[k]);
187 int old_num = o_ptr->number;
188 int remain = j_ptr->number + o_ptr->number - max_num;
189 object_absorb(j_ptr, o_ptr);
190 o_ptr->number = remain;
191 if (o_ptr->tval == TV_ROD) {
192 o_ptr->pval = o_ptr->pval * remain / old_num;
193 o_ptr->timeout = o_ptr->timeout * remain / old_num;
196 if (o_ptr->tval == TV_WAND) {
197 o_ptr->pval = o_ptr->pval * remain / old_num;
201 owner_ptr->window |= (PW_INVEN);
209 msg_print(_("ザックの中のアイテムをまとめ直した。", "You combine some items in your pack."));
213 * @brief プレイヤーの所持スロットに存在するオブジェクトを並び替える /
214 * Reorder items in the pack
215 * @param owner_ptr プレーヤーへの参照ポインタ
218 * Note special handling of the "overflow" slot
220 void reorder_pack(player_type *owner_ptr)
229 for (i = 0; i < INVEN_PACK; i++) {
230 if ((i == INVEN_PACK) && (owner_ptr->inven_cnt == INVEN_PACK))
233 o_ptr = &owner_ptr->inventory_list[i];
237 o_value = object_value(o_ptr);
238 for (j = 0; j < INVEN_PACK; j++) {
239 if (object_sort_comp(o_ptr, o_value, &owner_ptr->inventory_list[j]))
248 object_copy(q_ptr, &owner_ptr->inventory_list[i]);
249 for (k = i; k > j; k--) {
250 object_copy(&owner_ptr->inventory_list[k], &owner_ptr->inventory_list[k - 1]);
253 object_copy(&owner_ptr->inventory_list[j], q_ptr);
254 owner_ptr->window |= (PW_INVEN);
258 msg_print(_("ザックの中のアイテムを並べ直した。", "You reorder some items in your pack."));
262 * @brief オブジェクトをプレイヤーが拾って所持スロットに納めるメインルーチン /
263 * Add an item to the players inventory, and return the slot used.
264 * @param o_ptr 拾うオブジェクトの構造体参照ポインタ
265 * @return 収められた所持スロットのID、拾うことができなかった場合-1を返す。
267 * If the new item can combine with an existing item in the inventory,\n
268 * it will do so, using "object_similar()" and "object_absorb()", else,\n
269 * the item will be placed into the "proper" location in the inventory.\n
271 * This function can be used to "over-fill" the player's pack, but only\n
272 * once, and such an action must trigger the "overflow" code immediately.\n
273 * Note that when the pack is being "over-filled", the new item must be\n
274 * placed into the "overflow" slot, and the "overflow" must take place\n
275 * before the pack is reordered, but (optionally) after the pack is\n
276 * combined. This may be tricky. See "dungeon.c" for info.\n
278 * Note that this code must remove any location/stack information\n
279 * from the object once it is placed into the inventory.\n
281 s16b inven_carry(player_type *owner_ptr, object_type *o_ptr)
283 INVENTORY_IDX i, j, k;
284 INVENTORY_IDX n = -1;
287 for (j = 0; j < INVEN_PACK; j++) {
288 j_ptr = &owner_ptr->inventory_list[j];
293 if (object_similar(j_ptr, o_ptr)) {
294 object_absorb(j_ptr, o_ptr);
296 owner_ptr->total_weight += (o_ptr->number * o_ptr->weight);
297 owner_ptr->update |= (PU_BONUS);
298 owner_ptr->window |= (PW_INVEN);
303 if (owner_ptr->inven_cnt > INVEN_PACK)
306 for (j = 0; j <= INVEN_PACK; j++) {
307 j_ptr = &owner_ptr->inventory_list[j];
313 if (i < INVEN_PACK) {
314 s32b o_value = object_value(o_ptr);
315 for (j = 0; j < INVEN_PACK; j++) {
316 if (object_sort_comp(o_ptr, o_value, &owner_ptr->inventory_list[j]))
321 for (k = n; k >= i; k--) {
322 object_copy(&owner_ptr->inventory_list[k + 1], &owner_ptr->inventory_list[k]);
325 object_wipe(&owner_ptr->inventory_list[i]);
328 object_copy(&owner_ptr->inventory_list[i], o_ptr);
329 j_ptr = &owner_ptr->inventory_list[i];
330 j_ptr->next_o_idx = 0;
331 j_ptr->held_m_idx = 0;
332 j_ptr->iy = j_ptr->ix = 0;
333 j_ptr->marked = OM_TOUCHED;
335 owner_ptr->total_weight += (j_ptr->number * j_ptr->weight);
336 owner_ptr->inven_cnt++;
337 owner_ptr->update |= (PU_BONUS | PU_COMBINE | PU_REORDER);
338 owner_ptr->window |= (PW_INVEN);