OSDN Git Service

[Feature] 矢弾生成のレイシャルパワーを繰り返しコマンドに対応
authorHabu <habu1010+github@gmail.com>
Thu, 29 Apr 2021 00:56:07 +0000 (09:56 +0900)
committerHabu <habu1010+github@gmail.com>
Thu, 29 Apr 2021 01:33:39 +0000 (10:33 +0900)
アーチャーのレイシャルパワーである矢弾の生成で、矢弾の
種類を選択部分を繰り返しコマンドに対応させる。
これにより矢弾の生成を繰り返しコマンドで実行した時の
配列外アクセスの可能性などのおかしな挙動が修正される。

src/mind/mind-archer.cpp

index 5148097..bd56136 100644 (file)
@@ -10,6 +10,7 @@
 #include "grid/feature.h"
 #include "grid/grid.h"
 #include "inventory/inventory-object.h"
+#include "io/command-repeater.h"
 #include "object-enchant/apply-magic.h"
 #include "object-enchant/item-apply-magic.h"
 #include "object-enchant/object-boost.h"
@@ -33,47 +34,72 @@ enum ammo_creation_type {
     AMMO_BOLT = 3,
 };
 
-/*!
- * @brief「弾/矢の製造」処理 / do_cmd_cast calls this function if the player's class is 'archer'.
- * Hook to determine if an object is contertible in an arrow/bolt
- * @return 製造を実際に行ったらTRUE、キャンセルしたらFALSEを返す
- */
-bool create_ammo(player_type *creature_ptr)
+static bool select_ammo_creation_type(ammo_creation_type &type, PLAYER_LEVEL plev)
 {
-    char com[80];
-    if (creature_ptr->lev >= 20)
-        sprintf(com, _("[S]弾, [A]矢, [B]クロスボウの矢 :", "Create [S]hots, Create [A]rrow or Create [B]olt ?"));
-    else if (creature_ptr->lev >= 10)
-        sprintf(com, _("[S]弾, [A]矢:", "Create [S]hots or Create [A]rrow ?"));
+    COMMAND_CODE code;
+    if (repeat_pull(&code)) {
+        type = static_cast<ammo_creation_type>(code);
+        switch (type) {
+        case AMMO_SHOT:
+        case AMMO_ARROW:
+        case AMMO_BOLT:
+            return true;
+        case AMMO_NONE:
+        default:
+            break;
+        }
+    }
+
+    concptr com;
+    if (plev >= 20)
+        com = _("[S]弾, [A]矢, [B]クロスボウの矢 :", "Create [S]hots, Create [A]rrow or Create [B]olt ?");
+    else if (plev >= 10)
+        com = _("[S]弾, [A]矢:", "Create [S]hots or Create [A]rrow ?");
     else
-        sprintf(com, _("[S]弾:", "Create [S]hots ?"));
+        com = _("[S]弾:", "Create [S]hots ?");
 
-    if (cmd_limit_confused(creature_ptr) || cmd_limit_blind(creature_ptr))
-        return FALSE;
+    while (type == AMMO_NONE) {
+        char ch;
 
-    ammo_creation_type ext = AMMO_NONE;
-    char ch;
-    while (TRUE) {
         if (!get_com(com, &ch, TRUE)) {
-            return FALSE;
+            return false;
         }
 
         if (ch == 'S' || ch == 's') {
-            ext = AMMO_SHOT;
+            type = AMMO_SHOT;
             break;
         }
 
-        if ((ch == 'A' || ch == 'a') && (creature_ptr->lev >= 10)) {
-            ext = AMMO_ARROW;
+        if ((ch == 'A' || ch == 'a') && (plev >= 10)) {
+            type = AMMO_ARROW;
             break;
         }
 
-        if ((ch == 'B' || ch == 'b') && (creature_ptr->lev >= 20)) {
-            ext = AMMO_BOLT;
+        if ((ch == 'B' || ch == 'b') && (plev >= 20)) {
+            type = AMMO_BOLT;
             break;
         }
     }
 
+    repeat_push(static_cast<COMMAND_CODE>(type));
+    return true;
+}
+
+/*!
+ * @brief「弾/矢の製造」処理 / do_cmd_cast calls this function if the player's class is 'archer'.
+ * Hook to determine if an object is contertible in an arrow/bolt
+ * @return 製造を実際に行ったらTRUE、キャンセルしたらFALSEを返す
+ */
+bool create_ammo(player_type *creature_ptr)
+{
+    if (cmd_limit_confused(creature_ptr) || cmd_limit_blind(creature_ptr))
+        return FALSE;
+
+    ammo_creation_type ext = AMMO_NONE;
+
+    if (!select_ammo_creation_type(ext, creature_ptr->lev))
+        return false;
+
     switch (ext) {
     case AMMO_SHOT: {
         DIRECTION dir;