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(effect_monster_type *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, effect_monster_type *em_ptr)
47 em_ptr->obvious = true;
50 bool 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(MonsterPopulationType::NAZGUL);
55 has_resistance |= any_bits(em_ptr->r_ptr->flags7, RF7_UNIQUE2);
58 em_ptr->note = _("には効果がなかった。", " is unaffected.");
60 return ProcessResult::PROCESS_CONTINUE;
63 em_ptr->m_ptr->hp = em_ptr->m_ptr->maxhp;
64 if (multiply_monster(player_ptr, em_ptr->g_ptr->m_idx, true, 0L)) {
65 em_ptr->note = _("が分裂した!", " spawns!");
69 return ProcessResult::PROCESS_CONTINUE;
72 ProcessResult effect_monster_star_heal(PlayerType *player_ptr, effect_monster_type *em_ptr)
75 em_ptr->obvious = true;
78 (void)set_monster_csleep(player_ptr, em_ptr->g_ptr->m_idx, 0);
80 if (em_ptr->m_ptr->maxhp < em_ptr->m_ptr->max_maxhp) {
81 if (em_ptr->seen_msg) {
82 msg_print(_(format("%s^の強さが戻った。", em_ptr->m_name), format("%s^ recovers %s vitality.", em_ptr->m_name, em_ptr->m_poss)));
84 em_ptr->m_ptr->maxhp = em_ptr->m_ptr->max_maxhp;
87 auto &rfu = RedrawingFlagsUpdater::get_instance();
89 if (player_ptr->health_who == em_ptr->g_ptr->m_idx) {
90 rfu.set_flag(MainWindowRedrawingFlag::HEALTH);
93 if (player_ptr->riding == em_ptr->g_ptr->m_idx) {
94 rfu.set_flag(MainWindowRedrawingFlag::UHEALTH);
97 return ProcessResult::PROCESS_FALSE;
100 effect_monster_old_heal(player_ptr, em_ptr);
101 return ProcessResult::PROCESS_TRUE;
104 // who == 0ならばプレイヤーなので、それの判定.
105 static void effect_monster_old_heal_check_player(PlayerType *player_ptr, effect_monster_type *em_ptr)
107 if (em_ptr->who != 0) {
111 chg_virtue(player_ptr, Virtue::VITALITY, 1);
112 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
113 chg_virtue(player_ptr, Virtue::INDIVIDUALISM, 1);
116 if (em_ptr->m_ptr->is_friendly()) {
117 chg_virtue(player_ptr, Virtue::HONOUR, 1);
118 } else if (em_ptr->r_ptr->kind_flags.has_not(MonsterKindType::EVIL)) {
119 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::GOOD)) {
120 chg_virtue(player_ptr, Virtue::COMPASSION, 2);
122 chg_virtue(player_ptr, Virtue::COMPASSION, 1);
126 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::ANIMAL)) {
127 chg_virtue(player_ptr, Virtue::NATURE, 1);
131 static void effect_monster_old_heal_recovery(PlayerType *player_ptr, effect_monster_type *em_ptr)
133 if (em_ptr->m_ptr->get_remaining_stun()) {
134 if (em_ptr->seen_msg) {
135 msg_format(_("%s^は朦朧状態から立ち直った。", "%s^ is no longer stunned."), em_ptr->m_name);
138 (void)set_monster_stunned(player_ptr, em_ptr->g_ptr->m_idx, 0);
141 if (em_ptr->m_ptr->is_confused()) {
142 if (em_ptr->seen_msg) {
143 msg_format(_("%s^は混乱から立ち直った。", "%s^ is no longer confused."), em_ptr->m_name);
146 (void)set_monster_confused(player_ptr, em_ptr->g_ptr->m_idx, 0);
149 if (em_ptr->m_ptr->is_fearful()) {
150 if (em_ptr->seen_msg) {
151 msg_print(_(format("%s^は勇気を取り戻した。", em_ptr->m_name), format("%s^ recovers %s courage.", em_ptr->m_name, em_ptr->m_poss)));
154 (void)set_monster_monfear(player_ptr, em_ptr->g_ptr->m_idx, 0);
158 ProcessResult effect_monster_old_heal(PlayerType *player_ptr, effect_monster_type *em_ptr)
161 em_ptr->obvious = true;
165 (void)set_monster_csleep(player_ptr, em_ptr->g_ptr->m_idx, 0);
166 effect_monster_old_heal_recovery(player_ptr, em_ptr);
167 if (em_ptr->m_ptr->hp < MONSTER_MAXHP) {
168 em_ptr->m_ptr->hp += em_ptr->dam;
170 if (em_ptr->m_ptr->hp > em_ptr->m_ptr->maxhp) {
171 em_ptr->m_ptr->hp = em_ptr->m_ptr->maxhp;
174 effect_monster_old_heal_check_player(player_ptr, em_ptr);
175 if (em_ptr->m_ptr->r_idx == MonsterRaceId::LEPER) {
176 em_ptr->heal_leper = true;
178 chg_virtue(player_ptr, Virtue::COMPASSION, 5);
182 auto &rfu = RedrawingFlagsUpdater::get_instance();
183 if (player_ptr->health_who == em_ptr->g_ptr->m_idx) {
184 rfu.set_flag(MainWindowRedrawingFlag::HEALTH);
187 if (player_ptr->riding == em_ptr->g_ptr->m_idx) {
188 rfu.set_flag(MainWindowRedrawingFlag::UHEALTH);
191 em_ptr->note = _("は体力を回復したようだ。", " looks healthier.");
193 return ProcessResult::PROCESS_CONTINUE;
196 ProcessResult effect_monster_old_speed(PlayerType *player_ptr, effect_monster_type *em_ptr)
199 em_ptr->obvious = true;
202 if (set_monster_fast(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->m_ptr->get_remaining_acceleration() + 100)) {
203 em_ptr->note = _("の動きが速くなった。", " starts moving faster.");
207 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
208 chg_virtue(player_ptr, Virtue::INDIVIDUALISM, 1);
210 if (em_ptr->m_ptr->is_friendly()) {
211 chg_virtue(player_ptr, Virtue::HONOUR, 1);
216 return ProcessResult::PROCESS_CONTINUE;
219 ProcessResult effect_monster_old_slow(PlayerType *player_ptr, effect_monster_type *em_ptr)
222 em_ptr->obvious = true;
225 bool has_resistance = em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
226 has_resistance |= (em_ptr->r_ptr->level > randint1(std::max(1, em_ptr->dam - 10)) + 10);
228 /* Powerful monsters can resist */
229 if (has_resistance) {
230 em_ptr->note = _("には効果がなかった。", " is unaffected.");
231 em_ptr->obvious = false;
233 return ProcessResult::PROCESS_CONTINUE;
236 if (set_monster_slow(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->m_ptr->get_remaining_deceleration() + 50)) {
237 em_ptr->note = _("の動きが遅くなった。", " starts moving slower.");
241 return ProcessResult::PROCESS_CONTINUE;
245 * @todo 「ユニークは (魔法では)常に眠らない」はMonsterRaceDefinitionの趣旨に反すると思われる
246 * 眠る確率を半分にするとかしておいた方が良さそう
248 ProcessResult effect_monster_old_sleep(PlayerType *player_ptr, effect_monster_type *em_ptr)
251 em_ptr->obvious = true;
254 bool has_resistance = em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
255 has_resistance |= any_bits(em_ptr->r_ptr->flags3, RF3_NO_SLEEP);
256 has_resistance |= (em_ptr->r_ptr->level > randint1(std::max(1, em_ptr->dam - 10)) + 10);
258 if (has_resistance) {
259 if (em_ptr->r_ptr->flags3 & RF3_NO_SLEEP) {
260 if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr)) {
261 em_ptr->r_ptr->r_flags3 |= (RF3_NO_SLEEP);
265 em_ptr->note = _("には効果がなかった。", " is unaffected.");
266 em_ptr->obvious = false;
268 em_ptr->note = _("は眠り込んでしまった!", " falls asleep!");
269 em_ptr->do_sleep = 500;
273 return ProcessResult::PROCESS_CONTINUE;
277 * @todo 「ユニークは (魔法では)常に混乱しない」はMonsterRaceDefinitionの趣旨に反すると思われる
278 * 眠る確率を半分にするとかしておいた方が良さそう
280 ProcessResult effect_monster_old_conf(PlayerType *player_ptr, effect_monster_type *em_ptr)
283 em_ptr->obvious = true;
286 em_ptr->do_conf = damroll(3, (em_ptr->dam / 2)) + 1;
288 bool has_resistance = em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
289 has_resistance |= any_bits(em_ptr->r_ptr->flags3, RF3_NO_CONF);
290 has_resistance |= (em_ptr->r_ptr->level > randint1(std::max(1, em_ptr->dam - 10)) + 10);
291 if (has_resistance) {
292 if (em_ptr->r_ptr->flags3 & (RF3_NO_CONF)) {
293 if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr)) {
294 em_ptr->r_ptr->r_flags3 |= (RF3_NO_CONF);
299 em_ptr->note = _("には効果がなかった。", " is unaffected.");
300 em_ptr->obvious = false;
304 return ProcessResult::PROCESS_CONTINUE;
307 ProcessResult effect_monster_stasis(effect_monster_type *em_ptr, bool to_evil)
310 em_ptr->obvious = true;
313 int stasis_damage = (em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10);
314 bool has_resistance = em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
315 has_resistance |= em_ptr->r_ptr->level > randint1(stasis_damage) + 10;
317 has_resistance |= em_ptr->r_ptr->kind_flags.has_not(MonsterKindType::EVIL);
320 if (has_resistance) {
321 em_ptr->note = _("には効果がなかった。", " is unaffected.");
322 em_ptr->obvious = false;
324 em_ptr->note = _("は動けなくなった!", " is suspended!");
325 em_ptr->do_sleep = 500;
329 return ProcessResult::PROCESS_CONTINUE;
332 ProcessResult effect_monster_stun(effect_monster_type *em_ptr)
335 em_ptr->obvious = true;
338 em_ptr->do_stun = damroll((em_ptr->caster_lev / 20) + 3, (em_ptr->dam)) + 1;
340 bool has_resistance = em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
341 has_resistance |= (em_ptr->r_ptr->level > randint1(std::max(1, em_ptr->dam - 10)) + 10);
342 if (has_resistance) {
344 em_ptr->note = _("には効果がなかった。", " is unaffected.");
345 em_ptr->obvious = false;
349 return ProcessResult::PROCESS_CONTINUE;