MpSleep 2.0 - Compiled by Dace K. (djdace.k@gmail.com)
--------------------------------------------------------------------------
Was installing mpsleep on a new codebase of mine, and decided to compile
a fixed up version for anyone having problems with mpsleep. This version
fixes the bugs involving else statements used after mpsleep, which the
original version would simply skip over.

Any license that the original code may have been under still applies to this
one - I assume it simply involves leaving the comments intact, and giving
credit where credit's due.

Credits go to:
-------------
RASMUS BROSBOEL : Original mpsleep code.
Olcerin : Nested ifcheck fix.
Odis/WhiteKnight : Fix for skipped elsechecks.
Gohan_TheDragonball : Final fix for mpsleep within ifchecks.
===========================================================================
Introduction:
------------
The mpsleep snippet allows allows you to delay the execution of your mud
programs for a number of pulses. This will make a mob telling a story able
to pause after every line, or just some, to make it seem like the mob is
actually talking to you, not just throwing 2 pages of text after you. This
command does not pause the mob/obj/room, only the program.
This command is useable anywhere you would like to delay a mudprogram
before it moves on to the next line.
Example:
>greet_prog 80~
say Greetings $n
mpsleep 6
say I have now paused for 6 pulses
mpsleep 4
say I have now paused for 4 pulses

How to add this snippet
===========================================================================
The code in the following sections is changes needed and their surrounding
lines of code. If the line is not prefixed with a '-' or '+' it is a line
you need to find in your code. If it is prefixed with a '-' it is a line
you need to delete from your code and finally, the prefix '+' indicates a
line that must be added to your code. Lines containing only '---'
ends/begins a new block of code.

mud.h
===========================================================================
typedef struct clan_data CLAN_DATA;
typedef struct council_data COUNCIL_DATA;
typedef struct tourney_data TOURNEY_DATA;
typedef struct mob_prog_data MPROG_DATA;
typedef struct mob_prog_act_list MPROG_ACT_LIST;
+typedef struct mpsleep_data MPSLEEP_DATA;
typedef struct editor_data EDITOR_DATA;
typedef struct teleport_data TELEPORT_DATA;
typedef struct timer_data TIMER;
typedef struct godlist_data GOD_DATA;
typedef struct system_data SYSTEM_DATA;
---
sh_int open_hour; /* First opening hour */
sh_int close_hour; /* First closing hour */
};
-/* Mob program structures */
+/* Mob program structures and defines */
+/* Moved these defines here from mud_prog.c as I need them -rkb */
+#define MAX_IFS 20 /* should always be generous */
+#define IN_IF 0
+#define IN_ELSE 1
+#define DO_IF 2
+#define DO_ELSE 3
+
+#define MAX_PROG_NEST 20
+
struct act_prog_data
{
struct act_prog_data *next;
void *vo;
};
---
int resetdelay;
char * arglist;
char * comlist;
};
+/* Used to store sleeping mud progs. -rkb */
+typedef enum {MP_MOB, MP_ROOM, MP_OBJ} mp_types;
+struct mpsleep_data
+{
+ MPSLEEP_DATA * next;
+ MPSLEEP_DATA * prev;
+
+ int timer; /* Pulses to sleep */
+ mp_types type; /* Mob, Room or Obj prog */
+ ROOM_INDEX_DATA*room; /* Room when type is MP_ROOM */
+
+ /* mprog_driver state variables */
+ int ignorelevel;
+ int iflevel;
+ bool ifstate[MAX_IFS][DO_ELSE+1];
+
+ /* mprog_driver arguments */
+ char * com_list;
+ CHAR_DATA * mob;
+ CHAR_DATA * actor;
+ OBJ_DATA * obj;
+ void * vo;
+ bool single_step;
+};
+
+
bool MOBtrigger;
/*
* Per-class stuff.
*/
---
extern char * const wind_msg [];
/*
* Global variables.
*/
+extern MPSLEEP_DATA * first_mpwait; /* Storing sleeping mud progs */
+extern MPSLEEP_DATA * last_mpwait; /* - */
+extern MPSLEEP_DATA * current_mpwait; /* - */
+
extern char * bigregex;
extern char * preg;
extern char * target_name;
extern char * ranged_target_name;
---
void mprog_hour_trigger args ( ( CHAR_DATA *mob ) );
void mprog_time_trigger args ( ( CHAR_DATA *mob ) );
void progbug args( ( char *str, CHAR_DATA *mob ) );
void rset_supermob args( ( ROOM_INDEX_DATA *room) );
void release_supermob args( ( ) );
+void mpsleep_update args( ( ) );
/* planes.c */
PLANE_DATA * plane_lookup args( ( const char *name ) );
void load_planes args( ( void ) );
void save_planes args( ( void ) );
---
mud_prog.c
===========================================================================
#define IFIGNORED 8
#define ORIGNORED 9
/* Ifstate defines, used to create and access ifstate array
in mprog_driver. */
-#define MAX_IFS 20 /* should always be generous */
-#define IN_IF 0
-#define IN_ELSE 1
-#define DO_IF 2
-#define DO_ELSE 3
-
-#define MAX_PROG_NEST 20
+/* Moved these to mud.h as I needed two of them for mpsleep -rkb */
int mprog_do_command(char *cmnd, CHAR_DATA * mob, CHAR_DATA * actor,
OBJ_DATA * obj, void *vo, CHAR_DATA * rndm,
bool ignore, bool ignore_ors);
---
struct act_prog_data *room_act_list;
struct act_prog_data *obj_act_list;
struct act_prog_data *mob_act_list;
/*
+ * Global variables to handle sleeping mud progs.
+ */
+MPSLEEP_DATA *first_mpsleep = NULL;
+MPSLEEP_DATA *last_mpsleep = NULL;
+MPSLEEP_DATA *current_mpsleep = NULL;
+
+
+/*
* Local function prototypes
*/
char *mprog_next_command args((char *clist));
bool mprog_seval args((char *lhs, char *opr, char *rhs,
---
char *command_list;
char *cmnd;
CHAR_DATA *rndm = NULL;
CHAR_DATA *vch = NULL;
int count = 0;
+ int count2 = 0;
int ignorelevel = 0;
int iflevel, result;
bool ifstate[MAX_IFS][DO_ELSE + 1];
static int prog_nest;
+ MPSLEEP_DATA *mpsleep = NULL;
+ char arg[MAX_INPUT_LENGTH];
if IS_AFFECTED
(mob, AFF_CHARM)
return;
---
count++;
}
strcpy(tmpcmndlst, com_list);
command_list = tmpcmndlst;
+
+ /* mpsleep - Restore the environment -rkb */
+ if (current_mpsleep)
+ {
+ ignorelevel = current_mpsleep->ignorelevel;
+ iflevel = current_mpsleep->iflevel;
+
+ if (single_step)
+ mob->mpscriptpos = 0;
+
+ for (count = 0; count <= MAX_IFS; count++)
+ {
+ for (count2 = 0; count2 < DO_ELSE; count2++)
+ ifstate[count][count2] =
+ current_mpsleep->ifstate[count][count2];
+ }
+
+ current_mpsleep = NULL;
+ }
+
if (single_step)
{
if (mob->mpscriptpos > strlen(tmpcmndlst))
mob->mpscriptpos = 0;
else
---
}
--prog_nest;
return;
}


+ /* mpsleep - Check if we should sleep -rkb */
+    one_argument( cmnd, arg );
+ if (!str_prefix("mpsleep", cmnd) )
+ {
+   if ( (ifstate[iflevel][IN_IF] == ifstate[iflevel][DO_IF]) &&
+        (ifstate[iflevel][IN_ELSE] == ifstate[iflevel][DO_ELSE]) )
+ {
+ CREATE(mpsleep, MPSLEEP_DATA, 1);
+
+ /* State variables */
+ mpsleep->ignorelevel = ignorelevel;
+ mpsleep->iflevel = iflevel;
+ for (count = 0; count < MAX_IFS; count++)
+ {
+ for (count2 = 0; count2 < DO_ELSE; count2++)
+ {
+ mpsleep->ifstate[count][count2] =
+ ifstate[count][count2];
+ }
+ }
+ }
+
+ /* Driver arguments */
+ mpsleep->com_list = STRALLOC(command_list);
+ mpsleep->mob = mob;
+ mpsleep->actor = actor;
+ mpsleep->obj = obj;
+ mpsleep->vo = vo;
+ mpsleep->single_step = single_step;
+
+	/* Time to sleep */
+    cmnd = one_argument( cmnd, arg);
+    if (cmnd[0] == '\0')
+        mpsleep->timer = 4;
+    else
+        mpsleep->timer = atoi(cmnd);;
+
+ if (mpsleep->timer < 1)
+ {
+ progbug("mpsleep - bad arg, using default", mob);
+ mpsleep->timer = 4;
+ }
+
+ /* Save type of prog, room, object or mob */
+ if (mpsleep->mob->pIndexData->vnum == 3)
+ {
+ if (!str_prefix("Room", mpsleep->mob->description))
+ {
+ mpsleep->type = MP_ROOM;
+ mpsleep->room = mpsleep->mob->in_room;
+ }
+ else if (!str_prefix("Object", mpsleep->mob->description))
+ mpsleep->type = MP_OBJ;
+ }
+ else
+ mpsleep->type = MP_MOB;
+
+ LINK(mpsleep, first_mpsleep, last_mpsleep, next, prev);
+
+ --prog_nest;
+ return;
+ }
+
/* Evaluate/execute the command, check what happened. */
result = mprog_do_command(cmnd, mob, actor, obj, vo, rndm,
(ifstate[iflevel][IN_IF] && !ifstate[iflevel][DO_IF])
|| (ifstate[iflevel][IN_ELSE] && !ifstate[iflevel][DO_ELSE]),
(ignorelevel > 0));
---
}
/***************************************************************************
* Global function code and brief comments.
*/
+
+
+/* See if there's any mud programs waiting to be continued -rkb */
+void mpsleep_update()
+{
+ MPSLEEP_DATA *mpsleep;
+ MPSLEEP_DATA *tmpMpsleep;
+ bool delete_it;
+
+ mpsleep = first_mpsleep;
+ while (mpsleep)
+ {
+ delete_it = FALSE;
+
+ if (mpsleep->mob)
+ delete_it = char_died(mpsleep->mob);
+
+ if (mpsleep->actor && !delete_it)
+ delete_it = char_died(mpsleep->actor);
+
+ if (mpsleep->obj && !delete_it)
+ delete_it = obj_extracted(mpsleep->obj);
+
+ if (delete_it)
+ {
+ log_string("mpsleep_update - Deleting expired prog.");
+
+ tmpMpsleep = mpsleep;
+ mpsleep = mpsleep->next;
+ STRFREE(tmpMpsleep->com_list);
+ UNLINK(tmpMpsleep, first_mpsleep, last_mpsleep, next, prev);
+ DISPOSE(tmpMpsleep);
+
+ continue;
+ }
+
+ mpsleep = mpsleep->next;
+ }
+
+ mpsleep = first_mpsleep;
+ while (mpsleep) /* Find progs to continue */
+ {
+ if (--mpsleep->timer <= 0)
+ {
+ current_mpsleep = mpsleep;
+
+ if (mpsleep->type == MP_ROOM)
+ rset_supermob(mpsleep->room);
+ else if (mpsleep->type == MP_OBJ)
+ set_supermob(mpsleep->obj);
+
+ mprog_driver(mpsleep->com_list, mpsleep->mob, mpsleep->actor,
+ mpsleep->obj, mpsleep->vo, mpsleep->single_step);
+
+ release_supermob();
+
+ tmpMpsleep = mpsleep;
+ mpsleep = mpsleep->next;
+ STRFREE(tmpMpsleep->com_list);
+ UNLINK(tmpMpsleep, first_mpsleep, last_mpsleep, next, prev);
+ DISPOSE(tmpMpsleep);
+
+ continue;
+ }
+
+ mpsleep = mpsleep->next;
+ }
+}
+
bool mprog_keyword_check(const char *argu, const char *argl)
{
char word[MAX_INPUT_LENGTH];
char arg1[MAX_INPUT_LENGTH];
---
update.c
===========================================================================
{
auction->pulse = PULSE_AUCTION;
auction_update();
}
+ mpsleep_update(); /* Check for sleeping mud progs -rkb */
tele_update();
aggr_update();
obj_act_update();
room_act_update();
clean_obj_queue(); /* dispose of extracted objects */
---

Enjoy! :).
This snippet, and others, can be found at http://satsui.serverbox.org .
- Dace K.