OSDN Git Service

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