OSDN Git Service

Merge remote-tracking branch 'remotes/origin/feature/Fix-saved-floor-exceed' into...
[hengband/hengband.git] / src / object-enchant / apply-magic-armor.c
1 /*!
2  * todo ちょっと長い。要分割
3  * @brief 防具系のアイテムを強化して(恐らく床に)生成する処理
4  * @date 2020/06/02
5  * @author Hourier
6  */
7
8 #include "object-enchant/apply-magic-armor.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/object-kind-hook.h"
14 #include "object/object-kind.h"
15 #include "object-enchant/tr-types.h"
16 #include "object-enchant/trc-types.h"
17 #include "sv-definition/sv-armor-types.h"
18 #include "sv-definition/sv-protector-types.h"
19 #include "util/bit-flags-calculator.h"
20
21 /*!
22  * @brief 防具系オブジェクトに生成ランクごとの強化を与えるサブルーチン
23  * Apply magic to an item known to be "armor"
24  * @param owner_ptr プレーヤーへの参照ポインタ
25  * @param o_ptr 強化を与えたいオブジェクトの構造体参照ポインタ
26  * @param level 生成基準階
27  * @param power 生成ランク
28  * @return なし
29  * @details
30  * Hack -- note special processing for crown/helm\n
31  * Hack -- note special processing for robe of permanence\n
32  */
33 void apply_magic_armor(player_type *owner_ptr, object_type *o_ptr, DEPTH level, int power)
34 {
35     ARMOUR_CLASS toac1 = (ARMOUR_CLASS)randint1(5) + m_bonus(5, level);
36     ARMOUR_CLASS toac2 = (ARMOUR_CLASS)m_bonus(10, level);
37     if (power > 0) {
38         o_ptr->to_a += toac1;
39         if (power > 1) {
40             o_ptr->to_a += toac2;
41         }
42     } else if (power < 0) {
43         o_ptr->to_a -= toac1;
44         if (power < -1) {
45             o_ptr->to_a -= toac2;
46         }
47
48         if (o_ptr->to_a < 0)
49             o_ptr->curse_flags |= TRC_CURSED;
50     }
51
52     switch (o_ptr->tval) {
53     case TV_DRAG_ARMOR: {
54         /* power > 2 is debug only */
55         if (one_in_(50) || (power > 2))
56             become_random_artifact(owner_ptr, o_ptr, FALSE);
57         break;
58     }
59     case TV_HARD_ARMOR:
60     case TV_SOFT_ARMOR: {
61         if (power > 1) {
62             if ((o_ptr->tval == TV_SOFT_ARMOR) && (o_ptr->sval == SV_ROBE) && (randint0(100) < 15)) {
63                 if (one_in_(5)) {
64                     o_ptr->name2 = EGO_YOIYAMI;
65                     o_ptr->k_idx = lookup_kind(TV_SOFT_ARMOR, SV_YOIYAMI_ROBE);
66                     o_ptr->sval = SV_YOIYAMI_ROBE;
67                     o_ptr->ac = 0;
68                     o_ptr->to_a = 0;
69                 } else {
70                     o_ptr->name2 = EGO_PERMANENCE;
71                 }
72
73                 break;
74             }
75
76             /* power > 2 is debug only */
77             if (one_in_(20) || (power > 2)) {
78                 become_random_artifact(owner_ptr, o_ptr, FALSE);
79                 break;
80             }
81
82             while (TRUE) {
83                 bool okay_flag = TRUE;
84                 o_ptr->name2 = get_random_ego(INVEN_BODY, TRUE);
85                 switch (o_ptr->name2) {
86                 case EGO_DWARVEN:
87                     if (o_ptr->tval != TV_HARD_ARMOR) {
88                         okay_flag = FALSE;
89                     }
90
91                     break;
92                 case EGO_DRUID:
93                     if (o_ptr->tval != TV_SOFT_ARMOR) {
94                         okay_flag = FALSE;
95                     }
96
97                     break;
98                 default:
99                     break;
100                 }
101
102                 if (okay_flag)
103                     break;
104             }
105
106             switch (o_ptr->name2) {
107             case EGO_RESISTANCE:
108                 if (one_in_(4))
109                     add_flag(o_ptr->art_flags, TR_RES_POIS);
110                 break;
111             case EGO_DWARVEN:
112                 o_ptr->weight = (2 * k_info[o_ptr->k_idx].weight / 3);
113                 o_ptr->ac = k_info[o_ptr->k_idx].ac + 5;
114                 break;
115
116             case EGO_A_DEMON:
117                 if (one_in_(3))
118                     o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
119                 one_in_(3) ? add_flag(o_ptr->art_flags, TR_DRAIN_EXP)
120                            : one_in_(2) ? add_flag(o_ptr->art_flags, TR_DRAIN_HP) : add_flag(o_ptr->art_flags, TR_DRAIN_MANA);
121
122                 if (one_in_(3))
123                     add_flag(o_ptr->art_flags, TR_AGGRAVATE);
124                 if (one_in_(3))
125                     add_flag(o_ptr->art_flags, TR_ADD_L_CURSE);
126                 if (one_in_(5))
127                     add_flag(o_ptr->art_flags, TR_ADD_H_CURSE);
128                 if (one_in_(5))
129                     add_flag(o_ptr->art_flags, TR_DRAIN_HP);
130                 if (one_in_(5))
131                     add_flag(o_ptr->art_flags, TR_DRAIN_MANA);
132                 if (one_in_(5))
133                     add_flag(o_ptr->art_flags, TR_DRAIN_EXP);
134                 if (one_in_(5))
135                     add_flag(o_ptr->art_flags, TR_TY_CURSE);
136                 if (one_in_(5))
137                     add_flag(o_ptr->art_flags, TR_CALL_DEMON);
138                 break;
139             case EGO_A_MORGUL:
140                 if (one_in_(3))
141                     o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
142                 if (one_in_(9))
143                     add_flag(o_ptr->art_flags, TR_TY_CURSE);
144                 if (one_in_(4))
145                     add_flag(o_ptr->art_flags, TR_ADD_H_CURSE);
146                 if (one_in_(6))
147                     add_flag(o_ptr->art_flags, TR_AGGRAVATE);
148                 if (one_in_(9))
149                     add_flag(o_ptr->art_flags, TR_NO_MAGIC);
150                 if (one_in_(9))
151                     add_flag(o_ptr->art_flags, TR_NO_TELE);
152                 break;
153             default:
154                 break;
155             }
156         }
157
158         break;
159     }
160     case TV_SHIELD: {
161         if (o_ptr->sval == SV_DRAGON_SHIELD) {
162             dragon_resist(o_ptr);
163             if (!one_in_(3))
164                 break;
165         }
166
167         if (power > 1) {
168             /* power > 2 is debug only */
169             if (one_in_(20) || (power > 2)) {
170                 become_random_artifact(owner_ptr, o_ptr, FALSE);
171                 break;
172             }
173
174             while (TRUE) {
175                 o_ptr->name2 = get_random_ego(INVEN_SUB_HAND, TRUE);
176                 if (o_ptr->sval != SV_SMALL_METAL_SHIELD && o_ptr->sval != SV_LARGE_METAL_SHIELD && o_ptr->name2 == EGO_S_DWARVEN) {
177                     continue;
178                 }
179
180                 break;
181             }
182
183             switch (o_ptr->name2) {
184             case EGO_ENDURANCE:
185                 if (!one_in_(3))
186                     one_high_resistance(o_ptr);
187                 if (one_in_(4))
188                     add_flag(o_ptr->art_flags, TR_RES_POIS);
189                 break;
190             case EGO_REFLECTION:
191                 if (o_ptr->sval == SV_MIRROR_SHIELD)
192                     o_ptr->name2 = 0;
193                 break;
194
195             case EGO_S_DWARVEN:
196                 o_ptr->weight = (2 * k_info[o_ptr->k_idx].weight / 3);
197                 o_ptr->ac = k_info[o_ptr->k_idx].ac + 3;
198                 break;
199             }
200         }
201
202         break;
203     }
204     case TV_GLOVES: {
205         if (o_ptr->sval == SV_SET_OF_DRAGON_GLOVES) {
206             dragon_resist(o_ptr);
207             if (!one_in_(3))
208                 break;
209         }
210
211         if (power > 1) {
212             /* power > 2 is debug only */
213             if (one_in_(20) || (power > 2)) {
214                 become_random_artifact(owner_ptr, o_ptr, FALSE);
215                 break;
216             }
217             o_ptr->name2 = get_random_ego(INVEN_ARMS, TRUE);
218         } else if (power < -1) {
219             o_ptr->name2 = get_random_ego(INVEN_ARMS, FALSE);
220         }
221
222         break;
223     }
224
225     case TV_BOOTS: {
226         if (o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE) {
227             dragon_resist(o_ptr);
228             if (!one_in_(3))
229                 break;
230         }
231
232         if (power > 1) {
233             /* power > 2 is debug only */
234             if (one_in_(20) || (power > 2)) {
235                 become_random_artifact(owner_ptr, o_ptr, FALSE);
236                 break;
237             }
238
239             o_ptr->name2 = get_random_ego(INVEN_FEET, TRUE);
240             switch (o_ptr->name2) {
241             case EGO_SLOW_DESCENT:
242                 if (one_in_(2)) {
243                     one_high_resistance(o_ptr);
244                 }
245
246                 break;
247             }
248         } else if (power < -1) {
249             o_ptr->name2 = get_random_ego(INVEN_FEET, FALSE);
250         }
251
252         break;
253     }
254     case TV_CROWN: {
255         if (power > 1) {
256             /* power > 2 is debug only */
257             if (one_in_(20) || (power > 2)) {
258                 become_random_artifact(owner_ptr, o_ptr, FALSE);
259                 break;
260             }
261
262             while (TRUE) {
263                 bool ok_flag = TRUE;
264                 o_ptr->name2 = get_random_ego(INVEN_HEAD, TRUE);
265
266                 switch (o_ptr->name2) {
267                 case EGO_TELEPATHY:
268                     if (add_esp_strong(o_ptr))
269                         add_esp_weak(o_ptr, TRUE);
270                     else
271                         add_esp_weak(o_ptr, FALSE);
272                     break;
273                 case EGO_MAGI:
274                 case EGO_MIGHT:
275                 case EGO_REGENERATION:
276                 case EGO_LORDLINESS:
277                 case EGO_BASILISK:
278                     break;
279                 case EGO_SEEING:
280                     if (one_in_(3)) {
281                         if (one_in_(2))
282                             add_esp_strong(o_ptr);
283                         else
284                             add_esp_weak(o_ptr, FALSE);
285                     }
286                     break;
287                 default:
288                     /* not existing crown (wisdom,lite, etc...) */
289                     ok_flag = FALSE;
290                 }
291
292                 if (ok_flag)
293                     break;
294             }
295
296             break;
297         } else if (power < -1) {
298             while (TRUE) {
299                 bool ok_flag = TRUE;
300                 o_ptr->name2 = get_random_ego(INVEN_HEAD, FALSE);
301
302                 switch (o_ptr->name2) {
303                 case EGO_ANCIENT_CURSE:
304                     if (one_in_(3))
305                         add_flag(o_ptr->art_flags, TR_NO_MAGIC);
306                     if (one_in_(3))
307                         add_flag(o_ptr->art_flags, TR_NO_TELE);
308                     if (one_in_(3))
309                         add_flag(o_ptr->art_flags, TR_TY_CURSE);
310                     if (one_in_(3))
311                         add_flag(o_ptr->art_flags, TR_DRAIN_EXP);
312                     if (one_in_(3))
313                         add_flag(o_ptr->art_flags, TR_DRAIN_HP);
314                     if (one_in_(3))
315                         add_flag(o_ptr->art_flags, TR_DRAIN_MANA);
316                     break;
317                 }
318
319                 if (ok_flag)
320                     break;
321             }
322         }
323
324         break;
325     }
326     case TV_HELM: {
327         if (o_ptr->sval == SV_DRAGON_HELM) {
328             dragon_resist(o_ptr);
329             if (!one_in_(3))
330                 break;
331         }
332
333         if (power > 1) {
334             /* power > 2 is debug only */
335             if (one_in_(20) || (power > 2)) {
336                 become_random_artifact(owner_ptr, o_ptr, FALSE);
337                 break;
338             }
339
340             while (TRUE) {
341                 bool ok_flag = TRUE;
342                 o_ptr->name2 = get_random_ego(INVEN_HEAD, TRUE);
343                 switch (o_ptr->name2) {
344                 case EGO_BRILLIANCE:
345                 case EGO_DARK:
346                 case EGO_INFRAVISION:
347                 case EGO_H_PROTECTION:
348                     break;
349                 case EGO_SEEING:
350                     if (one_in_(7)) {
351                         if (one_in_(2))
352                             add_esp_strong(o_ptr);
353                         else
354                             add_esp_weak(o_ptr, FALSE);
355                     }
356
357                     break;
358                 case EGO_LITE:
359                     if (one_in_(3))
360                         add_flag(o_ptr->art_flags, TR_LITE_1);
361                     if (one_in_(3))
362                         add_flag(o_ptr->art_flags, TR_LITE_2);
363                     break;
364                 case EGO_H_DEMON:
365                     if (one_in_(3))
366                         o_ptr->curse_flags |= (TRC_HEAVY_CURSE);
367                     one_in_(3) ? add_flag(o_ptr->art_flags, TR_DRAIN_EXP)
368                                : one_in_(2) ? add_flag(o_ptr->art_flags, TR_DRAIN_HP) : add_flag(o_ptr->art_flags, TR_DRAIN_MANA);
369
370                     if (one_in_(3))
371                         add_flag(o_ptr->art_flags, TR_AGGRAVATE);
372                     if (one_in_(3))
373                         add_flag(o_ptr->art_flags, TR_ADD_L_CURSE);
374                     if (one_in_(5))
375                         add_flag(o_ptr->art_flags, TR_ADD_H_CURSE);
376                     if (one_in_(5))
377                         add_flag(o_ptr->art_flags, TR_DRAIN_HP);
378                     if (one_in_(5))
379                         add_flag(o_ptr->art_flags, TR_DRAIN_MANA);
380                     if (one_in_(5))
381                         add_flag(o_ptr->art_flags, TR_DRAIN_EXP);
382                     if (one_in_(5))
383                         add_flag(o_ptr->art_flags, TR_TY_CURSE);
384                     if (one_in_(5))
385                         add_flag(o_ptr->art_flags, TR_CALL_DEMON);
386                     break;
387                 default:
388                     /* not existing helm (Magi, Might, etc...)*/
389                     ok_flag = FALSE;
390                 }
391                 if (ok_flag)
392                     break;
393             }
394
395             break;
396         } else if (power < -1) {
397             while (TRUE) {
398                 bool ok_flag = TRUE;
399                 o_ptr->name2 = get_random_ego(INVEN_HEAD, FALSE);
400
401                 switch (o_ptr->name2) {
402                 case EGO_ANCIENT_CURSE:
403                     ok_flag = FALSE;
404                 }
405
406                 if (ok_flag)
407                     break;
408             }
409         }
410
411         break;
412     }
413     case TV_CLOAK: {
414         if (power > 1) {
415             /* power > 2 is debug only */
416             if (one_in_(20) || (power > 2)) {
417                 become_random_artifact(owner_ptr, o_ptr, FALSE);
418                 break;
419             }
420             o_ptr->name2 = get_random_ego(INVEN_OUTER, TRUE);
421
422             switch (o_ptr->name2) {
423             case EGO_BAT:
424                 o_ptr->to_d -= 6;
425                 o_ptr->to_h -= 6;
426                 break;
427             case EGO_NAZGUL:
428                 o_ptr->to_d -= 3;
429                 o_ptr->to_h -= 3;
430                 if (one_in_(3))
431                     add_flag(o_ptr->art_flags, TR_COWARDICE);
432                 if (one_in_(3))
433                     add_flag(o_ptr->art_flags, TR_CALL_UNDEAD);
434                 if (one_in_(3))
435                     add_flag(o_ptr->art_flags, TR_SLOW_REGEN);
436                 if (one_in_(3))
437                     add_flag(o_ptr->art_flags, TR_DRAIN_EXP);
438                 break;
439             }
440
441         } else if (power < -1) {
442             o_ptr->name2 = get_random_ego(INVEN_OUTER, FALSE);
443         }
444
445         break;
446     }
447     }
448 }