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

#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "debug.h"
#include "olc.h"
#include "db/db.h"

#define EDIT_OBJ(ch, obj)	(obj = (OBJ_INDEX_DATA*) ch->desc->pEdit)

DECLARE_OLC_FUN(objed_create		);
DECLARE_OLC_FUN(objed_edit		);
DECLARE_OLC_FUN(objed_touch		);
DECLARE_OLC_FUN(objed_show		);
DECLARE_OLC_FUN(objed_list		);
DECLARE_OLC_FUN(objed_del		);

DECLARE_OLC_FUN(objed_name		);
DECLARE_OLC_FUN(objed_short		);
DECLARE_OLC_FUN(objed_long		);
DECLARE_OLC_FUN(objed_addaffect		);
DECLARE_OLC_FUN(objed_addapply		);
DECLARE_OLC_FUN(objed_delaffect		);
DECLARE_OLC_FUN(objed_value0		);
DECLARE_OLC_FUN(objed_value1		);
DECLARE_OLC_FUN(objed_value2		);
DECLARE_OLC_FUN(objed_value3		);
DECLARE_OLC_FUN(objed_value4		);
DECLARE_OLC_FUN(objed_value5		);
DECLARE_OLC_FUN(objed_value6		);
DECLARE_OLC_FUN(objed_weight		);
DECLARE_OLC_FUN(objed_limit		);
DECLARE_OLC_FUN(objed_cost		);
DECLARE_OLC_FUN(objed_exd		);

DECLARE_OLC_FUN(objed_extra		);
DECLARE_OLC_FUN(objed_wear		);
DECLARE_OLC_FUN(objed_type		);
DECLARE_OLC_FUN(objed_affect		);
DECLARE_OLC_FUN(objed_material		);
DECLARE_OLC_FUN(objed_matdesc		);
DECLARE_OLC_FUN(objed_level		);
DECLARE_OLC_FUN(objed_condition		);
DECLARE_OLC_FUN(objed_clan		);
DECLARE_OLC_FUN(objed_clone		);
DECLARE_OLC_FUN(objed_sex		);
DECLARE_OLC_FUN(objed_race          );
DECLARE_OLC_FUN(objed_class         );
DECLARE_OLC_FUN(objed_size         );
DECLARE_OLC_FUN(objed_autoweapon	);
DECLARE_OLC_FUN(objed_autoarmor		);

DECLARE_VALIDATE_FUN(validate_condition);

olc_cmd_t olc_cmds_obj[] =
{
/*	{ command	function		arg			}, */

	{ 2, "create",		objed_create				},
	{ 2, "edit",		objed_edit				},
	{ 2, "touch",		objed_touch				},
	{ 0, "show",		objed_show				},
	{ 0, "list",		objed_list				},
	{ 2, "delete_ob",	olced_spell_out				},
	{ 2, "delete_obj",	objed_del				},

	{ 2, "addaffect",	objed_addaffect				},
	{ 2, "addapply",	objed_addapply				},
	{ 2, "cost",		objed_cost				},
	{ 2, "delaffect",	objed_delaffect				},
	{ 2, "exd",		objed_exd				},
	{ 2, "long",		objed_long				},
	{ 2, "name",		objed_name				},
	{ 2, "short",		objed_short				},
	{ 2, "v0",		objed_value0				},
	{ 2, "v1",		objed_value1				},
	{ 2, "v2",		objed_value2				},
	{ 2, "v3",		objed_value3				},
	{ 2, "v4",		objed_value4				},
	{ 2, "v5",		objed_value5				},
	{ 2, "v6",		objed_value6				},
	{ 2, "weight",		objed_weight				},
	{ 2, "limit",		objed_limit				},

	{ 2, "extra",		objed_extra,		extra_flags	},
	{ 2, "wear",		objed_wear,		wear_flags	},
	{ 2, "type",		objed_type,		item_types	},
	{ 2, "material",	objed_material 				},
	{ 2, "matdesc",		objed_matdesc				},
	{ 2, "level",		objed_level				},
	{ 2, "condition",	objed_condition,	validate_condition},
	{ 2, "clan",		objed_clan				},
	{ 2, "clone",		objed_clone				},
	{ 2, "autoweapon",	objed_autoweapon			},
	{ 2, "autoarmor",	objed_autoarmor				},
	{ 2, "sex",		objed_sex,		rsex_flags	},
	{ 2, "race",		objed_race,             rrace_flags     },
	{ 2, "class", 		objed_class,            rclass_flags    },
	{ 2, "size", 		objed_size,             rsize_flags     },

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

	{ 0, NULL }
};

static void	show_obj_values	(BUFFER *output, OBJ_INDEX_DATA *pObj);
static int	set_obj_values	(BUFFER *output, OBJ_INDEX_DATA *pObj,
				 const char *argument, int value_num);
static void	show_spells	(BUFFER *output, int tar);

OLC_FUN(objed_create)
{
	OBJ_INDEX_DATA *pObj;
	AREA_DATA *pArea;
	int  value;
	int  iHash;
	char arg[MAX_STRING_LENGTH];

	one_argument(argument, arg, sizeof(arg));
	value = atoi(arg);
	if (!value) {
		do_help(ch, "'OLC CREATE'");
		return FALSE;
	}

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

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

	if (get_obj_index(value)) {
		char_puts("ObjEd: Object vnum already exists.\n", ch);
		return FALSE;
	}
		 
	pObj			= new_obj_index();
	pObj->vnum		= value;
		 
	if (value > top_vnum_obj)
		top_vnum_obj = value;

	iHash			= value % MAX_KEY_HASH;
	pObj->next		= obj_index_hash[iHash];
	obj_index_hash[iHash]	= pObj;

	ch->desc->pEdit		= (void *)pObj;
	OLCED(ch)		= olced_lookup(ED_OBJ);
	touch_area(pArea);
	char_puts("ObjEd: Object created.\n", ch);
	return FALSE;
}

OLC_FUN(objed_edit)
{
	char arg[MAX_INPUT_LENGTH];
	int value;
	OBJ_INDEX_DATA *pObj;
	AREA_DATA *pArea;

	one_argument(argument, arg, sizeof(arg));
	if (arg[0] == '\0') {
		do_help(ch, "'OLC EDIT'");
		return FALSE;
	}

	value = atoi(arg);
	pObj = get_obj_index(value);
	if (!pObj) {
		char_puts("ObjEd: Vnum does not exist.\n", ch);
		return FALSE;
	}

	pArea = area_vnum_lookup(pObj->vnum);
	if (!IS_BUILDER(ch, pArea)) {
		char_puts("ObjEd: Insufficient security.\n", ch);
	       	return FALSE;
	}

	ch->desc->pEdit = (void*) pObj;
	OLCED(ch)	= olced_lookup(ED_OBJ);
	return FALSE;
}

OLC_FUN(objed_touch)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return touch_vnum(pObj->vnum);
}

OLC_FUN(objed_show)
{
	char arg[MAX_INPUT_LENGTH];
	OBJ_INDEX_DATA	*pObj;
	AREA_DATA	*pArea;
	AFFECT_DATA *paf;
	int cnt;
	BUFFER *output;
	clan_t *clan;
	int bp, bpmax;

	one_argument(argument, arg, sizeof(arg));
	if (arg[0] == '\0') {
		if (IS_EDIT(ch, ED_OBJ))
			EDIT_OBJ(ch, pObj);
		else {
			do_help(ch, "'OLC EDIT'");
			return FALSE;
		}
	}
	else {
		int value = atoi(arg);
		pObj = get_obj_index(value);
		if (!pObj) {
			char_puts("ObjEd: Vnum does not exist.\n", ch);
			return FALSE;
		}
	}

	pArea = area_vnum_lookup(pObj->vnum);

	output = buf_new(-1);
	buf_printf(output, "Vnum:              {D[{C%5d{D]{x\n",
		pObj->vnum);

	buf_printf(output, "Name:              {D[{c%s{D]{x\n",
		pObj->name);

	buf_printf(output, "Area:              {D[{c%5d{D]{x {%c%s{x\n",
		pArea->vnum, 
		IS_SET(pArea->flags, AREA_CLOSED)      ? 'R' :
		IS_SET(pArea->flags, AREA_PLAYERHOUSE) ? 'G' :
		IS_SET(pArea->flags, AREA_HIDDEN)      ? 'D' : 'x',
		pArea->name);

	buf_printf(output, "Type:              {D[{c%s{D]{x\n",
		flag_string(item_types, pObj->item_type));

        buf_printf(output, "Sex Restriction:   {D[{c%s{D]{x\n",
		flag_string(rsex_flags, pObj->rsex));

        buf_printf(output, "Size Restriction:  {D[{c%s{D]{x\n",
 		flag_string(rsize_flags, pObj->rsize));

        buf_printf(output, "Race Restriction:  {D[{c%s{D]{x\n",
                flag_string(rrace_flags, pObj->rrace));
  
        buf_printf(output, "Class Restriction: {D[{c%s{D]{x\n",
 		flag_string(rclass_flags, pObj->rclass));

	if (pObj->clan && (clan = clan_lookup(pObj->clan))) 
		buf_printf(output, 
			   "Clan:              {D[{c%s{D]{x\n", clan->name);

	if (pObj->limit != -1)
		buf_printf(output, "Limit:             {D[{c%5d{D]{x\n", pObj->limit);
	else
		buf_add(output, "Limit:             {D[{cnone{D]{x\n");

	buf_printf(output, "Level:             {D[{c%5d{D]{x\n", pObj->level);

	buf_printf(output, "Wear flags:        {D[{c%s{D]{x\n",
		flag_string(wear_flags, pObj->wear_flags));

	buf_printf(output, "Extra flags:       {D[{c%s{D]{x\n",
		flag_string(extra_flags, pObj->extra_flags));

	buf_printf(output, "Material:          {D[{c%s{D]{x\n",
		(pObj->material) ? pObj->material->name : "null");
	buf_printf(output, "MatDesc:           {D[{x%s{D]{x\n", 
		pObj->material_descr);

	buf_printf(output, "Weight:            {D[{c%4d.%01d{D] lbs{x\n"
			   "Cost:              {D[{Y%3d{x%02d{D] ",
		pObj->weight / 10, 
		pObj->weight % 10,
		pObj->cost / 100,
		pObj->cost % 100);

	if (IS_SET(pObj->extra_flags, ITEM_QUEST))
		buf_printf(output, 
			"QP return % by level: 100% = level QPs{x\n");
	else
		buf_printf(output, 
			"sug: {Y%d{x gold {W%d{x silver\n",
			get_autocost(pObj) / 100,
			get_autocost(pObj) % 100);

	buf_printf(output, "Condition:         {D[{c%5d{D]{x\n",         /* ROM */
		pObj->condition);
	if (pObj->ed) {
		ED_DATA *ed;

		buf_add(output, "Ex desc kwd: ");

		for (ed = pObj->ed; ed; ed = ed->next)
			buf_printf(output, "{D[{c%s{D]{x", ed->keyword);

		buf_add(output, "\n");
	}

	buf_add(output, "\n");

	mlstr_dump(output, "Short desc:  ", pObj->short_descr);
	mlstr_dump(output, "Long desc:   ", pObj->description);
	buf_add(output, "\n");

	show_obj_values(output, pObj);

	buf_add(output, "\n");

	for (cnt = 0, paf = pObj->affected; paf; paf = paf->next) {
		where_t *w = where_lookup(paf->where);

		if (cnt == 0) {
			buf_add(output, "Number      Affects Modifier Affects Bitvector\n");
			buf_add(output, "{D------ ------------ -------- ------- -----------------------------------------{x\n");
		}
		buf_printf(output, "{D[{x%4d{D] {c%12.12s {C%8d {c%7.7s %s{x"
				   "\n",
			   cnt,
			   flag_string(apply_flags, paf->location),
			   paf->modifier,
			   flag_string(apply_types, paf->where),
			   w ? flag_string(w->table, paf->bitvector) : "none");
		cnt++;
	}
	/*Zz*/
	build_points(pObj, &bp, &bpmax);
	if (cnt != 0)
		buf_add(output, "\n");
	
	buf_printf(output, "Build Points:              {%c%d {Dmax: %d{x\n",
		build_point_percent_color(bp, bpmax),
		bp, 
		bpmax);

	page_to_char(buf_string(output), ch);
	buf_free(output);

	return FALSE;
}

OLC_FUN(objed_list)
{
	OBJ_INDEX_DATA	*pObjIndex;
	AREA_DATA	*pArea;
	BUFFER		*buffer;
	const char *	name;
	char		arg  [MAX_INPUT_LENGTH];
	char		buf  [MAX_INPUT_LENGTH];
	int ansi_len = 0;
	bool fAll, found;
	int vnum;
	int  col = 0;
	int bp, bpmax;
	int count = 0;
	int bp_tot = 0, 
	    bpmax_tot = 0;
	int limiteds = 0,
	    rares = 0;

	one_argument(argument, arg, sizeof(arg));
/*
	if (arg[0] == '\0') {
		arg = "all";
		do_help(ch, "'OLC ALIST'");
		return FALSE;
	}
*/

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

	buffer  = buf_new(-1);
	fAll    = arg[0] == '\0' || !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)
			|| flag_value(item_types, arg) == pObjIndex->item_type) {

				found = TRUE;
				build_points(pObjIndex, &bp, &bpmax);
				bp_tot += bp;
				bpmax_tot += bpmax;
				count++;
				if (IS_OBJ_LIMITED(pObjIndex))
					limiteds++;

				if (IS_SET(pObjIndex->extra_flags, ITEM_RARE))
					rares++;

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

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

				buf_printf(buffer, buf,
					(IS_OBJ_LIMITED(pObjIndex)) ? 'B' :
					(IS_OBJ_RARE(pObjIndex))    ? 'b'
								    : 'D',	
					build_point_percent_color(bp, bpmax),
					pObjIndex->vnum,
					(IS_OBJ_LIMITED(pObjIndex)) ? 'B' :
					(IS_OBJ_RARE(pObjIndex))    ? 'b'
								    : 'D',	
					name);
				if (++col % 3 == 0)
					buf_add(buffer, "\n");
			}
		}
	}

	if (!found)
		char_puts("Object(s) not found in this area.\n", ch);
	else {
		if (col % 3 != 0)
			buf_add(buffer, "\n");

		buf_printf(buffer, "Average Build Points: {%c%d{x%%{x   "
				   "Rares: {c%d{x   Limiteds: {c%d{x",
				build_point_percent_color(bp_tot, bpmax_tot),
				(!bpmax_tot) ? 0 : (bp_tot * 100) / bpmax_tot,
				rares, limiteds);

		page_to_char(buf_string(buffer), ch);
	}

	buf_free(buffer);
	return FALSE;
}

OLC_FUN(objed_del)
{
	OBJ_INDEX_DATA *pObj;
	OBJ_DATA *obj, *obj_next;
	AREA_DATA *area;
	int i;
	bool error = FALSE;

	EDIT_OBJ(ch, pObj);

	if (olced_busy(ch, ED_OBJ, pObj, NULL))
		return FALSE;

/* check that pObj is not in resets */
	for (i = 0; i < MAX_KEY_HASH; i++) {
		ROOM_INDEX_DATA *room;

		for (room = room_index_hash[i]; room; room = room->next) {
			int j = 0;
			RESET_DATA *reset;

			for (reset = room->reset_first; reset;
							reset = reset->next) {
				bool found = FALSE;

				j++;
				switch (reset->command) {
				case 'P':
					if (reset->arg3 == pObj->vnum)
						found = TRUE;

					/* FALLTHRU */

				case 'O':
				case 'G':
				case 'E':
					if (reset->arg1 == pObj->vnum)
						found = TRUE;
					break;
				}

				if (!found)
					continue;

				if (!error) {
					error = TRUE;
					char_puts("ObjEd: can't delete obj "
						  "index: delete the "
						  "following resets:\n", ch);
				}

				char_printf(ch, "ObjEd: room %d, reset %d\n",
					    room->vnum, j);
			}
		}
	}

	if (error)
		return FALSE;

/* delete all the instances of obj index */
	for (obj = object_list; obj; obj = obj_next) {
		obj_next = obj->next;

		if (obj->pIndexData == pObj)
			extract_obj(obj, XO_F_NORECURSE);
	}

	if ((area = area_vnum_lookup(pObj->vnum)))
		touch_area(area);

/* delete obj index itself */
	i = pObj->vnum % MAX_KEY_HASH;
	if (pObj == obj_index_hash[i])
		obj_index_hash[i] = pObj->next;
	else {
		OBJ_INDEX_DATA *prev;

		for (prev = obj_index_hash[i]; prev; prev = prev->next)
			if (prev->next == pObj)
				break;

		if (prev)
			prev->next = pObj->next;
	}

	free_obj_index(pObj);
	char_puts("ObjEd: Obj index deleted.\n", ch);
	edit_done(ch->desc);
	return FALSE;
}

/*
 * Need to issue warning if flag isn't valid. -- does so now -- Hugin.
 */
OLC_FUN(objed_addaffect)
{
	int location;
	int modifier;
	flag32_t where;
	flag64_t bitvector;
	OBJ_INDEX_DATA *pObj;
	AFFECT_DATA *pAf;
	char loc[MAX_STRING_LENGTH];
	char mod[MAX_STRING_LENGTH];
	char wh[MAX_STRING_LENGTH];

	EDIT_OBJ(ch, pObj);

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

	if (loc[0] == '\0') {
		do_help(ch, "'OLC ADDAFFECT'");
		return FALSE;
	}

	if (!str_cmp(loc, "none")) {
		location = APPLY_NONE;
		modifier = 0;
	}
	else {
		if ((location = flag_value(apply_flags, loc)) < 0) {
			char_puts("Valid locations are:\n", ch);
			show_flags(ch, apply_flags);
			return FALSE;
		}

		if (!is_number(mod)) {
			do_help(ch, "'OLC ADDAFFECT'");
			return FALSE;
		}
		modifier = atoi(mod);
	}

	if (wh[0] == '\0') {
		where = -1;
		bitvector = 0;
	}
	else {
		where_t *w;

		if ((where = flag_value(apply_types, wh)) < 0) {
			char_puts("Valid bitaffect locations are:\n", ch);
			show_flags(ch, apply_types);
			return FALSE;
		}

		if ((w = where_lookup(where)) == NULL) {
			char_printf(ch, "%s: not in where_table.\n",
				    flag_string(apply_types, where));
			return FALSE;
		}

		if ((bitvector = flag_value(w->table, argument)) == 0) {
			char_printf(ch, "Valid '%s' bitaffect flags are:\n",
				    flag_string(apply_types, where));
			show_flags(ch, w->table);
			return FALSE;
		}
	}

	/* Zz */
	/* if not "unknown" affect, then add to value instead of
	 * adding another affect
	 */
	pAf = pObj->affected;
	while (pAf) {
		if (pAf->location != APPLY_NONE
		&& pAf->location == location) {
			pAf->modifier += modifier;
			char_puts("Previous affect adjusted.\n", ch);
			break;
		}
		pAf = pAf->next;
	}
	if (!pAf) {
		pAf             = aff_new();
		pAf->location   = location;
		pAf->modifier   = modifier;
		pAf->where	= where;
		pAf->type       = -1;
		pAf->duration   = -1;
		pAf->bitvector  = bitvector;
		pAf->level      = pObj->level;
		pAf->next       = pObj->affected;
		pObj->affected  = pAf;
		char_puts("New affect added.\n", ch);
	}

	return TRUE;
}

OLC_FUN(objed_addapply)
{
	int location, bv, where;
	OBJ_INDEX_DATA *pObj;
	AFFECT_DATA *pAf;
	where_t *wd;
	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, sizeof(type));
	argument = one_argument(argument, loc, sizeof(loc));
	argument = one_argument(argument, mod, sizeof(mod));
	one_argument(argument, bvector, sizeof(bvector));

	if ((where = flag_value(apply_types, type)) < 0) {
		char_puts("Invalid apply type. Valid apply types are:\n", ch);
		show_flags(ch, apply_types);
		return FALSE;
	}

	if ((location = flag_value(apply_flags, loc)) < 0) {
		char_puts("Valid applies are:\n", ch);
		show_flags(ch, apply_flags);
		return FALSE;
	}

	if ((wd = where_lookup(where)) == NULL) {
		char_puts("ObjEd: bit vector table undefined. "
			  "Report it to implementors.\n", ch);
		return FALSE;
	}

	if ((bv = flag_value(wd->table, bvector)) == 0) {
		char_puts("Valid bitvector types are:\n", ch);
		show_flags(ch, wd->table);
		return FALSE;
	}

	if (!is_number(mod)) {
		char_puts("Syntax: addapply type location "
			  "mod bitvector\n", ch);
		return FALSE;
	}

	pAf             = aff_new();
	pAf->location   = location;
	pAf->modifier   = atoi(mod);
	pAf->where	= where;
	pAf->type	= -1;
	pAf->duration   = -1;
	pAf->bitvector  = bv;
	pAf->level      = pObj->level;
	pAf->next       = pObj->affected;
	pObj->affected  = pAf;

	char_puts("Apply added.\n", ch);
	return TRUE;
}

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

	EDIT_OBJ(ch, pObj);

	one_argument(argument, affect, sizeof(affect));

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

	value = atoi(affect);

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

	if (!(pAf = pObj->affected))
	{
		char_puts("ObjEd:  Non-existant affect.\n", ch);
		return FALSE;
	}

	if(value == 0)	/* First case: Remove first affect */
	{
		pAf = pObj->affected;
		pObj->affected = pAf->next;
		aff_free(pAf);
	}
	else		/* Affect to remove is not the first */
	{
		while ((pAf_next = pAf->next) && (++cnt < value))
			 pAf = pAf_next;

		if(pAf_next)		/* See if it's the next affect */
		{
			pAf->next = pAf_next->next;
			aff_free(pAf_next);
		}
		else                                 /* Doesn't exist */
		{
			 char_puts("No such affect.\n", ch);
			 return FALSE;
		}
	}

	char_puts("Affect removed.\n", ch);
	return TRUE;
}

OLC_FUN(objed_name)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return olced_name(ch, argument, cmd, &pObj->name);
}

OLC_FUN(objed_short)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return olced_mlstr(ch, argument, cmd, &pObj->short_descr);
}

OLC_FUN(objed_long)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return olced_mlstr(ch, argument, cmd, &pObj->description);
}

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

	output = buf_new(-1);
	if (argument[0] == '\0'
	||  (errcode = set_obj_values(output, pObj, argument, value)) < 2)
		show_obj_values(output, pObj);
	page_to_char(buf_string(output), ch);
	buf_free(output);
	return !errcode;
}

OLC_FUN(objed_value0)
{
	return objed_values(ch, argument, 0);
}

OLC_FUN(objed_value1)
{
	return objed_values(ch, argument, 1);
}

OLC_FUN(objed_value2)
{
	return objed_values(ch, argument, 2);
}

OLC_FUN(objed_value3)
{
	return objed_values(ch, argument, 3);
}

OLC_FUN(objed_value4)
{
	return objed_values(ch, argument, 4);
}

OLC_FUN(objed_value5)
{
	return objed_values(ch, argument, 5);
}

OLC_FUN(objed_value6)
{
	return objed_values(ch, argument, 6);
}

OLC_FUN(objed_weight)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return olced_number(ch, argument, cmd, &pObj->weight);
}

OLC_FUN(objed_limit)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return olced_number(ch, argument, cmd, &pObj->limit);
}

OLC_FUN(objed_cost)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return olced_number(ch, argument, cmd, &pObj->cost);
}

OLC_FUN(objed_exd)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return olced_exd(ch, argument, cmd, &pObj->ed);
}

OLC_FUN(objed_extra)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return olced_flag64(ch, argument, cmd, &pObj->extra_flags);
}

OLC_FUN(objed_wear)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return olced_flag32(ch, argument, cmd, &pObj->wear_flags);
}

OLC_FUN(objed_type)
{
	bool changed;
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	changed = olced_flag32(ch, argument, cmd, &pObj->item_type);
	if (changed) {
		pObj->value[0] = 0;
		pObj->value[1] = 0;
		pObj->value[2] = 0;
		pObj->value[3] = 0;
		pObj->value[4] = 0;
		pObj->value[5] = 0;
		pObj->value[6] = 0;

		switch (pObj->item_type) {
			case ITEM_CONTAINER:
				pObj->value[ITEM_CONTAINER_WEIGHT_MULTI] = 100;
				break;
		}
	}
	return changed;
}

OLC_FUN(objed_matdesc)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return olced_str(ch, argument, cmd, &pObj->material_descr);
}

OLC_FUN(objed_level)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return olced_number(ch, argument, cmd, &pObj->level);
}

OLC_FUN(objed_condition)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return olced_number(ch, argument, cmd, &pObj->condition);
}

OLC_FUN(objed_material)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return olced_material(ch, argument, cmd, &pObj->material);
}

OLC_FUN(objed_clan)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return olced_clan(ch, argument, cmd, &pObj->clan);
}

OLC_FUN(objed_clone)
{
	OBJ_INDEX_DATA *pObj;
	OBJ_INDEX_DATA *pFrom;
	char arg[MAX_INPUT_LENGTH];
	int i;
	AFFECT_DATA *paf;
	AFFECT_DATA *paf_next;
	AFFECT_DATA **ppaf;

	one_argument(argument, arg, sizeof(arg));
	if (!is_number(arg)) {
		char_puts("Syntax: clone <vnum>\n", ch);
		return FALSE;
	}

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

	EDIT_OBJ(ch, pObj);
	if (pObj == pFrom)
		return FALSE;

	free_string(pObj->name);
	pObj->name		= str_qdup(pFrom->name);
	pObj->material		= pFrom->material;
	free_string(pObj->material_descr);
	pObj->material_descr	= str_qdup(pFrom->material_descr);
	mlstr_free(pObj->short_descr);
	pObj->short_descr	= mlstr_dup(pFrom->short_descr);
	mlstr_free(pObj->description);
	pObj->description	= mlstr_dup(pFrom->description);

	pObj->item_type		= pFrom->item_type;
	pObj->extra_flags	= pFrom->extra_flags;
	pObj->wear_flags	= pFrom->wear_flags;
	pObj->level		= pFrom->level;
	pObj->condition		= pFrom->condition;
	pObj->weight		= pFrom->weight;
	pObj->cost		= pFrom->cost;
	pObj->limit		= pFrom->limit;
	pObj->clan		= pFrom->clan;

	for (i = 0; i <ITEM_VALUE_MAX; i++)
		pObj->value[i]	= pFrom->value[i];

/* copy affects */
	for (paf = pObj->affected; paf; paf = paf_next) {
		paf_next = paf->next;
		aff_free(paf);
	}

	ppaf = &pObj->affected;
	for (paf = pFrom->affected; paf; paf = paf->next) {
		*ppaf = aff_dup(paf);
		ppaf = &(*ppaf)->next;
	}

/* copy extra descriptions */
	ed_free(pObj->ed);
	pObj->ed = ed_dup(pFrom->ed);

	return TRUE;
}

OLC_FUN(objed_sex)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return olced_flag32(ch, argument, cmd, &pObj->rsex);
}

OLC_FUN(objed_race)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
 	return olced_flag32(ch, argument, cmd, &pObj->rrace);
}

OLC_FUN(objed_class)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return olced_flag32(ch, argument, cmd, &pObj->rclass);
}

OLC_FUN(objed_size)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);
	return olced_flag32(ch, argument, cmd, &pObj->rsize);
}

void show_obj_values(BUFFER *output, OBJ_INDEX_DATA *pObj)
{
	int avg_dnum, avg_dsize, autow_avg = 0, w_avg = 0;
	ROOM_INDEX_DATA *loc = NULL;
	OBJ_INDEX_DATA *key = NULL;

	switch(pObj->item_type) {
	default:	/* No values. */
		buf_add(output, "Currently edited obj has unknown item type.\n");
		/* FALLTHRU */

	case ITEM_TREASURE:
	case ITEM_CLOTHING:
	case ITEM_TRASH:
	case ITEM_KEY:
	case ITEM_BOAT:
	case ITEM_CORPSE_NPC:
	case ITEM_CORPSE_PC:
	case ITEM_PROTECT:
	case ITEM_MAP:
	case ITEM_WARP_STONE :
	case ITEM_ROOM_KEY:
	case ITEM_GEM:
	case ITEM_JEWELRY:
	case ITEM_JUKEBOX:
	case ITEM_TATTOO:
	case ITEM_MEDAL:
		break;

		     
	case ITEM_LIGHT:
		if (pObj->value[ITEM_LIGHT_DURATION] == -1)
			buf_printf(output, "{D[{xv2{D]{x Light:  {cInfinite[-1]{x\n");
		else
			buf_printf(output, "{D[{xv2{D]{x Light:  {D[{c%d{D]{x\n", 
				pObj->value[ITEM_LIGHT_DURATION]);
		break;

	case ITEM_WAND:
	case ITEM_STAFF:
		buf_printf(output,
			"{D[{xv0{D]{x Level:          {D[{c%d{D]{x\n"
			"{D[{xv1{D]{x Charges Total:  {D[{c%d{D]{x\n"
			"{D[{xv2{D]{x Charges Left:   {D[{c%d{D]{x\n"
			"{D[{xv3{D]{x Spell:          {c%s{x\n",
			pObj->value[ITEM_WAND_LEVEL],
			pObj->value[ITEM_WAND_CHARGES_TOTAL],
			pObj->value[ITEM_WAND_CHARGES_REMAINING],
			skill_name(pObj->value[ITEM_WAND_SPELL]));
		break;

	case ITEM_PORTAL:
		buf_printf(output,
			    "{D[{xv0{D]{x Charges:        {D[{c%d{D]\n"
			      "[{xv1{D]{x Exit Flags:     {c%s\n"
			    "{D[{xv2{D]{x Portal Flags:   {c%s\n"
			    "{D[{xv3{D]{x Goes to (vnum): {D[{c%d{D] {x%s\n"
			    "{D[{xv4{D]{x Key (vnum):     {D[{c%d{D] %s{x\n",
			    pObj->value[ITEM_PORTAL_CHARGES],
			    flag_string(exit_flags, pObj->value[ITEM_PORTAL_EXIT_FLAGS]),
			    flag_string(portal_flags , pObj->value[ITEM_PORTAL_FLAGS]),
			    pObj->value[ITEM_PORTAL_DEST],
			    ((loc = get_room_index(pObj->value[ITEM_PORTAL_DEST])) == NULL)
				? ""
				: mlstr_mval(loc->name),
			    pObj->value[ITEM_PORTAL_KEY],
			    ((key = get_obj_index(pObj->value[ITEM_PORTAL_KEY])) == NULL)
				? ""
				: OBJ_SHORTNAME(key));
		break;

	case ITEM_PARCHMENT:
		buf_printf(output,
			"{D[{xv1{D]{x Write Flags: {c%s{x\n",
		flag_string(write_flags, pObj->value[ITEM_PARCHMENT_FLAGS]));
		break;

			
	case ITEM_FURNITURE:          
		buf_printf(output,
			    "{D[{xv0{D]{x Max people:      {D[{c%d{D]\n"
			      "[{xv1{D]{x Max weight:      {D[{c%d{D]\n"
			      "[{xv2{D]{x Furniture Flags: {c%s\n"
			    "{D[{xv3{D]{x Heal rate:       {D[{c%d{D]\n"
			      "[{xv4{D]{x Mana rate:       {D[{c%d{D]{x\n",
			    pObj->value[ITEM_FURNITURE_QUANTITY],
			    pObj->value[ITEM_FURNITURE_WEIGHT],
			    flag_string(furniture_flags, pObj->value[ITEM_FURNITURE_FLAGS]),
			    pObj->value[ITEM_FURNITURE_HEAL_RATE],
			    pObj->value[ITEM_FURNITURE_MANA_RATE]);
		break;

	case ITEM_SCROLL:
	case ITEM_POTION:
	case ITEM_PILL:
		buf_printf(output,
			"{D[{xv0{D]{x Level:  {D[{c%d{D]\n"
			  "[{xv1{D]{x Spell:  {c%s\n"
			"{D[{xv2{D]{x Spell:  {c%s\n"
			"{D[{xv3{D]{x Spell:  {c%s\n"
			"{D[{xv4{D]{x Spell:  {c%s{x\n",
			pObj->value[ITEM_POTION_LEVEL],
			skill_name(pObj->value[ITEM_POTION_SPELL1]),
			skill_name(pObj->value[ITEM_POTION_SPELL2]),
			skill_name(pObj->value[ITEM_POTION_SPELL3]),
			skill_name(pObj->value[ITEM_POTION_SPELL4]));
		break;

/* ARMOR for ROM */

	case ITEM_ARMOR:
		buf_printf(output,
			"{D[{xv0{D]{x AC Pierce:      {D[{c%d{D]\n"
			  "[{xv1{D]{x AC Bash:        {D[{c%d{D]\n"
			  "[{xv2{D]{x AC Slash:       {D[{c%d{D]\n"
			  "[{xv3{D]{x AC Exotic:      {D[{c%d{D]\n"
			  "[{xv4{D]{x Armor Type:     {c%s\n"
			"{D[{xv5{D]{x Armor Flags:    {D[{c%s{D]{x\n",
			pObj->value[ITEM_ARMOR_AC_PIERCE],
			pObj->value[ITEM_ARMOR_AC_BASH],
			pObj->value[ITEM_ARMOR_AC_SLASH],
			pObj->value[ITEM_ARMOR_AC_EXOTIC],
			flag_string(armor_types, pObj->value[ITEM_ARMOR_TYPE]),
			flag_string(armor_flags, pObj->value[ITEM_ARMOR_FLAGS])
			);
		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:
/*Zz*/
		autow_avg = get_autoweapon(pObj, &avg_dnum, &avg_dsize, 100);
		w_avg = (1 + pObj->value[ITEM_WEAPON_DICE_SIZE]) 
			* pObj->value[ITEM_WEAPON_DICE_NUM]/2;

		buf_printf(output, "Dam Average:         {%c%d {Dauto: %d (%d%%){x\n",
				w_avg > autow_avg * 1.20                ? 'R' :
				w_avg > autow_avg                       ? 'Y' : 
				w_avg > autow_avg * 0.90		? 'G' :
				w_avg > autow_avg * 0.80                ? 'B' : 'M',
				w_avg, autow_avg,
				(w_avg - autow_avg)*100 / autow_avg +100);

		buf_printf(output, 
			"{D[{xv0{D]{x Weapon class:   {c%s\n"
			"{D[{xv1{D]{x Number of dice: {D[{c%d{D]\n"
			  "[{xv2{D]{x Size of dice:   {D[{c%d{D]\n"
			  "[{xv3{D]{x Attack type:    {c%s\n"
			"{D[{xv4{D]{x Weapon Flags:   {c%s{x\n",
			flag_string(weapon_class, pObj->value[ITEM_WEAPON_TYPE]),
			pObj->value[ITEM_WEAPON_DICE_NUM],
			pObj->value[ITEM_WEAPON_DICE_SIZE],
			attack_table[pObj->value[ITEM_WEAPON_ATTACK_TYPE]].name,
			    flag_string(weapon_type2,  pObj->value[ITEM_WEAPON_FLAGS]));
		break;

	case ITEM_CONTAINER:
		buf_printf(output,
			"{D[{xv0{D]{x Total Weight:    {D[{c%d{x kg{D]\n"
			  "[{xv1{D]{x Flags:           {D[{c%s{D]\n"
			  "[{xv2{D]{x Key:             {D[{c%d{D] {c%s\n"
			"{D[{xv3{D]{x Per Item Weight: {D[{c%d{D]\n"
			  "[{xv4{D]{x Weight Mult:     {D[{c%d{D]\n"
			  "[{xv5{D]{x Max Quantity:    {D[{c%d{D] (0 unlimited){x\n",
			pObj->value[ITEM_CONTAINER_WEIGHT],
			flag_string(cont_flags, pObj->value[ITEM_CONTAINER_FLAGS]),
		        pObj->value[ITEM_CONTAINER_KEY],
			((key = get_obj_index(pObj->value[2])) == NULL)
				? ""
				: OBJ_SHORTNAME(key),
		        pObj->value[ITEM_CONTAINER_PER_ITEM_WEIGHT],
		        pObj->value[ITEM_CONTAINER_WEIGHT_MULTI],
		        pObj->value[ITEM_CONTAINER_QUANTITY]
			);

		if (IS_SET(pObj->extra_flags, ITEM_PIT))
			buf_printf(output, 
				"\n{Y*{x Cost of pit is trash compactor timer. {Y*{x\n");
		break;

	case ITEM_DRINK_CON:
	case ITEM_FOUNTAIN:
		buf_printf(output,
			    "{D[{xv0{D]{x Liquid Total: {D[{c%d{D]\n"
			      "[{xv1{D]{x Liquid Left:  {D[{c%d{D]\n"
			      "[{xv2{D]{x Liquid:       {c%s{x\n"
			    "{D[{xv3{D]{x Poisoned:     {c%s{x\n",
			    pObj->value[ITEM_DRINK_TOTAL],
			    pObj->value[ITEM_DRINK_REMAINING],
			    liq_table[pObj->value[ITEM_DRINK_TYPE]].liq_name,
			    pObj->value[ITEM_DRINK_POISON] ? "Yes" : "No");
		break;

	case ITEM_FOOD:
		buf_printf(output,
			"{D[{xv0{D]{x Food hours: {D[{c%d{D]\n"
			  "[{xv1{D]{x Full hours: {D[{c%d{D]\n"
			  "[{xv3{D]{x Poisoned:   {c%s{x\n",
			pObj->value[ITEM_FOOD_HOURS],
			pObj->value[ITEM_FOOD_FULL],
			pObj->value[ITEM_FOOD_POISON] ? "Yes" : "No");
		break;

	case ITEM_MONEY:
		buf_printf(output, "{D[{xv0{D]{x Silver: {D[{W%d{D]\n"
				     "[{xv1{D]{x Gold:   {D[{G%d{D]{x\n",
			   pObj->value[ITEM_MONEY_SILVER], 
			   pObj->value[ITEM_MONEY_GOLD]);
		break;

	case ITEM_AWARD:
		buf_printf(output, "{D[{xv0{D]{x Type: {D[{c%s{D]\n"
				     "[{xv1{D]{x Value:{D[{c%d{D]{x\n",
			flag_string(award_types, pObj->value[ITEM_AWARD_TYPE]),
			pObj->value[ITEM_AWARD_VALUE]);
		break;
	}
}

OLC_FUN(objed_autoweapon)
{
	OBJ_INDEX_DATA *pObj;
	EDIT_OBJ(ch, pObj);

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

	if (pObj->level < 1)
	{
		send_to_char( "{cAutoweapon requires a level to be set on the weapon first.{x\n\r", ch);
		return FALSE;
	}

	get_autoweapon(pObj, &pObj->value[1], &pObj->value[2], 100);
	pObj->cost = 25 * (pObj->value[2] * (pObj->value[1] + 1)) + 20 * pObj->level;
	pObj->weight = pObj->level + 1;

	send_to_char("{cExperimental values set on weapon...{x\n\r", ch);
	return TRUE;
}

OLC_FUN(objed_autoarmor)
{
	OBJ_INDEX_DATA *pObj;
	int size;
	EDIT_OBJ(ch, pObj);

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

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

	size = UMAX(1, pObj->level/2.8 + 1);

	pObj->weight = pObj->level + 1;
	pObj->cost = pObj->level^2 * 2;
	pObj->value[0] = size;
	pObj->value[1] = size;
	pObj->value[2] = size;
	pObj->value[3] = (size - 1);

	send_to_char( "{cAutoArmor has set experimental values for AC.{x\n", ch);
	return TRUE;
}

/*
 * Return values:
 *	0 - pObj was changed successfully
 *	1 - pObj was not changed
 *	2 - pObj was not changed, do not show obj values
 */
int set_obj_values(BUFFER *output, OBJ_INDEX_DATA *pObj,
		   const char *argument, int value_num)
{
	OBJ_INDEX_DATA *key = NULL;

	switch (pObj->item_type) {
		int	val;

	default:
		return 1;
		     
	case ITEM_LIGHT:
		switch (value_num) {
		default:
			return 1;
		case ITEM_LIGHT_DURATION:
			buf_add(output, "HOURS OF LIGHT SET.\n\n");
			pObj->value[ITEM_LIGHT_DURATION] = atoi(argument);
			break;
		}
		break;

	case ITEM_WAND:
	case ITEM_STAFF:
		switch (value_num) {
		default:
			return 1;
		case ITEM_WAND_LEVEL:
			buf_add(output, "SPELL LEVEL SET.\n\n");
			pObj->value[ITEM_WAND_LEVEL] = atoi(argument);
			break;
		case ITEM_WAND_CHARGES_TOTAL:
			buf_add(output, "TOTAL NUMBER OF CHARGES SET.\n\n");
			pObj->value[ITEM_WAND_CHARGES_TOTAL] = atoi(argument);
			break;
		case ITEM_WAND_CHARGES_REMAINING:
			buf_add(output, "CURRENT NUMBER OF CHARGES SET.\n\n");
			pObj->value[ITEM_WAND_CHARGES_REMAINING] = atoi(argument);
			break;
		case ITEM_WAND_SPELL:
			if (!str_cmp(argument, "?")
			||  (val = sn_lookup(argument)) < 0) {
				show_spells(output, -1);
				return 2;
			}
			buf_add(output, "SPELL TYPE SET.\n");
			pObj->value[ITEM_WAND_SPELL] = val;
			break;
		}
		break;

	case ITEM_SCROLL:
	case ITEM_POTION:
	case ITEM_PILL:
		switch (value_num) {
		case ITEM_POTION_LEVEL:
			buf_add(output, "SPELL LEVEL SET.\n\n");
			pObj->value[ITEM_POTION_LEVEL] = atoi(argument);
			break;
		case ITEM_POTION_SPELL1:
		case ITEM_POTION_SPELL2:
		case ITEM_POTION_SPELL3:
		case ITEM_POTION_SPELL4:
			if (!str_cmp(argument, "?")
			||  (val = sn_lookup(argument)) < 0) {
				show_spells(output, -1);
				return 2;
			}
			buf_printf(output, "SPELL TYPE %d SET.\n\n", value_num);
			pObj->value[value_num] = val;
			break;
 		}
		break;

/* ARMOR for ROM: */

	case ITEM_ARMOR:
		switch (value_num) {
		default:
			return 1;
		case ITEM_ARMOR_AC_PIERCE:
			buf_add(output, "AC PIERCE SET.\n\n");
			pObj->value[ITEM_ARMOR_AC_PIERCE] = atoi(argument);
			break;
		case ITEM_ARMOR_AC_BASH:
			buf_add(output, "AC BASH SET.\n\n");
			pObj->value[ITEM_ARMOR_AC_BASH] = atoi(argument);
			break;
		case ITEM_ARMOR_AC_SLASH:
			buf_add(output, "AC SLASH SET.\n\n");
			pObj->value[ITEM_ARMOR_AC_SLASH] = atoi(argument);
			break;
		case ITEM_ARMOR_AC_EXOTIC:
			buf_add(output, "AC EXOTIC SET.\n\n");
			pObj->value[ITEM_ARMOR_AC_EXOTIC] = atoi(argument);
			break;

		case ITEM_ARMOR_TYPE:
			if (!str_cmp(argument, "?")
			||  (val = flag_value(armor_types, argument)) < 0) {
				show_flags_buf(output, armor_types);
				return 2;
			}
			buf_add(output, "ARMOR TYPE SET.\n\n");
			pObj->value[ITEM_ARMOR_TYPE] = val;
			break;

		case ITEM_ARMOR_FLAGS:
			if (!str_cmp(argument, "?")
			||  (val = flag_value(armor_flags, argument)) < 0) {
				show_flags_buf(output, armor_flags);
				return 2;
			}
			buf_add(output, "ARMOR FLAG SET.\n\n");
			TOGGLE_BIT(pObj->value[ITEM_ARMOR_FLAGS], val);
			break;
		}
		break;

/* WEAPONS changed in ROM */

	case ITEM_WEAPON:
		switch (value_num) {
		default:
			return 1;
		case ITEM_WEAPON_TYPE:
			if (!str_cmp(argument, "?")
			||  (val = flag_value(weapon_class, argument)) < 0) {
				show_flags_buf(output, weapon_class);
				return 2;
			}
			buf_add(output, "WEAPON TYPE SET.\n\n");
			pObj->value[ITEM_WEAPON_TYPE] = val;
			break;
		case ITEM_WEAPON_DICE_NUM:
			buf_add(output, "NUMBER OF DICE SET.\n\n");
			pObj->value[ITEM_WEAPON_DICE_NUM] = atoi(argument);
			break;
		case ITEM_WEAPON_DICE_SIZE:
			buf_add(output, "TYPE OF DICE SET.\n\n");
			pObj->value[ITEM_WEAPON_DICE_SIZE] = atoi(argument);
			break;
		case ITEM_WEAPON_ATTACK_TYPE:
			if (!str_cmp(argument, "?")
			||  (val = attack_lookup(argument)) < 0) {
				show_attack_types(output);
				return 2;
			}
			buf_add(output, "WEAPON TYPE SET.\n\n");
			pObj->value[ITEM_WEAPON_ATTACK_TYPE] = val;
			break;
		case ITEM_WEAPON_FLAGS:
			if (!str_cmp(argument, "?")
			||  (val = flag_value(weapon_type2, argument)) < 0) {
				show_flags_buf(output, weapon_type2);
				return 2;
			}
			buf_add(output, "SPECIAL WEAPON TYPE TOGGLED.\n\n");
			TOGGLE_BIT(pObj->value[ITEM_WEAPON_FLAGS], val);
			break;
		}
		break;

	case ITEM_PORTAL:
		switch (value_num) {
		default:
			return 1;
		case ITEM_PORTAL_CHARGES:
			buf_add(output, "CHARGES SET.\n\n");
				     pObj->value[ITEM_PORTAL_CHARGES] = atoi(argument);
			break;
		case ITEM_PORTAL_EXIT_FLAGS:
			if (!str_cmp(argument, "?")
			||  (val = flag_value(exit_flags, argument)) < 0) {
				show_flags_buf(output, exit_flags);
				return 2;
			}
			buf_add(output, "EXIT FLAGS TOGGLED.\n\n");
			TOGGLE_BIT(pObj->value[ITEM_PORTAL_EXIT_FLAGS], val);
			break;
		case ITEM_PORTAL_FLAGS:
			if (!str_cmp(argument, "?")
			||  (val = flag_value(portal_flags, argument)) < 0) {
				show_flags_buf(output, portal_flags);
				return 2;
			}
			buf_add(output, "PORTAL FLAGS TOGGLED.\n\n");
			TOGGLE_BIT(pObj->value[ITEM_PORTAL_FLAGS], val);
			break;
		case ITEM_PORTAL_DEST:
			buf_add(output, "EXIT VNUM SET.\n\n");
			pObj->value[ITEM_PORTAL_DEST] = atoi(argument);
			break;
		case ITEM_PORTAL_KEY:
			if ((key = get_obj_index(atoi(argument))) == NULL) {
				buf_add(output, "ObjEd: key vnum doesn't exist.\n");
				return 2;
			}
			pObj->value[ITEM_PORTAL_KEY] = key->vnum;
			buf_printf(output, "PORTAL KEY SET [%d] %s",
				key->vnum,
				OBJ_SHORTNAME(key));
			break;
		}
		break;

	case ITEM_PARCHMENT:
		switch (value_num) {
		default:
			return 1;
		case ITEM_PARCHMENT_FLAGS:
			if(!str_cmp(argument, "?") 
			|| (val = flag_value(write_flags, argument)) < 0) {
				show_flags_buf(output, write_flags);
				return 1;
			}
			buf_add(output, "WRITE FLAG TOGGLED.\n\n");
			TOGGLE_BIT(pObj->value[ITEM_PARCHMENT_FLAGS], val);
				break;
		}
		break;

	case ITEM_FURNITURE:
		switch (value_num) {
		default:
			return 1;
		case ITEM_FURNITURE_QUANTITY:
			buf_add(output, "NUMBER OF PEOPLE SET.\n\n");
			pObj->value[ITEM_FURNITURE_QUANTITY] = atoi(argument);
			break;
		case ITEM_FURNITURE_WEIGHT:
			buf_add(output, "MAX WEIGHT SET.\n\n");
			pObj->value[ITEM_FURNITURE_WEIGHT] = atoi(argument);
			break;
		case ITEM_FURNITURE_FLAGS:
			if (!str_cmp(argument, "?")
			||  (val = flag_value(furniture_flags, argument)) < 0) {
				show_flags_buf(output, furniture_flags);
				return 2;
			}
		        buf_add(output, "FURNITURE FLAGS TOGGLED.\n\n");
			TOGGLE_BIT(pObj->value[ITEM_FURNITURE_FLAGS], val);
			break;
		case ITEM_FURNITURE_HEAL_RATE:
			buf_add(output, "HEAL RATE SET (100 is normal).\n\n");
			pObj->value[ITEM_FURNITURE_HEAL_RATE] = atoi(argument);
			break;
		case ITEM_FURNITURE_MANA_RATE:
			buf_add(output, "MANA RATE SET (100 is normal).\n\n");
			pObj->value[ITEM_FURNITURE_MANA_RATE] = atoi(argument);
			break;
		}
		break;
		   
	case ITEM_CONTAINER:
		switch (value_num) {
		default:
			return 1;
		case ITEM_CONTAINER_WEIGHT:
			buf_add(output, "TOTAL MAX WEIGHT CAPACITY SET.\n\n");
			pObj->value[ITEM_CONTAINER_WEIGHT] = atoi(argument);
			break;
		case ITEM_CONTAINER_FLAGS:
			if (!str_cmp(argument, "?")
			||  (val = flag_value(cont_flags, argument)) < 0) {
				show_flags_buf(output, cont_flags);
				return 2;
			}
			buf_add(output, "CONTAINER FLAGS SET.\n\n");
			TOGGLE_BIT(pObj->value[ITEM_CONTAINER_FLAGS], val);
			break;
		case ITEM_CONTAINER_KEY:
			if (atoi(argument) != 0) {
				if ((key = get_obj_index(atoi(argument))) == NULL) {
					buf_add(output, "THERE IS NO SUCH ITEM.\n\n");
					return 1;
				}

				if (key->item_type != ITEM_KEY) {
					buf_add(output, "THAT ITEM IS NOT A KEY.\n\n");
					return 1;
				}
			}
			buf_add(output, "CONTAINER KEY SET.\n\n");
			pObj->value[ITEM_CONTAINER_KEY] = key->vnum;
			buf_printf(output, "CONTAINER KEY SET [%d] %s",
				key->vnum,
				OBJ_SHORTNAME(key));
			break;
		case ITEM_CONTAINER_PER_ITEM_WEIGHT:
			buf_add(output, "CONTAINER MAX INDIVIDUAL ITEM WEIGHT SET.\n");
			pObj->value[ITEM_CONTAINER_PER_ITEM_WEIGHT] = atoi(argument);
			break;
		case ITEM_CONTAINER_WEIGHT_MULTI:
			buf_add(output, "WEIGHT MULTIPLIER SET.\n\n");
			pObj->value[ITEM_CONTAINER_WEIGHT_MULTI] = atoi(argument);
			break;
		case ITEM_CONTAINER_QUANTITY:
			buf_add(output, "CONTAINER MAX QUANTITY SET.\n\n");
			pObj->value[ITEM_CONTAINER_QUANTITY] = atoi(argument);
			break;
		}
		break;

	case ITEM_DRINK_CON:
	case ITEM_FOUNTAIN:
		switch (value_num) {
		default:
			return 1;
		case ITEM_DRINK_TOTAL:
			buf_add(output, "MAXIMUM AMOUT OF LIQUID SET.\n\n");
			pObj->value[ITEM_DRINK_TOTAL] = atoi(argument);
			break;
		case ITEM_DRINK_REMAINING:
			buf_add(output, "CURRENT AMOUNT OF LIQUID SET.\n\n");
			pObj->value[ITEM_DRINK_REMAINING] = atoi(argument);
			break;
		case ITEM_DRINK_TYPE:
			if (!str_cmp(argument, "?")
			||  (val = liq_lookup(argument)) < 0) {
				show_liq_types(output);
				return 2;
			}
			buf_add(output, "LIQUID TYPE SET.\n\n");
			pObj->value[ITEM_DRINK_TYPE] = val;
			break;
		case ITEM_DRINK_POISON:
			buf_add(output, "POISON VALUE TOGGLED.\n\n");
			pObj->value[ITEM_DRINK_POISON] = !pObj->value[ITEM_DRINK_POISON];
			break;
		}
		break;

	case ITEM_FOOD:
		switch (value_num) {
		default:
			return 1;
		case ITEM_FOOD_HOURS:
			buf_add(output, "HOURS OF FOOD SET.\n\n");
			pObj->value[ITEM_FOOD_HOURS] = atoi(argument);
			break;
		case ITEM_FOOD_FULL:
			buf_add(output, "HOURS OF FULL SET.\n\n");
			pObj->value[ITEM_FOOD_FULL] = atoi(argument);
			break;
		case ITEM_FOOD_POISON:
			buf_add(output, "POISON VALUE TOGGLED.\n\n");
			pObj->value[ITEM_FOOD_POISON] = !pObj->value[ITEM_FOOD_POISON];
			break;
		}
		break;

	case ITEM_MONEY:
		switch (value_num) {
		default:
			return 1;
		case ITEM_MONEY_SILVER:
			buf_add(output, "SILVER AMOUNT SET.\n\n");
			pObj->value[ITEM_MONEY_SILVER] = atoi(argument);
			break;
		case ITEM_MONEY_GOLD:
			buf_add(output, "GOLD AMOUNT SET.\n\n");
			pObj->value[ITEM_MONEY_GOLD] = atoi(argument);
			break;
		}
		break;

	case ITEM_AWARD:
		switch (value_num) {
		default:
			return 1;
		case ITEM_AWARD_TYPE:
			if (!str_cmp(argument, "?")
			||  (val = flag_value(award_types, argument)) < 0) {
				show_flags_buf(output, award_types);
				return 2;
			}
			buf_add(output, "AWARD TYPE SET.\n\n");
			pObj->value[ITEM_AWARD_TYPE] = val;
			break;
		case ITEM_AWARD_VALUE:
			buf_add(output, "AWARD AMOUNT SET.\n\n");
			pObj->value[ITEM_AWARD_VALUE] = atoi(argument);
			break;
		}
		break;
	}
	return 0;
}

/*****************************************************************************
 Name:		show_spells
 Purpose:	Displays all spells.
 ***************************************************************************/
static void show_spells(BUFFER *output, int tar)
{
	int  sn;
	int  col;
 
	col = 0;
	for (sn = 0; sn < skills.nused; sn++) {
		skill_t *sk = SKILL(sn);

		if (!str_cmp(sk->name, "reserved") || sk->spell_fun == NULL)
			continue;

		if (tar == -1 || sk->target == tar) {
			buf_printf(output, "%-19.18s", sk->name);
			if (++col % 4 == 0)
				buf_add(output, "\n");
		}
	}
 
	if (col % 4 != 0)
		buf_add(output, "\n");
}

void show_liqlist(CHAR_DATA *ch)
{
	int liq;
	BUFFER *buffer;
	
	buffer = buf_new(-1);
	
	for (liq = 0; liq_table[liq].liq_name != NULL; liq++) {
		if ((liq % 21) == 0)
			buf_add(buffer,"Name                 Color          Proof Full Thirst Food Ssize\n");

		buf_printf(buffer, "%-20s %-14s %5d %4d %6d %4d %5d\n",
			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]);
	}

	page_to_char(buf_string(buffer), ch);
	buf_free(buffer);
}

#if 0
	{ "type",	item_types,	"Types of objects."		},
	{ "extra",	extra_flags,	"Object attributes."		},
	{ "wear",	wear_flags,	"Where to wear object."		},
	{ "wear-loc",	wear_loc_flags,	"Where mobile wears object."	},
	{ "container",	cont_flags,"Container status."		},

/* ROM specific bits: */

	{ "armor",	ac_type,	"Ac for different attacks."	},
	{ "apply",	apply_flags,	"Apply flags"			},
	{ "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."		},
	{ NULL,		NULL,		 NULL				}
};
#endif

VALIDATE_FUN(validate_condition)
{
	int val = *(int*) arg;

	if (val < 0 || val > 100) {
		char_puts("ObjEd: condition can range from 0 (ruined) "
			  "to 100 (perfect).\n", ch);
		return FALSE;
	}
	return TRUE;
}

/* get_autoweapon - calculates the appropriate damage values
 * 	for different types of weapons.
 * 	The Object is not modified, only the r_dice and r_size values.
 *
 * 	percent_damage - applied against normal damage for the item
 *
 * by Zsuzsu
 */
int get_autoweapon(OBJ_INDEX_DATA* pObj, int *r_dice, int *r_size, int percent_damage) {
	int dice, size; 
	double avg;
        bool twoh = IS_WEAPON_STAT(pObj, WEAPON_TWO_HANDS);

	/*two-handed, bigger dice size for greater variation*/
	if (twoh) 
		dice = (pObj->level/30 + 1);
	else 
		dice = (pObj->level/20 + 1);

	avg = pObj->level;

	avg = avg * percent_damage / 100;

	switch (pObj->value[0])
	{
		case WEAPON_POLEARM:       avg *= (twoh) ? 0.80 : 0.00; dice-=2; break;
		case WEAPON_LANCE:         avg *= (twoh) ? 0.00 : 0.70; break;
		case WEAPON_BASTARDSWORD:  avg *= (twoh) ? 0.75 : 0.00; break;
		case WEAPON_KATANA:	   avg *= (twoh) ? 0.00 : 0.75; break;
		case WEAPON_LONGSWORD:     avg *= (twoh) ? 0.00 : 0.65; break;
		case WEAPON_AXE:	   avg *= (twoh) ? 0.75 : 0.65; break;
		case WEAPON_HAMMER:	   avg *= (twoh) ? 0.70 : 0.60; break;
		case WEAPON_SPEAR:	   avg *= (twoh) ? 0.70 : 0.55; break;
		case WEAPON_MACE:	   avg *= (twoh) ? 0.67 : 0.55; break;
		case WEAPON_FLAIL:	   avg *= (twoh) ? 0.67 : 0.55; break;
		case WEAPON_STAFF:         avg *= (twoh) ? 0.67 : 0.55; break;
		case WEAPON_BOW:           avg *= (twoh) ? 0.65 : 0.00; break;
		case WEAPON_SHORTSWORD:	   avg *= (twoh) ? 0.00 : 0.50; dice++; break;
		case WEAPON_DAGGER:	   avg *= (twoh) ? 0.00 : 0.45; dice++; break;
		case WEAPON_WHIP: 	   avg *= (twoh) ? 0.00 : 0.40; break;
		case WEAPON_ARROW:	   avg *= (twoh) ? 0.00 : 0.60; dice+=2;break;
		case WEAPON_SHURIKEN:	   avg *= (twoh) ? 0.00 : 0.10; break;
		case WEAPON_EXOTIC:
		default:
					   avg *= (twoh) ? 0.70 : 0.55; dice--; break;
	}

	/* if avg is 0 then there must be something wrong */
	if (avg <= 0.0) {
		DEBUG(DEBUG_BUILD_AUTO,
			"Autoweapon: obj[%d] has 0 avg damage",
			pObj->vnum, avg);
		*r_dice = 1;
		*r_size = 1;
		return 1;
	}

	if (pObj->value[0] != WEAPON_KATANA) {
		dice = UMAX(1, dice);

		size = 2 * avg / dice -1;

		size = UMAX(1, size);
	}
	/* katana - needs to be closer to average because of 'master sword'*/
	else {
		size = UMAX(1, dice);
		dice = 2 * avg / (size +1);
		dice = UMAX(1, dice);
	}

	*r_dice = dice;
	*r_size = size;

	return (1 + *r_size) * *r_dice / 2;
}

int get_autocost (OBJ_INDEX_DATA *pObjIndex)
{
	int level = pObjIndex->level;
	int cost = 1;
	int bp = 0, bpmax = 0;
	int liquid = 0;

	build_points(pObjIndex, &bp, &bpmax);

	cost = bp * 100;

	if (IS_OBJ_LIMITED(pObjIndex))
		cost = cost * 2;
	else if (IS_OBJ_RARE(pObjIndex))
		cost = cost * 3/2;
		
	switch (pObjIndex->item_type) {
	case ITEM_LIGHT:
		cost = cost * 1/2; break;
		if (!cost)
			cost = 20 * level;
		break;

	case ITEM_FOOD:
		cost = cost * 10/100;
		if (!cost) {
			cost = (pObjIndex->value[ITEM_FOOD_HOURS] * 12)
				- (pObjIndex->value[ITEM_FOOD_FULL] * 2);
		}
		
		break;

	case ITEM_DRINK_CON:
		cost = cost * 20/100;
		liquid = pObjIndex->value[ITEM_DRINK_TYPE];
		if (!cost) {
			cost = (pObjIndex->value[ITEM_DRINK_TOTAL] * 60)
				+ (pObjIndex->value[ITEM_DRINK_REMAINING] * 2);
			cost = cost * (100 
				+ liq_table[liquid].liq_affect[LIQ_AFFECT_PROOF]) / 100;
		}
		break;

	case ITEM_BOAT:
		if (!cost) cost = 2000;
		cost = cost * UMAX(10, 1000 - pObjIndex->weight) / 10;
		break;

	case ITEM_WEAPON:
		cost = cost * UMAX(1, (pObjIndex->level / 10));

		switch (pObjIndex->value[ITEM_WEAPON_TYPE]) {
		case WEAPON_KATANA:       cost = cost * 500 / 100; break;
		case WEAPON_BASTARDSWORD: cost = cost * 180 / 100; break;
		case WEAPON_LONGSWORD:    cost = cost * 150 / 100; break;
		case WEAPON_SHORTSWORD:   cost = cost *  70 / 100; break;
		case WEAPON_DAGGER:	  cost = cost *  50 / 100; break;
		case WEAPON_AXE:          cost = cost * 140 / 100; break;
		case WEAPON_MACE:	  cost = cost *  80 / 100; break;
		case WEAPON_HAMMER:       cost = cost * 100 / 100; break;
		case WEAPON_FLAIL:	  cost = cost * 110 / 100; break;
		case WEAPON_WHIP:	  cost = cost *  30 / 100; break;
		case WEAPON_POLEARM:	  cost = cost * 200 / 100; break;
		case WEAPON_LANCE:	  cost = cost * 200 / 100; break;
		case WEAPON_BOW:	  cost = cost * 120 / 100; break;
		case WEAPON_ARROW:	  cost = cost *  20 / 100; break;
		case WEAPON_STAFF:	  cost = cost *  60 / 100; break;
		case WEAPON_SHURIKEN:	  cost = cost *  20 / 100; break;
		case WEAPON_EXOTIC:       cost = cost * 120 / 100; break;
		}

		if (IS_SET(pObjIndex->value[ITEM_WEAPON_FLAGS], WEAPON_TWO_HANDS)) {
			switch (pObjIndex->value[ITEM_WEAPON_TYPE]) {
			case WEAPON_POLEARM:
			case WEAPON_BOW:
			case WEAPON_LANCE:
			case WEAPON_BASTARDSWORD:
				break;
			default:
				cost = cost * 170/100;
			}
		}

		break;

	case ITEM_ARMOR:
		cost = cost * 150/100;
		/* fall through */
	case ITEM_CLOTHING:
		cost = cost * UMAX(1, (pObjIndex->level / 10));

		if (IS_SET(pObjIndex->wear_flags, ITEM_WEAR_FINGER))
			cost = cost *  70/100;
		else if (IS_SET(pObjIndex->wear_flags, ITEM_WEAR_NECK))
			cost = cost *  80/100;
		else if (IS_SET(pObjIndex->wear_flags, ITEM_WEAR_LEGS))
			cost = cost * 130/100;
		else if (IS_SET(pObjIndex->wear_flags, ITEM_WEAR_FEET))
			cost = cost * 100/100;
		else if (IS_SET(pObjIndex->wear_flags, ITEM_WEAR_HANDS))
			cost = cost * 110/100;
		else if (IS_SET(pObjIndex->wear_flags, ITEM_WEAR_ARMS))
			cost = cost * 120/100;
		else if (IS_SET(pObjIndex->wear_flags, ITEM_WEAR_BODY))
			cost = cost * 200/100;
		else if (IS_SET(pObjIndex->wear_flags, ITEM_WEAR_SHIELD))
			cost = cost * 130/100;
		else if (IS_SET(pObjIndex->wear_flags, ITEM_WEAR_ABOUT))
			cost = cost * 110/100;
		else if (IS_SET(pObjIndex->wear_flags, ITEM_WEAR_WAIST))
			cost = cost *  90/100;
		else if (IS_SET(pObjIndex->wear_flags, ITEM_WEAR_WRIST))
			cost = cost *  80/100;
		else if (IS_SET(pObjIndex->wear_flags, ITEM_WEAR_FLOAT))
			cost = cost * 180/100;
		
		break;

	case ITEM_CONTAINER:
		cost += pObjIndex->value[ITEM_CONTAINER_WEIGHT] * 10;
		if (IS_SET(pObjIndex->value[ITEM_CONTAINER_FLAGS], CONT_QUIVER))
			cost = cost * 200/100;
		if (IS_SET(pObjIndex->value[ITEM_CONTAINER_FLAGS], CONT_SCROLL))
			cost = cost * 120/100;
		if (IS_SET(pObjIndex->value[ITEM_CONTAINER_FLAGS], CONT_POTION))
			cost = cost * 120/100;
		if (IS_SET(pObjIndex->value[ITEM_CONTAINER_FLAGS], CONT_PILL))
			cost = cost * 130/100;
		if (IS_SET(pObjIndex->value[ITEM_CONTAINER_FLAGS], CONT_WAND))
			cost = cost * 130/100;
		if (IS_SET(pObjIndex->value[ITEM_CONTAINER_FLAGS], CONT_STAFF))
			cost = cost * 140/100;
		if (IS_SET(pObjIndex->value[ITEM_CONTAINER_FLAGS], CONT_PICKPROOF))
			cost = cost * 300/100;

		if (IS_SET(pObjIndex->extra_flags, ITEM_BURN_PROOF))
			cost = cost * 500/100;

		break;

	case ITEM_WARP_STONE:
	case ITEM_SCROLL:
	case ITEM_WAND:
	case ITEM_STAFF:
	case ITEM_POTION:
	case ITEM_TRASH:
	default:
		cost = 0; break;


	}

	if (!IS_SET(pObjIndex->wear_flags, ITEM_TAKE))
		cost = 0;

	return cost;
}

/*
 * Calculate Build Points for the item
 * by Zsuzsu
 * XXX - one problem with this is if multiple
 * 	affects are added for the same location.
 * 	This will throw off the total.
 */
void build_points (OBJ_INDEX_DATA *pObj, int *bp, int *bpmax) {

	AFFECT_DATA *paf;
	int i;
	int elem_count = 0,
	    misc_count = 0,
	    level      = 0,
	    base_max   = 0,
	    stat_pos   = 0,
	    stat_neg   = 0;
	int count = 0;
	int item_max = 0;
	int autow_avg  = 0,
	    avg_dnum   = 0,
	    avg_dsize  = 0,
	    w_avg      = 0;


	*bp = 0;
	*bpmax = 0;

	/* don't count items you can't take */
	if (!IS_SET(pObj->wear_flags, ITEM_TAKE))
		return;

	level = (pObj->level > 10) ? pObj->level : 10;

	base_max = level * 3;

	*bpmax = level * (IS_OBJ_LIMITED(pObj) ? 5 :
		    IS_OBJ_RARE(pObj)          ? 4 : 
			    		         3);

	for (paf = pObj->affected; paf; paf = paf->next) {
		switch (paf->location) {
			case APPLY_STR:
			case APPLY_DEX:
			case APPLY_INT:
			case APPLY_WIS:
			case APPLY_CON:
			case APPLY_CHA:
				if (paf->modifier > 0)
					stat_pos += paf->modifier;
				else
					stat_neg += ABS(paf->modifier);
				break;

			case APPLY_AC:
				if (paf->modifier < 0) {
					i = ABS(paf->modifier) - level / 5; 
					i = (i > 0) ? i : 0;

					*bp += (ABS(paf->modifier) - i) * 1 ;
					*bp += i * 2;
				}
				else
					*bpmax += paf->modifier;
				break;

			case APPLY_MOVE:
				if (paf->modifier > 0) {
					i = paf->modifier - (level/10)*20; 
					i = (i > 0) ? i : 0;

					*bp += (paf->modifier - i) *1 ;
					*bp += i * 2;
				}
				else
					*bpmax += ABS(paf->modifier) / 2;
				break;

			case APPLY_MANA:
				if (paf->modifier > 0) {
					i = paf->modifier - (level/10)*20; 
					i = (i > 0) ? i : 0;

					*bp += (paf->modifier - i) *1 ;
					*bp += i * 2;
				}
				else
					*bpmax += ABS(paf->modifier) / 2;
				break;

			case APPLY_HIT:
				if (paf->modifier > 0) {
					i = paf->modifier - (level/10)*10; 
					i = (i > 0) ? i : 0;

					*bp += (paf->modifier - i) * 2;
					*bp += i * 3;
				}
				else
					*bpmax += ABS(paf->modifier) * 1;
				break;

			case APPLY_HITROLL:
			case APPLY_DAMROLL:
				if (paf->modifier > 0) {
					i = paf->modifier - (level / 10); 
					i = (i > 0) ? i : 0;

					*bp += (paf->modifier - i) * 10;
					*bp += i * 15;
				}
				else
					*bpmax += ABS(paf->modifier) * 8;
				break;

			case APPLY_SAVES:
			/* case APPLY_SAVING_PARA: */
			case APPLY_SAVING_ROD:
			case APPLY_SAVING_PETRI:
			case APPLY_SAVING_BREATH:
			case APPLY_SAVING_SPELL:
				if (paf->modifier < 0) {
					i = ABS(paf->modifier) - (level / 10); 
					i = (i > 0) ? i : 0;

					*bp += (ABS(paf->modifier) - i) * 20;
					*bp += i * 30;
				}
				else
					*bpmax += paf->modifier * 20;
				break;

			case APPLY_SPELL_AFFECT:
				break;

			case APPLY_LEVEL:
			case APPLY_RACE:
			case APPLY_SIZE:
				*bp = 1000;
				break;

			case APPLY_SEX:
			case APPLY_AGE:
			case APPLY_CLASS:
			case APPLY_HEIGHT:
			case APPLY_WEIGHT:
			case APPLY_GOLD:
			case APPLY_EXP:
			default:
				break;
		}
	}

	/* calc stat modifier costs */
	for (i = 1; i <= stat_pos; i++) {
		*bp += i * 10 + 10;
	}

	for (i = 1; i <= stat_neg; i++) {
		*bpmax += i * 7 + 7;
	}

	/* calc weapon flag costs */
	switch (pObj->item_type) {
	case ITEM_WEAPON:
		autow_avg = get_autoweapon(pObj, &avg_dnum, &avg_dsize, 100);
		w_avg = (1 + pObj->value[2]) * pObj->value[1]/2;

		if (w_avg > (autow_avg * 150/100))
			*bp += 1000;
		if (w_avg > (autow_avg * 140/100))
			*bp += IS_OBJ_LIMITED(pObj) ? base_max*5/3 : 1000;
		else if (w_avg > autow_avg * 130/100)
			*bp += base_max;
		else if (w_avg > autow_avg * 120/100)
			*bp += base_max * 2/3;
		else if (w_avg > autow_avg * 110/100)
			*bp += base_max * 1/2;
		else if (w_avg > autow_avg * 105/100)
			*bp += base_max * 1/3;
		else if (w_avg > autow_avg)
			*bp += base_max * 1/4;

		if (IS_WEAPON_STAT(pObj,WEAPON_FLAMING)) {
			*bp += base_max * 0.30;
			elem_count++;
		}
		if (IS_WEAPON_STAT(pObj,WEAPON_SHOCKING)) {
			*bp += base_max * 0.20;
			elem_count++;
		}
		if (IS_WEAPON_STAT(pObj,WEAPON_FROST)) {
			*bp += base_max * 0.20;
			elem_count++;
		}
		if (elem_count > 1)
			*bp += 1000;

		if (IS_WEAPON_STAT(pObj,WEAPON_VAMPIRIC)) {
			*bp += base_max * 0.20;
			misc_count++;
		}
		if (IS_WEAPON_STAT(pObj,WEAPON_SHARP)) {
			*bp += base_max * 0.20;
			misc_count++;
		}
		if (IS_WEAPON_STAT(pObj,WEAPON_VORPAL)) {
			*bp += base_max * 0.20;
			misc_count++;
		}
		if (IS_WEAPON_STAT(pObj,WEAPON_POISON))	{
			*bp += base_max * 0.15;
			misc_count++;
		}
		if (IS_WEAPON_STAT(pObj,WEAPON_HOLY)) {
			*bp += base_max * 0.20;
			misc_count++;
		}
		if (IS_WEAPON_STAT(pObj,WEAPON_KATANA))	{
			*bp += base_max * 0.20;
			misc_count++;
		}
		if (IS_WEAPON_STAT(pObj,WEAPON_CRUSH)) {
			*bp += base_max * 0.20;
			misc_count++;
		}

		*bp += (misc_count > 2) 
			? (misc_count -2) * base_max * 0.30
			: 0;

		if (!IS_OBJ_LIMITED(pObj) 
		&& elem_count + misc_count > 2)
			*bp += 1000;

		break;

	case ITEM_CONTAINER:
		item_max = 100;
		/* establishes maximum capacity for each type*/
		if (IS_CONTAINER_TYPE(pObj, CONT_QUIVER)) {
			count++;
			item_max = UMIN(item_max, 50);
		}
		if (IS_CONTAINER_TYPE(pObj, CONT_SCROLL)) {
			count++;
			item_max = UMIN(item_max, 25);
		}
		if (IS_CONTAINER_TYPE(pObj, CONT_PILL)) {
			count++;
			item_max = UMIN(item_max, 25);
		}
		if (IS_CONTAINER_TYPE(pObj, CONT_POTION)) {
			count++;
			item_max = UMIN(item_max, 15);
		}
		if (IS_CONTAINER_TYPE(pObj, CONT_WAND)) {
			count++;
			item_max = UMIN(item_max, 10);
		}
		if (IS_CONTAINER_TYPE(pObj, CONT_STAFF)) {
			count++;
			item_max = UMIN(item_max, 5);
		}

#if 0
		/* XXX - this really doesn't mean number of items, 
		 * need to do this later */
		/* capacity */
		if (pObj->value[3] > item_max)
			*bp += base_max * (pObj->value[3] - item_max) * 0.10;
#endif

		if (count > 1)
			*bp += base_max * ((count -1) * 0.33);

		/* BPs for weight multiplier */
		if (pObj->value[4] < 20) {
			*bp += 1000;
		}

		else if (pObj->value[4] > 100) {
			*bp += ABS(100 - pObj->value[4]) * 2;
		}
		else 
			*bp += (100 - pObj->value[4]) * 2;
		break;

	case ITEM_FURNITURE:
		if (pObj->value[3] > 300 || pObj->value[4] > 300)
			*bp += 1000;
		break;
	}
}

/* returns a color code indicating the percentage of build points
 * used compared to build point max for the item
 */
char build_point_percent_color (int bp, int bpmax) {
	return (bp > bpmax)		? 'r' :
		(bp > bpmax * 9/10) 	? 'R' :
		(bp > bpmax * 3/4) 	? 'Y' :
		(bp > bpmax * 1/2)	? 'G' : 
		(bp > bpmax * 1/4)	? 'b' : 
		(bp > 0)		? 'y' :
		(bp == 0)		? 'x' :
					  'D';
}