Merge remote-tracking branch 'origin/NetHack-3.6.0'
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 explode.c $NHDT-Date: 1503355817 2017/08/21 22:50:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.50 $ */
|
||||
/* NetHack 3.6 explode.c $NHDT-Date: 1511658058 2017/11/26 01:00:58 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.54 $ */
|
||||
/* Copyright (C) 1990 by Ken Arromdee */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -42,7 +42,8 @@ int expltype;
|
||||
uchar adtyp;
|
||||
int explmask[3][3]; /* 0=normal explosion, 1=do shieldeff, 2=do nothing */
|
||||
boolean shopdamage = FALSE, generic = FALSE, physical_dmg = FALSE,
|
||||
do_hallu = FALSE, inside_engulfer;
|
||||
do_hallu = FALSE, inside_engulfer, grabbed, grabbing;
|
||||
coord grabxy;
|
||||
char hallu_buf[BUFSZ];
|
||||
short exploding_wand_typ = 0;
|
||||
|
||||
@@ -87,6 +88,30 @@ int expltype;
|
||||
/* if hero is engulfed and caused the explosion, only hero and
|
||||
engulfer will be affected */
|
||||
inside_engulfer = (u.uswallow && type >= 0);
|
||||
/* held but not engulfed implies holder is reaching into second spot
|
||||
so might get hit by double damage */
|
||||
grabbed = grabbing = FALSE;
|
||||
if (u.ustuck && !u.uswallow) {
|
||||
if (Upolyd && sticks(youmonst.data))
|
||||
grabbing = TRUE;
|
||||
else
|
||||
grabbed = TRUE;
|
||||
grabxy.x = u.ustuck->mx;
|
||||
grabxy.y = u.ustuck->my;
|
||||
} else
|
||||
grabxy.x = grabxy.y = 0; /* lint suppression */
|
||||
/* FIXME:
|
||||
* It is possible for a grabber to be outside the explosion
|
||||
* radius and reaching inside to hold the hero. If so, it ought
|
||||
* to take damage (the extra half of double damage). It is also
|
||||
* possible for poly'd hero to be outside the radius and reaching
|
||||
* in to hold a monster. Hero should take damage in that situation.
|
||||
*
|
||||
* Probably the simplest way to handle this would be to expand
|
||||
* the radius used when collecting targets but exclude everything
|
||||
* beyond the regular radius which isn't reaching inside. Then
|
||||
* skip harm to gear of any extended targets when inflicting damage.
|
||||
*/
|
||||
|
||||
if (olet == MON_EXPLODE) {
|
||||
str = killer.name;
|
||||
@@ -401,8 +426,15 @@ int expltype;
|
||||
pline("%s resists the %s!", Monnam(mtmp), str);
|
||||
mdam = (dam + 1) / 2;
|
||||
}
|
||||
if (mtmp == u.ustuck)
|
||||
/* if grabber is reaching into hero's spot and
|
||||
hero's spot is within explosion radius, grabber
|
||||
gets hit by double damage */
|
||||
if (grabbed && mtmp == u.ustuck && distu(x, y) <= 2)
|
||||
mdam *= 2;
|
||||
/* being resistant to opposite type of damage makes
|
||||
target more vulnerable to current type of damage
|
||||
(when target is also resistant to current type,
|
||||
we won't get here) */
|
||||
if (resists_cold(mtmp) && adtyp == AD_FIRE)
|
||||
mdam *= 2;
|
||||
else if (resists_fire(mtmp) && adtyp == AD_COLD)
|
||||
@@ -468,6 +500,13 @@ int expltype;
|
||||
|
||||
ugolemeffects((int) adtyp, damu);
|
||||
if (uhurt == 2) {
|
||||
/* if poly'd hero is grabbing another victim, hero takes
|
||||
double damage (note: don't rely on u.ustuck here because
|
||||
that victim might have been killed when hit by the blast) */
|
||||
if (grabbing && dist2((int) grabxy.x, (int) grabxy.y, x, y) <= 2)
|
||||
damu *= 2;
|
||||
/* hero does not get same fire-resistant vs cold and
|
||||
cold-resistant vs fire double damage as monsters [why not?] */
|
||||
if (Upolyd)
|
||||
u.mh -= damu;
|
||||
else
|
||||
|
||||
35
src/invent.c
35
src/invent.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 invent.c $NHDT-Date: 1508827592 2017/10/24 06:46:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.220 $ */
|
||||
/* NetHack 3.6 invent.c $NHDT-Date: 1512096431 2017/12/01 02:47:11 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.222 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -617,8 +617,7 @@ void
|
||||
carry_obj_effects(obj)
|
||||
struct obj *obj;
|
||||
{
|
||||
/* Cursed figurines can spontaneously transform
|
||||
when carried. */
|
||||
/* Cursed figurines can spontaneously transform when carried. */
|
||||
if (obj->otyp == FIGURINE) {
|
||||
if (obj->cursed && obj->corpsenm != NON_PM
|
||||
&& !dead_species(obj->corpsenm, TRUE)) {
|
||||
@@ -1473,6 +1472,9 @@ redo_menu:
|
||||
else if (otmp->otyp == LOADSTONE && otmp->cursed)
|
||||
/* kludge for canletgo()'s can't-drop-this message */
|
||||
otmp->corpsenm = (int) cnt;
|
||||
} else if (!strcmp(word, "adjust")) {
|
||||
/* specifying stack's full count means something to #adjust */
|
||||
otmp->nomerge = 1;
|
||||
}
|
||||
}
|
||||
return otmp;
|
||||
@@ -3568,7 +3570,7 @@ doorganize() /* inventory organizer by Del Lamb */
|
||||
char qbuf[QBUFSZ];
|
||||
char allowall[4]; /* { ALLOW_COUNT, ALL_CLASSES, 0, 0 } */
|
||||
const char *adj_type;
|
||||
boolean ever_mind = FALSE;
|
||||
boolean ever_mind = FALSE, dont_collect = FALSE;
|
||||
|
||||
if (!invent) {
|
||||
You("aren't carrying anything to adjust.");
|
||||
@@ -3600,12 +3602,19 @@ doorganize() /* inventory organizer by Del Lamb */
|
||||
|
||||
/* figure out whether user gave a split count to getobj() */
|
||||
splitting = bumped = 0;
|
||||
for (otmp = invent; otmp; otmp = otmp->nobj)
|
||||
if (otmp->nobj == obj) { /* knowledge of splitobj() operation */
|
||||
if (otmp->invlet == obj->invlet)
|
||||
splitting = otmp;
|
||||
break;
|
||||
}
|
||||
if (obj->nomerge) {
|
||||
/* player specified full count; no split occurred and we'll
|
||||
avoid collecting compatible stacks when moving this one */
|
||||
obj->nomerge = 0;
|
||||
dont_collect = TRUE;
|
||||
} else {
|
||||
for (otmp = invent; otmp; otmp = otmp->nobj)
|
||||
if (otmp->nobj == obj) { /* knowledge of splitobj() operation */
|
||||
if (otmp->invlet == obj->invlet)
|
||||
splitting = otmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize the list with all lower and upper case letters */
|
||||
lets[GOLD_INDX] = (obj->oclass == COIN_CLASS) ? GOLD_SYM : ' ';
|
||||
@@ -3659,7 +3668,7 @@ doorganize() /* inventory organizer by Del Lamb */
|
||||
/* adjusting to same slot is meaningful since all
|
||||
compatible stacks get collected along the way,
|
||||
but splitting to same slot is not */
|
||||
|| (splitting && let == obj->invlet)) {
|
||||
|| ((splitting || dont_collect) && let == obj->invlet)) {
|
||||
noadjust:
|
||||
if (splitting)
|
||||
(void) merged(&splitting, &obj);
|
||||
@@ -3692,7 +3701,7 @@ doorganize() /* inventory organizer by Del Lamb */
|
||||
extract_nobj(obj, &invent);
|
||||
|
||||
for (otmp = invent; otmp;) {
|
||||
if (!splitting) {
|
||||
if (!splitting && !dont_collect) {
|
||||
if (merged(&otmp, &obj)) {
|
||||
adj_type = "Merging:";
|
||||
obj = otmp;
|
||||
@@ -3730,7 +3739,7 @@ doorganize() /* inventory organizer by Del Lamb */
|
||||
if (merged(&otmp, &obj)) {
|
||||
obj = otmp;
|
||||
extract_nobj(obj, &invent);
|
||||
} else if (inv_cnt(FALSE) >= 52) {
|
||||
} else if (inv_cnt(FALSE) >= 52 && !dont_collect) {
|
||||
(void) merged(&splitting, &obj); /* undo split */
|
||||
/* "knapsack cannot accommodate any more items" */
|
||||
Your("pack is too full.");
|
||||
|
||||
136
src/mklev.c
136
src/mklev.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 mklev.c $NHDT-Date: 1446191876 2015/10/30 07:57:56 $ $NHDT-Branch: master $:$NHDT-Revision: 1.44 $ */
|
||||
/* NetHack 3.6 mklev.c $NHDT-Date: 1511681724 2017/11/26 07:35:24 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.47 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -1256,6 +1256,7 @@ struct mkroom *croom;
|
||||
coord *tm;
|
||||
{
|
||||
register int kind;
|
||||
unsigned lvl = level_difficulty();
|
||||
coord m;
|
||||
|
||||
/* no traps in pools */
|
||||
@@ -1292,8 +1293,6 @@ coord *tm;
|
||||
/* bias the frequency of fire traps in Gehennom */
|
||||
kind = FIRE_TRAP;
|
||||
} else {
|
||||
unsigned lvl = level_difficulty();
|
||||
|
||||
do {
|
||||
kind = rnd(TRAPNUM - 1);
|
||||
/* reject "too hard" traps */
|
||||
@@ -1348,9 +1347,9 @@ coord *tm;
|
||||
if ((kind == TRAPDOOR || kind == HOLE) && !Can_fall_thru(&u.uz))
|
||||
kind = ROCKTRAP;
|
||||
|
||||
if (tm)
|
||||
if (tm) {
|
||||
m = *tm;
|
||||
else {
|
||||
} else {
|
||||
register int tryct = 0;
|
||||
boolean avoid_boulder = (kind == PIT || kind == SPIKED_PIT
|
||||
|| kind == TRAPDOOR || kind == HOLE);
|
||||
@@ -1369,6 +1368,133 @@ coord *tm;
|
||||
(void) maketrap(m.x, m.y, kind);
|
||||
if (kind == WEB)
|
||||
(void) makemon(&mons[PM_GIANT_SPIDER], m.x, m.y, NO_MM_FLAGS);
|
||||
|
||||
/* The hero isn't the only person who's entered the dungeon in
|
||||
search of treasure. On the very shallowest levels, there's a
|
||||
chance that a created trap will have killed something already
|
||||
(and this is guaranteed on the first level).
|
||||
|
||||
This isn't meant to give any meaningful treasure (in fact, any
|
||||
items we drop here are typically cursed, other than ammo fired
|
||||
by the trap). Rather, it's mostly just for flavour and to give
|
||||
players on very early levels a sufficient chance to avoid traps
|
||||
that may end up killing them before they have a fair chance to
|
||||
build max HP. Including cursed items gives the same fair chance
|
||||
to the starting pet, and fits the rule that possessions of the
|
||||
dead are normally cursed.
|
||||
|
||||
Some types of traps are excluded because they're entirely
|
||||
nonlethal, even indirectly. We also exclude all of the
|
||||
later/fancier traps because they tend to have special
|
||||
considerations (e.g. webs, portals), often are indirectly
|
||||
lethal, and tend not to generate on shallower levels anyway.
|
||||
Finally, pits are excluded because it's weird to see an item
|
||||
in a pit and yet not be able to identify that the pit is there. */
|
||||
if (lvl <= (unsigned) rnd(4)
|
||||
&& kind != SQKY_BOARD && kind != RUST_TRAP
|
||||
&& kind != PIT && kind != SPIKED_PIT && kind < HOLE) {
|
||||
/* Object generated by the trap; initially NULL, stays NULL if
|
||||
we fail to generate an object or if the trap doesn't
|
||||
generate objects. */
|
||||
struct obj *otmp = NULL;
|
||||
int victim_mnum; /* race of the victim */
|
||||
|
||||
/* Not all trap types have special handling here; only the ones
|
||||
that kill in a specific way that's obvious after the fact. */
|
||||
switch (kind) {
|
||||
case ARROW_TRAP:
|
||||
otmp = mksobj(ARROW, TRUE, FALSE);
|
||||
otmp->opoisoned = 0;
|
||||
/* don't adjust the quantity; maybe the trap shot multiple
|
||||
times, there was an untrapping attempt, etc... */
|
||||
break;
|
||||
case DART_TRAP:
|
||||
otmp = mksobj(DART, TRUE, FALSE);
|
||||
break;
|
||||
case ROCKTRAP:
|
||||
otmp = mksobj(ROCK, TRUE, FALSE);
|
||||
break;
|
||||
default:
|
||||
/* no item dropped by the trap */
|
||||
break;
|
||||
}
|
||||
if (otmp) {
|
||||
place_object(otmp, m.x, m.y);
|
||||
}
|
||||
|
||||
/* now otmp is reused for other items we're placing */
|
||||
|
||||
/* Place a random possession. This could be a weapon, tool,
|
||||
food, or gem, i.e. the item classes that are typically
|
||||
nonmagical and not worthless. */
|
||||
do {
|
||||
int poss_class = RANDOM_CLASS; /* init => lint suppression */
|
||||
|
||||
switch (rn2(4)) {
|
||||
case 0:
|
||||
poss_class = WEAPON_CLASS;
|
||||
break;
|
||||
case 1:
|
||||
poss_class = TOOL_CLASS;
|
||||
break;
|
||||
case 2:
|
||||
poss_class = FOOD_CLASS;
|
||||
break;
|
||||
case 3:
|
||||
poss_class = GEM_CLASS;
|
||||
break;
|
||||
}
|
||||
|
||||
otmp = mkobj(poss_class, FALSE);
|
||||
/* these items are always cursed, both for flavour (owned
|
||||
by a dead adventurer, bones-pile-style) and for balance
|
||||
(less useful to use, and encourage pets to avoid the trap) */
|
||||
if (otmp) {
|
||||
otmp->blessed = 0;
|
||||
otmp->cursed = 1;
|
||||
otmp->owt = weight(otmp);
|
||||
place_object(otmp, m.x, m.y);
|
||||
}
|
||||
|
||||
/* 20% chance of placing an additional item, recursively */
|
||||
} while (!rn2(5));
|
||||
|
||||
/* Place a corpse. */
|
||||
switch (rn2(15)) {
|
||||
case 0:
|
||||
/* elf corpses are the rarest as they're the most useful */
|
||||
victim_mnum = PM_ELF;
|
||||
break;
|
||||
case 1: case 2:
|
||||
victim_mnum = PM_DWARF;
|
||||
break;
|
||||
case 3: case 4: case 5:
|
||||
victim_mnum = PM_ORC;
|
||||
break;
|
||||
case 6: case 7: case 8: case 9:
|
||||
/* more common as they could have come from the Mines */
|
||||
victim_mnum = PM_GNOME;
|
||||
/* 10% chance of a candle too */
|
||||
if (!rn2(10)) {
|
||||
otmp = mksobj(rn2(4) ? TALLOW_CANDLE : WAX_CANDLE,
|
||||
TRUE, FALSE);
|
||||
otmp->quan = 1;
|
||||
otmp->blessed = 0;
|
||||
otmp->cursed = 1;
|
||||
otmp->owt = weight(otmp);
|
||||
place_object(otmp, m.x, m.y);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* the most common race */
|
||||
victim_mnum = PM_HUMAN;
|
||||
break;
|
||||
}
|
||||
otmp = mkcorpstat(CORPSE, NULL, &mons[victim_mnum], m.x, m.y,
|
||||
CORPSTAT_INIT);
|
||||
if (otmp)
|
||||
otmp->age -= 51; /* died too long ago to eat */
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user