diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 533a2f253..3c637f30b 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -382,6 +382,8 @@ all statues in a cockatrice nest were for giant ant if 'record' was empty when dying outside all shops on a level with multiple shopkeepers and one takes hero's stuff, choose one who is owed money over first one on fmon list hero poly'd into a critter without hands could still open tins +if a vault guard was killed, his inventory would be dropped at <0,0> +throwing gold to/at a vault guard will no longer be treated as an attack Platform- and/or Interface-Specific Fixes diff --git a/src/dokick.c b/src/dokick.c index 0d4babd3a..d76f1ff6d 100644 --- a/src/dokick.c +++ b/src/dokick.c @@ -252,8 +252,8 @@ register struct obj *gold; { boolean msg_given = FALSE; - if(!likes_gold(mtmp->data) && !mtmp->isshk && !mtmp->ispriest - && !is_mercenary(mtmp->data)) { + if (!likes_gold(mtmp->data) && !mtmp->isshk && !mtmp->ispriest && + !mtmp->isgd && !is_mercenary(mtmp->data)) { wakeup(mtmp); } else if (!mtmp->mcanmove) { /* too light to do real damage */ @@ -263,29 +263,23 @@ register struct obj *gold; msg_given = TRUE; } } else { -#ifdef GOLDOBJ - long value = gold->quan * objects[gold->otyp].oc_cost; -#endif + long umoney, value = gold->quan * objects[gold->otyp].oc_cost; + mtmp->msleeping = 0; finish_meating(mtmp); - if(!rn2(4)) setmangry(mtmp); /* not always pleasing */ - + if (!mtmp->isgd && !rn2(4)) /* not always pleasing */ + setmangry(mtmp); /* greedy monsters catch gold */ if (cansee(mtmp->mx, mtmp->my)) pline("%s catches the gold.", Monnam(mtmp)); -#ifndef GOLDOBJ - mtmp->mgold += gold->quan; -#endif + (void)mpickobj(mtmp, gold); + gold = (struct obj *)0; /* obj has been freed */ if (mtmp->isshk) { long robbed = ESHK(mtmp)->robbed; if (robbed) { -#ifndef GOLDOBJ - robbed -= gold->quan; -#else robbed -= value; -#endif - if (robbed < 0) robbed = 0; + if (robbed < 0L) robbed = 0L; pline_The("amount %scovers %s recent losses.", !robbed ? "" : "partially ", mhis(mtmp)); @@ -294,11 +288,7 @@ register struct obj *gold; make_happy_shk(mtmp, FALSE); } else { if(mtmp->mpeaceful) { -#ifndef GOLDOBJ - ESHK(mtmp)->credit += gold->quan; -#else ESHK(mtmp)->credit += value; -#endif You("have %ld %s in credit.", ESHK(mtmp)->credit, currency(ESHK(mtmp)->credit)); @@ -308,6 +298,23 @@ register struct obj *gold; if (mtmp->mpeaceful) verbalize("Thank you for your contribution."); else verbalize("Thanks, scum!"); + } else if (mtmp->isgd) { +#ifndef GOLDOBJ + umoney = u.ugold; +#else + umoney = money_cnt(invent); +#endif + /* Some of these are iffy, because a hostile guard + won't become peaceful and resume leading hero + out of the vault. If he did do that, player + could try fighting, then weasle out of being + killed by throwing his/her gold when losing. */ + verbalize(umoney ? "Drop the rest and follow me." : + hidden_gold() ? + "You still have hidden gold. Drop it now." : + mtmp->mpeaceful ? + "I'll take care of that; please move along." : + "I'll take that; now get moving."); } else if (is_mercenary(mtmp->data)) { long goldreqd = 0L; @@ -323,25 +330,19 @@ register struct obj *gold; if (goldreqd) { #ifndef GOLDOBJ - if (gold->quan > goldreqd + - (u.ugold + u.ulevel*rn2(5))/ACURR(A_CHA)) + umoney = u.ugold; #else - if (value > goldreqd + - (money_cnt(invent) + u.ulevel*rn2(5))/ACURR(A_CHA)) + umoney = money_cnt(invent); #endif - mtmp->mpeaceful = TRUE; + if (value > goldreqd + + (umoney + u.ulevel * rn2(5)) / ACURR(A_CHA)) + mtmp->mpeaceful = TRUE; } } if (mtmp->mpeaceful) verbalize("That should do. Now beat it!"); else verbalize("That's not enough, coward!"); } - -#ifndef GOLDOBJ - dealloc_obj(gold); -#else - add_to_minv(mtmp, gold); -#endif return TRUE; } diff --git a/src/mon.c b/src/mon.c index e36482dd1..214c2a482 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1261,17 +1261,17 @@ register int x,y; void dmonsfree() { - struct monst **mtmp; + struct monst **mtmp, *freetmp; int count = 0; for (mtmp = &fmon; *mtmp;) { - if ((*mtmp)->mhp <= 0) { - struct monst *freetmp = *mtmp; - *mtmp = (*mtmp)->nmon; + freetmp = *mtmp; + if (freetmp->mhp <= 0 && !freetmp->isgd) { + *mtmp = freetmp->nmon; dealloc_monst(freetmp); count++; } else - mtmp = &(*mtmp)->nmon; + mtmp = &(freetmp->nmon); } if (count != iflags.purge_monsters) @@ -1534,11 +1534,6 @@ register struct monst *mtmp; struct permonst *mptr; int tmp; - if(mtmp->isgd) { - /* if we're going to abort the death, it *must* be before - * the m_detach or there will be relmon problems later */ - if(!grddead(mtmp)) return; - } lifesaved_monster(mtmp); if (mtmp->mhp > 0) return; @@ -1588,6 +1583,11 @@ register struct monst *mtmp; } } + /* dead vault guard is actually kept at coordinate <0,0> until + his temporary corridor to/from the vault has been removed; + need to do this after life-saving and before m_detach() */ + if (mtmp->isgd && !grddead(mtmp)) return; + #ifdef STEED /* Player is thrown from his steed when it dies */ if (mtmp == u.usteed) diff --git a/src/steal.c b/src/steal.c index 32ffbf003..64b8deb7b 100644 --- a/src/steal.c +++ b/src/steal.c @@ -490,6 +490,10 @@ register struct obj *otmp; { int freed_otmp; + /* if monster is acquiring a thrown or kicked object, the throwing + or kicking code shouldn't continue to track and place it */ + if (otmp == thrownobj) thrownobj = 0; + else if (otmp == kickedobj) kickedobj = 0; #ifndef GOLDOBJ if (otmp->oclass == COIN_CLASS) { mtmp->mgold += otmp->quan; @@ -502,17 +506,13 @@ register struct obj *otmp; engulfers won't have external inventories; whirly monsters cause the light to be extinguished rather than letting it shine thru */ if (otmp->lamplit && /* hack to avoid function calls for most objs */ - obj_sheds_light(otmp) && + obj_sheds_light(otmp) && attacktype(mtmp->data, AT_ENGL)) { /* this is probably a burning object that you dropped or threw */ if (u.uswallow && mtmp == u.ustuck && !Blind) pline("%s out.", Tobjnam(otmp, "go")); snuff_otmp = TRUE; } - /* if monster is acquiring a thrown or kicked object, the throwing - or kicking code shouldn't continue to track and place it */ - if (otmp == thrownobj) thrownobj = 0; - else if (otmp == kickedobj) kickedobj = 0; /* for hero owned object on shop floor, mtmp is taking possession and if it's eventually dropped in a shop, shk will claim it */ if (!mtmp->mtame) otmp->no_charge = 0; @@ -686,6 +686,24 @@ boolean is_pet; /* If true, pet should keep wielded/worn items */ struct obj *otmp; int omx = mtmp->mx, omy = mtmp->my; + /* vault guard's gold goes away rather than be dropped... */ + if (mtmp->isgd && +#ifdef GOLDOBJ + (otmp = findgold(mtmp->minvent)) != 0 +#else + mtmp->mgold != 0L +#endif + ) { + if (canspotmon(mtmp)) + pline("%s gold %s.", s_suffix(Monnam(mtmp)), + canseemon(mtmp) ? "vanishes" : "seems to vanish"); +#ifdef GOLDOBJ + obfree(otmp, (struct obj *)0); +#else + mtmp->mgold = 0L; +#endif + } /* isgd && has gold */ + #ifndef GOLDOBJ /* handle gold first since droppables() would get stuck on it */ if (mtmp->mgold) { @@ -704,7 +722,7 @@ boolean is_pet; /* If true, pet should keep wielded/worn items */ mdrop_obj(mtmp, otmp, is_pet && flags.verbose); } - if (show & cansee(omx, omy)) + if (show && cansee(omx, omy)) newsym(omx, omy); } diff --git a/src/vault.c b/src/vault.c index eefb5f087..b46ce50bb 100644 --- a/src/vault.c +++ b/src/vault.c @@ -92,7 +92,10 @@ restfakecorr(grd) register struct monst *grd; { /* it seems you left the corridor - let the guard disappear */ - if(clear_fcorr(grd, FALSE)) mongone(grd); + if (clear_fcorr(grd, FALSE)) { + grd->isgd = 0; /* dmonsfree() should delete this mon */ + mongone(grd); + } } boolean @@ -101,7 +104,11 @@ register struct monst *grd; { register boolean dispose = clear_fcorr(grd, TRUE); - if(!dispose) { + if (!dispose) { + /* destroy guard's gold; drop any other inventory */ + relobj(grd, 0, FALSE); + /* guard is dead; monster traversal loops should skip it */ + grd->mhp = 0; /* see comment by newpos in gd_move() */ remove_monster(grd->mx, grd->my); newsym(grd->mx, grd->my); @@ -110,7 +117,8 @@ register struct monst *grd; EGD(grd)->ogy = grd->my; dispose = clear_fcorr(grd, TRUE); } - return(dispose); + if (dispose) grd->isgd = 0; /* for dmonsfree() */ + return dispose; } STATIC_OVL boolean @@ -175,9 +183,8 @@ invault() char buf[BUFSZ]; register int x, y, dd, gx, gy; int lx = 0, ly = 0; -#ifdef GOLDOBJ - long umoney; -#endif + long umoney; + /* first find the goal for the guard */ for(dd = 2; (dd < ROWNO || dd < COLNO); dd++) { for(y = u.uy-dd; y <= u.uy+dd; ly = y, y++) { @@ -331,29 +338,20 @@ fnd: } verbalize("I don't know you."); #ifndef GOLDOBJ - if (Deaf) + umoney = u.ugold; +#else + umoney = money_cnt(invent); +#endif + if (Deaf) { ; - else if (!u.ugold && !hidden_gold()) + } else if (!umoney && !hidden_gold()) { verbalize("Please follow me."); - else { - if (!u.ugold) + } else { + if (!umoney) verbalize("You have hidden gold."); verbalize("Most likely all your gold was stolen from this vault."); verbalize("Please drop that gold and follow me."); } -#else - umoney = money_cnt(invent); - if (Deaf) - ; - else if (!umoney && !hidden_gold()) - verbalize("Please follow me."); - else { - if (!umoney) - verbalize("You have hidden money."); - verbalize("Most likely all your money was stolen from this vault."); - verbalize("Please drop that money and follow me."); - } -#endif EGD(guard)->gdx = gx; EGD(guard)->gdy = gy; EGD(guard)->fcbeg = 0;