-#include "combat/shoot.h"
+#include "combat/shoot.h"
#include "artifact/fixed-art-types.h"
#include "avatar/avatar.h"
#include "combat/attack-criticality.h"
-#include "core/player-redraw-types.h"
-#include "core/player-update-types.h"
#include "core/stuff-handler.h"
#include "effect/attribute-types.h"
#include "effect/effect-characteristics.h"
#include "monster/monster-damage.h"
#include "monster/monster-describer.h"
#include "monster/monster-info.h"
+#include "monster/monster-pain-describer.h"
#include "monster/monster-status-setter.h"
#include "monster/monster-status.h"
#include "monster/monster-update.h"
#include "object/object-broken.h"
-#include "object/object-flags.h"
#include "object/object-info.h"
#include "object/object-mark-types.h"
#include "player-base/player-class.h"
#include "player/player-status-table.h"
#include "sv-definition/sv-bow-types.h"
#include "system/artifact-type-definition.h"
-#include "system/baseitem-info-definition.h"
+#include "system/baseitem-info.h"
#include "system/floor-type-definition.h"
#include "system/grid-type-definition.h"
#include "system/item-entity.h"
+#include "system/monster-entity.h"
#include "system/monster-race-info.h"
-#include "system/monster-type-definition.h"
#include "system/player-type-definition.h"
+#include "system/redrawing-flags-updater.h"
#include "target/projection-path-calculator.h"
#include "target/target-checker.h"
#include "target/target-getter.h"
AttributeFlags attribute_flags{};
attribute_flags.set(AttributeType::PLAYER_SHOOT);
- TrFlags flags{};
- auto arrow_flags = object_flags(arrow_ptr);
- auto bow_flags = object_flags(bow_ptr);
-
- flags = bow_flags | arrow_flags;
+ const auto arrow_flags = arrow_ptr->get_flags();
+ const auto bow_flags = bow_ptr->get_flags();
+ const auto flags = bow_flags | arrow_flags;
static const struct snipe_convert_table_t {
SPELL_IDX snipe_type;
{
MULTIPLY mult = 10;
- MonsterRaceInfo *race_ptr = &monraces_info[monster_ptr->r_idx];
-
- TrFlags flags{};
- auto arrow_flags = object_flags(arrow_ptr);
- auto bow_flags = object_flags(bow_ptr);
+ auto &monrace = monster_ptr->get_monrace();
- flags = bow_flags | arrow_flags;
+ const auto arrow_flags = arrow_ptr->get_flags();
+ const auto bow_flags = bow_ptr->get_flags();
+ const auto flags = bow_flags | arrow_flags;
/* Some "weapons" and "ammo" do extra damage */
- switch (arrow_ptr->tval) {
+ switch (arrow_ptr->bi_key.tval()) {
case ItemKindType::SHOT:
case ItemKindType::ARROW:
case ItemKindType::BOLT: {
- if ((flags.has(TR_SLAY_ANIMAL)) && race_ptr->kind_flags.has(MonsterKindType::ANIMAL)) {
+ if ((flags.has(TR_SLAY_ANIMAL)) && monrace.kind_flags.has(MonsterKindType::ANIMAL)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::ANIMAL);
+ monrace.r_kind_flags.set(MonsterKindType::ANIMAL);
}
if (mult < 17) {
mult = 17;
}
}
- if ((flags.has(TR_KILL_ANIMAL)) && race_ptr->kind_flags.has(MonsterKindType::ANIMAL)) {
+ if ((flags.has(TR_KILL_ANIMAL)) && monrace.kind_flags.has(MonsterKindType::ANIMAL)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::ANIMAL);
+ monrace.r_kind_flags.set(MonsterKindType::ANIMAL);
}
if (mult < 27) {
mult = 27;
}
}
- if ((flags.has(TR_SLAY_EVIL)) && race_ptr->kind_flags.has(MonsterKindType::EVIL)) {
+ if ((flags.has(TR_SLAY_EVIL)) && monrace.kind_flags.has(MonsterKindType::EVIL)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::EVIL);
+ monrace.r_kind_flags.set(MonsterKindType::EVIL);
}
if (mult < 15) {
mult = 15;
}
}
- if ((flags.has(TR_KILL_EVIL)) && race_ptr->kind_flags.has(MonsterKindType::EVIL)) {
+ if ((flags.has(TR_KILL_EVIL)) && monrace.kind_flags.has(MonsterKindType::EVIL)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::EVIL);
+ monrace.r_kind_flags.set(MonsterKindType::EVIL);
}
if (mult < 25) {
mult = 25;
}
}
- if ((flags.has(TR_SLAY_GOOD)) && race_ptr->kind_flags.has(MonsterKindType::GOOD)) {
+ if ((flags.has(TR_SLAY_GOOD)) && monrace.kind_flags.has(MonsterKindType::GOOD)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::GOOD);
+ monrace.r_kind_flags.set(MonsterKindType::GOOD);
}
if (mult < 15) {
mult = 15;
}
}
- if ((flags.has(TR_KILL_GOOD)) && race_ptr->kind_flags.has(MonsterKindType::GOOD)) {
+ if ((flags.has(TR_KILL_GOOD)) && monrace.kind_flags.has(MonsterKindType::GOOD)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::GOOD);
+ monrace.r_kind_flags.set(MonsterKindType::GOOD);
}
if (mult < 25) {
mult = 25;
}
}
- if ((flags.has(TR_SLAY_HUMAN)) && race_ptr->kind_flags.has(MonsterKindType::HUMAN)) {
+ if ((flags.has(TR_SLAY_HUMAN)) && monrace.kind_flags.has(MonsterKindType::HUMAN)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::HUMAN);
+ monrace.r_kind_flags.set(MonsterKindType::HUMAN);
}
if (mult < 17) {
mult = 17;
}
}
- if ((flags.has(TR_KILL_HUMAN)) && race_ptr->kind_flags.has(MonsterKindType::HUMAN)) {
+ if ((flags.has(TR_KILL_HUMAN)) && monrace.kind_flags.has(MonsterKindType::HUMAN)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::HUMAN);
+ monrace.r_kind_flags.set(MonsterKindType::HUMAN);
}
if (mult < 27) {
mult = 27;
}
}
- if ((flags.has(TR_SLAY_UNDEAD)) && race_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
+ if ((flags.has(TR_SLAY_UNDEAD)) && monrace.kind_flags.has(MonsterKindType::UNDEAD)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::UNDEAD);
+ monrace.r_kind_flags.set(MonsterKindType::UNDEAD);
}
if (mult < 20) {
mult = 20;
}
}
- if ((flags.has(TR_KILL_UNDEAD)) && race_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
+ if ((flags.has(TR_KILL_UNDEAD)) && monrace.kind_flags.has(MonsterKindType::UNDEAD)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::UNDEAD);
+ monrace.r_kind_flags.set(MonsterKindType::UNDEAD);
}
if (mult < 30) {
mult = 30;
}
}
- if ((flags.has(TR_SLAY_DEMON)) && race_ptr->kind_flags.has(MonsterKindType::DEMON)) {
+ if ((flags.has(TR_SLAY_DEMON)) && monrace.kind_flags.has(MonsterKindType::DEMON)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::DEMON);
+ monrace.r_kind_flags.set(MonsterKindType::DEMON);
}
if (mult < 20) {
mult = 20;
}
}
- if ((flags.has(TR_KILL_DEMON)) && race_ptr->kind_flags.has(MonsterKindType::DEMON)) {
+ if ((flags.has(TR_KILL_DEMON)) && monrace.kind_flags.has(MonsterKindType::DEMON)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::DEMON);
+ monrace.r_kind_flags.set(MonsterKindType::DEMON);
}
if (mult < 30) {
mult = 30;
}
}
- if ((flags.has(TR_SLAY_ORC)) && race_ptr->kind_flags.has(MonsterKindType::ORC)) {
+ if ((flags.has(TR_SLAY_ORC)) && monrace.kind_flags.has(MonsterKindType::ORC)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::ORC);
+ monrace.r_kind_flags.set(MonsterKindType::ORC);
}
if (mult < 20) {
mult = 20;
}
}
- if ((flags.has(TR_KILL_ORC)) && race_ptr->kind_flags.has(MonsterKindType::ORC)) {
+ if ((flags.has(TR_KILL_ORC)) && monrace.kind_flags.has(MonsterKindType::ORC)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::ORC);
+ monrace.r_kind_flags.set(MonsterKindType::ORC);
}
if (mult < 30) {
mult = 30;
}
}
- if ((flags.has(TR_SLAY_TROLL)) && race_ptr->kind_flags.has(MonsterKindType::TROLL)) {
+ if ((flags.has(TR_SLAY_TROLL)) && monrace.kind_flags.has(MonsterKindType::TROLL)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::TROLL);
+ monrace.r_kind_flags.set(MonsterKindType::TROLL);
}
if (mult < 20) {
}
}
- if ((flags.has(TR_KILL_TROLL)) && race_ptr->kind_flags.has(MonsterKindType::TROLL)) {
+ if ((flags.has(TR_KILL_TROLL)) && monrace.kind_flags.has(MonsterKindType::TROLL)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::TROLL);
+ monrace.r_kind_flags.set(MonsterKindType::TROLL);
}
if (mult < 30) {
mult = 30;
}
}
- if ((flags.has(TR_SLAY_GIANT)) && race_ptr->kind_flags.has(MonsterKindType::GIANT)) {
+ if ((flags.has(TR_SLAY_GIANT)) && monrace.kind_flags.has(MonsterKindType::GIANT)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::GIANT);
+ monrace.r_kind_flags.set(MonsterKindType::GIANT);
}
if (mult < 20) {
mult = 20;
}
}
- if ((flags.has(TR_KILL_GIANT)) && race_ptr->kind_flags.has(MonsterKindType::GIANT)) {
+ if ((flags.has(TR_KILL_GIANT)) && monrace.kind_flags.has(MonsterKindType::GIANT)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::GIANT);
+ monrace.r_kind_flags.set(MonsterKindType::GIANT);
}
if (mult < 30) {
mult = 30;
}
}
- if ((flags.has(TR_SLAY_DRAGON)) && race_ptr->kind_flags.has(MonsterKindType::DRAGON)) {
+ if ((flags.has(TR_SLAY_DRAGON)) && monrace.kind_flags.has(MonsterKindType::DRAGON)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::DRAGON);
+ monrace.r_kind_flags.set(MonsterKindType::DRAGON);
}
if (mult < 20) {
mult = 20;
}
}
- if ((flags.has(TR_KILL_DRAGON)) && race_ptr->kind_flags.has(MonsterKindType::DRAGON)) {
+ if ((flags.has(TR_KILL_DRAGON)) && monrace.kind_flags.has(MonsterKindType::DRAGON)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_kind_flags.set(MonsterKindType::DRAGON);
+ monrace.r_kind_flags.set(MonsterKindType::DRAGON);
}
if (mult < 30) {
mult = 30;
if (flags.has(TR_BRAND_ACID)) {
/* Notice immunity */
- if (race_ptr->resistance_flags.has_any_of(RFR_EFF_IM_ACID_MASK)) {
+ if (monrace.resistance_flags.has_any_of(RFR_EFF_IM_ACID_MASK)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_resistance_flags.set(race_ptr->resistance_flags & RFR_EFF_IM_ACID_MASK);
+ monrace.r_resistance_flags.set(monrace.resistance_flags & RFR_EFF_IM_ACID_MASK);
}
} else {
if (mult < 17) {
if (flags.has(TR_BRAND_ELEC)) {
/* Notice immunity */
- if (race_ptr->resistance_flags.has_any_of(RFR_EFF_IM_ELEC_MASK)) {
+ if (monrace.resistance_flags.has_any_of(RFR_EFF_IM_ELEC_MASK)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_resistance_flags.set(race_ptr->resistance_flags & RFR_EFF_IM_ELEC_MASK);
+ monrace.r_resistance_flags.set(monrace.resistance_flags & RFR_EFF_IM_ELEC_MASK);
}
} else {
if (mult < 17) {
if (flags.has(TR_BRAND_FIRE)) {
/* Notice immunity */
- if (race_ptr->resistance_flags.has_any_of(RFR_EFF_IM_FIRE_MASK)) {
+ if (monrace.resistance_flags.has_any_of(RFR_EFF_IM_FIRE_MASK)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_resistance_flags.set(race_ptr->resistance_flags & RFR_EFF_IM_FIRE_MASK);
+ monrace.r_resistance_flags.set(monrace.resistance_flags & RFR_EFF_IM_FIRE_MASK);
}
}
/* Otherwise, take the damage */
else {
- if (race_ptr->resistance_flags.has(MonsterResistanceType::HURT_FIRE)) {
+ if (monrace.resistance_flags.has(MonsterResistanceType::HURT_FIRE)) {
if (mult < 25) {
mult = 25;
}
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_resistance_flags.set(MonsterResistanceType::HURT_FIRE);
+ monrace.r_resistance_flags.set(MonsterResistanceType::HURT_FIRE);
}
} else if (mult < 17) {
mult = 17;
if (flags.has(TR_BRAND_COLD)) {
/* Notice immunity */
- if (race_ptr->resistance_flags.has_any_of(RFR_EFF_IM_COLD_MASK)) {
+ if (monrace.resistance_flags.has_any_of(RFR_EFF_IM_COLD_MASK)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_resistance_flags.set(race_ptr->resistance_flags & RFR_EFF_IM_COLD_MASK);
+ monrace.r_resistance_flags.set(monrace.resistance_flags & RFR_EFF_IM_COLD_MASK);
}
}
/* Otherwise, take the damage */
else {
- if (race_ptr->resistance_flags.has(MonsterResistanceType::HURT_COLD)) {
+ if (monrace.resistance_flags.has(MonsterResistanceType::HURT_COLD)) {
if (mult < 25) {
mult = 25;
}
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_resistance_flags.set(MonsterResistanceType::HURT_COLD);
+ monrace.r_resistance_flags.set(MonsterResistanceType::HURT_COLD);
}
} else if (mult < 17) {
mult = 17;
if (flags.has(TR_BRAND_POIS)) {
/* Notice immunity */
- if (race_ptr->resistance_flags.has_any_of(RFR_EFF_IM_POISON_MASK)) {
+ if (monrace.resistance_flags.has_any_of(RFR_EFF_IM_POISON_MASK)) {
if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
- race_ptr->r_resistance_flags.set(race_ptr->resistance_flags & RFR_EFF_IM_POISON_MASK);
+ monrace.r_resistance_flags.set(monrace.resistance_flags & RFR_EFF_IM_POISON_MASK);
}
}
/* Otherwise, take the damage */
if ((flags.has(TR_FORCE_WEAPON)) && (player_ptr->csp > (player_ptr->msp / 30))) {
player_ptr->csp -= (1 + (player_ptr->msp / 30));
- set_bits(player_ptr->redraw, PR_MANA);
+ RedrawingFlagsUpdater::get_instance().set_flag(MainWindowRedrawingFlag::MP);
mult = mult * 5 / 2;
}
break;
*/
void exe_fire(PlayerType *player_ptr, INVENTORY_IDX item, ItemEntity *j_ptr, SPELL_IDX snipe_type)
{
- DIRECTION dir;
- int i;
POSITION y, x, ny, nx, ty, tx, prev_y, prev_x;
- int tdam_base, tdis, thits, tmul;
- int bonus, chance;
- int cur_dis, visible;
- PERCENTAGE j;
-
ItemEntity forge;
ItemEntity *q_ptr;
ItemEntity *o_ptr;
AttributeFlags attribute_flags{};
attribute_flags.set(AttributeType::PLAYER_SHOOT);
- bool hit_body = false;
-
- GAME_TEXT o_name[MAX_NLEN];
-
- /* STICK TO */
- bool stick_to = false;
+ auto hit_body = false;
+ auto stick_to = false;
/* Access the item (if in the pack) */
+ auto *floor_ptr = player_ptr->current_floor_ptr;
if (item >= 0) {
o_ptr = &player_ptr->inventory_list[item];
} else {
- o_ptr = &player_ptr->current_floor_ptr->o_list[0 - item];
+ o_ptr = &floor_ptr->o_list[0 - item];
}
/* Sniper - Cannot shot a single arrow twice */
snipe_type = SP_NONE;
}
- describe_flavor(player_ptr, o_name, o_ptr, OD_OMIT_PREFIX);
+ const auto item_name = describe_flavor(player_ptr, o_ptr, OD_OMIT_PREFIX);
/* Use the proper number of shots */
- thits = player_ptr->num_fire;
+ auto thits = player_ptr->num_fire;
/* Use a base distance */
- tdis = 10;
+ auto tdis = 10;
/* Base damage from thrown object plus launcher bonus */
- tdam_base = damroll(o_ptr->dd, o_ptr->ds) + o_ptr->to_d + j_ptr->to_d;
+ auto tdam_base = damroll(o_ptr->dd, o_ptr->ds) + o_ptr->to_d + j_ptr->to_d;
/* Actually "fire" the object */
- bonus = (player_ptr->to_h_b + o_ptr->to_h + j_ptr->to_h);
- if ((j_ptr->sval == SV_LIGHT_XBOW) || (j_ptr->sval == SV_HEAVY_XBOW)) {
- chance = (player_ptr->skill_thb + (player_ptr->weapon_exp[j_ptr->tval][j_ptr->sval] / 400 + bonus) * BTH_PLUS_ADJ);
+ const auto tval = j_ptr->bi_key.tval();
+ const auto median_skill_exp = PlayerSkill::weapon_exp_at(PlayerSkillRank::MASTER) / 2;
+ const auto bonus = (player_ptr->to_h_b + o_ptr->to_h + j_ptr->to_h);
+ const auto &weapon_exps = player_ptr->weapon_exp[tval];
+ constexpr auto bow_magnification = 200;
+ constexpr auto xbow_magnification = 400;
+ int chance;
+ if (tval == ItemKindType::NONE) {
+ chance = (player_ptr->skill_thb + ((weapon_exps[0] - median_skill_exp) / bow_magnification + bonus) * BTH_PLUS_ADJ);
} else {
- chance = (player_ptr->skill_thb + ((player_ptr->weapon_exp[j_ptr->tval][j_ptr->sval] - (PlayerSkill::weapon_exp_at(PlayerSkillRank::MASTER) / 2)) / 200 + bonus) * BTH_PLUS_ADJ);
+ const auto sval = j_ptr->bi_key.sval().value();
+ if (j_ptr->is_cross_bow()) {
+ chance = (player_ptr->skill_thb + (weapon_exps[sval] / xbow_magnification + bonus) * BTH_PLUS_ADJ);
+ } else {
+ chance = (player_ptr->skill_thb + ((weapon_exps[sval] - median_skill_exp) / bow_magnification + bonus) * BTH_PLUS_ADJ);
+ }
}
- PlayerEnergy(player_ptr).set_player_turn_energy(bow_energy(j_ptr->sval));
- tmul = bow_tmul(j_ptr->sval);
+ PlayerEnergy(player_ptr).set_player_turn_energy(j_ptr->get_bow_energy());
+ auto tmul = j_ptr->get_arrow_magnification();
/* Get extra "power" from "extra might" */
if (player_ptr->xtra_might) {
tdam_base *= tmul;
tdam_base /= 100;
- auto sniper_data = PlayerClass(player_ptr).get_specific_data<sniper_data_type>();
+ auto sniper_data = PlayerClass(player_ptr).get_specific_data<SniperData>();
auto sniper_concent = sniper_data ? sniper_data->concent : 0;
/* Base range */
tdis = 13 + tmul / 80;
- if ((j_ptr->sval == SV_LIGHT_XBOW) || (j_ptr->sval == SV_HEAVY_XBOW)) {
+ if (j_ptr->is_cross_bow()) {
tdis -= (5 - (sniper_concent + 1) / 2);
}
project_length = tdis + 1;
/* Get a direction (or cancel) */
+ DIRECTION dir;
if (!get_aim_dir(player_ptr, &dir)) {
PlayerEnergy(player_ptr).reset_player_turn();
}
/* Take a (partial) turn */
- PlayerEnergy(player_ptr).div_player_turn_energy((ENERGY)thits);
+ PlayerEnergy(player_ptr).div_player_turn_energy(thits);
player_ptr->is_fired = true;
/* Sniper - Difficult to shot twice at 1 turn */
}
/* Sniper - Repeat shooting when double shots */
- for (i = 0; i < ((snipe_type == SP_DOUBLE) ? 2 : 1); i++) {
+ for (auto i = 0; i < ((snipe_type == SP_DOUBLE) ? 2 : 1); i++) {
/* Start at the player */
y = player_ptr->y;
x = player_ptr->x;
hit_body = false;
/* Travel until stopped */
- for (cur_dis = 0; cur_dis <= tdis;) {
+ for (auto cur_dis = 0; cur_dis <= tdis;) {
grid_type *g_ptr;
/* Hack -- Stop at the target */
/* Shatter Arrow */
if (snipe_type == SP_KILL_WALL) {
- g_ptr = &player_ptr->current_floor_ptr->grid_array[ny][nx];
+ g_ptr = &floor_ptr->grid_array[ny][nx];
if (g_ptr->cave_has_flag(TerrainCharacteristics::HURT_ROCK) && !g_ptr->m_idx) {
if (any_bits(g_ptr->info, (CAVE_MARK))) {
}
/* Forget the wall */
reset_bits(g_ptr->info, (CAVE_MARK));
- set_bits(player_ptr->update, PU_VIEW | PU_LITE | PU_FLOW | PU_MON_LITE);
+ static constexpr auto flags = {
+ StatusRecalculatingFlag::VIEW,
+ StatusRecalculatingFlag::LITE,
+ StatusRecalculatingFlag::FLOW,
+ StatusRecalculatingFlag::MONSTER_LITE,
+ };
+ RedrawingFlagsUpdater::get_instance().set_flags(flags);
/* Destroy the wall */
cave_alter_feat(player_ptr, ny, nx, TerrainCharacteristics::HURT_ROCK);
}
/* Stopped by walls/doors */
- if (!cave_has_flag_bold(player_ptr->current_floor_ptr, ny, nx, TerrainCharacteristics::PROJECT) && !player_ptr->current_floor_ptr->grid_array[ny][nx].m_idx) {
+ if (!cave_has_flag_bold(floor_ptr, ny, nx, TerrainCharacteristics::PROJECT) && !floor_ptr->grid_array[ny][nx].m_idx) {
break;
}
/* Sniper */
if (snipe_type == SP_LITE) {
- set_bits(player_ptr->current_floor_ptr->grid_array[ny][nx].info, CAVE_GLOW);
+ set_bits(floor_ptr->grid_array[ny][nx].info, CAVE_GLOW);
note_spot(player_ptr, ny, nx);
lite_spot(player_ptr, ny, nx);
}
/* Sniper */
if (snipe_type == SP_KILL_TRAP) {
- project(player_ptr, 0, 0, ny, nx, 0, AttributeType::KILL_TRAP, (PROJECT_JUMP | PROJECT_HIDE | PROJECT_GRID | PROJECT_ITEM));
+ constexpr auto flags = PROJECT_JUMP | PROJECT_HIDE | PROJECT_GRID | PROJECT_ITEM;
+ project(player_ptr, 0, 0, ny, nx, 0, AttributeType::KILL_TRAP, flags);
}
/* Sniper */
if (snipe_type == SP_EVILNESS) {
- reset_bits(player_ptr->current_floor_ptr->grid_array[ny][nx].info, (CAVE_GLOW | CAVE_MARK));
+ reset_bits(floor_ptr->grid_array[ny][nx].info, (CAVE_GLOW | CAVE_MARK));
note_spot(player_ptr, ny, nx);
lite_spot(player_ptr, ny, nx);
}
y = ny;
/* Monster here, Try to hit it */
- if (player_ptr->current_floor_ptr->grid_array[y][x].m_idx) {
+ if (floor_ptr->grid_array[y][x].m_idx) {
sound(SOUND_SHOOT_HIT);
- grid_type *c_mon_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
+ grid_type *c_mon_ptr = &floor_ptr->grid_array[y][x];
- auto *m_ptr = &player_ptr->current_floor_ptr->m_list[c_mon_ptr->m_idx];
- auto *r_ptr = &monraces_info[m_ptr->r_idx];
+ auto *m_ptr = &floor_ptr->m_list[c_mon_ptr->m_idx];
+ auto *r_ptr = &m_ptr->get_monrace();
/* Check the visibility */
- visible = m_ptr->ml;
+ auto visible = m_ptr->ml;
/* Note the collision */
hit_body = true;
if (m_ptr->is_asleep()) {
if (r_ptr->kind_flags.has_not(MonsterKindType::EVIL) || one_in_(5)) {
- chg_virtue(player_ptr, V_COMPASSION, -1);
+ chg_virtue(player_ptr, Virtue::COMPASSION, -1);
}
if (r_ptr->kind_flags.has_not(MonsterKindType::EVIL) || one_in_(5)) {
- chg_virtue(player_ptr, V_HONOUR, -1);
+ chg_virtue(player_ptr, Virtue::HONOUR, -1);
}
}
}
/* Did we hit it (penalize range) */
- if (test_hit_fire(player_ptr, chance - cur_dis, m_ptr, m_ptr->ml, o_name)) {
+ if (test_hit_fire(player_ptr, chance - cur_dis, m_ptr, m_ptr->ml, item_name.data())) {
bool fear = false;
auto tdam = tdam_base; //!< @note 実際に与えるダメージ
auto base_dam = tdam; //!< @note 補正前の与えるダメージ(無傷、全ての耐性など)
/* Handle unseen monster */
if (!visible) {
/* Invisible monster */
- msg_format(_("%sが敵を捕捉した。", "The %s finds a mark."), o_name);
+ msg_format(_("%sが敵を捕捉した。", "The %s finds a mark."), item_name.data());
}
/* Handle visible monster */
else {
- GAME_TEXT m_name[MAX_NLEN];
-
/* Get "the monster" or "it" */
- monster_desc(player_ptr, m_name, m_ptr, 0);
+ const auto m_name = monster_desc(player_ptr, m_ptr, 0);
- msg_format(_("%sが%sに命中した。", "The %s hits %s."), o_name, m_name);
+ msg_format(_("%sが%sに命中した。", "The %s hits %s."), item_name.data(), m_name.data());
if (m_ptr->ml) {
if (!player_ptr->effects()->hallucination()->is_hallucinated()) {
}
if (snipe_type == SP_NEEDLE) {
- if ((randint1(randint1(r_ptr->level / (3 + sniper_concent)) + (8 - sniper_concent)) == 1) && r_ptr->kind_flags.has_not(MonsterKindType::UNIQUE) && none_bits(r_ptr->flags7, RF7_UNIQUE2)) {
- GAME_TEXT m_name[MAX_NLEN];
-
+ const auto is_unique = r_ptr->kind_flags.has(MonsterKindType::UNIQUE);
+ const auto fatality = randint1(r_ptr->level / (3 + sniper_concent)) + (8 - sniper_concent);
+ if ((randint1(fatality) == 1) && !is_unique && none_bits(r_ptr->flags7, RF7_UNIQUE2)) {
/* Get "the monster" or "it" */
- monster_desc(player_ptr, m_name, m_ptr, 0);
+ const auto m_name = monster_desc(player_ptr, m_ptr, 0);
tdam = m_ptr->hp + 1;
base_dam = tdam;
- msg_format(_("%sの急所に突き刺さった!", "Your shot hit a fatal spot of %s!"), m_name);
+ msg_format(_("%sの急所に突き刺さった!", "Your shot hit a fatal spot of %s!"), m_name.data());
} else {
tdam = 1;
base_dam = tdam;
/* Sniper */
if (snipe_type == SP_HOLYNESS) {
- set_bits(player_ptr->current_floor_ptr->grid_array[ny][nx].info, CAVE_GLOW);
+ set_bits(floor_ptr->grid_array[ny][nx].info, CAVE_GLOW);
note_spot(player_ptr, ny, nx);
lite_spot(player_ptr, ny, nx);
}
/* Hit the monster, check for death */
MonsterDamageProcessor mdp(player_ptr, c_mon_ptr->m_idx, tdam, &fear, attribute_flags);
- if (mdp.mon_take_hit(extract_note_dies(m_ptr->get_real_r_idx()))) {
+ if (mdp.mon_take_hit(m_ptr->get_died_message())) {
/* Dead monster */
}
else {
/* STICK TO */
if (q_ptr->is_fixed_artifact() && (sniper_concent == 0)) {
- GAME_TEXT m_name[MAX_NLEN];
-
- monster_desc(player_ptr, m_name, m_ptr, 0);
+ const auto m_name = monster_desc(player_ptr, m_ptr, 0);
stick_to = true;
- msg_format(_("%sは%sに突き刺さった!", "%^s is stuck in %s!"), o_name, m_name);
+ msg_format(_("%sは%sに突き刺さった!", "%s^ is stuck in %s!"), item_name.data(), m_name.data());
}
- message_pain(player_ptr, c_mon_ptr->m_idx, tdam);
+ if (const auto pain_message = MonsterPainDescriber(player_ptr, c_mon_ptr->m_idx).describe(tdam);
+ !pain_message.empty()) {
+ msg_print(pain_message);
+ }
/* Anger the monster */
if (tdam > 0) {
}
if (fear && m_ptr->ml) {
- GAME_TEXT m_name[MAX_NLEN];
+ const auto m_name = monster_desc(player_ptr, m_ptr, 0);
sound(SOUND_FLEE);
- monster_desc(player_ptr, m_name, m_ptr, 0);
- msg_format(_("%^sは恐怖して逃げ出した!", "%^s flees in terror!"), m_name);
+ msg_format(_("%s^は恐怖して逃げ出した!", "%s^ flees in terror!"), m_name.data());
}
set_target(m_ptr, player_ptr->y, player_ptr->x);
mmove2(&ny, &nx, player_ptr->y, player_ptr->x, ty, tx);
/* Stopped by wilderness boundary */
- if (!in_bounds2(player_ptr->current_floor_ptr, ny, nx)) {
+ if (!in_bounds2(floor_ptr, ny, nx)) {
break;
}
/* Stopped by walls/doors */
- if (!player_can_enter(player_ptr, player_ptr->current_floor_ptr->grid_array[ny][nx].feat, 0)) {
+ if (!player_can_enter(player_ptr, floor_ptr->grid_array[ny][nx].feat, 0)) {
break;
}
break;
}
- player_ptr->current_floor_ptr->grid_array[ny][nx].m_idx = m_idx;
- player_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = 0;
+ floor_ptr->grid_array[ny][nx].m_idx = m_idx;
+ floor_ptr->grid_array[oy][ox].m_idx = 0;
m_ptr->fx = nx;
m_ptr->fy = ny;
}
/* Chance of breakage (during attacks) */
- j = (hit_body ? breakage_chance(player_ptr, q_ptr, PlayerClass(player_ptr).equals(PlayerClassType::ARCHER), snipe_type) : 0);
+ auto j = (hit_body ? breakage_chance(player_ptr, q_ptr, PlayerClass(player_ptr).equals(PlayerClassType::ARCHER), snipe_type) : 0);
if (stick_to) {
- MONSTER_IDX m_idx = player_ptr->current_floor_ptr->grid_array[y][x].m_idx;
- auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
- OBJECT_IDX o_idx = o_pop(player_ptr->current_floor_ptr);
+ MONSTER_IDX m_idx = floor_ptr->grid_array[y][x].m_idx;
+ auto *m_ptr = &floor_ptr->m_list[m_idx];
+ OBJECT_IDX o_idx = o_pop(floor_ptr);
if (!o_idx) {
- msg_format(_("%sはどこかへ行った。", "The %s went somewhere."), o_name);
+ msg_format(_("%sはどこかへ行った。", "The %s went somewhere."), item_name.data());
if (q_ptr->is_fixed_artifact()) {
- artifacts_info.at(j_ptr->fixed_artifact_idx).is_generated = false;
+ ArtifactsInfo::get_instance().get_artifact(j_ptr->fixed_artifact_idx).is_generated = false;
}
return;
}
- o_ptr = &player_ptr->current_floor_ptr->o_list[o_idx];
+ o_ptr = &floor_ptr->o_list[o_idx];
o_ptr->copy_from(q_ptr);
/* Forget mark */
- reset_bits(o_ptr->marked, OM_TOUCHED);
+ o_ptr->marked.reset(OmType::TOUCHED);
/* Forget location */
o_ptr->iy = o_ptr->ix = 0;
o_ptr->held_m_idx = m_idx;
/* Carry object */
- m_ptr->hold_o_idx_list.add(player_ptr->current_floor_ptr, o_idx);
- } else if (cave_has_flag_bold(player_ptr->current_floor_ptr, y, x, TerrainCharacteristics::PROJECT)) {
+ m_ptr->hold_o_idx_list.add(floor_ptr, o_idx);
+ } else if (cave_has_flag_bold(floor_ptr, y, x, TerrainCharacteristics::PROJECT)) {
/* Drop (or break) near that location */
(void)drop_near(player_ptr, q_ptr, j, y, x);
} else {
}
/*!
- * @brief プレイヤーからモンスターへの射撃命中判定 /
- * Determine if the player "hits" a monster (normal combat).
+ * @brief プレイヤーからモンスターへの射撃命中判定
* @param chance 基本命中値
* @param monster_ptr モンスターの構造体参照ポインタ
* @param vis 目標を視界に捕らえているならばTRUEを指定
- * @param o_name ã\83¡ã\83\83ã\82»ã\83¼ã\82¸è¡¨ç¤ºæ\99\82ã\81®ã\83¢ã\83³ã\82¹ã\82¿ã\83¼å\90\8d
+ * @param item_name ç\9f³å·\9däº\94å\8f³è¡\9bé\96\80å°\82ç\94¨ã\83¡ã\83\83ã\82»ã\83¼ã\82¸ï¼\9aç\84¡å\8a¹å\8c\96ã\81\97ã\81\9fç\9f¢å¼¾ã\81®å\90\8då\89\8d
* @return 命中と判定された場合TRUEを返す
- * @note Always miss 5%, always hit 5%, otherwise random.
+ * @note 最低命中率5%、最大命中率95%
*/
-bool test_hit_fire(PlayerType *player_ptr, int chance, MonsterEntity *m_ptr, int vis, char *o_name)
+bool test_hit_fire(PlayerType *player_ptr, int chance, MonsterEntity *m_ptr, int vis, std::string_view item_name)
{
int k;
ARMOUR_CLASS ac;
- auto *r_ptr = &monraces_info[m_ptr->r_idx];
+ auto *r_ptr = &m_ptr->get_monrace();
/* Percentile dice */
k = randint1(100);
- auto sniper_data = PlayerClass(player_ptr).get_specific_data<sniper_data_type>();
+ auto sniper_data = PlayerClass(player_ptr).get_specific_data<SniperData>();
auto sniper_concent = sniper_data ? sniper_data->concent : 0;
/* Snipers with high-concentration reduce instant miss percentage.*/
/* Power competes against armor */
if (randint0(chance) < (ac * 3 / 4)) {
if (m_ptr->r_idx == MonsterRaceId::GOEMON && !m_ptr->is_asleep()) {
- GAME_TEXT m_name[MAX_NLEN];
- monster_desc(player_ptr, m_name, m_ptr, 0);
- msg_format(_("%sは%sを斬り捨てた!", "%s cuts down %s!"), m_name, o_name);
+ const auto m_name = monster_desc(player_ptr, m_ptr, 0);
+ msg_format(_("%sは%sを斬り捨てた!", "%s cuts down %s!"), m_name.data(), item_name.data());
}
return false;
}
}
/*!
- * @brief プレイヤーからモンスターへの射撃クリティカル判定 /
- * Critical hits (from objects thrown by player) Factor in item weight, total plusses, and player level.
+ * @brief プレイヤーからモンスターへの射撃クリティカル判定
* @param weight 矢弾の重量
* @param plus_ammo 矢弾の命中修正
* @param plus_bow 弓の命中修正
*/
int critical_shot(PlayerType *player_ptr, WEIGHT weight, int plus_ammo, int plus_bow, int dam)
{
- int i, k;
- auto *j_ptr = &player_ptr->inventory_list[INVEN_BOW];
-
- /* Extract "shot" power */
- i = player_ptr->to_h_b + plus_ammo;
-
- if (player_ptr->tval_ammo == ItemKindType::BOLT) {
- i = (player_ptr->skill_thb + (player_ptr->weapon_exp[j_ptr->tval][j_ptr->sval] / 400 + i) * BTH_PLUS_ADJ);
+ const auto &item = player_ptr->inventory_list[INVEN_BOW];
+ const auto bonus = player_ptr->to_h_b + plus_ammo;
+ const auto tval = item.bi_key.tval();
+ const auto median_skill_exp = PlayerSkill::weapon_exp_at(PlayerSkillRank::MASTER) / 2;
+ const auto &weapon_exps = player_ptr->weapon_exp[tval];
+ constexpr auto bow_magnification = 200;
+ constexpr auto xbow_magnification = 400;
+ int power;
+ if (tval == ItemKindType::NONE) {
+ power = player_ptr->skill_thb + ((weapon_exps[0] - median_skill_exp) / bow_magnification + bonus) * BTH_PLUS_ADJ;
} else {
- i = (player_ptr->skill_thb + ((player_ptr->weapon_exp[j_ptr->tval][j_ptr->sval] - (PlayerSkill::weapon_exp_at(PlayerSkillRank::MASTER) / 2)) / 200 + i) * BTH_PLUS_ADJ);
+ const auto sval = item.bi_key.sval().value();
+ const auto weapon_exp = weapon_exps[sval];
+ if (player_ptr->tval_ammo == ItemKindType::BOLT) {
+ power = (player_ptr->skill_thb + (weapon_exp / xbow_magnification + bonus) * BTH_PLUS_ADJ);
+ } else {
+ power = player_ptr->skill_thb + ((weapon_exp - median_skill_exp) / bow_magnification + bonus) * BTH_PLUS_ADJ;
+ }
}
PlayerClass pc(player_ptr);
- auto sniper_data = pc.get_specific_data<sniper_data_type>();
- auto sniper_concent = sniper_data ? sniper_data->concent : 0;
+ const auto sniper_data = pc.get_specific_data<SniperData>();
+ const auto sniper_concent = sniper_data ? sniper_data->concent : 0;
/* Snipers can shot more critically with crossbows */
- i += ((i * sniper_concent) / 5);
+ power += ((power * sniper_concent) / 5);
if (pc.equals(PlayerClassType::SNIPER) && (player_ptr->tval_ammo == ItemKindType::BOLT)) {
- i *= 2;
+ power *= 2;
}
/* Good bow makes more critical */
- i += plus_bow * 8 * (sniper_concent + 5);
-
- /* Critical hit */
- if (randint1(10000) <= i) {
- k = weight * randint1(500);
-
- if (k < 900) {
- msg_print(_("手ごたえがあった!", "It was a good hit!"));
- dam += (dam / 2);
- } else if (k < 1350) {
- msg_print(_("かなりの手ごたえがあった!", "It was a great hit!"));
- dam *= 2;
- } else {
- msg_print(_("会心の一撃だ!", "It was a superb hit!"));
- dam *= 3;
- }
- }
-
- return dam;
-}
-
-/*!
- * @brief 射撃武器の攻撃に必要な基本消費エネルギーを返す/Return bow energy
- * @param sval 射撃武器のアイテム副分類ID
- * @return 消費する基本エネルギー
- */
-ENERGY bow_energy(OBJECT_SUBTYPE_VALUE sval)
-{
- ENERGY energy = 10000;
-
- /* Analyze the launcher */
- switch (sval) {
- /* Sling and ammo */
- case SV_SLING: {
- energy = 8000;
- break;
- }
-
- /* Short Bow and Arrow */
- case SV_SHORT_BOW: {
- energy = 10000;
- break;
- }
-
- /* Long Bow and Arrow */
- case SV_LONG_BOW: {
- energy = 10000;
- break;
- }
-
- /* Bow of irresponsiblity and Arrow */
- case SV_NAMAKE_BOW: {
- energy = 7777;
- break;
- }
-
- /* Light Crossbow and Bolt */
- case SV_LIGHT_XBOW: {
- energy = 12000;
- break;
- }
-
- /* Heavy Crossbow and Bolt */
- case SV_HEAVY_XBOW: {
- energy = 13333;
- break;
- }
- }
-
- return energy;
-}
-
-/*
- * Return bow tmul
- */
-int bow_tmul(OBJECT_SUBTYPE_VALUE sval)
-{
- int tmul = 0;
-
- /* Analyze the launcher */
- switch (sval) {
- /* Sling and ammo */
- case SV_SLING: {
- tmul = 2;
- break;
- }
-
- /* Short Bow and Arrow */
- case SV_SHORT_BOW: {
- tmul = 2;
- break;
- }
-
- /* Long Bow and Arrow */
- case SV_LONG_BOW: {
- tmul = 3;
- break;
- }
-
- /* Bow of irresponsiblity and Arrow */
- case SV_NAMAKE_BOW: {
- tmul = 3;
- break;
- }
-
- /* Light Crossbow and Bolt */
- case SV_LIGHT_XBOW: {
- tmul = 3;
- break;
+ power += plus_bow * 8 * (sniper_concent + 5);
+ if (randint1(10000) > power) {
+ return dam;
}
- /* Heavy Crossbow and Bolt */
- case SV_HEAVY_XBOW: {
- tmul = 4;
- break;
- }
+ const auto k = weight * randint1(500);
+ if (k < 900) {
+ msg_print(_("手ごたえがあった!", "It was a good hit!"));
+ dam += (dam / 2);
+ } else if (k < 1350) {
+ msg_print(_("かなりの手ごたえがあった!", "It was a great hit!"));
+ dam *= 2;
+ } else {
+ msg_print(_("会心の一撃だ!", "It was a superb hit!"));
+ dam *= 3;
}
- return tmul;
+ return dam;
}
/*!
*/
int calc_crit_ratio_shot(PlayerType *player_ptr, int plus_ammo, int plus_bow)
{
- int i;
auto *j_ptr = &player_ptr->inventory_list[INVEN_BOW];
/* Extract "shot" power */
- i = player_ptr->to_h_b + plus_ammo;
-
+ auto i = player_ptr->to_h_b + plus_ammo;
+ const auto tval = j_ptr->bi_key.tval();
+ const auto sval = j_ptr->bi_key.sval().value();
if (player_ptr->tval_ammo == ItemKindType::BOLT) {
- i = (player_ptr->skill_thb + (player_ptr->weapon_exp[j_ptr->tval][j_ptr->sval] / 400 + i) * BTH_PLUS_ADJ);
+ i = (player_ptr->skill_thb + (player_ptr->weapon_exp[tval][sval] / 400 + i) * BTH_PLUS_ADJ);
} else {
- i = (player_ptr->skill_thb + ((player_ptr->weapon_exp[j_ptr->tval][j_ptr->sval] - (PlayerSkill::weapon_exp_at(PlayerSkillRank::MASTER) / 2)) / 200 + i) * BTH_PLUS_ADJ);
+ i = (player_ptr->skill_thb + ((player_ptr->weapon_exp[tval][sval] - (PlayerSkill::weapon_exp_at(PlayerSkillRank::MASTER) / 2)) / 200 + i) * BTH_PLUS_ADJ);
}
PlayerClass pc(player_ptr);
- auto sniper_data = pc.get_specific_data<sniper_data_type>();
+ auto sniper_data = pc.get_specific_data<SniperData>();
auto sniper_concent = sniper_data ? sniper_data->concent : 0;
/* Snipers can shot more critically with crossbows */