OSDN Git Service

Merge pull request #3848 from Slimebreath6078/feature/Add_Damage_Cap
author火炎の飛竜 <87808091+Slimebreath6078@users.noreply.github.com>
Wed, 31 Jan 2024 11:06:07 +0000 (20:06 +0900)
committerGitHub <noreply@github.com>
Wed, 31 Jan 2024 11:06:07 +0000 (20:06 +0900)
ダメージキャップを先行実装

22 files changed:
Hengband/Hengband/Hengband.vcxproj
src/Makefile.am
src/info-reader/dungeon-reader.cpp
src/info-reader/race-info-tokens-table.cpp
src/info-reader/race-info-tokens-table.h
src/info-reader/race-reader.cpp
src/load/lore-loader.cpp
src/lore/lore-calculator.cpp
src/lore/lore-store.cpp
src/lore/lore-util.cpp
src/lore/lore-util.h
src/lore/monster-lore.cpp
src/monster-race/race-special-flags.h [new file with mode: 0644]
src/monster/monster-processor-util.cpp
src/monster/monster-processor-util.h
src/monster/monster-status.cpp
src/monster/monster-update.cpp
src/monster/monster-util.cpp
src/save/monster-writer.cpp
src/system/angband-version.h
src/system/dungeon-info.h
src/system/monster-race-info.h

index f4d9022..9280502 100644 (file)
     <ClInclude Include="..\..\src\monster-race\race-population-flags.h" />\r
     <ClInclude Include="..\..\src\monster-race\race-resistance-mask.h" />\r
     <ClInclude Include="..\..\src\monster-race\race-speak-flags.h" />\r
+    <ClInclude Include="..\..\src\monster-race\race-special-flags.h" />\r
     <ClInclude Include="..\..\src\monster-race\race-visual-flags.h" />\r
     <ClInclude Include="..\..\src\monster-race\race-wilderness-flags.h" />\r
     <ClInclude Include="..\..\src\monster\monster-pain-describer.h" />\r
index 35671a4..5cee090 100644 (file)
@@ -528,6 +528,7 @@ hengband_SOURCES = \
        monster-race/race-resistance-mask.cpp monster-race/race-resistance-mask.h \
        monster-race/race-sex-const.cpp monster-race/race-sex-const.h \
        monster-race/race-speak-flags.h \
+       monster-race/race-special-flags.h \
        monster-race/race-visual-flags.h \
        monster-race/race-wilderness-flags.h \
        \
index 5830924..899b2e1 100644 (file)
@@ -93,6 +93,10 @@ static bool grab_one_basic_monster_flag(dungeon_type *d_ptr, std::string_view wh
         return true;
     }
 
+    if (EnumClassFlagGroup<MonsterSpecialType>::grab_one_flag(d_ptr->mon_special_flags, r_info_special_flags, what)) {
+        return true;
+    }
+
     msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what.data());
     return false;
 }
index 9eab09b..3d5c83a 100644 (file)
@@ -9,6 +9,7 @@
 #include "monster-race/race-population-flags.h"
 #include "monster-race/race-sex-const.h"
 #include "monster-race/race-speak-flags.h"
+#include "monster-race/race-special-flags.h"
 #include "monster-race/race-visual-flags.h"
 #include "monster-race/race-wilderness-flags.h"
 
@@ -462,3 +463,7 @@ const std::unordered_map<std::string_view, MonsterSex> r_info_sex = {
     { "MALE", MonsterSex::MALE },
     { "FEMALE", MonsterSex::FEMALE },
 };
+
+const std::unordered_map<std::string_view, MonsterSpecialType> r_info_special_flags = {
+    { "DIMINISH_MAX_DAMAGE", MonsterSpecialType::DIMINISH_MAX_DAMAGE },
+};
index 1c2afe6..b72af67 100644 (file)
@@ -18,6 +18,7 @@
 #include "monster-race/race-population-flags.h"
 #include "monster-race/race-sex-const.h"
 #include "monster-race/race-speak-flags.h"
+#include "monster-race/race-special-flags.h"
 #include "monster-race/race-visual-flags.h"
 #include "monster-race/race-wilderness-flags.h"
 #include "system/angband.h"
@@ -46,3 +47,4 @@ extern const std::unordered_map<std::string_view, MonsterPopulationType> r_info_
 extern const std::unordered_map<std::string_view, MonsterSpeakType> r_info_speak_flags;
 extern const std::unordered_map<std::string_view, MonsterBrightnessType> r_info_brightness_flags;
 extern const std::unordered_map<std::string_view, MonsterSex> r_info_sex;
+extern const std::unordered_map<std::string_view, MonsterSpecialType> r_info_special_flags;
index 3ddc31e..64a9ce2 100644 (file)
@@ -80,6 +80,10 @@ static bool grab_one_basic_flag(MonsterRaceInfo *r_ptr, std::string_view what)
         return true;
     }
 
+    if (EnumClassFlagGroup<MonsterSpecialType>::grab_one_flag(r_ptr->special_flags, r_info_special_flags, what)) {
+        return true;
+    }
+
     msg_format(_("未知のモンスター・フラグ '%s'。", "Unknown monster flag '%s'."), what.data());
     return false;
 }
index 4b1894d..8c7731c 100644 (file)
@@ -337,6 +337,9 @@ static void rd_lore(MonsterRaceInfo *r_ptr, const MonsterRaceId r_idx)
     rd_r_kind_flags(r_ptr);
     rd_r_drop_flags(r_ptr);
     rd_r_feature_flags(r_ptr);
+    if (!loading_savefile_version_is_older_than(20)) {
+        rd_FlagGroup(r_ptr->special_flags, rd_byte);
+    }
     r_ptr->max_num = rd_byte();
     r_ptr->floor_id = rd_s16b();
 
@@ -357,6 +360,7 @@ static void rd_lore(MonsterRaceInfo *r_ptr, const MonsterRaceId r_idx)
     r_ptr->r_drop_flags &= r_ptr->drop_flags;
     r_ptr->r_kind_flags &= r_ptr->kind_flags;
     r_ptr->r_feature_flags &= r_ptr->feature_flags;
+    r_ptr->r_special_flags &= r_ptr->special_flags;
 }
 
 void load_lore(void)
index de206f5..d620ef8 100644 (file)
@@ -168,4 +168,5 @@ void set_flags_for_full_knowledge(lore_type *lore_ptr)
     lore_ptr->resistance_flags = lore_ptr->r_ptr->resistance_flags;
     lore_ptr->feature_flags = lore_ptr->r_ptr->feature_flags;
     lore_ptr->drop_flags = lore_ptr->r_ptr->drop_flags;
+    lore_ptr->special_flags = lore_ptr->r_ptr->special_flags;
 }
index fed7283..237acce 100644 (file)
@@ -95,6 +95,7 @@ int lore_do_probe(PlayerType *player_ptr, MonsterRaceId r_idx)
     n += count_lore_mflag_group(r_ptr->behavior_flags, r_ptr->r_behavior_flags);
     n += count_lore_mflag_group(r_ptr->drop_flags, r_ptr->r_drop_flags);
     n += count_lore_mflag_group(r_ptr->feature_flags, r_ptr->r_feature_flags);
+    n += count_lore_mflag_group(r_ptr->special_flags, r_ptr->r_special_flags);
 
     r_ptr->r_flags1 = r_ptr->flags1;
     r_ptr->r_flags2 = r_ptr->flags2;
@@ -104,6 +105,7 @@ int lore_do_probe(PlayerType *player_ptr, MonsterRaceId r_idx)
     r_ptr->r_behavior_flags = r_ptr->behavior_flags;
     r_ptr->r_drop_flags = r_ptr->drop_flags;
     r_ptr->r_feature_flags = r_ptr->feature_flags;
+    r_ptr->r_special_flags = r_ptr->special_flags;
 
     if (!r_ptr->r_can_evolve) {
         n++;
index 4523afb..cf4ba7b 100644 (file)
@@ -1,4 +1,4 @@
-#include "lore/lore-util.h"
+#include "lore/lore-util.h"
 #include "game-option/birth-options.h"
 #include "monster-attack/monster-attack-table.h"
 #include "monster-race/monster-race.h"
@@ -51,6 +51,7 @@ lore_type::lore_type(MonsterRaceId r_idx, monster_lore_mode mode)
     this->resistance_flags = (this->r_ptr->resistance_flags & this->r_ptr->r_resistance_flags);
     this->feature_flags = (this->r_ptr->feature_flags & this->r_ptr->r_feature_flags);
     this->brightness_flags = this->r_ptr->brightness_flags;
+    this->special_flags = (this->r_ptr->special_flags & this->r_ptr->r_special_flags);
 }
 
 /*!
index 924b117..31daa7c 100644 (file)
@@ -9,6 +9,7 @@
 #include "monster-race/race-feature-flags.h"
 #include "monster-race/race-flags-resistance.h"
 #include "monster-race/race-kind-flags.h"
+#include "monster-race/race-special-flags.h"
 #include "monster-race/race-visual-flags.h"
 #include "system/angband.h"
 #include "util/flag-group.h"
@@ -81,6 +82,7 @@ struct lore_type {
     EnumClassFlagGroup<MonsterDropType> drop_flags;
     EnumClassFlagGroup<MonsterFeatureType> feature_flags;
     EnumClassFlagGroup<MonsterBrightnessType> brightness_flags;
+    EnumClassFlagGroup<MonsterSpecialType> special_flags;
 };
 
 using hook_c_roff_pf = void (*)(TERM_COLOR attr, std::string_view str);
index 944513b..0035b0a 100644 (file)
@@ -183,6 +183,10 @@ void process_monster_lore(PlayerType *player_ptr, MonsterRaceId r_idx, monster_l
     }
 
     display_lore_this(player_ptr, lore_ptr);
+    if (lore_ptr->special_flags.has(MonsterSpecialType::DIMINISH_MAX_DAMAGE)) {
+        hooked_roff(format(_("%s^は", "%s^ "), Who::who(lore_ptr->msex)));
+        hook_c_roff(TERM_RED, _("致命的な威力の攻撃に対して大きな耐性を持っている。", "has the strong resistance for a critical damage.  "));
+    }
     display_monster_aura(lore_ptr);
     if (lore_ptr->flags2 & RF2_REFLECTING) {
         hooked_roff(format(_("%s^は矢の呪文を跳ね返す。", "%s^ reflects bolt spells.  "), Who::who(lore_ptr->msex)));
diff --git a/src/monster-race/race-special-flags.h b/src/monster-race/race-special-flags.h
new file mode 100644 (file)
index 0000000..c8246a9
--- /dev/null
@@ -0,0 +1,6 @@
+#pragma once
+
+enum class MonsterSpecialType {
+    DIMINISH_MAX_DAMAGE, /*!< ラフィーIIの軽減特性 */
+    MAX,
+};
index 463606f..47cbdc5 100644 (file)
@@ -275,6 +275,7 @@ old_race_flags::old_race_flags(MonsterRaceId monrace_id)
     this->old_r_resistance_flags = monrace.r_resistance_flags;
     this->old_r_drop_flags = monrace.r_drop_flags;
     this->old_r_feature_flags = monrace.r_feature_flags;
+    this->old_r_special_flags = monrace.r_special_flags;
 
     this->old_r_blows0 = monrace.r_blows[0];
     this->old_r_blows1 = monrace.r_blows[1];
index 487b52c..8ef8c0e 100644 (file)
@@ -12,6 +12,7 @@
 #include "monster-race/race-feature-flags.h"
 #include "monster-race/race-flags-resistance.h"
 #include "monster-race/race-kind-flags.h"
+#include "monster-race/race-special-flags.h"
 #include "system/angband.h"
 #include "util/flag-group.h"
 
@@ -50,6 +51,7 @@ struct old_race_flags {
     EnumClassFlagGroup<MonsterResistanceType> old_r_resistance_flags{};
     EnumClassFlagGroup<MonsterDropType> old_r_drop_flags{};
     EnumClassFlagGroup<MonsterFeatureType> old_r_feature_flags{};
+    EnumClassFlagGroup<MonsterSpecialType> old_r_special_flags{};
 
     byte old_r_blows0 = 0;
     byte old_r_blows1 = 0;
index dfed6d7..8520560 100644 (file)
@@ -11,6 +11,7 @@
 #include "monster-race/race-flags1.h"
 #include "monster-race/race-flags2.h"
 #include "monster-race/race-flags3.h"
+#include "monster-race/race-special-flags.h"
 #include "monster/monster-describer.h"
 #include "monster/monster-info.h"
 #include "monster/monster-list.h"
@@ -80,6 +81,16 @@ int mon_damage_mod(PlayerType *player_ptr, MonsterEntity *m_ptr, int dam, bool i
         }
     }
 
+    auto &race_info = m_ptr->get_monrace();
+
+    if (race_info.special_flags.has(MonsterSpecialType::DIMINISH_MAX_DAMAGE)) {
+        race_info.r_special_flags.set(MonsterSpecialType::DIMINISH_MAX_DAMAGE);
+        if (dam > m_ptr->hp / 10) {
+            dam = std::max(m_ptr->hp / 10, m_ptr->maxhp * 7 / 500);
+            msg_format(_("%s^は致命的なダメージを抑えた!", "%s^ resisted a critical damage!"), monster_desc(player_ptr, m_ptr, 0).data());
+        }
+    }
+
     if (!m_ptr->is_invulnerable()) {
         return dam;
     }
index e49e01e..fdd2222 100644 (file)
@@ -189,7 +189,8 @@ void update_player_window(PlayerType *player_ptr, old_race_flags *old_race_flags
         (old_race_flags_ptr->old_r_blows1 != r_ptr->r_blows[1]) || (old_race_flags_ptr->old_r_blows2 != r_ptr->r_blows[2]) ||
         (old_race_flags_ptr->old_r_blows3 != r_ptr->r_blows[3]) || (old_race_flags_ptr->old_r_cast_spell != r_ptr->r_cast_spell) ||
         (old_race_flags_ptr->old_r_behavior_flags != r_ptr->r_behavior_flags) || (old_race_flags_ptr->old_r_kind_flags != r_ptr->r_kind_flags) ||
-        (old_race_flags_ptr->old_r_drop_flags != r_ptr->r_drop_flags) || (old_race_flags_ptr->old_r_feature_flags != r_ptr->r_feature_flags)) {
+        (old_race_flags_ptr->old_r_drop_flags != r_ptr->r_drop_flags) || (old_race_flags_ptr->old_r_feature_flags != r_ptr->r_feature_flags) ||
+        (old_race_flags_ptr->old_r_special_flags != r_ptr->r_special_flags)) {
         RedrawingFlagsUpdater::get_instance().set_flag(SubWindowRedrawingFlag::MONSTER_LORE);
     }
 }
index 6a8c9f9..bd05e4f 100644 (file)
@@ -294,9 +294,13 @@ static errr do_get_mon_num_prep(PlayerType *player_ptr, const monsterrace_hook_t
                 continue;
             }
 
-            // クエスト内でRES_ALLの生成を禁止する (殲滅系クエストの詰み防止)
-            if (player_ptr->current_floor_ptr->is_in_quest() && r_ptr->resistance_flags.has(MonsterResistanceType::RESIST_ALL)) {
-                continue;
+            // クエスト内でRES_ALL及び指定階未満でのDIMINISH_MAX_DAMAGEの生成を禁止する (殲滅系クエストの詰み防止)
+            if (player_ptr->current_floor_ptr->is_in_quest()) {
+                auto is_indefeatable = r_ptr->resistance_flags.has(MonsterResistanceType::RESIST_ALL);
+                is_indefeatable |= r_ptr->special_flags.has(MonsterSpecialType::DIMINISH_MAX_DAMAGE) && r_ptr->level > floor_ptr->dun_level;
+                if (is_indefeatable) {
+                    continue;
+                }
             }
         }
 
index 70f0be4..4e84e3a 100644 (file)
@@ -214,6 +214,7 @@ void wr_lore(MonsterRaceId r_idx)
     wr_FlagGroup(r_ptr->r_kind_flags, wr_byte);
     wr_FlagGroup(r_ptr->r_drop_flags, wr_byte);
     wr_FlagGroup(r_ptr->r_feature_flags, wr_byte);
+    wr_FlagGroup(r_ptr->r_special_flags, wr_byte);
 
     wr_byte((byte)r_ptr->max_num);
     wr_s16b(r_ptr->floor_id);
index 054d3ac..9cbcccc 100644 (file)
@@ -28,7 +28,7 @@ constexpr std::string_view ROOT_VARIANT_NAME("Hengband");
 /*!
  * @brief セーブファイルのバージョン(3.0.0から導入)
  */
-constexpr uint32_t SAVEFILE_VERSION = 19;
+constexpr uint32_t SAVEFILE_VERSION = 20;
 
 /*!
  * @brief バージョンが開発版が安定版かを返す(廃止予定)
index 22c9ff6..0d7c477 100644 (file)
@@ -11,6 +11,7 @@
 #include "monster-race/race-population-flags.h"
 #include "monster-race/race-resistance-mask.h"
 #include "monster-race/race-speak-flags.h"
+#include "monster-race/race-special-flags.h"
 #include "monster-race/race-visual-flags.h"
 #include "monster-race/race-wilderness-flags.h"
 #include "system/angband.h"
@@ -98,6 +99,7 @@ struct dungeon_type {
     EnumClassFlagGroup<MonsterPopulationType> mon_population_flags;
     EnumClassFlagGroup<MonsterSpeakType> mon_speak_flags;
     EnumClassFlagGroup<MonsterBrightnessType> mon_brightness_flags;
+    EnumClassFlagGroup<MonsterSpecialType> mon_special_flags;
     MonsterSex mon_sex{};
 
     std::vector<char> r_chars; /* Monster symbols allowed */
index 696efac..52da3b3 100644 (file)
@@ -13,6 +13,7 @@
 #include "monster-race/race-population-flags.h"
 #include "monster-race/race-sex-const.h"
 #include "monster-race/race-speak-flags.h"
+#include "monster-race/race-special-flags.h"
 #include "monster-race/race-visual-flags.h"
 #include "monster-race/race-wilderness-flags.h"
 #include "system/angband.h"
@@ -94,6 +95,7 @@ public:
     EnumClassFlagGroup<MonsterPopulationType> population_flags; //!< 能力フラグ(出現数関連) / Population Flags
     EnumClassFlagGroup<MonsterSpeakType> speak_flags; //!< 能力フラグ(セリフ) / Speaking Flags
     EnumClassFlagGroup<MonsterBrightnessType> brightness_flags; //!< 能力フラグ(明暗) / Speaking Lite or Dark
+    EnumClassFlagGroup<MonsterSpecialType> special_flags; //!< 能力フラグ(特殊) / Special Flags
     MonsterBlow blows[MAX_NUM_BLOWS]{}; //!< 打撃能力定義 / Up to four blows per round
 
     //! 指定護衛リスト <モンスター種族ID,護衛数ダイス数,護衛数ダイス面>
@@ -136,6 +138,7 @@ public:
     EnumClassFlagGroup<MonsterResistanceType> r_resistance_flags; //!< 見た耐性フラグ / Observed racial resistances flags
     EnumClassFlagGroup<MonsterDropType> r_drop_flags; //!< 見た能力フラグ(ドロップ) / Observed drop flags
     EnumClassFlagGroup<MonsterFeatureType> r_feature_flags; //!< 見た能力フラグ(地形関連) / Observed feature flags
+    EnumClassFlagGroup<MonsterSpecialType> r_special_flags; //!< 見た能力フラグ(特殊) / Observed special flags
     PLAYER_LEVEL defeat_level{}; //!< 倒したレベル(ユニーク用) / player level at which defeated this race
     REAL_TIME defeat_time{}; //!< 倒した時間(ユニーク用) / time at which defeated this race
     PERCENTAGE cur_hp_per{}; //!< 生成時現在HP率(%)