fix issue #843 - vampire revival sequencing

Reported by Umbire:
|You kill SpaceMannSpiff!  SpaceMannSpiff puts on a dwarvish cloak.
|SpaceMannSpiff puts on a dwarvish iron helm.
|The seemingly dead SpaceMannSpiff suddenly transforms and rises as
| a Vampire.

This was tough to reproduce but I finally managed it.  The issue
text mentions that it was fixed by copperwater in xNetHack with
commit 8c4af50f0aa3e72522f3eb98df039ff25c2a1ea0 to the repository
for that variant.  My attempt to cherry-pick that failed--I'm not
even sure whether it should have been expected to work--and some of
the code has been impinged upon by changes, so I ended up applying
the contents of that commit manually.

The commit changes how/when monsters put on new armor rather than
anything directly related to vampires.  Circumstances similar to
the example above now yield:
|You kill SpaceMannSpiff!
|The seemingly dead SpaceMannSpiff suddenly transforms and rises as
| a Vampire.
on one turn, then on the next turn the revived vampire produces:
|SpaceMannSpiff puts on a dwarvish cloak.

My test case only had one item of interest; I assume that the second
item of armor gets worn on a subsequent turn rather than at the same
time as the first one.

Fixes #843
This commit is contained in:
PatR
2022-09-15 18:02:07 -07:00
parent 6353bddaf6
commit 2b04cc9f5b
6 changed files with 35 additions and 12 deletions

View File

@@ -502,7 +502,7 @@ dog_invent(struct monst *mtmp, struct edog *edog, int udist)
mtmp->weapon_check = NEED_HTH_WEAPON;
(void) mon_wield_item(mtmp);
}
m_dowear(mtmp, FALSE);
check_gear_next_turn(mtmp);
}
}
}

View File

@@ -1009,11 +1009,18 @@ movemon_singlemon(struct monst *mtmp)
if (mtmp->misc_worn_check & I_SPECIAL) {
long oldworn;
mtmp->misc_worn_check &= ~I_SPECIAL;
oldworn = mtmp->misc_worn_check;
m_dowear(mtmp, FALSE);
if (mtmp->misc_worn_check != oldworn || !mtmp->mcanmove)
return FALSE;
/* hostiles only try to equip things if they think hero isn't
* nearby; if they think hero is nearby, leave the flag intact so
* that it can be checked again on subsequent moves until the hero
* is perceived to be farther away. */
if (mtmp->mpeaceful || mtmp->mtame
|| dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) > (3 * 3)) {
mtmp->misc_worn_check &= ~I_SPECIAL;
oldworn = mtmp->misc_worn_check;
m_dowear(mtmp, FALSE);
if (mtmp->misc_worn_check != oldworn || !mtmp->mcanmove)
return FALSE; /* is spending this turn equipping */
}
}
if (is_hider(mtmp->data)) {
@@ -1636,7 +1643,8 @@ mpickstuff(struct monst *mtmp, const char *str)
}
obj_extract_self(otmp3); /* remove from floor */
(void) mpickobj(mtmp, otmp3); /* may merge and free otmp3 */
m_dowear(mtmp, FALSE);
/* let them try and equip it on the next turn */
check_gear_next_turn(mtmp);
newsym(mtmp->mx, mtmp->my);
return TRUE; /* pick only one object */
}
@@ -2519,7 +2527,7 @@ lifesaved_monster(struct monst* mtmp)
}
m_useup(mtmp, lifesave);
/* equip replacement amulet, if any, on next move */
mtmp->misc_worn_check |= I_SPECIAL;
check_gear_next_turn(mtmp);
surviver = !(g.mvitals[monsndx(mtmp->data)].mvflags & G_GENOD);
mtmp->mcanmove = 1;
@@ -4757,7 +4765,7 @@ newcham(
if (!(mtmp->misc_worn_check & W_ARMG))
mselftouch(mtmp, "No longer petrify-resistant, ",
!g.context.mon_moving);
m_dowear(mtmp, FALSE);
check_gear_next_turn(mtmp);
/* This ought to re-test can_carry() on each item in the inventory
* rather than just checking ex-giants & boulders, but that'd be
@@ -5160,4 +5168,14 @@ usmellmon(struct permonst* mdat)
return msg_given ? TRUE : FALSE;
}
/* setting misc_worn_check's I_SPECIAL bit flags a monster to reassess
and potentially re-equip gear at the start of its next move;
this hides the details of that */
void
check_gear_next_turn(mon)
struct monst *mon;
{
mon->misc_worn_check |= I_SPECIAL;
}
/*mon.c*/

View File

@@ -1145,7 +1145,7 @@ extract_from_minvent(
mon->misc_worn_check &= ~unwornmask;
/* give monster a chance to wear other equipment on its next
move instead of waiting until it picks something up */
mon->misc_worn_check |= I_SPECIAL;
check_gear_next_turn(mon);
}
obj_no_longer_held(obj);
if (unwornmask & W_WEP) {

View File

@@ -178,7 +178,8 @@ bhitm(struct monst *mtmp, struct obj *otmp)
if (disguised_mimic)
seemimic(mtmp);
mon_adjust_speed(mtmp, -1, otmp);
m_dowear(mtmp, FALSE); /* might want speed boots */
check_gear_next_turn(mtmp); /* might want speed boots */
if (engulfing_u(mtmp) && is_whirly(mtmp->data)) {
You("disrupt %s!", mon_nam(mtmp));
pline("A huge hole opens up...");
@@ -191,7 +192,7 @@ bhitm(struct monst *mtmp, struct obj *otmp)
if (disguised_mimic)
seemimic(mtmp);
mon_adjust_speed(mtmp, 1, otmp);
m_dowear(mtmp, FALSE); /* might want speed boots */
check_gear_next_turn(mtmp); /* might want speed boots */
}
if (mtmp->mtame)
helpful_gesture = TRUE;