]> granicus.if.org Git - nethack/commitdiff
Allow dissolving iron bars with potion of acid
authorPasi Kallinen <paxed@alt.org>
Wed, 6 Jan 2016 13:33:36 +0000 (15:33 +0200)
committerPasi Kallinen <paxed@alt.org>
Wed, 6 Jan 2016 13:49:06 +0000 (15:49 +0200)
Force-fight iron bars with wielded potion of acid to dissolve them

This change comes via UnNetHack by Patric Mueller.

doc/fixes36.1
include/extern.h
src/hack.c
src/mthrowu.c
src/trap.c
src/zap.c

index 88bbeecb73b3a754b85d01b7bad15a6ec1374d53..292a9ff31cc71a8415e48420f0cbdaad754cb3c3 100644 (file)
@@ -96,6 +96,7 @@ make commands that accept a count prefix for item selection
        show "Count:" like command repeating does
 allow picking a used inventory letter from menu when #adjusting
 zapping wand of opening at yourself, unlock carried boxes
+dissolve iron bars by force-fighting with wielded potion of acid
 
 
 Platform- and/or Interface-Specific Fixes
index 52ffc37aaae232fe8dfc8d859bc2b4279a8d9ec1..ea89ad2ba4084bdbd5abbcff96e2ff4bc3439f03 100644 (file)
@@ -1503,7 +1503,8 @@ E void FDECL(m_useupall, (struct monst *, struct obj *));
 E void FDECL(m_useup, (struct monst *, struct obj *));
 E void FDECL(m_throw,
              (struct monst *, int, int, int, int, int, struct obj *));
-E boolean FDECL(hits_bars, (struct obj **, int, int, int, int));
+E void FDECL(hit_bars, (struct obj **, int, int, int, int, boolean, boolean));
+E boolean FDECL(hits_bars, (struct obj **, int, int, int, int, int, int));
 
 /* ### muse.c ### */
 
index 6305ad1e70215b1a7602979b564e6ed658ce7a8a..098546579148c8ed31ee19a30e1d511d75697bed 100644 (file)
@@ -1437,6 +1437,19 @@ domove()
         }
     }
 
+    if (context.forcefight && levl[x][y].typ == IRONBARS && uwep) {
+        struct obj *obj = uwep;
+        if (breaktest(obj)) {
+            if (obj->quan > 1L)
+                obj = splitobj(obj, 1L);
+            else
+                setuwep((struct obj *)0);
+            freeinv(obj);
+        }
+        hit_bars(&obj, u.ux, u.uy, x, y, TRUE, TRUE);
+        return;
+    }
+
     /* specifying 'F' with no monster wastes a turn */
     if (context.forcefight
         /* remembered an 'I' && didn't use a move command */
index b63a47900816c3a000f99bae1c03496e6786752d..54ef961fd410bb7095e9d66b6680f2e51c15e350 100644 (file)
@@ -318,7 +318,9 @@ struct obj *obj;         /* missile (or stack providing it) */
         || IS_ROCK(levl[bhitpos.x + dx][bhitpos.y + dy].typ)
         || closed_door(bhitpos.x + dx, bhitpos.y + dy)
         || (levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS
-            && hits_bars(&singleobj, bhitpos.x, bhitpos.y, 0, 0))) {
+            && hits_bars(&singleobj,
+                         bhitpos.x, bhitpos.y,
+                         bhitpos.x + dx, bhitpos.y + dy, 0, 0))) {
         (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
         return;
     }
@@ -455,7 +457,10 @@ struct obj *obj;         /* missile (or stack providing it) */
             || closed_door(bhitpos.x + dx, bhitpos.y + dy)
             /* missile might hit iron bars */
             || (levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS
-                && hits_bars(&singleobj, bhitpos.x, bhitpos.y, !rn2(5), 0))
+                && hits_bars(&singleobj,
+                             bhitpos.x, bhitpos.y,
+                             bhitpos.x + dx, bhitpos.y + dy,
+                             !rn2(5), 0))
             /* Thrown objects "sink" */
             || IS_SINK(levl[bhitpos.x][bhitpos.y].typ)) {
             if (singleobj) /* hits_bars might have destroyed it */
@@ -831,11 +836,45 @@ int type;
     return (struct obj *) 0;
 }
 
+void
+hit_bars(objp, objx, objy, barsx, barsy, your_fault, from_invent)
+struct obj **objp;      /* *objp will be set to NULL if object breaks */
+int objx, objy, barsx, barsy;
+boolean your_fault, from_invent;
+{
+    struct obj *otmp = *objp;
+    int obj_type = otmp->otyp;
+    boolean unbreakable = (levl[barsx][barsy].wall_info & W_NONDIGGABLE) != 0;
+
+    if (your_fault
+        ? hero_breaks(otmp, objx, objy, from_invent)
+        : breaks(otmp, objx, objy)) {
+        *objp = 0; /* object is now gone */
+        /* breakage makes its own noises */
+        if (obj_type == POT_ACID) {
+            if (cansee(barsx, barsy) && !unbreakable)
+                pline_The("iron bars are dissolved!");
+            else
+                You_hear(Hallucination ? "angry snakes!" : "a hissing noise.");
+            if (!unbreakable)
+                dissolve_bars(barsx, barsy);
+        }
+    }
+    else if (obj_type == BOULDER || obj_type == HEAVY_IRON_BALL)
+        pline("Whang!");
+    else if (otmp->oclass == COIN_CLASS
+             || objects[obj_type].oc_material == GOLD
+             || objects[obj_type].oc_material == SILVER)
+        pline("Clink!");
+    else
+        pline("Clonk!");
+}
+
 /* TRUE iff thrown/kicked/rolled object doesn't pass through iron bars */
 boolean
-hits_bars(obj_p, x, y, always_hit, whodidit)
+hits_bars(obj_p, x, y, barsx, barsy, always_hit, whodidit)
 struct obj **obj_p; /* *obj_p will be set to NULL if object breaks */
-int x, y;
+int x, y, barsx, barsy;
 int always_hit; /* caller can force a hit for items which would fit through */
 int whodidit;   /* 1==hero, 0=other, -1==just check whether it'll pass thru */
 {
@@ -885,17 +924,7 @@ int whodidit;   /* 1==hero, 0=other, -1==just check whether it'll pass thru */
         }
 
     if (hits && whodidit != -1) {
-        if (whodidit ? hero_breaks(otmp, x, y, FALSE) : breaks(otmp, x, y))
-            *obj_p = otmp = 0; /* object is now gone */
-        /* breakage makes its own noises */
-        else if (obj_type == BOULDER || obj_type == HEAVY_IRON_BALL)
-            pline("Whang!");
-        else if (otmp->oclass == COIN_CLASS
-                 || objects[obj_type].oc_material == GOLD
-                 || objects[obj_type].oc_material == SILVER)
-            pline("Clink!");
-        else
-            pline("Clonk!");
+        hit_bars(obj_p, x,y, barsx,barsy, whodidit, FALSE);
     }
 
     return hits;
index 7f9a1ea7d16be945e73cc529ea860988b91dd8d2..71700c6c8b0d65035a8fae6a330935e70f4611b1 100644 (file)
@@ -1889,7 +1889,9 @@ int style;
         if (dist > 0 && isok(bhitpos.x + dx, bhitpos.y + dy)
             && levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS) {
             x2 = bhitpos.x, y2 = bhitpos.y; /* object stops here */
-            if (hits_bars(&singleobj, x2, y2, !rn2(20), 0)) {
+            if (hits_bars(&singleobj,
+                          x2, y2, x2+dx, y2+dy,
+                          !rn2(20), 0)) {
                 if (!singleobj) {
                     used_up = TRUE;
                     launch_drop_spot((struct obj *) 0, 0, 0);
index 3295e690a6be4a4053a267a9b2f2d5314b734a88..1aaa3d14e20b6a358634c6d1f9c27e4f5928e4dd 100644 (file)
--- a/src/zap.c
+++ b/src/zap.c
@@ -3103,6 +3103,7 @@ struct obj **pobj; /* object tossed/used, set to NULL
         /* iron bars will block anything big enough */
         if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
             && typ == IRONBARS && hits_bars(pobj, x - ddx, y - ddy,
+                                            bhitpos.x, bhitpos.y,
                                             point_blank ? 0 : !rn2(5), 1)) {
             /* caveat: obj might now be null... */
             obj = *pobj;