lava effects for monsters and objects
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().
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
26
src/apply.c
26
src/apply.c
@@ -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;
|
||||
|
||||
2
src/do.c
2
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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
42
src/mon.c
42
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] */
|
||||
|
||||
101
src/trap.c
101
src/trap.c
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user