Artifact and #offer rebalance, part 1: sacrifice gifts
In 3.6, artifact gifts are often either a) entirely useless or b) gamebreaking, neither of which is really ideal from a balance perspective. This commit aims to make artifact gifts more useful in the early game by greatly increasing the chance for situational artifacts to generate positively enchanted. However, the most powerful artifacts will now only be gifted if you offer a high-value corpse, meaning that they are only likely to be accessible later in the game. The selection of which artifact to gift has become more complicated in order to a) increase the chance that it fits the character and b) reduce cheese strategies (e.g. it is no longer possible for elves to force the gifting of Stormbringer as the first sacrifice gift).
This commit is contained in:
@@ -142,13 +142,16 @@ artiname(int artinum)
|
||||
If no alignment is given, then 'otmp' is converted
|
||||
into an artifact of matching type, or returned as-is if that's not
|
||||
possible.
|
||||
For the 2nd case, caller should use ``obj = mk_artifact(obj, A_NONE);''
|
||||
for the 1st, ``obj = mk_artifact((struct obj *) 0, some_alignment);''.
|
||||
For the 2nd case, caller should use ``obj = mk_artifact(obj, A_NONE, 99);''
|
||||
For the 1st, ``obj = mk_artifact((struct obj *) 0, some_alignment, ...);''.
|
||||
The max_giftvalue is the value of the sacrifice, for an artifact obtained
|
||||
by sacrificing, or 99 otherwise.
|
||||
*/
|
||||
struct obj *
|
||||
mk_artifact(
|
||||
struct obj *otmp, /* existing object; ignored if alignment specified */
|
||||
aligntyp alignment) /* target alignment, or A_NONE */
|
||||
struct obj *otmp, /* existing object; ignored if alignment specified */
|
||||
aligntyp alignment, /* target alignment, or A_NONE */
|
||||
uchar max_giftvalue) /* cap on generated giftvalue */
|
||||
{
|
||||
const struct artifact *a;
|
||||
int m, n, altn;
|
||||
@@ -156,6 +159,7 @@ mk_artifact(
|
||||
short o_typ = (by_align || !otmp) ? 0 : otmp->otyp;
|
||||
boolean unique = !by_align && otmp && objects[o_typ].oc_unique;
|
||||
short eligible[NROFARTIFACTS];
|
||||
xint16 skill_compatibility;
|
||||
|
||||
n = altn = 0; /* no candidates found yet */
|
||||
eligible[0] = 0; /* lint suppression */
|
||||
@@ -165,6 +169,8 @@ mk_artifact(
|
||||
continue;
|
||||
if ((a->spfx & SPFX_NOGEN) || unique)
|
||||
continue;
|
||||
if (a->gift_value > max_giftvalue)
|
||||
continue;
|
||||
|
||||
if (!by_align) {
|
||||
/* looking for a particular type of item; not producing a
|
||||
@@ -186,17 +192,33 @@ mk_artifact(
|
||||
n = 1;
|
||||
break; /* skip all other candidates */
|
||||
}
|
||||
|
||||
/* check if this is skill-compatible */
|
||||
skill_compatibility = P_SKILLED;
|
||||
if (objects[a->otyp].oc_class == WEAPON_CLASS) {
|
||||
schar skill = objects[a->otyp].oc_skill;
|
||||
if (skill < 0)
|
||||
skill_compatibility = P_MAX_SKILL(-skill);
|
||||
else
|
||||
skill_compatibility = P_MAX_SKILL(skill);
|
||||
}
|
||||
|
||||
/* found something to consider for random selection */
|
||||
if (a->alignment != A_NONE || u.ugifts > 0) {
|
||||
if ((a->alignment != A_NONE || u.ugifts > 0 || !rn2(3)) &&
|
||||
(!rn2(4) || skill_compatibility >= P_SKILLED ||
|
||||
(skill_compatibility >= P_BASIC && rn2(2)))) {
|
||||
/* right alignment, or non-aligned with at least 1
|
||||
previous gift bestowed, makes this one viable */
|
||||
previous gift bestowed, makes this one viable;
|
||||
unaligned artifacts are possible even as the first
|
||||
gift, but less likely; if it's a bad weapon type
|
||||
for the role that also makes it less likely */
|
||||
eligible[n++] = m;
|
||||
} else {
|
||||
/* non-aligned with no previous gifts;
|
||||
if no candidates have been found yet, record
|
||||
/* if no candidates have been found yet, record
|
||||
this one as a[nother] fallback possibility in
|
||||
case all aligned candidates have been used up
|
||||
(via wishing, naming, bones, random generation) */
|
||||
(via wishing, naming, bones, random generation)
|
||||
or failed the randomized compatibility checks */
|
||||
if (!n)
|
||||
eligible[altn++] = m;
|
||||
/* [once a regular candidate is found, the list
|
||||
@@ -215,9 +237,20 @@ mk_artifact(
|
||||
a = &artilist[m];
|
||||
|
||||
/* make an appropriate object if necessary, then christen it */
|
||||
if (by_align)
|
||||
if (by_align) {
|
||||
int new_spe;
|
||||
|
||||
otmp = mksobj((int) a->otyp, TRUE, FALSE);
|
||||
|
||||
/* Adjust otmp->spe by a->gen_spe. (This is a no-op for
|
||||
non-weapons, which always have a gen_spe of 0, and for many
|
||||
weapons, too.) The result is clamped into the "normal" range to
|
||||
prevent an outside chance of +12 artifacts generating. */
|
||||
new_spe = (int)otmp->spe + a->gen_spe;
|
||||
if (new_spe >= -10 && new_spe < 10)
|
||||
otmp->spe = new_spe;
|
||||
}
|
||||
|
||||
if (otmp) {
|
||||
/* prevent erosion from generating */
|
||||
otmp->oeroded = otmp->oeroded2 = 0;
|
||||
|
||||
@@ -880,7 +880,7 @@ mksobj_init(struct obj *otmp, boolean artif)
|
||||
otmp->opoisoned = 1;
|
||||
|
||||
if (artif && !rn2(20 + (10 * nartifact_exist())))
|
||||
otmp = mk_artifact(otmp, (aligntyp) A_NONE);
|
||||
otmp = mk_artifact(otmp, (aligntyp) A_NONE, 99);
|
||||
break;
|
||||
case FOOD_CLASS:
|
||||
otmp->oeaten = 0;
|
||||
@@ -1084,7 +1084,7 @@ mksobj_init(struct obj *otmp, boolean artif)
|
||||
} else
|
||||
blessorcurse(otmp, 10);
|
||||
if (artif && !rn2(40 + (10 * nartifact_exist())))
|
||||
otmp = mk_artifact(otmp, (aligntyp) A_NONE);
|
||||
otmp = mk_artifact(otmp, (aligntyp) A_NONE, 99);
|
||||
/* simulate lacquered armor for samurai */
|
||||
if (Role_if(PM_SAMURAI) && otmp->otyp == SPLINT_MAIL
|
||||
&& (svm.moves <= 1 || In_quest(&u.uz))) {
|
||||
@@ -1230,7 +1230,7 @@ mksobj(int otyp, boolean init, boolean artif)
|
||||
|
||||
/* unique objects may have an associated artifact entry */
|
||||
if (objects[otyp].oc_unique && !otmp->oartifact)
|
||||
otmp = mk_artifact(otmp, (aligntyp) A_NONE);
|
||||
otmp = mk_artifact(otmp, (aligntyp) A_NONE, 99);
|
||||
otmp->owt = weight(otmp);
|
||||
return otmp;
|
||||
}
|
||||
|
||||
@@ -262,7 +262,7 @@ mk_mplayer(struct permonst *ptr, coordxy x, coordxy y, boolean special)
|
||||
else if (!rn2(2))
|
||||
otmp->greased = 1;
|
||||
if (special && rn2(2))
|
||||
otmp = mk_artifact(otmp, A_NONE);
|
||||
otmp = mk_artifact(otmp, A_NONE, 99);
|
||||
/* usually increase stack size if stackable weapon */
|
||||
if (objects[otmp->otyp].oc_merge && !otmp->oartifact
|
||||
&& monmightthrowwep(otmp))
|
||||
|
||||
25
src/pray.c
25
src/pray.c
@@ -27,7 +27,7 @@ staticfn void offer_negative_valued(boolean, aligntyp);
|
||||
staticfn void offer_fake_amulet(struct obj *, boolean, aligntyp);
|
||||
staticfn void offer_different_alignment_altar(struct obj *, aligntyp);
|
||||
staticfn void sacrifice_your_race(struct obj *, boolean, aligntyp);
|
||||
staticfn int bestow_artifact(void);
|
||||
staticfn int bestow_artifact(uchar);
|
||||
staticfn int sacrifice_value(struct obj *);
|
||||
staticfn int eval_offering(struct obj *, aligntyp);
|
||||
staticfn void offer_corpse(struct obj *, boolean, aligntyp);
|
||||
@@ -1777,17 +1777,24 @@ sacrifice_your_race(
|
||||
}
|
||||
|
||||
staticfn int
|
||||
bestow_artifact(void)
|
||||
bestow_artifact(uchar max_giftvalue)
|
||||
{
|
||||
int nartifacts = nartifact_exist();
|
||||
boolean do_bestow = u.ulevel > 2 && u.uluck >= 0;
|
||||
if (do_bestow) {
|
||||
/* you were already in pretty good standing */
|
||||
/* The player can gain an artifact */
|
||||
/* The chance goes down as the number of artifacts goes up */
|
||||
if (wizard)
|
||||
do_bestow = y_n("Gift an artifact?");
|
||||
else
|
||||
do_bestow = !rn2(6 + (2 * u.ugifts * nartifacts));
|
||||
}
|
||||
|
||||
/* you were already in pretty good standing */
|
||||
/* The player can gain an artifact */
|
||||
/* The chance goes down as the number of artifacts goes up */
|
||||
if (u.ulevel > 2 && u.uluck >= 0
|
||||
&& !rn2(10 + (2 * u.ugifts * nartifacts))) {
|
||||
if (do_bestow) {
|
||||
struct obj *otmp;
|
||||
otmp = mk_artifact((struct obj *) 0, a_align(u.ux, u.uy));
|
||||
otmp = mk_artifact((struct obj *) 0, a_align(u.ux, u.uy),
|
||||
max_giftvalue);
|
||||
if (otmp) {
|
||||
char buf[BUFSZ];
|
||||
|
||||
@@ -2078,7 +2085,7 @@ offer_corpse(struct obj *otmp, boolean highaltar, aligntyp altaralign)
|
||||
}
|
||||
} else {
|
||||
int saved_luck = u.uluck;
|
||||
if (bestow_artifact())
|
||||
if (bestow_artifact(value))
|
||||
return;
|
||||
change_luck((value * LUCKMAX) / (MAXVALUE * 2));
|
||||
if ((int) u.uluck < 0)
|
||||
|
||||
Reference in New Issue
Block a user