HELPFILES


1 INSTAROOM~

Syntax: EDRESET INSTAROOM   Sets all the resets for the room you are standing in.


The Instaroom command allows a builder to instantly set up resets for the room
you are standing in. The way it works is thus:

A builder must LOAD all objects and mobs into the room for which they are to
be reset into. The mob and object put into the room must be within that areas
vnums. ( In other words, no loading of a Mob/Obj with vnum 1 into a room that has
a set of vnums 200 - 299 )

HOW TO USE: Very simple. Load a mobile into the room. Force that mob to hold something, 
wear something, or just 'give' it something. Also load any objects into the room.
If it's a container, put any objects you want inside that container within in it.
( If you load a box, make sure everything you want in the box is in there ). Then
just type in INSTAROOM.

!!A NOTE ON POSITIONS!!: It doesn't matter if your mob is awake or asleep when
you create the reset. Nor if an item is set as trash or not. The only thing the
code is looking for is where that mobs/obj's vnum is at in relevance to the rooms
vnum. SO THAT MEANS! Make sure all 'containers' within a room are OPEN before you
issue the instaroom command. Again, make sure you have all the containers open, so
that anything within the container can be read first. After you have done the
instaroom setting, you can then force your mobs to sleep, or close/lock your
containers.

This code contributed by Kyndig of kyndig.com
~

===============================instaroom.c======================================
/* Instaroom code by Kyndig
 * Allows resets to be placed on a room, according to current
 * mob/obj/container/exit placement of that room.
 * Syntax: instaroom
 *
 *
 * Additional needed install instructions:
 * Place the following 2 lines in => struct room_index_data{ in merc.h:
 *   RESET_DATA *        last_mob_reset;
 *   RESET_DATA *        last_obj_reset;
 * 
 * Place the following line in => struct  reset_data{ in merc.h
 * RESET_DATA *        prev;
 *
 * You can build an 'instant area reset maker' based off this code
 * Developed by Kyndig from http://www.kyndig.com/  kyndig@kyndig.com
 */
#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#include <sys/time.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <unistd.h>
#include "merc.h"
#include "olc.h"
#include "recycle.h"



/* Locals */
void wipe_resets( ROOM_INDEX_DATA *pRoom );
void instaroom( ROOM_INDEX_DATA *pRoom );


/* NOTE: This does not create RANDOM room exits, my exit system was
 * abit to much to port it to stock ROM so I simply removed. It will be up
 * to you to edit these functions to return what you desire
 */


/* Original idea taken from the SMAUG server, the LINK macro is a direct
 * reflection of the outstanding work of Thoric from realms.org
 */

/* double-linked list handling macros -Thoric */
#define LINK(link, first, last, next, prev)                     \
do                                                              \
{                                                               \
    if ( !(first) )                                             \
      (first)                   = (link);                       \
    else                                                        \
      (last)->next              = (link);                       \
    (link)->next                = NULL;                         \
    (link)->prev                = (last);                       \
    (last)                      = (link);                       \
} while(0)



/* called from do_instaroom further below */
void reset_instaroom( CHAR_DATA *ch, char *argument )
{
  ROOM_INDEX_DATA     *pRoom;
  CHAR_DATA           *mob;
  OBJ_DATA            *obj, *inobj;

  pRoom = ch->in_room;

  /* Containers can NOT be closed when doing an 'instaroom'. Thus a builder will have to close
   * the container after the reset is installed
   */

  /* lets go through a mob first */
  for ( mob = ch->in_room->people; mob; mob = mob->next_in_room )
  {
     if ( IS_NPC( mob ) )
     {
         /* only mobs with this areas vnums are allowed */
        if ( mob->pIndexData->area != pRoom->area )
        {
           send_to_char( "There is a mob in this room that is not part of your area, resets not set.\n\r", ch );
           return;
        }
    
        for ( obj = mob->carrying; obj; obj = obj->next_content )
        {
           if( obj->pIndexData->area != pRoom->area )
           {
               send_to_char( "There is an object in a MOB that is not part of your area, resets not set.\n\r", ch );
              return;
           }
      
           if ( IS_SET( obj->value[1], CONT_CLOSED ) )
           {
              send_to_char( "There is a container in a MOB I can't see inside of. Get the container from the mob, open\n\r"
                            "it up, give it _back_ to your mob, then do an instaroom.\n\r" 
                            "AFTER you have set the container to load into the mob,\n\r"
                            "you can then get the container from him again, close/lock it, and return it....In other words\n\r"
                            "A container must be open first, the reset installed, after that, you can close/lock it.\n\r",ch);
              return;
           }

           if ( obj->contains )
           {
               for (inobj = obj->contains; inobj; inobj = obj->next_content )
               {
                   if ( inobj->pIndexData->area != pRoom->area )
                   {
                      send_to_char("There is an object in a container which a MOB in this room has, which is not\n\r"
                                   "a vnum for this area. RESETS NOT SET.\n\r",ch);
                      return;
                   }
               }
           }
        }
     }
  }/* done looking at mobs and their eq/inv */


  /* lets take a look at objects in the room and their contents */ 
  for ( obj = pRoom->contents; obj != NULL; obj = obj->next_content )
  {
      if( obj->pIndexData->area != pRoom->area )
      {
          send_to_char( "There is an object in this room that is not a vnum of your area, resets not set.\n\r", ch );
          return;
      }
  
      if ( IS_SET( obj->value[1], CONT_CLOSED ) )
      {
          send_to_char( "There is a container in this room I can't see inside of. Open it up first, do the\n\r"
                        "instaroom command, THEN you can close/lock the container.\n\r",ch);
          return;
      }

      if ( obj->contains )
      {
         for (inobj = obj->contains; inobj; inobj = obj->next_content )
         {
            if ( inobj->pIndexData->area != pRoom->area )
            {
               send_to_char("There is an object in a container that does not a vnum in this area. No resets set.\n\r",ch);
               return;
            }
         }
      }
  }

  if ( pRoom->reset_first )
    wipe_resets(pRoom);  
  instaroom( pRoom );

  send_to_char( "Room resets installed.\n\r", ch );
  return;
}

/* Separate function for recursive purposes */
void delete_reset( ROOM_INDEX_DATA *pRoom, RESET_DATA *pReset, int insert_loc, bool wipe_all)
{

  if( !pRoom->reset_first )
  {
     return;
  }

  if ( insert_loc-1 <= 0 )
  {
       pReset = pRoom->reset_first;
       pRoom->reset_first = pRoom->reset_first->next;
       if ( !pRoom->reset_first )
           pRoom->reset_last = NULL;
   }
   else
   {
       int iReset = 0;
       RESET_DATA *prev = NULL;

       for ( pReset = pRoom->reset_first;
             pReset;
             pReset = pReset->next )
       {
             if ( ++iReset == insert_loc )
                    break;
             prev = pReset;
       }

       if ( !pReset )
       {
           return;
       }

        if ( prev )
            prev->next = prev->next->next;
        else
            pRoom->reset_first = pRoom->reset_first->next;

        for ( pRoom->reset_last = pRoom->reset_first;
              pRoom->reset_last->next;
              pRoom->reset_last = pRoom->reset_last->next );
   }/*else*/

   if ( pReset == pRoom->last_mob_reset )
    pRoom->last_mob_reset = NULL;
  if ( pReset == pRoom->last_obj_reset )
    pRoom->last_obj_reset = NULL;

   free_reset_data( pReset );

   /* TRUE/FALSE call on delete_reset here, so we can delete all resets or just one */
   if( wipe_all )
   {
     if( ( pReset = pRoom->reset_first)  != '\0')
       delete_reset( pRoom, pReset, 1, TRUE );
   }
}

void wipe_resets( ROOM_INDEX_DATA *pRoom )
{
  RESET_DATA *pReset;
  int i = 1;
  
  for ( pReset = pRoom->reset_first; pReset != NULL; )
  {
    if (pReset)
    {
      delete_reset(pRoom, pReset, i, TRUE);
    }
    i++;
    pReset = pReset->next;
  }
  return;
}

/* make_reset called by add_new_reset in order to create a blank
 * reset to load data into the reset_list 
 */
RESET_DATA *make_reset( char letter, int arg1, int arg2, int arg3, int arg4 )
{
        RESET_DATA *pReset;

        pReset          = new_reset_data();
        pReset->command = letter;
        pReset->arg1    = arg1;
        pReset->arg2    = arg2;
        pReset->arg3    = arg3;
        pReset->arg4    = arg4;
        return pReset;
}


/* add_new_reset called from several places below, it adds in the actual pReset
 * arguments to the reset_list..tricky footwork here 
 */
RESET_DATA *add_new_reset( ROOM_INDEX_DATA *pRoom, char letter, int arg1, int arg2, int arg3, int arg4 )
{
    RESET_DATA *pReset;

    if ( !pRoom )
    {
        bug( "add_reset: NULL area!", 0 );
        return NULL;
    }

    letter = UPPER(letter);
    pReset = make_reset( letter, arg1, arg2, arg3, arg4 );
    switch( letter )
    {
        case 'M':  pRoom->last_mob_reset = pReset;      break;
        case 'E':  case 'G':  case 'P':
        case 'O':  pRoom->last_obj_reset = pReset;      break;
            break;
    }

    /* LINK code from the SMAUG server */
    LINK( pReset, pRoom->reset_first, pRoom->reset_last, next, prev );
    return pReset;
}


/* Called from instaroom */
/* The below function debugged by Chalc on the Romlist, thanx again Chalc */
void add_obj_reset( ROOM_INDEX_DATA *pRoom, char cm, OBJ_DATA *obj, int v2, int v3, int v4 )
{
  add_new_reset( pRoom, cm, obj->pIndexData->vnum, v2, v3, v4 );

  if(obj->contains)
  {
    OBJ_INDEX_DATA **objList;
    OBJ_DATA *inObj;
    int *objCount;
    int count;
    int itemCount;

    for(inObj = obj->contains, itemCount = 0; inObj; inObj = inObj->next_content) itemCount++;

    /* Now have count objects in obj, allocate space for lists */
    objList = alloc_mem(itemCount * sizeof(OBJ_INDEX_DATA *));
    objCount = alloc_mem(itemCount * sizeof(int));
    
    /* Initialize Memory */
    memset(objList, 0, itemCount * sizeof(OBJ_INDEX_DATA *));
    memset(objCount, 0, itemCount * sizeof(int));

    /* Figure out how many of each obj is in the container */
    for(inObj = obj->contains; inObj; inObj = inObj->next_content)
    {
      for(count = 0; objList[count] && objList[count] != inObj->pIndexData; count++);
      if(!objList[count]) objList[count] = inObj->pIndexData;
      objCount[count]++;
    }    

    /* Create the resets */
    for(count = 0; objList[count]; count++)
      add_new_reset(pRoom, 'P', objList[count]->vnum, objCount[count], obj->pIndexData->vnum, objCount[count]);

    /* Free the memory */
    free_mem(objList, itemCount * sizeof(OBJ_INDEX_DATA *));
    free_mem(objCount, itemCount * sizeof(int));
  }
  /* And Done */
  return;
}

void instaroom( ROOM_INDEX_DATA *pRoom )
{
  CHAR_DATA *rch;
  OBJ_DATA *obj;
  
  for ( rch = pRoom->people; rch; rch = rch->next_in_room )
  {
    if ( !IS_NPC(rch) )
      continue;
    add_new_reset( pRoom, 'M',rch->pIndexData->vnum, rch->pIndexData->count, pRoom->vnum, 3 );
    for ( obj = rch->carrying; obj; obj = obj->next_content )
    {
      if ( obj->wear_loc == WEAR_NONE )
        add_obj_reset( pRoom, 'G', obj, 1, 0, 3 );
      else
        add_obj_reset( pRoom, 'E', obj, 1, obj->wear_loc, 3 );
    }
  }
  for ( obj = pRoom->contents; obj; obj = obj->next_content )
  {
    add_obj_reset( pRoom, 'O', obj, 1, pRoom->vnum, 1 );
  }
  return;
}

void do_instaroom( CHAR_DATA *ch, char *argument )
{
  ROOM_INDEX_DATA *pRoom = ch->in_room;
  char arg[MAX_INPUT_LENGTH];

  argument = one_argument(argument, arg);

  if ( pRoom->reset_first )
    wipe_resets(pRoom);  
  instaroom( pRoom );

  send_to_char( "Room resets installed.\n\r", ch );
}