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.
With 3.7+ aspirations of improving savefile interoperability between 32-bit
and 64-bit builds, as well as between platforms, it is better to not have
the underlying struct/array content be conditional.
This splits off some of the MAIL code into MAIL_STRUCTURES code. In theory,
since MAIL_STRUCTURES is unconditionally included, the macro could
just go away and leave that code unconditional, but this commit doesn't
go that far.
Flag existing occurrences of "You hear" as "Deaf-aware" so
that a grep for that string in the future doesn't need to
trigger further investigation of those.
If you ask for help when wishing, don't leave "help" in the buffer
for EDIT_GETLIN to use as default answer on next retry. It does still
leave anything rejected as unknown so that the player has a change to
review the spelling and conceivably add and/or remove from the end
witout having to retype everything.
Throwing or kicking a lit lamp, lit candle, or lit potion of oil
wasn't giving off any light as it travelled to its destination.
Now it does, and dungeon features, objects, or monsters that are
temporarily seen as it moves from square to square till appear on
the map. In the monster case, they go away as soon as the light
moves beyond range, but when it finishes moving the "remembered,
unseen monster" glyph will be drawn at their location. I think that
part has some room for improvement, but mapping temporarily seen
terrain features is the primary impetus for this change.
Also, any message delivery while the "lit missile" travelled still
showed its light around the hero. Noticeable for lamps or stacks
of sufficient candles if hero has no other light source.
This cannibalizes the monst->mburied bit for temporarily seeing a
monster. It has been present but unused for ages. I needed to
replace a couple of vision macros to make sure they didn't examine
it any more so that overloading for transient lighting doesn't
introduce any vision oddities. For version $NEXT, monst->mtemplit
can be given its own bit. It is only set during bhit() execution
and cleared by the time that returns, so has no effect on save files.
If a corpse with a revive timer included obj->oextra->omonst for
remembering the original monster (I think all corpses do these days)
and makemon() failed to create a new monster when the timer expired,
the copy of the original wasn't freed. makemon() will fail if there
is no room for the monster.
Carried containers could have their contents-known state and/or
lock-known state changed without persistent inventory window being
updated to show the new information.
This also changes the behavior when player has hero zap self with
wand of locking or wizard lock spell. If it doesn't trigger a
holding trap then the effect will hit inventory, similar to how
opening/knock operates (releasing hero from holding trap or hiting
inventory when that doesn't happen).
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.
Report forwarded from spam filter so not included in bugzilla list.
Make corpse revival feedback be more consistent. Some of the healer-
specific flavor is still there.
This is branched from Alex's hallu-rng-stability branch,
with two build corrections (detect.c, zap.c), and merged
with the isaac64 branch that we have ready to go.
Alex's dual rng is supported by setting up the array
of multiple isaac64 contexts.
I stuck with Alex's approach of passing the rng function
name around as the parameter (rng or rn2_on_display_rng)
for the new additional parameter needed for
set_random(), init_random(), reseed_random(),
and init_isaac64().
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).
The rationale is that since the player character resists conflict,
fake players should too.
[I'm not sure that I buy that. Player character is always the one
*causing* conflict and it doesn't affect self. But this is simple
as long as no other resistance checks are against attack-by-ring.]
Reported seven years ago, when ice melts underneath a monster, it
hovers there until its next move, then falls in and drowns. Dunk it
immediately, and give hero credit/blame if it happens during the
hero's turn (so presumably the melting was caused by the hero).
Also, let monster with teleport capability who gets dunked teleport
away from the water before getting wet, the way hero does.
struct rm.flags in overloaded for a bunch of rm.typ -dependent things
(doormask, altarmask, throne/fountain/sink looted, a few others) and
wasn't being reset for various cases where rm.typ gets changed.
I've changed a lot, some no doubt unnecessarily, and probably missed
plenty. This compiles but has not been thoroughly tested.
Make the sequence:
be zapped by lightning,
have worn ring of levitation be destroyed,
fall onto fire trap
work better. The fire trap handling will mark everything in inventory
as already processed; anything vulnerable to lightning past the destroyed
ring would not be checked. So delay destroying such a ring until after
all of inventory has been subjected to lightning.
Inventory traversal can be disrupted when items being traversed are
able to change inventory. I've lost track of how many times this
sort of thing has been discovered.
Report claimed that boiled potion of polymorph caused transformation
which resulted in dropped weapon and dropped or destroyed worn armor.
That was evidently a guess; potionbreathe() for that potion only
abuses constitution. The traceback showed 'you_were()' was involved.
Boiled potion of unholy water triggers human-to-beast transformation
of hero inflicted with lycanthropy, yielding similar situation.
I didn't notice anything unusual when reproducing this but inventory
was definitely vulnerable. My 'one line' fixes entries are steadily
getting to be more verbose; I may have to go back to 'fix bug'. :-}
If hero was carrying Schroedinger's Box at end of game, disclosing
inventory converted it into an ordinary box. That interferred with
subsequent disclosure when writing DUMPLOG, which saw an empty box
if inventory had been shown or the special box with newly-determined
contents if not. I tried a couple of ways to fix it and decided
that redoing it was better in the long run.
Schroedinger's box is still flagged with box->spe = 1, but instead
of having that affect the box's weight, now there is always a cat
corpse in the box. When opened, that will already be in place for
a dead cat or be discarded for a live one, but the weight will be
standard for container+contents and when box->cknown is set it will
always be "containing 1 item" (which might turn out to be a monster).
Some temporary code fixes up old save/bones files to stay compatible.
TODO: food detection used to skip Schroedinger's Box; now it will
always find a corpse, so some fixup like the ridiculous probing code
is needed.
Make being trapped in/on/over floor block Levitation and Flying, the
way that being inside solid rock already does, and the way levitating
blocks flight.
Blocked levitation still provides enhanced carrying capacity since
magic is attempting to make the hero's body be bouyant. I think that
that is appropriate but am not completely convinced.
One thing that almost certainly needs fixing is digging a hole when
trapped in the floor or tethered to a buried iron ball, where the
first part of digactualhole() releases the hero from being trapped.
If being released re-enables blocked levitation, the further stages
of digging might not make sense in some circumstances.
I recently realized that being held by a grabbing monster is similar
to being trapped so should also interfere with levitation and flying.
Nothing here attempts to address that.
Save files change, but in a compatible fashion unless trapped at the
time of saving. If someone saves while trapped prior to this patch,
then applies it and restores, the game will behave as if the patch
wasn't in place--until escape from trap is achieved. (Not verified.)
A polymoprh zap which creates a long worm can hit and transform the
same monster again depending upon tail segment placement. Similar
behavior occurs if monpolycontrol is set in wizard mode and player
chooses 'long worm' for what to transform an existing one into (in
which case polymorph fails and zap might hit that same worm again
in another segment, prompting player to choose its new shape again).
Simplest fix would be to make tail segments be immune to polymorph,
but that would prevent players from deliberately attacking the tail
(for polymorph attacks only). Next simplest would be to make long
worms M2_NOPOLY so that polymorph can't create them, then just live
with multiple promptings when monpolycontrol is set. This fix
tracks whether a long worm has just been created via polymorph (or
explicitly retained its shape via monpolycontrol) and makes further
hits on same creature on same zap have no effect. It does so by
setting mon->mextra->mcorpsenm to PM_LONG_WORM when a long worm is
result of polymorph, and setting context.bypasses to get end-of-zap
cleanup. (It doesn't bother discarding mon->mextra if reset of
mcorpsenm leaves mextra empty.)
The report was "doesn't kill even if unchanging", but it does cause
rehumanize() when not Unchanging, the same thing that happens when
you die due to loss of hit points. But losing the activating word(s)
and then having Unchanging retain the clay golem shape does seem
wrong, so make losing the word(s) while being unable to revert to
normal form be fatal.
Poly'd hero (without Unchanging) reverts to normal when cancelled,
so make monsters behave that way. Previously, only werecritters in
beast form were forced to human form. This changes cancellation to
make shapechangers and hiding mimics take on normal form too.
Cancelled shapechangers now behave as if the hero has the
Protection_from_shape_changes attribute and will be unable to change
their shape (after having been forced into normal form). Getting
polymorphed in any fashion uncancels them prior to giving new shape.
[There may be some newcham() situations that should be disallowed
when cancelled rather proceeding and consequently uncancelling.]