OSDN Git Service

[Refactor] #37353 health_track() を view-mainwindow.c/h に移動。
[hengband/hengband.git] / src / shoot.c
1 #include "angband.h"
2 #include "monster.h"
3 #include "monster-status.h"
4 #include "monster-spell.h"
5 #include "artifact.h"
6 #include "avatar.h"
7 #include "player-status.h"
8 #include "object-hook.h"
9 #include "floor.h"
10 #include "grid.h"
11 #include "spells.h"
12 #include "object-flavor.h"
13
14 #include "shoot.h"
15 #include "snipe.h"
16 #include "view-mainwindow.h"
17
18 /*!
19  * @brief 矢弾を射撃した際のスレイ倍率をかけた結果を返す /
20  * Determines the odds of an object breaking when thrown at a monster
21  * @param o_ptr 矢弾のオブジェクト構造体参照ポインタ
22  * @param tdam 計算途中のダメージ量
23  * @param m_ptr 目標モンスターの構造体参照ポインタ
24  * @return スレイ倍率をかけたダメージ量
25  */
26 static MULTIPLY tot_dam_aux_shot(object_type *o_ptr, HIT_POINT tdam, monster_type *m_ptr, SPELL_IDX snipe_type)
27 {
28         MULTIPLY mult = 10;
29
30         monster_race *r_ptr = &r_info[m_ptr->r_idx];
31
32         BIT_FLAGS flgs[TR_FLAG_SIZE];
33         object_flags(o_ptr, flgs);
34
35         /* Some "weapons" and "ammo" do extra damage */
36         switch (o_ptr->tval)
37         {
38         case TV_SHOT:
39         case TV_ARROW:
40         case TV_BOLT:
41         {
42                 if ((have_flag(flgs, TR_SLAY_ANIMAL)) && (r_ptr->flags3 & RF3_ANIMAL))
43                 {
44                         if (is_original_ap_and_seen(m_ptr))
45                         {
46                                 r_ptr->r_flags3 |= RF3_ANIMAL;
47                         }
48                         if (mult < 17) mult = 17;
49                 }
50
51                 if ((have_flag(flgs, TR_KILL_ANIMAL)) && (r_ptr->flags3 & RF3_ANIMAL))
52                 {
53                         if (is_original_ap_and_seen(m_ptr))
54                         {
55                                 r_ptr->r_flags3 |= RF3_ANIMAL;
56                         }
57                         if (mult < 27) mult = 27;
58                 }
59
60                 if ((have_flag(flgs, TR_SLAY_EVIL)) && (r_ptr->flags3 & RF3_EVIL))
61                 {
62                         if (is_original_ap_and_seen(m_ptr))
63                         {
64                                 r_ptr->r_flags3 |= RF3_EVIL;
65                         }
66                         if (mult < 15) mult = 15;
67                 }
68
69                 if ((have_flag(flgs, TR_KILL_EVIL)) && (r_ptr->flags3 & RF3_EVIL))
70                 {
71                         if (is_original_ap_and_seen(m_ptr))
72                         {
73                                 r_ptr->r_flags3 |= RF3_EVIL;
74                         }
75                         if (mult < 25) mult = 25;
76                 }
77
78                 if ((have_flag(flgs, TR_SLAY_HUMAN)) && (r_ptr->flags2 & RF2_HUMAN))
79                 {
80                         if (is_original_ap_and_seen(m_ptr))
81                         {
82                                 r_ptr->r_flags2 |= RF2_HUMAN;
83                         }
84                         if (mult < 17) mult = 17;
85                 }
86
87                 if ((have_flag(flgs, TR_KILL_HUMAN)) && (r_ptr->flags2 & RF2_HUMAN))
88                 {
89                         if (is_original_ap_and_seen(m_ptr))
90                         {
91                                 r_ptr->r_flags2 |= RF2_HUMAN;
92                         }
93                         if (mult < 27) mult = 27;
94                 }
95
96                 if ((have_flag(flgs, TR_SLAY_UNDEAD)) && (r_ptr->flags3 & RF3_UNDEAD))
97                 {
98                         if (is_original_ap_and_seen(m_ptr))
99                         {
100                                 r_ptr->r_flags3 |= RF3_UNDEAD;
101                         }
102                         if (mult < 20) mult = 20;
103                 }
104
105                 if ((have_flag(flgs, TR_KILL_UNDEAD)) && (r_ptr->flags3 & RF3_UNDEAD))
106                 {
107                         if (is_original_ap_and_seen(m_ptr))
108                         {
109                                 r_ptr->r_flags3 |= RF3_UNDEAD;
110                         }
111                         if (mult < 30) mult = 30;
112                 }
113
114                 if ((have_flag(flgs, TR_SLAY_DEMON)) && (r_ptr->flags3 & RF3_DEMON))
115                 {
116                         if (is_original_ap_and_seen(m_ptr))
117                         {
118                                 r_ptr->r_flags3 |= RF3_DEMON;
119                         }
120                         if (mult < 20) mult = 20;
121                 }
122
123                 if ((have_flag(flgs, TR_KILL_DEMON)) && (r_ptr->flags3 & RF3_DEMON))
124                 {
125                         if (is_original_ap_and_seen(m_ptr))
126                         {
127                                 r_ptr->r_flags3 |= RF3_DEMON;
128                         }
129                         if (mult < 30) mult = 30;
130                 }
131
132                 if ((have_flag(flgs, TR_SLAY_ORC)) && (r_ptr->flags3 & RF3_ORC))
133                 {
134                         if (is_original_ap_and_seen(m_ptr))
135                         {
136                                 r_ptr->r_flags3 |= RF3_ORC;
137                         }
138                         if (mult < 20) mult = 20;
139                 }
140
141                 if ((have_flag(flgs, TR_KILL_ORC)) && (r_ptr->flags3 & RF3_ORC))
142                 {
143                         if (is_original_ap_and_seen(m_ptr))
144                         {
145                                 r_ptr->r_flags3 |= RF3_ORC;
146                         }
147                         if (mult < 30) mult = 30;
148                 }
149
150                 if ((have_flag(flgs, TR_SLAY_TROLL)) && (r_ptr->flags3 & RF3_TROLL))
151                 {
152                         if (is_original_ap_and_seen(m_ptr))
153                         {
154                                 r_ptr->r_flags3 |= RF3_TROLL;
155                         }
156
157                         if (mult < 20) mult = 20;
158                 }
159
160                 if ((have_flag(flgs, TR_KILL_TROLL)) && (r_ptr->flags3 & RF3_TROLL))
161                 {
162                         if (is_original_ap_and_seen(m_ptr))
163                         {
164                                 r_ptr->r_flags3 |= RF3_TROLL;
165                         }
166                         if (mult < 30) mult = 30;
167                 }
168
169                 if ((have_flag(flgs, TR_SLAY_GIANT)) && (r_ptr->flags3 & RF3_GIANT))
170                 {
171                         if (is_original_ap_and_seen(m_ptr))
172                         {
173                                 r_ptr->r_flags3 |= RF3_GIANT;
174                         }
175                         if (mult < 20) mult = 20;
176                 }
177
178                 if ((have_flag(flgs, TR_KILL_GIANT)) && (r_ptr->flags3 & RF3_GIANT))
179                 {
180                         if (is_original_ap_and_seen(m_ptr))
181                         {
182                                 r_ptr->r_flags3 |= RF3_GIANT;
183                         }
184                         if (mult < 30) mult = 30;
185                 }
186
187                 if ((have_flag(flgs, TR_SLAY_DRAGON)) && (r_ptr->flags3 & RF3_DRAGON))
188                 {
189                         if (is_original_ap_and_seen(m_ptr))
190                         {
191                                 r_ptr->r_flags3 |= RF3_DRAGON;
192                         }
193                         if (mult < 20) mult = 20;
194                 }
195
196                 if ((have_flag(flgs, TR_KILL_DRAGON)) && (r_ptr->flags3 & RF3_DRAGON))
197                 {
198                         if (is_original_ap_and_seen(m_ptr))
199                         {
200                                 r_ptr->r_flags3 |= RF3_DRAGON;
201                         }
202                         if (mult < 30) mult = 30;
203                         if ((o_ptr->name1 == ART_BARD_ARROW) && (m_ptr->r_idx == MON_SMAUG) &&
204                                 (inventory[INVEN_BOW].name1 == ART_BARD))
205                                 mult *= 5;
206                 }
207
208                 if (have_flag(flgs, TR_BRAND_ACID))
209                 {
210                         /* Notice immunity */
211                         if (r_ptr->flagsr & RFR_EFF_IM_ACID_MASK)
212                         {
213                                 if (is_original_ap_and_seen(m_ptr))
214                                 {
215                                         r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_ACID_MASK);
216                                 }
217                         }
218                         else
219                         {
220                                 if (mult < 17) mult = 17;
221                         }
222                 }
223
224                 if (have_flag(flgs, TR_BRAND_ELEC))
225                 {
226                         /* Notice immunity */
227                         if (r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK)
228                         {
229                                 if (is_original_ap_and_seen(m_ptr))
230                                 {
231                                         r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK);
232                                 }
233                         }
234                         else
235                         {
236                                 if (mult < 17) mult = 17;
237                         }
238                 }
239
240                 if (have_flag(flgs, TR_BRAND_FIRE))
241                 {
242                         /* Notice immunity */
243                         if (r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK)
244                         {
245                                 if (is_original_ap_and_seen(m_ptr))
246                                 {
247                                         r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK);
248                                 }
249                         }
250                         /* Otherwise, take the damage */
251                         else
252                         {
253                                 if (r_ptr->flags3 & RF3_HURT_FIRE)
254                                 {
255                                         if (mult < 25) mult = 25;
256                                         if (is_original_ap_and_seen(m_ptr))
257                                         {
258                                                 r_ptr->r_flags3 |= RF3_HURT_FIRE;
259                                         }
260                                 }
261                                 else if (mult < 17) mult = 17;
262                         }
263                 }
264
265                 if (have_flag(flgs, TR_BRAND_COLD))
266                 {
267                         /* Notice immunity */
268                         if (r_ptr->flagsr & RFR_EFF_IM_COLD_MASK)
269                         {
270                                 if (is_original_ap_and_seen(m_ptr))
271                                 {
272                                         r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_COLD_MASK);
273                                 }
274                         }
275                         /* Otherwise, take the damage */
276                         else
277                         {
278                                 if (r_ptr->flags3 & RF3_HURT_COLD)
279                                 {
280                                         if (mult < 25) mult = 25;
281                                         if (is_original_ap_and_seen(m_ptr))
282                                         {
283                                                 r_ptr->r_flags3 |= RF3_HURT_COLD;
284                                         }
285                                 }
286                                 else if (mult < 17) mult = 17;
287                         }
288                 }
289
290                 if (have_flag(flgs, TR_BRAND_POIS))
291                 {
292                         /* Notice immunity */
293                         if (r_ptr->flagsr & RFR_EFF_IM_POIS_MASK)
294                         {
295                                 if (is_original_ap_and_seen(m_ptr))
296                                 {
297                                         r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_POIS_MASK);
298                                 }
299                         }
300                         /* Otherwise, take the damage */
301                         else
302                         {
303                                 if (mult < 17) mult = 17;
304                         }
305                 }
306
307                 if ((have_flag(flgs, TR_FORCE_WEAPON)) && (p_ptr->csp > (p_ptr->msp / 30)))
308                 {
309                         p_ptr->csp -= (1 + (p_ptr->msp / 30));
310                         p_ptr->redraw |= (PR_MANA);
311                         mult = mult * 5 / 2;
312                 }
313                 break;
314         }
315         }
316
317         /* Sniper */
318         if (snipe_type) mult = tot_dam_aux_snipe(mult, m_ptr, snipe_type);
319
320         /* Return the total damage */
321         return (tdam * mult / 10);
322 }
323
324
325 /*!
326  * @brief 射撃処理実行 /
327  * Fire an object from the pack or floor.
328  * @param item 射撃するオブジェクトの所持ID
329  * @param j_ptr 射撃武器のオブジェクト参照ポインタ
330  * @return なし
331  * @details
332  * <pre>
333  * You may only fire items that "match" your missile launcher.
334  * You must use slings + pebbles/shots, bows + arrows, xbows + bolts.
335  * See "calc_bonuses()" for more calculations and such.
336  * Note that "firing" a missile is MUCH better than "throwing" it.
337  * Note: "unseen" monsters are very hard to hit.
338  * Objects are more likely to break if they "attempt" to hit a monster.
339  * Rangers (with Bows) and Anyone (with "Extra Shots") get extra shots.
340  * The "extra shot" code works by decreasing the amount of energy
341  * required to make each shot, spreading the shots out over time.
342  * Note that when firing missiles, the launcher multiplier is applied
343  * after all the bonuses are added in, making multipliers very useful.
344  * Note that Bows of "Extra Might" get extra range and an extra bonus
345  * for the damage multiplier.
346  * Note that Bows of "Extra Shots" give an extra shot.
347  * </pre>
348  */
349 void exe_fire(INVENTORY_IDX item, object_type *j_ptr, SPELL_IDX snipe_type)
350 {
351         DIRECTION dir;
352         int i;
353         POSITION y, x, ny, nx, ty, tx, prev_y, prev_x;
354         int tdam_base, tdis, thits, tmul;
355         int bonus, chance;
356         int cur_dis, visible;
357         PERCENTAGE j;
358
359         object_type forge;
360         object_type *q_ptr;
361
362         object_type *o_ptr;
363
364         bool hit_body = FALSE;
365
366         GAME_TEXT o_name[MAX_NLEN];
367
368         u16b path_g[512];       /* For calcuration of path length */
369
370         int msec = delay_factor * delay_factor * delay_factor;
371
372         /* STICK TO */
373         bool stick_to = FALSE;
374
375         /* Access the item (if in the pack) */
376         if (item >= 0)
377         {
378                 o_ptr = &inventory[item];
379         }
380         else
381         {
382                 o_ptr = &current_floor_ptr->o_list[0 - item];
383         }
384
385         /* Sniper - Cannot shot a single arrow twice */
386         if ((snipe_type == SP_DOUBLE) && (o_ptr->number < 2)) snipe_type = SP_NONE;
387
388         object_desc(o_name, o_ptr, OD_OMIT_PREFIX);
389
390         /* Use the proper number of shots */
391         thits = p_ptr->num_fire;
392
393         /* Use a base distance */
394         tdis = 10;
395
396         /* Base damage from thrown object plus launcher bonus */
397         tdam_base = damroll(o_ptr->dd, o_ptr->ds) + o_ptr->to_d + j_ptr->to_d;
398
399         /* Actually "fire" the object */
400         bonus = (p_ptr->to_h_b + o_ptr->to_h + j_ptr->to_h);
401         if ((j_ptr->sval == SV_LIGHT_XBOW) || (j_ptr->sval == SV_HEAVY_XBOW))
402                 chance = (p_ptr->skill_thb + (p_ptr->weapon_exp[0][j_ptr->sval] / 400 + bonus) * BTH_PLUS_ADJ);
403         else
404                 chance = (p_ptr->skill_thb + ((p_ptr->weapon_exp[0][j_ptr->sval] - (WEAPON_EXP_MASTER / 2)) / 200 + bonus) * BTH_PLUS_ADJ);
405
406         p_ptr->energy_use = bow_energy(j_ptr->sval);
407         tmul = bow_tmul(j_ptr->sval);
408
409         /* Get extra "power" from "extra might" */
410         if (p_ptr->xtra_might) tmul++;
411
412         tmul = tmul * (100 + (int)(adj_str_td[p_ptr->stat_ind[A_STR]]) - 128);
413
414         /* Boost the damage */
415         tdam_base *= tmul;
416         tdam_base /= 100;
417
418         /* Base range */
419         tdis = 13 + tmul / 80;
420         if ((j_ptr->sval == SV_LIGHT_XBOW) || (j_ptr->sval == SV_HEAVY_XBOW))
421         {
422                 if (p_ptr->concent)
423                         tdis -= (5 - (p_ptr->concent + 1) / 2);
424                 else
425                         tdis -= 5;
426         }
427
428         project_length = tdis + 1;
429
430         /* Get a direction (or cancel) */
431         if (!get_aim_dir(&dir))
432         {
433                 free_turn(p_ptr);
434
435                 if (snipe_type == SP_AWAY) snipe_type = SP_NONE;
436
437                 /* need not to reset project_length (already did)*/
438
439                 return;
440         }
441
442         /* Predict the "target" location */
443         tx = p_ptr->x + 99 * ddx[dir];
444         ty = p_ptr->y + 99 * ddy[dir];
445
446         /* Check for "target request" */
447         if ((dir == 5) && target_okay())
448         {
449                 tx = target_col;
450                 ty = target_row;
451         }
452
453         /* Get projection path length */
454         tdis = project_path(path_g, project_length, p_ptr->y, p_ptr->x, ty, tx, PROJECT_PATH | PROJECT_THRU) - 1;
455
456         project_length = 0; /* reset to default */
457
458         /* Don't shoot at my feet */
459         if (tx == p_ptr->x && ty == p_ptr->y)
460         {
461                 free_turn(p_ptr);
462
463                 /* project_length is already reset to 0 */
464
465                 return;
466         }
467
468
469         /* Take a (partial) current_world_ptr->game_turn */
470         p_ptr->energy_use = (p_ptr->energy_use / thits);
471         is_fired = TRUE;
472
473         /* Sniper - Difficult to shot twice at 1 current_world_ptr->game_turn */
474         if (snipe_type == SP_DOUBLE)  p_ptr->concent = (p_ptr->concent + 1) / 2;
475
476         /* Sniper - Repeat shooting when double shots */
477         for (i = 0; i < ((snipe_type == SP_DOUBLE) ? 2 : 1); i++)
478         {
479
480                 /* Start at the player */
481                 y = p_ptr->y;
482                 x = p_ptr->x;
483                 q_ptr = &forge;
484
485                 /* Obtain a local object */
486                 object_copy(q_ptr, o_ptr);
487
488                 /* Single object */
489                 q_ptr->number = 1;
490
491                 /* Reduce and describe inventory */
492                 if (item >= 0)
493                 {
494                         inven_item_increase(item, -1);
495                         inven_item_describe(item);
496                         inven_item_optimize(item);
497                 }
498
499                 /* Reduce and describe floor item */
500                 else
501                 {
502                         floor_item_increase(0 - item, -1);
503                         floor_item_optimize(0 - item);
504                 }
505
506                 sound(SOUND_SHOOT);
507                 handle_stuff();
508
509                 prev_y = y;
510                 prev_x = x;
511
512                 /* The shot does not hit yet */
513                 hit_body = FALSE;
514
515                 /* Travel until stopped */
516                 for (cur_dis = 0; cur_dis <= tdis; )
517                 {
518                         grid_type *g_ptr;
519
520                         /* Hack -- Stop at the target */
521                         if ((y == ty) && (x == tx)) break;
522
523                         /* Calculate the new location (see "project()") */
524                         ny = y;
525                         nx = x;
526                         mmove2(&ny, &nx, p_ptr->y, p_ptr->x, ty, tx);
527
528                         /* Shatter Arrow */
529                         if (snipe_type == SP_KILL_WALL)
530                         {
531                                 g_ptr = &current_floor_ptr->grid_array[ny][nx];
532
533                                 if (cave_have_flag_grid(g_ptr, FF_HURT_ROCK) && !g_ptr->m_idx)
534                                 {
535                                         if (g_ptr->info & (CAVE_MARK)) msg_print(_("岩が砕け散った。", "Wall rocks were shattered."));
536                                         /* Forget the wall */
537                                         g_ptr->info &= ~(CAVE_MARK);
538                                         p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW | PU_MON_LITE);
539
540                                         /* Destroy the wall */
541                                         cave_alter_feat(ny, nx, FF_HURT_ROCK);
542
543                                         hit_body = TRUE;
544                                         break;
545                                 }
546                         }
547
548                         /* Stopped by walls/doors */
549                         if (!cave_have_flag_bold(ny, nx, FF_PROJECT) && !current_floor_ptr->grid_array[ny][nx].m_idx) break;
550
551                         /* Advance the distance */
552                         cur_dis++;
553
554                         /* Sniper */
555                         if (snipe_type == SP_LITE)
556                         {
557                                 current_floor_ptr->grid_array[ny][nx].info |= (CAVE_GLOW);
558                                 note_spot(ny, nx);
559                                 lite_spot(ny, nx);
560                         }
561
562                         /* The player can see the (on screen) missile */
563                         if (panel_contains(ny, nx) && player_can_see_bold(ny, nx))
564                         {
565                                 char c = object_char(q_ptr);
566                                 byte a = object_attr(q_ptr);
567
568                                 /* Draw, Hilite, Fresh, Pause, Erase */
569                                 print_rel(c, a, ny, nx);
570                                 move_cursor_relative(ny, nx);
571                                 Term_fresh();
572                                 Term_xtra(TERM_XTRA_DELAY, msec);
573                                 lite_spot(ny, nx);
574                                 Term_fresh();
575                         }
576
577                         /* The player cannot see the missile */
578                         else
579                         {
580                                 /* Pause anyway, for consistancy */
581                                 Term_xtra(TERM_XTRA_DELAY, msec);
582                         }
583
584                         /* Sniper */
585                         if (snipe_type == SP_KILL_TRAP)
586                         {
587                                 project(0, 0, ny, nx, 0, GF_KILL_TRAP,
588                                         (PROJECT_JUMP | PROJECT_HIDE | PROJECT_GRID | PROJECT_ITEM), -1);
589                         }
590
591                         /* Sniper */
592                         if (snipe_type == SP_EVILNESS)
593                         {
594                                 current_floor_ptr->grid_array[ny][nx].info &= ~(CAVE_GLOW | CAVE_MARK);
595                                 note_spot(ny, nx);
596                                 lite_spot(ny, nx);
597                         }
598
599                         prev_y = y;
600                         prev_x = x;
601
602                         /* Save the new location */
603                         x = nx;
604                         y = ny;
605
606                         /* Monster here, Try to hit it */
607                         if (current_floor_ptr->grid_array[y][x].m_idx)
608                         {
609                                 grid_type *c_mon_ptr = &current_floor_ptr->grid_array[y][x];
610
611                                 monster_type *m_ptr = &current_floor_ptr->m_list[c_mon_ptr->m_idx];
612                                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
613
614                                 /* Check the visibility */
615                                 visible = m_ptr->ml;
616
617                                 /* Note the collision */
618                                 hit_body = TRUE;
619
620                                 if (MON_CSLEEP(m_ptr))
621                                 {
622                                         if (!(r_ptr->flags3 & RF3_EVIL) || one_in_(5)) chg_virtue(V_COMPASSION, -1);
623                                         if (!(r_ptr->flags3 & RF3_EVIL) || one_in_(5)) chg_virtue(V_HONOUR, -1);
624                                 }
625
626                                 if ((r_ptr->level + 10) > p_ptr->lev)
627                                 {
628                                         int now_exp = p_ptr->weapon_exp[0][j_ptr->sval];
629                                         if (now_exp < s_info[p_ptr->pclass].w_max[0][j_ptr->sval])
630                                         {
631                                                 SUB_EXP amount = 0;
632                                                 if (now_exp < WEAPON_EXP_BEGINNER) amount = 80;
633                                                 else if (now_exp < WEAPON_EXP_SKILLED) amount = 25;
634                                                 else if ((now_exp < WEAPON_EXP_EXPERT) && (p_ptr->lev > 19)) amount = 10;
635                                                 else if (p_ptr->lev > 34) amount = 2;
636                                                 p_ptr->weapon_exp[0][j_ptr->sval] += amount;
637                                                 p_ptr->update |= (PU_BONUS);
638                                         }
639                                 }
640
641                                 if (p_ptr->riding)
642                                 {
643                                         if ((p_ptr->skill_exp[GINOU_RIDING] < s_info[p_ptr->pclass].s_max[GINOU_RIDING])
644                                                 && ((p_ptr->skill_exp[GINOU_RIDING] - (RIDING_EXP_BEGINNER * 2)) / 200 < r_info[current_floor_ptr->m_list[p_ptr->riding].r_idx].level)
645                                                 && one_in_(2))
646                                         {
647                                                 p_ptr->skill_exp[GINOU_RIDING] += 1;
648                                                 p_ptr->update |= (PU_BONUS);
649                                         }
650                                 }
651
652                                 /* Did we hit it (penalize range) */
653                                 if (test_hit_fire(chance - cur_dis, m_ptr, m_ptr->ml, o_name))
654                                 {
655                                         bool fear = FALSE;
656                                         int tdam = tdam_base;
657
658                                         /* Get extra damage from concentration */
659                                         if (p_ptr->concent) tdam = boost_concentration_damage(tdam);
660
661                                         /* Handle unseen monster */
662                                         if (!visible)
663                                         {
664                                                 /* Invisible monster */
665                                                 msg_format(_("%sが敵を捕捉した。", "The %s finds a mark."), o_name);
666                                         }
667
668                                         /* Handle visible monster */
669                                         else
670                                         {
671                                                 GAME_TEXT m_name[MAX_NLEN];
672
673                                                 /* Get "the monster" or "it" */
674                                                 monster_desc(m_name, m_ptr, 0);
675
676                                                 msg_format(_("%sが%sに命中した。", "The %s hits %s."), o_name, m_name);
677
678                                                 if (m_ptr->ml)
679                                                 {
680                                                         if (!p_ptr->image) monster_race_track(m_ptr->ap_r_idx);
681                                                         health_track(c_mon_ptr->m_idx);
682                                                 }
683                                         }
684
685                                         if (snipe_type == SP_NEEDLE)
686                                         {
687                                                 if ((randint1(randint1(r_ptr->level / (3 + p_ptr->concent)) + (8 - p_ptr->concent)) == 1)
688                                                         && !(r_ptr->flags1 & RF1_UNIQUE) && !(r_ptr->flags7 & RF7_UNIQUE2))
689                                                 {
690                                                         GAME_TEXT m_name[MAX_NLEN];
691
692                                                         /* Get "the monster" or "it" */
693                                                         monster_desc(m_name, m_ptr, 0);
694
695                                                         tdam = m_ptr->hp + 1;
696                                                         msg_format(_("%sの急所に突き刺さった!", "Your shot sticked on a fatal spot of %s!"), m_name);
697                                                 }
698                                                 else tdam = 1;
699                                         }
700                                         else
701                                         {
702                                                 /* Apply special damage */
703                                                 tdam = tot_dam_aux_shot(q_ptr, tdam, m_ptr, snipe_type);
704                                                 tdam = critical_shot(q_ptr->weight, q_ptr->to_h, j_ptr->to_h, tdam);
705
706                                                 /* No negative damage */
707                                                 if (tdam < 0) tdam = 0;
708
709                                                 /* Modify the damage */
710                                                 tdam = mon_damage_mod(m_ptr, tdam, FALSE);
711                                         }
712
713                                         msg_format_wizard(CHEAT_MONSTER,
714                                                 _("%dのダメージを与えた。(残りHP %d/%d(%d))", "You do %d damage. (left HP %d/%d(%d))"),
715                                                 tdam, m_ptr->hp - tdam, m_ptr->maxhp, m_ptr->max_maxhp);
716
717                                         /* Sniper */
718                                         if (snipe_type == SP_EXPLODE)
719                                         {
720                                                 u16b flg = (PROJECT_STOP | PROJECT_JUMP | PROJECT_KILL | PROJECT_GRID);
721
722                                                 sound(SOUND_EXPLODE); /* No explode sound - use breath fire instead */
723                                                 project(0, ((p_ptr->concent + 1) / 2 + 1), ny, nx, tdam, GF_MISSILE, flg, -1);
724                                                 break;
725                                         }
726
727                                         /* Sniper */
728                                         if (snipe_type == SP_HOLYNESS)
729                                         {
730                                                 current_floor_ptr->grid_array[ny][nx].info |= (CAVE_GLOW);
731                                                 note_spot(ny, nx);
732                                                 lite_spot(ny, nx);
733                                         }
734
735                                         /* Hit the monster, check for death */
736                                         if (mon_take_hit(c_mon_ptr->m_idx, tdam, &fear, extract_note_dies(real_r_idx(m_ptr))))
737                                         {
738                                                 /* Dead monster */
739                                         }
740
741                                         /* No death */
742                                         else
743                                         {
744                                                 /* STICK TO */
745                                                 if (object_is_fixed_artifact(q_ptr) &&
746                                                         (p_ptr->pclass != CLASS_SNIPER || p_ptr->concent == 0))
747                                                 {
748                                                         GAME_TEXT m_name[MAX_NLEN];
749
750                                                         monster_desc(m_name, m_ptr, 0);
751
752                                                         stick_to = TRUE;
753                                                         msg_format(_("%sは%sに突き刺さった!", "%^s have stuck into %s!"), o_name, m_name);
754                                                 }
755
756                                                 message_pain(c_mon_ptr->m_idx, tdam);
757
758                                                 /* Anger the monster */
759                                                 if (tdam > 0) anger_monster(m_ptr);
760
761                                                 if (fear && m_ptr->ml)
762                                                 {
763                                                         GAME_TEXT m_name[MAX_NLEN];
764                                                         sound(SOUND_FLEE);
765                                                         monster_desc(m_name, m_ptr, 0);
766                                                         msg_format(_("%^sは恐怖して逃げ出した!", "%^s flees in terror!"), m_name);
767                                                 }
768
769                                                 set_target(m_ptr, p_ptr->y, p_ptr->x);
770
771                                                 /* Sniper */
772                                                 if (snipe_type == SP_RUSH)
773                                                 {
774                                                         int n = randint1(5) + 3;
775                                                         MONSTER_IDX m_idx = c_mon_ptr->m_idx;
776
777                                                         for (; cur_dis <= tdis; )
778                                                         {
779                                                                 POSITION ox = nx;
780                                                                 POSITION oy = ny;
781
782                                                                 if (!n) break;
783
784                                                                 /* Calculate the new location (see "project()") */
785                                                                 mmove2(&ny, &nx, p_ptr->y, p_ptr->x, ty, tx);
786
787                                                                 /* Stopped by wilderness boundary */
788                                                                 if (!in_bounds2(ny, nx)) break;
789
790                                                                 /* Stopped by walls/doors */
791                                                                 if (!player_can_enter(current_floor_ptr->grid_array[ny][nx].feat, 0)) break;
792
793                                                                 /* Stopped by monsters */
794                                                                 if (!cave_empty_bold(ny, nx)) break;
795
796                                                                 current_floor_ptr->grid_array[ny][nx].m_idx = m_idx;
797                                                                 current_floor_ptr->grid_array[oy][ox].m_idx = 0;
798
799                                                                 m_ptr->fx = nx;
800                                                                 m_ptr->fy = ny;
801
802                                                                 update_monster(c_mon_ptr->m_idx, TRUE);
803
804                                                                 lite_spot(ny, nx);
805                                                                 lite_spot(oy, ox);
806
807                                                                 Term_fresh();
808                                                                 Term_xtra(TERM_XTRA_DELAY, msec);
809
810                                                                 x = nx;
811                                                                 y = ny;
812                                                                 cur_dis++;
813                                                                 n--;
814                                                         }
815                                                 }
816                                         }
817                                 }
818
819                                 /* Sniper */
820                                 if (snipe_type == SP_PIERCE)
821                                 {
822                                         if (p_ptr->concent < 1) break;
823                                         p_ptr->concent--;
824                                         continue;
825                                 }
826
827                                 /* Stop looking */
828                                 break;
829                         }
830                 }
831
832                 /* Chance of breakage (during attacks) */
833                 j = (hit_body ? breakage_chance(q_ptr, snipe_type) : 0);
834
835                 if (stick_to)
836                 {
837                         MONSTER_IDX m_idx = current_floor_ptr->grid_array[y][x].m_idx;
838                         monster_type *m_ptr = &current_floor_ptr->m_list[m_idx];
839                         OBJECT_IDX o_idx = o_pop();
840
841                         if (!o_idx)
842                         {
843                                 msg_format(_("%sはどこかへ行った。", "The %s have gone to somewhere."), o_name);
844                                 if (object_is_fixed_artifact(q_ptr))
845                                 {
846                                         a_info[j_ptr->name1].cur_num = 0;
847                                 }
848                                 return;
849                         }
850
851                         o_ptr = &current_floor_ptr->o_list[o_idx];
852                         object_copy(o_ptr, q_ptr);
853
854                         /* Forget mark */
855                         o_ptr->marked &= OM_TOUCHED;
856
857                         /* Forget location */
858                         o_ptr->iy = o_ptr->ix = 0;
859
860                         /* Memorize monster */
861                         o_ptr->held_m_idx = m_idx;
862
863                         /* Build a stack */
864                         o_ptr->next_o_idx = m_ptr->hold_o_idx;
865
866                         /* Carry object */
867                         m_ptr->hold_o_idx = o_idx;
868                 }
869                 else if (cave_have_flag_bold(y, x, FF_PROJECT))
870                 {
871                         /* Drop (or break) near that location */
872                         (void)drop_near(q_ptr, j, y, x);
873                 }
874                 else
875                 {
876                         /* Drop (or break) near that location */
877                         (void)drop_near(q_ptr, j, prev_y, prev_x);
878                 }
879
880                 /* Sniper - Repeat shooting when double shots */
881         }
882
883         /* Sniper - Loose his/her concentration after any shot */
884         if (p_ptr->concent) reset_concentration(FALSE);
885 }
886
887
888 /*!
889 * @brief プレイヤーからモンスターへの射撃命中判定 /
890 * Determine if the player "hits" a monster (normal combat).
891 * @param chance 基本命中値
892 * @param m_ptr モンスターの構造体参照ポインタ
893 * @param vis 目標を視界に捕らえているならばTRUEを指定
894 * @param o_name メッセージ表示時のモンスター名
895 * @return 命中と判定された場合TRUEを返す
896 * @note Always miss 5%, always hit 5%, otherwise random.
897 */
898 bool test_hit_fire(int chance, monster_type *m_ptr, int vis, char* o_name)
899 {
900         int k;
901         ARMOUR_CLASS ac;
902         monster_race *r_ptr = &r_info[m_ptr->r_idx];
903
904         /* Percentile dice */
905         k = randint1(100);
906
907         /* Snipers with high-concentration reduce instant miss percentage.*/
908         k += p_ptr->concent;
909
910         /* Hack -- Instant miss or hit */
911         if (k <= 5) return (FALSE);
912         if (k > 95) return (TRUE);
913
914         if (p_ptr->pseikaku == SEIKAKU_NAMAKE)
915                 if (one_in_(20)) return (FALSE);
916
917         /* Never hit */
918         if (chance <= 0) return (FALSE);
919
920         ac = r_ptr->ac;
921         if (p_ptr->concent)
922         {
923                 ac *= (8 - p_ptr->concent);
924                 ac /= 8;
925         }
926
927         if (m_ptr->r_idx == MON_GOEMON && !MON_CSLEEP(m_ptr)) ac *= 3;
928
929         /* Invisible monsters are harder to hit */
930         if (!vis) chance = (chance + 1) / 2;
931
932         /* Power competes against armor */
933         if (randint0(chance) < (ac * 3 / 4))
934         {
935                 if (m_ptr->r_idx == MON_GOEMON && !MON_CSLEEP(m_ptr))
936                 {
937                         GAME_TEXT m_name[MAX_NLEN];
938
939                         /* Extract monster name */
940                         monster_desc(m_name, m_ptr, 0);
941                         msg_format(_("%sは%sを斬り捨てた!", "%s cuts down %s!"), m_name, o_name);
942                 }
943                 return (FALSE);
944         }
945
946         /* Assume hit */
947         return (TRUE);
948 }
949
950
951
952
953 /*!
954 * @brief プレイヤーからモンスターへの射撃クリティカル判定 /
955 * Critical hits (from objects thrown by player) Factor in item weight, total plusses, and player level.
956 * @param weight 矢弾の重量
957 * @param plus_ammo 矢弾の命中修正
958 * @param plus_bow 弓の命中修正
959 * @param dam 現在算出中のダメージ値
960 * @return クリティカル修正が入ったダメージ値
961 */
962 HIT_POINT critical_shot(WEIGHT weight, int plus_ammo, int plus_bow, HIT_POINT dam)
963 {
964         int i, k;
965         object_type *j_ptr = &inventory[INVEN_BOW];
966
967         /* Extract "shot" power */
968         i = p_ptr->to_h_b + plus_ammo;
969
970         if (p_ptr->tval_ammo == TV_BOLT)
971                 i = (p_ptr->skill_thb + (p_ptr->weapon_exp[0][j_ptr->sval] / 400 + i) * BTH_PLUS_ADJ);
972         else
973                 i = (p_ptr->skill_thb + ((p_ptr->weapon_exp[0][j_ptr->sval] - (WEAPON_EXP_MASTER / 2)) / 200 + i) * BTH_PLUS_ADJ);
974
975
976         /* Snipers can shot more critically with crossbows */
977         if (p_ptr->concent) i += ((i * p_ptr->concent) / 5);
978         if ((p_ptr->pclass == CLASS_SNIPER) && (p_ptr->tval_ammo == TV_BOLT)) i *= 2;
979
980         /* Good bow makes more critical */
981         i += plus_bow * 8 * (p_ptr->concent ? p_ptr->concent + 5 : 5);
982
983         /* Critical hit */
984         if (randint1(10000) <= i)
985         {
986                 k = weight * randint1(500);
987
988                 if (k < 900)
989                 {
990                         msg_print(_("手ごたえがあった!", "It was a good hit!"));
991                         dam += (dam / 2);
992                 }
993                 else if (k < 1350)
994                 {
995                         msg_print(_("かなりの手ごたえがあった!", "It was a great hit!"));
996                         dam *= 2;
997                 }
998                 else
999                 {
1000                         msg_print(_("会心の一撃だ!", "It was a superb hit!"));
1001                         dam *= 3;
1002                 }
1003         }
1004
1005         return (dam);
1006 }
1007
1008
1009
1010
1011 /*!
1012  * @brief 射撃武器の攻撃に必要な基本消費エネルギーを返す/Return bow energy
1013  * @param sval 射撃武器のアイテム副分類ID
1014  * @return 消費する基本エネルギー
1015  */
1016 ENERGY bow_energy(OBJECT_SUBTYPE_VALUE sval)
1017 {
1018         ENERGY energy = 10000;
1019
1020         /* Analyze the launcher */
1021         switch (sval)
1022         {
1023                 /* Sling and ammo */
1024         case SV_SLING:
1025         {
1026                 energy = 8000;
1027                 break;
1028         }
1029
1030         /* Short Bow and Arrow */
1031         case SV_SHORT_BOW:
1032         {
1033                 energy = 10000;
1034                 break;
1035         }
1036
1037         /* Long Bow and Arrow */
1038         case SV_LONG_BOW:
1039         {
1040                 energy = 10000;
1041                 break;
1042         }
1043
1044         /* Bow of irresponsiblity and Arrow */
1045         case SV_NAMAKE_BOW:
1046         {
1047                 energy = 7777;
1048                 break;
1049         }
1050
1051         /* Light Crossbow and Bolt */
1052         case SV_LIGHT_XBOW:
1053         {
1054                 energy = 12000;
1055                 break;
1056         }
1057
1058         /* Heavy Crossbow and Bolt */
1059         case SV_HEAVY_XBOW:
1060         {
1061                 energy = 13333;
1062                 break;
1063         }
1064         }
1065
1066         return (energy);
1067 }
1068
1069
1070 /*
1071  * Return bow tmul
1072  */
1073 int bow_tmul(OBJECT_SUBTYPE_VALUE sval)
1074 {
1075         int tmul = 0;
1076
1077         /* Analyze the launcher */
1078         switch (sval)
1079         {
1080                 /* Sling and ammo */
1081         case SV_SLING:
1082         {
1083                 tmul = 2;
1084                 break;
1085         }
1086
1087         /* Short Bow and Arrow */
1088         case SV_SHORT_BOW:
1089         {
1090                 tmul = 2;
1091                 break;
1092         }
1093
1094         /* Long Bow and Arrow */
1095         case SV_LONG_BOW:
1096         {
1097                 tmul = 3;
1098                 break;
1099         }
1100
1101         /* Bow of irresponsiblity and Arrow */
1102         case SV_NAMAKE_BOW:
1103         {
1104                 tmul = 3;
1105                 break;
1106         }
1107
1108         /* Light Crossbow and Bolt */
1109         case SV_LIGHT_XBOW:
1110         {
1111                 tmul = 3;
1112                 break;
1113         }
1114
1115         /* Heavy Crossbow and Bolt */
1116         case SV_HEAVY_XBOW:
1117         {
1118                 tmul = 4;
1119                 break;
1120         }
1121         }
1122
1123         return (tmul);
1124 }
1125
1126