OSDN Git Service

[Refactor] #2141 floor_type *floor_ptrの宣言をautoに差し替えた
[hengbandforosx/hengbandosx.git] / src / player-base / player-race.cpp
1 /*!
2  * @brief プレイヤーの種族に基づく耐性・能力の判定処理等を行うクラス
3  * @date 2021/09/08
4  * @author Hourier
5  * @details PlayerRaceからPlayerClassへの依存はあるが、逆は依存させないこと.
6  */
7 #include "player-base/player-race.h"
8 #include "grid/feature-flag-types.h"
9 #include "grid/feature.h"
10 #include "player-base/player-class.h"
11 #include "player-info/mimic-info-table.h"
12 #include "player/race-info-table.h"
13 #include "system/floor-type-definition.h"
14 #include "system/grid-type-definition.h"
15 #include "system/player-type-definition.h"
16 #include "util/bit-flags-calculator.h"
17
18 /*!
19  * @brief Construct a new Player Race:: Player Race object
20  *
21  * @param base_race true の場合、仮に変身している場合でも元の種族について扱う。 false の場合変身している種族について扱う。
22  * 引数を省略した場合は false
23  */
24 PlayerRace::PlayerRace(PlayerType *player_ptr, bool base_race)
25     : player_ptr(player_ptr)
26     , base_race(base_race)
27 {
28 }
29
30 /*!
31  * @brief 種族固有の特性フラグを取得する
32  * @return
33  */
34 TrFlags PlayerRace::tr_flags() const
35 {
36     TrFlags flags;
37
38     auto race_ptr = this->get_info();
39     if (race_ptr->infra > 0)
40         flags.set(TR_INFRA);
41
42     for (auto &cond : race_ptr->extra_flags) {
43         if (player_ptr->lev < cond.level)
44             continue;
45         if (cond.pclass.has_value()) {
46             auto is_class_equal = PlayerClass(player_ptr).equals(cond.pclass.value());
47             if (cond.not_class && is_class_equal)
48                 continue;
49             if (!cond.not_class && !is_class_equal)
50                 continue;
51         }
52
53         flags.set(cond.type);
54     }
55
56     return flags;
57 }
58
59 /*!
60  * @brief プレイヤーの種族情報テーブルへのポインタを取得する
61  *
62  * @return プレイヤーの種族情報テーブルへのポインタ
63  */
64 const player_race_info *PlayerRace::get_info() const
65 {
66     if (this->base_race) {
67         return &race_info[enum2i(this->player_ptr->prace)];
68     }
69
70     switch (this->player_ptr->mimic_form) {
71     case MIMIC_DEMON:
72     case MIMIC_DEMON_LORD:
73     case MIMIC_VAMPIRE:
74         return &mimic_info[this->player_ptr->mimic_form];
75     default: // MIMIC_NONE or undefined
76         return &race_info[enum2i(this->player_ptr->prace)];
77     }
78 }
79
80 /*!
81  * @brief 種族の生命形態を返す
82  * @param player_ptr プレイヤー情報への参照ポインタ
83  * @return 生命形態
84  */
85 PlayerRaceLifeType PlayerRace::life() const
86 {
87     return this->get_info()->life;
88 }
89
90 /*!
91  * @brief 種族の食料形態を返す
92  * @param player_ptr プレイヤー情報への参照ポインタ
93  * @param base_race ミミック中も元種族の情報を返すならtrue
94  * @return 食料形態
95  */
96 PlayerRaceFoodType PlayerRace::food() const
97 {
98     return this->get_info()->food;
99 }
100
101 bool PlayerRace::is_mimic_nonliving() const
102 {
103     constexpr int nonliving_flag = 1;
104     return any_bits(mimic_info[this->player_ptr->mimic_form].choice, nonliving_flag);
105 }
106
107 bool PlayerRace::has_cut_immunity() const
108 {
109     auto cut_immunity = PlayerRace(this->player_ptr).equals(PlayerRaceType::GOLEM);
110     cut_immunity |= PlayerRace(this->player_ptr).equals(PlayerRaceType::SKELETON);
111     cut_immunity |= PlayerRace(this->player_ptr).equals(PlayerRaceType::SPECTRE);
112     cut_immunity |= PlayerRace(this->player_ptr).equals(PlayerRaceType::ZOMBIE) && (this->player_ptr->lev > 11);
113     return cut_immunity;
114 }
115
116
117 bool PlayerRace::has_stun_immunity() const
118 {
119     return PlayerRace(this->player_ptr).equals(PlayerRaceType::GOLEM);
120 }
121
122 bool PlayerRace::equals(PlayerRaceType prace) const
123 {
124     return (this->player_ptr->mimic_form == MIMIC_NONE) && (this->player_ptr->prace == prace);
125 }
126
127 /*!
128  * @brief 速度計算 - 種族
129  * @return 速度値の増減分
130  * @details
131  * ** クラッコンと妖精に加算(+レベル/10)
132  * ** 悪魔変化/吸血鬼変化で加算(+3)
133  * ** 魔王変化で加算(+5)
134  * ** マーフォークがFF_WATER地形にいれば加算(+2+レベル/10)
135  * ** そうでなく浮遊を持っていないなら減算(-2)
136  */
137 int16_t PlayerRace::speed() const
138 {
139     int16_t result = 0;
140
141     if (PlayerRace(this->player_ptr).equals(PlayerRaceType::KLACKON) || PlayerRace(this->player_ptr).equals(PlayerRaceType::SPRITE))
142         result += (this->player_ptr->lev) / 10;
143
144     if (PlayerRace(this->player_ptr).equals(PlayerRaceType::MERFOLK)) {
145         auto *floor_ptr = this->player_ptr->current_floor_ptr;
146         feature_type *f_ptr = &f_info[floor_ptr->grid_array[this->player_ptr->y][this->player_ptr->x].feat];
147         if (f_ptr->flags.has(FloorFeatureType::WATER)) {
148             result += (2 + this->player_ptr->lev / 10);
149         } else if (!this->player_ptr->levitation) {
150             result -= 2;
151         }
152     }
153
154     if (this->player_ptr->mimic_form) {
155         switch (this->player_ptr->mimic_form) {
156         case MIMIC_DEMON:
157             result += 3;
158             break;
159         case MIMIC_DEMON_LORD:
160             result += 5;
161             break;
162         case MIMIC_VAMPIRE:
163             result += 3;
164             break;
165         }
166     }
167     return result;
168 }
169
170 /*!
171  * @brief 腕力補正計算 - 種族
172  * @return 腕力補正値
173  * @details
174  * * 種族による腕力修正値。
175  * * エントはレベル26,41,46到達ごとに加算(+1)
176  */
177 int16_t PlayerRace::additional_strength() const
178 {
179     int16_t result = 0;
180
181     if (PlayerRace(this->player_ptr).equals(PlayerRaceType::ENT)) {
182         if (this->player_ptr->lev > 25)
183             result++;
184         if (this->player_ptr->lev > 40)
185             result++;
186         if (this->player_ptr->lev > 45)
187             result++;
188     }
189
190     return result;
191 }
192
193 /*!
194  * @brief 器用さ補正計算 - 種族
195  * @return 器用さ補正値
196  * @details
197  * * 種族による器用さ修正値。
198  * * エントはレベル26,41,46到達ごとに減算(-1)
199  */
200 int16_t PlayerRace::additional_dexterity() const
201 {
202     int16_t result = 0;
203
204     if (PlayerRace(this->player_ptr).equals(PlayerRaceType::ENT)) {
205         if (this->player_ptr->lev > 25)
206             result--;
207         if (this->player_ptr->lev > 40)
208             result--;
209         if (this->player_ptr->lev > 45)
210             result--;
211     }
212
213     return result;
214 }
215
216 /*!
217  * @brief 耐久力補正計算 - 種族
218  * @return 耐久力補正値
219  * @details
220  * * 種族による耐久力修正値。
221  * * エントはレベル26,41,46到達ごとに加算(+1)
222  */
223 int16_t PlayerRace::additional_constitution() const
224 {
225     int16_t result = 0;
226
227     if (PlayerRace(this->player_ptr).equals(PlayerRaceType::ENT)) {
228         if (this->player_ptr->lev > 25)
229             result++;
230         if (this->player_ptr->lev > 40)
231             result++;
232         if (this->player_ptr->lev > 45)
233             result++;
234     }
235
236     return result;
237 }