fix issue #949 - dropping welded iron ball

If punished and the attached iron ball was both cursed and wielded,
falling while going down stairs would drop it instead of leaving it
welded to hero's hand. ( Didn't happen for iron ball that wasn't
chained to hero's leg.)

I thought that this was going to be a one or two line fix but ball
and chain stuff is never that simple.

Fixes #949
This commit is contained in:
PatR
2022-12-15 13:48:59 -08:00
parent 995fae39b5
commit df7e575500
4 changed files with 30 additions and 7 deletions

View File

@@ -1068,6 +1068,8 @@ if hero's action caused engulfer to expel swallowed hero, it might do so onto
throwing recoil while levitating could send hero out of shop while carrying
unpaid items, triggering sanity check warnings; once outside, taking
a step other than back into the shop was treated as a robbery
if punished and iron ball was cursed and wielded--so welded to hand--falling
when doors would drop it instead of keeping it welded
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository

View File

@@ -22,7 +22,7 @@ static struct breadcrumbs bcpbreadcrumbs = {0}, bcubreadcrumbs = {0};
void
ballrelease(boolean showmsg)
{
if (carried(uball)) {
if (carried(uball) && !welded(uball)) {
if (showmsg)
pline("Startled, you drop the iron ball.");
if (uwep == uball)
@@ -44,6 +44,9 @@ ballfall(void)
{
boolean gets_hit;
if (uball && carried(uball) && welded(uball))
return;
gets_hit = (((uball->ox != u.ux) || (uball->oy != u.uy))
&& ((uwep == uball) ? FALSE : (boolean) rn2(5)));
ballrelease(TRUE);
@@ -996,7 +999,7 @@ drag_down(void)
*/
forward = carried(uball) && (uwep == uball || !uwep || !rn2(3));
if (carried(uball))
if (carried(uball) && !welded(uball))
You("lose your grip on the iron ball.");
cls(); /* previous level is still displayed although you

View File

@@ -595,6 +595,19 @@ canletgo(struct obj *obj, const char *word)
Norep("You cannot %s %s you are wearing.", word, something);
return FALSE;
}
if (obj == uwep && welded(uwep)) {
/* no weldmsg(), so uwep->bknown might become set silently
if word is "" */
if (*word) {
const char *hand = body_part(HAND);
if (bimanual(uwep))
hand = makeplural(hand);
Norep("You cannot %s %s welded to your %s.", word, something,
hand);
}
return FALSE;
}
if (obj->otyp == LOADSTONE && obj->cursed) {
/* getobj() kludge sets corpsenm to user's specified count
when refusing to split a stack of cursed loadstones */
@@ -1612,7 +1625,8 @@ goto_level(
You("fall down the %s.", ga.at_ladder ? "ladder" : "stairs");
if (Punished) {
drag_down();
ballrelease(FALSE);
if (!welded(uball))
ballrelease(FALSE);
}
/* falling off steed has its own losehp() call */
if (u.usteed)
@@ -1632,7 +1646,7 @@ goto_level(
} else { /* trap door or level_tele or In_endgame */
u_on_rndspot((up ? 1 : 0) | (was_in_W_tower ? 2 : 0));
if (falling) {
if (Punished)
if (Punished && !welded(uball))
ballfall();
selftouch("Falling, you");
do_fall_dmg = TRUE;

View File

@@ -1030,11 +1030,15 @@ void
weldmsg(struct obj *obj)
{
long savewornmask;
const char *hand = body_part(HAND);
if (bimanual(obj))
hand = makeplural(hand);
savewornmask = obj->owornmask;
pline("%s welded to your %s!", Yobjnam2(obj, "are"),
bimanual(obj) ? (const char *) makeplural(body_part(HAND))
: body_part(HAND));
obj->owornmask = 0L; /* suppress doname()'s "(weapon in hand)";
* Yobjnam2() doesn't actually need this because
* it is based on xname() rather than doname() */
pline("%s welded to your %s!", Yobjnam2(obj, "are"), hand);
obj->owornmask = savewornmask;
}