From: Pasi Kallinen Date: Wed, 30 Sep 2020 16:43:12 +0000 (+0300) Subject: Fire sources can ignite candles, lamps, and potions of oil X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6a35a84c56844e6c4bc6d2105c2368f9cd8f650e;p=nethack Fire sources can ignite candles, lamps, and potions of oil ... on the floor, in monster inventory, and in hero's inventory. Items in your inventory being ignited produce a message even if you're blind - you can see the lit-state by viewing inventory anyway, so just give player the message. (via xNetHack) --- diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 8897d086f..9355123bd 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -263,6 +263,7 @@ when make was invoked with -j makedefs instances could end up running in provide a work-alike mkstemp() implementation for windows visual studio in mdlib.c so there is no requirement to define HAS_NO_MKSTEMP there make piranhas faster and give them extra bite attack +fire sources can ignite candles, lamps, and potions of oil Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index 374598ae4..7e4af0781 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2715,6 +2715,7 @@ E boolean NDECL(lava_effects); E void NDECL(sink_into_lava); E void NDECL(sokoban_guilt); E const char * FDECL(trapname, (int, BOOLEAN_P)); +E void FDECL(ignite_items, (struct obj *)); /* ### u_init.c ### */ diff --git a/src/artifact.c b/src/artifact.c index 990be7b43..c71c0e87c 100644 --- a/src/artifact.c +++ b/src/artifact.c @@ -1192,6 +1192,8 @@ int dieroll; /* needed for Magicbane and vorpal blades */ (void) destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE); if (!rn2(7)) (void) destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE); + if (!rn2(4)) + ignite_items(mdef->minvent); if (youdefend && Slimed) burn_away_slime(); return realizes_damage; diff --git a/src/explode.c b/src/explode.c index 469eaeff2..8abe642fd 100644 --- a/src/explode.c +++ b/src/explode.c @@ -412,6 +412,9 @@ int expltype; idamnonres += destroy_mitem(mtmp, WAND_CLASS, (int) adtyp); idamnonres += destroy_mitem(mtmp, RING_CLASS, (int) adtyp); + if (adtyp == AD_FIRE) + ignite_items(mtmp->minvent); + if (explmask[i][j] == 1) { golemeffects(mtmp, (int) adtyp, dam + idamres); mtmp->mhp -= idamnonres; @@ -500,8 +503,10 @@ int expltype; You("are unharmed!"); } else if (adtyp == AD_PHYS || physical_dmg) damu = Maybe_Half_Phys(damu); - if (adtyp == AD_FIRE) + if (adtyp == AD_FIRE) { (void) burnarmor(&g.youmonst); + ignite_items(g.invent); + } destroy_item(SCROLL_CLASS, (int) adtyp); destroy_item(SPBOOK_CLASS, (int) adtyp); destroy_item(POTION_CLASS, (int) adtyp); diff --git a/src/mcastu.c b/src/mcastu.c index e53195f72..f6b23986e 100644 --- a/src/mcastu.c +++ b/src/mcastu.c @@ -553,6 +553,7 @@ int spellnum; destroy_item(SCROLL_CLASS, AD_FIRE); destroy_item(POTION_CLASS, AD_FIRE); destroy_item(SPBOOK_CLASS, AD_FIRE); + ignite_items(g.invent); (void) burn_floor_objects(u.ux, u.uy, TRUE, FALSE); break; case CLC_LIGHTNING: { diff --git a/src/mhitm.c b/src/mhitm.c index e848c1d99..e08ce35ba 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -1042,6 +1042,7 @@ int dieroll; } /* only potions damage resistant players in destroy_item */ tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE); + ignite_items(mdef->minvent); break; case AD_COLD: if (cancelled) { diff --git a/src/mhitu.c b/src/mhitu.c index ddfc45453..f28f0c6b7 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -1115,6 +1115,8 @@ register struct attack *mattk; destroy_item(POTION_CLASS, AD_FIRE); if ((int) mtmp->m_lev > rn2(25)) destroy_item(SPBOOK_CLASS, AD_FIRE); + if ((int) mtmp->m_lev > rn2(20)) + ignite_items(g.invent); burn_away_slime(); } else dmg = 0; @@ -2362,6 +2364,8 @@ struct attack *mattk; destroy_item(POTION_CLASS, AD_FIRE); if (lev > rn2(25)) destroy_item(SPBOOK_CLASS, AD_FIRE); + if (lev > rn2(20)) + ignite_items(g.invent); if (dmg) mdamageu(mtmp, dmg); } diff --git a/src/muse.c b/src/muse.c index 424a444c5..f14f979ff 100644 --- a/src/muse.c +++ b/src/muse.c @@ -1594,6 +1594,7 @@ struct monst *mtmp; (void) destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE); (void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE); (void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE); + ignite_items(mtmp->minvent); num = (2 * (rn1(3, 3) + 2 * bcsign(otmp)) + 1) / 3; if (Fire_resistance) You("are not harmed."); diff --git a/src/polyself.c b/src/polyself.c index fbfe59fd1..5beef979f 100644 --- a/src/polyself.c +++ b/src/polyself.c @@ -1447,6 +1447,8 @@ dogaze() (void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE); if (lev > rn2(25)) (void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE); + if (lev > rn2(20)) + ignite_items(mtmp->minvent); if (dmg) mtmp->mhp -= dmg; if (DEADMONSTER(mtmp)) diff --git a/src/trap.c b/src/trap.c index c2e30afd5..7aa3f3e71 100644 --- a/src/trap.c +++ b/src/trap.c @@ -2434,6 +2434,7 @@ register struct monst *mtmp; (void) destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE); (void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE); (void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE); + ignite_items(mtmp->minvent); } if (burn_floor_objects(mtmp->mx, mtmp->my, see_it, FALSE) && !see_it && distu(mtmp->mx, mtmp->my) <= 3 * 3) @@ -3196,6 +3197,7 @@ struct obj *box; /* null for floor trap */ destroy_item(SCROLL_CLASS, AD_FIRE); destroy_item(SPBOOK_CLASS, AD_FIRE); destroy_item(POTION_CLASS, AD_FIRE); + ignite_items(g.invent); } if (!box && burn_floor_objects(u.ux, u.uy, see_it, TRUE) && !see_it) You("smell paper burning."); @@ -5400,6 +5402,7 @@ lava_effects() destroy_item(SCROLL_CLASS, AD_FIRE); destroy_item(SPBOOK_CLASS, AD_FIRE); destroy_item(POTION_CLASS, AD_FIRE); + ignite_items(g.invent); return FALSE; } @@ -5560,4 +5563,45 @@ boolean override; return defsyms[trap_to_defsym(ttyp)].explanation; } +/* Ignite ignitable items in the given object chain, due to some external source + * of fire. The object chain should be somewhere exposed, like someone's open + * inventory or the floor. + * This is modeled after destroy_item() somewhat and hopefully will be able to + * merge into it in the future. + */ +void +ignite_items(objchn) +struct obj *objchn; +{ + struct obj *obj; + boolean vis = FALSE; + if (!objchn) + return; + + if (objchn->where == OBJ_INVENT) + vis = TRUE; /* even when blind; lit-state can be seen in inventory */ + else if (objchn->where == OBJ_MINVENT) + vis = canseemon(objchn->ocarry); + else if (objchn->where == OBJ_FLOOR) + vis = cansee(objchn->ox, objchn->oy); + else { + impossible("igniting item in a weird location %d", objchn->where); + return; + } + + for (obj = objchn; obj; obj = obj->nobj) { + if (!(ignitable(obj) || obj->otyp == MAGIC_LAMP) + /* The Candelabrum requires intention to be lit */ + || obj->otyp == CANDELABRUM_OF_INVOCATION + || obj->otyp == BRASS_LANTERN /* doesn't ignite via fire */ + || obj->in_use /* not available */ + || obj->lamplit) { /* already burning */ + continue; + } + begin_burn(obj, FALSE); + if (vis) + pline("%s on fire!", Yobjnam2(obj, "catch")); + } +} + /*trap.c*/ diff --git a/src/uhitm.c b/src/uhitm.c index 4a0b6f7e7..53a82d7d3 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -1790,6 +1790,7 @@ int specialdmg; /* blessed and/or silver bonus against various things */ } /* only potions damage resistant players in destroy_item */ tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE); + ignite_items(mdef->minvent); break; case AD_COLD: if (negated) { diff --git a/src/zap.c b/src/zap.c index 049090edc..3910b909a 100644 --- a/src/zap.c +++ b/src/zap.c @@ -2428,6 +2428,7 @@ boolean ordinary; destroy_item(POTION_CLASS, AD_FIRE); destroy_item(SPBOOK_CLASS, AD_FIRE); destroy_item(FOOD_CLASS, AD_FIRE); /* only slime for now */ + ignite_items(g.invent); break; case WAN_COLD: @@ -3717,6 +3718,8 @@ struct obj **ootmp; /* to return worn armor for caller to disintegrate */ (void) destroy_mitem(mon, SCROLL_CLASS, AD_FIRE); if (!rn2(5)) (void) destroy_mitem(mon, SPBOOK_CLASS, AD_FIRE); + if (!rn2(3)) + ignite_items(mon->minvent); destroy_mitem(mon, FOOD_CLASS, AD_FIRE); /* carried slime */ } break; @@ -3874,6 +3877,8 @@ xchar sx, sy; destroy_item(SCROLL_CLASS, AD_FIRE); if (!rn2(5)) destroy_item(SPBOOK_CLASS, AD_FIRE); + if (!rn2(3)) + ignite_items(g.invent); destroy_item(FOOD_CLASS, AD_FIRE); } break; @@ -4035,6 +4040,9 @@ boolean u_caused; } } } + /* This also ignites floor items, but does not change cnt + because they weren't consumed. */ + ignite_items(g.level.objects[x][y]); return cnt; }