zim/area/
zim/bin/
zim/clans/plists/
zim/corefiles/
zim/doc/muddy/
zim/gods/
zim/log/
zim/player/
zim/skill_tree/
zim/tmp/
/*-
 * Copyright (c) 1998 fjoe <fjoe@iclub.nsu.ru>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $Id: olc_room.c 871 2006-05-31 04:08:21Z zsuzsu $
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "merc.h"
#include "olc.h"
#include "db/db.h"

#define EDIT_ROOM(ch, room)	(room = (ROOM_INDEX_DATA*) ch->desc->pEdit)

/*
 * Room Editor Prototypes
 */
DECLARE_OLC_FUN(roomed_create		);
DECLARE_OLC_FUN(roomed_edit		);
DECLARE_OLC_FUN(roomed_touch		);
DECLARE_OLC_FUN(roomed_show		);
DECLARE_OLC_FUN(roomed_list		);

DECLARE_OLC_FUN(roomed_name		);
DECLARE_OLC_FUN(roomed_desc		);
DECLARE_OLC_FUN(roomed_exd		);
DECLARE_OLC_FUN(roomed_north		);
DECLARE_OLC_FUN(roomed_south		);
DECLARE_OLC_FUN(roomed_east		);
DECLARE_OLC_FUN(roomed_west		);
DECLARE_OLC_FUN(roomed_up		);
DECLARE_OLC_FUN(roomed_down		);
DECLARE_OLC_FUN(roomed_mreset		);
DECLARE_OLC_FUN(roomed_oreset		);
DECLARE_OLC_FUN(roomed_heal		);
DECLARE_OLC_FUN(roomed_mana		);
DECLARE_OLC_FUN(roomed_clan		);
DECLARE_OLC_FUN(roomed_owner		);
DECLARE_OLC_FUN(roomed_room		);
DECLARE_OLC_FUN(roomed_sector		);
DECLARE_OLC_FUN(roomed_reset		);
DECLARE_OLC_FUN(roomed_clone		);

olc_cmd_t olc_cmds_room[] =
{
/*	{ command	function			}, */

	{ 1, "create",	roomed_create			},
	{ 1, "edit",	roomed_edit			},
	{ 1, "touch",	roomed_touch			},
	{ 0, "show",	roomed_show			},
	{ 0, "list",	roomed_list			},

	{ 1, "desc",	roomed_desc			},
	{ 1, "exd",	roomed_exd			},
	{ 1, "name",	roomed_name			},
	{ 1, "heal",	roomed_heal			},
	{ 1, "mana",	roomed_mana			},
	{ 1, "clan",	roomed_clan			},
	{ 0, "clone",	roomed_clone			},

	{ 1, "north",	roomed_north			},
	{ 1, "south",	roomed_south			},
	{ 1, "east",	roomed_east			},
	{ 1, "west",	roomed_west			},
	{ 1, "up",	roomed_up			},
	{ 1, "down",	roomed_down			},

/* New reset commands. */
	{ 2, "mreset",	roomed_mreset			},
	{ 2, "oreset",	roomed_oreset			},
	{ 2, "owner",	roomed_owner			},
	{ 1, "room",	roomed_room,	room_flags	},
	{ 1, "flags",	roomed_room,	room_flags	},
	{ 1, "sector",	roomed_sector,	sector_types	},
	{ 2, "reset",	roomed_reset			},

	{ 0, "commands",show_commands			},
	{ 0, "version",	show_version			},

	{ 0, NULL }
};

static bool olced_exit(CHAR_DATA *ch, const char *argument,
		       olc_cmd_t *cmd, int door);
static void add_reset(ROOM_INDEX_DATA *room, RESET_DATA *pReset, int index);

OLC_FUN(roomed_create)
{
	AREA_DATA *pArea;
	ROOM_INDEX_DATA *pRoom;
	int value;
	int iHash;
	char arg[MAX_STRING_LENGTH];
	
	one_argument(argument, arg, sizeof(arg));
	value = atoi(arg);
	if (!value) {
		do_help(ch, "'OLC CREATE'");
		return FALSE;
	}

	pArea = area_vnum_lookup(value);
	if (!pArea) {
		char_puts("RoomEd: Vnum is not assigned an area.\n", ch);
		return FALSE;
	}

	if (!IS_BUILDER(ch, pArea)) {
        	char_puts("RoomEd: Insufficient security.\n", ch);
		return FALSE;
	}

	if (get_room_index(value)) {
		char_puts("RoomEd: Vnum already exists.\n", ch);
		return FALSE;
	}

	pRoom			= new_room_index();
	pRoom->area		= pArea;
	pRoom->vnum		= value;

	if (value > top_vnum_room)
		 top_vnum_room	= value;

	iHash			= value % MAX_KEY_HASH;
	pRoom->next		= room_index_hash[iHash];
	room_index_hash[iHash]	= pRoom;

	ch->desc->pEdit		= (void *)pRoom;
	OLCED(ch)		= olced_lookup(ED_ROOM);
	touch_area(pArea);
	char_puts("RoomEd: Room created.\n", ch);
	return FALSE;
}

OLC_FUN(roomed_edit)
{
	char arg[MAX_STRING_LENGTH];
	ROOM_INDEX_DATA *pRoom;

	one_argument(argument, arg, sizeof(arg));
	if (arg[0] == '\0')
		pRoom = ch->in_room;
	else if (!is_number(arg)) {
		do_help(ch, "'OLC EDIT'");
		return FALSE;
	}
	else if ((pRoom = get_room_index(atoi(arg))) == NULL) {
		char_puts("RoomEd: Vnum does not exist.\n", ch);
		return FALSE;
	}

	roomed_edit_room(ch, pRoom, FALSE);
	return FALSE;
}

OLC_FUN(roomed_touch)
{
	ROOM_INDEX_DATA *pRoom;
	EDIT_ROOM(ch, pRoom);
	return touch_vnum(pRoom->vnum);
}

OLC_FUN(roomed_show)
{
	char buf[MAX_STRING_LENGTH];
	char arg[MAX_STRING_LENGTH];
	ROOM_INDEX_DATA	*pRoom;
	BUFFER *	output;
	OBJ_DATA	*obj;
	CHAR_DATA	*rch;
	int		door;
	bool		fcnt;
	clan_t	*clan;
	
	one_argument(argument, arg, sizeof(arg));
	if (arg[0] == '\0') {
		if (IS_EDIT(ch, ED_ROOM))
			EDIT_ROOM(ch, pRoom);
		else
			pRoom = ch->in_room;
	}
	else if (!is_number(arg)) {
		do_help(ch, OLCED(ch) ? "'OLC EDIT'" : "'OLC ASHOW'");
		return FALSE;
	}
	else if ((pRoom = get_room_index(atoi(arg))) == NULL) {
		char_puts("RoomEd: Vnum does not exist.\n", ch);
		return FALSE;
	}

	output = buf_new(-1);
	
	buf_add(output, "Description:\n");
	mlstr_dump(output, str_empty, pRoom->description);
	mlstr_dump(output, "Name:       ", pRoom->name);
	buf_printf(output, "Area:       [%5d] %s\n",
		   pRoom->area->vnum, pRoom->area->name);
	buf_printf(output, "Vnum:       [%5d]\nSector:     [%s]\n",
		   pRoom->vnum, flag_string(sector_types, pRoom->sector_type));

	if (pRoom->clan && (clan = clan_lookup(pRoom->clan))) 
		buf_printf(output, "Clan      : [%s]\n", clan->name);

	buf_printf(output, "Room flags: [%s]\n",
		   flag_string(room_flags, pRoom->room_flags));

	if (pRoom->heal_rate != 100 || pRoom->mana_rate != 100)
		buf_printf(output, "Health rec: [%d]\nMana rec  : [%d]\n",
			   pRoom->heal_rate, pRoom->mana_rate);

	if (!IS_NULLSTR(pRoom->owner))
		buf_printf(output, "Owner     : [%s]\n", pRoom->owner);

	if (pRoom->ed) {
		ED_DATA *ed;

		buf_add(output, "Desc Kwds:  [");
		for (ed = pRoom->ed; ed != NULL; ed = ed->next) {
			buf_add(output, ed->keyword);
			if (ed->next != NULL)
				buf_add(output, " ");
		}
		buf_add(output, "]\n");
	}

	buf_add(output, "Characters: [");
	fcnt = FALSE;
	for (rch = pRoom->people; rch; rch = rch->next_in_room) {
		one_argument(rch->name, buf, sizeof(buf));
		buf_add(output, buf);
		if (rch->next_in_room != NULL)
			buf_add(output, " ");
		fcnt = TRUE;
	}

	if (fcnt) 
		buf_add(output, "]\n");
	else
		buf_add(output, "none]\n");

	buf_add(output, "Objects:    [");
	fcnt = FALSE;
	for (obj = pRoom->contents; obj; obj = obj->next_content) {
		one_argument(obj->name, buf, sizeof(buf));
		buf_add(output, buf);
		if (obj->next_content != NULL)
			buf_add(output, " ");
		fcnt = TRUE;
	}

	if (fcnt)
		buf_add(output, "]\n");
	else
		buf_add(output, "none]\n");

	for (door = 0; door < MAX_DIR; door++) {
		EXIT_DATA *pexit;

		if ((pexit = pRoom->exit[door]) != NULL) {
			char word[MAX_INPUT_LENGTH];
			char reset_state[MAX_STRING_LENGTH];
			const char *state;
			int i, length;

			buf_printf(output, "-%-5s to [%5d]\n"
					"     Key: [%5d]\n",
				   dir_name[door],
				   pexit->to_room.r ?
						pexit->to_room.r->vnum : 0,
				   pexit->key);

			/*
			 * Format up the exit info.
			 * Capitalize all flags that are not part of the reset info.
			 */
			strnzcpy(reset_state, sizeof(reset_state),
				 flag_string(exit_flags, pexit->rs_flags));
			state = flag_string(exit_flags, pexit->exit_info);
			buf_add(output, "     Exit flags: [");
			for (; ;) {
				state = one_argument(state, word, sizeof(word));

				if (word[0] == '\0') {
					buf_add(output, "]\n");
					break;
				}

				if (str_infix(word, reset_state)) {
					length = strlen(word);
					for (i = 0; i < length; i++)
						word[i] = UPPER(word[i]);
				}
				buf_add(output, word);
				buf_add(output, " ");
			}

			if (pexit->lock_level > 0 || pexit->trap_level > 0)
				buf_printf(output, "     Lock: %d  Trap: %d\n",
					pexit->lock_level,
					pexit->trap_level);

			buf_printf(output, "     Keywords: [%s]\n",
				   pexit->keyword);
			buf_printf(output, "     Descrip: ");
			mlstr_dump(output, str_empty, pexit->description);
		}
	}

	char_puts(buf_string(output), ch);
	buf_free(output);
	return FALSE;
}

OLC_FUN(roomed_list)
{
	ROOM_INDEX_DATA	*pRoomIndex;
	AREA_DATA	*pArea;
	BUFFER		*buffer;
	bool		found;
	int		vnum;
	int		col = 0;
	const char *	name;
	char		buf  [MAX_INPUT_LENGTH];
	int		ansi_len = 0;
	char		sector = 'x';


	if ((pArea = get_edited_area(ch)) == NULL)
		pArea = ch->in_room->area;

	buffer = buf_new(-1);
	found   = FALSE;

	for (vnum = pArea->min_vnum; vnum <= pArea->max_vnum; vnum++) {
		if ((pRoomIndex = get_room_index(vnum))) {
			found = TRUE;

			switch (pRoomIndex->sector_type) {
				case SECT_INSIDE:
					sector = 'D';
					break;
				case SECT_CITY:
					sector = 'Y';
					break;
				case SECT_FIELD:
					sector = 'G';
					break;
				case SECT_FOREST:
					sector = 'g';
					break;
				case SECT_HILLS:
					sector = 'y';
					break;
				case SECT_MOUNTAIN:
					sector = 'm';
					break;
				case SECT_WATER_SWIM:
					sector = 'B';
					break;
				case SECT_WATER_NOSWIM:
					sector = 'b';
					break;
				case SECT_UNUSED:
					sector = 'r';
					break;
				case SECT_AIR:
					sector = 'C';
					break;
				case SECT_DESERT:
					sector = 'Y';
					break;
				case SECT_ARCTIC:
					sector = 'W';
					break;
				case SECT_ROAD:
					sector = 'x';
					break;

				default:
					sector = 'r';
					break;
			}

			/*format: "{D[{W%5d{D]{x %-17.16s{x"*/
			name = mlstr_mval(pRoomIndex->name);
			ansi_len = astrlen(name, 17);

			snprintf(buf, sizeof(buf),
				"{D[{%%c%%5d{D]{x %%-%d.%ds{x",
				17 + ansi_len,
				16 + ansi_len);

			buf_printf(buffer, buf,
				   sector,
				   vnum,
				   name);

			if (++col % 3 == 0)
				buf_add(buffer, "\n");
		}
	}

	if (!found) 
		char_puts("RoomEd: No rooms in this area.\n", ch);
	else {
		if (col % 3 != 0)
			buf_add(buffer, "\n");

		page_to_char(buf_string(buffer), ch);
	}

	buf_free(buffer);
	return FALSE;
}

OLC_FUN(roomed_north)
{
	return olced_exit(ch, argument, cmd, DIR_NORTH);
}

OLC_FUN(roomed_south)
{
	return olced_exit(ch, argument, cmd, DIR_SOUTH);
}

OLC_FUN(roomed_east)
{
	return olced_exit(ch, argument, cmd, DIR_EAST);
}

OLC_FUN(roomed_west)
{
	return olced_exit(ch, argument, cmd, DIR_WEST);
}

OLC_FUN(roomed_up)
{
	return olced_exit(ch, argument, cmd, DIR_UP);
}

OLC_FUN(roomed_down)
{
	return olced_exit(ch, argument, cmd, DIR_DOWN);
}

OLC_FUN(roomed_exd)
{
	ROOM_INDEX_DATA *pRoom;
	EDIT_ROOM(ch, pRoom);
	return olced_exd(ch, argument, cmd, &pRoom->ed);
}

OLC_FUN(roomed_name)
{
	ROOM_INDEX_DATA *pRoom;
	EDIT_ROOM(ch, pRoom);
	return olced_mlstr(ch, argument, cmd, &pRoom->name);
}

OLC_FUN(roomed_desc)
{
	ROOM_INDEX_DATA *pRoom;
	EDIT_ROOM(ch, pRoom);
	return olced_mlstr_text(ch, argument, cmd, &pRoom->description);
}

OLC_FUN(roomed_heal)
{
	ROOM_INDEX_DATA *pRoom;
	EDIT_ROOM(ch, pRoom);
	return olced_number(ch, argument, cmd, &pRoom->heal_rate);
}       

OLC_FUN(roomed_mana)
{
	ROOM_INDEX_DATA *pRoom;
	EDIT_ROOM(ch, pRoom);
	return olced_number(ch, argument, cmd, &pRoom->mana_rate);
}       

OLC_FUN(roomed_clan)
{
	ROOM_INDEX_DATA *pRoom;
	EDIT_ROOM(ch, pRoom);
	return olced_clan(ch, argument, cmd, &pRoom->clan);
}
	  
#define MAX_MOB	1		/* Default maximum number for resetting mobs */

OLC_FUN(roomed_mreset)
{
	ROOM_INDEX_DATA	*pRoom;
	MOB_INDEX_DATA	*pMobIndex;
	AREA_DATA	*pArea;
	CHAR_DATA	*newmob;
	char		arg [ MAX_INPUT_LENGTH ];
	char		arg2 [ MAX_INPUT_LENGTH ];

	RESET_DATA	*pReset;

	EDIT_ROOM(ch, pRoom);

	argument = one_argument(argument, arg, sizeof(arg));
	argument = one_argument(argument, arg2, sizeof(arg2));

	if (arg[0] == '\0' || !is_number(arg)) {
		char_puts ("Syntax:  mreset <vnum> <max #x> <min #x>\n", ch);
		return FALSE;
	}

	if (!(pMobIndex = get_mob_index(atoi(arg)))) {
		char_puts("RoomEd: No mobile has that vnum.\n", ch);
		return FALSE;
	}

	pArea = area_vnum_lookup(pMobIndex->vnum);
	if (pArea != pRoom->area) {
		char_puts("RoomEd: No such mobile in this area.\n", ch);
		return FALSE;
	}

	/*
	 * Create the mobile reset.
	 */
	pReset              = new_reset_data();
	pReset->command	= 'M';
	pReset->arg1	= pMobIndex->vnum;
	pReset->arg2	= is_number(arg2) ? atoi(arg2) : MAX_MOB;
	pReset->arg3	= pRoom->vnum;
	pReset->arg4	= is_number(argument) ? atoi (argument) : 1;
	add_reset(pRoom, pReset, 0/* Last slot*/);

	/*
	 * Create the mobile.
	 */
	newmob = create_mob(pMobIndex);

	char_printf(ch, "%s (%d) has been loaded and added to resets.\n"
		"There will be a maximum of %d loaded to this room.\n",
		mlstr_mval(pMobIndex->short_descr),
		pMobIndex->vnum,
		pReset->arg2);
	act("$n has created $N!", ch, NULL, newmob, TO_ROOM);
	char_to_room(newmob, pRoom);
	return TRUE;
}

struct wear_type
{
	int	wear_loc;
	int	wear_bit;
};

const struct wear_type wear_table[] =
{
	{ WEAR_NONE,		ITEM_TAKE		},
	{ WEAR_LIGHT,		ITEM_LIGHT		},
	{ WEAR_FINGER_L,	ITEM_WEAR_FINGER	},
	{ WEAR_FINGER_R,	ITEM_WEAR_FINGER	},
	{ WEAR_NECK_1,		ITEM_WEAR_NECK		},
	{ WEAR_NECK_2,		ITEM_WEAR_NECK		},
	{ WEAR_BODY,		ITEM_WEAR_BODY		},
	{ WEAR_HEAD,		ITEM_WEAR_HEAD		},
	{ WEAR_LEGS,		ITEM_WEAR_LEGS		},
	{ WEAR_FEET,		ITEM_WEAR_FEET		},
	{ WEAR_HANDS,		ITEM_WEAR_HANDS		},
	{ WEAR_ARMS,		ITEM_WEAR_ARMS		},
	{ WEAR_SHIELD,		ITEM_WEAR_SHIELD	},
	{ WEAR_ABOUT,		ITEM_WEAR_ABOUT		},
	{ WEAR_WAIST,		ITEM_WEAR_WAIST		},
	{ WEAR_WRIST_L,		ITEM_WEAR_WRIST		},
	{ WEAR_WRIST_R,		ITEM_WEAR_WRIST		},
	{ WEAR_WIELD,		ITEM_WIELD		},
	{ WEAR_HOLD,		ITEM_HOLD		},
	{ WEAR_FLOAT,		ITEM_WEAR_FLOAT		},
	{ WEAR_TATTOO,		ITEM_WEAR_TATTOO	},
	{ WEAR_SECOND_WIELD,	ITEM_WIELD		},
	{ WEAR_STUCK_IN,	ITEM_WIELD		},
	{ WEAR_CLANMARK,	ITEM_WEAR_CLANMARK	},
	{ MAX_WEAR }
};

/*****************************************************************************
 Name:		wear_loc
 Purpose:	Returns the location of the bit that matches the count.
 		1 = first match, 2 = second match etc.
 Called by:	objed_reset(olc_act.c).
 ****************************************************************************/
int wear_loc(int bits, int count)
{
	int flag;
 
	for (flag = 0; wear_table[flag].wear_loc != MAX_WEAR; flag++) {
		 if (IS_SET(bits, wear_table[flag].wear_bit) && --count < 1)
		     return wear_table[flag].wear_loc;
	}
 
	return -1;
}

/*****************************************************************************
 Name:		wear_bit
 Purpose:	Converts a wear_loc into a bit.
 Called by:	roomed_oreset(olc_act.c).
 ****************************************************************************/
int wear_bit(int loc)
{
	int flag;
 
	for (flag = 0; wear_table[flag].wear_loc != MAX_WEAR; flag++) {
		if (loc == wear_table[flag].wear_loc)
			return wear_table[flag].wear_bit;
	}
 
	return 0;
}

OLC_FUN(roomed_oreset)
{
	ROOM_INDEX_DATA	*pRoom;
	OBJ_INDEX_DATA	*pObjIndex;
	AREA_DATA	*pArea;
	OBJ_DATA	*newobj;
	OBJ_DATA	*to_obj;
	CHAR_DATA	*to_mob;
	char		arg1 [ MAX_INPUT_LENGTH ];
	char		arg2 [ MAX_INPUT_LENGTH ];
	int		olevel = 0;

	RESET_DATA	*pReset;

	EDIT_ROOM(ch, pRoom);

	argument = one_argument(argument, arg1, sizeof(arg1));
	argument = one_argument(argument, arg2, sizeof(arg2));

	if (arg1[0] == '\0' || !is_number(arg1)) {
		char_puts ("Syntax:  oreset <vnum> <args>\n", ch);
		char_puts ("        -no_args               = into room\n", ch);
		char_puts ("        -<obj_name>            = into obj\n", ch);
		char_puts ("        -<mob_name> <wear_loc> = into mob\n", ch);
		return FALSE;
	}

	if (!(pObjIndex = get_obj_index(atoi(arg1)))) {
		char_puts("RoomEd: No object has that vnum.\n", ch);
		return FALSE;
	}

	pArea = area_vnum_lookup(pObjIndex->vnum);
	if (pArea != pRoom->area) {
		char_puts("RoomEd: No such object in this area.\n", ch);
		return FALSE;
	}

	/*
	 * Load into room.
	 */
	if (arg2[0] == '\0')
	{
		pReset		= new_reset_data();
		pReset->command	= 'O';
		pReset->arg1	= pObjIndex->vnum;
		pReset->arg2	= 0;
		pReset->arg3	= pRoom->vnum;
		pReset->arg4	= 0;
		add_reset(pRoom, pReset, 0/* Last slot*/);

		newobj = create_obj(pObjIndex, 0);
		obj_to_room(newobj, pRoom);

		char_printf(ch, "%s (%d) has been loaded and added to resets.\n",
			mlstr_mval(pObjIndex->short_descr),
			pObjIndex->vnum);
	}
	else
	/*
	 * Load into object's inventory.
	 */
	if (argument[0] == '\0'
	&& ((to_obj = get_obj_list(ch, arg2, pRoom->contents)) != NULL))
	{
		pReset		= new_reset_data();
		pReset->command	= 'P';
		pReset->arg1	= pObjIndex->vnum;
		pReset->arg2	= 0;
		pReset->arg3	= to_obj->pIndexData->vnum;
		pReset->arg4	= 1;
		add_reset(pRoom, pReset, 0/* Last slot*/);

		newobj = create_obj(pObjIndex, 0);
		newobj->cost = 0;
		obj_to_obj(newobj, to_obj);

		char_printf(ch, "%s (%d) has been loaded into "
			"%s (%d) and added to resets.\n",
			mlstr_mval(newobj->short_descr),
			newobj->pIndexData->vnum,
			mlstr_mval(to_obj->short_descr),
			to_obj->pIndexData->vnum);
	}
	else
	/*
	 * Load into mobile's inventory.
	 */
	if ((to_mob = get_char_room(ch, arg2)) != NULL) {
		int wear_loc;

		if (!str_cmp(argument, "?")) {
			show_flags(ch, wear_loc_flags);
			return FALSE;
		}

		wear_loc = flag_value(wear_loc_flags, argument);

		/*
		 * Disallow loading a sword(WEAR_WIELD) into WEAR_HEAD.
		 */
		if (!IS_SET(pObjIndex->wear_flags, wear_bit(wear_loc))) {
			char_printf(ch, "%s (%d) has wear flags: [%s]\n",
				    mlstr_mval(pObjIndex->short_descr),
				    pObjIndex->vnum,
				    flag_string(wear_flags,
						pObjIndex->wear_flags));
			return FALSE;
		}

		/*
		 * Can't load into same position.
		 */
		if (get_eq_char(to_mob, wear_loc)) {
			char_puts("RoomEd: Object already equipped.\n", ch);
			return FALSE;
		}

		pReset		= new_reset_data();
		pReset->arg1	= pObjIndex->vnum;
		pReset->arg2	= wear_loc;
		if (pReset->arg2 == WEAR_NONE)
			pReset->command = 'G';
		else
			pReset->command = 'E';
		pReset->arg3	= wear_loc;

		add_reset(pRoom, pReset, 0/* Last slot*/);

		olevel  = URANGE(0, to_mob->level - 2, LEVEL_HERO);
		 newobj = create_obj(pObjIndex, 0);

		if (to_mob->pIndexData->pShop) {	/* Shop-keeper? */
			switch (pObjIndex->item_type) {
			default:		olevel = 0;		break;
			case ITEM_PILL:	olevel = number_range( 0, 10);	break;
			case ITEM_POTION:olevel = number_range( 0, 10);	break;
			case ITEM_SCROLL:olevel = number_range( 5, 15);	break;
			case ITEM_WAND:	olevel = number_range(10, 20);	break;
			case ITEM_STAFF:olevel = number_range(15, 25);	break;
			case ITEM_ARMOR:olevel = number_range( 5, 15);	break;
			case ITEM_WEAPON: if (pReset->command == 'G')
					    olevel = number_range(5, 15);
				else
				    olevel = number_fuzzy(olevel);
			break;
			}

			newobj = create_obj(pObjIndex, 0);
			if (pReset->arg2 == WEAR_NONE)
			SET_BIT(newobj->extra_flags, ITEM_INVENTORY);
		}
		else
			newobj = create_obj(pObjIndex, 0);

		obj_to_char(newobj, to_mob);
		if (pReset->command == 'E')
			equip_char(to_mob, newobj, pReset->arg3);

		char_printf(ch, "%s (%d) has been loaded "
			"%s of %s (%d) and added to resets.\n",
			mlstr_mval(pObjIndex->short_descr),
			pObjIndex->vnum,
			flag_string(wear_loc_strings, pReset->arg3),
			mlstr_mval(to_mob->short_descr),
			to_mob->pIndexData->vnum);
	}
	else	/* Display Syntax */
	{
		char_puts("RoomEd: That mobile isn't here.\n", ch);
		return FALSE;
	}

	act("$n has created $p!", ch, newobj, NULL, TO_ROOM);
	return TRUE;
}

OLC_FUN(roomed_room)
{
	ROOM_INDEX_DATA *room;
	EDIT_ROOM(ch, room);
	return olced_flag32(ch, argument, cmd, &room->room_flags);
}

OLC_FUN(roomed_sector)
{
	ROOM_INDEX_DATA *room;
	EDIT_ROOM(ch, room);
	return olced_flag32(ch, argument, cmd, &room->sector_type);
}

OLC_FUN(roomed_owner)
{
	ROOM_INDEX_DATA *pRoom;
	EDIT_ROOM(ch, pRoom);

	if (argument[0] == '\0') {
		char_puts("Syntax:  owner [owner]\n", ch);
		char_puts("         owner none\n", ch);
		return FALSE;
	}

	free_string(pRoom->owner);
	if (!str_cmp(argument, "none"))
		pRoom->owner = str_dup(str_empty);
	else
		pRoom->owner = str_dup(argument);

	char_puts("Owner set.\n", ch);
	return TRUE;
}

OLC_FUN(roomed_reset)
{
	ROOM_INDEX_DATA *pRoom;
	EDIT_ROOM(ch, pRoom);
	reset_room(pRoom);
	char_puts("RoomEd: Room reset.\n", ch);
	return FALSE;
}

OLC_FUN(roomed_clone)
{
	ROOM_INDEX_DATA *room;
	ROOM_INDEX_DATA *proto;
	char arg[MAX_INPUT_LENGTH];
	int i;
	bool fAll = FALSE;

	argument = one_argument(argument, arg, sizeof(arg));
	if (!str_cmp(arg, "all")) {
		fAll = TRUE;
		argument = one_argument(argument, arg, sizeof(arg));
	}

	if (!is_number(arg)) {
		do_help(ch, "'OLC ROOM CLONE'");
		return FALSE;
	}

	i = atoi(arg);
	if ((proto = get_room_index(i)) == NULL) {
		char_printf(ch, "RoomEd: %d: Vnum does not exist.\n", i);
		return FALSE;
	}

	EDIT_ROOM(ch, room);
	if (room == proto) {
		char_puts("RoomEd: Huh, cloning from self?\n", ch);
		return FALSE;
	}

	mlstr_free(room->name);
	room->name = mlstr_dup(proto->name);

	mlstr_free(room->description);
	room->description = mlstr_dup(proto->description);

	if (fAll) {
		ed_free(room->ed);
		room->ed = ed_dup(proto->ed);

		free_string(room->owner);
		room->owner = str_dup(proto->owner);

		room->room_flags = proto->room_flags;
		room->sector_type = proto->sector_type;
		room->heal_rate = proto->heal_rate;
		room->mana_rate = proto->mana_rate;
		room->clan = proto->clan;
	}

	return TRUE;
}

void roomed_edit_room(CHAR_DATA *ch, ROOM_INDEX_DATA *pRoom, bool drop_out)
{
	AREA_DATA *pArea = area_vnum_lookup(pRoom->vnum);

	if (!IS_BUILDER(ch, pArea)) {
		char_puts("RoomEd: Insufficient security.\n", ch);
		if (drop_out)
			edit_done(ch->desc);
	       	return;
	}

	ch->desc->pEdit = (void*) pRoom;
	OLCED(ch)	= olced_lookup(ED_ROOM);
}

static bool olced_exit(CHAR_DATA *ch, const char *argument,
		       olc_cmd_t *cmd, int door)
{
	ROOM_INDEX_DATA *pRoom;
	char command[MAX_INPUT_LENGTH];
	char arg[MAX_INPUT_LENGTH];
	int  value;

	EDIT_ROOM(ch, pRoom);

	/*
	 * Set the exit flags, needs full argument.
	 * ----------------------------------------
	 */
	if ((value = flag_value(exit_flags, argument)) != 0) {
		ROOM_INDEX_DATA *pToRoom;
		int rev;                                    /* ROM OLC */

		if (!pRoom->exit[door]) {
		   	char_puts("Exit does not exist.\n",ch);
		   	return FALSE;
		}
		/*   pRoom->exit[door] = new_exit(); */

		/*
		 * This room.
		 */
		TOGGLE_BIT(pRoom->exit[door]->rs_flags,  value);

		/*
		 * Don't toggle exit_info because it can be
		 * changed by players.
		 */
		pRoom->exit[door]->exit_info = pRoom->exit[door]->rs_flags;

		/*
		 * Connected room.
		 */
		rev = rev_dir[door];
		pToRoom = pRoom->exit[door]->to_room.r;     /* ROM OLC */
		if (pToRoom && pToRoom->exit[rev] != NULL) {
			TOGGLE_BIT(pToRoom->exit[rev]->rs_flags,  value);
			TOGGLE_BIT(pToRoom->exit[rev]->exit_info, value);
		}

		char_puts("Exit flag toggled.\n", ch);
		return TRUE;
	}

	/*
	 * Now parse the arguments.
	 */
	argument = one_argument(argument, command, sizeof(command));
	argument = one_argument(argument, arg, sizeof(arg));

	if (command[0] == '\0' && argument[0] == '\0') { /* Move command. */
		move_char(ch, door, TRUE);                    /* ROM OLC */
		return FALSE;
	}

	if (command[0] == '?') {
		BUFFER *output;

		output = buf_new(-1);
		help_show(ch, output, "'OLC EXITS'", FALSE);
		buf_printf(output, "Valid exit commands are:\n");
		buf_printf(output, "delete  dig  link  lock_level  trap_level\n"
				"room  key  name  description\n");
		buf_printf(output, "Valid exit flags are:\n");
		show_flags_buf(output, exit_flags);
		page_to_char(buf_string(output), ch);
		buf_free(output);
		return FALSE;
	}

	if (!str_cmp(command, "delete")) {
		ROOM_INDEX_DATA *pToRoom;
		int rev;                                     /* ROM OLC */
		
		if (!pRoom->exit[door]) {
			char_puts("RoomEd: Cannot delete a null exit.\n", ch);
			return FALSE;
		}

		/*
		 * Remove ToRoom Exit.
		 */
		rev = rev_dir[door];
		pToRoom = pRoom->exit[door]->to_room.r;       /* ROM OLC */
		if (pToRoom && pToRoom->exit[rev]) {
			free_exit(pToRoom->exit[rev]);
			pToRoom->exit[rev] = NULL;
		}

		/*
		 * Remove this exit.
		 */
		free_exit(pRoom->exit[door]);
		pRoom->exit[door] = NULL;

		char_puts("Exit unlinked.\n", ch);
		return TRUE;
	}

	if (!str_cmp(command, "link")) {
		EXIT_DATA *pExit;
		ROOM_INDEX_DATA *pToRoom;

		if (arg[0] == '\0' || !is_number(arg)) {
			do_help(ch, "'OLC EXITS'");
			return FALSE;
		}

		value = atoi(arg);

		if ((pToRoom = get_room_index(value)) == NULL) {
			char_puts("RoomEd: Cannot link to non-existant room.\n", ch);
			return FALSE;
		}

		if (!IS_BUILDER(ch, pToRoom->area)) {
			char_puts("RoomEd: Cannot link to that area.\n", ch);
			return FALSE;
		}

		if (pToRoom->exit[rev_dir[door]]) {
			char_puts("RoomEd: Remote side's exit already exists.\n", ch);
			return FALSE;
		}

		if (!pRoom->exit[door])
			pRoom->exit[door] = new_exit();

		pRoom->exit[door]->to_room.r = pToRoom;
		pRoom->exit[door]->orig_door = door;
		
		door			= rev_dir[door];
		pExit			= new_exit();
		pExit->to_room.r	= pRoom;
		pExit->orig_door	= door;
		pToRoom->exit[door]	= pExit;

		char_puts("Two-way link established.\n", ch);
		return TRUE;
	}
		 
	if (!str_cmp(command, "dig")) {
		char buf[MAX_STRING_LENGTH];
		
		if (arg[0] == '\0' || !is_number(arg)) {
			char_printf(ch, "Syntax: %s dig <vnum>\n",
				    cmd->name);
			return FALSE;
		}
		
		roomed_create(ch, arg, cmd);
		ch->desc->pEdit = pRoom;
		snprintf(buf, sizeof(buf), "link %s", arg);
		olced_exit(ch, buf, cmd, door);
		return TRUE;
	}

	if (!str_cmp(command, "room")) {
		if (arg[0] == '\0' || !is_number(arg)) {
			char_printf(ch, "Syntax: %s room [vnum]\n",
				    cmd->name);
			return FALSE;
		}

		if (!pRoom->exit[door])
			pRoom->exit[door] = new_exit();

		value = atoi(arg);

		if (!get_room_index(value)) {
			char_puts("RoomEd: Cannot link to non-existant room.\n", ch);
			return FALSE;
		}

		pRoom->exit[door]->to_room.r = get_room_index(value);
		pRoom->exit[door]->orig_door = door;

		char_puts("One-way link established.\n", ch);
		return TRUE;
	}

	if (!str_cmp(command, "key")) {
		OBJ_INDEX_DATA *key;

		if (arg[0] == '\0' || !is_number(arg)) {
			char_printf(ch, "Syntax: %s key [vnum]\n",
				    cmd->name);
			return FALSE;
		}

		if (!pRoom->exit[door]) {
			char_puts("RoomEd: Exit does not exist.\n",ch);
			return FALSE;
		}

		value = atoi(arg);

		if ((key = get_obj_index(value)) == NULL) {
			char_puts("RoomEd: Obj doesn't exist.\n", ch);
			return FALSE;
		}

		if (key->item_type != ITEM_KEY) {
			char_puts("RoomEd: That obj is not key.\n", ch);
			return FALSE;
		}

		pRoom->exit[door]->key = value;

		char_puts("Exit key set.\n", ch);
		return TRUE;
	}

	if (!str_cmp(command, "lock_level")) {
		if (arg[0] == '\0' || !is_number(arg)) {
			char_printf(ch, "Syntax: %s lock_level [level]\n",
				    cmd->name);
			return FALSE;
		}

		if (!pRoom->exit[door]) {
			char_puts("RoomEd: Exit does not exist.\n",ch);
			return FALSE;
		}

		value = atoi(arg);

		if (value < 0) {
			char_puts("RoomEd: illegal lock level.\n", ch);
			return FALSE;
		}

		pRoom->exit[door]->lock_level = value;

		char_puts("Exit lock_level set.\n", ch);
		return TRUE;
	}

	if (!str_cmp(command, "trap_level")) {
		if (arg[0] == '\0' || !is_number(arg)) {
			char_printf(ch, "Syntax: %s trap_level [level]\n",
				    cmd->name);
			return FALSE;
		}

		if (!pRoom->exit[door]) {
			char_puts("RoomEd: Exit does not exist.\n",ch);
			return FALSE;
		}

		value = atoi(arg);

		if (value < 0) {
			char_puts("RoomEd: illegal trap level.\n", ch);
			return FALSE;
		}

		pRoom->exit[door]->trap_level = value;

		char_puts("Exit trap_level set.\n", ch);
		return TRUE;
	}

	if (!str_cmp(command, "name")) {
		if (arg[0] == '\0') {
			char_printf(ch, "Syntax: %s name [string]\n"
					"        %s name none\n",
				    cmd->name, cmd->name);
			return FALSE;
		}

		if (!pRoom->exit[door]) {
			char_puts("RoomEd: Exit does not exist.\n",ch);
			return FALSE;
		}

		free_string(pRoom->exit[door]->keyword);
		if (!str_cmp(arg, "none"))
			pRoom->exit[door]->keyword = str_dup(str_empty);
		else
			pRoom->exit[door]->keyword = str_dup(arg);

		char_puts("Exit name set.\n", ch);
		return TRUE;
	}

	if (!str_prefix(command, "description")) {
		if (!pRoom->exit[door]) {
			char_puts("RoomEd: Exit does not exist.\n",ch);
			return FALSE;
		}

		if (!mlstr_append(ch, &pRoom->exit[door]->description, arg)) {
			char_printf(ch, "Syntax: %s desc lang\n",
				    cmd->name);
			return FALSE;
		}
		return TRUE;
	}

	return FALSE;
}

void display_resets(CHAR_DATA *ch)
{
    ROOM_INDEX_DATA	*pRoom = ch->in_room;
    RESET_DATA		*pReset;
    MOB_INDEX_DATA	*pMob = NULL;
    BUFFER *		buf;
    int 		iReset = 0;
    int			ansi_len = 0;
    int			ansi_len2 = 0;
    char		format[MAX_INPUT_LENGTH];

    buf = buf_new(-1);
    
    buf_add(buf,
  " No.  Loads    Description       Location         Vnum   Mx Mn Description"
  "\n"
  "==== ======== ============= =================== ======== ===== ==========="
  "\n");

    for (pReset = pRoom->reset_first; pReset; pReset = pReset->next) {
	OBJ_INDEX_DATA  *pObj;
	MOB_INDEX_DATA  *pMobIndex;
	OBJ_INDEX_DATA  *pObjIndex;
	OBJ_INDEX_DATA  *pObjToIndex;
	ROOM_INDEX_DATA *pRoomIndex;
	char *start = buf_string(buf);

	buf_printf(buf, "[{c%2d{x] ", ++iReset);

	switch (pReset->command)
	{
	default:
	    buf_printf(buf, "Bad reset command: %c.", pReset->command);
	    break;

	case 'M':
	    if (!(pMobIndex = get_mob_index(pReset->arg1))) {
                buf_printf(buf, "Load Mobile - Bad Mob %d\n", pReset->arg1);
                continue;
	    }

	    if (!(pRoomIndex = get_room_index(pReset->arg3))) {
                buf_printf(buf, "Load Mobile - Bad Room %d\n", pReset->arg3);
                continue;
	    }

            pMob = pMobIndex;

	    ansi_len = astrlen(mlstr_mval(pMob->short_descr), 13);
	    ansi_len2 = astrlen(mlstr_mval(pRoomIndex->name), 15);

	    snprintf(format, sizeof(format),
            	"M{D[{W%%5d{D]{x %%-%d.%ds{x in room             "
		"R{D[{W%%5d{D]{x %%2d-%%2d %%-%d.%ds{x\n",
		13 + ansi_len,
		13 + ansi_len,
		15 + ansi_len2,
		15 + ansi_len2);

            buf_printf(buf, format,
                       pReset->arg1, mlstr_mval(pMob->short_descr),
			pReset->arg3, pReset->arg2, pReset->arg4,
			mlstr_mval(pRoomIndex->name));

	    /*
	     * Check for pet shop.
	     * -------------------
	     */
	    {
		ROOM_INDEX_DATA *pRoomIndexPrev;

		pRoomIndexPrev = get_room_index(pRoomIndex->vnum - 1);
		if (pRoomIndexPrev
		    && IS_SET(pRoomIndexPrev->room_flags, ROOM_PET_SHOP))
                    start[5] = 'P';
	    }

	    break;

	case 'O':
	    if (!(pObjIndex = get_obj_index(pReset->arg1))) {
                buf_printf(buf, "Load Object - Bad Object %d\n",
		    pReset->arg1);
                continue;
	    }

            pObj       = pObjIndex;

	    if (!(pRoomIndex = get_room_index(pReset->arg3))) {
                buf_printf(buf, "Load Object - Bad Room %d\n", pReset->arg3);
                continue;
	    }

	    ansi_len = astrlen(mlstr_mval(pObj->short_descr), 13);
	    ansi_len2 = astrlen(mlstr_mval(pRoomIndex->name), 15);

	    snprintf(format, sizeof(format),
            	"O{D[{W%%5d{D]{x %%-%d.%ds{x in room             "
		"R{D[{W%%5d{D]{x       %%-%d.%ds{x\n",
		13 + ansi_len,
		13 + ansi_len,
		15 + ansi_len2,
		15 + ansi_len2);

            buf_printf(buf, format,
		  pReset->arg1, mlstr_mval(pObj->short_descr),
		  pReset->arg3, mlstr_mval(pRoomIndex->name));

	    break;

	case 'P':
	    if (!(pObjIndex = get_obj_index(pReset->arg1))) {
                buf_printf(buf, "Put Object - Bad Object %d\n",
                    pReset->arg1);
                continue;
	    }

            pObj       = pObjIndex;

	    if (!(pObjToIndex = get_obj_index(pReset->arg3))) {
                buf_printf(buf, "Put Object - Bad To Object %d\n",
                    pReset->arg3);
                continue;
	    }

	    ansi_len = astrlen(mlstr_mval(pObj->short_descr), 13);
	    ansi_len2 = astrlen(mlstr_mval(pObjToIndex->short_descr), 15);

	    snprintf(format, sizeof(format),
            	"O{D[{W%%5d{D]{x %%-%d.%ds{x inside              "
		"O{D[{W%%5d{D]{x %%2d-%%2d %%-%d.%ds{x\n",
		13 + ansi_len,
		13 + ansi_len,
		15 + ansi_len2,
		15 + ansi_len2);

	    buf_printf(buf, format,
		pReset->arg1,
		mlstr_mval(pObj->short_descr),
		pReset->arg3,
		pReset->arg2,
		pReset->arg4,
		mlstr_mval(pObjToIndex->short_descr));

	    break;

	case 'G':
	case 'E':
	    if (!(pObjIndex = get_obj_index(pReset->arg1))) {
                buf_printf(buf, "Give/Equip Object - Bad Object %d\n",
                    pReset->arg1);
                continue;
	    }

            pObj       = pObjIndex;

	    if (!pMob) {
                buf_printf(buf, "Give/Equip Object - No Previous Mobile\n");
                break;
	    }

	    if (pMob->pShop) {
		    ansi_len = astrlen(mlstr_mval(pObj->short_descr), 13);
		    ansi_len2 = astrlen(mlstr_mval(pMob->short_descr), 15);

		    snprintf(format, sizeof(format),
			"O{D[{W%%5d{D]{x %%-%d.%ds{x in the inventory of "
			"S{D[{W%%5d{D]{x       %%-%d.%ds{x\n",
			13 + ansi_len,
			13 + ansi_len,
			15 + ansi_len2,
			15 + ansi_len2);
	        buf_printf(buf, format,
		pReset->arg1,
		mlstr_mval(pObj->short_descr),                           
		pMob->vnum,
		mlstr_mval(pMob->short_descr));
	    }
	    else {
		    ansi_len = astrlen(mlstr_mval(pObj->short_descr), 13);
		    ansi_len2 = astrlen(mlstr_mval(pMob->short_descr), 15);

		    snprintf(format, sizeof(format),
			"O{D[{W%%5d{D]{x %%-%d.%ds{x %%-19.19s{x "
			"M{D[{W%%5d{D]{x       %%-%d.%ds{x\n",
			13 + ansi_len,
			13 + ansi_len,
			15 + ansi_len2,
			15 + ansi_len2);
	    buf_printf(buf, format,
		pReset->arg1,
		mlstr_mval(pObj->short_descr),
		(pReset->command == 'G') ?
		    flag_string(wear_loc_strings, WEAR_NONE)
		  : flag_string(wear_loc_strings, pReset->arg3),
		  pMob->vnum,
		  mlstr_mval(pMob->short_descr));
	    }
	

	    break;

	/*
	 * Doors are set in rs_flags don't need to be displayed.
	 * If you want to display them then uncomment the new_reset
	 * line in the case 'D' in load_resets in db.c and here.
	 */
	case 'D':
	    pRoomIndex = get_room_index(pReset->arg1);
	    ansi_len = astrlen(mlstr_mval(pRoomIndex->name), 19);

	    snprintf(format, sizeof(format),
	        "R{D[{W%%5d{D]{x %%s{x door of %%-%d.%ds{x reset to %%s{x\n",
		19 + ansi_len,
		19 + ansi_len);

	    buf_printf(buf, format,
		pReset->arg1,
		dir_name[pReset->arg2],
		mlstr_mval(pRoomIndex->name),
		flag_string(door_resets, pReset->arg3));

	    break;
	/*
	 * End Doors Comment.
	 */
	case 'R':
	    if (!(pRoomIndex = get_room_index(pReset->arg1))) {
		buf_printf(buf, "Randomize Exits - Bad Room %d\n",
		    pReset->arg1);
		continue;
	    }

	    buf_printf(buf, 
		    "R{D[{W%5d{D]{x Exits are randomized in %s{x\n",
		pReset->arg1, mlstr_mval(pRoomIndex->name));

	    break;
	}
    }
    char_puts(buf_string(buf), ch);
    buf_free(buf);
}

void do_resets(CHAR_DATA *ch, const char *argument)
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char arg3[MAX_INPUT_LENGTH];
    char arg4[MAX_INPUT_LENGTH];
    char arg5[MAX_INPUT_LENGTH];
    char arg6[MAX_INPUT_LENGTH];
    char arg7[MAX_INPUT_LENGTH];
    RESET_DATA *pReset = NULL;
	ROOM_INDEX_DATA *pRoom = ch->in_room;


    argument = one_argument(argument, arg1, sizeof(arg1));
    argument = one_argument(argument, arg2, sizeof(arg2));
    argument = one_argument(argument, arg3, sizeof(arg3));
    argument = one_argument(argument, arg4, sizeof(arg4));
    argument = one_argument(argument, arg5, sizeof(arg5));
    argument = one_argument(argument, arg6, sizeof(arg6));
    argument = one_argument(argument, arg7, sizeof(arg7));

    if (!IS_BUILDER(ch, pRoom->area))
    {
	char_puts("Resets: Invalid security for editing this area.\n",
                      ch);
	return;
    }

    /*
     * Display resets in current room.
     * -------------------------------
     */
    if (arg1[0] == '\0')
    {
	if (pRoom->reset_first)
	{
	    char_puts(
		"Resets: M = mobile, R = room, O = object, "
		"P = pet, S = shopkeeper\n", ch);
	    display_resets(ch);
	}
	else
	    char_puts("No resets in this room.\n", ch);
    }


    /*
     * Take index number and search for commands.
     * ------------------------------------------
     */
    if (is_number(arg1))
    {
	/*
	 * Delete a reset.
	 * ---------------
	 */
	if (!str_cmp(arg2, "delete"))
	{
	    int insert_loc = atoi(arg1);

	    if (!pRoom->reset_first)
	    {
		char_puts("No resets in this area.\n", ch);
		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)
		{
		    char_puts("Reset not found.\n", ch);
		    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);
	    }

	    free_reset_data(pReset);
	    touch_area(pRoom->area);
	    char_puts("Reset deleted.\n", ch);
	}
	else
	/*
	 * Add a reset.
	 * ------------
	 */
	if ((!str_cmp(arg2, "mob") && is_number(arg3))
	  || (!str_cmp(arg2, "obj") && is_number(arg3)))
	{
	    /*
	     * Check for Mobile reset.
	     * -----------------------
	     */
	    if (!str_cmp(arg2, "mob"))
	    {
		if (get_mob_index(is_number(arg3) ? atoi(arg3) : 1) == NULL)
		  {
		    char_puts("Mob no existe.\n",ch);
		    return;
		  }
		pReset = new_reset_data();
		pReset->command = 'M';
		pReset->arg1    = atoi(arg3);
		pReset->arg2    = is_number(arg4) ? atoi(arg4) : 1; /* Max # */
		pReset->arg3    = pRoom->vnum;
		pReset->arg4	= is_number(arg5) ? atoi(arg5) : 1; /* Min # */
	    }
	    else
	    /*
	     * Check for Object reset.
	     * -----------------------
	     */
	    if (!str_cmp(arg2, "obj"))
	    {
		pReset = new_reset_data();
		pReset->arg1    = atoi(arg3);
		/*
		 * Inside another object.
		 * ----------------------
		 */
		if (!str_prefix(arg4, "inside"))
		{
		    OBJ_INDEX_DATA *temp;

		    temp = get_obj_index(is_number(arg5) ? atoi(arg5) : 1);
		    if ((temp->item_type != ITEM_CONTAINER) &&
		         (temp->item_type != ITEM_CORPSE_NPC))
		     {
		       char_puts("Objeto 2 no es container.\n", ch);
		       return;
		     }
		    pReset->command = 'P';
		    pReset->arg2    = is_number(arg6) ? atoi(arg6) : 1;
		    pReset->arg3    = is_number(arg5) ? atoi(arg5) : 1;
		    pReset->arg4    = is_number(arg7) ? atoi(arg7) : 1;
		}
		else
		/*
		 * Inside the room.
		 * ----------------
		 */
		if (!str_cmp(arg4, "room"))
		{
		    if (get_obj_index(atoi(arg3)) == NULL)
		      {
		         char_puts("Vnum no existe.\n",ch);
		         return;
		      }
		    pReset->command  = 'O';
		    pReset->arg2     = 0;
		    pReset->arg3     = pRoom->vnum;
		    pReset->arg4     = 0;
		}
		else {
		/*
		 * Into a Mobile's inventory.
		 * --------------------------
		 */
		    int loc = WEAR_NONE;
		    int vnum;

		    if (str_prefix(arg4, "none")
		    &&  str_prefix(arg4, "inventory")
		    &&  (loc = flag_value(wear_loc_flags, arg4)) < 0) {
				show_flags(ch, wear_loc_flags);
				return;
		    }

		    if (get_obj_index(vnum = atoi(arg3)) == NULL) {
		         char_puts("Vnum no existe.\n",ch);
		         return;
		    }
		    pReset->arg1 = vnum;
		    pReset->arg3 = loc;
		    if (pReset->arg3 == WEAR_NONE)
			pReset->command = 'G';
		    else
			pReset->command = 'E';
		}
	    }
	    add_reset(pRoom, pReset, atoi(arg1));
	    touch_area(pRoom->area);
	    char_puts("Reset added.\n", ch);
	}
	else
	if (!str_cmp(arg2, "random") && is_number(arg3))
	{
		if (atoi(arg3) < 1 || atoi(arg3) > 6)
			{
				char_puts("Invalid argument.\n", ch);
				return;
			}
		pReset = new_reset_data ();
		pReset->command = 'R';
		pReset->arg1 = pRoom->vnum;
		pReset->arg2 = atoi(arg3);
		add_reset(pRoom, pReset, atoi(arg1));
		touch_area(pRoom->area);
		char_puts("Random exits reset added.\n", ch);
	}
	else
	{
	char_puts("Syntax: RESET <number> OBJ <vnum> <wear_loc>\n", ch);
	char_puts("        RESET <number> OBJ <vnum> inside <vnum> [limit] [count]\n", ch);
	char_puts("        RESET <number> OBJ <vnum> room\n", ch);
	char_puts("        RESET <number> MOB <vnum> [max #x area] [max #x room]\n", ch);
	char_puts("        RESET <number> DELETE\n", ch);
	char_puts("        RESET <number> RANDOM [#x exits]\n", ch);
	}
    }
}

/* Static functions */

/*****************************************************************************
 Name:		add_reset
 Purpose:	Inserts a new reset in the given index slot.
 Called by:	do_resets(olc.c).
 ****************************************************************************/
static void add_reset(ROOM_INDEX_DATA *room, RESET_DATA *pReset, int index)
{
    RESET_DATA *reset;
    int iReset = 0;

    if (!room->reset_first)
    {
	room->reset_first	= pReset;
	room->reset_last	= pReset;
	pReset->next		= NULL;
	return;
    }

    index--;

    if (index == 0)	/* First slot (1) selected. */
    {
	pReset->next = room->reset_first;
	room->reset_first = pReset;
	return;
    }

    /*
     * If negative slot(<= 0 selected) then this will find the last.
     */
    for (reset = room->reset_first; reset->next; reset = reset->next)
    {
	if (++iReset == index)
	    break;
    }

    pReset->next	= reset->next;
    reset->next		= pReset;
    if (!pReset->next)
	room->reset_last = pReset;
    return;
}