OSDN Git Service

[feature] ソースファイルをC++に対応
[hengbandforosx/hengbandosx.git] / src / cmd-item / cmd-throw.c
1 #include "cmd-item/cmd-throw.h"
2 #include "action/throw-util.h"
3 #include "action/weapon-shield.h"
4 #include "artifact/fixed-art-types.h"
5 #include "combat/attack-power-table.h"
6 #include "combat/shoot.h"
7 #include "combat/slaying.h"
8 #include "core/player-redraw-types.h"
9 #include "core/player-update-types.h"
10 #include "core/stuff-handler.h"
11 #include "core/window-redrawer.h"
12 #include "effect/spells-effect-util.h"
13 #include "flavor/flavor-describer.h"
14 #include "flavor/object-flavor-types.h"
15 #include "floor/cave.h"
16 #include "floor/floor-object.h"
17 #include "floor/geometry.h"
18 #include "game-option/cheat-types.h"
19 #include "game-option/special-options.h"
20 #include "grid/feature-flag-types.h"
21 #include "grid/grid.h"
22 #include "inventory/inventory-object.h"
23 #include "inventory/inventory-slot-types.h"
24 #include "io/cursor.h"
25 #include "io/screen-util.h"
26 #include "main/sound-definitions-table.h"
27 #include "main/sound-of-music.h"
28 #include "monster-floor/monster-death.h"
29 #include "monster-floor/monster-summon.h"
30 #include "monster-floor/place-monster-types.h"
31 #include "monster/monster-describer.h"
32 #include "monster/monster-info.h"
33 #include "monster/monster-status-setter.h"
34 #include "monster/monster-status.h"
35 #include "object-enchant/tr-types.h"
36 #include "object-hook/hook-checker.h"
37 #include "object-hook/hook-expendable.h"
38 #include "object-hook/hook-weapon.h"
39 #include "object/item-tester-hooker.h"
40 #include "object/item-use-flags.h"
41 #include "object/object-broken.h"
42 #include "object/object-flags.h"
43 #include "object/object-generator.h"
44 #include "object/object-info.h"
45 #include "object/object-kind.h"
46 #include "object/object-stack.h"
47 #include "player/attack-defense-types.h"
48 #include "player/player-status-table.h"
49 #include "player/special-defense-types.h"
50 #include "racial/racial-android.h"
51 #include "specific-object/torch.h"
52 #include "status/action-setter.h"
53 #include "system/floor-type-definition.h"
54 #include "system/object-type-definition.h"
55 #include "target/target-checker.h"
56 #include "target/target-getter.h"
57 #include "term/screen-processor.h"
58 #include "util/bit-flags-calculator.h"
59 #include "view/display-messages.h"
60 #include "view/object-describer.h"
61 #include "wizard/wizard-messages.h"
62
63 static bool check_throw_boomerang(player_type *creature_ptr, it_type *it_ptr, concptr *q, concptr *s)
64 {
65     if (!it_ptr->boomerang)
66         return TRUE;
67
68     if (has_melee_weapon(creature_ptr, INVEN_MAIN_HAND) && has_melee_weapon(creature_ptr, INVEN_SUB_HAND)) {
69         item_tester_hook = item_tester_hook_boomerang;
70         *q = _("どの武器を投げますか? ", "Throw which item? ");
71         *s = _("投げる武器がない。", "You have nothing to throw.");
72         it_ptr->o_ptr = choose_object(creature_ptr, &it_ptr->item, *q, *s, USE_EQUIP, TV_NONE);
73         if (!it_ptr->o_ptr) {
74             flush();
75             return FALSE;
76         }
77
78         return TRUE;
79     }
80
81     if (has_melee_weapon(creature_ptr, INVEN_SUB_HAND)) {
82         it_ptr->item = INVEN_SUB_HAND;
83         it_ptr->o_ptr = &creature_ptr->inventory_list[it_ptr->item];
84         return TRUE;
85     }
86
87     it_ptr->item = INVEN_MAIN_HAND;
88     it_ptr->o_ptr = &creature_ptr->inventory_list[it_ptr->item];
89     return TRUE;
90 }
91
92 static bool check_what_throw(player_type *creature_ptr, it_type *it_ptr)
93 {
94     if (it_ptr->shuriken >= 0) {
95         it_ptr->item = it_ptr->shuriken;
96         it_ptr->o_ptr = &creature_ptr->inventory_list[it_ptr->item];
97         return TRUE;
98     }
99
100     concptr q, s;
101     if (!check_throw_boomerang(creature_ptr, it_ptr, &q, &s))
102         return FALSE;
103
104     q = _("どのアイテムを投げますか? ", "Throw which item? ");
105     s = _("投げるアイテムがない。", "You have nothing to throw.");
106     it_ptr->o_ptr = choose_object(creature_ptr, &it_ptr->item, q, s, USE_INVEN | USE_FLOOR | USE_EQUIP, TV_NONE);
107     if (!it_ptr->o_ptr) {
108         flush();
109         return FALSE;
110     }
111
112     return TRUE;
113 }
114
115 static bool check_can_throw(player_type *creature_ptr, it_type *it_ptr)
116 {
117     if (!check_what_throw(creature_ptr, it_ptr))
118         return FALSE;
119
120     if (object_is_cursed(it_ptr->o_ptr) && (it_ptr->item >= INVEN_MAIN_HAND)) {
121         msg_print(_("ふーむ、どうやら呪われているようだ。", "Hmmm, it seems to be cursed."));
122         return FALSE;
123     }
124
125     if (creature_ptr->current_floor_ptr->inside_arena && !it_ptr->boomerang && (it_ptr->o_ptr->tval != TV_SPIKE)) {
126         msg_print(_("アリーナではアイテムを使えない!", "You're in the arena now. This is hand-to-hand!"));
127         msg_print(NULL);
128         return FALSE;
129     }
130
131     return TRUE;
132 }
133
134 static void calc_throw_range(player_type *creature_ptr, it_type *it_ptr)
135 {
136     object_copy(it_ptr->q_ptr, it_ptr->o_ptr);
137     object_flags(creature_ptr, it_ptr->q_ptr, it_ptr->obj_flags);
138     torch_flags(it_ptr->q_ptr, it_ptr->obj_flags);
139     distribute_charges(it_ptr->o_ptr, it_ptr->q_ptr, 1);
140     it_ptr->q_ptr->number = 1;
141     describe_flavor(creature_ptr, it_ptr->o_name, it_ptr->q_ptr, OD_OMIT_PREFIX);
142     if (creature_ptr->mighty_throw)
143         it_ptr->mult += 3;
144
145     int mul = 10 + 2 * (it_ptr->mult - 1);
146     int div = ((it_ptr->q_ptr->weight > 10) ? it_ptr->q_ptr->weight : 10);
147     if ((has_flag(it_ptr->obj_flags, TR_THROW)) || it_ptr->boomerang)
148         div /= 2;
149
150     it_ptr->tdis = (adj_str_blow[creature_ptr->stat_ind[A_STR]] + 20) * mul / div;
151     if (it_ptr->tdis > mul)
152         it_ptr->tdis = mul;
153 }
154
155 static bool calc_throw_grid(player_type *creature_ptr, it_type *it_ptr)
156 {
157     if (it_ptr->shuriken >= 0) {
158         it_ptr->ty = randint0(101) - 50 + creature_ptr->y;
159         it_ptr->tx = randint0(101) - 50 + creature_ptr->x;
160         return TRUE;
161     }
162
163     project_length = it_ptr->tdis + 1;
164     DIRECTION dir;
165     if (!get_aim_dir(creature_ptr, &dir))
166         return FALSE;
167
168     it_ptr->tx = creature_ptr->x + 99 * ddx[dir];
169     it_ptr->ty = creature_ptr->y + 99 * ddy[dir];
170     if ((dir == 5) && target_okay(creature_ptr)) {
171         it_ptr->tx = target_col;
172         it_ptr->ty = target_row;
173     }
174
175     project_length = 0;
176     return TRUE;
177 }
178
179 static void reflect_inventory_by_throw(player_type *creature_ptr, it_type *it_ptr)
180 {
181     if ((it_ptr->q_ptr->name1 == ART_MJOLLNIR) || (it_ptr->q_ptr->name1 == ART_AEGISFANG) || it_ptr->boomerang)
182         it_ptr->return_when_thrown = TRUE;
183
184     if (it_ptr->item < 0) {
185         floor_item_increase(creature_ptr->current_floor_ptr, 0 - it_ptr->item, -1);
186         floor_item_optimize(creature_ptr, 0 - it_ptr->item);
187         return;
188     }
189
190     inven_item_increase(creature_ptr, it_ptr->item, -1);
191     if (!it_ptr->return_when_thrown)
192         inven_item_describe(creature_ptr, it_ptr->item);
193
194     inven_item_optimize(creature_ptr, it_ptr->item);
195 }
196
197 static void set_class_specific_throw_params(player_type *creature_ptr, it_type *it_ptr)
198 {
199     take_turn(creature_ptr, 100);
200     if ((creature_ptr->pclass == CLASS_ROGUE) || (creature_ptr->pclass == CLASS_NINJA))
201         creature_ptr->energy_use -= creature_ptr->lev;
202
203     it_ptr->y = creature_ptr->y;
204     it_ptr->x = creature_ptr->x;
205     handle_stuff(creature_ptr);
206     it_ptr->shuriken = (creature_ptr->pclass == CLASS_NINJA)
207         && ((it_ptr->q_ptr->tval == TV_SPIKE) || ((has_flag(it_ptr->obj_flags, TR_THROW)) && (it_ptr->q_ptr->tval == TV_SWORD)));
208 }
209
210 static void set_racial_chance(player_type *creature_ptr, it_type *it_ptr)
211 {
212     if (has_flag(it_ptr->obj_flags, TR_THROW))
213         it_ptr->chance = ((creature_ptr->skill_tht) + ((creature_ptr->to_h_b + it_ptr->q_ptr->to_h) * BTH_PLUS_ADJ));
214     else
215         it_ptr->chance = (creature_ptr->skill_tht + (creature_ptr->to_h_b * BTH_PLUS_ADJ));
216
217     if (it_ptr->shuriken != 0)
218         it_ptr->chance *= 2;
219 }
220
221 static bool check_racial_target_bold(player_type *creature_ptr, it_type *it_ptr)
222 {
223     it_ptr->ny[it_ptr->cur_dis] = it_ptr->y;
224     it_ptr->nx[it_ptr->cur_dis] = it_ptr->x;
225     mmove2(&it_ptr->ny[it_ptr->cur_dis], &it_ptr->nx[it_ptr->cur_dis], creature_ptr->y, creature_ptr->x, it_ptr->ty, it_ptr->tx);
226     if (cave_has_flag_bold(creature_ptr->current_floor_ptr, it_ptr->ny[it_ptr->cur_dis], it_ptr->nx[it_ptr->cur_dis], FF_PROJECT))
227         return FALSE;
228
229     it_ptr->hit_wall = TRUE;
230     return (it_ptr->q_ptr->tval == TV_FIGURINE) || object_is_potion(it_ptr->q_ptr)
231         || (creature_ptr->current_floor_ptr->grid_array[it_ptr->ny[it_ptr->cur_dis]][it_ptr->nx[it_ptr->cur_dis]].m_idx == 0);
232 }
233
234 static void check_racial_target_seen(player_type *creature_ptr, it_type *it_ptr)
235 {
236     if (!panel_contains(it_ptr->ny[it_ptr->cur_dis], it_ptr->nx[it_ptr->cur_dis])
237         || !player_can_see_bold(creature_ptr, it_ptr->ny[it_ptr->cur_dis], it_ptr->nx[it_ptr->cur_dis])) {
238         term_xtra(TERM_XTRA_DELAY, it_ptr->msec);
239         return;
240     }
241
242     if (it_ptr->msec > 0) {
243         SYMBOL_CODE c = object_char(it_ptr->q_ptr);
244         TERM_COLOR a = object_attr(it_ptr->q_ptr);
245         print_rel(creature_ptr, c, a, it_ptr->ny[it_ptr->cur_dis], it_ptr->nx[it_ptr->cur_dis]);
246         move_cursor_relative(it_ptr->ny[it_ptr->cur_dis], it_ptr->nx[it_ptr->cur_dis]);
247         term_fresh();
248         term_xtra(TERM_XTRA_DELAY, it_ptr->msec);
249         lite_spot(creature_ptr, it_ptr->ny[it_ptr->cur_dis], it_ptr->nx[it_ptr->cur_dis]);
250         term_fresh();
251     }
252 }
253
254 static bool check_racial_target_monster(player_type *creature_ptr, it_type *it_ptr)
255 {
256     it_ptr->prev_y = it_ptr->y;
257     it_ptr->prev_x = it_ptr->x;
258     it_ptr->x = it_ptr->nx[it_ptr->cur_dis];
259     it_ptr->y = it_ptr->ny[it_ptr->cur_dis];
260     it_ptr->cur_dis++;
261     return creature_ptr->current_floor_ptr->grid_array[it_ptr->y][it_ptr->x].m_idx == 0;
262 }
263
264 static void display_attack_racial_power(player_type *creature_ptr, it_type *it_ptr)
265 {
266     if (!it_ptr->visible) {
267         msg_format(_("%sが敵を捕捉した。", "The %s finds a mark."), it_ptr->o_name);
268         return;
269     }
270
271     msg_format(_("%sが%sに命中した。", "The %s hits %s."), it_ptr->o_name, it_ptr->m_name);
272     if (!it_ptr->m_ptr->ml)
273         return;
274
275     if (!creature_ptr->image)
276         monster_race_track(creature_ptr, it_ptr->m_ptr->ap_r_idx);
277
278     health_track(creature_ptr, it_ptr->g_ptr->m_idx);
279 }
280
281 static void calc_racial_power_damage(player_type *creature_ptr, it_type *it_ptr)
282 {
283     int dd = it_ptr->q_ptr->dd;
284     int ds = it_ptr->q_ptr->ds;
285     torch_dice(it_ptr->q_ptr, &dd, &ds);
286     it_ptr->tdam = damroll(dd, ds);
287     it_ptr->tdam = calc_attack_damage_with_slay(creature_ptr, it_ptr->q_ptr, it_ptr->tdam, it_ptr->m_ptr, HISSATSU_NONE, TRUE);
288     it_ptr->tdam = critical_shot(creature_ptr, it_ptr->q_ptr->weight, it_ptr->q_ptr->to_h, 0, it_ptr->tdam);
289     if (it_ptr->q_ptr->to_d > 0)
290         it_ptr->tdam += it_ptr->q_ptr->to_d;
291     else
292         it_ptr->tdam += -it_ptr->q_ptr->to_d;
293
294     if (it_ptr->boomerang) {
295         it_ptr->tdam *= (it_ptr->mult + creature_ptr->num_blow[it_ptr->item - INVEN_MAIN_HAND]);
296         it_ptr->tdam += creature_ptr->to_d_m;
297     } else if (has_flag(it_ptr->obj_flags, TR_THROW)) {
298         it_ptr->tdam *= (3 + it_ptr->mult);
299         it_ptr->tdam += creature_ptr->to_d_m;
300     } else {
301         it_ptr->tdam *= it_ptr->mult;
302     }
303
304     if (it_ptr->shuriken != 0)
305         it_ptr->tdam += ((creature_ptr->lev + 30) * (creature_ptr->lev + 30) - 900) / 55;
306
307     if (it_ptr->tdam < 0)
308         it_ptr->tdam = 0;
309
310     it_ptr->tdam = mon_damage_mod(creature_ptr, it_ptr->m_ptr, it_ptr->tdam, FALSE);
311 }
312
313 static void attack_racial_power(player_type *creature_ptr, it_type *it_ptr)
314 {
315     if (!test_hit_fire(creature_ptr, it_ptr->chance - it_ptr->cur_dis, it_ptr->m_ptr, it_ptr->m_ptr->ml, it_ptr->o_name))
316         return;
317
318     display_attack_racial_power(creature_ptr, it_ptr);
319     calc_racial_power_damage(creature_ptr, it_ptr);
320     msg_format_wizard(creature_ptr, CHEAT_MONSTER, _("%dのダメージを与えた。(残りHP %d/%d(%d))", "You do %d damage. (left HP %d/%d(%d))"), it_ptr->tdam,
321         it_ptr->m_ptr->hp - it_ptr->tdam, it_ptr->m_ptr->maxhp, it_ptr->m_ptr->max_maxhp);
322
323     bool fear = FALSE;
324     if (mon_take_hit(creature_ptr, it_ptr->g_ptr->m_idx, it_ptr->tdam, &fear, extract_note_dies(real_r_idx(it_ptr->m_ptr))))
325         return;
326
327     message_pain(creature_ptr, it_ptr->g_ptr->m_idx, it_ptr->tdam);
328     if ((it_ptr->tdam > 0) && !object_is_potion(it_ptr->q_ptr))
329         anger_monster(creature_ptr, it_ptr->m_ptr);
330
331     if (fear && it_ptr->m_ptr->ml) {
332         sound(SOUND_FLEE);
333         msg_format(_("%^sは恐怖して逃げ出した!", "%^s flees in terror!"), it_ptr->m_name);
334     }
335 }
336
337 static void exe_throw(player_type *creature_ptr, it_type *it_ptr)
338 {
339     it_ptr->cur_dis = 0;
340     while (it_ptr->cur_dis <= it_ptr->tdis) {
341         if ((it_ptr->y == it_ptr->ty) && (it_ptr->x == it_ptr->tx))
342             break;
343
344         if (check_racial_target_bold(creature_ptr, it_ptr))
345             break;
346
347         check_racial_target_seen(creature_ptr, it_ptr);
348         if (check_racial_target_monster(creature_ptr, it_ptr))
349             continue;
350
351         it_ptr->g_ptr = &creature_ptr->current_floor_ptr->grid_array[it_ptr->y][it_ptr->x];
352         it_ptr->m_ptr = &creature_ptr->current_floor_ptr->m_list[it_ptr->g_ptr->m_idx];
353         monster_name(creature_ptr, it_ptr->g_ptr->m_idx, it_ptr->m_name);
354         it_ptr->visible = it_ptr->m_ptr->ml;
355         it_ptr->hit_body = TRUE;
356         attack_racial_power(creature_ptr, it_ptr);
357         break;
358     }
359 }
360
361 void display_figurine_throw(player_type *creature_ptr, it_type *it_ptr)
362 {
363     if ((it_ptr->q_ptr->tval != TV_FIGURINE) || creature_ptr->current_floor_ptr->inside_arena)
364         return;
365
366     it_ptr->corruption_possibility = 100;
367     if (!(summon_named_creature(creature_ptr, 0, it_ptr->y, it_ptr->x, it_ptr->q_ptr->pval, !(object_is_cursed(it_ptr->q_ptr)) ? PM_FORCE_PET : PM_NONE))) {
368         msg_print(_("人形は捻じ曲がり砕け散ってしまった!", "The Figurine writhes and then shatters."));
369         return;
370     }
371
372     if (object_is_cursed(it_ptr->q_ptr))
373         msg_print(_("これはあまり良くない気がする。", "You have a bad feeling about this."));
374 }
375
376 void display_potion_throw(player_type *creature_ptr, it_type *it_ptr)
377 {
378     if (!object_is_potion(it_ptr->q_ptr))
379         return;
380
381     if (!it_ptr->hit_body && !it_ptr->hit_wall && (randint1(100) >= it_ptr->corruption_possibility)) {
382         it_ptr->corruption_possibility = 0;
383         return;
384     }
385
386     msg_format(_("%sは砕け散った!", "The %s shatters!"), it_ptr->o_name);
387     if (!potion_smash_effect(creature_ptr, 0, it_ptr->y, it_ptr->x, it_ptr->q_ptr->k_idx)) {
388         it_ptr->do_drop = FALSE;
389         return;
390     }
391
392     monster_type *m_ptr = &creature_ptr->current_floor_ptr->m_list[creature_ptr->current_floor_ptr->grid_array[it_ptr->y][it_ptr->x].m_idx];
393     if ((creature_ptr->current_floor_ptr->grid_array[it_ptr->y][it_ptr->x].m_idx == 0) || !is_friendly(m_ptr) || monster_invulner_remaining(m_ptr)) {
394         it_ptr->do_drop = FALSE;
395         return;
396     }
397
398     GAME_TEXT m_name[MAX_NLEN];
399     monster_desc(creature_ptr, m_name, m_ptr, 0);
400     msg_format(_("%sは怒った!", "%^s gets angry!"), m_name);
401     set_hostile(creature_ptr, &creature_ptr->current_floor_ptr->m_list[creature_ptr->current_floor_ptr->grid_array[it_ptr->y][it_ptr->x].m_idx]);
402     it_ptr->do_drop = FALSE;
403 }
404
405 static void display_boomerang_throw(player_type *creature_ptr, it_type *it_ptr)
406 {
407     if ((it_ptr->back_chance > 37) && !creature_ptr->blind && (it_ptr->item >= 0)) {
408         msg_format(_("%sが手元に返ってきた。", "%s comes back to you."), it_ptr->o2_name);
409         it_ptr->come_back = TRUE;
410         return;
411     }
412
413     if (it_ptr->item >= 0)
414         msg_format(_("%sを受け損ねた!", "%s comes back, but you can't catch!"), it_ptr->o2_name);
415     else
416         msg_format(_("%sが返ってきた。", "%s comes back."), it_ptr->o2_name);
417
418     it_ptr->y = creature_ptr->y;
419     it_ptr->x = creature_ptr->x;
420 }
421
422 static void process_boomerang_throw(player_type *creature_ptr, it_type *it_ptr)
423 {
424     if ((it_ptr->back_chance <= 30) || (one_in_(100) && !it_ptr->super_boomerang)) {
425         msg_format(_("%sが返ってこなかった!", "%s doesn't come back!"), it_ptr->o2_name);
426         return;
427     }
428
429     for (int i = it_ptr->cur_dis - 1; i > 0; i--) {
430         if (!panel_contains(it_ptr->ny[i], it_ptr->nx[i]) || !player_can_see_bold(creature_ptr, it_ptr->ny[i], it_ptr->nx[i])) {
431             term_xtra(TERM_XTRA_DELAY, it_ptr->msec);
432             continue;
433         }
434
435         SYMBOL_CODE c = object_char(it_ptr->q_ptr);
436         byte a = object_attr(it_ptr->q_ptr);
437
438         if (it_ptr->msec > 0) {
439             print_rel(creature_ptr, c, a, it_ptr->ny[i], it_ptr->nx[i]);
440             move_cursor_relative(it_ptr->ny[i], it_ptr->nx[i]);
441             term_fresh();
442             term_xtra(TERM_XTRA_DELAY, it_ptr->msec);
443             lite_spot(creature_ptr, it_ptr->ny[i], it_ptr->nx[i]);
444             term_fresh();
445         }
446     }
447
448     display_boomerang_throw(creature_ptr, it_ptr);
449 }
450
451 static void check_boomerang_throw(player_type *creature_ptr, it_type *it_ptr)
452 {
453     if (!it_ptr->return_when_thrown)
454         return;
455
456     it_ptr->back_chance = randint1(30) + 20 + ((int)(adj_dex_th[creature_ptr->stat_ind[A_DEX]]) - 128);
457     it_ptr->super_boomerang = (((it_ptr->q_ptr->name1 == ART_MJOLLNIR) || (it_ptr->q_ptr->name1 == ART_AEGISFANG)) && it_ptr->boomerang);
458     it_ptr->corruption_possibility = -1;
459     if (it_ptr->boomerang)
460         it_ptr->back_chance += 4 + randint1(5);
461
462     if (it_ptr->super_boomerang)
463         it_ptr->back_chance += 100;
464
465     describe_flavor(creature_ptr, it_ptr->o2_name, it_ptr->q_ptr, OD_OMIT_PREFIX | OD_NAME_ONLY);
466     process_boomerang_throw(creature_ptr, it_ptr);
467 }
468
469 static void process_boomerang_back(player_type *creature_ptr, it_type *it_ptr)
470 {
471     if (it_ptr->come_back) {
472         if ((it_ptr->item != INVEN_MAIN_HAND) && (it_ptr->item != INVEN_SUB_HAND)) {
473             store_item_to_inventory(creature_ptr, it_ptr->q_ptr);
474             it_ptr->do_drop = FALSE;
475             return;
476         }
477
478         it_ptr->o_ptr = &creature_ptr->inventory_list[it_ptr->item];
479         object_copy(it_ptr->o_ptr, it_ptr->q_ptr);
480         creature_ptr->equip_cnt++;
481         creature_ptr->update |= PU_BONUS | PU_TORCH | PU_MANA;
482         creature_ptr->window_flags |= PW_EQUIP;
483         it_ptr->do_drop = FALSE;
484         return;
485     }
486
487     if (it_ptr->equiped_item) {
488         verify_equip_slot(creature_ptr, it_ptr->item);
489         calc_android_exp(creature_ptr);
490     }
491 }
492
493 static void drop_thrown_item(player_type *creature_ptr, it_type *it_ptr)
494 {
495     if (!it_ptr->do_drop)
496         return;
497
498     if (cave_has_flag_bold(creature_ptr->current_floor_ptr, it_ptr->y, it_ptr->x, FF_PROJECT))
499         (void)drop_near(creature_ptr, it_ptr->q_ptr, it_ptr->corruption_possibility, it_ptr->y, it_ptr->x);
500     else
501         (void)drop_near(creature_ptr, it_ptr->q_ptr, it_ptr->corruption_possibility, it_ptr->prev_y, it_ptr->prev_x);
502 }
503
504 /*!
505  * @brief 投射処理メインルーチン /
506  * Throw an object from the pack or floor.
507  * @param mult 威力の倍率
508  * @param creature_ptr プレーヤーへの参照ポインタ
509  * @param boomerang ブーメラン処理ならばTRUE
510  * @param shuriken 忍者の手裏剣処理ならばTRUE ← 間違い、-1が渡されてくることがある。要調査.
511  * @return ターンを消費した場合TRUEを返す
512  * @details
513  * <pre>
514  * Note: "unseen" monsters are very hard to hit.
515  *
516  * Should throwing a weapon do full damage?  Should it allow the magic
517  * to hit bonus of the weapon to have an effect?  Should it ever cause
518  * the item to be destroyed?  Should it do any damage at all?
519  * </pre>
520  */
521 bool do_cmd_throw(player_type *creature_ptr, int mult, bool boomerang, OBJECT_IDX shuriken)
522 {
523     if (creature_ptr->wild_mode)
524         return FALSE;
525
526     if (creature_ptr->special_defense & KATA_MUSOU)
527         set_action(creature_ptr, ACTION_NONE);
528
529     it_type tmp_it;
530     object_type tmp_object;
531     it_type *it_ptr = initialize_it_type(&tmp_it, &tmp_object, delay_factor, mult, boomerang, shuriken);
532     if (!check_can_throw(creature_ptr, it_ptr))
533         return FALSE;
534
535     calc_throw_range(creature_ptr, it_ptr);
536     if (!calc_throw_grid(creature_ptr, it_ptr))
537         return FALSE;
538
539     reflect_inventory_by_throw(creature_ptr, it_ptr);
540     if (it_ptr->item >= INVEN_MAIN_HAND) {
541         it_ptr->equiped_item = TRUE;
542         creature_ptr->redraw |= PR_EQUIPPY;
543     }
544
545     set_class_specific_throw_params(creature_ptr, it_ptr);
546     set_racial_chance(creature_ptr, it_ptr);
547     it_ptr->prev_y = it_ptr->y;
548     it_ptr->prev_x = it_ptr->x;
549     exe_throw(creature_ptr, it_ptr);
550     if (it_ptr->hit_body)
551         torch_lost_fuel(it_ptr->q_ptr);
552
553     it_ptr->corruption_possibility = (it_ptr->hit_body ? breakage_chance(creature_ptr, it_ptr->q_ptr, creature_ptr->pclass == CLASS_ARCHER, 0) : 0);
554     display_figurine_throw(creature_ptr, it_ptr);
555     display_potion_throw(creature_ptr, it_ptr);
556     check_boomerang_throw(creature_ptr, it_ptr);
557     process_boomerang_back(creature_ptr, it_ptr);
558     drop_thrown_item(creature_ptr, it_ptr);
559     return TRUE;
560 }