OSDN Git Service

Merge branch 'master' of https://github.com/hengband/hengband
[hengbandforosx/hengbandosx.git] / src / action / activation-execution.cpp
1 /*!
2  * @file activation-execution.cpp
3  * @brief アイテムの発動実行定義
4  */
5
6 #include "action/activation-execution.h"
7 #include "action/action-limited.h"
8 #include "artifact/random-art-effects.h"
9 #include "core/window-redrawer.h"
10 #include "effect/attribute-types.h"
11 #include "effect/spells-effect-util.h"
12 #include "flavor/flavor-describer.h"
13 #include "flavor/object-flavor-types.h"
14 #include "floor/geometry.h"
15 #include "game-option/disturbance-options.h"
16 #include "game-option/input-options.h"
17 #include "main/sound-definitions-table.h"
18 #include "main/sound-of-music.h"
19 #include "monster-floor/monster-generator.h"
20 #include "monster-floor/place-monster-types.h"
21 #include "monster/monster-info.h"
22 #include "monster/monster-util.h"
23 #include "object-activation/activation-switcher.h"
24 #include "object-activation/activation-util.h"
25 #include "object-enchant/activation-info-table.h"
26 #include "object-enchant/object-ego.h"
27 #include "object/object-info.h"
28 #include "player-base/player-class.h"
29 #include "player-status/player-energy.h"
30 #include "racial/racial-android.h"
31 #include "spell-kind/spells-launcher.h"
32 #include "spell-kind/spells-teleport.h"
33 #include "spell-realm/spells-hex.h"
34 #include "spell-realm/spells-song.h"
35 #include "sv-definition/sv-lite-types.h"
36 #include "sv-definition/sv-ring-types.h"
37 #include "system/artifact-type-definition.h"
38 #include "system/baseitem-info.h"
39 #include "system/floor-type-definition.h"
40 #include "system/item-entity.h"
41 #include "system/monster-entity.h"
42 #include "system/player-type-definition.h"
43 #include "system/redrawing-flags-updater.h"
44 #include "target/target-getter.h"
45 #include "term/screen-processor.h"
46 #include "timed-effect/timed-effects.h"
47 #include "view/display-messages.h"
48 #include "world/world.h"
49
50 static void decide_activation_level(ae_type *ae_ptr)
51 {
52     if (ae_ptr->o_ptr->is_fixed_artifact()) {
53         ae_ptr->lev = ae_ptr->o_ptr->get_fixed_artifact().level;
54         return;
55     }
56
57     if (ae_ptr->o_ptr->is_random_artifact()) {
58         const auto it_activation = ae_ptr->o_ptr->find_activation_info();
59         if (it_activation != activation_info.end()) {
60             ae_ptr->lev = it_activation->level;
61         }
62
63         return;
64     }
65
66     const auto tval = ae_ptr->o_ptr->bi_key.tval();
67     if (((tval == ItemKindType::RING) || (tval == ItemKindType::AMULET)) && ae_ptr->o_ptr->is_ego()) {
68         ae_ptr->lev = ae_ptr->o_ptr->get_ego().level;
69     }
70 }
71
72 static void decide_chance_fail(PlayerType *player_ptr, ae_type *ae_ptr)
73 {
74     ae_ptr->chance = player_ptr->skill_dev;
75     if (player_ptr->effects()->confusion().is_confused()) {
76         ae_ptr->chance = ae_ptr->chance / 2;
77     }
78
79     ae_ptr->fail = ae_ptr->lev + 5;
80     if (ae_ptr->chance > ae_ptr->fail) {
81         ae_ptr->fail -= (ae_ptr->chance - ae_ptr->fail) * 2;
82     } else {
83         ae_ptr->chance -= (ae_ptr->fail - ae_ptr->chance) * 2;
84     }
85
86     if (ae_ptr->fail < USE_DEVICE) {
87         ae_ptr->fail = USE_DEVICE;
88     }
89
90     if (ae_ptr->chance < USE_DEVICE) {
91         ae_ptr->chance = USE_DEVICE;
92     }
93 }
94
95 static void decide_activation_success(PlayerType *player_ptr, ae_type *ae_ptr)
96 {
97     if (PlayerClass(player_ptr).equals(PlayerClassType::BERSERKER)) {
98         ae_ptr->success = false;
99         return;
100     }
101
102     if (ae_ptr->chance > ae_ptr->fail) {
103         ae_ptr->success = randint0(ae_ptr->chance * 2) >= ae_ptr->fail;
104         return;
105     }
106
107     ae_ptr->success = randint0(ae_ptr->fail * 2) < ae_ptr->chance;
108 }
109
110 static bool check_activation_success(ae_type *ae_ptr)
111 {
112     if (ae_ptr->success) {
113         return true;
114     }
115
116     if (flush_failure) {
117         flush();
118     }
119
120     msg_print(_("うまく始動させることができなかった。", "You failed to activate it properly."));
121     sound(SOUND_FAIL);
122     return false;
123 }
124
125 static bool check_activation_conditions(PlayerType *player_ptr, ae_type *ae_ptr)
126 {
127     if (!check_activation_success(ae_ptr)) {
128         return false;
129     }
130
131     if (ae_ptr->o_ptr->timeout) {
132         msg_print(_("それは微かに音を立て、輝き、消えた...", "It whines, glows and fades..."));
133         return false;
134     }
135
136     if (ae_ptr->o_ptr->is_fuel() && (ae_ptr->o_ptr->fuel == 0)) {
137         msg_print(_("燃料がない。", "It has no fuel."));
138         PlayerEnergy(player_ptr).reset_player_turn();
139         return false;
140     }
141
142     return true;
143 }
144
145 /*!
146  * @brief アイテムの発動効果を処理する。
147  * @param player_ptr プレイヤーへの参照ポインタ
148  * @param o_ptr 対象のオブジェクト構造体ポインタ
149  * @return 発動実行の是非を返す。
150  */
151 static bool activate_artifact(PlayerType *player_ptr, ItemEntity *o_ptr)
152 {
153     const auto it_activation = o_ptr->find_activation_info();
154     if (it_activation == activation_info.end()) {
155         msg_print("Activation information is not found.");
156         return false;
157     }
158
159     const auto item_name = describe_flavor(player_ptr, o_ptr, OD_NAME_ONLY | OD_OMIT_PREFIX | OD_BASE_NAME);
160     if (!switch_activation(player_ptr, &o_ptr, it_activation->index, item_name)) {
161         return false;
162     }
163
164     if (it_activation->constant) {
165         o_ptr->timeout = static_cast<short>(*it_activation->constant);
166         if (it_activation->dice > 0) {
167             o_ptr->timeout += static_cast<short>(randint1(it_activation->dice));
168         }
169
170         return true;
171     }
172
173     switch (it_activation->index) {
174     case RandomArtActType::BR_FIRE:
175         o_ptr->timeout = o_ptr->bi_key == BaseitemKey(ItemKindType::RING, SV_RING_FLAMES) ? 200 : 250;
176         return true;
177     case RandomArtActType::BR_COLD:
178         o_ptr->timeout = o_ptr->bi_key == BaseitemKey(ItemKindType::RING, SV_RING_ICE) ? 200 : 250;
179         return true;
180     case RandomArtActType::TERROR:
181         o_ptr->timeout = 3 * (player_ptr->lev + 10);
182         return true;
183     case RandomArtActType::MURAMASA:
184         return true;
185     default:
186         msg_format("Special timeout is not implemented: %d.", enum2i(it_activation->index));
187         return false;
188     }
189 }
190
191 /*!
192  * @brief 装備を発動するコマンドのサブルーチン
193  * @param player_ptr プレイヤーへの参照ポインタ
194  * @param i_idx 発動するオブジェクトの所持品ID
195  */
196 void exe_activate(PlayerType *player_ptr, INVENTORY_IDX i_idx)
197 {
198     PlayerEnergy(player_ptr).set_player_turn_energy(100);
199     ae_type tmp_ae;
200     ae_type *ae_ptr = initialize_ae_type(player_ptr, &tmp_ae, i_idx);
201     decide_activation_level(ae_ptr);
202     decide_chance_fail(player_ptr, ae_ptr);
203     if (cmd_limit_time_walk(player_ptr)) {
204         return;
205     }
206
207     decide_activation_success(player_ptr, ae_ptr);
208     if (!check_activation_conditions(player_ptr, ae_ptr)) {
209         return;
210     }
211
212     msg_print(_("始動させた...", "You activate it..."));
213     sound(SOUND_ZAP);
214     if (ae_ptr->o_ptr->has_activation()) {
215         (void)activate_artifact(player_ptr, ae_ptr->o_ptr);
216         static constexpr auto flags = {
217             SubWindowRedrawingFlag::INVENTORY,
218             SubWindowRedrawingFlag::EQUIPMENT,
219         };
220         RedrawingFlagsUpdater::get_instance().set_flags(flags);
221         return;
222     }
223
224     msg_print(_("おっと、このアイテムは始動できない。", "Oops.  That object cannot be activated."));
225 }