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:
@@ -1988,6 +1988,9 @@ vampire shapeshifting in a door (pr #794 by entrez)
|
|||||||
split "act_on_act" into separate function (pr #777 by argrath)
|
split "act_on_act" into separate function (pr #777 by argrath)
|
||||||
unnecessary null-check on parsesymbols() (pr #793 by argrath)
|
unnecessary null-check on parsesymbols() (pr #793 by argrath)
|
||||||
split cleaning-up on gd_move() into separate function (pr #791 by argrath)
|
split cleaning-up on gd_move() into separate function (pr #791 by argrath)
|
||||||
|
from xNetHack: better handling for monsters putting on equipment; fixes
|
||||||
|
issue #843: "Mon dies. Mon puts on <armor>. The seemingly dead Mon
|
||||||
|
rises as a vampire."
|
||||||
|
|
||||||
|
|
||||||
Code Cleanup and Reorganization
|
Code Cleanup and Reorganization
|
||||||
|
|||||||
@@ -1603,6 +1603,7 @@ extern boolean angry_guards(boolean);
|
|||||||
extern void pacify_guards(void);
|
extern void pacify_guards(void);
|
||||||
extern void decide_to_shapeshift(struct monst *, int);
|
extern void decide_to_shapeshift(struct monst *, int);
|
||||||
extern boolean vamp_stone(struct monst *);
|
extern boolean vamp_stone(struct monst *);
|
||||||
|
extern void check_gear_next_turn(struct monst *);
|
||||||
|
|
||||||
/* ### mondata.c ### */
|
/* ### mondata.c ### */
|
||||||
|
|
||||||
|
|||||||
@@ -502,7 +502,7 @@ dog_invent(struct monst *mtmp, struct edog *edog, int udist)
|
|||||||
mtmp->weapon_check = NEED_HTH_WEAPON;
|
mtmp->weapon_check = NEED_HTH_WEAPON;
|
||||||
(void) mon_wield_item(mtmp);
|
(void) mon_wield_item(mtmp);
|
||||||
}
|
}
|
||||||
m_dowear(mtmp, FALSE);
|
check_gear_next_turn(mtmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
34
src/mon.c
34
src/mon.c
@@ -1009,11 +1009,18 @@ movemon_singlemon(struct monst *mtmp)
|
|||||||
if (mtmp->misc_worn_check & I_SPECIAL) {
|
if (mtmp->misc_worn_check & I_SPECIAL) {
|
||||||
long oldworn;
|
long oldworn;
|
||||||
|
|
||||||
mtmp->misc_worn_check &= ~I_SPECIAL;
|
/* hostiles only try to equip things if they think hero isn't
|
||||||
oldworn = mtmp->misc_worn_check;
|
* nearby; if they think hero is nearby, leave the flag intact so
|
||||||
m_dowear(mtmp, FALSE);
|
* that it can be checked again on subsequent moves until the hero
|
||||||
if (mtmp->misc_worn_check != oldworn || !mtmp->mcanmove)
|
* is perceived to be farther away. */
|
||||||
return FALSE;
|
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)) {
|
if (is_hider(mtmp->data)) {
|
||||||
@@ -1636,7 +1643,8 @@ mpickstuff(struct monst *mtmp, const char *str)
|
|||||||
}
|
}
|
||||||
obj_extract_self(otmp3); /* remove from floor */
|
obj_extract_self(otmp3); /* remove from floor */
|
||||||
(void) mpickobj(mtmp, otmp3); /* may merge and free otmp3 */
|
(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);
|
newsym(mtmp->mx, mtmp->my);
|
||||||
return TRUE; /* pick only one object */
|
return TRUE; /* pick only one object */
|
||||||
}
|
}
|
||||||
@@ -2519,7 +2527,7 @@ lifesaved_monster(struct monst* mtmp)
|
|||||||
}
|
}
|
||||||
m_useup(mtmp, lifesave);
|
m_useup(mtmp, lifesave);
|
||||||
/* equip replacement amulet, if any, on next move */
|
/* 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);
|
surviver = !(g.mvitals[monsndx(mtmp->data)].mvflags & G_GENOD);
|
||||||
mtmp->mcanmove = 1;
|
mtmp->mcanmove = 1;
|
||||||
@@ -4757,7 +4765,7 @@ newcham(
|
|||||||
if (!(mtmp->misc_worn_check & W_ARMG))
|
if (!(mtmp->misc_worn_check & W_ARMG))
|
||||||
mselftouch(mtmp, "No longer petrify-resistant, ",
|
mselftouch(mtmp, "No longer petrify-resistant, ",
|
||||||
!g.context.mon_moving);
|
!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
|
/* This ought to re-test can_carry() on each item in the inventory
|
||||||
* rather than just checking ex-giants & boulders, but that'd be
|
* rather than just checking ex-giants & boulders, but that'd be
|
||||||
@@ -5160,4 +5168,14 @@ usmellmon(struct permonst* mdat)
|
|||||||
return msg_given ? TRUE : FALSE;
|
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*/
|
/*mon.c*/
|
||||||
|
|||||||
@@ -1145,7 +1145,7 @@ extract_from_minvent(
|
|||||||
mon->misc_worn_check &= ~unwornmask;
|
mon->misc_worn_check &= ~unwornmask;
|
||||||
/* give monster a chance to wear other equipment on its next
|
/* give monster a chance to wear other equipment on its next
|
||||||
move instead of waiting until it picks something up */
|
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);
|
obj_no_longer_held(obj);
|
||||||
if (unwornmask & W_WEP) {
|
if (unwornmask & W_WEP) {
|
||||||
|
|||||||
@@ -178,7 +178,8 @@ bhitm(struct monst *mtmp, struct obj *otmp)
|
|||||||
if (disguised_mimic)
|
if (disguised_mimic)
|
||||||
seemimic(mtmp);
|
seemimic(mtmp);
|
||||||
mon_adjust_speed(mtmp, -1, otmp);
|
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)) {
|
if (engulfing_u(mtmp) && is_whirly(mtmp->data)) {
|
||||||
You("disrupt %s!", mon_nam(mtmp));
|
You("disrupt %s!", mon_nam(mtmp));
|
||||||
pline("A huge hole opens up...");
|
pline("A huge hole opens up...");
|
||||||
@@ -191,7 +192,7 @@ bhitm(struct monst *mtmp, struct obj *otmp)
|
|||||||
if (disguised_mimic)
|
if (disguised_mimic)
|
||||||
seemimic(mtmp);
|
seemimic(mtmp);
|
||||||
mon_adjust_speed(mtmp, 1, otmp);
|
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)
|
if (mtmp->mtame)
|
||||||
helpful_gesture = TRUE;
|
helpful_gesture = TRUE;
|
||||||
|
|||||||
Reference in New Issue
Block a user