OSDN Git Service

Merge pull request #3569 from sikabane-works/release/3.0.0.88-alpha
[hengbandforosx/hengbandosx.git] / src / timed-effect / player-stun.cpp
1 #include "timed-effect/player-stun.h"
2 #include "system/angband-exceptions.h"
3 #include "system/angband.h"
4
5 enum class PlayerStunRank {
6     NONE = 0,
7     SLIGHT = 1,
8     NORMAL = 2,
9     HARD = 3,
10     UNCONSCIOUS = 4,
11     KNOCKED = 5,
12 };
13
14 PlayerStunRank PlayerStun::get_rank(short value)
15 {
16     if (value > 200) {
17         return PlayerStunRank::KNOCKED;
18     }
19
20     if (value > 150) {
21         return PlayerStunRank::UNCONSCIOUS;
22     }
23
24     if (value > 100) {
25         return PlayerStunRank::HARD;
26     }
27
28     if (value > 50) {
29         return PlayerStunRank::NORMAL;
30     }
31
32     if (value > 0) {
33         return PlayerStunRank::SLIGHT;
34     }
35
36     return PlayerStunRank::NONE;
37 }
38
39 std::string_view PlayerStun::get_stun_mes(PlayerStunRank stun_rank)
40 {
41     switch (stun_rank) {
42     case PlayerStunRank::NONE:
43         return "";
44     case PlayerStunRank::SLIGHT:
45         return _("意識が少しもうろうとしてきた。", "You have been slightly stunned.");
46     case PlayerStunRank::NORMAL:
47         return _("意識がもうろうとしてきた。", "You have been stunned.");
48     case PlayerStunRank::HARD:
49         return _("意識がひどくもうろうとしてきた。", "You have been heavily stunned.");
50     case PlayerStunRank::UNCONSCIOUS:
51         return _("頭がクラクラして意識が遠のいてきた。", "You have been unconcious.");
52     case PlayerStunRank::KNOCKED:
53         return _("あなたはぶっ倒れた!", "You are knocked out!!");
54     default:
55         THROW_EXCEPTION(std::logic_error, "Invalid StunRank is specified!");
56     }
57 }
58
59 short PlayerStun::get_accumulation(int rank)
60 {
61     switch (rank) {
62     case 0:
63         return 0;
64     case 1:
65         return randint1(10);
66     case 2:
67         return randint1(10) + 10;
68     case 3:
69         return randint1(10) + 20;
70     case 4:
71         return randint1(10) + 30;
72     case 5:
73         return randint1(10) + 40;
74     case 6:
75         return randint1(10) + 50;
76     case 7:
77         return randint1(10) + 60;
78     default: // 8 or more.
79         return randint1(10) + 70;
80     }
81 }
82
83 /*!
84  * @brief モンスター打撃の朦朧蓄積ランクを返す.
85  * @param total 痛恨の一撃でない場合の最大ダメージ
86  * @param dam プレイヤーに与えた実際のダメージ
87  * @return 朦朧蓄積ランク
88  * @details
89  * totalは、ダイスXdY に対し、X*Y
90  * damageは、痛恨 かつ AC < 125 ならばtotalを超える可能性あり
91  */
92 int PlayerStun::get_accumulation_rank(int total, int damage)
93 {
94     auto is_no_stun = damage < total * 19 / 20;
95     is_no_stun |= damage <= 20;
96     if (is_no_stun) {
97         return 0;
98     }
99
100     if (damage > 256) {
101         return 8;
102     }
103
104     if (damage > 111) {
105         return 7;
106     }
107
108     if (damage > 96) {
109         return 6;
110     }
111
112     if (damage > 81) {
113         return 5;
114     }
115
116     if (damage > 66) {
117         return 4;
118     }
119
120     if (damage > 51) {
121         return 3;
122     }
123
124     if (damage > 36) {
125         return 2;
126     }
127
128     // damage > 21.
129     return 1;
130 }
131
132 short PlayerStun::current() const
133 {
134     return this->stun;
135 }
136
137 PlayerStunRank PlayerStun::get_rank() const
138 {
139     return this->get_rank(this->stun);
140 }
141
142 /*!
143  * @brief 朦朧ランクに応じて魔法系の失率を上げる.
144  * @return 失率
145  * @details
146  * 昏倒ならばそもそも動けないのでこのメソッドを通らない.
147  * しかし今後の拡張を考慮して100%としておく.
148  */
149 int PlayerStun::get_magic_chance_penalty() const
150 {
151     switch (this->get_rank()) {
152     case PlayerStunRank::NONE:
153         return 0;
154     case PlayerStunRank::SLIGHT:
155         return 10;
156     case PlayerStunRank::NORMAL:
157         return 20;
158     case PlayerStunRank::HARD:
159         return 30;
160     case PlayerStunRank::UNCONSCIOUS:
161         return 50;
162     case PlayerStunRank::KNOCKED:
163         return 100;
164     default:
165         THROW_EXCEPTION(std::logic_error, "Invalid StunRank is specified!");
166     }
167 }
168
169 /*!
170  * @brief 朦朧ランクに応じてアイテム使用の失率を上げる.
171  * @return リファクタリング中の暫定的な値 (意識不明瞭ならば100%、それ以外は常に0%)
172  * @details
173  * 昏倒ならばそもそも動けないのでこのメソッドを通らない.
174  * しかし今後の拡張を考慮して100%としておく.
175  */
176 int PlayerStun::get_item_chance_penalty() const
177 {
178     switch (this->get_rank()) {
179     case PlayerStunRank::NONE:
180     case PlayerStunRank::SLIGHT:
181     case PlayerStunRank::NORMAL:
182         return 0;
183     case PlayerStunRank::HARD:
184         return 5;
185     case PlayerStunRank::UNCONSCIOUS:
186         return 10;
187     case PlayerStunRank::KNOCKED:
188         return 100;
189     default:
190         THROW_EXCEPTION(std::logic_error, "Invalid StunRank is specified!");
191     }
192 }
193
194 /*!
195  * @brief 朦朧ランクに応じてダメージ量 or 命中率を下げる.
196  * @return 朦朧ならば5、ひどく朦朧ならば20.
197  * @details
198  * 呼び出し元で減算しているのでこのメソッドでは正値.
199  * 意識不明瞭ならばそもそも動けないのでこのメソッドを通らない.
200  * しかし今後の拡張を考慮して100としておく.
201  */
202 short PlayerStun::get_damage_penalty() const
203 {
204     switch (this->get_rank()) {
205     case PlayerStunRank::NONE:
206         return 0;
207     case PlayerStunRank::SLIGHT:
208         return 5;
209     case PlayerStunRank::NORMAL:
210         return 10;
211     case PlayerStunRank::HARD:
212         return 20;
213     case PlayerStunRank::UNCONSCIOUS:
214         return 40;
215     case PlayerStunRank::KNOCKED:
216         return 100;
217     default:
218         THROW_EXCEPTION(std::logic_error, "Invalid StunRank is specified!");
219     }
220 }
221
222 /*!
223  * @brief プレイヤーが朦朧しているかを返す
224  * @return 朦朧状態ならばtrue、頭がハッキリしているならばfalse
225  */
226 bool PlayerStun::is_stunned() const
227 {
228     return this->get_rank() > PlayerStunRank::NONE;
229 }
230
231 /*!
232  * @brief プレイヤーが朦朧で行動不能かを返す
233  * @return 昏倒状態ならばtrue、それ以外ならばfalse
234  */
235 bool PlayerStun::is_knocked_out() const
236 {
237     return this->get_rank() == PlayerStunRank::KNOCKED;
238 }
239
240 std::tuple<term_color_type, std::string_view> PlayerStun::get_expr() const
241 {
242     switch (this->get_rank()) {
243     case PlayerStunRank::NONE: // dummy.
244         return std::make_tuple(TERM_WHITE, "            ");
245     case PlayerStunRank::SLIGHT:
246         return std::make_tuple(TERM_WHITE, _("やや朦朧    ", "Slight stun "));
247     case PlayerStunRank::NORMAL:
248         return std::make_tuple(TERM_YELLOW, _("朦朧        ", "Stun        "));
249     case PlayerStunRank::HARD:
250         return std::make_tuple(TERM_ORANGE, _("ひどく朦朧  ", "Heavy stun  "));
251     case PlayerStunRank::UNCONSCIOUS:
252         return std::make_tuple(TERM_RED, _("意識不明瞭  ", "Unconcious  "));
253     case PlayerStunRank::KNOCKED:
254         return std::make_tuple(TERM_VIOLET, _("昏倒        ", "Knocked out "));
255     default:
256         THROW_EXCEPTION(std::logic_error, "Invalid StunRank is specified!");
257     }
258 }
259
260 void PlayerStun::set(short value)
261 {
262     this->stun = value;
263 }
264
265 void PlayerStun::reset()
266 {
267     this->set(0);
268 }