OSDN Git Service

[fix] #41503 超能力者でゲームを開始しようとするとクラッシュ
[hengband/hengband.git] / src / object-enchant / apply-magic-weapon.c
1 /*!
2  * todo ちょっと長い。要分割
3  * @brief 武器系のアイテムを強化して(恐らく床に)生成する処理
4  * @date 2020/06/02
5  * @author Hourier
6  */
7
8 #include "object-enchant/apply-magic-weapon.h"
9 #include "artifact/random-art-generator.h"
10 #include "inventory/inventory-slot-types.h"
11 #include "object-enchant/object-boost.h"
12 #include "object-enchant/object-ego.h"
13 #include "object-enchant/tr-types.h"
14 #include "object-enchant/trc-types.h"
15 #include "sv-definition/sv-weapon-types.h"
16 #include "system/floor-type-definition.h"
17 #include "util/bit-flags-calculator.h"
18
19 /*!
20  * @brief 武器系オブジェクトに生成ランクごとの強化を与えるサブルーチン
21  * Apply magic to an item known to be a "weapon"
22  * @param owner_ptr プレーヤーへの参照ポインタ
23  * @param o_ptr 強化を与えたいオブジェクトの構造体参照ポインタ
24  * @param level 生成基準階
25  * @param power 生成ランク
26  * @return なし
27  * @details
28  * Hack -- note special base damage dice boosting\n
29  * Hack -- note special processing for weapon/digger\n
30  */
31 void apply_magic_weapon(player_type *owner_ptr, object_type *o_ptr, DEPTH level, int power)
32 {
33     HIT_PROB tohit1 = randint1(5) + (HIT_PROB)m_bonus(5, level);
34     HIT_POINT todam1 = randint1(5) + (HIT_POINT)m_bonus(5, level);
35
36     HIT_PROB tohit2 = (HIT_PROB)m_bonus(10, level);
37     HIT_POINT todam2 = (HIT_POINT)m_bonus(10, level);
38
39     if ((o_ptr->tval == TV_BOLT) || (o_ptr->tval == TV_ARROW) || (o_ptr->tval == TV_SHOT)) {
40         tohit2 = (tohit2 + 1) / 2;
41         todam2 = (todam2 + 1) / 2;
42     }
43
44     if (power > 0) {
45         o_ptr->to_h += tohit1;
46         o_ptr->to_d += todam1;
47         if (power > 1) {
48             o_ptr->to_h += tohit2;
49             o_ptr->to_d += todam2;
50         }
51     } else if (power < 0) {
52         o_ptr->to_h -= tohit1;
53         o_ptr->to_d -= todam1;
54         if (power < -1) {
55             o_ptr->to_h -= tohit2;
56             o_ptr->to_d -= todam2;
57         }
58
59         if (o_ptr->to_h + o_ptr->to_d < 0)
60             o_ptr->curse_flags |= TRC_CURSED;
61     }
62
63     if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_DIAMOND_EDGE))
64         return;
65
66     switch (o_ptr->tval) {
67     case TV_DIGGING: {
68         if (power > 1) {
69             /* power > 2 is debug only */
70             if (one_in_(30) || (power > 2))
71                 become_random_artifact(owner_ptr, o_ptr, FALSE);
72             else
73                 o_ptr->name2 = EGO_DIGGING;
74         } else if (power < -1) {
75             o_ptr->pval = 0 - (5 + randint1(5));
76         } else if (power < 0) {
77             o_ptr->pval = 0 - (o_ptr->pval);
78         }
79
80         break;
81     }
82     case TV_HAFTED:
83     case TV_POLEARM:
84     case TV_SWORD: {
85         if (power > 1) {
86             /* power > 2 is debug only */
87             if (one_in_(40) || (power > 2)) {
88                 become_random_artifact(owner_ptr, o_ptr, FALSE);
89                 break;
90             }
91             while (TRUE) {
92                 o_ptr->name2 = get_random_ego(INVEN_MAIN_HAND, TRUE);
93                 if (o_ptr->name2 == EGO_SHARPNESS && o_ptr->tval != TV_SWORD)
94                     continue;
95                 if (o_ptr->name2 == EGO_EARTHQUAKES && o_ptr->tval != TV_HAFTED)
96                     continue;
97                 if (o_ptr->name2 == EGO_WEIRD && o_ptr->tval != TV_SWORD)
98                     continue;
99                 break;
100             }
101
102             switch (o_ptr->name2) {
103             case EGO_HA:
104                 if (one_in_(4) && (level > 40))
105                     add_flag(o_ptr->art_flags, TR_BLOWS);
106                 break;
107             case EGO_DF:
108                 if (one_in_(3))
109                     add_flag(o_ptr->art_flags, TR_RES_POIS);
110                 if (one_in_(3))
111                     add_flag(o_ptr->art_flags, TR_WARNING);
112                 break;
113             case EGO_KILL_DRAGON:
114                 if (one_in_(3))
115                     add_flag(o_ptr->art_flags, TR_RES_POIS);
116                 break;
117             case EGO_WEST:
118                 if (one_in_(3))
119                     add_flag(o_ptr->art_flags, TR_RES_FEAR);
120                 break;
121             case EGO_SLAYING_WEAPON:
122                 if (one_in_(3))
123                     o_ptr->dd *= 2;
124                 else {
125                     do {
126                         o_ptr->dd++;
127                     } while (one_in_(o_ptr->dd));
128
129                     do {
130                         o_ptr->ds++;
131                     } while (one_in_(o_ptr->ds));
132                 }
133
134                 if (one_in_(5)) {
135                     add_flag(o_ptr->art_flags, TR_BRAND_POIS);
136                 }
137                 if (o_ptr->tval == TV_SWORD && one_in_(3)) {
138                     add_flag(o_ptr->art_flags, TR_VORPAL);
139                 }
140                 break;
141             case EGO_TRUMP:
142                 if (one_in_(5))
143                     add_flag(o_ptr->art_flags, TR_SLAY_DEMON);
144                 if (one_in_(7))
145                     one_ability(o_ptr);
146                 break;
147             case EGO_PATTERN:
148                 if (one_in_(3))
149                     add_flag(o_ptr->art_flags, TR_HOLD_EXP);
150                 if (one_in_(3))
151                     add_flag(o_ptr->art_flags, TR_DEX);
152                 if (one_in_(5))
153                     add_flag(o_ptr->art_flags, TR_RES_FEAR);
154                 break;
155             case EGO_SHARPNESS:
156                 o_ptr->pval = (PARAMETER_VALUE)m_bonus(5, level) + 1;
157                 break;
158             case EGO_EARTHQUAKES:
159                 if (one_in_(3) && (level > 60))
160                     add_flag(o_ptr->art_flags, TR_BLOWS);
161                 else
162                     o_ptr->pval = (PARAMETER_VALUE)m_bonus(3, level);
163                 break;
164             case EGO_VAMPIRIC:
165                 if (one_in_(5))
166                     add_flag(o_ptr->art_flags, TR_SLAY_HUMAN);
167                 break;
168             case EGO_DEMON:
169
170                 if (one_in_(3))
171                     o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
172                 one_in_(3) ? add_flag(o_ptr->art_flags, TR_DRAIN_EXP)
173                            : one_in_(2) ? add_flag(o_ptr->art_flags, TR_DRAIN_HP) : add_flag(o_ptr->art_flags, TR_DRAIN_MANA);
174
175                 if (one_in_(3))
176                     add_flag(o_ptr->art_flags, TR_CHAOTIC);
177                 if (one_in_(4))
178                     add_flag(o_ptr->art_flags, TR_BLOWS);
179                 if (one_in_(5))
180                     add_flag(o_ptr->art_flags, TR_ADD_H_CURSE);
181                 if (one_in_(5))
182                     add_flag(o_ptr->art_flags, TR_CALL_DEMON);
183                 break;
184             }
185
186             if (!o_ptr->art_name) {
187                 while (one_in_(10L * o_ptr->dd * o_ptr->ds))
188                     o_ptr->dd++;
189
190                 if (o_ptr->dd > 9)
191                     o_ptr->dd = 9;
192             }
193         } else if (power < -1) {
194             if (randint0(MAX_DEPTH) < level) {
195                 while (TRUE) {
196                     o_ptr->name2 = get_random_ego(INVEN_MAIN_HAND, FALSE);
197                     if (o_ptr->name2 == EGO_WEIRD && o_ptr->tval != TV_SWORD) {
198                         continue;
199                     }
200
201                     break;
202                 }
203
204                 switch (o_ptr->name2) {
205                 case EGO_MORGUL:
206                     if (one_in_(6))
207                         add_flag(o_ptr->art_flags, TR_TY_CURSE);
208                     if (one_in_(3))
209                         o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
210                     break;
211                 }
212             }
213         }
214
215         break;
216     }
217     case TV_BOW: {
218         if (power > 1) {
219             /* power > 2 is debug only */
220             if (one_in_(20) || (power > 2)) {
221                 become_random_artifact(owner_ptr, o_ptr, FALSE);
222                 break;
223             }
224
225             o_ptr->name2 = get_random_ego(INVEN_BOW, TRUE);
226         }
227
228         break;
229     }
230     case TV_BOLT:
231     case TV_ARROW:
232     case TV_SHOT: {
233         if (power > 1) {
234             /* power > 2 is debug only */
235             if (power > 2) {
236                 become_random_artifact(owner_ptr, o_ptr, FALSE);
237                 break;
238             }
239
240             o_ptr->name2 = get_random_ego(INVEN_AMMO, TRUE);
241             switch (o_ptr->name2) {
242             case EGO_SLAYING_BOLT:
243                 o_ptr->dd++;
244                 break;
245             }
246
247             while (one_in_(10L * o_ptr->dd * o_ptr->ds))
248                 o_ptr->dd++;
249
250             if (o_ptr->dd > 9)
251                 o_ptr->dd = 9;
252         } else if (power < -1) {
253             if (randint0(MAX_DEPTH) < level) {
254                 o_ptr->name2 = get_random_ego(INVEN_AMMO, FALSE);
255             }
256         }
257
258         break;
259     }
260     }
261 }