OSDN Git Service

Merge pull request #765 from sikabane-works/release/3.0.0Alpha17
[hengbandforosx/hengbandosx.git] / src / object-enchant / apply-magic-weapon.cpp
1 /*!
2  * @brief 武器系のアイテムを強化して(恐らく床に)生成する処理
3  * @date 2020/06/02
4  * @author Hourier
5  * @todo ちょっと長い。要分割
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_SLAYING_WEAPON:
104                 if (one_in_(3))
105                     o_ptr->dd *= 2;
106                 else {
107                     do {
108                         o_ptr->dd++;
109                     } while (one_in_(o_ptr->dd));
110
111                     do {
112                         o_ptr->ds++;
113                     } while (one_in_(o_ptr->ds));
114                 }
115                 break;
116             case EGO_SHARPNESS:
117                 o_ptr->pval = (PARAMETER_VALUE)m_bonus(5, level) + 1;
118                 break;
119             case EGO_EARTHQUAKES:
120                 if (one_in_(3) && (level > 60))
121                     add_flag(o_ptr->art_flags, TR_BLOWS);
122                 else
123                     o_ptr->pval = (PARAMETER_VALUE)m_bonus(3, level);
124                 break;
125             default:
126                 break;
127             }
128
129             if (!o_ptr->art_name) {
130                 while (one_in_(10L * o_ptr->dd * o_ptr->ds))
131                     o_ptr->dd++;
132
133                 if (o_ptr->dd > 9)
134                     o_ptr->dd = 9;
135             }
136         } else if (power < -1) {
137             if (randint0(MAX_DEPTH) < level) {
138                 while (TRUE) {
139                     o_ptr->name2 = get_random_ego(INVEN_MAIN_HAND, FALSE);
140                     if (o_ptr->name2 == EGO_WEIRD && o_ptr->tval != TV_SWORD) {
141                         continue;
142                     }
143
144                     break;
145                 }
146             }
147         }
148
149         break;
150     }
151     case TV_BOW: {
152         if (power > 1) {
153             /* power > 2 is debug only */
154             if (one_in_(20) || (power > 2)) {
155                 become_random_artifact(owner_ptr, o_ptr, FALSE);
156                 break;
157             }
158
159             o_ptr->name2 = get_random_ego(INVEN_BOW, TRUE);
160         }
161
162         break;
163     }
164     case TV_BOLT:
165     case TV_ARROW:
166     case TV_SHOT: {
167         if (power > 1) {
168             /* power > 2 is debug only */
169             if (power > 2) {
170                 become_random_artifact(owner_ptr, o_ptr, FALSE);
171                 break;
172             }
173
174             o_ptr->name2 = get_random_ego(INVEN_AMMO, TRUE);
175             switch (o_ptr->name2) {
176             case EGO_SLAYING_BOLT:
177                 o_ptr->dd++;
178                 break;
179             }
180
181             while (one_in_(10L * o_ptr->dd * o_ptr->ds))
182                 o_ptr->dd++;
183
184             if (o_ptr->dd > 9)
185                 o_ptr->dd = 9;
186         } else if (power < -1) {
187             if (randint0(MAX_DEPTH) < level) {
188                 o_ptr->name2 = get_random_ego(INVEN_AMMO, FALSE);
189             }
190         }
191
192         break;
193     }
194
195     default:
196         break;
197     }
198 }