Shopkeepers hold a grudge against past thieves
When you steal from a shop, its shopkeeper will remember you as a thief and charge you higher prices in the future (as well as be more curt and less polite in interactions with you, though not outright hostile) even if you pacify them, or die on the level and revisit it later as a bones file. This was an idea aosdict had, and I think it makes sense that a shopkeeper doesn't forgive and forget, immediately returning to treating you exactly like anyone else, just because you were terrorized into paying her back. Paying a shopkeeper off may cause her to stop actively attacking you, but it feels like she'd have her eye on you as a known thief going forward (and maybe would hang up a sign with your picture, saying something like "DO NOT ACCEPT CHECKS FROM THIS HERO"). This surchage already existed, but since it was tied to active anger (which typically causes a shopkeeper to quickly abandon their shop to follow you) it was somewhat rare to see it in action. I did not implement it here, but one possible further tweak might be to clear the surcharge if the shopkeeper is pacified via taming magic (which more-or-less magically brainwashes the target to feel positively towards the hero) but not if you simply pay your debts.
This commit is contained in:
committed by
Pasi Kallinen
parent
94e8141c01
commit
8a549b0a60
77
src/shk.c
77
src/shk.c
@@ -28,7 +28,7 @@ static const char the_contents_of[] = "the contents of ";
|
|||||||
|
|
||||||
static void append_honorific(char *);
|
static void append_honorific(char *);
|
||||||
static long addupbill(struct monst *);
|
static long addupbill(struct monst *);
|
||||||
static void pacify_shk(struct monst *);
|
static void pacify_shk(struct monst *, boolean);
|
||||||
static struct bill_x *onbill(struct obj *, struct monst *, boolean);
|
static struct bill_x *onbill(struct obj *, struct monst *, boolean);
|
||||||
static struct monst *next_shkp(struct monst *, boolean);
|
static struct monst *next_shkp(struct monst *, boolean);
|
||||||
static long shop_debt(struct eshk *);
|
static long shop_debt(struct eshk *);
|
||||||
@@ -166,10 +166,7 @@ next_shkp(register struct monst *shkp, boolean withbill)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (shkp) {
|
if (shkp) {
|
||||||
if (NOTANGRY(shkp)) {
|
if (ANGRY(shkp)) {
|
||||||
if (ESHK(shkp)->surcharge)
|
|
||||||
pacify_shk(shkp);
|
|
||||||
} else {
|
|
||||||
if (!ESHK(shkp)->surcharge)
|
if (!ESHK(shkp)->surcharge)
|
||||||
rile_shk(shkp);
|
rile_shk(shkp);
|
||||||
}
|
}
|
||||||
@@ -246,7 +243,7 @@ restshk(struct monst* shkp, boolean ghostly)
|
|||||||
if (ghostly) {
|
if (ghostly) {
|
||||||
assign_level(&eshkp->shoplevel, &u.uz);
|
assign_level(&eshkp->shoplevel, &u.uz);
|
||||||
if (ANGRY(shkp) && strncmpi(eshkp->customer, g.plname, PL_NSIZ))
|
if (ANGRY(shkp) && strncmpi(eshkp->customer, g.plname, PL_NSIZ))
|
||||||
pacify_shk(shkp);
|
pacify_shk(shkp, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -413,15 +410,16 @@ u_left_shop(char *leavestring, boolean newlev)
|
|||||||
* Player just stepped onto shop-boundary (known from above logic).
|
* Player just stepped onto shop-boundary (known from above logic).
|
||||||
* Try to intimidate him into paying his bill
|
* Try to intimidate him into paying his bill
|
||||||
*/
|
*/
|
||||||
|
boolean not_upset = !eshkp->surcharge;
|
||||||
if (!Deaf && !muteshk(shkp))
|
if (!Deaf && !muteshk(shkp))
|
||||||
verbalize(NOTANGRY(shkp) ? "%s! Please pay before leaving."
|
verbalize(not_upset ? "%s! Please pay before leaving."
|
||||||
: "%s! Don't you leave without paying!",
|
: "%s! Don't you leave without paying!",
|
||||||
g.plname);
|
g.plname);
|
||||||
else
|
else
|
||||||
pline("%s %s that you need to pay before leaving%s",
|
pline("%s %s that you need to pay before leaving%s",
|
||||||
Shknam(shkp),
|
Shknam(shkp),
|
||||||
NOTANGRY(shkp) ? "points out" : "makes it clear",
|
not_upset ? "points out" : "makes it clear",
|
||||||
NOTANGRY(shkp) ? "." : "!");
|
not_upset ? "." : "!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -594,7 +592,7 @@ u_entered_shop(char* enterstring)
|
|||||||
eshkp->visitct = 0;
|
eshkp->visitct = 0;
|
||||||
eshkp->following = 0;
|
eshkp->following = 0;
|
||||||
(void) strncpy(eshkp->customer, g.plname, PL_NSIZ);
|
(void) strncpy(eshkp->customer, g.plname, PL_NSIZ);
|
||||||
pacify_shk(shkp);
|
pacify_shk(shkp, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (muteshk(shkp) || eshkp->following)
|
if (muteshk(shkp) || eshkp->following)
|
||||||
@@ -620,6 +618,13 @@ u_entered_shop(char* enterstring)
|
|||||||
pline("%s seems %s over your return to %s %s!",
|
pline("%s seems %s over your return to %s %s!",
|
||||||
Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
|
Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
|
||||||
noit_mhis(shkp), shtypes[rt - SHOPBASE].name);
|
noit_mhis(shkp), shtypes[rt - SHOPBASE].name);
|
||||||
|
} else if (eshkp->surcharge) {
|
||||||
|
if (!Deaf && !muteshk(shkp))
|
||||||
|
verbalize("Back again, %s? I've got my %s on you.",
|
||||||
|
g.plname, mbodypart(shkp, EYE));
|
||||||
|
else
|
||||||
|
pline_The("atmosphere at %s %s seems unwelcoming.",
|
||||||
|
s_suffix(shkname(shkp)), shtypes[rt - SHOPBASE].name);
|
||||||
} else if (eshkp->robbed) {
|
} else if (eshkp->robbed) {
|
||||||
if (!Deaf)
|
if (!Deaf)
|
||||||
pline("%s mutters imprecations against shoplifters.",
|
pline("%s mutters imprecations against shoplifters.",
|
||||||
@@ -640,7 +645,7 @@ u_entered_shop(char* enterstring)
|
|||||||
}
|
}
|
||||||
/* can't do anything about blocking if teleported in */
|
/* can't do anything about blocking if teleported in */
|
||||||
if (!inside_shop(u.ux, u.uy)) {
|
if (!inside_shop(u.ux, u.uy)) {
|
||||||
boolean should_block;
|
boolean should_block, not_upset = !eshkp->surcharge;
|
||||||
int cnt;
|
int cnt;
|
||||||
const char *tool;
|
const char *tool;
|
||||||
struct obj *pick = carrying(PICK_AXE),
|
struct obj *pick = carrying(PICK_AXE),
|
||||||
@@ -667,25 +672,25 @@ u_entered_shop(char* enterstring)
|
|||||||
makeknown(DWARVISH_MATTOCK);
|
makeknown(DWARVISH_MATTOCK);
|
||||||
}
|
}
|
||||||
if (!Deaf && !muteshk(shkp))
|
if (!Deaf && !muteshk(shkp))
|
||||||
verbalize(NOTANGRY(shkp)
|
verbalize(not_upset
|
||||||
? "Will you please leave your %s%s outside?"
|
? "Will you please leave your %s%s outside?"
|
||||||
: "Leave the %s%s outside.",
|
: "Leave the %s%s outside.",
|
||||||
tool, plur(cnt));
|
tool, plur(cnt));
|
||||||
else
|
else
|
||||||
pline("%s %s to let you in with your %s%s.",
|
pline("%s %s to let you in with your %s%s.",
|
||||||
Shknam(shkp),
|
Shknam(shkp),
|
||||||
NOTANGRY(shkp) ? "is hesitant" : "refuses",
|
not_upset ? "is hesitant" : "refuses",
|
||||||
tool, plur(cnt));
|
tool, plur(cnt));
|
||||||
should_block = TRUE;
|
should_block = TRUE;
|
||||||
} else if (u.usteed) {
|
} else if (u.usteed) {
|
||||||
if (!Deaf && !muteshk(shkp))
|
if (!Deaf && !muteshk(shkp))
|
||||||
verbalize(NOTANGRY(shkp) ? "Will you please leave %s outside?"
|
verbalize(not_upset ? "Will you please leave %s outside?"
|
||||||
: "Leave %s outside.",
|
: "Leave %s outside.",
|
||||||
y_monnam(u.usteed));
|
y_monnam(u.usteed));
|
||||||
else
|
else
|
||||||
pline("%s %s to let you in while you're riding %s.",
|
pline("%s %s to let you in while you're riding %s.",
|
||||||
Shknam(shkp),
|
Shknam(shkp),
|
||||||
NOTANGRY(shkp) ? "doesn't want" : "refuses",
|
not_upset ? "doesn't want" : "refuses",
|
||||||
y_monnam(u.usteed));
|
y_monnam(u.usteed));
|
||||||
should_block = TRUE;
|
should_block = TRUE;
|
||||||
} else {
|
} else {
|
||||||
@@ -832,10 +837,7 @@ shop_keeper(char rmno)
|
|||||||
shkp = (rmno >= ROOMOFFSET) ? g.rooms[rmno - ROOMOFFSET].resident : 0;
|
shkp = (rmno >= ROOMOFFSET) ? g.rooms[rmno - ROOMOFFSET].resident : 0;
|
||||||
if (shkp) {
|
if (shkp) {
|
||||||
if (has_eshk(shkp)) {
|
if (has_eshk(shkp)) {
|
||||||
if (NOTANGRY(shkp)) {
|
if (ANGRY(shkp)) {
|
||||||
if (ESHK(shkp)->surcharge)
|
|
||||||
pacify_shk(shkp);
|
|
||||||
} else {
|
|
||||||
if (!ESHK(shkp)->surcharge)
|
if (!ESHK(shkp)->surcharge)
|
||||||
rile_shk(shkp);
|
rile_shk(shkp);
|
||||||
}
|
}
|
||||||
@@ -1070,10 +1072,10 @@ angry_shk_exists(void)
|
|||||||
|
|
||||||
/* remove previously applied surcharge from all billed items */
|
/* remove previously applied surcharge from all billed items */
|
||||||
static void
|
static void
|
||||||
pacify_shk(register struct monst* shkp)
|
pacify_shk(register struct monst* shkp, boolean clear_surcharge)
|
||||||
{
|
{
|
||||||
NOTANGRY(shkp) = TRUE; /* make peaceful */
|
NOTANGRY(shkp) = TRUE; /* make peaceful */
|
||||||
if (ESHK(shkp)->surcharge) {
|
if (clear_surcharge && ESHK(shkp)->surcharge) {
|
||||||
register struct bill_x *bp = ESHK(shkp)->bill_p;
|
register struct bill_x *bp = ESHK(shkp)->bill_p;
|
||||||
register int ct = ESHK(shkp)->billct;
|
register int ct = ESHK(shkp)->billct;
|
||||||
|
|
||||||
@@ -1125,7 +1127,7 @@ make_happy_shk(register struct monst* shkp, register boolean silentkops)
|
|||||||
boolean wasmad = ANGRY(shkp);
|
boolean wasmad = ANGRY(shkp);
|
||||||
struct eshk *eshkp = ESHK(shkp);
|
struct eshk *eshkp = ESHK(shkp);
|
||||||
|
|
||||||
pacify_shk(shkp);
|
pacify_shk(shkp, FALSE);
|
||||||
eshkp->following = 0;
|
eshkp->following = 0;
|
||||||
eshkp->robbed = 0L;
|
eshkp->robbed = 0L;
|
||||||
if (!Role_if(PM_ROGUE))
|
if (!Role_if(PM_ROGUE))
|
||||||
@@ -1559,13 +1561,15 @@ dopay(void)
|
|||||||
}
|
}
|
||||||
if (!ANGRY(shkp) && paid) {
|
if (!ANGRY(shkp) && paid) {
|
||||||
if (!Deaf && !muteshk(shkp))
|
if (!Deaf && !muteshk(shkp))
|
||||||
verbalize("Thank you for shopping in %s %s!",
|
verbalize("Thank you for shopping in %s %s%s",
|
||||||
s_suffix(shkname(shkp)),
|
s_suffix(shkname(shkp)),
|
||||||
shtypes[eshkp->shoptype - SHOPBASE].name);
|
shtypes[eshkp->shoptype - SHOPBASE].name,
|
||||||
|
!eshkp->surcharge ? "!" : ".");
|
||||||
else
|
else
|
||||||
pline("%s nods appreciatively at you for shopping in %s %s!",
|
pline("%s nods%s at you for shopping in %s %s%s",
|
||||||
Shknam(shkp), noit_mhis(shkp),
|
Shknam(shkp), !eshkp->surcharge ? " appreciatively" : "",
|
||||||
shtypes[eshkp->shoptype - SHOPBASE].name);
|
noit_mhis(shkp), shtypes[eshkp->shoptype - SHOPBASE].name,
|
||||||
|
!eshkp->surcharge ? "!" : ".");
|
||||||
}
|
}
|
||||||
return ECMD_TIME;
|
return ECMD_TIME;
|
||||||
}
|
}
|
||||||
@@ -1865,7 +1869,7 @@ inherits(struct monst* shkp, int numsk, int croaked, boolean silently)
|
|||||||
: "you ",
|
: "you ",
|
||||||
noit_mhim(shkp));
|
noit_mhim(shkp));
|
||||||
/* shopkeeper has now been paid in full */
|
/* shopkeeper has now been paid in full */
|
||||||
pacify_shk(shkp);
|
pacify_shk(shkp, FALSE);
|
||||||
eshkp->following = 0;
|
eshkp->following = 0;
|
||||||
eshkp->robbed = 0L;
|
eshkp->robbed = 0L;
|
||||||
}
|
}
|
||||||
@@ -2713,10 +2717,11 @@ addtobill(
|
|||||||
} else {
|
} else {
|
||||||
long save_quan = obj->quan;
|
long save_quan = obj->quan;
|
||||||
|
|
||||||
Strcpy(buf, "\"For you, ");
|
Strcpy(buf, "\"For you,");
|
||||||
if (ANGRY(shkp)) {
|
if (ANGRY(shkp)) {
|
||||||
Strcat(buf, "scum;");
|
Strcat(buf, " scum;");
|
||||||
} else {
|
} else if (!ESHK(shkp)->surcharge) {
|
||||||
|
Strcat(buf, " ");
|
||||||
append_honorific(buf);
|
append_honorific(buf);
|
||||||
Strcat(buf, "; only");
|
Strcat(buf, "; only");
|
||||||
}
|
}
|
||||||
@@ -4339,7 +4344,7 @@ pay_for_damage(const char* dmgstr, boolean cant_mollify)
|
|||||||
pline("Mollified, %s accepts your restitution.", shkname(shkp));
|
pline("Mollified, %s accepts your restitution.", shkname(shkp));
|
||||||
/* move shk back to his home loc */
|
/* move shk back to his home loc */
|
||||||
home_shk(shkp, FALSE);
|
home_shk(shkp, FALSE);
|
||||||
pacify_shk(shkp);
|
pacify_shk(shkp, FALSE);
|
||||||
/* home_shk() suppresses rloc()'s vanish/appear messages */
|
/* home_shk() suppresses rloc()'s vanish/appear messages */
|
||||||
if (shkp->mx != sx || shkp->my != sy) {
|
if (shkp->mx != sx || shkp->my != sy) {
|
||||||
if (was_outside && canspotmon(shkp))
|
if (was_outside && canspotmon(shkp))
|
||||||
@@ -4569,6 +4574,10 @@ shk_chat(struct monst* shkp)
|
|||||||
pline("%s %s about a recent robbery.",
|
pline("%s %s about a recent robbery.",
|
||||||
Shknam(shkp),
|
Shknam(shkp),
|
||||||
(!Deaf && !muteshk(shkp)) ? "complains" : "indicates concern");
|
(!Deaf && !muteshk(shkp)) ? "complains" : "indicates concern");
|
||||||
|
} else if (eshk->surcharge) {
|
||||||
|
pline("%s %s that %s is watching you carefully.", Shknam(shkp),
|
||||||
|
(!Deaf && !muteshk(shkp)) ? "warns you" : "indicates",
|
||||||
|
noit_mhe(shkp));
|
||||||
} else if ((shkmoney = money_cnt(shkp->minvent)) < 50L) {
|
} else if ((shkmoney = money_cnt(shkp->minvent)) < 50L) {
|
||||||
pline("%s %s that business is bad.",
|
pline("%s %s that business is bad.",
|
||||||
Shknam(shkp),
|
Shknam(shkp),
|
||||||
|
|||||||
Reference in New Issue
Block a user