dotd-2.3.7/area/
dotd-2.3.7/clans/
dotd-2.3.7/classes/
dotd-2.3.7/councils/
dotd-2.3.7/deity/
dotd-2.3.7/dict/
dotd-2.3.7/doc/mudprogs/
dotd-2.3.7/player/a/
dotd-2.3.7/player/g/
/****************************************************************************
 * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame      |   \\._.//   *
 * -----------------------------------------------------------|   (0...0)   *
 * SMAUG 1.0 (C) 1994, 1995, 1996 by Derek Snider             |    ).:.(    *
 * -----------------------------------------------------------|    {o o}    *
 * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus,      |   / ' ' \   *
 * Scryn, Rennard, Swordbearer, Gorog, Grishnakh and Tricops  |~'~.VxvxV.~'~*
 * ------------------------------------------------------------------------ *
 * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael        *
 * Chastain, Michael Quan, and Mitchell Tse.                                *
 * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,          *
 * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.     *
 * ------------------------------------------------------------------------ *
 *			 Online Reset Editing Module			    *
 ****************************************************************************/

/*
 * This file relies heavily on the fact that your linked lists are correct,
 * and that pArea->reset_first is the first reset in pArea.  Likewise,
 * pArea->reset_last *MUST* be the last reset in pArea.  Weird and
 * wonderful things will happen if any of your lists are messed up, none
 * of them good.  The most important are your pRoom->contents,
 * pRoom->people, rch->carrying, obj->contains, and pArea->reset_first ..
 * pArea->reset_last.  -- Altrag
 */

/*static char rcsid[] = "$Id: reset.c,v 1.24 2004/04/06 22:00:11 dotd Exp $";*/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "mud.h"
#include "rareobj.h"

DECLARE_DO_FUN(do_reset);
DECLARE_DO_FUN(do_rreset);

/* Externals */
extern	int	top_reset;
char *		sprint_reset	args( ( CHAR_DATA *ch, RESET_DATA *pReset,
                                        sh_int num, bool rlist ) );
RESET_DATA *	parse_reset	args( ( AREA_DATA *tarea, char *argument,
                                        CHAR_DATA *ch ) );
int		get_wearloc	args( ( char *type ) );
int		get_trapflag	args( ( char *flag ) );
int		get_exflag	args( ( char *flag ) );
int		get_rflag	args( ( char *flag ) );

bool is_room_reset  args( ( RESET_DATA *pReset, ROOM_INDEX_DATA *aRoom,
                            AREA_DATA *pArea ) );
void add_obj_reset  args( ( AREA_DATA *pArea, char cm, OBJ_DATA *obj,
                            int v2, int v3 ) );
void delete_reset   args( ( AREA_DATA *pArea, RESET_DATA *pReset ) );
void instaroom      args( ( AREA_DATA *pArea, ROOM_INDEX_DATA *pRoom,
                            bool dodoors ) );
#define RID ROOM_INDEX_DATA
RID *find_room      args( ( CHAR_DATA *ch, char *argument,
                            ROOM_INDEX_DATA *pRoom ) );
#undef RID
void edit_reset     args( ( CHAR_DATA *ch, char *argument, AREA_DATA *pArea,
                            ROOM_INDEX_DATA *aRoom ) );
#define RD RESET_DATA
RD *find_reset      args( ( AREA_DATA *pArea, ROOM_INDEX_DATA *pRoom,
                            int num ) );
#undef RD
void list_resets    args( ( CHAR_DATA *ch, AREA_DATA *pArea,
                            ROOM_INDEX_DATA *pRoom, int start, int end ) );



RESET_DATA *find_reset(AREA_DATA *pArea, ROOM_INDEX_DATA *pRoom, int numb)
{
    RESET_DATA *pReset;
    int num = 0;
    
    for ( pReset = pArea->first_reset; pReset; pReset = pReset->next )
        if ( is_room_reset(pReset, pRoom, pArea) && ++num >= numb )
            return pReset;
    return NULL;
}

/* This is one loopy function.  Ugh. -- Altrag */
bool is_room_reset( RESET_DATA *pReset, ROOM_INDEX_DATA *aRoom,
                    AREA_DATA *pArea )
{
    ROOM_INDEX_DATA *pRoom;
    RESET_DATA *reset;
    int pr;
    
    if ( !aRoom )
        return TRUE;
    switch( pReset->command )
    {
    case 'M':
    case 'O':
        pRoom = get_room_index( pReset->arg3 );
        if ( !pRoom || pRoom != aRoom )
            return FALSE;
        return TRUE;
    case 'P':
    case 'T':
    case 'H':
        if ( pReset->command == 'H' )
            pr = pReset->arg1;
        else
            pr = pReset->arg3;
        for ( reset = pReset->prev; reset; reset = reset->prev )
            if ( (reset->command == 'O' || reset->command == 'P' ||
                  reset->command == 'G' || reset->command == 'E') &&
                 (!pr || pr == reset->arg1) && obj_exists_index(reset->arg1) )
                break;
        if ( reset && is_room_reset(reset, aRoom, pArea) )
            return TRUE;
        return FALSE;
    case 'B':
        switch(pReset->arg2 & BIT_RESET_TYPE_MASK)
        {
        case BIT_RESET_DOOR:
        case BIT_RESET_ROOM:
            return (aRoom->vnum == pReset->arg1);
        case BIT_RESET_MOBILE:
            for ( reset = pReset->prev; reset; reset = reset->prev )
                if ( reset->command == 'M' && mob_exists_index(reset->arg1) )
                    break;
            if ( reset && is_room_reset(reset, aRoom, pArea) )
                return TRUE;
            return FALSE;
        case BIT_RESET_OBJECT:
            for ( reset = pReset->prev; reset; reset = reset->prev )
                if ( (reset->command == 'O' || reset->command == 'P' ||
                      reset->command == 'G' || reset->command == 'E') &&
                     (!pReset->arg1 || pReset->arg1 == reset->arg1) &&
                     obj_exists_index(reset->arg1) )
                    break;
            if ( reset && is_room_reset(reset, aRoom, pArea) )
                return TRUE;
            return FALSE;
        }
        return FALSE;
    case 'G':
    case 'E':
        for ( reset = pReset->prev; reset; reset = reset->prev )
            if ( reset->command == 'M' && mob_exists_index(reset->arg1) )
                break;
        if ( reset && is_room_reset(reset, aRoom, pArea) )
            return TRUE;
        return FALSE;
    case 'D':
    case 'R':
        pRoom = get_room_index( pReset->arg1 );
        if ( !pRoom || pRoom->area != pArea || (aRoom && pRoom != aRoom) )
            return FALSE;
        return TRUE;
    default:
        return FALSE;
    }
    return FALSE;
}

ROOM_INDEX_DATA *find_room( CHAR_DATA *ch, char *argument,
                            ROOM_INDEX_DATA *pRoom )
{
    char arg[MAX_INPUT_LENGTH];
    
    if ( pRoom )
        return pRoom;
    one_argument(argument, arg);
    if ( !is_number(arg) && arg[0] != '\0' )
    {
        send_to_char( "Reset to which room?\n\r", ch );
        return NULL;
    }
    if ( arg[0] == '\0' )
        pRoom = ch->in_room;
    else
        pRoom = get_room_index(atoi(arg));
    if ( !pRoom )
    {
        send_to_char( "Room does not exist.\n\r", ch );
        return NULL;
    }
    return pRoom;
}

/* Separate function for recursive purposes */
#define DEL_RESET(area, reset, rprev) \
    do { \
    rprev = reset->prev; \
    delete_reset(area, reset); \
    reset = rprev; \
    continue; \
    } while(0)
void delete_reset( AREA_DATA *pArea, RESET_DATA *pReset )
{
    RESET_DATA *reset;
    RESET_DATA *reset_prev;
    
    if ( pReset->command == 'M' )
    {
        for ( reset = pReset->next; reset; reset = reset->next )
        {
            /* Break when a new mob found */
            if ( reset->command == 'M' )
                break;
            /* Delete anything mob is holding */
            if ( reset->command == 'G' || reset->command == 'E' )
                DEL_RESET(pArea, reset, reset_prev);
            if ( reset->command == 'B' &&
                 (reset->arg2 & BIT_RESET_TYPE_MASK) == BIT_RESET_MOBILE &&
                 (!reset->arg1 || reset->arg1 == pReset->arg1) )
                DEL_RESET(pArea, reset, reset_prev);
        }
    }
    else if ( pReset->command == 'O' || pReset->command == 'P' ||
              pReset->command == 'G' || pReset->command == 'E' )
    {
        for ( reset = pReset->next; reset; reset = reset->next )
        {
            if ( reset->command == 'T' &&
                 (!reset->arg3 || reset->arg3 == pReset->arg1) )
                DEL_RESET(pArea, reset, reset_prev);
            if ( reset->command == 'H' &&
                 (!reset->arg1 || reset->arg1 == pReset->arg1) )
                DEL_RESET(pArea, reset, reset_prev);
            /* Delete nested objects, even if they are the same object. */
            if ( reset->command == 'P' && (reset->arg3 > 0 ||
                                           pReset->command != 'P' || reset->extra-1 == pReset->extra) &&
                 (!reset->arg3 || reset->arg3 == pReset->arg1) )
                DEL_RESET(pArea, reset, reset_prev);
            if ( reset->command == 'B' &&
                 (reset->arg2 & BIT_RESET_TYPE_MASK) == BIT_RESET_OBJECT &&
                 (!reset->arg1 || reset->arg1 == pReset->arg1) )
                DEL_RESET(pArea, reset, reset_prev);
            
            /* Break when a new object of same type is found */
            if ( (reset->command == 'O' || reset->command == 'P' ||
                  reset->command == 'G' || reset->command == 'E') &&
                 reset->arg1 == pReset->arg1 )
                break;
        }
    }
    if ( pReset == pArea->last_mob_reset )
        pArea->last_mob_reset = NULL;
    if ( pReset == pArea->last_obj_reset )
        pArea->last_obj_reset = NULL;
    UNLINK(pReset, pArea->first_reset, pArea->last_reset, next, prev);
    DISPOSE(pReset);
    return;
}
#undef DEL_RESET

RESET_DATA *find_oreset(CHAR_DATA *ch, AREA_DATA *pArea,
                        ROOM_INDEX_DATA *pRoom, char *name)
{
    RESET_DATA *reset;
    
    if ( !*name )
    {
        for ( reset = pArea->last_reset; reset; reset = reset->prev )
        {
            if ( !is_room_reset(reset, pRoom, pArea) )
                continue;
            switch(reset->command)
            {
            default:
                continue;
            case 'O': case 'E': case 'G': case 'P':
                break;
            }
            break;
        }
        if ( !reset )
            send_to_char( "No object resets in list.\n\r", ch );
        return reset;
    }
    else
    {
        char arg[MAX_INPUT_LENGTH];
        int cnt = 0, num = number_argument(name, arg);
        OBJ_INDEX_DATA *pObjTo = NULL;
        
        for ( reset = pArea->first_reset; reset; reset = reset->next )
        {
            if ( !is_room_reset(reset, pRoom, pArea) )
                continue;
            switch(reset->command)
            {
            default:
                continue;
            case 'O': case 'E': case 'G': case 'P':
                break;
            }
            if ( (pObjTo = get_obj_index(reset->arg1)) &&
                 is_name(arg, pObjTo->name) && ++cnt == num )
                break;
        }
        if ( !pObjTo || !reset )
        {
            send_to_char( "To object not in reset list.\n\r", ch );
            return NULL;
        }
    }
    return reset;
}

RESET_DATA *find_mreset(CHAR_DATA *ch, AREA_DATA *pArea,
                        ROOM_INDEX_DATA *pRoom, char *name)
{
    RESET_DATA *reset;
    
    if ( !*name )
    {
        for ( reset = pArea->last_reset; reset; reset = reset->prev )
        {
            if ( !is_room_reset(reset, pRoom, pArea) )
                continue;
            switch(reset->command)
            {
            default:
                continue;
            case 'M':
                break;
            }
            break;
        }
        if ( !reset )
            send_to_char( "No mobile resets in list.\n\r", ch );
        return reset;
    }
    else
    {
        char arg[MAX_INPUT_LENGTH];
        int cnt = 0, num = number_argument(name, arg);
        MOB_INDEX_DATA *pMob = NULL;
        
        for ( reset = pArea->first_reset; reset; reset = reset->next )
        {
            if ( !is_room_reset(reset, pRoom, pArea) )
                continue;
            switch(reset->command)
            {
            default:
                continue;
            case 'M':
                break;
            }
            if ( (pMob = get_mob_index(reset->arg1)) &&
                 is_name(arg, pMob->player_name) && ++cnt == num )
                break;
        }
        if ( !pMob || !reset )
        {
            send_to_char( "Mobile not in reset list.\n\r", ch );
            return NULL;
        }
    }
    return reset;
}

void edit_reset( CHAR_DATA *ch, char *argument, AREA_DATA *pArea,
                 ROOM_INDEX_DATA *aRoom )
{
    char arg[MAX_INPUT_LENGTH];
    RESET_DATA *pReset = NULL;
    RESET_DATA *reset = NULL;
    MOB_INDEX_DATA *pMob = NULL;
    ROOM_INDEX_DATA *pRoom;
    OBJ_INDEX_DATA *pObj;
    int num = 0;
    int vnum;
    char *origarg = argument;
    
    argument = one_argument(argument, arg);
    if ( !*arg || !str_cmp(arg, "?") )
    {
	const char *nm = (ch->substate == SUB_REPEATCMD ? "" : (aRoom ? "rreset "
                                                          : "reset "));
	const char *rn = (aRoom ? "" : " [room#]");
        ch_printf(ch, "Syntax: %s<list|edit|delete|add|insert|place%s>\n\r",
                  nm, (aRoom ? "" : "|area"));
        ch_printf( ch, "Syntax: %sremove <#>\n\r", nm );
        ch_printf( ch, "Syntax: %smobile <mob#> [limit]%s\n\r", nm, rn );
        ch_printf( ch, "Syntax: %sobject <obj#> [limit [room%s]]\n\r", nm, rn );
        ch_printf( ch, "Syntax: %sobject <obj#> give <mob name> [limit]\n\r", nm );
        ch_printf( ch, "Syntax: %sobject <obj#> equip <mob name> <location> "
                   "[limit]\n\r", nm );
        ch_printf( ch, "Syntax: %sobject <obj#> put <to_obj name> [limit]\n\r",
                   nm );
        ch_printf( ch, "Syntax: %shide <obj name>\n\r", nm );
        ch_printf( ch, "Syntax: %strap <obj name> <type> <charges> <flags>\n\r",
                   nm );
        ch_printf( ch, "Syntax: %strap room <type> <charges> <flags>\n\r", nm );
        ch_printf( ch, "Syntax: %sbit <set|toggle|remove> door%s <dir> "
                   "<exit flags>\n\r", nm, rn );
        ch_printf( ch, "Syntax: %sbit <set|toggle|remove> object <obj name> "
                   "<extra flags>\n\r", nm );
        ch_printf( ch, "Syntax: %sbit <set|toggle|remove> mobile <mob name> "
                   "<affect flags>\n\r", nm );
        ch_printf( ch, "Syntax: %sbit <set|toggle|remove> room%s <room flags>"
                   "\n\r", nm, rn );
        ch_printf( ch, "Syntax: %srandom <last dir>%s\n\r", nm, rn );
        if ( !aRoom )
        {
            send_to_char( "\n\r[room#] will default to the room you are in, "
                          "if unspecified.\n\r", ch );
        }
        return;
    }
    if ( !str_cmp(arg, "on") )
    {
        ch->substate = SUB_REPEATCMD;
        ch->dest_buf = (aRoom ? (void *)aRoom : (void *)pArea);
        send_to_char( "Reset mode on.\n\r", ch );
        return;
    }
    if ( !aRoom && !str_cmp(arg, "area") )
    {
        if ( !pArea->first_reset )
        {
            send_to_char( "You don't have any resets defined.\n\r", ch );
            return;
        }
        num = pArea->nplayer;
        pArea->nplayer = 0;
        reset_area(pArea);
        pArea->nplayer = num;
        send_to_char( "Done.\n\r", ch );
        return;
    }
    
    if ( !str_cmp(arg, "list") )
    {
        int start, end;
        
        argument = one_argument(argument, arg);
        start = is_number(arg) ? atoi(arg) : -1;
        argument = one_argument(argument, arg);
        end   = is_number(arg) ? atoi(arg) : -1;
        list_resets(ch, pArea, aRoom, start, end);
        return;
    }
    
    if ( !str_cmp(arg, "edit") )
    {
        argument = one_argument(argument, arg);
        if ( !*arg || !is_number(arg) )
        {
            send_to_char( "Usage: reset edit <number> <command>\n\r", ch );
            return;
        }
        if ( !(pReset = find_reset(pArea, aRoom, num)) )
        {
            send_to_char( "Reset not found.\n\r", ch );
            return;
        }
        if ( !(reset = parse_reset(pArea, argument, ch)) )
        {
            send_to_char( "Error in reset.  Reset not changed.\n\r", ch );
            return;
        }
        reset->prev = pReset->prev;
        reset->next = pReset->next;
        if ( !pReset->prev )
            pArea->first_reset = reset;
        else
            pReset->prev->next = reset;
        if ( !pReset->next )
            pArea->last_reset  = reset;
        else
            pReset->next->prev = reset;
        DISPOSE(pReset);

        SET_AREA_FLAG(pArea, AFLAG_MODIFIED);

        send_to_char( "Done.\n\r", ch );
        return;
    }
    if ( !str_cmp(arg, "add") )
    {
        if ( (pReset = parse_reset(pArea, argument, ch)) == NULL )
        {
            send_to_char( "Error in reset.  Reset not added.\n\r", ch );
            return;
        }
        add_reset(pArea, pReset->command, pReset->extra, pReset->arg1,
                  pReset->arg2, pReset->arg3);
        DISPOSE(pReset);

        SET_AREA_FLAG(pArea, AFLAG_MODIFIED);

        send_to_char( "Done.\n\r", ch );
        return;
    }
    if ( !str_cmp(arg, "place") )
    {
        if ( (pReset = parse_reset(pArea, argument, ch)) == NULL )
        {
            send_to_char( "Error in reset.  Reset not added.\n\r", ch );
            return;
        }
        place_reset(pArea, pReset->command, pReset->extra, pReset->arg1,
                    pReset->arg2, pReset->arg3);
        DISPOSE(pReset);

        SET_AREA_FLAG(pArea, AFLAG_MODIFIED);

        send_to_char( "Done.\n\r", ch );
        return;
    }
    if ( !str_cmp(arg, "insert") )
    {
        argument = one_argument(argument, arg);
        if ( !*arg || !is_number(arg) )
        {
            send_to_char( "Usage: reset insert <number> <command>\n\r", ch );
            return;
        }
        num = atoi(arg);
        if ( (reset = find_reset(pArea, aRoom, num)) == NULL )
        {
            send_to_char( "Reset not found.\n\r", ch );
            return;
        }
        if ( (pReset = parse_reset(pArea, argument, ch)) == NULL )
        {
            send_to_char( "Error in reset.  Reset not inserted.\n\r", ch );
            return;
        }
        INSERT(pReset, reset, pArea->first_reset, next, prev);

        SET_AREA_FLAG(pArea, AFLAG_MODIFIED);

        send_to_char( "Done.\n\r", ch );
        return;
    }
    if ( !str_cmp(arg, "delete") )
    {
        int start, end;
        bool found;
        
        if ( !*argument )
        {
            send_to_char( "Usage: reset delete <start> [end]\n\r", ch );
            return;
        }
        argument = one_argument(argument, arg);
        start = is_number(arg) ? atoi(arg) : -1;
        end   = is_number(arg) ? atoi(arg) : -1;
        num = 0; found = FALSE;
        for ( pReset = pArea->first_reset; pReset; pReset = reset )
        {
            reset = pReset->next;
            if ( !is_room_reset(pReset, aRoom, pArea) )
                continue;
            if ( start > ++num )
                continue;
            if ( (end != -1 && num > end) || (end == -1 && found) )
                return;
            UNLINK(pReset, pArea->first_reset, pArea->last_reset, next, prev);
            if ( pReset == pArea->last_mob_reset )
                pArea->last_mob_reset = NULL;
            DISPOSE(pReset);
            SET_AREA_FLAG(pArea, AFLAG_MODIFIED);
            top_reset--;
            found = TRUE;
        }
        if ( !found )
            send_to_char( "Reset not found.\n\r", ch );
        else
            send_to_char( "Done.\n\r", ch );
        return;
    }
    
    if ( !str_cmp(arg, "remove") )
    {
        int iarg;
        
        argument = one_argument(argument, arg);
        if ( arg[0] == '\0' || !is_number(arg) )
        {
            send_to_char( "Delete which reset?\n\r", ch );
            return;
        }
        iarg = atoi(arg);
        for ( pReset = pArea->first_reset; pReset; pReset = pReset->next )
        {
            if ( is_room_reset( pReset, aRoom, pArea ) && ++num == iarg )
                break;
        }
        if ( !pReset )
        {
            send_to_char( "Reset does not exist.\n\r", ch );
            return;
        }
        delete_reset( pArea, pReset );

        SET_AREA_FLAG(pArea, AFLAG_MODIFIED);

        send_to_char( "Reset deleted.\n\r", ch );
        return;
    }
    if ( !str_prefix( arg, "mobile" ) )
    {
        argument = one_argument(argument, arg);
        if ( arg[0] == '\0' || !is_number(arg) )
        {
            send_to_char( "Reset which mobile vnum?\n\r", ch );
            return;
        }
        if ( !(pMob = get_mob_index(atoi(arg))) )
        {
            send_to_char( "Mobile does not exist.\n\r", ch );
            return;
        }
        argument = one_argument(argument, arg);
        if ( arg[0] == '\0' )
            num = 1;
        else if ( !is_number(arg) )
        {
            send_to_char( "Reset how many mobiles?\n\r", ch );
            return;
        }
        else
            num = atoi(arg);
        if ( !(pRoom = find_room(ch, argument, aRoom)) )
            return;
        pReset = make_reset('M', 0, pMob->ivnum, num, pRoom->vnum);
        LINK(pReset, pArea->first_reset, pArea->last_reset, next, prev);

        SET_AREA_FLAG(pArea, AFLAG_MODIFIED);

        send_to_char( "Mobile reset added.\n\r", ch );
        return;
    }
    if ( !str_prefix(arg, "object") )
    {
        argument = one_argument(argument, arg);
        if ( arg[0] == '\0' || !is_number(arg) )
        {
            send_to_char( "Reset which object vnum?\n\r", ch );
            return;
        }
        if ( !(pObj = get_obj_index(atoi(arg))) )
        {
            send_to_char( "Object does not exist.\n\r", ch );
            return;
        }
        argument = one_argument(argument, arg);
        if ( arg[0] == '\0' )
            strcpy(arg, "room");
        if ( !str_prefix( arg, "put" ) )
        {
            argument = one_argument(argument, arg);
            if ( !(reset = find_oreset(ch, pArea, aRoom, arg)) )
                return;
            /* Put in_objects after hide and trap resets */
            while ( reset->next && (reset->next->command == 'H' ||
                                    reset->next->command == 'T' || reset->next->command == 'B') )
                reset = reset->next;
            /*      pReset = make_reset('P', 1, pObj->vnum, num, reset->arg1);*/
            argument = one_argument(argument, arg);
            if ( (vnum = atoi(arg)) < 1 )
                vnum = 1;
            pReset = make_reset('P', reset->extra+1, pObj->ivnum, 0, vnum);
            /* Grumble.. insert puts pReset before reset, and we need it after,
             so we make a hackup and reverse all the list params.. :P.. */
            INSERT(pReset, reset, pArea->last_reset, prev, next);

            SET_AREA_FLAG(pArea, AFLAG_MODIFIED);

            send_to_char( "Object reset in object created.\n\r", ch );
            return;
        }
        if ( !str_prefix( arg, "give" ) )
        {
            argument = one_argument(argument, arg);
            if ( !(reset = find_mreset(ch, pArea, aRoom, arg)) )
                return;
            while ( reset->next && reset->next->command == 'B' )
                reset = reset->next;
            argument = one_argument(argument, arg);
            if ( (vnum = atoi(arg)) < 1 )
                vnum = 1;
            pReset = make_reset('G', 1, pObj->ivnum, vnum, 0);
            INSERT(pReset, reset, pArea->last_reset, prev, next);

            SET_AREA_FLAG(pArea, AFLAG_MODIFIED);

            send_to_char( "Object reset to mobile created.\n\r", ch );
            return;
        }
        if ( !str_prefix( arg, "equip" ) )
        {
            argument = one_argument(argument, arg);
            if ( !(reset = find_mreset(ch, pArea, aRoom, arg)) )
                return;
            while ( reset->next && reset->next->command == 'B' )
                reset = reset->next;
            num = get_wearloc(argument);
            if ( num < 0 )
            {
                send_to_char( "Reset object to which location?\n\r", ch );
                return;
            }
            for ( pReset = reset->next; pReset; pReset = pReset->next )
            {
                if ( pReset->command == 'M' )
                    break;
                if ( pReset->command == 'E' && pReset->arg3 == num )
                {
                    send_to_char( "Mobile already has an item equipped there.\n\r", ch);
                    return;
                }
            }
            argument = one_argument(argument, arg);
            if ( (vnum = atoi(arg)) < 1 )
                vnum = 1;
            pReset = make_reset('E', 1, pObj->ivnum, vnum, num);

            SET_AREA_FLAG(pArea, AFLAG_MODIFIED);

            INSERT(pReset, reset, pArea->last_reset, prev, next);
            send_to_char( "Object reset equipped by mobile created.\n\r", ch );
            return;
        }
        if ( arg[0] == '\0' || !(num = (int)str_cmp(arg, "room")) ||
             is_number(arg) )
        {
            if ( !(bool)num )
                argument = one_argument(argument, arg);
            if ( !(pRoom = find_room(ch, argument, aRoom)) )
                return;
            if ( pRoom->area != pArea )
            {
                send_to_char( "Cannot reset objects to other areas.\n\r", ch );
                return;
            }
            if ( (vnum = atoi(arg)) < 1 )
                vnum = 1;
            pReset = make_reset('O', 0, pObj->ivnum, vnum, pRoom->vnum);

            SET_AREA_FLAG(pArea, AFLAG_MODIFIED);

            LINK(pReset, pArea->first_reset, pArea->last_reset, next, prev);
            send_to_char( "Object reset added.\n\r", ch );
            return;
        }
        send_to_char( "Reset object to where?\n\r", ch );
        return;
    }
    if ( !str_cmp(arg, "random") )
    {
        argument = one_argument(argument, arg);
        vnum = get_dir( arg );
        if ( vnum < 0 || vnum > 9 )
        {
            send_to_char( "Reset which random doors?\n\r", ch );
            return;
        }
        if ( vnum == 0 )
        {
            send_to_char( "There is no point in randomizing one door.\n\r", ch );
            return;
        }
        pRoom = find_room(ch, argument, aRoom);
        if ( pRoom->area != pArea )
        {
            send_to_char( "Cannot randomize doors in other areas.\n\r", ch );
            return;
        }
        pReset = make_reset('R', 0, pRoom->vnum, vnum, 0);
        LINK(pReset, pArea->first_reset, pArea->last_reset, next, prev);

        SET_AREA_FLAG(pArea, AFLAG_MODIFIED);

        send_to_char( "Reset random doors created.\n\r", ch );
        return;
    }
    if ( !str_cmp(arg, "trap") )
    {
        char oname[MAX_INPUT_LENGTH];
        int chrg, value, extra = 0;
        bool isobj;
        
        argument = one_argument(argument, oname);
        argument = one_argument(argument, arg);
        num = is_number(arg) ? atoi(arg) : -1;
        argument = one_argument(argument, arg);
        chrg = is_number(arg) ? atoi(arg) : -1;
        isobj = is_name(argument, "obj");
        if ( isobj == is_name(argument, "room") )
        {
            send_to_char( "Reset: TRAP: Must specify ROOM or OBJECT\n\r", ch );
            return;
        }
        if ( !str_cmp(oname, "room") && !isobj )
        {
            vnum = (aRoom ? aRoom->vnum : ch->in_room->vnum);
            extra = TRAP_ROOM;
        }
        else
        {
            if ( is_number(oname) && !isobj )
            {
                vnum = atoi(oname);
                if ( !room_exists_index(vnum) )
                {
                    send_to_char( "Reset: TRAP: no such room\n\r", ch );
                    return;
                }
                reset = NULL;
                extra = TRAP_ROOM;
            }
            else
            {
                if ( !(reset = find_oreset(ch, pArea, aRoom, oname)) )
                    return;
                /*        vnum = reset->arg1;*/
                vnum = 0;
                extra = TRAP_OBJ;
            }
        }
        if ( num < 1 || num > MAX_TRAPTYPE )
        {
            send_to_char( "Reset: TRAP: invalid trap type\n\r", ch );
            return;
        }
        if ( chrg < 0 || chrg > 10000 )
        {
            send_to_char( "Reset: TRAP: invalid trap charges\n\r", ch );
            return;
        }
        while ( *argument )
        {
            argument = one_argument(argument, arg);
            value = get_trapflag(arg);
            if ( value < 0 || value > 31 )
            {
                send_to_char( "Reset: TRAP: bad flag\n\r", ch );
                return;
            }
            SET_BIT(extra, 1 << value);
        }
        pReset = make_reset('T', extra, num, chrg, vnum);
        if ( reset )
            INSERT(pReset, reset, pArea->last_reset, prev, next);
        else
            LINK(pReset, pArea->first_reset, pArea->last_reset, next, prev);

        SET_AREA_FLAG(pArea, AFLAG_MODIFIED);

        send_to_char( "Trap created.\n\r", ch );
        return;
    }
    if ( !str_cmp(arg, "bit") )
    {
        int (*flfunc)(char *type);
        int flags = 0;
        char option[MAX_INPUT_LENGTH];
        char *parg;
        
        argument = one_argument(argument, option);
        if ( !*option )
        {
            send_to_char( "You must specify SET, REMOVE, or TOGGLE.\n\r", ch );
            return;
        }
        num = 0;
        if ( !str_prefix(option, "set") )
            SET_BIT(num, BIT_RESET_SET);
        else if ( !str_prefix(option, "toggle") )
            SET_BIT(num, BIT_RESET_TOGGLE);
        else if ( str_prefix(option, "remove") )
        {
            send_to_char( "You must specify SET, REMOVE, or TOGGLE.\n\r", ch );
            return;
        }
        argument = one_argument(argument, option);
        parg = argument;
        argument = one_argument(argument, arg);
        if ( !*option )
        {
            send_to_char( "Must specify OBJECT, MOBILE, ROOM, or DOOR.\n\r", ch );
            return;
        }
        if ( !str_prefix(option, "door") )
        {
            SET_BIT(num, BIT_RESET_DOOR);
            if ( aRoom )
            {
                pRoom = aRoom;
                argument = parg;
            }
            else if ( !is_number(arg) )
            {
                pRoom = ch->in_room;
                argument = parg;
            }
            else if ( !(pRoom = find_room(ch, arg, aRoom)) )
                return;
            argument = one_argument(argument, arg);
            if ( !*arg )
            {
                send_to_char( "Must specify direction.\n\r", ch );
                return;
            }
            vnum = get_dir(arg);
            SET_BIT(num, vnum << BIT_RESET_DOOR_THRESHOLD);
            vnum = pRoom->vnum;
            flfunc = &get_exflag;
            reset = NULL;
        }
        else if ( !str_prefix(option, "object") )
        {
            SET_BIT(num, BIT_RESET_OBJECT);
            vnum = 0;
            flfunc = &get_oflag;
            if ( !(reset = find_oreset(ch, pArea, aRoom, arg)) )
                return;
        }
        else if ( !str_prefix(option, "mobile") )
        {
            SET_BIT(num, BIT_RESET_MOBILE);
            vnum = 0;
            flfunc = &get_aflag;
            if ( !(reset = find_mreset(ch, pArea, aRoom, arg)) )
                return;
        }
        else if ( !str_prefix(option, "room") )
        {
            SET_BIT(num, BIT_RESET_ROOM);
            if ( aRoom )
            {
                pRoom = aRoom;
                argument = parg;
            }
            else if ( !is_number(arg) )
            {
                pRoom = ch->in_room;
                argument = parg;
            }
            else if ( !(pRoom = find_room(ch, arg, aRoom)) )
                return;
            vnum = pRoom->vnum;
            flfunc = &get_rflag;
            reset = NULL;
        }
        else
        {
            send_to_char( "Must specify OBJECT, MOBILE, ROOM, or DOOR.\n\r", ch );
            return;
        }
        while ( *argument )
        {
            int value;
            argument = one_argument(argument, arg);
            value = (*flfunc)(arg);
            if ( value < 0 || value > 31 )
            {
                send_to_char( "Reset: BIT: bad flag\n\r", ch );
                return;
            }
            SET_BIT(flags, 1 << value);
        }
        if ( !flags )
        {
            send_to_char( "Set which flags?\n\r", ch );
            return;
        }
        pReset = make_reset('B', 1, vnum, num, flags);
        if ( reset )
            INSERT(pReset, reset, pArea->last_reset, prev, next);
        else
            LINK(pReset, pArea->first_reset, pArea->last_reset, next, prev);

        SET_AREA_FLAG(pArea, AFLAG_MODIFIED);

        send_to_char( "Bitvector reset created.\n\r", ch );
        return;
    }
    if ( !str_cmp(arg, "hide") )
    {
        argument = one_argument(argument, arg);
        if ( !(reset = find_oreset(ch, pArea, aRoom, arg)) )
            return;
        /*    pReset = make_reset('H', 1, reset->arg1, 0, 0);*/
        pReset = make_reset('H', 1, 0, 0, 0);
        INSERT(pReset, reset, pArea->last_reset, prev, next);
        send_to_char( "Object hide reset created.\n\r", ch );

        SET_AREA_FLAG(pArea, AFLAG_MODIFIED);

        return;
    }
    if ( ch->substate == SUB_REPEATCMD )
    {
        ch->substate = SUB_NONE;
        interpret(ch, origarg);
        ch->substate = SUB_REPEATCMD;
        ch->last_cmd = (aRoom ? do_rreset : do_reset);
    }
    else
        edit_reset(ch, "", pArea, aRoom);
    return;
}

void do_reset( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea = NULL;
    char arg[MAX_INPUT_LENGTH];
    char *parg;
    
    parg = one_argument(argument, arg);
    if ( ch->substate == SUB_REPEATCMD )
    {
        pArea = (AREA_DATA *)ch->dest_buf;
        if ( pArea && pArea != ch->pcdata->area && pArea != ch->in_room->area )
        {
            AREA_DATA *tmp;
            
            for ( tmp = first_build; tmp; tmp = tmp->next )
                if ( tmp == pArea )
                    break;
            if ( !tmp )
                for ( tmp = first_area; tmp; tmp = tmp->next )
                    if ( tmp == pArea )
                        break;
            if ( !tmp )
            {
                send_to_char("Your area pointer got lost.  Reset mode off.\n\r", ch);
                bug("do_reset: %s's dest_buf points to invalid area",
                    ch->name);
                ch->substate = SUB_NONE;
                ch->dest_buf = NULL;
                return;
            }
        }
        if ( !*arg )
        {
            ch_printf(ch, "Editing resets for area: %s\n\r", pArea->name);
            return;
        }
        if ( !str_cmp(arg, "done") || !str_cmp(arg, "off") )
        {
            send_to_char( "Reset mode off.\n\r", ch );
            ch->substate = SUB_NONE;
            ch->dest_buf = NULL;
            return;
        }
    }
    if ( !pArea && get_trust(ch) > LEVEL_GOD )
    {
        char fname[80];
        
        sprintf(fname, "%s.are", capitalize(arg));
        for ( pArea = first_build; pArea; pArea = pArea->next )
            if ( !str_cmp(fname, pArea->name) )
            {
                argument = parg;
                break;
            }
        if ( !pArea )
            pArea = ch->pcdata->area;
        if ( !pArea )
            pArea = ch->in_room->area;
    }
    else
        pArea = ch->pcdata->area;
    if ( !pArea )
    {
        send_to_char( "You do not have an assigned area.\n\r", ch );
        return;
    }
    edit_reset(ch, argument, pArea, NULL);
    return;
}

void do_rreset( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA *pRoom;
    
    if ( ch->substate == SUB_REPEATCMD )
    {
        pRoom = (ROOM_INDEX_DATA *)ch->dest_buf;
        if ( !pRoom )
        {
            send_to_char( "Your room pointer got lost.  Reset mode off.\n\r", ch);
            bug("do_rreset: %s's dest_buf points to invalid room", ch->name);
        }
        ch->substate = SUB_NONE;
        ch->dest_buf = NULL;
        return;
    }
    else
        pRoom = ch->in_room;
    if ( !can_rmodify(ch, pRoom) )
        return;
    edit_reset(ch, argument, pRoom->area, pRoom);
    return;
}

void add_obj_reset( AREA_DATA *pArea, char cm, OBJ_DATA *obj, int v2, int v3 )
{
    OBJ_DATA *inobj;
    static int iNest;
    
    if ( (cm == 'O' || cm == 'P') && obj->vnum == OBJ_VNUM_TRAP )
    {
        if ( cm == 'O' )
            add_reset(pArea, 'T', obj->value[3], obj->value[1], obj->value[0], v3);
        return;
    }
    add_reset( pArea, cm, (cm == 'P' ? iNest : 1), obj->vnum,
               v2, v3 );
    /* Only add hide for in-room objects that are hidden and cant be moved, as
     hide is an update reset, not a load-only reset. */
    if ( cm == 'O' && IS_OBJ_STAT(obj, ITEM_HIDDEN) &&
         !IS_SET(obj->wear_flags, ITEM_TAKE) )
        add_reset(pArea, 'H', 1, 0, 0, 0);
    for ( inobj = obj->first_content; inobj; inobj = inobj->next_content )
        if ( inobj->vnum == OBJ_VNUM_TRAP )
            add_obj_reset(pArea, 'O', inobj, 0, 0);
    if ( cm == 'P' )
        iNest++;
    for ( inobj = obj->first_content; inobj; inobj = inobj->next_content )
        add_obj_reset( pArea, 'P', inobj, 1, obj->vnum );
    if ( cm == 'P' )
        iNest--;
    return;
}

void instaroom( AREA_DATA *pArea, ROOM_INDEX_DATA *pRoom, bool dodoors )
{
    CHAR_DATA *rch;
    OBJ_DATA *obj;
    
    for ( rch = pRoom->first_person; rch; rch = rch->next_in_room )
    {
        if ( !IS_NPC(rch) )
            continue;
        add_reset( pArea, 'M', 1, rch->vnum, rch->pIndexData->count,
                   pRoom->vnum );
        for ( obj = rch->first_carrying; obj; obj = obj->next_content )
        {
            if ( obj->wear_loc == WEAR_NONE )
                add_obj_reset( pArea, 'G', obj, 1, 0 );
            else
                add_obj_reset( pArea, 'E', obj, 1, obj->wear_loc );
        }
    }
    for ( obj = pRoom->first_content; obj; obj = obj->next_content )
    {
        add_obj_reset( pArea, 'O', obj, 1, pRoom->vnum );
    }
    if ( dodoors )
    {
        EXIT_DATA *pexit;
        
        for ( pexit = pRoom->first_exit; pexit; pexit = pexit->next )
        {
            int state = 0;
            
            if ( !IS_SET( pexit->exit_info, EX_ISDOOR ) )
                continue;
            if ( IS_SET( pexit->exit_info, EX_CLOSED ) )
            {
                if ( IS_SET( pexit->exit_info, EX_LOCKED ) )
                    state = 2;
                else
                    state = 1;
            }
            add_reset( pArea, 'D', 0, pRoom->vnum, pexit->vdir, state );
        }
    }
    return;
}

void wipe_resets( AREA_DATA *pArea, ROOM_INDEX_DATA *pRoom )
{
    RESET_DATA *pReset;
    
    for ( pReset = pArea->first_reset; pReset; )
    {
        if ( pReset->command != 'R' && is_room_reset( pReset, pRoom, pArea ) )
        {
            /* Resets always go forward, so we can safely use the previous reset,
             providing it exists, or first_reset if it doesnt.  -- Altrag */
            RESET_DATA *prev = pReset->prev;
            
            delete_reset(pArea, pReset);
            pReset = (prev ? prev->next : pArea->first_reset);
        }
        else
            pReset = pReset->next;
    }
    return;
}

void do_instaroom( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    ROOM_INDEX_DATA *pRoom;
    bool dodoors;
    char arg[MAX_INPUT_LENGTH];
    
    if ( IS_NPC(ch) || get_trust(ch) < LEVEL_SAVIOR || !ch->pcdata ||
         !ch->pcdata->area )
    {
        send_to_char( "You don't have an assigned area to create resets for.\n\r",
                      ch );
        return;
    }
    argument = one_argument(argument, arg);
    if ( !str_cmp(argument, "nodoors") )
        dodoors = FALSE;
    else
        dodoors = TRUE;
    pArea = ch->pcdata->area;
    if ( !(pRoom = find_room(ch, arg, NULL)) )
    {
        send_to_char( "Room doesn't exist.\n\r", ch );
        return;
    }
    if ( !can_rmodify(ch, pRoom) )
        return;
    if ( pRoom->area != pArea && get_trust(ch) < LEVEL_GREATER )
    {
        send_to_char( "You cannot reset that room.\n\r", ch );
        return;
    }
    if ( pArea->first_reset )
        wipe_resets(pArea, pRoom);
    instaroom(pArea, pRoom, dodoors);
    send_to_char( "Room resets installed.\n\r", ch );
}

void do_instazone( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    int vnum;
    ROOM_INDEX_DATA *pRoom;
    bool dodoors;
    
    if ( IS_NPC(ch) || get_trust(ch) < LEVEL_SAVIOR || !ch->pcdata ||
         !ch->pcdata->area )
    {
        send_to_char( "You don't have an assigned area to create resets for.\n\r",
                      ch );
        return;
    }
    if ( !str_cmp(argument, "nodoors") )
        dodoors = FALSE;
    else
        dodoors = TRUE;
    pArea = ch->pcdata->area;
    if ( pArea->first_reset )
        wipe_resets(pArea, NULL);
    for ( vnum = pArea->low_r_vnum; vnum <= pArea->hi_r_vnum; vnum++ )
    {
        if ( !(pRoom = get_room_index(vnum)) || pRoom->area != pArea )
            continue;
        instaroom( pArea, pRoom, dodoors );
    }
    send_to_char( "Area resets installed.\n\r", ch );
    return;
}

/*
 int generate_itemlevel( AREA_DATA *pArea, OBJ_INDEX_DATA *pObjIndex )
 {
 int olevel;
 int min = UMAX(pArea->low_soft_range, 1);
 int max = UMIN(pArea->hi_soft_range, min + 15);
 
 if ( pObjIndex->rent < MIN_OBJ_RENT )
 return 0;
 
 if ( pObjIndex->level > 0 )
 olevel = UMIN(pObjIndex->level, MAX_LEVEL);
 else
 switch ( pObjIndex->item_type )
 {
 default:		olevel = 0;				break;
 case ITEM_PILL:	olevel = number_range(  min, max );	break;
 case ITEM_POTION:	olevel = number_range(  min, max );	break;
 case ITEM_SCROLL:	olevel = pObjIndex->value[0];		break;
 case ITEM_WAND:	olevel = number_range( min+4, max+1 );	break;
 case ITEM_STAFF:	olevel = number_range( min+9, max+5 );	break;
 case ITEM_ARMOR:	olevel = number_range( min+4, max+1 );	break;
 case ITEM_WEAPON:	olevel = number_range( min+4, max+1 );	break;
 }
 return olevel;
 }
 */

/*
 * Reset one area.
 */
void reset_area( AREA_DATA *pArea )
{
    RESET_DATA *pReset;
    CHAR_DATA *mob;
    OBJ_DATA *obj;
    OBJ_DATA *lastobj;
    ROOM_INDEX_DATA *pRoomIndex;
    MOB_INDEX_DATA *pMobIndex;
    OBJ_INDEX_DATA *pObjIndex;
    OBJ_INDEX_DATA *pObjToIndex;
    EXIT_DATA *pexit;
    OBJ_DATA *to_obj = NULL;
    int level = 0;
    int *plc = NULL;
    
    if ( !pArea )
    {
        bug( "reset_area: NULL pArea" );
        return;
    }

    aprog_reset_trigger(pArea);

    mob = NULL;
    obj = NULL;
    lastobj = NULL;
    if ( !pArea->first_reset )
    {
        /*    bug( "%s: reset_area: no resets", (int)pArea->filename );*/
        return;
    }
    level = 0;
    for ( pReset = pArea->first_reset; pReset; pReset = pReset->next )
    {
        switch( pReset->command )
        {
        default:
            bug( "Reset_area: bad command %c.", pReset->command );
            break;
            
        case 'M':
            if ( !(pMobIndex = get_mob_index(pReset->arg1)) )
            {
                bug( "Reset_area: 'M': bad mob vnum %d.", pReset->arg1 );
                continue;
            }
            if ( !(pRoomIndex = get_room_index(pReset->arg3)) )
            {
                bug( "Reset_area: 'M': bad room vnum %d.", pReset->arg3 );
                continue;
            }
            if ( pMobIndex->count >= pReset->arg2 )
            {
                mob = NULL;
                break;
            }
            mob = create_mobile(pMobIndex->ivnum);
            {
                ROOM_INDEX_DATA *pRoomPrev = get_room_index(pReset->arg3 - 1);
                
                if ( pRoomPrev && IS_SET(pRoomPrev->room_flags, ROOM_PET_SHOP) )
                    SET_BIT(mob->act, ACT_PET);
            }
            if ( room_is_dark(pRoomIndex) )
                SET_BIT(mob->affected_by, AFF_INFRARED);
            char_to_room(mob, pRoomIndex);
            mprog_birth_trigger(NULL, mob);
            economize_mobgold(mob);
            level = URANGE(0, GetMaxLevel(mob) - 2, LEVEL_AVATAR);
            break;
            
        case 'G':
        case 'E':
            if ( !(pObjIndex = get_obj_index(pReset->arg1)) )
            {
                bug( "Reset_area: 'E' or 'G': bad obj vnum %d.", pReset->arg1 );
                continue;
            }
            if ( !mob )
            {
                lastobj = NULL;
                break;
            }
            /*if ( pObjIndex->count > pReset->arg2 )*/
            if ( count_objs_for_reset(pObjIndex) > pReset->arg2 )
            {
                obj = NULL;
                lastobj = NULL;
                log_printf_plus(LOG_DEBUG, LEVEL_IMMORTAL, SEV_TREET, "reset_area: obj count %d/%d exceeds reset %d vnum %d",
                                pObjIndex->count,
                                count_objs_for_reset(pObjIndex),
                                pReset->arg2,
                                pReset->arg1 );
                break;
            }
            obj = create_object(pObjIndex->ivnum);
            obj = obj_to_char(obj, mob);
            if ( pReset->command == 'E' )
                equip_char(mob, obj, pReset->arg3);
            else if ( mob->pIndexData->pShop ) /* don't set inventory on equip */
                SET_BIT(obj->extra_flags, ITEM_INVENTORY);

            if (!obj->carried_by)
                bug( "Reset_area: '%c': obj %d not carried",
                     pReset->command, pReset->arg1);
            lastobj = obj;
            break;
            
        case 'O':
            if ( !(pObjIndex = get_obj_index(pReset->arg1)) )
            {
                bug( "Reset_area: 'O': bad obj vnum %d.", pReset->arg1 );
                continue;
            }
            if ( !(pRoomIndex = get_room_index(pReset->arg3)) )
            {
                bug( "Reset_area: 'O': bad room vnum %d.", pReset->arg3 );
                continue;
            }
            /*if ( pObjIndex->count >= pReset->arg2 )*/
            if ( count_objs_for_reset(pObjIndex) >= pReset->arg2 )
            {
                obj = NULL;
                lastobj = NULL;
                break;
            }
            /*
             if ( pArea->nplayer > 0 ||
             count_obj_list(pObjIndex, pRoomIndex->first_content) > 0 )
             {
             obj = NULL;
             lastobj = NULL;
             break;
             }
             */
            obj = create_object(pObjIndex->ivnum);
            obj = obj_to_room(obj, pRoomIndex);
            if (!obj->in_room)
                bug( "Reset_area: 'O': obj %d not in room %d", pReset->arg1, pReset->arg3);
            lastobj = obj;
            break;
            
        case 'P':
            if ( !(pObjIndex = get_obj_index(pReset->arg1)) )
            {
                bug( "Reset_area: 'P': bad obj vnum %d.", pReset->arg1 );
                continue;
            }
            if ( pReset->arg3 > 0 )
            {
                if ( !(pObjToIndex = get_obj_index(pReset->arg3)) )
                {
                    bug( "Reset_area: 'P': bad objto vnum %d.", pReset->arg3 );
                    continue;
                }
                /*if ( pObjIndex->count >= pReset->arg2 )*/
                if ( count_objs_for_reset(pObjIndex) >= pReset->arg2 )
                {
                    obj = NULL;
                    break;
                }
                if ( !(to_obj = get_obj_type(pObjToIndex)) ||
                     !to_obj->in_room )
                {
                    obj = NULL;
                    break;
                }
                /*
                 if ( pArea->nplayer > 0 ||
                 count_obj_list(pObjIndex, to_obj->first_content) > 0 )
                 {
                 obj = NULL;
                 break;
                 }
                 */
                lastobj = to_obj;
            }
            else
            {
                int iNest;
                
                if ( !lastobj )
                    break;
                to_obj = lastobj;
                for ( iNest = 0; iNest < pReset->extra; iNest++ )
                    if ( !(to_obj = to_obj->last_content) )
                    {
                        bug( "Reset_area: 'P': Invalid nesting obj %d.", pReset->arg1 );
                        iNest = -1;
                        break;
                    }
                if ( iNest < 0 )
                    continue;
            }
            obj = create_object(pObjIndex->ivnum);
            obj = obj_to_obj(obj, to_obj);
            if (!obj->in_obj)
                bug( "Reset_area: 'P': obj %d not in obj %d", pReset->arg1, pReset->arg3);
            break;
            
        case 'T':
            if ( IS_SET(pReset->extra, TRAP_OBJ) )
            {
                /* We need to preserve obj for future 'T' and 'H' checks */
                OBJ_DATA *pobj;
                
                if ( pReset->arg3 > 0 )
                {
                    if ( !(pObjToIndex = get_obj_index(pReset->arg3)) )
                    {
                        bug( "Reset_area: 'T': bad objto vnum %d.", pReset->arg3 );
                        continue;
                    }
                    if ( pArea->nplayer > 0 ||
                         !(to_obj = get_obj_type(pObjToIndex)) ||
                         (to_obj->carried_by && !IS_NPC(to_obj->carried_by)) ||
                         is_trapped(to_obj) )
                        break;
                }
                else
                {
                    if ( !lastobj || !obj )
                        break;
                    to_obj = obj;
                }
                pobj = make_trap( pReset->arg2, pReset->arg1, 10, pReset->extra );
                obj_to_obj(pobj, to_obj);
            }
            else
            {
                if ( !(pRoomIndex = get_room_index(pReset->arg3)) )
                {
                    bug( "Reset_area: 'T': bad room %d.", pReset->arg3 );
                    continue;
                }
                if ( pArea->nplayer > 0 ||
                     count_obj_list(get_obj_index(OBJ_VNUM_TRAP),
                                    pRoomIndex->first_content) > 0 )
                    break;
                to_obj = make_trap(pReset->arg1, pReset->arg1, 10, pReset->extra);
                obj_to_room(to_obj, pRoomIndex);
            }
            break;
            
        case 'H':
            if ( pReset->arg1 > 0 )
            {
                if ( !(pObjToIndex = get_obj_index(pReset->arg1)) )
                {
                    bug( "Reset_area: 'H': bad objto vnum %d.", pReset->arg1 );
                    continue;
                }
                if ( pArea->nplayer > 0 ||
                     !(to_obj = get_obj_type(pObjToIndex)) ||
                     !to_obj->in_room ||
                     to_obj->in_room->area != pArea ||
                     IS_OBJ_STAT(to_obj, ITEM_HIDDEN) )
                    break;
            }
            else
            {
                if ( !lastobj || !obj )
                    break;
                to_obj = obj;
            }
            SET_BIT(to_obj->extra_flags, ITEM_HIDDEN);
            break;
            
        case 'B':
            switch(pReset->arg2 & BIT_RESET_TYPE_MASK)
            {
            case BIT_RESET_DOOR:
                {
                    int doornum;
                    
                    if ( !(pRoomIndex = get_room_index(pReset->arg1)) )
                    {
                        bug( "Reset_area: 'B': door: bad room vnum %d.", pReset->arg1 );
                        continue;
                    }
                    doornum = (pReset->arg2 & BIT_RESET_DOOR_MASK)
                        >> BIT_RESET_DOOR_THRESHOLD;
                    if ( !(pexit = get_exit(pRoomIndex, doornum)) )
                        break;
                    plc = &pexit->exit_info;
                }
                break;
            case BIT_RESET_ROOM:
                if ( !(pRoomIndex = get_room_index(pReset->arg1)) )
                {
                    bug( "Reset_area: 'B': room: bad room vnum %d.", pReset->arg1 );
                    continue;
                }
                plc = &pRoomIndex->room_flags;
                break;
            case BIT_RESET_OBJECT:
                if ( pReset->arg1 > 0 )
                {
                    if ( !(pObjToIndex = get_obj_index(pReset->arg1)) )
                    {
                        bug( "Reset_area: 'B': object: bad objto vnum %d.", pReset->arg1 );
                        continue;
                    }
                    if ( !(to_obj = get_obj_type(pObjToIndex)) ||
                         !to_obj->in_room ||
                         to_obj->in_room->area != pArea )
                        continue;
                }
                else
                {
                    if ( !lastobj || !obj )
                        continue;
                    to_obj = obj;
                }
                plc = &to_obj->extra_flags;
                break;
            case BIT_RESET_MOBILE:
                if ( !mob )
                    continue;
                plc = &mob->affected_by;
                break;
            default:
                bug( "Reset_area: 'B': bad options %d.", pReset->arg2 );
                continue;
            }
            if ( IS_SET(pReset->arg2, BIT_RESET_SET) )
                SET_BIT(*plc, pReset->arg3);
            else if ( IS_SET(pReset->arg2, BIT_RESET_TOGGLE) )
                TOGGLE_BIT(*plc, pReset->arg3);
            else
                REMOVE_BIT(*plc, pReset->arg3);
            break;
            
        case 'D':
            if ( !(pRoomIndex = get_room_index(pReset->arg1)) )
            {
                bug( "Reset_area: 'D': bad room vnum %d.", pReset->arg1 );
                continue;
            }
            if ( !(pexit = get_exit(pRoomIndex, pReset->arg2)) )
                break;
            switch( pReset->arg3 )
            {
            case 0:
                REMOVE_BIT(pexit->exit_info, EX_CLOSED);
                REMOVE_BIT(pexit->exit_info, EX_LOCKED);
                break;
            case 1:
                SET_BIT(   pexit->exit_info, EX_CLOSED);
                REMOVE_BIT(pexit->exit_info, EX_LOCKED);
                if ( IS_SET(pexit->exit_info, EX_xSEARCHABLE) )
                    SET_BIT( pexit->exit_info, EX_SECRET);
                break;
            case 2:
                SET_BIT(   pexit->exit_info, EX_CLOSED);
                SET_BIT(   pexit->exit_info, EX_LOCKED);
                if ( IS_SET(pexit->exit_info, EX_xSEARCHABLE) )
                    SET_BIT( pexit->exit_info, EX_SECRET);
                break;
            }
            break;
            
        case 'R':
            if ( !(pRoomIndex = get_room_index(pReset->arg1)) )
            {
                bug( "Reset_area: 'R': bad room vnum %d.", pReset->arg1 );
                continue;
            }
            randomize_exits(pRoomIndex, pReset->arg2-1);
            break;
        }
    }
    return;
}

void list_resets( CHAR_DATA *ch, AREA_DATA *pArea, ROOM_INDEX_DATA *pRoom,
                  int start, int end )
{
    RESET_DATA *pReset;
    ROOM_INDEX_DATA *room;
    MOB_INDEX_DATA *mob;
    OBJ_INDEX_DATA *obj, *obj2;
    OBJ_INDEX_DATA *lastobj;
    RESET_DATA *lo_reset;
    bool found;
    int num = 0;
    const char *rname = "???", *mname = "???", *oname = "???";
    char buf[256];
    char *pbuf;
    
    if ( !ch || !pArea )
        return;
    room = NULL;
    mob = NULL;
    obj = NULL;
    lastobj = NULL;
    lo_reset = NULL;
    found = FALSE;
    
    for ( pReset = pArea->first_reset; pReset; pReset = pReset->next )
    {
        if ( !is_room_reset(pReset, pRoom, pArea) )
            continue;
        ++num;
        sprintf(buf, "%2d) ", num);
        pbuf = buf+strlen(buf);
        switch( pReset->command )
        {
        default:
            sprintf(pbuf, "*** BAD RESET: %c %d %d %d %d ***\n\r",
                    pReset->command, pReset->extra, pReset->arg1, pReset->arg2,
                    pReset->arg3);
            break;
        case 'M':
            if ( !(mob = get_mob_index(pReset->arg1)) )
                mname = "Mobile: *BAD VNUM*";
            else
                mname = mob->player_name;
            if ( !(room = get_room_index(pReset->arg3)) )
                rname = "Room: *BAD VNUM*";
            else
                rname = room->name;
            sprintf( pbuf, "%s (%d) -> %s (%d) [%d]", mname, pReset->arg1, rname,
                     pReset->arg3, pReset->arg2 );
            if ( !room )
                mob = NULL;
            if ( (room = get_room_index(pReset->arg3-1)) &&
                 IS_SET(room->room_flags, ROOM_PET_SHOP) )
                strcat( buf, " (pet)\n\r" );
            else
                strcat( buf, "\n\r" );
            break;
        case 'G':
        case 'E':
            if ( !mob )
                mname = "* ERROR: NO MOBILE! *";
            if ( !(obj = get_obj_index(pReset->arg1)) )
                oname = "Object: *BAD VNUM*";
            else
                oname = obj->name;
            sprintf( pbuf, "%s (%d) -> %s (%s) [%d]", oname, pReset->arg1, mname,
                     (pReset->command == 'G' ? "carry" : wear_locs[pReset->arg3]),
                     pReset->arg2 );
            if ( mob && mob->pShop )
                strcat( buf, " (shop)\n\r" );
            else
                strcat( buf, "\n\r" );
            lastobj = obj;
            lo_reset = pReset;
            break;
        case 'O':
            if ( !(obj = get_obj_index(pReset->arg1)) )
                oname = "Object: *BAD VNUM*";
            else
                oname = obj->name;
            if ( !(room = get_room_index(pReset->arg3)) )
                rname = "Room: *BAD VNUM*";
            else
                rname = room->name;
            sprintf( pbuf, "(object) %s (%d) -> %s (%d) [%d]\n\r", oname,
                     pReset->arg1, rname, pReset->arg3, pReset->arg2 );
            if ( !room )
                obj = NULL;
            lastobj = obj;
            lo_reset = pReset;
            break;
        case 'P':
            if ( !(obj = get_obj_index(pReset->arg1)) )
                oname = "Object1: *BAD VNUM*";
            else
                oname = obj->name;
            obj2 = NULL;
            if ( pReset->arg3 > 0 )
            {
                obj2 = get_obj_index(pReset->arg3);
                rname = (obj2 ? obj2->name : "Object2: *BAD VNUM*");
                lastobj = obj2;
            }
            else if ( !lastobj )
                rname = "Object2: *NULL obj*";
            else if ( pReset->extra == 0 )
            {
                rname = lastobj->name;
                obj2 = lastobj;
            }
            else
            {
                int iNest;
                RESET_DATA *reset;
                
                reset = lo_reset->next;
                for ( iNest = 0; iNest < pReset->extra; iNest++ )
                {
                    for ( ; reset; reset = reset->next )
                        if ( reset->command == 'O' || reset->command == 'G' ||
                             reset->command == 'E' || (reset->command == 'P' &&
                                                       !reset->arg3 && reset->extra == iNest) )
                            break;
                    if ( !reset || reset->command != 'P' )
                        break;
                }
                if ( !reset )
                    rname = "Object2: *BAD NESTING*";
                else if ( !(obj2 = get_obj_index(reset->arg1)) )
                    rname = "Object2: *NESTED BAD VNUM*";
                else
                    rname = obj2->name;
            }
            sprintf( pbuf, "(Put) %s (%d) -> %s (%d) [%d] {nest %d}\n\r", oname,
                     pReset->arg1, rname, (obj2 ? obj2->ivnum : pReset->arg3),
                     pReset->arg2, pReset->extra );
            break;
        case 'T':
            sprintf(pbuf, "TRAP: %d %d %d %d (%s)\n\r", pReset->extra, pReset->arg1,
                    pReset->arg2, pReset->arg3, flag_string(pReset->extra, trap_flags));
            break;
        case 'H':
            if ( pReset->arg1 > 0 )
            {
                if ( !(obj2 = get_obj_index(pReset->arg1)) )
                    rname = "Object: *BAD VNUM*";
                else
                    rname = obj2->name;
            }
            else if ( !obj )
                rname = "Object: *NULL obj*";
            else
                rname = oname;
            sprintf(pbuf, "Hide %s (%d)\n\r", rname,
                    (pReset->arg1 > 0 ? pReset->arg1 : obj ? obj->ivnum : 0));
            break;
        case 'B':
            {
                char * const *flagarray;
                
                strcpy(pbuf, "BIT: ");
                pbuf += 5;
                if ( IS_SET(pReset->arg2, BIT_RESET_SET) )
                {
                    strcpy(pbuf, "Set: ");
                    pbuf += 5;
                }
                else if ( IS_SET(pReset->arg2, BIT_RESET_TOGGLE) )
                {
                    strcpy(pbuf, "Toggle: ");
                    pbuf += 8;
                }
                else
                {
                    strcpy(pbuf, "Remove: ");
                    pbuf += 8;
                }
                switch(pReset->arg2 & BIT_RESET_TYPE_MASK)
                {
                case BIT_RESET_DOOR:
                    {
                        int door;
                        
                        if ( !(room = get_room_index(pReset->arg1)) )
                            rname = "Room: *BAD VNUM*";
                        else
                            rname = room->name;
                        door = (pReset->arg2 & BIT_RESET_DOOR_MASK)
                            >> BIT_RESET_DOOR_THRESHOLD;
                        door = URANGE(0, door, MAX_REXITS-1);
                        sprintf(pbuf, "Exit %s%s (%d), Room %s (%d)", dir_name(door),
                                (room && get_exit(room, door) ? "" : " (NO EXIT!)"), door,
                                rname, pReset->arg1);
                    }
                    flagarray = ex_flags;
                    break;
                case BIT_RESET_ROOM:
                    if ( !(room = get_room_index(pReset->arg1)) )
                        rname = "Room: *BAD VNUM*";
                    else
                        rname = room->name;
                    sprintf(pbuf, "Room %s (%d)", rname, pReset->arg1);
                    flagarray = r_flags;
                    break;
                case BIT_RESET_OBJECT:
                    if ( pReset->arg1 > 0 )
                    {
                        if ( !(obj2 = get_obj_index(pReset->arg1)) )
                            rname = "Object: *BAD VNUM*";
                        else
                            rname = obj2->name;
                    }
                    else if ( !obj )
                        rname = "Object: *NULL obj*";
                    else
                        rname = oname;
                    sprintf(pbuf, "Object %s (%d)", rname,
                            (pReset->arg1 > 0 ? pReset->arg1 : obj ? obj->ivnum : 0));
                    flagarray = o_flags;
                    break;
                case BIT_RESET_MOBILE:
                    if ( pReset->arg1 > 0 )
                    {
                        MOB_INDEX_DATA *mob2;
                        
                        if ( !(mob2 = get_mob_index(pReset->arg1)) )
                            rname = "Mobile: *BAD VNUM*";
                        else
                            rname = mob2->player_name;
                    }
                    else if ( !mob )
                        rname = "Mobile: *NULL mob*";
                    else
                        rname = mname;
                    sprintf(pbuf, "Mobile %s (%d)", rname,
                            (pReset->arg1 > 0 ? pReset->arg1 : mob ? mob->ivnum : 0));
                    flagarray = a_flags;
                    break;
                default:
                    sprintf(pbuf, "bad type %d", pReset->arg2 & BIT_RESET_TYPE_MASK);
                    flagarray = NULL;
                    break;
                }
                pbuf += strlen(pbuf);
                if ( flagarray )
                    sprintf(pbuf, "; flags: %s [%d]\n\r",
                            flag_string(pReset->arg3, flagarray), pReset->arg3);
                else
                    sprintf(pbuf, "; flags %d\n\r", pReset->arg3);
            }
            break;
        case 'D':
            {
                char *ef_name;
                
                pReset->arg2 = URANGE(0, pReset->arg2, MAX_REXITS-1);
                if ( !(room = get_room_index(pReset->arg1)) )
                    rname = "Room: *BAD VNUM*";
                else
                    rname = room->name;
                switch(pReset->arg3)
                {
                default:	ef_name = "(* ERROR *)";	break;
                case 0:	ef_name = "Open";		break;
                case 1:	ef_name = "Close";		break;
                case 2:	ef_name = "Close and lock";	break;
                }
                sprintf(pbuf, "%s [%d] the %s%s [%d] door %s (%d)\n\r", ef_name,
                        pReset->arg3, dir_name(pReset->arg2),
                        (room && get_exit(room, pReset->arg2) ? "" : " (NO EXIT!)"),
                        pReset->arg2, rname, pReset->arg1);
            }
            break;
        case 'R':
            if ( !(room = get_room_index(pReset->arg1)) )
                rname = "Room: *BAD VNUM*";
            else
                rname = room->name;
            sprintf(pbuf, "Randomize exits 0 to %d -> %s (%d)\n\r", pReset->arg2,
                    rname, pReset->arg1);
            break;
        }
        if ( start == -1 || num >= start )
            send_to_pager( buf, ch );
        if ( end != -1 && num >= end )
            break;
    }
    if ( num == 0 )
        send_to_char( "You don't have any resets defined.\n\r", ch );
    return;
}

/* Setup put nesting levels, regardless of whether or not the resets will
 actually reset, or if they're bugged. */
void renumber_put_resets( AREA_DATA *pArea )
{
    RESET_DATA *pReset, *lastobj = NULL;
    
    for ( pReset = pArea->first_reset; pReset; pReset = pReset->next )
    {
        switch(pReset->command)
        {
        default:
            break;
        case 'G': case 'E': case 'O':
            lastobj = pReset;
            break;
        case 'P':
            if ( pReset->arg3 == 0 )
            {
                if ( !lastobj )
                    pReset->extra = 1000000;
                else if ( lastobj->command != 'P' || lastobj->arg3 > 0 )
                    pReset->extra = 0;
                else
                    pReset->extra = lastobj->extra+1;
                lastobj = pReset;
            }
        }
    }
    return;
}

/*
 * Create a new reset (for online building)			-Thoric
 */
RESET_DATA *make_reset( char letter, int extra, int arg1, int arg2, int arg3 )
{
    RESET_DATA *pReset;
    
    CREATE( pReset, RESET_DATA, 1 );
    pReset->command	= letter;
    pReset->extra	= extra;
    pReset->arg1	= arg1;
    pReset->arg2	= arg2;
    pReset->arg3	= arg3;
    top_reset++;	
    return pReset;
}

/*
 * Add a reset to an area				-Thoric
 */
RESET_DATA *add_reset( AREA_DATA *tarea, char letter, int extra, int arg1, int arg2, int arg3 )
{
    RESET_DATA *pReset;
    
    if ( !tarea )
    {
        bug( "add_reset: NULL area!" );
        return NULL;
    }
    
    letter = UPPER(letter);
    pReset = make_reset( letter, extra, arg1, arg2, arg3 );
    switch( letter )
    {
    case 'M':  tarea->last_mob_reset = pReset;	break;
    case 'H':  if ( arg1 > 0 )			break;
    case 'E':  case 'G':  case 'P':
    case 'O':  tarea->last_obj_reset = pReset;	break;
    case 'T':
        if ( IS_SET( extra, TRAP_OBJ ) && arg1 == 0)
            tarea->last_obj_reset = pReset;
        break;
    }
    
    LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
    return pReset;
}

/*
 * Place a reset into an area, insert sorting it		-Thoric
 */
RESET_DATA *place_reset( AREA_DATA *tarea, char letter, int extra, int arg1, int arg2, int arg3 )
{
    RESET_DATA *pReset, *tmp, *tmp2;
    
    if ( !tarea )
    {
        bug( "place_reset: NULL area!" );
        return NULL;
    }
    
    letter = UPPER(letter);
    pReset = make_reset( letter, extra, arg1, arg2, arg3 );
    if ( letter == 'M' )
        tarea->last_mob_reset = pReset;
    
    if ( tarea->first_reset )
    {
        switch( letter )
        {
        default:
            bug( "place_reset: Bad reset type %c", letter );
            return NULL;
        case 'D':	case 'R':
            for ( tmp = tarea->last_reset; tmp; tmp = tmp->prev )
                if ( tmp->command == letter )
                    break;
            if ( tmp )	/* organize by location */
                for ( ; tmp && tmp->command == letter && tmp->arg1 > arg1; tmp = tmp->prev );
            if ( tmp )	/* organize by direction */
                for ( ; tmp && tmp->command == letter && tmp->arg1 == tmp->arg1 && tmp->arg2 > arg2; tmp = tmp->prev );
            if ( tmp )
                INSERT( pReset, tmp, tarea->first_reset, next, prev );
            else
                LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
            return pReset;
        case 'M':	case 'O':
            /* find last reset of same type */
            for ( tmp = tarea->last_reset; tmp; tmp = tmp->prev )
                if ( tmp->command == letter )
                    break;
            tmp2 = tmp ? tmp->next : NULL;
            /* organize by location */
            for ( ; tmp; tmp = tmp->prev )
                if ( tmp->command == letter && tmp->arg3 <= arg3 )
                {
                    tmp2 = tmp->next;
                    /* organize by vnum */
                    if ( tmp->arg3 == arg3 )
                        for ( ; tmp; tmp = tmp->prev )
                            if ( tmp->command == letter
                                 &&   tmp->arg3 == tmp->arg3
                                 &&   tmp->arg1 <= arg1 )
                            {
                                tmp2 = tmp->next;
                                break;
                            }
                    break;
                }
            /* skip over E or G for that mob */
            if ( tmp2 && letter == 'M' )
            {
                for ( ; tmp2; tmp2 = tmp2->next )
                    if ( tmp2->command != 'E' && tmp2->command != 'G' )
                        break;
            }
            else
                /* skip over P, T or H for that obj */
                if ( tmp2 && letter == 'O' )
                {
                    for ( ; tmp2; tmp2 = tmp2->next )
                        if ( tmp2->command != 'P' && tmp2->command != 'T'
                             &&   tmp2->command != 'H' )
                            break;
                }
            if ( tmp2 )
                INSERT( pReset, tmp2, tarea->first_reset, next, prev );
            else
                LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
            return pReset;
        case 'G':	case 'E':
            /* find the last mob */
            if ( (tmp=tarea->last_mob_reset) != NULL )
            {
                /*
                 * See if there are any resets for this mob yet,
                 * put E before G and organize by vnum
                 */
                if ( tmp->next )
                {
                    tmp = tmp->next;
                    if ( tmp && tmp->command == 'E' )
                    {
                        if ( letter == 'E' )
                            for ( ; tmp && tmp->command == 'E' && tmp->arg1 < arg1; tmp = tmp->next );
                        else
                            for ( ; tmp && tmp->command == 'E'; tmp = tmp->next );
                    }
                    else
                        if ( tmp && tmp->command == 'G' && letter == 'G' )
                            for ( ; tmp && tmp->command == 'G' && tmp->arg1 < arg1; tmp = tmp->next );
                    if ( tmp )
                        INSERT( pReset, tmp, tarea->first_reset, next, prev );
                    else
                        LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
                }
                else
                    LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
                return pReset;
            }
            break;
        case 'P':	case 'T':   case 'H':
            /* find the object in question */
            if ( ((letter == 'P' && arg3 == 0)
                  ||    (letter == 'T' && IS_SET(extra, TRAP_OBJ) && arg1 == 0)
                  ||    (letter == 'H' && arg1 == 0))
                 &&    (tmp=tarea->last_obj_reset) != NULL )
            {
                if ( (tmp=tmp->next) != NULL )
                    INSERT( pReset, tmp, tarea->first_reset, next, prev );
                else
                    LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
                return pReset;
            }
            
            for ( tmp = tarea->last_reset; tmp; tmp = tmp->prev )
                if ( (tmp->command == 'O' || tmp->command == 'G'
                      ||    tmp->command == 'E' || tmp->command == 'P')
                     &&    tmp->arg1 == arg3 )
                {
                    /*
                     * See if there are any resets for this object yet,
                     * put P before H before T and organize by vnum
                     */
                    if ( tmp->next )
                    {
                        tmp = tmp->next;
                        if ( tmp && tmp->command == 'P' )
                        {
                            if ( letter == 'P' && tmp->arg3 == arg3 )
                                for ( ; tmp && tmp->command == 'P' && tmp->arg3 == arg3 && tmp->arg1 < arg1; tmp = tmp->next );
                            else
                                if ( letter != 'T' )
                                    for ( ; tmp && tmp->command == 'P' && tmp->arg3 == arg3; tmp = tmp->next );
                        }
                        else
                            if ( tmp && tmp->command == 'H' )
                            {
                                if ( letter == 'H' && tmp->arg3 == arg3 )
                                    for ( ; tmp && tmp->command == 'H' && tmp->arg3 == arg3 && tmp->arg1 < arg1; tmp = tmp->next );
                                else
                                    if ( letter != 'H' )
                                        for ( ; tmp && tmp->command == 'H' && tmp->arg3 == arg3; tmp = tmp->next );
                            }
                            else
                                if ( tmp && tmp->command == 'T' && letter == 'T' )
                                    for ( ; tmp && tmp->command == 'T' && tmp->arg3 == arg3 && tmp->arg1 < arg1; tmp = tmp->next );
                        if ( tmp )
                            INSERT( pReset, tmp, tarea->first_reset, next, prev );
                        else
                            LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
                    }
                    else
                        LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
                    return pReset;
                }
            break;
        }
        /* likely a bad reset if we get here... add it anyways */
    }
    LINK( pReset, tarea->first_reset, tarea->last_reset, next, prev );
    return pReset;
}