OSDN Git Service

Merge pull request #2050 from daradarach/feature/refactoring
[hengbandforosx/hengbandosx.git] / src / object-enchant / others / apply-magic-others.cpp
1 /*!
2  * @brief 防具系のアイテムを強化して(恐らく床に)生成する処理
3  * @date 2020/06/02
4  * @author Hourier
5  * @todo ちょっと長い。要分割
6  */
7
8 #include "object-enchant/others/apply-magic-others.h"
9 #include "artifact/random-art-generator.h"
10 #include "game-option/cheat-options.h"
11 #include "inventory/inventory-slot-types.h"
12 #include "monster-race/monster-race-hook.h"
13 #include "monster-race/monster-race.h"
14 #include "monster-race/race-flags9.h"
15 #include "monster-race/race-indice-types.h"
16 #include "monster/monster-list.h"
17 #include "monster/monster-util.h"
18 #include "object-enchant/object-ego.h"
19 #include "object-enchant/tr-types.h"
20 #include "object-enchant/trc-types.h"
21 #include "object/object-kind.h"
22 #include "perception/object-perception.h"
23 #include "sv-definition/sv-lite-types.h"
24 #include "sv-definition/sv-other-types.h"
25 #include "system/floor-type-definition.h"
26 #include "system/monster-race-definition.h"
27 #include "system/object-type-definition.h"
28 #include "system/player-type-definition.h"
29 #include "util/bit-flags-calculator.h"
30 #include "view/display-messages.h"
31
32 /*!
33  * @brief その他雑多のオブジェクトに生成ランクごとの強化を与えるサブルーチン
34  * Apply magic to an item known to be "boring"
35  * @param player_ptr プレイヤーへの参照ポインタ
36  * @param o_ptr 強化を与えたいオブジェクトの構造体参照ポインタ
37  * @param power 生成ランク
38  * @details
39  * Hack -- note the special code for various items
40  */
41 void apply_magic_others(PlayerType *player_ptr, object_type *o_ptr, int power)
42 {
43     object_kind *k_ptr = &k_info[o_ptr->k_idx];
44
45     floor_type *floor_ptr = player_ptr->current_floor_ptr;
46     switch (o_ptr->tval) {
47     case ItemKindType::WHISTLE: {
48         break;
49     }
50     case ItemKindType::FLASK: {
51         o_ptr->xtra4 = o_ptr->pval;
52         o_ptr->pval = 0;
53         break;
54     }
55     case ItemKindType::LITE: {
56         if (o_ptr->sval == SV_LITE_TORCH) {
57             if (o_ptr->pval > 0)
58                 o_ptr->xtra4 = randint1(o_ptr->pval);
59             o_ptr->pval = 0;
60         }
61
62         if (o_ptr->sval == SV_LITE_LANTERN) {
63             if (o_ptr->pval > 0)
64                 o_ptr->xtra4 = randint1(o_ptr->pval);
65             o_ptr->pval = 0;
66         }
67
68         /* power > 2はデバッグ専用. */
69         if (power > 2) {
70             become_random_artifact(player_ptr, o_ptr, false);
71         } else if ((power == 2) || ((power == 1) && one_in_(3))) {
72             while (!o_ptr->name2) {
73                 while (true) {
74                     bool okay_flag = true;
75
76                     o_ptr->name2 = get_random_ego(INVEN_LITE, true);
77
78                     switch (o_ptr->name2) {
79                     case EGO_LITE_LONG:
80                         if (o_ptr->sval == SV_LITE_FEANOR)
81                             okay_flag = false;
82                     }
83
84                     if (okay_flag)
85                         break;
86                 }
87             }
88         } else if (power == -2) {
89             o_ptr->name2 = get_random_ego(INVEN_LITE, false);
90             switch (o_ptr->name2) {
91             case EGO_LITE_DARKNESS:
92                 o_ptr->xtra4 = 0;
93
94                 if (o_ptr->sval == SV_LITE_TORCH) {
95                     o_ptr->art_flags.set(TR_LITE_M1);
96                 } else if (o_ptr->sval == SV_LITE_LANTERN) {
97                     o_ptr->art_flags.set(TR_LITE_M2);
98                 } else if (o_ptr->sval == SV_LITE_FEANOR) {
99                     o_ptr->art_flags.set(TR_LITE_M3);
100                 }
101                 break;
102             }
103         }
104
105         break;
106     }
107     case ItemKindType::WAND:
108     case ItemKindType::STAFF: {
109         /* The wand or staff gets a number of initial charges equal
110          * to between 1/2 (+1) and the full object kind's pval. -LM-
111          */
112         o_ptr->pval = k_ptr->pval / 2 + randint1((k_ptr->pval + 1) / 2);
113         break;
114     }
115     case ItemKindType::ROD: {
116         o_ptr->pval = k_ptr->pval;
117         break;
118     }
119     case ItemKindType::CAPTURE: {
120         o_ptr->pval = 0;
121         object_aware(player_ptr, o_ptr);
122         object_known(o_ptr);
123         break;
124     }
125     case ItemKindType::FIGURINE: {
126         PARAMETER_VALUE i = 1;
127         int check;
128         monster_race *r_ptr;
129         while (true) {
130             i = randint1(r_info.size() - 1);
131
132             if (!item_monster_okay(player_ptr, i))
133                 continue;
134             if (i == MON_TSUCHINOKO)
135                 continue;
136
137             r_ptr = &r_info[i];
138             check = (floor_ptr->dun_level < r_ptr->level) ? (r_ptr->level - floor_ptr->dun_level) : 0;
139             if (!r_ptr->rarity)
140                 continue;
141             if (r_ptr->rarity > 100)
142                 continue;
143             if (randint0(check))
144                 continue;
145
146             break;
147         }
148
149         o_ptr->pval = i;
150         if (one_in_(6))
151             o_ptr->curse_flags.set(CurseTraitType::CURSED);
152
153         break;
154     }
155     case ItemKindType::CORPSE: {
156         PARAMETER_VALUE i = 1;
157         int check;
158         uint32_t match = 0;
159         monster_race *r_ptr;
160         if (o_ptr->sval == SV_SKELETON) {
161             match = RF9_DROP_SKELETON;
162         } else if (o_ptr->sval == SV_CORPSE) {
163             match = RF9_DROP_CORPSE;
164         }
165
166         get_mon_num_prep(player_ptr, item_monster_okay, nullptr);
167         while (true) {
168             i = get_mon_num(player_ptr, 0, floor_ptr->dun_level, 0);
169             r_ptr = &r_info[i];
170             check = (floor_ptr->dun_level < r_ptr->level) ? (r_ptr->level - floor_ptr->dun_level) : 0;
171             if (!r_ptr->rarity)
172                 continue;
173             if (!(r_ptr->flags9 & match))
174                 continue;
175             if (randint0(check))
176                 continue;
177
178             break;
179         }
180
181         o_ptr->pval = i;
182         object_aware(player_ptr, o_ptr);
183         object_known(o_ptr);
184         break;
185     }
186     case ItemKindType::STATUE: {
187         PARAMETER_VALUE i = 1;
188         monster_race *r_ptr;
189         while (true) {
190             i = randint1(r_info.size() - 1);
191             r_ptr = &r_info[i];
192             if (!r_ptr->rarity)
193                 continue;
194
195             break;
196         }
197
198         o_ptr->pval = i;
199         if (cheat_peek) {
200             msg_format(_("%sの像", "Statue of %s"), r_ptr->name.c_str());
201         }
202
203         object_aware(player_ptr, o_ptr);
204         object_known(o_ptr);
205         break;
206     }
207     case ItemKindType::CHEST: {
208         DEPTH obj_level = k_info[o_ptr->k_idx].level;
209         if (obj_level <= 0)
210             break;
211
212         o_ptr->pval = randint1(obj_level);
213         if (o_ptr->sval == SV_CHEST_KANDUME)
214             o_ptr->pval = 6;
215
216         o_ptr->xtra3 = floor_ptr->dun_level + 5;
217         if (o_ptr->pval > 55)
218             o_ptr->pval = 55 + (byte)randint0(5);
219
220         break;
221     }
222
223     default:
224         break;
225     }
226 }