1 #include "effect/effect-monster-oldies.h"
2 #include "avatar/avatar.h"
3 #include "effect/effect-monster-util.h"
4 #include "monster-floor/monster-generator.h"
5 #include "monster-race/monster-race.h"
6 #include "monster-race/race-flags1.h"
7 #include "monster-race/race-flags3.h"
8 #include "monster-race/race-flags7.h"
9 #include "monster-race/race-indice-types.h"
10 #include "monster/monster-info.h"
11 #include "monster/monster-status-setter.h"
12 #include "monster/monster-status.h"
13 #include "system/floor-type-definition.h"
14 #include "system/grid-type-definition.h"
15 #include "system/monster-entity.h"
16 #include "system/monster-race-info.h"
17 #include "system/player-type-definition.h"
18 #include "system/redrawing-flags-updater.h"
19 #include "util/bit-flags-calculator.h"
20 #include "view/display-messages.h"
22 // Powerful monsters can resist.
23 ProcessResult effect_monster_old_poly(EffectMonster *em_ptr)
26 em_ptr->obvious = true;
28 em_ptr->do_polymorph = true;
30 bool has_resistance = em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
31 has_resistance |= any_bits(em_ptr->r_ptr->flags1, RF1_QUESTOR);
32 has_resistance |= (em_ptr->r_ptr->level > randint1(std::max(1, em_ptr->dam - 10)) + 10);
35 em_ptr->note = _("には効果がなかった。", " is unaffected.");
36 em_ptr->do_polymorph = false;
37 em_ptr->obvious = false;
41 return ProcessResult::PROCESS_CONTINUE;
44 ProcessResult effect_monster_old_clone(PlayerType *player_ptr, EffectMonster *em_ptr)
47 em_ptr->obvious = true;
50 auto has_resistance = (player_ptr->current_floor_ptr->inside_arena);
51 has_resistance |= em_ptr->m_ptr->is_pet();
52 has_resistance |= em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
53 has_resistance |= any_bits(em_ptr->r_ptr->flags1, RF1_QUESTOR);
54 has_resistance |= em_ptr->r_ptr->population_flags.has_any_of({ MonsterPopulationType::NAZGUL, MonsterPopulationType::ONLY_ONE });
57 em_ptr->note = _("には効果がなかった。", " is unaffected.");
59 return ProcessResult::PROCESS_CONTINUE;
62 em_ptr->m_ptr->hp = em_ptr->m_ptr->maxhp;
63 if (multiply_monster(player_ptr, em_ptr->g_ptr->m_idx, true, 0L)) {
64 em_ptr->note = _("が分裂した!", " spawns!");
68 return ProcessResult::PROCESS_CONTINUE;
71 ProcessResult effect_monster_star_heal(PlayerType *player_ptr, EffectMonster *em_ptr)
74 em_ptr->obvious = true;
77 (void)set_monster_csleep(player_ptr, em_ptr->g_ptr->m_idx, 0);
79 if (em_ptr->m_ptr->maxhp < em_ptr->m_ptr->max_maxhp) {
80 if (em_ptr->seen_msg) {
81 msg_print(_(format("%s^の強さが戻った。", em_ptr->m_name), format("%s^ recovers %s vitality.", em_ptr->m_name, em_ptr->m_poss)));
83 em_ptr->m_ptr->maxhp = em_ptr->m_ptr->max_maxhp;
86 auto &rfu = RedrawingFlagsUpdater::get_instance();
88 if (player_ptr->health_who == em_ptr->g_ptr->m_idx) {
89 rfu.set_flag(MainWindowRedrawingFlag::HEALTH);
92 if (player_ptr->riding == em_ptr->g_ptr->m_idx) {
93 rfu.set_flag(MainWindowRedrawingFlag::UHEALTH);
96 return ProcessResult::PROCESS_FALSE;
99 effect_monster_old_heal(player_ptr, em_ptr);
100 return ProcessResult::PROCESS_TRUE;
103 // who == 0ならばプレイヤーなので、それの判定.
104 static void effect_monster_old_heal_check_player(PlayerType *player_ptr, EffectMonster *em_ptr)
106 if (em_ptr->who != 0) {
110 chg_virtue(player_ptr, Virtue::VITALITY, 1);
111 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
112 chg_virtue(player_ptr, Virtue::INDIVIDUALISM, 1);
115 if (em_ptr->m_ptr->is_friendly()) {
116 chg_virtue(player_ptr, Virtue::HONOUR, 1);
117 } else if (em_ptr->r_ptr->kind_flags.has_not(MonsterKindType::EVIL)) {
118 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::GOOD)) {
119 chg_virtue(player_ptr, Virtue::COMPASSION, 2);
121 chg_virtue(player_ptr, Virtue::COMPASSION, 1);
125 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::ANIMAL)) {
126 chg_virtue(player_ptr, Virtue::NATURE, 1);
130 static void effect_monster_old_heal_recovery(PlayerType *player_ptr, EffectMonster *em_ptr)
132 if (em_ptr->m_ptr->get_remaining_stun()) {
133 if (em_ptr->seen_msg) {
134 msg_format(_("%s^は朦朧状態から立ち直った。", "%s^ is no longer stunned."), em_ptr->m_name);
137 (void)set_monster_stunned(player_ptr, em_ptr->g_ptr->m_idx, 0);
140 if (em_ptr->m_ptr->is_confused()) {
141 if (em_ptr->seen_msg) {
142 msg_format(_("%s^は混乱から立ち直った。", "%s^ is no longer confused."), em_ptr->m_name);
145 (void)set_monster_confused(player_ptr, em_ptr->g_ptr->m_idx, 0);
148 if (em_ptr->m_ptr->is_fearful()) {
149 if (em_ptr->seen_msg) {
150 msg_print(_(format("%s^は勇気を取り戻した。", em_ptr->m_name), format("%s^ recovers %s courage.", em_ptr->m_name, em_ptr->m_poss)));
153 (void)set_monster_monfear(player_ptr, em_ptr->g_ptr->m_idx, 0);
157 ProcessResult effect_monster_old_heal(PlayerType *player_ptr, EffectMonster *em_ptr)
160 em_ptr->obvious = true;
164 (void)set_monster_csleep(player_ptr, em_ptr->g_ptr->m_idx, 0);
165 effect_monster_old_heal_recovery(player_ptr, em_ptr);
166 if (em_ptr->m_ptr->hp < MONSTER_MAXHP) {
167 em_ptr->m_ptr->hp += em_ptr->dam;
169 if (em_ptr->m_ptr->hp > em_ptr->m_ptr->maxhp) {
170 em_ptr->m_ptr->hp = em_ptr->m_ptr->maxhp;
173 effect_monster_old_heal_check_player(player_ptr, em_ptr);
174 if (em_ptr->m_ptr->r_idx == MonsterRaceId::LEPER) {
175 em_ptr->heal_leper = true;
177 chg_virtue(player_ptr, Virtue::COMPASSION, 5);
181 auto &rfu = RedrawingFlagsUpdater::get_instance();
182 if (player_ptr->health_who == em_ptr->g_ptr->m_idx) {
183 rfu.set_flag(MainWindowRedrawingFlag::HEALTH);
186 if (player_ptr->riding == em_ptr->g_ptr->m_idx) {
187 rfu.set_flag(MainWindowRedrawingFlag::UHEALTH);
190 em_ptr->note = _("は体力を回復したようだ。", " looks healthier.");
192 return ProcessResult::PROCESS_CONTINUE;
195 ProcessResult effect_monster_old_speed(PlayerType *player_ptr, EffectMonster *em_ptr)
198 em_ptr->obvious = true;
201 if (set_monster_fast(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->m_ptr->get_remaining_acceleration() + 100)) {
202 em_ptr->note = _("の動きが速くなった。", " starts moving faster.");
206 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
207 chg_virtue(player_ptr, Virtue::INDIVIDUALISM, 1);
209 if (em_ptr->m_ptr->is_friendly()) {
210 chg_virtue(player_ptr, Virtue::HONOUR, 1);
215 return ProcessResult::PROCESS_CONTINUE;
218 ProcessResult effect_monster_old_slow(PlayerType *player_ptr, EffectMonster *em_ptr)
221 em_ptr->obvious = true;
224 bool has_resistance = em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
225 has_resistance |= (em_ptr->r_ptr->level > randint1(std::max(1, em_ptr->dam - 10)) + 10);
227 /* Powerful monsters can resist */
228 if (has_resistance) {
229 em_ptr->note = _("には効果がなかった。", " is unaffected.");
230 em_ptr->obvious = false;
232 return ProcessResult::PROCESS_CONTINUE;
235 if (set_monster_slow(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->m_ptr->get_remaining_deceleration() + 50)) {
236 em_ptr->note = _("の動きが遅くなった。", " starts moving slower.");
240 return ProcessResult::PROCESS_CONTINUE;
244 * @todo 「ユニークは (魔法では)常に眠らない」はMonsterRaceDefinitionの趣旨に反すると思われる
245 * 眠る確率を半分にするとかしておいた方が良さそう
247 ProcessResult effect_monster_old_sleep(PlayerType *player_ptr, EffectMonster *em_ptr)
250 em_ptr->obvious = true;
253 bool has_resistance = em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
254 has_resistance |= em_ptr->r_ptr->resistance_flags.has(MonsterResistanceType::NO_SLEEP);
255 has_resistance |= (em_ptr->r_ptr->level > randint1(std::max(1, em_ptr->dam - 10)) + 10);
257 if (has_resistance) {
258 if (em_ptr->r_ptr->resistance_flags.has(MonsterResistanceType::NO_SLEEP)) {
259 if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr)) {
260 em_ptr->r_ptr->resistance_flags.set(MonsterResistanceType::NO_SLEEP);
264 em_ptr->note = _("には効果がなかった。", " is unaffected.");
265 em_ptr->obvious = false;
267 em_ptr->note = _("は眠り込んでしまった!", " falls asleep!");
268 em_ptr->do_sleep = 500;
272 return ProcessResult::PROCESS_CONTINUE;
276 * @todo 「ユニークは (魔法では)常に混乱しない」はMonsterRaceDefinitionの趣旨に反すると思われる
277 * 眠る確率を半分にするとかしておいた方が良さそう
279 ProcessResult effect_monster_old_conf(PlayerType *player_ptr, EffectMonster *em_ptr)
282 em_ptr->obvious = true;
285 em_ptr->do_conf = damroll(3, (em_ptr->dam / 2)) + 1;
287 bool has_resistance = em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
288 has_resistance |= em_ptr->r_ptr->resistance_flags.has(MonsterResistanceType::NO_CONF);
289 has_resistance |= (em_ptr->r_ptr->level > randint1(std::max(1, em_ptr->dam - 10)) + 10);
290 if (has_resistance) {
291 if (em_ptr->r_ptr->resistance_flags.has(MonsterResistanceType::NO_CONF)) {
292 if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr)) {
293 em_ptr->r_ptr->resistance_flags.set(MonsterResistanceType::NO_CONF);
298 em_ptr->note = _("には効果がなかった。", " is unaffected.");
299 em_ptr->obvious = false;
303 return ProcessResult::PROCESS_CONTINUE;
306 ProcessResult effect_monster_stasis(EffectMonster *em_ptr, bool to_evil)
309 em_ptr->obvious = true;
312 int stasis_damage = (em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10);
313 bool has_resistance = em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
314 has_resistance |= em_ptr->r_ptr->level > randint1(stasis_damage) + 10;
316 has_resistance |= em_ptr->r_ptr->kind_flags.has_not(MonsterKindType::EVIL);
319 if (has_resistance) {
320 em_ptr->note = _("には効果がなかった。", " is unaffected.");
321 em_ptr->obvious = false;
323 em_ptr->note = _("は動けなくなった!", " is suspended!");
324 em_ptr->do_sleep = 500;
328 return ProcessResult::PROCESS_CONTINUE;
331 ProcessResult effect_monster_stun(EffectMonster *em_ptr)
334 em_ptr->obvious = true;
337 em_ptr->do_stun = damroll((em_ptr->caster_lev / 20) + 3, (em_ptr->dam)) + 1;
339 bool has_resistance = em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
340 has_resistance |= (em_ptr->r_ptr->level > randint1(std::max(1, em_ptr->dam - 10)) + 10);
341 if (has_resistance) {
343 em_ptr->note = _("には効果がなかった。", " is unaffected.");
344 em_ptr->obvious = false;
348 return ProcessResult::PROCESS_CONTINUE;