OSDN Git Service

[Implement] get_value() 関数を実装して、ウィザードモードの一部数値入力のみ汎化。
[hengbandforosx/hengbandosx.git] / src / wizard / wizard-spells.cpp
1 /*!
2  * @brief ウィザードモード専用のスペル処理
3  * @date 2020/06/27
4  * @author Hourier
5  */
6
7 #include <vector>
8
9 #include "wizard/wizard-spells.h"
10 #include "blue-magic/blue-magic-checker.h"
11 #include "core/asking-player.h"
12 #include "effect/effect-characteristics.h"
13 #include "effect/effect-processor.h"
14 #include "floor/cave.h"
15 #include "floor/floor-util.h"
16 #include "floor/pattern-walk.h"
17 #include "mind/mind-blue-mage.h"
18 #include "monster-floor/monster-generator.h"
19 #include "monster-floor/monster-summon.h"
20 #include "monster-floor/place-monster-types.h"
21 #include "monster-race/race-ability-flags.h"
22 #include "monster-race/monster-race.h"
23 #include "mutation/mutation-processor.h"
24 #include "object-enchant/object-smith.h"
25 #include "spell-kind/spells-launcher.h"
26 #include "spell-kind/spells-teleport.h"
27 #include "spell-kind/spells-random.h"
28 #include "spell-realm/spells-chaos.h"
29 #include "spell/spells-status.h"
30 #include "spell/summon-types.h"
31 #include "system/floor-type-definition.h"
32 #include "system/player-type-definition.h"
33 #include "system/monster-race-definition.h"
34 #include "target/grid-selector.h"
35 #include "target/target-checker.h"
36 #include "target/target-getter.h"
37 #include "util/enum-converter.h"
38 #include "util/flag-group.h"
39 #include "view/display-messages.h"
40
41 debug_spell_command debug_spell_commands_list[SPELL_MAX] = {
42     { 2, "vanish dungeon", { .spell2 = { vanish_dungeon } } },
43     { 3, "true healing", { .spell3 = { true_healing } } },
44     { 2, "drop weapons", { .spell2 = { drop_weapons } } },
45     { 4, "ty curse", { .spell4 = { activate_ty_curse } } },
46     { 5, "pattern teleport", { .spell5 = { pattern_teleport } } },
47 };
48
49 /*!
50  * @brief コマンド入力により任意にスペル効果を起こす / Wizard spells
51  * @return 実際にテレポートを行ったらTRUEを返す
52  */
53 bool wiz_debug_spell(player_type *player_ptr)
54 {
55     char tmp_val[50] = "\0";
56     int tmp_int;
57
58     if (!get_string("SPELL: ", tmp_val, 32))
59         return false;
60
61     for (int i = 0; i < SPELL_MAX; i++) {
62         if (strcmp(tmp_val, debug_spell_commands_list[i].command_name) != 0)
63             continue;
64
65         switch (debug_spell_commands_list[i].type) {
66         case 2:
67             (*(debug_spell_commands_list[i].command_function.spell2.spell_function))(player_ptr);
68             return true;
69             break;
70         case 3:
71             tmp_val[0] = '\0';
72             if (!get_string("POWER:", tmp_val, 32))
73                 return false;
74             tmp_int = atoi(tmp_val);
75             (*(debug_spell_commands_list[i].command_function.spell3.spell_function))(player_ptr, tmp_int);
76             return true;
77             break;
78         case 4:
79             (*(debug_spell_commands_list[i].command_function.spell4.spell_function))(player_ptr, true, &tmp_int);
80             return true;
81             break;
82         case 5:
83             (*(debug_spell_commands_list[i].command_function.spell5.spell_function))(player_ptr);
84             return true;
85             break;
86         default:
87             break;
88         }
89     }
90
91     msg_format("Command not found.");
92     return false;
93 }
94
95 /*!
96  * @brief 必ず成功するウィザードモード用次元の扉処理 / Wizard Dimension Door
97  * @param player_ptr プレイヤーへの参照ポインタ
98  */
99 void wiz_dimension_door(player_type *player_ptr)
100 {
101     POSITION x = 0, y = 0;
102     if (!tgt_pt(player_ptr, &x, &y))
103         return;
104
105     teleport_player_to(player_ptr, y, x, TELEPORT_NONMAGICAL);
106 }
107
108 /*!
109  * @brief ウィザードモード用モンスターの群れ生成 / Summon a horde of monsters
110  * @param player_ptr プレイヤーへの参照ポインタ
111  */
112 void wiz_summon_horde(player_type *player_ptr)
113 {
114     POSITION wy = player_ptr->y, wx = player_ptr->x;
115     int attempts = 1000;
116
117     while (--attempts) {
118         scatter(player_ptr, &wy, &wx, player_ptr->y, player_ptr->x, 3, PROJECT_NONE);
119         if (is_cave_empty_bold(player_ptr, wy, wx))
120             break;
121     }
122
123     (void)alloc_horde(player_ptr, wy, wx, summon_specific);
124 }
125
126 /*!
127  * @brief ウィザードモード用処理としてターゲット中の相手をテレポートバックする / Hack -- Teleport to the target
128  */
129 void wiz_teleport_back(player_type *player_ptr)
130 {
131     if (!target_who)
132         return;
133
134     teleport_player_to(player_ptr, target_row, target_col, TELEPORT_NONMAGICAL);
135 }
136
137 /*!
138  * @brief 青魔導師の魔法を全て習得済みにする /
139  * debug command for blue mage
140  */
141 void wiz_learn_blue_magic_all(player_type *player_ptr)
142 {
143     EnumClassFlagGroup<RF_ABILITY> ability_flags;
144     for (int j = 1; j < A_MAX; j++) {
145         set_rf_masks(ability_flags, i2enum<blue_magic_type>(j));
146
147         std::vector<RF_ABILITY> spells;
148         EnumClassFlagGroup<RF_ABILITY>::get_flags(ability_flags, std::back_inserter(spells));
149         for (auto spell : spells) {
150             player_ptr->magic_num2[enum2i(spell)] = 1;
151         }
152     }
153 }
154
155 /*!
156  * @brief 鍛冶師の全てのエッセンスを最大所持量にする
157  */
158 void wiz_fillup_all_smith_essences(player_type *player_ptr)
159 {
160     for (auto essence : Smith::get_essence_list()) {
161         player_ptr->magic_num1[enum2i(essence)] = Smith::ESSENCE_AMOUNT_MAX;
162     }
163 }
164
165 /*!
166  * @brief 現在のフロアに合ったモンスターをランダムに召喚する /
167  * Summon some creatures
168  * @param player_ptr プレイヤーへの参照ポインタ
169  * @param num 生成処理回数
170  */
171 void wiz_summon_random_enemy(player_type *player_ptr, int num)
172 {
173     for (int i = 0; i < num; i++)
174         (void)summon_specific(player_ptr, 0, player_ptr->y, player_ptr->x, player_ptr->current_floor_ptr->dun_level, SUMMON_NONE, PM_ALLOW_GROUP | PM_ALLOW_UNIQUE);
175 }
176
177 /*!
178  * @brief モンスターを種族IDを指定して自然生成と同じように召喚する /
179  * Summon a creature of the specified type
180  * @param r_idx モンスター種族ID(回数指定コマンド'0'で指定した回数がIDになる)
181  * @details
182  * This function is rather dangerous
183  */
184 void wiz_summon_specific_enemy(player_type *player_ptr, MONRACE_IDX r_idx)
185 {
186     if (r_idx <= 0) {
187         int val;
188         if(!get_value("MonsterID", 1, r_info.size() - 1, &val)) {
189             return;
190         }
191         r_idx = static_cast<MONRACE_IDX>(val);
192     }
193     (void)summon_named_creature(player_ptr, 0, player_ptr->y, player_ptr->x, r_idx, PM_ALLOW_SLEEP | PM_ALLOW_GROUP);
194 }
195
196 /*!
197  * @brief モンスターを種族IDを指定してペット召喚する /
198  * Summon a creature of the specified type
199  * @param r_idx モンスター種族ID(回数指定コマンド'0'で指定した回数がIDになる)
200  * @details
201  * This function is rather dangerous
202  */
203 void wiz_summon_pet(player_type *player_ptr, MONRACE_IDX r_idx)
204 {
205     if (r_idx <= 0) {
206         int val;
207         if (!get_value("MonsterID", 1, r_info.size() - 1, &val)) {
208             return;
209         }
210         r_idx = static_cast<MONRACE_IDX>(val);
211     }
212     (void)summon_named_creature(player_ptr, 0, player_ptr->y, player_ptr->x, r_idx, PM_ALLOW_SLEEP | PM_ALLOW_GROUP | PM_FORCE_PET);
213 }
214
215 /*!
216  * @brief ターゲットを指定して指定ダメージ・指定属性・半径0のボールを放つ
217  * @param dam ダメージ量
218  * @param effect_idx 属性ID
219  * @details デフォルトは100万・GF_ARROW(射撃)。RES_ALL持ちも一撃で殺せる。
220  */
221 void wiz_kill_enemy(player_type *player_ptr, HIT_POINT dam, EFFECT_ID effect_idx)
222 {
223     if (dam <= 0) {
224         char tmp[80] = "";
225         sprintf(tmp, "Damage (1-999999): ");
226         char tmp_val[10] = "1000";
227         if (!get_string(tmp, tmp_val, 6))
228             return;
229
230         dam = (HIT_POINT)atoi(tmp_val);
231     }
232
233     if (effect_idx <= GF_NONE) {
234         char tmp[80] = "";
235         sprintf(tmp, "Effect ID (1-%d): ", MAX_GF - 1);
236         char tmp_val[10] = "";
237         if (!get_string(tmp, tmp_val, 3))
238             return;
239
240         effect_idx = (EFFECT_ID)atoi(tmp_val);
241     }
242
243
244     if (effect_idx <= GF_NONE || effect_idx >= MAX_GF) {
245         msg_format(_("番号は1から%dの間で指定して下さい。", "ID must be between 1 to %d."), MAX_GF - 1);
246         return;
247     }
248
249     DIRECTION dir;
250
251     if (!get_aim_dir(player_ptr, &dir))
252         return;
253
254     fire_ball(player_ptr, effect_idx, dir, dam, 0);
255 }
256
257 /*!
258  * @brief 自分に指定ダメージ・指定属性・半径0のボールを放つ
259  * @param dam ダメージ量
260  * @param effect_idx 属性ID
261  */
262 void wiz_kill_me(player_type *player_ptr, HIT_POINT dam, EFFECT_ID effect_idx)
263 {
264     if (dam <= 0) {
265         char tmp[80] = "";
266         sprintf(tmp, "Damage (1-999999): ");
267         char tmp_val[10] = "1000";
268         if (!get_string(tmp, tmp_val, 6))
269             return;
270
271         dam = (HIT_POINT)atoi(tmp_val);
272     }
273
274     if (effect_idx <= GF_NONE) {
275         char tmp[80] = "";
276         sprintf(tmp, "Effect ID (1-%d): ", MAX_GF - 1);
277         char tmp_val[10] = "1";
278         if (!get_string(tmp, tmp_val, 3))
279             return;
280
281         effect_idx = (EFFECT_ID)atoi(tmp_val);
282     }
283
284     if (effect_idx <= GF_NONE || effect_idx >= MAX_GF) {
285         msg_format(_("番号は1から%dの間で指定して下さい。", "ID must be between 1 to %d."), MAX_GF - 1);
286         return;
287     }
288
289     project(player_ptr, -1, 0, player_ptr->y, player_ptr->x, dam, effect_idx, PROJECT_KILL | PROJECT_PLAYER);
290 }