OSDN Git Service

27d3e691beed097478c4119e8d827bfeaecb4a16
[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 "artifact/artifact-info.h"
10 #include "core/window-redrawer.h"
11 #include "effect/spells-effect-util.h"
12 #include "floor/geometry.h"
13 #include "game-option/disturbance-options.h"
14 #include "game-option/input-options.h"
15 #include "main/sound-definitions-table.h"
16 #include "main/sound-of-music.h"
17 #include "monster-floor/monster-generator.h"
18 #include "monster-floor/place-monster-types.h"
19 #include "monster-race/monster-race.h"
20 #include "monster/monster-info.h"
21 #include "monster/monster-util.h"
22 #include "object-activation/activation-switcher.h"
23 #include "object-activation/activation-util.h"
24 #include "object-enchant/activation-info-table.h"
25 #include "object-enchant/object-ego.h"
26 #include "object/object-info.h"
27 #include "object/object-kind.h"
28 #include "player-status/player-energy.h"
29 #include "racial/racial-android.h"
30 #include "specific-object/monster-ball.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 "spell/spell-types.h"
36 #include "sv-definition/sv-lite-types.h"
37 #include "sv-definition/sv-ring-types.h"
38 #include "system/artifact-type-definition.h"
39 #include "system/floor-type-definition.h"
40 #include "system/monster-type-definition.h"
41 #include "system/object-type-definition.h"
42 #include "system/player-type-definition.h"
43 #include "target/target-getter.h"
44 #include "term/screen-processor.h"
45 #include "util/quarks.h"
46 #include "util/sort.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 = a_info[ae_ptr->o_ptr->name1].level;
54         return;
55     }
56
57     if (ae_ptr->o_ptr->is_random_artifact()) {
58         auto act_ptr = find_activation_info(ae_ptr->o_ptr);
59         if (act_ptr.has_value()) {
60             ae_ptr->lev = act_ptr.value()->level;
61         }
62
63         return;
64     }
65
66     if (((ae_ptr->o_ptr->tval == ItemKindType::RING) || (ae_ptr->o_ptr->tval == ItemKindType::AMULET)) && ae_ptr->o_ptr->name2)
67         ae_ptr->lev = e_info[ae_ptr->o_ptr->name2].level;
68 }
69
70 static void decide_chance_fail(player_type *player_ptr, ae_type *ae_ptr)
71 {
72     ae_ptr->chance = player_ptr->skill_dev;
73     if (player_ptr->confused)
74         ae_ptr->chance = ae_ptr->chance / 2;
75
76     ae_ptr->fail = ae_ptr->lev + 5;
77     if (ae_ptr->chance > ae_ptr->fail)
78         ae_ptr->fail -= (ae_ptr->chance - ae_ptr->fail) * 2;
79     else
80         ae_ptr->chance -= (ae_ptr->fail - ae_ptr->chance) * 2;
81
82     if (ae_ptr->fail < USE_DEVICE)
83         ae_ptr->fail = USE_DEVICE;
84
85     if (ae_ptr->chance < USE_DEVICE)
86         ae_ptr->chance = USE_DEVICE;
87 }
88
89 static void decide_activation_success(player_type *player_ptr, ae_type *ae_ptr)
90 {
91     if (player_ptr->pclass == PlayerClassType::BERSERKER) {
92         ae_ptr->success = false;
93         return;
94     }
95
96     if (ae_ptr->chance > ae_ptr->fail) {
97         ae_ptr->success = randint0(ae_ptr->chance * 2) >= ae_ptr->fail;
98         return;
99     }
100
101     ae_ptr->success = randint0(ae_ptr->fail * 2) < ae_ptr->chance;
102 }
103
104 static bool check_activation_success(ae_type *ae_ptr)
105 {
106     if (ae_ptr->success)
107         return true;
108
109     if (flush_failure)
110         flush();
111
112     msg_print(_("うまく始動させることができなかった。", "You failed to activate it properly."));
113     sound(SOUND_FAIL);
114     return false;
115 }
116
117 static bool check_activation_conditions(player_type *player_ptr, ae_type *ae_ptr)
118 {
119     if (!check_activation_success(ae_ptr))
120         return false;
121
122     if (ae_ptr->o_ptr->timeout) {
123         msg_print(_("それは微かに音を立て、輝き、消えた...", "It whines, glows and fades..."));
124         return false;
125     }
126
127     if (!ae_ptr->o_ptr->xtra4 && (ae_ptr->o_ptr->tval == ItemKindType::FLASK) && ((ae_ptr->o_ptr->sval == SV_LITE_TORCH) || (ae_ptr->o_ptr->sval == SV_LITE_LANTERN))) {
128         msg_print(_("燃料がない。", "It has no fuel."));
129         PlayerEnergy(player_ptr).reset_player_turn();
130         return false;
131     }
132
133     return true;
134 }
135
136 /*!
137  * @brief アイテムの発動効果を処理する。
138  * @param player_ptr プレイヤーへの参照ポインタ
139  * @param o_ptr 対象のオブジェクト構造体ポインタ
140  * @return 発動実行の是非を返す。
141  */
142 static bool activate_artifact(player_type *player_ptr, object_type *o_ptr)
143 {
144     concptr name = k_info[o_ptr->k_idx].name.c_str();
145     auto tmp_act_ptr = find_activation_info(o_ptr);
146     if (!tmp_act_ptr.has_value()) {
147         msg_print("Activation information is not found.");
148         return false;
149     }
150
151     auto *act_ptr = tmp_act_ptr.value();
152     if (!switch_activation(player_ptr, &o_ptr, act_ptr, name)) {
153         return false;
154     }
155
156     if (act_ptr->timeout.constant >= 0) {
157         o_ptr->timeout = (int16_t)act_ptr->timeout.constant;
158         if (act_ptr->timeout.dice > 0)
159             o_ptr->timeout += randint1(act_ptr->timeout.dice);
160
161         return true;
162     }
163
164     switch (act_ptr->index) {
165     case RandomArtActType::BR_FIRE:
166         o_ptr->timeout = ((o_ptr->tval == ItemKindType::RING) && (o_ptr->sval == SV_RING_FLAMES)) ? 200 : 250;
167         return true;
168     case RandomArtActType::BR_COLD:
169         o_ptr->timeout = ((o_ptr->tval == ItemKindType::RING) && (o_ptr->sval == SV_RING_ICE)) ? 200 : 250;
170         return true;
171     case RandomArtActType::TERROR:
172         o_ptr->timeout = 3 * (player_ptr->lev + 10);
173         return true;
174     case RandomArtActType::MURAMASA:
175         return true;
176     default:
177         msg_format("Special timeout is not implemented: %d.", act_ptr->index);
178         return false;
179     }
180 }
181
182 static bool activate_whistle(player_type *player_ptr, ae_type *ae_ptr)
183 {
184     if (ae_ptr->o_ptr->tval != ItemKindType::WHISTLE)
185         return false;
186
187     if (music_singing_any(player_ptr))
188         stop_singing(player_ptr);
189
190     if (SpellHex(player_ptr).is_spelling_any()) {
191         (void)SpellHex(player_ptr).stop_all_spells();
192     }
193
194     std::vector<MONSTER_IDX> who;
195     for (MONSTER_IDX pet_ctr = player_ptr->current_floor_ptr->m_max - 1; pet_ctr >= 1; pet_ctr--)
196         if (is_pet(&player_ptr->current_floor_ptr->m_list[pet_ctr]) && (player_ptr->riding != pet_ctr))
197             who.push_back(pet_ctr);
198
199     uint16_t dummy_why;
200     ang_sort(player_ptr, who.data(), &dummy_why, who.size(), ang_sort_comp_pet, ang_sort_swap_hook);
201     for (auto pet_ctr : who) {
202         teleport_monster_to(player_ptr, pet_ctr, player_ptr->y, player_ptr->x, 100, TELEPORT_PASSIVE);
203     }
204
205     ae_ptr->o_ptr->timeout = 100 + randint1(100);
206     return true;
207 }
208
209 /*!
210  * @brief 装備を発動するコマンドのサブルーチン /
211  * Activate a wielded object.  Wielded objects never stack.
212  * And even if they did, activatable objects never stack.
213  * @param item 発動するオブジェクトの所持品ID
214  * @details
215  * <pre>
216  * Currently, only (some) artifacts, and Dragon Scale Mail, can be activated.
217  * But one could, for example, easily make an activatable "Ring of Plasma".
218  * Note that it always takes a turn to activate an artifact, even if
219  * the user hits "escape" at the "direction" prompt.
220  * </pre>
221  */
222 void exe_activate(player_type *player_ptr, INVENTORY_IDX item)
223 {
224     PlayerEnergy(player_ptr).set_player_turn_energy(100);
225     ae_type tmp_ae;
226     ae_type *ae_ptr = initialize_ae_type(player_ptr, &tmp_ae, item);
227     decide_activation_level(ae_ptr);
228     decide_chance_fail(player_ptr, ae_ptr);
229     if (cmd_limit_time_walk(player_ptr))
230         return;
231
232     decide_activation_success(player_ptr, ae_ptr);
233     if (!check_activation_conditions(player_ptr, ae_ptr))
234         return;
235
236     msg_print(_("始動させた...", "You activate it..."));
237     sound(SOUND_ZAP);
238     if (activation_index(ae_ptr->o_ptr) > RandomArtActType::NONE) {
239         (void)activate_artifact(player_ptr, ae_ptr->o_ptr);
240         player_ptr->window_flags |= PW_INVEN | PW_EQUIP;
241         return;
242     }
243
244     if (activate_whistle(player_ptr, ae_ptr))
245         return;
246
247     if (exe_monster_capture(player_ptr, ae_ptr))
248         return;
249
250     msg_print(_("おっと、このアイテムは始動できない。", "Oops.  That object cannot be activated."));
251 }