OSDN Git Service

Merge pull request #2122 from sikabane-works/release/3.0.0Alpha52
[hengbandforosx/hengbandosx.git] / src / smith / smith-info.cpp
1 #include "smith/smith-info.h"
2 #include "object-enchant/tr-types.h"
3 #include "object/object-flags.h"
4 #include "smith/smith-types.h"
5 #include "sv-definition/sv-weapon-types.h"
6 #include "system/object-type-definition.h"
7 #include "system/player-type-definition.h"
8
9 ISmithInfo::ISmithInfo(SmithEffectType effect, concptr name, SmithCategoryType category, std::vector<SmithEssenceType> need_essences, int consumption)
10     : effect(effect)
11     , name(name)
12     , category(category)
13     , need_essences(std::move(need_essences))
14     , consumption(consumption)
15 {
16 }
17
18 TrFlags ISmithInfo::tr_flags() const
19 {
20     return {};
21 }
22
23 BasicSmithInfo::BasicSmithInfo(SmithEffectType effect, concptr name, SmithCategoryType category, std::vector<SmithEssenceType> need_essences, int consumption, TrFlags add_flags)
24     : ISmithInfo(effect, name, category, std::move(need_essences), consumption)
25     , add_flags(add_flags)
26 {
27 }
28
29 bool BasicSmithInfo::add_essence(PlayerType *, object_type *o_ptr, int) const
30 {
31     o_ptr->smith_effect = effect;
32
33     return true;
34 }
35
36 void BasicSmithInfo::erase_essence(object_type *o_ptr) const
37 {
38     o_ptr->smith_effect = std::nullopt;
39     auto flgs = object_flags(o_ptr);
40     if (flgs.has_none_of(TR_PVAL_FLAG_MASK))
41         o_ptr->pval = 0;
42 }
43
44 TrFlags BasicSmithInfo::tr_flags() const
45 {
46     return this->add_flags;
47 }
48
49 bool BasicSmithInfo::can_give_smith_effect(const object_type *o_ptr) const
50 {
51     /*!
52      * @note 固定orランダムアーティファクトもしくはすでに鍛冶済みでないかを最初にチェックし、
53      * 残る具体的な絞り込みは BasicSmithInfo::can_give_smith_effect_impl およびその派生クラスで
54      * オーバーライドした関数にて行う
55      */
56     if (o_ptr->is_artifact() || o_ptr->smith_effect.has_value()) {
57         return false;
58     }
59
60     return this->can_give_smith_effect_impl(o_ptr);
61 }
62
63 bool BasicSmithInfo::can_give_smith_effect_impl(const object_type *o_ptr) const
64 {
65     if (this->effect == SmithEffectType::XTRA_MIGHT || this->effect == SmithEffectType::XTRA_SHOTS) {
66         return o_ptr->tval == ItemKindType::BOW;
67     }
68     if (this->effect == SmithEffectType::VORPAL) {
69         return (o_ptr->tval == ItemKindType::SWORD) && (o_ptr->sval != SV_POISON_NEEDLE);
70     }
71     if (this->effect == SmithEffectType::EASY_2WEAPON) {
72         return (o_ptr->tval == ItemKindType::GLOVES);
73     }
74     if (this->category == SmithCategoryType::WEAPON_ATTR && o_ptr->is_ammo()) {
75         return this->add_flags.has_any_of({ TR_BRAND_ACID, TR_BRAND_ELEC, TR_BRAND_FIRE, TR_BRAND_COLD, TR_BRAND_POIS });
76     }
77     if (this->category == SmithCategoryType::WEAPON_ATTR || this->category == SmithCategoryType::SLAYING) {
78         return o_ptr->is_melee_ammo();
79     }
80
81     return o_ptr->is_weapon_armour_ammo() && o_ptr->is_wearable();
82 }
83
84 ActivationSmithInfo::ActivationSmithInfo(SmithEffectType effect, concptr name, SmithCategoryType category, std::vector<SmithEssenceType> need_essences, int consumption, RandomArtActType act_idx)
85     : ISmithInfo(effect, name, category, std::move(need_essences), consumption)
86     , act_idx(act_idx)
87 {
88 }
89
90 bool ActivationSmithInfo::add_essence(PlayerType *, object_type *o_ptr, int) const
91 {
92     o_ptr->smith_act_idx = this->act_idx;
93
94     return true;
95 }
96
97 void ActivationSmithInfo::erase_essence(object_type *o_ptr) const
98 {
99     o_ptr->smith_act_idx = std::nullopt;
100 }
101
102 bool ActivationSmithInfo::can_give_smith_effect(const object_type *o_ptr) const
103 {
104     if (o_ptr->is_artifact() || o_ptr->smith_act_idx.has_value()) {
105         return false;
106     }
107
108     return o_ptr->is_weapon_armour_ammo() && o_ptr->is_wearable();
109 }
110
111 EnchantWeaponSmithInfo::EnchantWeaponSmithInfo(SmithEffectType effect, concptr name, SmithCategoryType category, std::vector<SmithEssenceType> need_essences, int consumption)
112     : ISmithInfo(effect, name, category, std::move(need_essences), consumption)
113 {
114 }
115
116 bool EnchantWeaponSmithInfo::add_essence(PlayerType *player_ptr, object_type *o_ptr, int) const
117 {
118     const auto max_val = player_ptr->lev / 5 + 5;
119     if ((o_ptr->to_h >= max_val) && (o_ptr->to_d >= max_val)) {
120         return false;
121     }
122
123     if (o_ptr->to_h < max_val) {
124         o_ptr->to_h++;
125     }
126     if (o_ptr->to_d < max_val) {
127         o_ptr->to_d++;
128     }
129
130     return true;
131 }
132
133 bool EnchantWeaponSmithInfo::can_give_smith_effect(const object_type *o_ptr) const
134 {
135     return o_ptr->allow_enchant_weapon();
136 }
137
138 EnchantArmourSmithInfo::EnchantArmourSmithInfo(SmithEffectType effect, concptr name, SmithCategoryType category, std::vector<SmithEssenceType> need_essences, int consumption)
139     : ISmithInfo(effect, name, category, std::move(need_essences), consumption)
140 {
141 }
142
143 bool EnchantArmourSmithInfo::add_essence(PlayerType *player_ptr, object_type *o_ptr, int) const
144 {
145     const auto max_val = player_ptr->lev / 5 + 5;
146     if (o_ptr->to_a >= max_val) {
147         return false;
148     }
149
150     o_ptr->to_a++;
151
152     return true;
153 }
154
155 bool EnchantArmourSmithInfo::can_give_smith_effect(const object_type *o_ptr) const
156 {
157     return o_ptr->is_armour();
158 }
159
160 SustainSmithInfo::SustainSmithInfo(SmithEffectType effect, concptr name, SmithCategoryType category, std::vector<SmithEssenceType> need_essences, int consumption)
161     : ISmithInfo(effect, name, category, std::move(need_essences), consumption)
162 {
163 }
164
165 bool SustainSmithInfo::add_essence(PlayerType *, object_type *o_ptr, int) const
166 {
167     o_ptr->art_flags.set(TR_IGNORE_ACID);
168     o_ptr->art_flags.set(TR_IGNORE_ELEC);
169     o_ptr->art_flags.set(TR_IGNORE_FIRE);
170     o_ptr->art_flags.set(TR_IGNORE_COLD);
171
172     return true;
173 }
174
175 bool SustainSmithInfo::can_give_smith_effect(const object_type *o_ptr) const
176 {
177     return o_ptr->is_weapon_armour_ammo();
178 }
179
180 SlayingGlovesSmithInfo::SlayingGlovesSmithInfo(SmithEffectType effect, concptr name, SmithCategoryType category, std::vector<SmithEssenceType> need_essences, int consumption)
181     : BasicSmithInfo(effect, name, category, std::move(need_essences), consumption, {})
182 {
183 }
184
185 bool SlayingGlovesSmithInfo::add_essence(PlayerType *player_ptr, object_type *o_ptr, int number) const
186 {
187     BasicSmithInfo::add_essence(player_ptr, o_ptr, number);
188
189     HIT_PROB get_to_h = ((number + 1) / 2 + randint0(number / 2 + 1));
190     HIT_POINT get_to_d = ((number + 1) / 2 + randint0(number / 2 + 1));
191     o_ptr->xtra4 = (get_to_h << 8) + get_to_d;
192     o_ptr->to_h += get_to_h;
193     o_ptr->to_d += get_to_d;
194
195     return true;
196 }
197
198 void SlayingGlovesSmithInfo::erase_essence(object_type *o_ptr) const
199 {
200     BasicSmithInfo::erase_essence(o_ptr);
201
202     o_ptr->to_h -= (o_ptr->xtra4 >> 8);
203     o_ptr->to_d -= (o_ptr->xtra4 & 0x000f);
204     o_ptr->xtra4 = 0;
205     if (o_ptr->to_h < 0)
206         o_ptr->to_h = 0;
207     if (o_ptr->to_d < 0)
208         o_ptr->to_d = 0;
209 }
210
211 bool SlayingGlovesSmithInfo::can_give_smith_effect_impl(const object_type *o_ptr) const
212 {
213     return o_ptr->tval == ItemKindType::GLOVES;
214 }