diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 8931658e9..a5c65fa1c 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -66,6 +66,7 @@ Izchak's lighting store is now able to stock oil for your lamp provide core support for saving of messsage history in save file the following actions can now be continued after save/restore: digging, eating, studying, removing armor +hero-created and monster-created ice will eventually melt away Platform- and/or Interface-Specific New Features diff --git a/include/extern.h b/include/extern.h index 1eec66732..84f183458 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1982,6 +1982,7 @@ E void NDECL(run_timers); E void FDECL(obj_move_timers, (struct obj *, struct obj *)); E void FDECL(obj_split_timers, (struct obj *, struct obj *)); E void FDECL(obj_stop_timers, (struct obj *)); +E void FDECL(spot_stop_timers, (XCHAR_P,XCHAR_P,SHORT_P)); E boolean FDECL(obj_is_local, (struct obj *)); E void FDECL(save_timers, (int,int,int)); E void FDECL(restore_timers, (int,int,BOOLEAN_P,long)); @@ -2379,7 +2380,9 @@ E struct monst *FDECL(bhit, (int,int,int,int,int (*)(MONST_P,OBJ_P), E struct monst *FDECL(boomhit, (int,int)); E int FDECL(burn_floor_paper, (int,int,BOOLEAN_P,BOOLEAN_P)); E void FDECL(buzz, (int,int,XCHAR_P,XCHAR_P,int,int)); -E void FDECL(melt_ice, (XCHAR_P,XCHAR_P)); +E void FDECL(melt_ice, (XCHAR_P,XCHAR_P,const char *)); +E void FDECL(start_melt_ice_timeout, (XCHAR_P,XCHAR_P)); +E void FDECL(melt_ice_away, (genericptr_t, long)); E int FDECL(zap_over_floor, (XCHAR_P,XCHAR_P,int,boolean *)); E void FDECL(fracture_rock, (struct obj *)); E boolean FDECL(break_statue, (struct obj *)); diff --git a/include/timeout.h b/include/timeout.h index 481bf95bf..5c729ad99 100644 --- a/include/timeout.h +++ b/include/timeout.h @@ -28,7 +28,8 @@ typedef void FDECL((*timeout_proc), (genericptr_t, long)); #define BURN_OBJECT 3 #define HATCH_EGG 4 #define FIG_TRANSFORM 5 -#define NUM_TIME_FUNCS 6 +#define MELT_ICE_AWAY 6 +#define NUM_TIME_FUNCS 7 /* used in timeout.c */ typedef struct fe { diff --git a/src/timeout.c b/src/timeout.c index 75f6ef861..12314da9e 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -1309,7 +1309,8 @@ static const ttable timeout_funcs[NUM_TIME_FUNCS] = { TTAB(revive_mon, (timeout_proc)0, "revive_mon"), TTAB(burn_object, cleanup_burn, "burn_object"), TTAB(hatch_egg, (timeout_proc)0, "hatch_egg"), - TTAB(fig_transform, (timeout_proc)0, "fig_transform") + TTAB(fig_transform, (timeout_proc)0, "fig_transform"), + TTAB(melt_ice_away, (timeout_proc)0, "melt_ice_away") }; #undef TTAB @@ -1554,6 +1555,36 @@ obj_stop_timers(obj) obj->timed = 0; } +/* + * Stop all timers of index func_index at this spot. + * + */ +void +spot_stop_timers(x,y,func_index) +xchar x,y; +short func_index; +{ + timer_element *curr, *prev, *next_timer=0; + long where = (((long)x << 16) | ((long)y)); + + for (prev = 0, curr = timer_base; curr; curr = next_timer) { + next_timer = curr->next; + if (curr->kind == TIMER_LEVEL && + curr->func_index == func_index && curr->arg == (genericptr_t)where) { + if (prev) + prev->next = curr->next; + else + timer_base = curr->next; + if (timeout_funcs[curr->func_index].cleanup) + (*timeout_funcs[curr->func_index].cleanup)(curr->arg, + curr->timeout); + free((genericptr_t) curr); + } else { + prev = curr; + } + } +} + /* Insert timer into the global queue */ STATIC_OVL void diff --git a/src/trap.c b/src/trap.c index c5ac3ece0..ffec6778c 100644 --- a/src/trap.c +++ b/src/trap.c @@ -1904,7 +1904,7 @@ glovecheck: target = which_armor(mtmp, W_ARMG); !see_it && distu(mtmp->mx, mtmp->my) <= 3*3) You("smell smoke."); if (is_ice(mtmp->mx,mtmp->my)) - melt_ice(mtmp->mx,mtmp->my); + melt_ice(mtmp->mx,mtmp->my, (char *)0); if (see_it) seetrap(trap); break; @@ -2440,7 +2440,7 @@ struct obj *box; /* null for floor trap */ if (!box && burn_floor_paper(u.ux, u.uy, see_it, TRUE) && !see_it) You("smell paper burning."); if (is_ice(u.ux, u.uy)) - melt_ice(u.ux, u.uy); + melt_ice(u.ux, u.uy, (char *)0); } STATIC_OVL void diff --git a/src/zap.c b/src/zap.c index 7b1879110..f4eaa9ea4 100644 --- a/src/zap.c +++ b/src/zap.c @@ -3479,12 +3479,14 @@ register int dx,dy; } void -melt_ice(x, y) +melt_ice(x, y, msg) xchar x, y; +const char *msg; { struct rm *lev = &levl[x][y]; struct obj *otmp; + if (!msg) msg = "The ice crackles and melts."; if (lev->typ == DRAWBRIDGE_UP) lev->drawbridgemask &= ~DB_ICE; /* revert to DB_MOAT */ else { /* lev->typ == ICE */ @@ -3496,11 +3498,12 @@ xchar x, y; #endif lev->icedpool = 0; } + spot_stop_timers(x, y, MELT_ICE_AWAY); /* no more ice to melt away */ obj_ice_effects(x, y, FALSE); unearth_objs(x, y); if (Underwater) vision_recalc(1); newsym(x,y); - if (cansee(x,y)) Norep("The ice crackles and melts."); + if (cansee(x,y)) Norep(msg); if ((otmp = sobj_at(BOULDER, x, y)) != 0) { if (cansee(x,y)) pline("%s settles...", An(xname(otmp))); do { @@ -3515,6 +3518,38 @@ xchar x, y; spoteffects(TRUE); /* possibly drown, notice objects */ } +/* + * Start a melt_ice timer. + */ +void +start_melt_ice_timeout(x,y) +xchar x,y; +{ + long when, where; + short action = MELT_ICE_AWAY; + for (when = 50L; when < 2000L; when++) + if (!rn2(3)) break; + where = (((long)x << 16) | ((long)y)); + (void) start_timer(when, TIMER_LEVEL, action, (genericptr_t)where); +} + +/* + * Called when ice has melted completely away. + */ +void +melt_ice_away(arg, timeout) +genericptr_t arg; +long timeout; /* unused */ +{ + xchar x,y; + long where = (long)arg; + + y = (xchar)(where & 0xFFFF); + x = (xchar)((where >> 16) & 0xFFFF); + /* melt_ice does newsym when appropriate */ + melt_ice(x,y,"Some ice melts away."); +} + /* Burn floor scrolls, evaporate pools, etc... in a single square. Used * both for normal bolts of fire, cold, etc... and for fireballs. * Sets shopdamage to TRUE if a shop door is destroyed, and returns the @@ -3541,7 +3576,7 @@ boolean *shopdamage; if (cansee(x,y)) newsym(x,y); } if(is_ice(x, y)) { - melt_ice(x, y); + melt_ice(x, y, (char *)0); } else if(is_pool(x,y)) { const char *msgtxt = "You hear hissing gas."; if(lev->typ != POOL) { /* MOAT or DRAWBRIDGE_UP */ @@ -3627,6 +3662,7 @@ boolean *shopdamage; } } } + start_melt_ice_timeout(x,y); obj_ice_effects(x,y,TRUE); } if(closed_door(x, y)) {