1 #include "status/base-status.h"
2 #include "avatar/avatar.h"
3 #include "core/window-redrawer.h"
4 #include "game-option/birth-options.h"
5 #include "inventory/inventory-slot-types.h"
6 #include "object-enchant/item-feeling.h"
7 #include "object-enchant/special-object-flags.h"
8 #include "perception/object-perception.h"
9 #include "player/player-status-flags.h"
10 #include "spell-kind/spells-floor.h"
11 #include "system/item-entity.h"
12 #include "system/player-type-definition.h"
13 #include "system/redrawing-flags-updater.h"
14 #include "util/bit-flags-calculator.h"
15 #include "view/display-messages.h"
17 /* Array of stat "descriptions" */
18 static concptr desc_stat_pos[] = {
22 _("器用に", "more dextrous"),
23 _("健康に", "healthier"),
27 /* Array of stat "descriptions" */
28 static concptr desc_stat_neg[] = {
31 _("愚かに", "more naive"),
32 _("不器用に", "clumsier"),
33 _("不健康に", "more sickly"),
38 * @brief プレイヤーの基本能力値を増加させる / Increases a stat by one randomized level -RAK-
39 * @param stat 上昇させるステータスID
40 * @return 実際に上昇した場合TRUEを返す。
42 * Note that this function (used by stat potions) now restores\n
43 * the stat BEFORE increasing it.\n
45 bool inc_stat(PlayerType *player_ptr, int stat)
47 auto value = player_ptr->stat_cur[stat];
48 if (value >= player_ptr->stat_max_max[stat]) {
53 value += (randint0(100) < 75) ? 1 : 2;
54 } else if (value < (player_ptr->stat_max_max[stat] - 2)) {
55 auto gain = (((player_ptr->stat_max_max[stat]) - value) / 2 + 3) / 2;
60 value += randint1(gain) + gain / 2;
61 if (value > (player_ptr->stat_max_max[stat] - 1)) {
62 value = player_ptr->stat_max_max[stat] - 1;
68 player_ptr->stat_cur[stat] = value;
69 if (value > player_ptr->stat_max[stat]) {
70 player_ptr->stat_max[stat] = value;
73 RedrawingFlagsUpdater::get_instance().set_flag(StatusRedrawingFlag::BONUS);
78 * @brief プレイヤーの基本能力値を減少させる / Decreases a stat by an amount indended to vary from 0 to 100 percent.
79 * @param stat 減少させるステータスID
80 * @param amount 減少させる基本量
81 * @param permanent TRUEならば現在の最大値を減少させる
82 * @return 実際に減少した場合TRUEを返す。
85 * Amount could be a little higher in extreme cases to mangle very high\n
86 * stats from massive assaults. -CWS\n
88 * Note that "permanent" means that the *given* amount is permanent,\n
89 * not that the new value becomes permanent. This may not work exactly\n
90 * as expected, due to "weirdness" in the algorithm, but in general,\n
91 * if your stat is already drained, the "max" value will not drop all\n
92 * the way down to the "cur" value.\n
94 bool dec_stat(PlayerType *player_ptr, int stat, int amount, int permanent)
97 auto cur = player_ptr->stat_cur[stat];
98 auto max = player_ptr->stat_max[stat];
99 int same = (cur == max);
113 int loss = (((cur - 18) / 2 + 1) / 2 + 1);
118 loss = ((randint1(loss) + loss) * amount) / 100;
119 if (loss < amount / 2) {
125 cur = (amount <= 20) ? 18 : 17;
133 if (cur != player_ptr->stat_cur[stat]) {
138 if (permanent && (max > 3)) {
139 chg_virtue(player_ptr, Virtue::SACRIFICE, 1);
140 if (stat == A_WIS || stat == A_INT) {
141 chg_virtue(player_ptr, Virtue::ENLIGHTEN, -2);
156 int loss = (((max - 18) / 2 + 1) / 2 + 1);
157 loss = ((randint1(loss) + loss) * amount) / 100;
158 if (loss < amount / 2) {
164 max = (amount <= 20) ? 18 : 17;
168 if (same || (max < cur)) {
172 if (max != player_ptr->stat_max[stat]) {
178 player_ptr->stat_cur[stat] = cur;
179 player_ptr->stat_max[stat] = max;
180 auto &rfu = RedrawingFlagsUpdater::get_instance();
181 rfu.set_flag(MainWindowRedrawingFlag::ABILITY_SCORE);
182 rfu.set_flag(StatusRedrawingFlag::BONUS);
189 * @brief プレイヤーの基本能力値を回復させる / Restore a stat. Return TRUE only if this actually makes a difference.
190 * @param stat 回復ステータスID
191 * @return 実際に回復した場合TRUEを返す。
193 bool res_stat(PlayerType *player_ptr, int stat)
195 if (player_ptr->stat_cur[stat] != player_ptr->stat_max[stat]) {
196 player_ptr->stat_cur[stat] = player_ptr->stat_max[stat];
197 auto &rfu = RedrawingFlagsUpdater::get_instance();
198 rfu.set_flag(StatusRedrawingFlag::BONUS);
199 rfu.set_flag(MainWindowRedrawingFlag::ABILITY_SCORE);
209 bool do_dec_stat(PlayerType *player_ptr, int stat)
214 if (has_sustain_str(player_ptr)) {
219 if (has_sustain_int(player_ptr)) {
224 if (has_sustain_wis(player_ptr)) {
229 if (has_sustain_dex(player_ptr)) {
234 if (has_sustain_con(player_ptr)) {
239 if (has_sustain_chr(player_ptr)) {
245 if (sust && (!ironman_nightmare || randint0(13))) {
246 msg_format(_("%sなった気がしたが、すぐに元に戻った。", "You feel %s for a moment, but the feeling passes."), desc_stat_neg[stat]);
250 if (dec_stat(player_ptr, stat, 10, (ironman_nightmare && !randint0(13)))) {
251 msg_format(_("ひどく%sなった気がする。", "You feel %s."), desc_stat_neg[stat]);
259 * Restore lost "points" in a stat
261 bool do_res_stat(PlayerType *player_ptr, int stat)
263 if (res_stat(player_ptr, stat)) {
264 msg_format(_("元通りに%sなった気がする。", "You feel %s."), desc_stat_pos[stat]);
272 * Gain a "point" in a stat
274 bool do_inc_stat(PlayerType *player_ptr, int stat)
276 bool res = res_stat(player_ptr, stat);
277 if (inc_stat(player_ptr, stat)) {
279 chg_virtue(player_ptr, Virtue::ENLIGHTEN, 1);
280 chg_virtue(player_ptr, Virtue::FAITH, 1);
281 } else if (stat == A_INT) {
282 chg_virtue(player_ptr, Virtue::KNOWLEDGE, 1);
283 chg_virtue(player_ptr, Virtue::ENLIGHTEN, 1);
284 } else if (stat == A_CON) {
285 chg_virtue(player_ptr, Virtue::VITALITY, 1);
288 msg_format(_("ワーオ!とても%sなった!", "Wow! You feel %s!"), desc_stat_pos[stat]);
293 msg_format(_("元通りに%sなった気がする。", "You feel %s."), desc_stat_pos[stat]);
303 bool lose_all_info(PlayerType *player_ptr)
305 chg_virtue(player_ptr, Virtue::KNOWLEDGE, -5);
306 chg_virtue(player_ptr, Virtue::ENLIGHTEN, -5);
307 for (int i = 0; i < INVEN_TOTAL; i++) {
308 auto *o_ptr = &player_ptr->inventory_list[i];
309 if (!o_ptr->is_valid() || o_ptr->is_fully_known()) {
313 o_ptr->feeling = FEEL_NONE;
314 o_ptr->ident &= ~(IDENT_EMPTY);
315 o_ptr->ident &= ~(IDENT_KNOWN);
316 o_ptr->ident &= ~(IDENT_SENSE);
319 auto &rfu = RedrawingFlagsUpdater::get_instance();
320 const auto flags_srf = {
321 StatusRedrawingFlag::BONUS,
322 StatusRedrawingFlag::COMBINATION,
323 StatusRedrawingFlag::REORDER,
325 rfu.set_flags(flags_srf);
326 set_bits(player_ptr->window_flags, PW_INVENTORY | PW_EQUIPMENT | PW_PLAYER | PW_FLOOR_ITEMS | PW_FOUND_ITEMS);
327 wiz_dark(player_ptr);