fix #2253 - shk dismissing kops from other level (trunk only)
From a bug report, if you rob a shop, let the angry shopkeeper catch up with you outside his shop, escape to another level with adjacent shk tagging along, then pacify the shk by paying him off, he will dismiss kops on the present level and return to his shop but when you return to his shop level there'll still be kops chasing you there. This fix adds an extra flag to the eshk structure so that kops can be dismissed a second time when the shk migrates back to shop level. The first dismisal (on the "wrong" level) still takes place in case any kops are around. Neither dismissal actually occurs if there happens to be another angry shk present on the level where dismissal is being done.
This commit is contained in:
46
src/dog.c
46
src/dog.c
@@ -1,5 +1,4 @@
|
||||
/* NetHack 3.5 dog.c $Date$ $Revision$ */
|
||||
/* SCCS Id: @(#)dog.c 3.5 2008/10/20 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -218,12 +217,57 @@ void
|
||||
losedogs()
|
||||
{
|
||||
register struct monst *mtmp, *mtmp0 = 0, *mtmp2;
|
||||
int dismissKops = 0;
|
||||
|
||||
/*
|
||||
* First, scan migrating_mons for shopkeepers who want to dismiss Kops,
|
||||
* and scan mydogs for shopkeepers who want to retain kops.
|
||||
* Second, dismiss kops if warranted, making more room for arrival.
|
||||
* Third, place monsters accompanying the hero.
|
||||
* Last, place migrating monsters coming to this level.
|
||||
*
|
||||
* Hero might eventually be displaced (due to the third step, but
|
||||
* occuring later), which is the main reason to do the second step
|
||||
* sooner (in turn necessitating the first step, rather than combining
|
||||
* the list scans with monster placement).
|
||||
*/
|
||||
|
||||
/* check for returning shk(s) */
|
||||
for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon) {
|
||||
if (mtmp->mux != u.uz.dnum || mtmp->muy != u.uz.dlevel) continue;
|
||||
if (mtmp->isshk) {
|
||||
if (ESHK(mtmp)->dismiss_kops) {
|
||||
if (dismissKops == 0) dismissKops = 1;
|
||||
ESHK(mtmp)->dismiss_kops = FALSE; /* reset */
|
||||
} else if (!mtmp->mpeaceful) {
|
||||
/* an unpacified shk is returning; don't dismiss kops
|
||||
even if another pacified one is willing to do so */
|
||||
dismissKops = -1;
|
||||
/* [keep looping; later monsters might need ESHK reset] */
|
||||
}
|
||||
}
|
||||
}
|
||||
/* make the same check for mydogs */
|
||||
for (mtmp = mydogs; mtmp && dismissKops >= 0; mtmp = mtmp->nmon) {
|
||||
if (mtmp->isshk) {
|
||||
/* hostile shk might accompany hero [ESHK(mtmp)->dismiss_kops
|
||||
can't be set here; it's only used for migrating_mons] */
|
||||
if (!mtmp->mpeaceful) dismissKops = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* when a hostile shopkeeper chases hero to another level
|
||||
and then gets paid off there, get rid of summoned kops
|
||||
here now that he has returned to his shop level */
|
||||
if (dismissKops > 0) make_happy_shoppers(TRUE);
|
||||
|
||||
/* place pets and/or any other monsters who accompany hero */
|
||||
while ((mtmp = mydogs) != 0) {
|
||||
mydogs = mtmp->nmon;
|
||||
mon_arrive(mtmp, TRUE);
|
||||
}
|
||||
|
||||
/* time for migrating monsters to arrive */
|
||||
for(mtmp = migrating_mons; mtmp; mtmp = mtmp2) {
|
||||
mtmp2 = mtmp->nmon;
|
||||
if (mtmp->mux == u.uz.dnum && mtmp->muy == u.uz.dlevel) {
|
||||
|
||||
12
src/shk.c
12
src/shk.c
@@ -1019,13 +1019,23 @@ register boolean silentkops;
|
||||
/* arrive near shop's door */
|
||||
migrate_to_level(shkp, ledger_no(&eshkp->shoplevel),
|
||||
MIGR_APPROX_XY, &eshkp->shd);
|
||||
/* dismiss kops on that level when shk arrives */
|
||||
eshkp->dismiss_kops = TRUE;
|
||||
}
|
||||
if (vanished)
|
||||
pline("Satisfied, %s suddenly disappears!", shk_nam);
|
||||
} else if(wasmad)
|
||||
pline("%s calms down.", Monnam(shkp));
|
||||
|
||||
if(!angry_shk_exists()) {
|
||||
make_happy_shoppers(silentkops);
|
||||
}
|
||||
|
||||
/* called by make_happy_shk() and also by losedogs() for migrating shk */
|
||||
void
|
||||
make_happy_shoppers(silentkops)
|
||||
boolean silentkops;
|
||||
{
|
||||
if (!angry_shk_exists()) {
|
||||
#ifdef KOPS
|
||||
kops_gone(silentkops);
|
||||
#endif
|
||||
|
||||
36
src/shknam.c
36
src/shknam.c
@@ -1,5 +1,4 @@
|
||||
/* NetHack 3.5 shknam.c $Date$ $Revision$ */
|
||||
/* SCCS Id: @(#)shknam.c 3.5 2007/09/14 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -458,11 +457,12 @@ void
|
||||
neweshk(mtmp)
|
||||
struct monst *mtmp;
|
||||
{
|
||||
if (!mtmp->mextra) mtmp->mextra = newmextra();
|
||||
if (!ESHK(mtmp)) {
|
||||
if (!mtmp->mextra)
|
||||
mtmp->mextra = newmextra();
|
||||
if (!ESHK(mtmp))
|
||||
ESHK(mtmp) = (struct eshk *)alloc(sizeof(struct eshk));
|
||||
(void) memset((genericptr_t) ESHK(mtmp), 0, sizeof(struct eshk));
|
||||
}
|
||||
(void) memset((genericptr_t)ESHK(mtmp), 0, sizeof (struct eshk));
|
||||
ESHK(mtmp)->bill_p = (struct bill_x *)0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -483,6 +483,7 @@ struct mkroom *sroom;
|
||||
{
|
||||
register int sh, sx, sy;
|
||||
struct monst *shk;
|
||||
struct eshk *eshkp;
|
||||
|
||||
/* place the shopkeeper in the given room */
|
||||
sh = sroom->fdoor;
|
||||
@@ -535,24 +536,23 @@ struct mkroom *sroom;
|
||||
/* now initialize the shopkeeper monster structure */
|
||||
if(!(shk = makemon(&mons[PM_SHOPKEEPER], sx, sy, MM_ESHK)))
|
||||
return(-1);
|
||||
eshkp = ESHK(shk); /* makemon(...,MM_ESHK) allocates this */
|
||||
shk->isshk = shk->mpeaceful = 1;
|
||||
set_malign(shk);
|
||||
shk->msleeping = 0;
|
||||
shk->mtrapseen = ~0; /* we know all the traps already */
|
||||
ESHK(shk)->shoproom = (schar)((sroom - rooms) + ROOMOFFSET);
|
||||
eshkp->shoproom = (schar)((sroom - rooms) + ROOMOFFSET);
|
||||
sroom->resident = shk;
|
||||
ESHK(shk)->shoptype = sroom->rtype;
|
||||
assign_level(&(ESHK(shk)->shoplevel), &u.uz);
|
||||
ESHK(shk)->shd = doors[sh];
|
||||
ESHK(shk)->shk.x = sx;
|
||||
ESHK(shk)->shk.y = sy;
|
||||
ESHK(shk)->robbed = 0L;
|
||||
ESHK(shk)->credit = 0L;
|
||||
ESHK(shk)->debit = 0L;
|
||||
ESHK(shk)->loan = 0L;
|
||||
ESHK(shk)->visitct = 0;
|
||||
ESHK(shk)->following = 0;
|
||||
ESHK(shk)->billct = 0;
|
||||
eshkp->shoptype = sroom->rtype;
|
||||
assign_level(&eshkp->shoplevel, &u.uz);
|
||||
eshkp->shd = doors[sh];
|
||||
eshkp->shk.x = sx;
|
||||
eshkp->shk.y = sy;
|
||||
eshkp->robbed = eshkp->credit = eshkp->debit = eshkp->loan = 0L;
|
||||
eshkp->following = eshkp->surcharge = eshkp->dismiss_kops = FALSE;
|
||||
eshkp->billct = eshkp->visitct = 0;
|
||||
eshkp->bill_p = (struct bill_x *)0;
|
||||
eshkp->customer[0] = '\0';
|
||||
#ifndef GOLDOBJ
|
||||
shk->mgold = 1000L + 30L*(long)rnd(100); /* initial capital */
|
||||
#else
|
||||
|
||||
Reference in New Issue
Block a user