When already polymorphed, polymorphing into 'human' (or character's
species) to revert to normal when at low level has the infuriating
tendency to yield "your new form isn't healthy enough to survive".
Allow specifying your own role as a way to rehumanize() instead of
going through newman() and level/sex/characteristics randomization
which that performs.
Noticed while working on something else: hero kept wearing a towel
after polymorphing into a form without any head. And when not already
wearing one, could put on a blindfold/towel/lenses while in a headless
form.
Slippery fingers would transfer from bare hands to gloved hands if
you put gloves on. The reverse, transfering from gloves to bare
hands when taking gloves off, was already being prevented for
directly taking them off, but still allowed the slipperiness to
transfer when gloves were lost. This prevents putting on gloves
when fingers are slippery and attempts to handle cases where gloves
get unworn by ways other than 'T' (or 'R') or 'A'.
There's no slippery attribute for objects (way too much work for too
little value); slippery gloves is just the combination of wearing
gloves and having slippery fingers (which now has to have happened
while already wearing those gloves). This changes inventory to use
"(being worn; slippery)" when applicable and much of the patch deals
with funnelling Glib changes through new make_glib() to try to make
sure that persistent inventory adds or removes "; slippery" right
away when changes happen.
If gloves are taken off involuntarily (shapechange to a form that
can't wear them, destruction via scroll of destroy armor or monster
spell of same or via overenchantment, theft), slippery fingers ends
right away instead of the usual few turns later.
when polymorph causes loss of levitation boots or water walking boots
while over water. If discarding stuff while trying to crawl out got
rid of the taken-off boots, they wouldn't be in inventory any more
when break_armor() tried to drop them after taking them off.
Hero polymorphed into a vampire or v.lord can use #monster to switch
to vampire bat or fog cloud [or wolf for lord] but it was a one shot
polymorph. Remember when current form is a shape-shifted vampire and
allow #monster in shifted form to pick another shifted form or the
vampire form.
Genocide of the alternate shape forces back to base vampire. Genocide
of base vampire does too, then reverts to human (or dwarf, &c) as
vampires go away. Being killed while shafe-shifted reverts all the
way to human rather than to vampire. [Just realized: interaction
with Unchanging wasn't taken into consideration so hasn't been tested.]
Since 'youmonst' isn't saved and restored, I had to add a field to 'u'
to hold youmonst.cham during save/restore.
Tested with 3.6.2+ and seemed to be working (except saving while
shape-shifted restored as ordinary bat/cloud/wolf because new u.mcham
wasn't there to hold youmonst.cham yet). Builds with 3.7.0- but not
execution tested yet (I didn't want to clobber my current playground).
Fixes#196
If you didn't die from turning into green slime but then died because
green slimes had been genocided, the message given assumed that you
had just seen "OK, you don't die" from answering No to "Really die?".
Its wording didn't make sense if the reason you didn't die was an
amulet of life-saving. Give a different message for that case.
Also, if you survive turning into slime (via either method) and either
green slimes are still around or you answer No to "Really die?" when
they've been genocided, give a message after "You survived that attempt
on your life" pointing out that you have done so in green slime form.
Useful since prior to 3.6.2 you would have reverted to original form--
despite the Slimed countdown saying you had turned into green slime.
Fixes#187
Qt5 gave "status 'reassess' before init" panic at start of new game.
Don't call status_initialize(REASSESS) from set_usamon()--used for
hero setup as well as for hero polymorph--unless it was previously
called from display_gamewindows() with !REASSESS [which happens when
windowprocs.wincap2 has WC2_STATUS_HILITES or WC2_FLUSH_STATUS set].
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.
Generally, fish should lay their eggs in the water and
not on land, but the game was only allowing the opposite.
Eels are catadromous and lay their eggs in the Sargasso Sea,
not in the dungeon.
Noticed while fixing the 'monster intrinsics from worn gear' bug(s):
set_uasmon() calls set_mon_data(&youmonst,...) which updates movement
when the monster polymorphs into something slower, then it did the
same thing to youmonst.movement itself, hitting the hero with a double
dose of reduction for any movement points not yet spent on current
turn. Remove the set_uasmon() side of that, and change set_mon_data()
side to add a redundant non-zero test to prevent static analysis from
warning that it might be dividing by 0.
Fixes#177
The monst struct has 'mintrinsics' field which attempts to handle
both mon->data->mresists and extrinsics supplied by worn armor, but
polymorph/shape-change was clobbering the extrinsics side of things.
Potentially fixing that by changing newcham() to use set_mon_data(...,1)
instead of (...,0) solved that but exposed two other bugs. Intrinsics
from the old form carried over to the new form along with extrinsics
from worn armor, and update_mon_intrinsics() for armor being destroyed
or dropped only worked as intended if the armor->owornmask was cleared
beforehand--some places were clearing it after, so extrinsics from worn
gear could persist even after that gear was gone.
So, fixing the set_mon_data() call in newcham() was a no go. This
fixes update_mon_intrinsics() and adopts the suggested code from
github pull request #177 to have mon->mintrinsics only handle worn
gear instead of trying to overload innate intrinsics with that. This
is a superset of that; the flag argument to set_mon_data() is gone
and mon->mintrinsics has been renamed mon->mextrinsics. (The routine
update_mon_intrinsics() ought to be renamed too, but I didn't do that.)
Take a first step towards making the mons[] array be readonly.
The only other place that updates it is when changing succubus and
incubus AD_SSEX attacks to AD_SEDU ones and that can be handled
via existing getmattk(), but so far has proven to be trickier than
anticipated.
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.)
Report classified this as 'segfault' but it's actually a controlled
panic(). When hero has lycanthropy and is wielding a potion of unholy
water while in human form, if that potion is boiled then it triggers
a transformation to beast form which in turn causes wielded weapon to
be dropped. When the code unwinds back up through potionbreathe() to
destroy_item(), the boiled potion won't be found in inventory any more
and useup() -> useupall() -> freeinv() -> extract_nobj() panics.
When hero poly'd into paper golem "burns completely" he is rehumanized
even if he has the Unchanging attribute. A comment states that that is
intentional, but there was no explanation given to the player. Report
that "your amulet of unchanging failed" when rehumanization despite
Unchanging happens. (Don't ask me how or why it fails; I don't know.)
It seems to me that the reaction to "you feel dead inside" when you're
polymorphed into an undead creature at the time would be "so what else
is new?". Vary the "dead" when current form is something which gets
reported as "destroyed" rather than "killed" when killed. That happens
for things flagged as non-living. Now undead "feel condemned inside"
and golems "feel empty inside". Neither of those are ideal but they're
more interesting than "feel dead inside".
After becoming dead inside, give a reminder about that during
enlightenment and if you restore a saved game in that condition. It
was the latter that set this in motion: I wanted to confirm that
restoring with u.uhp == -1 didn't give "you aren't healthy enough to
survive restoration" when polymorphed. (It doesn't; the game resumes
and you'll die if/when you rehumanize.)
From end of last December: turning into a "new man" or "new woman"
used the right gender if the hero was polymorphed at the time, but
always used "new man" if it happened when trying/failing to polymorph
while in original form.
setmangry() and wakeup() were being used for multiple purposes. Add an
extra parameter to track which. This fixes several minor bugs (e.g.
whether monsters with no eyes were angered by (useless) gaze attacks
against them previously depended on the state of a UI option, and
the Minetown guards would be annoyed if you used a cursed scroll of
tame monster on a shopkeeper). It's also a prerequisite for the
Elbereth changes I'm working on.
Hero was poly'd into a hider monster and was swallowed by something.
Attempting to hide via '#monster' gave "You can't hide while you're
being held." It correctly blocked hiding due to u.ustuck but the
feedback ignored the possibility of u.ustuck+u.uswallow.
Polyself with gender change into a creature with fixed gender
would deliver a message containing "a <creature>" regardless of
whether "an" was warranted.
(Into any creature which supports both genders it yielded
"a male <creature>" or "a female <creature>" so "an" was never
needed. And when no gender change was involved, it used an()
so got "a <creature>" or "an <creature>" as applicable.)
From a July 2011 report listing multiple movement anomalies, fix one
of the easier ones. If you polymorph from a fast from into a slow
one, pending movement points can let the slow form get in some moves
it shouldn't.
I've deliberately avoided adjusting pending movement when you change
into a faster form, which will get it's own movement boost on the
next turn.
Adding deafness to the status line spurred me on to something I've
wanted to do for a long time. This adds 'Stone' and 'Strngl' as
new status conditions, and moves the five fatal ones: "Stone Slime
Strngl FoodPois TermIll" to the front of the status list since
information about them is more important than any of the others.
"Ill" has been renamed "TermIll"; "Df" has been renamed "Deaf";
"Lev", "Fly", and "Ride" are three additional new conditions, with
Lev and Fly being mutually exclusive. After the fatal ones, the
order of the rest is now
<hunger> <encumbrance> Blind Deaf Stun Conf Hallu Lev Fly Ride
To handle the longer potential status line, the basic bot2() is now
smarter. If the line is wider than the map, 'T:moves' is moved from
the middle to the end. If the line without time is still wider than
the map, then experience (HD if polyd, Xp:M/nnnnnn is showexp is on,
or Exp:M) is moved in front of time at the end. If the line without
experience and time is still wider than the map, dungeon level plus
gold is moved from the beginning to be in front of experience. The
fields are just reordered, not truncated, so if the interface code
can display lines wider than the map they'll retain the extra info.
The gist is than health and associated fields (Hp, Pw, Ac) get first
priority, status conditions get second priority, then the rest. In
the usual case where there aren't many conditions, status display is
the same as it has been in the past.
STATUS_VIA_WINDOWPORT has been updated too, and it builds for tty
and X11. But the bot2() revision to reorder sections has not been
implemented for that.
win/win32/mswproc.c has been updated but not tested.
STATUS_VIA_WINDOWPORT without STATUS_HILITES had several compile
problems; now fixed for core and tty. STATUS_VIA_WINDOWPORT with
STATUS_HILITES has not been tested.