1
0
Fork 0
mirror of https://codeberg.org/noisytoot/notnotdnethack.git synced 2025-07-27 07:52:25 +01:00

Fix how timers are paused

Do not remove from global list! Doing so makes it invisible.

Instead, put paused & migrating timers on back end of procchain, not executable.
This commit is contained in:
NeroOneTrueKing 2022-08-07 13:38:50 -05:00
parent 70903321ed
commit d8b483ef65
6 changed files with 106 additions and 21 deletions

View file

@ -2885,8 +2885,12 @@ E void FDECL(desummon_obj, (genericptr_t, long));
E void FDECL(summoner_gone, (struct monst *, boolean));
E void FDECL(stop_corpse_timers, (struct obj *));
E boolean FDECL(start_timer, (long, SHORT_P, SHORT_P, genericptr_t));
E void FDECL(pause_timer, (timer_element *));
E void FDECL(resume_timer, (timer_element *));
E void FDECL(pause_timers, (timer_element *));
E void FDECL(resume_timers, (timer_element *));
E void FDECL(migrate_timers, (timer_element *));
E void FDECL(receive_timers, (timer_element *));
E long FDECL(stop_timer, (SHORT_P, timer_element *));
E void FDECL(stop_all_timers, (timer_element *));
E void NDECL(run_timers);

View file

@ -49,13 +49,16 @@ typedef void FDECL((*timeout_proc), (genericptr_t, long));
/* used in timeout.c */
typedef struct timer {
struct timer *next; /* next item in PROCESSING chain */
struct timer *tnxt; /* next item in LOCAL chain */
long timeout; /* when we time out */
unsigned long tid; /* timer ID */
short kind; /* kind of use */
short func_index; /* what to call when we time out */
genericptr_t arg; /* pointer to timeout argument */
struct timer *next; /* next item in PROCESSING chain */
struct timer *tnxt; /* next item in LOCAL chain */
long timeout; /* when we time out */
unsigned long tid; /* timer ID */
short kind; /* kind of use */
short func_index; /* what to call when we time out */
genericptr_t arg; /* pointer to timeout argument */
int timerflags; /* flags for the timer */
} timer_element;
#define TIMERFLAG_PAUSED 0x01 /* pause progression of timer -- 'timeout' is how many turns were remaining when paused, instead of end-turn*/
#define TIMERFLAG_MIGRATING 0x10 /* progress but do not execute timer, as 'arg' is migrating */
#endif /* TIMEOUT_H */

View file

@ -547,7 +547,7 @@ boolean with_you;
}
}
/* now that it's placed, we can resume timers (which may kill mtmp) */
resume_timers(mtmp->timed);
receive_timers(mtmp->timed);
}
/* heal monster for time spent elsewhere */
@ -921,7 +921,7 @@ migrate_to_level(mtmp, tolev, xyloc, cc)
summoner_gone(mtmp, TRUE);
/* timers pause processing while mon is migrating */
pause_timers(mtmp->timed);
migrate_timers(mtmp->timed);
relmon(mtmp);
mtmp->nmon = migrating_mons;

View file

@ -1845,7 +1845,7 @@ obj_delivery()
otmp->ox = otmp->oy = 0;
rloco(otmp);
}
resume_timers(otmp->timed);
receive_timers(otmp->timed);
}
}

View file

@ -3486,7 +3486,7 @@ add_to_migration(obj)
if (obj->where != OBJ_FREE)
panic("add_to_migration: obj not free");
pause_timers(obj->timed);
migrate_timers(obj->timed);
obj->where = OBJ_MIGRATING;
obj->nobj = migrating_objs;
migrating_objs = obj;

View file

@ -2692,7 +2692,9 @@ STATIC_DCL void FDECL(rem_procchain_tm, (timer_element *));
STATIC_DCL void FDECL(rem_locchain_tm, (timer_element *, timer_element **));
/* ordered timer list */
static timer_element *timer_base; /* "active" */
static timer_element *timer_base; /* head of timer procchain */
static timer_element *timer_paused; /* helper pointer to first paused/migrating timer in procchain */
static timer_element *timer_last; /* last timer in procchain */
static unsigned long timer_id = 1;
@ -2879,16 +2881,32 @@ timer_element * tm;
return;
}
}
/* insert in ordered place in processing loop */
for (prev = 0, curr = timer_base; curr; prev = curr, curr = curr->next)
/* insert into procchain */
if (tm->timerflags & (TIMERFLAG_PAUSED | TIMERFLAG_MIGRATING)) {
/* timer is not executable, goes on very end, order independent */
prev = timer_last;
curr = (timer_element *)0;
if (!timer_paused)
timer_paused = tm;
}
else
{
if (curr->timeout >= tm->timeout) break;
/* insert in ordered place in processing loop */
for (prev = 0, curr = timer_base; curr && curr != timer_paused; prev = curr, curr = curr->next)
{
if (curr->timeout >= tm->timeout) break;
}
}
tm->next = curr;
if (prev)
prev->next = tm;
prev->next = tm;
else
timer_base = tm;
timer_base = tm;
if (!curr)
timer_last = tm;
return;
}
@ -2902,16 +2920,32 @@ timer_element * tm;
if (timer_base == tm) {
timer_base = tm->next;
if (timer_paused == tm)
timer_paused = tm->next;
if (!tm->next)
timer_last = timer_base;
return;
}
else for (tmtmp = timer_base; tmtmp; tmtmp = tmtmp->next) {
if (tmtmp->next == tm) {
tmtmp->next = tm->next;
if (timer_paused == tm)
timer_paused = tm->next;
if (!tm->next)
timer_last = tmtmp;
return;
}
}
return;
}
/* removes and readds a timer from the procchain, so that it is in the correct place */
void
adj_procchain_tm(tm)
timer_element * tm;
{
rem_procchain_tm(tm);
add_procchain_tm(tm);
}
/* removes a timer from a local chain */
void
@ -3037,6 +3071,26 @@ timer_element * tm;
}
}
/* temporarily pause processing of a single timer */
void
pause_timer(tm)
timer_element * tm;
{
tm->timeout = tm->timeout - monstermoves;
tm->timerflags |= TIMERFLAG_PAUSED;
adj_procchain_tm(tm);
}
/* resume processing of a single timer */
void
resume_timer(tm)
timer_element * tm;
{
tm->timeout = tm->timeout + monstermoves;
tm->timerflags &= ~TIMERFLAG_PAUSED;
adj_procchain_tm(tm);
flags.run_timers = TRUE;
}
/* temporarily pause processing of all timers on chain until it they are resumed */
void
pause_timers(tm)
@ -3044,7 +3098,7 @@ timer_element * tm;
{
timer_element *curr;
for (curr = tm; curr; curr = tm->tnxt)
rem_procchain_tm(curr);
pause_timer(curr);
}
/* resume processing of all timers on chain */
@ -3054,9 +3108,33 @@ timer_element * tm;
{
timer_element *curr;
for (curr = tm; curr; curr = tm->tnxt)
add_procchain_tm(curr);
/* catch up with lost time */
run_timers();
resume_timer(curr);
}
/* set all timers on chain as migrating (do not execute) */
void
migrate_timers(tm)
timer_element * tm;
{
timer_element *curr;
for (curr = tm; curr; curr = tm->tnxt)
{
curr->timerflags |= TIMERFLAG_MIGRATING;
adj_procchain_tm(curr);
}
}
/* resume handling of migrating timers on chain */
void
receive_timers(tm)
timer_element * tm;
{
timer_element *curr;
for (curr = tm; curr; curr = tm->tnxt)
{
curr->timerflags &= ~TIMERFLAG_MIGRATING;
adj_procchain_tm(curr);
}
flags.run_timers = TRUE;
}
void