OSDN Git Service

Merge branch 'master' of git.osdn.net:/gitroot/hengband/hengband
[hengband/hengband.git] / src / market / building-craft-fix.c
1 #include "market/building-craft-fix.h"
2 #include "artifact/artifact-info.h"
3 #include "art-definition/art-sword-types.h"
4 #include "core/asking-player.h"
5 #include "core/player-update-types.h"
6 #include "core/stuff-handler.h"
7 #include "flavor/flavor-describer.h"
8 #include "flavor/object-flavor-types.h"
9 #include "floor/floor-object.h"
10 #include "inventory/inventory-object.h"
11 #include "market/building-util.h"
12 #include "object-enchant/object-boost.h"
13 #include "object-enchant/special-object-flags.h"
14 #include "object-enchant/tr-types.h"
15 #include "object-hook/hook-enchant.h"
16 #include "object-hook/hook-weapon.h"
17 #include "object/item-tester-hooker.h"
18 #include "object/item-use-flags.h"
19 #include "object/object-flags.h"
20 #include "object/object-kind-hook.h"
21 #include "object/object-kind.h"
22 #include "object/object-value.h"
23 #include "racial/racial-android.h"
24 #include "spell-realm/spells-hex.h"
25 #include "sv-definition/sv-other-types.h"
26 #include "sv-definition/sv-weapon-types.h"
27 #include "term/screen-processor.h"
28 #include "util/bit-flags-calculator.h"
29 #include "view/display-messages.h"
30
31 /*!
32  * @brief 修復材料のオブジェクトから修復対象に特性を移植する。
33  * @param to_ptr 修復対象オブジェクトの構造体の参照ポインタ。
34  * @param from_ptr 修復材料オブジェクトの構造体の参照ポインタ。
35  * @return 修復対象になるならTRUEを返す。
36  */
37 static void give_one_ability_of_object(player_type *player_ptr, object_type *to_ptr, object_type *from_ptr)
38 {
39     BIT_FLAGS to_flgs[TR_FLAG_SIZE];
40     BIT_FLAGS from_flgs[TR_FLAG_SIZE];
41     object_flags(player_ptr, to_ptr, to_flgs);
42     object_flags(player_ptr, from_ptr, from_flgs);
43
44     int n = 0;
45     int cand[TR_FLAG_MAX];
46     for (tr_type i = 0; i < TR_FLAG_MAX; i++) {
47         switch (i) {
48         case TR_IGNORE_ACID:
49         case TR_IGNORE_ELEC:
50         case TR_IGNORE_FIRE:
51         case TR_IGNORE_COLD:
52         case TR_ACTIVATE:
53         case TR_RIDING:
54         case TR_THROW:
55         case TR_SHOW_MODS:
56         case TR_HIDE_TYPE:
57         case TR_ES_ATTACK:
58         case TR_ES_AC:
59         case TR_FULL_NAME:
60         case TR_FIXED_FLAVOR:
61             break;
62         default:
63             if (have_flag(from_flgs, i) && !have_flag(to_flgs, i)) {
64                 if (!(is_pval_flag(i) && (from_ptr->pval < 1)))
65                     cand[n++] = i;
66             }
67         }
68     }
69
70     if (n <= 0)
71         return;
72
73     int tr_idx = cand[randint0(n)];
74     add_flag(to_ptr->art_flags, tr_idx);
75     if (is_pval_flag(tr_idx))
76         to_ptr->pval = MAX(to_ptr->pval, 1);
77     int bmax = MIN(3, MAX(1, 40 / (to_ptr->dd * to_ptr->ds)));
78     if (tr_idx == TR_BLOWS)
79         to_ptr->pval = MIN(to_ptr->pval, bmax);
80     if (tr_idx == TR_SPEED)
81         to_ptr->pval = MIN(to_ptr->pval, 4);
82 }
83
84 /*!
85  * @brief アイテム修復処理のメインルーチン / Repair broken weapon
86  * @param player_ptr プレーヤーへの参照ポインタ
87  * @param bcost 基本修復費用
88  * @return 実際にかかった費用
89  */
90 static PRICE repair_broken_weapon_aux(player_type *player_ptr, PRICE bcost)
91 {
92     clear_bldg(0, 22);
93     int row = 7;
94     prt(_("修復には材料となるもう1つの武器が必要です。", "Hand one material weapon to repair a broken weapon."), row, 2);
95     prt(_("材料に使用した武器はなくなります!", "The material weapon will disappear after repairing!!"), row + 1, 2);
96
97     concptr q = _("どの折れた武器を修復しますか?", "Repair which broken weapon? ");
98     concptr s = _("修復できる折れた武器がありません。", "You have no broken weapon to repair.");
99     item_tester_hook = item_tester_hook_broken_weapon;
100
101     OBJECT_IDX item;
102     object_type *o_ptr;
103     o_ptr = choose_object(player_ptr, &item, q, s, (USE_INVEN | USE_EQUIP), 0);
104     if (!o_ptr)
105         return 0;
106
107     if (!object_is_ego(o_ptr) && !object_is_artifact(o_ptr)) {
108         msg_format(_("それは直してもしょうがないぜ。", "It is worthless to repair."));
109         return 0;
110     }
111
112     if (o_ptr->number > 1) {
113         msg_format(_("一度に複数を修復することはできません!", "They are too many to repair at once!"));
114         return 0;
115     }
116
117     char basenm[MAX_NLEN];
118     describe_flavor(player_ptr, basenm, o_ptr, OD_NAME_ONLY);
119     prt(format(_("修復する武器 : %s", "Repairing: %s"), basenm), row + 3, 2);
120
121     q = _("材料となる武器は?", "Which weapon for material? ");
122     s = _("材料となる武器がありません。", "You have no material to repair.");
123
124     item_tester_hook = item_tester_hook_orthodox_melee_weapons;
125     OBJECT_IDX mater;
126     object_type *mo_ptr;
127     mo_ptr = choose_object(player_ptr, &mater, q, s, (USE_INVEN | USE_EQUIP), 0);
128     if (!mo_ptr)
129         return 0;
130     if (mater == item) {
131         msg_print(_("クラインの壷じゃない!", "This is not a klein bottle!"));
132         return 0;
133     }
134
135     describe_flavor(player_ptr, basenm, mo_ptr, OD_NAME_ONLY);
136     prt(format(_("材料とする武器: %s", "Material : %s"), basenm), row + 4, 2);
137     PRICE cost = bcost + object_value_real(player_ptr, o_ptr) * 2;
138     if (!get_check(format(_("$%dかかりますがよろしいですか? ", "Costs %d gold, okay? "), cost)))
139         return 0;
140
141     if (player_ptr->au < cost) {
142         describe_flavor(player_ptr, basenm, o_ptr, OD_NAME_ONLY);
143         msg_format(_("%sを修復するだけのゴールドがありません!", "You do not have the gold to repair %s!"), basenm);
144         msg_print(NULL);
145         return 0;
146     }
147
148     player_ptr->total_weight -= o_ptr->weight;
149     KIND_OBJECT_IDX k_idx;
150     if (o_ptr->sval == SV_BROKEN_DAGGER) {
151         int n = 1;
152         k_idx = 0;
153         for (KIND_OBJECT_IDX j = 1; j < max_k_idx; j++) {
154             object_kind *k_aux_ptr = &k_info[j];
155
156             if (k_aux_ptr->tval != TV_SWORD)
157                 continue;
158             if ((k_aux_ptr->sval == SV_BROKEN_DAGGER) || (k_aux_ptr->sval == SV_BROKEN_SWORD) || (k_aux_ptr->sval == SV_POISON_NEEDLE))
159                 continue;
160             if (k_aux_ptr->weight > 99)
161                 continue;
162
163             if (one_in_(n)) {
164                 k_idx = j;
165                 n++;
166             }
167         }
168     } else {
169         tval_type tval = (one_in_(5) ? mo_ptr->tval : TV_SWORD);
170         while (TRUE) {
171             object_kind *ck_ptr;
172             k_idx = lookup_kind(tval, SV_ANY);
173             ck_ptr = &k_info[k_idx];
174
175             if (tval == TV_SWORD) {
176                 if ((ck_ptr->sval == SV_BROKEN_DAGGER) || (ck_ptr->sval == SV_BROKEN_SWORD) || (ck_ptr->sval == SV_DIAMOND_EDGE)
177                     || (ck_ptr->sval == SV_POISON_NEEDLE))
178                     continue;
179             }
180             if (tval == TV_POLEARM) {
181                 if ((ck_ptr->sval == SV_DEATH_SCYTHE) || (ck_ptr->sval == SV_TSURIZAO))
182                     continue;
183             }
184             if (tval == TV_HAFTED) {
185                 if ((ck_ptr->sval == SV_GROND) || (ck_ptr->sval == SV_WIZSTAFF) || (ck_ptr->sval == SV_NAMAKE_HAMMER))
186                     continue;
187             }
188
189             break;
190         }
191     }
192
193     int dd_bonus = o_ptr->dd - k_info[o_ptr->k_idx].dd;
194     int ds_bonus = o_ptr->ds - k_info[o_ptr->k_idx].ds;
195     dd_bonus += mo_ptr->dd - k_info[mo_ptr->k_idx].dd;
196     ds_bonus += mo_ptr->ds - k_info[mo_ptr->k_idx].ds;
197
198     object_kind *k_ptr;
199     k_ptr = &k_info[k_idx];
200     o_ptr->k_idx = k_idx;
201     o_ptr->weight = k_ptr->weight;
202     o_ptr->tval = k_ptr->tval;
203     o_ptr->sval = k_ptr->sval;
204     o_ptr->dd = k_ptr->dd;
205     o_ptr->ds = k_ptr->ds;
206
207     for (int i = 0; i < TR_FLAG_SIZE; i++)
208         o_ptr->art_flags[i] |= k_ptr->flags[i];
209     if (k_ptr->pval)
210         o_ptr->pval = MAX(o_ptr->pval, randint1(k_ptr->pval));
211     if (have_flag(k_ptr->flags, TR_ACTIVATE))
212         o_ptr->xtra2 = (byte)k_ptr->act_idx;
213
214     if (dd_bonus > 0) {
215         o_ptr->dd++;
216         for (int i = 1; i < dd_bonus; i++) {
217             if (one_in_(o_ptr->dd + i))
218                 o_ptr->dd++;
219         }
220     }
221
222     if (ds_bonus > 0) {
223         o_ptr->ds++;
224         for (int i = 1; i < ds_bonus; i++) {
225             if (one_in_(o_ptr->ds + i))
226                 o_ptr->ds++;
227         }
228     }
229
230     if (have_flag(k_ptr->flags, TR_BLOWS)) {
231         int bmax = MIN(3, MAX(1, 40 / (o_ptr->dd * o_ptr->ds)));
232         o_ptr->pval = MIN(o_ptr->pval, bmax);
233     }
234
235     give_one_ability_of_object(player_ptr, o_ptr, mo_ptr);
236     o_ptr->to_d += MAX(0, (mo_ptr->to_d / 3));
237     o_ptr->to_h += MAX(0, (mo_ptr->to_h / 3));
238     o_ptr->to_a += MAX(0, (mo_ptr->to_a));
239
240     if ((o_ptr->name1 == ART_NARSIL) || (object_is_random_artifact(o_ptr) && one_in_(1)) || (object_is_ego(o_ptr) && one_in_(7))) {
241         if (object_is_ego(o_ptr)) {
242             add_flag(o_ptr->art_flags, TR_IGNORE_FIRE);
243             add_flag(o_ptr->art_flags, TR_IGNORE_ACID);
244         }
245
246         give_one_ability_of_object(player_ptr, o_ptr, mo_ptr);
247         if (!activation_index(player_ptr, o_ptr))
248             one_activation(o_ptr);
249
250         if (o_ptr->name1 == ART_NARSIL) {
251             one_high_resistance(o_ptr);
252             one_ability(o_ptr);
253         }
254
255         msg_print(_("これはかなりの業物だったようだ。", "This blade seems to be exceptional."));
256     }
257
258     describe_flavor(player_ptr, basenm, o_ptr, OD_NAME_ONLY);
259 #ifdef JP
260     msg_format("$%dで%sに修復しました。", cost, basenm);
261 #else
262     msg_format("Repaired into %s for %d gold.", basenm, cost);
263 #endif
264     msg_print(NULL);
265     o_ptr->ident &= ~(IDENT_BROKEN);
266     o_ptr->discount = 99;
267
268     player_ptr->total_weight += o_ptr->weight;
269     calc_android_exp(player_ptr);
270     inven_item_increase(player_ptr, mater, -1);
271     inven_item_optimize(player_ptr, mater);
272
273     player_ptr->update |= PU_BONUS;
274     handle_stuff(player_ptr);
275     return (cost);
276 }
277
278 /*!
279  * @brief アイテム修復処理の過渡ルーチン / Repair broken weapon
280  * @param player_ptr プレーヤーへの参照ポインタ
281  * @param bcost 基本鑑定費用
282  * @return 実際にかかった費用
283  */
284 int repair_broken_weapon(player_type *player_ptr, PRICE bcost)
285 {
286     PRICE cost;
287     screen_save();
288     cost = repair_broken_weapon_aux(player_ptr, bcost);
289     screen_load();
290     return cost;
291 }