Allows the fire-command to autowield a launcher; it will now
do either swapweapon or wield an appropriate launcher, if you
have ammo quivered.
This assistance can be turned off with the fireassist boolean option.
Adds a rudimentary command queue, which allows the code to add keys
or extended commands into the queue, and they're executed as if
the user did them. Time passes normally when doing the queue,
and the queue will get cleared if hero is interrupted.
[From 14 months ago; I've got an old email for this but can't find
it in the bug list.]
Some things shouldn't hurt the hero when thrown upward and falling
back on head. I've been pretty conservative about what won't do
any harm.
Adopt a feature mentioned in the xNetHack release announcement.
If you use the fire ('f') command when wielding a throw-and-return
weapon while your quiver is empty and the 'autoquiver' option is
Off, throw the wielded weapon instead of prompting to fill the
quiver. It will usually return and be re-wielded, so be ready to
fire again.
Implemented from scratch.
Assigning a partial stack of gold to quiver (Qnn$) resulted in
an extra '$' slot in inventory, one for the unquivered part and
another for the quivered part.
Throwing a non-quivered partial stack of gold at self (tnn$.)
also resulted in an extra '$' slot after throwing at self was
rejected.
For the first case, reject the quiver-subset-of-gold attempt.
For both cases, recombine the two stacks back to original amount.
Fixes#469
This replaces the arcane system previously used by getobj where the
caller would pass in a "string" whose characters were object class
numbers, with the first up to four characters being special constants
that effectively acted as flags and had to be in a certain order.
Because there are many places where getobj must behave more granularly
than just object class filtering, this was supplemented by over a
hundred lines enumerating all these special cases and "ugly checks", as
well as other ugly code spread around in getobj callers that formatted
the "string".
Now, getobj callers pass in a callback which will return one of five
possible values for any given object in the player's inventory. The
logic of determining the eligibility of a given object is handled in the
caller, which greatly simplifies the code and makes it clearer to read.
Particularly since there's no real need to cram everything into one if
statement.
This is related to pull request #77 by FIQ; it's largely a
reimplementation of its callbacks system, without doing a bigger than
necessary refactor of getobj or adding the ability to select a
floor/trap/dungeon feature with getobj. Differences in implementation
are mostly minor:
- using enum constants for returns instead of magic numbers
- 5 possible return values for callbacks instead of 3, due to trying to
make it behave exactly as it did previously. PR #77 would sometimes
outright exclude objects because it lacked semantics for invalid
objects that should be selectable anyway, or give slightly different
messages.
- passing a bitmask of flags to getobj rather than booleans (easier to
add more flags later - such as FIQ's "allow floor features" flag, if
that becomes desirable)
- renaming some of getobj's variables to clearer versions
- naming all callbacks consistently with "_ok"
- generally more comments explaining things
The callbacks use the same logic from getobj_obj_exclude,
getobj_obj_exclude_too and getobj_obj_acceptable_unlisted (and in a few
cases, from special cases still within getobj). In a number of them, I
added comments suggesting possible further refinements to what is and
isn't eligible (e.g. should a bullwhip really be presented as a
candidate for readying a thrown weapon?)
This also removed ALLOW_COUNT and ALLOW_NONE, relics of the old system,
and moved ALLOW_ALL's definition into detect.c which is the only place
it's used now (unrelated to getobj). The ALLOW_ALL functionality still
exists as the GETOBJ_PROMPT flag, because its main use is to force
getobj to prompt for input even if nothing is valid.
I did not refactor ggetobj() as part of this change.
add MALE, FEMALE, and gender-neutral names for individual monster species
to the mons array. The gender-neutral name (NEUTRAL) is mandatory, the
MALE and FEMALE versions are not.
replace code uses of the mname field of permonst with one of the three
potentially-available gender-specific names.
consolidate some separate mons entries that differed only by species into a
single mons entry (caveman, cavewoman and priest,priestess etc.)
consolidate several "* lord" and "* queen/* king" monst entries into
their single species, and allow both genders on some where it makes some
sense (there is probably more work and cleanup to come out of this at some
point, and the chosen gender-neutral name variations are not cast in stone
if someone has better suggestions).
related function or macro additions:
pmname(pm, gender) to get the gender variation of the permonst name. It
guards against monsters that haven't got anything except NEUTRAL naming
and falls back to the NEUTRAL version if FEMALE and MALE versions are
missing.
Ugender to obtain the current hero gender.
Mgender(mtmp) to obtain the gender of a monster
While the code can safely refer directly to pmnames[NEUTRAL] safely in the
code because it always exists, the other two (pmnames[MALE] and
pmnames[FEMALE] may not exist so use:
pmname(ptr, gidx)
where -ptr is a permonst *
-gidx is an index into the pmnames array field of the
permonst struct
pmname() checks for a valid index and checks for null-pointers for
pmnames[MALE] and pmnames[FEMALE], and will fall back to pmnames[NEUTRAL] if
the pointer requested if the requested variation is unavailable, or if the
gidx is out-of-range.
Allow code to specify makemon flags to request female or male (via MM_MALE
and MM_FEMALE flags respectively)to makedefs, since the species alone doesn't
distinguish male/female anymore. Specifying MM_MALE or MM_FEMALE won't
override the pm M2_MALE and M2_FEMALE flags on a mons[] entry.
male and female tiles have been added to win/share/monsters.txt.
The majority are duplicated placeholders except for those that were
separate mons entries before. Perhaps someone will contribute artwork in the
future to make the male and female variations visually distinguishable.
tilemapping via has the MALE tile indexes in the glyph2tile[]
array produced at build time. If a window port has information that the
FEMALE tile is required, it just has to increment the index returned
from the glyph2tile[] array by 1.
statues already preserved gender of the monster through STATUE_FEMALE
and STATUE_MALE, so ensure that pmnames takes that into consideration.
I expect some refinement will be required after broad play-testing puts it to
the test.
consolidate caveman,cavewoman and priest,priestess monst.c entries etc
This commit will require a bump of editlevel in patchlevel.h because it alters
the index numbers of the monsters due to the consolidation of some. Those
index numbers are saved in some other structures, even though the mons[] array
itself is not part of the savefile.
Window Port Interface Change
Also add a parameter to print_glyph to convey additional information beyond
the glyph to the window ports. Every single window port was calling back to
mapglyph for the information anyway, so just included it in the interface and
produce the information right in the display core.
The mapglyph() function uses will be eliminated, although there are still some
in the code yet to be dealt with.
win32, tty, x11, Qt, msdos window ports have all had adjustments done to
utilize the new parameter instead of calling mapglyph, but some of those
window ports have not been thoroughly tested since the changes.
Interface change additional info:
print_glyph(window, x, y, glyph, bkglyph, *glyphmod)
-- Print the glyph at (x,y) on the given window. Glyphs are
integers at the interface, mapped to whatever the window-
port wants (symbol, font, color, attributes, ...there's
a 1-1 map between glyphs and distinct things on the map).
-- bkglyph is a background glyph for potential use by some
graphical or tiled environments to allow the depiction
to fall against a background consistent with the grid
around x,y. If bkglyph is NO_GLYPH, then the parameter
should be ignored (do nothing with it).
-- glyphmod provides extended information about the glyph
that window ports can use to enhance the display in
various ways.
unsigned int glyphmod[NUM_GLYPHMOD]
where:
glyphmod[GM_TTYCHAR] is the text characters associated
with the original NetHack display.
glyphmod[GM_FLAGS] are the special flags that denote
additional information that window
ports can use.
glyphmod[GM_COLOR] is the text character
color associated with the original
NetHack display.
Support for including the glyphmod info in the display glyph buffer
alongside the glyph itself was added and is the default operation.
That can be turned off by defining UNBUFFERED_GLYPHMOD at compile time.
With UNBUFFERED_GLYPHMOD operation, a call will be placed to map_glyphmod()
immediately prior to every print_glyph() call.
This got out of hand pretty quickly. can_reach_floor() had
different criteria than trap activation. Objects dropped at a
hole locations that don't fall through were treated as if they
were at the bottom of an abyss, so couldn't be examined or
picked up.
This a bunch of changes; it is bound to introduce some new bugs.
Kicking a container that had gold in it took the gold amount
away from hero's credit or added to hero's debt, then didn't
give a refund if the container and its gold landed within the
shop. Throwing behaved likewise, just less verbosely.
The problem is caused by addtobill() treating gold specially
and then subfrombill() not being able to perform a reverse
operation. Actually, it may be possible for subfrombill() to
do that, but verifying all its uses is too much work. This
moves the gold handling for drop+selling into its own routine
and adds calls to that for the throwing and kicking refunds.
The other calls to subfrombill() outside of shk.c appear to be
ok as-is. (The calls inside that file are the ones that still
need evaluation if the gold handling is to move to there.)
bill_dummy_object() now uses the same o_id assignment for its
dummy object as split_object() does for its new partial stack.
I don't know whether the old code led to any price glitches.
A reddit thread mentioned that throwing rocks at unicorns behaved
the same as throwing gems at them: not treated as an attack and if
teleporting away is allowed, they will. Change to treat shooting
gems and glass at unicorns with a sling as an attack rather than as
just giving the gem or piece of glass to them, and treat throwing
or shooting rocks and gray stones as an attack too.
If picked up by blind hero while not yet seen, gems and glass
format as "gem" and rocks and gray stones format as "stone" so the
player can always tell the difference. Forgetting to unwield a
sling before interacting with a unicorn is on the player's head.
when the drop is being caused by encumbrance or punishment triggering
a fall while going down stairs.
Also, remove a couple instances of 'if (obj==GOLD) contexl.botl=TRUE'
when dropping gold. They were held over from the obsolete !GOLDOBJ
configuration. Both are immediately followed by freeinv() which
calls freeinv_core() whichs starts off by setting the botl flag when
taking gold out of inventory.
This fixes the reported situation of recoiling from a throw while
levitating and carrying the ball not bringing the chain but it might
introduce other problems. If it does, drag_ball() would be the place
to fix that, not hurtle_step().
Separate bug (not fixed): throwing while the ball is on the floor
ought to let you recoil to as far as the chain will reach but it just
yields "you feel a tug from the ball" and you don't recoil at all.
Implement the request that a wielded+thrown aklys be given the same
inventory letter when it returns and is caught and rewielded, even for
the !fixinv setting where inventory letters don't stick. Works for
Valkyrie-thrown Mjollnir and returning (ie, didn't hit) boomerangs as
well as for aklys.
I'm not sure how useful this really is, because on the rare occasions
that it either doesn't return or fails to be caught, it won't be given
the same letter when subsequently picked up. So the player who relies
on it will still be vulnerable to using the wrong letter next time a
throw is attempted. But at least picking it up explicitly displays
the new inventory letter, unlike catching it upon return.
Make wearing a wet towel confer new attribute Half_gas_damage in
addition to the usual blindness. It reduces damage from being inside
a gas cloud region and from being hit by poison gas breath attack.
It also fully blocks breathing of potion vapors.
Might make the Plane of Fire easier although overcoming its blindness
with telepathy won't reveal elementals. Definitely has the potential
to make blind-from-birth conduct easier which wasn't the intent and
probably isn't significant.
Jumping, Newton's 3rd Law hurtling, and throwing an iron ball:
attempting to do any of these in such a way that you would diagonally
pass between boulders/walls causes the Luck penalty. However, none of
these actually get you through the diagonal gap, thus they can't be used
to cheat and the penalty doesn't make sense.
When GOLDOBJ was activated unconditionally, several texts started referencing
"money" instead of "gold".
As we don't have the intention to introduce a complex coin system with
different denominations, change it back and also some other places that
reference "money".
This adds a boolean option, autounlock, defaulting to true. When this is
set to TRUE, messages stating that some door or container is locked are
automatically followed by a prompt asking if you would like to unlock
it, if you are carrying an unlocking tool (key, lock pick, or credit
card).
Architecturally, this extends the pick_lock function to take three
additional arguments (door coordinates or a box on the ground you are
autounlocking).
The code that selects an unlocking tool will always look first for a
skeleton key, then a lock pick, then a credit card. Since curses, rust,
and other attributes don't really have an effect on the viability of the
unlocking device, it didn't seem to warrant making a more complex
function for that.
Add hallucinatory trap names
This adds many funny, realistic, and nonsensical traps to the game, to
be shown when the player is hallucinating.
Architecturally, the biggest change is merging the what_trap macro and
the "defsyms[trap_to_defsym(ttyp)].explanation" pattern into a single
function "trapname", which returns the name of the trap, handling the
hallucination case. There is also a second parameter used for overriding
hallucination in the occasional cases where the actual trap name should
always be returned.
In addition, the what_trap and random_trap macros are now obsolete and
not used anywhere, so they are removed.
reinstate anti-rng abuse bit on hallucination
updates to hallucinatory trap names and fixes37.0 entry
Fixes#240
Monster versus monster (melee and throwing) didn't handle shades
(need silver or blessed weapon to take damage) or silver feedback
(extra info when silver-haters are hit).
I did a lot of test, revise, re-test but didn't always re-test
everything that had previously been tested, so bugs that I thought
were quashed might have crept in.
Now if a missile weapon "passes harmlessly through the shade" it
will continue on and maybe hit something else. (Regular misses
still stop at the missed target.)
A couple of minor ball&chain changes accidentally got included.
Reported directly to devteam rather than via the web contact form:
throwing wielded aklys while swallowed would hit the engulfer and
return to the hero's hand but leave a stale 'thrownobj' pointer if
the monster survived. Under usual circumstances, throwing anything
else or throwing the aklys again when not engulfed would clear that
pointer, putting things back to normal. However, killing any engulfer
with the same weapon would try to add it to engulfer's inventory to
be dropped as it died. If the killing blow was via melee rather than
another throw, the object in question would still be in hero's
inventory instead of free, hence panic.
The initial returning-aklys implementation shared Mjollnir's code
which doesn't have this issue. This reverts from having attached
aklys always returning successfully when thrown while swallowed to
Mjollnir's 99% chance of return and 99% to be caught when it does
come back. (That was already the case if the engulfer was killed by
the throw, where hero wasn't swallowed anymore after the damage was
inflicted.)
If a poly'd hero spits venom and it lands at a 'soft' spot such as
water, it would remain as an intact venom object. (Venom spat by
monsters seems to always be used up regardless of where it lands.)
Preserve temporary fake object's previous dknown value by storing it
as a flag value within the m_ap_type field of the posing monster, and
recalling it when it is needed.
This is intended to help eliminate observable differences in price display
between real objects and mimics posing as objects.
98% of this is just switching the code to utilize macro M_AP_TYPE(mon)
everywhere to ensure that the flag bits are stripped off when needed.
Take another crack at describing yesterday's do-again fix. Having
'autoquiver' enabled wasn't necessary to encounter the problem.
Also, 'in_doagain' is an int rather than a boolean.
One-line fix is much shorter than attempting to describe the problem.
^A could misuse previous input if 'f'<direction> needed to fill the
quiver and there was nothing suitable, so that the sequence became
'f'<what to throw>. If previous <direction> was an inventory letter
that was occupied, and the item it that slot wasn't already worn in
some other slot, it would be put in quiver slot. Then player would
be asked for direction rather than immediately throwing it since the
what-to-throw prompt had just used up the last of the ^A queue.
Miscellaneous formatting included....
This is based on the multiple-RNGs code fron NetHack4, but using
only the parts relevant to the display RNG (and with substantial
changes, both because of post-3.4.3 changes, and because Nethack4's
display code is based on Slash'EM's rather than NetHack's).