2 * @brief 同種のアイテムをインベントリや床に重ね合わせたり、その判断を行う処理
7 #include "object/object-stack.h"
8 #include "game-option/game-play-options.h"
9 #include "object-enchant/object-ego.h"
10 #include "object-enchant/object-smith.h"
11 #include "object-enchant/special-object-flags.h"
12 #include "object-enchant/trc-types.h"
13 #include "object/object-kind.h"
14 #include "object/object-value.h"
15 #include "perception/object-perception.h"
16 #include "sv-definition/sv-other-types.h"
17 #include "system/object-type-definition.h"
20 * @brief 魔法棒やロッドのスロット分割時に使用回数を分配する /
21 * Distribute charges of rods or wands.
22 * @param o_ptr 分割元オブジェクトの構造体参照ポインタ source item
23 * @param q_ptr 分割先オブジェクトの構造体参照ポインタ target item, must be of the same type as o_ptr
24 * @param amt 分割したい回数量 number of items that are transfered
26 * Hack -- If rods or wands are dropped, the total maximum timeout or\n
27 * charges need to be allocated between the two stacks. If all the items\n
28 * are being dropped, it makes for a neater message to leave the original\n
29 * stack's pval alone. -LM-\n
31 void distribute_charges(object_type *o_ptr, object_type *q_ptr, int amt)
33 if ((o_ptr->tval != ItemKindType::WAND) && (o_ptr->tval != ItemKindType::ROD))
36 q_ptr->pval = o_ptr->pval * amt / o_ptr->number;
37 if (amt < o_ptr->number)
38 o_ptr->pval -= q_ptr->pval;
40 if ((o_ptr->tval != ItemKindType::ROD) || !o_ptr->timeout)
43 if (q_ptr->pval > o_ptr->timeout)
44 q_ptr->timeout = o_ptr->timeout;
46 q_ptr->timeout = q_ptr->pval;
48 if (amt < o_ptr->number)
49 o_ptr->timeout -= q_ptr->timeout;
53 * @brief 魔法棒やロッドの使用回数を減らす /
54 * @param o_ptr オブジェクトの構造体参照ポインタ source item
55 * @param amt 減らしたい回数量 number of items that are transfered
57 * Hack -- If rods or wand are destroyed, the total maximum timeout or\n
58 * charges of the stack needs to be reduced, unless all the items are\n
59 * being destroyed. -LM-\n
61 void reduce_charges(object_type *o_ptr, int amt)
63 if (((o_ptr->tval == ItemKindType::WAND) || (o_ptr->tval == ItemKindType::ROD)) && (amt < o_ptr->number)) {
64 o_ptr->pval -= o_ptr->pval * amt / o_ptr->number;
69 * @brief 両オブジェクトをスロットに重ね合わせ可能な最大数を返す。
70 * Determine if an item can partly absorb a second item. Return maximum number of stack.
71 * @param o_ptr 検証したいオブジェクトの構造体参照ポインタ1
72 * @param j_ptr 検証したいオブジェクトの構造体参照ポインタ2
73 * @return 重ね合わせ可能なアイテム数
75 int object_similar_part(const object_type *o_ptr, const object_type *j_ptr)
77 const int max_stack_size = 99;
78 int max_num = max_stack_size;
79 if (o_ptr->k_idx != j_ptr->k_idx)
82 switch (o_ptr->tval) {
83 case ItemKindType::CHEST:
84 case ItemKindType::CARD:
85 case ItemKindType::CAPTURE: {
88 case ItemKindType::STATUE: {
89 if ((o_ptr->sval != SV_PHOTO) || (j_ptr->sval != SV_PHOTO))
91 if (o_ptr->pval != j_ptr->pval)
95 case ItemKindType::FIGURINE:
96 case ItemKindType::CORPSE: {
97 if (o_ptr->pval != j_ptr->pval)
102 case ItemKindType::FOOD:
103 case ItemKindType::POTION:
104 case ItemKindType::SCROLL: {
107 case ItemKindType::STAFF: {
108 if ((!(o_ptr->ident & (IDENT_EMPTY)) && !o_ptr->is_known()) || (!(j_ptr->ident & (IDENT_EMPTY)) && !j_ptr->is_known()))
111 if (o_ptr->pval != j_ptr->pval)
116 case ItemKindType::WAND: {
117 if ((!(o_ptr->ident & (IDENT_EMPTY)) && !o_ptr->is_known()) || (!(j_ptr->ident & (IDENT_EMPTY)) && !j_ptr->is_known()))
122 case ItemKindType::ROD: {
123 max_num = std::min(max_num, MAX_SHORT / k_info[o_ptr->k_idx].pval);
126 case ItemKindType::BOW:
127 case ItemKindType::DIGGING:
128 case ItemKindType::HAFTED:
129 case ItemKindType::POLEARM:
130 case ItemKindType::SWORD:
131 case ItemKindType::BOOTS:
132 case ItemKindType::GLOVES:
133 case ItemKindType::HELM:
134 case ItemKindType::CROWN:
135 case ItemKindType::SHIELD:
136 case ItemKindType::CLOAK:
137 case ItemKindType::SOFT_ARMOR:
138 case ItemKindType::HARD_ARMOR:
139 case ItemKindType::DRAG_ARMOR:
140 case ItemKindType::RING:
141 case ItemKindType::AMULET:
142 case ItemKindType::LITE:
143 case ItemKindType::WHISTLE: {
144 if (!o_ptr->is_known() || !j_ptr->is_known())
148 case ItemKindType::BOLT:
149 case ItemKindType::ARROW:
150 case ItemKindType::SHOT: {
151 if (o_ptr->is_known() != j_ptr->is_known())
153 if (o_ptr->feeling != j_ptr->feeling)
155 if (o_ptr->to_h != j_ptr->to_h)
157 if (o_ptr->to_d != j_ptr->to_d)
159 if (o_ptr->to_a != j_ptr->to_a)
161 if (o_ptr->pval != j_ptr->pval)
163 if (o_ptr->is_artifact() || j_ptr->is_artifact())
165 if (o_ptr->name2 != j_ptr->name2)
167 if (o_ptr->xtra3 != j_ptr->xtra3)
169 if (o_ptr->xtra4 != j_ptr->xtra4)
171 if (o_ptr->xtra1 || j_ptr->xtra1)
173 if (o_ptr->timeout || j_ptr->timeout)
175 if (o_ptr->ac != j_ptr->ac)
177 if (o_ptr->dd != j_ptr->dd)
179 if (o_ptr->ds != j_ptr->ds)
181 if (Smith::object_effect(o_ptr) != Smith::object_effect(j_ptr))
183 if (Smith::object_activation(o_ptr) != Smith::object_activation(j_ptr))
188 if (!o_ptr->is_known() || !j_ptr->is_known())
195 if (o_ptr->art_flags != j_ptr->art_flags)
198 if (o_ptr->curse_flags != j_ptr->curse_flags)
200 if ((o_ptr->ident & (IDENT_BROKEN)) != (j_ptr->ident & (IDENT_BROKEN)))
203 if (o_ptr->inscription && j_ptr->inscription && (o_ptr->inscription != j_ptr->inscription))
206 if (!stack_force_notes && (o_ptr->inscription != j_ptr->inscription))
208 if (!stack_force_costs && (o_ptr->discount != j_ptr->discount))
215 * @brief 両オブジェクトをスロットに重ねることができるかどうかを返す。
216 * Determine if an item can absorb a second item.
217 * @param o_ptr 検証したいオブジェクトの構造体参照ポインタ1
218 * @param j_ptr 検証したいオブジェクトの構造体参照ポインタ2
219 * @return 重ね合わせ可能ならばTRUEを返す。
221 bool object_similar(const object_type *o_ptr, const object_type *j_ptr)
223 int total = o_ptr->number + j_ptr->number;
224 int max_num = object_similar_part(o_ptr, j_ptr);
234 * @brief 両オブジェクトをスロットに重ね合わせる。
235 * Allow one item to "absorb" another, assuming they are similar
236 * @param o_ptr 重ね合わせ先のオブジェクトの構造体参照ポインタ
237 * @param j_ptr 重ね合わせ元のオブジェクトの構造体参照ポインタ
239 void object_absorb(object_type *o_ptr, object_type *j_ptr)
241 int max_num = object_similar_part(o_ptr, j_ptr);
242 int total = o_ptr->number + j_ptr->number;
243 int diff = (total > max_num) ? total - max_num : 0;
245 o_ptr->number = (total > max_num) ? max_num : total;
246 if (j_ptr->is_known())
249 if (((o_ptr->ident & IDENT_STORE) || (j_ptr->ident & IDENT_STORE)) && (!((o_ptr->ident & IDENT_STORE) && (j_ptr->ident & IDENT_STORE)))) {
250 if (j_ptr->ident & IDENT_STORE)
251 j_ptr->ident &= 0xEF;
252 if (o_ptr->ident & IDENT_STORE)
253 o_ptr->ident &= 0xEF;
256 if (j_ptr->is_fully_known())
257 o_ptr->ident |= (IDENT_FULL_KNOWN);
258 if (j_ptr->inscription)
259 o_ptr->inscription = j_ptr->inscription;
261 o_ptr->feeling = j_ptr->feeling;
262 if (o_ptr->discount < j_ptr->discount)
263 o_ptr->discount = j_ptr->discount;
264 if (o_ptr->tval == ItemKindType::ROD) {
265 o_ptr->pval += j_ptr->pval * (j_ptr->number - diff) / j_ptr->number;
266 o_ptr->timeout += j_ptr->timeout * (j_ptr->number - diff) / j_ptr->number;
269 if (o_ptr->tval == ItemKindType::WAND) {
270 o_ptr->pval += j_ptr->pval * (j_ptr->number - diff) / j_ptr->number;