Changeset 400

Show
Ignore:
Timestamp:
07/28/07 17:05:56 (1 year ago)
Author:
takkaria
Message:

Move player attack stuff out to attack.c. (part of #214)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/Makefile.src

    r399 r400  
    1919 
    2020ANGFILES = \ 
     21        attack.o \ 
    2122        birth.o \ 
    2223        cave.o \ 
  • trunk/src/cmd1.c

    r399 r400  
    1313 
    1414 
    15 /* 
    16  * Determine if the player "hits" a monster. 
    17  * 
    18  * Note -- Always miss 5%, always hit 5%, otherwise random. 
    19  */ 
    20 bool test_hit(int chance, int ac, int vis) 
    21 { 
    22         int k; 
    23  
    24         /* Percentile dice */ 
    25         k = rand_int(100); 
    26  
    27         /* Hack -- Instant miss or hit */ 
    28         if (k < 10) return (k < 5); 
    29  
    30         /* Penalize invisible targets */ 
    31         if (!vis) chance = chance / 2; 
    32  
    33         /* Power competes against armor */ 
    34         if ((chance > 0) && (rand_int(chance) >= (ac * 3 / 4))) return (TRUE); 
    35  
    36         /* Assume miss */ 
    37         return (FALSE); 
    38 } 
    39  
    40  
    41  
    42 /* 
    43  * Critical hits (from objects thrown by player) 
    44  * Factor in item weight, total plusses, and player level. 
    45  */ 
    46 int critical_shot(int weight, int plus, int dam) 
    47 { 
    48         int i, k; 
    49  
    50         /* Extract "shot" power */ 
    51         i = (weight + ((p_ptr->to_h + plus) * 4) + (p_ptr->lev * 2)); 
    52  
    53         /* Critical hit */ 
    54         if (randint(5000) <= i) 
    55         { 
    56                 k = weight + randint(500); 
    57  
    58                 if (k < 500) 
    59                 { 
    60                         msg_print("It was a good hit!"); 
    61                         dam = 2 * dam + 5; 
    62                 } 
    63                 else if (k < 1000) 
    64                 { 
    65                         msg_print("It was a great hit!"); 
    66                         dam = 2 * dam + 10; 
    67                 } 
    68                 else 
    69                 { 
    70                         msg_print("It was a superb hit!"); 
    71                         dam = 3 * dam + 15; 
    72                 } 
    73         } 
    74  
    75         return (dam); 
    76 } 
    77  
    78  
    79  
    80 /* 
    81  * Critical hits (by player) 
    82  * 
    83  * Factor in weapon weight, total plusses, player level. 
    84  */ 
    85 int critical_norm(int weight, int plus, int dam) 
    86 { 
    87         int i, k; 
    88  
    89         /* Extract "blow" power */ 
    90         i = (weight + ((p_ptr->to_h + plus) * 5) + (p_ptr->lev * 3)); 
    91  
    92         /* Chance */ 
    93         if (randint(5000) <= i) 
    94         { 
    95                 k = weight + randint(650); 
    96  
    97                 if (k < 400) 
    98                 { 
    99                         sound(MSG_HIT_GOOD); 
    100                         msg_print("It was a good hit!"); 
    101                         dam = 2 * dam + 5; 
    102                 } 
    103                 else if (k < 700) 
    104                 { 
    105                         sound(MSG_HIT_GREAT); 
    106                         msg_print("It was a great hit!"); 
    107                         dam = 2 * dam + 10; 
    108                 } 
    109                 else if (k < 900) 
    110                 { 
    111                         sound(MSG_HIT_SUPERB); 
    112                         msg_print("It was a superb hit!"); 
    113                         dam = 3 * dam + 15; 
    114                 } 
    115                 else if (k < 1300) 
    116                 { 
    117                         sound(MSG_HIT_HI_GREAT); 
    118                         msg_print("It was a *GREAT* hit!"); 
    119                         dam = 3 * dam + 20; 
    120                 } 
    121                 else 
    122                 { 
    123                         sound(MSG_HIT_HI_SUPERB); 
    124                         msg_print("It was a *SUPERB* hit!"); 
    125                         dam = ((7 * dam) / 2) + 25; 
    126                 } 
    127         } 
    128         else  
    129         { 
    130                 sound(MSG_HIT); 
    131         } 
    132  
    133         return (dam); 
    134 } 
    135  
    136  
    137  
    138 /* 
    139  * Extract the "total damage" from a given object hitting a given monster. 
    140  * 
    141  * Note that "flasks of oil" do NOT do fire damage, although they 
    142  * certainly could be made to do so.  XXX XXX 
    143  * 
    144  * Note that most brands and slays are x3, except Slay Animal (x2), 
    145  * Slay Evil (x2), and Kill dragon (x5). 
    146  */ 
    147 int tot_dam_aux(const object_type *o_ptr, int tdam, const monster_type *m_ptr) 
    148 { 
    149         int mult = 1; 
    150  
    151         monster_race *r_ptr = &r_info[m_ptr->r_idx]; 
    152         monster_lore *l_ptr = &l_list[m_ptr->r_idx]; 
    153  
    154         u32b f1, f2, f3; 
    155  
    156         /* Extract the flags */ 
    157         object_flags(o_ptr, &f1, &f2, &f3); 
    158  
    159         /* Some "weapons" and "ammo" do extra damage */ 
    160         switch (o_ptr->tval) 
    161         { 
    162                 case TV_SHOT: 
    163                 case TV_ARROW: 
    164                 case TV_BOLT: 
    165                 case TV_HAFTED: 
    166                 case TV_POLEARM: 
    167                 case TV_SWORD: 
    168                 case TV_DIGGING: 
    169                 { 
    170                         /* Slay Animal */ 
    171                         if ((f1 & (TR1_SLAY_ANIMAL)) && 
    172                             (r_ptr->flags3 & (RF3_ANIMAL))) 
    173                         { 
    174                                 if (m_ptr->ml) 
    175                                 { 
    176                                         l_ptr->flags3 |= (RF3_ANIMAL); 
    177                                 } 
    178  
    179                                 if (mult < 2) mult = 2; 
    180                         } 
    181  
    182                         /* Slay Evil */ 
    183                         if ((f1 & (TR1_SLAY_EVIL)) && 
    184                             (r_ptr->flags3 & (RF3_EVIL))) 
    185                         { 
    186                                 if (m_ptr->ml) 
    187                                 { 
    188                                         l_ptr->flags3 |= (RF3_EVIL); 
    189                                 } 
    190  
    191                                 if (mult < 2) mult = 2; 
    192                         } 
    193  
    194                         /* Slay Undead */ 
    195                         if ((f1 & (TR1_SLAY_UNDEAD)) && 
    196                             (r_ptr->flags3 & (RF3_UNDEAD))) 
    197                         { 
    198                                 if (m_ptr->ml) 
    199                                 { 
    200                                         l_ptr->flags3 |= (RF3_UNDEAD); 
    201                                 } 
    202  
    203                                 if (mult < 3) mult = 3; 
    204                         } 
    205  
    206                         /* Slay Demon */ 
    207                         if ((f1 & (TR1_SLAY_DEMON)) && 
    208                             (r_ptr->flags3 & (RF3_DEMON))) 
    209                         { 
    210                                 if (m_ptr->ml) 
    211                                 { 
    212                                         l_ptr->flags3 |= (RF3_DEMON); 
    213                                 } 
    214  
    215                                 if (mult < 3) mult = 3; 
    216                         } 
    217  
    218                         /* Slay Orc */ 
    219                         if ((f1 & (TR1_SLAY_ORC)) && 
    220                             (r_ptr->flags3 & (RF3_ORC))) 
    221                         { 
    222                                 if (m_ptr->ml) 
    223                                 { 
    224                                         l_ptr->flags3 |= (RF3_ORC); 
    225                                 } 
    226  
    227                                 if (mult < 3) mult = 3; 
    228                         } 
    229  
    230                         /* Slay Troll */ 
    231                         if ((f1 & (TR1_SLAY_TROLL)) && 
    232                             (r_ptr->flags3 & (RF3_TROLL))) 
    233                         { 
    234                                 if (m_ptr->ml) 
    235                                 { 
    236                                         l_ptr->flags3 |= (RF3_TROLL); 
    237                                 } 
    238  
    239                                 if (mult < 3) mult = 3; 
    240                         } 
    241  
    242                         /* Slay Giant */ 
    243                         if ((f1 & (TR1_SLAY_GIANT)) && 
    244                             (r_ptr->flags3 & (RF3_GIANT))) 
    245                         { 
    246                                 if (m_ptr->ml) 
    247                                 { 
    248                                         l_ptr->flags3 |= (RF3_GIANT); 
    249                                 } 
    250  
    251                                 if (mult < 3) mult = 3; 
    252                         } 
    253  
    254                         /* Slay Dragon */ 
    255                         if ((f1 & (TR1_SLAY_DRAGON)) && 
    256                             (r_ptr->flags3 & (RF3_DRAGON))) 
    257                         { 
    258                                 if (m_ptr->ml) 
    259                                 { 
    260                                         l_ptr->flags3 |= (RF3_DRAGON); 
    261                                 } 
    262  
    263                                 if (mult < 3) mult = 3; 
    264                         } 
    265  
    266                         /* Execute Dragon */ 
    267                         if ((f1 & (TR1_KILL_DRAGON)) && 
    268                             (r_ptr->flags3 & (RF3_DRAGON))) 
    269                         { 
    270                                 if (m_ptr->ml) 
    271                                 { 
    272                                         l_ptr->flags3 |= (RF3_DRAGON); 
    273                                 } 
    274  
    275                                 if (mult < 5) mult = 5; 
    276                         } 
    277  
    278                         /* Execute demon */ 
    279                         if ((f1 & (TR1_KILL_DEMON)) && 
    280                             (r_ptr->flags3 & (RF3_DEMON))) 
    281                         { 
    282                                 if (m_ptr->ml) 
    283                                 { 
    284                                         l_ptr->flags3 |= (RF3_DEMON); 
    285                                 } 
    286  
    287                                 if (mult < 5) mult = 5; 
    288                         } 
    289  
    290                         /* Execute undead */ 
    291                         if ((f1 & (TR1_KILL_UNDEAD)) && 
    292                             (r_ptr->flags3 & (RF3_UNDEAD))) 
    293                         { 
    294                                 if (m_ptr->ml) 
    295                                 { 
    296                                         l_ptr->flags3 |= (RF3_UNDEAD); 
    297                                 } 
    298  
    299                                 if (mult < 5) mult = 5; 
    300                         } 
    301  
    302                         /* Brand (Acid) */ 
    303                         if (f1 & (TR1_BRAND_ACID)) 
    304                         { 
    305                                 /* Notice immunity */ 
    306                                 if (r_ptr->flags3 & (RF3_IM_ACID)) 
    307                                 { 
    308                                         if (m_ptr->ml) 
    309                                         { 
    310                                                 l_ptr->flags3 |= (RF3_IM_ACID); 
    311                                         } 
    312                                 } 
    313  
    314                                 /* Otherwise, take the damage */ 
    315                                 else 
    316                                 { 
    317                                         if (mult < 3) mult = 3; 
    318                                 } 
    319                         } 
    320  
    321                         /* Brand (Elec) */ 
    322                         if (f1 & (TR1_BRAND_ELEC)) 
    323                         { 
    324                                 /* Notice immunity */ 
    325                                 if (r_ptr->flags3 & (RF3_IM_ELEC)) 
    326                                 { 
    327                                         if (m_ptr->ml) 
    328                                         { 
    329                                                 l_ptr->flags3 |= (RF3_IM_ELEC); 
    330                                         } 
    331                                 } 
    332  
    333                                 /* Otherwise, take the damage */ 
    334                                 else 
    335                                 { 
    336                                         if (mult < 3) mult = 3; 
    337                                 } 
    338                         } 
    339  
    340                         /* Brand (Fire) */ 
    341                         if (f1 & (TR1_BRAND_FIRE)) 
    342                         { 
    343                                 /* Notice immunity */ 
    344                                 if (r_ptr->flags3 & (RF3_IM_FIRE)) 
    345                                 { 
    346                                         if (m_ptr->ml) 
    347                                         { 
    348                                                 l_ptr->flags3 |= (RF3_IM_FIRE); 
    349                                         } 
    350                                 } 
    351  
    352                                 /* Otherwise, take the damage */ 
    353                                 else 
    354                                 { 
    355                                         if (mult < 3) mult = 3; 
    356                                 } 
    357                         } 
    358  
    359                         /* Brand (Cold) */ 
    360                         if (f1 & (TR1_BRAND_COLD)) 
    361                         { 
    362                                 /* Notice immunity */ 
    363                                 if (r_ptr->flags3 & (RF3_IM_COLD)) 
    364                                 { 
    365                                         if (m_ptr->ml) 
    366                                         { 
    367                                                 l_ptr->flags3 |= (RF3_IM_COLD); 
    368                                         } 
    369                                 } 
    370  
    371                                 /* Otherwise, take the damage */ 
    372                                 else 
    373                                 { 
    374                                         if (mult < 3) mult = 3; 
    375                                 } 
    376                         } 
    377  
    378                         /* Brand (Poison) */ 
    379                         if (f1 & (TR1_BRAND_POIS)) 
    380                         { 
    381                                 /* Notice immunity */ 
    382                                 if (r_ptr->flags3 & (RF3_IM_POIS)) 
    383                                 { 
    384                                         if (m_ptr->ml) 
    385                                         { 
    386                                                 l_ptr->flags3 |= (RF3_IM_POIS); 
    387                                         } 
    388                                 } 
    389  
    390                                 /* Otherwise, take the damage */ 
    391                                 else 
    392                                 { 
    393                                         if (mult < 3) mult = 3; 
    394                                 } 
    395                         } 
    396  
    397                         break; 
    398                 } 
    399         } 
    400  
    401  
    402         /* Return the total damage */ 
    403         return (tdam * mult); 
    404 } 
    40515 
    40616 
     
    1229839        } 
    1230840} 
    1231  
    1232  
    1233  
    1234 /* 
    1235  * Attack the monster at the given location 
    1236  * 
    1237  * If no "weapon" is available, then "punch" the monster one time. 
    1238  */ 
    1239 void py_attack(int y, int x) 
    1240 { 
    1241         int num = 0, k, bonus, chance; 
    1242  
    1243         monster_type *m_ptr; 
    1244         monster_race *r_ptr; 
    1245         monster_lore *l_ptr; 
    1246  
    1247         object_type *o_ptr; 
    1248  
    1249         char m_name[80]; 
    1250  
    1251         bool fear = FALSE; 
    1252  
    1253         bool do_quake = FALSE; 
    1254  
    1255  
    1256         /* Get the monster */ 
    1257         m_ptr = &mon_list[cave_m_idx[y][x]]; 
    1258         r_ptr = &r_info[m_ptr->r_idx]; 
    1259         l_ptr = &l_list[m_ptr->r_idx]; 
    1260  
    1261  
    1262         /* Disturb the player */ 
    1263         disturb(0, 0); 
    1264  
    1265  
    1266         /* Disturb the monster */ 
    1267         m_ptr->csleep = 0; 
    1268  
    1269  
    1270         /* Extract monster name (or "it") */ 
    1271         monster_desc(m_name, sizeof(m_name), m_ptr, 0); 
    1272  
    1273  
    1274         /* Auto-Recall if possible and visible */ 
    1275         if (m_ptr->ml) monster_race_track(m_ptr->r_idx); 
    1276  
    1277         /* Track a new monster */ 
    1278         if (m_ptr->ml) health_track(cave_m_idx[y][x]); 
    1279  
    1280  
    1281         /* Handle player fear */ 
    1282         if (p_ptr->timed[TMD_AFRAID]) 
    1283         { 
    1284                 /* Message */ 
    1285                 msg_format("You are too afraid to attack %s!", m_name); 
    1286  
    1287                 /* Done */ 
    1288                 return; 
    1289         } 
    1290  
    1291  
    1292         /* Get the weapon */ 
    1293         o_ptr = &inventory[INVEN_WIELD]; 
    1294  
    1295         /* Calculate the "attack quality" */ 
    1296         bonus = p_ptr->to_h + o_ptr->to_h; 
    1297         chance = (p_ptr->skills[SKILL_THN] + (bonus * BTH_PLUS_ADJ)); 
    1298  
    1299  
    1300         /* Attack once for each legal blow */ 
    1301         while (num++ < p_ptr->num_blow) 
    1302         { 
    1303                 /* Test for hit */ 
    1304                 if (test_hit(chance, r_ptr->ac, m_ptr->ml)) 
    1305                 { 
    1306                         /* Message */ 
    1307                         message_format(MSG_GENERIC, m_ptr->r_idx, "You hit %s.", m_name); 
    1308  
    1309                         /* Hack -- bare hands do one damage */ 
    1310                         k = 1; 
    1311  
    1312                         /* Handle normal weapon */ 
    1313                         if (o_ptr->k_idx) 
    1314                         { 
    1315                                 k = damroll(o_ptr->dd, o_ptr->ds); 
    1316                                 k = tot_dam_aux(o_ptr, k, m_ptr); 
    1317                                 if (p_ptr->impact && (k > 50)) do_quake = TRUE; 
    1318                                 k = critical_norm(o_ptr->weight, o_ptr->to_h, k); 
    1319                                 k += o_ptr->to_d; 
    1320                         } 
    1321  
    1322                         /* Apply the player damage bonuses */ 
    1323                         k += p_ptr->to_d; 
    1324  
    1325                         /* No negative damage */ 
    1326                         if (k < 0) k = 0; 
    1327  
    1328                         /* Complex message */ 
    1329                         if (p_ptr->wizard) 
    1330                         { 
    1331                                 msg_format("You do %d (out of %d) damage.", k, m_ptr->hp); 
    1332                         } 
    1333  
    1334                         /* Damage, check for fear and death */ 
    1335                         if (mon_take_hit(cave_m_idx[y][x], k, &fear, NULL)) break; 
    1336  
    1337                         /* Confusion attack */ 
    1338                         if (p_ptr->confusing) 
    1339                         { 
    1340                                 /* Cancel glowing hands */ 
    1341                                 p_ptr->confusing = FALSE; 
    1342  
    1343                                 /* Message */ 
    1344                                 msg_print("Your hands stop glowing."); 
    1345  
    1346                                 /* Confuse the monster */ 
    1347                                 if (r_ptr->flags3 & (RF3_NO_CONF)) 
    1348                                 { 
    1349                                         if (m_ptr->ml) 
    1350                                         { 
    1351                                                 l_ptr->flags3 |= (RF3_NO_CONF); 
    1352                                         } 
    1353  
    1354                                         msg_format("%^s is unaffected.", m_name); 
    1355                                 } 
    1356                                 else if (rand_int(100) < r_ptr->level) 
    1357                                 { 
    1358                                         msg_format("%^s is unaffected.", m_name); 
    1359                                 } 
    1360                                 else 
    1361                                 { 
    1362                                         msg_format("%^s appears confused.", m_name); 
    1363                                         m_ptr->confused += 10 + rand_int(p_ptr->lev) / 5; 
    1364                                 } 
    1365                         } 
    1366                 } 
    1367  
    1368                 /* Player misses */ 
    1369                 else 
    1370                 { 
    1371                         /* Message */ 
    1372                         message_format(MSG_MISS, m_ptr->r_idx, "You miss %s.", m_name); 
    1373                 } 
    1374         } 
    1375  
    1376  
    1377         /* Hack -- delay fear messages */ 
    1378         if (fear && m_ptr->ml) 
    1379         { 
    1380                 /* Message */ 
    1381                 message_format(MSG_FLEE, m_ptr->r_idx, "%^s flees in terror!", m_name); 
    1382         } 
    1383  
    1384  
    1385         /* Mega-Hack -- apply earthquake brand */ 
    1386         if (do_quake) earthquake(p_ptr->py, p_ptr->px, 10); 
    1387 } 
    1388  
    1389841 
    1390842 
  • trunk/src/cmd2.c

    r399 r400  
    23222322 
    23232323 
    2324  
    2325  
    2326  
    2327 /* 
    2328  * Determines the odds of an object breaking when thrown at a monster 
    2329  * 
    2330  * Note that artifacts never break, see the "drop_near()" function. 
    2331  */ 
    2332 static int breakage_chance(const object_type *o_ptr) 
    2333 { 
    2334         /* Examine the item type */ 
    2335         switch (o_ptr->tval) 
    2336         { 
    2337                 /* Always break */ 
    2338                 case TV_FLASK: 
    2339                 case TV_POTION: 
    2340                 case TV_BOTTLE: 
    2341                 case TV_FOOD: 
    2342                 case TV_JUNK: 
    2343                 { 
    2344                         return (100); 
    2345                 } 
    2346  
    2347                 /* Often break */ 
    2348                 case TV_LITE: 
    2349                 case TV_SCROLL: 
    2350                 case TV_SKELETON: 
    2351                 { 
    2352                         return (50); 
    2353                 } 
    2354  
    2355                 /* Sometimes break */ 
    2356                 case TV_ARROW: 
    2357                 { 
    2358                         return (35); 
    2359                 } 
    2360  
    2361                 /* Sometimes break */ 
    2362                 case TV_WAND: 
    2363                 case TV_SHOT: 
    2364                 case TV_BOLT: 
    2365                 case TV_SPIKE: 
    2366                 { 
    2367                         return (25); 
    2368                 } 
    2369         } 
    2370  
    2371         /* Rarely break */ 
    2372         return (10); 
    2373 } 
    2374  
    2375  
    2376 /* 
    2377  * Fire an object from the pack or floor. 
    2378  * 
    2379  * You may only fire items that "match" your missile launcher. 
    2380  * 
    2381  * You must use slings + pebbles/shots, bows + arrows, xbows + bolts. 
    2382  * 
    2383  * See "calc_bonuses()" for more calculations and such. 
    2384  * 
    2385  * Note that "firing" a missile is MUCH better than "throwing" it. 
    2386  * 
    2387  * Note: "unseen" monsters are very hard to hit. 
    2388  * 
    2389  * Objects are more likely to break if they "attempt" to hit a monster. 
    2390  * 
    2391  * Rangers (with Bows) and Anyone (with "Extra Shots") get extra shots. 
    2392  * 
    2393  * The "extra shot" code works by decreasing the amount of energy 
    2394  * required to make each shot, spreading the shots out over time. 
    2395  * 
    2396  * Note that when firing missiles, the launcher multiplier is applied 
    2397  * after all the bonuses are added in, making multipliers very useful. 
    2398  * 
    2399  * Note that Bows of "Extra Might" get extra range and an extra bonus 
    2400  * for the damage multiplier. 
    2401  * 
    2402  * Note that Bows of "Extra Shots" give an extra shot. 
    2403  */ 
    2404 void do_cmd_fire(void) 
    2405 { 
    2406         int dir, item; 
    2407         int i, j, y, x, ty, tx; 
    2408         int tdam, tdis, thits, tmul; 
    2409         int bonus, chance; 
    2410  
    2411         object_type *o_ptr; 
    2412         object_type *j_ptr; 
    2413  
    2414         object_type *i_ptr; 
    2415         object_type object_type_body; 
    2416  
    2417         bool hit_body = FALSE; 
    2418  
    2419         byte missile_attr; 
    2420         char missile_char; 
    2421  
    2422         char o_name[80]; 
    2423  
    2424         int path_n; 
    2425         u16b path_g[256]; 
    2426  
    2427         cptr q, s; 
    2428  
    2429         int msec = op_ptr->delay_factor * op_ptr->delay_factor; 
    2430  
    2431  
    2432         /* Get the "bow" (if any) */ 
    2433         j_ptr = &inventory[INVEN_BOW]; 
    2434  
    2435         /* Require a usable launcher */ 
    2436         if (!j_ptr->tval || !p_ptr->ammo_tval) 
    2437         { 
    2438                 msg_print("You have nothing to fire with."); 
    2439                 return; 
    2440         } 
    2441  
    2442  
    2443         /* Require proper missile */ 
    2444         item_tester_tval = p_ptr->ammo_tval; 
    2445  
    2446         /* Get an item */ 
    2447         q = "Fire which item? "; 
    2448         s = "You have nothing to fire."; 
    2449         if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; 
    2450  
    2451         /* Get the object */ 
    2452         if (item >= 0) 
    2453         { 
    2454                 o_ptr = &inventory[item]; 
    2455         } 
    2456         else 
    2457         { 
    2458                 o_ptr = &o_list[0 - item]; 
    2459         } 
    2460  
    2461  
    2462         /* Get a direction (or cancel) */ 
    2463         if (!get_aim_dir(&dir)) return; 
    2464  
    2465  
    2466         /* Get local object */ 
    2467         i_ptr = &object_type_body; 
    2468  
    2469         /* Obtain a local object */ 
    2470         object_copy(i_ptr, o_ptr); 
    2471  
    2472         /* Single object */ 
    2473         i_ptr->number = 1; 
    2474  
    2475         /* Reduce and describe inventory */ 
    2476         if (item >= 0) 
    2477         { 
    2478                 inven_item_increase(item, -1); 
    2479                 inven_item_describe(item); 
    2480                 inven_item_optimize(item); 
    2481         } 
    2482  
    2483         /* Reduce and describe floor item */ 
    2484         else 
    2485         { 
    2486                 floor_item_increase(0 - item, -1); 
    2487                 floor_item_optimize(0 - item); 
    2488         } 
    2489  
    2490  
    2491         /* Sound */ 
    2492         sound(MSG_SHOOT); 
    2493  
    2494  
    2495         /* Describe the object */ 
    2496         object_desc(o_name, sizeof(o_name), i_ptr, FALSE, 3); 
    2497  
    2498         /* Find the color and symbol for the object for throwing */ 
    2499         missile_attr = object_attr(i_ptr); 
    2500         missile_char = object_char(i_ptr); 
    2501  
    2502  
    2503         /* Use the proper number of shots */ 
    2504         thits = p_ptr->num_fire; 
    2505  
    2506         /* Base damage from thrown object plus launcher bonus */ 
    2507         tdam = damroll(i_ptr->dd, i_ptr->ds) + i_ptr->to_d + j_ptr->to_d; 
    2508  
    2509         /* Actually "fire" the object */ 
    2510         bonus = (p_ptr->to_h + i_ptr->to_h + j_ptr->to_h); 
    2511         chance = (p_ptr->skills[SKILL_THB] + (bonus * BTH_PLUS_ADJ)); 
    2512  
    2513         /* Assume a base multiplier */ 
    2514         tmul = p_ptr->ammo_mult; 
    2515  
    2516         /* Boost the damage */ 
    2517         tdam *= tmul; 
    2518  
    2519         /* Base range XXX XXX */ 
    2520         tdis = 10 + 5 * tmul; 
    2521  
    2522  
    2523         /* Take a (partial) turn */ 
    2524         p_ptr->energy_use = (100 / thits); 
    2525  
    2526  
    2527         /* Start at the player */ 
    2528         y = p_ptr->py; 
    2529         x = p_ptr->px; 
    2530  
    2531         /* Predict the "target" location */ 
    2532         ty = p_ptr->py + 99 * ddy[dir]; 
    2533         tx = p_ptr->px + 99 * ddx[dir]; 
    2534  
    2535         /* Check for "target request" */ 
    2536         if ((dir == 5) && target_okay()) 
    2537         { 
    2538                 tx = p_ptr->target_col; 
    2539                 ty = p_ptr->target_row; 
    2540         } 
    2541  
    2542         /* Calculate the path */ 
    2543         path_n = project_path(path_g, tdis, p_ptr->py, p_ptr->px, ty, tx, 0); 
    2544  
    2545  
    2546         /* Hack -- Handle stuff */ 
    2547         handle_stuff(); 
    2548  
    2549         /* Project along the path */ 
    2550         for (i = 0; i < path_n; ++i) 
    2551         { 
    2552                 int ny = GRID_Y(path_g[i]); 
    2553                 int nx = GRID_X(path_g[i]); 
    2554  
    2555                 /* Hack -- Stop before hitting walls */ 
    2556                 if (!cave_floor_bold(ny, nx)) break; 
    2557  
    2558                 /* Advance */ 
    2559                 x = nx; 
    2560                 y = ny; 
    2561  
    2562                 /* Only do visuals if the player can "see" the missile */ 
    2563                 if (player_can_see_bold(y, x)) 
    2564                 { 
    2565                         /* Visual effects */ 
    2566                         print_rel(missile_char, missile_attr, y, x); 
    2567                         move_cursor_relative(y, x); 
    2568  
    2569                         Term_fresh(); 
    2570                         if (p_ptr->window) window_stuff(); 
    2571  
    2572                         Term_xtra(TERM_XTRA_DELAY, msec); 
    2573                         lite_spot(y, x); 
    2574  
    2575                         Term_fresh(); 
    2576                         if (p_ptr->window) window_stuff(); 
    2577                 } 
    2578  
    2579                 /* Delay anyway for consistency */ 
    2580                 else 
    2581                 { 
    2582                         /* Pause anyway, for consistancy */ 
    2583                         Term_xtra(TERM_XTRA_DELAY, msec); 
    2584                 } 
    2585  
    2586                 /* Handle monster */ 
    2587                 if (cave_m_idx[y][x] > 0) 
    2588                 { 
    2589                         monster_type *m_ptr = &mon_list[cave_m_idx[y][x]]; 
    2590                         monster_race *r_ptr = &r_info[m_ptr->r_idx]; 
    2591  
    2592                         int chance2 = chance - distance(p_ptr->py, p_ptr->px, y, x); 
    2593  
    2594                         int visible = m_ptr->ml; 
    2595  
    2596                         /* Note the collision */ 
    2597                         hit_body = TRUE; 
    2598  
    2599                         /* Did we hit it (penalize distance travelled) */ 
    2600                         if (test_hit(chance2, r_ptr->ac, m_ptr->ml)) 
    2601                         { 
    2602                                 bool fear = FALSE; 
    2603  
    2604                                 /* Assume a default death */ 
    2605                                 cptr note_dies = " dies."; 
    2606  
    2607                                 /* Some monsters get "destroyed" */ 
    2608                                 if ((r_ptr->flags3 & (RF3_DEMON)) || 
    2609                                     (r_ptr->flags3 & (RF3_UNDEAD)) || 
    2610                                     (r_ptr->flags2 & (RF2_STUPID)) || 
    2611                                     (strchr("Evg", r_ptr->d_char))) 
    2612                                 { 
    2613                                         /* Special note at death */ 
    2614                                         note_dies = " is destroyed."; 
    2615                                 } 
    2616  
    2617  
    2618                                 /* Handle unseen monster */ 
    2619                                 if (!visible) 
    2620                                 { 
    2621                                         /* Invisible monster */ 
    2622                                         message_format(MSG_SHOOT_HIT, 0, "The %s finds a mark.", o_name); 
    2623                                 } 
    2624  
    2625                                 /* Handle visible monster */ 
    2626                                 else 
    2627                                 { 
    2628                                         char m_name[80]; 
    2629  
    2630