OSDN Git Service

[Refactor] #40653 Separated mind-archer.c/h from spells-object.c/h
[hengband/hengband.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                     caster_ptr->total_weight -= q_ptr->weight;
86                     item = store_item_to_inventory(caster_ptr, q_ptr);
87
88                     msg_print(_("杖をまとめなおした。", "You unstack your staff."));
89                 }
90             } else {
91                 msg_print(_("吸収できる魔力がありません!", "There's no energy there to absorb!"));
92             }
93
94             if (!o_ptr->pval)
95                 o_ptr->ident |= IDENT_EMPTY;
96         }
97     }
98
99     if (is_eating_successful) {
100         return redraw_player(caster_ptr);
101     }
102
103     if (object_is_fixed_artifact(o_ptr)) {
104         describe_flavor(caster_ptr, o_name, o_ptr, OD_NAME_ONLY);
105         msg_format(_("魔力が逆流した!%sは完全に魔力を失った。", "The recharging backfires - %s is completely drained!"), o_name);
106         if (o_ptr->tval == TV_ROD)
107             o_ptr->timeout = k_ptr->pval * o_ptr->number;
108         else if ((o_ptr->tval == TV_WAND) || (o_ptr->tval == TV_STAFF))
109             o_ptr->pval = 0;
110
111         return redraw_player(caster_ptr);
112     }
113
114     describe_flavor(caster_ptr, o_name, o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
115
116     /* Mages recharge objects more safely. */
117     if (is_wizard_class(caster_ptr)) {
118         /* 10% chance to blow up one rod, otherwise draining. */
119         if (o_ptr->tval == TV_ROD) {
120             if (one_in_(10))
121                 fail_type = 2;
122             else
123                 fail_type = 1;
124         }
125         /* 75% chance to blow up one wand, otherwise draining. */
126         else if (o_ptr->tval == TV_WAND) {
127             if (!one_in_(3))
128                 fail_type = 2;
129             else
130                 fail_type = 1;
131         }
132         /* 50% chance to blow up one staff, otherwise no effect. */
133         else if (o_ptr->tval == TV_STAFF) {
134             if (one_in_(2))
135                 fail_type = 2;
136             else
137                 fail_type = 0;
138         }
139     }
140
141     /* All other classes get no special favors. */
142     else {
143         /* 33% chance to blow up one rod, otherwise draining. */
144         if (o_ptr->tval == TV_ROD) {
145             if (one_in_(3))
146                 fail_type = 2;
147             else
148                 fail_type = 1;
149         }
150         /* 20% chance of the entire stack, else destroy one wand. */
151         else if (o_ptr->tval == TV_WAND) {
152             if (one_in_(5))
153                 fail_type = 3;
154             else
155                 fail_type = 2;
156         }
157         /* Blow up one staff. */
158         else if (o_ptr->tval == TV_STAFF) {
159             fail_type = 2;
160         }
161     }
162
163     if (fail_type == 1) {
164         if (o_ptr->tval == TV_ROD) {
165             msg_format(_("ロッドは破損を免れたが、魔力は全て失なわれた。", "You save your rod from destruction, but all charges are lost."), o_name);
166             o_ptr->timeout = k_ptr->pval * o_ptr->number;
167         } else if (o_ptr->tval == TV_WAND) {
168             msg_format(_("%sは破損を免れたが、魔力が全て失われた。", "You save your %s from destruction, but all charges are lost."), o_name);
169             o_ptr->pval = 0;
170         }
171     }
172
173     if (fail_type == 2) {
174         if (o_ptr->number > 1) {
175             msg_format(_("乱暴な魔法のために%sが一本壊れた!", "Wild magic consumes one of your %s!"), o_name);
176             /* Reduce rod stack maximum timeout, drain wands. */
177             if (o_ptr->tval == TV_ROD)
178                 o_ptr->timeout = MIN(o_ptr->timeout, k_ptr->pval * (o_ptr->number - 1));
179             else if (o_ptr->tval == TV_WAND)
180                 o_ptr->pval = o_ptr->pval * (o_ptr->number - 1) / o_ptr->number;
181         } else {
182             msg_format(_("乱暴な魔法のために%sが何本か壊れた!", "Wild magic consumes your %s!"), o_name);
183         }
184
185         vary_item(caster_ptr, item, -1);
186     }
187
188     if (fail_type == 3) {
189         if (o_ptr->number > 1)
190             msg_format(_("乱暴な魔法のために%sが全て壊れた!", "Wild magic consumes all your %s!"), o_name);
191         else
192             msg_format(_("乱暴な魔法のために%sが壊れた!", "Wild magic consumes your %s!"), o_name);
193
194         vary_item(caster_ptr, item, -999);
195     }
196
197     return redraw_player(caster_ptr);
198 }