hero with lycanthropy is vulnerable to silver in human form as well as beast
changing alignment or shape triggers a check for equipment evading hero's grasp
passive fire effects can damage attackers weapons
+wielded bow shouldn't affect outcome of kicked arrows
+ranged polearm hit can divide puddings and can use confuse monster effect
Platform- and/or Interface-Specific Fixes
-/* SCCS Id: @(#)hack.h 3.5 2007/02/21 */
+/* SCCS Id: @(#)hack.h 3.5 2007/03/24 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
#define FLASHED_LIGHT 3
#define INVIS_BEAM 4
+/* attack mode for hmon() */
+#define HMON_MELEE 0 /* hand-to-hand */
+#define HMON_THROWN 1 /* normal ranged (or spitting while poly'd) */
+#define HMON_KICKED 2 /* alternate ranged */
+#define HMON_APPLIED 3 /* polearm, treated as ranged */
+#define HMON_DRAGGED 4 /* attached iron ball, pulled into mon */
+
#define MATCH_WARN_OF_MON(mon) (Warn_of_mon && \
((context.warntype.obj && \
(context.warntype.obj & (mon)->data->mflags2)) || \
-/* SCCS Id: @(#)ball.c 3.5 2003/02/03 */
+/* SCCS Id: @(#)ball.c 3.5 2007/03/24 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
tmp = -2 + Luck + find_mac(victim);
tmp += omon_adj(victim, uball, TRUE);
if (tmp >= rnd(20))
- (void) hmon(victim,uball,1);
+ (void) hmon(victim, uball, HMON_DRAGGED);
else
miss(xname(uball), victim);
-/* SCCS Id: @(#)dothrow.c 3.5 2007/01/10 */
+/* SCCS Id: @(#)dothrow.c 3.5 2007/03/23 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
struct obj *thrownobj = 0; /* tracks an object until it lands */
+extern struct obj *kickobj; /* from dokick.c */
extern boolean notonhead; /* for long worms */
}
#define quest_arti_hits_leader(obj,mon) \
- (obj->oartifact && is_quest_artifact(obj) && (mon->data->msound == MS_LEADER))
+ (obj->oartifact && is_quest_artifact(obj) && \
+ mon->m_id == quest_status.leader_m_id)
/*
* Object thrown by player arrives at monster's location.
* Return 1 if obj has disappeared or otherwise been taken care of,
* 0 if caller must take care of it.
+ * Also used for kicked objects and for polearms/grapnel applied at range.
*/
int
thitmonst(mon, obj)
register struct monst *mon;
-register struct obj *obj;
+register struct obj *obj; /* thrownobj or kickobj or uwep */
{
register int tmp; /* Base chance to hit */
register int disttmp; /* distance modifier */
- int otyp = obj->otyp;
+ int otyp = obj->otyp, hmode;
boolean guaranteed_hit = (u.uswallow && mon == u.ustuck);
+ hmode = (obj == uwep) ? HMON_APPLIED :
+ (obj == kickobj) ? HMON_KICKED : HMON_THROWN;
+
/* Differences from melee weapons:
*
* Dex still gives a bonus, but strength does not.
}
tmp += omon_adj(mon, obj, TRUE);
- if (is_orc(mon->data) && maybe_polyd(is_elf(youmonst.data),
- Race_if(PM_ELF)))
+ if (is_orc(mon->data) &&
+ maybe_polyd(is_elf(youmonst.data), Race_if(PM_ELF)))
tmp++;
if (guaranteed_hit) {
tmp += 1000; /* Guaranteed hit */
}
/* don't make game unwinnable if naive player throws artifact
- at leader.... */
- if (quest_arti_hits_leader(obj, mon)) {
+ at leader... (kicked artifact is ok too; HMON_APPLIED could
+ occur if quest artifact polearm or grapnel ever gets added) */
+ if (hmode != HMON_APPLIED && quest_arti_hits_leader(obj, mon)) {
/* not wakeup(), which angers non-tame monsters */
mon->msleeping = 0;
mon->mstrategy &= ~STRAT_WAITMASK;
if (obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
obj->oclass == GEM_CLASS) {
- if (is_ammo(obj)) {
+ if (hmode == HMON_KICKED) {
+ /* throwing adjustments and weapon skill bonus don't apply */
+ tmp -= (is_ammo(obj) ? 5 : 3);
+ } else if (is_ammo(obj)) {
if (!ammo_and_launcher(obj, uwep)) {
tmp -= 4;
} else {
tmp++;
}
}
- } else {
+ } else { /* thrown non-ammo or applied polearm/grapnel */
if (otyp == BOOMERANG) /* arbitrary */
tmp += 4;
else if (throwing_weapon(obj)) /* meant to be thrown */
tmp += 2;
- else /* not meant to be thrown */
+ else if (obj == thrownobj) /* not meant to be thrown */
tmp -= 2;
/* we know we're dealing with a weapon or weptool handled
by WEAPON_SKILLS once ammo objects have been excluded */
}
if (tmp >= rnd(20)) {
- if (hmon(mon,obj,1)) { /* mon still alive */
+ if (hmon(mon, obj, hmode)) { /* mon still alive */
cutworm(mon, bhitpos.x, bhitpos.y, obj);
}
exercise(A_DEX, TRUE);
int was_swallowed = guaranteed_hit;
exercise(A_DEX, TRUE);
- if (!hmon(mon,obj,1)) { /* mon killed */
+ if (!hmon(mon, obj, hmode)) { /* mon killed */
if (was_swallowed && !u.uswallow && obj == uball)
return 1; /* already did placebc() */
}
exercise(A_STR, TRUE);
if (tmp >= rnd(20)) {
exercise(A_DEX, TRUE);
- (void) hmon(mon,obj,1);
+ (void) hmon(mon, obj, hmode);
} else {
tmiss(obj, mon, TRUE);
}
} else if ((otyp == EGG || otyp == CREAM_PIE ||
otyp == BLINDING_VENOM || otyp == ACID_VENOM) &&
(guaranteed_hit || ACURR(A_DEX) > rnd(25))) {
- (void) hmon(mon, obj, 1);
+ (void) hmon(mon, obj, hmode);
return 1; /* hmon used it up */
} else if (obj->oclass == POTION_CLASS &&
/* we hit the monster; be careful: it might die or
be knocked into a different location */
notonhead = (mon->mx != x || mon->my != y);
- malive = hmon(mon, weapon, 0);
+ malive = hmon(mon, weapon, HMON_MELEE);
if (malive) {
/* monster still alive */
if(!rn2(25) && mon->mhp < mon->mhpmax/2
hmon(mon, obj, thrown) /* return TRUE if mon still alive */
struct monst *mon;
struct obj *obj;
-int thrown;
+int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
{
boolean result, anger_guards;
hmon_hitmon(mon, obj, thrown)
struct monst *mon;
struct obj *obj;
-int thrown;
+int thrown; /* HMON_xxx (0 => hand-to-hand, other => ranged) */
{
int tmp;
struct permonst *mdat = mon->data;
#endif
is_pole(obj)) ||
/* or throw a missile without the proper bow... */
- (is_ammo(obj) && !ammo_and_launcher(obj, uwep))) {
+ (is_ammo(obj) && (thrown != HMON_THROWN ||
+ !ammo_and_launcher(obj, uwep)))) {
/* then do only 1-2 points of damage */
if (mdat == &mons[PM_SHADE] && obj->otyp != SILVER_ARROW)
tmp = 0;
if (jousting) valid_weapon_attack = TRUE;
}
#endif
- if (thrown && (is_ammo(obj) || is_missile(obj))) {
+ if (thrown == HMON_THROWN &&
+ (is_ammo(obj) || is_missile(obj))) {
if (ammo_and_launcher(obj, uwep)) {
/* Elves and Samurai do extra damage using
* their bows&arrows; they're highly trained.
/* If you throw using a propellor, you don't get a strength
* bonus but you do get an increase-damage bonus.
*/
- if(!thrown || !obj || !uwep || !ammo_and_launcher(obj, uwep))
+ if (thrown != HMON_THROWN || !obj || !uwep ||
+ !ammo_and_launcher(obj, uwep))
tmp += dbon();
}
abuse_dog(mon);
monflee(mon, 10 * rnd(tmp), FALSE, FALSE);
}
- if((mdat == &mons[PM_BLACK_PUDDING] || mdat == &mons[PM_BROWN_PUDDING])
- && obj && obj == uwep
- && objects[obj->otyp].oc_material == IRON
- && mon->mhp > 1 && !thrown && !mon->mcan
- /* && !destroyed -- guaranteed by mhp > 1 */ ) {
+ if ((mdat == &mons[PM_BLACK_PUDDING] ||
+ mdat == &mons[PM_BROWN_PUDDING]) &&
+ /* pudding is alive and healthy enough to split */
+ mon->mhp > 1 && !mon->mcan &&
+ /* iron weapon using melee or polearm hit */
+ obj && obj == uwep &&
+ objects[obj->otyp].oc_material == IRON &&
+ (thrown == HMON_MELEE ||
+ (thrown == HMON_APPLIED && is_pole(obj)))) {
if (clone_mon(mon, 0, 0)) {
pline("%s divides as you hit it!", Monnam(mon));
hittxt = TRUE;
} else if (destroyed) {
if (!already_killed)
killed(mon); /* takes care of most messages */
- } else if(u.umconf && !thrown) {
+ } else if (u.umconf &&
+ (thrown == HMON_MELEE || thrown == HMON_APPLIED)) {
nohandglow(mon);
if (!mon->mconf && !resist(mon, SPBOOK_CLASS, 0, NOTELL)) {
mon->mconf = 1;