Fix: bill_dummy_obj billed excessively for stacks

Add a way to request that unpaid_cost() produce the cost for a single
item, which is necessary for the price adjustment made in
bill_dummy_object.  Another option would be to simply divide by quan in
bill_dummy_object, but this might be more future-proof in case
unpaid_cost ever involves more than simple multiplication by quan
(e.g. the use of alternate units vs the base price, as are used for
globs).

Fixes #1236
This commit is contained in:
Michael Meyer
2024-04-27 11:22:48 -04:00
committed by PatR
parent 1f8db3a0f3
commit b662134eba
7 changed files with 24 additions and 11 deletions

View File

@@ -314,7 +314,7 @@ dog_eat(struct monst *mtmp,
if (obj->unpaid) {
/* edible item owned by shop has been thrown or kicked
by hero and caught by tame or food-tameable monst */
oprice = unpaid_cost(obj, TRUE);
oprice = unpaid_cost(obj, COST_CONTENTS);
pline("That %s will cost you %ld %s.", objnambuf, oprice,
currency(oprice));
/* m_consume_obj->delobj->obfree will handle actual shop billing update */

View File

@@ -4110,7 +4110,7 @@ dounpaid(
}
if (otmp && !contnr) {
/* 1 item; use pline instead of popup menu */
cost = unpaid_cost(otmp, FALSE);
cost = unpaid_cost(otmp, COST_NOCONTENTS);
iflags.suppress_price++; /* suppress "(unpaid)" suffix */
pline1(xprname(otmp, distant_name(otmp, doname),
carried(otmp) ? otmp->invlet : CONTAINED_SYM,
@@ -4136,7 +4136,7 @@ dounpaid(
classcount++;
}
totcost += cost = unpaid_cost(otmp, FALSE);
totcost += cost = unpaid_cost(otmp, COST_NOCONTENTS);
iflags.suppress_price++; /* suppress "(unpaid)" suffix */
putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
ilet, TRUE, cost, 0L));
@@ -4162,7 +4162,7 @@ dounpaid(
marker = (struct obj *) 0; /* haven't found any */
while (find_unpaid(otmp->cobj, &marker)) {
totcost += cost = unpaid_cost(marker, FALSE);
totcost += cost = unpaid_cost(marker, COST_NOCONTENTS);
contcost += cost;
if (otmp->cknown) {
iflags.suppress_price++; /* suppress "(unpaid)" sfx */

View File

@@ -710,7 +710,7 @@ bill_dummy_object(struct obj *otmp)
long cost = 0L;
if (otmp->unpaid) {
cost = unpaid_cost(otmp, FALSE);
cost = unpaid_cost(otmp, COST_SINGLEOBJ);
subfrombill(otmp, shop_keeper(*u.ushops));
}
dummy = newobj();

View File

@@ -1624,7 +1624,7 @@ doname_base(
; /* don't attempt to obtain any shop pricing, even if 'with_price' */
} else if (is_unpaid(obj)) { /* in inventory or in container in invent */
char pricebuf[40];
long quotedprice = unpaid_cost(obj, TRUE);
long quotedprice = unpaid_cost(obj, COST_CONTENTS);
/* separately formatted suffix avoids need for ConcatF3() */
Sprintf(pricebuf, "%ld %s", quotedprice, currency(quotedprice));

View File

@@ -2705,7 +2705,7 @@ alter_cost(
long
unpaid_cost(
struct obj *unp_obj, /* known to be unpaid or contain unpaid */
boolean include_contents)
uchar cost_type) /* COST_NOCONTENTS, COST_CONTENTS, or COST_SINGLEOBJ */
{
struct bill_x *bp = (struct bill_x *) 0;
struct monst *shkp = 0;
@@ -2729,9 +2729,15 @@ unpaid_cost(
#endif
for (shop = u.ushops; *shop; shop++) {
if ((shkp = shop_keeper(*shop)) != 0) {
if ((bp = onbill(unp_obj, shkp, TRUE)))
amt = unp_obj->quan * bp->price;
if (include_contents && Has_contents(unp_obj))
if ((bp = onbill(unp_obj, shkp, TRUE))) {
amt = bp->price;
if (cost_type != COST_SINGLEOBJ) {
/* use quan rather than get_pricing_units -- glob weight
should already be factored into bp->price */
amt *= unp_obj->quan;
}
}
if (cost_type == COST_CONTENTS && Has_contents(unp_obj))
amt = contained_cost(unp_obj, shkp, amt, FALSE, TRUE);
if (bp || (!unp_obj->unpaid && amt))
break;