]> granicus.if.org Git - nethack/commitdiff
kicking vs throwing vs polearms (trunk only)
authornethack.rankin <nethack.rankin>
Sun, 25 Mar 2007 05:31:13 +0000 (05:31 +0000)
committernethack.rankin <nethack.rankin>
Sun, 25 Mar 2007 05:31:13 +0000 (05:31 +0000)
     Wielding a bow while kicking arrows gave a shooting bonus.  Also,
From a bug report:  applying a
polearm to hit at range never caused a pudding to split because the attack
gets treated as throwing.  Likewise, confuse monster effect (hands glowing
red) didn't kick in for applied polearms.

doc/fixes35.0
include/hack.h
src/ball.c
src/dothrow.c
src/uhitm.c

index f8431ba08805244b4162e76c8c80b6d2acf5a751..b0657a7062d5dc9bfa25c0b7db7911f2d2ffd507 100644 (file)
@@ -200,6 +200,8 @@ artifacts which subsequently evade your grasp/control after already being
 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
index cb895aed84100e95df178dc77a1270b6c4568cc3..ae3ec1a800b26478fc5fb27731b63f42cddd9d15 100644 (file)
@@ -1,4 +1,4 @@
-/*     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. */
 
@@ -129,6 +129,13 @@ NEARDATA extern coord bhitpos;     /* place where throw or zap hits or stops */
 #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)) || \
index 7bc7b743b4e99ebb64fa7adb12a74b35b698b7f2..e78110ff253926f93b9dac46aed0ef2aa65a7163 100644 (file)
@@ -1,4 +1,4 @@
-/*     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. */
 
@@ -585,7 +585,7 @@ drag:
                    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);
 
index c2b0e832ff2906b8da6ec36bc5df9552dbfc6697..0a59224679250ca962eabc43e984a5c80e1e3fd0 100644 (file)
@@ -1,4 +1,4 @@
-/*     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. */
 
@@ -27,6 +27,7 @@ static NEARDATA const char bullets[] =
 
 struct obj *thrownobj = 0;     /* tracks an object until it lands */
 
+extern struct obj *kickobj;    /* from dokick.c */
 extern boolean notonhead;      /* for long worms */
 
 
@@ -1225,23 +1226,28 @@ boolean maybe_wakeup;
 }
 
 #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.
@@ -1287,8 +1293,8 @@ register struct obj   *obj;
        }
 
        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 */
@@ -1308,8 +1314,9 @@ register struct obj   *obj;
        }
 
        /* 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;
@@ -1336,7 +1343,10 @@ register struct obj   *obj;
 
        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 {
@@ -1358,12 +1368,12 @@ register struct obj   *obj;
                            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 */
@@ -1371,7 +1381,7 @@ register struct obj   *obj;
            }
 
            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);
@@ -1411,7 +1421,7 @@ register struct obj   *obj;
                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() */
                }
@@ -1423,7 +1433,7 @@ register struct obj   *obj;
            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);
            }
@@ -1431,7 +1441,7 @@ register struct obj   *obj;
        } 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 &&
index c63e38b9be0b9bce2f0643c09d89d401b89dd3bb..18eb479de5877b12d3c0909bd36dc098d4e717f8 100644 (file)
@@ -453,7 +453,7 @@ struct attack *uattk;
            /* 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
@@ -514,7 +514,7 @@ boolean                     /* general "damage monster" routine */
 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;
 
@@ -533,7 +533,7 @@ STATIC_OVL boolean
 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;
@@ -605,7 +605,8 @@ int thrown;
 #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;
@@ -690,7 +691,8 @@ int thrown;
                        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.
@@ -924,7 +926,8 @@ int thrown;
                /* 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();
        }
 
@@ -1027,11 +1030,15 @@ int thrown;
                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;
@@ -1085,7 +1092,8 @@ int thrown;
        } 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;