]> granicus.if.org Git - nethack/commitdiff
lava effects for monsters and objects
authorcohrs <cohrs>
Sun, 20 Jan 2002 07:04:18 +0000 (07:04 +0000)
committercohrs <cohrs>
Sun, 20 Jan 2002 07:04:18 +0000 (07:04 +0000)
This patch, based on code sent to us by <Someone> well over a year ago, addresses
bugs recently resurfaced.  Namely, that lava does not generally do anything
to monsters or objects that land in java.  Newly renamed minliquid() handles
both water and lava, and new fire_damage() is used similar to water_damage().

doc/fixes33.2
include/extern.h
src/apply.c
src/do.c
src/fountain.c
src/hack.c
src/mon.c
src/trap.c
src/zap.c
sys/msdos/schema3.MSC

index 5fa8064a4f6d87005684af7f0542b8b211a81c14..9bea526d9879147483b40eb623c85610eb233d75 100644 (file)
@@ -396,6 +396,8 @@ gaining a level while polymorphed increases current monst hit points as well
        as latent human (or whatever) hit points
 pets should not try to go after food that they can't reach
 monsters shouldn't use wands of digging in Sokoban
+objects dropped in or travelling across java pools can take damage
+monsters that enter lava can take damage
 
 
 Platform- and/or Interface-Specific Fixes
index a52365e9e1ec93d3c49f6bba807d86ed0eac9fbd..15234fa8ee60de5391c384a31cba02a64f311283 100644 (file)
@@ -43,6 +43,7 @@ E boolean FDECL(wield_tool, (struct obj *));
 E boolean FDECL(um_dist, (XCHAR_P,XCHAR_P,XCHAR_P));
 E boolean FDECL(snuff_candle, (struct obj *));
 E boolean FDECL(snuff_lit, (struct obj *));
+E boolean FDECL(catch_lit, (struct obj *));
 E void FDECL(use_unicorn_horn, (struct obj *));
 E boolean FDECL(tinnable, (struct obj *));
 E void NDECL(reset_trapset);
@@ -1059,7 +1060,7 @@ E struct mkroom *FDECL(search_special, (SCHAR_P));
 
 E int FDECL(undead_to_corpse, (int));
 E int FDECL(pm_to_cham, (int));
-E int FDECL(minwater, (struct monst *));
+E int FDECL(minliquid, (struct monst *));
 E int NDECL(movemon);
 E int FDECL(meatmetal, (struct monst *));
 E int FDECL(meatobj, (struct monst *));
@@ -1938,6 +1939,7 @@ E void FDECL(mselftouch, (struct monst *,const char *,BOOLEAN_P));
 E void NDECL(float_up);
 E void FDECL(fill_pit, (int,int));
 E int FDECL(float_down, (long, long));
+E int FDECL(fire_damage, (struct obj *,BOOLEAN_P,BOOLEAN_P,xchar,xchar));
 E void FDECL(water_damage, (struct obj *,BOOLEAN_P,BOOLEAN_P));
 E boolean NDECL(drown);
 E void FDECL(drain_en, (int));
index f58b59a1749a2fd2826aaebcf9c6fb1137a2e8a7..7f7d95a6fe1d264d8dd7b8b639ba70be7343f8c6 100644 (file)
@@ -1016,6 +1016,32 @@ struct obj *obj;
        return FALSE;
 }
 
+/* Called when potentially lightable object is affected by fire_damage().
+   Return TRUE if object was lit and FALSE otherwise --ALI */
+boolean
+catch_lit(obj)
+struct obj *obj;
+{
+       xchar x, y;
+
+       if (!obj->lamplit && (obj->otyp == CANDELABRUM_OF_INVOCATION ||
+               obj->otyp == WAX_CANDLE || obj->otyp == TALLOW_CANDLE ||
+               obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
+               obj->otyp == BRASS_LANTERN || obj->otyp == POT_OIL)) {
+           if (obj->otyp == MAGIC_LAMP && obj->spe == 0)
+               return FALSE;
+           else if (obj->otyp != MAGIC_LAMP && obj->age == 0)
+               return FALSE;
+           if (!get_obj_location(obj, &x, &y, 0))
+               return FALSE;
+           if (obj->where == OBJ_MINVENT ? cansee(x,y) : !Blind)
+               pline("%s catches light!", Yname2(obj));
+           begin_burn(obj, TRUE);
+           return TRUE;
+       }
+       return FALSE;
+}
+
 STATIC_OVL void
 use_lamp(obj)
 struct obj *obj;
index fdc2b6d4a9f10d2b71dbb159b046b2f375553876..7014d52756320b4ab4046bb7ea056b01ed20899d 100644 (file)
--- a/src/do.c
+++ b/src/do.c
@@ -202,6 +202,8 @@ const char *verb;
                bury_objs(x, y);
                newsym(x,y);
                return TRUE;
+       } else if (is_lava(x, y)) {
+               return fire_damage(obj, FALSE, FALSE, x, y);
        } else if (is_pool(x, y)) {
                water_damage(obj, FALSE, FALSE);
        }
index 1374f8eae27b020a700382ef6e26dd40ab598d9e..032c107b7258f6fbd852a64b45d64c4721168da1 100644 (file)
@@ -126,7 +126,7 @@ genericptr_t poolcnt;
        water_damage(level.objects[x][y], FALSE, TRUE);
 
        if ((mtmp = m_at(x, y)) != 0)
-               (void) minwater(mtmp);
+               (void) minliquid(mtmp);
        else
                newsym(x,y);
 }
index a996207aa06fe681ba678e218b85d97eb46ff1c6..e6a4cc8807e1a57c6e3fdfbd45dee29194dd0289 100644 (file)
@@ -1208,7 +1208,7 @@ domove()
                place_monster(mtmp, u.ux0, u.uy0);
 
                /* check for displacing it into pools and traps */
-               switch (minwater(mtmp) ? 2 : mintrap(mtmp)) {
+               switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) {
                case 0:
                    You("%s %s.", mtmp->mtame ? "displaced" : "frightened",
                        pnambuf);
@@ -1230,7 +1230,7 @@ domove()
                    }
 
                    /* you killed your pet by direct action.
-                    * minwater and mintrap don't know to do this
+                    * minliquid and mintrap don't know to do this
                     */
                    u.uconduct.killer++;
                    break;
index 9d0cb72acdf03c89f68c990363b15891186a45d8..0e2d1e9bfe5aea7af233fc8cfa599150af9bb5d6 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -308,19 +308,21 @@ warn_effects()
 }
 #endif /* 0 */
 
-/* check mtmp and water for compatibility, 0 (survived), 1 (drowned) */
+/* check mtmp and water/lava for compatibility, 0 (survived), 1 (died) */
 int
-minwater(mtmp)
+minliquid(mtmp)
 register struct monst *mtmp;
 {
-    boolean inpool, infountain;
+    boolean inpool, inlava, infountain;
 
     inpool = is_pool(mtmp->mx,mtmp->my) &&
             !is_flyer(mtmp->data) && !is_floater(mtmp->data);
+    inlava = is_lava(mtmp->mx,mtmp->my) &&
+            !is_flyer(mtmp->data) && !is_floater(mtmp->data);
     infountain = IS_FOUNTAIN(levl[mtmp->mx][mtmp->my].typ);
 
 #ifdef STEED
-       /* Flying and levitation keeps our steed out of the water */
+       /* Flying and levitation keeps our steed out of the liquid */
        /* (but not water-walking or swimming) */
        if (mtmp == u.usteed && (Flying || Levitation))
                return (0);
@@ -349,7 +351,35 @@ register struct monst *mtmp;
        return (0);
     }
 
-    if (inpool) {
+    if (inlava) {
+       /*
+        * Lava effects much as water effects. Lava likers are able to
+        * protect their stuff. Fire resistant monsters can only protect
+        * themselves  --ALI
+        */
+       if (!is_clinger(mtmp->data) && !likes_lava(mtmp->data)) {
+           if (!resists_fire(mtmp)) {
+               if (cansee(mtmp->mx,mtmp->my))
+                   pline("%s burns to a crisp.", Monnam(mtmp));
+               mondead(mtmp);
+           }
+           else {
+               if (--mtmp->mhp < 1) {
+                   if (cansee(mtmp->mx,mtmp->my))
+                       pline("%s surrenders to the fire.", Monnam(mtmp));
+                   mondead(mtmp);
+               }
+               else if (cansee(mtmp->mx,mtmp->my))
+                   pline("%s burns slightly.", Monnam(mtmp));
+           }
+           if (mtmp->mhp > 0) {
+               fire_damage(mtmp->minvent, FALSE, FALSE, mtmp->mx, mtmp->my);
+               rloc(mtmp);
+               return 0;
+           }
+           return (1);
+       }
+    } else if (inpool) {
        /* Most monsters drown in pools.  flooreffects() will take care of
         * water damage to dead monsters' inventory, but survivors need to
         * be handled here.  Swimmers are able to protect their stuff...
@@ -480,7 +510,7 @@ movemon()
 
        if (vision_full_recalc) vision_recalc(0);       /* vision! */
 
-       if (minwater(mtmp)) continue;
+       if (minliquid(mtmp)) continue;
 
        if (is_hider(mtmp->data)) {
            /* unwatched mimics and piercers may hide again  [MRS] */
index 44b0b552e71ab1f7bb5d54d93f849269be068425..7b7f2b41a3b5c79b3753d2dcd73a741ba89286f0 100644 (file)
@@ -4,6 +4,8 @@
 
 #include "hack.h"
 
+extern const char *destroy_strings[];
+
 STATIC_DCL void FDECL(dofiretrap, (struct obj *));
 STATIC_DCL void NDECL(domagictrap);
 STATIC_DCL boolean FDECL(emergency_disrobe,(boolean *));
@@ -2284,6 +2286,105 @@ domagictrap()
          }
 }
 
+/*
+ * Scrolls, spellbooks, potions, and flammable items
+ * may get affected by the fire.
+ *
+ * Return number of objects destroyed. --ALI
+ */
+int
+fire_damage(chain, force, here, x, y)
+struct obj *chain;
+boolean force, here;
+xchar x, y;
+{
+    int chance;
+    struct obj *obj, *otmp, *nobj, *ncobj;
+    int retval = 0;
+    int in_sight = !Blind && couldsee(x, y);   /* Don't care if it's lit */
+    int dindx;
+
+    for (obj = chain; obj; obj = nobj) {
+       nobj = here ? obj->nexthere : obj->nobj;
+
+       /* object might light in a controlled manner */
+       if (catch_lit(obj))
+           continue;
+
+       if (Is_container(obj)) {
+           switch (obj->otyp) {
+           case ICE_BOX:
+               continue;               /* Immune */
+               break;
+           case CHEST:
+               chance = 40;
+               break;
+           case LARGE_BOX:
+               chance = 30;
+               break;
+           default:
+               chance = 20;
+               break;
+           }
+           if (!force && (Luck + 5) > rn2(chance))
+               continue;
+           /* Container is burnt up - dump contents out */
+           if (in_sight) pline("%s catches fire and burns.", Yname2(obj));
+           if (Has_contents(obj)) {
+               if (in_sight) pline("Its contents fall out.");
+               for (otmp = obj->cobj; otmp; otmp = ncobj) {
+                   ncobj = otmp->nobj;
+                   obj_extract_self(otmp);
+                   if (!flooreffects(otmp, x, y, ""))
+                       place_object(otmp, x, y);
+               }
+           }
+           delobj(obj);
+           retval++;
+       } else if (!force && (Luck + 5) > rn2(20)) {
+           /*  chance per item of sustaining damage:
+            *  max luck (full moon):    5%
+            *  max luck (elsewhen):    10%
+            *  avg luck (Luck==0):     75%
+            *  awful luck (Luck<-4):  100%
+            */
+           continue;
+       } else if (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS) {
+           if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
+               continue;
+           if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
+               if (in_sight) pline("Smoke rises from %s.", the(xname(obj)));
+               continue;
+           }
+           dindx = (obj->oclass == SCROLL_CLASS) ? 2 : 3;
+           if (in_sight)
+               pline("%s %s.", Yname2(obj), (obj->quan > 1) ?
+                     destroy_strings[dindx*3 + 1] : destroy_strings[dindx*3]);
+           delobj(obj);
+           retval++;
+       } else if (obj->oclass == POTION_CLASS) {
+           dindx = 1;
+           if (in_sight)
+               pline("%s %s.", Yname2(obj), (obj->quan > 1) ?
+                     destroy_strings[dindx*3 + 1] : destroy_strings[dindx*3]);
+           delobj(obj);
+           retval++;
+       } else if (is_flammable(obj) && obj->oeroded < MAX_ERODE &&
+                  !(obj->oerodeproof || (obj->blessed && !rnl(4)))) {
+           if (in_sight) {
+               pline("%s burn%s%s.", Yname2(obj), obj->quan > 1 ? "": "s",
+                     obj->oeroded+1 == MAX_ERODE ? " completely" :
+                     obj->oeroded ? " further" : "");
+           }
+           obj->oeroded++;
+       }
+    }
+
+    if (retval && !in_sight)
+       You("smell smoke.");
+    return retval;
+}
+
 void
 water_damage(obj, force, here)
 register struct obj *obj;
index bac73350e63b9203852bbb8a1053d3099705003e..10cb25ee6c2e8c5a6467463824ff846e9fe4f408 100644 (file)
--- a/src/zap.c
+++ b/src/zap.c
@@ -2744,7 +2744,8 @@ boolean costly = shop_keeper(*in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) &&
                delay_output();
                /* kicked objects fall in pools */
                if((weapon == KICKED_WEAPON) &&
-                  is_pool(bhitpos.x, bhitpos.y))
+                  (is_pool(bhitpos.x, bhitpos.y) ||
+                  is_lava(bhitpos.x, bhitpos.y)))
                    break;
 #ifdef SINKS
                if(IS_SINK(typ) && weapon != FLASHED_LIGHT)
index 8523ddee4a7be808eb7c701b6bcf7d08094fbf83..a046f6826031e43df007420ec88c5a7bab1d0dd2 100644 (file)
@@ -421,7 +421,7 @@ functions:382 _write_timer _yyyymmdd _zap_steed
 functions:383 _getprice _getreturn _getrumor _gettrack
 functions:384 _ini_inv _knows_object _knows_class _restricted_spell_discipline _ready_weapon
 functions:385 _doname _Doname2
-functions:386 _minwater 
+functions:386 _minliquid 
 functions:387 _missmm 
 functions:388 _missmu 
 functions:389 _missum