From the newsgroup: slash'em lychanthrope character could throw
while in wolf form. That came straight from nethack; any animal capable
of manipulating an object--possibly with its mouth--could throw things.
Now hands are required. This doesn't require free hands, although it
probably should; it's kind of tough to imagine making a competent throw
while your hands are stuck to a cursed two-handed weapon.
Make all stackable weapons capable of multi-shot volleys when thrown.
Affects knives, spears & javelins, and boomerangs; requires advanced skill
assignment (skilled: 1-2 missiles per throw, expert: 1-3 missiles) or
role-specific bonus (ranger class's general +1 bonus is the only one that
applies to any of these weapon types). For monsters, prince-caste get 1-3
missiles and lord-caste get 1-2, as before, with fake player monsters now
also getting 1-2; those counts apply to all stackable weapons regardless
of whether the species or role ordinarily uses whatever is being thrown.
Related changes: monks now get a role-based +1 count for shuriken,
throwing 1-2 instead of just one (they're only allowed to achieve basic
skill so won't reach any higher volley count). Monster monks and ninjas
get that too; ninjas now get the same for darts and they're guaranteed
weapons in starting inventory. Also, fake player rogues now sometimes
get orcish daggers instead of short sword, providing a decent chance to
occasionally have Grimtooth be randomly generated on the Astral level.
Potentially controversial: wizards can still become expert in dagger
skill and receive the to-hit and damage bonuses for that when throwing as
well as when wielding, but the number of missiles for them has now been
reduced to 1-2 (in other words, going from skilled to expert no longer
improves the max count for the volley amount for wizard role). They're
supposed to be spellcasters; being able to throw up to three +7 daggers
at a pop was a big temptation for resorting to brute force, particularly
since they'll already want highest dagger skill for wielding Magicbane.
To do: throwing multiple boomerangs either needs to behave as if
they're all in flight before the first returns, or else the volley needs
to be cut short if one comes back and isn't successfully caught. The
latter is a lot easier to do but the former fits better with what multi-
shot volley is supposed to represent. Another alternative is to change
them to no longer be stackable, then this sequencing issue goes away.
To do too: make worm teeth and crysknives become stackable like the
other knife-skill weapons.
From a bug report:
crossbow shot range shouldn't depend upon strength. Make it fire for a
distance of BOLT_LIM regardless of whether if would have gone shorter or
longer by using the normal ranged calucations. However, strength is
necessary to load crossbows, so make characters with low strength be less
capable of launching multi-shot volleys.
Some code I recently added was misusing count_unpaid() and would
traverse some or all of inventory instead of just container's contents
when looking for unpaid items. Add mew routine `is_unpaid(obj)' to do
what I was intending to do with count_unpaid().
[I accidentally left this out of the previous commit.]
Throwing didn't handle a container owned by the hero which contained
items owned by the shopkeeper. I'm still not quite sure what's going on
there, but throwing the container out of the shop didn't give any feedback
but did add to shop charges which don't show up in ``I x'' (but do get
revealed by ``$'' or ``I $''). Now there's some shop feedback for the
throw and the contents show up for ``I x''.
More explicit control over the behavior of spoteffects() is probably
the way to go in the long run, but this much simpler fix handles the case
at hand. I'm not sure what `thrownobj' was intended to be used for in the
first place, but it came in handy here. (It was being left as a dangling
pointer when thitmonst() reports that the missile has been used up; that's
fixed now.)
Fix the reported problem of lookhere/autopickup not seeing the missile
which just killed the engulfing monster whose death caused the hero to be
put back onto the map and so look/pickup upon arrival. Normally the missile
gets placed after damage has been dealt and the throw has finished. This
overrides that so that the missile is put into the engulfer's inventory as
it is being killed (which will then put that inventory onto the floor prior
to expelling the hero on top of same). If the monster happens to get
life-saved it just ends up collecting the thrown-from-inside object a little
sooner than usual.
This wouldn't correctly handle the same case for a kicked object, if
that were possible. But it isn't possible to kick objects while engulfed,
so that's moot. Other calls to thitmonst() and hmon() don't appear to have
any objects in transit so shouldn't need any comparable fix (I hope...).
<Someone> wrote:
>>comments:
>>When you commit suicide with a potion of oil (lit), sometimes nethack
>>reports an `obj_is_local' error just after disclosing all the game
>>variables. This has been found in-game (don't ask) and reproduced in
>>wizard mode and in-game (start-scumming).
>
> 0) a neutral human wizard (the scrolls/spellbooks burning, potions boiling ;))
> 1) wish up 3 potions of oil (so that the 2 remaining will definitely kill you)
> 2) a'pply one of them
> 3) stand 1 square away from a wall, like "| @"
> 4) throw the lit potion into the wall (`h' in this case)
> 5) answer `yes' on all prompts.
The thrown potion of oil, which was extracted from any chain
during the throw, still had its timers attached when the call to
splatter_burning_oil() was made. If that killed the hero, a
panic would result during bones file creation (saving timers)
because (obj->where == OBJ_FREE) on the potion.
Remove the timer prior to splattering the oil inside.
The recent fix for "breaking glass wand in tool shop" looked suspect,
adding a call to costly_alteration after an existing call to stolen_value.
Either one or the other ought to suffice. (For items on the floor,
costly_alteration() calls stolen_value(); for items in inventory, or just
released from inventory and not placed on floor yet, costly_alteration()
adds a usage fee to the shop bill but doesn't annoy the shopkeeper into
adding surcharges to prices or summoning the kops if already hostile.)
In 3.4.3, stolen_value() wasn't smart enough to charge for an out-of-
shk's-field item (like a wand in a tool shop) taken from a shop container,
and that's the problem the user was reporting. But the post-3.4.3 code was
changed to handle that by checking billable() instead of saleable(); this
bug should have been gone. Unfortunately, billable() treats items already
on the bill as not interesting--from the perspective of adding things to
the bill--so the change accidentally resulted in stolen_value() no longer
handling objects which are marked unpaid, triggering the same symptom for
a different reason. (Other events besides the breakage of thrown objects
suffered from the bug's new incarnation since various places deliberately
call stolen_value() for unpaid objects.) This updates stolen_value() and
stolen_container() to account for the behavior of billable(). And a few
calls to subfrombill() go away since stolen_value() now takes care of that.
<email deleted> wrote:
> - when in a hardware store, I put a glass wand out of a sack (the glass wand
> will cost you 266 zorkmids) and threw it in the shop => shattered into a
> thousand pieces BUT if I try to pay, I do not owe the shopkeeper anything !!!
> If I break a potion with a /oS, I have to pay !
This patch by <email deleted> was released
when 3.4.1 was current and has been incorporated into slash'em. It is
extremely useful while using ranged weapons. When both autopickup and
pickup_thrown are enabled, walking across previously thrown objects will
pick them up even if they don't match the current pickup_types list.
[See cvs log for patchlevel.h for longer description.]
move oattached and oname and other things that vary
the size of the obj structure into a separate
non-adjacent oextra structure, similar to what has
already been done for mextra. The obj structure
itself becomes a fixed size.
New macros:
#define ONAME(o) ((o)->oextra->oname)
#define OMID(o) ((o)->oextra->omid)
#define OMONST(o) ((o)->oextra->omonst)
#define OLONG(o) ((o)->oextra->olong)
#define OMAILCMD(o) ((o)->oextra->omailcmd)
#define has_oname(o) ((o)->oextra && ONAME(o))
#define has_omid(o) ((o)->oextra && OMID(o))
#define has_omonst(o) ((o)->oextra && OMONST(o))
#define has_olong(o) ((o)->oextra && OLONG(o))
#define has_omailcmd(o) ((o)->oextra && OMAILCMD(o))
changed macros:
has_name(mon) becomes has_mname(mon) to correspond.
The CVS repository was tagged with
NETHACK_PRE_OEXTRA
before commiting these, and
tagged with
NETHACK_POST_OEXTRA
immediately after. The diff
between those two tags is this oextra patch.
The associated mail daemon changes to use an oextra
structure instead of a hidden command located in the
name after the terminating NUL, have not been tried
or tested.
<Someone> reported that thitu() was adding d20 damage for silver object
hitting silver-hating hero even though all the callers were using dmgval()
which also does that, resulting in doubled silver bonus/penalty. This
fixes that (including for boomerangs thrown by player, which weren't using
dmgval(), to handle a hyptothetical silver boomerang). While testing it,
I noticed that there was no "the silver sears your flesh" message when a
monster hit you with a wielded silver weapon, so this fixes that too.
(How did we miss that? And how did <Someone>? :-)
Note: The CVS repository was tagged with NETHACK_PRE_MEXTRA
prior to application of this patch to allow easy withdrawal if necessary.
Adds a new mextra structure type that has a set
of pointers to various types of monster structures
including:
mname, egd, epri, eshk, emin, edog
Replaces the mextra bits in the monst structure
with a single pointer called mtmp->mextra of type
(struct mextra *).
The pointer can be null if there are no additional
structures attached. The mextra structure is not
adjacent to the monst structure.
Reduces the in-memory footprint of the monst that
has no other structures attached, at the cost
of adding 6 extra long ints per monster to
the save file
The new mextra structure has the mextra fields
independent of each other, not overlapping as was
the case with previous NetHack versions.
This patch doesn't do anything to capitalize on
that difference however.
Consolidates vault.h, epri.h, eshk.h, emin.h and edog.h
into mextra.h
Adds a macro for checking for whether a monster has
a name:
has_name(monst)
This fixes the magic trap panic
expels() -> spoteffects() -> dotrap() ->
domagictrap() -> tamedog()
because the monst no longer varies in size so no
replacement is required.
Extend the capabilities of corpse_xname() so that various callers can
be simplified. It can how handle an article prefix, effectively turning it
into corpse_doname() (not quite; still need doname() to see a count when
quantity is more than one, or to see bless/curse state). It can also handle
inclusion of adjectives like "partly eaten" or "bite-covered". For unique
monsters those come out in the form
the Chromatic Dragon's partly eaten corpse
instead of the old
partly eaten Chromatic Dragon corpse
[so wishing probably needs to be taught about potentially finding a monster
name before assorted adjectives such as blessed; also, name_to_mon() needs
to learn how to cope with the possessive suffix].
A sizeable chunk of this patch deals with consolidating some of the
redundant "petrified by a cockatrice corpse" handling. It may be possible
to consolidate all remaining instances together since they're quite similar,
but I didn't think about that until just now and I want to get this patch
over with.
A couple of items pointed out by <Someone>: the killer reason
when hit by mis-return of thrown Mjollnir would vary depending upon whether
it was fully identified, unlike several other death-by-missile cases which
force the object to be described as if fully ID'd. Also, the killer reason
when death is caused by kicking an object would give way too much detail
about the object if it was ID'd. Fix both by switching to killer_xname().
Now "killed by a war hammer named Mjollnir" becomes "killed by Mjollnir"
(same as when already ID'd), and "killed by kicking 5 cursed poisoned -1
orcish arrows" becomes "killed by kicking orcish arrows" whether ID'd or not.
[Trunk only] question? Should being hit by returning Mjollnir really
be receiving half-physical-damage reduction when hero has that attribute?
It ignores the fact that Mjollnir is also dishing out lightning damage.
Are other artifact hits ignoring such things too?
From the newsgroup three or four weeks ago: sleeping or pararlyzed
unicorns would catch thrown gems despite being unable to move. Now they'll
magically dodge instead--in other words, thrown gems will always simply
miss the target (and land at its feet) when a unicorn is unable to move.
The unicorn won't be angered or awakened by the attempt.
From a bug report. <Someone> as slashem-Bugs-883643 on 1/24/2004. To avoid
using the possibly invalid object pointer after calling bhit(), changed as
suggested to add another level of indirection allowing bhit to null the
object pointer before returning. Callers that are affected update their
object pointers after bhit returns.
While auditing nomul() I noticed unconscious() treats (multi < 0 && !nomovemsg)
as unconscious. This explains the behavior in M29 (unconscious message
while performing #turn). I checked all the places with this combination,
and found a few that did not appear to fall under the "unconscious" category.
Most I changed to use You_can_move_again to ensure the same display w/o the
unconscious behavior. Also:
- found another string that unconscious() should have considered
- vomit() now sets nomovemsg, one caller was also doing this redundantly
- vomiting_dialogue() was calling stop_occupation() after vomit(), which can
reset multi. I reversed the order and removed a doubly-redundant nomul call.
tele() still has a problem: some cases where multi < 0 should probably take
a branch like the unconscious() branch but with a different message.
doturn()'s behavior - turn then wait - is also less than perfect, but I
think this is a known problem.
Finally apply the patch sent by <Someone> in 11/2003 for slashem-Bugs-799278,
updated to match the current code and handle additional cases. The fix
is brute force: always ensure nomovemsg is set when nomul is called with
a negative value. I also scanned the code for places manually setting
multi negative, they all set nomovemsg. It would be nice to have a function
that did the right thing, but there are several special cases and I was
not feeling creative.
Fix a buglist entry: fracturing a boulder or statue owned by a shop
was ignored by the shopkeeper. The existing vague fixes entry of "some
shop thefts weren't charged" covers this.
<Someone> reported: You kill it! A potion of invisibility shatters!
Change the rule in hero_breaks() to avoid giving info for things out of
sight, except when from_invent is set, to preserve desired behavior.
Eggs thrown straight up which don't splatter on the ceiling yield
"you've got it all over your face", so wearing a helmet shouldn't protect
against petrification from cockatrice eggs in that situation. This was
part of my delayed helm vs hat stuff; I can't remember whether it was done
before or after this same issue came up in the newsgroup.
There was no feedback when gold was thrown or kicked at monsters
who weren't interested in catching it. Now it'll give the same "<obj>
misses <monster>" message as other thrown or kicked items objects which
don't hit.
- [fixed in trunk] Alchemical explosion
- [fixed in trunk] Artifacts' blasting
- [fixed in trunk] Boiling/freezing potions
- [fixed in trunk] Chest/door/tin traps
- [fixed in trunk] Falling rocks/boulders (trap, digging, scroll of earth)
- [fixed in trunk] Mixing water and acid
- [fixed in trunk] Thrown potion (acid)
This is my last patch on this today.
- [fixed in trunk] Jumping/Newton's-Thirding into something solid
- [fixed in trunk] Being hit by Mjollnir on the return
- [fixed in trunk] Contaminated or boiling water from a sink
- [fixed in trunk] Falling on a sink while levitating
- [fixed in trunk, fire only] Any passive attack
- [fixed in trunk] Zapping yourself with a wand, horn or spell
- [fixed in trunk] Burning (un)holy water
- [fixed in trunk] Thrown potion (bottle)
- [fixed in trunk] Bumping head on ceiling by cursed levitation
- [fixed in trunk] Exploding rings and wands (under all circumstances)
- [fixed in trunk] Stinking cloud damage
- [fixed in trunk] Sitting in a spiked pit, in lava
- [fixed in trunk] Exploding spellbooks
- [fixed in trunk] Falling off or failing to mount a steed
- [fixed in trunk] Falling into a (spiked) pit
- [fixed in trunk] Land mine explosion
- [fixed in trunk] Fire traps
Another batch of missing Half_physical_damage checks
from the list provided by <Someone>:
- Scrolls of fire (!confused)
- Broken wands
- Splattered burning oil from thrown potion
- Dipping a lit lamp into a potion of oil
- Scrolls of fire (confused, didn't bother with non-confused)
- Being caught in a fireball
Adds a macro Maybe_Half_Phys to assist.
<Someone> suggested that a dragon, lacking hands, shouldn't be able to
throw things. Dragons can pick things up, and it seems they can throw
things the same way. However, it does seem that a notake() monster, which
cannot pick things up, shouldn't be able to throw things either.
Introduce a new set of functions to manage delayed killers in the trunk, used
in addressing the various reports of delayed killer confusion. Since existing
delayed killers are related to player properties, the delayed killers are
keyed by uprop indexes. I did this to avoid adding yet another set of
similar identifiers.
- the new delayed_killer() is used for stoning, sliming, sickness, and
delayed self-genocide while polymorphed. Some other timed events don't
use it (and didn't use the old delayed_killer variable) because they
use a fixed message when the timeout occurs.
- A new data structure, struct kinfo, is used to track both delayed and
immediate killers. This encapsulates all the info involved with
identifying a killer. The structure contains a buffer, which subsumes the
old killer_buf and several other buffers that didn't/couldn't use killer_buf.
- the killer list is saved and restored as part of the game state.
- the special case of usick_cause was removed and a delayed killer list
entry is now used in its place
- common code dealing with (un)sliming is moved to a new make_slimed function
- attempted to update all make dependencies for new end.c -> lev.h
dependency, sorry if I messed any up
Pat Rankin wrote:
> collect them all into some new struct and
> save that separately rather than jamming more non-option stuff
> into struct flags.
This patch:
- collects all context/tracking related fields from flags
into a new structure called "context."
It also adds the following to the new structure:
- stethoscope turn support
- victual support
- tin support
This patch introduces a change to yname() and Yname2() that avoids the
possessive "your" for the hero's normal, fully identified artifacts.
Quest artifacts still get the possessive, as do all other objects and all
objects not in the hero's possession. shk_your()/Shk_Your() are used in
many places with a specific, generalized name for the object, so I didn't
introduce the artifact behavior there, although I did change them to append
a space, which simplified some other code. Through added use of yname(),
there may be some places that used to just say "corpse" that will now be more
descriptive via yname()'s use of cxname(). I'm sure <Someone> will point
out any such places that are too onerous, although nothing obviously is.
I took the opportunity to inspect many uses of "your" and even Your(). Two
new functions are also introduced, yobjnam() and Yobjnam2(), which work
like aobjnam() and yname() combined, because I found that many uses of
aobjnam() were preceeded by "your" and I couldn't generally provide the
desired behavior for artifacts (or future artifacts) without a combined
function. In some cases, this change allowed better sharing of code.
rust_dmg() still takes a string as input which is sometimes initialized
from xname() and often prepends "your" to it. Currently, this isn't a
problem since there currently are no normal, armor artifacts. If/when any
are introduced, rust_dmg() will need to be addressed.
The patch is for the trunk only. A lot of research was required and I
didn't feel the upside was there for repeating it in the 3.4.3 branch.
<email deleted> wrote:
> If more monsters fall through a trap door than can fit on the
> level below, when you go down the stairs, you get the following
> message:
> "Program in disorder - perhaps you'd better #quit.
> rloc(): couldn't relocate monster"
> This message seems to appear once for every monster-too-many that
> fell through the hole. I originally found this while
> intentionally completely filling a level with black puddings
> (there was a trap door I didn't know about). I also confirmed it
> in a wiz-mode test using gremlins and water.
[confirmed: moveloop -> deferred_goto -> goto_level ->
losedogs -> mon_arrive -> rloc -> impossible]
This patch:
- causes rloc() to return TRUE if successful,
or FALSE if it wasn't.
- adds code to mon_arrive() in dog.c to deal with
the failed rloc()
- allows the x,y parameters to mkcorpstat() to
be 0,0 in order to trigger random placement of the
corpse on the level
- if you define DEBUG_MIGRATING_MONS when you build cmd.c
then you'll have a debug-mode command #migratemons to
store the number of random monsters that you specify
on the migrating monsters chain.
Since traps can no longer provide an infinite supply, and people were
complaining that they always ran out of ammo before, make it less likely
to break enchanted and blessed ammo, and more likely to break eroded
ones.
<Someone> pointed out a disagreement between the comment and code in
throwing_weapon(): comment says daggers & knife can be thrown, but
code also allowed short swords. Assuming the comment was correct, changed
the code to match.
<Someone> noted that if you dropped a box while levitating, nothing would
break. This is true for sacks too, which shouldn't be immune either.
Throwing didn't break contained objects either, not mentioned in his report.
Refactored out the code in kick_object that handled damage for objects
contained in normal containers and added calls in hitfloor and throwit.
kick_object still only calls it for boxes, but other callers will call it
for any object letting it decide if damage is required. BoH objects aren't
affected, since traditionally the inside of the BoH is "somewhere else".
<Someone> reported that a tame dwarf wouldn't eat food tossed at it.
He also reported that it wouldn't eat off the ground, which I couldn't
reproduce nor see in a problem in the code. The code in thitmonst didn't
allow for sharing food with non-domestic, already tame monsters.
Prevent burying a ball from ending your punishment.
When you bury the ball, internally NetHack Punishment
ceases, but a new trap type of TT_BURIEDBALL immediately
kicks in (acting similar to TT_INFLOOR in some ways).
You can eventually work the ball free (or teleport, etc.),
but that will just return you back to normal Punishment.
While an object is being thrown, it isn't on any list. This means that
killing a shopkeeper with an unpaid object wouldn't be able to clear the
unpaid bit. By the time the object lands, the shopkeeper is gone, and then
it's too late. Added a new global to track a thrown object, set it and later
clear it in throwit(), also clear it as needed in dealloc_obj(), and check
it in setpaid(). It should be possible to use this global to avoid losing
thrown objects during hangup saves as well. But that can wait.
>More worrying is the fact that applying a figurine over water lets
>the monster wait until its next move before it drowns (giving
>you time to teleport it to safety, or whatever) [...]
>Should there be a minliquid() check as part of make_familiar()?
Applying at the water location next to you was easy. But
applying it at your own location (triggering BY_YOU) could
end up placing the figurine at the far side of the level if
there was lots of water.
Correcting that required the ability to pass a flag from
make_familiar to makemon() telling it to not rule out
water locations as good positions. The flag had to
be passed on down to goodpos() and enexto().
The bulk of this patch is just adding an additional
argument to goodpos() in all of the callers.
hold_another_object() will try to quiver the object being held if
it's a weapon (or gem/rock ammo) and the autoquiver option is enabled and
the quiver is empty. It was doing that even if the object had just merged
with primary or secondary weapon, resulting in it being equipped in two
slots at once. (Easiest way to reproduce it is via wish+wield+wish for
similar item, but it could also occur when stealing while in nymph form.)
This also addresses one of the old items on <Someone>'s list: if you
carry a sling equipped in the alternate weapon slot, include gems and
rocks as likely candidates for quivering same as when wielding a sling.
This extends that to autoquivering; ammo appropriate for your alternate
is now given preference over arbitrary weapons (ammo for your wielded
weapon and arbitrary missiles still take precedence over alternate ammo).
Bug? pickup_object() is not autoquiver aware, hence autopickup isn't
either.
Bug too (perhaps moot if the above is changed)? Snagging a monster's
weapon with a bullwhip uses hold_another_object() so possibly autoquivers;
snagging an object off the floor with a grappling hook uses pickup_object()
so doesn't.
Narrow openings are currently not checked for by hurtle_step() or
mhurtle_step. This has the consequence that you can jump or use
Newton's 3rd to get through somewhere you can't get through on the
ground, and monsters can stagger or be jousted through somewhere
they wouldn't attempt under their own steam.
This patch fixes hurtle_step(). It does not address mhurtle_step.
The heros_fault() macro added to region.h relatively recently causes
a K&R vintage compiler to choke on the heros_fault variable in dothrow.c.
Although the latter has been around longer, changing it was a little bit
simpler.
Building with an old version of gcc with various warnings enabled
generated a lot of noise. Most of it was due to not guarding string
literals with `const', but there were a couple of actual problems too.
<Someone> reported several incorrect death messages
1) "petrified by deliberately gazing at Medusa's hideous countenance" is
too long and won't fit on the tombstone. I reworded it, which also better
reflects that Medusa's gaze is really an active attack.
2) "killed by war hammer named Mjollnir" for partly identified Mjollnir now
says "killed by a war hammer named Mjollnir".
3) "using a magical horn on himself" was missing the "killed by" prefix
4) there were supposedly cases the the a/an article was missing after being
killed by a monster. I didn't see where this was occuring (eg AoLS resets
killer_format before it returns), but now done_in_by always resets
killer_format, which should address any such cases.
Incorporate a fix from <Someone> that resets the timestamp on
stinking clouds left in bones files. This does allow the cloud's ttl to
restart. Extended it to reset the player_inside flag.
Then noticed that the only placed that called in_out_region was domove().
Added calls when changing levels (which causes player_inside to be set
correctly if the cloud covers the location where the player starts on the
bones level), teleporting, and inside hurtle_step. There are still other
places that fail to call in_out_region, which others may choose to tackle.
I split out the remaining stinking cloud bug reported in the same e-mail
into a separate betabug. That one probably cannot be addressed without
changing the level file format to track the creator.