OSDN Git Service

90c1a1d6bddf567132d7237d86ae8a635a7c37d6
[hengbandforosx/hengbandosx.git] / src / action / racial-execution.cpp
1 /*!
2  * @file racial-execution.cpp
3  * @brief レイシャルパワー実行処理実装
4  */
5
6 #include "action/racial-execution.h"
7 #include "action/action-limited.h"
8 #include "artifact/fixed-art-types.h"
9 #include "core/asking-player.h"
10 #include "game-option/disturbance-options.h"
11 #include "inventory/inventory-slot-types.h"
12 #include "player-status/player-energy.h"
13 #include "racial/racial-switcher.h"
14 #include "racial/racial-util.h"
15 #include "system/object-type-definition.h"
16 #include "system/player-type-definition.h"
17 #include "term/screen-processor.h"
18 #include "timed-effect/player-stun.h"
19 #include "timed-effect/timed-effects.h"
20 #include "view/display-messages.h"
21
22 /*!
23  * @brief レイシャル・パワー発動処理
24  * @param player_ptr プレイヤーへの参照ポインタ
25  * @param command 発動するレイシャルのID
26  * @return 処理を実際に実行した場合はTRUE、キャンセルした場合FALSEを返す。
27  */
28 bool exe_racial_power(player_type *player_ptr, const int32_t command)
29 {
30     if (command <= -3)
31         return switch_class_racial_execution(player_ptr, command);
32
33     if (player_ptr->mimic_form)
34         return switch_mimic_racial_execution(player_ptr);
35
36     return switch_race_racial_execution(player_ptr, command);
37 }
38
39 /*!
40  * @brief レイシャル・パワーの発動成功率を計算する / Returns the chance to activate a racial power/mutation
41  * @param rpi_ptr 発動したいレイシャル・パワー情報の構造体参照ポインタ
42  * @return 成功率(%)を返す
43  */
44 PERCENTAGE racial_chance(player_type *player_ptr, rpi_type *rpi_ptr)
45 {
46     if ((player_ptr->lev < rpi_ptr->min_level) || player_ptr->confused)
47         return 0;
48
49     PERCENTAGE difficulty = rpi_ptr->fail;
50     if (difficulty == 0)
51         return 100;
52
53     auto player_stun = player_ptr->effects()->stun();
54     if (player_stun->is_stunned()) {
55         difficulty += player_stun->current();
56     } else if (player_ptr->lev > rpi_ptr->min_level) {
57         PERCENTAGE lev_adj = (PERCENTAGE)((player_ptr->lev - rpi_ptr->min_level) / 3);
58         if (lev_adj > 10)
59             lev_adj = 10;
60
61         difficulty -= lev_adj;
62     }
63
64     auto special_easy = player_ptr->pclass == CLASS_IMITATOR;
65     special_easy &= player_ptr->inventory_list[INVEN_NECK].name1 == ART_GOGO_PENDANT;
66     special_easy &= rpi_ptr->racial_name.compare("倍返し") == 0;
67     if (special_easy) {
68         difficulty -= 12;
69     }
70
71     if (difficulty < 5)
72         difficulty = 5;
73
74     difficulty = difficulty / 2;
75     const BASE_STATUS stat = player_ptr->stat_cur[rpi_ptr->stat];
76     int sum = 0;
77     for (int i = 1; i <= stat; i++) {
78         int val = i - difficulty;
79         if (val > 0)
80             sum += (val <= difficulty) ? val : difficulty;
81     }
82
83     if (difficulty == 0)
84         return 100;
85     else
86         return ((sum * 100) / difficulty) / stat;
87 }
88
89 static void adjust_racial_power_difficulty(player_type *player_ptr, rpi_type *rpi_ptr, int *difficulty)
90 {
91     if (*difficulty == 0)
92         return;
93
94     auto player_stun = player_ptr->effects()->stun();
95     if (player_stun->is_stunned()) {
96         *difficulty += player_stun->current();
97     } else if (player_ptr->lev > rpi_ptr->min_level) {
98         int lev_adj = ((player_ptr->lev - rpi_ptr->min_level) / 3);
99         if (lev_adj > 10)
100             lev_adj = 10;
101         *difficulty -= lev_adj;
102     }
103
104     if (*difficulty < 5)
105         *difficulty = 5;
106 }
107
108 /*!
109  * @brief レイシャル・パワーの発動の判定処理
110  * @param rpi_ptr 発動したいレイシャル・パワー情報の構造体参照ポインタ
111  * @return racial_level_check_result
112  */
113 racial_level_check_result check_racial_level(player_type *player_ptr, rpi_type *rpi_ptr)
114 {
115     PLAYER_LEVEL min_level = rpi_ptr->min_level;
116     int use_stat = rpi_ptr->stat;
117     int difficulty = rpi_ptr->fail;
118     int use_hp = 0;
119     rpi_ptr->racial_cost = rpi_ptr->cost;
120     if (player_ptr->csp < rpi_ptr->racial_cost) {
121         use_hp = rpi_ptr->racial_cost - player_ptr->csp;
122     }
123
124     PlayerEnergy energy(player_ptr);
125     if (player_ptr->lev < min_level) {
126         msg_format(_("この能力を使用するにはレベル %d に達していなければなりません。", "You need to attain level %d to use this power."), min_level);
127         energy.reset_player_turn();
128         return RACIAL_CANCEL;
129     }
130
131     if (cmd_limit_confused(player_ptr)) {
132         energy.reset_player_turn();
133         return RACIAL_CANCEL;
134     } else if (player_ptr->chp < use_hp) {
135         if (!get_check(_("本当に今の衰弱した状態でこの能力を使いますか?", "Really use the power in your weakened state? "))) {
136             energy.reset_player_turn();
137             return RACIAL_CANCEL;
138         }
139     }
140
141     adjust_racial_power_difficulty(player_ptr, rpi_ptr, &difficulty);
142     energy.set_player_turn_energy(100);
143     if (randint1(player_ptr->stat_cur[use_stat]) >= ((difficulty / 2) + randint1(difficulty / 2)))
144         return RACIAL_SUCCESS;
145
146     if (flush_failure)
147         flush();
148
149     msg_print(_("充分に集中できなかった。", "You've failed to concentrate hard enough."));
150     return RACIAL_FAILURE;
151 }