When spiders try to spin webs, don't let them do so in Sokoban
unless the level has already been solved or the spider can see the
stairs up (which was the simplest way I could achieve something
close to "is in the same room as the stairs up") where it can't
interfere with solving the level.
Restoring a level cleared residence pointer from those subrooms
which were in the restored level, but if the previous level had
more subrooms, those pointers weren't cleared.
This caused weird problems when a shopkeeper data was looked
up based on the subroom number.
Just to be safe, clear all the room data when freeing the level.
Shop population code set the mimic shape to strange object
without checking for protection from shape changers.
Let set_mimic_sym (via makemon) handle it correctly instead.
For Angels who appear in a flash of light, temporarily light the
spot where they arrive. If not previously visible, it will go back
to dark and change the angel to the remembered, unseen monster glyph,
usually before the player even notices.
Add more monsters to msummon_environ() so that it has latent support
for various light, fire, and lava creatures from mondata.h even
though these extra ones, like previous vortices, don't get summoned
by msummon().
Allow shopkeeper to remove webs and pits.
Change the damage fix messaging to be more specific when
shopkeeper removes a trap. Before this the message was
"A trap was removed from the floor", which sounds really silly
when it comes to holes.
Change the damage fixing so the shopkeeper will fix one damage spot
at a time (instead of all at once), so it's more like a monster action.
Some code cleanup, splitting into smaller functions.
While doing this, I noticed that shopkeepers don't actually bill
the hero for the damage, but that'll have to be another commit...
When shopkeeper fixes a wall and there are items on that location,
shopkeeper tries to move those items into their shop. Split
the code dealing with that into separate functions.
Revisited this feature, and the chance of a spider spinning a web
depends now on the number of webs already present on the level.
For a giant spider to spin a web in the middle of a room with no
supports, the limit of existing webs is 4, next to one support 9,
next to two supports 14, and so on. Cave spider limits are much lower.
Now that the appear message isn't limited to summoning by demon,
seeing "the Angel of <foo> appears in a cloud of smoke" seems
strange. Angels weren't covered by the vapor/dust/&c change for
elementals. Make angels appear in a flash of light.
While testing monster summoning by using a debugger to force the
outcome, I saw "the renegade Angel of <foo> appears in a cloud of
smoke" as if only one such creature existed. Trying to change
that to "a renegate Angel" pointed out some problems: type names
like Angel, Green-elf, and Uruk-hai fool an() into using "the"
because of their capital letter. Fixing that was a bit of a hack
and worked for Green-elf and Uruk-hai but not for Angel because
it has the eminion extension so uses priestname() instead of the
guts of x_monnam(). Fixing that involved more hackery and now I
feel unclean, but it seems to be working.
It wasn't as noticeable as it might have been because most of the
time that "the Angel of <foo>" or "the priest of <bar>" was shown,
the caller is requesting "the" rather than "a/an".
Have water demons appear in a cloud of vapor rather than a cloud of
smoke. This adds a few other alternatives but they'll never happen.
Elementals could only be summoned by Angels but Angels never call
msummon() as far as I can tell. Vortices aren't summoned at all
but the smoke/vapor/&c routine has provisions for them.
The cloud of smoke message used to be given only when the summoner
is a demon. Now it will be given if the last--or only--summoned
creature can be seen to arrive, no matter whether summoned by a
demon, a non-demon (which I think isn't possible), or post-Wizard
harassment.
Use (obj->spe & CORPSTAT_GENDER) for figurines as well as for
statues and corpses.
Support wishing for
"{female,male,neuter} {corpse,statue,figurine} [of <monster>]".
and
"{female,male,neuter} <monster> {corpse,statue,figurine}".
Also
"{corpse,statue,figurine} of {female,male,neuter} <monster>"
where the qualifier might be in the middle instead of a prefix.
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.
While testing some corpse/statue name manipulation changes I managed
to trigger a panic during end-of-game cleanup. Using a bullwhip to
snatch a wielded cockatrice corpse from a monster's inventory into
the hero's inventory and being turned to stone due to lack of gloves
took the corpse out of the monster's inventory but didn't place it
anywhere. If no life-saving took place, it led to an "obj_is_local"
panic during timer cleanup when freeing the level.
This patch includes some of the stuff I've been testing rather than
just the fix for the panic (which is the very last bit of the diff).
Revive some code from 5 or so years ago that's been sitting in a
defunct local git branch. There are a couple of references to
figurines having gender; the old, unfinished code did already have
support for that, the current code doesn't. It probably won't take
much effort to add it in but I want to get this first part out of
the way.
Replace some of the
pmname(mon->data, Mgender[mon]) calls with simpler
mon_pmname(mon) and some
pmname(&mons[statue->corpsenm],
(statue->spe & CORPSTAT_GENDER) == ... ? ... : ...) with simpler
obj_pmname(obj). There are other instances of them which haven't
been changed but could be.
Wishing for "{corpse,statue} of gnome queen" would produce a corpse or
statue of a gnome queen, but wishing for "gnome queen {corpse,statue}"
would produce corpse or statue of a gnome king. The matching for
gender-specific monster name was only passing back the corresponding
gender when an exact match occurred (which happens for "foo of pmname"
but not for "pmname foo" since 'pmname' through end of string is what
the name_to_mon() matching code is looking at).
Dead monsters that had traits saved with the corpse would revive as
the same gender, but ordinary corpses revived with random gender so
could be different from before they got killed.
Since corpses of monsters lacked gender, those for monsters with
gender-specific names were described by the neuter name.
This is a fairly big change for a fairly minor problem and needs a
lot more testing.
Fixes#531
^X feedback and end of game disclosure reported
Your two weapon skill {is,was} [also] limited by being <skill rating>
with with <secondary weapon>.
when the skill rating for the secondary weapon is/was less than the
skill rating for two-weapon combat. The corresponding message for
primary weapon did not duplicate the word "with".
Fixes#530
Have curses call the core get_count() routine instead rolling its
own so that backspace and delete are supported. That part was
trivial to accomplish. Unfortunately it brought the disappearing
menu phenomenon back so it became more complicated overall.
The stair handling reorganization changed drinking a cursed potion
of levitation to only check whether stairs up existed on the level
instead of whether the hero drank the potion while at their spot.
That resulted in always attempting to go up and then getting "you
can't go up here" when not at stairs instead of the intended "you
hit your head on the ceiling".
Fixes#527
being given when it shouldn't be. A change for perm_invent handling
back in March screwed up the if/then/else logic for code executed
when finishing MENUCOLOR manipulation via the 'O' command. That
resulted in the reminder to set menucolors to True being given even
when it was already True if perm_invent happened to be False.
I noticed this myself recently, then neglected to investigate it or
even write it down anywhere.
Fixes#526
Quit is not a commmand you usually need very often, and generally
don't want to use by accident.
Apparently, on Spanish keyboard layout, n-with-tilde is interpreted
by the Windows NetHack as M-q, and the key is next to l. Loot also
asks for confirmation, just like quit.
Prevent stuff like this by not binding the quit command to any key.
Valkyrie player monster was set to be chaotic even though valk
hero is lawful by default and can also be neutral but not chaotic.
Change it to be lawful. Warrior quest monsters attending leader
were also chaotic; change to lawful to match revised valk. If
hero is a neutral valk then both the player monster and warriors
get changed to neutral at start of game (and stay that way even
if hero changes alignment). The leader defaults to neutral but
gets changed to lawful for lawful valk hero.
Attentdant quest monsters with the healer leader were lawful but
if they gain enough experience they get promoted to healer, so
make them neutral like the latter.
I've added some miscellaneous comments and done a small amount of
reformatting. Comment about alignment changing in bones applies
to all roles that can be played with different alignments, not
just to valkyries. It isn't new; I just thought that it ought to
be mentioned somewhere.
Fixes#521
More for issue #524.
The revised append_str() was still vulnerable to unsigned subtraction
overflowing from small negative value to huge positive one, if caller
ever passed an outbuf buffer which already had more than BUFSZ
characters in it.
Also the semantics were changed. If there wasn't room for the whole
" or "+string to be appended, it used to add as much as would fit.
The revised version changed that to all-or-nothing. This changes it
back, although players will probably never know the difference.
Like /m for nearby monsters and /O for all objects, implement /^
and /" to view a list of nearby traps or all known traps. Only
lists discovered traps (or mimics immitating traps, or detected
door or chest traps iff still shown as such on map), but lists
map traps even when an object or monster at the same location is
blocking view of them.
For traps on the Water and Air levels that have been mapped, they
will only be listed when within line of sight so that this feature
can't be used to track portal location as it moves around. However,
when within line of sight it does allow the portal to be recognized
if that has become covered.
When using '//' or ';' to examine the map and player uses '^' to
move the cursor to the next displayed trap, have cursor go to
locations containing webs, the vibrating square, or other non-'^'
trap when such is the next trap symbol up. Otherwise looking at
webs is very tedious because '"' is treated as a look-at command
rather than than a target symbol.
For the baalz 'lit=0' fix, I first tried 'lit=false'. That isn't
supported and triggered an error, but the error reporting passed
a null pointer to sprintf() for a %s argument. OSX's stdio shows
"null" instead of crashing in that situation; most implementations
wouldn't be so forgiving.
It intends to complain about "false" but that won't work if the
unexpected value doesn't get put into the lua table. I don't know
how to fix that aspect of this. This fix just avoids passing a
null pointer to sprintf. Plus some miscellaneous reformatting.