OSDN Git Service

Merge pull request #3569 from sikabane-works/release/3.0.0.88-alpha
[hengbandforosx/hengbandosx.git] / src / cmd-action / cmd-shoot.cpp
1 #include "cmd-action/cmd-shoot.h"
2 #include "combat/shoot.h"
3 #include "floor/floor-object.h"
4 #include "inventory/inventory-slot-types.h"
5 #include "mind/snipe-types.h"
6 #include "object/item-tester-hooker.h"
7 #include "object/item-use-flags.h"
8 #include "player-base/player-class.h"
9 #include "player-info/samurai-data-type.h"
10 #include "player-info/sniper-data-type.h"
11 #include "player/attack-defense-types.h"
12 #include "player/special-defense-types.h"
13 #include "spell-kind/spells-teleport.h"
14 #include "status/action-setter.h"
15 #include "status/bad-status-setter.h"
16 #include "sv-definition/sv-bow-types.h"
17 #include "system/item-entity.h"
18 #include "system/player-type-definition.h"
19 #include "term/screen-processor.h"
20 #include "view/display-messages.h"
21
22 /*!
23  * @brief 射撃処理のメインルーチン
24  * @param player_ptr プレイヤーへの参照ポインタ
25  * @param snipe_type スナイパーの射撃術の種類
26  */
27 void do_cmd_fire(PlayerType *player_ptr, SPELL_IDX snipe_type)
28 {
29     if (player_ptr->wild_mode) {
30         return;
31     }
32
33     player_ptr->is_fired = false;
34     auto *item_ptr = &player_ptr->inventory_list[INVEN_BOW];
35     const auto tval = item_ptr->bi_key.tval();
36     if (tval == ItemKindType::NONE) {
37         msg_print(_("射撃用の武器を持っていない。", "You have nothing to fire with."));
38         flush();
39         return;
40     }
41
42     const auto sval = item_ptr->bi_key.sval();
43     if (sval == SV_CRIMSON) {
44         msg_print(_("この武器は発動して使うもののようだ。", "It's already activated."));
45         flush();
46         return;
47     }
48
49     if (sval == SV_HARP) {
50         msg_print(_("この武器で射撃はできない。", "It's not for firing."));
51         flush();
52         return;
53     }
54
55     PlayerClass(player_ptr).break_samurai_stance({ SamuraiStanceType::MUSOU });
56     const auto q = _("どれを撃ちますか? ", "Fire which item? ");
57     const auto s = _("発射されるアイテムがありません。", "You have nothing to fire.");
58     short item;
59     const auto *ammo_ptr = choose_object(player_ptr, &item, q, s, USE_INVEN | USE_FLOOR, TvalItemTester(player_ptr->tval_ammo));
60     if (!ammo_ptr) {
61         flush();
62         return;
63     }
64
65     exe_fire(player_ptr, item, item_ptr, snipe_type);
66     if (!player_ptr->is_fired || !PlayerClass(player_ptr).equals(PlayerClassType::SNIPER)) {
67         return;
68     }
69
70     if (snipe_type == SP_AWAY) {
71         auto sniper_data = PlayerClass(player_ptr).get_specific_data<SniperData>();
72         teleport_player(player_ptr, 10 + (sniper_data->concent * 2), TELEPORT_SPONTANEOUS);
73     }
74
75     auto effects = player_ptr->effects();
76     if (snipe_type == SP_FINAL) {
77         msg_print(_("射撃の反動が体を襲った。", "The weapon's recoil stuns you. "));
78         BadStatusSetter bss(player_ptr);
79         (void)bss.mod_deceleration(randint0(7) + 7, false);
80         (void)bss.mod_stun(randint1(25));
81     }
82 }