1stMUD/corefiles/
1stMUD/gods/
1stMUD/notes/
1stMUD/player/
1stMUD/win32/
1stMUD/win32/ROM/
/**************************************************************************
*  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
*  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
*                                                                         *
*  Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael         *
*  Chastain, Michael Quan, and Mitchell Tse.                              *
*                                                                         *
*  In order to use any part of this Merc Diku Mud, you must comply with   *
*  both the original Diku license in 'license.doc' as well the Merc       *
*  license in 'license.txt'.  In particular, you may not remove either of *
*  these copyright notices.                                               *
*                                                                         *
*  Much time and thought has gone into this software and you are          *
*  benefiting.  We hope that you share your changes too.  What goes       *
*  around, comes around.                                                  *
***************************************************************************
*       ROM 2.4 is copyright 1993-1998 Russ Taylor                        *
*       ROM has been brought to you by the ROM consortium                 *
*           Russ Taylor (rtaylor@hypercube.org)                           *
*           Gabrielle Taylor (gtaylor@hypercube.org)                      *
*           Brian Moore (zump@rom.org)                                    *
*       By using this code, you have agreed to follow the terms of the    *
*       ROM license, in the file Rom24/doc/rom.license                    *
***************************************************************************
*       1stMUD ROM Derivative (c) 2001-2002 by Ryan Jennings              *
*            http://1stmud.dlmud.com/  <r-jenn@shaw.ca>                   *
***************************************************************************/
/***************************************************************************
 *  File: olc_act.c                                                        *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 *                                                                         *
 *  This code was freely distributed with the The Isles 1.1 source code,   *
 *  and has been used here for OLC - OLC would not be what it is without   *
 *  all the previous coders who released their source code.                *
 *                                                                         *
 ***************************************************************************/

#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "tables.h"
#include "olc.h"
#include "recycle.h"
#include "lookup.h"
#include "interp.h"
#include "magic.h"

#define ALT_FLAGVALUE_SET( _blargh, _table, _arg )		\
	{							\
		flag_t blah = flag_value( _table, _arg );		\
		_blargh = UMAX(0, blah);		\
	}

#define ALT_FLAGVALUE_TOGGLE( _blargh, _table, _arg )		\
	{							\
		flag_t blah = flag_value( _table, _arg );		\
		TOGGLE_BIT(_blargh, UMAX(0, blah));	\
	}

/* Return TRUE if area changed, FALSE if not. */
#define REDIT( fun )		bool fun( CHAR_DATA *ch, const char *argument )
#define OEDIT( fun )		bool fun( CHAR_DATA *ch, const char *argument )
#define MEDIT( fun )		bool fun( CHAR_DATA *ch, const char *argument )
#define AEDIT( fun )		bool fun( CHAR_DATA *ch, const char *argument )
#define CEDIT( fun )        bool fun( CHAR_DATA *ch, const char *argument )

struct olc_help_type
{
	char *command;
	const void *structure;
	char *desc;
};

void unlink_reset(ROOM_INDEX_DATA * pRoom, RESET_DATA * pReset)
{
	RESET_DATA *prev, *wReset;

	for (wReset = pRoom->reset_first; wReset; wReset = prev)
	{
		prev = wReset->next;

		if (wReset == pReset)
		{
			UNLINK(pReset, pRoom->reset_first, pRoom->reset_last, next, prev);
		}
	}
}

void unlink_obj_index(OBJ_INDEX_DATA * pObj)
{
	int iHash;

	iHash = pObj->vnum % MAX_KEY_HASH;

	UNLINK_SINGLE(pObj, next, OBJ_INDEX_DATA, obj_index_hash[iHash]);
}

void unlink_room_index(ROOM_INDEX_DATA * pRoom)
{
	int iHash;

	iHash = pRoom->vnum % MAX_KEY_HASH;

	UNLINK_SINGLE(pRoom, next, ROOM_INDEX_DATA, room_index_hash[iHash]);
}

void unlink_mob_index(MOB_INDEX_DATA * pMob)
{
	int iHash;

	iHash = pMob->vnum % MAX_KEY_HASH;

	UNLINK_SINGLE(pMob, next, MOB_INDEX_DATA, mob_index_hash[iHash]);
}

bool show_version(CHAR_DATA * ch, char *argument)
{
	chprintln(ch, VERSION);
	chprintln(ch, AUTHOR);
	chprintln(ch, DATE);
	chprintln(ch, CREDITS);

	return FALSE;
}

/*
 * This table contains help commands and a brief description of each.
 * ------------------------------------------------------------------
 */
const struct olc_help_type help_table[] = {
	{"area", area_flags, "Area attributes."},
	{"room", room_flags, "Room attributes."},
	{"sector", sector_flags, "Sector types, terrain."},
	{"exit", exit_flags, "Exit types."},
	{"type", type_flags, "Types of objects."},
	{"extra", extra_flags, "Object attributes."},
	{"wear", wear_flags, "Where to wear object."},
	{"spec", spec_table, "Available special programs."},
	{"sex", sex_flags, "Sexes."},
	{"act", act_flags, "Mobile attributes."},
	{"affect", affect_flags, "Mobile affects."},
	{"wear-loc", wear_loc_flags, "Where mobile wears object."},
	{"container", container_flags, "Container status."},
	{"targets", target_flags, "Skill target types."},

/* ROM specific bits: */

	{"armor", ac_type, "Ac for different attacks."},
	{"apply", apply_flags, "Apply flags"},
	{"form", form_flags, "Mobile body form."},
	{"part", part_flags, "Mobile body parts."},
	{"imm", imm_flags, "Mobile immunity."},
	{"res", res_flags, "Mobile resistance."},
	{"vuln", vuln_flags, "Mobile vulnerability."},
	{"off", off_flags, "Mobile offensive behaviour."},
	{"size", size_flags, "Mobile size."},
	{"position", position_flags, "Mobile positions."},
	{"wclass", weapon_class, "Weapon class."},
	{"wtype", weapon_type2, "Special weapon type."},
	{"portal", portal_flags, "Portal types."},
	{"furniture", furniture_flags, "Furniture types."},
	{"liquid", liq_table, "Liquid types."},
	{"apptype", apply_types, "Apply types."},
	{"weapon", attack_table, "Weapon types."},
	{"mprog", mprog_flags, "MobProgram flags."},
	{"logflags", log_flags, "Command log types."},
	{NULL, NULL, NULL}
};

/*****************************************************************************
 Name:		show_flag_cmds
 Purpose:	Displays settable flags and stats.
 Called by:	show_help(olc_act.c).
 ****************************************************************************/
void show_flag_cmds(CHAR_DATA * ch, const struct flag_type *flag_table)
{
	char buf[MAX_STRING_LENGTH];
	char buf1[MAX_STRING_LENGTH];
	int flag;
	int col;

	buf1[0] = '\0';
	col = 0;
	for (flag = 0; flag_table[flag].name != NULL; flag++)
	{
		if (flag_table[flag].settable)
		{
			sprintf(buf, "%-19.18s", flag_table[flag].name);
			strcat(buf1, buf);
			if (++col % 4 == 0)
				strcat(buf1, "\n\r");
		}
	}

	if (col % 4 != 0)
		strcat(buf1, "\n\r");

	chprint(ch, buf1);
	return;
}

/*****************************************************************************
 Name:		show_skill_cmds
 Purpose:	Displays all skill functions.
 		Does remove those damn immortal commands from the list.
 		Could be improved by:
 		(1) Adding a check for a particular class.
 		(2) Adding a check for a level range.
 Called by:	show_help(olc_act.c).
 ****************************************************************************/
void show_skill_cmds(CHAR_DATA * ch, int tar)
{
	char buf[MAX_STRING_LENGTH];
	char buf1[MAX_STRING_LENGTH * 2];
	int sn;
	int col;

	buf1[0] = '\0';
	col = 0;
	for (sn = 0; sn < maxSkill; sn++)
	{
		if (!skill_table[sn].name)
			break;

		if (!str_cmp(skill_table[sn].name, "reserved") ||
			skill_table[sn].spell_fun == spell_null)
			continue;

		if (tar == -1 || skill_table[sn].target == tar)
		{
			sprintf(buf, "%-19.18s", skill_table[sn].name);
			strcat(buf1, buf);
			if (++col % 4 == 0)
				strcat(buf1, "\n\r");
		}
	}

	if (col % 4 != 0)
		strcat(buf1, "\n\r");

	chprint(ch, buf1);
	return;
}

/*****************************************************************************
 Name:		show_spec_cmds
 Purpose:	Displays settable special functions.
 Called by:	show_help(olc_act.c).
 ****************************************************************************/
void show_spec_cmds(CHAR_DATA * ch)
{
	char buf[MAX_STRING_LENGTH];
	char buf1[MAX_STRING_LENGTH];
	int spec;
	int col;

	buf1[0] = '\0';
	col = 0;
	chprintln(ch, "Preceed special functions with 'spec_'\n\r");
	for (spec = 0; spec_table[spec].function != NULL; spec++)
	{
		sprintf(buf, "%-19.18s", &spec_table[spec].name[5]);
		strcat(buf1, buf);
		if (++col % 4 == 0)
			strcat(buf1, "\n\r");
	}

	if (col % 4 != 0)
		strcat(buf1, "\n\r");

	chprint(ch, buf1);
	return;
}

/*****************************************************************************
 Name:		show_help
 Purpose:	Displays help for many tables used in OLC.
 Called by:	olc interpreters.
 ****************************************************************************/
bool show_help(CHAR_DATA * ch, const char *argument)
{
	char arg[MAX_INPUT_LENGTH];
	char spell[MAX_INPUT_LENGTH];
	int cnt;

	argument = one_argument(argument, arg);
	one_argument(argument, spell);

	/*
	 * Display syntax.
	 */
	if (arg[0] == '\0')
	{
		chprintln(ch, "Syntax:  ? [command]\n\r");
		chprintln(ch, "[command]  [description]");
		for (cnt = 0; help_table[cnt].command != NULL; cnt++)
		{
			chprintlnf(ch, "%-10.10s -%s",
					   capitalize(help_table[cnt].command),
					   help_table[cnt].desc);
		}
		return FALSE;
	}

	/*
	 * Find the command, show changeable data.
	 * ---------------------------------------
	 */
	for (cnt = 0; help_table[cnt].command != NULL; cnt++)
	{
		if (arg[0] == help_table[cnt].command[0] &&
			!str_prefix(arg, help_table[cnt].command))
		{
			if (help_table[cnt].structure == spec_table)
			{
				show_spec_cmds(ch);
				return FALSE;
			}
			else if (help_table[cnt].structure == liq_table)
			{
				show_liqlist(ch);
				return FALSE;
			}
			else if (help_table[cnt].structure == attack_table)
			{
				show_damlist(ch);
				return FALSE;
			}
			else if (help_table[cnt].structure == skill_table)
			{

				if (spell[0] == '\0')
				{
					chprintln(ch, "Syntax:  ? spells "
							  "[ignore/attack/defend/self/object/all]");
					return FALSE;
				}

				if (!str_prefix(spell, "all"))
					show_skill_cmds(ch, -1);
				else if (!str_prefix(spell, "ignore"))
					show_skill_cmds(ch, TAR_IGNORE);
				else if (!str_prefix(spell, "attack"))
					show_skill_cmds(ch, TAR_CHAR_OFFENSIVE);
				else if (!str_prefix(spell, "defend"))
					show_skill_cmds(ch, TAR_CHAR_DEFENSIVE);
				else if (!str_prefix(spell, "self"))
					show_skill_cmds(ch, TAR_CHAR_SELF);
				else if (!str_prefix(spell, "object"))
					show_skill_cmds(ch, TAR_OBJ_INV);
				else
					chprintln(ch, "Syntax:  ? spell "
							  "[ignore/attack/defend/self/object/all]");

				return FALSE;
			}
			else
			{
				show_flag_cmds(ch,
							   (struct flag_type *) help_table[cnt].structure);
				return FALSE;
			}
		}
	}

	show_help(ch, "");
	return FALSE;
}

REDIT(redit_format)
{
	ROOM_INDEX_DATA *pRoom;

	EDIT_ROOM(ch, pRoom);

	pRoom->description = format_string(pRoom->description);

	chprintln(ch, "String formatted.");
	return TRUE;
}

REDIT(redit_rlist)
{
	ROOM_INDEX_DATA *pRoomIndex;
	AREA_DATA *pArea;
	char buf[MAX_STRING_LENGTH];
	BUFFER *buf1;
	char arg[MAX_INPUT_LENGTH];
	bool found;
	vnum_t vnum;
	int col = 0;

	one_argument(argument, arg);

	pArea = ch->in_room->area;
	buf1 = new_buf();
/*    buf1[0] = '\0'; */
	found = FALSE;

	for (vnum = pArea->min_vnum; vnum <= pArea->max_vnum; vnum++)
	{
		if ((pRoomIndex = get_room_index(vnum)))
		{
			found = TRUE;
			sprintf(buf, "[%5ld] %-17.16s", vnum, capitalize(pRoomIndex->name));
			add_buf(buf1, buf);
			if (++col % 3 == 0)
				add_buf(buf1, "\n\r");
		}
	}

	if (!found)
	{
		chprintln(ch, "Room(s) not found in this area.");
		return FALSE;
	}

	if (col % 3 != 0)
		add_buf(buf1, "\n\r");

	page_to_char(buf_string(buf1), ch);
	free_buf(buf1);
	return FALSE;
}

REDIT(redit_mlist)
{
	MOB_INDEX_DATA *pMobIndex;
	AREA_DATA *pArea;
	char buf[MAX_STRING_LENGTH];
	BUFFER *buf1;
	char arg[MAX_INPUT_LENGTH];
	bool fAll, found;
	vnum_t vnum;
	int col = 0;

	one_argument(argument, arg);
	if (arg[0] == '\0')
	{
		chprintln(ch, "Syntax:  mlist <all/name>");
		return FALSE;
	}

	buf1 = new_buf();
	pArea = ch->in_room->area;
/*    buf1[0] = '\0'; */
	fAll = !str_cmp(arg, "all");
	found = FALSE;

	for (vnum = pArea->min_vnum; vnum <= pArea->max_vnum; vnum++)
	{
		if ((pMobIndex = get_mob_index(vnum)) != NULL)
		{
			if (fAll || is_name(arg, pMobIndex->player_name))
			{
				found = TRUE;
				sprintf(buf, "[%5ld] %-17.16s", pMobIndex->vnum,
						capitalize(pMobIndex->short_descr));
				add_buf(buf1, buf);
				if (++col % 3 == 0)
					add_buf(buf1, "\n\r");
			}
		}
	}

	if (!found)
	{
		chprintln(ch, "Mobile(s) not found in this area.");
		return FALSE;
	}

	if (col % 3 != 0)
		add_buf(buf1, "\n\r");

	page_to_char(buf_string(buf1), ch);
	free_buf(buf1);
	return FALSE;
}

REDIT(redit_delete)
{
	ROOM_INDEX_DATA *pRoom, *pRoom2;
	RESET_DATA *pReset;
	EXIT_DATA *ex;
	OBJ_DATA *Obj, *obj_next;
	CHAR_DATA *wch, *wnext;
	EXTRA_DESCR_DATA *pExtra;
	char arg[MIL];
	vnum_t pIndex, v;
	int i, iHash, rcount, ecount, mcount, ocount, edcount;

	if (IS_NULLSTR(argument))
	{
		if (ch)
			chprintln(ch, "Syntax:  redit delete [vnum]");
		return FALSE;
	}

	one_argument(argument, arg);

	if (is_number(arg))
	{
		pIndex = atol(arg);
		pRoom = get_room_index(pIndex);
	}
	else
	{
		if (ch)
			chprintln(ch, "That is not a number.");
		return FALSE;
	}

	for (i = 0; vnum_table[i].vnum != -1; i++)
	{
		if (vnum_table[i].type != VNUM_ROOM)
			continue;

		if (vnum_table[i].vnum == pIndex)
		{
			if (ch)
				chprintln(ch, "That vnum is reserved.");
			return FALSE;
		}
	}
	if (!pRoom)
	{
		if (ch)
			chprintln(ch, "No such room.");
		return FALSE;
	}

	stop_editing(pRoom);

	SET_BIT(pRoom->area->area_flags, AREA_CHANGED);

	rcount = 0;

	for (pReset = pRoom->reset_first; pReset; pReset = pReset->next)
	{
		rcount++;
	}

	ocount = 0;
	for (Obj = pRoom->first_content; Obj; Obj = obj_next)
	{
		obj_next = Obj->next_content;

		extract_obj(Obj);
		ocount++;
	}

	mcount = 0;
	for (wch = pRoom->first_person; wch; wch = wnext)
	{
		wnext = wch->next_in_room;
		if (IS_NPC(wch))
		{
			extract_char(wch, TRUE);
			mcount++;
		}
		else
		{
			chprintln(wch,
					  "This room is being deleted. Moving you somewhere safe.");
			if (wch->fighting != NULL)
				stop_fighting(wch, TRUE);

			char_from_room(wch);

			char_to_room(wch, get_room_index(ROOM_VNUM_TEMPLE));
			wch->was_in_room = wch->in_room;
		}
	}

	ecount = 0;
	for (iHash = 0; iHash < MAX_KEY_HASH; iHash++)
	{
		for (pRoom2 = room_index_hash[iHash]; pRoom2; pRoom2 = pRoom2->next)
		{
			for (i = 0; i <= MAX_DIR; i++)
			{
				if (!(ex = pRoom2->exit[i]))
					continue;

				if (pRoom2 == pRoom)
				{

					ecount++;
					continue;
				}

				if (ex->u1.to_room == pRoom)
				{
					free_exit(pRoom2->exit[i]);
					pRoom2->exit[i] = NULL;
					SET_BIT(pRoom2->area->area_flags, AREA_CHANGED);
					ecount++;
				}
			}
		}
	}

	edcount = 0;
	for (pExtra = pRoom->first_extra_descr; pExtra; pExtra = pExtra->next)
	{
		edcount++;
	}

	if (top_vnum_room == pIndex)
		for (v = 1; v < pIndex; v++)
			if (get_room_index(v))
				top_vnum_room = v;

	top_room--;
	if (!IS_SET(pRoom->room_flags, ROOM_NOEXPLORE))
		top_explored--;

	unlink_room_index(pRoom);

	pRoom->area = NULL;
	pRoom->vnum = 0;

	free_room_index(pRoom);

	if (ch)
	{
		chprintf(ch,
				 "Removed room vnum {C%ld{x, %d resets, %d extra "
				 "descriptions and %d exits.\n\r", pIndex, rcount,
				 edcount, ecount);
		chprintf(ch,
				 "{C%d{x objects and {C%d{x mobiles were extracted "
				 "from the room.\n\r", ocount, mcount);
	}
	return TRUE;
}

REDIT(redit_olist)
{
	OBJ_INDEX_DATA *pObjIndex;
	AREA_DATA *pArea;
	char buf[MAX_STRING_LENGTH];
	BUFFER *buf1;
	char arg[MAX_INPUT_LENGTH];
	bool fAll, found;
	vnum_t vnum;
	int col = 0;

	one_argument(argument, arg);
	if (arg[0] == '\0')
	{
		chprintln(ch, "Syntax:  olist <all/name/item_type>");
		return FALSE;
	}

	pArea = ch->in_room->area;
	buf1 = new_buf();
/*    buf1[0] = '\0'; */
	fAll = !str_cmp(arg, "all");
	found = FALSE;

	for (vnum = pArea->min_vnum; vnum <= pArea->max_vnum; vnum++)
	{
		if ((pObjIndex = get_obj_index(vnum)))
		{
			if (fAll || is_name(arg, pObjIndex->name) ||
				(int) flag_value(type_flags, arg) == pObjIndex->item_type)
			{
				found = TRUE;
				sprintf(buf, "[%5ld] %-17.16s", pObjIndex->vnum,
						capitalize(pObjIndex->short_descr));
				add_buf(buf1, buf);
				if (++col % 3 == 0)
					add_buf(buf1, "\n\r");
			}
		}
	}

	if (!found)
	{
		chprintln(ch, "Object(s) not found in this area.");
		return FALSE;
	}

	if (col % 3 != 0)
		add_buf(buf1, "\n\r");

	page_to_char(buf_string(buf1), ch);
	free_buf(buf1);
	return FALSE;
}

REDIT(redit_mshow)
{
	MOB_INDEX_DATA *pMob;
	vnum_t value;

	if (argument[0] == '\0')
	{
		chprintln(ch, "Syntax:  mshow <vnum>");
		return FALSE;
	}

	if (!is_number(argument))
	{
		chprintln(ch, "REdit: Ingresa un numero.");
		return FALSE;
	}

	if (is_number(argument))
	{
		value = atol(argument);
		if (!(pMob = get_mob_index(value)))
		{
			chprintln(ch, "REdit:  That mobile does not exist.");
			return FALSE;
		}

		ch->desc->pEdit = (void *) pMob;
	}

	medit_show(ch, argument);
	ch->desc->pEdit = (void *) ch->in_room;
	return FALSE;
}

REDIT(redit_oshow)
{
	OBJ_INDEX_DATA *pObj;
	vnum_t value;

	if (argument[0] == '\0')
	{
		chprintln(ch, "Syntax:  oshow <vnum>");
		return FALSE;
	}

	if (!is_number(argument))
	{
		chprintln(ch, "REdit: Ingresa un numero.");
		return FALSE;
	}

	if (is_number(argument))
	{
		value = atol(argument);
		if (!(pObj = get_obj_index(value)))
		{
			chprintln(ch, "REdit:  That object does not exist.");
			return FALSE;
		}

		ch->desc->pEdit = (void *) pObj;
	}

	oedit_show(ch, argument);
	ch->desc->pEdit = (void *) ch->in_room;
	return FALSE;
}

/*****************************************************************************
 Name:		check_range( lower vnum, upper vnum )
 Purpose:	Ensures the range spans only one area.
 Called by:	aedit_vnum(olc_act.c).
 ****************************************************************************/
bool check_range(long lower, long upper)
{
	AREA_DATA *pArea;
	int cnt = 0;

	for (pArea = area_first; pArea; pArea = pArea->next)
	{
		/*
		 * lower < area < upper
		 */
		if ((lower <= pArea->min_vnum && pArea->min_vnum <= upper) ||
			(lower <= pArea->max_vnum && pArea->max_vnum <= upper))
			++cnt;

		if (cnt > 1)
			return FALSE;
	}
	return TRUE;
}

AREA_DATA *get_vnum_area(vnum_t vnum)
{
	AREA_DATA *pArea;

	for (pArea = area_first; pArea; pArea = pArea->next)
	{
		if (vnum >= pArea->min_vnum && vnum <= pArea->max_vnum)
			return pArea;
	}

	return 0;
}

/*
 * Area Editor Functions.
 */
AEDIT(aedit_show)
{
	AREA_DATA *pArea;

	EDIT_AREA(ch, pArea);

	chprintf(ch, "%s\n\r",
			 stringf(ch, 0, ALIGN_CENTER, "-",
					 FORMATF("[ %s: %s ]", olc_ed_name(ch), olc_ed_vnum(ch))));

	chprintlnf(ch, "Name:     [%5d] %s", pArea->vnum, pArea->name);

#if 0							/* ROM OLC */
	chprintlnf(ch, "Recall:   [%5d] %s", pArea->recall,
			   get_room_index(pArea->recall) ? get_room_index(pArea->recall)->
			   name : "none");
#endif							/* ROM */

	chprintlnf(ch, "File:     %s", pArea->file_name);

	chprintlnf(ch, "Vnums:    [%ld-%ld]", pArea->min_vnum, pArea->max_vnum);

	chprintlnf(ch, "Age:      [%d]", pArea->age);

	chprintlnf(ch, "Players:  [%d]", pArea->nplayer);

	chprintlnf(ch, "Security: [%d]", pArea->security);

	chprintlnf(ch, "Builders: [%s]", pArea->builders);

	chprintlnf(ch, "Credits : [%s]", pArea->credits);

	chprintlnf(ch, "Flags:    [%s]",
			   flag_string(area_flags, pArea->area_flags));
	chprintln(ch, draw_line(ch, NULL, 0));

	return FALSE;
}

AEDIT(aedit_reset)
{
	AREA_DATA *pArea;

	EDIT_AREA(ch, pArea);

	reset_area(pArea);
	chprintln(ch, "Area reset.");

	return FALSE;
}

AEDIT(aedit_create)
{
	AREA_DATA *pArea;

	pArea = new_area();
	add_area(pArea);
	top_area++;
	edit_start(ch, pArea, ED_AREA);
	SET_BIT(pArea->area_flags, AREA_ADDED);
	chprintln(ch, "Area Created.");
	return FALSE;
}

AEDIT(aedit_file)
{
	AREA_DATA *pArea;
	char file[MAX_STRING_LENGTH];
	int i, length;

	EDIT_AREA(ch, pArea);

	one_argument(argument, file);	/* Forces Lowercase */

	if (argument[0] == '\0')
	{
		chprintln(ch, "Syntax:  filename [$file]");
		return FALSE;
	}

	/*
	 * Simple Syntax Check.
	 */
	length = strlen(argument);
	if (length > 8)
	{
		chprintln(ch, "No more than eight characters allowed.");
		return FALSE;
	}

	/*
	 * Allow only letters and numbers.
	 */
	for (i = 0; i < length; i++)
	{
		if (!isalnum(file[i]))
		{
			chprintln(ch, "Only letters and numbers are valid.");
			return FALSE;
		}
	}

	free_string(pArea->file_name);
	strcat(file, ".are");
	pArea->file_name = str_dup(file);

	chprintln(ch, "Filename set.");
	return TRUE;
}

AEDIT(aedit_builder)
{
	AREA_DATA *pArea;
	char name[MAX_STRING_LENGTH];
	char buf[MAX_STRING_LENGTH];

	EDIT_AREA(ch, pArea);

	one_argument(argument, name);

	if (name[0] == '\0')
	{
		chprintln(ch, "Syntax:  builder [$name]  -toggles builder");
		chprintln(ch, "Syntax:  builder All      -allows everyone");
		return FALSE;
	}

	name[0] = UPPER(name[0]);

	if (strstr(pArea->builders, name) != '\0')
	{
		pArea->builders = string_replace(pArea->builders, name, "\0");
		pArea->builders = string_unpad(pArea->builders);

		if (pArea->builders[0] == '\0')
		{
			free_string(pArea->builders);
			pArea->builders = str_dup("None");
		}
		chprintln(ch, "Builder removed.");
		return TRUE;
	}
	else
	{
		buf[0] = '\0';
		if (strstr(pArea->builders, "None") != '\0')
		{
			pArea->builders = string_replace(pArea->builders, "None", "\0");
			pArea->builders = string_unpad(pArea->builders);
		}

		if (pArea->builders[0] != '\0')
		{
			strcat(buf, pArea->builders);
			strcat(buf, " ");
		}
		strcat(buf, name);
		free_string(pArea->builders);
		pArea->builders = string_proper(str_dup(buf));

		chprintln(ch, "Builder added.");
		chprint(ch, pArea->builders);
		return TRUE;
	}

	return FALSE;
}

AEDIT(aedit_vnum)
{
	AREA_DATA *pArea;
	char lower[MAX_STRING_LENGTH];
	char upper[MAX_STRING_LENGTH];
	vnum_t ilower;
	vnum_t iupper;

	EDIT_AREA(ch, pArea);

	argument = one_argument(argument, lower);
	one_argument(argument, upper);

	if (!is_number(lower) || lower[0] == '\0' || !is_number(upper) ||
		upper[0] == '\0')
	{
		chprintln(ch, "Syntax:  vnum [#xlower] [#xupper]");
		return FALSE;
	}

	if ((ilower = atoi(lower)) > (iupper = atoi(upper)))
	{
		chprintln(ch, "AEdit:  Upper must be larger then lower.");
		return FALSE;
	}

	if (!check_range(atol(lower), atol(upper)))
	{
		chprintln(ch, "AEdit:  Range must include only this area.");
		return FALSE;
	}

	if (get_vnum_area(ilower) && get_vnum_area(ilower) != pArea)
	{
		chprintln(ch, "AEdit:  Lower vnum already assigned.");
		return FALSE;
	}

	pArea->min_vnum = ilower;
	chprintln(ch, "Lower vnum set.");

	if (get_vnum_area(iupper) && get_vnum_area(iupper) != pArea)
	{
		chprintln(ch, "AEdit:  Upper vnum already assigned.");
		return TRUE;			/* The lower value has been set. */
	}

	if (iupper > MAX_VNUM)
	{
		chprintlnf(ch, "Vnum can't be higher than %d.", MAX_VNUM);
		return FALSE;
	}

	pArea->max_vnum = iupper;
	chprintln(ch, "Upper vnum set.");

	return TRUE;
}

AEDIT(aedit_lvnum)
{
	AREA_DATA *pArea;
	char lower[MAX_STRING_LENGTH];
	vnum_t ilower;
	vnum_t iupper;

	EDIT_AREA(ch, pArea);

	one_argument(argument, lower);

	if (!is_number(lower) || lower[0] == '\0')
	{
		chprintln(ch, "Syntax:  min_vnum [#xlower]");
		return FALSE;
	}

	if ((ilower = atol(lower)) > (iupper = pArea->max_vnum))
	{
		chprintln(ch, "AEdit:  Value must be less than the max_vnum.");
		return FALSE;
	}

	if (!check_range(ilower, iupper))
	{
		chprintln(ch, "AEdit:  Range must include only this area.");
		return FALSE;
	}

	if (get_vnum_area(ilower) && get_vnum_area(ilower) != pArea)
	{
		chprintln(ch, "AEdit:  Lower vnum already assigned.");
		return FALSE;
	}

	if (ilower > MAX_VNUM)
	{
		chprintlnf(ch, "Vnum can't be higher than %d", MAX_VNUM);
		return FALSE;
	}

	pArea->min_vnum = ilower;
	chprintln(ch, "Lower vnum set.");
	return TRUE;
}

AEDIT(aedit_uvnum)
{
	AREA_DATA *pArea;
	char upper[MAX_STRING_LENGTH];
	vnum_t ilower;
	vnum_t iupper;

	EDIT_AREA(ch, pArea);

	one_argument(argument, upper);

	if (!is_number(upper) || upper[0] == '\0')
	{
		chprintln(ch, "Syntax:  max_vnum [#xupper]");
		return FALSE;
	}

	if ((ilower = pArea->min_vnum) > (iupper = atol(upper)))
	{
		chprintln(ch, "AEdit:  Upper must be larger then lower.");
		return FALSE;
	}

	if (!check_range(ilower, iupper))
	{
		chprintln(ch, "AEdit:  Range must include only this area.");
		return FALSE;
	}

	if (get_vnum_area(iupper) && get_vnum_area(iupper) != pArea)
	{
		chprintln(ch, "AEdit:  Upper vnum already assigned.");
		return FALSE;
	}

	pArea->max_vnum = iupper;
	chprintln(ch, "Upper vnum set.");

	return TRUE;
}

/*
 * Room Editor Functions.
 */
REDIT(redit_show)
{
	ROOM_INDEX_DATA *pRoom;
	char buf[MAX_STRING_LENGTH];
	char buf1[2 * MAX_STRING_LENGTH];
	OBJ_DATA *obj;
	CHAR_DATA *rch;
	int door;
	bool fcnt;
	PROG_LIST *list;

	EDIT_ROOM(ch, pRoom);

	buf1[0] = '\0';

	strcat(buf1,
		   stringf(ch, 0, ALIGN_CENTER, "-",
				   FORMATF("[ %s: %s ]", olc_ed_name(ch), olc_ed_vnum(ch))));
	strcat(buf1, "\n\r");

	sprintf(buf, "Description:\n\r%s", pRoom->description);
	strcat(buf1, buf);

	sprintf(buf, "Name:       [%s]\n\rArea:       [%5d] %s\n\r",
			pRoom->name, pRoom->area->vnum, pRoom->area->name);
	strcat(buf1, buf);

	sprintf(buf, "Vnum:       [%5ld]\n\rSector:     [%s]\n\r", pRoom->vnum,
			flag_string(sector_flags, pRoom->sector_type));
	strcat(buf1, buf);

	sprintf(buf, "Room flags: [%s]\n\r",
			flag_string(room_flags, pRoom->room_flags));
	strcat(buf1, buf);

	if (pRoom->heal_rate != 100 || pRoom->mana_rate != 100)
	{
		sprintf(buf, "Health rec: [%d]\n\rMana rec  : [%d]\n\r",
				pRoom->heal_rate, pRoom->mana_rate);
		strcat(buf1, buf);
	}

	if (pRoom->clan != NULL)
	{
		sprintf(buf, "Clan      : %s\n\r", pRoom->clan->name);
		strcat(buf1, buf);
	}

	if (!IS_NULLSTR(pRoom->owner))
	{
		sprintf(buf, "Owner     : [%s]\n\r", pRoom->owner);
		strcat(buf1, buf);
	}

	if (pRoom->first_extra_descr)
	{
		EXTRA_DESCR_DATA *ed;

		strcat(buf1, "Desc Kwds:  [");
		for (ed = pRoom->first_extra_descr; ed; ed = ed->next)
		{
			strcat(buf1, ed->keyword);
			if (ed->next)
				strcat(buf1, " ");
		}
		strcat(buf1, "]\n\r");
	}

	strcat(buf1, "Characters: [");
	fcnt = FALSE;
	for (rch = pRoom->first_person; rch; rch = rch->next_in_room)
	{
		one_argument(rch->name, buf);
		strcat(buf1, buf);
		strcat(buf1, " ");
		fcnt = TRUE;
	}

	if (fcnt)
	{
		int end;

		end = strlen(buf1) - 1;
		buf1[end] = ']';
		strcat(buf1, "\n\r");
	}
	else
		strcat(buf1, "none]\n\r");

	strcat(buf1, "Objects:    [");
	fcnt = FALSE;
	for (obj = pRoom->first_content; obj; obj = obj->next_content)
	{
		one_argument(obj->name, buf);
		strcat(buf1, buf);
		strcat(buf1, " ");
		fcnt = TRUE;
	}

	if (fcnt)
	{
		int end;

		end = strlen(buf1) - 1;
		buf1[end] = ']';
		strcat(buf1, "\n\r");
	}
	else
		strcat(buf1, "none]\n\r");

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

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

			sprintf(buf, "-%-5s to [%5ld] Key: [%5ld] ",
					capitalize(dir_name[door]),
					pexit->u1.to_room ? pexit->u1.to_room->vnum : 0,	/* ROM OLC */
					pexit->key);
			strcat(buf1, buf);

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

				if (word[0] == '\0')
				{
					int end;

					end = strlen(buf1) - 1;
					buf1[end] = ']';
					strcat(buf1, "\n\r");
					break;
				}

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

			if (pexit->keyword && pexit->keyword[0] != '\0')
			{
				sprintf(buf, "Kwds: [%s]\n\r", pexit->keyword);
				strcat(buf1, buf);
			}
			if (pexit->description && pexit->description[0] != '\0')
			{
				sprintf(buf, "%s", pexit->description);
				strcat(buf1, buf);
			}
		}
	}

	strcat(buf1, draw_line(ch, NULL, 0));
	chprintln(ch, buf1);
	if (pRoom->first_rprog)
	{
		int cnt;

		sprintf(buf, "\n\rROOMPrograms for [%5ld]:", pRoom->vnum);
		chprintln(ch, buf);

		for (cnt = 0, list = pRoom->first_rprog; list; list = list->next)
		{
			if (cnt == 0)
			{
				chprintln(ch, " Number Vnum Trigger Phrase");
				chprintln(ch, " ------ ---- ------- ------");
			}

			chprintlnf(ch, "[%5d] %4ld %7s %s", cnt,
					   list->vnum, prog_type_to_name(list->trig_type),
					   list->trig_phrase);
			cnt++;
		}
	}
	return FALSE;
}

/* Local function. */
bool change_exit(CHAR_DATA * ch, const char *argument, int door)
{
	ROOM_INDEX_DATA *pRoom;
	char command[MAX_INPUT_LENGTH];
	char arg[MAX_INPUT_LENGTH];
	flag_t value;

	EDIT_ROOM(ch, pRoom);

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

		if (!pRoom->exit[door])
		{
			chprintln(ch, "Salida no existe.");
			return FALSE;
		}

		/*
		 * 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.
		 */
		pToRoom = pRoom->exit[door]->u1.to_room;	/* ROM OLC */
		rev = rev_dir[door];

		if (pToRoom->exit[rev] != NULL)
		{
			pToRoom->exit[rev]->rs_flags = pRoom->exit[door]->rs_flags;
			pToRoom->exit[rev]->exit_info = pRoom->exit[door]->exit_info;
		}

		chprintln(ch, "Exit flag toggled.");
		return TRUE;
	}

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

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

	if (command[0] == '?')
	{
		do_oldhelp(ch, "EXIT");
		return FALSE;
	}

	if (!str_cmp(command, "delete"))
	{
		ROOM_INDEX_DATA *pToRoom;
		int rev;				/* ROM OLC */

		if (!pRoom->exit[door])
		{
			chprintln(ch, "REdit:  Cannot delete a null exit.");
			return FALSE;
		}

		/*
		 * Remove ToRoom Exit.
		 */
		rev = rev_dir[door];
		pToRoom = pRoom->exit[door]->u1.to_room;	/* ROM OLC */

		if (pToRoom->exit[rev])
		{
			free_exit(pToRoom->exit[rev]);
			pToRoom->exit[rev] = NULL;
		}

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

		chprintln(ch, "Exit unlinked.");
		return TRUE;
	}

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

		if (arg[0] == '\0' || !is_number(arg))
		{
			chprintln(ch, "Syntax:  [direction] link [vnum]");
			return FALSE;
		}

		value = atol(arg);

		if (!(toRoom = get_room_index(value)))
		{
			chprintln(ch, "REdit:  Cannot link to non-existant room.");
			return FALSE;
		}

		if (!IS_BUILDER(ch, toRoom->area))
		{
			chprintln(ch, "REdit:  Cannot link to that area.");
			return FALSE;
		}

		if (toRoom->exit[rev_dir[door]])
		{
			chprintln(ch, "REdit:  Remote side's exit already exists.");
			return FALSE;
		}

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

		pRoom->exit[door]->u1.to_room = toRoom;
		pRoom->exit[door]->orig_door = door;

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

		chprintln(ch, "Two-way link established.");
		return TRUE;
	}

	if (!str_cmp(command, "dig"))
	{
		char buf[MAX_STRING_LENGTH];

		if (arg[0] == '\0' || !is_number(arg))
		{
			chprintln(ch, "Syntax: [direction] dig <vnum>");
			return FALSE;
		}

		redit_create(ch, arg);
		sprintf(buf, "link %s", arg);
		change_exit(ch, buf, door);
		return TRUE;
	}

	if (!str_cmp(command, "room"))
	{
		ROOM_INDEX_DATA *toRoom;

		if (arg[0] == '\0' || !is_number(arg))
		{
			chprintln(ch, "Syntax:  [direction] room [vnum]");
			return FALSE;
		}

		value = atol(arg);

		if (!(toRoom = get_room_index(value)))
		{
			chprintln(ch, "REdit:  Cannot link to non-existant room.");
			return FALSE;
		}

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

		pRoom->exit[door]->u1.to_room = toRoom;	/* ROM OLC */
		pRoom->exit[door]->orig_door = door;

		chprintln(ch, "One-way link established.");
		return TRUE;
	}

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

		if (arg[0] == '\0' || !is_number(arg))
		{
			chprintln(ch, "Syntax:  [direction] key [vnum]");
			return FALSE;
		}

		if (!pRoom->exit[door])
		{
			chprintln(ch, "Salida no existe.");
			return FALSE;
		}

		value = atol(arg);

		if (!(key = get_obj_index(value)))
		{
			chprintln(ch, "REdit:  Key doesn't exist.");
			return FALSE;
		}

		if (key->item_type != ITEM_KEY)
		{
			chprintln(ch, "REdit:  Objeto no es llave.");
			return FALSE;
		}

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

		chprintln(ch, "Exit key set.");
		return TRUE;
	}

	if (!str_cmp(command, "name"))
	{
		if (arg[0] == '\0')
		{
			chprintln(ch, "Syntax:  [direction] name [string]");
			chprintln(ch, "         [direction] name none");
			return FALSE;
		}

		if (!pRoom->exit[door])
		{
			chprintln(ch, "Salida no existe.");
			return FALSE;
		}

		free_string(pRoom->exit[door]->keyword);

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

		chprintln(ch, "Exit name set.");
		return TRUE;
	}

	if (!str_prefix(command, "description"))
	{
		if (arg[0] == '\0')
		{
			if (!pRoom->exit[door])
			{
				chprintln(ch, "Salida no existe.");
				return FALSE;
			}

			string_append(ch, &pRoom->exit[door]->description);
			return TRUE;
		}

		chprintln(ch, "Syntax:  [direction] desc");
		return FALSE;
	}

	return FALSE;
}

REDIT(redit_create)
{
	AREA_DATA *pArea;
	ROOM_INDEX_DATA *pRoom;
	vnum_t value;
	int iHash;

	EDIT_ROOM(ch, pRoom);

	value = atol(argument);

	if (argument[0] == '\0' || value <= 0)
	{
		chprintln(ch, "Syntax:  create [vnum > 0]");
		return FALSE;
	}

	pArea = get_vnum_area(value);
	if (!pArea)
	{
		chprintln(ch, "REdit:  That vnum is not assigned an area.");
		return FALSE;
	}

	if (!IS_BUILDER(ch, pArea))
	{
		chprintln(ch, "REdit:  Vnum in an area you cannot build in.");
		return FALSE;
	}

	if (get_room_index(value))
	{
		chprintln(ch, "REdit:  Room vnum already exists.");
		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;
	LINK_SINGLE(pRoom, next, room_index_hash[iHash]);
	edit_start(ch, pRoom, ED_ROOM);
	chprintln(ch, "Room created.");
	return TRUE;
}

REDIT(redit_clan)
{
	ROOM_INDEX_DATA *pRoom;

	EDIT_ROOM(ch, pRoom);

	pRoom->clan = clan_lookup(argument);

	chprintln(ch, "Clan set.");
	return TRUE;
}

REDIT(redit_mreset)
{
	ROOM_INDEX_DATA *pRoom;
	MOB_INDEX_DATA *pMobIndex;
	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);
	argument = one_argument(argument, arg2);

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

	if (!(pMobIndex = get_mob_index(atol(arg))))
	{
		chprintln(ch, "REdit: No mobile has that vnum.");
		return FALSE;
	}

	if (pMobIndex->area != pRoom->area)
	{
		chprintln(ch, "REdit: No such mobile in this area.");
		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_mobile(pMobIndex);
	char_to_room(newmob, pRoom);

	chprintlnf(ch,
			   "%s (%ld) has been loaded and added to resets.\n\r"
			   "There will be a maximum of %d loaded to this room.",
			   capitalize(pMobIndex->short_descr), pMobIndex->vnum,
			   pReset->arg2);
	act("$n has created $N!", ch, NULL, newmob, TO_ROOM);
	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},
	{-2, -2}
};

/*****************************************************************************
 Name:		wear_loc
 Purpose:	Returns the location of the bit that matches the count.
 		1 = first match, 2 = second match etc.
 Called by:	oedit_reset(olc_act.c).
 ****************************************************************************/
int wear_loc(flag_t bits, int count)
{
	int flag;

	for (flag = 0; wear_table[flag].wear_bit != -2; flag++)
	{
		if (IS_SET(bits, wear_table[flag].wear_bit) && --count < 1)
			return wear_table[flag].wear_loc;
	}

	return 0;
}

/*****************************************************************************
 Name:		wear_bit
 Purpose:	Converts a wear_loc into a bit.
 Called by:	redit_oreset(olc_act.c).
 ****************************************************************************/
flag_t wear_bit(int loc)
{
	int flag;

	for (flag = 0; wear_table[flag].wear_loc != -2; flag++)
	{
		if (loc == wear_table[flag].wear_loc)
			return wear_table[flag].wear_bit;
	}

	return 0;
}

REDIT(redit_oreset)
{
	ROOM_INDEX_DATA *pRoom;
	OBJ_INDEX_DATA *pObjIndex;
	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);
	argument = one_argument(argument, arg2);

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

	if (!(pObjIndex = get_obj_index(atol(arg1))))
	{
		chprintln(ch, "REdit: No object has that vnum.");
		return FALSE;
	}

	if (pObjIndex->area != pRoom->area)
	{
		chprintln(ch, "REdit: No such object in this area.");
		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_object(pObjIndex, number_fuzzy(olevel));
		obj_to_room(newobj, pRoom);

		chprintlnf(ch,
				   "%s (%ld) has been loaded and added to resets.",
				   capitalize(pObjIndex->short_descr), pObjIndex->vnum);
	}
	else
		/*
		 * Load into object's inventory.
		 */
		if (argument[0] == '\0' &&
			((to_obj = get_obj_list(ch, arg2, pRoom->first_content)) != 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_object(pObjIndex, number_fuzzy(olevel));
		newobj->cost = 0;
		obj_to_obj(newobj, to_obj);

		chprintlnf(ch,
				   "%s (%ld) has been loaded into "
				   "%s (%ld) and added to resets.",
				   capitalize(newobj->short_descr),
				   newobj->pIndexData->vnum, to_obj->short_descr,
				   to_obj->pIndexData->vnum);
	}
	else
		/*
		 * Load into mobile's inventory.
		 */
	if ((to_mob = get_char_room(ch, NULL, arg2)) != NULL)
	{
		int pwear_loc = -1;

		/*
		 * Make sure the location on mobile is valid.
		 */
		if ((pwear_loc = flag_value(wear_loc_flags, argument)) == NO_FLAG)
		{
			chprintln(ch, "REdit: Invalid wear_loc.  '? wear-loc'");
			return FALSE;
		}

		/*
		 * Disallow loading a sword(WEAR_WIELD) into WEAR_HEAD.
		 */
		if (!IS_SET(pObjIndex->wear_flags, wear_bit(pwear_loc)))
		{
			chprintlnf(ch, "%s (%ld) has wear flags: [%s]",
					   capitalize(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, pwear_loc))
		{
			chprintln(ch, "REdit:  Object already equipped.");
			return FALSE;
		}

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

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

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

		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_object(pObjIndex, olevel);
			if (pReset->arg2 == WEAR_NONE)
				SET_BIT(newobj->extra_flags, ITEM_INVENTORY);
		}
		else
			newobj = create_object(pObjIndex, number_fuzzy(olevel));

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

		chprintlnf(ch,
				   "%s (%ld) has been loaded "
				   "%s of %s (%ld) and added to resets.",
				   capitalize(pObjIndex->short_descr), pObjIndex->vnum,
				   flag_string(wear_loc_strings, pReset->arg3),
				   to_mob->short_descr, to_mob->pIndexData->vnum);
	}
	else						/* Display Syntax */
	{
		chprintln(ch, "REdit:  That mobile isn't here.");
		return FALSE;
	}

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

/*
 * Object Editor Functions.
 */
void show_obj_values(CHAR_DATA * ch, OBJ_INDEX_DATA * obj)
{
	switch (obj->item_type)
	{
	default:					/* No values. */
		break;

	case ITEM_LIGHT:
		if (obj->value[2] == -1 || obj->value[2] == 999)	/* ROM OLC */
			chprintln(ch, "[v2] Light:  Infinite[-1]");
		else
			chprintlnf(ch, "[v2] Light:  [%ld]", obj->value[2]);
		break;

	case ITEM_WAND:
	case ITEM_STAFF:
		chprintlnf(ch,
				   "[v0] Level:          [%ld]\n\r"
				   "[v1] Charges Total:  [%ld]\n\r"
				   "[v2] Charges Left:   [%ld]\n\r"
				   "[v3] Spell:          %s", obj->value[0],
				   obj->value[1], obj->value[2],
				   obj->value[3] !=
				   -1 ? skill_table[obj->value[3]].name : "none");
		break;

	case ITEM_PORTAL:
		chprintlnf(ch,
				   "[v0] Charges:        [%ld]\n\r"
				   "[v1] Exit Flags:     %s\n\r"
				   "[v2] Portal Flags:   %s\n\r"
				   "[v3] Goes to (vnum): [%ld]", obj->value[0],
				   flag_string(exit_flags, obj->value[1]),
				   flag_string(portal_flags, obj->value[2]), obj->value[3]);
		break;

	case ITEM_FURNITURE:
		chprintlnf(ch,
				   "[v0] Max people:      [%ld]\n\r"
				   "[v1] Max weight:      [%ld]\n\r"
				   "[v2] Furniture Flags: %s\n\r"
				   "[v3] Heal bonus:      [%ld]\n\r"
				   "[v4] Mana bonus:      [%ld]", obj->value[0],
				   obj->value[1], flag_string(furniture_flags,
											  obj->value[2]),
				   obj->value[3], obj->value[4]);
		break;

	case ITEM_SCROLL:
	case ITEM_POTION:
	case ITEM_PILL:
		chprintlnf(ch,
				   "[v0] Level:  [%ld]\n\r" "[v1] Spell:  %s\n\r"
				   "[v2] Spell:  %s\n\r" "[v3] Spell:  %s\n\r"
				   "[v4] Spell:  %s", obj->value[0],
				   obj->value[1] !=
				   -1 ? skill_table[obj->value[1]].name : "none",
				   obj->value[2] !=
				   -1 ? skill_table[obj->value[2]].name : "none",
				   obj->value[3] !=
				   -1 ? skill_table[obj->value[3]].name : "none",
				   obj->value[4] !=
				   -1 ? skill_table[obj->value[4]].name : "none");
		break;

/* ARMOR for ROM */

	case ITEM_ARMOR:
		chprintlnf(ch,
				   "[v0] Ac pierce       [%ld]\n\r"
				   "[v1] Ac bash         [%ld]\n\r"
				   "[v2] Ac slash        [%ld]\n\r"
				   "[v3] Ac exotic       [%ld]", obj->value[0],
				   obj->value[1], obj->value[2], obj->value[3]);
		break;

/* WEAPON changed in ROM: */
/* I had to split the output here, I have no idea why, but it helped -- Hugin */
/* It somehow fixed a bug in showing scroll/pill/potions too ?! */
	case ITEM_WEAPON:
		chprintlnf(ch, "[v0] Weapon class:   %s",
				   flag_string(weapon_class, obj->value[0]));
		chprintlnf(ch, "[v1] Number of dice: [%ld]", obj->value[1]);
		chprintlnf(ch, "[v2] Type of dice:   [%ld]", obj->value[2]);
		chprintlnf(ch, "[v3] Type:           %s",
				   attack_table[obj->value[3]].name);
		chprintlnf(ch, "[v4] Special type:   %s",
				   flag_string(weapon_type2, obj->value[4]));
		break;

	case ITEM_CONTAINER:
		chprintlnf(ch,
				   "[v0] Weight:     [%ld kg]\n\r"
				   "[v1] Flags:      [%s]\n\r" "[v2] Key:     %s [%ld]\n\r"
				   "[v3] Capacity    [%ld]\n\r"
				   "[v4] Weight Mult [%ld]", obj->value[0],
				   flag_string(container_flags, obj->value[1]),
				   get_obj_index(obj->value[2]) ? get_obj_index(obj->value
																[2])->short_descr
				   : "none", obj->value[2], obj->value[3], obj->value[4]);
		break;

	case ITEM_DRINK_CON:
		chprintlnf(ch,
				   "[v0] Liquid Total: [%ld]\n\r"
				   "[v1] Liquid Left:  [%ld]\n\r"
				   "[v2] Liquid:       %s\n\r" "[v3] Poisoned:     %s",
				   obj->value[0], obj->value[1],
				   liq_table[obj->value[2]].liq_name,
				   obj->value[3] != 0 ? "Yes" : "No");
		break;

	case ITEM_FOUNTAIN:
		chprintlnf(ch,
				   "[v0] Liquid Total: [%ld]\n\r"
				   "[v1] Liquid Left:  [%ld]\n\r"
				   "[v2] Liquid:	    %s", obj->value[0],
				   obj->value[1], liq_table[obj->value[2]].liq_name);
		break;

	case ITEM_FOOD:
		chprintlnf(ch,
				   "[v0] Food hours: [%ld]\n\r"
				   "[v1] Full hours: [%ld]\n\r" "[v3] Poisoned:   %s",
				   obj->value[0], obj->value[1],
				   obj->value[3] != 0 ? "Yes" : "No");
		break;

	case ITEM_MONEY:
		chprintlnf(ch, "[v0] Gold:   [%ld]", obj->value[0]);
		break;
	}

	return;
}

bool set_obj_values(CHAR_DATA * ch, OBJ_INDEX_DATA * pObj, int value_num,
					const char *argument)
{
	switch (pObj->item_type)
	{
	default:
		break;

	case ITEM_LIGHT:
		switch (value_num)
		{
		default:
			do_oldhelp(ch, "ITEM_LIGHT");
			return FALSE;
		case 2:
			chprintln(ch, "HOURS OF LIGHT SET.\n\r");
			pObj->value[2] = atol(argument);
			break;
		}
		break;

	case ITEM_WAND:
	case ITEM_STAFF:
		switch (value_num)
		{
		default:
			do_oldhelp(ch, "ITEM_STAFF_WAND");
			return FALSE;
		case 0:
			chprintln(ch, "SPELL LEVEL SET.\n\r");
			pObj->value[0] = atol(argument);
			break;
		case 1:
			chprintln(ch, "TOTAL NUMBER OF CHARGES SET.\n\r");
			pObj->value[1] = atol(argument);
			break;
		case 2:
			chprintln(ch, "CURRENT NUMBER OF CHARGES SET.\n\r");
			pObj->value[2] = atol(argument);
			break;
		case 3:
			chprintln(ch, "SPELL TYPE SET.");
			pObj->value[3] = skill_lookup(argument);
			break;
		}
		break;

	case ITEM_SCROLL:
	case ITEM_POTION:
	case ITEM_PILL:
		switch (value_num)
		{
		default:
			do_oldhelp(ch, "ITEM_SCROLL_POTION_PILL");
			return FALSE;
		case 0:
			chprintln(ch, "SPELL LEVEL SET.\n\r");
			pObj->value[0] = atol(argument);
			break;
		case 1:
			chprintln(ch, "SPELL TYPE 1 SET.\n\r");
			pObj->value[1] = skill_lookup(argument);
			break;
		case 2:
			chprintln(ch, "SPELL TYPE 2 SET.\n\r");
			pObj->value[2] = skill_lookup(argument);
			break;
		case 3:
			chprintln(ch, "SPELL TYPE 3 SET.\n\r");
			pObj->value[3] = skill_lookup(argument);
			break;
		case 4:
			chprintln(ch, "SPELL TYPE 4 SET.\n\r");
			pObj->value[4] = skill_lookup(argument);
			break;
		}
		break;

/* ARMOR for ROM: */

	case ITEM_ARMOR:
		switch (value_num)
		{
		default:
			do_oldhelp(ch, "ITEM_ARMOR");
			return FALSE;
		case 0:
			chprintln(ch, "AC PIERCE SET.\n\r");
			pObj->value[0] = atol(argument);
			break;
		case 1:
			chprintln(ch, "AC BASH SET.\n\r");
			pObj->value[1] = atol(argument);
			break;
		case 2:
			chprintln(ch, "AC SLASH SET.\n\r");
			pObj->value[2] = atol(argument);
			break;
		case 3:
			chprintln(ch, "AC EXOTIC SET.\n\r");
			pObj->value[3] = atol(argument);
			break;
		}
		break;

/* WEAPONS changed in ROM */

	case ITEM_WEAPON:
		switch (value_num)
		{
		default:
			do_oldhelp(ch, "ITEM_WEAPON");
			return FALSE;
		case 0:
			chprintln(ch, "WEAPON CLASS SET.\n\r");
			ALT_FLAGVALUE_SET(pObj->value[0], weapon_class, argument);
			break;
		case 1:
			chprintln(ch, "NUMBER OF DICE SET.\n\r");
			pObj->value[1] = atol(argument);
			break;
		case 2:
			chprintln(ch, "TYPE OF DICE SET.\n\r");
			pObj->value[2] = atol(argument);
			break;
		case 3:
			chprintln(ch, "WEAPON TYPE SET.\n\r");
			pObj->value[3] = attack_lookup(argument);
			break;
		case 4:
			chprintln(ch, "SPECIAL WEAPON TYPE TOGGLED.\n\r");
			ALT_FLAGVALUE_TOGGLE(pObj->value[4], weapon_type2, argument);
			break;
		}
		break;

	case ITEM_PORTAL:
		switch (value_num)
		{
		default:
			do_oldhelp(ch, "ITEM_PORTAL");
			return FALSE;

		case 0:
			chprintln(ch, "CHARGES SET.\n\r");
			pObj->value[0] = atol(argument);
			break;
		case 1:
			chprintln(ch, "EXIT FLAGS SET.\n\r");
			ALT_FLAGVALUE_SET(pObj->value[1], exit_flags, argument);
			break;
		case 2:
			chprintln(ch, "PORTAL FLAGS SET.\n\r");
			ALT_FLAGVALUE_SET(pObj->value[2], portal_flags, argument);
			break;
		case 3:
			chprintln(ch, "EXIT vnum_t SET.\n\r");
			pObj->value[3] = atol(argument);
			break;
		}
		break;

	case ITEM_FURNITURE:
		switch (value_num)
		{
		default:
			do_oldhelp(ch, "ITEM_FURNITURE");
			return FALSE;

		case 0:
			chprintln(ch, "NUMBER OF PEOPLE SET.\n\r");
			pObj->value[0] = atol(argument);
			break;
		case 1:
			chprintln(ch, "MAX WEIGHT SET.\n\r");
			pObj->value[1] = atol(argument);
			break;
		case 2:
			chprintln(ch, "FURNITURE FLAGS TOGGLED.\n\r");
			ALT_FLAGVALUE_TOGGLE(pObj->value[2], furniture_flags, argument);
			break;
		case 3:
			chprintln(ch, "HEAL BONUS SET.\n\r");
			pObj->value[3] = atol(argument);
			break;
		case 4:
			chprintln(ch, "MANA BONUS SET.\n\r");
			pObj->value[4] = atol(argument);
			break;
		}
		break;

	case ITEM_CONTAINER:
		switch (value_num)
		{
			flag_t value;

		default:
			do_oldhelp(ch, "ITEM_CONTAINER");
			return FALSE;
		case 0:
			chprintln(ch, "WEIGHT CAPACITY SET.\n\r");
			pObj->value[0] = atol(argument);
			break;
		case 1:
			if ((value = flag_value(container_flags, argument)) != NO_FLAG)
				TOGGLE_BIT(pObj->value[1], value);
			else
			{
				do_oldhelp(ch, "ITEM_CONTAINER");
				return FALSE;
			}
			chprintln(ch, "CONTAINER TYPE SET.\n\r");
			break;
		case 2:
			if (atol(argument) != 0)
			{
				if (!get_obj_index(atol(argument)))
				{
					chprintln(ch, "THERE IS NO SUCH ITEM.\n\r");
					return FALSE;
				}

				if (get_obj_index(atol(argument))->item_type != ITEM_KEY)
				{
					chprintln(ch, "THAT ITEM IS NOT A KEY.\n\r");
					return FALSE;
				}
			}
			chprintln(ch, "CONTAINER KEY SET.\n\r");
			pObj->value[2] = atol(argument);
			break;
		case 3:
			chprintln(ch, "CONTAINER MAX WEIGHT SET.");
			pObj->value[3] = atol(argument);
			break;
		case 4:
			chprintln(ch, "WEIGHT MULTIPLIER SET.\n\r");
			pObj->value[4] = atol(argument);
			break;
		}
		break;

	case ITEM_DRINK_CON:
		switch (value_num)
		{
		default:
			do_oldhelp(ch, "ITEM_DRINK");
/* OLC		    do_oldhelp( ch, "liquids" );    */
			return FALSE;
		case 0:
			chprintln(ch, "MAXIMUM AMOUT OF LIQUID HOURS SET.\n\r");
			pObj->value[0] = atol(argument);
			break;
		case 1:
			chprintln(ch, "CURRENT AMOUNT OF LIQUID HOURS SET.\n\r");
			pObj->value[1] = atol(argument);
			break;
		case 2:
			chprintln(ch, "LIQUID TYPE SET.\n\r");
			pObj->value[2] =
				(liq_lookup(argument) != -1 ? liq_lookup(argument) : 0);
			break;
		case 3:
			chprintln(ch, "POISON VALUE TOGGLED.\n\r");
			pObj->value[3] = (pObj->value[3] == 0) ? 1 : 0;
			break;
		}
		break;

	case ITEM_FOUNTAIN:
		switch (value_num)
		{
		default:
			do_oldhelp(ch, "ITEM_FOUNTAIN");
/* OLC		    do_oldhelp( ch, "liquids" );    */
			return FALSE;
		case 0:
			chprintln(ch, "MAXIMUM AMOUT OF LIQUID HOURS SET.\n\r");
			pObj->value[0] = atol(argument);
			break;
		case 1:
			chprintln(ch, "CURRENT AMOUNT OF LIQUID HOURS SET.\n\r");
			pObj->value[1] = atol(argument);
			break;
		case 2:
			chprintln(ch, "LIQUID TYPE SET.\n\r");
			pObj->value[2] =
				(liq_lookup(argument) != -1 ? liq_lookup(argument) : 0);
			break;
		}
		break;

	case ITEM_FOOD:
		switch (value_num)
		{
		default:
			do_oldhelp(ch, "ITEM_FOOD");
			return FALSE;
		case 0:
			chprintln(ch, "HOURS OF FOOD SET.\n\r");
			pObj->value[0] = atol(argument);
			break;
		case 1:
			chprintln(ch, "HOURS OF FULL SET.\n\r");
			pObj->value[1] = atol(argument);
			break;
		case 3:
			chprintln(ch, "POISON VALUE TOGGLED.\n\r");
			pObj->value[3] = (pObj->value[3] == 0) ? 1 : 0;
			break;
		}
		break;

	case ITEM_MONEY:
		switch (value_num)
		{
		default:
			do_oldhelp(ch, "ITEM_MONEY");
			return FALSE;
		case 0:
			chprintln(ch, "GOLD AMOUNT SET.\n\r");
			pObj->value[0] = atol(argument);
			break;
		case 1:
			chprintln(ch, "SILVER AMOUNT SET.\n\r");
			pObj->value[1] = atol(argument);
			break;
		}
		break;
	}

	show_obj_values(ch, pObj);

	return TRUE;
}

OEDIT(oedit_show)
{
	OBJ_INDEX_DATA *pObj;
	AFFECT_DATA *paf;
	int cnt;
	PROG_LIST *list;

	EDIT_OBJ(ch, pObj);

	chprintf(ch, "%s\n\r",
			 stringf(ch, 0, ALIGN_CENTER, "-",
					 FORMATF("[ %s: %s ]", olc_ed_name(ch), olc_ed_vnum(ch))));

	chprintlnf(ch, "Name:        [%s]\n\rArea:        [%5d] %s",
			   pObj->name, !pObj->area ? -1 : pObj->area->vnum,
			   !pObj->area ? "No Area" : pObj->area->name);

	chprintlnf(ch, "Vnum:        [%5ld]\n\rType:        [%s]", pObj->vnum,
			   flag_string(type_flags, pObj->item_type));

	chprintlnf(ch, "Level:       [%5d]", pObj->level);

	chprintlnf(ch, "Wear flags:  [%s]",
			   flag_string(wear_flags, pObj->wear_flags));

	chprintlnf(ch, "Extra flags: [%s]",
			   flag_string(extra_flags, pObj->extra_flags));

	chprintlnf(ch, "Material:    [%s]",	/* ROM */
			   pObj->material);

	chprintlnf(ch, "Condition:   [%5d]",	/* ROM */
			   pObj->condition);

	chprintlnf(ch, "Weight:      [%5d]\n\rCost:        [%5d]",
			   pObj->weight, pObj->cost);

	if (pObj->first_extra_descr)
	{
		EXTRA_DESCR_DATA *ed;

		chprint(ch, "Ex desc kwd: ");

		for (ed = pObj->first_extra_descr; ed; ed = ed->next)
		{
			chprint(ch, "[");
			chprint(ch, ed->keyword);
			chprint(ch, "]");
		}

		chprintln(ch, "");
	}

	chprintlnf(ch, "Short desc:  %s\n\rLong desc:\n\r     %s",
			   pObj->short_descr, pObj->description);

	for (cnt = 0, paf = pObj->first_affect; paf; paf = paf->next)
	{
		if (cnt == 0)
		{
			chprintln(ch, "Number Modifier Affects");
			chprintln(ch, "------ -------- -------");
		}
		chprintlnf(ch, "[%4d] %-8d %s", cnt, paf->modifier,
				   flag_string(apply_flags, paf->location));
		cnt++;
	}

	show_obj_values(ch, pObj);

	chprintln(ch, draw_line(ch, NULL, 0));
	if (pObj->first_oprog)
	{
		int cnt;

		chprintlnf(ch, "\n\rOBJPrograms for [%5ld]:", pObj->vnum);

		for (cnt = 0, list = pObj->first_oprog; list; list = list->next)
		{
			if (cnt == 0)
			{
				chprintln(ch, " Number Vnum Trigger Phrase");
				chprintln(ch, " ------ ---- ------- ------");
			}

			chprintlnf(ch, "[%5d] %4ld %7s %s", cnt,
					   list->vnum, prog_type_to_name(list->trig_type),
					   list->trig_phrase);
			cnt++;
		}
	}
	return FALSE;
}

/*
 * Need to issue warning if flag_t isn't valid. -- does so now -- Hugin.
 */
OEDIT(oedit_addaffect)
{
	int value;
	OBJ_INDEX_DATA *pObj;
	AFFECT_DATA *pAf;
	char loc[MAX_STRING_LENGTH];
	char mod[MAX_STRING_LENGTH];

	EDIT_OBJ(ch, pObj);

	argument = one_argument(argument, loc);
	one_argument(argument, mod);

	if (loc[0] == '\0' || mod[0] == '\0' || !is_number(mod))
	{
		chprintln(ch, "Syntax:  addaffect [location] [#xmod]");
		return FALSE;
	}

	if ((value = flag_value(apply_flags, loc)) == NO_FLAG)	/* Hugin */
	{
		chprintln(ch, "Valid affects are:");
		show_help(ch, "apply");
		return FALSE;
	}

	pAf = new_affect();
	pAf->location = value;
	pAf->modifier = atoi(mod);
	pAf->where = TO_OBJECT;
	pAf->type = -1;
	pAf->duration = -1;
	pAf->bitvector = 0;
	pAf->level = pObj->level;
	LINK(pAf, pObj->first_affect, pObj->last_affect, next, prev);

	chprintln(ch, "Affect added.");
	return TRUE;
}

OEDIT(oedit_delete)
{
	OBJ_DATA *obj, *obj_next;
	OBJ_INDEX_DATA *pObj;
	RESET_DATA *pReset, *wReset;
	ROOM_INDEX_DATA *pRoom;
	char arg[MIL];
	vnum_t pIndex, i;
	int rcount, ocount, iHash;

	if (IS_NULLSTR(argument))
	{
		if (ch)
			chprintln(ch, "Syntax:  oedit delete [vnum]");
		return FALSE;
	}

	one_argument(argument, arg);

	if (is_number(arg))
	{
		pIndex = atol(arg);
		pObj = get_obj_index(pIndex);
	}
	else
	{
		if (ch)
			chprintln(ch, "That is not a number.");
		return FALSE;
	}

	for (i = 0; vnum_table[i].vnum != -1; i++)
	{
		if (vnum_table[i].type != VNUM_OBJ)
			continue;

		if (vnum_table[i].vnum == pIndex)
		{
			if (ch)
				chprintln(ch, "That vnum is reserved.");
			return FALSE;
		}
	}

	if (!pObj)
	{
		if (ch)
			chprintln(ch, "No such object.");
		return FALSE;
	}

	stop_editing(pObj);

	SET_BIT(pObj->area->area_flags, AREA_CHANGED);

	if (top_vnum_obj == pIndex)
		for (i = 1; i < pIndex; i++)
			if (get_obj_index(i))
				top_vnum_obj = i;

	top_obj_index--;

	ocount = 0;
	for (obj = object_first; obj; obj = obj_next)
	{
		obj_next = obj->next;

		if (obj->pIndexData == pObj)
		{
			extract_obj(obj);
			ocount++;
		}
	}

	rcount = 0;
	for (iHash = 0; iHash < MAX_KEY_HASH; iHash++)
	{
		for (pRoom = room_index_hash[iHash]; pRoom; pRoom = pRoom->next)
		{
			for (pReset = pRoom->reset_first; pReset; pReset = wReset)
			{
				wReset = pReset->next;
				switch (pReset->command)
				{
				case 'O':
				case 'E':
				case 'P':
				case 'G':
					if ((pReset->arg1 == pIndex) ||
						((pReset->command == 'P') && (pReset->arg3 == pIndex)))
					{
						unlink_reset(pRoom, pReset);
						free_reset_data(pReset);

						rcount++;
						SET_BIT(pRoom->area->area_flags, AREA_CHANGED);

					}
				}
			}
		}
	}

	unlink_obj_index(pObj);

	pObj->area = NULL;
	pObj->vnum = 0;

	free_obj_index(pObj);

	if (ch)
	{
		chprintf(ch,
				 "Removed object vnum {C%ld{x and" " {C%d{x resets.\n\r",
				 pIndex, rcount);

		chprintf(ch,
				 "{C%d{x occurences of the object"
				 " were extracted from the mud.\n\r", ocount);

	}
	return TRUE;
}

OEDIT(oedit_addapply)
{
	int value, typ;
	flag_t bv;
	OBJ_INDEX_DATA *pObj;
	AFFECT_DATA *pAf;
	char loc[MAX_STRING_LENGTH];
	char mod[MAX_STRING_LENGTH];
	char type[MAX_STRING_LENGTH];
	char bvector[MAX_STRING_LENGTH];

	EDIT_OBJ(ch, pObj);

	argument = one_argument(argument, type);
	argument = one_argument(argument, loc);
	argument = one_argument(argument, mod);
	one_argument(argument, bvector);

	if (type[0] == '\0' || (typ = flag_value(apply_types, type)) == NO_FLAG)
	{
		chprintln(ch, "Invalid apply type. Valid apply types are:");
		show_help(ch, "apptype");
		return FALSE;
	}

	if (loc[0] == '\0' || (value = flag_value(apply_flags, loc)) == NO_FLAG)
	{
		chprintln(ch, "Valid applys are:");
		show_help(ch, "apply");
		return FALSE;
	}

	if (bvector[0] == '\0' ||
		(bv = flag_value(bitvector_type[typ].table, bvector)) == NO_FLAG)
	{
		chprintln(ch, "Invalid bitvector type.");
		chprintln(ch, "Valid bitvector types are:");
		show_help(ch, bitvector_type[typ].help);
		return FALSE;
	}

	if (mod[0] == '\0' || !is_number(mod))
	{
		chprintln(ch,
				  "Syntax:  addapply [type] [location] [#xmod] [bitvector]");
		return FALSE;
	}

	pAf = new_affect();
	pAf->location = value;
	pAf->modifier = atoi(mod);
	pAf->where = apply_types[typ].bit;
	pAf->type = -1;
	pAf->duration = -1;
	pAf->bitvector = bv;
	pAf->level = pObj->level;
	LINK(pAf, pObj->first_affect, pObj->last_affect, next, prev);

	chprintln(ch, "Apply added.");
	return TRUE;
}

/*
 * My thanks to Hans Hvidsten Birkeland and Noam Krendel(Walker)
 * for really teaching me how to manipulate pointers.
 */
OEDIT(oedit_delaffect)
{
	OBJ_INDEX_DATA *pObj;
	AFFECT_DATA *pAf;
	char affect[MAX_STRING_LENGTH];
	int value;
	int cnt = 0;

	EDIT_OBJ(ch, pObj);

	one_argument(argument, affect);

	if (!is_number(affect) || affect[0] == '\0')
	{
		chprintln(ch, "Syntax:  delaffect [#xaffect]");
		return FALSE;
	}

	value = atoi(affect);

	if (value < 0)
	{
		chprintln(ch, "Only non-negative affect-numbers allowed.");
		return FALSE;
	}

	for (pAf = pObj->first_affect; pAf != NULL; pAf = pAf->next)
		if (++cnt == value)
			break;

	if (!pAf)
	{
		chprintln(ch, "OEdit:  Non-existant affect.");
		return FALSE;
	}

	UNLINK(pAf, pObj->first_affect, pObj->last_affect, next, prev);
	free_affect(pAf);

	chprintln(ch, "Affect removed.");
	return TRUE;
}

bool set_value(CHAR_DATA * ch, OBJ_INDEX_DATA * pObj, const char *argument,
			   int value)
{
	if (argument[0] == '\0')
	{
		set_obj_values(ch, pObj, -1, "");	/* '\0' changed to "" -- Hugin */
		return FALSE;
	}

	if (set_obj_values(ch, pObj, value, argument))
		return TRUE;

	return FALSE;
}

/*****************************************************************************
 Name:		oedit_values
 Purpose:	Finds the object and sets its value.
 Called by:	The four valueX functions below. (now five -- Hugin )
 ****************************************************************************/
bool oedit_values(CHAR_DATA * ch, const char *argument, int value)
{
	OBJ_INDEX_DATA *pObj;

	EDIT_OBJ(ch, pObj);

	if (set_value(ch, pObj, argument, value))
		return TRUE;

	return FALSE;
}

OEDIT(oedit_create)
{
	OBJ_INDEX_DATA *pObj;
	AREA_DATA *pArea;
	vnum_t value;
	int iHash;

	value = atol(argument);
	if (argument[0] == '\0' || value == 0)
	{
		chprintln(ch, "Syntax:  oedit create [vnum]");
		return FALSE;
	}

	pArea = get_vnum_area(value);
	if (!pArea)
	{
		chprintln(ch, "OEdit:  That vnum is not assigned an area.");
		return FALSE;
	}

	if (!IS_BUILDER(ch, pArea))
	{
		chprintln(ch, "OEdit:  Vnum in an area you cannot build in.");
		return FALSE;
	}

	if (get_obj_index(value))
	{
		chprintln(ch, "OEdit:  Object vnum already exists.");
		return FALSE;
	}

	pObj = new_obj_index();
	pObj->vnum = value;
	pObj->area = pArea;

	if (value > top_vnum_obj)
		top_vnum_obj = value;

	iHash = value % MAX_KEY_HASH;
	LINK_SINGLE(pObj, next, obj_index_hash[iHash]);
	edit_start(ch, pObj, ED_OBJECT);
	chprintln(ch, "Object Created.");
	return TRUE;
}

/*
 * Mobile Editor Functions.
 */
MEDIT(medit_show)
{
	MOB_INDEX_DATA *pMob;
	PROG_LIST *list;

	EDIT_MOB(ch, pMob);

	chprintf(ch, "%s\n\r",
			 stringf(ch, 0, ALIGN_CENTER, "-",
					 FORMATF("[ %s: %s ]", olc_ed_name(ch), olc_ed_vnum(ch))));

	chprintlnf(ch, "Name:        [%s]\n\rArea:        [%5d] %s",
			   pMob->player_name, !pMob->area ? -1 : pMob->area->vnum,
			   !pMob->area ? "No Area" : pMob->area->name);

	chprintlnf(ch, "Act:         [%s]", flag_string(act_flags, pMob->act));

	chprintlnf(ch, "Vnum:        [%5ld] Sex:   [%s]   Race: [%s]",
			   pMob->vnum,
			   pMob->sex == SEX_MALE ? "male   " : pMob->sex ==
			   SEX_FEMALE ? "female " : pMob->sex ==
			   3 ? "random " : "neutral", pMob->race->name);

	chprintlnf(ch,
			   "Level:       [%2d]    Align: [%4d]      Hitroll: [%2d] Dam Type:    [%s]",
			   pMob->level, pMob->alignment, pMob->hitroll,
			   attack_table[pMob->dam_type].name);

	if (pMob->group)
	{
		chprintlnf(ch, "Group:       [%5ld]", pMob->group);
	}

	chprintf(ch, "Hit dice:    [%2dd%-3d+%4d] ", pMob->hit[DICE_NUMBER],
			 pMob->hit[DICE_TYPE], pMob->hit[DICE_BONUS]);

	chprintf(ch, "Damage dice: [%2dd%-3d+%4d] ", pMob->damage[DICE_NUMBER],
			 pMob->damage[DICE_TYPE], pMob->damage[DICE_BONUS]);

	chprintlnf(ch, "Mana dice:   [%2dd%-3d+%4d]", pMob->mana[DICE_NUMBER],
			   pMob->mana[DICE_TYPE], pMob->mana[DICE_BONUS]);

/* ROM values end */

	chprintlnf(ch, "Affected by: [%s]",
			   flag_string(affect_flags, pMob->affected_by));

/* ROM values: */

	chprintlnf(ch,
			   "Armor:       [pierce: %d  bash: %d  slash: %d  magic: %d]",
			   pMob->ac[AC_PIERCE], pMob->ac[AC_BASH], pMob->ac[AC_SLASH],
			   pMob->ac[AC_EXOTIC]);

	chprintlnf(ch, "Form:        [%s]", flag_string(form_flags, pMob->form));

	chprintlnf(ch, "Parts:       [%s]", flag_string(part_flags, pMob->parts));

	chprintlnf(ch, "Imm:         [%s]",
			   flag_string(imm_flags, pMob->imm_flags));

	chprintlnf(ch, "Res:         [%s]",
			   flag_string(res_flags, pMob->res_flags));

	chprintlnf(ch, "Vuln:        [%s]",
			   flag_string(vuln_flags, pMob->vuln_flags));

	chprintlnf(ch, "Off:         [%s]",
			   flag_string(off_flags, pMob->off_flags));

	chprintlnf(ch, "Size:        [%s]", flag_string(size_flags, pMob->size));

	chprintlnf(ch, "Material:    [%s]", pMob->material);

	chprintlnf(ch, "Start pos.   [%s]",
			   flag_string(position_flags, pMob->start_pos));

	chprintlnf(ch, "Default pos  [%s]",
			   flag_string(position_flags, pMob->default_pos));

	chprintlnf(ch, "Wealth:      [%5ld]", pMob->wealth);

/* ROM values end */

	if (pMob->spec_fun)
	{
		chprintlnf(ch, "Spec fun:    [%s]", spec_name(pMob->spec_fun));
	}

	chprintf(ch, "Short descr: %s\n\rLong descr:\n\r%s", pMob->short_descr,
			 pMob->long_descr);

	chprintf(ch, "Description:\n\r%s", pMob->description);

	if (pMob->pShop)
	{
		SHOP_DATA *pShop;
		int iTrade;

		pShop = pMob->pShop;

		chprintlnf(ch,
				   "Shop data for [%5ld]:\n\r"
				   "  Markup for purchaser: %d%%\n\r"
				   "  Markdown for seller:  %d%%", pShop->keeper,
				   pShop->profit_buy, pShop->profit_sell);
		chprintlnf(ch, "  Hours: %d to %d.", pShop->open_hour,
				   pShop->close_hour);

		for (iTrade = 0; iTrade < MAX_TRADE; iTrade++)
		{
			if (pShop->buy_type[iTrade] != 0)
			{
				if (iTrade == 0)
				{
					chprintln(ch, "  Number Trades Type");
					chprintln(ch, "  ------ -----------");
				}
				chprintlnf(ch, "  [%4d] %s", iTrade,
						   flag_string(type_flags, pShop->buy_type[iTrade]));
			}
		}
	}

	if (pMob->first_mprog)
	{
		int cnt;

		chprintlnf(ch, "\n\rMOBPrograms for [%5ld]:", pMob->vnum);

		for (cnt = 0, list = pMob->first_mprog; list; list = list->next)
		{
			if (cnt == 0)
			{
				chprintln(ch, " Number Vnum Trigger Phrase");
				chprintln(ch, " ------ ---- ------- ------");
			}

			chprintlnf(ch, "[%5d] %4ld %7s %s", cnt, list->vnum,
					   prog_type_to_name(list->trig_type), list->trig_phrase);
			cnt++;
		}
	}

	chprintln(ch, draw_line(ch, NULL, 0));
	return FALSE;
}

MEDIT(medit_create)
{
	MOB_INDEX_DATA *pMob;
	AREA_DATA *pArea;
	vnum_t value;
	int iHash;

	value = atol(argument);
	if (argument[0] == '\0' || value == 0)
	{
		chprintln(ch, "Syntax:  medit create [vnum]");
		return FALSE;
	}

	pArea = get_vnum_area(value);

	if (!pArea)
	{
		chprintln(ch, "MEdit:  That vnum is not assigned an area.");
		return FALSE;
	}

	if (!IS_BUILDER(ch, pArea))
	{
		chprintln(ch, "MEdit:  Vnum in an area you cannot build in.");
		return FALSE;
	}

	if (get_mob_index(value))
	{
		chprintln(ch, "MEdit:  Mobile vnum already exists.");
		return FALSE;
	}

	pMob = new_mob_index();
	pMob->vnum = value;
	pMob->area = pArea;

	if (value > top_vnum_mob)
		top_vnum_mob = value;

	pMob->act = ACT_IS_NPC;
	iHash = value % MAX_KEY_HASH;
	LINK_SINGLE(pMob, next, mob_index_hash[iHash]);
	edit_start(ch, pMob, ED_MOBILE);
	chprintln(ch, "Mobile Created.");
	return TRUE;
}

MEDIT(medit_delete)
{
	CHAR_DATA *wch, *wnext;
	MOB_INDEX_DATA *pMob;
	RESET_DATA *pReset, *wReset;
	ROOM_INDEX_DATA *pRoom;
	char arg[MIL];
	vnum_t pIndex, i;
	int mcount, rcount, iHash;
	bool foundmob = FALSE;
	bool foundobj = FALSE;

	if (IS_NULLSTR(argument))
	{
		if (ch)
			chprintln(ch, "Syntax:  medit delete [vnum]");
		return FALSE;
	}

	one_argument(argument, arg);

	if (is_number(arg))
	{
		pIndex = atol(arg);
		pMob = get_mob_index(pIndex);
	}
	else
	{
		if (ch)
			chprintln(ch, "That is not a number.");
		return FALSE;
	}

	for (i = 0; vnum_table[i].vnum != -1; i++)
	{
		if (vnum_table[i].type != VNUM_MOB)
			continue;

		if (vnum_table[i].vnum == pIndex)
		{
			if (ch)
				chprintln(ch, "That vnum is reserved.");
			return FALSE;
		}
	}

	if (!pMob)
	{
		if (ch)
			chprintln(ch, "No such mobile.");
		return FALSE;
	}

	stop_editing(pMob);

	SET_BIT(pMob->area->area_flags, AREA_CHANGED);

	if (top_vnum_mob == pIndex)
		for (i = 1; i < pIndex; i++)
			if (get_mob_index(i))
				top_vnum_mob = i;

	top_mob_index--;

	rcount = 0;
	mcount = 0;

	for (iHash = 0; iHash < MAX_KEY_HASH; iHash++)
	{
		for (pRoom = room_index_hash[iHash]; pRoom; pRoom = pRoom->next)
		{

			for (wch = pRoom->first_person; wch; wch = wnext)
			{
				wnext = wch->next_in_room;
				if (wch->pIndexData == pMob)
				{
					extract_char(wch, TRUE);
					mcount++;
				}
			}

			for (pReset = pRoom->reset_first; pReset; pReset = wReset)
			{
				wReset = pReset->next;
				switch (pReset->command)
				{
				case 'M':
					if (pReset->arg1 == pIndex)
					{
						foundmob = TRUE;

						unlink_reset(pRoom, pReset);
						free_reset_data(pReset);

						rcount++;
						SET_BIT(pRoom->area->area_flags, AREA_CHANGED);

					}
					else
						foundmob = FALSE;

					break;
				case 'E':
				case 'G':
					if (foundmob)
					{
						foundobj = TRUE;

						unlink_reset(pRoom, pReset);
						free_reset_data(pReset);

						rcount++;
						SET_BIT(pRoom->area->area_flags, AREA_CHANGED);

					}
					else
						foundobj = FALSE;

					break;
				case '0':
					foundobj = FALSE;
					break;
				case 'P':
					if (foundobj && foundmob)
					{
						unlink_reset(pRoom, pReset);
						free_reset_data(pReset);

						rcount++;
						SET_BIT(pRoom->area->area_flags, AREA_CHANGED);
					}
				}
			}
		}
	}

	unlink_mob_index(pMob);

	pMob->area = NULL;
	pMob->vnum = 0;

	free_mob_index(pMob);

	if (ch)
	{
		chprintf(ch,
				 "Removed mobile vnum {C%ld{x and {C%d{x resets.\n\r",
				 pIndex, rcount);
		chprintf(ch,
				 "{C%d{x mobiles were extracted" " from the mud.\n\r", mcount);
	}
	return TRUE;
}

void show_liqlist(CHAR_DATA * ch)
{
	int liq;
	BUFFER *buffer;
	char buf[MAX_STRING_LENGTH];

	buffer = new_buf();

	for (liq = 0; liq_table[liq].liq_name != NULL; liq++)
	{
		if ((liq % 21) == 0)
			add_buf(buffer,
					"Name                 Color          Proof Full Thirst Food Ssize\n\r");

		sprintf(buf, "%-20s %-14s %5d %4d %6d %4d %5d\n\r",
				liq_table[liq].liq_name, liq_table[liq].liq_color,
				liq_table[liq].liq_affect[0],
				liq_table[liq].liq_affect[1],
				liq_table[liq].liq_affect[2],
				liq_table[liq].liq_affect[3], liq_table[liq].liq_affect[4]);
		add_buf(buffer, buf);
	}

	page_to_char(buf_string(buffer), ch);
	free_buf(buffer);

	return;
}

void show_damlist(CHAR_DATA * ch)
{
	int att;
	BUFFER *buffer;
	char buf[MAX_STRING_LENGTH];

	buffer = new_buf();

	for (att = 0; attack_table[att].name != NULL; att++)
	{
		if ((att % 21) == 0)
			add_buf(buffer, "Name                 Noun\n\r");

		sprintf(buf, "%-20s %-20s\n\r", attack_table[att].name,
				attack_table[att].noun);
		add_buf(buffer, buf);
	}

	page_to_char(buf_string(buffer), ch);
	free_buf(buffer);

	return;
}

MEDIT(medit_group)
{
	MOB_INDEX_DATA *pMob;
	MOB_INDEX_DATA *pMTemp;
	char arg[MAX_STRING_LENGTH];
	char buf[MAX_STRING_LENGTH];
	int temp;
	BUFFER *buffer;
	bool found = FALSE;

	EDIT_MOB(ch, pMob);

	if (argument[0] == '\0')
	{
		chprintln(ch, "Syntax: group [number]");
		chprintln(ch, "        group show [number]");
		return FALSE;
	}

	if (is_number(argument))
	{
		pMob->group = atol(argument);
		chprintln(ch, "Group set.");
		return TRUE;
	}

	argument = one_argument(argument, arg);

	if (!str_cmp(arg, "show") && is_number(argument))
	{
		if (atol(argument) == 0)
		{
			chprintln(ch, "Are you crazy?");
			return FALSE;
		}

		buffer = new_buf();

		for (temp = 0; temp < 65536; temp++)
		{
			pMTemp = get_mob_index(temp);
			if (pMTemp && (pMTemp->group == atol(argument)))
			{
				found = TRUE;
				sprintf(buf, "[%5ld] %s\n\r", pMTemp->vnum,
						pMTemp->player_name);
				add_buf(buffer, buf);
			}
		}

		if (found)
			page_to_char(buf_string(buffer), ch);
		else
			chprintln(ch, "No mobs in that group.");

		free_buf(buffer);
		return FALSE;
	}

	return FALSE;
}

MEDIT(medit_addmprog)
{
	flag_t value;
	MOB_INDEX_DATA *pMob;
	PROG_LIST *list;
	PROG_CODE *code;
	char trigger[MAX_STRING_LENGTH];
	char phrase[MAX_STRING_LENGTH];
	char num[MAX_STRING_LENGTH];

	EDIT_MOB(ch, pMob);
	argument = one_argument(argument, num);
	argument = one_argument(argument, trigger);
	argument = one_argument(argument, phrase);

	if (!is_number(num) || trigger[0] == '\0' || phrase[0] == '\0')
	{
		chprintln(ch, "Syntax:   addmprog [vnum] [trigger] [phrase]");
		return FALSE;
	}

	if ((value = flag_value(mprog_flags, trigger)) == NO_FLAG)
	{
		chprintln(ch, "Valid flags are:");
		show_help(ch, "mprog");
		return FALSE;
	}

	if ((code = get_prog_index(atol(num), PRG_MPROG)) == NULL)
	{
		chprintln(ch, "No such MOBProgram.");
		return FALSE;
	}

	list = new_prog();
	list->vnum = atol(num);
	list->trig_type = value;
	list->trig_phrase = str_dup(phrase);
	replace_string(list->code, code->code);
	SET_BIT(pMob->mprog_flags, value);
	LINK(list, pMob->first_mprog, pMob->last_mprog, next, prev);

	chprintln(ch, "Mprog Added.");
	return TRUE;
}

MEDIT(medit_delmprog)
{
	MOB_INDEX_DATA *pMob;
	PROG_LIST *list;
	char mprog[MAX_STRING_LENGTH];
	int value;
	int cnt = 0;

	EDIT_MOB(ch, pMob);

	one_argument(argument, mprog);
	if (!is_number(mprog) || mprog[0] == '\0')
	{
		chprintln(ch, "Syntax:  delmprog [#mprog]");
		return FALSE;
	}

	value = atoi(mprog);

	if (value < 0)
	{
		chprintln(ch, "Only non-negative mprog-numbers allowed.");
		return FALSE;
	}

	for (list = pMob->first_mprog; list != NULL; list = list->next)
		if ((++cnt == value))
			break;

	if (!list)
	{
		chprintln(ch, "MEdit:  Non existant mprog.");
		return FALSE;
	}
	REMOVE_BIT(pMob->mprog_flags, list->trig_type);
	UNLINK(list, pMob->first_mprog, pMob->last_mprog, next, prev);
	free_prog(list);

	chprintln(ch, "Mprog removed.");
	return TRUE;
}

OEDIT(oedit_addoprog)
{
	flag_t value;
	OBJ_INDEX_DATA *pObj;
	PROG_LIST *list;
	PROG_CODE *code;
	char trigger[MSL];
	char phrase[MSL];
	char num[MSL];

	EDIT_OBJ(ch, pObj);
	argument = one_argument(argument, num);
	argument = one_argument(argument, trigger);
	strcpy(phrase, argument);

	if (!is_number(num) || IS_NULLSTR(trigger) || IS_NULLSTR(phrase))
	{
		chprintln(ch, "Syntax:   addoprog [vnum] [trigger] [phrase]");
		return FALSE;
	}

	if ((value = flag_value(oprog_flags, trigger)) == NO_FLAG)
	{
		chprintln(ch, "Valid flags are:");
		show_help(ch, "oprog");
		return FALSE;
	}

	if ((code = get_prog_index(atol(num), PRG_OPROG)) == NULL)
	{
		chprintln(ch, "No such OBJProgram.");
		return FALSE;
	}

	list = new_prog();
	list->vnum = atol(num);
	list->trig_type = value;
	replace_string(list->trig_phrase, phrase);
	replace_string(list->code, code->code);
	SET_BIT(pObj->oprog_flags, value);
	LINK(list, pObj->first_oprog, pObj->last_oprog, next, prev);
	chprintln(ch, "Oprog Added.");
	return TRUE;
}

OEDIT(oedit_deloprog)
{
	OBJ_INDEX_DATA *pObj;
	PROG_LIST *list;
	char oprog[MSL];
	int value;
	int cnt = -1;

	EDIT_OBJ(ch, pObj);

	one_argument(argument, oprog);
	if (!is_number(oprog) || IS_NULLSTR(oprog))
	{
		chprintln(ch, "Syntax:  deloprog [#oprog]");
		return FALSE;
	}

	value = atoi(oprog);

	if (value < 0)
	{
		chprintln(ch, "Only non-negative oprog-numbers allowed.");
		return FALSE;
	}

	for (list = pObj->first_oprog; list != NULL; list = list->next)
		if (++cnt == value)
			break;

	if (!list)
	{
		chprintln(ch, "OEdit:  Non existant oprog.");
		return FALSE;
	}

	REMOVE_BIT(pObj->oprog_flags, list->trig_type);
	UNLINK(list, pObj->first_oprog, pObj->last_oprog, next, prev);
	free_prog(list);

	chprintln(ch, "Oprog removed.");
	return TRUE;
}

REDIT(redit_addrprog)
{
	flag_t value;
	ROOM_INDEX_DATA *pRoom;
	PROG_LIST *list;
	PROG_CODE *code;
	char trigger[MSL];
	char phrase[MSL];
	char num[MSL];

	EDIT_ROOM(ch, pRoom);
	argument = one_argument(argument, num);
	argument = one_argument(argument, trigger);
	strcpy(phrase, argument);

	if (!is_number(num) || IS_NULLSTR(trigger) || IS_NULLSTR(phrase))
	{
		chprintln(ch, "Syntax:   addrprog [vnum] [trigger] [phrase]");
		return FALSE;
	}

	if ((value = flag_value(rprog_flags, trigger)) == NO_FLAG)
	{
		chprintln(ch, "Valid flags are:");
		show_help(ch, "rprog");
		return FALSE;
	}

	if ((code = get_prog_index(atol(num), PRG_RPROG)) == NULL)
	{
		chprintln(ch, "No such ROOMProgram.");
		return FALSE;
	}

	list = new_prog();
	list->vnum = atol(num);
	list->trig_type = value;
	replace_string(list->trig_phrase, phrase);
	replace_string(list->code, code->code);
	SET_BIT(pRoom->rprog_flags, value);
	LINK(list, pRoom->first_rprog, pRoom->last_rprog, next, prev);
	chprintln(ch, "Rprog Added.");
	return TRUE;
}

REDIT(redit_delrprog)
{
	ROOM_INDEX_DATA *pRoom;
	PROG_LIST *list;
	char rprog[MSL];
	int value;
	int cnt = -1;

	EDIT_ROOM(ch, pRoom);

	one_argument(argument, rprog);
	if (!is_number(rprog) || IS_NULLSTR(rprog))
	{
		chprintln(ch, "Syntax:  delrprog [#rprog]");
		return FALSE;
	}

	value = atoi(rprog);

	if (value < 0)
	{
		chprintln(ch, "Only non-negative rprog-numbers allowed.");
		return FALSE;
	}

	for (list = pRoom->first_rprog; list != NULL; list = list->next)
		if ((++cnt == value))
			break;

	if (!list)
	{
		chprintln(ch, "REdit:  Non existant rprog.");
		return FALSE;
	}
	REMOVE_BIT(pRoom->rprog_flags, list->trig_type);
	UNLINK(list, pRoom->first_rprog, pRoom->last_rprog, next, prev);
	free_prog(list);
	chprintln(ch, "Rprog removed.");
	return TRUE;
}

VALIDATE_FUN(validate_level)
{
	int num = *(int *) arg;

	if (num < 0 || num > MAX_LEVEL)
	{
		chprintf(ch, "Number must be between 0 and %d.\n\r", MAX_LEVEL);
		return FALSE;
	}

	return TRUE;
}

VALIDATE_FUN(validate_align)
{
	int num = *(int *) arg;

	if (num < -1000 || num > 1000)
	{
		chprintln(ch, "Number must be between -1000 and 1000.");
		return FALSE;
	}

	return TRUE;
}

ED_FUN_DEC(olced_str)
{
	VALIDATE_FUN *validator;
	const char **string = (const char **) arg;

	if (IS_NULLSTR(argument))
	{
		chprintf(ch, "Syntax: %s string\n\r", n_fun);
		return FALSE;
	}

	if ((validator = (VALIDATE_FUN *) par) && !validator(ch, argument))
		return FALSE;

	replace_string(*string, argument);
	chprintln(ch, "Ok.");
	return TRUE;
}

ED_FUN_DEC(olced_str_line)
{
	VALIDATE_FUN *validator;
	const char **string = (const char **) arg;
	char buf[MSL];

	if (IS_NULLSTR(argument))
	{
		chprintf(ch, "Syntax: %s string\n\r", n_fun);
		return FALSE;
	}

	if ((validator = (VALIDATE_FUN *) par) && !validator(ch, argument))
		return FALSE;

	sprintf(buf, "%s\n\r", argument);
	replace_string(*string, buf);
	chprintln(ch, "Ok.");
	return TRUE;
}

ED_FUN_DEC(olced_desc)
{
	if (IS_NULLSTR(argument))
	{
		string_append(ch, (const char **) arg);
		return TRUE;
	}

	chprintln(ch, "Syntax : desc");

	return FALSE;
}

ED_FUN_DEC(olced_bool)
{
	if (IS_NULLSTR(argument))
	{
		chprintf(ch, "Syntax : %s [TRUE/FALSE]\n\r\n\r", n_fun);
		return FALSE;
	}

	if (!str_cmp(argument, "TRUE"))
		*(bool *) arg = TRUE;
	else if (!str_cmp(argument, "FALSE"))
		*(bool *) arg = FALSE;
	else
	{
		chprintln(ch, "ERROR : invalid argument.");
		return FALSE;
	}

	chprintln(ch, "Ok.");
	return TRUE;
}

ED_FUN_DEC(olced_olded)
{
	return (*(OLC_FUN *) par) (ch, argument);
}

ED_FUN_DEC(olced_number)
{
	int *value = (int *) arg;
	char *endptr;
	int temp;
	char arg1[MIL];
	VALIDATE_FUN *validator;

	one_argument(argument, arg1);
	temp = strtol(arg1, &endptr, 0);
	if (IS_NULLSTR(arg1) || !IS_NULLSTR(endptr))
	{
		chprintf(ch, "Syntax: %s number\n\r", n_fun);
		return FALSE;
	}

	if ((validator = (VALIDATE_FUN *) par) && !validator(ch, &temp))
		return FALSE;

	*value = temp;
	chprintln(ch, "Ok.");
	return TRUE;
}

ED_FUN_DEC(olced_number_long)
{
	long *value = (long *) arg;
	char *endptr;
	long temp;
	char arg1[MIL];
	VALIDATE_FUN *validator;

	one_argument(argument, arg1);
	temp = strtol(arg1, &endptr, 0);
	if (IS_NULLSTR(arg1) || !IS_NULLSTR(endptr))
	{
		chprintf(ch, "Syntax: %s number\n\r", n_fun);
		return FALSE;
	}

	if ((validator = (VALIDATE_FUN *) par) && !validator(ch, &temp))
		return FALSE;

	*value = temp;
	chprintln(ch, "Ok.");
	return TRUE;
}

ED_FUN_DEC(olced_vnum)
{
	vnum_t *value = (vnum_t *) arg;
	char *endptr;
	vnum_t temp;
	char arg1[MIL];
	VALIDATE_FUN *validator;

	one_argument(argument, arg1);
	temp = strtol(arg1, &endptr, 0);
	if (IS_NULLSTR(arg1) || !IS_NULLSTR(endptr))
	{
		chprintf(ch, "Syntax: %s number\n\r", n_fun);
		return FALSE;
	}

	if ((validator = (VALIDATE_FUN *) par) && !validator(ch, &temp))
		return FALSE;

	*value = temp;
	chprintln(ch, "Ok.");
	return TRUE;
}

void show_flags_buf(BUFFER * output, const struct flag_type *flag_table)
{
	int flag;
	char buf[MSL];
	int col;

	col = 0;
	for (flag = 0; flag_table[flag].name != NULL; flag++)
	{
		if (flag_table[flag].settable)
		{
			sprintf(buf, "%-19.18s", flag_table[flag].name);
			add_buf(output, buf);
			if (++col % 4 == 0)
				add_buf(output, "\n\r");
		}
	}

	if (col % 4 != 0)
		add_buf(output, "\n\r");
}

/*****************************************************************************
 Name:		show_flags
 Purpose:	Displays settable flags and stats.
 ****************************************************************************/
void show_flags(CHAR_DATA * ch, const struct flag_type *flag_table)
{
	BUFFER *output;

	output = new_buf();
	show_flags_buf(output, flag_table);
	page_to_char(buf_string(output), ch);
	free_buf(output);
}

ED_FUN_DEC(olced_flag)
{
	int stat;
	const struct flag_type *f;
	flag_t marked;

	if ((stat = is_stat((const struct flag_type *) par)) < 0)
	{
		chprintf
			(ch,
			 "%s: Unknown table of values (report it to implementors).", n_fun);
		return FALSE;
	}

	if (IS_NULLSTR(argument))
	{
		chprintlnf(ch, "Syntax: %s value\n\r\n\r"
				   "Type '%s ?' for a list of "
				   "acceptable values.", n_fun, n_fun);
		return FALSE;
	}

	if (!str_cmp(argument, "?"))
	{
		show_flags(ch, (const struct flag_type *) par);
		return FALSE;
	}

	if (stat)
	{
		if ((f = flag_lookup(argument, (const struct flag_type *) par)) == NULL)
		{
			chprintlnf(ch, "Syntax: %s value\n\r\n\r"
					   "Type '%s ?' for a list of "
					   "acceptable values.", n_fun, n_fun);
			return FALSE;
		}
		if (!f->settable)
		{
			chprintf(ch, "%s: '%s': value is not settable.\n\n\r",
					 n_fun, f->name);
			return FALSE;
		}
		*(int *) arg = f->bit;
		chprintf(ch, "%s: '%s': Ok.\n\n\r", n_fun, f->name);
		return TRUE;
	}

	marked = 0;

	/*
	 * Accept multiple flags.
	 */
	for (;;)
	{
		char word[MAX_INPUT_LENGTH];

		argument = one_argument(argument, word);

		if (IS_NULLSTR(word))
			break;

		if ((f = flag_lookup(word, (const struct flag_type *) par)) == NULL)
		{
			chprintf(ch, "Syntax: %s flag...\n\r\n\r"
					 "Type '%s ?' for a list of "
					 "acceptable flags.", n_fun, n_fun);
			return FALSE;
		}
		if (!f->settable)
		{
			chprintf(ch, "%s: '%s': flag is not settable.\n\r", n_fun, f->name);
			continue;
		}
		SET_BIT(marked, f->bit);
	}

	if (marked)
	{
		TOGGLE_BIT(*(flag_t *) arg, marked);
		chprintf(ch, "%s: '%s': flag(s) toggled.\n\r",
				 n_fun, flag_string((const struct flag_type *) par, marked));
		return TRUE;
	}
	return FALSE;
}

ED_FUN_DEC(olced_shop)
{
	MOB_INDEX_DATA *pMob = (MOB_INDEX_DATA *) arg;
	char command[MAX_INPUT_LENGTH];
	char arg1[MAX_INPUT_LENGTH];

	argument = one_argument(argument, command);
	argument = one_argument(argument, arg1);

	if (IS_NULLSTR(command))
	{
		chprintln(ch, "Syntax : shop hours [open] [close]");
		chprintln(ch, "         shop profit [%% buy] [%% sell]");
		chprintln(ch, "         shop type [0-4] [obj type]");
		chprintln(ch, "         shop type [0-4] none");
		chprintln(ch, "         shop assign");
		chprintln(ch, "         shop remove");

		return FALSE;
	}

	if (!str_cmp(command, "hours"))
	{
		if (IS_NULLSTR(arg1) || !is_number(arg1)
			|| IS_NULLSTR(argument) || !is_number(argument))
		{
			chprintln(ch, "Syntax : shop hours [open] [close]");
			return FALSE;
		}

		if (!pMob->pShop)
		{
			chprintln(ch, "ERROR : Debes crear un shop primero (shop assign).");
			return FALSE;
		}

		pMob->pShop->open_hour = atoi(arg1);
		pMob->pShop->close_hour = atoi(argument);

		chprintln(ch, "Hours set.");
		return TRUE;
	}

	if (!str_cmp(command, "profit"))
	{
		if (IS_NULLSTR(arg1) || !is_number(arg1)
			|| IS_NULLSTR(argument) || !is_number(argument))
		{
			chprintf(ch, "Syntax : shop profit [%% buy] [%% sell]\n\r");
			return FALSE;
		}

		if (!pMob->pShop)
		{
			chprintln(ch,
					  "MEdit:  You must create a shop first  (shop assign).");
			return FALSE;
		}

		pMob->pShop->profit_buy = atoi(arg1);
		pMob->pShop->profit_sell = atoi(argument);

		chprintln(ch, "Shop profit set.");
		return TRUE;
	}

	if (!str_cmp(command, "type"))
	{
		flag_t value = 0;

		if (IS_NULLSTR(arg1) || !is_number(arg1) || IS_NULLSTR(argument))
		{
			chprintln(ch, "Syntax:  shop type [#x0-4] [item type]");
			return FALSE;
		}

		if (atoi(arg1) >= MAX_TRADE)
		{
			chprintf(ch, "MEdit:  May sell %d items max.\n\r", MAX_TRADE);
			return FALSE;
		}

		if (!pMob->pShop)
		{
			chprintln(ch,
					  "MEdit:  You must create a shop first  (shop assign).");
			return FALSE;
		}

		if ((value = flag_value(type_flags, argument)) == NO_FLAG)
		{
			chprintln(ch, "MEdit:  That type of item is not known.");
			return FALSE;
		}

		pMob->pShop->buy_type[atoi(arg1)] = value;

		chprintln(ch, "Shop type set.");
		return TRUE;
	}

	/* shop assign && shop delete by Phoenix */
	if (!str_prefix(command, "assign"))
	{
		if (pMob->pShop)
		{
			chprintln(ch, "Mob already has a shop assigned to it.");
			return FALSE;
		}

		pMob->pShop = new_shop();
		LINK(pMob->pShop, shop_first, shop_last, next, prev);
		pMob->pShop->keeper = pMob->vnum;

		chprintln(ch, "New shop assigned to mobile.");
		return TRUE;
	}

	if (!str_prefix(command, "remove"))
	{
		SHOP_DATA *pShop;

		pShop = pMob->pShop;
		pMob->pShop = NULL;

		UNLINK(pShop, shop_first, shop_last, next, prev);

		free_shop(pShop);

		chprintln(ch, "Mobile is no longer a shopkeeper.");
		return TRUE;
	}

	olced_shop(n_fun, ch, str_empty, arg, par);

	return FALSE;
}

ED_FUN_DEC(olced_spec)
{
	SPEC_FUN **spec = (SPEC_FUN **) arg;

	if (IS_NULLSTR(argument))
	{
		chprintf(ch, "Sintaxis : %s [%s]\n\r", n_fun, n_fun);
		return FALSE;
	}

	if (!str_cmp(argument, "none"))
	{
		*spec = NULL;
		chprintln(ch, "Spec removed.");
		return TRUE;
	}

	if (spec_lookup(argument))
	{
		*spec = spec_lookup(argument);
		chprintln(ch, "Spec set.");
		return TRUE;
	}
	else
	{
		chprintln(ch, "ERROR : Spec inexistente.");
		return FALSE;
	}

	return FALSE;
}

ED_FUN_DEC(olced_race)
{
	MOB_INDEX_DATA *pMob = (MOB_INDEX_DATA *) arg;
	RACE_DATA *race;

	if (!IS_NULLSTR(argument) && (race = race_lookup(argument)) != NULL)
	{
		pMob->race = race;
		pMob->act |= race->act;
		pMob->affected_by |= race->aff;
		pMob->off_flags |= race->off;
		pMob->imm_flags |= race->imm;
		pMob->res_flags |= race->res;
		pMob->vuln_flags |= race->vuln;
		pMob->form |= race->form;
		pMob->parts |= race->parts;

		chprintln(ch, "Race set.");
		return TRUE;
	}

	if (argument[0] == '?')
	{
		int i = 0;

		chprintln(ch, "Available races are:");

		for (race = race_first; race != NULL; race = race->next)
		{
			if ((i % 3) == 0)
				chprintln(ch, "");
			chprintf(ch, " %-15s", race->name);
			i++;
		}

		chprintln(ch, "");
		return FALSE;
	}

	chprintln(ch, "Syntax:  race [race]\n\r"
			  "Type 'race ?' for a list of races.");
	return FALSE;
}

ED_FUN_DEC(olced_ac)
{
	MOB_INDEX_DATA *pMob = (MOB_INDEX_DATA *) arg;
	char blarg[MAX_INPUT_LENGTH];
	int pierce, bash, slash, exotic;

	do							/* So that I can use break and send the syntax in one place */
	{
		if (IS_NULLSTR(argument))
			break;

		argument = one_argument(argument, blarg);

		if (!is_number(blarg))
			break;
		pierce = atoi(blarg);
		argument = one_argument(argument, blarg);

		if (!IS_NULLSTR(blarg))
		{
			if (!is_number(blarg))
				break;
			bash = atoi(blarg);
			argument = one_argument(argument, blarg);
		}
		else
			bash = pMob->ac[AC_BASH];

		if (!IS_NULLSTR(blarg))
		{
			if (!is_number(blarg))
				break;
			slash = atoi(blarg);
			argument = one_argument(argument, blarg);
		}
		else
			slash = pMob->ac[AC_SLASH];

		if (!IS_NULLSTR(blarg))
		{
			if (!is_number(blarg))
				break;
			exotic = atoi(blarg);
		}
		else
			exotic = pMob->ac[AC_EXOTIC];

		pMob->ac[AC_PIERCE] = pierce;
		pMob->ac[AC_BASH] = bash;
		pMob->ac[AC_SLASH] = slash;
		pMob->ac[AC_EXOTIC] = exotic;

		chprintln(ch, "Ac set.");
		return TRUE;
	}
	while (FALSE);				/* Just do it once.. */

	chprintln(ch,
			  "Syntax:  ac [ac-pierce [ac-bash [ac-slash [ac-exotic]]]]\n\r"
			  "help MOB_AC  gives a list of reasonable ac-values.");

	return FALSE;
}

ED_FUN_DEC(olced_dice)
{
	static char syntax[] = "Syntax:  %s <number> d <type> + <bonus>\n\r";
	char *numb, *type, *bonus, *cp;
	int *arreglo = (int *) arg;

	if (IS_NULLSTR(argument))
	{
		chprintf(ch, syntax, n_fun);
		return FALSE;
	}

	numb = cp = (char *) argument;

	while (isdigit(*cp))
		++cp;
	while (*cp != '\0' && !isdigit(*cp))
		*(cp++) = '\0';

	type = cp;

	while (isdigit(*cp))
		++cp;
	while (*cp != '\0' && !isdigit(*cp))
		*(cp++) = '\0';

	bonus = cp;

	while (isdigit(*cp))
		++cp;
	if (*cp != '\0')
		*cp = '\0';

	if ((!is_number(numb) || atoi(numb) < 1)
		|| (!is_number(type) || atoi(type) < 1)
		|| (!is_number(bonus) || atoi(bonus) < 0))
	{
		chprintf(ch, syntax, n_fun);
		return FALSE;
	}

	arreglo[DICE_NUMBER] = atoi(numb);
	arreglo[DICE_TYPE] = atoi(type);
	arreglo[DICE_BONUS] = atoi(bonus);

	chprintf(ch, "%s set.\n\r", n_fun);

	return TRUE;
}

ED_FUN_DEC(olced_ed)
{
	EXTRA_DESCR_DATA *ed;
	EXTRA_DESCR_DATA **pEd = (EXTRA_DESCR_DATA **) arg;
	EXTRA_DESCR_DATA **lEd = (EXTRA_DESCR_DATA **) par;
	char command[MAX_INPUT_LENGTH];
	char keyword[MAX_INPUT_LENGTH];

	argument = one_argument(argument, command);
	argument = one_argument(argument, keyword);

	if (IS_NULLSTR(command))
	{
		chprintln(ch, "Syntax:  ed add [keyword]");
		chprintln(ch, "         ed delete [keyword]");
		chprintln(ch, "         ed edit [keyword]");
		chprintln(ch, "         ed format [keyword]");
		chprintln(ch, "         ed rename [keyword]");
		return FALSE;
	}

	if (!str_cmp(command, "add"))
	{
		if (IS_NULLSTR(keyword))
		{
			chprintln(ch, "Syntax:  ed add [keyword]");
			return FALSE;
		}

		ed = new_extra_descr();
		replace_string(ed->keyword, keyword);
		LINK(ed, *pEd, *lEd, next, prev);

		string_append(ch, &ed->description);

		return TRUE;
	}

	if (!str_cmp(command, "edit"))
	{
		if (IS_NULLSTR(keyword))
		{
			chprintln(ch, "Syntax:  ed edit [keyword]");
			return FALSE;
		}

		for (ed = *pEd; ed; ed = ed->next)
		{
			if (is_name(keyword, ed->keyword))
				break;
		}

		if (!ed)
		{
			chprintln(ch, "ERROR : No such extra description.");
			return FALSE;
		}

		string_append(ch, &ed->description);

		return TRUE;
	}

	if (!str_cmp(command, "delete"))
	{
		EXTRA_DESCR_DATA *ped = NULL;

		if (IS_NULLSTR(keyword))
		{
			chprintln(ch, "Syntax:  ed delete [keyword]");
			return FALSE;
		}

		for (ed = *pEd; ed; ed = ed->next)
		{
			if (is_name(keyword, ed->keyword))
				break;
			ped = ed;
		}

		if (!ed)
		{
			chprintln(ch, "ERROR : No such extra description.");
			return FALSE;
		}

		UNLINK(ed, *pEd, *lEd, next, prev);

		free_extra_descr(ed);

		chprintln(ch, "Extra description deleted.");
		return TRUE;
	}

	if (!str_cmp(command, "format"))
	{
		EXTRA_DESCR_DATA *ped = NULL;

		if (IS_NULLSTR(keyword))
		{
			chprintln(ch, "Syntax:  ed format [keyword]");
			return FALSE;
		}

		for (ed = *pEd; ed; ed = ed->next)
		{
			if (is_name(keyword, ed->keyword))
				break;
			ped = ed;
		}

		if (!ed)
		{
			chprintln(ch, "ERROR : No Such Extra Description");
			return FALSE;
		}

		ed->description = format_string(ed->description);

		chprintln(ch, "Extra description formatted.");
		return TRUE;
	}

	if (!str_cmp(command, "rename"))
	{
		EXTRA_DESCR_DATA *ped = NULL;

		if (IS_NULLSTR(keyword))
		{
			chprintln(ch, "Syntax:  ed rename [old] [new]");
			return FALSE;
		}

		for (ed = *pEd; ed; ed = ed->next)
		{
			if (is_name(keyword, ed->keyword))
				break;
			ped = ed;
		}

		if (!ed)
		{
			chprintln(ch, "ERROR : No such extra description");
			return FALSE;
		}

		replace_string(ed->keyword, argument);

		chprintln(ch, "Extra description renamed.");
		return TRUE;
	}

	return olced_ed(n_fun, ch, "", arg, par);
}

ED_FUN_DEC(olced_direction)
{
	return change_exit(ch, argument, (int) par);
}

ED_FUN_DEC(olced_docomm)
{
	(*(DO_FUN *) par) (ch, argument);
	return FALSE;
}

ED_FUN_DEC(olced_value)
{
	return oedit_values(ch, argument, (int) par);
}

bool templookup(const char *n_fun, CHAR_DATA * ch, const char *argument,
				void *arg, const void *par, int temp)
{
	int value;
	LOOKUP_F *blah = (LOOKUP_F *) par;

	if (!emptystring(argument))
	{
		if ((value = ((*blah) (argument))) > temp)
		{
			*(int *) arg = value;
			chprintf(ch, "%s set.\n\r", n_fun);
			return TRUE;
		}
		else
		{
			chprintf(ch, "ERROR : %s doesn't exist.\n\r", n_fun);
			return FALSE;
		}
	}

	chprintf(ch, "Syntax : %s [%s]\n\r"
			 "Type '? %s' for a list of arguments.\n\r", n_fun, n_fun, n_fun);

	return FALSE;
}

ED_FUN_DEC(olced_poslookup)
{
	return templookup(n_fun, ch, argument, arg, par, 0);
}

ED_FUN_DEC(olced_neglookup)
{
	return templookup(n_fun, ch, argument, arg, par, -1);
}

CEDIT(cedit_show)
{
	CLAN_DATA *pClan;
	int r;

	EDIT_CLAN(ch, pClan);

	chprintf(ch, "Name: %s\n\r", pClan->name);
	chprintf(ch, "Who:  %s\n\r", pClan->who_name);
	chprintf(ch, "Hall: %ld\n\r", pClan->hall);
	chprintf(ch, "Independant: %s\n\r", pClan->independent ? "TRUE" : "FALSE");
	for (r = 0; r < MAX_RANK; r++)
		chprintf(ch, "Rank %d: %s\n\r", r + 1, pClan->rank[r].rankname);
	return TRUE;
}

CEDIT(cedit_rank)
{
	CLAN_DATA *pClan;
	char arg1[MIL];

	EDIT_CLAN(ch, pClan);

	argument = one_argument(argument, arg1);

	if (is_number(arg1) && atoi(arg1) <= MAX_RANK && atoi(arg1) > 0)
	{
		int value;

		value = atoi(arg1) - 1;

		if (!IS_NULLSTR(argument))
		{
			replace_string(pClan->rank[value].rankname, argument);
			chprintln(ch, "Rank name changed.");
			return TRUE;
		}

	}

	chprintln(ch, "Syntax: rank rank# newname");
	return FALSE;
}

CEDIT(cedit_create)
{
	CLAN_DATA *pClan;
	char buf[MIL];

	if (!IS_NULLSTR(argument) && clan_lookup(argument) == NULL)
		sprintf(buf, argument);
	else
		sprintf(buf, "New Clan%d", maxClan + 1);

	pClan = new_clan();
	replace_string(pClan->name, buf);
	replace_string(pClan->who_name, buf);
	LINK(pClan, clan_first, clan_last, next, prev);

	edit_start(ch, pClan, ED_CLAN);
	chprintln(ch, "Clan created.");
	return TRUE;
}

CEDIT(cedit_delete)
{
	CLAN_DATA *pClan;

	EDIT_CLAN(ch, pClan);

	if (str_cmp(argument, "confirm"))
	{
		chprintln(ch,
				  "Typing 'delete confirm' again will permanetely remove this clan!\n\r"
				  "-or- 'delete cancel' will cancel the deletion.");
		return FALSE;
	}
	else
	{
		CHAR_DATA *pch;
		int hash;
		ROOM_INDEX_DATA *pRoom;
		MBR_DATA *pmbr, *next = NULL;

		for (pmbr = mbr_first; pmbr != NULL; pmbr = next)
		{
			next = pmbr->next;

			if (pmbr->clan == pClan)
			{
				UNLINK(pmbr, mbr_first, mbr_last, next, prev);
				free_mbr(pmbr);
			}
		}

		for (pch = char_first; pch != NULL; pch = pch->next)
		{
			if (pch->clan == pClan)
			{
				pch->clan = NULL;
				pch->rank = 0;
			}
		}

		for (hash = 0; hash < MAX_KEY_HASH; hash++)
		{
			for (pRoom = room_index_hash[hash]; pRoom; pRoom = pRoom->next)
			{
				if (pRoom->clan == pClan)
				{
					pRoom->clan = NULL;
					SET_BIT(pRoom->area->area_flags, AREA_CHANGED);
				}
			}
		}

		UNLINK(pClan, clan_first, clan_last, next, prev);
		free_clan(pClan);
		pClan = clan_first;
		edit_start(ch, pClan, ED_CLAN);
		chprintln(ch, "Clan deleted.");
	}

	return TRUE;
}

OEDIT(oedit_autoweapon)
{
	OBJ_INDEX_DATA *pObj;

	EDIT_OBJ(ch, pObj);

	if (pObj->item_type != ITEM_WEAPON)
	{
		chprintln(ch, " {rAutoweapon only works on weapons...{x");
		return FALSE;
	}

	if (pObj->level < 1)
	{
		chprintlnf
			(ch,
			 " {cAutoweapon requires a level to be set on the weapon first(vnum %ld).{x",
			 pObj->vnum);
		return FALSE;
	}

	if (IS_OBJ_STAT(pObj, ITEM_QUEST))
	{
		chprintln(ch, "This weapon cannot be autoset.");
		return FALSE;
	}

	autoweapon(pObj);
	chprintln(ch, "Weapon set to default values., check for accuracy.");

	return TRUE;
}

OEDIT(oedit_autoarmor)
{
	OBJ_INDEX_DATA *pObj;

	EDIT_OBJ(ch, pObj);

	if (pObj->item_type != ITEM_ARMOR)
	{
		chprintln(ch, " {rAutoArmor only works on Armor ...{x");
		return FALSE;
	}

	if (pObj->level < 1)
	{
		chprintlnf
			(ch,
			 " {cAutoArmor requires a level to be set on the armor first.(vnum %ld){x",
			 pObj->vnum);
		return FALSE;
	}

	if (IS_OBJ_STAT(pObj, ITEM_QUEST))
	{
		chprintln(ch, "This weapon cannot be autoset.");
		return FALSE;
	}

	autoarmor(pObj);
	chprintln(ch, "AutoArmor has set experimental values for AC.{x");
	return TRUE;
}

MEDIT(medit_autoset)
{
	MOB_INDEX_DATA *pMob;

	EDIT_MOB(ch, pMob);

	if (pMob->level < 1)
	{
		chprintlnf(ch, "Set a level on the mob first!!!(vnum %ld)", pMob->vnum);
		return FALSE;
	}

	autoset(pMob);
	chprintln(ch, " Values set, check for accuracy.");
	return TRUE;
}

MEDIT(medit_autohard)
{
	MOB_INDEX_DATA *pMob;

	EDIT_MOB(ch, pMob);

	if (pMob->level < 1)
	{
		chprintlnf(ch, "Set a level on the mob first!!!(vnum %ld)", pMob->vnum);
		return FALSE;
	}

	autohard(pMob);

	chprintln(ch, " Hard values set, check for accuracy.");

	return TRUE;
}

MEDIT(medit_autoeasy)
{
	MOB_INDEX_DATA *pMob;

	EDIT_MOB(ch, pMob);
	if (pMob->level < 1)
	{
		chprintlnf(ch, "Set a level on the mob first!!!(vnum %ld)", pMob->vnum);
		return FALSE;
	}
	autoeasy(pMob);

	chprintln(ch, " Easy values set, check for accuracy.");

	return TRUE;
}