OSDN Git Service

モンスター魔法「ユニークモンスター口寄せ」を追加。併せて使用するモンスターの追加、巨大サイバー以下略の使用魔法に追加、青魔法とものまねも追加。
[hengbandforosx/hengbandosx.git] / src / object-enchant / others / apply-magic-others.cpp
index f1ba759..12be934 100644 (file)
@@ -1,51 +1,57 @@
 /*!
- * @brief 防具系のアイテムを強化して(恐らく床に)生成する処理
- * @date 2020/06/02
+ * @brief 武器でも防具でもアクセサリでもない、その他のアイテム群を生成・強化する処理
+ * @date 2022/02/23
  * @author Hourier
- * @todo ちょっと長い。要分割
+ * @details 他との兼ね合いでEnchanterとなっているが、油つぼ・人形・死体・像は生成のみで強化はしない
  */
 
 #include "object-enchant/others/apply-magic-others.h"
 #include "artifact/random-art-generator.h"
 #include "game-option/cheat-options.h"
 #include "inventory/inventory-slot-types.h"
+#include "monster-floor/place-monster-types.h"
 #include "monster-race/monster-race-hook.h"
 #include "monster-race/monster-race.h"
-#include "monster-race/race-flags9.h"
 #include "monster-race/race-indice-types.h"
 #include "monster/monster-list.h"
 #include "monster/monster-util.h"
 #include "object-enchant/object-ego.h"
 #include "object-enchant/tr-types.h"
 #include "object-enchant/trc-types.h"
-#include "object/object-kind.h"
+#include "object/tval-types.h"
 #include "perception/object-perception.h"
 #include "sv-definition/sv-lite-types.h"
 #include "sv-definition/sv-other-types.h"
+#include "system/baseitem-info.h"
 #include "system/floor-type-definition.h"
-#include "system/monster-race-definition.h"
-#include "system/object-type-definition.h"
+#include "system/item-entity.h"
+#include "system/monster-race-info.h"
 #include "system/player-type-definition.h"
 #include "util/bit-flags-calculator.h"
 #include "view/display-messages.h"
+#include <unordered_map>
 
-OtherItemsEnchanter::OtherItemsEnchanter(PlayerType *player_ptr, ObjectType *o_ptr)
+/*!
+ * @brief コンストラクタ
+ * @param player_ptr プレイヤーへの参照ポインタ
+ * @param o_ptr 強化を与えたい/生成したいオブジェクトの構造体参照ポインタ
+ * @param power 生成ランク
+ * @details power > 2はデバッグ専用.
+ */
+OtherItemsEnchanter::OtherItemsEnchanter(PlayerType *player_ptr, ItemEntity *o_ptr)
     : player_ptr(player_ptr)
     , o_ptr(o_ptr)
 {
 }
 
 /*!
- * @brief その他雑多のオブジェクトに生成ランクごとの強化を与えるサブルーチン
- * Apply magic to an item known to be "boring"
- * @param player_ptr プレイヤーへの参照ポインタ
- * @param o_ptr 強化を与えたいオブジェクトの構造体参照ポインタ
- * @param power 生成ランク
+ * @brief その他雑多のオブジェクトに生成ランクごとの強化を与える
  * @details power > 2はデバッグ専用.
  */
 void OtherItemsEnchanter::apply_magic()
 {
-    switch (this->o_ptr->tval) {
+    const auto tval = this->o_ptr->bi_key.tval();
+    switch (tval) {
     case ItemKindType::FLASK:
         this->o_ptr->fuel = this->o_ptr->pval;
         this->o_ptr->pval = 0;
@@ -55,7 +61,7 @@ void OtherItemsEnchanter::apply_magic()
         this->enchant_wand_staff();
         break;
     case ItemKindType::ROD:
-        this->o_ptr->pval = k_info[this->o_ptr->k_idx].pval;
+        this->o_ptr->pval = this->o_ptr->get_baseitem().pval;
         break;
     case ItemKindType::CAPTURE:
         this->o_ptr->pval = 0;
@@ -63,16 +69,16 @@ void OtherItemsEnchanter::apply_magic()
         object_known(this->o_ptr);
         break;
     case ItemKindType::FIGURINE:
-        this->enchant_figurine();
+        this->generate_figurine();
         break;
     case ItemKindType::CORPSE:
-        this->enchant_corpse();
+        this->generate_corpse();
         break;
     case ItemKindType::STATUE:
-        this->enchant_statue();
+        this->generate_statue();
         break;
     case ItemKindType::CHEST:
-        this->enchant_chest();
+        this->generate_chest();
         break;
     default:
         break;
@@ -86,22 +92,29 @@ void OtherItemsEnchanter::apply_magic()
  */
 void OtherItemsEnchanter::enchant_wand_staff()
 {
-    auto *k_ptr = &k_info[this->o_ptr->k_idx];
-    this->o_ptr->pval = k_ptr->pval / 2 + randint1((k_ptr->pval + 1) / 2);
+    const auto &baseitem = this->o_ptr->get_baseitem();
+    this->o_ptr->pval = baseitem.pval / 2 + randint1((baseitem.pval + 1) / 2);
 }
 
-void OtherItemsEnchanter::enchant_figurine()
+/*
+ * @brief ランダムに選択したモンスター種族IDからその人形を作る
+ * @details
+ * ツチノコの人形は作らない
+ * レアリティが1~100のものだけ生成対象になる
+ * レベルの高い人形ほど生成されにくい
+ * たまに呪われる
+ */
+void OtherItemsEnchanter::generate_figurine()
 {
     auto *floor_ptr = this->player_ptr->current_floor_ptr;
-    short r_idx;
-    while (true)
-    {
-        r_idx = randint1(r_info.size() - 1);
-        if (!item_monster_okay(this->player_ptr, r_idx) || (r_idx == MON_TSUCHINOKO)) {
+    MonsterRaceId r_idx;
+    while (true) {
+        r_idx = MonsterRace::pick_one_at_random();
+        if (!item_monster_okay(this->player_ptr, r_idx) || (r_idx == MonsterRaceId::TSUCHINOKO)) {
             continue;
         }
 
-        auto *r_ptr = &r_info[r_idx];
+        auto *r_ptr = &monraces_info[r_idx];
         auto check = (floor_ptr->dun_level < r_ptr->level) ? (r_ptr->level - floor_ptr->dun_level) : 0;
         if ((r_ptr->rarity == 0) || (r_ptr->rarity > 100) || (randint0(check) > 0)) {
             continue;
@@ -110,72 +123,90 @@ void OtherItemsEnchanter::enchant_figurine()
         break;
     }
 
-    this->o_ptr->pval = r_idx;
+    this->o_ptr->pval = enum2i(r_idx);
     if (one_in_(6)) {
         this->o_ptr->curse_flags.set(CurseTraitType::CURSED);
     }
 }
 
-void OtherItemsEnchanter::enchant_corpse()
+/*
+ * @brief ランダムに選択したモンスター種族IDからその死体/骨を作る
+ * @details
+ * そもそも死体も骨も落とさないモンスターは対象外
+ * ユニークやあやしい影等、そこらに落ちている死体としてふさわしくないものは弾く
+ * レアリティが1~100のものだけ生成対象になる (はず)
+ * レベルの高い死体/骨ほど生成されにくい
+ */
+void OtherItemsEnchanter::generate_corpse()
 {
-    uint32_t match = 0;
-    if (this->o_ptr->sval == SV_SKELETON) {
-        match = RF9_DROP_SKELETON;
-    } else if (this->o_ptr->sval == SV_CORPSE) {
-        match = RF9_DROP_CORPSE;
-    }
+    const std::unordered_map<int, MonsterDropType> match = {
+        { SV_SKELETON, MonsterDropType::DROP_SKELETON },
+        { SV_CORPSE, MonsterDropType::DROP_CORPSE },
+    };
 
     get_mon_num_prep(this->player_ptr, item_monster_okay, nullptr);
     auto *floor_ptr = this->player_ptr->current_floor_ptr;
-    short r_idx;
+    MonsterRaceId r_idx;
     while (true) {
-        r_idx = get_mon_num(this->player_ptr, 0, floor_ptr->dun_level, 0);
-        auto *r_ptr = &r_info[r_idx];
-        auto check = (floor_ptr->dun_level < r_ptr->level) ? (r_ptr->level - floor_ptr->dun_level) : 0;
-        if ((r_ptr->rarity == 0) || none_bits(r_ptr->flags9, match) || (randint0(check) > 0)) {
+        r_idx = get_mon_num(this->player_ptr, 0, floor_ptr->dun_level, PM_NONE);
+        auto &r_ref = monraces_info[r_idx];
+        auto check = (floor_ptr->dun_level < r_ref.level) ? (r_ref.level - floor_ptr->dun_level) : 0;
+        const auto sval = this->o_ptr->bi_key.sval();
+        if (!sval.has_value()) {
+            continue;
+        }
+
+        if ((r_ref.rarity == 0) || (match.find(sval.value()) != match.end() && r_ref.drop_flags.has_not(match.at(sval.value()))) || (randint0(check) > 0)) {
             continue;
         }
 
         break;
     }
 
-    this->o_ptr->pval = r_idx;
+    this->o_ptr->pval = enum2i(r_idx);
     object_aware(this->player_ptr, this->o_ptr);
     object_known(this->o_ptr);
 }
 
-void OtherItemsEnchanter::enchant_statue()
+/*
+ * @brief ランダムに選択したモンスター種族IDからその像を作る
+ * @details レアリティが1以上のものだけ生成対象になる
+ */
+void OtherItemsEnchanter::generate_statue()
 {
-    short r_idx;
-    auto &r_ref = r_info[0];
-    while (true) {
-        r_idx = randint1(r_info.size() - 1);
-        r_ref = r_info[r_idx];
-        if (r_ref.rarity == 0) {
-            continue;
+    auto pick_r_idx_for_statue = [] {
+        while (true) {
+            auto r_idx = MonsterRace::pick_one_at_random();
+            if (monraces_info[r_idx].rarity > 0) {
+                return r_idx;
+            }
         }
+    };
+    auto r_idx = pick_r_idx_for_statue();
+    auto *r_ptr = &monraces_info[r_idx];
 
-        break;
-    }
-
-    this->o_ptr->pval = r_idx;
+    this->o_ptr->pval = enum2i(r_idx);
     if (cheat_peek) {
-        msg_format(_("%sの像", "Statue of %s"), r_ref.name.c_str());
+        msg_format(_("%sの像", "Statue of %s"), r_ptr->name.data());
     }
 
     object_aware(this->player_ptr, this->o_ptr);
     object_known(this->o_ptr);
 }
 
-void OtherItemsEnchanter::enchant_chest()
+/*
+ * @brief 箱を生成する
+ * @details 箱にはレベルがあり、箱の召喚トラップが発動すると箱レベルと同等のモンスターが召喚される
+ */
+void OtherItemsEnchanter::generate_chest()
 {
-    auto obj_level = k_info[this->o_ptr->k_idx].level;
+    auto obj_level = this->o_ptr->get_baseitem().level;
     if (obj_level <= 0) {
         return;
     }
 
     this->o_ptr->pval = randint1(obj_level);
-    if (this->o_ptr->sval == SV_CHEST_KANDUME) {
+    if (this->o_ptr->bi_key.sval() == SV_CHEST_KANDUME) {
         this->o_ptr->pval = 6;
     }