deal with gold leaving shop via scatter()

fixes #538
This commit is contained in:
nhmall
2021-07-10 19:41:55 -04:00
parent a4711739c0
commit ed9647310a
4 changed files with 87 additions and 17 deletions

View File

@@ -2355,7 +2355,7 @@ extern void price_quote(struct obj *);
extern void shk_chat(struct monst *);
extern void check_unpaid_usage(struct obj *, boolean);
extern void check_unpaid(struct obj *);
extern void costly_gold(xchar, xchar, long);
extern void costly_gold(xchar, xchar, long, boolean);
extern long get_cost_of_shop_item(struct obj *, int *);
extern int oid_price_adjustment(struct obj *, unsigned);
extern boolean block_door(xchar, xchar);
@@ -2364,6 +2364,7 @@ extern char *shk_your(char *, struct obj *);
extern char *Shk_Your(char *, struct obj *);
extern void globby_bill_fixup(struct obj *, struct obj *);
extern void globby_donation(struct obj *, struct obj *);
extern void credit_report(struct monst *shkp, int idx, boolean silent);
/* ### shknam.c ### */

View File

@@ -689,7 +689,7 @@ really_kick_object(xchar x, xchar y)
if (costly && (!costly_spot(g.bhitpos.x, g.bhitpos.y)
|| *in_rooms(x, y, SHOPBASE) != bhitroom)) {
if (isgold)
costly_gold(x, y, g.kickedobj->quan);
costly_gold(x, y, g.kickedobj->quan, FALSE);
else
(void) stolen_value(g.kickedobj, x, y, (boolean) shkp->mpeaceful,
FALSE);

View File

@@ -644,7 +644,8 @@ scatter(int sx, int sy, /* location of objects to scatter */
long qtmp;
boolean used_up;
boolean individual_object = obj ? TRUE : FALSE;
struct monst *mtmp;
boolean shop_origin, lostgoods = FALSE;
struct monst *mtmp, *shkp = 0;
struct scatter_chain *stmp, *stmp2 = 0;
struct scatter_chain *schain = (struct scatter_chain *) 0;
long total = 0L;
@@ -653,6 +654,11 @@ scatter(int sx, int sy, /* location of objects to scatter */
impossible("scattered object <%d,%d> not at scatter site <%d,%d>",
obj->ox, obj->oy, sx, sy);
shop_origin = ((shkp = shop_keeper(*in_rooms(sx, sy, SHOPBASE))) != 0
&& costly_spot(sx, sy));
if (shop_origin)
credit_report(shkp, 0, TRUE); /* establish baseline, without msgs */
while ((otmp = (individual_object ? obj : g.level.objects[sx][sy])) != 0) {
if (otmp == uball || otmp == uchain) {
boolean waschain = (otmp == uchain);
@@ -792,14 +798,35 @@ scatter(int sx, int sy, /* location of objects to scatter */
}
for (stmp = schain; stmp; stmp = stmp2) {
int x, y;
boolean obj_left_shop = FALSE;
stmp2 = stmp->next;
x = stmp->ox;
y = stmp->oy;
if (stmp->obj) {
if (x != sx || y != sy)
if (x != sx || y != sy) {
total += stmp->obj->quan;
obj_left_shop = (shop_origin && !costly_spot(x, y));
}
if (!flooreffects(stmp->obj, x, y, "land")) {
if (obj_left_shop
&& index(u.urooms, *in_rooms(u.ux, u.uy, SHOPBASE))) {
/* At the moment this only takes on gold. While it is
simple enough to call addtobill for other items that
leave the shop due to scatter(), by default the hero
will get billed for the full shopkeeper asking-price
on the object's way out of shop. That can leave the
hero in a pickle. Even if the hero then manages to
retrieve the item and drop it back inside the shop,
the owed charges will only be reduced at that point
by the lesser shopkeeper buying-price.
The non-gold situation will likely get adjusted further.
*/
if (stmp->obj->otyp == GOLD_PIECE) {
addtobill(stmp->obj, FALSE, FALSE, TRUE);
lostgoods = TRUE;
}
}
place_object(stmp->obj, x, y);
stackobj(stmp->obj);
}
@@ -811,6 +838,8 @@ scatter(int sx, int sy, /* location of objects to scatter */
if (sx == u.ux && sy == u.uy && u.uundetected
&& hides_under(g.youmonst.data))
(void) hideunder(&g.youmonst);
if (lostgoods) /* implies shop_origin and therefore shkp valid */
credit_report(shkp, 1, FALSE);
return total;
}

View File

@@ -432,6 +432,42 @@ u_left_shop(char* leavestring, boolean newlev)
}
}
void
credit_report(struct monst *shkp, int idx, boolean silent)
{
struct eshk *eshkp = ESHK(shkp);
static long credit_snap[2][3] = {{0L, 0L, 0L}, {0L, 0L, 0L}};
if (!idx) {
credit_snap[BEFORE][0] = credit_snap[NOW][0] = 0L;
credit_snap[BEFORE][1] = credit_snap[NOW][1] = 0L;
credit_snap[BEFORE][2] = credit_snap[NOW][2] = 0L;
} else {
idx = 1;
}
credit_snap[idx][0] = eshkp->credit;
credit_snap[idx][1] = eshkp->debit;
credit_snap[idx][2] = eshkp->loan;
if (idx && !silent) {
long amt = 0L;
const char *msg = "debt has increased";
if (credit_snap[NOW][0] < credit_snap[BEFORE][0]) {
amt = credit_snap[BEFORE][0] - credit_snap[NOW][0];
msg = "credit has been reduced";
} else if (credit_snap[NOW][1] > credit_snap[BEFORE][1]) {
amt = credit_snap[NOW][1] - credit_snap[BEFORE][1];
} else if (credit_snap[NOW][2] > credit_snap[BEFORE][2]) {
amt = credit_snap[NOW][2] - credit_snap[BEFORE][2];
}
if (amt)
Your("%s by %ld %s.", msg, amt, currency(amt));
}
}
/* robbery from outside the shop via telekinesis or grappling hook */
void
remote_burglary(xchar x, xchar y)
@@ -2573,7 +2609,7 @@ addtobill(
return;
if (obj->oclass == COIN_CLASS) {
costly_gold(obj->ox, obj->oy, obj->quan);
costly_gold(obj->ox, obj->oy, obj->quan, silent);
return;
} else if (ESHK(shkp)->billct == BILLSZ) {
if (!silent)
@@ -2607,7 +2643,7 @@ addtobill(
ltmp += cltmp;
if (gltmp) {
costly_gold(obj->ox, obj->oy, gltmp);
costly_gold(obj->ox, obj->oy, gltmp, silent);
if (!ltmp)
return;
}
@@ -4574,7 +4610,7 @@ check_unpaid(struct obj* otmp)
}
void
costly_gold(register xchar x, register xchar y, register long amount)
costly_gold(xchar x, xchar y, long amount, boolean silent)
{
register long delta;
register struct monst *shkp;
@@ -4587,19 +4623,23 @@ costly_gold(register xchar x, register xchar y, register long amount)
eshkp = ESHK(shkp);
if (eshkp->credit >= amount) {
if (eshkp->credit > amount)
Your("credit is reduced by %ld %s.", amount, currency(amount));
else
Your("credit is erased.");
if (!silent) {
if (eshkp->credit > amount)
Your("credit is reduced by %ld %s.", amount, currency(amount));
else
Your("credit is erased.");
}
eshkp->credit -= amount;
} else {
delta = amount - eshkp->credit;
if (eshkp->credit)
Your("credit is erased.");
if (eshkp->debit)
Your("debt increases by %ld %s.", delta, currency(delta));
else
You("owe %s %ld %s.", shkname(shkp), delta, currency(delta));
if (!silent) {
if (eshkp->credit)
Your("credit is erased.");
if (eshkp->debit)
Your("debt increases by %ld %s.", delta, currency(delta));
else
You("owe %s %ld %s.", shkname(shkp), delta, currency(delta));
}
eshkp->debit += delta;
eshkp->loan += delta;
eshkp->credit = 0L;