Commit Graph

291 Commits

Author SHA1 Message Date
Pasi Kallinen
2bec685bae Pyrolisk eggs explode when broken 2024-06-02 10:50:58 +03:00
Pasi Kallinen
472cb7f7fa Prevent throwing gold out of the map 2024-04-25 12:39:02 +03:00
Pasi Kallinen
f131942dd2 Another tamedog message
Give a different message when a peaceful creature was tamed.
Allow suppressing this and the previous message, when the caller
handles messaging.
2024-03-24 10:48:29 +02:00
nhkeni
9c0ed8ae63 NOSTATICFN for src/* 2024-03-14 17:41:51 -04:00
PatR
4af03d8ef8 fix garbled comment
The prolog comment for hurtle() ends with
 * dx and dy should be the direction of the hurtle, not of the original
 * kick or throw and be only.
The clause "and be only" is incomplete and was added sometime between
3.3.0 and 3.4.0.

I suspect it was meant to say "and be only -1 or 0 or +1" but the code
enforces that with sgn(dx) and sgn(dy) so if that's the case, it isn't
necessary.  Whether that guess is right or wrong, remove the clause
since as it stands now, it makes no sense.
2024-03-08 23:34:12 -08:00
nhmall
688ac6ffbe remove register from variable declarations 2024-02-19 16:30:07 -05:00
nhmall
25a8c258e6 replace x >= LOW_PM with ismnum(x) shorthand macro 2024-01-11 14:01:10 -05:00
Mika Kuoppala
91781ef0a6 dothrow: Check for LOW_PM before accessing mon array
on toss_up() when checking for touch_petrifies, add
a check for corpsenm >= LOW_PM as EGG can be without
corpse reference.

This prevents:
dothrow.c:1266:29: runtime error: index -1 out of bounds for type 'permonst [384]'
2024-01-10 17:26:38 +02:00
nhmall
70dcab833d remove obj guard from stone_missile(obj) macro
Checking the callers:
toss_up() would have segfaulted prior to use of stone_missile() if obj were NULL.
thitu() now has a guard prior to use of stone_missile()
ohitmon() would have crashed from earlier dereference otmp->dknown if it were NULL,
   otmp arg is declared nonnull
thitm() now has a guard prior to use of stone_missile().
hmon_hitmon_do_hit() null obj takes a different code path than the code path
    using stone_missile(); comment asserting that added
2023-12-16 07:58:44 -05:00
Michael Meyer
1736f3caaa Add 'pickup_stolen' option
Add pickup_stolen option to autopick items stolen from you by a nymph or
monkey, even if they don't match your normal autopickup settings.
Replace was_dropped, was_thrown with a 2-bit bitfield that can contain
values LOST_DROPPED, LOST_THROWN, and LOST_STOLEN (or 0), since they
should all be mutually exclusive anyway as they track the most recent
way the item left the hero's inventory.

[Rebase/merge conflict fixed up.  PR]
2023-12-08 15:19:54 -08:00
Alex Smith
7ca9951996 Reduce code duplication in extrinsics-protect-items code
The same checks were being repeated for every damage type; this
sends them through two centralised functions (one for checking
whether an extrinsic blocks a specific instance of item destruction
and one for the enlightenment message), so that new mechanisms of
item destruction prevention will need to change only one point in
the code.
2023-12-05 04:34:24 +00:00
nhmall
85e08c4034 splash 2023-11-25 21:14:22 -05:00
Michael Meyer
d42564bacd Better align drop_throw with hero ammo breakage
There is a comment above the function indicating that it should be
aligned with hero ammo breakage, but this wasn't the case.  One big
difference is that any monster-thrown or -shot object would be deleted
unconditionally if it hit another monster trapped in a pit.  I don't
know why that was in there, but it's not present in hero ammo breakage
chances, and it meant that a monster could sling the Mines luckstone at
the hero, hit a monster in the pit, and permanently lock the hero out of
getting the luckstone (as just happened to a player during the current
tournament).  This pulls the hero breakage rules out into their own
function and uses that for monster breakage as well, to make sure they
are aligned.  I also refactored drop_throw a bit to reduce the number of
separate variables tracking whether the object was deleted (was create,
objgone, and retvalu), and changed its (and ohitmon's) type to boolean.
2023-11-11 01:17:54 -08:00
Michael Meyer
98d2b0ecb3 Follow up on disturbing buried zombies
Change 852f8e4 by requiring a minimum impact before a buried zombie
nearby will be disturbed: light, but still excluding things like
scrolls, if it's a violent impact (dropped while levitating, thrown, or
kicked), and fairly heavy if the hero is just placing the item on the
ground normally.

Moving the call out of flooreffects meant it no longer applied to
pushing boulders around, so have moverock disturb nearby zombies.  I
additionally had wake_nearby do the same thing.

Finally, I renamed check_buried_zombies (which doesn't really reflect
what it does) to disturb_buried_zombies.
2023-11-05 21:51:45 -08:00
Michael Meyer
5ba7939110 Fix: hurtling into wall of water
A hero hurtled into a wall of water while levitating, flying, or wearing
water-walking boots wouldn't be stopped by it unless it was on the Plane
of Water.  Make it stop hurtling heroes immediately no matter the
location.

I also noticed that once I was hurtled safely into the wall of water, it
was described as a "pool" when I examined it with ':'.  Fix that, too,
even though I think it shouldn't really be encountered in-game.
2023-11-03 11:04:34 -07:00
nhmall
6cbefc7c2d Revert "granular verbose message suppression mechanics"
This reverts commit be76727265.
2023-10-29 20:39:07 -04:00
Michael Meyer
602af21ca3 Have leader keep already-used invocation items
The other suggestion from Pat about potential extensions to bda0b3b.  I
think it's interesting from a story perspective, and hopefully nobody
will run into this by mistake when they hoped to use the Candelabra as a
light source later!  The specific language used by the leader could be
changed if someone has a better idea (as could the code itself, for that
matter).
2023-09-22 21:40:12 -07:00
Michael Meyer
dedf1ade18 Have quest leader ID thrown unknown fake Amulet
If the hero throws an unidentified fake Amulet of Yendor at the quest
leader, the leader will identify it and toss it back, similar to the
behavior for the real Amulet.

This was one of Pat's suggestions for continuing in the same key as
bda0b3b; I think this makes a lot of sense, especially now that people
may be encouraged to throw things called "Amulet of Yendor" at the quest
leader.  Arguable about whether a _known_ fake Amulet should still anger
the leader and quest helpers; as I have it in this commit, it will, but
I'm somewhat ambivalent about what makes more sense.
2023-09-22 21:40:12 -07:00
PatR
14c7b2015d PR #1093 - quest leader vs thrown invocation items
Pull request from entrez:  if hero throws (or kicks) an invocation
item or the Amulet at the quest leader, identify it and give it back
instead of treating the throw (or kicked item) as an attack.

In addition to the fixes entry I've made several tweaks to related
code, mostly to refer to the leader as "Someone" rather than "It" if
unseen.

Closes #1093
2023-09-20 12:10:57 -07:00
Michael Meyer
bda0b3b807 Allow quest leader to catch and return unique item
It's been possible for a while to throw your quest artifact to your
quest leader, completing the quest (he will then throw the object back
to you).  The quest leader will also react to being brought the Amulet
of Yendor (i.e. having it in inventory when you approach or #chat), but
tossing it over like the quest artifact was treated as a hostile act and
would cause the quest leader and guardians to become hostile and attack
the hero.

Make throwing the Amulet of Yendor at the quest leader work like
throwing the quest artifact, and treat the invocation items similarly
just in case people try throwing those (maybe because they are lost,
unsure what to do, and have already seen their quest leader catch and
react to the quest artifact -- regardless of the reason, throwing over
the Book of the Dead is almost certainly not intended to be an attack).
Doing so for invocation items will ID them but not do much more than
that.  The Amulet of Yendor triggers the existing quest pager message.
2023-09-20 11:00:32 -07:00
PatR
dd05f5183e addinv_nomerge()
Replace several instances of
 obj->nomerge = 1;
 addinv(obj);
 obj->nomerge = 0;
with new
 addinv_nomerge(obj);
and add various related comments.
2023-09-19 14:40:33 -07:00
PatR
e9c58c2fe4 breaking crystal armor
Instead of a 5% chance for crystal plate mail or crystal helmet to
break each time it's subjected to breakage, switch to a 10% chance
but the damage is treated as erosion rather than break/don't-break.
'crystal foo' will need to go through four stages of damage before
breaking:  cracked crystal foo, very cracked crystal foo, thoroughly
cracked crystal foo, then gone.  Crackproof handling is included,
described as tempered crystal foo.

It mostly still applies to throwing and kicking the item.  Having
some hits trigger damage might be worthwhile but isn't implemented.

Object creation within lua code probably needs to be updated, and
when the Mitre of Holiness is created in the priest/priestess quest
it should start out as tempered (erodeproof).  Perhaps it ought to
be erodeproof regardless of where/how it's created.
2023-06-14 15:54:04 -07:00
PatR
450f060132 github issue #1060 - crystal helmet
Issue reported by vultur-cadens:  changing helm of brilliance to
crystal made it stop being classified as "hard helmet" so it gave
less protection against things falling onto the hero's head.

Change the is_metallic() tests used on helmets to new hard_helmet().
Unlike when thrown, crystal helmets don't break when objects fall
on them.

Fixes #1060
2023-06-14 06:13:11 -07:00
PatR
41c8a18d3d hurtling monster bumping into hero
Typo/thinko resulted in passing wrong monster variable to x_monnam().
2023-05-05 17:50:57 -07:00
PatR
53adba6602 maybe fix #K3909 - hurtled monster detached twice
I haven't forced a test case to verify this, but the logic for
calling mliquid() at the end of mhurtle() was clearly wrong.

Also, implement missing case of one monster causing another to
hurtle and hit the hero.  Compiles but is otherwise untested.
2023-05-03 12:18:15 -07:00
PatR
7778d91193 fix for breaking a crystal helm
Avoid impossible warning "breaking odd object?" when throwing a helm
of brilliance causes it to break.  Presumably dropping one while
levitating or zapping one of the floor with striking/force bolt would
yield similar result.

While in there, reduce the chance of breakage from 99% to 5% for both
helm of brilliance and crystal plate mail.
2023-05-03 05:30:51 -07:00
PatR
1c94bdac89 blindness overhaul
I was working on this at the time 3.6.0 was released and set it aside
until later.  Later has finally arrived.  Redo the Blind, Blinded,
Blindfolded,&c macros to make more complete use of intrinsic property
handling.  Blinded was being treated as a number which could be added
to or subtracted from; now that has to be done via TIMEOUT mask
because it has FROMOUTSIDE (OPTIONS:blind) and FROMFORM (poly'd into
!haseyes() form) bits included.  Object definitions for blindfold and
towel now specify the BLINDED property; overriding blindness via the
Eyes of the Overworld is accomplished via props[BLINDED].blocked.

Code generated for the scores of Blind and !Blind tests throughout
the program should be smaller.

One bug that has been fixed is that putting on the Eyes of the
Overworld cured permanent blindness (from OPTIONS:blind).  The
u.uroleplay.blind flag was cleared and stayed so after taking them
off.  Putting the Eyes on still breaks blind-from-birth conduct but
now blindness will resume when they are removed.

This was untested at the time it was set aside and is only lightly
tested now.  A large number of the changes here are just to switch
from Blinded to BlindedTimeout for current timed value and to call
set_itimeout() for setting a new value.
2023-04-27 14:53:28 -07:00
nhmall
826ce951e7 get rid of NetHack macro conflict with curses routine delay_output() 2023-04-21 08:25:53 -04:00
nhmall
de79240dea some comment spelling fixes 2023-03-16 22:27:01 -04:00
PatR
74ed2999de knockback feedback
Adjust the message given when an attack knocks its target back.  Say
|<defender> is knocked backward by <attacker>
if target will actually move or
|<defender> is knocked back by <attacker>
if there's something preventing the move.  Most players probably won't
even notice the difference.  (Possibly "rocked back" would be better
when not changing location but this hasn't gone that far.)

Also make the knock back distance be 1 step 2/3 of the time or 2 steps
1/3 instead of 50:50 chance for 1 or 2 steps.
2023-03-11 11:21:09 -08:00
Pasi Kallinen
f61e1e8e23 Tiny chance of breaking iron bars with war hammer
Also add some different sounds to hitting the iron bars,
and make it noisy.
2023-01-26 18:21:53 +02:00
Pasi Kallinen
677b32c2a7 Hit and wake sleeping monster makes it growl
Unless you kill the monster with one hit, it'll wake up
cranky and make noise - waking up other sleeping monsters.

This was a bit tricky with all the message sequencing; I tested
all the hit/throw/fire/zap combos I could think of, and it took
a while to get things looking right.
2023-01-21 16:52:23 +02:00
PatR
a294fdf179 boomerang bits
Refine the recent throw-and-return catching routine.
2022-12-25 13:28:02 -08:00
PatR
9a9f2d596d fix boomerang equiped in multiple slots
Reported directly to devteam:  with one quivered boomerang and a
compatable stack of one or more boomerangs either wielded or in the
alternate weapon slot, throwing the quivered one, failing to hit any
target or obstacle, and catching the returning boomerang would empty
the quiver, merge the caught boomerang with the wielded weapon or
swap-weapon slot, then re-quiver and yield
|x - 2 boomerangs (wielded) (at the ready)
or
|y - 2 boomerangs (alternate weapon; not wielded) (at the ready)
If 'sanity_check' was On, complaints would ensue.

'autoquiver' may need to be On in addition to the thrown boomerang
being the last item in the quiver.

The unsplit portion of the fix feels unclean.  There's bound to be a
better way.
2022-12-24 00:27:59 -08:00
PatR
e724034995 unpaid sanity_check: leaving shop via recoil
Throwing while levitating or getting hit for knockback effect could
move hero carrying unpaid items out of a shop.  If that happened,
sanity_check complained that unpaid items weren't in a tended shop.

Check for entering and leaving special rooms during recoil same as
gets done for ordinary movement.  Leaving a shop via recoil or
knockback while owing a bill now gets treated as robbery immediately
rather than waiting until hero voluntarily moves to another spot
after recoil has finished.
2022-12-06 10:57:14 -08:00
nhmall
02a48aa8cf split g into multiple structures
The consolidation of global variables from scattered source
files into decl.c and declared in decl.h was begun in 3.7.0.
Their placement in common files was done for centralized
initialization and potential re-initialization during a
"play again" scenario.

It wasn't really necessary for all of them to be housed in a
single huge structure to meet the "play again" requirement,
and the single huge structure has been a little unwieldy when
it comes to maintenance.

Following this commit, instead of one single extremely large structure
named 'g' to house all of the relocated global variables, they
are distributed into several ga through gz.

To make things easy for the developer, each variable is placed
into the struct corresponding to the starting letter of the variable.
That way, no lookup is required in order to know which struct houses
a particular variable, it is a simple match to the starting letter
for all the centralized global variables.

A global variable named 'amulets', would be found in ga.
    ga.amulets
     ^ ^
A global varable named 'move', would be found in gm.
    gm.moves
     ^ ^
A global variable named 'val_for_n_or_more' would be found in gv.
    gv.val_for_n_or_more
     ^ ^
A global variable named 'youmonst' would be found in gy.
    gy.youmonst
     ^ ^
2022-11-29 21:53:21 -05:00
PatR
55ec68ef0a Longbow of Diana
Give an extra +1 to potential multi-shot to rangers wielding the
Longbow of Diana and shooting any type of arrow.  When an elf ranger
has been wielding an elven bow to shoot elvish arrows or an orc
ranger has been wielding an orcish bow to shoot orcish arrows, they
lose their racial bonus but won't lose any multi-shot capability by
switching to their quest artifact.  Human and gnome rangers gain the
+1 bonus.  (I have no idea how a gnome could wield a longbow.  One
would need a step ladder to hold it vertically, and could only draw
the string back a stubby arm's length if they held if horizonally.)

That bonus gets applied before feeding the multi-shot counter to
rnd() so doesn't mean an extra arrow every time.  And you have to
be wielding your own quest artifact--in addition to it being the
appropriate launcher for the ammo you're shooting--so doesn't provide
any multi-shot benefit to other types of characters who wish for it.
2022-10-31 23:13:05 -07:00
nhmall
99a93fe50b some C99 changes
Instead of using index() macro defined to strchr, use C99 strchr.
Instead of using rindex() macro defined to strrchr, use C99 strrchr.

If you want to try building on a platform that doesn't offer those
two functions, these are available:
    define NOT_C99       /* to make some non-C99 code available */
    define NEED_INDEX    /* to define a macro for index()  */
    define NEED_RINDX    /* to define a macro for rindex() */
2022-10-29 10:54:25 -04:00
Michael Meyer
47076c3625 Fix: duplicate invlet from throwing obj with count
Specifying a count of 1 when throwing an object could leave you with two
stacks sharing one inventory letter.  The second stack gets split off
when the player specifies a count (e.g. 't1o'), but keeps its original
invlet.  Some early returns, like trying to throw at yourself with '.',
could fail to unsplit the stack.  Theoretically, specifying multiple
items to multishot and then failing to throw them all could also leave a
partial stack; I don't think this is actually possible right now with
't' but I tried to make sure it won't become a problem if greater counts
than 1 are ever allowed.

The fix doesn't affect 'f', which can be a combined "create a quiver
stack and throw" action and doesn't have the issue with duping invlets.
Specifying a count to split off a new quiver stack with 'f' shouldn't be
reverted if the throwing fails or only part of the stack is thrown,
because the newly created stack may be intended for continued use as the
quiver in future turns.  This slightly changes the behavior of the
existing unsplit when cancelling the throw (which previously unsplit the
newly created quiver and quivered the entire parent stack), but I think
this actually makes more sense -- the player only declined to throw the
new stack, not to create it (as if they canceled earlier in the action).

I routed a couple early returns through the stack unsplitting that
shouldn't actually need it (like Mjollnir and welded items) for
consistency's sake; I don't think it hurts anything.
2022-10-23 00:01:54 -07:00
PatR
c3633ca4e6 mhurtle_step() bit
A very splight simplification.
2022-10-05 07:16:00 -07:00
PatR
a1dae3caf8 "no monster to remove" for steed knockback
Reported directly to devteam, mounted hero whose steed got hit
for knockback effect triggered impossible "no monster to remove".

In addition to fixing that, this makes a knockback attempt at a
hero who is stuck to a cursed saddle knock the hero and steed back
instead of knocking the hero out of the saddle.

mhurtle_step() should be able to use u.ux0,u.uy0 to update the
hero's old location after moving the hero in order to move the
steed, but the value was different from what was expected and the
map showed stale steed symbol when I used that.  I'm not sure what
is going on there; saving u.ux,u.uy before moving the hero worked
as intended so I didn't pursue it.
2022-10-05 03:40:35 -07:00
PatR
b07fe59b3c attack/damage by trapper and lurker above
Change trappers and lurkers above to remove digestion damage.  They
fold themselves around rather than swallow the victim.  There were
are lot of places that assumed that an engulfer which is an animal
would swallow and digest the victim.  In hindsight, it might have
been simpler to take the M1_ANIMAL flag off of trappers and lurkers
above.

This adds a new digests() predicate for creatures with AT_ENGL+AD_DGST
(purple worm) and also enfolds() for AT_ENGL+AD_WRAP (both 't'-class
critters).

There are several minor fixes mixed in with this.  I didn't record
them as I went along but the two I remember are
1) if poly'd into a holder and holding on to a monster, the '<' and
   '>' commands refursed to work; release the held creature first
   and then treat those commands as normal;
2) throwing a non-weapon while engulfed by an ochre jelly reported
   "the <item> vanishes into the ochre jelly's /currents/".

This needs a lot more testing.  I found and fixed multiple minor
details before my own testing burned out.
2022-08-15 04:14:36 -07:00
Pasi Kallinen
9be2e581b7 Macros for checking is object artifact 2022-08-12 19:37:34 +03:00
Pasi Kallinen
fd9745f9c6 Command repeating by using cmd queues
This replaces the old pushq/saveq arrays (which were used to save
the keys pressed by the user for repeating a previous command)
with a new command queue.  This means there's no hard-coded limit
to the saved keys, and it can repeat extended commands which are
not bound to any key.
2022-08-09 11:54:45 +03:00
nhmall
3004cf2d34 be more consistent with coordinates 2022-07-02 09:10:03 -04:00
nhmall
30b557f7d5 change xchar to other typedefs
One of the drivers of this change was that screen coordinates require a
type that can hold values greater than 127. Parameters to the window
port routines require a large type in order to be able to have values
a fair bit larger than COLNO and ROWNO passed to them, particularly for
their use to the right of the map window.

This splits the uses of xchar into 3 different situations, and adjusts
their type and size:

                        xchar
                          |
               -----------------------
               |          |          |
            coordxy     xint16     xint8

coordxy: Actual x or y coordinates for various things (moved to 16-bits).

xint16:  Same data size as coordxy, but for non-coordinate use (16-bits).

xint8:   There are only a few use cases initially, where it was very
         plain to see that the variable could remain as 8-bits, rather
         than be bumped to 16-bits.  There are probably more such cases
         that could be changed after additional review.

Note: This first changed all xchar variables to coordxy. Some were
reviewed and got changed to xint16 or xint8 when it became apparent that
their usage was not for coordinates.

This increments EDITLEVEL in patchlevel.h
2022-06-30 23:48:18 -04:00
nhmall
be76727265 granular verbose message suppression mechanics
Switch to using a macro invocation Verbos(n, s) in place of the
flags.verbose checks.

Provide the mechanics for individual suppression of any of the
existing messages that were considered verbose.

Mechanics only - this code update does not provide any means of
setting the suppression bits.

iflags.verbose = 0
is still a master suppression of all the verbose messages.

iflags.verbose = 1
turns on the verbose messages only for those whose suppression
bit is 0 (not set).
2022-06-09 13:53:20 -04:00
PatR
40d0caa157 'f'ire revamp
The fire command could claim that time passed when it hadn't (fill
quiver with ammo, which takes no time, then queue commands to switch
to matching launcher, which should also take no time while queueing,
only during subsequent execution).

If quiver is empty or has ammo in it, give wielded thrown-and-return
weapon (aklys) priority over filling quiver or switching to ammo's
launcher.  Don't do that if quiver has non-ammo in it, otherwise
players running Valks who wield Mjollnir with super strength but
want to throw quivered daggers would complain.

When player is being asked what to fill the quiver with, use the
\#quiver command to do that.  Using it honors a count to split a
stack, handles switching uwep or uswapwep to uquiver, and gives
feedback.  This is actually a fairly substantial change.

For 'fireassist', when switching to a launcher that isn't already
uswapwep pick one known to be blessed or uncursed over one having
unknown BUC status.  But use the latter as last resort.
2022-04-23 02:12:21 -07:00
Michael Meyer
a384f0353b Fix: "in the the purple worm's entrails"
The message printed if the hero threw gold while swallowed by an animal
used "the <mon_nam>'s entrails", which produced a doubled 'the'.  It
could also use the wrong possessive form, since it doesn't take
advantage of any of the special case handling in s_suffix.  I think the
only way that could ever be a problem with the current cast of engulfers
is if the hero was swallowed by a purple worm while hallucinating, but I
changed it to use s_suffix anyway.
2022-04-20 00:09:02 -07:00
PatR
385a9a7fde encumbrance checks
I polymorphed into something wimpy and became overloaded or even
overtaxed so I dropped everything.  The status line still showed
overloaded or overtaxed until my next move.  That didn't happen in
3.6.x or 3.4.3 but I didn't pursue trying to figure out what caused
this misbehavior.

I wanted to add an encumber_msg() call to freeinv() but that would
cause message sequencing issues.  Instead, add a call to it in a
few places where items are leaving hero's inventory, particularly
for the chain of calls for dropping stuff.  I've left it off in a
bunch of other potential places.

Also add a few missing (void) casts where the return value of
existing encumber_msg() calls is being ignored.
2022-03-22 10:48:23 -07:00