Re: Mob Wait States?

From: Patrick Dughi (
Date: 03/20/00

> Got a quick question...  Is there any way to get mobs to obey wait states

        Actually, I spent all weekend dealing with this issue actually -
I had a few related problems, anything from players being able to cause
wait-state's to mobs, to scripted mobs firing off their script too
quickly.  I had an 'event' command which would delay something by a given
number of seconds (event <time> <command>), but this wouldn't work for
every case.  But, finally I got mobs to react to wait_state like players -
this may be different from stock, so bear with me.

        So, the first thing I did was add the wait_state into the
mob_specials structure.

        Then I edited up the WAIT_STATE macro so it chooses the correct
structure based on IS_NPC.

        Then, I added another structure in the mob_specials structure, a
simple linked list ;

struct command_list {
  char *command;
  struct command_list *next;

        I reference this with a macro -  CLIST(ch).

        Then, I added a function in heartbeat() on a per-second basis in
comm.c.  This function looks like the following:

my_function() {
  char *tempstr;
  struct char_data *tempchar;
  struct command_list *tempcmd;
  extern struct cur_error_state;
  extern struct char_data *cur_character;

  while(running through all mobs - hopefully using the safe mob check
          I wrote a bit ago for people who extract/kill chars with commands ) {
        if (WAIT_STATE(ch)>0) {


        while( cur_error_state == 0 && WAIT_STATE(ch) <= 0 && CLIST(ch)) {


  then, in handler.c, in extract_char(), i do a check, if cur_character ==
ch (the one being extracted) and if so, i set cur_error_state to 1.  Below
this, I wrote a small loop to wipe the memory allocated by the CLIST(ch)

  near the end i went through the code and found most of the references to
mobs 'doing' things using direct command calls like 'do_say' and the sort,
and changed them to the command_interpreter(,) equivilent. Some things
like the junk-collector specproc had to be changed from
'obj_from_room();obj_to_char()' to something more reasonable.

  Lastly, in command_interpreter, I add a check to see if WAIT_STATE(ch)
is > 0, and if IS_NPC(ch).  If so, I enqueue the command instead of
running it, throwing it into the CLIST at the _END_.

        Whew. Took a bit and looks like I do a bit of work.  Lets see why:

1) commands are enqueued last in - last out

  This is because any given command may have the unexpected result of
purging or altering the current state of the list.  Even more important
though - if you put em LILO, you can just pop the head and the commands
will be in the correct order.

2) the command_list struct is copied to temp vars, and the real one freed
before anything happens.

  this is important if you don't want a memory leak.  See, normally you'd
run the command, and free the structure - but if the command caused the
player to be deleted or the sort, then it'd crash when you tried to free
it..worse..there's no way to check that it's already been freed, when it's
superstructure has already been freed.  I am generating this from memory,
but I think I had to play with the command command_interpreter recieves as
well, freeing it when it returns, or not....there were some odd crash
issues associated with this one.  Anyway, this is the safe way to do it.

3) cur_character & cur_error_state ?

  yeah, well, if your character is extracted, you need to know to not try
to look at his CLIST(ch) struct, or the refernce will be the cause of a

        The one bit I glossed over - the bit about choosing the 'next'
character - for that you'll have to reference a previous posting I wrote
regarding safe character list referencing for mobs that purge/kill
themselves/others in specprocs or progs.

        Sorry for the long post, and hope that answered your question


     | Ensure that you have read the CircleMUD Mailing List FAQ:  |
     |  |

This archive was generated by hypermail 2b30 : 04/10/01 PDT