Mud20/accounts/
Mud20/accounts/c/
Mud20/accounts/f/
Mud20/accounts/k/
Mud20/accounts/s/
Mud20/accounts/t/
Mud20/area_current/
Mud20/area_current/newareas/
Mud20/bin/
Mud20/clans/
Mud20/gods/
Mud20/old-sources/
Mud20/player/
Mud20/player/a/del/
Mud20/player/b/
Mud20/player/b/bak/
Mud20/player/b/del/
Mud20/player/f/
Mud20/player/f/bak/
Mud20/player/f/del/
Mud20/player/k/
Mud20/player/k/bak/
Mud20/player/k/del/
Mud20/player/k/dmp/
Mud20/player/m/
Mud20/player/m/bak/
Mud20/player/o/
Mud20/player/o/bak/
Mud20/player/p/
Mud20/player/s/
Mud20/player/s/bak/
Mud20/player/s/del/
Mud20/player/t/
Mud20/player/t/del/
Mud20/player/v/
Mud20/public_html/
Mud20/races/
Mud20/skilltables/
__MACOSX/Mud20/accounts/
__MACOSX/Mud20/accounts/c/
__MACOSX/Mud20/accounts/f/
__MACOSX/Mud20/accounts/k/
__MACOSX/Mud20/accounts/s/
__MACOSX/Mud20/area_current/
__MACOSX/Mud20/area_current/core_areas/
__MACOSX/Mud20/area_current/helps/
__MACOSX/Mud20/area_current/newareas/
__MACOSX/Mud20/backups/
__MACOSX/Mud20/bin/
__MACOSX/Mud20/clans/
__MACOSX/Mud20/gods/
__MACOSX/Mud20/log/
__MACOSX/Mud20/old-sources/
__MACOSX/Mud20/player/
__MACOSX/Mud20/player/a/del/
__MACOSX/Mud20/player/b/
__MACOSX/Mud20/player/b/bak/
__MACOSX/Mud20/player/f/
__MACOSX/Mud20/player/f/bak/
__MACOSX/Mud20/player/f/del/
__MACOSX/Mud20/player/k/
__MACOSX/Mud20/player/k/bak/
__MACOSX/Mud20/player/k/del/
__MACOSX/Mud20/player/k/dmp/
__MACOSX/Mud20/player/m/
__MACOSX/Mud20/player/m/bak/
__MACOSX/Mud20/player/o/
__MACOSX/Mud20/player/o/bak/
__MACOSX/Mud20/player/p/
__MACOSX/Mud20/player/s/
__MACOSX/Mud20/player/s/bak/
__MACOSX/Mud20/player/t/del/
__MACOSX/Mud20/player/v/
__MACOSX/Mud20/public_html/
__MACOSX/Mud20/races/
__MACOSX/Mud20/skilltables/
/***************************************************************************
 * Mud20 1.0 by Todd H. Johnson (Kregor) a derivative of the Open Gaming   *
 * License by Wizards of the Coast. All comments referring to D20, OGL,    *
 * and SRD refer to the System Reference Document for the Open Gaming      *
 * system. Any inclusion of these derivatives must include credit to the   *
 * Mud20 system, the full and complete Open Gaming LIcense, and credit to  *
 * the respective authors. See ../doc/srd.txt for more information.        *
 *                                                                         *
 * Emud  2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem.   *
 *                                                                         *
 * MrMud 1.4 by David Bills, Dug Michael and Martin Gallwey                *
 *                                                                         *
 * Merc  2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael      *
 * Chastain, Michael Quan, and Mitchell Tse.                               *
 *                                                                         *
 * Original Diku Mud copyright (C) 1990 1991 by Sebastian Hammer,          *
 * Michael Seifert, Hans Henrik St{rfeld, Tom Madsen, and Katje Nyboe.     *
 ***************************************************************************/

/***************************************************************************
 * act_obj.c: Anything you can do with an object.												   *
 ***************************************************************************/

#include "mud.h"
#include <math.h>

/*
	Local functions.
*/

bool			get_obj				args( ( CHAR_DATA *ch, OBJ_DATA *obj, OBJ_DATA *container, bool fDisplay, bool fReveal ) );
bool			put_obj				args( ( CHAR_DATA *ch, OBJ_DATA *obj, OBJ_DATA *container, bool fDisplay, bool fReveal ) );
bool			drop_obj			args( ( CHAR_DATA *ch, OBJ_DATA *obj, OBJ_DATA *container, bool fDisplay ) );
bool			sacrifice_obj	args( ( CHAR_DATA *ch, OBJ_DATA *obj, OBJ_DATA *container, bool fDisplay ) );
bool			can_loot_corpse			args( ( CHAR_DATA *ch, OBJ_DATA *corpse ) );


/*
 * Is the character the pkiller of a corpse,
 * checked for looting purposes - Kregor
 */
bool can_loot_corpse(CHAR_DATA *ch, OBJ_DATA *corpse)
{
	int pvnum;

	push_call("can_loot_corpse(%p,%p)",ch,corpse);

	if (IS_NPC(ch))
	{
		pop_call();
		return FALSE;
	}
	if (!IS_OBJ_TYPE(corpse, ITEM_CORPSE_PC))
	{
		pop_call();
		return FALSE;
	}
	if ((pvnum = corpse->value[4]) == 0 || pvnum != ch->pcdata->pvnum)
	{
		pop_call();
		return FALSE;
	}
	pop_call();
	return TRUE;
}

bool is_container(OBJ_DATA *obj)
{
	switch (obj->item_type)
	{
		case ITEM_SPELLPOUCH:
		case ITEM_CONTAINER:
		case ITEM_SHEATH:
		case ITEM_CART:
		case ITEM_QUIVER:
			return TRUE;
		default:
			break;
	}
	return FALSE;
}


char *  const   worn_flags [] =
{
	"taken carried and held",
	"floating about the head",
	"on the head",
	"on the face",
	"on the ears",
	"around the neck",
	"on the arms",
	"on the wrist",
	"on the hands",
	"on the finger",
	"about the body",
	"on the torso",
	"as a saddle",
	"on the back",
	"around the waist",
	"on the belt",	
	"on the legs",
	"around the ankle",
	"on the feet",
	"as a shield",
	"wielded in a hand",
	"held in both hands",
	"held in the hand",
	"*"
};


/*
	Determines if ch can wear an object based on class - Scandum 06-07-2002
*/

bool class_allowed(OBJ_DATA *obj, CHAR_DATA *ch, bool fDisplay)
{
	bool forbidden = TRUE;
	int cls;

	push_call("class_allowed(%p,%p,%p)",obj,ch,fDisplay);

	if (obj->pIndexData->class_flags == 0)
	{
		pop_call();
		return TRUE;
	}

	for (cls = 0 ; cls < MAX_CLASS ; cls++)
	{
		if (!class_level(ch, cls))
			continue;

		if (IS_SET(obj->pIndexData->class_flags, 1 << cls))
		{
			forbidden = FALSE;
			break;
		}
	}

  if (forbidden)
 	{
 		if (fDisplay)
		{
			act( "You are of the wrong class to use $p.", ch, obj, NULL, TO_CHAR);
		}
		pop_call();
		return FALSE;
	}
	pop_call();
	return TRUE;
}


int count_total_objects( OBJ_DATA *container )
{
	int count;
	OBJ_DATA *obj;

	push_call("count_total_objects(%p)",container);

	for (count = 0, obj = container->first_content ; obj ; obj = obj->next_content)
	{
		count++;
	}
	pop_call();
	return( count );
}


bool get_obj( CHAR_DATA *ch, OBJ_DATA *obj, OBJ_DATA *container, bool fDisplay, bool fReveal )
{
	CHAR_DATA *rch;

	push_call("get_obj(%p,%p,%p,%p,%p)",ch,obj,container,fDisplay,fReveal);

	if (IS_AFFECTED(ch, AFF_GASEOUS) || IS_INCORPOREAL(ch))
	{
		if (fDisplay)
		{
			act( "You cannot grasp $p in your physical state.", ch, obj, NULL, TO_CHAR );
		}
		pop_call();
		return FALSE;
	}

	if (!IS_SET(obj->wear_flags, CAN_WEAR_TAKE))
	{
		if (fDisplay)
		{
			send_to_char( "You cannot take that.\n\r", ch );
		}
		pop_call();
		return FALSE;
	}

	for (rch = ch->in_room->first_person ; rch ; rch = rch->next_in_room)
	{
		if (rch->furniture == obj)
		{
			if (fDisplay)
			{
				act( "$N seems to be using $p", ch, obj, rch, TO_CHAR);
			}
			pop_call();
			return FALSE;
		}
	}

	if (ch->carry_number >= can_carry_n(ch))
	{
		if (fDisplay)
		{
			act( "You cannot carry that many items.", ch, NULL, NULL, TO_CHAR);
		}
		pop_call();
		return FALSE;
	}

	if (container == NULL || container->carried_by != ch)
	{
		if (!IS_IMMORTAL(ch))
		{
			if (get_carry_w(ch) + get_obj_weight(obj) > can_carry_w(ch) * 2)
			{
				if (fDisplay)
				{
					act( "You can't even begin to carry that weight!", ch, obj, NULL, TO_CHAR);
					pop_call();
					return FALSE;
				}
			}
			else if (get_carry_w(ch) + get_obj_weight(obj) > can_carry_w(ch))
			{
				if (fDisplay)
				{
					act( "You strain under the weight of $p!", ch, obj, NULL, TO_CHAR);
					act( "$n strains under the weight of $p!", ch, obj, NULL, TO_ROOM);
					fReveal = FALSE;
				}
			}
			else if (get_carry_w(ch) + get_obj_weight(obj) > can_carry_w(ch) * 2 / 3)
			{
				if (fDisplay)
				{
					act( "You get $p with considerable effort.", ch, obj, NULL, TO_CHAR);
					act( "$n gets $p with considerable effort.", ch, obj, NULL, TO_ROOM);
					fReveal = FALSE;
				}
			}
			else if (get_carry_w(ch) + get_obj_weight(obj) > can_carry_w(ch) / 3)
			{
				if (fDisplay)
				{
					act( "You encumber yourself with $p.", ch, obj, NULL, TO_CHAR);
					act( "$n gets $p with a little effort.", ch, obj, NULL, TO_ROOM);
					fReveal = FALSE;
				}
			}
		}
	}

	if (IS_OBJ_TYPE(obj, ITEM_FURNITURE) && obj->first_content)
	{
		while (obj->first_content)
		{
			OBJ_DATA *oobj = obj->first_content;
			if (fDisplay)
			{
				act( "$p falls from $P as it is moved.", ch, oobj, obj, TO_CHAR);
				act( "$p falls from $P as it is moved.", ch, oobj, obj, TO_ROOM);
			}
			obj_from_obj(oobj);
			obj_to_room(oobj, ch->in_room->vnum);
		}
	}

	obj_to_char(obj, ch);

	if (fDisplay && fReveal)
	{
		if (container)
		{
			act( "You get $p from $P.", ch, obj, container, TO_CHAR );
			if (container->carried_by == ch)
				act( "$n gets $p from $P.", ch, obj, container, TO_CAN_SEE );
			else
				act( "$n gets $p from $P.", ch, obj, container, TO_ROOM );
		}
		else
		{
			act( "You get $p.", ch, obj, container, TO_CHAR );
			act( "$n gets $p.", ch, obj, container, TO_ROOM );
		}
	}

	if (obj && obj->item_type == ITEM_MONEY)
	{
		give_gold(ch, obj->value[0] * 100);
		give_gold(ch, obj->value[1] * 10);
		give_gold(ch, obj->value[2]);
		junk_obj(obj);
	}

	if (oprog_get_trigger(ch, obj))
	{
		if (!IS_AWAKE(ch))
		{
			pop_call();
			return TRUE;
		}
	}
	if (trig_obj_trap(ch, obj, TRAP_TRIG_GET_PUT))
	{
		if (!IS_AWAKE(ch))
		{
			pop_call();
			return TRUE;
		}
	}
	pop_call();
	return TRUE;
}

bool put_obj( CHAR_DATA *ch, OBJ_DATA *obj, OBJ_DATA *container, bool fDisplay, bool fReveal )
{
	push_call("put_obj(%p,%p,%p,%p,%p)",ch,obj,container,fDisplay,fReveal);

	if (obj == container)
	{
		if (fDisplay)
		{
			send_to_char( "You cannot fold it into itself.\n\r", ch );
		}
		pop_call();
		return FALSE;
	}
	
	if (!IS_SET(obj->wear_flags, CAN_WEAR_TAKE))
	{
		pop_call();
		return FALSE;
	}

	if (!IS_OBJ_STAT(obj, ITEM_CONCEALED) && !can_drop_obj(ch, obj))
	{
		if (fDisplay)
		{
			send_to_char( "You cannot let go of it.\n\r", ch );
		}
		pop_call();
		return FALSE;
	}

	if (container->item_type == ITEM_SPELLPOUCH && obj->item_type != ITEM_COMPONENT
	&& (obj->item_type != ITEM_TREASURE || !obj->value[5]))
	{
		if (fDisplay)
		{
			send_to_char( "You can only put components in a spellpouch.\n\r", ch);
		}
		pop_call();
		return FALSE;
	}

	if (container->item_type == ITEM_QUIVER)
	{
		if (obj->item_type != ITEM_AMMO)
		{
			if (fDisplay)
			{
				send_to_char( "You can only put ammo in a quiver.\n\r", ch);
			}
			pop_call();
			return FALSE;
		}
		if (count_total_objects(container) >= (container->value[3] ? container->value[3] : 20))
		{
			if (fDisplay)
			{
				send_to_char( "That quiver is already full.\n\r", ch);
			}
			pop_call();
			return FALSE;
		}
	}

	if (container->item_type == ITEM_SHEATH)
	{
		if (obj->item_type != ITEM_WEAPON)
		{
			if (fDisplay)
			{
				send_to_char( "You can only put a weapon in a sheath.\n\r", ch);
			}
			pop_call();
			return FALSE;
		}
		if (obj->size > container->size)
		{
			if (fDisplay)
			{
				send_to_char( "That weapon is too big.\n\r", ch);
			}
			pop_call();
			return FALSE;
		}
		if (count_total_objects(container) >= (container->value[3] ? container->value[3] : 1))
		{
			if (fDisplay)
			{
				send_to_char( "That sheath is already full.\n\r", ch);
			}
			pop_call();
			return FALSE;
		}
	}

	if (container->item_type == ITEM_FURNITURE)
	{
		if (!IS_SET(container->value[2], FURN_PLACE_ON))
		{
			if (fDisplay)
			{
				send_to_char( "You cannot put anything on that.\n\r", ch);
			}
			pop_call();
			return FALSE;
		}
		if (!container->in_room)
		{
			if (fDisplay)
			{
				send_to_char( "You can't put something on that unless it's set down.\n\r", ch);
			}
			pop_call();
			return FALSE;
		}
	}

	if (container->item_type == ITEM_CONTAINER && get_obj_weight(obj) + container->content_weight > container->value[0])
	{
		if (fDisplay)
		{
			send_to_char( "It's too heavy to fit.\n\r", ch);
		}
		pop_call();
		return FALSE;
	}

	if (container->item_type == ITEM_CART && get_obj_weight(obj) + container->content_weight > container->value[0])
	{
		if (fDisplay)
		{
			send_to_char( "It's too heavy to fit.\n\r", ch);
		}
		pop_call();
		return FALSE;
	}

	if (container->item_type != ITEM_FURNITURE && count_total_objects(container) >= (container->value[3] ? container->value[3] : MAX_OBJECTS_IN_CONTAINER))
	{
		if (fDisplay)
		{
			send_to_char( "There is too much in that container already.\n\r", ch);
		}
		pop_call();
		return FALSE;
	}

	if (obj->item_type == ITEM_CONTAINER && container->item_type != ITEM_FURNITURE)
	{
		if (obj->first_content)
		{
			if (fDisplay)
			{
				act("You must empty $p before you put it in $P", ch, obj, container, TO_CHAR);
			}
			pop_call();
			return FALSE;
		}
	}

	if (IS_OBJ_STAT(obj, ITEM_CONCEALED))
	{
		REMOVE_BIT(obj->extra_flags,ITEM_CONCEALED);
		if (fReveal)
		{
			act ("You produce $p from its concealment.", ch, obj, NULL, TO_CHAR);
			act ("$n produces %s from its concealment.", ch, obj, NULL, TO_CAN_SEE);
		}
	}

	obj_to_obj( obj, container );
	
	if (fDisplay)
	{
		if (IS_OBJ_TYPE(container, ITEM_FURNITURE))
		{
			act( "You put $p onto $P.", ch, obj, container, TO_CHAR );
			act( "$n puts $p onto $P.", ch, obj, container, TO_ROOM );
		}
		else
		{
			act( "You put $p in $P.", ch, obj, container, TO_CHAR );
			if (container->carried_by == ch)
				act( "$n puts $p in $P.", ch, obj, container, TO_CAN_SEE );
			else
				act( "$n puts $p in $P.", ch, obj, container, TO_ROOM );
		}
	}
	if (trig_obj_trap(ch, obj, TRAP_TRIG_GET_PUT) || trig_obj_trap(ch, container, TRAP_TRIG_GET_PUT))
	{
		if (!IS_AWAKE(ch))
		{
			pop_call();
			return TRUE;
		}
	}
	pop_call();
	return TRUE;
}


bool drop_obj( CHAR_DATA *ch, OBJ_DATA *obj, OBJ_DATA *container, bool fDisplay )
{
	push_call("drop_obj(%p,%p,%p,%p)",ch,obj,container,fDisplay);

	if (!can_drop_obj(ch, obj))
	{
		if (fDisplay)
		{
			send_to_char( "You cannot let go of it.\n\r", ch );
		}
		pop_call();
		return FALSE;
	}

	if (ch->in_room && !IS_SET(ch->in_room->room_flags, ROOM_CLANSTOREROOM))
		obj->sac_timer = OBJ_SAC_TIME;

	if (fDisplay)
	{
		act( "You drop $p.", ch, obj, NULL, TO_CHAR );
		act( "$n drops $p.", ch, obj, NULL, TO_ROOM );
	}
	obj_to_room( obj, ch->in_room->vnum );

	oprog_drop_trigger(ch, obj);
	
	pop_call();
	return TRUE;
}

bool sacrifice_obj( CHAR_DATA *ch, OBJ_DATA *obj, OBJ_DATA *container, bool fDisplay )
{
	CHAR_DATA	*rch;

	push_call("sacrifice_obj(%p,%p,%p,%p)",ch,obj,container,fDisplay);

	if (!IS_SET(obj->wear_flags, CAN_WEAR_TAKE))
	{
		if (fDisplay)
		{
			act( "$p is not an acceptable sacrifice.", ch, obj, NULL, TO_CHAR);
		}
		pop_call();
		return FALSE;
	}

	if (obj->item_type == ITEM_CORPSE_PC)
	{
		if (!IS_OWNER(obj, ch))
		{
			if (fDisplay)
			{
				act( "$p is not yours to sacrifice.", ch, obj, NULL, TO_CHAR);
			}
			pop_call();
			return FALSE;
		}
	}

	for (rch = ch->in_room->first_person ; rch ; rch = rch->next_in_room)
	{
		if (rch->furniture == obj)
		{
			if (fDisplay)
			{
				act( "$N seems to be using $p", ch, obj, rch, TO_CHAR);
			}
			pop_call();
			return FALSE;
		}
	}

	act( "You make a gruesome sacrifice of $p.", ch, obj, NULL, TO_CHAR);
	act( "$n makes a gruesome sacrifice of $p.", ch, obj, NULL, TO_ROOM);

	oprog_sac_trigger(ch, obj);

	if (obj->first_content)
	{
		while (obj->first_content)
		{
			obj->first_content->sac_timer = OBJ_SAC_TIME;

			for (rch = ch->in_room->first_person ; rch ; rch = rch->next_in_room)
			{
				if (IS_NPC(rch) || !IS_SET(rch->act, PLR_QUIET))
				{
					act( "  $p falls out onto the floor.", rch, obj->first_content, NULL, TO_CHAR);
				}
			}
			obj_to_room(obj->first_content, ch->in_room->vnum);
		}
	}

	if (!IS_NPC(ch) && obj == ch->pcdata->corpse)
	{
		ch->pcdata->corpse = find_char_corpse(ch, TRUE);
	}

	if (!IS_NPC(ch) && obj == ch->pcdata->cart)
	{
		ch->pcdata->cart = NULL;
	}

	junk_obj(obj);

	pop_call();
	return TRUE;
}


void corpse_loot( CHAR_DATA *ch )
{
	push_call("corpse_loot(%p)",ch);

	while (ch->pcdata->corpse->first_content)
	{
		obj_to_char(ch->pcdata->corpse->first_content, ch);
	}

	act( "You get everything from $p.",ch, ch->pcdata->corpse, NULL, TO_CHAR );
	act( "$n gets everything from $p.",ch, ch->pcdata->corpse, NULL, TO_ROOM );

	junk_obj(ch->pcdata->corpse);

	ch->pcdata->corpse = find_char_corpse(ch, TRUE);

	save_char_obj(ch, NORMAL_SAVE);

	pop_call();
	return;
}


void do_get( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	char buf1[MAX_INPUT_LENGTH];
	char buf2[MAX_INPUT_LENGTH];
	
	CHAR_DATA *rch;

	OBJ_DATA *obj			= NULL;
	OBJ_DATA *obj_next		= NULL;
	OBJ_DATA *container		= NULL;
	OBJ_DATA *found_obj		= NULL;

	bool clutter		= FALSE;
	bool shrtd			= FALSE;
	bool nomoves		= FALSE;
	bool quickdraw  = FALSE;

	int amount			=  1;
	int cnt				=  0;
	int cnt_not_got		=  0;
	int split				=  0;

	push_call("do_get(%p,%p)",ch,argument);

	if (!learned(ch, gsn_blind_fight) && !check_blind(ch))
	{
		pop_call();
		return;
	}

	/*
	 * special approach for player corpses.
	 * Keeps weight and other factors from preventing
	 * item retrieval.
	 */
	if (!IS_NPC(ch) && ch->pcdata->corpse && ch->in_room->vnum == ch->pcdata->corpse_room)
	{
		corpse_loot(ch);
		pop_call();
		return;
	}

	if (*argument == 0)
	{
		send_to_char("Get what?\n\r", ch);
		pop_call();
		return;
	}

	if (!is_handy(ch) || hands_full(ch))
	{
		send_to_char( "You have no free hand to pick anything up.\n\r", ch );
		pop_call();
		return;
	}
		
	if (IS_SET(ch->action, ACTION_STANDARD) && IS_SET(ch->action, ACTION_MOVE))
		nomoves = TRUE;
		
	argument = one_argument( argument, arg1 );

	if (is_number(arg1))
	{
		amount	= UMAX(1, atol(arg1));
		argument	= one_argument( argument, arg1 );
	}

	argument = one_argument( argument, arg2 );
	
	// allow "from" in command - Kregor
	if (!strcasecmp(arg2, "from"))
		argument = one_argument( argument, arg2 );

	if (arg2[0] == '\0')
	{
		if (in_combat(ch) && !is_active(ch))
		{
			send_to_char("Just wait your turn!\n\r", ch);
			pop_call();
			return;
		}

		if (nomoves)
		{
			send_to_char("You have no actions left this round.\n\r", ch);
			pop_call();
			return;
		}

		if (strcasecmp(arg1, "all") && str_prefix("all.", arg1))
		{
			if ((obj = get_obj_list(ch, arg1, ch->in_room->first_content)) == NULL)
			{
				act( "You see no $T here.", ch, NULL, short_to_name(arg1, amount), TO_CHAR);
				pop_call();
				return;
			}

			if (amount == 1)
			{
				if (get_obj(ch, obj, NULL, TRUE, TRUE))
					TAKE_ACTION(ch, ACTION_MOVE);
				pop_call();
				return;
			}

			for ( ; shrtd <= 1 && !found_obj ; shrtd++)
			{
				for (obj = ch->in_room->first_content ; obj ; obj = obj_next)
				{
					obj_next = obj->next_content;

					if (!can_see_obj(ch, obj) || !IS_SET(obj->wear_flags, CAN_WEAR_TAKE))
					{
						continue;
					}

					if (!shrtd && !is_name(arg1, obj->name))
					{
						continue;
					}

					if (shrtd  && !is_name_short(arg1, obj->name))
					{
						continue;
					}

					if (found_obj == NULL)
					{
						found_obj = obj;
					}

					if (obj->short_descr != found_obj->short_descr)
					{
						continue;
					}

					if (get_obj(ch, obj, NULL, FALSE, FALSE))
					{
						cnt++;
					}
					else
					{
						cnt_not_got++;
					}

					if (cnt >= amount)
					{
						break;
					}
				}
			}
			if (found_obj)
			{
				sprintf(buf1, "You get %d %s.", cnt, short_to_name(found_obj->short_descr, cnt));
				sprintf(buf2, "$n gets %d %s.", cnt, short_to_name(found_obj->short_descr, cnt));
				act( buf1, ch, found_obj, NULL, TO_CHAR);
				act( buf2, ch, found_obj, NULL, TO_ROOM);
			}
			else
			{
				do_get(ch, arg1);
			}
			TAKE_ACTION(ch, ACTION_MOVE);
		}
		else
		{
			/*
				'get all' or 'get all.object'
			*/
			if (IS_SET(ch->action, ACTION_FULL))
			{
				send_to_char("Getting 'all' from a room is a full-round action\n\r", ch);
				pop_call();
				return;
			}
			for ( ; shrtd <= 1 && !found_obj ; shrtd++)
			{
				for (obj = ch->in_room->first_content ; obj ; obj = obj_next)
				{
					obj_next = obj->next_content;

					if (!can_see_obj(ch, obj) || !IS_SET(obj->wear_flags, CAN_WEAR_TAKE))
					{
						continue;
					}

					if (!shrtd && arg1[3] && !is_name(&arg1[4], obj->name))
					{
						continue;
					}

					if (shrtd  && arg1[3] && !is_name_short(&arg1[4], obj->name))
					{
						continue;
					}

					if (found_obj == NULL)
					{
						found_obj = obj;
					}

					if (obj->short_descr != found_obj->short_descr)
					{
						clutter = TRUE;
					}

					if (get_obj(ch, obj, NULL, FALSE, FALSE))
					{
						cnt++;
					}
					else
					{
						cnt_not_got++;
					}
				}
			}
			if (found_obj == NULL)
			{
				if (arg1[3] == '\0')
				{
					send_to_char( "You see nothing here.\n\r", ch );
				}
				else
				{
					act( "You see no $T here.", ch, NULL, short_to_name(&arg1[4], 0), TO_CHAR );
				}
			}
			else
			{
				if (cnt_not_got > 0)
				{
					if (arg1[3] == '\0' || clutter)
					{
						ch_printf_color(ch, "You get all but %d of the items.\n\r", cnt_not_got);
						act( "$n gets some items.", ch, NULL, NULL, TO_ROOM);
					}
					else
					{
						sprintf(buf1, "You get %d %s.", cnt, short_to_name(found_obj->short_descr, cnt));
						sprintf(buf2, "$n gets %d %s.", cnt, short_to_name(found_obj->short_descr, cnt));
						act( buf1, ch, found_obj, NULL, TO_CHAR);
						act( buf2, ch, found_obj, NULL, TO_ROOM);
					}
				}
				else
				{
					if (clutter)
					{
						if (arg1[3] == '\0')
						{
							act( "You get everything here.", ch, NULL, NULL, TO_CHAR);
							act( "$n gets everything here.", ch, NULL, NULL, TO_ROOM);
						}
						else
						{
							act( "You get all the $T here.", ch, NULL, short_to_name(&arg1[4], cnt), TO_CHAR);
							act( "$n gets all the $T here.", ch, NULL, short_to_name(&arg1[4], cnt), TO_ROOM);
						}
					}
					else
					{
						sprintf(buf1, "You get every %s here.", short_to_name(found_obj->short_descr, 1));
						sprintf(buf2, "$n gets every %s here.", short_to_name(found_obj->short_descr, 1));
						act( buf1, ch, found_obj, NULL, TO_CHAR);
						act( buf2, ch, found_obj, NULL, TO_ROOM);
					}
				}
				TAKE_ACTION(ch, ACTION_FULL);
			}
		}
		pop_call();
		return;
	}
	else if ((rch = get_char_room(ch, arg2)) != NULL)
	{
		/*
			"get <all|all.object|item> from pet/companion"
		*/
		if (!rch->master || rch->master != ch || !IS_ACT(rch, ACT_PET|ACT_FAMILIAR|ACT_COMPANION))
		{
			act( "$N is not your pet to take that from.", ch, NULL, rch, TO_CHAR );
			pop_call();
			return;
		}

		if (in_combat(ch) && !is_active(ch))
		{
			send_to_char("Just wait your turn!\n\r", ch);
			pop_call();
			return;
		}

		if (strcasecmp(arg1, "all") && str_prefix("all.", arg1))
		{
			/*
				"get object pet"
			*/
			if ((obj = get_obj_list(ch, arg1, rch->first_carrying)) == NULL)
			{
				act( "You see nothing like that on $N.", ch, NULL, rch, TO_CHAR);
				pop_call();
				return;
			}

			if (amount == 1)
			{
				obj_from_char(obj);
				obj_to_char(obj, ch);
				act( "$n gets $p from $N.", ch, obj, rch, TO_NOTVICT);
				act( "$n gets $p from you.", ch, obj, rch, TO_VICT);
				act( "You get $p from $N.", ch, obj, rch, TO_CHAR);
				TAKE_ACTION(ch, ACTION_MOVE);
				pop_call();
				return;
			}
			
			for ( ; shrtd <= 1 && !found_obj ; shrtd++)
			{
				for (obj = rch->first_carrying ; obj ; obj = obj_next)
				{
					obj_next = obj->next_content;

					if (!shrtd && !is_name(arg1, obj->name))
					{
						continue;
					}

					if (shrtd  && !is_name_short(arg1, obj->name))
					{
						continue;
					}

					if (found_obj == NULL)
					{
						found_obj = obj;
					}

					if (obj->short_descr != found_obj->short_descr)
					{
						continue;
					}
					
					if (ch->carry_weight + get_obj_weight(obj) <= can_carry_w(ch) * 2)
					{
						cnt++;
					}
					else
					{
						cnt_not_got++;
						continue;
					}
					
					obj_from_char(obj);
					obj_to_char(obj, ch);

					if (cnt >= amount)
					{
						break;
					}
				}
			}
			if (found_obj)
			{
				sprintf(buf1, "You get %d %s from $N.", cnt, short_to_name(found_obj->short_descr, cnt));
				sprintf(buf2, "$n gets %d %s from $N", cnt, short_to_name(found_obj->short_descr, cnt));
				act( buf1, ch, NULL, rch, TO_CHAR);
				act( buf2, ch, NULL, rch, TO_ROOM);
			}
			TAKE_ACTION(ch, ACTION_MOVE);
		}
		else
		{
			/*
				"get all pet" or "get all.object pet"
			*/
			if (in_combat(ch) && !is_active(ch))
			{
				send_to_char("Just wait your turn!\n\r", ch);
				pop_call();
				return;
			}
			if (ch->action > ACTION_SWIFT)
			{
				send_to_char("It takes a full round action to get 'all' from a pet\n\r", ch);
				pop_call();
				return;
			}

			for ( ; shrtd <= 1 && !found_obj ; shrtd++)
			{
				for (obj = rch->first_carrying ; obj ; obj = obj_next)
				{
					obj_next = obj->next_content;

					if (!shrtd && arg1[3] && !is_name(&arg1[4], obj->name))
					{
						continue;
					}

					if (shrtd  && arg1[3] && !is_name_short(&arg1[4], obj->name))
					{
						continue;
					}

					if (found_obj == NULL)
					{
						found_obj = obj;
					}

					if (obj->short_descr != found_obj->short_descr)
					{
						clutter = TRUE;
					}

					if (ch->carry_weight + get_obj_weight(obj) <= can_carry_w(ch) * 2)
					{
						cnt++;
					}
					else
					{
						cnt_not_got++;
						continue;
					}
				}
			}

			if (found_obj == NULL)
			{
				if (arg1[3] == '\0')
				{
					act( "You see nothing on $N.", ch, NULL, rch, TO_CHAR );
				}
				else
				{
					act( "You see nothing like that on $N.", ch, NULL, rch, TO_CHAR );
				}
			}
			else
			{
				if (cnt_not_got)
				{
					if (arg1[3] == '\0' || clutter)
					{
						ch_printf_color(ch, "You get all but %d of the items from %s.\n\r", cnt_not_got, get_name(rch));
						act( "$n gets some items from $N.", ch, NULL, rch, TO_ROOM);
					}
					else
					{
						sprintf(buf1, "You get %d %s from $N.", cnt, short_to_name(found_obj->short_descr, cnt));
						sprintf(buf2, "$n gets %d %s from $N.", cnt, short_to_name(found_obj->short_descr, cnt));
						act( buf1, ch, NULL, rch, TO_CHAR);
						act( buf2, ch, NULL, rch, TO_ROOM);
					}
				}
				else if (cnt == 1)
				{
					act( "You get $p from $N.", ch, found_obj, rch, TO_CHAR);
					act( "$n gets $p from $N.", ch, found_obj, rch, TO_ROOM);
				}
				else if (clutter)
				{
					if (arg1[3] == '\0')
					{
						act( "You get everything from $N.",ch, NULL, rch, TO_CHAR );
						act( "$n gets everything from $N.",ch, NULL, rch, TO_ROOM );
					}
					else
					{
						act( "You get all $t from $N.",ch, short_to_name(&arg1[4], 0), rch, TO_CHAR );
						act( "$n gets all $t from $N.",ch, short_to_name(&arg1[4], 0), rch, TO_ROOM );
					}
				}
				else
				{
					sprintf(buf1, "You get every %s from $N.", short_to_name(found_obj->short_descr, 1));
					sprintf(buf2, "$n gets every %s from $N.", short_to_name(found_obj->short_descr, 1));
					act( buf1, ch, NULL, rch, TO_CHAR);
					act( buf2, ch, NULL, rch, TO_ROOM);
				}
			}
		}
		TAKE_ACTION(ch, ACTION_FULL);
	}
	else
	{
		/*
			"get <all|all.object|item> container"
		*/

		if ((container = get_obj_here(ch, arg2)) == NULL)
		{
			act( "You see no $T here.", ch, NULL, arg2, TO_CHAR );
			pop_call();
			return;
		}

		switch (container->item_type)
		{
			case ITEM_FURNITURE:
			case ITEM_SPELLPOUCH:
			case ITEM_CONTAINER:
			case ITEM_CART:
			case ITEM_SHEATH:
			case ITEM_QUIVER:
				break;
			case ITEM_CORPSE_NPC:
				split	= UMAX(1, ch->gold);
				break;
			case ITEM_CORPSE_PC:
				if (!IS_OWNER(container, ch) && !can_loot_corpse(ch, container))
				{
					send_to_char( "You have no right to those items.\n\r", ch );
					pop_call();
					return;
				}
				break;
			default:
				send_to_char( "That's not a container.\n\r", ch );
				pop_call();
				return;
		}

		if (IS_SET(container->value[1], CONT_CLOSED))
		{
			act( "$p is closed.", ch, container, NULL, TO_CHAR );
			pop_call();
			return;
		}
		
		if (learned(ch, gsn_quick_draw) && container->carried_by
		&& container->carried_by == ch && IS_WORN(container)
		&& !WEAR_LOC(container, WEAR_BACK) && !WEAR_LOC(container, WEAR_BODY)
		&& (IS_WEAPON(obj) || IS_AMMO(obj)))
			quickdraw = TRUE;
			
		if (!quickdraw)
		{
			if (in_combat(ch) && !is_active(ch))
			{
				send_to_char("Just wait your turn!\n\r", ch);
				pop_call();
				return;
			}
		}

		if (strcasecmp(arg1, "all") && str_prefix("all.", arg1))
		{
			/*
				"get object container"
			*/
			if ((obj = get_obj_list(ch, arg1, container->first_content)) == NULL)
			{
				act( "You see nothing like that in $p.", ch, container, NULL, TO_CHAR);
				pop_call();
				return;
			}

			if (amount == 1)
			{
				if (get_obj(ch, obj, container, TRUE, TRUE))
				{
					if (!quickdraw || !container->carried_by || container->carried_by != ch)
					{
						TAKE_ACTION(ch, ACTION_MOVE);
					}
					if (can_loot_corpse(ch, container))
					{
						container->value[4] = 0;
					}
				}		
				pop_call();
				return;
			}

			if (IS_OBJ_TYPE(container, ITEM_CORPSE_PC))
			{
				send_to_char("OOC: Pkill rules only allow you to loot ONE item from your prey.\n\r", ch);
				pop_call();
				return;
			}
			
			if (nomoves)
			{
				if (!quickdraw)
				{
					send_to_char("You cannot make another move action this round.\n\r", ch);
					pop_call();
					return;
				}
			}

			for ( ; shrtd <= 1 && !found_obj ; shrtd++)
			{
				for (obj = container->first_content ; obj ; obj = obj_next)
				{
					obj_next = obj->next_content;

					if (!can_see_obj(ch, obj) || !IS_SET(obj->wear_flags, CAN_WEAR_TAKE))
					{
						continue;
					}

					if (!shrtd && !is_name(arg1, obj->name))
					{
						continue;
					}

					if (shrtd  && !is_name_short(arg1, obj->name))
					{
						continue;
					}

					if (found_obj == NULL)
					{
						found_obj = obj;
					}

					if (obj->short_descr != found_obj->short_descr)
					{
						continue;
					}

					if (get_obj(ch, obj, container, FALSE, FALSE))
					{
						cnt++;
					}
					else
					{
						cnt_not_got++;
					}

					if (cnt >= amount)
					{
						break;
					}
				}
			}
			if (found_obj)
			{
				sprintf(buf1, "You get %d %s from $p.", cnt, short_to_name(found_obj->short_descr, cnt));
				sprintf(buf2, "$n gets %d %s from $p", cnt, short_to_name(found_obj->short_descr, cnt));
				act( buf1, ch, container, NULL, TO_CHAR);
				act( buf2, ch, container, NULL, TO_ROOM);
			}
			else
			{
				cat_sprintf(arg1, " %s", arg2);
				do_get(ch, arg1);
			}
			if (!quickdraw)
				TAKE_ACTION(ch, ACTION_MOVE);
		}
		else
		{
			/*
				"get all container" or "get all.object container"
			*/
			if (IS_OBJ_TYPE(container, ITEM_CORPSE_PC))
			{
				send_to_char("OOC: Pkill rules only allow you to loot ONE item from your prey.\n\r", ch);
				pop_call();
				return;
			}
			if (in_combat(ch) && !is_active(ch))
			{
				send_to_char("Just wait your turn!\n\r", ch);
				pop_call();
				return;
			}
			if (IS_SET(ch->action, ACTION_STANDARD))
			{
				send_to_char("It takes a standard action to get 'all' from a container\n\r", ch);
				pop_call();
				return;
			}

			for ( ; shrtd <= 1 && !found_obj ; shrtd++)
			{
				for (obj = container->first_content ; obj ; obj = obj_next)
				{
					obj_next = obj->next_content;

					if (!can_see_obj(ch, obj) || !IS_SET(obj->wear_flags, CAN_WEAR_TAKE))
					{
						continue;
					}

					if (!shrtd && arg1[3] && !is_name(&arg1[4], obj->name))
					{
						continue;
					}

					if (shrtd  && arg1[3] && !is_name_short(&arg1[4], obj->name))
					{
						continue;
					}

					if (split)
					{
						if (obj->item_type != ITEM_MONEY)
						{
							continue;
						}
					}

					if (found_obj == NULL)
					{
						found_obj = obj;
					}

					if (obj->short_descr != found_obj->short_descr)
					{
						clutter = TRUE;
					}

					if (get_obj(ch, obj, container, FALSE, FALSE))
					{
						cnt++;
					}
					else
					{
						cnt_not_got++;
					}
				}
			}

			if (found_obj == NULL)
			{
				if (!split)
				{
					if (arg1[3] == '\0')
					{
						act( "You see nothing in $p.", ch, container, NULL, TO_CHAR );
					}
					else
					{
						act( "You see nothing like that in $p.", ch, container, NULL, TO_CHAR );
					}
				}
			}
			else
			{
				if (cnt_not_got)
				{
					if (arg1[3] == '\0' || clutter)
					{
						ch_printf_color(ch, "You get all but %d of the items from %s.\n\r", cnt_not_got, container->short_descr);
						act( "$n gets some items from $p.",ch,container,NULL,TO_ROOM);
					}
					else
					{
						sprintf(buf1, "You get %d %s from $p.", cnt, short_to_name(found_obj->short_descr, cnt));
						sprintf(buf2, "$n gets %d %s from $p.", cnt, short_to_name(found_obj->short_descr, cnt));
						act( buf1, ch, container, NULL, TO_CHAR);
						act( buf2, ch, container, NULL, TO_ROOM);
					}
				}
				else if (split && cnt == 1)
				{
					sprintf(buf1, "You get %s from $p.", found_obj->short_descr);
					sprintf(buf2, "$n gets %s from $p.", found_obj->short_descr);
					act( buf1, ch, container, NULL, TO_CHAR);
					act( buf2, ch, container, NULL, TO_ROOM);
				}
				else if (clutter)
				{
					if (arg1[3] == '\0')
					{
						act( "You get everything from $p.",ch, container, NULL, TO_CHAR );
						act( "$n gets everything from $p.",ch, container, NULL, TO_ROOM );
					}
					else
					{
						act( "You get all $T from $p.",ch, container, short_to_name(&arg1[4], 0), TO_CHAR );
						act( "$n gets all $T from $p.",ch, container, short_to_name(&arg1[4], 0), TO_ROOM );
					}
				}
				else
				{
					sprintf(buf1, "You get every %s from $p.", short_to_name(found_obj->short_descr, 1));
					sprintf(buf2, "$n gets every %s from $p.", short_to_name(found_obj->short_descr, 1));
					act( buf1, ch, container, NULL, TO_CHAR);
					act( buf2, ch, container, NULL, TO_ROOM);
				}
			}
		}
		TAKE_ACTION(ch, ACTION_STANDARD);
	}
	pop_call();
	return;
}


void do_put( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	char buf1[MAX_INPUT_LENGTH];
	char buf2[MAX_INPUT_LENGTH];

	OBJ_DATA *container		= NULL;
	OBJ_DATA *found_obj		= NULL;
	OBJ_DATA *obj			= NULL;
	OBJ_DATA *obj_next		= NULL;

	bool shrtd			= FALSE;
	bool clutter		= FALSE;
	bool put_in			= FALSE;
	bool put_on			= FALSE;

	int amount			= 1;
	int cnt				= 0;
	int cnt_not_put		= 0;

	push_call("do_put(%p,%p)",ch,argument);

	argument = one_argument( argument, arg1 );

	if (is_number(arg1))
	{
		amount	= UMAX(1, atol(arg1));
		argument	= one_argument( argument, arg1 );
	}

	argument = one_argument( argument, arg2 );
	
	// allow "in" and "on" in command - Kregor
	if (!strcasecmp(arg2, "on") || !strcasecmp(arg2, "onto"))
	{
		argument = one_argument( argument, arg2 );
		put_on = TRUE;
	}
	else if (!strcasecmp(arg2, "in") || !strcasecmp(arg2, "into"))
	{
		argument = one_argument( argument, arg2 );
		put_in = TRUE;
	}

	if (*arg1 == 0 || *arg2 == 0)
	{
		send_to_char( "Put what in what?\n\r", ch );
		pop_call();
		return;
	}

	if ((container = get_obj_here(ch, arg2)) == NULL)
	{
		act( "You see no $T here.", ch, NULL, arg2, TO_CHAR );
		pop_call();
		return;
	}

	if (put_on)
	{
		if (!IS_OBJ_TYPE(container, ITEM_FURNITURE))
		{
			act( "You cannot put anything on $p.", ch, container, NULL, TO_CHAR );
			pop_call();
			return;
		}
	}
	else if (put_in)
	{
		if (!is_container(container))
		{
			act( "You cannot put anything in $p.", ch, container, NULL, TO_CHAR );
			pop_call();
			return;
		}
	}
	else
	{
		if (!is_container(container))
		{
			if (!IS_OBJ_TYPE(container, ITEM_FURNITURE))
			{
				act( "$p is not a container.", ch, container, NULL, TO_CHAR );
				pop_call();
				return;
			}
		}
	}

	if (is_container(container) && IS_SET(container->value[1], CONT_CLOSED))
	{
		act( "$p is closed.", ch, container, NULL, TO_CHAR );
		pop_call();
		return;
	}

	if (strcasecmp(arg1, "all") && str_prefix("all.", arg1))
	{
		/*
			'put obj container'
		*/

		if ((obj = get_obj_carry(ch, arg1)) == NULL)
		{
			send_to_char( "You do not have that item.\n\r", ch );
			pop_call();
			return;
		}

		if (amount == 1)
		{
			put_obj(ch, obj, container, TRUE, TRUE);
			pop_call();
			return;
		}

		for ( ; shrtd <= 1 && !found_obj ; shrtd++)
		{
			for (obj = ch->first_carrying ; obj ; obj = obj_next)
			{
				obj_next = obj->next_content;

				if (!can_see_obj(ch, obj) || !IS_CARRIED(obj))
				{
					continue;
				}

				if (!shrtd && !is_name(arg1, obj->name))
				{
					continue;
				}

				if (shrtd  && !is_name_short(arg1, obj->name))
				{
					continue;
				}

				if (found_obj == NULL)
				{
					found_obj = obj;
				}

				if (obj->short_descr != found_obj->short_descr)
				{
					continue;
				}

				if (put_obj(ch, obj, container, FALSE, TRUE))
				{
					cnt++;
				}
				else
				{
					cnt_not_put++;
				}

				if (cnt >= amount)
				{
					break;
				}
			}
		}
		if (found_obj)
		{
			if (container->item_type != ITEM_FURNITURE)
			{
				sprintf(buf1, "You put %d %s into $p.", cnt, short_to_name(found_obj->short_descr, cnt));
				act( buf1, ch, container, NULL, TO_CHAR);
				sprintf(buf2, "$n puts %d %s into $p.", cnt, short_to_name(found_obj->short_descr, cnt));
				act( buf2, ch, container, NULL, TO_ROOM);
			}
			else
			{
				sprintf(buf1, "You put %d %s onto $p.", cnt, short_to_name(found_obj->short_descr, cnt));
				act( buf1, ch, container, NULL, TO_CHAR);
				sprintf(buf2, "$n puts %d %s onto $p.", cnt, short_to_name(found_obj->short_descr, cnt));
				act( buf2, ch, container, NULL, TO_ROOM);
			}
		}
		else
		{
			do_put(ch, arg1);
		}
		pop_call();
		return;
	}
	else
	{
		/*
			'put all container' or 'put all.obj container'
		*/

		for ( ; shrtd <= 1 && !found_obj ; shrtd++)
		{
			for (obj = ch->first_carrying ; obj ; obj = obj_next)
			{
				obj_next = obj->next_content;

				if (!can_see_obj(ch, obj) || !IS_CARRIED(obj) || obj == container)
				{
					continue;
				}

				if (!shrtd && arg1[3] && !is_name(&arg1[4], obj->name))
				{
					continue;
				}

				if (shrtd  && arg1[3] && !is_name_short(&arg1[4], obj->name))
				{
					continue;
				}

				if (found_obj == NULL)
				{
					found_obj = obj;
				}

				if (obj->short_descr != found_obj->short_descr)
				{
					clutter = TRUE;
				}

				if (put_obj(ch, obj, container, FALSE, TRUE))
				{
					cnt++;
				}
				else
				{
					cnt_not_put++;
				}
			}
		}

		if (found_obj)
		{
			if (cnt_not_put > 0)
			{
				if (arg1[3] == '\0' || clutter)
				{
					if (container->item_type != ITEM_FURNITURE)
					{
						sprintf(buf1, "You put all but %d of the items into $P.", cnt_not_put);
						sprintf(buf2, "$n puts some items into $P.");
					}
					else
					{
						sprintf(buf1, "You put all but %d of the items onto $P.", cnt_not_put);
						sprintf(buf2, "$n puts some items onto $P.");
					}
				}
				else
				{
					if (container->item_type != ITEM_FURNITURE)
					{
						sprintf(buf1, "You put %d %s into $P.", cnt, short_to_name(found_obj->short_descr, cnt));
						sprintf(buf2, "$n puts %d %s into $P.", cnt, short_to_name(found_obj->short_descr, cnt));
					}
					else
					{
						sprintf(buf1, "You put %d %s onto $P.", cnt, short_to_name(found_obj->short_descr, cnt));
						sprintf(buf2, "$n puts %d %s onto $P.", cnt, short_to_name(found_obj->short_descr, cnt));
					}
				}
			}
			else if (clutter)
			{
				if (arg1[3] == 0)
				{
					if (container->item_type != ITEM_FURNITURE)
					{
						sprintf(buf1, "You put everything into $P.");
						sprintf(buf2, "$n puts everything into $P.");
					}
					else
					{
						sprintf(buf1, "You put everything onto $P.");
						sprintf(buf2, "$n puts everything onto $P.");
					}
				}
				else
				{
					if (container->item_type != ITEM_FURNITURE)
					{
						sprintf(buf1, "You put all %s into $P.", short_to_name(&arg1[4], 0));
						sprintf(buf2, "$n puts all %s into $P.", short_to_name(&arg1[4], 0));
					}
					else
					{
						sprintf(buf1, "You put all %s onto $P.", short_to_name(&arg1[4], 0));
						sprintf(buf2, "$n puts all %s onto $P.", short_to_name(&arg1[4], 0));
					}
				}
			}
			else
			{
				if (container->item_type != ITEM_FURNITURE)
				{
					sprintf(buf1, "You put all your %s into $P.", short_to_name(found_obj->short_descr, 0));
					sprintf(buf2, "$n puts all $s %s into $P.", short_to_name(found_obj->short_descr, 0));
				}
				else
				{
					sprintf(buf1, "You put all your %s onto $P.", short_to_name(found_obj->short_descr, 0));
					sprintf(buf2, "$n puts all $s %s onto $P.", short_to_name(found_obj->short_descr, 0));
				}
			}
			act( buf1, ch, found_obj, container, TO_CHAR);
			act( buf2, ch, found_obj, container, TO_ROOM);
		}
		else
		{
			act( "You don't have $T.", ch, obj, arg1, TO_CHAR );
		}
	}
	pop_call();
	return;
}

void do_drop( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];

	char buf1[MAX_INPUT_LENGTH];
	char buf2[MAX_INPUT_LENGTH];

	OBJ_DATA *obj			= NULL;
	OBJ_DATA *found_obj		= NULL;
	OBJ_DATA *obj_next		= NULL;

	bool shrtd			= FALSE;
	bool clutter			= FALSE;

	int amount			= 1;
	int cnt				= 0;
	int cnt_not_dropped		= 0;

	push_call("do_drop(%p,%p)",ch,argument);

	argument = one_argument( argument, arg1 );

	if (is_number(arg1))
	{
		amount	= UMAX(1, atol(arg1));
		argument	= one_argument( argument, arg1 );
	}

	if (*arg1 == 0)
	{
		send_to_char( "Drop what?\n\r", ch );
		pop_call();
		return;
	}

	/*
		'drop object'
	*/

	if (strcasecmp(arg1, "all") && str_prefix("all.", arg1))
	{
		if (!strcasecmp(arg1, "gold") || !strcasecmp(arg1, "silver") ||!strcasecmp(arg1, "copper"))
		{
			char buf1[MAX_STRING_LENGTH];
			char buf2[MAX_STRING_LENGTH];
			char buf3[MAX_STRING_LENGTH];
			int val;
			
			if (!strcasecmp(arg1, "gold"))
			{
				if (amount * 100 > ch->gold)
				{
					send_to_char( "You do not have that much coin.\n\r", ch );
					pop_call();
					return;
				}
				if (amount > 1)
				{
					sprintf(buf1, "gold coins");
					sprintf(buf2, "{138}%d gold coins", amount);
					sprintf(buf3, "%s lie here.", buf2);
				}
				else
				{
					sprintf(buf1, "gold coin");
					sprintf(buf2, "{138}1 gold coin");
					sprintf(buf3, "%s lies here.", buf2);
				}
				val = 0;
			}
			else if (!strcasecmp(arg1, "silver"))
			{
				if (amount * 10 > ch->gold)
				{
					send_to_char( "You do not have that much coin.\n\r", ch );
					pop_call();
					return;
				}
				if (amount > 1)
				{
					sprintf(buf1, "silver coins");
					sprintf(buf2, "{078}%d silver coins", amount);
					sprintf(buf3, "%s lie here.", buf2);
				}
				else
				{
					sprintf(buf1, "silver coin");
					sprintf(buf2, "{078}1 silver coin");
					sprintf(buf3, "%s lies here.", buf2);
				}
				val = 1;
			}
			else
			{
				if (amount > ch->gold)
				{
					send_to_char( "You do not have that much coin.\n\r", ch );
					pop_call();
					return;
				}
				if (amount > 1)
				{
					sprintf(buf1, "copper coins");
					sprintf(buf2, "{038}%d copper coins", amount);
					sprintf(buf3, "%s lie here.", buf2);
				}
				else
				{
					sprintf(buf1, "copper coin");
					sprintf(buf2, "{038}1 copper coin");
					sprintf(buf3, "%s lies here.", buf2);
				}
				val = 2;
			}
			obj = create_object(get_obj_index(OBJ_VNUM_MONEY_SOME), 0);
			STRFREE( obj->name );
			obj->name = STRALLOC( buf1 );
			STRFREE( obj->short_descr );
			obj->short_descr = STRALLOC( buf2 );
			STRFREE( obj->long_descr );
			obj->long_descr = STRALLOC( buf3 );
			
			obj->value[val] = amount;
			obj->cost = obj->value[0] * 100;
			obj->cost += obj->value[1] * 10;
			obj->cost += obj->value[2];

			obj_to_char(obj, ch);
			drop_obj(ch, obj, NULL, TRUE);
			ch->gold -= obj->cost;
			ch->carry_weight = get_carry_w(ch);
			pop_call();
			return;
		}
		
		if ((obj = get_obj_carry(ch, arg1)) == NULL)
		{
			send_to_char( "You do not have that item.\n\r", ch );
			pop_call();
			return;
		}
		
		if (amount == 1)
		{
			drop_obj(ch, obj, NULL, TRUE);
			pop_call();
			return;
		}

		for ( ; shrtd <= 1 && !found_obj ; shrtd++)
		{
			for (obj = ch->first_carrying ; obj ; obj = obj_next)
			{
				obj_next = obj->next_content;

				if (!can_see_obj(ch, obj) || !IS_CARRIED(obj))
				{
					continue;
				}

				if (!shrtd && !is_name(arg1, obj->name))
				{
					continue;
				}

				if (shrtd  && !is_name_short(arg1, obj->name))
				{
					continue;
				}

				if (found_obj == NULL)
				{
					found_obj = obj;
				}

				if (obj->short_descr != found_obj->short_descr)
				{
					continue;
				}

				if (drop_obj(ch, obj, NULL, FALSE))
				{
					cnt++;
				}
				else
				{
					cnt_not_dropped++;
				}

				if (cnt >= amount)
				{
					break;
				}
			}
		}
		if (found_obj)
		{
			sprintf(buf1, "You drop %d %s.", cnt, short_to_name(found_obj->short_descr, cnt));
			sprintf(buf2, "$n drops %d %s.", cnt, short_to_name(found_obj->short_descr, cnt));
			act( buf1, ch, found_obj, NULL, TO_CHAR);
			act( buf2, ch, found_obj, NULL, TO_ROOM);
		}
		else
		{
			do_drop(ch, arg1);
		}
		pop_call();
		return;
	}
	else
	{
		/*
			'drop all' or 'drop all.object'
		*/

		for ( ; shrtd <= 1 && !found_obj ; shrtd++)
		{
			for (obj = ch->first_carrying ; obj ; obj = obj_next)
			{
				obj_next = obj->next_content;

				if (!can_see_obj(ch, obj) || !IS_CARRIED(obj))
				{
					continue;
				}

				if (!shrtd && arg1[3] && !is_name(&arg1[4], obj->name))
				{
					continue;
				}

				if (shrtd  && arg1[3] && !is_name_short(&arg1[4], obj->name))
				{
					continue;
				}

				if (found_obj == NULL)
				{
					found_obj = obj;
				}

				if (obj->short_descr != found_obj->short_descr)
				{
					clutter = TRUE;
				}

				if (drop_obj(ch, obj, NULL, FALSE))
				{
					cnt++;
				}
				else
				{
					cnt_not_dropped++;
				}
			}
		}

		if (found_obj)
		{
			if (cnt_not_dropped > 0)
			{
				if (arg1[3] == '\0' || clutter)
				{
					sprintf(buf1, "You drop all but %d of the items.", cnt_not_dropped);
					sprintf(buf2, "$n drops some items.");
				}
				else
				{
					sprintf(buf1, "You drop %d %s.", cnt, short_to_name(found_obj->short_descr, cnt));
					sprintf(buf2, "$n drops %d %s..", cnt, short_to_name(found_obj->short_descr, cnt));
				}
			}
			else if (clutter)
			{
				if (arg1[3] == 0)
				{
					sprintf(buf1, "You drop everything.");
					sprintf(buf2, "$n drops everything.");
				}
				else
				{
					sprintf(buf1, "You drop all your %s.", short_to_name(&arg1[4], 0));
					sprintf(buf2, "$n drops all $s %s.",   short_to_name(&arg1[4], 0));
				}
			}
			else
			{
				sprintf(buf1, "You drop all your %s.", short_to_name(found_obj->short_descr, 0));
				sprintf(buf2, "$n drops all $s %s.",   short_to_name(found_obj->short_descr, 0));
			}
			act( buf1, ch, found_obj, NULL, TO_CHAR);
			act( buf2, ch, found_obj, NULL, TO_ROOM);
		}
		else
		{
			if (!found_obj)
			{
				if (arg1[3] == '\0' )
				{
					act( "You are not carrying anything.", ch, NULL, NULL, TO_CHAR );
				}
				else
				{
					act( "You are not carrying any $T.", ch, NULL, short_to_name(&arg1[4], 0), TO_CHAR );
				}
			}
		}
	}
	pop_call();
	return;
}

void do_give( CHAR_DATA *ch, char *argument )
{
	char arg1 [MAX_INPUT_LENGTH];
	char arg2 [MAX_INPUT_LENGTH];
	char buf1 [MAX_STRING_LENGTH];
	CHAR_DATA *victim;
	OBJ_DATA  *obj;

	push_call("do_give(%p,%p)",ch,argument);

	argument = one_argument( argument, arg1 );
	argument = one_argument( argument, arg2 );
	
	// allow "to" in command - Kregor
	if (!strcasecmp(arg2, "to"))
		argument = one_argument( argument, arg2 );

	if ( arg1[0] == '\0' || arg2[0] == '\0' )
	{
		send_to_char( "Give what to whom?\n\r", ch );
		pop_call();
		return;
	}

	if ( is_number( arg1 ) )
	{
		/* 'give NNNN coins victim' */

		int amount = atol(arg1);

		if (amount <= 0 || (strcasecmp(arg2, "gold") && strcasecmp(arg2, "silver") && strcasecmp(arg2, "copper")))
		{
			send_to_char( "Sorry, you cannot do that.\n\r", ch );
			pop_call();
			return;
		}

		if (amount > 0 && !strcasecmp(arg2, "gold"))
		{
			amount *= 100;
			sprintf(buf1, "{138}%d gold %s{300}", amount/100, amount > 100 ? "pieces" : "piece");
		}
		if (amount > 0 && !strcasecmp(arg2, "silver"))
		{
			amount *= 10;
			sprintf(buf1, "{078}%d silver %s{300}", amount/10, amount > 10 ? "pieces" : "piece");
		}
		if (amount > 0 && !strcasecmp(arg2, "copper"))
		{
			amount *= 1;
			sprintf(buf1, "{038}%d copper %s{300}", amount, amount > 1 ? "pieces" : "piece");
		}
			
		argument = one_argument( argument, arg2 );

		if ( arg2[0] == '\0' )
		{
			send_to_char( "Give what to whom?\n\r", ch );
			pop_call();
			return;
		}

		if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
		{
			send_to_char( "They aren't here.\n\r", ch );
			pop_call();
			return;
		}
		
		if (victim == ch)
		{
			send_to_char("Bribing yourself?? Right...\n\r", ch);
			pop_call();
			return;
		}

		if ( ch->gold < amount )
		{
			send_to_char( "You haven't got that much money.\n\r", ch );
			pop_call();
			return;
		}

		gold_transaction(ch, 0 - amount);
		gold_transaction(victim, amount);

		act( "You give $t to $N.", ch, buf1, victim, TO_CHAR);
		act( "$n gives you $t.", ch, buf1, victim, TO_VICT);
		act( "$n gives $N some money.",  ch, NULL, victim, TO_NOTVICT);

		mprog_bribe_trigger(victim, ch, amount);

		pop_call();
		return;
	}

	if ( ( obj = get_obj_carry( ch, arg1 ) ) == NULL )
	{
		send_to_char( "You do not have that item.\n\r", ch );

		pop_call();
		return;
	}

	if (IS_WORN(obj))
	{
		send_to_char( "You have to remove it first.\n\r", ch );
		pop_call();
		return;
	}

	if (!IS_CARRIED(obj))
	{
		send_to_char( "You can't find it to give it.\n\r", ch );
		pop_call();
		return;
	}

	if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
	{
		send_to_char( "They aren't here.\n\r", ch );
		pop_call();
		return;
	}

	if (victim == ch)
	{
		send_to_char( "But, you already have it.\n\r", ch );
		pop_call();
		return;
	}

	if (!can_drop_obj(ch, obj) && !IS_IMMORTAL(ch))
	{
		send_to_char( "You cannot let go of it.\n\r", ch );
		pop_call();
		return;
	}

	if (!IS_IMMORTAL(ch))
	{
		if (victim->carry_number >= can_carry_n(victim))
		{
			act( "$N cannot carry that many items.", ch, NULL, victim, TO_CHAR );
			pop_call();
			return;
		}
	}

	if (!IS_IMMORTAL(ch))
	{
		if ( !can_see_obj( victim, obj ) )
		{
			act( "$N cannot see it.", ch, NULL, victim, TO_CHAR );
			pop_call();
			return;
		}
		if (get_carry_w(victim) + get_obj_weight( obj ) > can_carry_w( victim ) * 2)
		{
			act( "$N cannot even begin to carry $p.", ch, obj, victim, TO_CHAR );
			act( "$n tries to give you $p, but it's far too heavy.", ch, obj, victim, TO_VICT );
			pop_call();
			return;
		}
	}

	act( "You give $p to $N.", ch, obj, victim, TO_CHAR    );
	act( "$n gives you $p.",   ch, obj, victim, TO_VICT    );
	act( "$n gives $p to $N.", ch, obj, victim, TO_NOTVICT );

	if (!IS_IMMORTAL(ch))
	{
		if (get_carry_w(victim) + get_obj_weight( obj ) > can_carry_w( victim ) )
		{
			act( "$N buckles under the weight you've given $M.", ch, NULL, victim, TO_CHAR );
			act( "You buckle under the weight $n gives you.", ch, NULL, victim, TO_VICT );
		}
		else if (get_carry_w(victim) + get_obj_weight( obj ) > can_carry_w( victim ) * 2 / 3 )
		{
			act( "$N is close to carrying all $E can.", ch, NULL, victim, TO_CHAR );
			act( "You bear the weight of $p with considerable effort.", ch, NULL, victim, TO_VICT );
		}
		else if (get_carry_w(victim) + get_obj_weight( obj ) > can_carry_w( victim ) / 3)
		{
			act( "$N shows a little effort trying to carry $p.", ch, obj, victim, TO_CHAR );
			act( "You bear the weight of $p with a little effort.", ch, NULL, victim, TO_VICT);
		}
	}

	if (obj->item_type == ITEM_MONEY)
	{
		give_gold(victim, obj->value[0] * 100);
		give_gold(victim, obj->value[1] * 10);
		give_gold(victim, obj->value[2]);
		junk_obj(obj);
	}
	else
	{
		obj_to_char( obj, victim );

		if (IS_NPC(victim))
		{
			mprog_give_trigger(victim, ch, obj);
		}
		oprog_give_trigger(ch, obj);
	}
	pop_call();
	return;
}

/*
 * REQUEST command uses Diplomacy skill to ask for
 * an obj from NPC. Also used with pets to obtain
 * items from them. - Kregor
 */
void do_request(CHAR_DATA *ch, char *argument)
{
	char arg1 [MAX_INPUT_LENGTH];
	char arg2 [MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	OBJ_DATA  *obj;
	int roll, dc;

	push_call("do_request(%p)",ch);

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

	// allow "from" in command - Kregor
	if (!strcasecmp(arg2, "from"))
		argument = one_argument( argument, arg2 );

	if (IS_NPC(ch))
	{
		pop_call();
		return;
	}

	if (arg1[0] == '\0' || arg2[0] == '\0')
	{
		send_to_char("Request what from whom?\n\r", ch);
		pop_call();
		return;
	}

	if ((victim = get_char_room(ch, arg2)) == NULL)
	{
		send_to_char("They aren't here.\n\r", ch);
		pop_call();
		return;
	}
	
	if (find_keeper(victim) != NULL)
	{
		send_to_char("You cannot request in shops.\n\r", ch);
		pop_call();
		return;
	}

	if (!IS_NPC(victim))
	{
		send_to_char("Why don't you just ask?\n\r", ch);
		pop_call();
		return;
	}	

	if (((obj = get_obj_carry(victim , arg1)) == NULL
	&& (obj = get_obj_wear(victim, arg1)) == NULL)
	|| !can_see_obj(ch, obj))
	{
		act( "$N does not appear to have that.", ch, NULL, victim, TO_CHAR);
		pop_call();
		return;
	}
	
	// master can request anything from pet w/o check - Kregor
	if (!is_master(victim, ch))
	{
		if (!CAN_TALK(victim) || !can_understand(victim, ch, FALSE))
		{
			send_to_char("They cannot understand your request.\n\r", ch);
			pop_call();
			return;
		}

		log_god_printf("REQUEST %s is attempting to request %s from %s", ch->name, arg1, victim->name);

		/* uses modified diplomacy skill rules */
		roll = diplomacy_roll(ch);
		roll += reputation_bonus(ch);
		if (ch->race == victim->race && learned(ch, gsn_noble_birth))
			roll += 2;
		dc = dice(1,20) + victim->level + stat_bonus(TRUE, victim, APPLY_WIS);
		dc += OPPOSITE_ALIGN(ch, victim) / 5;
		if (ch->god == victim->god)
			dc -= 5;
		if (god_table[victim->god].faith_enemy[ch->god])
			dc += 10;
		if (!IS_ACT(victim, ACT_REQUEST) || !diplomacy_check(ch, victim, roll, dc))
		{
			act("$n requests $p from $N, but is refused.", ch, obj, victim, TO_ROOM);
			act("$N denies your request for $p.", ch, obj, victim, TO_CHAR);
			pop_call();
			return;
		}
	}

	if (IS_WORN(obj))
		unequip_char(victim, obj, TRUE);

	if (!can_drop_obj(victim, obj)) 
	{
		act( "$N cannot let go of it.", ch, NULL, victim, TO_CHAR);
		pop_call();
		return;
	}

	if (ch->carry_number + 1 > can_carry_n(ch))
	{
		send_to_char("You are carrying too much.\n\r", ch);
		pop_call();
		return;
	}

	if (ch->carry_weight + get_obj_weight(obj) > can_carry_w(ch) * 2)
	{
		send_to_char("You can't carry that much weight.\n\r", ch);
		pop_call();
		return;
	}

	obj->cost = 1;
	obj_from_char(obj);
	obj_to_char(obj, ch);
	act( "$n requests $p from $N, who gives it willingly.", ch, obj, victim, TO_NOTVICT);
	act( "You request $p from $N, who gives it willingly.",	 ch, obj, victim, TO_CHAR);
	act( "$n requests $p from you.", ch, obj, victim, TO_VICT);

	pop_call();
	return;
}

/*
 * DEMAND command uses intimidate to demand an obj
 * from an NPC, results in a penalty to alignment. - Kregor
 */
void do_demand(CHAR_DATA *ch, char *argument)
{
	char arg1 [MAX_INPUT_LENGTH];
	char arg2 [MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	OBJ_DATA  *obj;
	int roll;

	push_call("do_demand(%p)",ch);

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

	// allow "from" in command - Kregor
	if (!strcasecmp(arg2, "from"))
		argument = one_argument( argument, arg2 );

	if (IS_NPC(ch))
	{
		pop_call();
		return;
	}

	if (arg1[0] == '\0' || arg2[0] == '\0')
	{
		send_to_char("Demand what from whom?\n\r", ch);
		pop_call();
		return;
	}

	if ((victim = get_char_room(ch, arg2)) == NULL)
	{
		send_to_char("They aren't here.\n\r", ch);
		pop_call();
		return;
	}

	if (find_keeper(victim) != NULL)
	{
		send_to_char("You cannot demand in shops.\n\r", ch);
		pop_call();
		return;
	}

	if (!IS_NPC(victim))
	{
		send_to_char("Why don't you just ask?\n\r", ch);
		pop_call();
		return;
	}	

	if (!CAN_TALK(victim) || !can_understand(victim, ch, FALSE))
	{
		send_to_char("They cannot understand your request.\n\r", ch);
		pop_call();
		return;
	}
	if (is_immune(victim, SDESC_FEAR))
	{
		send_to_char("They are immune to your threats.\n\r", ch);
		pop_call();
		return;
	}
	
	log_god_printf("DEMAND %s is attempting to demand %s from %s", ch->name, arg1, victim->name);

	/* uses intimidate skill rules */
	roll = intimidate_roll(ch);
	//reputation = positive mod for intimidate
	roll -= OPPOSITE_ALIGN(ch, victim) / 5;

	if (((obj = get_obj_carry(victim , arg1)) == NULL
	&& (obj = get_obj_wear(victim, arg1)) == NULL)
	|| !can_see_obj(ch, obj))
	{
		act( "$N does not appear to have that.", ch, NULL, victim, TO_CHAR);
		pop_call();
		return;
	}
	
	if (intimidate_check(ch, victim, roll, 0) >= 0)
	{
		if (CAN_TALK(victim))
		{
			do_say(victim, "I'm not about to give you anything!");
			command(victim, do_shout, "Help! I am being assaulted by %s at %s.", adjective(ch), victim->in_room->name);
			if (IS_CITIZEN(victim))
			{
				set_bounty(victim, ch, CRIME_ASSAULT);
				check_guard_assist(victim, ch);
			}
			gain_reputation(ch, -1);
		}
		else
		{
			act("$n attempts to bully $N for $p, but is refused.", ch, obj, victim, TO_ROOM);
			act("$N resists your attempt to bully $M.", ch, obj, victim, TO_CHAR);
		}
		pop_call();
		return;
	}

	if (IS_WORN(obj))
		unequip_char(victim, obj, TRUE);

	if (!can_drop_obj(victim, obj)) 
	{
		act( "$N cannot let go of it.", ch, NULL, victim, TO_CHAR);
		pop_call();
		return;
	}

	if (ch->carry_number + 1 > can_carry_n(ch))
	{
		send_to_char("You are carrying too much.\n\r", ch);
		pop_call();
		return;
	}

	if (ch->carry_weight + get_obj_weight(obj) > can_carry_w(ch) * 2)
	{
		send_to_char("You can't carry that much weight.\n\r", ch);
		pop_call();
		return;
	}

	obj->cost = 1;
	obj_from_char(obj);
	obj_to_char(obj, ch);
	act( "$n demands $p from $N, who gives it over trembling.", ch, obj, victim, TO_NOTVICT);
	act( "You demand $p from $N, who gives it over trembling.",	ch, obj, victim, TO_CHAR  );
	act( "$n demands $p from you.", ch, obj, victim, TO_VICT  );
	
	if (!IS_EVIL(victim))
	{
		ch->alignment = UMAX(-1000, ch->alignment - 10);
		send_to_char_color("{108}Your alignment has shifted 10 points toward evil.\n\r", ch);
	}
	
	pop_call();
	return;
}

/*
 * SWINDLE command uses bluff to con an obj from mobile
 * from an NPC, results in a penalty to ethos. - Kregor
 */
void do_swindle(CHAR_DATA *ch, char *argument)
{
	char arg1 [MAX_INPUT_LENGTH];
	char arg2 [MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	OBJ_DATA  *obj;
	int roll, dc;

	push_call("do_swindle(%p)",ch);

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

	// allow "from" in command - Kregor
	if (!strcasecmp(arg2, "from"))
		argument = one_argument( argument, arg2 );

	if (IS_NPC(ch))
	{
		pop_call();
		return;
	}

	if (arg1[0] == '\0' || arg2[0] == '\0')
	{
		send_to_char("Swindle what from whom?\n\r", ch);
		pop_call();
		return;
	}

	if ((victim = get_char_room(ch, arg2)) == NULL)
	{
		send_to_char("They aren't here.\n\r", ch);
		pop_call();
		return;
	}

	if (find_keeper(victim) != NULL)
	{
		send_to_char("You cannot swindle a shopkeeper.\n\r", ch);
		pop_call();
		return;
	}

	if (!IS_NPC(victim))
	{
		send_to_char("Why don't you just ask?\n\r", ch);
		pop_call();
		return;
	}	

	if (!CAN_TALK(victim) || !can_understand(victim, ch, FALSE))
	{
		send_to_char("They cannot understand your request.\n\r", ch);
		pop_call();
		return;
	}

	log_god_printf("SWINDLE %s is attempting to swindle %s from %s", ch->name, arg1, victim->name);

	/* uses bluff skill rules */
	roll = intimidate_roll(ch);

	dc = sense_motive_roll(victim);

	if (((obj = get_obj_carry(victim , arg1)) == NULL
	&& (obj = get_obj_wear(victim, arg1)) == NULL)
	|| !can_see_obj(ch, obj))
	{
		act( "$N does not appear to have that.", ch, NULL, victim, TO_CHAR);
		pop_call();
		return;
	}
	
	if (!bluff_check(ch, victim, roll, dc))
	{
		act("$n attempts to bluff $N out of $p, but is refused.", ch, obj, victim, TO_ROOM);
		act("$N refuses your attempt to bluff $M.", ch, obj, victim, TO_CHAR);
		pop_call();
		return;
	}

	if (IS_WORN(obj))
		unequip_char(victim, obj, TRUE);

	if (!can_drop_obj(victim, obj)) 
	{
		act( "$N cannot let go of it.", ch, NULL, victim, TO_CHAR);
		pop_call();
		return;
	}

	if (ch->carry_number + 1 > can_carry_n(ch))
	{
		send_to_char("You are carrying too much.\n\r", ch);
		pop_call();
		return;
	}

	if (ch->carry_weight + get_obj_weight(obj) > can_carry_w(ch) * 2)
	{
		send_to_char("You can't carry that much weight.\n\r", ch);
		pop_call();
		return;
	}

	obj->cost = 1;
	obj_from_char(obj);
	obj_to_char(obj, ch);
	act( "$N willingly gives $p to $n.", ch, obj, victim, TO_NOTVICT);
	act( "You manage to con $N out of $p.", ch, obj, victim, TO_CHAR  );
	act( "$n swindles you for $p.", ch, obj, victim, TO_VICT  );
	
	ch->ethos = UMAX(-1000, ch->ethos - 10);
	send_to_char_color("{108}Your alignment has shifted 10 points toward chaotic.\n\r", ch);
	
	pop_call();
	return;
}

/*
 * Added containers - Kregor
 */
void do_fill( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	OBJ_DATA *fountain;
	bool found;

	push_call("do_fill(%p,%p)",ch,argument);

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

	// allow "with" in command - Kregor
	if (!strcasecmp(arg2, "with"))
		argument = one_argument( argument, arg2 );

	if (arg1[0] == '\0')
	{
		send_to_char( "Fill what?\n\r", ch );
		pop_call();
		return;
	}

	if ((obj = get_obj_carry(ch, arg1)) == NULL)
	{
		send_to_char( "You are not carrying that item.\n\r", ch );
		pop_call();
		return;
	}

	found = FALSE;

	/* adding refillable lamps and lanterns */
	if (IS_OBJ_TYPE(obj, ITEM_LIGHT))
	{
		if (!obj->value[1])
		{
			act( "$p cannot be refilled.", ch, obj, NULL, TO_CHAR );
			pop_call();
			return;
		}
		if (obj->value[2] >= obj->pIndexData->value[2])
		{
			act( "$p is already full.", ch, obj, NULL, TO_CHAR );
			pop_call();
			return;
		}
		if (arg2[0] == '\0')
		{
			act( "Fill $p from what?", ch, obj, NULL, TO_CHAR );
			pop_call();
			return;
		}
		if ((fountain = get_obj_carry(ch, arg2)) == NULL)
		{
			if ((fountain = get_obj_carry_type(ch, ITEM_DRINK_CON)) == NULL)
			{
				act("You aren't carrying something to fill $p with.", ch, obj, NULL, TO_CHAR);
				pop_call();
				return;
			}
		}
		if (!IS_OBJ_TYPE(fountain, ITEM_DRINK_CON))
		{
			act( "You cannot fill $p with $P.", ch, obj, fountain, TO_CHAR );
			pop_call();
			return;
		}
		if (fountain->value[2] != LIQ_OIL)
		{
			act( "You can only fill $p with oil.", ch, obj, NULL, TO_CHAR );
			pop_call();
			return;
		}	
		if (fountain->value[1] == 0)
		{
			act( "$p is already empty.", ch, fountain, NULL, TO_CHAR );
			pop_call();
			return;
		}	
		act( "You fill $p from $P.", ch, obj, fountain, TO_CHAR );
		act( "$n fills $p from $P.", ch, obj, fountain, TO_ROOM );
		
		int amount = obj->pIndexData->value[2] - obj->value[2];

		obj->value[2] += UMIN(amount, fountain->value[1]);
		if (fountain->value[1] >= 0)
			fountain->value[1] = UMAX(0, fountain->value[1] - amount);
		if (obj->value[2] >= obj->pIndexData->value[2])
			act( "$p is now full.", ch, obj, NULL, TO_CHAR );
		if (fountain->value[1] == 0)
			act( "$p is now empty.", ch, fountain, NULL, TO_CHAR );
	}
	else if (IS_OBJ_TYPE(obj, ITEM_DRINK_CON))
	{
		int amount;

		if ((amount = obj->value[0] - obj->value[1]) <= 0 || obj->value[1] == -1)
		{
			act( "$p is already full.", ch, obj, NULL, TO_CHAR );
			pop_call();
			return;
		}
		if (arg2[0] == '\0')
		{
			for (fountain = ch->in_room->first_content ; fountain ; fountain = fountain->next_content)
			{
				if (IS_OBJ_TYPE(fountain, ITEM_FOUNTAIN))
				{
					break;
				}
			}		
			if (!fountain)
			{
				act( "Fill $p with what?", ch, obj, NULL, TO_CHAR );
				pop_call();
				return;
			}
		}
		else if ((fountain = get_obj_here(ch, arg2)) == NULL)
		{
			ch_printf_color(ch, "You see no %s here.\n\r", arg2);
			pop_call();
			return;
		}
		if (!IS_OBJ_TYPE(fountain, ITEM_FOUNTAIN) && !IS_OBJ_TYPE(fountain, ITEM_DRINK_CON))
		{
			act( "You cannot fill $p with $P.", ch, obj, fountain, TO_CHAR );
			act( "$n tries to fill $p with $P... (Don't ask how.)", ch, obj, fountain, TO_ROOM );
			pop_call();
			return;
		}		
		if (obj->value[1] != 0 && obj->value[2] != fountain->value[2])
		{
			send_to_char( "There is already another liquid in it.\n\r", ch );
			pop_call();
			return;
		}	
		if (fountain->value[1] == 0)
		{
			act( "$p is already empty.", ch, fountain, NULL, TO_CHAR );
			pop_call();
			return;
		}	
		act( "You fill $p from $P.", ch, obj, fountain, TO_CHAR );
		act( "$n fills $p from $P.", ch, obj, fountain, TO_ROOM );
		obj->value[2] = fountain->value[2];
		obj->value[1] += UMIN(amount, fountain->value[1]);
		if (fountain->value[1] >= 0)
			fountain->value[1] = UMAX(0, fountain->value[1] - amount);
		if (obj->value[1] >= obj->value[0])
			act( "$p is now full.", ch, obj, NULL, TO_CHAR );
		if (fountain->value[1] == 0)
			act( "$p is now empty.", ch, fountain, NULL, TO_CHAR );
		
		pop_call();
		return;
	}

	if (!IS_OBJ_TYPE(obj, ITEM_CONTAINER)
	&& !IS_OBJ_TYPE(obj, ITEM_SPELLPOUCH)
	&& !IS_OBJ_TYPE(obj, ITEM_QUIVER))
	{
		act( "You cannot fill $p.", ch, obj, NULL, TO_CHAR );
		pop_call();
		return;
	}
	
	if (in_combat(ch))
	{
		act( "You cannot fill $p while you are in combat.", ch, obj, NULL, TO_CHAR );
		pop_call();
		return;
	}
	
	if (IS_SET(obj->value[1], CONT_CLOSED))
	{
		act( "$p is closed.", ch, obj, NULL, TO_CHAR );
		pop_call();
		return;
	}

	OBJ_DATA *get_obj, *obj_next;
	OBJ_DATA *found_obj = NULL;
	
	for (get_obj = ch->in_room->first_content ; get_obj ; get_obj = obj_next)
	{
		obj_next = get_obj->next_content;

		if (!can_see_obj(ch, get_obj) || !IS_SET(get_obj->wear_flags, CAN_WEAR_TAKE))
		{
			continue;
		}
		
		if (IS_OBJ_TYPE(obj, ITEM_SPELLPOUCH)) // only put components in spell pouch
		{
			if (get_obj->item_type != ITEM_COMPONENT
			&& (get_obj->item_type != ITEM_TREASURE || !get_obj->value[5]))
				continue;
		}

		if (IS_OBJ_TYPE(obj, ITEM_QUIVER) && get_obj->item_type != ITEM_AMMO) // only ammo in quiver
			continue;

		if (get_carry_w(ch) + get_obj_weight(get_obj) > can_carry_w(ch))
		{
			continue;
		}

		if (!put_obj(ch, get_obj, obj, FALSE, FALSE))
		{
			continue;
		}

		if (found_obj == NULL)
		{
			found_obj = get_obj;
		}
	}
	if (found_obj == NULL)
	{
		act( "You see nothing here to fill $p with.", ch, obj, NULL, TO_CHAR );
	}
	else
	{
		act( "You fill $p.", ch, obj, NULL, TO_CHAR );
		act( "$n fills $p.", ch, obj, NULL, TO_ROOM );
		
		if (get_carry_w(ch) >= can_carry_w(ch))
		{
			act( "You strain under the weight of $p!", ch, obj, NULL, TO_CHAR);
			act( "$n strains under the weight of $p!", ch, obj, NULL, TO_ROOM);
		}
		else if (get_carry_w(ch) > can_carry_w(ch) * 2 / 3)
		{
			act( "You carry $p with considerable effort.", ch, obj, NULL, TO_CHAR);
			act( "$n carries $p with considerable effort.", ch, obj, NULL, TO_ROOM);
		}
		else if (get_carry_w(ch) > can_carry_w(ch) / 3)
		{
			act( "You encumber yourself with $p.", ch, obj, NULL, TO_CHAR);
			act( "$n carries $p with a little effort.", ch, obj, NULL, TO_ROOM);
		}		
	}
	pop_call();
	return;
}


/*
 * Variant of do_fill, to empty - Kregor
 */
void do_empty( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	OBJ_DATA *obj, *tar_obj;
	CHAR_DATA *victim;
	int amount;

	push_call("do_empty(%p,%p)",ch,argument);

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

	// allow prepositions in command - Kregor
	if (!strcasecmp(arg2, "into") || !strcasecmp(arg2, "onto"))
		argument = one_argument( argument, arg2 );

	if (arg1[0] == '\0')
	{
		send_to_char( "Fill what?\n\r", ch );
		pop_call();
		return;
	}

	if ((obj = get_obj_carry(ch, arg1)) == NULL)
	{
		send_to_char( "You are not carrying that item.\n\r", ch );
		pop_call();
		return;
	}

	if (IS_OBJ_TYPE(obj, ITEM_DRINK_CON))
	{
		if ((amount = obj->value[1]) == 0)
		{
			act( "$p is already empty.", ch, obj, NULL, TO_CHAR );
			pop_call();
			return;
		}
		if ((amount = obj->value[1]) == -1)
		{
			act( "You pour $p, but it never seems to empty.", ch, obj, NULL, TO_CHAR );
			act( "$n pours $p, but it never seems to empty.", ch, obj, NULL, TO_ROOM );
			pop_call();
			return;
		}
		
		victim = NULL;
		tar_obj = NULL;
		
		if (arg2[0] != '\0')
		{
			if ((tar_obj = get_obj_here(ch, arg2)) == NULL)
			{
				if ((victim = get_char_room(ch, arg2)) == NULL)
				{
					ch_printf_color(ch, "You see no %s here.\n\r", arg2);
					pop_call();
					return;
				}
			}
		}
		if (tar_obj)
		{
			if (IS_OBJ_TYPE(tar_obj, ITEM_DRINK_CON))
			{
				if (tar_obj->value[1] != 0 && tar_obj->value[2] != obj->value[2])
				{
					send_to_char( "There is already another liquid in it.\n\r", ch );
					pop_call();
					return;
				}
				act( "You pour $p into $P.", ch, obj, tar_obj, TO_CHAR );
				act( "$n pours $p into $P.", ch, obj, tar_obj, TO_ROOM );
				amount = UMIN(amount, tar_obj->value[0] - tar_obj->value[1]);
				tar_obj->value[1] += amount;
				tar_obj->value[2] = obj->value[2];
				obj->value[1] -= amount;
				
				pop_call();
				return;
			}
			act( "You empty $p onto $P.", ch, obj, tar_obj, TO_CHAR );
			act( "$n empties $p onto $P.", ch, obj, tar_obj, TO_ROOM );
			if (IS_OBJ_TYPE(tar_obj, ITEM_FIRE))
			{
				act("$p is extinguished.", ch, tar_obj, NULL, TO_CHAR);
				junk_obj(tar_obj);
			}
		}
		else if (victim)
		{
			act( "You empty $p onto $N.", ch, obj, victim, TO_CHAR );
			act( "$n empties $p onto $N.", ch, obj, victim, TO_NOTVICT );
			act( "$n empties $p onto you.", ch, obj, victim, TO_VICT );
			act( "You are soaking wet!", ch, NULL, victim, TO_VICT );
		}
		else
		{
			act( "You pours out $p.", ch, obj, NULL, TO_CHAR );
			act( "$n pours out $p.", ch, obj, NULL, TO_ROOM );
		}
		obj->value[1] = 0;
		if (obj->value[0] <= 2)
			junk_obj(obj);
		
		pop_call();
		return;
	}

	if (!IS_OBJ_TYPE(obj, ITEM_CONTAINER)
	&& !IS_OBJ_TYPE(obj, ITEM_SPELLPOUCH)
	&& !IS_OBJ_TYPE(obj, ITEM_QUIVER))
	{
		act( "$p cannot be emptied.", ch, obj, NULL, TO_CHAR );
		pop_call();
		return;
	}

	if (IS_SET(obj->value[1], CONT_CLOSED))
	{
		act( "$p is closed.", ch, obj, NULL, TO_CHAR );
		pop_call();
		return;
	}

	if (!obj->first_content)
	{
		act( "$p is already empty.", ch, obj, NULL, TO_CHAR );
		pop_call();
		return;
	}
	
	if (arg2[0] != '\0')
	{
		if ((tar_obj = get_obj_here(ch, arg2)) != NULL)
		{
			if (!IS_OBJ_TYPE(tar_obj, ITEM_CONTAINER)
			&& !IS_OBJ_TYPE(tar_obj, ITEM_SPELLPOUCH)
			&& !IS_OBJ_TYPE(tar_obj, ITEM_QUIVER))
			{
				act( "$p is not a container.", ch, tar_obj, NULL, TO_CHAR );
				pop_call();
				return;
			}
			if (IS_SET(tar_obj->value[1], CONT_CLOSED))
			{
				act( "$p is closed.", ch, tar_obj, NULL, TO_CHAR );
				pop_call();
				return;
			}
	
			act( "You empty $p into $P.", ch, obj, tar_obj, TO_CHAR );
			act( "$n empties $p into $P.", ch, obj, tar_obj, TO_ROOM );
	
			while (obj->first_content)
			{
				if (!put_obj(ch, obj->first_content, tar_obj, FALSE, FALSE))
				{
					obj->first_content->sac_timer = OBJ_SAC_TIME;
					obj_to_room(obj->first_content, ch->in_room->vnum);
					act( "  $p falls out onto the floor.", ch, obj->first_content, NULL, TO_ROOM);
				}
				else
				{
					obj_to_obj(obj->first_content, tar_obj);
				}
			}
			pop_call();
			return;
		}
	}
	
	while (obj->first_content)
	{
		obj->first_content->sac_timer = OBJ_SAC_TIME;
		obj_to_room(obj->first_content, ch->in_room->vnum);
	}
	act( "You empty out $p.", ch, obj, NULL, TO_CHAR );
	act( "$n empties out $p.", ch, obj, NULL, TO_ROOM );
	
	pop_call();
	return;
}

/*
 * Added potions here instead of quaff - Kregor
 * Also added drinking water from watery sectors
 */
void drink_obj( CHAR_DATA *ch, OBJ_DATA *obj )
{
	CHAR_DATA *rch;
	int liquid;

	push_call("drink_obj(%p,%p)",ch,obj);
	
	if (IS_INCORPOREAL(ch))
	{
		act("You are unable to drink $p.", ch, obj, NULL, TO_CHAR);
		pop_call();
		return;
	}
	switch (obj->item_type)
	{
		default:
			send_to_char( "You cannot drink from that.\n\r", ch );
			pop_call();
			return;

		// move potion quaffing to the drink function - Kregor
		case ITEM_POTION:
			if (obj->value[1] == 0 || obj->value[0] == 0)
			{
				act( "$p is already empty.", ch, obj, NULL, TO_CHAR);
				pop_call();
				return;
			}
			if (in_combat(ch))
			{
				for (rch = ch->in_room->first_person ; rch ; rch = rch->next_in_room)
				{
					if (who_fighting(rch) && who_fighting(rch) == ch)
					{
						attack_of_opportunity(rch, ch);
					}
				}
			}
			act( "You drink $p.", ch, obj, NULL ,TO_CHAR );
			act( "$n drinks $p.", ch, obj, NULL, TO_ROOM );
		
			if (obj_cast_spell( obj->value[1], obj->value[0], ch, ch, obj ))
			{
				obj->value[0] = 0;
				obj->value[1] = 0;
				REMOVE_BIT(obj->extra_flags, ITEM_MAGIC);
			}
			break;

		case ITEM_DRINK_CON:
		case ITEM_FOUNTAIN:
			if (obj->item_type == ITEM_DRINK_CON && obj->value[1] == 0)
			{
				act( "$p is already empty.", ch, obj, NULL, TO_CHAR );
				pop_call();
				return;
			}

			if ((liquid = obj->value[2]) >= LIQ_MAX)
			{
				log_printf( "do_drink(%s, i%d) bad liquid number %d.", get_name(ch), obj->pIndexData->vnum, liquid);
				liquid = obj->value[2] = 0;
			}

			act( "You drink $T from $p.", ch, obj, liq_table[liquid].liq_name, TO_CHAR );
			act( "$n drinks from $p.", ch, obj, NULL, TO_ROOM );

			if (!IS_RACE(ch, RACE_VAMPIRE) || liquid == LIQ_BLOOD)
			{
				if (!IS_NPC(ch))
				{
					gain_condition( ch, COND_DRUNK, liq_table[liquid].liq_affect[COND_DRUNK] );
					gain_condition( ch, COND_FULL, liq_table[liquid].liq_affect[COND_FULL] );
					gain_condition( ch, COND_THIRST, liq_table[liquid].liq_affect[COND_THIRST] );
				}
				if (obj->value[3] != 0 && poison_table[obj->value[3]].type == POISON_TYPE_INGEST)	/* poisoned */
				{
					POISON_DATA pd;

					pd.type      					= obj->value[3];
					pd.constant_duration  = -1;
					pd.owner  						= -1;
					pd.poisoner  					= -1;
					pd.dc									= 0;
					poison_to_char( ch, ch, &pd );
				}
			}
			if (obj->poison != NULL && poison_table[obj->poison->type].type == POISON_TYPE_INGEST) /* the better poison code */
			{
				obj_affect_poison(obj, ch);
			}
			if (obj->item_type == ITEM_DRINK_CON)
			{
				obj->value[1] -= 1;
				if (obj->value[1] <= 0 && obj->value[0] <= 2)
				{
					act( "You finish $p.\n\r", ch, obj, NULL, TO_CHAR );
					act( "$n finishes $p.\n\r", ch, obj, NULL, TO_ROOM );
					junk_obj( obj );
				}
			}
			break;

		case ITEM_CORPSE_NPC:
		case ITEM_CORPSE_PC:
			if (IS_RACE(ch, RACE_VAMPIRE))
			{
				if (obj->level > 1)
				{
					int wanted = 24;

					if (!IS_NPC(ch))
					{
						wanted = 48 - ch->pcdata->condition[COND_THIRST];
					}

					if ((wanted = UMIN(wanted, obj->level)) == 0)
					{
						ch_printf_color(ch, "You are too full to drink from %s.\n\r", obj->short_descr);
					}
					else
					{
						gain_condition(ch, COND_FULL,   wanted);
						gain_condition(ch, COND_THIRST, wanted);

						if (ch->hit < get_max_hit(ch))
						{
							int heal = UMIN(wanted, get_max_hit(ch)-ch->hit);
							ch_printf_color(ch,"You drink blood from %s, restoring %d hp.\n\r", obj->short_descr, heal);
							ch->hit += heal;
						}
						else
						{
							ch_printf_color(ch,"You drink blood from %s.\n\r",obj->short_descr);
						}
						obj->level -= wanted;
						act( "$n drinks blood from the $p.", ch, obj, NULL, TO_ROOM );
					}
					/*
						the corpse remains, it's only drained!
					*/
				}
				else
				{
					ch_printf_color(ch,"There's no blood left in %s.\n\r", obj->short_descr);
				}
				break;
			}
			else
			{
				send_to_char("You cannot drink from that.\n\r",ch);
				break;
			}
	}	
	pop_call();
	return;
}

void do_drink( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	int cnt;
	bool Drank = FALSE;

	push_call("do_drink(%p,%p)",ch,argument);

	if (!check_blind(ch))
	{
		pop_call();
		return;
	}

	one_argument( argument, arg );

	if (arg[0] == '\0')
	{
		if ((obj = get_obj_wear_type(ch, ITEM_DRINK_CON)) == NULL)
		{
			for (obj = ch->in_room->first_content ; obj ; obj = obj->next_content)
			{
				if (obj->item_type == ITEM_FOUNTAIN)
				{
					break;
				}
			}
			// add in ability to drink from watery sectors - Kregor
			if (IS_RACE(ch, RACE_VAMPIRE))
			{
				for (cnt = 0 ; cnt < MAX_LAST_LEFT ; cnt++)
				{
					if (IS_SET(ch->in_room->last_left_bits[cnt], TRACK_BLOOD))
					{
						/* vampires drink blood-trails too */
						send_to_char( "You lick blood from the ground.\n\r", ch );
						act( "$n licks blood from the ground.", ch, NULL, NULL, TO_ROOM );
						gain_condition( ch, COND_FULL,   2);
						gain_condition( ch, COND_THIRST, 2);
	
						REMOVE_BIT(ch->in_room->last_left_bits[cnt], TRACK_BLOOD);
						Drank = TRUE;
					}
				}
			}
			else
			{
				switch (ch->in_room->sector_type)
				{
					default:
						break;
						
					case SECT_LAKE:
					case SECT_RIVER:
						if (!IS_NPC(ch))
						{
							gain_condition( ch, COND_FULL, liq_table[LIQ_WATER].liq_affect[COND_FULL] );
							gain_condition( ch, COND_THIRST, liq_table[LIQ_WATER].liq_affect[COND_THIRST] );
						}
						act ("{168}You take a drink of the water.", ch, NULL, NULL, TO_CHAR);
						act ("{168}$n takes a drink of the water.", ch, NULL, NULL, TO_ROOM);
						Drank = TRUE;
						break;
					case SECT_OCEAN:
						if (!IS_NPC(ch))
						{
							gain_condition( ch, COND_FULL, liq_table[LIQ_SALTWATER].liq_affect[COND_FULL] );
							gain_condition( ch, COND_THIRST, liq_table[LIQ_SALTWATER].liq_affect[COND_THIRST] );
						}
						act ("{148}You take a drink of salt water.", ch, NULL, NULL, TO_CHAR);
						act ("{148}$n takes a drink of salt water.", ch, NULL, NULL, TO_ROOM);
						Drank = TRUE;
						break;
				}
			}			
		}
	}
	else
	{
		if ((obj = get_obj_here(ch, arg)) == NULL)
		{
			send_to_char( "You cannot find that.\n\r", ch );

			pop_call();
			return;
		}
	}

	if (obj && !IS_NPC(ch) && ch->pcdata->condition[COND_DRUNK] > 10)
	{
		send_to_char( "You fail to reach your mouth. *Hic*\n\r", ch );
		pop_call();
		return;
	}
	
	if (!Drank)
	{
		if (obj == NULL)
		{
			send_to_char( "Drink what?\n\r", ch );
			pop_call();
			return;
		}
		drink_obj(ch, obj);
	}
	else
	{
		TAKE_ACTION(ch, ACTION_STANDARD);
	}
	pop_call();
	return;
}

/*
 * Altered do_eat to take bites from food
 * much like drink takes sips of a container - Kregor
 */
void do_eat( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;

	push_call("do_eat(%p,%p)",ch,argument);

	one_argument( argument, arg );

	if (arg[0] == '\0')
	{
		send_to_char( "Eat what?\n\r", ch );
		pop_call();
		return;
	}

	if ((obj = get_obj_here(ch, arg)) == NULL)
	{
		send_to_char( "You do not see that here.\n\r", ch );
		pop_call();
		return;
	}

	if (obj->item_type == ITEM_CORPSE_PC)
	{
		send_to_char( "That's not edible.\n\r", ch );
		pop_call();
		return;
	}

	if (IS_GOD(ch))
	{
		act( "You eat $p.", ch, obj, NULL, TO_CHAR );
		act( "$n eats $p.",  ch, obj, NULL, TO_ROOM );
		junk_obj( obj );
		pop_call();
		return;
	}

	if (obj->item_type != ITEM_FOOD && obj->item_type != ITEM_PILL)
	{
		send_to_char( "That's not edible.\n\r", ch );
		pop_call();
		return;
	}

	if (obj->item_type != ITEM_PILL && who_fighting(ch))
	{
		send_to_char( "You may not do that while fighting.\n\r", ch);
		pop_call();
		return;
	}

	if (!IS_NPC(ch) && ch->pcdata->condition[COND_FULL] >= 48 && obj->item_type != ITEM_PILL)
	{
		send_to_char( "You are too full to eat more.\n\r", ch );
		pop_call();
		return;
	}

	switch ( obj->item_type )
	{
		case ITEM_FOOD:
			if (!IS_NPC(ch) && !IS_UNDEAD(ch) && !IS_RACE(ch, RACE_VAMPIRE))
			{
				gain_condition( ch, COND_FULL, 1 );
				--obj->value[0];
			}

			// will eventually have food types to give differet nutrient and effects - Kregor
			switch(obj->value[1])
			{
				case FOOD_GARLIC:
				case FOOD_BREAD:
					break;
			}

			if (obj->value[3] != 0 && poison_table[obj->value[3]].type == POISON_TYPE_INGEST)	/* classic poison */
			{
				POISON_DATA pd;

				pd.type      					= obj->value[3];
				pd.constant_duration  = -1;
				pd.owner  						= -1;
				pd.poisoner  					= -1;
				pd.dc									= 0;
				poison_to_char( ch, ch, &pd );
			}
			if (obj->poison != NULL && poison_table[obj->poison->type].type == POISON_TYPE_INGEST) /* the better poison code */
			{
				obj_affect_poison(obj, ch);
			}
			if (obj->value[0] <= 0)
			{
				act( "You finishe $p.", ch, obj, NULL, TO_CHAR );
				act( "$n finishes $p.",  ch, obj, NULL, TO_ROOM );
				junk_obj( obj );
			}
			else
			{
				act( "You take a bite of $p.", ch, obj, NULL, TO_CHAR );
				act( "$n takes a bite of $p.",  ch, obj, NULL, TO_ROOM );
			}
			break;

		case ITEM_PILL:
			act( "You eat $p.", ch, obj, NULL, TO_CHAR );
			act( "$n eats $p.",  ch, obj, NULL, TO_ROOM );

			obj_cast_spell( obj->value[1], obj->value[0], ch, ch, obj );
			obj_cast_spell( obj->value[2], obj->value[0], ch, ch, obj );
			obj_cast_spell( obj->value[3], obj->value[0], ch, ch, obj );
			TAKE_ACTION(ch, ACTION_STANDARD);
			junk_obj( obj );
			break;

		default:
			break;
			
	}
	pop_call();
	return;
}

/*
 * (Reminder) shoot and eat don't check poison yet - Scandum
 * Ammo does now! AND added empty vials to make poison for spiking - Kregor
 * cleaned up and tightened strings for echoes and renaming.
 * eat and drink now check for poison.
 */
/*
 * Put the poison onto a weapon or consumable - Kregor
 */
void do_poison( CHAR_DATA *ch, char *argument )
{
	char arg [MAX_INPUT_LENGTH];
	OBJ_DATA *obj, *poison;
	POISON_DATA *pd;

	push_call("do_poison(%p,%p)",ch,argument);

	argument = one_argument( argument, arg );

	if (arg[0] == '\0')
	{
		send_to_char( "Poison what?\n\r", ch );
		pop_call();
		return;
	}
	
	if ((obj = get_obj_list(ch, arg, ch->first_carrying)) == NULL)
	{
		send_to_char( "You do not have that.\n\r", ch );
		pop_call();
		return;
	}
	
	switch (obj->item_type)
	{
		case ITEM_WEAPON:
		case ITEM_AMMO:
		case ITEM_FOOD:
		case ITEM_DRINK_CON:
		case ITEM_FOUNTAIN:
			break;
		default:
			send_to_char( "You cannot poison that.\n\r", ch );
			pop_call();
			return;
	}			

	if (obj->poison != NULL)
	{
		send_to_char( "That object is already poisoned.\n\r", ch );
		pop_call();
		return;
	}

	if ((poison = get_obj_carry_type(ch, ITEM_POTION)) == NULL || (pd = poison->poison) == NULL)
	{
		send_to_char( "You are not carrying a vial of poison.\n\r", ch );
		pop_call();
		return;
	}
		
	if (class_level(ch, CLASS_PALADIN))
	{
		send_to_char( "{018}Your patron frowns on your deeds!\n\r", ch );
		ch->ethos = UMAX(-1000, ch->ethos - 200);
		ch->pcdata->god_favor = UMAX(-100, ch->pcdata->god_favor - 50);
	}

	if (number_percent() <= 5 && !learned(ch, gsn_poison_use) && !is_immune(ch, SDESC_POISON))
	{
		poison_to_char(ch, ch, pd);
		pop_call();
		return;
	}
	act("You taint $p with $T.", ch, obj, poison_table[pd->type].name, TO_CHAR);
	act("$n taints $p with $P.", ch, obj, poison, TO_CAN_SEE);

	poison_to_obj(ch, obj, pd);
	poison->poison = NULL;
	FREEMEM(pd);
	RESTRING(poison->name, poison->pIndexData->name);

	pop_call();
	return;
}

/*
	Remove an object.
*/

bool remove_obj( CHAR_DATA *ch, int iWear, bool fReplace, bool fDisplay )
{
	OBJ_DATA *obj;

	push_call("remove_obj(%p,%p,%p,%p)",ch,iWear,fReplace,fDisplay);

	if (IS_EQ_MELDED(ch))
	{
		if (fDisplay)
			send_to_char("You cannot remove anything melded to your form.\n\r", ch);
		pop_call();
		return FALSE;
	}

	if ((obj = get_eq_char(ch, iWear)) == NULL)
	{
		pop_call();
		return TRUE;
	}

	if (!fReplace && ch->carry_number >= can_carry_n(ch))
	{
		if (fDisplay)
			act( "You cannot carry that many items.", ch, NULL, NULL, TO_CHAR);
		pop_call();
		return FALSE;
	}

	if ( !fReplace )
	{
		pop_call();
		return FALSE;
	}

	if (IS_SET(obj->extra_flags, ITEM_NOREMOVE))
	{
		if (fDisplay)
		{
			act( "You cannot remove $p.", ch, obj, NULL, TO_CHAR );
		}
		pop_call();
		return FALSE;
	}

	unequip_char( ch, obj, fDisplay );

	if (fDisplay)
	{
		act( "You stop using $p.", ch, obj, NULL, TO_CHAR );
		act( "$n stops using $p.", ch, obj, NULL, TO_CAN_SEE );
	}
	pop_call();
	return TRUE;
}

int get_layer (OBJ_DATA *obj)
{
	int layer;
	
	push_call("get_layer(%p)",obj);
	
	if (obj == NULL)
	{
		pop_call();
		return -1;
	}
	
	switch (obj->item_type)
	{
		case ITEM_ARMOR:
			if ((layer = obj->value[4]) == 0 || armor_table[obj->value[0]].type != ARMOR_TYPE_CLOTH)
				layer = LAYER_ARMOR;
			break;
		case ITEM_TREASURE:
		case ITEM_SHEATH:
		case ITEM_CART:
		case ITEM_CONTAINER:
		case ITEM_QUIVER:
			layer = obj->value[4];
			break;
		default:
			layer = LAYER_ARMOR;
			break;
	}
	pop_call();
	return layer;
}
			
	
bool can_layer( CHAR_DATA *ch, OBJ_DATA *object, int iWear, bool fReplace, bool fDisplay )
{
	OBJ_DATA *obj;

	push_call("can_layer(%p,%p,%p,%p,%p)",ch,object,iWear,fReplace,fDisplay);

  for( obj = ch->first_carrying; obj; obj = obj->next_content )
	{
		if (WEAR_LOC(obj, iWear))
		{
			if (get_layer(obj) > get_layer(object))
			{
				act( "You must remove $p first.", ch, obj, object, TO_CHAR);
				pop_call();
				return FALSE;
			}
			else if (get_layer(obj) == get_layer(object))
			{
				if ( !fReplace )
				{
					pop_call();
					return FALSE;
				}
			
				if (IS_SET(obj->extra_flags, ITEM_NOREMOVE))
				{
					if (fDisplay)
					{
						act( "You cannot remove $p.", ch, obj, NULL, TO_CHAR );
					}
					pop_call();
					return FALSE;
				}
			
				unequip_char( ch, obj, fDisplay );

				if (fDisplay)
				{
					act( "You stop using $p.", ch, obj, NULL, TO_CHAR );
					act( "$n stops using $p.", ch, obj, NULL, TO_CAN_SEE );
				}

				pop_call();
				return TRUE;
			}
		}
	}
	pop_call();
	return TRUE;
}

/*
	Wear one object.
	Optional replacement of existing objects.
	Big repetitive code, ick.
	Made less repetitive and a little smaller by Kregor 4/25/08
*/

bool wear_obj( CHAR_DATA *ch, OBJ_DATA *obj, bool fReplace, int location, bool fDisplay )
{
	OBJ_DATA *tmpobj;
	lg_int locs;
	short cnt;

	push_call("wear_obj(%p,%p,%p,%p,%p)",ch,obj,fReplace,location,fDisplay);

	if (IS_EQ_MELDED(ch))
	{
		if (fDisplay)
			send_to_char("You cannot wear anything until you revert to your original form.\n\r", ch);
		pop_call();
		return FALSE;
	}
	
	if (!class_allowed(obj, ch, fDisplay))
	{
		pop_call();
		return FALSE;
	}
	
	if (IS_OBJ_STAT(obj, ITEM_BROKEN))
	{
		if (fDisplay)
			act("$p is broken, and cannot be used until it's repaired.", ch, obj, NULL, TO_CHAR );
		pop_call();
		return FALSE;
	}

	if(location == -1)
	{
		for(cnt = 1; cnt < 31; cnt++)
		{
			if(CAN_WEAR( obj, 1 << cnt ))
			{
				location = 1 << cnt;
				break;
			}
		}
		if (location == CAN_WEAR_WIELD
		|| location == CAN_WEAR_BOTH
		|| location == CAN_WEAR_SHIELD
		|| location == CAN_WEAR_HOLD)
		{
			if (fDisplay)
				send_to_char("You can't wear that, perhaps you could HOLD or WIELD it?\n\r", ch);
			pop_call();
			return FALSE;
		}
	}
	else
	{		
		if(!CAN_WEAR( obj, location ))
		{
			if(fReplace)
			{
				switch (location)
				{
					case CAN_WEAR_BOTH:
						if (fDisplay)
							send_to_char( "You cannot hold that in both hands.\r\n", ch );
						break;
					case CAN_WEAR_HOLD:
						if (fDisplay)
							send_to_char( "You cannot hold that.\r\n", ch );
						break;
					case CAN_WEAR_FLOAT:
						if (fDisplay)
							send_to_char( "That cannot float around you.\r\n", ch );
						break;
					case CAN_WEAR_WIELD:
						if (fDisplay)
							send_to_char( "You cannot wield that as a weapon.\r\n", ch );
						break;
					default:
						ch_printf_color( ch, "You cannot wear that %s.\r\n", flag_string(location, worn_flags) );
						break;
				}
			}
			pop_call();
			return FALSE;
		}
	}
	
	if (IS_OBJ_TYPE(obj, ITEM_ARMOR))
	{
		if (location != WEAR_SHIELD && in_combat(ch))
		{
			if (fDisplay)
				send_to_char( "You cannot don armor in combat!\r\n", ch );
			pop_call();
			return FALSE;
		}
		if (obj->value[3])
		{
			// resize flag allows a new item to be the right size for the owner
			if (IS_OBJ_STAT(obj, ITEM_RESIZE))
			{
				REMOVE_BIT(obj->extra_flags, ITEM_RESIZE);
				obj->value[3] = get_size(ch);
			}
			else if (obj->value[3] > get_size(ch))
			{
				if (fDisplay)
				{
					act( "$p is too large for you to wear.", ch, obj, NULL, TO_CHAR);
					act( "$n tries to wear $p, but it is too large.", ch, obj, NULL, TO_ROOM);
				}
				pop_call();
				return FALSE;
			}
			else if (obj->value[3] < get_size(ch))
			{
				if (fDisplay)
				{
					act( "$p is too small for you to wear.", ch, obj, NULL, TO_CHAR);
					act( "$n tries to wear $p, but it is too small.", ch, obj, NULL, TO_ROOM);
				}
				pop_call();
				return FALSE;
			}
		}
	}

	if (IS_NPC(ch) && ch->race == RACE_NONE)
	{
		locs = ch->pIndexData->wear_locs;
	}
	else
	{
		locs = race_table[get_race(ch)].wear_locs;
	}
		
	/*
	 * added this little bit to determine whether a creature 
	 * could actually equip a certain location - Kregor
	 */
	switch (location)
	{
		case CAN_WEAR_TAKE:
		case CAN_WEAR_FLOAT:
			break;
		default:
			if (!IS_SET(locs, location))
			{
				if (fDisplay)
					act("You do not have a $T to wear $p on.", ch, obj, flag_string(location, w_flags), TO_CHAR);
				pop_call();
				return FALSE;
			}
			break;
		case CAN_WEAR_SHIELD:
		case CAN_WEAR_WIELD:
		case CAN_WEAR_BOTH:
		case CAN_WEAR_HOLD:
			if (IS_SEVERED(ch, CAN_WEAR_HANDS))
			{
				if (fDisplay)
					act("Your hands are currently severed!", ch, obj, NULL, TO_CHAR);
				pop_call();
				return FALSE;
			}
			if (!is_handy(ch))
			{
				if (fDisplay)
					act("You do not have hands to hold $p.", ch, obj, NULL, TO_CHAR);
				pop_call();
				return FALSE;
			}
			break;
		case CAN_WEAR_HANDS:
		case CAN_WEAR_FINGER:
		case CAN_WEAR_WRIST:
			if (!IS_SET(locs, location))
			{
				if (fDisplay)
					act("You do not have a $T to wear $p on.", ch, obj, flag_string(location, w_flags), TO_CHAR);
				pop_call();
				return FALSE;
			}
			if (IS_SEVERED(ch, CAN_WEAR_HANDS))
			{
				if (fDisplay)
					act("Your hands are currently severed!", ch, obj, NULL, TO_CHAR);
				pop_call();
				return FALSE;
			}
			if (!is_handy(ch))
			{
				act("You do not have hands to wear $p on.", ch, obj, NULL, TO_CHAR);
				pop_call();
				return FALSE;
			}
			break;
		case CAN_WEAR_FEET:
		case CAN_WEAR_ANKLE:
			if (!IS_SET(locs, location))
			{
				if (fDisplay)
					act("You do not have a $T to wear $p on.", ch, obj, flag_string(location, w_flags), TO_CHAR);
				pop_call();
				return FALSE;
			}
			if (IS_SEVERED(ch, CAN_WEAR_FEET))
			{
				if (fDisplay)
					act("Your feet are currently severed!", ch, obj, NULL, TO_CHAR);
				pop_call();
				return FALSE;
			}
			break;
	}
	
	switch (location)
	{
	  default:
			bug( "wear_obj: uknown/unused item_wear bit %d", location );
			if( fDisplay )
				send_to_char( "You can't wear that.\r\n", ch );
			pop_call();
			return FALSE;

		case CAN_WEAR_TAKE:
			if (!remove_obj( ch, WEAR_HOLD, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}	
			equip_char( ch, obj, WEAR_HOLD );	
			if (fDisplay)
			{
				act( "You hold $p in your hand.", ch, obj, NULL, TO_CHAR );
				act( "$n holds $p in $s hand.", ch, obj, NULL, TO_CAN_SEE );
			}
			pop_call();
			return TRUE;

		case CAN_WEAR_FLOAT:
			if (!remove_obj(ch, WEAR_FLOAT, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			equip_char( ch, obj, WEAR_FLOAT );
			if (fDisplay)
			{
				act( "You set $p spinning around your head.", ch, obj, NULL, TO_CHAR );
				act( "$n sets $p spinning around $s head.", ch, obj, NULL, TO_CAN_SEE );
			}
			pop_call();
			return TRUE;

		case CAN_WEAR_FACE:
			if (!remove_obj( ch, WEAR_FACE, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			equip_char( ch, obj, WEAR_FACE );
			if (fDisplay)
			{
				act( "You don $p upon your face.", ch, obj, NULL, TO_CHAR );
				act( "$n dons $p upon $s face.", ch, obj, NULL, TO_CAN_SEE );
			}
			pop_call();
			return TRUE;

		case CAN_WEAR_SADDLE:
			if (!remove_obj( ch, WEAR_SADDLE, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}	
			equip_char( ch, obj, WEAR_SADDLE );	
			if (fDisplay)
			{
				act( "You wear $p as a saddle.", ch, obj, NULL, TO_CHAR );
				act( "$n wears $p as a saddle.", ch, obj, NULL, TO_CAN_SEE );
			}
			pop_call();
			return TRUE;

		case CAN_WEAR_EARS:
			if (!remove_obj( ch, WEAR_EARS, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			equip_char( ch, obj, WEAR_EARS );
			if (fDisplay)
			{
				act( "You wear $p on your ears.", ch, obj, NULL, TO_CHAR );
				act( "$n wears $p on $s ears.", ch, obj, NULL, TO_CAN_SEE );
			}
			pop_call();
			return TRUE;
	
		case CAN_WEAR_NECK:
			if (get_eq_char(ch, WEAR_NECK_1) != NULL
			&&  get_eq_char(ch, WEAR_NECK_2) != NULL
			&&  !remove_obj(ch, WEAR_NECK_1, fReplace, fDisplay)
			&&  !remove_obj(ch, WEAR_NECK_2, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			if (get_eq_char(ch, WEAR_NECK_1) == NULL)
			{
				equip_char( ch, obj, WEAR_NECK_1 );
	
				if (fDisplay)
				{
					act( "You fasten $p around your neck.", ch, obj, NULL, TO_CHAR );
					act( "$n fastens $p around $s neck.", ch, obj, NULL, TO_CAN_SEE );
				}
				pop_call();
				return TRUE;
			}
			if (get_eq_char(ch, WEAR_NECK_2) == NULL)
			{
				equip_char( ch, obj, WEAR_NECK_2 );
				if (fDisplay)
				{
					act( "You fasten $p around your neck.", ch, obj, NULL, TO_CHAR );
					act( "$n fastens $p around $s neck.", ch, obj, NULL, TO_CAN_SEE );
				}
				pop_call();
				return TRUE;
			}
			bug( "Wear_obj: no free neck.", 0 );
			if (fDisplay)
			{
				send_to_char( "You already wear two neck items.\n\r", ch );
			}
			pop_call();
			return FALSE;

		case CAN_WEAR_BACK:
			if (!remove_obj(ch, WEAR_BACK, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			equip_char( ch, obj, WEAR_BACK );
			if (fDisplay)
			{
				act( "You wear $p upon your back.", ch, obj, NULL, TO_CHAR );
				act( "$n wears $p upon $s back.", ch, obj, NULL, TO_CAN_SEE );
			}
			pop_call();
			return TRUE;

		case CAN_WEAR_BODY:
			if (!can_layer(ch, obj, WEAR_BODY, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			equip_char( ch, obj, WEAR_BODY );
			if (fDisplay)
			{
				act( "You wear $p on your body.", ch, obj, NULL, TO_CHAR );
				act( "$n wears $p on $s body.", ch, obj, NULL, TO_CAN_SEE );
			}
			pop_call();
			return TRUE;

		case CAN_WEAR_HEAD:
			if (!can_layer(ch, obj, WEAR_HEAD, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			equip_char( ch, obj, WEAR_HEAD );
			if ( fDisplay )
			{
				act( "You place $p upon your head.", ch, obj, NULL, TO_CHAR );
				act( "$n places $p upon $n head.", ch, obj, NULL, TO_CAN_SEE );
			}
			pop_call();
			return TRUE;

		case CAN_WEAR_ARMS:
			if (!can_layer(ch, obj, WEAR_ARMS, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			equip_char( ch, obj, WEAR_ARMS );
			if (fDisplay)
			{
				act( "You wear $p on your arms.", ch, obj, NULL, TO_CHAR );
				act( "$n wears $p on $s arms.", ch, obj, NULL, TO_CAN_SEE );
			}
			pop_call();
			return TRUE;

		case CAN_WEAR_WRIST:
			if (get_eq_char(ch, WEAR_WRIST_L) != NULL
			&&  get_eq_char(ch, WEAR_WRIST_R) != NULL
			&&  !remove_obj(ch, WEAR_WRIST_L, fReplace, fDisplay)
			&&  !remove_obj(ch, WEAR_WRIST_R, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			if ( get_eq_char( ch, WEAR_WRIST_L ) == NULL )
			{
				equip_char( ch, obj, WEAR_WRIST_L );
	
				if (fDisplay)
				{
					act( "You slide $p over your left wrist.", ch, obj, NULL, TO_CHAR );
					act( "$n slides $p over $s left wrist.", ch, obj, NULL, TO_CAN_SEE );
				}
				pop_call();
				return TRUE;
			}
			if ( get_eq_char( ch, WEAR_WRIST_R ) == NULL )
			{
				if (IS_SEVERED(ch, CAN_WEAR_WRIST))
				{
					if (fDisplay)
						act("You have no free wrist to wear $p on!", ch, obj, NULL, TO_CHAR);
					pop_call();
					return FALSE;
				}
				equip_char( ch, obj, WEAR_WRIST_R );
	
				if( fDisplay )
				{
					act( "You slide $p over your right wrist.", ch, obj, NULL, TO_CHAR );
					act( "$n slides $p over $s right wrist.", ch, obj, NULL, TO_CAN_SEE );
				}
				pop_call();
				return TRUE;
			}
			bug( "Wear_obj: no free wrist.", 0 );
			if( fDisplay )
			{
				send_to_char( "You already wear two wrist items.\n\r", ch );
			}
			pop_call();
			return FALSE;

		case CAN_WEAR_HANDS:
			if (!remove_obj( ch, WEAR_HANDS, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			equip_char( ch, obj, WEAR_HANDS );
			if (fDisplay)
			{
				act( "You slip $p over your hands.", ch, obj, NULL, TO_CHAR );
				act( "$n slips $p over $s hands.", ch, obj, NULL, TO_CAN_SEE );
			}
			pop_call();
			return TRUE;

		case CAN_WEAR_FINGER:
			if (get_eq_char(ch, WEAR_FINGER_L) != NULL
			&&  get_eq_char(ch, WEAR_FINGER_R) != NULL
			&&  !remove_obj(ch, WEAR_FINGER_L, fReplace, fDisplay)
			&&  !remove_obj(ch, WEAR_FINGER_R, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			if (get_eq_char(ch, WEAR_FINGER_L) == NULL)
			{
				equip_char(ch, obj, WEAR_FINGER_L);
	
				if (fDisplay)
				{
					act( "You slip $p onto your left finger.",  ch, obj, NULL, TO_CHAR );
					act( "$n slips $p onto $s left finger.",  ch, obj, NULL, TO_CAN_SEE );
				}
				pop_call();
				return TRUE;
			}
			if (get_eq_char(ch, WEAR_FINGER_R) == NULL)
			{
				if (IS_SEVERED(ch, CAN_WEAR_FINGER|CAN_WEAR_WRIST))
				{
					if (fDisplay)
						act("You have no free finger to wear $p on!", ch, obj, NULL, TO_CHAR);
					pop_call();
					return FALSE;
				}
				equip_char( ch, obj, WEAR_FINGER_R );
	
				if (fDisplay)
				{
					act( "You slip $p onto your right finger.", ch, obj, NULL, TO_CHAR );
					act( "$n slips $p onto $s right finger.",  ch, obj, NULL, TO_CAN_SEE );
				}
				pop_call();
				return TRUE;
			}
			bug( "Wear_obj: no free finger.", 0 );
			if (fDisplay)
			{
				send_to_char( "You already wear two rings.\n\r", ch );
			}
			pop_call();
			return FALSE;

		case CAN_WEAR_ABOUT:
			if (!remove_obj( ch, WEAR_ABOUT, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			equip_char( ch, obj, WEAR_ABOUT );
			if (fDisplay)
			{
				act( "You wrap $p about your body.", ch, obj, NULL, TO_CHAR );
				act( "$n wraps $p about $n body.", ch, obj, NULL, TO_CAN_SEE );
			}
			pop_call();
			return TRUE;

		case CAN_WEAR_WAIST:
			if (!remove_obj( ch, WEAR_WAIST, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			equip_char( ch, obj, WEAR_WAIST );
	
			if (fDisplay)
			{
				act( "You fasten $p around your waist.", ch, obj, NULL, TO_CHAR );
				act( "$n fastens $p around $s waist.", ch, obj, NULL, TO_CAN_SEE );
			}
			pop_call();
			return TRUE;

		case CAN_WEAR_BELT:
			if (get_eq_char(ch, WEAR_WAIST) == NULL)
			{
				if (fDisplay)
				{
					act( "You have no belt to hang it on.", ch, obj, NULL, TO_CHAR );
				}
				pop_call();
				return FALSE;
			}
			if (get_eq_char(ch, WEAR_BELT_1) != NULL
			&&  get_eq_char(ch, WEAR_BELT_2) != NULL
			&&  get_eq_char(ch, WEAR_BELT_3) != NULL
			&&  !remove_obj(ch, WEAR_BELT_1, fReplace, fDisplay)
			&&  !remove_obj(ch, WEAR_BELT_2, fReplace, fDisplay)
			&&  !remove_obj(ch, WEAR_BELT_3, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			if (get_eq_char(ch, WEAR_BELT_1) == NULL)
			{
				equip_char( ch, obj, WEAR_BELT_1 );
	
				if (fDisplay)
				{
					act( "You fasten $p onto your belt.", ch, obj, NULL, TO_CHAR );
					act( "$n fastens $p onto $s belt.", ch, obj, NULL, TO_CAN_SEE );
				}
				pop_call();
				return TRUE;
			}
			if (get_eq_char(ch, WEAR_BELT_2) == NULL)
			{
				equip_char( ch, obj, WEAR_BELT_2 );
				if (fDisplay)
				{
					act( "You fasten $p onto your belt.", ch, obj, NULL, TO_CHAR );
					act( "$n fastens $p onto $s belt.", ch, obj, NULL, TO_CAN_SEE );
				}
				pop_call();
				return TRUE;
			}
			if (get_eq_char(ch, WEAR_BELT_3) == NULL)
			{
				equip_char( ch, obj, WEAR_BELT_3 );
				if (fDisplay)
				{
					act( "You fasten $p onto your belt.", ch, obj, NULL, TO_CHAR );
					act( "$n fastens $p onto $s belt.", ch, obj, NULL, TO_CAN_SEE );
				}
				pop_call();
				return TRUE;
			}
			bug( "Wear_obj: no free belt slot.", 0 );
			if (fDisplay)
			{
				send_to_char( "You already wear three belt items.\n\r", ch );
			}
			pop_call();
			return FALSE;

		case CAN_WEAR_LEGS:
			if (!can_layer(ch, obj, WEAR_LEGS, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			equip_char( ch, obj, WEAR_LEGS );
			if (fDisplay)
			{
				act( "You slip into $p.", ch, obj, NULL, TO_CHAR );
				act( "$n slips into $p.", ch, obj, NULL, TO_CAN_SEE );
			}
			pop_call();
			return TRUE;

		case CAN_WEAR_ANKLE:
			if (get_eq_char(ch, WEAR_ANKLE_L) != NULL
			&&  get_eq_char(ch, WEAR_ANKLE_R) != NULL
			&&  !remove_obj(ch, WEAR_ANKLE_L, fReplace, fDisplay)
			&&  !remove_obj(ch, WEAR_ANKLE_R, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			if ( get_eq_char( ch, WEAR_ANKLE_L ) == NULL )
			{
				equip_char( ch, obj, WEAR_ANKLE_L );
	
				if (fDisplay)
				{
					act( "You slide $p over your left ankle.", ch, obj, NULL, TO_CHAR );
					act( "$n slides $p over $s left ankle.", ch, obj, NULL, TO_CAN_SEE );
				}
				pop_call();
				return TRUE;
			}
			if ( get_eq_char( ch, WEAR_ANKLE_R ) == NULL )
			{
				if (IS_SEVERED(ch, CAN_WEAR_ANKLE))
				{
					if (fDisplay)
						act("You have no free ankle to wear $p on!", ch, obj, NULL, TO_CHAR);
					pop_call();
					return FALSE;
				}
				equip_char( ch, obj, WEAR_ANKLE_R );
	
				if( fDisplay )
				{
					act( "You slips $p over your right ankle.", ch, obj, NULL, TO_CHAR );
					act( "$n slides $p over $s right ankle.", ch, obj, NULL, TO_CAN_SEE );
				}
				pop_call();
				return TRUE;
			}
			bug( "Wear_obj: no free wrist.", 0 );
			if( fDisplay )
			{
				send_to_char( "You already wear two ankle items.\n\r", ch );
			}
			pop_call();
			return FALSE;

		case CAN_WEAR_FEET:
			if (IS_SEVERED(ch, CAN_WEAR_FEET))
			{
				act("You have no feet to wear $p on!", ch, obj, NULL, TO_CHAR);
				pop_call();
				return FALSE;
			}
			if (!can_layer(ch, obj, WEAR_FEET, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			equip_char(ch, obj, WEAR_FEET);
			if (fDisplay)
			{
				act( "You pull $p onto your feet.", ch, obj, NULL, TO_CHAR );
				act( "$n pulls $p onto $s feet.", ch, obj, NULL, TO_CAN_SEE );
			}
			pop_call();
			return TRUE;

		case CAN_WEAR_SHIELD:
			if (!many_armed(ch))
			{
				if (IS_SEVERED(ch, CAN_WEAR_WRIST))
				{
					if ((get_eq_char(ch, WEAR_WIELD) && !remove_obj(ch, WEAR_WIELD, fReplace, fDisplay))
					|| (get_eq_char(ch, WEAR_HOLD) && !remove_obj(ch, WEAR_HOLD, fReplace, fDisplay)))
					{
						if (fDisplay)
							act("You have no free hand to hold $p with!", ch, obj, NULL, TO_CHAR);
						pop_call();
						return FALSE;
					}
				}	
				if ((get_eq_char(ch, WEAR_DUAL_WIELD) && !remove_obj(ch, WEAR_DUAL_WIELD, fReplace, fDisplay))
				|| (get_eq_char(ch, WEAR_BOTH_HANDS) && !remove_obj(ch, WEAR_BOTH_HANDS, fReplace, fDisplay))
				|| (get_eq_char(ch, WEAR_HOLD) && !remove_obj(ch, WEAR_HOLD, fReplace, fDisplay)))
				{
					if (fDisplay)
					{
						send_to_char("You have no free hand!\n\r", ch);
					}
					pop_call();
					return FALSE;
				}
			}
			if (!remove_obj(ch, WEAR_SHIELD, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			equip_char( ch, obj, WEAR_SHIELD );
			if (fDisplay)
			{
				act( "You strap $p to your arm.", ch, obj, NULL, TO_CHAR );
				act( "$n straps $p to $s arm.", ch, obj, NULL, TO_CAN_SEE );
			}
			pop_call();
			return TRUE;

		case CAN_WEAR_WIELD:
			if (!IS_WEAPON(obj))
			{
				send_to_char( "Only weapons can be wielded!\n\r", ch );
				pop_call();
				return FALSE;
			}
			if (obj->size > get_size(ch) + (learned(ch, gsn_smaller_weapons) ? 1 : 2))
			{
				send_to_char( "It's just far too big to hold in your hands\n\r", ch );
				pop_call();
				return FALSE;
			}
			if (!many_armed(ch))
			{
				if (IS_SEVERED(ch, CAN_WEAR_WRIST))
				{
					if ((get_eq_char(ch, WEAR_HOLD) && !remove_obj(ch, WEAR_HOLD, fReplace, fDisplay))
					|| (get_eq_char(ch, WEAR_WIELD) && !remove_obj(ch, WEAR_WIELD, fReplace, fDisplay))
					|| (get_eq_char(ch, WEAR_SHIELD) && !remove_obj(ch, WEAR_SHIELD, fReplace, fDisplay)))
					{
						if (fDisplay)
							act("You have no free hand to hold $p with!", ch, obj, NULL, TO_CHAR);
						pop_call();
						return FALSE;
					}
				}	
				if (get_eq_char(ch, WEAR_BOTH_HANDS) && !remove_obj(ch, WEAR_BOTH_HANDS, fReplace, fDisplay))
				{
					if (fDisplay)
					{
						send_to_char("Your hands are full!\n\r", ch);
					}
					pop_call();
					return FALSE;
				}
			}
			if (obj->size > (learned(ch, gsn_smaller_weapons) ? get_size(ch) - 1 : get_size(ch)))
			{
				if (!many_armed(ch))
				{
					if ((get_eq_char(ch, WEAR_SHIELD) && !remove_obj(ch, WEAR_SHIELD, fReplace, fDisplay))
					|| (get_eq_char(ch, WEAR_HOLD) && !remove_obj(ch, WEAR_HOLD, fReplace, fDisplay))
					|| (get_eq_char(ch, WEAR_WIELD) && !remove_obj(ch, WEAR_WIELD, fReplace, fDisplay))
					|| (get_eq_char(ch, WEAR_DUAL_WIELD) && !remove_obj(ch, WEAR_DUAL_WIELD, fReplace, fDisplay)))
					{
						if (fDisplay)
						{
							send_to_char("Your hands are full!\n\r", ch);
						}
						pop_call();
						return FALSE;
					}
				}
				if (!remove_obj(ch, WEAR_BOTH_HANDS, fReplace, fDisplay))
				{
					pop_call();
					return FALSE;
				}
				equip_char( ch, obj, WEAR_BOTH_HANDS );
				if (fDisplay)
				{
					act( "You hold $p in two hands.", ch, obj, NULL, TO_CHAR );
					act( "$n holds $p in two hands.", ch, obj, NULL, TO_CAN_SEE );
				}
				if (!fDisplay)
				{
					pop_call();
					return TRUE;
				}
				if (!weapon_skill(ch, obj))
					act( "You wonder which end is up on $p.", ch, obj, NULL, TO_CHAR);
				else if (IS_SET(weapon_skill(ch, obj), WSKILL_EPIC_FOCUS))
					act( "$p feels like a part of you.", ch, obj, NULL, TO_CHAR);
				else if (IS_SET(weapon_skill(ch, obj), WSKILL_GREATER_FOCUS))
					act( "Few could wield $p better than you.", ch, obj, NULL, TO_CHAR);
				else if (IS_SET(weapon_skill(ch, obj), WSKILL_FOCUS))
					act( "$p feels comfortable in your hands.", ch, obj, NULL, TO_CHAR);
				else
					act( "You are proficient with $p.", ch, obj, NULL, TO_CHAR);
				pop_call();
				return TRUE;
			}
			else
			{
				if (get_eq_char(ch, WEAR_WIELD) || hands_full(ch))
				{
					if (!many_armed(ch))
					{
						if ((get_eq_char(ch, WEAR_HOLD) && !remove_obj(ch, WEAR_HOLD, fReplace, fDisplay))
						|| get_eq_char(ch, WEAR_DUAL_WIELD) || get_eq_char(ch, WEAR_SHIELD))
						{
							if (!remove_obj(ch, WEAR_WIELD, fReplace, fDisplay))
							{
								if (fDisplay)
								{
									send_to_char("Your hands are full!\n\r", ch);
								}
								pop_call();
								return FALSE;
							}
						}
					}
					if ((tmpobj = get_eq_char(ch, WEAR_WIELD)) != NULL && !get_eq_char(ch, WEAR_DUAL_WIELD))
					{
						equip_char( ch, obj, WEAR_DUAL_WIELD );
						if (fDisplay)
						{
							act( "You wield $p in your offhand.", ch, obj, NULL, TO_CHAR );
							act( "$n wields $p in $s offhand.", ch, obj, NULL, TO_CAN_SEE );
						}
						if (!fDisplay)
						{
							pop_call();
							return TRUE;
						}
							if (!weapon_skill(ch, obj))
							act( "You wonder which end is up on $p.", ch, obj, NULL, TO_CHAR);
						else if (IS_SET(weapon_skill(ch, obj), WSKILL_EPIC_FOCUS))
							act( "$p feels like a part of you.", ch, obj, NULL, TO_CHAR);
						else if (IS_SET(weapon_skill(ch, obj), WSKILL_GREATER_FOCUS))
							act( "Few could wield $p better than you.", ch, obj, NULL, TO_CHAR);
						else if (IS_SET(weapon_skill(ch, obj), WSKILL_FOCUS))
							act( "$p feels comfortable in your hands.", ch, obj, NULL, TO_CHAR);
						else
							act( "You are proficient with $p.", ch, obj, NULL, TO_CHAR);
	
						pop_call();
						return TRUE;
					}
				}
				if (!remove_obj(ch, WEAR_WIELD, fReplace, fDisplay))
				{
					pop_call();
					return FALSE;
				}
				equip_char( ch, obj, WEAR_WIELD );
				if (fDisplay)
				{
					act( "You wield $p.", ch, obj, NULL, TO_CHAR );
					act( "$n wields $p.", ch, obj, NULL, TO_CAN_SEE );
				}
				if (!fDisplay)
				{
					pop_call();
					return TRUE;
				}
				if (!weapon_skill(ch, obj))
					act( "You wonder which end is up on $p.", ch, obj, NULL, TO_CHAR);
				else if (IS_SET(weapon_skill(ch, obj), WSKILL_EPIC_FOCUS))
					act( "$p feels like a part of you.", ch, obj, NULL, TO_CHAR);
				else if (IS_SET(weapon_skill(ch, obj), WSKILL_GREATER_FOCUS))
					act( "Few could wield $p better than you.", ch, obj, NULL, TO_CHAR);
				else if (IS_SET(weapon_skill(ch, obj), WSKILL_FOCUS))
					act( "$p feels comfortable in your hands.", ch, obj, NULL, TO_CHAR);
				else
					act( "You are proficient with $p.", ch, obj, NULL, TO_CHAR);
			}
			pop_call();
			return TRUE;

		case CAN_WEAR_BOTH:
			if (obj->size > get_size(ch) + (learned(ch, gsn_smaller_weapons) ? 1 : 2))
			{
				send_to_char( "It's just far too big to hold in your hands\n\r", ch );
				pop_call();
				return FALSE;
			}
			if (!many_armed(ch))
			{
				if (IS_SEVERED(ch, CAN_WEAR_WRIST))
				{
					if (fDisplay)
						act("You don't have two hands to hold $p with!", ch, obj, NULL, TO_CHAR);
					pop_call();
					return FALSE;
				}	
				if ((get_eq_char(ch, WEAR_SHIELD) && !remove_obj(ch, WEAR_SHIELD, fReplace, fDisplay))
				|| (get_eq_char(ch, WEAR_HOLD) && !remove_obj(ch, WEAR_HOLD, fReplace, fDisplay))
				|| (get_eq_char(ch, WEAR_WIELD) && !remove_obj(ch, WEAR_WIELD, fReplace, fDisplay))
				|| (get_eq_char(ch, WEAR_DUAL_WIELD) && !remove_obj(ch, WEAR_DUAL_WIELD, fReplace, fDisplay)))
				{
					if (fDisplay)
					{
						send_to_char("Your hands are full!\n\r", ch);
					}
					pop_call();
					return FALSE;
				}
			}
			if (!remove_obj(ch, WEAR_BOTH_HANDS, fReplace, fDisplay))
			{
				pop_call();
				return FALSE;
			}
			equip_char( ch, obj, WEAR_BOTH_HANDS );
			if (fDisplay)
			{
				act( "You hold $p in two hands.", ch, obj, NULL, TO_CHAR );
				act( "$n holds $p in two hands.", ch, obj, NULL, TO_CAN_SEE );
			}
			if (!fDisplay)
			{
				pop_call();
				return TRUE;
			}
			if (IS_WEAPON(obj))
			{
				if (!weapon_skill(ch, obj))
					act( "You wonder which end is up on $p.", ch, obj, NULL, TO_CHAR);
				else if (IS_SET(weapon_skill(ch, obj), WSKILL_EPIC_FOCUS))
					act( "$p feels like a part of you.", ch, obj, NULL, TO_CHAR);
				else if (IS_SET(weapon_skill(ch, obj), WSKILL_GREATER_FOCUS))
					act( "Few could wield $p better than you.", ch, obj, NULL, TO_CHAR);
				else if (IS_SET(weapon_skill(ch, obj), WSKILL_FOCUS))
					act( "$p feels comfortable in your hands.", ch, obj, NULL, TO_CHAR);
				else
					act( "You are proficient with $p.", ch, obj, NULL, TO_CHAR);
			}
			pop_call();
			return TRUE;

		case CAN_WEAR_HOLD:
			if (obj->size > get_size(ch) + (learned(ch, gsn_smaller_weapons) ? 1 : 2))
			{
				send_to_char( "It's just far too big to hold in your hands\n\r", ch );
				pop_call();
				return FALSE;
			}
			if (!remove_obj(ch, WEAR_HOLD, fReplace, fDisplay))
			{
				if (!many_armed(ch))
				{
					if (IS_SEVERED(ch, CAN_WEAR_WRIST))
					{
						if ((get_eq_char(ch, WEAR_HOLD) && !remove_obj(ch, WEAR_HOLD, fReplace, fDisplay))
						|| (get_eq_char(ch, WEAR_WIELD) && !remove_obj(ch, WEAR_WIELD, fReplace, fDisplay))
						|| (get_eq_char(ch, WEAR_SHIELD) && !remove_obj(ch, WEAR_SHIELD, fReplace, fDisplay)))
						{
							if (fDisplay)
								act("You have no free hand to hold $p with!", ch, obj, NULL, TO_CHAR);
							pop_call();
							return FALSE;
						}
					}	
					if ((get_eq_char(ch, WEAR_WIELD) && !remove_obj(ch, WEAR_WIELD, fReplace, fDisplay))
					|| (get_eq_char(ch, WEAR_BOTH_HANDS) && !remove_obj(ch, WEAR_BOTH_HANDS, fReplace, fDisplay))
					|| (get_eq_char(ch, WEAR_DUAL_WIELD) && !remove_obj(ch, WEAR_DUAL_WIELD, fReplace, fDisplay)))
					{
						if (fDisplay)
						{
							send_to_char("Your hands are full!\n\r", ch);
						}
						pop_call();
						return FALSE;
					}
				}
			}
			equip_char( ch, obj, WEAR_HOLD );
			if (fDisplay)
			{
				act( "You hold $p in your hand.", ch, obj, NULL, TO_CHAR );
				act( "$n holds $p in $s hand.", ch, obj, NULL, TO_CAN_SEE );
			}
			pop_call();
			return TRUE;
	}
	pop_call();
	return FALSE;
}


void do_wear( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	char local[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	OBJ_DATA *obj_next, *obj_old;
	int location;

	push_call("do_wear(%p,%p)",ch,argument);

	if (IS_EQ_MELDED(ch))
	{
		send_to_char("You cannot wear anything until you revert to your original form.\n\r", ch);
		pop_call();
		return;
	}
	
	argument = one_argument( argument, arg );
	one_argument( argument, local );

	if (arg[0] == '\0')
	{
		send_to_char( "Wear what?\n\r", ch );
		pop_call();
		return;
	}

	if (!strcasecmp(arg, "hood"))
	{
		if (IS_AFFECTED(ch, AFF_HOODED))
		{
			send_to_char("You are already wearing a hood.\n\r", ch);
			pop_call();
			return;
		}
		for (obj = ch->first_carrying ; obj ; obj = obj_next)
		{
			obj_next = obj->next_content;

			if (!ARMOR_FLAG(obj, ARMORFLAG_HOODED))
				continue;

			if (!IS_WORN(obj))
			{
				act( "You have to wear $p $Tto don its hood.", ch, obj, get_color_string(ch, COLOR_TEXT, VT102_DIM), TO_CHAR);
				continue;
			}
			else
			{
				break;
			}
		}
		if (!obj)
		{
			act( "You have no hood to don upon your head.", ch, NULL, NULL, TO_CHAR);
		}
		else
		{
			act( "You don the hood of $p upon your head.", ch, obj, get_color_string(ch, COLOR_TEXT, VT102_DIM), TO_CHAR);
			act( "$n dons the hood of $p upon $s head.", ch, obj, NULL, TO_ROOM);
			SET_BIT(ch->affected_by, AFF_HOODED);
		}
		pop_call();
		return;
	}
		
	if (!strcasecmp(arg, "all"))
	{
		if (in_combat(ch))
		{
			send_to_char( "You cannot 'wear all' in combat!\n\r", ch );
			pop_call();
			return;
		}
			
		bool foundi, tfound;
		int loc;

		foundi  = FALSE;
		obj_old = NULL;

		for (obj = ch->first_carrying ; obj ; obj = obj_next)
		{
			obj_next = obj->next_content;
			loc      = 0;
			tfound   = FALSE;

			if (obj->carried_by == NULL)
			{
				break;
			}

			if (IS_CARRIED(obj) && can_see_obj(ch, obj))
			{
				while (loc != -1 && !tfound)
				{
					loc = wear_flags_to_wear_loc(obj, loc);

					if (loc != -1)
					{
						obj_old = get_eq_char(ch, loc);

						if ((obj_old == NULL || compare_obj(obj_old, obj) < 0)
						&& !(IS_OBJ_STAT(obj, ITEM_GOOD) && IS_EVIL(ch))
						&& !(IS_OBJ_STAT(obj, ITEM_EVIL) && IS_GOOD(ch))
						&& !(IS_OBJ_STAT(obj, ITEM_CHAOTIC) && IS_LAWFUL(ch))
						&& !(IS_OBJ_STAT(obj, ITEM_LAWFUL) && IS_CHAOTIC(ch))
						&& !(IS_OBJ_STAT(obj, ITEM_UNCONCERNED) && !IS_UNCONCERNED(ch))
						&& !(IS_OBJ_STAT(obj, ITEM_NEUTRAL) && !IS_NEUTRAL(ch)))
						{
							if (wear_obj(ch, obj, TRUE, -1, FALSE))
							{
								foundi = TRUE;
								tfound = TRUE;
							}
						}
						loc++;
					}
				}
			}
		}
		if (foundi)
		{
			act( "You wear the best equipment that you have.",ch,NULL,NULL,TO_CHAR);
			act( "$n wears all $s equipment.", ch, NULL, NULL, TO_ROOM);
		}
		else
		{
			send_to_char( "You wear nothing new.\n\r", ch);
		}
		pop_call();
		return;
	}
	else
	{
		if ((obj = get_obj_carry(ch, arg)) == NULL)
		{
			ch_printf_color(ch, "You do not have the item '%s'.\n\r", arg);
			pop_call();
			return;
		}
		location = -1;
		
		if (!strcasecmp(local, "finger"))	location = CAN_WEAR_FINGER;
		if (!strcasecmp(local, "neck"))	location = CAN_WEAR_NECK;
		if (!strcasecmp(local, "body"))	location = CAN_WEAR_BODY;
		if (!strcasecmp(local, "head"))	location = CAN_WEAR_HEAD;
		if (!strcasecmp(local, "legs"))	location = CAN_WEAR_LEGS;
		if (!strcasecmp(local, "feet"))	location = CAN_WEAR_FEET;
		if (!strcasecmp(local, "hands"))	location = CAN_WEAR_HANDS;
		if (!strcasecmp(local, "arms"))	location = CAN_WEAR_ARMS;
		if (!strcasecmp(local, "about"))	location = CAN_WEAR_ABOUT;
		if (!strcasecmp(local, "waist"))	location = CAN_WEAR_WAIST;
		if (!strcasecmp(local, "wrist"))	location = CAN_WEAR_WRIST;
		if (!strcasecmp(local, "hold"))	location = CAN_WEAR_HOLD;
		if (!strcasecmp(local, "belt"))	location = CAN_WEAR_BELT;
		if (!strcasecmp(local, "float"))	location = CAN_WEAR_FLOAT;
		if (!strcasecmp(local, "face"))	location = CAN_WEAR_FACE;
		if (!strcasecmp(local, "ears"))	location = CAN_WEAR_EARS;
		if (!strcasecmp(local, "ankle"))	location = CAN_WEAR_ANKLE;
		if (!strcasecmp(local, "back"))	location = CAN_WEAR_BACK;
		if (!strcasecmp(local, "saddle"))	location = CAN_WEAR_SADDLE;
		
		wear_obj( ch, obj, TRUE, location , TRUE);
	}
	pop_call();
	return;
}

void do_hold( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	char local[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	int location;

	push_call("do_hold(%p,%p)",ch,argument);

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

	if (arg[0] == '\0')
	{
		send_to_char( "Hold what?\n\r", ch );
		pop_call();
		return;
	}

	if ((obj = get_obj_carry(ch, arg)) == NULL)
	{
		ch_printf_color(ch, "You do not have that item to hold it.\n\r");
		pop_call();
		return;
	}
	
	if (obj->size > get_size(ch) + (learned(ch, gsn_smaller_weapons) ? 1 : 2))
	{
		send_to_char( "It's just far too big to hold in your hands.\n\r", ch );
		pop_call();
		return;
	}

	if (!strcasecmp(local, "both") || (obj->size > (learned(ch, gsn_smaller_weapons) ? get_size(ch) - 1 : get_size(ch))))
		location = CAN_WEAR_BOTH;
	else if (IS_WEAPON(obj))
		location = CAN_WEAR_WIELD;
	else if (CAN_WEAR(obj, CAN_WEAR_SHIELD))
		location = CAN_WEAR_SHIELD;
	else
		location = CAN_WEAR_HOLD;

	wear_obj( ch, obj, TRUE, location , TRUE);

	pop_call();
	return;
}

/*
 * Because there really needs to be
 * a limit to how much you can do
 * with your hands at once - Kregor
 */
bool hands_full( CHAR_DATA * ch )
{
	OBJ_DATA *obj = NULL;
	OBJ_DATA *wield = NULL;
	OBJ_DATA *wield2 = NULL;
	OBJ_DATA *hold = NULL;
	OBJ_DATA *both = NULL;
	OBJ_DATA *shield = NULL;

	push_call("hands_full(%p)",ch);
	
	for (obj = ch->first_carrying ; obj ; obj = obj->next_content)
	{
		if (WEAR_LOC(obj, WEAR_WIELD))
		{
			wield = obj;
		}
		if (WEAR_LOC(obj, WEAR_HOLD))
		{
			hold = obj;
		}
		if (WEAR_LOC(obj, WEAR_BOTH_HANDS))
		{
			both = obj;
		}
		if (WEAR_LOC(obj, WEAR_DUAL_WIELD))
		{
			wield2 = obj;
		}
		if (WEAR_LOC(obj, WEAR_SHIELD))
		{
			shield = obj;
		}
	}

	if (!many_armed(ch))
	{
		if (both != NULL)
		{
			pop_call();
			return TRUE;
		}
		if (wield != NULL)
		{
			if (shield != NULL || hold != NULL || wield2 != NULL)
			{
				pop_call();
				return TRUE;
			}
		}
		if (shield != NULL)
		{
			if (wield != NULL || hold != NULL || wield2 != NULL)
			{
				pop_call();
				return TRUE;
			}
		}
		if (hold != NULL)
		{
			if (shield != NULL || wield != NULL || wield2 != NULL)
			{
				pop_call();
				return TRUE;
			}
		}
		if (wield2 != NULL)
		{
			if (shield != NULL || hold != NULL || wield != NULL)
			{
				pop_call();
				return TRUE;
			}
		}
	}
	pop_call();
	return FALSE;
}


bool is_handy( CHAR_DATA *ch )
{
	push_call("is_handy(%p)",ch);
	
	if (!has_body_part(ch, CAN_WEAR_HANDS)
	|| !has_body_part(ch, CAN_WEAR_FINGER))
	{
		pop_call();
		return FALSE;
	}
	pop_call();
	return TRUE;
}
		

void do_remove( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	OBJ_DATA *obj_next;

	push_call("do_remove(%p,%p)",ch,argument);

	one_argument( argument, arg );

	if (IS_EQ_MELDED(ch))
	{
		send_to_char("You cannot wear anything until you revert to your original form.\n\r", ch);
		pop_call();
		return;
	}
	
	if ( arg[0] == '\0' )
	{
		send_to_char( "Remove what?\n\r", ch );

		pop_call();
		return;
	}

	if (!strcasecmp(arg, "hood"))
	{
		if (!IS_AFFECTED(ch, AFF_HOODED))
		{
			send_to_char("You are not wearing a hood.\n\r", ch);
			pop_call();
			return;
		}
		else
		{
			act( "{078}You pull the hood off of your head.", ch, NULL, NULL, TO_CHAR);
			act( "$n {078}pulls the hood off of $s head.", ch, NULL, NULL, TO_ROOM);
			REMOVE_BIT(ch->affected_by, AFF_HOODED);
		}
		pop_call();
		return;
	}
		
	/* all added by Trom */
	if (!strcasecmp(arg, "all"))
	{
		act( "You remove all your equipment.",ch,NULL,NULL,TO_CHAR);
		act( "$n removes all $s equipment.", ch, NULL, NULL, TO_ROOM);

		for (obj = ch->first_carrying ; obj != NULL ; obj = obj_next)
		{
			obj_next = obj->next_content;

			if (obj->carried_by == NULL)
			{
				break;
			}

			if (IS_WORN(obj))
			{
				if (remove_obj(ch, obj->wear_loc, TRUE, FALSE))
				{
					// obj_prog for remove was removed here.
				}
			}
		}
	}
	else
	{
		if ((obj = get_obj_wear( ch, arg ) ) == NULL )
		{
			ch_printf_color(ch, "You do not have the item '%s'.\n\r", arg);
			pop_call();
			return;
		}
		if (can_layer( ch, obj, obj->wear_loc, TRUE , TRUE))
		{
			// and here
		}
	}
	pop_call();
	return;
}


/*
 * Conceal and reveal by Kregor - 6/19/07
 */
void do_conceal( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	CHAR_DATA *fch;
	OBJ_DATA *obj; 

	push_call("do_conceal(%p,%p)",ch,argument);

	if(argument[0] == '\0')
	{
		send_to_char("Conceal what?\n\r", ch);
		pop_call();
		return;
	}
	
	argument = one_argument(arg, argument);
	
	if ((obj = get_obj_carry(ch,arg)) == NULL)
	{
		if ((obj = get_obj_wear(ch,arg)) == NULL)
		{
			send_to_char("You don't have that item.\n\r",ch);
			pop_call();
			return;
		}
	}

	if (IS_SET(obj->extra_flags, ITEM_CONCEALED))
	{
		send_to_char("That object is already concealed on you.\n\r",ch);
		pop_call();
		return;
	}

	if (get_size(ch) - obj->size <= 1)
	{
		send_to_char("That object is too large to conceal on your person.\n\r",ch);
		pop_call();
		return;
	}

	if (obj->weight > 5)
	{
		send_to_char("That object is too heavy to conceal.\n\r",ch);
		pop_call();
		return;
	}

	if (!can_drop_obj(ch, obj))
	{
		send_to_char( "You cannot conceal it.\n\r", ch );
		pop_call();
		return;
	}

	if (obj->wear_loc != WEAR_NONE)
	{
		switch (obj->wear_loc)
		{
			case WEAR_WIELD:
			case WEAR_DUAL_WIELD:
			case WEAR_HOLD:
			case WEAR_BOTH_HANDS:
				unequip_char(ch, obj, TRUE);
				break;
			default:
				act( "You can't conceal $p while worn.", ch, obj, NULL, TO_CHAR);
				pop_call();
				return;
		}
	}
	SET_BIT(obj->extra_flags,ITEM_CONCEALED);
	act ("You furtively attempt to conceal $p.", ch, obj, NULL, TO_CHAR);
	
	int hide = obj_conceal_check(obj);

	for (fch = ch->in_room->first_person ; fch ; fch = fch->next_in_room)
	{
		if (fch == ch || !IS_AWAKE(fch) || !can_see(fch, ch))
			continue;
			
		if (!perception_check(fch, ch, perception_roll(fch, SENSE_SIGHT), hide))
			continue;
			
		act ("$n furtively attempts to conceal $p.", ch, obj, fch, TO_VICT);
	}
	TAKE_ACTION(ch, ACTION_STANDARD);

	pop_call();
	return;
}


void do_reveal( CHAR_DATA *ch, char *argument )
{
	OBJ_DATA *obj;
	CHAR_DATA *victim, *rch;

	push_call("do_reveal(%p,%p)",ch,argument);

	if(argument[0] == '\0')
	{
		send_to_char("Reveal what or who?\n\r", ch);
		pop_call();
		return;
	}
	
	if ((victim = get_char_room(ch, argument)) != NULL)
	{
		if (!IS_AFFECTED(victim, AFF_HIDE))
		{
			act( "You point accusingly at $N, as if to reveal something.", ch, NULL, victim, TO_CHAR);
			act( "$n points accusingly at you, as if you're hiding something.", ch, NULL, victim, TO_VICT);
			act( "$n points accusingly at $N, as if $E's hiding something.", ch, NULL, victim, TO_NOTVICT);
			pop_call();
			return;
		}

		act( "You call out $N from $S hiding spot to your allies.", ch, NULL, victim, TO_CHAR);
		act( "$n attempts to point you out to $s allies.", ch, NULL, victim, TO_VICT);
		
		for (rch = ch->in_room->first_person ; rch ; rch = rch->next_in_room)
		{
			if (ch == rch || rch == victim)
				continue;
			if (!is_same_group(ch, rch))
			{
				act( "$N attempts to point out someone from their surroundings.", rch, NULL, ch, TO_CHAR);
				continue;
			}
			if (!can_see(rch, victim) && !perception_check(rch, victim, perception_roll(rch, SENSE_SIGHT) + 4, hide_roll(victim)))
			{
				act( "Despite $N's effort, you can't seem to find who he points out.", rch, NULL, ch, TO_CHAR);
				continue;
			}
			act( "$t points $N out to you from $S surroundings.", rch, PERS(victim, rch), ch, TO_CHAR);
			if (!IS_NPC(rch))
			{
				if (!IS_NPC(victim))
					rch->pcdata->found_pvnum[victim->pcdata->pvnum] = 1;
				else
					rch->pcdata->found_vnum[victim->pIndexData->vnum] = 1;
			}
		}
		pop_call();
		return;
	}	
	if ((obj = get_obj_carry(ch, argument)) == NULL)
	{
		send_to_char("That person or item isn't here.\n\r",ch);
		pop_call();
		return;
	}

	if (!IS_SET(obj->extra_flags, ITEM_CONCEALED))
	{
		send_to_char("That object is not concealed.\n\r",ch);
		pop_call();
		return;
	}

	REMOVE_BIT(obj->extra_flags,ITEM_CONCEALED);
	act ("You produce $p from its concealment.", ch, obj, NULL, TO_CHAR);
	act ("$n produces $p from its concealment.", ch, obj, NULL, TO_ROOM);

	pop_call();
	return;
}


void do_sacrifice( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];

	OBJ_DATA *obj			= NULL;
	OBJ_DATA *obj_next		= NULL;

	bool	found			= FALSE;
	bool shrtd			= FALSE;

	int amount			= 1;
	int cnt				= 0;

	push_call("do_sacrifice(%p,%p)",ch,argument);
	
  send_to_char("Sacrifice is disabled on this server.\n\r", ch);
  send_to_char("If you wish to sacrifice your prey, RP it out!\n\r", ch);
  pop_call();
  return;

	argument = one_argument( argument, arg1 );

	if (is_number(arg1))
	{
		amount	= UMAX(1, atol(arg1));
		argument	= one_argument( argument, arg1 );
	}

	if (*arg1 == 0)
	{
		send_to_char("Sacrifice what?\n\r", ch);
		pop_call();
		return;
	}

	if (!check_blind(ch))
	{
		pop_call();
		return;
	}

	if (strcasecmp(arg1, "all") && str_prefix("all.", arg1))
	{
		if ((obj = get_obj_list(ch, arg1, ch->in_room->first_content)) == NULL)
		{
			send_to_char( "You cannot find it.\n\r", ch );
			pop_call();
			return;
		}

		for ( ; shrtd <= 1 && !found ; shrtd++)
		{
			for (obj = ch->in_room->first_content ; obj ; obj = obj_next)
			{
				obj_next = obj->next_content;

				if (!can_see_obj(ch, obj))
				{
					continue;
				}

				if (!shrtd && !is_name(arg1, obj->name))
				{
					continue;
				}

				if (shrtd  && !is_name_short(arg1, obj->name))
				{
					continue;
				}

				found = TRUE;

				if (obj->first_content)
				{
					obj_next = NULL;
				}

				if (sacrifice_obj(ch, obj, NULL, TRUE))
				{
					if (++cnt >= amount)
					{
						break;
					}
				}
			}
		}
		pop_call();
		return;
	}
	else
	{
		for ( ; shrtd <= 1 && !found ; shrtd++)
		{
			for (obj = ch->in_room->first_content ; obj ; obj = obj_next)
			{
				obj_next = obj->next_content;

				if (!can_see_obj(ch, obj) || !IS_SET(obj->wear_flags, CAN_WEAR_TAKE))
				{
					continue;
				}

				if (!shrtd && arg1[3] && !is_name(&arg1[4], obj->name))
				{
					continue;
				}

				if (shrtd  && arg1[3] && !is_name_short(&arg1[4], obj->name))
				{
					continue;
				}

				found = TRUE;

				if (obj->first_content)
				{
					obj_next = NULL;
				}

				sacrifice_obj(ch, obj, NULL, TRUE);
			}
		}
		if (found == FALSE)
		{
			if (arg1[3] == '\0')
			{
				send_to_char( "You see nothing here.\n\r", ch );
			}
			else
			{
				act( "You see no $T here.", ch, NULL, short_to_name(&arg1[4], 0), TO_CHAR );
			}
		}
	}
	pop_call();
	return;
}


/*
 * Item connection code originally from ACKMud
 */
void do_join( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_STRING_LENGTH];
	char arg2[MAX_STRING_LENGTH];
	char buf[MAX_STRING_LENGTH];
	OBJ_DATA * first_ob;
	OBJ_DATA * second_ob;
	OBJ_DATA * new_ob;
	
	push_call("do_join(%p,%p)",ch,argument);

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

	if (arg1[0] == '\0' || arg2[0] == '\0')
	{
		send_to_char( "Join what piece to what piece?\n\r", ch );
		pop_call();
		return;
	}

	if ((first_ob = get_obj_carry(ch, arg1)) == NULL )
	{
		sprintf( buf, "You aren't carrying that.\n\r" );
		send_to_char( buf, ch );
		pop_call();
		return;
	}

	if ((second_ob = get_obj_carry(ch, arg2)) == NULL )
	{
		sprintf( buf, "You aren't carrying that.\n\r" );
		send_to_char( buf, ch );
		pop_call();
		return;
	}

	if (first_ob->item_type != ITEM_PIECE || second_ob->item_type !=ITEM_PIECE)
	{
		send_to_char( "Both items must be pieces of another item!\n\r", ch );
		pop_call();
		return;
	}

	/* check to see if the pieces connect */
	if ((first_ob->value[0] == second_ob->pIndexData->vnum)
	|| (first_ob->value[1] == second_ob->pIndexData->vnum))
	{
		new_ob = create_object( get_obj_index( first_ob->value[2] ), 0 );
		extract_obj( first_ob );
		extract_obj( second_ob );
		obj_to_char( new_ob, ch );
		act( "$n jiggles some pieces together, and suddenly they snap in place, creating $p! Perfect Fit!!", ch, new_ob,NULL,	TO_ROOM );
		act( "You jiggle the pieces together, and suddenly they snap into place, creating $p!", ch, new_ob, NULL, TO_CHAR);
	}
	else
	{
		act( "$n jiggles some pieces together, but can't seem to join them.", ch, NULL, NULL, TO_ROOM);
		act( "You try to join them together every which way, but they just don't.", ch, NULL, NULL, TO_CHAR);
		pop_call();
		return;
	}
	pop_call();
	return;
}


int wear_flags_to_wear_loc( OBJ_DATA *obj, int last)
{
	push_call("wear_flags_to_wear_loc(%p,%p)",obj,last);

	if( last == WEAR_FLOAT || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_FLOAT))
		{
			pop_call();
			return( WEAR_FLOAT );
		}
	}
	if( last == WEAR_HEAD || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_HEAD))
		{
			pop_call();
			return( WEAR_HEAD );
		}
	}
	if( last == WEAR_FACE || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_FACE))
		{
			pop_call();
			return( WEAR_FACE );
		}
	}
	if( last == WEAR_EARS || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_EARS))
		{
			pop_call();
			return( WEAR_EARS );
		}
	}
	if( last == WEAR_NECK_1 || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_NECK))
		{
			pop_call();
			return( WEAR_NECK_1 );
		}
	}
	if( last == WEAR_NECK_2 || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_NECK))
		{
			pop_call();
			return( WEAR_NECK_2 );
		}
	}
	if( last == WEAR_ARMS || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_ARMS))
		{
			pop_call();
			return( WEAR_ARMS );
		}
	}
	if( last == WEAR_WRIST_L || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_WRIST))
		{
			pop_call();
			return( WEAR_WRIST_L );
		}
	}
	if( last == WEAR_WRIST_R || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_WRIST))
		{
			pop_call();
			return( WEAR_WRIST_R );
		}
	}
	if( last == WEAR_HANDS || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_BODY))
		{
			pop_call();
			return( WEAR_HANDS );
		}
	}
	if( last == WEAR_FINGER_L || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_FINGER))
		{
			pop_call();
			return( WEAR_FINGER_L );
		}
	}
	if( last == WEAR_FINGER_R || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_FINGER))
		{
			pop_call();
			return( WEAR_FINGER_R );
		}
	}
	if( last == WEAR_BODY || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_BODY))
		{
			pop_call();
			return( WEAR_BODY );
		}
	}
	if( last == WEAR_ABOUT || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_ABOUT))
		{
			pop_call();
			return( WEAR_ABOUT );
		}
	}
	if( last == WEAR_BACK || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_BACK))
		{
			pop_call();
			return( WEAR_BACK );
		}
	}
	if( last == WEAR_WAIST || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_WAIST))
		{
			pop_call();
			return( WEAR_WAIST );
		}
	}
	if( last == WEAR_BELT_1 || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_BELT))
		{
			pop_call();
			return( WEAR_BELT_1 );
		}
	}
	if( last == WEAR_BELT_2 || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_BELT))
		{
			pop_call();
			return( WEAR_BELT_2 );
		}
	}
	if( last == WEAR_BELT_3 || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_BELT))
		{
			pop_call();
			return( WEAR_BELT_3 );
		}
	}
	if( last == WEAR_LEGS || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_LEGS))
		{
			pop_call();
			return( WEAR_LEGS );
		}
	}
	if( last == WEAR_ANKLE_L || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_ANKLE))
		{
			pop_call();
			return( WEAR_ANKLE_L );
		}
	}
	if( last == WEAR_ANKLE_R || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_ANKLE))
		{
			pop_call();
			return( WEAR_ANKLE_R );
		}
	}
	if( last == WEAR_FEET || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_FEET))
		{
			pop_call();
			return( WEAR_FEET );
		}
	}
	if( last == WEAR_SHIELD || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_SHIELD))
		{
			pop_call();
			return( WEAR_SHIELD );
		}
	}
	if( last == WEAR_SADDLE || last < 1 )
	{
		if(IS_SET(obj->wear_flags, CAN_WEAR_SADDLE))
		{
			pop_call();
			return( WEAR_SADDLE );
		}
	}
	pop_call();
	return( -1 );
}


/*
 * New improved bash door, adds support
 * for breaking containers - Kregor
 */
void do_bash( CHAR_DATA *ch, char *argument )
{
	EXIT_DATA *pExit;
	OBJ_DATA *obj;
	CHAR_DATA *victim, *caster;
	int        door;
	char       arg[MAX_INPUT_LENGTH];
	int diceroll, dc;

	push_call("do_bash(%p,%p)",ch,argument);

	one_argument( argument, arg );

	if (arg[0] == '\0')
	{
		if ((victim = ch->last_attacked) == NULL)
		{
			send_to_char( "Bash what or whom?\n\r", ch );
			pop_call();
			return;
		}
	}
	else if ((door = direction_door(arg)) >= 0)
	{
		ROOM_INDEX_DATA *to_room;
		ROOM_TIMER_DATA *rtd;
		EXIT_DATA *pExit_rev;
		dc = 0;

		if ((pExit = ch->in_room->exit[door]) == NULL)
		{
			send_to_char( "There is no exit in that direction.\n\r", ch );
			pop_call();
			return;
		}

		if ((to_room = room_index[pExit->to_room]) == NULL)
		{
			send_to_char( "The door seems to go to nowhere.\n\r", ch );
			pop_call();
			return;
		}

		if ((rtd = get_room_affect(ch->in_room, ROOM_BLOCK)) == NULL || (rtd->modifier != -1 && rtd->modifier != door))
		{
			if ((rtd = get_room_affect(to_room, ROOM_BLOCK)) == NULL || (rtd->modifier != -1 && rtd->modifier != rev_dir[door]))
			{
				if (IS_SET(pExit->exit_info, EX_BASHED))
				{
					send_to_char( "It's already been bashed open!\n\r", ch );
					pop_call();
					return;
				}

				if (!IS_SET(pExit->exit_info, EX_CLOSED))
				{
					send_to_char( "Calm down! It is already open.\n\r", ch );
					pop_call();
					return;
				}
			}
		}
		if (!rtd)
		{
			send_to_char( "Calm down! It is already open.\n\r", ch );
			pop_call();
			return;
		}			

		wait_state(ch, (PULSE_VIOLENCE * 3 / 2));

		diceroll = str_roll(ch);
		
		if (rtd)
		{
			if (rtd->type == gsn_wall_of_force)
			{
				send_to_char( "The barrier cannot be bashed open.\n\r", ch );
				pop_call();
				return;
			}
			else if (rtd->type == gsn_wall_of_stone)
			{
				dc = rtd->level * 2 / 4 + 20;
			}
			else if (rtd->type == gsn_wall_of_iron)
			{
				dc = rtd->level * 3 / 4 + 30;
			}
			else if (rtd->type == gsn_wall_of_ice)
			{
				dc = rtd->level + 15;
			}
			else
			{
				send_to_char( "The barrier cannot be bashed open.\n\r", ch );
				pop_call();
				return;
			}
		}
				
		if (IS_SET(pExit->exit_info, EX_IRON_DOOR))
			dc = UMAX(dc, 28);
		else if (IS_SET(pExit->exit_info, EX_HEAVY_DOOR))
			dc = UMAX(dc, 23);
		else if (IS_SET(pExit->exit_info, EX_WEAK_DOOR))
			dc = UMAX(dc, 13);
		else
			dc = UMAX(dc, 18);
		
		if (IS_SET(pExit->exit_info, EX_MAGICAL_LOCK))
			dc += 10;
		else if (IS_SET(pExit->exit_info, EX_BARRED))
			dc += 5;
			
		if (diceroll < dc && domain_apotheosis(ch, DOMAIN_STRENGTH))
			diceroll = UMAX(diceroll, str_roll(ch));
		
		act( "{138}WHAAAAM!!!{300}", ch, NULL, NULL, TO_CHAR);
		act( "{138}WHAAAAM!!!{300}", ch, NULL, NULL, TO_ROOM);

		if (!IS_SET(pExit->exit_info, EX_BASHPROOF) && diceroll >= dc)
		{
			REMOVE_BIT(pExit->exit_info, EX_CLOSED);
			REMOVE_BIT(pExit->exit_info, EX_LOCKED);
			SET_BIT( pExit->exit_info, EX_BASHED );

			act( "You bash open the $d!", ch, NULL, pExit->keyword, TO_CHAR );
			act( "$n bashes open the $d!",  ch, NULL, pExit->keyword, TO_ROOM );

			if ((pExit_rev = room_index[pExit->to_room]->exit[rev_dir[direction_door(arg)]]) != NULL
			&&  room_index[pExit_rev->to_room] == ch->in_room )
			{
				CHAR_DATA *rch;

				REMOVE_BIT(pExit_rev->exit_info, EX_CLOSED);
				REMOVE_BIT(pExit_rev->exit_info, EX_LOCKED);
				SET_BIT( pExit_rev->exit_info, EX_BASHED );

				for (rch = to_room->first_person ; rch ; rch = rch->next_in_room)
				{
					act( "{138}WHAAAAM!!!{300}", rch, NULL, NULL, TO_CHAR);
					act( "The $d crashes open!", rch, NULL, pExit_rev->keyword, TO_CHAR);
				}
			}
			if (rtd)
			{
				if (rtd->type == gsn_wall_of_ice) // damage for bashing wall of ice
				{
					if ((caster = get_caster_room(rtd)) == NULL)
						damage(ch, ch, dice(1,6) + rtd->level, gsn_wall_of_ice, NULL); 
					else
						damage(caster, ch, dice(1,6) + rtd->level, gsn_wall_of_ice, NULL);
				}
				del_room_timer(rtd->vnum, rtd->type);
			}
		}
		else
		{
			act( "You bash against the $d, but it doesn't budge.", ch, NULL, pExit->keyword, TO_CHAR );
			act( "$n bashes against the $d, but it holds strong.", ch, NULL, pExit->keyword, TO_ROOM );
			
			// Only stands to reason that anyone on the other side of 
			// the door would HEAR the door being banged against - Kregor
			
			if ((to_room = room_index[pExit->to_room]) != NULL
			&&  (pExit_rev = room_index[pExit->to_room]->exit[rev_dir[direction_door(arg)]]) != NULL
			&&  room_index[pExit_rev->to_room] == ch->in_room )
			{
				CHAR_DATA *rch;
	
				for (rch = to_room->first_person ; rch ; rch = rch->next_in_room)
				{
					act( "{138}WHAAAAM!!!{300}", rch, NULL, NULL, TO_CHAR);
					act( "Someone bashes against the $d from the other side!", rch, NULL, pExit_rev->keyword, TO_CHAR);
				}
			}
		}
		trig_room_trap(ch, trap_door[door]);
	}
	/* bash container */
	else if ((obj = get_obj_here(ch, arg)) != NULL)
	{		
		if (obj->item_type != ITEM_CONTAINER)
		{
			act( "$p is not a container.", ch, obj, NULL, TO_CHAR);
			pop_call();
			return;
		}

		if (!IS_SET(obj->value[1], CONT_CLOSED))
		{
			act( "$p is not closed.", ch, obj, NULL, TO_CHAR);
			pop_call();
			return;
		}

		if (!IS_SET(obj->value[1], CONT_LOCKED))
		{
			act( "$p is already unlocked.", ch, obj, NULL, TO_CHAR);
			pop_call();
			return;
		}
		
		diceroll = str_roll(ch);

		if (IS_SET(obj->value[1], CONT_STRONG))
		{
			dc = 28;
		}
		else if (IS_SET(obj->value[1], CONT_WEAK))
		{
			dc = 17;
		}
		else
		{
			dc = 23;
		}

		if (IS_SET(obj->value[1], CONT_MAGICAL_LOCK))
		{
			dc += 10;
		}

		if (diceroll < dc && domain_apotheosis(ch, DOMAIN_STRENGTH))
			diceroll = UMAX(diceroll, str_roll(ch));

		act( "{138}WHAAAAM!!!{300}", ch, NULL, NULL, TO_CHAR);
		act( "{138}WHAAAAM!!!{300}", ch, NULL, NULL, TO_ROOM);

		if (IS_SET(obj->value[1], CONT_BASHPROOF) || diceroll < dc)
		{
			act( "You attempt to break open $p but fail.",  ch, obj, NULL, TO_CHAR);
			act( "$n attempts to break open $p but fails.", ch, obj, NULL, TO_ROOM);
		}
		else
		{
			REMOVE_BIT(obj->value[1], CONT_LOCKED);
			REMOVE_BIT(obj->value[1], CONT_CLOSED);
	
			act( "You smash open $p!", ch, obj, NULL, TO_CHAR);
			act( "$n smashes open $p!", ch, obj, NULL, TO_ROOM);
		}
		trig_obj_trap(ch, obj, TRAP_TRIG_OPEN_OBJ|TRAP_TRIG_GET_PUT);
	}
	/* shield bash victim */
	else if ((victim = get_char_room(ch, arg)) != NULL)
	{
		if (is_safe(ch, victim))
		{
			pop_call();
			return;
		}
		bash(ch, victim, 0);
	}
	else
	{
		act( "You see nothing to bash.", ch, NULL, NULL, TO_CHAR );
	}
	pop_call();
	return;
}

/*
 * Code courtesy of Stu, from the mailing list. Allows player
 * to destroy an item in their inventory.
 * Debugged and cleaned up on 4-16-01 by Samson.
 */
void do_junk( CHAR_DATA * ch, char *argument )
{
	OBJ_DATA *obj;
	
	push_call("do_junk(%p,%p)",ch,argument);

	if (!argument || argument[0] == '\0')
	{
		send_to_char( "Junk what?\r\n", ch );
		pop_call();
		return;
	}

	if ((obj = get_obj_carry(ch, argument)) == NULL)
	{
		send_to_char( "You are not carrying that.\r\n", ch );
		pop_call();
		return;
	}

	if (!can_drop_obj( ch, obj ) && ch->level < LEVEL_IMMORTAL)
	{
		send_to_char( "You cannot junk that.\r\n", ch );
		pop_call();
		return;
	}
	if (!IS_GOD(ch) && !IS_OWNER(obj, ch))
	{
		send_to_char("You cannot junk what isn't yours to junk.\r\n", ch);
		pop_call();
		return;
	}

	if (obj->first_content)
	{
		while (obj->first_content)
		{
			obj->first_content->sac_timer = OBJ_SAC_TIME;
			act( "  $p falls out onto the floor.", ch, obj->first_content, NULL, TO_ALL);
			obj_to_room(obj->first_content, ch->in_room->vnum);
		}
	}

	obj_from_char(obj);
	junk_obj(obj);
	act( "$n junks $p.", ch, obj, NULL, TO_ROOM );
	act( "You junk $p.", ch, obj, NULL, TO_CHAR );

	pop_call();
	return;
}

/*
 * draw and sheath by Kregor
 */
void do_draw( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	OBJ_DATA *weapon, *cont;
	int location;
	bool named = FALSE;
	
	push_call("do_draw(%p,%p)",ch,argument);
	
	if (in_combat(ch) && !is_active(ch))
	{
		send_to_char( "You have to wait your turn.\n\r", ch );
		pop_call();
		return;
	}
		
	argument = one_argument(argument, arg1);
	argument = one_argument(argument, arg2);

	if (arg1[0] != '\0')
		named = TRUE;
	
	if (!is_handy(ch) || hands_full(ch))
	{
		send_to_char( "You have no hands free to draw a weapon.\n\r", ch );
		pop_call();
		return;
	}
	
	for (cont = ch->first_carrying ; cont ; cont = cont->next_content)
	{
		if (cont->item_type != ITEM_SHEATH)
			continue;
			
		if (!named)
		{
			if ((weapon = cont->first_content) != NULL)
				break;
		}
		else if ((weapon = get_obj_list(ch, arg1, cont->first_content)) != NULL && weapon->item_type == ITEM_WEAPON)
		{
			break;
		}
	}
	if (!cont)
	{
		ch_printf_color(ch, "You are not wearing a sheath.\n\r");
		pop_call();
		return;
	}
	if (!weapon)
	{
		if (!named)
			ch_printf_color(ch, "You do not have any weapon to draw.\n\r");
		else
			ch_printf_color(ch, "You do not see that in any sheath.\n\r");
		pop_call();
		return;
	}
	if (IS_SET(cont->value[1], CONT_CLOSED))
	{
		act( "$p is closed.", ch, cont, NULL, TO_CHAR);
		pop_call();
		return;
	}

	location = CAN_WEAR_WIELD;

	if (arg2[0] != '\0')
	{
		if (!strcasecmp(arg2, "both"))
		{
			if ((CAN_WEAR(weapon, CAN_WEAR_WIELD) && get_size(ch) <= (learned(ch, gsn_smaller_weapons) ? weapon->size - 1 : weapon->size)) || CAN_WEAR(weapon, CAN_WEAR_BOTH))
			{
				location = CAN_WEAR_BOTH;
			}
			else
			{
				act("$p is too small to be wielded in both hands.", ch, weapon, NULL, TO_CHAR);
				pop_call();
				return;
			}
		}
	}
	
	if (get_obj(ch, weapon, cont, FALSE, FALSE))
	{
		act( "$n draws $p from $P.", ch, weapon, cont, TO_CAN_SEE );
		act( "You draw $p from $P.", ch, weapon, cont, TO_CHAR );
		wear_obj( ch, weapon, TRUE, location , TRUE);
	}
	if (*arg2 != '\0' && location == CAN_WEAR_WIELD)
	{
		do_draw(ch, arg2);
	}
	else
	{
		if (!learned(ch, gsn_quick_draw))
		{
			TAKE_ACTION(ch, ACTION_MOVE);
		}
		else
		{
			TAKE_ACTION(ch, ACTION_SWIFT);
		}
	}
	pop_call();
	return;
}


void do_sheath( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	OBJ_DATA *weapon, *cont;
	
	push_call("do_sheath(%p,%p)",ch,argument);
	
	if (in_combat(ch) && !is_active(ch))
	{
		send_to_char( "You have to wait your turn.\n\r", ch );
		pop_call();
		return;
	}
		
	argument = one_argument(argument, arg1);
	argument = one_argument(argument, arg2);

	if (arg1[0] != '\0' && strcasecmp(arg1, "both"))
	{
		if ((weapon = get_obj_wear(ch, arg1)) == NULL)
		{
			ch_printf_color(ch, "You are not wielding that.\n\r");
			pop_call();
			return;
		}
	}
	else
	{
		if ((weapon = get_wield(ch, TRUE)) == NULL)
		{
			if ((weapon = get_wield(ch, FALSE)) == NULL)
			{
				send_to_char( "You aren't wielding a weapon.\n\r", ch );
				pop_call();
				return;
			}
		}
	}
	if (!can_drop_obj(ch, weapon))
	{
		act( "You cannot sheath $p.", ch, weapon, NULL, TO_CHAR);
		pop_call();
		return;
	}	
	
	if (arg2[0] != '\0')
	{
		if ((cont = get_obj_wear( ch, arg2 ) ) == NULL )
		{
			if ((cont = get_obj_carry( ch, arg2 ) ) == NULL )
			{
				act( "You cannot find that sheath.", ch, NULL, NULL, TO_CHAR);
				pop_call();
				return;
			}
		}
		if (!IS_OBJ_TYPE(cont, ITEM_SHEATH))
		{
			send_to_char( "That is not a sheath.\n\r", ch);
			pop_call();
			return;
		}
		if (IS_SET(cont->value[1], CONT_CLOSED))
		{
			send_to_char( "That sheath is closed.\n\r", ch);
			pop_call();
			return;
		}
		if (weapon->size > cont->size)
		{
			send_to_char( "That weapon is too big.\n\r", ch);
			pop_call();
			return;
		}
		if (count_total_objects(cont) >= (cont->value[3] ? cont->value[3] : 1))
		{
			send_to_char( "That sheath is already full.\n\r", ch);
			pop_call();
			return;
		}
	}
	else
	{
		for (cont = ch->first_carrying ; cont ; cont = cont->next_content)
		{
			if (cont->item_type != ITEM_SHEATH)
				continue;
			if (cont->size < weapon->size)
				continue;
			if (IS_SET(cont->value[1], CONT_CLOSED))
				continue;
			if (count_total_objects(cont) >= (cont->value[3] ? cont->value[3] : 1))
				continue;
			break;
		}
	}
	if (!cont)
	{
		ch_printf_color(ch, "You have no open sheath for that weapon.\n\r");
	}
	else
	{
		unequip_char(ch, weapon, TRUE);
		put_obj(ch, weapon, cont, FALSE, TRUE);
		act( "$n sheaths $p in $P.", ch, weapon, cont, TO_CAN_SEE );
		act( "You sheath $p in $P.", ch, weapon, cont, TO_CHAR );
		if (!strcasecmp(arg1, "both"))
		{
			do_sheath(ch, "");
		}
		else
		{
			if (!learned(ch, gsn_quick_draw))
			{
				TAKE_ACTION(ch, ACTION_MOVE);
			}
			else
			{
				TAKE_ACTION(ch, ACTION_SWIFT);
			}
		}
	}	
	pop_call();
	return;
}


void do_repair( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	CHAR_DATA *keeper;
	OBJ_DATA *obj, *kit;
	int cost, skill, tool, condition;
	
	push_call("do_repair(%p,%p)",ch,argument);

	if (IS_NPC( ch ))
	{
		pop_call();
		return;
	}

	if (argument[0] == '\0' )
	{
		send_to_char( "Repair what?\n\r", ch);
		pop_call();
		return;
	}

	argument = one_argument( argument, arg );

	if ((obj = get_obj_carry(ch, arg)) == NULL)
	{
		send_to_char("You do not have that object.\n\r", ch);
		pop_call();
		return;
	}
	
	skill = -1;
	
	if ((condition = what_percent(obj->hit_points, UMAX(1, get_obj_max_hit(obj)))) >= 100)
	{
		act("$p does not need to be repaired.", ch, obj, NULL, TO_CHAR);
		pop_call();
		return;
	}
	
	if (IS_OBJ_TYPE(obj, ITEM_ARMOR))
	{
		switch (obj->value[0])
		{
			default:
				skill = gsn_craft_armor;
				if (weapon_table[obj->value[0]].material == MATERIAL_TYPE_WOOD)
					tool = TOOL_WOODWORKERS_TOOLS;
				else
					tool = TOOL_SMITH_TOOLS;
				break;
			case ARMOR_TYPE_LEATHER:
			case ARMOR_TYPE_STUDDED_LEATHER:
			case ARMOR_TYPE_HIDE:
				skill = gsn_craft_leather;
				tool = TOOL_TANNING_TOOLS;
				break;
			case ARMOR_TYPE_PADDED:
			case ARMOR_TYPE_CLOTH:
				skill = gsn_craft_tailoring;
				tool = TOOL_TAILORS_TOOLS;
				break;
		}
		switch (obj->material)
		{
			default:
				break;
			case MATERIAL_FUR:
			case MATERIAL_LEATHER:
			case MATERIAL_HIDE:
			case MATERIAL_DRAGONHIDE:
				skill = gsn_craft_leather;
				tool = TOOL_TANNING_TOOLS;
				break;
		}
	}
	else if (IS_OBJ_TYPE(obj, ITEM_WEAPON))
	{
		switch (obj->value[0])
		{
			default:
				if (weapon_table[obj->value[0]].material == MATERIAL_TYPE_HIDE)
				{
					skill = gsn_craft_leather;
					tool = TOOL_TANNING_TOOLS;
				}
				else if (weapon_table[obj->value[0]].material == MATERIAL_TYPE_WOOD)
				{
					skill = gsn_craft_weapons;
					tool = TOOL_WOODWORKERS_TOOLS;
				}
				else
				{
					skill = gsn_craft_weapons;
					tool = TOOL_SMITH_TOOLS;
				}
				break;
			case WEAPON_TYPE_SHORTBOW:
			case WEAPON_TYPE_SHORTBOW_COMPOSITE:
			case WEAPON_TYPE_LONGBOW:
			case WEAPON_TYPE_LONGBOW_COMPOSITE:
				skill = gsn_craft_bows;
				tool = TOOL_WOODWORKERS_TOOLS;
				break;
		}
	}
	else if (IS_OBJ_TYPE(obj, ITEM_TREASURE))
	{
		skill = gsn_craft_jewelry;
		tool = TOOL_JEWELERS_TOOLS;
	}

	if (skill == -1)
	{
		send_to_char("You cannot repair that type of object.\n\r", ch);
		pop_call();
		return;
	}
	

	/* check for repairer mobile first, then character skill */
	if ((keeper = find_keeper(ch)) == NULL)
	{
		if (!learned(ch, skill))
		{
			send_to_char("There is no repairer here.\n\r",ch);
			pop_call();
			return;
		}
	}
	if (keeper && !learned(keeper, skill))
	{
		send_to_char("That cannot be repaired here.\n\r",ch);
		pop_call();
		return;
	}

	if (keeper)
	{	
		CHECK_KEEPER(ch, keeper);

		cost = obj->cost/3;
		cost = (100 - condition) * cost / 100;
		cost = haggle(ch, keeper, cost, TRUE);		

		if (!gold_transaction(ch, cost))
		{
			command(keeper, do_sayto, "%s It will cost you %s to repair %s.",  ansi_strip(ansi_translate(format_coins(cost,TRUE))), obj->short_descr, short_to_name(get_name(ch),1));
			command(keeper, do_sayto, "%s Which, I see, you cannot afford.", short_to_name(get_name(ch),1));
			pop_call();
			return;
		}
		
		obj->hit_points = get_obj_max_hit(obj);
		act("You pay $t to $N.", ch, format_coins(cost, TRUE), keeper, TO_CHAR);
		act("$N sets to repairing $p.", ch, obj, keeper, TO_CHAR);
		act("$N sets to repairing $p.", ch, obj, keeper, TO_ROOM);
		act("$N returns $p to you, good as new.", ch, obj, keeper, TO_CHAR);
		act("$N returns $p to $n, good as new.", ch, obj, keeper, TO_ROOM);
	}
	else
	{
		if ((kit = get_obj_carry_type(ch, ITEM_TOOLS)) == NULL || !TOOL_TYPE(kit, tool))
		{
			ch_printf_color(ch, "You need a proper crafting kit to repair that.\n\r");
			pop_call();
			return;
		}		
		kit->value[1]--;

		if (kit->value[1] <= 0)
			junk_obj(kit);

		obj->hit_points = get_obj_max_hit(obj);
		act("$n sets to repairing $p.", ch, obj, NULL, TO_CHAR);
		act("$n sets to repairing $p.", ch, obj, NULL, TO_ROOM);
	}
	pop_call();
	return;
}

/*
 * Burning and cooking functions for
 * good old fashioned cookouts - Kregor
 */
void do_cook( CHAR_DATA *ch, char *argument )
{
	OBJ_DATA *fire, *pot, *food;
	int roll;
	
	push_call("do_cook(%p,%p)",ch,argument);
	
	if (argument[0] == '\0')
	{
		send_to_char("Cook what?\n\r", ch);
		pop_call();
		return;
	}
	for (fire = ch->in_room->first_content ; fire != NULL ; fire = fire->next_content)
	{
		if (IS_OBJ_TYPE(fire, ITEM_FIRE))
			break;
	}
	if (!fire)
	{
		send_to_char("There's no fire here to cook on.\n\r", ch);
		pop_call();
		return;
	}
	if ((pot = get_obj_carry_type(ch, ITEM_TOOLS)) == NULL || !TOOL_TYPE(pot, TOOL_COOKING_POT))
	{
		send_to_char("You don't have a cooking vessel to cook in.\n\r", ch);
		pop_call();
		return;
	}
	if ((food = get_obj_carry(ch, argument)) == NULL)
	{
		ch_printf_color(ch, "You aren't carrying any %s.\n\r", argument);
		pop_call();
		return;
	}
	if (food->value[2])
	{
		act("$p is already cooked.", ch, food, NULL, TO_CHAR);
		pop_call();
		return;
	}
	if ((roll = craft_cooking_roll(ch)) < 8)
	{
		act("You burn $p so badly its inedible.", ch, food, NULL, TO_CHAR);
		act("$n burns $p so badly its inedible.", ch, food, NULL, TO_ROOM);
		extract_obj(food);
		pop_call();
		return;
	}
	else if (roll < 12)
	{
		act("You overcook $p.", ch, food, NULL, TO_CHAR);
		act("$n overcooks $p.", ch, food, NULL, TO_ROOM);
		food->value[2] += 2;
		pop_call();
		return;
	}
	
	act("You cook $p over $P.", ch, food, fire, TO_CHAR);
	act("$n cooks $p over $P.", ch, food, fire, TO_ROOM);
	food->value[2] += 1;
	pop_call();
	return;
}


void do_burn( CHAR_DATA *ch, char *argument )
{
	OBJ_DATA *tinder, *obj, *fire;
	
	push_call("do_burn(%p,%p)",ch,argument);
	
	if (*argument == '\0')
	{
		send_to_char("Burn what?\n\r", ch);
		pop_call();
		return;
	}
	if ((obj = get_obj_here(ch, argument)) == NULL)
	{
		ch_printf_color(ch, "There isn't any %s here.\n\r", argument);
		pop_call();
		return;
	}
	switch (obj->material)
	{
		default:
			send_to_char("That is not flammable.\n\r", ch);
			pop_call();
			return;
		case MATERIAL_HARDWOOD:
		case MATERIAL_SOFTWOOD:
		case MATERIAL_OAK:
		case MATERIAL_YEW:
		case MATERIAL_EBONY:
		case MATERIAL_PAPER:
		case MATERIAL_OIL:
			if (IS_OBJ_STAT(obj, ITEM_MAGIC))
			{
				send_to_char("You can't burn that.\n\r", ch);
				pop_call();
				return;
			}
			break;
	}
	
	fire = NULL;
	
	for (fire = ch->in_room->first_content ; fire != NULL ; fire = fire->next_content)
	{
		if (IS_OBJ_TYPE(fire, ITEM_FIRE))
			break;
	}
	if (!fire)
	{
		if ((tinder = get_obj_carry_type(ch, ITEM_TOOLS)) == NULL || !TOOL_TYPE(tinder, TOOL_TINDER))
		{
			send_to_char("You're not carrying any tinder.\n\r", ch);
			pop_call();
			return;
		}
		if ((fire = create_object( get_obj_index( OBJ_VNUM_FIRE ), 0 )) == NULL)
		{
			bug("do_burn: OBJ_VNUM_FIRE not created.", 0);
			pop_call();
			return;
		}
		if (--tinder->value[1] == 0)
		{
			act( "You use the rest of $p.", ch, tinder, NULL, TO_CHAR );
			junk_obj(tinder);
		}
		fire->value[2] = obj->size * obj->size;
		act( "You use $p and set to work starting a fire.", ch, tinder, NULL, TO_CHAR );
		act( "$n uses $p and sets to work starting a fire.", ch, tinder, NULL, TO_ROOM );
		obj_to_room( fire, ch->in_room->vnum );
		junk_obj(obj);
		
		pop_call();
		return;
	}
	else
	{
		act( "You cast $p into $P.", ch, obj, fire, TO_CHAR );
		act( "$n casts $p into $P.", ch, obj, fire, TO_ROOM );
		
		fire->value[2] += obj->size * obj->size;
		junk_obj(obj);
	}
	pop_call();
	return;
}