nerf potion alchemy (trunk only)

Something I've had in mind for a long time:  make it harder to acquire
dozens of potions of full healing and thereby (8 * dozens) of extra hit
points.  When dipping a stack of more than 2 potions into another potion
other than water, first split the stack so that 2 to 9 potions are dipped
rather than all of them.  Alchemy still works but it will take more dips
(hence need more resources) to convert large amounts.  Dipping into water
isn't affected, nor is dipping non-potions.

     Also fix a bug where dipping a stack--now perhaps a subset stack after
splitting--which triggered an explosion was only using up one of the dipped
potions (plus the one being dipped into) instead of the whole stack.
This commit is contained in:
nethack.rankin
2012-02-19 02:06:43 +00:00
parent ec966362a6
commit 6a9217d568
2 changed files with 97 additions and 62 deletions

View File

@@ -409,6 +409,8 @@ theft of worn armor with wear/unwear delay would interfere with completion of
(disrupted wear attempt for +N helm of brilliance would result in loss
of N points of Int and Wis; gauntlets of dexterity had similar problem)
#sit while swallowed would give the wrong message
alchemical explosion or evaporation only used up one potion instead of all
the potions being dipped
Platform- and/or Interface-Specific Fixes
@@ -558,6 +560,7 @@ display version and build information at startup
repeatedly setting the fruit option will check to see if fruits have been
created, so the user can't easily overflow the maximum this way
bones files now include extra data to identify dead hero and reason for death
dipping multiple potions in another potion may only dip part of their stack
Platform- and/or Interface-Specific New Features

View File

@@ -1815,14 +1815,14 @@ dodip()
potion : obj, 5, 95)) {
pline1(nothing_happens);
} else {
boolean was_wep = FALSE, was_swapwep = FALSE, was_quiver = FALSE;
boolean was_wep, was_swapwep, was_quiver;
short save_otyp = obj->otyp;
/* KMH, conduct */
u.uconduct.polypiles++;
if (obj == uwep) was_wep = TRUE;
else if (obj == uswapwep) was_swapwep = TRUE;
else if (obj == uquiver) was_quiver = TRUE;
was_wep = (obj == uwep);
was_swapwep = (obj == uswapwep);
was_quiver = (obj == uquiver);
obj = poly_obj(obj, STRANGE_OBJECT);
@@ -1842,66 +1842,98 @@ dodip()
}
potion->in_use = FALSE; /* didn't go poof */
return(1);
} else if(obj->oclass == POTION_CLASS && obj->otyp != potion->otyp) {
/* Mixing potions is dangerous... */
pline_The("potions mix...");
/* KMH, balance patch -- acid is particularly unstable */
if (obj->cursed || obj->otyp == POT_ACID || !rn2(10)) {
pline("BOOM! They explode!");
wake_nearto(u.ux, u.uy, (BOLT_LIM+1)*(BOLT_LIM+1));
exercise(A_STR, FALSE);
if (!breathless(youmonst.data) || haseyes(youmonst.data))
potionbreathe(obj);
useup(obj);
useup(potion);
losehp(rnd(10), "alchemic blast", /* not physical damage */
KILLED_BY_AN);
return(1);
} else if (obj->oclass == POTION_CLASS && obj->otyp != potion->otyp) {
long amt = obj->quan;
Strcpy(qbuf, "The");
if (amt > (objects[potion->otyp].oc_magic ? 2L : 9L)) {
/* trying to dip multiple potions will usually affect only a
subset; pick an amount between 2 and min(N,9), inclusive */
amt -= 1L;
do {
amt = (long)rnd((int)amt);
} while (amt >= 9L);
amt += 1L;
if (amt < obj->quan) {
obj = splitobj(obj, amt);
Sprintf(qbuf, "%ld of the", obj->quan);
}
obj->blessed = obj->cursed = obj->bknown = 0;
if (Blind || Hallucination) obj->dknown = 0;
if ((mixture = mixtype(obj, potion)) != 0) {
obj->otyp = mixture;
} else {
switch (obj->odiluted ? 1 : rnd(8)) {
case 1:
obj->otyp = POT_WATER;
break;
case 2:
case 3:
obj->otyp = POT_SICKNESS;
break;
case 4:
{
struct obj *otmp;
otmp = mkobj(POTION_CLASS,FALSE);
obj->otyp = otmp->otyp;
obfree(otmp, (struct obj *)0);
}
break;
default:
if (!Blind)
pline_The("mixture glows brightly and evaporates.");
useup(obj);
useup(potion);
return(1);
}
}
obj->odiluted = (obj->otyp != POT_WATER);
if (obj->otyp == POT_WATER && !Hallucination) {
pline_The("mixture bubbles%s.",
Blind ? "" : ", then clears");
} else if (!Blind) {
pline_The("mixture looks %s.",
hcolor(OBJ_DESCR(objects[obj->otyp])));
}
}
/* [N of] the {obj(s)} mix(es) with [one of] {the potion}... */
pline("%s %s %s with %s%s...", qbuf,
simpleonames(obj), otense(obj, "mix"),
(potion->quan > 1L) ? "one of " : "",
thesimpleoname(potion));
/* Mixing potions is dangerous...
KMH, balance patch -- acid is particularly unstable */
if (obj->cursed || obj->otyp == POT_ACID || !rn2(10)) {
/* it would be better to use up the whole stack in advance
of the message, but we can't because we need to keep it
around for potionbreathe() [and we can't set obj->in_use
to 'amt' because that's not implemented] */
obj->in_use = 1;
pline("BOOM! They explode!");
wake_nearto(u.ux, u.uy, (BOLT_LIM+1)*(BOLT_LIM+1));
exercise(A_STR, FALSE);
if (!breathless(youmonst.data) || haseyes(youmonst.data))
potionbreathe(obj);
useupall(obj);
useup(potion);
return(1);
losehp((int)(amt + rnd(9)), /* not physical damage */
"alchemic blast", KILLED_BY_AN);
return 1;
}
obj->blessed = obj->cursed = obj->bknown = 0;
if (Blind || Hallucination) obj->dknown = 0;
if ((mixture = mixtype(obj, potion)) != 0) {
obj->otyp = mixture;
} else {
switch (obj->odiluted ? 1 : rnd(8)) {
case 1:
obj->otyp = POT_WATER;
break;
case 2:
case 3:
obj->otyp = POT_SICKNESS;
break;
case 4:
{
struct obj *otmp = mkobj(POTION_CLASS, FALSE);
obj->otyp = otmp->otyp;
obfree(otmp, (struct obj *)0);
}
break;
default:
useupall(obj);
useup(potion);
if (!Blind)
pline_The("mixture glows brightly and evaporates.");
return 1;
}
}
obj->odiluted = (obj->otyp != POT_WATER);
if (obj->otyp == POT_WATER && !Hallucination) {
pline_The("mixture bubbles%s.", Blind ? "" : ", then clears");
} else if (!Blind) {
pline_The("mixture looks %s.",
hcolor(OBJ_DESCR(objects[obj->otyp])));
}
useup(potion);
/* this is required when 'obj' was split off from a bigger stack,
so that 'obj' will now be assigned its own inventory slot;
it has a side-effect of merging 'obj' into another compatible
stack if there is one, so we do it even when no split has
been made in order to get the merge result for both cases;
as a consequence, mixing while Fumbling drops the mixture */
freeinv(obj);
(void) hold_another_object(obj, "You drop %s!", doname(obj),
(const char *)0);
return 1;
}
#ifdef INVISIBLE_OBJECTS