I developed this system because I felt the stock smaug mob program script system
was very underdeveloped. The stock system moved one line at a time, did not take
ifchecks into account, and also every script on a mob ran constantly all at once.

Features:
 * Creation of script groups, allowing for multiple stages of a script, with only
   one of the scripts from the group allowed to run at a single time.
 * Ability to stop/start/restart scripts via the mpscript command.
 * Like stock smaug only one line runs at a time, however ifchecks are taken into
   account by implementing the mpsleep system, which will restore the current
   environment after every line.
 * When combined with the mob prog variables snippet (my modified version of which
   is included) and the mpsleep system (included and required) will provide greater
   script flexibility.

NOTE: It is recommended that you install the mpsleep snippet before installing this
snippet. Also make sure to backup all source files in case you prefer the old system.
In case you already have mpsleep, if you haven't already, there is a fix needed for
the mpsleep system to work properly, as the originally released snippet is bugged in
regards to ifchecks, any mpsleep call inside an ifcheck did not work previously. I
fixed the bug and someone named rewrote and released the snippet, which is what is
included in this zip file.

Please email me at blueicelt@hotmail.com if you have any questions or comments, also
just drop me a line if you install and like/keep the system, would be cool to know
others find what i developed a good thing for their mud.

Function notes:
  do_mpscript():
      Syntax: mpscript <script group name>
           - This will increment the chosen script group by 1, if it is running at
             the highest script, it will revert to 0.
      Syntax: mpscript <script group name> goto <script number>
           - Will jump the given script group to the given script number

      FYI: Changing the scripts number will not terminate the script currently running
           from that group. Also, changing to -1 (or any number less than the lowest
           added script number for that group) will essentially turn that script group off.
           Same as if you don't include a number 0 script for a group, that script will not
           run until an outside prog or script essentially activates that group.

  script_group_set():
      The whole basis of the script groups works off the resetdelay variable which is
      unused by the smaug program system. Its value determines what script in a given group
      is active. Should your system use this variable in another place, or it does not
      exist in your system, you will need to add an integer variable to the mprog_data struct.

Modifications:
 Inside mud.h:
  Inside struct mpsleep_data{} add:
       MPROG_DATA *        mprg;
  
 Inside mud_prog.c:
  Change every instance of mprog_driver() calls including the prototype at the top to:
	void    mprog_driver            args( ( MPROG_DATA *mprg, char* com_list, CHAR_DATA* mob,
                                                CHAR_DATA* actor, OBJ_DATA* obj,
                                                void* vo, bool single_step ) );

     For the calls you simply need to add the following:
                mprog_driver( mprg, ......

     The exception is the call from mpsleep_update which should become:
                mprog_driver( mpsleep->mprg, ......

  Go to the mprog_driver() function:
      void mprog_driver()
      {
          // variable definitions
          bool forcedSleep = FALSE;

	  mprg->triggered = TRUE;
          .....
          while ( TRUE )
          {
              if ( !forcedSleep )
              {
                  cmnd         = command_list;
                  command_list = mprog_next_command( command_list );
          
                  /* Are we at the end? */
                  if ( cmnd[0] == '\0' )
                  {
                    if ( ifstate[iflevel][IN_IF] || ifstate[iflevel][IN_ELSE] )
                    {
                      progbug( "Missing endif", mob );
                    }
                    mprg->triggered = FALSE;
                    --prog_nest;
                    return;
                  }
          
                  /* mpsleep - Check if we should sleep -rkb *gohan */
                  one_argument( cmnd, arg );
              }
              if (forcedSleep || !str_cmp(arg, "mpsleep"))
              {
	          .....
                  mpsleep->mprg = mprg;

                  if ( !forcedSleep )
                  {
                      /* Time to sleep */
                      cmnd = one_argument( cmnd, arg);
                      if (cmnd[0] == '\0')
                          mpsleep->timer = 4;
                      else
                          mpsleep->timer = atoi(cmnd);
                  }
                  else
                      mpsleep->timer = 8;
		  .....
              }
	      .....
	      result = mprog_do_command()

              /* Script prog support  -Thoric */
              if ( single_step )
              {
                forcedSleep = TRUE;
              }
	      .....
          }
      }

  Now another thing within the mprog_driver function that you need to do is
  wherever the function is forced to return, except inside the mpsleep part
  of the function, you need to add the following just before it:
      mprg->triggered = FALSE;

  Replace the mprog_scrip_trigger() function with the following:
      void mprog_script_trigger( CHAR_DATA *mob )
      {
          MPROG_DATA * mprg;
          char * argument;
          char arg[MAX_STRING_LENGTH];
          int num;
      
          if ( HAS_PROG(mob->pIndexData, SCRIPT_PROG) )
          {
              for ( mprg = mob->pIndexData->mudprogs; mprg; mprg = mprg->next )
              {
                  if ( mprg->type == SCRIPT_PROG && !mprg->triggered )
                  {
                      if ( mprg->arglist[0] != '\0' )
                      {
                          argument = str_dup(mprg->arglist);
                          argument = one_argument(argument,arg);
                          if ( arg[0] != '\0' )
                          {
                              num = atoi(argument);
                              if ( num == mprg->resetdelay )
                                  mprog_driver( mprg, mprg->comlist, mob, NULL, NULL, NULL, TRUE );
                          }
                      }
                  }
              }
          }
      }

Function additions:
 Add to mud_comm.c:

    void do_mpscript( CHAR_DATA *ch, char *argument )
    {
        char *    arguments;
        char      arg[ MAX_INPUT_LENGTH ];
        char      arg2[ MAX_INPUT_LENGTH ];
        char      arg3[ MAX_STRING_LENGTH ];
        char      buf[ MAX_STRING_LENGTH];
        MPROG_DATA * mprg;
        int num = -2, cur = -1, max = 0;
        bool found = FALSE;
    
        if ( !IS_NPC( ch ) || IS_AFFECTED( ch, AFF_CHARM ))
        {
              stc( "Huh?\n\r", ch );
              return;
        }
    
        argument = one_argument( argument, arg ); // Script group
        argument = one_argument( argument, arg2 ); // Goto argument, otherwise auto-increment
                                                   // argument = script num to go to
        if ( arg[0] == '\0')
        {
            progbug( "Mpscript - No argument", ch );
            return;
        }
    
        if ( !str_cmp( arg2, "goto" ) )
        {
            if ( argument[0] == '\0' )
            {
                progbug( "Mpscript - Goto, no script number given", ch );
                return;
            }
    
            if ( !is_number(argument) )
            {
                progbug( "Mpscript - Goto, illegal argument", ch );
                return;
            }
    
            num = atoi(argument);
    
            if ( num < -1 )
            {
                progbug( "Mpscript - illegal script number", ch );
                return;
            }
        }
    
        if ( HAS_PROG(ch->pIndexData, SCRIPT_PROG) )
        {
            for ( mprg = ch->pIndexData->mudprogs; mprg; mprg = mprg->next )
            {
                if ( mprg->type == SCRIPT_PROG )
                {
                    if ( mprg->arglist[0] != '\0' )
                    {
                        arguments = str_dup( mprg->arglist );
                        arguments = one_argument(arguments,arg3);
    
                        if ( arg3[0] != '\0' )
                        {
                            if ( !str_cmp( arg, arg3 ) )
                            {
                                found = TRUE;
                                max = UMAX( atoi(arguments), max );
                                cur = UMAX( mprg->resetdelay, cur );
                            }
                        }
                    }
                }
            }
    
            if ( found )
            {
                if ( num == -2 )
                {
                    if ( cur >= max )
                        cur = 0;
                    else
                        cur++;
                    num = cur;
                }
    
                script_group_set( ch->pIndexData->mudprogs, arg, num );
                return;
            }
        }
        else
        {
            progbug( "Mpscript - mob has no script progs", ch );
            return;
        }
    
        sprintf( buf, "Mpscript - no script found on mob matching '%s'", arg );
        progbug( buf, ch );
        return;
    }

    void script_group_set( MPROG_DATA *mprg, char *group, int script )
    {
        char arg[MAX_STRING_LENGTH];
    
        if ( !mprg || !group || group[0] == '\0' )
            return;
    
        for ( ; mprg; mprg = mprg->next )
        {
            if ( mprg->type == SCRIPT_PROG )
            {
                if ( mprg->arglist[0] != '\0' )
                {
                    one_argument( mprg->arglist, arg );
    
                    if ( !str_cmp( arg, group ) )
                        mprg->resetdelay = script;
                }
            }
        }
    }


