OSDN Git Service

[Implement] ウサウサストライカー召喚処理を追加
[hengbandforosx/hengbandosx.git] / src / action / mutation-execution.cpp
1 /*!
2  * @file mutation-execution.cpp
3  * @brief プレイヤーの変異能力実行定義
4  */
5
6 #include "action/mutation-execution.h"
7 #include "cmd-item/cmd-throw.h"
8 #include "core/asking-player.h"
9 #include "dungeon/quest.h"
10 #include "effect/attribute-types.h"
11 #include "effect/spells-effect-util.h"
12 #include "floor/geometry.h"
13 #include "game-option/play-record-options.h"
14 #include "inventory/inventory-slot-types.h"
15 #include "io/write-diary.h"
16 #include "mind/mind-mage.h"
17 #include "mind/mind-warrior.h"
18 #include "monster-floor/monster-remover.h"
19 #include "monster-floor/monster-summon.h"
20 #include "monster-floor/place-monster-types.h"
21 #include "monster-race/monster-race.h"
22 #include "monster-race/race-flags1.h"
23 #include "monster-race/race-flags3.h"
24 #include "monster/monster-describer.h"
25 #include "monster/monster-description-types.h"
26 #include "monster/monster-flag-types.h"
27 #include "monster/monster-info.h"
28 #include "mutation/mutation-flag-types.h"
29 #include "mutation/mutation-techniques.h"
30 #include "object-enchant/item-feeling.h"
31 #include "player-info/self-info.h"
32 #include "player-status/player-energy.h"
33 #include "player/player-damage.h"
34 #include "player/player-status.h"
35 #include "racial/racial-vampire.h"
36 #include "spell-kind/earthquake.h"
37 #include "spell-kind/spells-charm.h"
38 #include "spell-kind/spells-detection.h"
39 #include "spell-kind/spells-fetcher.h"
40 #include "spell-kind/spells-launcher.h"
41 #include "spell-kind/spells-lite.h"
42 #include "spell-kind/spells-sight.h"
43 #include "spell-kind/spells-teleport.h"
44 #include "spell-kind/spells-world.h"
45 #include "spell-realm/spells-sorcery.h"
46 #include "spell/spells-status.h"
47 #include "spell/summon-types.h"
48 #include "status/element-resistance.h"
49 #include "status/shape-changer.h"
50 #include "system/floor-type-definition.h"
51 #include "system/grid-type-definition.h"
52 #include "system/item-entity.h"
53 #include "system/monster-entity.h"
54 #include "system/monster-race-info.h"
55 #include "system/player-type-definition.h"
56 #include "target/target-getter.h"
57 #include "util/bit-flags-calculator.h"
58 #include "view/display-messages.h"
59
60 /*!
61  * @brief 突然変異のレイシャル効果実装
62  * @param player_ptr プレイヤーへの参照ポインタ
63  * @param power 発動させる突然変異レイシャルのID
64  * @return レイシャルを実行した場合TRUE、キャンセルした場合FALSEを返す
65  */
66 bool exe_mutation_power(PlayerType *player_ptr, PlayerMutationType power)
67 {
68     DIRECTION dir = 0;
69     PLAYER_LEVEL lvl = player_ptr->lev;
70     auto &floor = *player_ptr->current_floor_ptr;
71     switch (power) {
72     case PlayerMutationType::SPIT_ACID:
73         if (!get_aim_dir(player_ptr, &dir)) {
74             return false;
75         }
76
77         stop_mouth(player_ptr);
78         msg_print(_("酸を吐きかけた...", "You spit acid..."));
79         fire_ball(player_ptr, AttributeType::ACID, dir, lvl, 1 + (lvl / 30));
80         return true;
81     case PlayerMutationType::BR_FIRE:
82         if (!get_aim_dir(player_ptr, &dir)) {
83             return false;
84         }
85
86         stop_mouth(player_ptr);
87         msg_print(_("あなたは火炎のブレスを吐いた...", "You breathe fire..."));
88         fire_breath(player_ptr, AttributeType::FIRE, dir, lvl * 2, 1 + (lvl / 20));
89         return true;
90     case PlayerMutationType::HYPN_GAZE:
91         if (!get_aim_dir(player_ptr, &dir)) {
92             return false;
93         }
94
95         msg_print(_("あなたの目は幻惑的になった...", "Your eyes look mesmerizing..."));
96         (void)charm_monster(player_ptr, dir, lvl);
97         return true;
98     case PlayerMutationType::TELEKINES:
99         if (!get_aim_dir(player_ptr, &dir)) {
100             return false;
101         }
102
103         msg_print(_("集中している...", "You concentrate..."));
104         fetch_item(player_ptr, dir, lvl * 10, true);
105         return true;
106     case PlayerMutationType::VTELEPORT:
107         msg_print(_("集中している...", "You concentrate..."));
108         teleport_player(player_ptr, 10 + 4 * lvl, TELEPORT_SPONTANEOUS);
109         return true;
110     case PlayerMutationType::MIND_BLST:
111         if (!get_aim_dir(player_ptr, &dir)) {
112             return false;
113         }
114
115         msg_print(_("集中している...", "You concentrate..."));
116         fire_bolt(player_ptr, AttributeType::PSI, dir, damroll(3 + ((lvl - 1) / 5), 3));
117         return true;
118     case PlayerMutationType::RADIATION:
119         msg_print(_("体から放射能が発生した!", "Radiation flows from your body!"));
120         fire_ball(player_ptr, AttributeType::NUKE, 0, (lvl * 2), 3 + (lvl / 20));
121         return true;
122     case PlayerMutationType::VAMPIRISM:
123         vampirism(player_ptr);
124         return true;
125     case PlayerMutationType::SMELL_MET:
126         stop_mouth(player_ptr);
127         (void)detect_treasure(player_ptr, DETECT_RAD_DEFAULT);
128         return true;
129     case PlayerMutationType::SMELL_MON:
130         stop_mouth(player_ptr);
131         (void)detect_monsters_normal(player_ptr, DETECT_RAD_DEFAULT);
132         return true;
133     case PlayerMutationType::BLINK:
134         teleport_player(player_ptr, 10, TELEPORT_SPONTANEOUS);
135         return true;
136     case PlayerMutationType::EAT_ROCK:
137         return eat_rock(player_ptr);
138     case PlayerMutationType::SWAP_POS:
139         project_length = -1;
140         if (!get_aim_dir(player_ptr, &dir)) {
141             project_length = 0;
142             return false;
143         }
144
145         (void)teleport_swap(player_ptr, dir);
146         project_length = 0;
147         return true;
148     case PlayerMutationType::SHRIEK:
149         stop_mouth(player_ptr);
150         (void)fire_ball(player_ptr, AttributeType::SOUND, 0, 2 * lvl, 8);
151         (void)aggravate_monsters(player_ptr, 0);
152         return true;
153     case PlayerMutationType::ILLUMINE:
154         (void)lite_area(player_ptr, damroll(2, (lvl / 2)), (lvl / 10) + 1);
155         return true;
156     case PlayerMutationType::DET_CURSE:
157         for (int i = 0; i < INVEN_TOTAL; i++) {
158             auto *o_ptr = &player_ptr->inventory_list[i];
159             if (!o_ptr->is_valid() || !o_ptr->is_cursed()) {
160                 continue;
161             }
162
163             o_ptr->feeling = FEEL_CURSED;
164         }
165
166         return true;
167     case PlayerMutationType::BERSERK:
168         (void)berserk(player_ptr, randint1(25) + 25);
169         return true;
170     case PlayerMutationType::POLYMORPH:
171         if (!input_check(_("変身します。よろしいですか?", "You will polymorph your self. Are you sure? "))) {
172             return false;
173         }
174
175         do_poly_self(player_ptr);
176         return true;
177     case PlayerMutationType::MIDAS_TCH:
178         return alchemy(player_ptr);
179     case PlayerMutationType::GROW_MOLD:
180         for (DIRECTION i = 0; i < 8; i++) {
181             summon_specific(player_ptr, -1, player_ptr->y, player_ptr->x, lvl, SUMMON_MOLD, PM_FORCE_PET);
182         }
183
184         return true;
185     case PlayerMutationType::RESIST: {
186         int num = lvl / 10;
187         TIME_EFFECT dur = randint1(20) + 20;
188         if (randint0(5) < num) {
189             (void)set_oppose_acid(player_ptr, dur, false);
190             num--;
191         }
192
193         if (randint0(4) < num) {
194             (void)set_oppose_elec(player_ptr, dur, false);
195             num--;
196         }
197
198         if (randint0(3) < num) {
199             (void)set_oppose_fire(player_ptr, dur, false);
200             num--;
201         }
202
203         if (randint0(2) < num) {
204             (void)set_oppose_cold(player_ptr, dur, false);
205             num--;
206         }
207
208         if (num != 0) {
209             (void)set_oppose_pois(player_ptr, dur, false);
210             num--;
211         }
212
213         return true;
214     }
215     case PlayerMutationType::EARTHQUAKE:
216         (void)earthquake(player_ptr, player_ptr->y, player_ptr->x, 10, 0);
217         return true;
218     case PlayerMutationType::EAT_MAGIC:
219         return eat_magic(player_ptr, player_ptr->lev * 2);
220     case PlayerMutationType::WEIGH_MAG:
221         report_magics(player_ptr);
222         return true;
223     case PlayerMutationType::STERILITY:
224         msg_print(_("突然頭が痛くなった!", "You suddenly have a headache!"));
225         take_hit(player_ptr, DAMAGE_LOSELIFE, randint1(17) + 17, _("禁欲を強いた疲労", "the strain of forcing abstinence"));
226         floor.num_repro += MAX_REPRODUCTION;
227         return true;
228     case PlayerMutationType::HIT_AND_AWAY:
229         return hit_and_away(player_ptr);
230     case PlayerMutationType::DAZZLE:
231         stun_monsters(player_ptr, lvl * 4);
232         confuse_monsters(player_ptr, lvl * 4);
233         turn_monsters(player_ptr, lvl * 4);
234         return true;
235     case PlayerMutationType::LASER_EYE:
236         if (!get_aim_dir(player_ptr, &dir)) {
237             return false;
238         }
239
240         fire_beam(player_ptr, AttributeType::LITE, dir, 2 * lvl);
241         return true;
242     case PlayerMutationType::RECALL:
243         return recall_player(player_ptr, randint0(21) + 15);
244     case PlayerMutationType::BANISH: {
245         if (!get_direction(player_ptr, &dir)) {
246             return false;
247         }
248
249         const auto y = player_ptr->y + ddy[dir];
250         const auto x = player_ptr->x + ddx[dir];
251         const auto &grid = floor.grid_array[y][x];
252         if (!grid.m_idx) {
253             msg_print(_("邪悪な存在を感じとれません!", "You sense no evil there!"));
254             return true;
255         }
256
257         auto &monster = floor.m_list[grid.m_idx];
258         const auto &monrace = monster.get_monrace();
259         auto can_banish = monrace.kind_flags.has(MonsterKindType::EVIL);
260         can_banish &= monrace.misc_flags.has_not(MonsterMiscType::QUESTOR);
261         can_banish &= monrace.kind_flags.has_not(MonsterKindType::UNIQUE);
262         can_banish &= !floor.inside_arena;
263         can_banish &= !floor.is_in_quest();
264         can_banish &= (monrace.level < randint1(player_ptr->lev + 50));
265         can_banish &= monster.mflag2.has_not(MonsterConstantFlagType::NOGENO);
266         if (can_banish) {
267             if (record_named_pet && monster.is_named_pet()) {
268                 const auto m_name = monster_desc(player_ptr, &monster, MD_INDEF_VISIBLE);
269                 exe_write_diary(player_ptr, DiaryKind::NAMED_PET, RECORD_NAMED_PET_GENOCIDE, m_name);
270             }
271
272             delete_monster_idx(player_ptr, grid.m_idx);
273             msg_print(_("その邪悪なモンスターは硫黄臭い煙とともに消え去った!", "The evil creature vanishes in a puff of sulfurous smoke!"));
274             return true;
275         }
276
277         msg_print(_("祈りは効果がなかった!", "Your invocation is ineffectual!"));
278         if (one_in_(13)) {
279             monster.mflag2.set(MonsterConstantFlagType::NOGENO);
280         }
281
282         return true;
283     }
284     case PlayerMutationType::COLD_TOUCH: {
285         if (!get_direction(player_ptr, &dir)) {
286             return false;
287         }
288
289         const auto y = player_ptr->y + ddy[dir];
290         const auto x = player_ptr->x + ddx[dir];
291         auto &grid = floor.grid_array[y][x];
292         if (!grid.m_idx) {
293             msg_print(_("あなたは何もない場所で手を振った。", "You wave your hands in the air."));
294             return true;
295         }
296
297         fire_bolt(player_ptr, AttributeType::COLD, dir, 2 * lvl);
298         return true;
299     }
300     case PlayerMutationType::LAUNCHER:
301         return ThrowCommand(player_ptr).do_cmd_throw(2 + lvl / 40, false, -1);
302     default:
303         PlayerEnergy(player_ptr).reset_player_turn();
304         msg_format(_("能力 PlayerMutationType::%d は実装されていません。", "Power PlayerMutationType::%d not implemented. Oops."), enum2i(power));
305         return true;
306     }
307 }