2 * @brief プレイヤーの職業クラスに基づく耐性・能力の判定処理等を行うクラス
6 #include "player-base/player-class.h"
7 #include "core/player-redraw-types.h"
8 #include "core/player-update-types.h"
9 #include "inventory/inventory-slot-types.h"
10 #include "mind/mind-elementalist.h"
11 #include "player-info/bard-data-type.h"
12 #include "player-info/bluemage-data-type.h"
13 #include "player-info/equipment-info.h"
14 #include "player-info/force-trainer-data-type.h"
15 #include "player-info/magic-eater-data-type.h"
16 #include "player-info/mane-data-type.h"
17 #include "player-info/monk-data-type.h"
18 #include "player-info/ninja-data-type.h"
19 #include "player-info/samurai-data-type.h"
20 #include "player-info/smith-data-type.h"
21 #include "player-info/sniper-data-type.h"
22 #include "player-info/spell-hex-data-type.h"
23 #include "player/attack-defense-types.h"
24 #include "player/player-status-flags.h"
25 #include "player/special-defense-types.h"
26 #include "realm/realm-types.h"
27 #include "status/action-setter.h"
28 #include "system/object-type-definition.h"
29 #include "system/player-type-definition.h"
30 #include "util/bit-flags-calculator.h"
32 PlayerClass::PlayerClass(player_type *player_ptr)
33 : player_ptr(player_ptr)
38 * @brief プレイヤーの職業により得られる特性フラグを返す
40 TrFlags PlayerClass::tr_flags() const
43 const auto plev = this->player_ptr->lev;
45 switch (this->player_ptr->pclass) {
46 case PlayerClassType::WARRIOR: {
48 flags.set(TR_RES_FEAR);
54 case PlayerClassType::SAMURAI: {
56 flags.set(TR_RES_FEAR);
60 case PlayerClassType::PALADIN: {
62 flags.set(TR_RES_FEAR);
66 case PlayerClassType::CHAOS_WARRIOR: {
68 flags.set(TR_RES_CHAOS);
70 flags.set(TR_RES_FEAR);
74 case PlayerClassType::MONK:
75 case PlayerClassType::FORCETRAINER: {
76 if ((plev > 9) && !heavy_armor(this->player_ptr))
78 if ((plev > 24) && !heavy_armor(this->player_ptr))
79 flags.set(TR_FREE_ACT);
83 case PlayerClassType::NINJA: {
84 if (heavy_armor(this->player_ptr)) {
87 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)))
89 if (plev > 24 && !this->player_ptr->is_icky_wield[0] && !this->player_ptr->is_icky_wield[1])
90 flags.set(TR_FREE_ACT);
93 flags.set(TR_SLOW_DIGEST);
94 flags.set(TR_RES_FEAR);
96 flags.set(TR_RES_POIS);
98 flags.set(TR_SUST_DEX);
100 flags.set(TR_SEE_INVIS);
104 case PlayerClassType::MINDCRAFTER: {
106 flags.set(TR_RES_FEAR);
108 flags.set(TR_SUST_WIS);
110 flags.set(TR_RES_CONF);
112 flags.set(TR_TELEPATHY);
116 case PlayerClassType::BARD: {
117 flags.set(TR_RES_SOUND);
120 case PlayerClassType::BERSERKER: {
121 flags.set(TR_SUST_STR);
122 flags.set(TR_SUST_DEX);
123 flags.set(TR_SUST_CON);
125 flags.set(TR_FREE_ACT);
128 flags.set(TR_REFLECT);
132 case PlayerClassType::MIRROR_MASTER: {
134 flags.set(TR_REFLECT);
138 case PlayerClassType::ELEMENTALIST:
139 if (has_element_resist(this->player_ptr, ElementRealm::FIRE, 1))
140 flags.set(TR_RES_FIRE);
141 if (has_element_resist(this->player_ptr, ElementRealm::FIRE, 30))
142 flags.set(TR_IM_FIRE);
143 if (has_element_resist(this->player_ptr, ElementRealm::ICE, 1))
144 flags.set(TR_RES_COLD);
145 if (has_element_resist(this->player_ptr, ElementRealm::ICE, 30))
146 flags.set(TR_IM_COLD);
147 if (has_element_resist(this->player_ptr, ElementRealm::SKY, 1))
148 flags.set(TR_RES_ELEC);
149 if (has_element_resist(this->player_ptr, ElementRealm::SKY, 30))
150 flags.set(TR_IM_ELEC);
151 if (has_element_resist(this->player_ptr, ElementRealm::SEA, 1))
152 flags.set(TR_RES_ACID);
153 if (has_element_resist(this->player_ptr, ElementRealm::SEA, 30))
154 flags.set(TR_IM_ACID);
155 if (has_element_resist(this->player_ptr, ElementRealm::DARKNESS, 1))
156 flags.set(TR_RES_DARK);
157 if (has_element_resist(this->player_ptr, ElementRealm::DARKNESS, 30))
158 flags.set(TR_RES_NETHER);
159 if (has_element_resist(this->player_ptr, ElementRealm::CHAOS, 1))
160 flags.set(TR_RES_CONF);
161 if (has_element_resist(this->player_ptr, ElementRealm::CHAOS, 30))
162 flags.set(TR_RES_CHAOS);
163 if (has_element_resist(this->player_ptr, ElementRealm::EARTH, 1))
164 flags.set(TR_RES_SHARDS);
165 if (has_element_resist(this->player_ptr, ElementRealm::EARTH, 30))
166 flags.set(TR_REFLECT);
167 if (has_element_resist(this->player_ptr, ElementRealm::DEATH, 1))
168 flags.set(TR_RES_POIS);
169 if (has_element_resist(this->player_ptr, ElementRealm::DEATH, 30))
170 flags.set(TR_RES_DISEN);
179 TrFlags PlayerClass::stance_tr_flags() const
183 switch (this->get_samurai_stance()) {
184 case SamuraiStance::FUUJIN:
185 if (!this->player_ptr->blind) {
186 flags.set(TR_REFLECT);
189 case SamuraiStance::MUSOU:
190 flags.set({ TR_RES_ACID, TR_RES_ELEC, TR_RES_FIRE, TR_RES_COLD, TR_RES_POIS });
191 flags.set({ TR_REFLECT, TR_RES_FEAR, TR_RES_LITE, TR_RES_DARK, TR_RES_BLIND, TR_RES_CONF,
192 TR_RES_SOUND, TR_RES_SHARDS, TR_RES_NETHER, TR_RES_NEXUS, TR_RES_CHAOS, TR_RES_DISEN,
193 TR_RES_WATER, TR_RES_TIME, TR_RES_CURSE });
194 flags.set({ TR_HOLD_EXP, TR_FREE_ACT, TR_LEVITATION, TR_LITE_1, TR_SEE_INVIS, TR_TELEPATHY, TR_SLOW_DIGEST, TR_REGEN });
195 flags.set({ TR_SH_FIRE, TR_SH_ELEC, TR_SH_COLD });
196 flags.set({ TR_SUST_STR, TR_SUST_INT, TR_SUST_WIS, TR_SUST_DEX, TR_SUST_CON, TR_SUST_CHR });
198 case SamuraiStance::KOUKIJIN:
199 flags.set({ TR_VUL_ACID, TR_VUL_ELEC, TR_VUL_FIRE, TR_VUL_COLD });
205 switch (this->get_monk_stance()) {
206 case MonkStance::GENBU:
207 flags.set(TR_REFLECT);
209 case MonkStance::SUZAKU:
210 flags.set(TR_LEVITATION);
212 case MonkStance::SEIRYU:
213 flags.set({ TR_RES_ACID, TR_RES_ELEC, TR_RES_FIRE, TR_RES_COLD, TR_RES_POIS });
214 flags.set({ TR_SH_FIRE, TR_SH_ELEC, TR_SH_COLD });
215 flags.set(TR_LEVITATION);
224 bool PlayerClass::has_stun_immunity() const
226 return (this->player_ptr->pclass == PlayerClassType::BERSERKER) && (this->player_ptr->lev > 34);
229 bool PlayerClass::is_wizard() const
231 auto is_wizard = this->player_ptr->pclass == PlayerClassType::MAGE;
232 is_wizard |= this->player_ptr->pclass == PlayerClassType::HIGH_MAGE;
233 is_wizard |= this->player_ptr->pclass == PlayerClassType::SORCERER;
234 is_wizard |= this->player_ptr->pclass == PlayerClassType::MAGIC_EATER;
235 is_wizard |= this->player_ptr->pclass == PlayerClassType::BLUE_MAGE;
236 is_wizard |= this->player_ptr->pclass == PlayerClassType::ELEMENTALIST;
240 bool PlayerClass::lose_balance()
242 if (this->player_ptr->pclass != PlayerClassType::SAMURAI) {
246 if (this->samurai_stance_is(SamuraiStance::NONE)) {
250 this->set_samurai_stance(SamuraiStance::NONE);
251 this->player_ptr->update |= PU_BONUS;
252 this->player_ptr->update |= PU_MONSTERS;
253 this->player_ptr->redraw |= PR_STATE;
254 this->player_ptr->redraw |= PR_STATUS;
255 this->player_ptr->action = ACTION_NONE;
259 SamuraiStance PlayerClass::get_samurai_stance() const
261 auto samurai_data = this->get_specific_data<samurai_data_type>();
263 return SamuraiStance::NONE;
266 return samurai_data->stance;
269 bool PlayerClass::samurai_stance_is(SamuraiStance stance) const
271 return this->get_samurai_stance() == stance;
277 * @param stance_list 崩す型を指定する。取っている型が指定された型に含まれない場合は崩さない。
279 void PlayerClass::break_samurai_stance(std::initializer_list<SamuraiStance> stance_list)
281 auto samurai_data = this->get_specific_data<samurai_data_type>();
286 for (auto stance : stance_list) {
287 if (samurai_data->stance == stance) {
288 set_action(player_ptr, ACTION_NONE);
289 samurai_data->stance = SamuraiStance::NONE;
295 void PlayerClass::set_samurai_stance(SamuraiStance stance) const
297 auto samurai_data = this->get_specific_data<samurai_data_type>();
302 samurai_data->stance = stance;
305 MonkStance PlayerClass::get_monk_stance() const
307 auto monk_data = this->get_specific_data<monk_data_type>();
309 return MonkStance::NONE;
312 return monk_data->stance;
315 bool PlayerClass::monk_stance_is(MonkStance stance) const
317 return this->get_monk_stance() == stance;
320 void PlayerClass::set_monk_stance(MonkStance stance) const
322 auto monk_data = this->get_specific_data<monk_data_type>();
327 monk_data->stance = stance;
331 * @brief プレイヤーの職業にで使用する職業固有データ領域を初期化する
332 * @details 事前条件: player_type の職業や領域が決定済みであること
334 void PlayerClass::init_specific_data()
336 switch (this->player_ptr->pclass) {
337 case PlayerClassType::SMITH:
338 this->player_ptr->class_specific_data = std::make_shared<smith_data_type>();
340 case PlayerClassType::FORCETRAINER:
341 this->player_ptr->class_specific_data = std::make_shared<force_trainer_data_type>();
343 case PlayerClassType::BLUE_MAGE:
344 this->player_ptr->class_specific_data = std::make_shared<bluemage_data_type>();
346 case PlayerClassType::MAGIC_EATER:
347 this->player_ptr->class_specific_data = std::make_shared<magic_eater_data_type>();
349 case PlayerClassType::BARD:
350 this->player_ptr->class_specific_data = std::make_shared<bard_data_type>();
352 case PlayerClassType::IMITATOR:
353 this->player_ptr->class_specific_data = std::make_shared<mane_data_type>();
355 case PlayerClassType::SNIPER:
356 this->player_ptr->class_specific_data = std::make_shared<sniper_data_type>();
358 case PlayerClassType::SAMURAI:
359 this->player_ptr->class_specific_data = std::make_shared<samurai_data_type>();
361 case PlayerClassType::MONK:
362 this->player_ptr->class_specific_data = std::make_shared<monk_data_type>();
364 case PlayerClassType::NINJA:
365 this->player_ptr->class_specific_data = std::make_shared<ninja_data_type>();
367 case PlayerClassType::HIGH_MAGE:
368 if (this->player_ptr->realm1 == REALM_HEX) {
369 this->player_ptr->class_specific_data = std::make_shared<spell_hex_data_type>();
371 this->player_ptr->class_specific_data = no_class_specific_data();
375 this->player_ptr->class_specific_data = no_class_specific_data();