OSDN Git Service

Merge pull request #3837 from hengband/release/3.0.1.6-Beta
[hengbandforosx/hengbandosx.git] / src / lore / lore-store.cpp
1 /*!
2  * @brief モンスターの思い出を記憶する処理
3  * @date 2020/06/09
4  * @author Hourier
5  */
6
7 #include "lore/lore-store.h"
8 #include "core/window-redrawer.h"
9 #include "monster-race/monster-race.h"
10 #include "monster-race/race-feature-mask.h"
11 #include "monster-race/race-flags1.h"
12 #include "monster/monster-info.h"
13 #include "system/floor-type-definition.h"
14 #include "system/monster-entity.h" //!< @todo 違和感、m_ptr は外から与えることとしたい.
15 #include "system/monster-race-info.h"
16 #include "system/player-type-definition.h"
17 #include "system/redrawing-flags-updater.h"
18
19 template <class T>
20 static int count_lore_mflag_group(const EnumClassFlagGroup<T> &flags, const EnumClassFlagGroup<T> &r_flags)
21 {
22     auto result_flags = flags;
23     auto num = result_flags.reset(r_flags).count();
24     return num;
25 }
26
27 /*!
28  * @brief モンスターの調査による思い出補完処理 / Learn about a monster (by "probing" it)
29  * @param player_ptr プレイヤーへの参照ポインタ
30  * @param r_idx 補完されるモンスター種族ID
31  * @return 明らかになった情報の度数
32  * @details
33  * Return the number of new flags learnt.  -Mogami-
34  */
35 int lore_do_probe(PlayerType *player_ptr, MonsterRaceId r_idx)
36 {
37     int n = 0;
38     auto *r_ptr = &monraces_info[r_idx];
39     if (r_ptr->r_wake != MAX_UCHAR) {
40         n++;
41     }
42     if (r_ptr->r_ignore != MAX_UCHAR) {
43         n++;
44     }
45     r_ptr->r_wake = r_ptr->r_ignore = MAX_UCHAR;
46
47     for (auto i = 0; i < 4; i++) {
48         if (r_ptr->blows[i].effect != RaceBlowEffectType::NONE || r_ptr->blows[i].method != RaceBlowMethodType::NONE) {
49             if (r_ptr->r_blows[i] != MAX_UCHAR) {
50                 n++;
51             }
52             r_ptr->r_blows[i] = MAX_UCHAR;
53         }
54     }
55
56     using Mdt = MonsterDropType;
57     byte tmp_byte = (r_ptr->drop_flags.has(Mdt::DROP_4D2) ? 8 : 0);
58     tmp_byte += (r_ptr->drop_flags.has(Mdt::DROP_3D2) ? 6 : 0);
59     tmp_byte += (r_ptr->drop_flags.has(Mdt::DROP_2D2) ? 4 : 0);
60     tmp_byte += (r_ptr->drop_flags.has(Mdt::DROP_1D2) ? 2 : 0);
61     tmp_byte += (r_ptr->drop_flags.has(Mdt::DROP_90) ? 1 : 0);
62     tmp_byte += (r_ptr->drop_flags.has(Mdt::DROP_60) ? 1 : 0);
63
64     if (r_ptr->drop_flags.has_not(Mdt::ONLY_GOLD)) {
65         if (r_ptr->r_drop_item != tmp_byte) {
66             n++;
67         }
68         r_ptr->r_drop_item = tmp_byte;
69     }
70     if (r_ptr->drop_flags.has_not(Mdt::ONLY_ITEM)) {
71         if (r_ptr->r_drop_gold != tmp_byte) {
72             n++;
73         }
74         r_ptr->r_drop_gold = tmp_byte;
75     }
76
77     if (r_ptr->r_cast_spell != MAX_UCHAR) {
78         n++;
79     }
80     r_ptr->r_cast_spell = MAX_UCHAR;
81
82     for (int i = 0; i < 32; i++) {
83         if (!(r_ptr->r_flags1 & (1UL << i)) && (r_ptr->flags1 & (1UL << i))) {
84             n++;
85         }
86         if (!(r_ptr->r_flags2 & (1UL << i)) && (r_ptr->flags2 & (1UL << i))) {
87             n++;
88         }
89         if (!(r_ptr->r_flags3 & (1UL << i)) && (r_ptr->flags3 & (1UL << i))) {
90             n++;
91         }
92     }
93
94     n += count_lore_mflag_group(r_ptr->resistance_flags, r_ptr->r_resistance_flags);
95     n += count_lore_mflag_group(r_ptr->ability_flags, r_ptr->r_ability_flags);
96     n += count_lore_mflag_group(r_ptr->behavior_flags, r_ptr->r_behavior_flags);
97     n += count_lore_mflag_group(r_ptr->drop_flags, r_ptr->r_drop_flags);
98     n += count_lore_mflag_group(r_ptr->feature_flags & feature_lore_flags2, r_ptr->r_feature_flags);
99
100     r_ptr->r_flags1 = r_ptr->flags1;
101     r_ptr->r_flags2 = r_ptr->flags2;
102     r_ptr->r_flags3 = r_ptr->flags3;
103     r_ptr->r_resistance_flags = r_ptr->resistance_flags;
104     r_ptr->r_ability_flags = r_ptr->ability_flags;
105     r_ptr->r_behavior_flags = r_ptr->behavior_flags;
106     r_ptr->r_drop_flags = r_ptr->drop_flags;
107     r_ptr->r_feature_flags.set(r_ptr->feature_flags & feature_lore_flags2);
108
109     if (!r_ptr->r_can_evolve) {
110         n++;
111     }
112     r_ptr->r_can_evolve = true;
113
114     if (player_ptr->monster_race_idx == r_idx) {
115         RedrawingFlagsUpdater::get_instance().set_flag(SubWindowRedrawingFlag::MONSTER_LORE);
116     }
117
118     return n;
119 }
120
121 /*!
122  * @brief モンスターの撃破に伴うドロップ情報の記憶処理 / Take note that the given monster just dropped some treasure
123  * @param player_ptr プレイヤーへの参照ポインタ
124  * @param m_idx モンスター情報のID
125  * @param num_item 手に入れたアイテム数
126  * @param num_gold 手に入れた財宝の単位数
127  */
128 void lore_treasure(PlayerType *player_ptr, MONSTER_IDX m_idx, ITEM_NUMBER num_item, ITEM_NUMBER num_gold)
129 {
130     auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
131     auto *r_ptr = &m_ptr->get_monrace();
132
133     if (!m_ptr->is_original_ap()) {
134         return;
135     }
136
137     if (num_item > r_ptr->r_drop_item) {
138         r_ptr->r_drop_item = num_item;
139     }
140     if (num_gold > r_ptr->r_drop_gold) {
141         r_ptr->r_drop_gold = num_gold;
142     }
143
144     if (r_ptr->drop_flags.has(MonsterDropType::DROP_GOOD)) {
145         r_ptr->r_drop_flags.set(MonsterDropType::DROP_GOOD);
146     }
147     if (r_ptr->drop_flags.has(MonsterDropType::DROP_GREAT)) {
148         r_ptr->r_drop_flags.set(MonsterDropType::DROP_GREAT);
149     }
150     if (player_ptr->monster_race_idx == m_ptr->r_idx) {
151         RedrawingFlagsUpdater::get_instance().set_flag(SubWindowRedrawingFlag::MONSTER_LORE);
152     }
153 }