2 * @brief 敵への攻撃によって徳を変化させる処理
7 #include "avatar/avatar-changer.h"
8 #include "avatar/avatar.h"
9 #include "monster-race/monster-kind-mask.h"
10 #include "monster-race/monster-race.h"
11 #include "monster-race/race-ability-mask.h"
12 #include "monster-race/race-flags1.h"
13 #include "monster-race/race-flags2.h"
14 #include "monster-race/race-flags3.h"
15 #include "monster-race/race-indice-types.h"
16 #include "monster/monster-info.h"
17 #include "system/dungeon-info.h"
18 #include "system/floor-type-definition.h"
19 #include "system/monster-entity.h"
20 #include "system/monster-race-info.h"
21 #include "system/player-type-definition.h"
22 #include "util/bit-flags-calculator.h"
25 * @brief AvaterChangerコンストラクタ
27 AvatarChanger::AvatarChanger(PlayerType *player_ptr, MonsterEntity *m_ptr)
28 : player_ptr(player_ptr)
34 * @brief 徳変化処理のメインルーチン
36 void AvatarChanger::change_virtue()
38 this->change_virtue_non_beginner();
39 this->change_virtue_unique();
40 const auto &r_ref = this->m_ptr->get_real_r_ref();
41 if (m_ptr->r_idx == MonsterRaceId::BEGGAR || m_ptr->r_idx == MonsterRaceId::LEPER) {
42 chg_virtue(this->player_ptr, Virtue::COMPASSION, -1);
45 this->change_virtue_good_evil();
46 if (r_ref.kind_flags.has(MonsterKindType::UNDEAD) && r_ref.kind_flags.has(MonsterKindType::UNIQUE)) {
47 chg_virtue(this->player_ptr, Virtue::VITALITY, 2);
50 this->change_virtue_revenge();
51 if (any_bits(r_ref.flags2, RF2_MULTIPLY) && (r_ref.r_akills > 1000) && one_in_(10)) {
52 chg_virtue(this->player_ptr, Virtue::VALOUR, -1);
55 this->change_virtue_wild_thief();
56 this->change_virtue_good_animal();
60 * @brief 非BEGINNERダンジョン時に伴う徳の変化処理
62 void AvatarChanger::change_virtue_non_beginner()
64 auto *floor_ptr = this->player_ptr->current_floor_ptr;
65 auto *r_ptr = &monraces_info[m_ptr->r_idx];
66 if (floor_ptr->get_dungeon_definition().flags.has(DungeonFeatureType::BEGINNER)) {
70 if ((floor_ptr->dun_level == 0) && !this->player_ptr->ambush_flag && !floor_ptr->inside_arena) {
71 chg_virtue(this->player_ptr, Virtue::VALOUR, -1);
72 } else if (r_ptr->level > floor_ptr->dun_level) {
73 if (randint1(10) <= (r_ptr->level - floor_ptr->dun_level)) {
74 chg_virtue(this->player_ptr, Virtue::VALOUR, 1);
78 if (r_ptr->level > 60) {
79 chg_virtue(this->player_ptr, Virtue::VALOUR, 1);
82 if (r_ptr->level >= 2 * (this->player_ptr->lev + 1)) {
83 chg_virtue(this->player_ptr, Virtue::VALOUR, 2);
88 * @brief ユニークを攻撃対象にした場合限定の徳変化処理
90 void AvatarChanger::change_virtue_unique()
92 auto *r_ptr = &monraces_info[m_ptr->r_idx];
93 if (r_ptr->kind_flags.has_not(MonsterKindType::UNIQUE)) {
97 if (r_ptr->kind_flags.has_any_of(alignment_mask)) {
98 chg_virtue(this->player_ptr, Virtue::HARMONY, 2);
101 if (r_ptr->kind_flags.has(MonsterKindType::GOOD)) {
102 chg_virtue(this->player_ptr, Virtue::UNLIFE, 2);
103 chg_virtue(this->player_ptr, Virtue::VITALITY, -2);
107 chg_virtue(this->player_ptr, Virtue::INDIVIDUALISM, -1);
112 * @brief 攻撃を与えたモンスターが天使か悪魔だった場合、徳を変化させる
113 * @details 天使かつ悪魔だった場合、天使であることが優先される
115 void AvatarChanger::change_virtue_good_evil()
117 auto *floor_ptr = this->player_ptr->current_floor_ptr;
118 auto *r_ptr = &monraces_info[m_ptr->r_idx];
119 if (r_ptr->kind_flags.has(MonsterKindType::GOOD) && ((r_ptr->level) / 10 + (3 * floor_ptr->dun_level) >= randint1(100))) {
120 chg_virtue(this->player_ptr, Virtue::UNLIFE, 1);
123 if (r_ptr->kind_flags.has(MonsterKindType::ANGEL)) {
124 if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
125 chg_virtue(this->player_ptr, Virtue::FAITH, -2);
126 } else if ((r_ptr->level) / 10 + (3 * floor_ptr->dun_level) >= randint1(100)) {
127 auto change_value = r_ptr->kind_flags.has(MonsterKindType::GOOD) ? -1 : 1;
128 chg_virtue(this->player_ptr, Virtue::FAITH, change_value);
134 if (r_ptr->kind_flags.has(MonsterKindType::DEMON)) {
135 if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
136 chg_virtue(this->player_ptr, Virtue::FAITH, 2);
137 } else if ((r_ptr->level) / 10 + (3 * floor_ptr->dun_level) >= randint1(100)) {
138 chg_virtue(this->player_ptr, Virtue::FAITH, 1);
144 * @brief 過去に@を殺したことがあるユニークにリゾンべを果たせたら徳を上げる
146 void AvatarChanger::change_virtue_revenge()
148 auto *floor_ptr = this->player_ptr->current_floor_ptr;
149 auto *r_ptr = &monraces_info[m_ptr->r_idx];
150 if (r_ptr->r_deaths == 0) {
154 if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
155 chg_virtue(this->player_ptr, Virtue::HONOUR, 10);
159 if ((r_ptr->level) / 10 + (2 * floor_ptr->dun_level) >= randint1(100)) {
160 chg_virtue(this->player_ptr, Virtue::HONOUR, 1);
165 * @brief 盗み逃げをするモンスター及び地上のモンスターを攻撃した際に徳を変化させる
167 void AvatarChanger::change_virtue_wild_thief()
169 auto *floor_ptr = this->player_ptr->current_floor_ptr;
170 auto *r_ptr = &monraces_info[m_ptr->r_idx];
171 auto innocent = true;
173 for (const auto &blow : r_ptr->blows) {
174 if (blow.d_dice != 0) {
178 if ((blow.effect == RaceBlowEffectType::EAT_ITEM) || (blow.effect == RaceBlowEffectType::EAT_GOLD)) {
183 if (r_ptr->level > 0) {
188 if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
189 chg_virtue(this->player_ptr, Virtue::JUSTICE, 3);
193 if (1 + ((r_ptr->level) / 10 + (2 * floor_ptr->dun_level)) >= randint1(100)) {
194 chg_virtue(this->player_ptr, Virtue::JUSTICE, 1);
201 chg_virtue(this->player_ptr, Virtue::JUSTICE, -1);
206 * @brief 邪悪でなく、魔法も持たない動物を攻撃した時に徳を下げる
208 void AvatarChanger::change_virtue_good_animal()
210 auto *r_ptr = &monraces_info[m_ptr->r_idx];
211 auto magic_ability_flags = r_ptr->ability_flags;
212 magic_ability_flags.reset(RF_ABILITY_NOMAGIC_MASK);
213 if (r_ptr->kind_flags.has_not(MonsterKindType::ANIMAL) || r_ptr->kind_flags.has(MonsterKindType::EVIL) || magic_ability_flags.any()) {
218 chg_virtue(this->player_ptr, Virtue::NATURE, -1);