case MUTA::TRUNK:
case MUTA::TENTACLES:
default: {
- MonsterDamageProcessor mdp(player_ptr, m_idx, k, fear);
+ MonsterDamageProcessor mdp(player_ptr, m_idx, k, fear, GF_ATTACK);
*mdeath = mdp.mon_take_hit(nullptr);
break;
}
HIT_POINT dam = damroll(2, 6);
dam = mon_damage_mod(player_ptr, monap_ptr->m_ptr, dam, false);
msg_format(_("%^sは突然熱くなった!", "%^s is suddenly very hot!"), monap_ptr->m_name);
- MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear);
+ MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, GF_FIRE);
if (mdp.mon_take_hit(_("は灰の山になった。", " turns into a pile of ash."))) {
monap_ptr->blinked = false;
monap_ptr->alive = false;
HIT_POINT dam = damroll(2, 6);
dam = mon_damage_mod(player_ptr, monap_ptr->m_ptr, dam, false);
msg_format(_("%^sは電撃をくらった!", "%^s gets zapped!"), monap_ptr->m_name);
- MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear);
+ MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, GF_ELEC);
if (mdp.mon_take_hit(_("は燃え殻の山になった。", " turns into a pile of cinders."))) {
monap_ptr->blinked = false;
monap_ptr->alive = false;
HIT_POINT dam = damroll(2, 6);
dam = mon_damage_mod(player_ptr, monap_ptr->m_ptr, dam, false);
msg_format(_("%^sは冷気をくらった!", "%^s is very cold!"), monap_ptr->m_name);
- MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear);
+ MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, GF_COLD);
if (mdp.mon_take_hit(_("は凍りついた。", " was frozen."))) {
monap_ptr->blinked = false;
monap_ptr->alive = false;
HIT_POINT dam = damroll(2, 6);
dam = mon_damage_mod(player_ptr, monap_ptr->m_ptr, dam, false);
msg_format(_("%^sは鏡の破片をくらった!", "%^s gets sliced!"), monap_ptr->m_name);
- MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear);
+ MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, GF_SHARDS);
if (mdp.mon_take_hit(_("はズタズタになった。", " is torn to pieces."))) {
monap_ptr->blinked = false;
monap_ptr->alive = false;
HIT_POINT dam = damroll(2, 6);
dam = mon_damage_mod(player_ptr, monap_ptr->m_ptr, dam, false);
msg_format(_("%^sは聖なるオーラで傷ついた!", "%^s is injured by holy power!"), monap_ptr->m_name);
- MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear);
+ MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, GF_HOLY_FIRE);
if (mdp.mon_take_hit(_("は倒れた。", " is destroyed."))) {
monap_ptr->blinked = false;
monap_ptr->alive = false;
HIT_POINT dam = damroll(2, 6);
dam = mon_damage_mod(player_ptr, monap_ptr->m_ptr, dam, false);
msg_format(_("%^sが鋭い闘気のオーラで傷ついた!", "%^s is injured by the Force"), monap_ptr->m_name);
- MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear);
+ MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, GF_MANA);
if (mdp.mon_take_hit(_("は倒れた。", " is destroyed."))) {
monap_ptr->blinked = false;
monap_ptr->alive = false;
dam = mon_damage_mod(player_ptr, monap_ptr->m_ptr, dam, false);
msg_format(_("影のオーラが%^sに反撃した!", "Enveloping shadows attack %^s."), monap_ptr->m_name);
- MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear);
+ MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, GF_DARK);
if (mdp.mon_take_hit(_("は倒れた。", " is destroyed."))) {
monap_ptr->blinked = false;
monap_ptr->alive = false;
#include "world/world-object.h"
/*!
+ * @brief 矢弾の属性を定義する
+ * @param bow_ptr 弓のオブジェクト構造体参照ポインタ
+ * @param arrow_ptr 矢弾のオブジェクト構造体参照ポインタ
+ * @return スナイパーの射撃属性、弓矢の属性を考慮する。デフォルトはGF_PLAYER_SHOOT。
+ */
+EFFECT_ID shot_effect_type(player_type *player_ptr, object_type *bow_ptr, object_type *arrow_ptr, SPELL_IDX snipe_type)
+{
+ TrFlags flags{};
+ auto arrow_flags = object_flags(arrow_ptr);
+ auto bow_flags = object_flags(bow_ptr);
+
+ flags = bow_flags | arrow_flags;
+
+ static const struct snipe_convert_table_t {
+ SPELL_IDX snipe_type;
+ EFFECT_ID effect_type;
+ } snipe_convert_table[] = {
+ { SP_LITE, GF_LITE },
+ { SP_FIRE, GF_FIRE },
+ { SP_COLD, GF_COLD },
+ { SP_ELEC, GF_ELEC },
+ { SP_KILL_WALL, GF_KILL_WALL },
+ { SP_EVILNESS, GF_HELL_FIRE },
+ { SP_HOLYNESS, GF_HOLY_FIRE },
+ { SP_FINAL, GF_MANA },
+ };
+
+ static const struct brand_convert_table_t {
+ tr_type brand_type;
+ EFFECT_ID effect_type;
+ } brand_convert_table[] = {
+ { TR_BRAND_ACID, GF_ACID },
+ { TR_BRAND_FIRE, GF_FIRE },
+ { TR_BRAND_ELEC, GF_ELEC },
+ { TR_BRAND_COLD, GF_COLD },
+ { TR_BRAND_POIS, GF_POIS },
+ { TR_SLAY_GOOD, GF_HELL_FIRE },
+ { TR_KILL_GOOD, GF_HELL_FIRE },
+ { TR_SLAY_EVIL, GF_HOLY_FIRE },
+ { TR_KILL_EVIL, GF_HOLY_FIRE },
+ };
+
+ for (size_t i = 0; i < sizeof(snipe_convert_table) / sizeof(snipe_convert_table[0]); ++i) {
+ const struct snipe_convert_table_t *p = &snipe_convert_table[i];
+
+ if (snipe_type == p->snipe_type)
+ return p->effect_type;
+ }
+
+ for (size_t i = 0; i < sizeof(brand_convert_table) / sizeof(brand_convert_table[0]); ++i) {
+ const struct brand_convert_table_t *p = &brand_convert_table[i];
+
+ if (flags.has(p->brand_type))
+ return p->effect_type;
+ }
+
+ if ((flags.has(TR_FORCE_WEAPON)) && (player_ptr->csp > (player_ptr->msp / 30))) {
+ return GF_MANA;
+ }
+
+ return GF_PLAYER_SHOOT;
+}
+
+/*!
* @brief 矢弾を射撃した際のスレイ倍率をかけた結果を返す /
* Determines the odds of an object breaking when thrown at a monster
* @param bow_ptr 弓のオブジェクト構造体参照ポインタ
object_type forge;
object_type *q_ptr;
-
object_type *o_ptr;
+ EFFECT_ID effect_type = GF_PLAYER_SHOOT;
+
bool hit_body = false;
GAME_TEXT o_name[MAX_NLEN];
base_dam = tdam;
}
} else {
+
+ effect_type = shot_effect_type(player_ptr, j_ptr, q_ptr, snipe_type);
/* Apply special damage */
tdam = calc_shot_damage_with_slay(player_ptr, j_ptr, q_ptr, tdam, m_ptr, snipe_type);
tdam = critical_shot(player_ptr, q_ptr->weight, q_ptr->to_h, j_ptr->to_h, tdam);
}
/* Hit the monster, check for death */
- MonsterDamageProcessor mdp(player_ptr, c_mon_ptr->m_idx, tdam, &fear);
+ MonsterDamageProcessor mdp(player_ptr, c_mon_ptr->m_idx, tdam, &fear, effect_type);
if (mdp.mon_take_hit(extract_note_dies(real_r_idx(m_ptr)))) {
/* Dead monster */
}
#include "realm/realm-hex-numbers.h"
#include "specific-object/torch.h"
#include "spell-realm/spells-hex.h"
+#include "spell/spell-types.h"
#include "system/monster-race-definition.h"
#include "system/monster-type-definition.h"
#include "system/object-type-definition.h"
mult = 150;
return (tdam * mult / 10);
}
+
+EFFECT_ID melee_effect_type(player_type *player_ptr, object_type *o_ptr, combat_options mode)
+{
+ if (player_ptr->pclass == PlayerClassType::SAMURAI) {
+ static const struct samurai_convert_table_t {
+ combat_options hissatsu_type;
+ EFFECT_ID effect_type;
+ } samurai_convert_table[] = {
+ { HISSATSU_FIRE, GF_FIRE },
+ { HISSATSU_COLD, GF_COLD },
+ { HISSATSU_ELEC, GF_ELEC },
+ { HISSATSU_POISON, GF_POIS },
+ { HISSATSU_HAGAN, GF_KILL_WALL },
+ };
+
+ for (size_t i = 0; i < sizeof(samurai_convert_table) / sizeof(samurai_convert_table[0]); ++i) {
+ const struct samurai_convert_table_t *p = &samurai_convert_table[i];
+
+ if (mode == p->hissatsu_type)
+ return p->effect_type;
+ }
+ }
+
+ auto flgs = object_flags(o_ptr);
+
+ if (player_ptr->special_attack & (ATTACK_ACID))
+ flgs.set(TR_BRAND_ACID);
+ if (player_ptr->special_attack & (ATTACK_COLD))
+ flgs.set(TR_BRAND_COLD);
+ if (player_ptr->special_attack & (ATTACK_ELEC))
+ flgs.set(TR_BRAND_ELEC);
+ if (player_ptr->special_attack & (ATTACK_FIRE))
+ flgs.set(TR_BRAND_FIRE);
+ if (player_ptr->special_attack & (ATTACK_POIS))
+ flgs.set(TR_BRAND_POIS);
+
+ if (SpellHex(player_ptr).is_spelling_specific(HEX_RUNESWORD))
+ flgs.set(TR_SLAY_GOOD);
+
+ static const struct brand_convert_table_t {
+ tr_type brand_type;
+ EFFECT_ID effect_type;
+ } brand_convert_table[] = {
+ { TR_BRAND_ACID, GF_ACID },
+ { TR_BRAND_FIRE, GF_FIRE },
+ { TR_BRAND_ELEC, GF_ELEC },
+ { TR_BRAND_COLD, GF_COLD },
+ { TR_BRAND_POIS, GF_POIS },
+ { TR_SLAY_GOOD, GF_HELL_FIRE },
+ { TR_KILL_GOOD, GF_HELL_FIRE },
+ { TR_SLAY_EVIL, GF_HOLY_FIRE },
+ { TR_KILL_EVIL, GF_HOLY_FIRE },
+ };
+
+ for (size_t i = 0; i < sizeof(brand_convert_table) / sizeof(brand_convert_table[0]); ++i) {
+ const struct brand_convert_table_t *p = &brand_convert_table[i];
+
+ if (flgs.has(p->brand_type))
+ return p->effect_type;
+ }
+
+
+ if ((flgs.has(TR_FORCE_WEAPON)) && (player_ptr->csp > (o_ptr->dd * o_ptr->ds / 5))) {
+ return GF_MANA;
+ }
+
+ return GF_ATTACK;
+}
MULTIPLY mult_slaying(player_type *player_ptr, MULTIPLY mult, const TrFlags &flgs, monster_type *m_ptr);
MULTIPLY mult_brand(player_type *player_ptr, MULTIPLY mult, const TrFlags &flgs, monster_type *m_ptr);
HIT_POINT calc_attack_damage_with_slay(player_type *player_ptr, object_type *o_ptr, HIT_POINT tdam, monster_type *m_ptr, combat_options mode, bool thrown);
+EFFECT_ID melee_effect_type(player_type *player_ptr, object_type *o_ptr, combat_options mode);
#pragma once
#include "system/angband.h"
+#include "spell/spell-types.h"
struct grid_type;;
struct monster_type;
static bool deal_effect_damage_from_player(player_type *player_ptr, effect_monster_type *em_ptr)
{
bool fear = false;
- MonsterDamageProcessor mdp(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam, &fear);
+ MonsterDamageProcessor mdp(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam, &fear, em_ptr->effect_type);
if (mdp.mon_take_hit(em_ptr->note_dies))
return true;
#pragma once
#include "system/angband.h"
+#include "spell/spell-types.h"
struct player_type;
bool affect_monster(player_type *player_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ, BIT_FLAGS flag, bool see_s_msg);
}
sound(SOUND_EXPLODE);
- MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, monap_ptr->m_ptr->hp + 1, &monap_ptr->fear);
+ MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, monap_ptr->m_ptr->hp + 1, &monap_ptr->fear, GF_NONE);
if (mdp.mon_take_hit(nullptr)) {
monap_ptr->blinked = false;
monap_ptr->alive = false;
* @param m_idx ダメージを与えたモンスターのID
* @param dam 与えたダメージ量
* @param fear ダメージによってモンスターが恐慌状態に陥ったならばtrue
+ * @param type 与えたダメージの種類
* @param note モンスターが倒された際の特別なメッセージ述語
*/
-MonsterDamageProcessor::MonsterDamageProcessor(player_type *player_ptr, MONSTER_IDX m_idx, HIT_POINT dam, bool *fear)
+MonsterDamageProcessor::MonsterDamageProcessor(player_type *player_ptr, MONSTER_IDX m_idx, HIT_POINT dam, bool *fear, EFFECT_ID effect_type)
: player_ptr(player_ptr)
, m_idx(m_idx)
, dam(dam)
, fear(fear)
+ , effect_type(effect_type)
{
}
}
if (allow_debug_options) {
- msg_format(_("合計%d/%dのダメージを与えた。", "You do %d (out of %d) damage."), m_ptr->dealt_damage, m_ptr->maxhp);
+ msg_format(_("合計%d/%dのダメージを与えた。(EffectID: %d)", "You do %d (out of %d) damage. (EffectID: %d)"), m_ptr->dealt_damage, m_ptr->maxhp, this->effect_type);
}
if (this->process_dead_exp_virtue(note, &exp_mon)) {
#include "monster-race/race-indice-types.h"
#include "system/angband.h"
+#include "spell/spell-types.h"
#include <tuple>
#include <vector>
typedef std::vector<std::tuple<monster_race_type, monster_race_type, monster_race_type>> combined_uniques;
class MonsterDamageProcessor {
public:
- MonsterDamageProcessor(player_type *player_ptr, MONSTER_IDX m_idx, HIT_POINT dam, bool *fear);
+ MonsterDamageProcessor(player_type *player_ptr, MONSTER_IDX m_idx, HIT_POINT dam, bool *fear, EFFECT_ID effect_type);
virtual ~MonsterDamageProcessor() = default;
bool mon_take_hit(concptr note);
MONSTER_IDX m_idx;
HIT_POINT dam;
bool *fear;
+ EFFECT_ID effect_type;
void get_exp_from_mon(monster_type *m_ptr, HIT_POINT exp_dam);
bool genocide_chaos_patron();
bool process_dead_exp_virtue(concptr note, monster_type *exp_mon);
#include "player/player-status-table.h"
#include "racial/racial-android.h"
#include "specific-object/torch.h"
+#include "spell/spell-types.h"
#include "system/floor-type-definition.h"
#include "system/grid-type-definition.h"
#include "system/monster-type-definition.h"
this->m_ptr->hp - this->tdam, this->m_ptr->maxhp, this->m_ptr->max_maxhp);
auto fear = false;
- MonsterDamageProcessor mdp(this->player_ptr, this->g_ptr->m_idx, this->tdam, &fear);
+ EFFECT_ID effect_type = GF_PLAYER_SHOOT;
+ if (is_active_torch(this->o_ptr))
+ effect_type = GF_FIRE;
+
+ MonsterDamageProcessor mdp(this->player_ptr, this->g_ptr->m_idx, this->tdam, &fear, effect_type);
if (mdp.mon_take_hit(extract_note_dies(real_r_idx(this->m_ptr)))) {
return;
}
int drain_result{}; //!< 吸血した累積量
int drain_left{}; //!< 吸血できる残量(最大MAX_VAMPIRIC_DRAIN)
bool weak{}; //!< 打撃効果でモンスターが弱くなったかどうか
+ EFFECT_ID effect_type{}; //!< 与えたダメージの種類
} player_attack_type;
*/
static bool check_fear_death(player_type *player_ptr, player_attack_type *pa_ptr, const int num, const bool is_lowlevel)
{
- MonsterDamageProcessor mdp(player_ptr, pa_ptr->m_idx, pa_ptr->attack_damage, pa_ptr->fear);
+ MonsterDamageProcessor mdp(player_ptr, pa_ptr->m_idx, pa_ptr->attack_damage, pa_ptr->fear, pa_ptr->effect_type);
if (!mdp.mon_take_hit(nullptr))
return false;
if (!process_attack_hit(player_ptr, pa_ptr, chance))
continue;
+ pa_ptr->effect_type = melee_effect_type(player_ptr, o_ptr, pa_ptr->mode);
apply_actual_attack(player_ptr, pa_ptr, &do_quake, is_zantetsu_nullified, is_ej_nullified);
calc_drain(pa_ptr);
if (check_fear_death(player_ptr, pa_ptr, num, is_lowlevel))
#include <vector>
/*!
+ * @brief 該当オブジェクトが残量アリの松明か否かを判定。
+ * @param o_ptr オブジェクトの構造体参照ポインタ
+ * @return 残量アリの松明ならtrue
+ */
+bool is_active_torch(object_type *o_ptr)
+{
+ return (o_ptr->tval == ItemKindType::LITE) && (o_ptr->sval == SV_LITE_TORCH) && (o_ptr->xtra4 > 0);
+}
+
+/*!
* @brief 投擲時たいまつに投げやすい/焼棄/アンデッドスレイの特別効果を返す。
* Torches have special abilities when they are flaming.
* @param o_ptr 投擲するオブジェクトの構造体参照ポインタ
*/
void torch_flags(object_type *o_ptr, TrFlags &flgs)
{
- if ((o_ptr->tval != ItemKindType::LITE) || (o_ptr->sval != SV_LITE_TORCH) || (o_ptr->xtra4 <= 0))
+ if (!is_active_torch(o_ptr))
return;
flgs.set(TR_BRAND_FIRE);
*/
void torch_dice(object_type *o_ptr, DICE_NUMBER *dd, DICE_SID *ds)
{
- if ((o_ptr->tval != ItemKindType::LITE) || (o_ptr->sval != SV_LITE_TORCH) || (o_ptr->xtra4 <= 0))
+ if (!is_active_torch(o_ptr))
return;
*dd = 1;
*/
void torch_lost_fuel(object_type *o_ptr)
{
- if ((o_ptr->tval != ItemKindType::LITE) || (o_ptr->sval != SV_LITE_TORCH))
+ if (!is_active_torch(o_ptr))
return;
o_ptr->xtra4 -= (FUEL_TORCH / 25);
struct object_type;
struct player_type;
+bool is_active_torch(object_type *o_ptr);
void torch_flags(object_type *o_ptr, TrFlags &flgs);
void torch_dice(object_type *o_ptr, DICE_NUMBER *dd, DICE_SID *ds);
void torch_lost_fuel(object_type *o_ptr);
GF_VOID = 118, /*!< 魔法効果: 虚無 */
GF_ABYSS = 119, /*!< 魔法効果: 深淵 */
GF_HUNGRY = 120, /*!< 魔法効果: 空腹>*/
- MAX_GF = 121, /*!< 欠番を無視した最大サイズ (直上の値+1) */
+ GF_PLAYER_SHOOT = 121, /*!< 属性取得用: プレイヤーの射撃/投擲>*/
+ MAX_GF = 122, /*!< 欠番を無視した最大サイズ (直上の値+1) */
};