OSDN Git Service

[Refactor] 乗馬スキルの上昇処理を PlayerSkill クラスに移設
[hengbandforosx/hengbandosx.git] / src / player / player-skill.cpp
1 #include "player/player-skill.h"
2 #include "core/player-update-types.h"
3 #include "monster-race/monster-race.h"
4 #include "system/floor-type-definition.h"
5 #include "system/monster-race-definition.h"
6 #include "system/monster-type-definition.h"
7 #include "system/object-type-definition.h"
8 #include "system/player-type-definition.h"
9 #include "util/bit-flags-calculator.h"
10
11 /* Proficiency of weapons and misc. skills (except riding) */
12 constexpr SUB_EXP WEAPON_EXP_UNSKILLED = 0;
13 constexpr SUB_EXP WEAPON_EXP_BEGINNER = 4000;
14 constexpr SUB_EXP WEAPON_EXP_SKILLED = 6000;
15 constexpr SUB_EXP WEAPON_EXP_EXPERT = 7000;
16 constexpr SUB_EXP WEAPON_EXP_MASTER = 8000;
17
18 /* Proficiency of riding */
19 constexpr SUB_EXP RIDING_EXP_UNSKILLED = 0;
20 constexpr SUB_EXP RIDING_EXP_BEGINNER = 500;
21 constexpr SUB_EXP RIDING_EXP_SKILLED = 2000;
22 constexpr SUB_EXP RIDING_EXP_EXPERT = 5000;
23 constexpr SUB_EXP RIDING_EXP_MASTER = 8000;
24
25 /*
26  * The skill table
27  */
28 std::vector<skill_table> s_info;
29
30 /*!
31  * @brief 技能値到達表記テーブル
32  */
33 const concptr exp_level_str[5] =
34 #ifdef JP
35     { "[初心者]", "[入門者]", "[熟練者]", "[エキスパート]", "[達人]" };
36 #else
37     { "[Unskilled]", "[Beginner]", "[Skilled]", "[Expert]", "[Master]" };
38 #endif
39
40 PlayerSkill::PlayerSkill(player_type *player_ptr)
41     : player_ptr(player_ptr)
42 {
43 }
44
45 SUB_EXP PlayerSkill::weapon_exp_at(int level)
46 {
47     switch (level) {
48     case EXP_LEVEL_UNSKILLED:
49         return WEAPON_EXP_UNSKILLED;
50     case EXP_LEVEL_BEGINNER:
51         return WEAPON_EXP_BEGINNER;
52     case EXP_LEVEL_SKILLED:
53         return WEAPON_EXP_SKILLED;
54     case EXP_LEVEL_EXPERT:
55         return WEAPON_EXP_EXPERT;
56     case EXP_LEVEL_MASTER:
57         return WEAPON_EXP_MASTER;
58     }
59
60     return WEAPON_EXP_UNSKILLED;
61 }
62
63 /*!
64  * @brief 武器や各種スキル(騎乗以外)の抽象的表現ランクを返す。 /  Return proficiency level of weapons and misc. skills (except riding)
65  * @param weapon_exp 経験値
66  * @return ランク値
67  */
68 int PlayerSkill::weapon_exp_level(int weapon_exp)
69 {
70     if (weapon_exp < WEAPON_EXP_BEGINNER)
71         return EXP_LEVEL_UNSKILLED;
72     else if (weapon_exp < WEAPON_EXP_SKILLED)
73         return EXP_LEVEL_BEGINNER;
74     else if (weapon_exp < WEAPON_EXP_EXPERT)
75         return EXP_LEVEL_SKILLED;
76     else if (weapon_exp < WEAPON_EXP_MASTER)
77         return EXP_LEVEL_EXPERT;
78     else
79         return EXP_LEVEL_MASTER;
80 }
81
82 bool PlayerSkill::valid_weapon_exp(int weapon_exp)
83 {
84     return (WEAPON_EXP_UNSKILLED <= weapon_exp) && (weapon_exp <= WEAPON_EXP_MASTER);
85 }
86
87 /*!
88  * @brief 騎乗スキルの抽象的ランクを返す。 / Return proficiency level of riding
89  * @param riding_exp 経験値
90  * @return ランク値
91  */
92 int PlayerSkill::riding_exp_level(int riding_exp)
93 {
94     if (riding_exp < RIDING_EXP_BEGINNER)
95         return EXP_LEVEL_UNSKILLED;
96     else if (riding_exp < RIDING_EXP_SKILLED)
97         return EXP_LEVEL_BEGINNER;
98     else if (riding_exp < RIDING_EXP_EXPERT)
99         return EXP_LEVEL_SKILLED;
100     else if (riding_exp < RIDING_EXP_MASTER)
101         return EXP_LEVEL_EXPERT;
102     else
103         return EXP_LEVEL_MASTER;
104 }
105
106 void PlayerSkill::gain_melee_weapon_exp(const object_type *o_ptr)
107 {
108     auto now_exp = this->player_ptr->weapon_exp[o_ptr->tval][o_ptr->sval];
109     if (now_exp >= s_info[enum2i(this->player_ptr->pclass)].w_max[o_ptr->tval][o_ptr->sval])
110         return;
111
112     SUB_EXP amount = 0;
113     if (now_exp < WEAPON_EXP_BEGINNER)
114         amount = 80;
115     else if (now_exp < WEAPON_EXP_SKILLED)
116         amount = 10;
117     else if ((now_exp < WEAPON_EXP_EXPERT) && (this->player_ptr->lev > 19))
118         amount = 1;
119     else if ((player_ptr->lev > 34) && one_in_(2))
120         amount = 1;
121
122     this->player_ptr->weapon_exp[o_ptr->tval][o_ptr->sval] += amount;
123     set_bits(this->player_ptr->update, PU_BONUS);
124 }
125
126 void PlayerSkill::gain_range_weapon_exp(const object_type *o_ptr)
127 {
128     auto now_exp = this->player_ptr->weapon_exp[o_ptr->tval][o_ptr->sval];
129     if (now_exp >= s_info[enum2i(this->player_ptr->pclass)].w_max[o_ptr->tval][o_ptr->sval])
130         return;
131
132     SUB_EXP amount = 0;
133     if (now_exp < WEAPON_EXP_BEGINNER)
134         amount = 80;
135     else if (now_exp < WEAPON_EXP_SKILLED)
136         amount = 25;
137     else if ((now_exp < WEAPON_EXP_EXPERT) && (this->player_ptr->lev > 19))
138         amount = 10;
139     else if (this->player_ptr->lev > 34)
140         amount = 2;
141
142     this->player_ptr->weapon_exp[o_ptr->tval][o_ptr->sval] += amount;
143     set_bits(this->player_ptr->update, PU_BONUS);
144 }
145
146 void PlayerSkill::gain_martial_arts_skill_exp()
147 {
148     auto now_exp = this->player_ptr->skill_exp[SKILL_MARTIAL_ARTS];
149     if (now_exp >= s_info[enum2i(this->player_ptr->pclass)].s_max[SKILL_MARTIAL_ARTS])
150         return;
151
152     SUB_EXP amount = 0;
153     if (now_exp < WEAPON_EXP_BEGINNER)
154         amount = 40;
155     else if (now_exp < WEAPON_EXP_SKILLED)
156         amount = 5;
157     else if ((now_exp < WEAPON_EXP_EXPERT) && (this->player_ptr->lev > 19))
158         amount = 1;
159     else if ((this->player_ptr->lev > 34) && one_in_(3))
160         amount = 1;
161
162     this->player_ptr->skill_exp[SKILL_MARTIAL_ARTS] += amount;
163     set_bits(this->player_ptr->update, PU_BONUS);
164 }
165
166 void PlayerSkill::gain_two_weapon_skill_exp()
167 {
168     auto now_exp = this->player_ptr->skill_exp[SKILL_TWO_WEAPON];
169     if (now_exp >= s_info[enum2i(this->player_ptr->pclass)].s_max[SKILL_TWO_WEAPON])
170         return;
171
172     SUB_EXP amount = 0;
173     if (now_exp < WEAPON_EXP_BEGINNER)
174         amount = 80;
175     else if (now_exp < WEAPON_EXP_SKILLED)
176         amount = 4;
177     else if ((now_exp < WEAPON_EXP_EXPERT) && (this->player_ptr->lev > 19))
178         amount = 1;
179     else if ((this->player_ptr->lev > 34) && one_in_(3))
180         amount = 1;
181
182     this->player_ptr->skill_exp[SKILL_TWO_WEAPON] += amount;
183     set_bits(this->player_ptr->update, PU_BONUS);
184 }
185
186 void PlayerSkill::gain_riding_skill_exp_on_melee_attack(const monster_race *r_ptr)
187 {
188     auto now_exp = this->player_ptr->skill_exp[SKILL_RIDING];
189     auto max_exp = s_info[enum2i(this->player_ptr->pclass)].s_max[SKILL_RIDING];
190     if (now_exp >= max_exp)
191         return;
192
193     auto riding_level = r_info[this->player_ptr->current_floor_ptr->m_list[this->player_ptr->riding].r_idx].level;
194     int inc = 0;
195
196     if ((now_exp / 200 - 5) < r_ptr->level)
197         inc += 1;
198
199     if ((now_exp / 100) < riding_level) {
200         if ((now_exp / 100 + 15) < riding_level)
201             inc += 1 + (riding_level - (now_exp / 100 + 15));
202         else
203             inc += 1;
204     }
205
206     this->player_ptr->skill_exp[SKILL_RIDING] = std::min<SUB_EXP>(max_exp, now_exp + inc);
207     set_bits(this->player_ptr->update, PU_BONUS);
208 }
209
210 void PlayerSkill::gain_riding_skill_exp_on_range_attack()
211 {
212     auto now_exp = this->player_ptr->skill_exp[SKILL_RIDING];
213     auto max_exp = s_info[enum2i(this->player_ptr->pclass)].s_max[SKILL_RIDING];
214     if (now_exp >= max_exp)
215         return;
216
217     if (((this->player_ptr->skill_exp[SKILL_RIDING] - (RIDING_EXP_BEGINNER * 2)) / 200 < r_info[this->player_ptr->current_floor_ptr->m_list[this->player_ptr->riding].r_idx].level) && one_in_(2)) {
218         this->player_ptr->skill_exp[SKILL_RIDING] += 1;
219         set_bits(this->player_ptr->update, PU_BONUS);
220     }
221 }
222
223 void PlayerSkill::gain_riding_skill_exp_on_fall_off_check(HIT_POINT dam)
224 {
225     auto now_exp = this->player_ptr->skill_exp[SKILL_RIDING];
226     auto max_exp = s_info[enum2i(this->player_ptr->pclass)].s_max[SKILL_RIDING];
227     if (now_exp >= max_exp || max_exp <= 1000)
228         return;
229
230     auto riding_level = r_info[this->player_ptr->current_floor_ptr->m_list[this->player_ptr->riding].r_idx].level;
231
232     if ((dam / 2 + riding_level) <= (now_exp / 30 + 10))
233         return;
234
235     int inc = 0;
236     if ((now_exp / 100 + 15) < riding_level)
237         inc += 1 + (riding_level - (now_exp / 100 + 15));
238     else
239         inc += 1;
240
241     player_ptr->skill_exp[SKILL_RIDING] = std::min<SUB_EXP>(max_exp, now_exp + inc);
242     set_bits(this->player_ptr->update, PU_BONUS);
243 }