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:
@@ -2809,7 +2809,7 @@ extern long contained_gold(struct obj *, boolean) NONNULLARG1;
|
|||||||
extern void picked_container(struct obj *) NONNULLARG1;
|
extern void picked_container(struct obj *) NONNULLARG1;
|
||||||
extern void gem_learned(int);
|
extern void gem_learned(int);
|
||||||
extern void alter_cost(struct obj *, long) NONNULLARG1;
|
extern void alter_cost(struct obj *, long) NONNULLARG1;
|
||||||
extern long unpaid_cost(struct obj *, boolean) NONNULLARG1;
|
extern long unpaid_cost(struct obj *, uchar) NONNULLARG1;
|
||||||
extern boolean billable(struct monst **, struct obj *, char,
|
extern boolean billable(struct monst **, struct obj *, char,
|
||||||
boolean) NONNULLARG12;
|
boolean) NONNULLARG12;
|
||||||
extern void addtobill(struct obj *, boolean, boolean, boolean) NONNULLARG1;
|
extern void addtobill(struct obj *, boolean, boolean, boolean) NONNULLARG1;
|
||||||
|
|||||||
@@ -308,6 +308,13 @@ enum cost_alteration_types {
|
|||||||
COST_CRACK = 19, /* damage to crystal armor */
|
COST_CRACK = 19, /* damage to crystal armor */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* used by unpaid_cost(shk.h) */
|
||||||
|
enum unpaid_cost_flags {
|
||||||
|
COST_NOCONTENTS = 0,
|
||||||
|
COST_CONTENTS = 1,
|
||||||
|
COST_SINGLEOBJ = 2,
|
||||||
|
};
|
||||||
|
|
||||||
/* read.c, create_particular() & create_particular_parse() */
|
/* read.c, create_particular() & create_particular_parse() */
|
||||||
struct _create_particular_data {
|
struct _create_particular_data {
|
||||||
int quan;
|
int quan;
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ dog_eat(struct monst *mtmp,
|
|||||||
if (obj->unpaid) {
|
if (obj->unpaid) {
|
||||||
/* edible item owned by shop has been thrown or kicked
|
/* edible item owned by shop has been thrown or kicked
|
||||||
by hero and caught by tame or food-tameable monst */
|
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,
|
pline("That %s will cost you %ld %s.", objnambuf, oprice,
|
||||||
currency(oprice));
|
currency(oprice));
|
||||||
/* m_consume_obj->delobj->obfree will handle actual shop billing update */
|
/* m_consume_obj->delobj->obfree will handle actual shop billing update */
|
||||||
|
|||||||
@@ -4110,7 +4110,7 @@ dounpaid(
|
|||||||
}
|
}
|
||||||
if (otmp && !contnr) {
|
if (otmp && !contnr) {
|
||||||
/* 1 item; use pline instead of popup menu */
|
/* 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 */
|
iflags.suppress_price++; /* suppress "(unpaid)" suffix */
|
||||||
pline1(xprname(otmp, distant_name(otmp, doname),
|
pline1(xprname(otmp, distant_name(otmp, doname),
|
||||||
carried(otmp) ? otmp->invlet : CONTAINED_SYM,
|
carried(otmp) ? otmp->invlet : CONTAINED_SYM,
|
||||||
@@ -4136,7 +4136,7 @@ dounpaid(
|
|||||||
classcount++;
|
classcount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
totcost += cost = unpaid_cost(otmp, FALSE);
|
totcost += cost = unpaid_cost(otmp, COST_NOCONTENTS);
|
||||||
iflags.suppress_price++; /* suppress "(unpaid)" suffix */
|
iflags.suppress_price++; /* suppress "(unpaid)" suffix */
|
||||||
putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
|
putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
|
||||||
ilet, TRUE, cost, 0L));
|
ilet, TRUE, cost, 0L));
|
||||||
@@ -4162,7 +4162,7 @@ dounpaid(
|
|||||||
|
|
||||||
marker = (struct obj *) 0; /* haven't found any */
|
marker = (struct obj *) 0; /* haven't found any */
|
||||||
while (find_unpaid(otmp->cobj, &marker)) {
|
while (find_unpaid(otmp->cobj, &marker)) {
|
||||||
totcost += cost = unpaid_cost(marker, FALSE);
|
totcost += cost = unpaid_cost(marker, COST_NOCONTENTS);
|
||||||
contcost += cost;
|
contcost += cost;
|
||||||
if (otmp->cknown) {
|
if (otmp->cknown) {
|
||||||
iflags.suppress_price++; /* suppress "(unpaid)" sfx */
|
iflags.suppress_price++; /* suppress "(unpaid)" sfx */
|
||||||
|
|||||||
@@ -710,7 +710,7 @@ bill_dummy_object(struct obj *otmp)
|
|||||||
long cost = 0L;
|
long cost = 0L;
|
||||||
|
|
||||||
if (otmp->unpaid) {
|
if (otmp->unpaid) {
|
||||||
cost = unpaid_cost(otmp, FALSE);
|
cost = unpaid_cost(otmp, COST_SINGLEOBJ);
|
||||||
subfrombill(otmp, shop_keeper(*u.ushops));
|
subfrombill(otmp, shop_keeper(*u.ushops));
|
||||||
}
|
}
|
||||||
dummy = newobj();
|
dummy = newobj();
|
||||||
|
|||||||
@@ -1624,7 +1624,7 @@ doname_base(
|
|||||||
; /* don't attempt to obtain any shop pricing, even if 'with_price' */
|
; /* don't attempt to obtain any shop pricing, even if 'with_price' */
|
||||||
} else if (is_unpaid(obj)) { /* in inventory or in container in invent */
|
} else if (is_unpaid(obj)) { /* in inventory or in container in invent */
|
||||||
char pricebuf[40];
|
char pricebuf[40];
|
||||||
long quotedprice = unpaid_cost(obj, TRUE);
|
long quotedprice = unpaid_cost(obj, COST_CONTENTS);
|
||||||
|
|
||||||
/* separately formatted suffix avoids need for ConcatF3() */
|
/* separately formatted suffix avoids need for ConcatF3() */
|
||||||
Sprintf(pricebuf, "%ld %s", quotedprice, currency(quotedprice));
|
Sprintf(pricebuf, "%ld %s", quotedprice, currency(quotedprice));
|
||||||
|
|||||||
14
src/shk.c
14
src/shk.c
@@ -2705,7 +2705,7 @@ alter_cost(
|
|||||||
long
|
long
|
||||||
unpaid_cost(
|
unpaid_cost(
|
||||||
struct obj *unp_obj, /* known to be unpaid or contain unpaid */
|
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 bill_x *bp = (struct bill_x *) 0;
|
||||||
struct monst *shkp = 0;
|
struct monst *shkp = 0;
|
||||||
@@ -2729,9 +2729,15 @@ unpaid_cost(
|
|||||||
#endif
|
#endif
|
||||||
for (shop = u.ushops; *shop; shop++) {
|
for (shop = u.ushops; *shop; shop++) {
|
||||||
if ((shkp = shop_keeper(*shop)) != 0) {
|
if ((shkp = shop_keeper(*shop)) != 0) {
|
||||||
if ((bp = onbill(unp_obj, shkp, TRUE)))
|
if ((bp = onbill(unp_obj, shkp, TRUE))) {
|
||||||
amt = unp_obj->quan * bp->price;
|
amt = bp->price;
|
||||||
if (include_contents && Has_contents(unp_obj))
|
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);
|
amt = contained_cost(unp_obj, shkp, amt, FALSE, TRUE);
|
||||||
if (bp || (!unp_obj->unpaid && amt))
|
if (bp || (!unp_obj->unpaid && amt))
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user