#include "main/sound-definitions-table.h"
#include "main/sound-of-music.h"
#include "mind/mind-blue-mage.h"
-#include "monster-race/race-flags4.h"
#include "monster-race/race-flags-ability1.h"
#include "monster-race/race-flags-ability2.h"
+#include "monster-race/race-flags4.h"
#include "mspell/monster-power-table.h"
#include "mspell/mspell-mask-definitions.h"
+#include "mspell/mspell-type.h"
#include "player/attack-defense-types.h"
#include "status/experience.h"
#include "view/display-messages.h"
/*!
+ * @brief モンスター特技がラーニング可能かどうかを返す
+ * @param ms_type モンスター特技ID
+ */
+bool monster_spell_is_learnable(const int monspell)
+{
+ switch (monspell) {
+ case MS_DISPEL:
+ case MS_ROCKET:
+ case MS_SHOOT:
+ case MS_BR_ACID:
+ case MS_BR_ELEC:
+ case MS_BR_FIRE:
+ case MS_BR_COLD:
+ case MS_BR_POIS:
+ case MS_BR_NETHER:
+ case MS_BR_LITE:
+ case MS_BR_DARK:
+ case MS_BR_CONF:
+ case MS_BR_SOUND:
+ case MS_BR_CHAOS:
+ case MS_BR_DISEN:
+ case MS_BR_NEXUS:
+ case MS_BR_TIME:
+ case MS_BR_INERTIA:
+ case MS_BR_GRAVITY:
+ case MS_BR_SHARDS:
+ case MS_BR_PLASMA:
+ case MS_BR_FORCE:
+ case MS_BR_MANA:
+ case MS_BALL_NUKE:
+ case MS_BR_NUKE:
+ case MS_BALL_CHAOS:
+ case MS_BR_DISI:
+ case MS_BALL_ACID:
+ case MS_BALL_ELEC:
+ case MS_BALL_FIRE:
+ case MS_BALL_COLD:
+ case MS_BALL_POIS:
+ case MS_BALL_NETHER:
+ case MS_BALL_WATER:
+ case MS_BALL_MANA:
+ case MS_BALL_DARK:
+ case MS_DRAIN_MANA:
+ case MS_MIND_BLAST:
+ case MS_BRAIN_SMASH:
+ case MS_CAUSE_1:
+ case MS_CAUSE_2:
+ case MS_CAUSE_3:
+ case MS_CAUSE_4:
+ case MS_BOLT_ACID:
+ case MS_BOLT_ELEC:
+ case MS_BOLT_FIRE:
+ case MS_BOLT_COLD:
+ case MS_STARBURST:
+ case MS_BOLT_NETHER:
+ case MS_BOLT_WATER:
+ case MS_BOLT_MANA:
+ case MS_BOLT_PLASMA:
+ case MS_BOLT_ICE:
+ case MS_MAGIC_MISSILE:
+ case MS_SCARE:
+ case MS_BLIND:
+ case MS_CONF:
+ case MS_SLOW:
+ case MS_SLEEP:
+ case MS_HAND_DOOM:
+ case MS_TELE_TO:
+ case MS_TELE_AWAY:
+ case MS_PSY_SPEAR:
+ case MS_DARKNESS:
+ case MS_MAKE_TRAP:
+ case MS_FORGET:
+ case MS_S_KIN:
+ case MS_S_CYBER:
+ case MS_S_MONSTER:
+ case MS_S_MONSTERS:
+ case MS_S_ANT:
+ case MS_S_SPIDER:
+ case MS_S_HOUND:
+ case MS_S_HYDRA:
+ case MS_S_ANGEL:
+ case MS_S_DEMON:
+ case MS_S_UNDEAD:
+ case MS_S_DRAGON:
+ case MS_S_HI_UNDEAD:
+ case MS_S_HI_DRAGON:
+ case MS_S_AMBERITE:
+ case MS_S_UNIQUE:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+/*!
* @brief 青魔法のラーニング判定と成功した場合のラーニング処理
* @param monspell ラーニングを試みるモンスター攻撃のID
* @return なし
#include "system/angband.h"
typedef enum blue_magic_type blue_magic_type;
+
+bool monster_spell_is_learnable(int monspell);
void learn_spell(player_type *learner_ptr, int monspell);
void set_rf_masks(BIT_FLAGS *f4, BIT_FLAGS *f5, BIT_FLAGS *f6, blue_magic_type mode);
{
if ((randint0(100 + ep_ptr->rlev / 2) < target_ptr->skill_sav) && !check_multishadow(target_ptr)) {
msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
- learn_spell(target_ptr, ep_ptr->monspell);
} else {
if (!check_multishadow(target_ptr))
curse_equipment(target_ptr, 15, 0);
{
if ((randint0(100 + ep_ptr->rlev / 2) < target_ptr->skill_sav) && !check_multishadow(target_ptr)) {
msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
- learn_spell(target_ptr, ep_ptr->monspell);
} else {
if (!check_multishadow(target_ptr))
curse_equipment(target_ptr, 25, MIN(ep_ptr->rlev / 2 - 15, 5));
{
if ((randint0(100 + ep_ptr->rlev / 2) < target_ptr->skill_sav) && !check_multishadow(target_ptr)) {
msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
- learn_spell(target_ptr, ep_ptr->monspell);
} else {
if (!check_multishadow(target_ptr))
curse_equipment(target_ptr, 33, MIN(ep_ptr->rlev / 2 - 15, 15));
{
if ((randint0(100 + ep_ptr->rlev / 2) < target_ptr->skill_sav) && !(ep_ptr->m_ptr->r_idx == MON_KENSHIROU) && !check_multishadow(target_ptr)) {
msg_print(_("しかし秘孔を跳ね返した!", "You resist the effects!"));
- learn_spell(target_ptr, ep_ptr->monspell);
} else {
ep_ptr->get_damage = take_hit(target_ptr, DAMAGE_ATTACK, ep_ptr->dam, ep_ptr->killer, ep_ptr->monspell);
if (!check_multishadow(target_ptr))
msg_print(_("気分がよくなった。", "You feel invigorated!"));
hp_player(target_ptr, ep_ptr->dam / 4);
- learn_spell(target_ptr, ep_ptr->monspell);
}
void effect_player_water(player_type *target_ptr, effect_player_type *ep_ptr)
{
if ((randint0(100 + ep_ptr->rlev / 2) < target_ptr->skill_sav) && !check_multishadow(target_ptr)) {
msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
- learn_spell(target_ptr, ep_ptr->monspell);
} else {
if (!check_multishadow(target_ptr)) {
msg_print(_("あなたは命が薄まっていくように感じた!", "You feel your life fade away!"));
target_ptr->csp -= ep_ptr->dam;
}
- learn_spell(target_ptr, ep_ptr->monspell);
target_ptr->redraw |= (PR_MANA);
target_ptr->window_flags |= (PW_PLAYER | PW_SPELL);
{
if ((randint0(100 + ep_ptr->rlev / 2) < MAX(5, target_ptr->skill_sav)) && !check_multishadow(target_ptr)) {
msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
- learn_spell(target_ptr, ep_ptr->monspell);
return;
}
{
if ((randint0(100 + ep_ptr->rlev / 2) < MAX(5, target_ptr->skill_sav)) && !check_multishadow(target_ptr)) {
msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
- learn_spell(target_ptr, ep_ptr->monspell);
return;
}
#include "mspell/improper-mspell-remover.h"
#include "mspell/mspell-attack-util.h"
#include "mspell/mspell-checker.h"
+#include "mspell/mspell-learn-checker.h"
#include "mspell/mspell-lite.h"
#include "mspell/mspell-mask-definitions.h"
#include "mspell/mspell-selector.h"
if (!check_thrown_mspell(target_ptr, msa_ptr))
return FALSE;
+ // 特技使用前の時点でプレイヤーがモンスターを視認できているかチェック(ラーニングの必要条件)。
+ const bool player_could_see_monster = spell_learnable(target_ptr, m_idx);
+
// 特技を使う。
msa_ptr->dam = monspell_to_player(target_ptr, msa_ptr->thrown_spell, msa_ptr->y, msa_ptr->x, m_idx);
if (msa_ptr->dam < 0)
return FALSE;
- // 召喚を行う特技の場合、ラーニング処理。
- // TODO: 全てのラーニング処理をここに集約する。
- if ((target_ptr->action == ACTION_LEARN) && msa_ptr->thrown_spell >= RF4_SPELL_START + MS_S_KIN)
- learn_spell(target_ptr, msa_ptr->thrown_spell - RF4_SPELL_START);
+ // 条件を満たしていればラーニングを試みる。
+ if (player_could_see_monster) {
+ const int monspell = msa_ptr->thrown_spell - RF4_SPELL_START;
+ // XXX: 「暗闇」は特定条件下でライトエリアになる関係上、やむを得ずラー
+ // ニング処理を特技処理に含めた。よって二重ラーニングを行わないようここ
+ // では除外する。
+ const bool try_learn = monster_spell_is_learnable(monspell) && monspell != MS_DARKNESS;
+ if (try_learn)
+ learn_spell(target_ptr, monspell);
+ }
check_mspell_imitation(target_ptr, msa_ptr);
remember_mspell(msa_ptr);
if (typ != GF_ARROW)
flg |= PROJECT_REFLECTABLE;
- bool learnable = spell_learnable(target_ptr, m_idx);
- (void)project(target_ptr, m_idx, 0, y, x, dam_hp, typ, flg, (learnable ? monspell : -1));
+ (void)project(target_ptr, m_idx, 0, y, x, dam_hp, typ, flg, monspell);
}
/*!
break;
}
- bool learnable = spell_learnable(target_ptr, m_idx);
- (void)project(target_ptr, m_idx, 0, y, x, dam_hp, typ, flg, (learnable ? monspell : -1));
+ (void)project(target_ptr, m_idx, 0, y, x, dam_hp, typ, flg, monspell);
}
/*!
break;
}
- bool learnable = spell_learnable(target_ptr, m_idx);
- (void)project(target_ptr, m_idx, rad, y, x, dam_hp, typ, flg, (learnable ? monspell : -1));
+ (void)project(target_ptr, m_idx, rad, y, x, dam_hp, typ, flg, monspell);
}
/*!
#include "status/temporary-resistance.h"
#include "view/display-messages.h"
-#include "status/buff-setter.h"
#include "core/speed-table.h"
#include "monster/monster-status-setter.h"
#include "player/attack-defense-types.h"
#include "player/player-race.h"
+#include "status/buff-setter.h"
/*!
* @brief プレイヤーに魔力消去効果を与える。
msg_print(_("弱い者いじめは止めるんだ!", ""));
}
- learn_spell(target_ptr, MS_DISPEL);
return;
}
if (TARGET_TYPE == MONSTER_TO_PLAYER) {
teleport_player_to(target_ptr, m_ptr->fy, m_ptr->fx, TELEPORT_PASSIVE);
- learn_spell(target_ptr, MS_TELE_TO);
return;
}
msg_print(_("弱い者いじめは止めるんだ!", ""));
}
- learn_spell(target_ptr, MS_TELE_AWAY);
teleport_player_away(m_idx, target_ptr, 100, FALSE);
return;
}
teleport_level(target_ptr, 0);
}
- learn_spell(target_ptr, MS_TELE_LEVEL);
update_smart_learn(target_ptr, m_idx, DRS_NEXUS);
return;
}
if (can_use_lite_area) {
(void)lite_area(target_ptr, 0, 3);
} else {
+ // XXX: ラーニング条件が特技IDのみから決まらないため、やむを得ずここでラーニング処理を行う。
learn_spell(target_ptr, MS_DARKNESS);
(void)unlite_area(target_ptr, 0, 3);
}
else
msg_format(_("%^sが呪文を唱えて邪悪に微笑んだ。", "%^s casts a spell and cackles evilly."), m_name);
- learn_spell(target_ptr, MS_MAKE_TRAP);
(void)trap_creation(target_ptr, y, x);
}
* @param target_ptr プレーヤーへの参照ポインタ
* @param m_idx モンスターID
* @return プレイヤーが青魔法で学習できるならTRUE、そうでなければFALSEを返す。
+ *
+ * モンスターが特技を使う前にプレイヤーがモンスターを視認できているかどうかの判定用。
*/
bool spell_learnable(player_type *target_ptr, MONSTER_IDX m_idx)
{
#include "core/player-redraw-types.h"
#include "mind/drs-types.h"
#include "monster-race/monster-race.h"
-#include "monster-race/race-indice-types.h"
#include "monster-race/race-flags1.h"
#include "monster-race/race-flags3.h"
+#include "monster-race/race-indice-types.h"
#include "monster/monster-describer.h"
#include "monster/monster-description-types.h"
#include "monster/monster-info.h"
(void)set_afraid(target_ptr, target_ptr->afraid + randint0(4) + 4);
}
- learn_spell(target_ptr, MS_SCARE);
update_smart_learn(target_ptr, m_idx, DRS_FEAR);
return;
}
(void)set_blind(target_ptr, 12 + randint0(4));
}
- learn_spell(target_ptr, MS_BLIND);
update_smart_learn(target_ptr, m_idx, DRS_BLIND);
return;
}
(void)set_confused(target_ptr, target_ptr->confused + randint0(4) + 4);
}
- learn_spell(target_ptr, MS_CONF);
update_smart_learn(target_ptr, m_idx, DRS_CONF);
return;
}
(void)set_paralyzed(target_ptr, target_ptr->paralyzed + randint0(4) + 4);
}
- learn_spell(target_ptr, MS_SLEEP);
update_smart_learn(target_ptr, m_idx, DRS_FREE);
return;
}
(void)set_slow(target_ptr, target_ptr->slow + randint0(4) + 4, FALSE);
}
- learn_spell(target_ptr, MS_SLOW);
update_smart_learn(target_ptr, m_idx, DRS_FREE);
return;
}
} else if (lose_all_info(target_ptr)) {
msg_print(_("記憶が薄れてしまった。", "Your memories fade away."));
}
-
- learn_spell(target_ptr, MS_FORGET);
}
int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
bool double_resist = is_oppose_acid(creature_ptr);
dam = dam * calc_acid_damage_rate(creature_ptr) / 100;
- if (dam <= 0) {
- learn_spell(creature_ptr, monspell);
+ if (dam <= 0)
return 0;
- }
if (aura || !check_multishadow(creature_ptr)) {
if ((!(double_resist || has_resist_acid(creature_ptr))) && one_in_(HURT_CHANCE))
dam = dam * calc_elec_damage_rate(creature_ptr) / 100;
- if (dam <= 0) {
- learn_spell(creature_ptr, monspell);
+ if (dam <= 0)
return 0;
- }
if (aura || !check_multishadow(creature_ptr)) {
if ((!(double_resist || has_resist_elec(creature_ptr))) && one_in_(HURT_CHANCE))
bool double_resist = is_oppose_fire(creature_ptr);
/* Totally immune */
- if (has_immune_fire(creature_ptr) || (dam <= 0)) {
- learn_spell(creature_ptr, monspell);
+ if (has_immune_fire(creature_ptr) || (dam <= 0))
return 0;
- }
dam = dam * calc_fire_damage_rate(creature_ptr) / 100;
if (aura || !check_multishadow(creature_ptr)) {
{
int inv = (dam < 30) ? 1 : (dam < 60) ? 2 : 3;
bool double_resist = is_oppose_cold(creature_ptr);
- if (has_immune_cold(creature_ptr) || (dam <= 0)) {
- learn_spell(creature_ptr, monspell);
+ if (has_immune_cold(creature_ptr) || (dam <= 0))
return 0;
- }
dam = dam * calc_cold_damage_rate(creature_ptr) / 100;
if (aura || !check_multishadow(creature_ptr)) {
}
}
- if (monspell >= 0)
- learn_spell(creature_ptr, monspell);
-
if ((damage_type != DAMAGE_USELIFE) && (damage_type != DAMAGE_LOSELIFE)) {
if (is_invuln(creature_ptr) && (damage < 9000)) {
if (damage_type == DAMAGE_FORCE) {