OSDN Git Service

86051642dc1263609b9298e012090f965ce8068c
[hengbandforosx/hengbandosx.git] / src / mind / mind-mage.c
1 /*!
2  * @brief 魔力喰い処理
3  * @date 2020/06/27
4  * @author Hourier
5  */
6
7 #include "mind/mind-mage.h"
8 #include "core/stuff-handler.h"
9 #include "flavor/flavor-describer.h"
10 #include "flavor/object-flavor-types.h"
11 #include "floor/floor-object.h"
12 #include "inventory/inventory-object.h"
13 #include "object-enchant/special-object-flags.h"
14 #include "object-hook/hook-enchant.h"
15 #include "object-hook/hook-magic.h"
16 #include "object/item-tester-hooker.h"
17 #include "object/item-use-flags.h"
18 #include "object/object-generator.h"
19 #include "object/object-kind.h"
20 #include "player/player-realm.h"
21 #include "system/object-type-definition.h"
22 #include "view/display-messages.h"
23
24 /*!
25  * @brief 魔力食い処理
26  * @param caster_ptr プレーヤーへの参照ポインタ
27  * @param power 基本効力
28  * @return ターンを消費した場合TRUEを返す
29  */
30 bool eat_magic(player_type *caster_ptr, int power)
31 {
32     byte fail_type = 1;
33     GAME_TEXT o_name[MAX_NLEN];
34
35     item_tester_hook = item_tester_hook_recharge;
36
37     concptr q = _("どのアイテムから魔力を吸収しますか?", "Drain which item? ");
38     concptr s = _("魔力を吸収できるアイテムがありません。", "You have nothing to drain.");
39
40     object_type *o_ptr;
41     OBJECT_IDX item;
42     o_ptr = choose_object(caster_ptr, &item, q, s, (USE_INVEN | USE_FLOOR), 0);
43     if (!o_ptr)
44         return FALSE;
45
46     object_kind *k_ptr;
47     k_ptr = &k_info[o_ptr->k_idx];
48     DEPTH lev = k_info[o_ptr->k_idx].level;
49
50     int recharge_strength = 0;
51     bool is_eating_successful = TRUE;
52     if (o_ptr->tval == TV_ROD) {
53         recharge_strength = ((power > lev / 2) ? (power - lev / 2) : 0) / 5;
54         if (one_in_(recharge_strength)) {
55             is_eating_successful = FALSE;
56         } else {
57             if (o_ptr->timeout > (o_ptr->number - 1) * k_ptr->pval) {
58                 msg_print(_("充填中のロッドから魔力を吸収することはできません。", "You can't absorb energy from a discharged rod."));
59             } else {
60                 caster_ptr->csp += lev;
61                 o_ptr->timeout += k_ptr->pval;
62             }
63         }
64     } else {
65         recharge_strength = (100 + power - lev) / 15;
66         if (recharge_strength < 0)
67             recharge_strength = 0;
68
69         if (one_in_(recharge_strength)) {
70             is_eating_successful = FALSE;
71         } else {
72             if (o_ptr->pval > 0) {
73                 caster_ptr->csp += lev / 2;
74                 o_ptr->pval--;
75
76                 if ((o_ptr->tval == TV_STAFF) && (item >= 0) && (o_ptr->number > 1)) {
77                     object_type forge;
78                     object_type *q_ptr;
79                     q_ptr = &forge;
80                     object_copy(q_ptr, o_ptr);
81
82                     q_ptr->number = 1;
83                     o_ptr->pval++;
84                     o_ptr->number--;
85                     item = store_item_to_inventory(caster_ptr, q_ptr);
86
87                     msg_print(_("杖をまとめなおした。", "You unstack your staff."));
88                 }
89             } else {
90                 msg_print(_("吸収できる魔力がありません!", "There's no energy there to absorb!"));
91             }
92
93             if (!o_ptr->pval)
94                 o_ptr->ident |= IDENT_EMPTY;
95         }
96     }
97
98     if (is_eating_successful) {
99         return redraw_player(caster_ptr);
100     }
101
102     if (object_is_fixed_artifact(o_ptr)) {
103         describe_flavor(caster_ptr, o_name, o_ptr, OD_NAME_ONLY);
104         msg_format(_("魔力が逆流した!%sは完全に魔力を失った。", "The recharging backfires - %s is completely drained!"), o_name);
105         if (o_ptr->tval == TV_ROD)
106             o_ptr->timeout = k_ptr->pval * o_ptr->number;
107         else if ((o_ptr->tval == TV_WAND) || (o_ptr->tval == TV_STAFF))
108             o_ptr->pval = 0;
109
110         return redraw_player(caster_ptr);
111     }
112
113     describe_flavor(caster_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
114
115     /* Mages recharge objects more safely. */
116     if (is_wizard_class(caster_ptr)) {
117         /* 10% chance to blow up one rod, otherwise draining. */
118         if (o_ptr->tval == TV_ROD) {
119             if (one_in_(10))
120                 fail_type = 2;
121             else
122                 fail_type = 1;
123         }
124         /* 75% chance to blow up one wand, otherwise draining. */
125         else if (o_ptr->tval == TV_WAND) {
126             if (!one_in_(3))
127                 fail_type = 2;
128             else
129                 fail_type = 1;
130         }
131         /* 50% chance to blow up one staff, otherwise no effect. */
132         else if (o_ptr->tval == TV_STAFF) {
133             if (one_in_(2))
134                 fail_type = 2;
135             else
136                 fail_type = 0;
137         }
138     }
139
140     /* All other classes get no special favors. */
141     else {
142         /* 33% chance to blow up one rod, otherwise draining. */
143         if (o_ptr->tval == TV_ROD) {
144             if (one_in_(3))
145                 fail_type = 2;
146             else
147                 fail_type = 1;
148         }
149         /* 20% chance of the entire stack, else destroy one wand. */
150         else if (o_ptr->tval == TV_WAND) {
151             if (one_in_(5))
152                 fail_type = 3;
153             else
154                 fail_type = 2;
155         }
156         /* Blow up one staff. */
157         else if (o_ptr->tval == TV_STAFF) {
158             fail_type = 2;
159         }
160     }
161
162     if (fail_type == 1) {
163         if (o_ptr->tval == TV_ROD) {
164             msg_format(_("ロッドは破損を免れたが、魔力は全て失なわれた。", "You save your rod from destruction, but all charges are lost."), o_name);
165             o_ptr->timeout = k_ptr->pval * o_ptr->number;
166         } else if (o_ptr->tval == TV_WAND) {
167             msg_format(_("%sは破損を免れたが、魔力が全て失われた。", "You save your %s from destruction, but all charges are lost."), o_name);
168             o_ptr->pval = 0;
169         }
170     }
171
172     if (fail_type == 2) {
173         if (o_ptr->number > 1) {
174             msg_format(_("乱暴な魔法のために%sが一本壊れた!", "Wild magic consumes one of your %s!"), o_name);
175             /* Reduce rod stack maximum timeout, drain wands. */
176             if (o_ptr->tval == TV_ROD)
177                 o_ptr->timeout = MIN(o_ptr->timeout, k_ptr->pval * (o_ptr->number - 1));
178             else if (o_ptr->tval == TV_WAND)
179                 o_ptr->pval = o_ptr->pval * (o_ptr->number - 1) / o_ptr->number;
180         } else {
181             msg_format(_("乱暴な魔法のために%sが何本か壊れた!", "Wild magic consumes your %s!"), o_name);
182         }
183
184         vary_item(caster_ptr, item, -1);
185     }
186
187     if (fail_type == 3) {
188         if (o_ptr->number > 1)
189             msg_format(_("乱暴な魔法のために%sが全て壊れた!", "Wild magic consumes all your %s!"), o_name);
190         else
191             msg_format(_("乱暴な魔法のために%sが壊れた!", "Wild magic consumes your %s!"), o_name);
192
193         vary_item(caster_ptr, item, -999);
194     }
195
196     return redraw_player(caster_ptr);
197 }