OSDN Git Service

[Refactor] #40534 Separated object-flavor-types.h from object-flavor.h
[hengband/hengband.git] / src / monster-attack / monster-eating.c
1 /*!
2  * @brief プレーヤーのHP/MP、アイテム、お金・明かりの残りターン、充填魔力を盗んだり減少させたりする処理
3  * @date 2020/05/31
4  * @author Hourier
5  */
6
7 #include "monster-attack/monster-eating.h"
8 #include "core/player-redraw-types.h"
9 #include "core/player-update-types.h"
10 #include "core/window-redrawer.h"
11 #include "flavor/object-flavor-types.h"
12 #include "floor/floor.h"
13 #include "inventory/inventory-object.h"
14 #include "inventory/inventory-slot-types.h"
15 #include "mind/mind-mirror-master.h"
16 #include "monster/monster-status.h"
17 #include "object-hook/hook-enchant.h"
18 #include "object/object-flavor.h"
19 #include "object/object-generator.h"
20 #include "object/object-mark-types.h"
21 #include "object/object-info.h"
22 #include "player/avatar.h"
23 #include "player/mimic-info-table.h"
24 #include "status/experience.h"
25 #include "view/display-messages.h"
26 #include "world/world-object.h"
27
28 void process_eat_gold(player_type *target_ptr, monap_type *monap_ptr)
29 {
30     if (!target_ptr->paralyzed && (randint0(100) < (adj_dex_safe[target_ptr->stat_ind[A_DEX]] + target_ptr->lev))) {
31         msg_print(_("しかし素早く財布を守った!", "You quickly protect your money pouch!"));
32         if (randint0(3))
33             monap_ptr->blinked = TRUE;
34
35         return;
36     }
37
38     PRICE gold = (target_ptr->au / 10) + randint1(25);
39     if (gold < 2)
40         gold = 2;
41
42     if (gold > 5000)
43         gold = (target_ptr->au / 20) + randint1(3000);
44
45     if (gold > target_ptr->au)
46         gold = target_ptr->au;
47
48     target_ptr->au -= gold;
49     if (gold <= 0) {
50         msg_print(_("しかし何も盗まれなかった。", "Nothing was stolen."));
51     } else if (target_ptr->au > 0) {
52         msg_print(_("財布が軽くなった気がする。", "Your purse feels lighter."));
53         msg_format(_("$%ld のお金が盗まれた!", "%ld coins were stolen!"), (long)gold);
54         chg_virtue(target_ptr, V_SACRIFICE, 1);
55     } else {
56         msg_print(_("財布が軽くなった気がする。", "Your purse feels lighter."));
57         msg_print(_("お金が全部盗まれた!", "All of your coins were stolen!"));
58         chg_virtue(target_ptr, V_SACRIFICE, 2);
59     }
60
61     target_ptr->redraw |= (PR_GOLD);
62     target_ptr->window |= (PW_PLAYER);
63     monap_ptr->blinked = TRUE;
64 }
65
66 /*!
67  * @brief 盗み打撃の時にアイテムが盗まれるかどうかを判定する
68  * @param target_ptr プレーヤーへの参照ポインタ
69  * @monap_ptr モンスターからモンスターへの直接攻撃構造体への参照ポインタ
70  * @return 盗まれたらTRUE、何も盗まれなかったらFALSE
71  */
72 bool check_eat_item(player_type *target_ptr, monap_type *monap_ptr)
73 {
74     if (monster_confused_remaining(monap_ptr->m_ptr))
75         return FALSE;
76
77     if (target_ptr->is_dead || check_multishadow(target_ptr))
78         return FALSE;
79
80     if (!target_ptr->paralyzed && (randint0(100) < (adj_dex_safe[target_ptr->stat_ind[A_DEX]] + target_ptr->lev))) {
81         msg_print(_("しかしあわててザックを取り返した!", "You grab hold of your backpack!"));
82         monap_ptr->blinked = TRUE;
83         monap_ptr->obvious = TRUE;
84         return FALSE;
85     }
86
87     return TRUE;
88 }
89
90 /*!
91  * @brief プレーヤーが持っているアイテムをモンスターに移す
92  * @param target_ptr プレーヤーへの参照ポインタ
93  * @monap_ptr モンスターからモンスターへの直接攻撃構造体への参照ポインタ
94  * @return なし
95  */
96 static void move_item_to_monster(player_type *target_ptr, monap_type *monap_ptr, const OBJECT_IDX o_idx)
97 {
98     if (o_idx == 0)
99         return;
100
101     object_type *j_ptr;
102     j_ptr = &target_ptr->current_floor_ptr->o_list[o_idx];
103     object_copy(j_ptr, monap_ptr->o_ptr);
104     j_ptr->number = 1;
105     if ((monap_ptr->o_ptr->tval == TV_ROD) || (monap_ptr->o_ptr->tval == TV_WAND)) {
106         j_ptr->pval = monap_ptr->o_ptr->pval / monap_ptr->o_ptr->number;
107         monap_ptr->o_ptr->pval -= j_ptr->pval;
108     }
109
110     j_ptr->marked = OM_TOUCHED;
111     j_ptr->held_m_idx = monap_ptr->m_idx;
112     j_ptr->next_o_idx = monap_ptr->m_ptr->hold_o_idx;
113     monap_ptr->m_ptr->hold_o_idx = o_idx;
114 }
115
116 /*!
117  * @brief アイテム盗み処理
118  * @param target_ptr プレーヤーへの参照ポインタ
119  * @monap_ptr モンスターからモンスターへの直接攻撃構造体への参照ポインタ
120  * @return なし
121  * @details eatとあるがお金や食べ物と違ってなくならない、盗んだモンスターを倒せば取り戻せる
122  */
123 void process_eat_item(player_type *target_ptr, monap_type *monap_ptr)
124 {
125     for (int i = 0; i < 10; i++) {
126         OBJECT_IDX o_idx;
127         INVENTORY_IDX i_idx = (INVENTORY_IDX)randint0(INVEN_PACK);
128         monap_ptr->o_ptr = &target_ptr->inventory_list[i_idx];
129         if (!monap_ptr->o_ptr->k_idx)
130             continue;
131
132         if (object_is_artifact(monap_ptr->o_ptr))
133             continue;
134
135         object_desc(target_ptr, monap_ptr->o_name, monap_ptr->o_ptr, OD_OMIT_PREFIX);
136 #ifdef JP
137         msg_format("%s(%c)を%s盗まれた!", monap_ptr->o_name, index_to_label(i_idx), ((monap_ptr->o_ptr->number > 1) ? "一つ" : ""));
138 #else
139         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));
140 #endif
141         chg_virtue(target_ptr, V_SACRIFICE, 1);
142         o_idx = o_pop(target_ptr->current_floor_ptr);
143         move_item_to_monster(target_ptr, monap_ptr, o_idx);
144         inven_item_increase(target_ptr, i_idx, -1);
145         inven_item_optimize(target_ptr, i_idx);
146         monap_ptr->obvious = TRUE;
147         monap_ptr->blinked = TRUE;
148         break;
149     }
150 }
151
152 void process_eat_food(player_type *target_ptr, monap_type *monap_ptr)
153 {
154     for (int i = 0; i < 10; i++) {
155         INVENTORY_IDX i_idx = (INVENTORY_IDX)randint0(INVEN_PACK);
156         monap_ptr->o_ptr = &target_ptr->inventory_list[i_idx];
157         if (!monap_ptr->o_ptr->k_idx)
158             continue;
159
160         if ((monap_ptr->o_ptr->tval != TV_FOOD) && !((monap_ptr->o_ptr->tval == TV_CORPSE) && (monap_ptr->o_ptr->sval)))
161             continue;
162
163         object_desc(target_ptr, monap_ptr->o_name, monap_ptr->o_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
164 #ifdef JP
165         msg_format("%s(%c)を%s食べられてしまった!", monap_ptr->o_name, index_to_label(i_idx), ((monap_ptr->o_ptr->number > 1) ? "一つ" : ""));
166 #else
167         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));
168 #endif
169         inven_item_increase(target_ptr, i_idx, -1);
170         inven_item_optimize(target_ptr, i_idx);
171         monap_ptr->obvious = TRUE;
172         break;
173     }
174 }
175
176 void process_eat_lite(player_type *target_ptr, monap_type *monap_ptr)
177 {
178     if ((monap_ptr->o_ptr->xtra4 <= 0) || object_is_fixed_artifact(monap_ptr->o_ptr))
179         return;
180
181     monap_ptr->o_ptr->xtra4 -= (s16b)(250 + randint1(250));
182     if (monap_ptr->o_ptr->xtra4 < 1)
183         monap_ptr->o_ptr->xtra4 = 1;
184
185     if (!target_ptr->blind) {
186         msg_print(_("明かりが暗くなってしまった。", "Your light dims."));
187         monap_ptr->obvious = TRUE;
188     }
189
190     target_ptr->window |= (PW_EQUIP);
191 }
192
193 /*!
194  * @brief モンスターからの攻撃による充填魔力吸収処理
195  * @param target_ptr プレーヤーへの参照ポインタ
196  * @monap_ptr モンスターからモンスターへの直接攻撃構造体への参照ポインタ
197  * @return 吸収されたらTRUE、されなかったらFALSE
198  */
199 bool process_un_power(player_type *target_ptr, monap_type *monap_ptr)
200 {
201     if (((monap_ptr->o_ptr->tval != TV_STAFF) && (monap_ptr->o_ptr->tval != TV_WAND)) || (monap_ptr->o_ptr->pval == 0))
202         return FALSE;
203
204     int heal = monap_ptr->rlev * monap_ptr->o_ptr->pval;
205     if (monap_ptr->o_ptr->tval == TV_STAFF)
206         heal *= monap_ptr->o_ptr->number;
207
208     heal = MIN(heal, monap_ptr->m_ptr->maxhp - monap_ptr->m_ptr->hp);
209     msg_print(_("ザックからエネルギーが吸い取られた!", "Energy drains from your pack!"));
210     monap_ptr->obvious = TRUE;
211     monap_ptr->m_ptr->hp += (HIT_POINT)heal;
212     if (target_ptr->health_who == monap_ptr->m_idx)
213         target_ptr->redraw |= (PR_HEALTH);
214
215     if (target_ptr->riding == monap_ptr->m_idx)
216         target_ptr->redraw |= (PR_UHEALTH);
217
218     monap_ptr->o_ptr->pval = 0;
219     target_ptr->update |= (PU_COMBINE | PU_REORDER);
220     target_ptr->window |= (PW_INVEN);
221     return TRUE;
222 }
223
224 bool check_drain_hp(player_type *target_ptr, const s32b d)
225 {
226     bool resist_drain = !drain_exp(target_ptr, d, d / 10, 50);
227     if (target_ptr->mimic_form)
228         return (mimic_info[target_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_NONLIVING) != 0 ? TRUE : resist_drain;
229
230     switch (target_ptr->prace) {
231     case RACE_ZOMBIE:
232     case RACE_VAMPIRE:
233     case RACE_SPECTRE:
234     case RACE_SKELETON:
235     case RACE_BALROG:
236     case RACE_GOLEM:
237     case RACE_ANDROID:
238         return TRUE;
239     default:
240         return resist_drain;
241     }
242 }
243
244 void process_drain_life(player_type *target_ptr, monap_type *monap_ptr, const bool resist_drain)
245 {
246     if ((monap_ptr->damage <= 5) || resist_drain)
247         return;
248
249     bool did_heal = monap_ptr->m_ptr->hp < monap_ptr->m_ptr->maxhp;
250     monap_ptr->m_ptr->hp += damroll(4, monap_ptr->damage / 6);
251     if (monap_ptr->m_ptr->hp > monap_ptr->m_ptr->maxhp)
252         monap_ptr->m_ptr->hp = monap_ptr->m_ptr->maxhp;
253
254     if (target_ptr->health_who == monap_ptr->m_idx)
255         target_ptr->redraw |= (PR_HEALTH);
256
257     if (target_ptr->riding == monap_ptr->m_idx)
258         target_ptr->redraw |= (PR_UHEALTH);
259
260     if (monap_ptr->m_ptr->ml && did_heal)
261         msg_format(_("%sは体力を回復したようだ。", "%^s appears healthier."), monap_ptr->m_name);
262 }
263
264 void process_drain_mana(player_type *target_ptr, monap_type *monap_ptr)
265 {
266     if (check_multishadow(target_ptr)) {
267         msg_print(_("攻撃は幻影に命中し、あなたには届かなかった。", "The attack hits Shadow, but you are unharmed!"));
268         return;
269     }
270
271     monap_ptr->do_cut = 0;
272     target_ptr->csp -= monap_ptr->damage;
273     if (target_ptr->csp < 0) {
274         target_ptr->csp = 0;
275         target_ptr->csp_frac = 0;
276     }
277
278     target_ptr->redraw |= (PR_MANA);
279 }