OSDN Git Service

668e201422c55f16ddc6adc8fd9e07e61efd28b8
[hengbandforosx/hengbandosx.git] / src / player-status / player-speed.cpp
1 #include "player-status/player-speed.h"
2 #include "artifact/fixed-art-types.h"
3 #include "grid/feature-flag-types.h"
4 #include "grid/feature.h"
5 #include "inventory/inventory-slot-types.h"
6 #include "monster-race/monster-race.h"
7 #include "monster/monster-status.h"
8 #include "mutation/mutation-flag-types.h"
9 #include "object-enchant/tr-types.h"
10 #include "object/object-flags.h"
11 #include "player-base/player-class.h"
12 #include "player-base/player-race.h"
13 #include "player-info/equipment-info.h"
14 #include "player-info/monk-data-type.h"
15 #include "player-info/race-info.h"
16 #include "player/attack-defense-types.h"
17 #include "player/digestion-processor.h"
18 #include "player/player-skill.h"
19 #include "player/player-status-flags.h"
20 #include "player/player-status.h"
21 #include "player/special-defense-types.h"
22 #include "realm/realm-hex-numbers.h"
23 #include "realm/realm-types.h"
24 #include "spell-realm/spells-hex.h"
25 #include "system/floor-type-definition.h"
26 #include "system/grid-type-definition.h"
27 #include "system/monster-race-definition.h"
28 #include "system/monster-type-definition.h"
29 #include "system/object-type-definition.h"
30 #include "system/player-type-definition.h"
31 #include "util/bit-flags-calculator.h"
32
33 PlayerSpeed::PlayerSpeed(player_type *player_ptr)
34     : PlayerStatusBase(player_ptr)
35 {
36 }
37
38 /*!
39  * @brief 速度 - 初期値、下限、上限
40  * @details
41  * * 初期値110 - 加速+0に相当
42  * * 上限209 - 加速+99相当
43  * * 下限11 - 加速-99相当
44  */
45 void PlayerSpeed::set_locals()
46 {
47     this->default_value = 110;
48     this->min_value = 11;
49     this->max_value = 209;
50     this->tr_flag = TR_SPEED;
51     this->tr_bad_flag = TR_SPEED;
52 }
53
54 /*!
55  * @brief 速度計算 - 種族
56  * @return 速度値の増減分
57  * @details
58  * ** クラッコンと妖精に加算(+レベル/10)
59  * ** 悪魔変化/吸血鬼変化で加算(+3)
60  * ** 魔王変化で加算(+5)
61  * ** マーフォークがFF_WATER地形にいれば加算(+2+レベル/10)
62  * ** そうでなく浮遊を持っていないなら減算(-2)
63  */
64 int16_t PlayerSpeed::race_value()
65 {
66     int16_t result = 0;
67
68     if (PlayerRace(this->player_ptr).equals(PlayerRaceType::KLACKON) || PlayerRace(this->player_ptr).equals(PlayerRaceType::SPRITE))
69         result += (this->player_ptr->lev) / 10;
70
71     if (PlayerRace(this->player_ptr).equals(PlayerRaceType::MERFOLK)) {
72         floor_type *floor_ptr = this->player_ptr->current_floor_ptr;
73         feature_type *f_ptr = &f_info[floor_ptr->grid_array[this->player_ptr->y][this->player_ptr->x].feat];
74         if (f_ptr->flags.has(FF::WATER)) {
75             result += (2 + this->player_ptr->lev / 10);
76         } else if (!this->player_ptr->levitation) {
77             result -= 2;
78         }
79     }
80
81     if (this->player_ptr->mimic_form) {
82         switch (this->player_ptr->mimic_form) {
83         case MIMIC_DEMON:
84             result += 3;
85             break;
86         case MIMIC_DEMON_LORD:
87             result += 5;
88             break;
89         case MIMIC_VAMPIRE:
90             result += 3;
91             break;
92         }
93     }
94     return result;
95 }
96
97 /*!
98  * @brief 速度計算 - 職業
99  * @return 速度値の増減分
100  * @details
101  * ** 忍者の装備が重ければ減算(-レベル/10)
102  * ** 忍者の装備が適正ならば加算(+3)さらにクラッコン、妖精、いかさま以外なら加算(+レベル/10)
103  * ** 錬気術師で装備が重くなくクラッコン、妖精、いかさま以外なら加算(+レベル/10)
104  * ** 狂戦士なら加算(+3),レベル20/30/40/50ごとに+1
105  */
106 int16_t PlayerSpeed::class_value()
107 {
108     SPEED result = 0;
109
110     if (this->player_ptr->pclass == PlayerClassType::NINJA) {
111         if (heavy_armor(this->player_ptr)) {
112             result -= (this->player_ptr->lev) / 10;
113         } else if ((!this->player_ptr->inventory_list[INVEN_MAIN_HAND].k_idx || can_attack_with_main_hand(this->player_ptr)) && (!this->player_ptr->inventory_list[INVEN_SUB_HAND].k_idx || can_attack_with_sub_hand(this->player_ptr))) {
114             result += 3;
115             if (!(PlayerRace(this->player_ptr).equals(PlayerRaceType::KLACKON) || PlayerRace(this->player_ptr).equals(PlayerRaceType::SPRITE) || (this->player_ptr->ppersonality == PERSONALITY_MUNCHKIN)))
116                 result += (this->player_ptr->lev) / 10;
117         }
118     }
119
120     if ((this->player_ptr->pclass == PlayerClassType::MONK || this->player_ptr->pclass == PlayerClassType::FORCETRAINER) && !(heavy_armor(this->player_ptr))) {
121         if (!(PlayerRace(this->player_ptr).equals(PlayerRaceType::KLACKON) || PlayerRace(this->player_ptr).equals(PlayerRaceType::SPRITE) || (this->player_ptr->ppersonality == PERSONALITY_MUNCHKIN)))
122             result += (this->player_ptr->lev) / 10;
123     }
124
125     if (this->player_ptr->pclass == PlayerClassType::BERSERKER) {
126         result += 2;
127         if (this->player_ptr->lev > 29)
128             result++;
129         if (this->player_ptr->lev > 39)
130             result++;
131         if (this->player_ptr->lev > 44)
132             result++;
133         if (this->player_ptr->lev > 49)
134             result++;
135     }
136     return result;
137 }
138
139 /*!
140  * @brief 速度計算 - 性格
141  * @return 速度値の増減分
142  * @details
143  * ** いかさまでクラッコン/妖精以外なら加算(+5+レベル/10)
144  */
145 int16_t PlayerSpeed::personality_value()
146 {
147     int16_t result = 0;
148     if (this->player_ptr->ppersonality == PERSONALITY_MUNCHKIN && this->player_ptr->prace != PlayerRaceType::KLACKON && this->player_ptr->prace != PlayerRaceType::SPRITE) {
149         result += (this->player_ptr->lev) / 10 + 5;
150     }
151     return result;
152 }
153
154 /*!
155  * @brief 速度計算 - 装備品特殊セット
156  * @return 速度値の増減分
157  * @details
158  * ** 棘セット装備中ならば加算(+7)
159  * ** アイシングデス-トゥインクル装備中ならば加算(+7)
160  */
161 int16_t PlayerSpeed::special_weapon_set_value()
162 {
163     int16_t result = 0;
164     if (has_melee_weapon(this->player_ptr, INVEN_MAIN_HAND) && has_melee_weapon(this->player_ptr, INVEN_SUB_HAND)) {
165         if ((this->player_ptr->inventory_list[INVEN_MAIN_HAND].name1 == ART_QUICKTHORN) && (this->player_ptr->inventory_list[INVEN_SUB_HAND].name1 == ART_TINYTHORN)) {
166             result += 7;
167         }
168
169         if ((this->player_ptr->inventory_list[INVEN_MAIN_HAND].name1 == ART_ICINGDEATH) && (this->player_ptr->inventory_list[INVEN_SUB_HAND].name1 == ART_TWINKLE)) {
170             result += 5;
171         }
172     }
173     return result;
174 }
175
176 /*!
177  * @brief 速度計算 - 装備品
178  * @return 速度値の増減分
179  * @details
180  * ** 装備品にTR_SPEEDがあれば加算(+pval+1
181  * ** セットで加速増減があるものを計算
182  */
183 int16_t PlayerSpeed::equipments_value()
184 {
185     int16_t result = PlayerStatusBase::equipments_value();
186     result += this->special_weapon_set_value();
187
188     return result;
189 }
190
191 /*!
192  * @brief 速度計算 - 一時的効果
193  * @return 速度値の増減分
194  * @details
195  * ** 加速状態中なら加算(+10)
196  * ** 減速状態中なら減算(-10)
197  * ** 呪術「衝撃のクローク」で加算(+3)
198  * ** 食い過ぎなら減算(-10)
199  * ** 光速移動中は+999(最終的に+99になる)
200  */
201 int16_t PlayerSpeed::time_effect_value()
202 {
203     int16_t result = 0;
204
205     if (is_fast(this->player_ptr)) {
206         result += 10;
207     }
208
209     if (this->player_ptr->slow) {
210         result -= 10;
211     }
212
213     if (this->player_ptr->realm1 == REALM_HEX) {
214         if (SpellHex(this->player_ptr).is_spelling_specific(HEX_SHOCK_CLOAK)) {
215             result += 3;
216         }
217     }
218
219     if (this->player_ptr->food >= PY_FOOD_MAX)
220         result -= 10;
221
222     /* Temporary lightspeed forces to be maximum speed */
223     if (this->player_ptr->lightspeed)
224         result += 999;
225
226     return result;
227 }
228
229 /*!
230  * @brief 速度計算 - 型
231  * @return 速度値の増減分
232  * @details
233  * ** 朱雀の構えなら加算(+10)
234  */
235 int16_t PlayerSpeed::battleform_value()
236 {
237     int16_t result = 0;
238     if (PlayerClass(player_ptr).monk_stance_is(MonkStance::SUZAKU))
239         result += 10;
240     return result;
241 }
242
243 /*!
244  * @brief 速度計算 - 変異
245  * @return 速度値の増減分
246  * @details
247  * ** 変異MUT3_XTRA_FATなら減算(-2)
248  * ** 変異MUT3_XTRA_LEGなら加算(+3)
249  * ** 変異MUT3_SHORT_LEGなら減算(-3)
250  */
251 int16_t PlayerSpeed::mutation_value()
252 {
253     SPEED result = 0;
254
255     const auto &muta = this->player_ptr->muta;
256     if (muta.has(MUTA::XTRA_FAT)) {
257         result -= 2;
258     }
259
260     if (muta.has(MUTA::XTRA_LEGS)) {
261         result += 3;
262     }
263
264     if (muta.has(MUTA::SHORT_LEG)) {
265         result -= 3;
266     }
267
268     return result;
269 }
270
271 /*!
272  * @brief 速度計算 - 乗馬
273  * @return 速度値の増減分
274  * @details
275  * * 騎乗中ならばモンスターの加速に準拠、ただし騎乗技能値とモンスターレベルによるキャップ処理あり
276  */
277 int16_t PlayerSpeed::riding_value()
278 {
279     monster_type *riding_m_ptr = &(this->player_ptr)->current_floor_ptr->m_list[this->player_ptr->riding];
280     SPEED speed = riding_m_ptr->mspeed;
281     SPEED result = 0;
282
283     if (!this->player_ptr->riding) {
284         return 0;
285     }
286
287     if (riding_m_ptr->mspeed > 110) {
288         result = (int16_t)((speed - 110) * (this->player_ptr->skill_exp[SKILL_RIDING] * 3 + this->player_ptr->lev * 160L - 10000L) / (22000L));
289         if (result < 0)
290             result = 0;
291     } else {
292         result = speed - 110;
293     }
294
295     result += (this->player_ptr->skill_exp[SKILL_RIDING] + this->player_ptr->lev * 160L) / 3200;
296
297     if (monster_fast_remaining(riding_m_ptr))
298         result += 10;
299     if (monster_slow_remaining(riding_m_ptr))
300         result -= 10;
301
302     return result;
303 }
304
305 /*!
306  * @brief 速度計算 - 重量
307  * @return 速度値の増減分
308  * @details
309  * * 所持品の重量による減速処理。乗馬時は別計算。
310  */
311 int16_t PlayerSpeed::inventory_weight_value()
312 {
313     int16_t result = 0;
314     auto weight = calc_inventory_weight(this->player_ptr);
315     if (this->player_ptr->riding) {
316         auto *riding_m_ptr = &(this->player_ptr)->current_floor_ptr->m_list[this->player_ptr->riding];
317         auto *riding_r_ptr = &r_info[riding_m_ptr->r_idx];
318         auto count = 1500 + riding_r_ptr->level * 25;
319         if (weight > count) {
320             result -= ((weight - count) / (count / 5));
321         }
322     } else {
323         auto count = calc_weight_limit(this->player_ptr);
324         if (weight > count) {
325             result -= ((weight - count) / (count / 5));
326         }
327     }
328
329     return result;
330 }
331
332 /*!
333  * @brief 速度計算 - ACTION
334  * @return 速度値の増減分
335  * @details
336  * * 探索中なら減算(-10)
337  */
338 int16_t PlayerSpeed::action_value()
339 {
340     SPEED result = 0;
341     if (this->player_ptr->action == ACTION_SEARCH)
342         result -= 10;
343     return result;
344 }
345
346 /*!
347  * @brief 速度フラグ - 装備
348  * @return 加速修正が0でない装備に対応したBIT_FLAG
349  * @details
350  * * セット二刀流は両手のフラグをONにする
351  */
352 BIT_FLAGS PlayerSpeed::equipments_flags(tr_type check_flag)
353 {
354     BIT_FLAGS result = PlayerStatusBase::equipments_flags(check_flag);
355
356     if (this->special_weapon_set_value() != 0)
357         set_bits(result, FLAG_CAUSE_INVEN_MAIN_HAND | FLAG_CAUSE_INVEN_SUB_HAND);
358
359     return result;
360 }
361
362 /*!
363  * @brief 速度計算 - 乗馬時の例外処理
364  * @return 計算済の速度値
365  * @details
366  * * 非乗馬時 - ここまでの修正値合算をそのまま使用
367  * * 乗馬時 - 乗馬の速度と重量減衰のみを計算
368  */
369 int16_t PlayerSpeed::set_exception_value(int16_t value)
370 {
371     if (this->player_ptr->riding) {
372         value = this->default_value;
373         value += this->riding_value();
374         value += this->inventory_weight_value();
375         value += this->action_value();
376     }
377     return value;
378 }