New feature to sometimes hit twice for skilled martial-arts/bare-handed
was unconditionally using uswapwep for the second hit. If it was a
breakable object, hitting could break it and produce impossible "objfree:
obj not free".
Only use uswapwep for u.twoweap; use Null for second bare-handed hit.
The 'status' section early in the Guidebook says that encumbrance is
one of "Unencumbered, Encumbered, Stressed" and so on. The second in
the list should say "Burdened" rather than "Encumbered".
uhitm.c:843:63: warning: operator '?:' has lower precedence than '|'; '|' will be evaluated first [-Wbitwise-conditional-parentheses]
| (hmd->twohits == 0 || hmd->twohits == 2) ? W_RINGL : 0L);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
uhitm.c:843:63: note: place parentheses around the '|' expression to silence this warning
| (hmd->twohits == 0 || hmd->twohits == 2) ? W_RINGL : 0L);
^
)
uhitm.c:843:63: note: place parentheses around the '?:' expression to evaluate it first
| (hmd->twohits == 0 || hmd->twohits == 2) ? W_RINGL : 0L);
This is a re-creation of a project that was lost years ago while not
quite finished. The old version included some instrumentation to
measure how many hits it takes to kill things during actual play; that
wasn't ready for prime time and this hasn't attempted to redo it.
Changes:
1) improves martial arts and bare-handed combat: they now have a
chance to hit twice when skill is better than 'basic'; 20% chance
for second hit at skilled, 40% at expert, 60% at master, and 80% at
grandmaster; when attacking more than once, strength bonus is
handled as in #2;
2) nerfs two-weapon combat a bit: hitting twice uses only 3/4 strength
bonus on each hit, but when both attacks hit that's 3/2 bonus from
strength which is still more than you get for one hit at a time;
3) beefs up two-handed weapons: hitting via melee with a two-handed
weapon uses 3/2 of stength bonus to reflect the increased influence
of strength; isn't done for applied polearms though.
The reduction in strength bonus for two-weapon has far less impact
than it might sound, due to rounding up with the low values involved.
| full 3/4
| +1 -> +1
| +2 -> +2
| +3 -> +2
| +4 -> +3
| +5 -> +4
| +6 -> +5
The small reduction also doesn't matter if/when current hit happens to
deal a killing blow anyway.
Rings of increase damage apply at full value to every hit, same as
before.
When hitting bare-handed (#1 without gloves), a silver ring on either
hand continues to give a damage bonus against silver haters when you
make an ordinary single attack. However if you attack twice, a silver
ring only applies on the first hit when it is worn on the right hand
and only applies on the second hit when worn on the left hand. (Two
hits with a silver ring on each hand will give silver bonus for both.)
We might conceivably need to add support for a count prefix of 1 to
let player explicitly avoid a second bare-handed/martial-arts hit
attempt (similar to how throw and fire accept a count to limit missile
volley amount).
Kicking has been ignored.
When testing water-vault chests, I kept getting
|Klick! Klick!
when zapping them with a wand of opening. This had me scratching my
head for a while, but it seems to have been caused by partially adding
a sound effect. pline("Klick!") became duplicated and presumeably one
of the two was intended to be edited into a sound-effect call but got
overlooked.
Sound_effect(se_klick,) doesn't make any sound though.
I realized that the previous attempt was misusing the item's locked
state when attempting to create the chest that the item would go into,
which was absurd. I hadn't realized that I was also misspelling
"olocked" as "locked".
This fix was already in progress before the mail about the previous
commit. I did try switching to 'lckd = nil' for the attempt to retain
the chest's random locked/unlocked state but that resulted in all the
chests being created locked. Using separate box=... expressions does
work as intended. Doing something with totable() doesn't seem to be
necessary.
The indentation seems to be messed up compared to the rest of the
file (initial indent of 5 with increments of 4 rather than 3 and 3);
I have't done anything to try to fix it.
When generating an "escape item" inside one of the chests in the
"water-surrounded vault" theme room, make sure that the chest is not
locked if the item is made of glass or crystal. Otherwise kicking the
chest to get access to its contents might destroy the item.
I imagine that this could be done more cleanly, but after quite a bit
of thrashing about I have something which seems to work. To test, I
temporarily modified object shuffling to force wand of digging to be
made out of crystal and gave the water-vault a very high generation
frequency.
Don't use "slither" for movement action when observing an aquatic
monster go into hiding underwater. Use "dive" instead.
Shark, pirahna, and jellyfish had been flagged M1_SLITHY but aren't
anymore. Giant eel and electric eel are still M1_SLITHY and kraken
wasn't and still isn't.
There may be some odd cases that used to use slither and it went by
unnoticed where now use of the default verb might become noticeable.
When returning to play from within the tutorial, remove the level files
similar to how they're discarded for the rest of the dungeon when going
into the endgame. It turned out to be a bit messier than anticipated.
The dungeon.c bit is sufficient for #overview, which now hides regular
level 1 while in the tutorial and hides all tutorial levels once exited.
Those will still appear in end-of-game disclosure.
vs lycanthropes
Issue reported by Umbire: when hero had Protection_from_shape_changers
extrinsic, a lycanthrope in human form that attacked could change into
critter form. It would change back to human on its next move.
Prevent werecreatures from transforming from human form to critter form
if hero has Protection_from_shape_changers. That attribute does not
prevent a human werecreature from summoning animal companions.
Fixes#1082
Backslash doesn't need to be escaped by backslash inside a verbatim
block (presumably the first character is an exception). The doubled
backslashes in SOUNDDIR example were producing doubled backslashes in
the output.
There didn't seem to be any other instances of this.
Pull request from vultur-cadens: add a new status highlight pattern
OPTIONS=hilite:hitpoints/criticalhp/color&attribute
to highlight hit points when they drop to the point where prayer
classifies them as a major problem. The threshold for that varies
depending on max HP and experience level.
It affects hitpointbar as well as the status field for hit points.
Right now a highlight rule for HP down or HP changed or HP up takes
precedence over criticalhp until the temporary highlight times out.
I'm not sure how best to deal with that. With regeneration and an
up or changed rule for HP, the criticalhp highlight probably won't be
seen even with a very short statushilites timeout.
I've added a fixes entry and updated Guidebook.mn but Guidebook.tex
is lagging.
Closes#1071
This allows players to specify a highlight for critically low HP in
the config file, for example:
OPTIONS=hilite_status:hitpoints/criticalhp/purple&inverse
This will cause the hitpoints field to be highlighted when HP is low
enough to be considered a major trouble. The new "criticalhp" setting
only applies to the hitpoints field.
Since the critical HP threshold changes with level (and most of the
fractions are not integer percents) it was impossible to set
highlights to match the critical HP threshold using percentage
settings.
A printf call was introduced in 20fb008012 that caused the terminal
window to be filled with repeated debugging messages as the window
containing the Qt windowport was resized. I removed it because I
assumed it was meant to be temporary and was left in the commit by
mistake, considering it isn't mentioned in the commit message; if it was
meant to be permanent it'd probably be good to block it out with #ifdef
DEBUG or something at least, because it produces a real deluge of
terminal output if the player spends any time resizing the window by
hand.
ff727e9 introduced an issue where unseen water and cloud on the
respective planes were shown with open and closed drawbridge glyphs
instead of the appropriate glyphs. This is because they fall into cmap
section B, but the translation from symbols/cmap index to glyphs was
being done as though they were in cmap section A (ff727e9 manually used
that particular cmap section macro instead of the general cmap_to_glyph
to work around some compiler warning).
From a reddit thread: statue weight is one and half times corpse
weight and some monsters that don't leave a corpse are defined as
having mons[].cwt==0 so statues of those weighed nothing.
Rather than assigning a non-zero corpse weight to every type of
creature, statues that weigh less than an arbitrary value based on
monster size have their weight increased to that value. The weight
of a statue of a killer bee jumps from 1 to 100, that of a leprechaun
increases from 90 to 100, that of a yellow light is changed from 0
to 300, wraith from 0 to 500, and air elemental from 0 to 900. That
last one is actually too low but making the formula more complex
doesn't seem worth it.
Add support for
|OPTIONS=paranoid_confirm:+foo !bar
to enable confirmation for foo and disable it for bar while leaving
other settings intact. Drop support for
|OPTIONS=!paranoid_confirm:bar
since paranoid_confirm:-bar and paranoid_confirm:+!bar accomplish the
same thing. !paranoid_confirm still works as paranoid_confirm:none.
Update the documentation for paranoid_confirmation. It doesn't spell
out all the ins and outs but should cover enough for actual use.
The revised Guidebook.tex is untested.
Pull request from erwinton: the template run-time configuration file
had a MENUCOLOR pattern for cursed worn armor that didn't work.
The regular epxression containing "(being worn)" needed to quote its
parentheses.
The same fix was needed for sys/share/NetHack.cnf.
Closes#1075
Sitting on a squeaky board wasn't triggering it even after the
handler for that type of trap allowed VIASITTING to override Flying.
The check_in_air() test for floor traps didn't have the same override,
so the squeaky board handler didn't get called.
This fixes that, which led to inconsistency with some other trap
types, and additional fixes for pits and bear traps. There might be
others that still behave oddly. For example, if flying over a hole,
using #sit yields
|You land. There's a gaping hole under you! You don't fall in.
I think that's a message phrasing issue rather than a falling trap
issue; if you want to go down, use '>' instead of #sit. On the other
hand, you do now fall into pit traps for #sit while flying over them.
If the hero deliberately sits on the floor while flying over a squeaky
board, then either they're trying to squeak it on purpose or they haven't
noticed it. Either way, sitting should trigger it.
Issue reported by vultur-cadens: tame monsters capable of using items
would pick up cursed ones and even wear cursed armor.
The report cites commit 6c9700ab25 but
I don't see any reason why it would be the cause. However, I was able
to reproduce the misbehavior and this commit seems to fix it.
Fixes#1072
Pull request from vultur-cadens: writing an unknown spellbook will
succeed if corresponding spell is well known (feasible via divine gift
in 3.7 or object amnesia in earlier versions). When nearing the point
of fading from memory, Luck is still required but non-wizards only
need the much lower wizard amount. If already forgotten, the chance
to write the book remains the same as if the spell wasn't known.
Closes#1069
Allow hero to write an unknown spellbook if the spell is freshly known
(from divine knowledge). If the spell is going stale, the chance of
successfully writing the spellbook depends on Luck, but only rnl(5)
(like a Wizard) instead of rnl(15). Forgotten spells do not help when
writing unknown spellbooks.
Pull request from entrez: pits created by breaking a wand of digging
or applying a drum of earthquake used to be able to destroy altars
but a change to prevent placing traps on 'furniture' unintentionally
caused that to stop working.
Closes#1057
Especially powerful magic is meant to be able to destroy altars
(breaking a wand of digging or using a drum of earthquake), but it was
being blocked by a check added to maketrap() in a7f6460 designed to
prevent wizard-mode trap wishing from overwriting stairs. The check was
refined in 6a3d82c to add an exception for digging up graves, but
continued to prevent the destruction of other types of
previously-destructible terrain.
Since this block was a side effect of an attempt to add some guard rails
to wizmode terrain wishes, and the code to explicitly permit the
destruction of other furniture with especially powerful magic is still
present, it doesn't seem like it was actually intended. Open up terrain
destruction by digging magic a bit more by excluding only
non-destructible terrain, not all furniture other than graves, from
being overwritten by pits and holes.
Also, use AM_SANCTUM to more precisely identify non-destructible high
altars in dig_check() rather than checking whether the hero is on the
Astral or Sanctum levels.
Pull request from entrez: when creating a detached theme room of type
"water-surrounded vault", make sure that one of the chests contains an
item that could be used to escape from the room in case hero arrives
via trap door or [level] teleportation.
Closes#1051
Water vaults are one of the few places that can/will generate completely
sealed off in a normal level. Other such spots are designed to provide
a guaranteed means of escape (vault guard, scrolls of teleportation in
niches, etc) -- water vaults were an exception that didn't do this, so a
hero who fell into one from above could have ended up in a position
where she had no choice but to wait to starve to death or #quit. Provide
an escape item in one of the vault's chests to give a hero more options
in that position.
Also fix a minor mistake (I'm pretty sure, though I'm not a Lua expert
enough to be certain) in an nhlib.c comment describing how to use
obj.addcontent() -- when called as box.addcontent(contents) as the
comment suggested it produces an error, but works OK when called as
box:addcontent(contents) or obj.addcontent(box, contents).