2 * @brief プレイヤーのHP/MP、アイテム、お金・明かりの残りターン、充填魔力を盗んだり減少させたりする処理
7 #include "monster-attack/monster-eating.h"
8 #include "avatar/avatar.h"
9 #include "core/player-redraw-types.h"
10 #include "core/player-update-types.h"
11 #include "core/window-redrawer.h"
12 #include "flavor/flavor-describer.h"
13 #include "flavor/object-flavor-types.h"
14 #include "inventory/inventory-object.h"
15 #include "inventory/inventory-slot-types.h"
16 #include "mind/mind-mirror-master.h"
17 #include "monster-attack/monster-attack-player.h"
18 #include "monster/monster-status.h"
19 #include "object/object-info.h"
20 #include "object/object-mark-types.h"
21 #include "player-base/player-race.h"
22 #include "player-info/race-info.h"
23 #include "player/digestion-processor.h"
24 #include "player/player-status-flags.h"
25 #include "player/player-status-table.h"
26 #include "status/experience.h"
27 #include "system/baseitem-info-definition.h"
28 #include "system/floor-type-definition.h"
29 #include "system/monster-type-definition.h"
30 #include "system/object-type-definition.h"
31 #include "system/player-type-definition.h"
32 #include "timed-effect/player-blindness.h"
33 #include "timed-effect/player-paralysis.h"
34 #include "timed-effect/timed-effects.h"
35 #include "util/bit-flags-calculator.h"
36 #include "view/display-messages.h"
37 #include "world/world-object.h"
39 void process_eat_gold(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
41 auto is_paralyzed = player_ptr->effects()->paralysis()->is_paralyzed();
42 if (!is_paralyzed && (randint0(100) < (adj_dex_safe[player_ptr->stat_index[A_DEX]] + player_ptr->lev))) {
43 msg_print(_("しかし素早く財布を守った!", "You quickly protect your money pouch!"));
45 monap_ptr->blinked = true;
51 PRICE gold = (player_ptr->au / 10) + randint1(25);
57 gold = (player_ptr->au / 20) + randint1(3000);
60 if (gold > player_ptr->au) {
61 gold = player_ptr->au;
64 player_ptr->au -= gold;
66 msg_print(_("しかし何も盗まれなかった。", "Nothing was stolen."));
67 } else if (player_ptr->au > 0) {
68 msg_print(_("財布が軽くなった気がする。", "Your purse feels lighter."));
69 msg_format(_("$%ld のお金が盗まれた!", "%ld coins were stolen!"), (long)gold);
70 chg_virtue(player_ptr, V_SACRIFICE, 1);
72 msg_print(_("財布が軽くなった気がする。", "Your purse feels lighter."));
73 msg_print(_("お金が全部盗まれた!", "All of your coins were stolen!"));
74 chg_virtue(player_ptr, V_SACRIFICE, 2);
77 player_ptr->redraw |= (PR_GOLD);
78 player_ptr->window_flags |= (PW_PLAYER);
79 monap_ptr->blinked = true;
83 * @brief 盗み打撃の時にアイテムが盗まれるかどうかを判定する
84 * @param player_ptr プレイヤーへの参照ポインタ
85 * @monap_ptr モンスターからモンスターへの直接攻撃構造体への参照ポインタ
86 * @return 盗まれたらTRUE、何も盗まれなかったらFALSE
88 bool check_eat_item(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
90 if (monap_ptr->m_ptr->is_confused()) {
94 if (player_ptr->is_dead || check_multishadow(player_ptr)) {
98 auto is_paralyzed = player_ptr->effects()->paralysis()->is_paralyzed();
99 if (!is_paralyzed && (randint0(100) < (adj_dex_safe[player_ptr->stat_index[A_DEX]] + player_ptr->lev))) {
100 msg_print(_("しかしあわててザックを取り返した!", "You grab hold of your backpack!"));
101 monap_ptr->blinked = true;
102 monap_ptr->obvious = true;
110 * @brief プレイヤーが持っているアイテムをモンスターに移す
111 * @param player_ptr プレイヤーへの参照ポインタ
112 * @monap_ptr モンスターからモンスターへの直接攻撃構造体への参照ポインタ
114 static void move_item_to_monster(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr, const OBJECT_IDX o_idx)
121 j_ptr = &player_ptr->current_floor_ptr->o_list[o_idx];
122 j_ptr->copy_from(monap_ptr->o_ptr);
124 if ((monap_ptr->o_ptr->tval == ItemKindType::ROD) || (monap_ptr->o_ptr->tval == ItemKindType::WAND)) {
125 j_ptr->pval = monap_ptr->o_ptr->pval / monap_ptr->o_ptr->number;
126 monap_ptr->o_ptr->pval -= j_ptr->pval;
129 j_ptr->marked = OM_TOUCHED;
130 j_ptr->held_m_idx = monap_ptr->m_idx;
131 monap_ptr->m_ptr->hold_o_idx_list.add(player_ptr->current_floor_ptr, o_idx);
136 * @param player_ptr プレイヤーへの参照ポインタ
137 * @monap_ptr モンスターからモンスターへの直接攻撃構造体への参照ポインタ
138 * @details eatとあるがお金や食べ物と違ってなくならない、盗んだモンスターを倒せば取り戻せる
140 void process_eat_item(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
142 for (int i = 0; i < 10; i++) {
144 INVENTORY_IDX i_idx = (INVENTORY_IDX)randint0(INVEN_PACK);
145 monap_ptr->o_ptr = &player_ptr->inventory_list[i_idx];
146 if (!monap_ptr->o_ptr->k_idx) {
150 if (monap_ptr->o_ptr->is_artifact()) {
154 describe_flavor(player_ptr, monap_ptr->o_name, monap_ptr->o_ptr, OD_OMIT_PREFIX);
156 msg_format("%s(%c)を%s盗まれた!", monap_ptr->o_name, index_to_label(i_idx), ((monap_ptr->o_ptr->number > 1) ? "一つ" : ""));
158 msg_format("%sour %s (%c) was stolen!", ((monap_ptr->o_ptr->number > 1) ? "One of y" : "Y"), monap_ptr->o_name, index_to_label(i_idx));
160 chg_virtue(player_ptr, V_SACRIFICE, 1);
161 o_idx = o_pop(player_ptr->current_floor_ptr);
162 move_item_to_monster(player_ptr, monap_ptr, o_idx);
163 inven_item_increase(player_ptr, i_idx, -1);
164 inven_item_optimize(player_ptr, i_idx);
165 monap_ptr->obvious = true;
166 monap_ptr->blinked = true;
171 void process_eat_food(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
173 for (int i = 0; i < 10; i++) {
174 INVENTORY_IDX i_idx = (INVENTORY_IDX)randint0(INVEN_PACK);
175 monap_ptr->o_ptr = &player_ptr->inventory_list[i_idx];
176 if (!monap_ptr->o_ptr->k_idx) {
180 if ((monap_ptr->o_ptr->tval != ItemKindType::FOOD) && !((monap_ptr->o_ptr->tval == ItemKindType::CORPSE) && (monap_ptr->o_ptr->sval))) {
184 describe_flavor(player_ptr, monap_ptr->o_name, monap_ptr->o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
186 msg_format("%s(%c)を%s食べられてしまった!", monap_ptr->o_name, index_to_label(i_idx), ((monap_ptr->o_ptr->number > 1) ? "一つ" : ""));
188 msg_format("%sour %s (%c) was eaten!", ((monap_ptr->o_ptr->number > 1) ? "One of y" : "Y"), monap_ptr->o_name, index_to_label(i_idx));
190 inven_item_increase(player_ptr, i_idx, -1);
191 inven_item_optimize(player_ptr, i_idx);
192 monap_ptr->obvious = true;
197 void process_eat_lite(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
199 if ((monap_ptr->o_ptr->fuel <= 0) || monap_ptr->o_ptr->is_fixed_artifact()) {
203 monap_ptr->o_ptr->fuel -= 250 + randint1(250);
204 if (monap_ptr->o_ptr->fuel < 1) {
205 monap_ptr->o_ptr->fuel = 1;
208 if (!player_ptr->effects()->blindness()->is_blind()) {
209 msg_print(_("明かりが暗くなってしまった。", "Your light dims."));
210 monap_ptr->obvious = true;
213 player_ptr->window_flags |= (PW_EQUIP);
217 * @brief モンスターからの攻撃による充填魔力吸収処理
218 * @param player_ptr プレイヤーへの参照ポインタ
219 * @monap_ptr モンスターからモンスターへの直接攻撃構造体への参照ポインタ
220 * @return 吸収されたらTRUE、されなかったらFALSE
221 * @details 魔道具使用能力向上フラグがあれば、吸収量は全部ではない
222 * 詳細はOSDN #40911の議論を参照のこと
224 bool process_un_power(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
226 if (((monap_ptr->o_ptr->tval != ItemKindType::STAFF) && (monap_ptr->o_ptr->tval != ItemKindType::WAND)) || (monap_ptr->o_ptr->pval == 0)) {
230 bool is_magic_mastery = has_magic_mastery(player_ptr) != 0;
231 BaseitemInfo *kind_ptr = &baseitems_info[monap_ptr->o_ptr->k_idx];
232 PARAMETER_VALUE pval = kind_ptr->pval;
233 DEPTH level = monap_ptr->rlev;
234 auto drain = is_magic_mastery ? std::min<short>(pval, pval * level / 400 + pval * randint1(level) / 400) : pval;
235 drain = std::min(drain, monap_ptr->o_ptr->pval);
240 msg_print(_("ザックからエネルギーが吸い取られた!", "Energy was drained from your pack!"));
241 if (is_magic_mastery && (drain != monap_ptr->o_ptr->pval)) {
242 msg_print(_("しかし、あなたの魔法を操る力がその一部を取り返した!", "However, your skill of magic mastery got back the part of energy!"));
245 monap_ptr->obvious = true;
246 int recovery = drain * kind_ptr->level;
248 if (monap_ptr->o_ptr->tval == ItemKindType::STAFF) {
249 recovery *= monap_ptr->o_ptr->number;
252 recovery = std::min(recovery, monap_ptr->m_ptr->maxhp - monap_ptr->m_ptr->hp);
253 monap_ptr->m_ptr->hp += recovery;
255 if (player_ptr->health_who == monap_ptr->m_idx) {
256 player_ptr->redraw |= PR_HEALTH;
259 if (player_ptr->riding == monap_ptr->m_idx) {
260 player_ptr->redraw |= PR_UHEALTH;
263 monap_ptr->o_ptr->pval = !is_magic_mastery || (monap_ptr->o_ptr->pval == 1) ? 0 : monap_ptr->o_ptr->pval - drain;
264 player_ptr->update |= PU_COMBINE | PU_REORDER;
265 player_ptr->window_flags |= PW_INVEN;
269 bool check_drain_hp(PlayerType *player_ptr, const int32_t d)
271 bool resist_drain = !drain_exp(player_ptr, d, d / 10, 50);
272 if (player_ptr->mimic_form != MimicKindType::NONE) {
273 return PlayerRace(player_ptr).is_mimic_nonliving() ? true : resist_drain;
276 switch (player_ptr->prace) {
277 case PlayerRaceType::ZOMBIE:
278 case PlayerRaceType::VAMPIRE:
279 case PlayerRaceType::SPECTRE:
280 case PlayerRaceType::SKELETON:
281 case PlayerRaceType::BALROG:
282 case PlayerRaceType::GOLEM:
283 case PlayerRaceType::ANDROID:
290 void process_drain_life(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr, const bool resist_drain)
292 if ((monap_ptr->damage <= 5) || resist_drain) {
296 bool did_heal = monap_ptr->m_ptr->hp < monap_ptr->m_ptr->maxhp;
297 monap_ptr->m_ptr->hp += damroll(4, monap_ptr->damage / 6);
298 if (monap_ptr->m_ptr->hp > monap_ptr->m_ptr->maxhp) {
299 monap_ptr->m_ptr->hp = monap_ptr->m_ptr->maxhp;
302 if (player_ptr->health_who == monap_ptr->m_idx) {
303 player_ptr->redraw |= (PR_HEALTH);
306 if (player_ptr->riding == monap_ptr->m_idx) {
307 player_ptr->redraw |= (PR_UHEALTH);
310 if (monap_ptr->m_ptr->ml && did_heal) {
311 msg_format(_("%sは体力を回復したようだ。", "%^s appears healthier."), monap_ptr->m_name);
315 void process_drain_mana(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
317 if (check_multishadow(player_ptr)) {
318 msg_print(_("攻撃は幻影に命中し、あなたには届かなかった。", "The attack hits Shadow, but you are unharmed!"));
322 monap_ptr->do_cut = 0;
323 player_ptr->csp -= monap_ptr->damage;
324 if (player_ptr->csp < 0) {
326 player_ptr->csp_frac = 0;
329 player_ptr->redraw |= (PR_MANA);
333 * @brief モンスターからの空腹進行処理
334 * @param player_ptr プレイヤーへの参照ポインタ
335 * @monap_ptr モンスターからモンスターへの直接攻撃構造体への参照ポインタ
336 * @details 空腹、衰弱の一歩手前で止める優しさは残す。
338 void process_monster_attack_hungry(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
340 msg_format(_("あなたは腹が減った!", "You feel hungry!"));
341 auto subtracted_food = static_cast<int16_t>(player_ptr->food - monap_ptr->damage);
342 if ((player_ptr->food >= PY_FOOD_ALERT) && (PY_FOOD_ALERT > subtracted_food)) {
343 set_food(player_ptr, PY_FOOD_ALERT - 1);
344 } else if ((player_ptr->food > PY_FOOD_FAINT) && (PY_FOOD_FAINT >= subtracted_food)) {
345 set_food(player_ptr, PY_FOOD_FAINT);
347 set_food(player_ptr, subtracted_food);