abstract
| - Below is the full text to wield.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.0/wield.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)wield.c 3.3 1999/08/16 */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. 7. /* KMH -- Differences between the three weapon slots. 8. * 9. * The main weapon (uwep): 10. * 1. Is filled by the (w)ield command. 11. * 2. Can be filled with any type of item. 12. * 3. May be carried in one or both hands. 13. * 4. Is used as the melee weapon and as the launcher for 14. * ammunition. 15. * 5. Only conveys intrinsics when it is a weapon, weapon-tool, 16. * or artifact. 17. * 6. Certain cursed items will weld to the hand and cannot be 18. * unwielded or dropped. See erodeable_wep() and will_weld() 19. * below for the list of which items apply. 20. * 21. * The secondary weapon (uswapwep): 22. * 1. Is filled by the e(x)change command, which swaps this slot 23. * with the main weapon. If the "pushweapon" option is set, 24. * the (w)ield command will also store the old weapon in the 25. * secondary slot. 26. * 2. Can be field with anything that will fit in the main weapon 27. * slot; that is, any type of item. 28. * 3. Is usually NOT considered to be carried in the hands. 29. * That would force too many checks among the main weapon, 30. * second weapon, shield, gloves, and rings; and it would 31. * further be complicated by bimanual weapons. A special 32. * exception is made for two-weapon combat. 33. * 4. Is used as the second weapon for two-weapon combat, and as 34. * a convenience to swap with the main weapon. 35. * 5. Never conveys intrinsics. 36. * 6. Cursed items never weld (see #3 for reasons), but they also 37. * prevent two-weapon combat. 38. * 39. * The quiver (uquiver): 40. * 1. Is filled by the (Q)uiver command. 41. * 2. Can be filled with any type of item. 42. * 3. Is considered to be carried in a special part of the pack. 43. * 4. Is used as the item to throw with the (f)ire command. 44. * This is a convenience over the normal (t)hrow command. 45. * 5. Never conveys intrinsics. 46. * 6. Cursed items never weld; their effect is handled by the normal 47. * throwing code. 48. * 49. * No item may be in more than one of these slots. 50. */ 51. 52. 53. static int FDECL(ready_weapon, (struct obj *)); 54. 55. /* elven weapons vibrate warningly when enchanted beyond a limit */ 56. #define is_elven_weapon(optr) ((optr)->otyp == ELVEN_ARROW\ 57. || (optr)->otyp == ELVEN_SPEAR\ 58. || (optr)->otyp == ELVEN_DAGGER\ 59. || (optr)->otyp == ELVEN_SHORT_SWORD\ 60. || (optr)->otyp == ELVEN_BROADSWORD\ 61. || (optr)->otyp == ELVEN_BOW) 62. 63. /* used by will_weld() */ 64. /* probably should be renamed */ 65. #define erodeable_wep(optr) ((optr)->oclass == WEAPON_CLASS \ 66. || is_weptool(optr) \ 67. || (optr)->otyp == HEAVY_IRON_BALL \ 68. || (optr)->otyp == IRON_CHAIN) 69. 70. /* used by welded(), and also while wielding */ 71. #define will_weld(optr) ((optr)->cursed \ 72. && (erodeable_wep(optr) \ 73. || (optr)->otyp == TIN_OPENER)) 74. 75. 76. /*** Functions that place a given item in a slot ***/ 77. /* Proper usage includes: 78. * 1. Initializing the slot during character generation or a 79. * restore. 80. * 2. Setting the slot due to a player's actions. 81. * 3. If one of the objects in the slot are split off, these 82. * functions can be used to put the remainder back in the slot. 83. * 4. Putting an item that was thrown and returned back into the slot. 84. * 5. Emptying the slot, by passing a null object. NEVER pass 85. * zeroobj! 86. * 87. * Note: setuwep() with a null obj, and uwepgone(), are NOT the same! 88. * Sometimes unwielding a weapon can kill you, and lifesaving will then 89. * put it back into your hand. If lifesaving is permitted to do this, 90. * use setwuep((struct obj *)0); otherwise use uwepgone(). 91. * 92. * If the item is being moved from another slot, it is the caller's 93. * responsibility to handle that. It's also the caller's responsibility 94. * to print the appropriate messages. 95. */ 96. void 97. setuwep(obj) 98. register struct obj *obj; 99. { 100. if (obj == uwep) return; /* necessary to not set unweapon */ 101. setworn(obj, W_WEP); 102. /* Note: Explicitly wielding a pick-axe will not give a "bashing" 103. * message. Wielding one via 'a'pplying it will. 104. * 3.2.2: Wielding arbitrary objects will give bashing message too. 105. */ 106. if (obj) { 107. unweapon = (obj->oclass == WEAPON_CLASS) ? 108. is_launcher(obj) || is_ammo(obj) || 109. is_missile(obj) || is_pole(obj) : 110. !is_weptool(obj); 111. } else 112. unweapon = TRUE; /* for "bare hands" message */ 113. update_inventory(); 114. } 115. 116. static int 117. ready_weapon(wep) 118. struct obj *wep; 119. { 120. /* Separated function so swapping works easily */ 121. int res = 0; 122. 123. if (!wep) { 124. /* No weapon */ 125. if (uwep) { 126. You("are empty %s.", body_part(HANDED)); 127. setuwep((struct obj *) 0); 128. res++; 129. } else 130. You("are already empty %s.", body_part(HANDED)); 131. } else if (!uarmg && !Stone_resistance && wep->otyp == CORPSE 132. && touch_petrifies(&mons[wep->corpsenm])) { 133. /* Prevent wielding cockatrice when not wearing gloves --KAA */ 134. char kbuf[BUFSZ]; 135. 136. You("wield the %s corpse in your bare %s.", 137. mons[wep->corpsenm].mname, makeplural(body_part(HAND))); 138. Sprintf(kbuf, "%s corpse", an(mons[wep->corpsenm].mname)); 139. instapetrify(kbuf); 140. } else if (uarms && bimanual(wep)) 141. You("cannot wield a two-handed %s while wearing a shield.", 142. is_sword(wep) ? "sword" : 143. wep->otyp == BATTLE_AXE ? "axe" : "weapon"); 144. else if (wep->oartifact && !touch_artifact(wep, &youmonst)) { 145. res++; /* takes a turn even though it doesn't get wielded */ 146. } else { 147. /* Weapon WILL be wielded after this point */ 148. res++; 149. if (will_weld(wep)) { 150. const char *tmp = xname(wep), *thestr = "The "; 151. if (strncmp(tmp, thestr, 4) && !strncmp(The(tmp),thestr,4)) 152. tmp = thestr; 153. else tmp = ""; 154. pline("%s%s %s to your %s!", tmp, aobjnam(wep, "weld"), 155. (wep->quan == 1L) ? "itself" : "themselves", /* a3 */ 156. bimanual(wep) ? 157. (const char *)makeplural(body_part(HAND)) 158. : body_part(HAND)); 159. wep->bknown = TRUE; 160. } else { 161. /* The message must be printed before setuwep (since 162. * you might die and be revived from changing weapons), 163. * and the message must be before the death message and 164. * Lifesaved rewielding. Yet we want the message to 165. * say "weapon in hand", thus this kludge. 166. */ 167. long dummy = wep->owornmask; 168. wep->owornmask |= W_WEP; 169. prinv((char *)0, wep, 0L); 170. wep->owornmask = dummy; 171. } 172. setuwep(wep); 173. 174. /* KMH -- Talking artifacts are finally implemented */ 175. arti_speak(wep); 176. 177. #if 0 178. /* we'll get back to this someday, but it's not balanced yet */ 179. if (Race_if(PM_ELF) && !wep->oartifact && 180. objects[wep->otyp].oc_material == IRON) { 181. /* Elves are averse to wielding cold iron */ 182. You("have an uneasy feeling about wielding cold iron."); 183. change_luck(-1); 184. } 185. #endif 186. 187. if (wep->unpaid) { 188. struct monst *this_shkp; 189. 190. if ((this_shkp = shop_keeper(inside_shop(u.ux, u.uy))) != 191. (struct monst *)0) { 192. pline("%s says \"You be careful with my %s!\"", 193. shkname(this_shkp), 194. xname(wep)); 195. } 196. } 197. } 198. return(res); 199. /* Take no time if we are dextrous enough */ 200. /* return ((rnd(20) > ACURR(A_DEX)) ? res : 0);*/ 201. } 202. 203. void 204. setuqwep(obj) 205. register struct obj *obj; 206. { 207. setworn(obj, W_QUIVER); 208. update_inventory(); 209. } 210. 211. void 212. setuswapwep(obj) 213. register struct obj *obj; 214. { 215. setworn(obj, W_SWAPWEP); 216. update_inventory(); 217. } 218. 219. 220. /*** Commands to change particular slot(s) ***/ 221. 222. static NEARDATA const char wield_objs[] = 223. { ALL_CLASSES, ALLOW_NONE, WEAPON_CLASS, TOOL_CLASS, 0 }; 224. 225. int 226. dowield() 227. { 228. register struct obj *wep; 229. int result; 230. 231. /* May we attempt this? */ 232. multi = 0; 233. if (cantwield(youmonst.data)) { 234. pline("Don't be ridiculous!"); 235. return(0); 236. } 237. 238. /* Prompt for a new weapon */ 239. if (!(wep = getobj(wield_objs, "wield"))) 240. /* Cancelled */ 241. return (0); 242. else if (wep == uwep) { 243. You("are already wielding that!"); 244. if (is_weptool(wep)) unweapon = FALSE; /* [see setuwep()] */ 245. return (0); 246. } else if (welded(uwep)) { 247. weldmsg(uwep); 248. return (0); 249. } 250. 251. /* Handle no object, or object in other slot */ 252. if (wep == &zeroobj) 253. wep = (struct obj *) 0; 254. else if (wep == uswapwep) 255. return (doswapweapon()); 256. else if (wep == uquiver) 257. setuqwep((struct obj *) 0); 258. else if (wep->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL 259. #ifdef STEED 260. | W_SADDLE 261. #endif 262. )) { 263. You("cannot wield that!"); 264. return (0); 265. } 266. 267. /* Set your new primary weapon */ 268. if (flags.pushweapon && uwep) 269. setuswapwep(uwep); 270. result = ready_weapon(wep); 271. untwoweapon(); 272. 273. return (result); 274. } 275. 276. int 277. doswapweapon() 278. { 279. register struct obj *oldwep, *oldswap; 280. int result = 0; 281. 282. 283. /* May we attempt this? */ 284. multi = 0; 285. if (cantwield(youmonst.data)) { 286. pline("Don't be ridiculous!"); 287. return(0); 288. } 289. if (welded(uwep)) { 290. weldmsg(uwep); 291. return (0); 292. } 293. 294. /* Unwield your current secondary weapon */ 295. oldwep = uwep; 296. oldswap = uswapwep; 297. setuswapwep((struct obj *) 0); 298. 299. /* Set your new primary weapon */ 300. result = ready_weapon(oldswap); 301. 302. /* Set your new secondary weapon */ 303. if (uwep == oldwep) 304. /* Wield failed for some reason */ 305. setuswapwep(oldswap); 306. else { 307. setuswapwep(oldwep); 308. if (uswapwep) 309. prinv((char *)0, uswapwep, 0L); 310. else 311. You("have no secondary weapon readied."); 312. } 313. 314. if (u.twoweap && !can_twoweapon()) 315. untwoweapon(); 316. 317. return (result); 318. } 319. 320. int 321. dowieldquiver() 322. { 323. register struct obj *newquiver; 324. 325. 326. /* Since the quiver isn't in your hands, don't check cantwield(), */ 327. /* will_weld(), touch_petrifies(), etc. */ 328. multi = 0; 329. 330. /* Because 'Q' used to be quit... */ 331. if (!flags.suppress_alert || flags.suppress_alert < FEATURE_NOTICE_VER(3,3,0)) 332. pline("Note: Please use #quit if you wish to exit the game."); 333. 334. /* Prompt for a new quiver */ 335. if (!(newquiver = getobj(wield_objs, "ready"))) 336. /* Cancelled */ 337. return (0); 338. 339. /* Handle no object, or object in other slot */ 340. /* Any type is okay, since we give no intrinsics anyways */ 341. if (newquiver == &zeroobj) { 342. /* Explicitly nothing */ 343. if (uquiver) { 344. pline("You now have no ammunition readied."); 345. setuqwep(newquiver = (struct obj *) 0); 346. } else { 347. pline("You already have no ammunition readied!"); 348. return(0); 349. } 350. } else if (newquiver == uquiver) { 351. pline("That ammunition is already readied!"); 352. return(0); 353. } else if (newquiver == uwep) { 354. /* Prevent accidentally readying the main weapon */ 355. pline("That is already being used as a weapon!"); 356. return(0); 357. } else if (newquiver->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL 358. #ifdef STEED 359. | W_SADDLE 360. #endif 361. )) { 362. You("cannot ready that!"); 363. return (0); 364. } else { 365. long dummy; 366. 367. 368. /* Check if it's the secondary weapon */ 369. if (newquiver == uswapwep) { 370. setuswapwep((struct obj *) 0); 371. untwoweapon(); 372. } 373. 374. /* Okay to put in quiver; print it */ 375. dummy = newquiver->owornmask; 376. newquiver->owornmask |= W_QUIVER; 377. prinv((char *)0, newquiver, 0L); 378. newquiver->owornmask = dummy; 379. } 380. 381. /* Finally, place it in the quiver */ 382. setuqwep(newquiver); 383. /* Take no time if we are dextrous enough */ 384. return (rnd(20) > ACURR(A_DEX)); 385. } 386. 387. int 388. can_twoweapon() 389. { 390. #define NOT_WEAPON(obj) (!is_weptool(obj) && obj->oclass != WEAPON_CLASS) 391. if (Upolyd) 392. You("can only use two weapons in your normal form."); 393. else if (!uwep || !uswapwep) 394. Your("%s%s%s empty.", uwep ? "left " : uswapwep ? "right " : "", 395. body_part(HAND), (!uwep && !uswapwep) ? "s are" : " is"); 396. else if (NOT_WEAPON(uwep) || bimanual(uwep)) 397. pline("%s isn't %s%s%s.", Yname2(uwep), 398. NOT_WEAPON(uwep) ? "a ": "", 399. bimanual(uwep) ? "one-handed": "", 400. NOT_WEAPON(uwep) ? "weapon": ""); 401. else if (NOT_WEAPON(uswapwep) || bimanual(uswapwep)) 402. pline("%s isn't %s%s%s.", Yname2(uswapwep), 403. NOT_WEAPON(uswapwep) ? "a ": "", 404. bimanual(uswapwep) ? "one-handed": "", 405. NOT_WEAPON(uswapwep) ? "weapon": ""); 406. else if (uarms) 407. You("can't use two weapons while wearing a shield."); 408. else if (uswapwep->oartifact) 409. pline("%s resists being held second to another weapon!", 410. Yname2(uswapwep)); 411. else if (!uarmg && !Stone_resistance && (uswapwep->otyp == CORPSE && 412. (touch_petrifies(&mons[uswapwep->corpsenm])))) { 413. char kbuf[BUFSZ]; 414. 415. You("wield the %s corpse with your bare %s.", 416. mons[uswapwep->corpsenm].mname, body_part(HAND)); 417. Sprintf(kbuf, "%s corpse", an(mons[uswapwep->corpsenm].mname)); 418. instapetrify(kbuf); 419. } else if (Glib || uswapwep->cursed) { 420. struct obj *obj = uswapwep; 421. 422. Your("%s from your %s!", aobjnam(obj, "slip"), 423. makeplural(body_part(HAND))); 424. if (!Glib) 425. obj->bknown = TRUE; 426. setuswapwep((struct obj *) 0); 427. dropx(obj); 428. } else 429. return (TRUE); 430. return (FALSE); 431. } 432. 433. int 434. dotwoweapon() 435. { 436. /* You can always toggle it off */ 437. if (u.twoweap) { 438. You("switch to your primary weapon."); 439. u.twoweap = 0; 440. return (0); 441. } 442. 443. /* May we use two weapons? */ 444. if (can_twoweapon()) { 445. /* Success! */ 446. You("begin two-weapon combat."); 447. u.twoweap = 1; 448. return (rnd(20) > ACURR(A_DEX)); 449. } 450. return (0); 451. } 452. 453. /*** Functions to empty a given slot ***/ 454. /* These should be used only when the item can't be put back in 455. * the slot by life saving. Proper usage includes: 456. * 1. The item has been eaten, stolen, burned away, or rotted away. 457. * 2. Making an item disappear for a bones pile. 458. */ 459. void 460. uwepgone() 461. { 462. if (uwep) { 463. setworn((struct obj *)0, W_WEP); 464. unweapon = TRUE; 465. update_inventory(); 466. } 467. } 468. 469. void 470. uswapwepgone() 471. { 472. if (uswapwep) { 473. setworn((struct obj *)0, W_SWAPWEP); 474. update_inventory(); 475. } 476. } 477. 478. void 479. uqwepgone() 480. { 481. if (uquiver) { 482. setworn((struct obj *)0, W_QUIVER); 483. update_inventory(); 484. } 485. } 486. 487. void 488. untwoweapon() 489. { 490. if (u.twoweap) { 491. You("can no longer use two weapons at once."); 492. u.twoweap = FALSE; 493. } 494. return; 495. } 496. 497. /* Maybe rust weapon, or corrode it if acid damage is called for */ 498. void 499. erode_weapon(victim, acid_dmg) 500. struct monst *victim; 501. boolean acid_dmg; 502. { 503. int erosion; 504. struct obj *target; 505. boolean vismon = (victim != &youmonst) && canseemon(victim); 506. 507. target = (victim == &youmonst) ? uwep : MON_WEP(victim); 508. if (!target) 509. return; 510. 511. erosion = acid_dmg ? target->oeroded2 : target->oeroded; 512. 513. if (target->greased) { 514. grease_protect(target,(char *)0,FALSE,victim); 515. } else if (target->oerodeproof || 516. (acid_dmg ? !is_corrodeable(target) : !is_rustprone(target))) { 517. if (flags.verbose || !(target->oerodeproof && target->rknown)) { 518. if (victim == &youmonst) 519. Your("%s not affected.", aobjnam(target, "are")); 520. else if (vismon) 521. pline("%s's %s not affected.", Monnam(victim), 522. aobjnam(target, "are")); 523. } 524. if (target->oerodeproof) target->rknown = TRUE; 525. } else if (erosion < MAX_ERODE) { 526. if (victim == &youmonst) 527. Your("%s%s!", aobjnam(target, acid_dmg ? "corrode" : "rust"), 528. erosion+1 == MAX_ERODE ? " completely" : 529. erosion ? " further" : ""); 530. else if (vismon) 531. pline("%s's %s%s!", Monnam(victim), 532. aobjnam(target, acid_dmg ? "corrode" : "rust"), 533. erosion+1 == MAX_ERODE ? " completely" : 534. erosion ? " further" : ""); 535. if (acid_dmg) 536. target->oeroded2++; 537. else 538. target->oeroded++; 539. } else { 540. if (flags.verbose) { 541. if (victim == &youmonst) 542. Your("%s completely %s.", 543. aobjnam(target, Blind ? "feel" : "look"), 544. acid_dmg ? "corroded" : "rusty"); 545. else if (vismon) 546. pline("%s's %s completely %s.", Monnam(victim), 547. aobjnam(target, "look"), 548. acid_dmg ? "corroded" : "rusty"); 549. } 550. } 551. } 552. 553. int 554. chwepon(otmp, amount) 555. register struct obj *otmp; 556. register int amount; 557. { 558. register const char *color = hcolor((amount < 0) ? Black : blue); 559. register const char *xtime; 560. 561. if(!uwep || (uwep->oclass != WEAPON_CLASS && !is_weptool(uwep))) { 562. char buf[BUFSZ]; 563. 564. Sprintf(buf, "Your %s %s.", makeplural(body_part(HAND)), 565. (amount >= 0) ? "twitch" : "itch"); 566. strange_feeling(otmp, buf); 567. exercise(A_DEX, (boolean) (amount >= 0)); 568. return(0); 569. } 570. 571. if(uwep->otyp == WORM_TOOTH && amount >= 0) { 572. uwep->otyp = CRYSKNIFE; 573. uwep->oerodeproof = 0; 574. Your("weapon seems sharper now."); 575. uwep->cursed = 0; 576. return(1); 577. } 578. 579. if(uwep->otyp == CRYSKNIFE && amount < 0) { 580. uwep->otyp = WORM_TOOTH; 581. uwep->oerodeproof = 0; 582. Your("weapon seems duller now."); 583. return(1); 584. } 585. 586. if (amount < 0 && uwep->oartifact && restrict_name(uwep, ONAME(uwep))) { 587. if (!Blind) 588. Your("%s %s.", aobjnam(uwep, "faintly glow"), color); 589. return(1); 590. } 591. /* there is a (soft) upper and lower limit to uwep->spe */ 592. if(((uwep->spe > 5 && amount >= 0) || (uwep->spe < -5 && amount < 0)) 593. && rn2(3)) { 594. if (!Blind) 595. Your("%s %s for a while and then evaporate%s.", 596. aobjnam(uwep, "violently glow"), color, 597. uwep->quan == 1L ? "s" : ""); 598. else 599. Your("%s.", aobjnam(uwep, "evaporate")); 600. 601. while(uwep) /* let all of them disappear */ 602. /* note: uwep->quan = 1 is nogood if unpaid */ 603. useup(uwep); 604. return(1); 605. } 606. if (!Blind) { 607. xtime = (amount*amount == 1) ? "moment" : "while"; 608. Your("%s %s for a %s.", 609. aobjnam(uwep, amount == 0 ? "violently glow" : "glow"), 610. color, xtime); 611. } 612. uwep->spe += amount; 613. if(amount > 0) uwep->cursed = 0; 614. 615. /* 616. * Enchantment, which normally improves a weapon, has an 617. * addition adverse reaction on Magicbane whose effects are 618. * spe dependent. Give an obscure clue here. 619. */ 620. if (uwep->oartifact == ART_MAGICBANE && uwep->spe >= 0) { 621. Your("right %s %sches!", 622. body_part(HAND), 623. (((amount > 1) && (uwep->spe > 1)) ? "flin" : "it")); 624. } 625. 626. /* an elven magic clue, cookie@keebler */ 627. if ((uwep->spe > 5) 628. && (is_elven_weapon(uwep) || uwep->oartifact || !rn2(7))) 629. Your("%s unexpectedly.", 630. aobjnam(uwep, "suddenly vibrate")); 631. 632. return(1); 633. } 634. 635. int 636. welded(obj) 637. register struct obj *obj; 638. { 639. if (obj && obj == uwep && will_weld(obj)) { 640. obj->bknown = TRUE; 641. return 1; 642. } 643. return 0; 644. } 645. 646. void 647. weldmsg(obj) 648. register struct obj *obj; 649. { 650. long savewornmask; 651. 652. savewornmask = obj->owornmask; 653. Your("%s %s welded to your %s!", 654. xname(obj), (obj->quan == 1L) ? "is" : "are", 655. bimanual(obj) ? (const char *)makeplural(body_part(HAND)) 656. : body_part(HAND)); 657. obj->owornmask = savewornmask; 658. } 659. 660. /*wield.c*/
|