This is a modified sleep code based off of mpsleep
and an updated snippet by Jason De Leon. This version
not only does mprogs, but all progs and I even made the
timer go by seconds, not pulses, so pause 4 literally is
4 seconds of waiting.

-Bojack

Example:
obj echo The fountain's water turns {Ggreen{x because of $n's presence.
pause 4
obj echo The water recirculates and becomes {Bblue{x again.

OR

obj echo The fountain's water turns {Ggreen{x because of $n's presence.
wait 4
obj echo The water recirculates and becomes {Bblue{x again.


--------Installation----------

---merc.h---
Find:
/*
 * Structure types.
 */

Add somewhere in there:
typedef struct    prog_pause_data  PROG_PAUSE_DATA;

Find:
/*
 * Prog types
 */

Add after #define PRG_RPROG       2:

/* Moved from mob_prog.c for pause code */
#define MAX_NESTED_LEVEL 12 /* Maximum nested if-else-endif's (stack size) */
#define BEGIN_BLOCK       0 /* Flag: Begin of if-else-endif block */
#define IN_BLOCK         -1 /* Flag: Executable statements */
#define END_BLOCK        -2 /* Flag: End of if-else-endif block */
#define MAX_CALL_LEVEL   12 /* Maximum nested calls */

--Note: We use 12 max level calls, set it to whatever you like

Find:
struct prog_code
{
    sh_int              vnum;
    char *              code;
    PROG_CODE *         next;
};

Add after:

//For pausing mprogs/oprogs/rprogs
struct prog_pause_data
{
    PROG_PAUSE_DATA *   next;
    PROG_PAUSE_DATA *   prev;
    CHAR_DATA       *   player;
    CHAR_DATA       *   actor;
    OBJ_DATA        *   obj;
    ROOM_INDEX_DATA *   room;
    char            *   code;
    sh_int              vnum;
    int                 pause;
    const void      *   arg1;
    const void      *   arg2;
    int                 lines;
    int                 state[MAX_NESTED_LEVEL];
    bool                cond[MAX_NESTED_LEVEL];
    int                 level;
    bool                set;
    bool                valid;
};


Find:
void    program_flow    args( (

After:
                                const void *arg2 ) );
Add:
                                , PROG_PAUSE_DATA *tmp ) );
So it looks like this:
                                const void *arg2, PROG_PAUSE_DATA *tmp ) );

At the bottom after:
/*
 * Global variables
 */

Add this in somewhere:
extern        PROG_PAUSE_DATA * first_pause;
extern        PROG_PAUSE_DATA * last_pause;


---mob_cmds.c---
In this file change every: extern void program_flow(
to this:
    extern void program_flow( sh_int, char *, CHAR_DATA *, OBJ_DATA *, ROOM_INDEX_DATA *, CHAR_DATA *, const void *, const void *, PROG_PAUSE_DATA * );

And for every: program_flow( prg->vnum 
call, add a NULL after: (void *)obj2

An EXAMPLE looks like this:
    program_flow( prg->vnum, prg->code, ch, NULL, NULL, vch, (void *)obj1, (void *)obj2, NULL );

--Note: DO not copy and paste that ^, it is just an example!

---mob_prog.c---
At the top with the includes, add at the end of those:
#include "recycle.h" //For pause data

After:
extern int flag_lookup

Add:
PROG_PAUSE_DATA *first_pause = NULL;
PROG_PAUSE_DATA *last_pause = NULL;


Find:
void program_flow(

Add after: const void *arg2
, PROG_PAUSE_DATA *tmp )

So void program_flow should look like this:
void program_flow(
        sh_int pvnum,  /* For diagnostic purposes */
        char *source,  /* the actual MOBprog code */
        CHAR_DATA *mob,
        OBJ_DATA *obj,
        ROOM_INDEX_DATA *room,
        CHAR_DATA *ch, const void *arg1, const void *arg2,
        PROG_PAUSE_DATA *tmp )

Add after: sh_int mvnum = 0, ovnum = 0, rvnum = 0;
    PROG_PAUSE_DATA *pause;
    int count = 0;

Find:
    if( ++call_level > MAX_CALL_LEVEL )

Change To:
    if( !tmp && ++call_level > MAX_CALL_LEVEL )

Find:
    /*
     * Reset "stack"
     */

Change To:
    if ( tmp && tmp->set == TRUE )
    {
        for ( level = 0; level < MAX_NESTED_LEVEL; level++ )
        {
            state[level] = tmp->state[level];
            cond[level] = tmp->cond[level];
        }
        level = tmp->level;
    }
    else {
        for ( level = 0; level < MAX_NESTED_LEVEL; level++ )
        {
            state[level] = IN_BLOCK;
            cond[level]  = TRUE;
        }
        level = 0;
    }

Find:
        /*
         * Match control words
         */

Right after that, add this:
        //If paused, find lines and start there
        if ( ( tmp ) && count++ < tmp->lines )
            continue;

Then above: if (!str_cmp( control, "if" ) )
Add this:
        count++;

--Note: The count has to be after the tmp check, otherwise the lines get
thrown off.

Find:
        else if ( cond[level] == TRUE
            && ( !str_cmp( control, "break" ) || !str_cmp( control, "end" ) ) )

Add after:  return; }
        else if ( !str_cmp( control, "pause" ) || !str_cmp( control, "wait" ) )
        {
            //First check to see if its in an if statement
            if ( level && cond[level-1] == FALSE ) continue;

            //Secondly check to see if this pause is the same one returned
            if ( ( tmp ) && count == tmp->lines ) continue;

            int amount, roll;

            line = one_argument( line, control );
            //Check first
            if (!is_number( control ) || (amount = atoi( control )) <= 0)
                amount = 1;
            //Get amount
            else {
                amount = atoi( control );
            }

            //Save information
            pause = new_pause();

            pause->player = ch;
            if ( mob )
                pause->actor = mob;
            else
                pause->actor = NULL;
            if ( obj )
                pause->obj = obj;
            else
                pause->obj = NULL;
            if ( room )
                pause->room = room;
            else
                pause->room = NULL;
            pause->pause = amount;
            pause->vnum = pvnum;
            pause->code = source;
            pause->lines = count;
            pause->arg1 = arg1;
            pause->arg2 = arg2;
            for (roll = 0; roll < MAX_NESTED_LEVEL; roll++)
            {
                pause->state[roll] = state[roll];
                pause->cond[roll] = cond[roll];
            }
            pause->level = level;
            pause->set = TRUE;

            pause->next = first_pause;
            if (first_pause)
                first_pause->prev = pause;
            first_pause = pause;
            return; //Stop the program here
        }


--Now before doing the below changes, first go through this
whole file looking for program_flow () calls and add at the end
after arg2 this:
, NULL )
An EXAMPLE would look like this:
                program_flow( prg->vnum, prg->code, mob, NULL, NULL, ch, arg1, arg2 );

                program_flow( prg->vnum, prg->code, mob, NULL, NULL, ch, arg1, arg2, NULL );

Once that is all complete, start the below changes.

Find:
void p_act_trigger(

Add after PROG_LIST *prg;
    PROG_PAUSE_DATA *pause;

In the same function, find: if ( mob )
Right before program_flow( prg->vnum, prg->code, mob, NULL ....
Add:
                for(pause = first_pause; pause != NULL; pause = pause->next)
                    if(pause->player == ch && pause->vnum == prg->vnum)
                        return;
Do the same for: else if ( obj ) and: else if ( room )


Find:
bool p_percent_trigger(

Add after PROG_LIST *prg;
    PROG_PAUSE_DATA *pause;

In the same function, find: if ( mob )
Right before program_flow( prg->vnum, prg->code, mob, NULL ....
Add:
                for(pause = first_pause; pause != NULL; pause = pause->next)
                    if(pause->actor == mob && pause->vnum == prg->vnum)
                        return ( TRUE );
In else if ( obj ) before program_flow( prg->vnum, prg->code ...
Add:
                for(pause = first_pause; pause != NULL; pause = pause->next)
                    if(pause->obj == obj && pause->vnum == prg->vnum)
                        return ( TRUE );

In else if ( room ) before program_flow( prg->vnum, prg->code ...
Add:
                for(pause = first_pause; pause != NULL; pause = pause->next)
                    if(pause->room == room && pause->vnum == prg->vnum)
                        return ( TRUE );

Reason we aren't using if(pause->player == ch for the above codes
is p_percent_trigger doesnt have to have a person near to have the trigger
go off. Using random as a trigger is one example.

Find:
void p_bribe_trigger(

Add after PROG_LIST *prg;
    PROG_PAUSE_DATA *pause;

Right before program_flow( prg->vnum, prg->code, mob, NULL ...
Add:
            for(pause = first_pause; pause != NULL; pause = pause->next)
                if(pause->player == ch && pause->vnum == prg->vnum)
                    return;

Find:
bool p_exit_trigger(
Add after PROG_LIST *prg;
    PROG_PAUSE_DATA *pause;

In this function BEFORE ALL program_flow calls, add this:
                        for(pause = first_pause; pause != NULL; pause = pause->next)
                            if(pause->player == ch && pause->vnum == prg->vnum)
                                return TRUE;

Find:
void p_give_trigger(
Add after PROG_LIST *prg;
    PROG_PAUSE_DATA *pause;

In if ( mob ) before both program_flow calls, add:
                        for(pause = first_pause; pause != NULL; pause = pause->next)
                            if(pause->player == ch && pause->vnum == prg->vnum)
                                return;

In else if ( obj ) before program_flow, add:
                for(pause = first_pause; pause != NULL; pause = pause->next)
                    if(pause->obj == obj && pause->vnum == prg->vnum)
                        return;

In else if ( room ) before both program_flow calls, add:
                        for(pause = first_pause; pause != NULL; pause = pause->next)
                            if(pause->room == room && pause->vnum == prg->vnum)
                                return;

Find:
void p_hprct_trigger

Before the program_flow call, add:
            for(pause = first_pause; pause != NULL; pause = pause->next)
                if(pause->player == ch && pause->vnum == prg->vnum)
                    return;


---recycle.c---
At the bottom of this file, add:
PROG_PAUSE_DATA *pause_free;

PROG_PAUSE_DATA *new_pause( void )
{
    static PROG_PAUSE_DATA pause_zero;
    PROG_PAUSE_DATA *tmp;
    int count;

    if (pause_free == NULL)
        tmp = alloc_perm(sizeof(*tmp));
    else {
        tmp = pause_free;
        pause_free = pause_free->next;
    }

    *tmp = pause_zero;
    tmp->room = NULL;
    tmp->obj = NULL;
    tmp->actor = NULL;
    tmp->player = NULL;
    tmp->pause = 0;
    tmp->vnum = 0;
    tmp->code = str_dup("");
    tmp->arg1 = NULL;
    tmp->arg2 = NULL;
    tmp->lines = 0;
    for (count = 0; count < MAX_NESTED_LEVEL; count++)
    {
        tmp->state[count] = 0;
        tmp->cond[count] = FALSE;
    }
    tmp->level = 0;
    tmp->set = FALSE;
    VALIDATE (tmp);

    return tmp;
}

void free_pause( PROG_PAUSE_DATA *tmp )
{
    if (!IS_VALID(tmp))
        return;

    INVALIDATE (tmp);
    tmp->room = NULL;
    tmp->obj = NULL;
    tmp->actor = NULL;
    tmp->arg1 = NULL;
    tmp->arg2 = NULL;
    free_string(tmp->code);

    tmp->next = pause_free;
    pause_free = tmp;
}



---recycle.h---
Add at the bottom of this file:

PROG_PAUSE_DATA *new_pause      args( ( void ) );
void            free_pause      args( ( PROG_PAUSE_DATA * ) );


---update.c---
Add with the Local functions.

void prog_update        args ( ( void ) );

Find:
void update_handler (void)

Add before that and the int pulse_backup (if its there):

//See if any progs need to continue
void prog_update( void )
{
    PROG_PAUSE_DATA *tmp, *tmp_next;

    for (tmp = first_pause; tmp != NULL; tmp = tmp_next)
    {
        tmp_next = tmp->next;

        if (tmp->actor == NULL && tmp->obj == NULL
            && tmp->room == NULL)
        {
            //Delete pause data
            logstr (LOG_GAME, "Prog update: Found null progs, deleting.", 0);
            if (tmp->prev)
                tmp->prev->next = tmp->next;
            if (tmp->next)
                tmp->next->prev = tmp->prev;
            if (tmp == first_pause && (tmp->next == NULL || tmp->prev == NULL) )
                first_pause = tmp->next;
            free_pause( tmp );
            continue;
        }

        //Takes away 1 sec and checks it
        if (--tmp->pause <= 0)
        {
            //Continue prog
            if (tmp->vnum > 0)
                program_flow( tmp->vnum, tmp->code, tmp->actor, tmp->obj,
                    tmp->room, tmp->player, tmp->arg1, tmp->arg2, tmp );
            //Delete pause data
            if (tmp->prev)
                tmp->prev->next = tmp->next;
            if (tmp->next)
                tmp->next->prev = tmp->prev;
            if (tmp == first_pause && (tmp->next == NULL || tmp->prev == NULL) )
                first_pause = tmp->next;

            free_pause( tmp );
        }
    }
    return;
}


In:
void update_handler (void)
Add with the static int's:
    static int pulse_progs = 0;

Before:
    aggr_update ();
Add:
    if (--pulse_progs <= 0)
    {
        pulse_progs = PULSE_SECOND;
        prog_update();
    }

--This above sets every call to prog update to an actual second
instead of having it each pulse. 4 pulses = 1 second
PULSE_SECOND should be defined in merc.h, if it is not
then change: pulse_progs = PULSE_SECOND; to:
pulse_progs = 4;

Thats it for the installation, just do a make/copyover and
you should be set. Enjoy!