area/
build/testing/
log/
player/
player/backup/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/
#include <glib.h>

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <merc.h>
#include <interp.h>
#include <fight.h>
#include <player.h>



/*
 * Local functions.
 */
#define CD CHAR_DATA
void	get_obj		args( ( CHAR_DATA *ch, OBJ_DATA *obj,
	OBJ_DATA *container ) );
CD *	find_keeper	args( ( CHAR_DATA *ch ) );
int	get_cost	args( ( CHAR_DATA *keeper, OBJ_DATA *obj, bool fBuy ) );
void	sheath		args( ( CHAR_DATA *ch, bool right ) );
void	draw		args( ( CHAR_DATA *ch, bool right ) );
char	*special_item_name args( ( OBJ_DATA *obj ) );
void 	call_all	args( ( CHAR_DATA *ch ) );
#undef	CD



void do_call( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	CHAR_DATA *victim = NULL;
	ROOM_INDEX_DATA *chroom;
	ROOM_INDEX_DATA *objroom;
	
	one_argument( argument, arg );
	
	if ( arg[0] == '\0' )
	{
		send_to_char( "What object do you wish to call?\n\r", ch );
		return;
	}
	
	if (IS_NPC(ch)) {send_to_char("Not while switched.\n\r",ch); return;}
	
	if (!IS_HEAD(ch, LOST_HEAD))
	{
		act("Your eyes flicker with yellow energy.",ch,NULL,NULL,TO_CHAR);
		act("$n's eyes flicker with yellow energy.",ch,NULL,NULL,TO_ROOM);
	}
	
	if (!str_cmp(arg,"all"))
	{
		call_all(ch);
		return;
	}
	
	if ( ( obj = get_obj_world( ch, arg ) ) == NULL )
	{
		send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch );
		return;
	}
	
	if ( obj->item_type == ITEM_PAGE )
		return;

	if (obj->questowner == NULL || obj->questowner->len < 2 ||
		str_cmp(obj->questowner->str,ch->name->str))
	{
		send_to_char( "Nothing happens.\n\r", ch );
		return;
	}

	if ( ch->carry_weight + get_obj_weight( obj ) > can_carry_w( ch ) )
	{
		send_to_char( "You can't carry that much weight!\n\r",ch);
		return;
	}
	
	if (obj->carried_by != NULL && obj->carried_by != ch)
	{
		victim = obj->carried_by;
		if (!IS_NPC(victim) && victim->desc != NULL && 
                victim->desc->connected != CON_PLAYING) 
                         return;
		act("$p suddenly vanishes from your hands!",victim,obj,NULL,TO_CHAR);
		act("$p suddenly vanishes from $n's hands!",victim,obj,NULL,TO_ROOM);
		obj_from_char(obj);
	}
	else if (obj->in_room != NULL)
	{
		chroom = ch->in_room;
		objroom = obj->in_room;
		char_from_room(ch);
		char_to_room(ch,objroom);
		act("$p vanishes from the ground!",ch,obj,NULL,TO_ROOM);
		if (chroom == objroom) act("$p vanishes from the ground!",ch,obj,NULL,TO_CHAR);
		char_from_room(ch);
		char_to_room(ch,chroom);
		obj_from_room(obj);
	}
	else if (obj->in_obj != NULL) obj_from_obj(obj);
	else
	{
		if (!IS_HEAD(ch, LOST_HEAD))
			send_to_char( "Nothing happens.\n\r", ch );
		return;
	}
	
	obj_to_char(obj,ch);
	if (IS_SET(obj->extra_flags,ITEM_SHADOWPLANE))
		REMOVE_BIT(obj->extra_flags,ITEM_SHADOWPLANE);
	act("$p materializes in your hands.",ch,obj,NULL,TO_CHAR);
	act("$p materializes in $n's hands.",ch,obj,NULL,TO_ROOM);
	do_autosave(ch,"");
	if (victim != NULL) do_autosave(victim,"");
	return;
}

void look_for_ownereq(OBJ_DATA *obj, CHAR_DATA *ch)
{
	ROOM_INDEX_DATA *chroom;
	ROOM_INDEX_DATA *objroom;
	bool found = FALSE;
	OBJ_DATA *in_obj;
		
	if ( obj->item_type == ITEM_PAGE )
		return;

	if ( obj->questowner == NULL || obj->questowner->len < 2 || 
		str_cmp( ch->name->str, obj->questowner->str ))
		return;
		
	if ( ch->carry_weight + get_obj_weight( obj ) > can_carry_w( ch ) )
	{
		send_to_char("{RYou are carring WAY too much.. wear something then try again!{x\n\r",ch);
		return;
	}
	found = TRUE;
	
	for ( in_obj = obj; in_obj->in_obj != NULL; in_obj = in_obj->in_obj )
		;
		
	if (in_obj->carried_by != NULL)
	{
		if (in_obj->carried_by == ch) return;
	}
		
	if (obj->carried_by != NULL)
	{
		if (obj->carried_by == ch || obj->carried_by->desc == NULL || 
			obj->carried_by->desc->connected != CON_PLAYING) 
		{
			if (!IS_NPC(obj->carried_by)) 
				return;
		}
		act("$p suddenly vanishes from your hands!",obj->carried_by,obj,NULL,TO_CHAR);
		act("$p suddenly vanishes from $n's hands!",obj->carried_by,obj,NULL,TO_ROOM);
		SET_BIT(obj->carried_by->extra, EXTRA_CALL_ALL);
		obj_from_char(obj);
	}
	else if (obj->in_room != NULL)
	{
		chroom = ch->in_room;
		objroom = obj->in_room;
		char_from_room(ch);
		char_to_room(ch,objroom);
		act("$p vanishes from the ground!",ch,obj,NULL,TO_ROOM);
		if (chroom == objroom) act("$p vanishes from the ground!",ch,obj,NULL,TO_CHAR);
		char_from_room(ch);
		char_to_room(ch,chroom);
		obj_from_room(obj);
	}
	else 
		if (obj->in_obj != NULL) obj_from_obj(obj);
	else 
		return;
	obj_to_char(obj,ch);
	if (IS_SET(obj->extra_flags,ITEM_SHADOWPLANE))
		REMOVE_BIT(obj->extra_flags,ITEM_SHADOWPLANE);
	if (!IS_HEAD(ch, LOST_HEAD))
	{
		act("$p materializes in your hands.",ch,obj,NULL,TO_CHAR);
		act("$p materializes in $n's hands.",ch,obj,NULL,TO_ROOM);
	}
	return;
}

void call_all( CHAR_DATA *ch )
{
	CHAR_DATA *victim = NULL;
	DESCRIPTOR_DATA *d;
	bool found = FALSE;
	GSList *desc_list = descriptor_list;
	
	g_slist_foreach(object_list, (GFunc)look_for_ownereq, ch);

	if ( !found && !IS_HEAD(ch, LOST_HEAD) )
		send_to_char( "Nothing happens.\n\r", ch );
	
	for ( desc_list =descriptor_list; desc_list != NULL; desc_list = g_slist_next(desc_list))
	{
		d = (DESCRIPTOR_DATA*)desc_list->data;
		if ( d->connected != CON_PLAYING ) 
			continue;
		if ( (victim = d->character) == NULL ) 
			continue;
		if ( IS_NPC(victim) ) 
			continue;
		if ( ch != victim && !IS_EXTRA(victim,EXTRA_CALL_ALL) ) 
			continue;
		REMOVE_BIT(victim->extra, EXTRA_CALL_ALL);
		do_autosave(victim,"");
	}
	g_slist_free(desc_list);
	return;
}

void get_obj( CHAR_DATA *ch, OBJ_DATA *obj, OBJ_DATA *container )
{
	OBJ_DATA *obj2;
	OBJ_DATA *obj_next;
	ROOM_INDEX_DATA *objroom;
	bool move_ch = FALSE;
	
    /* Objects should only have a shadowplane flag when on the floor */

	if ( ch->plane != obj->plane ){
		send_to_char( "Your hand passes right through it!\n\r", ch );
		return;
	}
	if ( !CAN_WEAR(obj, ITEM_TAKE) && ch->level < LEVEL_HIGHJUDGE )
	{
		send_to_char( "You can't take that.\n\r", ch );
		return;
	}
	
	if ( ch->carry_number + 1 > can_carry_n( ch ) )
	{
		act( "$d: you can't carry that many items.",
			ch, NULL, obj->name->str, TO_CHAR );
		return;
	}
	
	if ( ch->carry_weight + get_obj_weight( obj ) > can_carry_w( ch ) )
	{
		act( "$d: you can't carry that much weight.",
			ch, NULL, obj->name->str, TO_CHAR );
		return;
	}
	
	if ( container != NULL )
	{
		if (ch->plane != obj->plane ){	
			send_to_char( "Your hand passes right through it!\n\r", ch );
			return;
		}
		act( "You get $p from $P.", ch, obj, container, TO_CHAR );
		act( "$n gets $p from $P.", ch, obj, container, TO_ROOM );
		for ( obj2 = container->contains; obj2 != NULL; obj2 = obj_next )
		{
			obj_next = obj2->next_content;
			if ( obj2->chobj != NULL )
			{act( "A hand reaches inside $P and takes $p out.", obj2->chobj, obj, container, TO_CHAR );
			move_ch = TRUE;}
		}
		obj_from_obj( obj );
	}
	else
	{
		act( "You pick up $p.", ch, obj, container, TO_CHAR );
		act( "$n picks $p up.", ch, obj, container, TO_ROOM );
		if (obj != NULL) obj_from_room( obj );
	}
	
	if ( obj->item_type == ITEM_MONEY )
	{
		ch->gold += obj->value[0];
		extract_obj( obj );
	}
	else
	{
		obj_to_char( obj, ch );
		if ( move_ch && obj->chobj != NULL )
		{
			if (obj->carried_by != NULL && obj->carried_by != obj->chobj)
				objroom = get_room_index(obj->carried_by->in_room->vnum);
			else objroom = NULL;
			if (objroom != NULL && get_room_index(obj->chobj->in_room->vnum) != objroom)
			{
				char_from_room(obj->chobj);
				char_to_room(obj->chobj,objroom);
				do_look(obj->chobj,"auto");
			}
		}
	}
	
	return;
}



void do_get( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	OBJ_DATA *obj_next;
	OBJ_DATA *container;
	bool found;
	
	argument = one_argument( argument, arg1 );
	argument = one_argument( argument, arg2 );
	
    /* Get type. */
	if ( arg1[0] == '\0' )
	{
		send_to_char( "Get what?\n\r", ch );
		return;
	}
	
	if ( arg2[0] == '\0' )
	{
		if ( str_cmp( arg1, "all" ) && str_prefix( "all.", arg1 ) )
		{
			/* 'get obj' */
			obj = get_obj_list( ch, arg1, ch->in_room->contents );
			if ( obj == NULL )
			{
				act( "I see no $T here.", ch, NULL, arg1, TO_CHAR );
				return;
			}

			if (IS_ARTIFACT(obj) && !CAN_PK(ch) && !IS_IMMORTAL(ch) )
			{
				send_to_char( "You cannot pick artifacts up while mortal.\n\r", ch );
				return;
			}

			if (obj->pIndexData->vnum == ch->questobj && str_cmp(obj->OOwner->str,ch->name->str))
			{
				send_to_char("Thats not yours.. don't touch\n\r",ch);
				return;
			}
			// portals
			if (( obj->item_type == 27 ) && !IS_IMMORTAL(ch) )
			{
				send_to_char( "You can't take that.\n\r", ch );
				return;
			}
			get_obj( ch, obj, NULL );
		}
		else
		{
			/* 'get all' or 'get all.obj' */
			found = FALSE;
			for ( obj = ch->in_room->contents; obj != NULL; obj = obj_next )
			{
				obj_next = obj->next_content;
				if ( ( arg1[3] == '\0' || is_name( &arg1[4], obj->name->str ) )
						&&   can_see_obj( ch, obj ) )
				{
					found = TRUE;

					if (obj->pIndexData->vnum == ch->questobj && str_cmp(obj->OOwner->str,ch->name->str))
					{

						send_to_char("Thats not yours.. don't touch\n\r",ch);
						continue;
					}

					if (IS_ARTIFACT(obj) && !CAN_PK(ch) && !IS_IMMORTAL(ch) )
					{
						send_to_char( "Leaving the artifact for a non-mortal.\n\r", ch );
					} 
					else get_obj( ch, obj, NULL );
				}
			}

			if ( !found ) 
			{
				if ( arg1[3] == '\0' )
					send_to_char( "I see nothing here.\n\r", ch );
				else
					act( "I see no $T here.", ch, NULL, &arg1[4], TO_CHAR );
			}
		}
	}
	else
	{
	/* 'get ... container' */
		if ( !str_cmp( arg2, "all" ) || !str_prefix( "all.", arg2 ) )
		{
			send_to_char( "You can't do that.\n\r", ch );
			return;
		}
		
		if ( ( container = get_obj_here( ch, arg2 ) ) == NULL )
		{
			act( "I see no $T here.", ch, NULL, arg2, TO_CHAR );
			return;
		}
		
		switch ( container->item_type )
		{
			default:
				send_to_char( "That's not a container.\n\r", ch );
				return;
				
			case ITEM_CONTAINER:
			case ITEM_CORPSE_NPC:
				break;
				
			case ITEM_CORPSE_PC:
				{
					char name[MAX_INPUT_LENGTH];
					char *pd;
					
					if ( IS_NPC(ch) && ch->level < 12 )
					{
						send_to_char( "You can't do that.\n\r", ch );
						return;
					}
					
					pd = container->short_descr->str;
					pd = one_argument( pd, name );
					pd = one_argument( pd, name );
					pd = one_argument( pd, name );
				}
		}
		
		if ( IS_SET(container->value[1], CONT_CLOSED) )
		{
			act( "The $d is closed.", ch, NULL, container->name, TO_CHAR );
			return;
		}
		
		if ( str_cmp( arg1, "all" ) && str_prefix( "all.", arg1 ) )
		{
	    /* 'get obj container' */
			obj = get_obj_list( ch, arg1, container->contains );
			if ( obj == NULL)
			{
				act( "I see nothing like that in the $T.",
					ch, NULL, arg2, TO_CHAR );
				return;
			}
			if (IS_ARTIFACT(obj) && !CAN_PK(ch) && !IS_IMMORTAL(ch) )
			{
				send_to_char( "Leaving the artifact for a non-mortal.\n\r", ch );
			} 
			else get_obj( ch, obj, container );
			
		}
		else
		{
	    /* 'get all container' or 'get all.obj container' */
			found = FALSE;
			for ( obj = container->contains; obj != NULL; obj = obj_next )
			{
				obj_next = obj->next_content;
				if ( ( arg1[3] == '\0' || is_name( &arg1[4], obj->name->str ) )
					&&   can_see_obj( ch, obj ) )
				{
					found = TRUE;
					if (IS_ARTIFACT(obj) && !CAN_PK(ch) && !IS_IMMORTAL(ch) )
					{
						send_to_char( "Leaving the artifact for a non-mortal.\n\r", ch );
					} 
					else get_obj( ch, obj, container );
				}
			}
			
			if ( !found )
			{
				if ( arg1[3] == '\0' )
					act( "I see nothing in the $T.",
						ch, NULL, arg2, TO_CHAR );
				else
					act( "I see nothing like that in the $T.",
						ch, NULL, arg2, TO_CHAR );
			}
		}
	}
	do_autosave(ch,"");
	return;
}



void do_put( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	OBJ_DATA *container;
	OBJ_DATA *obj;
	OBJ_DATA *obj2;
	OBJ_DATA *obj_next;
	OBJ_DATA *obj_next2;
	ROOM_INDEX_DATA *objroom = get_room_index(ROOM_VNUM_IN_OBJECT);
	
	argument = one_argument( argument, arg1 );
	argument = one_argument( argument, arg2 );
	
	if ( arg1[0] == '\0' || arg2[0] == '\0' )
	{
		send_to_char( "Put what in what?\n\r", ch );
		return;
	}
	
	if ( !str_cmp( arg2, "all" ) || !str_prefix( "all.", arg2 ) )
	{
		send_to_char( "You can't do that.\n\r", ch );
		return;
	}
/* I'll leave this out for now - KaVir
    if ( ( ( container = get_obj_carry( ch, arg2 ) ) == NULL ) &&
         ( ( container = get_obj_wear(  ch, arg2 ) ) == NULL ) &&
	   ( IS_AFFECTED(ch,AFF_ETHEREAL) ) )
    {
	send_to_char( "You can't let go of it!\n\r", ch );
	return;
    }
*/
	if ( ( container = get_obj_here( ch, arg2 ) ) == NULL )
	{
		act( "I see no $T here.", ch, NULL, arg2, TO_CHAR );
		return;
	}
	
	if ( container->item_type != ITEM_CONTAINER )
	{
		send_to_char( "That's not a container.\n\r", ch );
		return;
	}
	
	if ( IS_SET(container->value[1], CONT_CLOSED) )
	{
		act( "The $d is closed.", ch, NULL, container->name, TO_CHAR );
		return;
	}
	
	if ( str_cmp( 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 );
			return;
		}
		
		if ( obj == container )
		{
			send_to_char( "You can't fold it into itself.\n\r", ch );
			return;
		}
		
		if ( obj->item_type == ITEM_FOUNTAIN )
		{
			send_to_char("You can't put that in there!\n\r",ch);
			return;
		}
		
		if (str_cmp(obj->questowner->str,"") && str_cmp(obj->questowner->str,ch->name->str))
		{
			send_to_char("You can't put that in there!\n\r",ch);
			return;
		}
		
		if ( IS_SET( obj->quest, QUEST_ARTIFACT) )
		{
			send_to_char("You cannot put artifacts in a container.\n\r",ch);
			return;
		}
		
		if ( !can_drop_obj( ch, obj ) )
		{
			send_to_char( "You can't let go of it.\n\r", ch );
			return;
		}
		
		if ( get_obj_weight( obj ) + get_obj_weight( container )
			> container->value[0] )
		{
			send_to_char( "It won't fit.\n\r", ch );
			return;
		}
		
		for ( obj2 = container->contains; obj2 != NULL; obj2 = obj_next2 )
		{
			obj_next2 = obj2->next_content;
			if ( obj2->chobj != NULL && obj != obj2)
				act( "A hand reaches inside $P and drops $p.", obj2->chobj, obj, container, TO_CHAR );
		}
		obj_from_char( obj );
		obj_to_obj( obj, container );
		act( "$n puts $p in $P.", ch, obj, container, TO_ROOM );
		act( "You put $p in $P.", ch, obj, container, TO_CHAR );
	}
	else
	{
	/* 'put all container' or 'put all.obj container' */
		for ( obj = ch->carrying; obj != NULL; obj = obj_next )
		{
			obj_next = obj->next_content;
			
			if ( ( arg1[3] == '\0' || is_name( &arg1[4], obj->name->str ) )
				&&   can_see_obj( ch, obj )
				&&   obj->wear_loc == WEAR_NONE
				&&   obj != container
				&&   !IS_SET( obj->quest, QUEST_ARTIFACT)
				&&   can_drop_obj( ch, obj )
				&&   get_obj_weight( obj ) + get_obj_weight( container )
				<= container->value[0] )
			{
				if ( obj->item_type == ITEM_FOUNTAIN )
				{
					continue;
				}
				
				if (str_cmp(obj->questowner->str,"") && str_cmp(obj->questowner->str,ch->name->str))
				{
					continue;
				}
				for ( obj2 = container->contains; obj2 != NULL; obj2 = obj_next2 )
				{
					obj_next2 = obj2->next_content;
					if ( obj2->chobj != NULL && obj2->chobj->in_room != NULL)
					{
						if (objroom != get_room_index(obj2->chobj->in_room->vnum))
						{
							char_from_room(obj2->chobj);
							char_to_room(obj2->chobj,objroom);
							do_look(obj2->chobj,"auto");
						}
						if (obj != obj2)
							act( "A hand reaches inside $P and drops $p.", obj2->chobj, obj, container, TO_CHAR );
					}
				}
				obj_from_char( obj );
				obj_to_obj( obj, container );
				act( "$n puts $p in $P.", ch, obj, container, TO_ROOM );
				act( "You put $p in $P.", ch, obj, container, TO_CHAR );
			}
		}
	}
	do_autosave(ch,"");
	return;
}



void do_drop( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj,*money;
	OBJ_DATA *obj_next;
	bool found;
	
	argument = one_argument( argument, arg );
	
	if ( arg[0] == '\0' )
	{
		send_to_char( "Drop what?\n\r", ch );
		return;
	}
	
	if ( is_number( arg ) )
	{
	/* 'drop NNNN coins' */
		int amount;
		
		amount   = atoi(arg);
		argument = one_argument( argument, arg );
		if ( amount <= 0
			|| ( str_cmp( arg, "coins" ) && str_cmp( arg, "coin" ) ) )
		{
			send_to_char( "Sorry, you can't do that.\n\r", ch );
			return;
		}
		
	/* Otherwise causes complications if there's a pile on each plane */
		
		if ( ch->gold < amount )
		{
			send_to_char( "You haven't got that many coins.\n\r", ch );
			return;
		}
		
		ch->gold -= amount;
		
		for ( obj = ch->in_room->contents; obj != NULL; obj = obj_next )
		{
			obj_next = obj->next_content;
			
			switch ( obj->pIndexData->vnum )
			{
				case OBJ_VNUM_MONEY_ONE:
					amount += 1;
					extract_obj( obj );
					break;
					
				case OBJ_VNUM_MONEY_SOME:
					amount += obj->value[0];
					extract_obj( obj );
					break;
			}
		}
		money = create_money( amount );
		money->plane = ch->plane;
		obj_to_room( money, ch->in_room );
		act( "$n drops some gold.", ch, NULL, NULL, TO_ROOM );
		send_to_char( "OK.\n\r", ch );
		do_autosave(ch,"");
		return;
	}
	
	if ( str_cmp( arg, "all" ) && str_prefix( "all.", arg ) )
	{
	/* 'drop obj' */
		if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
		{
			send_to_char( "You do not have that item.\n\r", ch );
			return;
		}
		
		if ( !can_drop_obj( ch, obj ) )
		{
			send_to_char( "You can't let go of it.\n\r", ch );
			return;
		}
		
		obj->plane = ch->plane;
		obj_from_char( obj );
		obj_to_room( obj, ch->in_room );
	/* Objects should only have a shadowplane flag when on the floor */
		act( "$n drops $p.", ch, obj, NULL, TO_ROOM );
		act( "You drop $p.", ch, obj, NULL, TO_CHAR );
	}
	else
	{
	/* 'drop all' or 'drop all.obj' */
		found = FALSE;
		for ( obj = ch->carrying; obj != NULL; obj = obj_next )
		{
			obj_next = obj->next_content;
			
			if ( ( arg[3] == '\0' || is_name( &arg[4], obj->name->str ) )
				&&   can_see_obj( ch, obj )
				&&   obj->wear_loc == WEAR_NONE
				&&   can_drop_obj( ch, obj ) )
			{
				found = TRUE;
				obj->plane = ch->plane;
				obj_from_char( obj );
				obj_to_room( obj, ch->in_room );
		/* Objects should only have a shadowplane flag when on the floor */
				act( "$n drops $p.", ch, obj, NULL, TO_ROOM );
				act( "You drop $p.", ch, obj, NULL, TO_CHAR );
			}
		}
		
		if ( !found )
		{
			if ( arg[3] == '\0' )
				act( "You are not carrying anything.",
					ch, NULL, arg, TO_CHAR );
			else
				act( "You are not carrying any $T.",
					ch, NULL, &arg[4], TO_CHAR );
		}
	}
	
	do_autosave(ch,"");
	return;
}



void do_give( CHAR_DATA *ch, char *argument )
{
	char arg1 [MAX_INPUT_LENGTH];
	char arg2 [MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	OBJ_DATA  *obj;
	
	argument = one_argument( argument, arg1 );
	argument = one_argument( argument, arg2 );
	
	if ( arg1[0] == '\0' || arg2[0] == '\0' )
	{
		send_to_char( "Give what to whom?\n\r", ch );
		return;
	}
	
	if ( is_number( arg1 ) )
	{
	/* 'give NNNN coins victim' */
		int amount;
		
		amount   = atoi(arg1);
		if ( amount <= 0
			|| ( str_cmp( arg2, "coins" ) && str_cmp( arg2, "coin" ) ) )
		{
			send_to_char( "Sorry, you can't do that.\n\r", ch );
			return;
		}
		
		argument = one_argument( argument, arg2 );
		if ( arg2[0] == '\0' )
		{
			send_to_char( "Give what to whom?\n\r", ch );
			return;
		}
		
		if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
		{
			send_to_char( "They aren't here.\n\r", ch );
			return;
		}
		
		if (ch->plane != victim->plane){
			send_to_char("They are not on this plane.\n\r",ch);
			return;
		}
		
		if ( ch->gold < amount )
		{
			send_to_char( "You haven't got that much gold.\n\r", ch );
			return;
		}
		
		ch->gold     -= amount;
		victim->gold += amount;
		
		/*
 		 * Bribe trigger
	 	 */
		if ( IS_NPC(victim) && HAS_TRIGGER( victim, TRIG_BRIBE ) )
			mp_bribe_trigger( victim, ch, ch->gold ? amount : amount * 100 );
		
		act( "$n gives you some gold.", ch, NULL, victim, TO_VICT    );
		act( "$n gives $N some gold.",  ch, NULL, victim, TO_NOTVICT );
		act( "You give $N some gold.",  ch, NULL, victim, TO_CHAR    );
		send_to_char( "OK.\n\r", ch );
		do_autosave(ch,"");
		do_autosave(victim,"");
		return;
	}
	
	if ( ( obj = get_obj_carry( ch, arg1 ) ) == NULL )
	{
		send_to_char( "You do not have that item.\n\r", ch );
		return;
	}
	
	if ( obj->wear_loc != WEAR_NONE )
	{
		send_to_char( "You must remove it first.\n\r", ch );
		return;
	}
	
	if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
	{
		send_to_char( "They aren't here.\n\r", ch );
		return;
	}
	
	if ( !can_drop_obj( ch, obj ) )
	{
		send_to_char( "You can't let go of it.\n\r", ch );
		return;
	}
	
	if (ch->plane != victim->plane){
		send_to_char("They are not in the same plane.\n\r",ch);
		return;
	}
	
	if ( victim->carry_number + 1 > can_carry_n( victim ) )
	{
		act( "$N has $S hands full.", ch, NULL, victim, TO_CHAR );
		return;
	}
	
	if ( victim->carry_weight + get_obj_weight( obj ) > can_carry_w( victim ) )
	{
		act( "$N can't carry that much weight.", ch, NULL, victim, TO_CHAR );
		return;
	}
	
	if ( !can_see_obj( victim, obj ) )
	{
		act( "$N can't see it.", ch, NULL, victim, TO_CHAR );
		return;
	}
	
	if (IS_ARTIFACT(obj) && !CAN_PK(victim) && !IS_IMMORTAL(victim))
	{
		send_to_char( "You cannot give artifacts to mortals.\n\r", ch );
		return;
	}
	
	obj_from_char( obj );
	obj_to_char( obj, victim );
	MOBtrigger = FALSE;
	act( "$n gives $p to $N.", ch, obj, victim, TO_NOTVICT );
	act( "$n gives you $p.",   ch, obj, victim, TO_VICT    );
	act( "You give $p to $N.", ch, obj, victim, TO_CHAR    );
	MOBtrigger = TRUE;
	/*
	  * Give trigger
	  */
	if ( IS_NPC(victim) && HAS_TRIGGER( victim, TRIG_GIVE ) )
		mp_give_trigger( victim, ch, obj );
	
	do_autosave(ch,"");
	do_autosave(victim,"");
	return;
}




void do_fill( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	OBJ_DATA *fountain;
	bool found;
	int liquid;
	
	one_argument( argument, arg );
	
	if ( arg[0] == '\0' )
	{
		send_to_char( "Fill what?\n\r", ch );
		return;
	}
	
	if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
	{
		send_to_char( "You do not have that item.\n\r", ch );
		return;
	}
	
	found = FALSE;
	for ( fountain = ch->in_room->contents; fountain != NULL;
		fountain = fountain->next_content )
	{
		if ( fountain->item_type == ITEM_FOUNTAIN )
		{
			found = TRUE;
			break;
		}
	}
	
	if ( !found )
	{
		send_to_char( "There is no fountain here!\n\r", ch );
		return;
	}
	
	if (ch->plane != obj->plane){
		send_to_char("Don't think so, your not even on the same plane\n\r",ch);
		return;
	}
	
	if ( obj->item_type != ITEM_DRINK_CON )
	{
		send_to_char( "You can't fill that.\n\r", ch );
		return;
	}
	
	if ( obj->value[1] >= obj->value[0] )
	{
		send_to_char( "Your container is already full.\n\r", ch );
		return;
	}
	
	if ( (obj->value[2] != fountain->value[2]) && obj->value[1] > 0)
	{
		send_to_char( "You cannot mix two different liquids.\n\r", ch );
		return;
	}
	
	act( "$n dips $p into $P.", ch, obj, fountain, TO_ROOM );
	act( "You dip $p into $P.", ch, obj, fountain, TO_CHAR );
	obj->value[2] = fountain->value[2];
	obj->value[1] = obj->value[0];
	liquid = obj->value[2];
	act( "$n fills $p with $T.", ch, obj, liq_table[liquid].liq_name, TO_ROOM );
	act( "You fill $p with $T.", ch, obj, liq_table[liquid].liq_name, TO_CHAR );
	return;
}



void do_drink( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	char buf[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	CHAR_DATA *victim;
	int chance;
	int amount;
	int liquid;
	
	one_argument( argument, arg );
	
	if ( arg[0] == '\0' )
	{
		for ( obj = ch->in_room->contents; obj; obj = obj->next_content )
		{
			if ( obj->item_type == ITEM_FOUNTAIN )
				break;
		}
		
		if ( obj == NULL )
		{
			send_to_char( "Drink what?\n\r", ch );
			return;
		}
	}
	else
	{
		if ( ( obj = get_obj_here( ch, arg ) ) == NULL )
		{
			if ( !IS_CLASS(ch,CLASS_VAMPIRE) )
			{   
				send_to_char( "You can't find it.\n\r", ch );
				return;
			}
			else /* we're trying to drink from a char */
			{
				if ( ( victim = get_char_room( ch, arg ) ) == NULL )
				{
					send_to_char( "You can't find anything or anyone to drink from.\n\r", ch );
					return;
				}
				
				if ( !IS_VAMPAFF(ch,VAM_FANGS) )
				{
					send_to_char("You'd better get your fangs out!\n\r", ch);
					return;
				}
				switch (ch->plane){
					case PLANE_SPIRIT:
						send_to_char("You cannot drink on this plane.\n\e",ch);
						return;	
					case PLANE_PUNISHMENT:
						send_to_char("You cannot drink on this plane.\n\e",ch);
						return;
				}
				if ( is_tempsafe(ch) )
				{
					send_to_char( "You cannot drink in a safe room.\n\r", ch );
					return;
				}
				if (IS_EXTRA(ch,TIED_UP) || IS_EXTRA(ch,BLINDFOLDED))
				{
					send_to_char( "Not while you are tied up or blindfolded!\n\r", ch );
					return;
				}
				if ( !IS_NPC( victim ) && !CAN_PK( victim ) )
				{
					send_to_char( "You can only feed on mobiles and Avatars.\n\r", ch );
					return;
				}
                                if ( victim->level > 95 && ch->level < 10 ) // high level mobs
                                {
                                        send_to_char("You can't drink from them!\n\r", ch);
                                        return;
                                }				
				chance = 60;
				if ( get_disc(ch,DISC_CELERITY) > 0 ) 
					chance += 10;
				if ( get_disc(ch,DISC_DOMINATE) > 0 ) 
					chance += 10;
				if ( get_disc(ch,DISC_OBFUSCATE) > 0 ) 
					chance += 5;
				if ( number_percent() < chance )
				{
                 /* if ( !IS_NPC(victim) && victim->position == POS_MORTAL )
                    {
                        <SET DIABLARIE STUFF>
                    } */
					
					if ( victim->hit < 2000 )
					{
						sprintf( buf, "You can't get enough blood from %s.\n\r", PERS(victim,ch) );  
						send_to_char( buf, ch );
						return;
					}
                                        if ( victim->hit > 200000 )
                                        {
                                                sprintf( buf, "You can't get close enough to %s.\n\r", PERS(victim,ch) );
                                                send_to_char( buf, ch );
                                                return;
                                        }					
					amount = number_range(3, 10);
					if ( amount == 8 && ch->beast != 0 && ch->beast < 100
						&&   number_range(1,500) <= ch->beast)
					{
						ch->beast = UMIN(ch->beast + 1,100);
						if ( ch->beast == 100 )
							send_to_char("You feel your beast take more control over your actions.\n\r", ch);
						else
							send_to_char("Your beast has fully taken over control of your actions!\n\r", ch);
					}
					
					if ( get_disc(ch,DISC_QUIETUS) >= 5 ) 
						amount = amount * 2;
					
					if ( get_disc(victim,DISC_VICISSITUDE) >= 5 )
						amount = -10;     
					
					if ( get_disc(victim,DISC_SERPENTIS) >= 3 )
						amount = -10;     
					
					gain_condition( ch, COND_THIRST, amount * 5 );
					act("You sink your teeth into $S neck and drink.",ch,NULL,victim,TO_CHAR);
					act("$n sinks $s teeth into $N's neck and drinks.",ch,NULL,victim,TO_NOTVICT);
					act("$n sinks $s teeth into your neck and drinks.",ch,NULL,victim,TO_VICT);
					victim->hit -= ( amount * 10 );
					WAIT_STATE( ch, PULSE_VIOLENCE / 2 );
					if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_VAMPIRE) &&
						ch->pcdata->condition[COND_THIRST] >= 100 + ch->pcdata->stats[UNI_BLOOD_MAX] )
						send_to_char( "Your blood thirst is sated.\n\r", ch );
					return;
				}
				else
				{
					multi_hit( ch, victim, TYPE_UNDEFINED );
					return;
				}
			}
		}
	}
	
	if ( !IS_NPC(ch) && ch->pcdata->condition[COND_DRUNK] > 10 )
	{
		send_to_char( "You fail to reach your mouth.  *Hic*\n\r", ch );
		return;
	}
	
	switch (ch->plane){
		case PLANE_SPIRIT:
			send_to_char("You cannot drink on this plane.\n\e",ch);
			return;	
		case PLANE_PUNISHMENT:
			send_to_char("You cannot drink on this plane.\n\e",ch);
			return;
	}

	switch ( obj->item_type )
	{
		default:
			send_to_char( "You can't drink from that.\n\r", ch );
			break;
			
		case ITEM_POTION:
			do_quaff(ch,obj->name->str);
			return;
		case ITEM_FOUNTAIN:
			if ( ( liquid = obj->value[2] ) >= LIQ_MAX )
			{
				bug( "Do_drink: bad liquid number %d.", liquid );
				liquid = obj->value[2] = 0;
			}
			
			if ( liquid != 13 && IS_CLASS(ch,CLASS_VAMPIRE) )
			{
				send_to_char( "You can only drink blood.\n\r", ch );
				break;
			}
			
			act( "$n drinks from $p.", ch, obj, liq_table[liquid].liq_name, TO_ROOM );
			act( "You drink $T from $p.", ch, obj, liq_table[liquid].liq_name, TO_CHAR );
			
			amount = number_range(3, 10);
			amount = UMIN(amount, obj->value[1]);
			
			gain_condition( ch, COND_DRUNK,
				amount * liq_table[liquid].liq_affect[COND_DRUNK  ] );
			gain_condition( ch, COND_THIRST,
				amount * liq_table[liquid].liq_affect[COND_THIRST ] );
			
			if ( !IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE) &&
				ch->pcdata->condition[COND_DRUNK]  > 10 )
				send_to_char( "You feel drunk.\n\r", ch );
			if ( !IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE) &&
				ch->pcdata->condition[COND_FULL]   >= 50 )
				send_to_char( "You are full.\n\r", ch );
			if ( !IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE) &&
				ch->pcdata->condition[COND_THIRST] >= 50 )
				send_to_char( "You do not feel thirsty.\n\r", ch );
			if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_VAMPIRE) &&
				ch->pcdata->condition[COND_THIRST] >= 100 )
				send_to_char( "Your blood thirst is sated.\n\r", ch );
			
			if ( obj->value[3] != 0 && (!IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE)))
			{
	                 /* The shit was poisoned ! */
				AFFECT_DATA af;
				
				act( "$n chokes and gags.", ch, NULL, NULL, TO_ROOM );
				send_to_char( "You choke and gag.\n\r", ch );
				af.type      = gsn_poison;
				af.duration  = 3 * amount;
				af.location  = APPLY_NONE;
				af.modifier  = 0;
				af.bitvector = AFF_POISON;
				affect_join( ch, &af );
			}
			break;
			
		case ITEM_DRINK_CON:
			if ( obj->value[1] <= 0 )
			{
				send_to_char( "It is already empty.\n\r", ch );
				return;
			}
			
			if ( ( liquid = obj->value[2] ) >= LIQ_MAX )
			{
				bug( "Do_drink: bad liquid number %d.", liquid );
				liquid = obj->value[2] = 0;
			}
			
			if ( liquid != 13 && IS_CLASS(ch,CLASS_VAMPIRE) )
			{
				send_to_char( "You can only drink blood.\n\r", ch );
				break;
			}
			
			act( "$n drinks from $p.", ch, obj, NULL, TO_ROOM );
//	act( "$n drinks $T from $p.", ch, obj, liq_table[liquid].liq_name, TO_ROOM );
			act( "You drink $T from $p.",
				ch, obj, liq_table[liquid].liq_name, TO_CHAR );
			
			amount = number_range(3, 10);
			amount = UMIN(amount, obj->value[1]);
			
			gain_condition( ch, COND_DRUNK,
				amount * liq_table[liquid].liq_affect[COND_DRUNK  ] );
			gain_condition( ch, COND_FULL,
				amount * liq_table[liquid].liq_affect[COND_FULL   ] );
			gain_condition( ch, COND_THIRST,
				amount * liq_table[liquid].liq_affect[COND_THIRST ] );
			
			if ( !IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE) &&
				ch->pcdata->condition[COND_DRUNK]  > 10 )
				send_to_char( "You feel drunk.\n\r", ch );
			if ( !IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE) &&
				ch->pcdata->condition[COND_FULL]   >= 50 )
				send_to_char( "You are full.\n\r", ch );
			if ( !IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE) &&
				ch->pcdata->condition[COND_THIRST] >= 50 )
				send_to_char( "You do not feel thirsty.\n\r", ch );
			if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_VAMPIRE) &&
				ch->pcdata->condition[COND_THIRST] >= 100 )
				send_to_char( "Your blood thirst is sated.\n\r", ch );
			
			if ( obj->value[3] != 0 && (!IS_NPC(ch) && !IS_CLASS(ch, CLASS_VAMPIRE)))
			{
	                 /* The shit was poisoned ! */
				AFFECT_DATA af;
				
				act( "$n chokes and gags.", ch, NULL, NULL, TO_ROOM );
				send_to_char( "You choke and gag.\n\r", ch );
				af.type      = gsn_poison;
				af.duration  = 3 * amount;
				af.location  = APPLY_NONE;
				af.modifier  = 0;
				af.bitvector = AFF_POISON;
				affect_join( ch, &af );
			}
			
			obj->value[1] -= amount;
			if ( obj->value[1] <= 0 )
			{
				obj->value[1] = 0;
			}
			break;
	}
	
	return;
}


void do_empty( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	int liquid;
	
	one_argument( argument, arg );
	
	if ( arg[0] == '\0' )
	{
		send_to_char( "Empty what?\n\r", ch );
		return;
	}
	
	if ( ( obj = get_obj_here( ch, arg ) ) == NULL )
	{
		send_to_char( "You can't find it.\n\r", ch );
		return;
	}
	
	if (ch->plane != PLANE_NORMAL){
		send_to_char("Nope, not on this plane.\n\r",ch);
		return;
	}
	
	switch ( obj->item_type )
	{
		default:
			send_to_char( "You cannot empty that.\n\r", ch );
			break;
			
		case ITEM_DRINK_CON:
			if ( obj->value[1] <= 0 )
			{
				send_to_char( "It is already empty.\n\r", ch );
				return;
			}
			
			if ( ( liquid = obj->value[2] ) >= LIQ_MAX )
			{
				bug( "Do_drink: bad liquid number %d.", liquid );
				liquid = obj->value[2] = 0;
			}
			
			act( "$n empties $T from $p.", ch, obj, liq_table[liquid].liq_name, TO_ROOM );
			act( "You empty $T from $p.",
				ch, obj, liq_table[liquid].liq_name, TO_CHAR );
			
			obj->value[1] = 0;
			break;
	}
	
	return;
}



void do_eat( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	int level;
	
	one_argument( argument, arg );
	if ( arg[0] == '\0' )
	{
		send_to_char( "Eat what?\n\r", ch );
		return;
	}
	
	if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
	{
		send_to_char( "You do not have that item.\n\r", ch );
		return;
	}
	
	if ( !IS_IMMORTAL(ch) )
	{
		if ( !IS_NPC(ch) && IS_CLASS(ch, CLASS_VAMPIRE) && obj->item_type == ITEM_FOOD)
		{   
			send_to_char( "You are unable to stomach it.\n\r", ch );
			return;
		}
		
		if ( obj->item_type != ITEM_FOOD && obj->item_type != ITEM_PILL &&
			obj->item_type != ITEM_EGG && obj->item_type != ITEM_QUEST 
			&& obj->item_type != ITEM_COOKIE )
		{
			if (IS_NPC(ch) || !IS_SET(ch->special,SPC_WOLFMAN) || 
				obj->item_type != ITEM_TRASH)
			{
				send_to_char( "That's not edible.\n\r", ch );
				return;
			}
		}
		
		if ( !IS_NPC(ch) && ch->pcdata->condition[COND_FULL] >= 50 &&
			obj->item_type != ITEM_TRASH && obj->item_type != ITEM_QUEST &&
			obj->item_type != ITEM_PILL && obj->item_type != ITEM_COOKIE)
		{
			send_to_char( "You are too full to eat more.\n\r", ch );
			return;
		}
	}
	
	act( "$n eats $p.",  ch, obj, NULL, TO_ROOM );
	act( "You eat $p.", ch, obj, NULL, TO_CHAR );
	
	switch ( obj->item_type )
	{
		default:
			break;
			
		case ITEM_FOOD:
			if ( !IS_NPC(ch) )
			{
				int condition;
				
				condition = ch->pcdata->condition[COND_FULL];
				gain_condition( ch, COND_FULL, obj->value[0] );
				if ( condition == 0 && ch->pcdata->condition[COND_FULL] > 10 )
					send_to_char( "You are no longer hungry.\n\r", ch );
				else if ( ch->pcdata->condition[COND_FULL] >= 50 )
					send_to_char( "You are full.\n\r", ch );
			}
			
			if ( obj->value[3] != 0 )
			{
	                 /* The shit was poisoned! */
				AFFECT_DATA af;
				
				act( "$n chokes and gags.", ch, NULL, NULL, TO_ROOM );
				send_to_char( "You choke and gag.\n\r", ch );
				
				af.type      = gsn_poison;
				af.duration  = 2 * obj->value[0];
				af.location  = APPLY_NONE;
				af.modifier  = 0;
				af.bitvector = AFF_POISON;
				affect_join( ch, &af );
			}
			break;
			
		case ITEM_PILL:
			level = obj->value[0];
			if (level < 1) level = 1;
			if (level > MAX_SPELL) level = MAX_SPELL;
			
			obj_cast_spell( obj->value[1], level, ch, ch, NULL );
			obj_cast_spell( obj->value[2], level, ch, ch, NULL );
			obj_cast_spell( obj->value[3], level, ch, ch, NULL );
			if (ch->position == POS_FIGHTING) 
			{
				if (!IS_IMMORTAL( ch))
					WAIT_STATE(ch, 36 );
			}
			break;
			
		case ITEM_QUEST:
			if ( !IS_NPC(ch) ) ch->pcdata->quest += obj->value[0];
			break;
			
		case ITEM_EGG:
			if ( !IS_NPC(ch) )
			{
				int condition;
				
				condition = ch->pcdata->condition[COND_FULL];
				gain_condition( ch, COND_FULL, obj->value[1] );
				if ( condition == 0 && ch->pcdata->condition[COND_FULL] > 10 )
					send_to_char( "You are no longer hungry.\n\r", ch );
				else if ( ch->pcdata->condition[COND_FULL] >= 50 )
					send_to_char( "You are full.\n\r", ch );
			}
			
	/* Note to myself...remember to set v2 for mobiles that hatch within
	 * the player (like aliens ;).  KaVir.
           - SAY WHAT? rc
	 */
			
			if ( obj->value[3] != 0 )
			{
	                 /* The shit was poisoned! */
				AFFECT_DATA af;
				
				act( "$n chokes and gags.", ch, NULL, NULL, TO_ROOM );
				send_to_char( "You choke and gag.\n\r", ch );
				
				af.type      = gsn_poison;
				af.duration  = 2 * obj->value[0];
				af.location  = APPLY_NONE;
				af.modifier  = 0;
				af.bitvector = AFF_POISON;
				affect_join( ch, &af );
			}
			break;
	}
	
	if (obj != NULL) extract_obj( obj );
	return;
}



/*
 * Remove an object.
 */
bool remove_obj( CHAR_DATA *ch, int iWear, bool fReplace )
{
	OBJ_DATA *obj;
	
	if ( ( obj = get_eq_char( ch, iWear ) ) == NULL )
		return TRUE;
	
	if ( !fReplace )
		return FALSE;
	
	if ( IS_SET(obj->extra_flags, ITEM_NOREMOVE) )
	{
		act( "You can't remove $p.", ch, obj, NULL, TO_CHAR );
		return FALSE;
	}
	
	if (IS_ITEMAFF(ch, ITEMA_RAGER) && ch->fighting != NULL )
	{
		act( "You can't remove $p.", ch, obj, NULL, TO_CHAR );
		return FALSE;
	}
	
	unequip_char( ch, obj );
	act( "$n stops using $p.", ch, obj, NULL, TO_ROOM );
	act( "You stop using $p.", ch, obj, NULL, TO_CHAR );
	return TRUE;
}



/*
 * Wear one object.
 * Optional replacement of existing objects.
 * Big repetitive code, ick.
 */
void wear_obj( CHAR_DATA *ch, OBJ_DATA *obj, bool fReplace )
{
	bool wolf_ok = FALSE;
	  
	if (obj->questowner != NULL && obj->questowner->len > 2 ) 
	{
		if (str_cmp(obj->questowner->str,ch->name->str))
		{
			send_to_char("You can't wear someone elses claimed eq!\n\r",ch);
			return;
		}
	}	

	if (!IS_NPC(ch) && IS_CLASS(ch, CLASS_WEREWOLF) && 
		IS_SET(obj->spectype, SITEM_WOLFWEAPON)) wolf_ok = TRUE;
	
	if ( CAN_WEAR( obj, ITEM_WIELD ) || CAN_WEAR( obj, ITEM_HOLD ) ||
		CAN_WEAR( obj, ITEM_WEAR_SHIELD ))
	{
		if ( get_eq_char( ch, WEAR_WIELD    ) != NULL
			&&   get_eq_char( ch, WEAR_HOLD     ) != NULL
			&&   get_eq_char( ch, WEAR_SHIELD   ) != NULL
			&&   !remove_obj( ch, WEAR_SHIELD, fReplace )
			&&   !remove_obj( ch, WEAR_WIELD , fReplace )
			&&   !remove_obj( ch, WEAR_HOLD  , fReplace ) )
			return;
		if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WIELD))
		{
			send_to_char("You are unable to use it.\n\r",ch);
			return;
		}
		if (get_eq_char( ch, WEAR_WIELD ) == NULL && is_ok_to_wear(ch,wolf_ok,"right_hand"))
		{
			if (IS_SWWF(ch) && ch->pcdata->wwf_shape != SHAPE_HOMID)
            {
                send_to_char("You cannot wield this in this shape.\n\r",ch);
                return;
            }
            act( "$n clutches $p in $s right hand.",    ch, obj, NULL, TO_ROOM );
			act( "You clutch $p in your right hand.",  ch, obj, NULL, TO_CHAR );
			if (obj->item_type == ITEM_WEAPON)
			{
				if ( obj->pIndexData->vnum == 30000 || IS_OBJ_STAT(obj,ITEM_LOYAL))
				{
					if ( obj->questowner->str != NULL && str_cmp(ch->name->str,obj->questowner->str) && obj->questowner->len > 1 )
					{
						act( "$p leaps out of $n's hand.", ch, obj, NULL, TO_ROOM );
						act( "$p leaps out of your hand.", ch, obj, NULL, TO_CHAR );
						obj_from_char(obj);
						obj_to_room(obj,ch->in_room);
						return;
					}
				}
				equip_char( ch, obj, WEAR_WIELD );
				if (!IS_NPC(ch)) do_skillz(ch, ch->name->str);
				return;
			}
			equip_char( ch, obj, WEAR_WIELD );
			return;
		}
		else if (get_eq_char( ch, WEAR_HOLD ) == NULL && is_ok_to_wear(ch,wolf_ok,"left_hand"))
		{
			if (IS_SWWF(ch) && ch->pcdata->wwf_shape != SHAPE_HOMID)
            {
                send_to_char("You cannot wield this in this shape.\n\r",ch);
                return;
            }
            act( "$n clutches $p in $s left hand.",    ch, obj, NULL, TO_ROOM );
			act( "You clutch $p in your left hand.",  ch, obj, NULL, TO_CHAR );
			if (obj->item_type == ITEM_WEAPON)
			{
				if ( obj->pIndexData->vnum == 30000 || IS_OBJ_STAT(obj,ITEM_LOYAL))
				{
					if ( obj->questowner != NULL && str_cmp(ch->name->str,obj->questowner->str) && obj->questowner->len > 1 )
					{
						act( "$p leaps out of $n's hand.", ch, obj, NULL, TO_ROOM );
						act( "$p leaps out of your hand.", ch, obj, NULL, TO_CHAR );
						obj_from_char(obj);
						obj_to_room(obj,ch->in_room);
						return;
					}
				}
				equip_char( ch, obj, WEAR_HOLD );
				if (!IS_NPC(ch)) do_skillz(ch, ch->name->str);
				return;
			}
			equip_char( ch, obj, WEAR_HOLD );
			return;
		}
		if (!is_ok_to_wear(ch,wolf_ok,"left_hand") && !is_ok_to_wear(ch,wolf_ok,"right_hand"))
			send_to_char( "You cannot use anything in your hands.\n\r", ch );
		else
			send_to_char( "You have no free hands.\n\r", ch );
		return;
	}
	
	if ( obj->item_type == ITEM_LIGHT )
	{
		if ( !remove_obj( ch, WEAR_LIGHT, fReplace ) )
			return;
		act( "$n lights $p and uses it.", ch, obj, NULL, TO_ROOM );
		act( "You light $p and use it.",  ch, obj, NULL, TO_CHAR );
		equip_char( ch, obj, WEAR_LIGHT );
		return;
	}
	if ( obj->item_type == ITEM_CONTAINER && IS_SET(ch->extra,EXTRA_HAGS))
	{
		if (!remove_obj(ch,WEAR_HAGS,fReplace))
			return;
	
		equip_char( ch, obj, WEAR_HAGS );
		return;
		
	}
    if ( obj->item_type == ITEM_WWF_CONT )
	{
		if ( !remove_obj( ch, WEAR_HIDDEN, fReplace ) )
			return;
		equip_char( ch, obj, WEAR_HIDDEN );
		return;
	}
	
	if ( CAN_WEAR( obj, ITEM_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 )
			&&   !remove_obj( ch, WEAR_FINGER_R, fReplace ) )
			return;
		if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_FINGER))
		{
			send_to_char("You are unable to wear it.\n\r",ch);
			return;
		}
		
		if ( get_eq_char( ch, WEAR_FINGER_L ) == NULL && is_ok_to_wear(ch,wolf_ok,"left_finger"))
		{
			act( "$n places $p on $s left finger.",    ch, obj, NULL, TO_ROOM );
			act( "You place $p on your left finger.",  ch, obj, NULL, TO_CHAR );
			equip_char( ch, obj, WEAR_FINGER_L );
			return;
		}
		else if ( get_eq_char( ch, WEAR_FINGER_R ) == NULL && is_ok_to_wear(ch,wolf_ok,"right_finger"))
		{
			act( "$n places $p on $s right finger.",   ch, obj, NULL, TO_ROOM );
			act( "You place $p on your right finger.", ch, obj, NULL, TO_CHAR );
			equip_char( ch, obj, WEAR_FINGER_R );
			return;
		}
		if (!is_ok_to_wear(ch,wolf_ok,"left_finger") && !is_ok_to_wear(ch,wolf_ok,"right_finger"))
			send_to_char( "You cannot wear any rings.\n\r", ch );
		else
			send_to_char( "You cannot wear any more rings.\n\r", ch );
		return;
	}
	
	if ( CAN_WEAR( obj, ITEM_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 )
			&&   !remove_obj( ch, WEAR_NECK_2, fReplace ) )
			return;
		if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_NECK))
		{
			send_to_char("You are unable to wear it.\n\r",ch);
			return;
		}
		
		if ( get_eq_char( ch, WEAR_NECK_1 ) == NULL )
		{
			act( "$n slips $p around $s neck.",   ch, obj, NULL, TO_ROOM );
			act( "You slip $p around your neck.", ch, obj, NULL, TO_CHAR );
			equip_char( ch, obj, WEAR_NECK_1 );
			return;
		}
		
		if ( get_eq_char( ch, WEAR_NECK_2 ) == NULL )
		{
			act( "$n slips $p around $s neck.",   ch, obj, NULL, TO_ROOM );
			act( "You slip $p around your neck.", ch, obj, NULL, TO_CHAR );
			equip_char( ch, obj, WEAR_NECK_2 );
			return;
		}
		bug( "Wear_obj: no free neck.", 0 );
		send_to_char( "You are already wearing two things around your neck.\n\r", ch );
		return;
	}
	
	if ( CAN_WEAR( obj, ITEM_WEAR_BODY ) )
	{
		if ( !remove_obj( ch, WEAR_BODY, fReplace ) )
			return;
		
		if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_BODY))
		{
			send_to_char("You are unable to wear it.\n\r",ch);
			return;
		}
		act( "$n fits $p on $s body.",   ch, obj, NULL, TO_ROOM );
		act( "You fit $p on your body.", ch, obj, NULL, TO_CHAR );
		equip_char( ch, obj, WEAR_BODY );
		return;
	}
	
	if ( CAN_WEAR( obj, ITEM_WEAR_HEAD ) )
	{
		if ( !remove_obj( ch, WEAR_HEAD, fReplace ) )
			return;
		if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_HEAD))
		{
			send_to_char("You are unable to wear it.\n\r",ch);
			return;
		}
		if (!is_ok_to_wear(ch,wolf_ok,"head"))
		{
			send_to_char("You have no head to wear it on.\n\r",ch);
			return;
		}
		act( "$n places $p on $s head.",   ch, obj, NULL, TO_ROOM );
		act( "You place $p on your head.", ch, obj, NULL, TO_CHAR );
		equip_char( ch, obj, WEAR_HEAD );
		return;
	}
	
	if ( CAN_WEAR( obj, ITEM_WEAR_FACE ) )
	{
		if ( !remove_obj( ch, WEAR_FACE, fReplace ) )
			return;
		if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_HEAD))
		{
			send_to_char("You are unable to wear it.\n\r",ch);
			return;
		}
                if ( ( obj->quest == QUEST_MASTERY )
                        && (!is_name(ch->name->str, obj->name->str)) )
                {
                        send_to_char("Too bad it's not really yours!\n\r",ch);
                        return;                                 
                }
		if (!is_ok_to_wear(ch,wolf_ok,"face"))
		{
			send_to_char("You have no face to wear it on.\n\r",ch);
			return;
		}
		act( "$n places $p on $s face.",   ch, obj, NULL, TO_ROOM );
		act( "You place $p on your face.", ch, obj, NULL, TO_CHAR );
		equip_char( ch, obj, WEAR_FACE );
		return;
	}
	
	if ( CAN_WEAR( obj, ITEM_WEAR_LEGS ) )
	{
		if ( !remove_obj( ch, WEAR_LEGS, fReplace ) )
			return;
		if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_LEGS))
		{
			send_to_char("You are unable to wear it.\n\r",ch);
			return;
		}
		if (!is_ok_to_wear(ch,wolf_ok,"legs"))
		{
			send_to_char("You have no legs to wear them on.\n\r",ch);
			return;
		}
		act( "$n slips $s legs into $p.",   ch, obj, NULL, TO_ROOM );
		act( "You slip your legs into $p.", ch, obj, NULL, TO_CHAR );
		equip_char( ch, obj, WEAR_LEGS );
		return;
	}
	
	if ( CAN_WEAR( obj, ITEM_WEAR_FEET ) )
	{
		if ( !remove_obj( ch, WEAR_FEET, fReplace ) )
			return;
		if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_FEET))
		{
			send_to_char("You are unable to wear it.\n\r",ch);
			return;
		}
		if (!is_ok_to_wear(ch,wolf_ok,"feet"))
		{
			send_to_char("You have no feet to wear them on.\n\r",ch);
			return;
		}
		act( "$n slips $s feet into $p.",   ch, obj, NULL, TO_ROOM );
		act( "You slip your feet into $p.", ch, obj, NULL, TO_CHAR );
		equip_char( ch, obj, WEAR_FEET );
		return;
	}
	
	if ( CAN_WEAR( obj, ITEM_WEAR_HANDS ) )
	{
		if ( !remove_obj( ch, WEAR_HANDS, fReplace ) )
			return;
		if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_HANDS))
		{
			send_to_char("You are unable to wear it.\n\r",ch);
			return;
		}
		if (!is_ok_to_wear(ch,wolf_ok,"hands"))
		{
			send_to_char("You have no hands to wear them on.\n\r",ch);
			return;
		}
		act( "$n pulls $p onto $s hands.",   ch, obj, NULL, TO_ROOM );
		act( "You pull $p onto your hands.", ch, obj, NULL, TO_CHAR );
		equip_char( ch, obj, WEAR_HANDS );
		return;
	}
	
	if ( CAN_WEAR( obj, ITEM_WEAR_ARMS ) )
	{
		if ( !remove_obj( ch, WEAR_ARMS, fReplace ) )
			return;
		if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_ARMS))
		{
			send_to_char("You are unable to wear it.\n\r",ch);
			return;
		}
		if (!is_ok_to_wear(ch,wolf_ok,"arms"))
		{
			send_to_char("You have no arms to wear them on.\n\r",ch);
			return;
		}
		act( "$n slides $s arms into $p.",   ch, obj, NULL, TO_ROOM );
		act( "You slide your arms into $p.", ch, obj, NULL, TO_CHAR );
		equip_char( ch, obj, WEAR_ARMS );
		return;
	}
	
	if ( CAN_WEAR( obj, ITEM_WEAR_ABOUT ) )
	{
		if ( !remove_obj( ch, WEAR_ABOUT, fReplace ) )
			return;
		if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_ABOUT))
		{
			send_to_char("You are unable to wear it.\n\r",ch);
			return;
		}
		act( "$n pulls $p about $s body.",   ch, obj, NULL, TO_ROOM );
		act( "You pull $p about your body.", ch, obj, NULL, TO_CHAR );
		equip_char( ch, obj, WEAR_ABOUT );
		return;
	}
	
	if ( CAN_WEAR( obj, ITEM_WEAR_WAIST ) )
	{
		if ( !remove_obj( ch, WEAR_WAIST, fReplace ) )
			return;
		if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_WAIST))
		{
			send_to_char("You are unable to wear it.\n\r",ch);
			return;
		}
		act( "$n ties $p around $s waist.",   ch, obj, NULL, TO_ROOM );
		act( "You tie $p around your waist.", ch, obj, NULL, TO_CHAR );
		equip_char( ch, obj, WEAR_WAIST );
		return;
	}
	
	if ( CAN_WEAR( obj, ITEM_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 )
			&&   !remove_obj( ch, WEAR_WRIST_R, fReplace ) )
			return;
		if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_WRIST))
		{
			send_to_char("You are unable to wear it.\n\r",ch);
			return;
		}
		
		if ( get_eq_char( ch, WEAR_WRIST_L ) == NULL && is_ok_to_wear(ch,wolf_ok,"right_wrist"))
		{
			act( "$n slides $s left wrist into $p.",
				ch, obj, NULL, TO_ROOM );
			act( "You slide your left wrist into $p.",
				ch, obj, NULL, TO_CHAR );
			equip_char( ch, obj, WEAR_WRIST_L );
			return;
		}
		else if ( get_eq_char( ch, WEAR_WRIST_R ) == NULL && is_ok_to_wear(ch,wolf_ok,"left_wrist"))
		{
			act( "$n slides $s left wrist into $p.",
				ch, obj, NULL, TO_ROOM );
			act( "You slide your right wrist into $p.",
				ch, obj, NULL, TO_CHAR );
			equip_char( ch, obj, WEAR_WRIST_R );
			return;
		}
		if (!is_ok_to_wear(ch,wolf_ok,"left_wrist") && !is_ok_to_wear(ch,wolf_ok,"right_wrist"))
			send_to_char( "You cannot wear anything on your wrists.\n\r", ch );
		else
			send_to_char( "You cannot wear any more on your wrists.\n\r", ch );
		return;
	}
	
	if ( CAN_WEAR( obj, ITEM_WEAR_SHIELD ) )
	{
		if ( !remove_obj( ch, WEAR_SHIELD, fReplace ) )
			return;
		if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WEAR_SHIELD))
		{
			send_to_char("You are unable to wear it.\n\r",ch);
			return;
		}
		act( "$n straps $p onto $s shield arm.", ch, obj, NULL, TO_ROOM );
		act( "You strap $p onto your shield arm.", ch, obj, NULL, TO_CHAR );
		equip_char( ch, obj, WEAR_SHIELD );
		return;
	}
	
	if ( CAN_WEAR( obj, ITEM_WIELD ) )
	{
		if ( !remove_obj( ch, WEAR_WIELD, fReplace ) )
			return;
		if (!IS_NPC(ch) && !IS_FORM(ch,ITEM_WIELD))
		{
			send_to_char("You are unable to wield it.\n\r",ch);
			return;
		}
		
		if ( get_obj_weight( obj ) > str_app[get_curr_str(ch)].wield )
		{
			send_to_char( "It is too heavy for you to wield.\n\r", ch );
			return;
		}
		
		act( "$n wields $p.", ch, obj, NULL, TO_ROOM );
		act( "You wield $p.", ch, obj, NULL, TO_CHAR );
		
		if ( obj->pIndexData->vnum == 30000 || IS_OBJ_STAT(obj,ITEM_LOYAL))
		{
			if ( obj->questowner != NULL && str_cmp(ch->name->str,obj->questowner->str) && obj->questowner->len > 1 )
			{
				act( "$p leaps out of $n's hand.", ch, obj, NULL, TO_ROOM );
				act( "$p leaps out of your hand.", ch, obj, NULL, TO_CHAR );
				obj_from_char(obj);
				obj_to_room(obj,ch->in_room);
				return;
			}
		}
		equip_char( ch, obj, WEAR_WIELD );
		if (!IS_NPC(ch)) do_skillz(ch, ch->name->str);
		return;
	}
	
	if ( fReplace )
		send_to_char( "You can't wear, wield or hold that.\n\r", ch );
	
	return;
}



void do_wear( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	
	one_argument( argument, arg );
	
	if (IS_AFFECTED(ch,AFF_POLYMORPH) && !IS_NPC(ch) && 
		!IS_VAMPAFF(ch,VAM_DISGUISED) && !IS_CLASS(ch, CLASS_WEREWOLF))
	{
		send_to_char( "You cannot wear anything in this form.\n\r", ch );
		return;
	}
	
	if ( arg[0] == '\0' )
	{
		send_to_char( "Wear, wield, or hold what?\n\r", ch );
		return;
	}
	
	if (IS_NPC(ch) && IS_SET(ch->act,ACT_ANIMAL))
	{
		return;
	}

	if (IS_SWWF(ch) && (ch->pcdata->wwf_shape == SHAPE_CRINOS 
		|| ch->pcdata->wwf_shape == SHAPE_HISPO
        || ch->pcdata->wwf_shape == SHAPE_LUPUS))
	{
		send_to_char("Not in that form!\n\r",ch);
		return;
	}
	
    if ( !str_cmp( arg, "all" ) )
	{
		OBJ_DATA *obj_next;
		
		for ( obj = ch->carrying; obj != NULL; obj = obj_next )
		{
			obj_next = obj->next_content;
			if ( obj->wear_loc == WEAR_NONE && can_see_obj( ch, obj ) && obj->item_type != ITEM_WWF_CONT)
				wear_obj( ch, obj, FALSE );
		}
		return;
	}
	else
	{
		if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
		{
			send_to_char( "You do not have that item.\n\r", ch );
			return;
		}
		if (obj->item_type == ITEM_WWF_CONT)
			return;
		
		wear_obj( ch, obj, TRUE );
	}
	
	return;
}



void do_remove( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	
	one_argument( argument, arg );
	
	if ( arg[0] == '\0' )
	{
		send_to_char( "Remove what?\n\r", ch );
		return;
	}
	
	if ( !str_cmp( arg, "all" ) )
	{
		OBJ_DATA *obj_next;
		
		for ( obj = ch->carrying; obj != NULL; obj = obj_next )
		{
			obj_next = obj->next_content;
			if ( obj->item_type != ITEM_WWF_CONT && obj->wear_loc != WEAR_NONE && can_see_obj( ch, obj ) )
				remove_obj( ch, obj->wear_loc, TRUE );
		}
		return;
	}
	if ( ( obj = get_obj_wear( ch, arg ) ) == NULL )
	{
		send_to_char( "You do not have that item.\n\r", ch );
		return;
	}
	if (obj->item_type == ITEM_WWF_CONT)
		return;
	
	remove_obj( ch, obj->wear_loc, TRUE );
	return;
}



void do_sacrifice( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	char buf[MAX_INPUT_LENGTH];
	char log_buf[MAX_INPUT_LENGTH];
	int expgain;
	
	one_argument( argument, arg );
	
	if ( arg[0] == '\0' )
	{
		send_to_char("Sacrifice what?\n\r",ch);
		return;
	}
	
	obj = get_obj_list( ch, arg, ch->in_room->contents );
	if ( obj == NULL )
	{
		send_to_char( "You can't find it.\n\r", ch );
		return;
	}

	if (obj->in_room == NULL)  /* destroy it */
	{
		extract_obj(obj);
		return;
	}

	if (obj->points > 3999 && !IS_IMMORTAL(ch))
	{	
		send_to_char("You can't sacrifice mythical equipment.\n\r",ch);
		return;	
	}
	
	if ( obj->item_type == ITEM_CORPSE_NPC )
	{
		OBJ_DATA *t_obj, *next_obj;
		
		if (IS_SET(mudsetting->mud_setting,MS_LIVING_DEAD))
			return;
		
		for (t_obj = obj->contains; t_obj != NULL; t_obj = next_obj)
		{
			next_obj = t_obj->next_content;
			obj_from_obj(t_obj);
			
			if (IS_SET(t_obj->quest, QUEST_ARTIFACT) || t_obj->points > 100 )
				obj_to_room(t_obj,obj->in_room);
			else
				extract_obj(t_obj);
		}
	}
	
	
	if ( !CAN_WEAR(obj, ITEM_TAKE) || obj->item_type == ITEM_QUEST 
		|| obj->item_type == ITEM_MONEY 
		|| obj->item_type == ITEM_TREASURE 
		|| obj->item_type == ITEM_QUESTCARD 
		|| IS_SET(obj->quest, QUEST_ARTIFACT) 
		|| ( ( obj->questowner != NULL && !IS_IMMORTAL(ch))  
		&& obj->questowner->len > 1 && (str_cmp(ch->name->str,obj->questowner->str) 
		&& obj->item_type != ITEM_CORPSE_NPC)))
	{
		act( "You are unable to drain any energy from $p.", ch, obj, 0, TO_CHAR );
		return;
	}
	else if (obj->chobj != NULL && !IS_NPC(obj->chobj) &&
		obj->chobj->pcdata->obj_vnum != 0)
	{
		act( "You are unable to drain any energy from $p.", ch, obj, 0, TO_CHAR );
		return;
	}
	expgain = obj->cost / 100;
	if (expgain < 1)
		expgain = 1;
	if (expgain > 50)
		expgain = 50;
	ch->exp += expgain;
	sprintf( buf,"You drain %d exp of energy from $p.", expgain );
	act( buf, ch, obj, NULL, TO_CHAR );
	act( "$p disintegrates into a fine powder.", ch, obj, NULL, TO_CHAR );
	act( "$n drains the energy from $p.", ch, obj, NULL, TO_ROOM );
	act( "$p disintegrates into a fine powder.", ch, obj, NULL, TO_ROOM );
	if (obj->points > 0 && !IS_NPC(ch) && obj->item_type != ITEM_PAGE)
	{
		sprintf( buf, "You receive a refund of %d quest points from $p.", obj->points);
		act( buf, ch, obj, NULL, TO_CHAR );
		ch->pcdata->quest += obj->points;
	}
	sprintf(log_buf,"%s sacrificed %s.\n\r",ch->name->str,obj->short_descr->str);
	if (obj->pIndexData->vnum != OBJ_VNUM_CORPSE_NPC)
		logchan(log_buf,NULL,NULL,WIZ_SACCING,0,LEVEL_IMMORTAL);
	extract_obj( obj );
	return;
}



void do_quaff( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	int level;
	
	one_argument( argument, arg );
	
	if ( arg[0] == '\0' )
	{
		send_to_char( "Quaff what?\n\r", ch );
		return;
	}
	
	if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
	{
		send_to_char( "You do not have that potion.\n\r", ch );
		return;
	}
	
	if ( obj->item_type != ITEM_POTION )
	{
		send_to_char( "You can quaff only potions.\n\r", ch );
		return;
	}
	
	act( "$n quaffs $p.", ch, obj, NULL, TO_ROOM );
	act( "You quaff $p.", ch, obj, NULL ,TO_CHAR );
	
	level = obj->value[0];
	if (level < 1) level = 1;
	if (level > MAX_SPELL) level = MAX_SPELL;
	
	obj_cast_spell( obj->value[1], level, ch, ch, NULL );
	obj_cast_spell( obj->value[2], level, ch, ch, NULL );
	obj_cast_spell( obj->value[3], level, ch, ch, NULL );
	
	extract_obj( obj );
	if (ch->position == POS_FIGHTING) 
	{
		if (!IS_IMMORTAL( ch))
			WAIT_STATE(ch, 6 );
	}
	return;
}



void do_recite( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	OBJ_DATA *scroll;
	OBJ_DATA *obj;
	int level;
        victim = NULL;
	
	argument = one_argument( argument, arg1 );
	argument = one_argument( argument, arg2 );
	
	if ( ch->position == POS_FIGHTING )
	{
		send_to_char("You lose your concentration while fighting.\n\r",ch);
		return;
	}

	if ( ( scroll = get_obj_carry( ch, arg1 ) ) == NULL )
	{
		send_to_char( "You do not have that scroll.\n\r", ch );
		return;
	}
	
	if ( scroll->item_type != ITEM_SCROLL )
	{
		send_to_char( "You can recite only scrolls.\n\r", ch );
		return;
	}
	
	obj = NULL;
	if ( arg2[0] == '\0' )
	{
		victim = ch;
	}
	else
	{
		if ( ( victim = get_char_room ( ch, arg2 ) ) == NULL
			&&   ( obj    = get_obj_here  ( ch, arg2 ) ) == NULL )
		{
			send_to_char( "You can't find it.\n\r", ch );
			return;
		}
	}
	
	if (victim != NULL)
	{
       if (!IS_NPC(victim) && (!CAN_PK(ch) || !CAN_PK(victim)) && (ch != victim))
       {
                send_to_char( "You are unable to affect them.\n\r", ch );
                return;
       }
       /* You cannot attack across planes */
       if (ch->plane != victim->plane){
	       send_to_char("Your going to attack who?\n\r",ch);
                return;
        }
	if (check_pk(ch,victim,CHECK_DELAY|CHECK_ATTACK))
		return;
	}
	act( "$n recites $p.", ch, scroll, NULL, TO_ROOM );
	act( "You recite $p.", ch, scroll, NULL, TO_CHAR );
	
	level = scroll->value[0];
	if (level < 1) level = 1;
	if (level > MAX_SPELL) level = MAX_SPELL;
	
	obj_cast_spell( scroll->value[1], level, ch, victim, obj );
	obj_cast_spell( scroll->value[2], level, ch, victim, obj );
	obj_cast_spell( scroll->value[3], level, ch, victim, obj );
	
	extract_obj( scroll );
	if (ch->position == POS_FIGHTING) 
	{
		WAIT_STATE(ch,PULSE_VIOLENCE * 2);
	}
	return;
}



void do_brandish( CHAR_DATA *ch, char *argument )
{
	CHAR_DATA *vch;
	CHAR_DATA *vch_next;
	OBJ_DATA *temp;
	OBJ_DATA *staff;
	int sn;
	int level;
        vch = NULL;

        if (HAS_DELAY(ch))
        {
                send_to_char( "Not with a wait timer...\n\r", ch );
                return;
        }
	
	staff = get_eq_char( ch, WEAR_WIELD );
	temp = get_eq_char( ch, WEAR_HOLD );
	
	if ( staff == NULL && temp == NULL )
	{
		send_to_char( "You hold nothing in your hand.\n\r", ch );
		return;
	}
	
	if ( staff == NULL ) staff = temp;
	if ( temp == NULL  ) temp = staff;
	
	if ( staff->item_type != ITEM_STAFF ) staff=temp;
	
	if ( staff->item_type != ITEM_STAFF )
	{
		send_to_char( "You can brandish only with a staff.\n\r", ch );
		return;
	}
	
	if ( ( sn = staff->value[3] ) < 0
		||   sn >= MAX_SKILL
		||   skill_table[sn].spell_fun == 0 )
	{
		bug( "Do_brandish: bad sn %d.", sn );
		return;
	}
	
	if (!IS_IMMORTAL( ch))
		WAIT_STATE( ch, 2 * PULSE_VIOLENCE );

	if ( staff->value[2] > 0 )
	{
		act( "$n brandishes $p.", ch, staff, NULL, TO_ROOM );
		act( "You brandish $p.",  ch, staff, NULL, TO_CHAR );
		for ( vch = ch->in_room->people; vch; vch = vch_next )
		{
			vch_next	= vch->next_in_room;
			
			if (check_pk(ch,vch,CHECK_DELAY|CHECK_ATTACK))
				return;

			switch ( skill_table[sn].target )
			{
				default:
					bug( "Do_brandish: bad target for sn %d.", sn );
					return;
					
				case TAR_IGNORE:
					if ( vch != ch )
						continue;
					break;
					
				case TAR_CHAR_OFFENSIVE:
					if (ch->plane != vch->plane){
						send_to_char("Your going to attack who?\n\r",ch);
						return;
					}
					if ( IS_NPC(ch) ? IS_NPC(vch) : !IS_NPC(vch) )
						continue;
       if (!IS_NPC(vch) && (!CAN_PK(ch) || !CAN_PK(vch)) && (ch != vch))
       {
                send_to_char( "You are unable to affect them.\n\r", ch );
                return;
       }
	
					break;
					
				case TAR_CHAR_DEFENSIVE:
					if (ch->plane != vch->plane){
						send_to_char("Your going to do what to who?\n\r",ch);
						return;
					}
					if ( IS_NPC(ch) ? !IS_NPC(vch) : IS_NPC(vch) )
						continue;
					break;
					
				case TAR_CHAR_SELF:
					if ( vch != ch )
						continue;
					break;
			}
			
			level = staff->value[0];
			if (level < 1) level = 1;
			if (level > MAX_SPELL) level = MAX_SPELL;
			
			obj_cast_spell( staff->value[3], level, ch, vch, NULL );
		}
	}
	
	if ( --staff->value[2] <= 0 )
	{
		act( "$n's $p blazes bright and is gone.", ch, staff, NULL, TO_ROOM );
		act( "Your $p blazes bright and is gone.", ch, staff, NULL, TO_CHAR );
		extract_obj( staff );
	}
	
	return;
}



void do_zap( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	OBJ_DATA *temp;
	OBJ_DATA *wand;
	OBJ_DATA *obj;
	int level;
        victim = NULL;
	
	one_argument( argument, arg );
	if ( arg[0] == '\0' && ch->fighting == NULL )
	{
		send_to_char( "Zap whom or what?\n\r", ch );
		return;
	}

        if (HAS_DELAY(ch))
        {
                send_to_char( "Not with a wait timer...\n\r", ch );
                return;
        }
	
	wand = get_eq_char( ch, WEAR_WIELD );
	temp = get_eq_char( ch, WEAR_HOLD );
	
	if ( wand == NULL && temp == NULL )
	{
		send_to_char( "You hold nothing in your hand.\n\r", ch );
		return;
	}
	
	if ( wand == NULL ) wand = temp;
	if ( temp == NULL ) temp = wand;
	
	if ( wand->item_type != ITEM_WAND ) wand=temp;
	
	if ( wand->item_type != ITEM_WAND )
	{
		send_to_char( "You can zap only with a wand.\n\r", ch );
		return;
	}
	
	obj = NULL;
	if ( arg[0] == '\0' )
	{
		if ( ch->fighting != NULL )
		{
			victim = ch->fighting;
		}
		else
		{
			send_to_char( "Zap whom or what?\n\r", ch );
			return;
		}
	}
	else
	{
		if ( ( victim = get_char_room ( ch, arg ) ) == NULL
			&&   ( obj    = get_obj_here  ( ch, arg ) ) == NULL )
		{
			send_to_char( "You can't find it.\n\r", ch );
			return;
		}
	}

       if (!IS_NPC(victim) && (!CAN_PK(ch) || !CAN_PK(victim)) && (ch != victim))
       {
                send_to_char( "You are unable to affect them.\n\r", ch );
                return;
       }

       if (ch->plane != victim->plane){
	       send_to_char("They are not on this plane.\n\r",ch);
                return;
       }
	
	if (!IS_IMMORTAL( ch))
		WAIT_STATE( ch, 2 * PULSE_VIOLENCE );
	
	if ( wand->value[2] > 0 )
	{
		if ( victim != NULL )
		{
			act( "$n zaps $N with $p.", ch, wand, victim, TO_ROOM );
			act( "You zap $N with $p.", ch, wand, victim, TO_CHAR );
		}
		else
		{
			if (victim != NULL && check_pk(ch,victim,CHECK_DELAY|CHECK_ATTACK))
				return;
			act( "$n zaps $P with $p.", ch, wand, obj, TO_ROOM );
			act( "You zap $P with $p.", ch, wand, obj, TO_CHAR );
		}
		
		level = wand->value[0];
		if (level < 1) level = 1;
		if (level > MAX_SPELL) level = MAX_SPELL;
		
		obj_cast_spell( wand->value[3], level, ch, victim, obj );
	}
	
	if ( --wand->value[2] <= 0 )
	{
		act( "$n's $p explodes into fragments.", ch, wand, NULL, TO_ROOM );
		act( "Your $p explodes into fragments.", ch, wand, NULL, TO_CHAR );
		extract_obj( wand );
	}
	
	return;
}



void do_steal( CHAR_DATA *ch, char *argument )
{
	char buf  [MAX_STRING_LENGTH];
	char arg1 [MAX_INPUT_LENGTH];
	char arg2 [MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	OBJ_DATA *obj;
	int percent;
        victim = NULL;

        if (HAS_DELAY(ch))
        {
                send_to_char( "Not with a wait timer...\n\r", ch );
                return;
        }

	argument = one_argument( argument, arg1 );
	argument = one_argument( argument, arg2 );
	
	if ( arg1[0] == '\0' || arg2[0] == '\0' )
	{
		send_to_char( "Steal what from whom?\n\r", ch );
		return;
	}
	
	if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
	{
		send_to_char( "They aren't here.\n\r", ch );
		return;
	}

	if (is_safe(ch,victim))
	{
		send_to_char("Not here.\n\r",ch);
		return;
	}


	if (ch->plane != victim->plane){
		send_to_char("They are not on this plane.\n\r",ch);
		return;
	}

	
	if ( ch->level < 3 )
	{
		send_to_char( "That's pointless.\n\r", ch );
		return;
	}
	
	if ( victim->level < 3 )
	{
		send_to_char( "That's pointless.\n\r", ch );
		return;
	}
	
	if ( victim == ch )
	{
		send_to_char( "That's pointless.\n\r", ch );
		return;
	}
	
	if ( IS_IMMORTAL( victim ))
	{
		send_to_char("Steal from an immortal, are you crazy?!\n\r", ch);
		return;
	}

	if (check_pk(ch,victim,CHECK_DELAY|CHECK_ATTACK))
		return;
	
	if (!IS_IMMORTAL( ch))
		WAIT_STATE( ch, skill_table[gsn_steal].beats );
	
	percent  = number_percent( ) + ( IS_AWAKE(victim) ? 10 : -50 );
	
	if (IS_IMMFLAW(ch,IMM_FLAW_STEAL))
		percent += 100;

	if ( ( ch->level + number_range(1,20) < victim->level          )
		||   ( !IS_NPC(ch) && !IS_NPC(victim) && ch->level < 3         )
		||   ( !IS_NPC(ch) && !IS_NPC(victim) && victim->level < 3     )
		||   ( victim->position == POS_FIGHTING                        )
		||   ( !IS_NPC(victim) && IS_IMMMERIT(victim,IMM_MERIT_STEAL)    )
		||   ( !IS_NPC(victim) && IS_IMMORTAL(victim)                  )
		||   ( !IS_NPC(ch) && percent > ch->pcdata->learned[gsn_steal] ) )
	{
	/*
	 * Failure.
	 */
		send_to_char( "Oops.\n\r", ch );
		act( "$n tried to steal from you.\n\r", ch, NULL, victim, TO_VICT    );
		act( "$n tried to steal from $N.\n\r",  ch, NULL, victim, TO_NOTVICT );
		sprintf( buf, "%s is a bloody thief!", ch->name->str );
		do_shout( victim, buf );
		if ( !IS_NPC(ch) )
		{
			if ( IS_NPC(victim) )
			{
				multi_hit( victim, ch, TYPE_UNDEFINED );
			}
			else
			{
				log_string2( buf );
				logchan(log_buf, NULL, NULL,WIZ_GENERAL,0, LEVEL_QUESTMAKER);
				save_char_obj( ch );
			}
		}
		
		return;
	}
	
	if ( !str_cmp( arg1, "coin"  )
		||   !str_cmp( arg1, "coins" )
		||   !str_cmp( arg1, "gold"  ) )
	{
		int amount;
		
		amount = victim->gold * number_range(1, 10) / 100;
		if ( amount <= 0 )
		{
			send_to_char( "You couldn't get any gold.\n\r", ch );
			return;
		}
		
		ch->gold     += amount;
		victim->gold -= amount;
		sprintf( buf, "Bingo!  You got %d gold coins.\n\r", amount );
		send_to_char( buf, ch );
		do_autosave(ch,"");
		do_autosave(victim,"");
		return;
	}
	
	if ( ( obj = get_obj_carry( victim, arg1 ) ) == NULL )
	{
		send_to_char( "You can't find it.\n\r", ch );
		return;
	}
	
	if ( !can_drop_obj( ch, obj )
		||   IS_SET(obj->extra_flags, ITEM_LOYAL)
		||   IS_SET(obj->extra_flags, ITEM_INVENTORY) )
	{
		send_to_char( "You can't pry it away.\n\r", ch );
		return;
	}
	
	if ( ch->carry_number + 1 > can_carry_n( ch ) )
	{
		send_to_char( "You have your hands full.\n\r", ch );
		return;
	}
	
	if ( ch->carry_weight + get_obj_weight( obj ) > can_carry_w( ch ) )
	{
		send_to_char( "You can't carry that much weight.\n\r", ch );
		return;
	}
	
	obj_from_char( obj );
	obj_to_char( obj, ch );
	send_to_char( "You got it!\n\r", ch );
	do_autosave(ch,"");
	do_autosave(victim,"");
	return;
}



/*
 * Shopping commands.
 */
CHAR_DATA *find_keeper( CHAR_DATA *ch )
{
	CHAR_DATA *keeper;
	SHOP_DATA *pShop;
	char buf [MAX_STRING_LENGTH];
	
	pShop = NULL;
	for ( keeper = ch->in_room->people; keeper; keeper = keeper->next_in_room )
	{
		if ( IS_NPC(keeper) && (pShop = keeper->pIndexData->pShop) != NULL )
			break;
	}
	
	if ( pShop == NULL )
	{
		send_to_char( "You can't do that here.\n\r", ch );
		return NULL;
	}
	
    /*
     * Shop hours.
     */
	if ( time_info.hour < pShop->open_hour )
	{
		str_cpy( buf, "Sorry, come back later." );
		do_say( keeper, buf );
		return NULL;
	}
	
	if ( time_info.hour > pShop->close_hour )
	{
		str_cpy( buf, "Sorry, come back tomorrow." );
		do_say( keeper, buf );
		return NULL;
	}
	
    /*
     * Invisible or hidden people.
     */
	if ( !can_see( keeper, ch ) )
	{
		str_cpy( buf, "I don't trade with folks I can't see." );
		do_say( keeper, buf );
		return NULL;
	}
	
	return keeper;
}



int get_cost( CHAR_DATA *keeper, OBJ_DATA *obj, bool fBuy )
{
	SHOP_DATA *pShop;
	int cost;
	
	if ( obj == NULL || ( pShop = keeper->pIndexData->pShop ) == NULL )
		return 0;
	
	if ( fBuy )
	{
		if (obj->item_type == ITEM_FOOD)
			cost = (obj->value[0] * pShop->profit_buy  / 500) + 1;
		else
			cost = (obj->level * pShop->profit_buy  / 100) + 1;
	}
	else
	{
		OBJ_DATA *obj2;
		int itype;
		
		cost = 0;
		for ( itype = 0; itype < MAX_TRADE; itype++ )
		{
			if ( obj->item_type == pShop->buy_type[itype] )
			{
				if (obj->item_type == ITEM_FOOD)
					cost = (obj->value[0] * pShop->profit_sell  / 500) + 1;
				else
					cost = (obj->level * pShop->profit_sell / 100) + 1;
				break;
			}
		}
		
		for ( obj2 = keeper->carrying; obj2; obj2 = obj2->next_content )
		{
			if ( obj->pIndexData == obj2->pIndexData )
			{
				cost = 0;
				break;
			}
		}
	}
	
	if ( obj->item_type == ITEM_STAFF || obj->item_type == ITEM_WAND )
		cost = cost * obj->value[2] / obj->value[1];
	
	return cost;
}



void do_buy( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	
	argument = one_argument( argument, arg );
	
	if ( arg[0] == '\0' )
	{
		send_to_char( "Buy what?\n\r", ch );
		return;
	}
	
	if ( IS_SET(ch->in_room->room_flags, ROOM_PET_SHOP) )
	{
		char buf[MAX_STRING_LENGTH];
		CHAR_DATA *pet;
		int pChoise = 0,pVnum = 0;

		if ( IS_NPC(ch) )
			return;
		
        if (!IS_IMMORTAL(ch))
        {
            send_to_char("Pets are not finished yet! get outta here!\n\r",ch);
            return;
        }

		if (!str_cmp(arg,"dog"))
        {
            pChoise = PET_TYPE_DOG;
            pVnum = MOB_VNUM_PET_DOG;
        }
        
        if (!str_cmp(arg,"cat"))
        {
            pChoise = PET_TYPE_CAT;
            pVnum = MOB_VNUM_PET_CAT;
        }

        if (!str_cmp(arg,"lion"))
        {
            pChoise = PET_TYPE_LION;
            pVnum = MOB_VNUM_PET_LION;
        }

        if (pChoise == 0)
        {
        	send_to_char( "Sorry, you can't buy that here.\n\r", ch );
			return;
        }
        
        if (get_mob_index(pVnum) == NULL)
            return;
        
        pet         = create_mobile(get_mob_index(pVnum));
		
        if ( pet == NULL )
		{
			send_to_char( "Sorry, you can't buy that here.\n\r", ch );
			return;
		}

		        
		if ( ch->gold < 100 )
		{
			send_to_char( "You can't afford it.\n\r", ch );
			return;
		}
		
		ch->gold		-= 100;
		
        SET_BIT(pet->mob_con, MOBCON_PET);
		
        pet->pet_stats[PET_HUNGER] = 100;
        pet->pet_stats[PET_THIRST] = 100;
        pet->pet_stats[PET_AFFECTION] = 100;
        pet->pet_stats[PET_BEHAVIOR] = 0;
        pet->pet_stats[PET_PERM_AFF] = 35;
        pet->pet_stats[PET_TYPE] = pChoise;

        ch->pet = pet;
	    pet->pet_master = ch;

		argument = one_argument( argument, arg );
		
        sprintf( buf, "%s %s", pet->name->str, arg );
		pet->name = g_string_assign(pet->name,buf);
		
		sprintf( buf, "%sA neck tag says 'I belong to %s'.\n\r",
			pet->description->str, ch->name->str );
		
        pet->description = g_string_assign(pet->description,buf);
        
		char_to_room( pet, ch->in_room );
		add_follower( pet, ch );
		send_to_char( "Enjoy your pet.\n\r", ch );
		act( "$n bought $N as a pet.", ch, NULL, pet, TO_ROOM );
		return;
	}
	else
	{
		CHAR_DATA *keeper;
		OBJ_DATA *obj;
		int cost;
		
		if ( ( keeper = find_keeper( ch ) ) == NULL )
			return;
		
		obj  = get_obj_carry( keeper, arg );
		cost = get_cost( keeper, obj, TRUE );
		
		if ( cost <= 0 || !can_see_obj( ch, obj ) )
		{
			act( "$n tells you 'I don't sell that -- try 'list''.",
				keeper, NULL, ch, TO_VICT );
			ch->reply = keeper;
			return;
		}
		
		if ( ch->gold < cost )
		{
			act( "$n tells you 'You can't afford to buy $p'.",
				keeper, obj, ch, TO_VICT );
			ch->reply = keeper;
			return;
		}
		
//		if ( (obj->level > ch->level) && ch->level < 3 )
//		{
//			act( "$n tells you 'You can't use $p yet'.",
//				keeper, obj, ch, TO_VICT );
//			ch->reply = keeper;
//			return;
//		}
		
		if ( ch->carry_number + 1 > can_carry_n( ch ) )
		{
			send_to_char( "You can't carry that many items.\n\r", ch );
			return;
		}
		
		if ( ch->carry_weight + get_obj_weight( obj ) > can_carry_w( ch ) )
		{
			send_to_char( "You can't carry that much weight.\n\r", ch );
			return;
		}
		
		act( "$n buys $p.", ch, obj, NULL, TO_ROOM );
		act( "You buy $p.", ch, obj, NULL, TO_CHAR );
		ch->gold     -= cost;
		keeper->gold += cost;
		
		if ( IS_SET( obj->extra_flags, ITEM_INVENTORY ) )
			obj = create_object( obj->pIndexData, obj->level );
		else
			obj_from_char( obj );
		
		obj_to_char( obj, ch );
		return;
	}
}



void do_list( CHAR_DATA *ch, char *argument )
{
	char buf[MAX_STRING_LENGTH];
	
	if ( IS_SET(ch->in_room->room_flags, ROOM_PET_SHOP) )
	{
		ROOM_INDEX_DATA *pRoomIndexNext;
		bool found;
		
		pRoomIndexNext = get_room_index( ch->in_room->vnum + 1 );
		if ( pRoomIndexNext == NULL )
		{
			bug( "Do_list: bad pet shop at vnum %d.", ch->in_room->vnum );
			send_to_char( "You can't do that here.\n\r", ch );
			return;
		}
		
		found = TRUE;
		send_to_char("Pets you can buy: \n\r",ch);
        send_to_char("----------------------------\n\r",ch);
        send_to_char(" Dog               100 gold \n\r",ch);
        send_to_char("----------------------------\n\r",ch);
        return;
	}
	else
	{
		char arg[MAX_INPUT_LENGTH];
		CHAR_DATA *keeper;
		OBJ_DATA *obj;
		int cost;
		bool found;
		
		one_argument( argument, arg );
		
		if ( ( keeper = find_keeper( ch ) ) == NULL )
			return;
		
		found = FALSE;
		for ( obj = keeper->carrying; obj; obj = obj->next_content )
		{
			if ( obj->wear_loc == WEAR_NONE
				&&   can_see_obj( ch, obj )
				&& ( cost = get_cost( keeper, obj, TRUE ) ) > 0
				&& ( arg[0] == '\0' || is_name( arg, obj->name->str ) ) )
			{
				if ( !found )
				{
					found = TRUE;
					send_to_char( "[Price] Item\n\r", ch );
				}
				
				sprintf( buf, "[%5d] %s.\n\r",
					cost, capitalize( obj->short_descr->str ) );
				send_to_char( buf, ch );
			}
		}
		
		if ( !found )
		{
			if ( arg[0] == '\0' )
				send_to_char( "You can't buy anything here.\n\r", ch );
			else
				send_to_char( "You can't buy that here.\n\r", ch );
		}
		return;
	}
}



void do_sell( CHAR_DATA *ch, char *argument )
{
	char buf[MAX_STRING_LENGTH];
	char arg[MAX_INPUT_LENGTH];
	CHAR_DATA *keeper;
	OBJ_DATA *obj;
	int cost;
	
	one_argument( argument, arg );
	
	if ( arg[0] == '\0' )
	{
		send_to_char( "Sell what?\n\r", ch );
		return;
	}
	
	if ( ( keeper = find_keeper( ch ) ) == NULL )
		return;
	
	if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
	{
		act( "$n tells you 'You don't have that item'.",
			keeper, NULL, ch, TO_VICT );
		ch->reply = keeper;
		return;
	}
	
	if ( !can_drop_obj( ch, obj ) )
	{
		send_to_char( "You can't let go of it.\n\r", ch );
		return;
	}

        // don't sell if object is claimed, or it will be called back - FIX
        if ( strcmp(obj->questowner->str,""))
	{
                send_to_char( "You can't sell that.\n\r", ch );
                return;
        }

	if ( ( cost = get_cost( keeper, obj, FALSE ) ) <= 0 )
	{
		act( "$n looks uninterested in $p.", keeper, obj, ch, TO_VICT );
		return;
	}
	
	act( "$n sells $p.", ch, obj, NULL, TO_ROOM );
	sprintf( buf, "You sell $p for %d gold piece%s.",
		cost, cost == 1 ? "" : "s" );
	act( buf, ch, obj, NULL, TO_CHAR );
	ch->gold     += cost;
	keeper->gold -= cost;
	if ( keeper->gold < 0 )
		keeper->gold = 0;
	
	if ( obj->item_type == ITEM_TRASH )
	{
		extract_obj( obj );
	}
	else
	{
		obj_from_char( obj );
		obj_to_char( obj, keeper );
	}
	
	return;
}



void do_value( CHAR_DATA *ch, char *argument )
{
	char buf[MAX_STRING_LENGTH];
	char arg[MAX_INPUT_LENGTH];
	CHAR_DATA *keeper;
	OBJ_DATA *obj;
	int cost;
	
	one_argument( argument, arg );
	
	if ( arg[0] == '\0' )
	{
		send_to_char( "Value what?\n\r", ch );
		return;
	}
	
	if ( ( keeper = find_keeper( ch ) ) == NULL )
		return;
	
	if ( ( obj = get_obj_carry( ch, arg ) ) == NULL )
	{
		act( "$n tells you 'You don't have that item'.",
			keeper, NULL, ch, TO_VICT );
		ch->reply = keeper;
		return;
	}
	
	if ( !can_drop_obj( ch, obj ) )
	{
		send_to_char( "You can't let go of it.\n\r", ch );
		return;
	}
	
	if ( ( cost = get_cost( keeper, obj, FALSE ) ) <= 0 )
	{
		act( "$n looks uninterested in $p.", keeper, obj, ch, TO_VICT );
		return;
	}
	
	sprintf( buf, "$n tells you 'I'll give you %d gold coins for $p'.", cost );
	act( buf, keeper, obj, ch, TO_VICT );
	ch->reply = keeper;
	
	return;
}

void do_activate( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	OBJ_DATA *obj2;
	CHAR_DATA *victim;
	CHAR_DATA *victim_next;
	CHAR_DATA *mount;
	CHAR_DATA *mob;
	ROOM_INDEX_DATA *pRoomIndex;
	
	argument = one_argument( argument, arg1 );
	argument = one_argument( argument, arg2 );
	
	if ( arg1[0] == '\0' )
	{
		send_to_char( "Which item do you wish to activate?\n\r", ch );
		return;
	}
	if ( (obj = get_obj_wear(ch,arg1)) == NULL ) 
	{
		if ( ( obj = get_obj_here( ch, arg1 ) ) == NULL )
		{
			send_to_char( "You can't find that item.\n\r", ch );
			return;
		}
	/* You should only be able to use nontake items on floor */
		if (CAN_WEAR(obj, ITEM_TAKE))
		{
			send_to_char( "But you are not wearing it!\n\r", ch );
			return;
		}
	}
	
	if (HAS_PROG(obj->pIndexData,TRIG_ACTIVATE))
	{
		oprog_percent_trigger(obj,ch,NULL,NULL,TRIG_ACTIVATE);
		return;
	}
	
	if ( obj == NULL || !IS_SET(obj->spectype, SITEM_ACTIVATE) )
	{
		send_to_char( "This item cannot be activated.\n\r", ch );
		return;
	}
	if ( IS_SET(obj->spectype, SITEM_TARGET) && arg2[0] == '\0' )
	{
		send_to_char( "Who do you wish to activate it on?\n\r", ch );
		return;
	}
	if ( IS_SET(obj->spectype, SITEM_TARGET) )
	{
		if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
		{
			send_to_char( "Nobody here by that name.\n\r", ch );
			return;
		}
	}
	else victim = ch;
	if (obj->chpoweruse != NULL && obj->chpoweruse != '\0'
		&& str_cmp(obj->chpoweruse->str,"(null)") )
		kavitem(obj->chpoweruse->str,ch,obj,NULL,TO_CHAR);
	if (obj->victpoweruse != NULL && obj->victpoweruse != '\0'
		&& str_cmp(obj->victpoweruse->str,"(null)") )
		kavitem(obj->victpoweruse->str,ch,obj,NULL,TO_ROOM);
	if ( IS_SET(obj->spectype, SITEM_SPELL))
	{
		int castlevel = obj->level;
		if (castlevel < 1) castlevel = 1;
		else if (castlevel > 60) castlevel = 60;
		obj_cast_spell( obj->specpower, castlevel, ch, victim, NULL );
		if (!IS_IMMORTAL( ch))
			WAIT_STATE(ch,6);
		if ( IS_SET(obj->spectype, SITEM_DELAY1)) WAIT_STATE(ch,6);
		if ( IS_SET(obj->spectype, SITEM_DELAY2)) WAIT_STATE(ch,12);
		return;
	}
	else if ( IS_SET(obj->spectype, SITEM_TRANSPORTER))
	{
		if (obj->chpoweron != NULL && obj->chpoweron != '\0'
			&& str_cmp(obj->chpoweron->str,"(null)") )
			kavitem(obj->chpoweron->str,ch,obj,NULL,TO_CHAR);
		if (obj->victpoweron != NULL && obj->victpoweron != '\0'
			&& str_cmp(obj->victpoweron->str,"(null)") )
			kavitem(obj->victpoweron->str,ch,obj,NULL,TO_ROOM);
		pRoomIndex     = get_room_index(obj->specpower);
		obj->specpower = ch->in_room->vnum;
		if ( pRoomIndex == NULL ) return;
		char_from_room(ch);
		char_to_room(ch,pRoomIndex);
		do_look(ch,"auto");
		if (obj->chpoweroff != NULL && obj->chpoweroff != '\0'
			&& str_cmp(obj->chpoweroff->str,"(null)") )
			kavitem(obj->chpoweroff->str,ch,obj,NULL,TO_CHAR);
		if (obj->victpoweroff != NULL && obj->victpoweroff != '\0'
			&& str_cmp(obj->victpoweroff->str,"(null)") )
			kavitem(obj->victpoweroff->str,ch,obj,NULL,TO_ROOM);
		if (!IS_SET(obj->quest, QUEST_ARTIFACT) &&
			IS_SET(ch->in_room->room_flags, ROOM_NO_TELEPORT) &&
			CAN_WEAR(obj,ITEM_TAKE))
		{
			send_to_char("A powerful force hurls you from the room.\n\r",ch);
			act("$n is hurled from the room by a powerful force.",ch,NULL,NULL,TO_ROOM);
			ch->position = POS_STUNNED;
			char_from_room(ch);
			char_to_room(ch,get_room_index(ROOM_VNUM_LIMBO));
			act("$n appears in the room, and falls to the ground stunned.",ch,NULL,NULL,TO_ROOM);
		}
		if ( (mount = ch->mount) == NULL) return;
		char_from_room( mount );
		char_to_room( mount, ch->in_room );
		do_look( mount, "auto" );
		return;
	}
	else if ( IS_SET(obj->spectype, SITEM_TELEPORTER))
	{
		if (obj->chpoweron != NULL && obj->chpoweron != '\0'
			&& str_cmp(obj->chpoweron->str,"(null)") )
			kavitem(obj->chpoweron->str,ch,obj,NULL,TO_CHAR);
		if (obj->victpoweron != NULL && obj->victpoweron != '\0'
			&& str_cmp(obj->victpoweron->str,"(null)") )
			kavitem(obj->victpoweron->str,ch,obj,NULL,TO_ROOM);
		pRoomIndex     = get_room_index(obj->specpower);
		if ( pRoomIndex == NULL ) return;
		char_from_room(ch);
		char_to_room(ch,pRoomIndex);
		do_look(ch,"auto");
		if (obj->chpoweroff != NULL && obj->chpoweroff != '\0'
			&& str_cmp(obj->chpoweroff->str,"(null)") )
			kavitem(obj->chpoweroff->str,ch,obj,NULL,TO_CHAR);
		if (obj->victpoweroff != NULL && obj->victpoweroff != '\0'
			&& str_cmp(obj->victpoweroff->str,"(null)") )
			kavitem(obj->victpoweroff->str,ch,obj,NULL,TO_ROOM);
		if (!IS_SET(obj->quest, QUEST_ARTIFACT) &&
			IS_SET(ch->in_room->room_flags, ROOM_NO_TELEPORT) &&
			CAN_WEAR(obj,ITEM_TAKE))
		{
			send_to_char("A powerful force hurls you from the room.\n\r",ch);
			act("$n is hurled from the room by a powerful force.",ch,NULL,NULL,TO_ROOM);
			ch->position = POS_STUNNED;
			char_from_room(ch);
			char_to_room(ch,get_room_index(ROOM_VNUM_LIMBO));
			act("$n appears in the room, and falls to the ground stunned.",ch,NULL,NULL,TO_ROOM);
		}
		if ( (mount = ch->mount) == NULL) return;
		char_from_room( mount );
		char_to_room( mount, ch->in_room );
		do_look( mount, "auto" );
		return;
	}
	else if ( IS_SET(obj->spectype, SITEM_OBJECT))
	{
		if ( get_obj_index(obj->specpower) == NULL ) return;
		obj2 = create_object(get_obj_index(obj->specpower), ch->level);
		if ( CAN_WEAR(obj2,ITEM_TAKE) ) obj_to_char(obj2,ch);
		else                           obj_to_room(obj2,ch->in_room);
	}
	else if ( IS_SET(obj->spectype, SITEM_MOBILE))
	{
		if ( get_mob_index(obj->specpower) == NULL ) return;
		mob = create_mobile(get_mob_index(obj->specpower));
		char_to_room(mob,ch->in_room);
	}
	else if ( IS_SET(obj->spectype, SITEM_ACTION))
	{
		interpret(ch,obj->victpoweron->str);
		if (obj->victpoweroff != NULL && str_cmp(obj->victpoweroff->str,"(null)") &&
			obj->victpoweroff != '\0')
		{
			for ( victim = char_list; victim != NULL; victim = victim_next )
			{
				victim_next	= victim->next;
				if ( victim->in_room == NULL ) continue;
				if ( victim == ch ) continue;
				if ( victim->in_room == ch->in_room )
				{
					interpret(victim,obj->victpoweroff->str);
					continue;
				}
			}
		}
	} 
	mudsetting->last_proc_logged = 6;
	return;
}

void do_press( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	OBJ_DATA *obj2;
	CHAR_DATA *victim;
	CHAR_DATA *victim_next;
	CHAR_DATA *mount;
	CHAR_DATA *mob;
	ROOM_INDEX_DATA *pRoomIndex;
	
	argument = one_argument( argument, arg1 );
	argument = one_argument( argument, arg2 );
	
	if ( arg1[0] == '\0' )
	{
		send_to_char( "Which item do you wish to press?\n\r", ch );
		return;
	}
	if ( (obj = get_obj_wear(ch,arg1)) == NULL ) 
	{
		if ( ( obj = get_obj_here( ch, arg1 ) ) == NULL )
		{
			send_to_char( "You can't find that item.\n\r", ch );
			return;
		}
	/* You should only be able to use nontake items on floor */
		if (CAN_WEAR(obj, ITEM_TAKE))
		{
			send_to_char( "But you are not wearing it!\n\r", ch );
			return;
		}
	}
	
	if (HAS_PROG(obj->pIndexData,TRIG_PUSH))
	{
		oprog_percent_trigger(obj,ch,NULL,NULL,TRIG_PUSH);
		return;
	}
	
	if ( obj == NULL || !IS_SET(obj->spectype, SITEM_PRESS) )
	{
		send_to_char( "There is nothing on this item to press.\n\r", ch );
		return;
	}
	
	
	if ( IS_SET(obj->spectype, SITEM_TARGET) && arg2[0] == '\0' )
	{
		send_to_char( "Who do you wish to use it on?\n\r", ch );
		return;
	}
	if ( IS_SET(obj->spectype, SITEM_TARGET) )
	{
		if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
		{
			send_to_char( "Nobody here by that name.\n\r", ch );
			return;
		}
	}
	else victim = ch;
	if (obj->chpoweruse != NULL && obj->chpoweruse != '\0'
		&& str_cmp(obj->chpoweruse->str,"(null)") )
		kavitem(obj->chpoweruse->str,ch,obj,NULL,TO_CHAR);
	if (obj->victpoweruse != NULL && obj->victpoweruse != '\0'
		&& str_cmp(obj->victpoweruse->str,"(null)") )
		kavitem(obj->victpoweruse->str,ch,obj,NULL,TO_ROOM);
	if ( IS_SET(obj->spectype, SITEM_SPELL))
	{
		int castlevel = obj->level;
		if (castlevel < 1) castlevel = 1;
		else if (castlevel > 60) castlevel = 60;
		obj_cast_spell( obj->specpower, castlevel, ch, victim, NULL );
		if (!IS_IMMORTAL( ch))
			WAIT_STATE(ch,6);
		if ( IS_SET(obj->spectype, SITEM_DELAY1)) 
		{
			if (!IS_IMMORTAL( ch))
				WAIT_STATE(ch,6);
		}
		if ( IS_SET(obj->spectype, SITEM_DELAY2)) 
		{
			if (!IS_IMMORTAL( ch))
				WAIT_STATE(ch,12);
		}
		return;
	}
	else if ( IS_SET(obj->spectype, SITEM_TRANSPORTER))
	{
		if (obj->chpoweron != NULL && obj->chpoweron != '\0'
			&& str_cmp(obj->chpoweron->str,"(null)") )
			kavitem(obj->chpoweron->str,ch,obj,NULL,TO_CHAR);
		if (obj->victpoweron != NULL && obj->victpoweron != '\0'
			&& str_cmp(obj->victpoweron->str,"(null)") )
			kavitem(obj->victpoweron->str,ch,obj,NULL,TO_ROOM);
		pRoomIndex     = get_room_index(obj->specpower);
		obj->specpower = ch->in_room->vnum;
		if ( pRoomIndex == NULL ) return;
		char_from_room(ch);
		char_to_room(ch,pRoomIndex);
		do_look(ch,"auto");
		if (obj->chpoweroff != NULL && obj->chpoweroff != '\0'
			&& str_cmp(obj->chpoweroff->str,"(null)") )
			kavitem(obj->chpoweroff->str,ch,obj,NULL,TO_CHAR);
		if (obj->victpoweroff != NULL && obj->victpoweroff != '\0'
			&& str_cmp(obj->victpoweroff->str,"(null)") )
			kavitem(obj->victpoweroff->str,ch,obj,NULL,TO_ROOM);
		if (!IS_SET(obj->quest, QUEST_ARTIFACT) &&
			IS_SET(ch->in_room->room_flags, ROOM_NO_TELEPORT) &&
			CAN_WEAR(obj,ITEM_TAKE))
		{
			send_to_char("A powerful force hurls you from the room.\n\r",ch);
			act("$n is hurled from the room by a powerful force.",ch,NULL,NULL,TO_ROOM);
			ch->position = POS_STUNNED;
			char_from_room(ch);
			char_to_room(ch,get_room_index(ROOM_VNUM_LIMBO));
			act("$n appears in the room, and falls to the ground stunned.",ch,NULL,NULL,TO_ROOM);
		}
		if ( (mount = ch->mount) == NULL) return;
		char_from_room( mount );
		char_to_room( mount, ch->in_room );
		do_look( mount, "auto" );
		return;
	}
	else if ( IS_SET(obj->spectype, SITEM_TELEPORTER))
	{
		if (obj->chpoweron != NULL && obj->chpoweron != '\0'
			&& str_cmp(obj->chpoweron->str,"(null)") )
			kavitem(obj->chpoweron->str,ch,obj,NULL,TO_CHAR);
		if (obj->victpoweron != NULL && obj->victpoweron != '\0'
			&& str_cmp(obj->victpoweron->str,"(null)") )
			kavitem(obj->victpoweron->str,ch,obj,NULL,TO_ROOM);
		pRoomIndex     = get_room_index(obj->specpower);
		if ( pRoomIndex == NULL ) return;
		char_from_room(ch);
		char_to_room(ch,pRoomIndex);
		do_look(ch,"auto");
		if (obj->chpoweroff != NULL && obj->chpoweroff != '\0'
			&& str_cmp(obj->chpoweroff->str,"(null)") )
			kavitem(obj->chpoweroff->str,ch,obj,NULL,TO_CHAR);
		if (obj->victpoweroff != NULL && obj->victpoweroff != '\0'
			&& str_cmp(obj->victpoweroff->str,"(null)") )
			kavitem(obj->victpoweroff->str,ch,obj,NULL,TO_ROOM);
		if (!IS_SET(obj->quest, QUEST_ARTIFACT) &&
			IS_SET(ch->in_room->room_flags, ROOM_NO_TELEPORT) &&
			CAN_WEAR(obj,ITEM_TAKE))
		{
			send_to_char("A powerful force hurls you from the room.\n\r",ch);
			act("$n is hurled from the room by a powerful force.",ch,NULL,NULL,TO_ROOM);
			ch->position = POS_STUNNED;
			char_from_room(ch);
			char_to_room(ch,get_room_index(ROOM_VNUM_LIMBO));
			act("$n appears in the room, and falls to the ground stunned.",ch,NULL,NULL,TO_ROOM);
		}
		if ( (mount = ch->mount) == NULL) return;
		char_from_room( mount );
		char_to_room( mount, ch->in_room );
		do_look( mount, "auto" );
		return;
	}
	else if ( IS_SET(obj->spectype, SITEM_OBJECT))
	{
		if ( get_obj_index(obj->specpower) == NULL ) return;
		obj2 = create_object(get_obj_index(obj->specpower), ch->level);
		if ( CAN_WEAR(obj2,ITEM_TAKE) ) obj_to_char(obj2,ch);
		else                           obj_to_room(obj2,ch->in_room);
	}
	else if ( IS_SET(obj->spectype, SITEM_MOBILE))
	{
		if ( get_mob_index(obj->specpower) == NULL ) return;
		mob = create_mobile(get_mob_index(obj->specpower));
		char_to_room(mob,ch->in_room);
	}
	else if ( IS_SET(obj->spectype, SITEM_ACTION))
	{
		interpret(ch,obj->victpoweron->str);
		if (obj->victpoweroff != NULL && str_cmp(obj->victpoweroff->str,"(null)") &&
			obj->victpoweroff != '\0')
		{
			for ( victim = char_list; victim != NULL; victim = victim_next )
			{
				victim_next	= victim->next;
				if ( victim->in_room == NULL ) continue;
				if ( victim == ch ) continue;
				if ( victim->in_room == ch->in_room )
				{
					interpret(victim,obj->victpoweroff->str);
					continue;
				}
			}
		}
	}
	mudsetting->last_proc_logged = 7;
	return;
}

void do_twist( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	OBJ_DATA *obj2;
	CHAR_DATA *victim;
	CHAR_DATA *victim_next;
	CHAR_DATA *mount;
	CHAR_DATA *mob;
	ROOM_INDEX_DATA *pRoomIndex;
	
	argument = one_argument( argument, arg1 );
	argument = one_argument( argument, arg2 );
	
	if ( arg1[0] == '\0' )
	{
		send_to_char( "Which item do you wish to twist?\n\r", ch );
		return;
	}
	if ( (obj = get_obj_wear(ch,arg1)) == NULL ) 
	{
		if ( ( obj = get_obj_here( ch, arg1 ) ) == NULL )
		{
			send_to_char( "You can't find that item.\n\r", ch );
			return;
		}
	/* You should only be able to use nontake items on floor */
		if (CAN_WEAR(obj, ITEM_TAKE))
		{
			send_to_char( "But you are not wearing it!\n\r", ch );
			return;
		}
	}
	
	if (HAS_PROG(obj->pIndexData,TRIG_TWIST))
	{
		oprog_percent_trigger(obj,ch,NULL,NULL,TRIG_TWIST);
		return;
	}
	
	if ( obj == NULL || !IS_SET(obj->spectype, SITEM_TWIST) )
	{
		send_to_char( "This item cannot be twisted.\n\r", ch );
		return;
	}
	if ( IS_SET(obj->spectype, SITEM_TARGET) && arg2[0] == '\0' )
	{
		send_to_char( "Who do you wish to use it on?\n\r", ch );
		return;
	}
	if ( IS_SET(obj->spectype, SITEM_TARGET) )
	{
		if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
		{
			send_to_char( "Nobody here by that name.\n\r", ch );
			return;
		}
	}
	else victim = ch;
	if (obj->chpoweruse != NULL && obj->chpoweruse != '\0'
		&& str_cmp(obj->chpoweruse->str,"(null)") )
		kavitem(obj->chpoweruse->str,ch,obj,NULL,TO_CHAR);
	if (obj->victpoweruse != NULL && obj->victpoweruse != '\0'
		&& str_cmp(obj->victpoweruse->str,"(null)") )
		kavitem(obj->victpoweruse->str,ch,obj,NULL,TO_ROOM);
	if ( IS_SET(obj->spectype, SITEM_SPELL))
	{
		int castlevel = obj->level;
		if (castlevel < 1) castlevel = 1;
		else if (castlevel > 60) castlevel = 60;
		obj_cast_spell( obj->specpower, castlevel, ch, victim, NULL );
		if (!IS_IMMORTAL( ch))
			WAIT_STATE(ch,6);
		if ( IS_SET(obj->spectype, SITEM_DELAY1)) 
		{
			if (!IS_IMMORTAL( ch))
				WAIT_STATE(ch,6);
		}
		if ( IS_SET(obj->spectype, SITEM_DELAY2))
		{
			if (!IS_IMMORTAL( ch))
				WAIT_STATE(ch,12);
		}
		return;
	}
	else if ( IS_SET(obj->spectype, SITEM_TRANSPORTER))
	{
		if (obj->chpoweron != NULL && obj->chpoweron != '\0'
			&& str_cmp(obj->chpoweron->str,"(null)") )
			kavitem(obj->chpoweron->str,ch,obj,NULL,TO_CHAR);
		if (obj->victpoweron != NULL && obj->victpoweron != '\0'
			&& str_cmp(obj->victpoweron->str,"(null)") )
			kavitem(obj->victpoweron->str,ch,obj,NULL,TO_ROOM);
		pRoomIndex     = get_room_index(obj->specpower);
		obj->specpower = ch->in_room->vnum;
		if ( pRoomIndex == NULL ) return;
		char_from_room(ch);
		char_to_room(ch,pRoomIndex);
		do_look(ch,"auto");
		if (obj->chpoweroff != NULL && obj->chpoweroff != '\0'
			&& str_cmp(obj->chpoweroff->str,"(null)") )
			kavitem(obj->chpoweroff->str,ch,obj,NULL,TO_CHAR);
		if (obj->victpoweroff != NULL && obj->victpoweroff != '\0'
			&& str_cmp(obj->victpoweroff->str,"(null)") )
			kavitem(obj->victpoweroff->str,ch,obj,NULL,TO_ROOM);
		if (!IS_SET(obj->quest, QUEST_ARTIFACT) &&
			IS_SET(ch->in_room->room_flags, ROOM_NO_TELEPORT) &&
			CAN_WEAR(obj,ITEM_TAKE))
		{
			send_to_char("A powerful force hurls you from the room.\n\r",ch);
			act("$n is hurled from the room by a powerful force.",ch,NULL,NULL,TO_ROOM);
			ch->position = POS_STUNNED;
			char_from_room(ch);
			char_to_room(ch,get_room_index(ROOM_VNUM_LIMBO));
			act("$n appears in the room, and falls to the ground stunned.",ch,NULL,NULL,TO_ROOM);
		}
		if ( (mount = ch->mount) == NULL) return;
		char_from_room( mount );
		char_to_room( mount, ch->in_room );
		do_look( mount, "auto" );
		return;
	}
	else if ( IS_SET(obj->spectype, SITEM_TELEPORTER))
	{
		if (obj->chpoweron != NULL && obj->chpoweron != '\0'
			&& str_cmp(obj->chpoweron->str,"(null)") )
			kavitem(obj->chpoweron->str,ch,obj,NULL,TO_CHAR);
		if (obj->victpoweron != NULL && obj->victpoweron != '\0'
			&& str_cmp(obj->victpoweron->str,"(null)") )
			kavitem(obj->victpoweron->str,ch,obj,NULL,TO_ROOM);
		pRoomIndex     = get_room_index(obj->specpower);
		if ( pRoomIndex == NULL ) return;
		char_from_room(ch);
		char_to_room(ch,pRoomIndex);
		do_look(ch,"auto");
		if (obj->chpoweroff != NULL && obj->chpoweroff != '\0'
			&& str_cmp(obj->chpoweroff->str,"(null)") )
			kavitem(obj->chpoweroff->str,ch,obj,NULL,TO_CHAR);
		if (obj->victpoweroff != NULL && obj->victpoweroff != '\0'
			&& str_cmp(obj->victpoweroff->str,"(null)") )
			kavitem(obj->victpoweroff->str,ch,obj,NULL,TO_ROOM);
		if (!IS_SET(obj->quest, QUEST_ARTIFACT) &&
			IS_SET(ch->in_room->room_flags, ROOM_NO_TELEPORT) &&
			CAN_WEAR(obj,ITEM_TAKE))
		{
			send_to_char("A powerful force hurls you from the room.\n\r",ch);
			act("$n is hurled from the room by a powerful force.",ch,NULL,NULL,TO_ROOM);
			ch->position = POS_STUNNED;
			char_from_room(ch);
			char_to_room(ch,get_room_index(ROOM_VNUM_LIMBO));
			act("$n appears in the room, and falls to the ground stunned.",ch,NULL,NULL,TO_ROOM);
		}
		if ( (mount = ch->mount) == NULL) return;
		char_from_room( mount );
		char_to_room( mount, ch->in_room );
		do_look( mount, "auto" );
		return;
	}
	else if ( IS_SET(obj->spectype, SITEM_OBJECT))
	{
		if ( get_obj_index(obj->specpower) == NULL ) return;
		obj2 = create_object(get_obj_index(obj->specpower), ch->level);
		if ( CAN_WEAR(obj2,ITEM_TAKE) ) obj_to_char(obj2,ch);
		else                           obj_to_room(obj2,ch->in_room);
	}
	else if ( IS_SET(obj->spectype, SITEM_MOBILE))
	{
		if ( get_mob_index(obj->specpower) == NULL ) return;
		mob = create_mobile(get_mob_index(obj->specpower));
		char_to_room(mob,ch->in_room);
	}
	else if ( IS_SET(obj->spectype, SITEM_ACTION))
	{
		interpret(ch,obj->victpoweron->str);
		if (obj->victpoweroff != NULL && str_cmp(obj->victpoweroff->str,"(null)") &&
			obj->victpoweroff != '\0')
		{
			for ( victim = char_list; victim != NULL; victim = victim_next )
			{
				victim_next	= victim->next;
				if ( victim->in_room == NULL ) continue;
				if ( victim == ch ) continue;
				if ( victim->in_room == ch->in_room )
				{
					interpret(victim,obj->victpoweroff->str);
					continue;
				}
			}
		}
	}
	mudsetting->last_proc_logged = 8;
	return;
}

void do_pull( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	OBJ_DATA *obj2;
	CHAR_DATA *victim;
	CHAR_DATA *victim_next;
	CHAR_DATA *mount;
	CHAR_DATA *mob;
	ROOM_INDEX_DATA *pRoomIndex;
	
	argument = one_argument( argument, arg1 );
	argument = one_argument( argument, arg2 );
	
	if ( arg1[0] == '\0' )
	{
		send_to_char( "What do you wish to pull?\n\r", ch );
		return;
	}
	if ( (obj = get_obj_wear(ch,arg1)) == NULL ) 
	{
		if ( ( obj = get_obj_here( ch, arg1 ) ) == NULL )
		{
			send_to_char( "You can't find that item.\n\r", ch );
			return;
		}
	/* You should only be able to use nontake items on floor */
		if (CAN_WEAR(obj, ITEM_TAKE))
		{
			send_to_char( "But you are not wearing it!\n\r", ch );
			return;
		}
	}
	
	if (HAS_PROG(obj->pIndexData,TRIG_PULL))
	{
		oprog_percent_trigger(obj,ch,NULL,NULL,TRIG_PULL);
		return;
	}
		
	if ( obj == NULL || !IS_SET(obj->spectype, SITEM_PULL) )
	{
		send_to_char( "This item cannot be pulled.\n\r", ch );
		return;
	}
	if ( IS_SET(obj->spectype, SITEM_TARGET) && arg2[0] == '\0' )
	{
		send_to_char( "Who do you wish to use it on?\n\r", ch );
		return;
	}
	if ( IS_SET(obj->spectype, SITEM_TARGET) )
	{
		if ( ( victim = get_char_room( ch, arg2 ) ) == NULL )
		{
			send_to_char( "Nobody here by that name.\n\r", ch );
			return;
		}
	}
	else victim = ch;
	if (obj->chpoweruse != NULL && obj->chpoweruse != '\0'
		&& str_cmp(obj->chpoweruse->str,"(null)") )
		kavitem(obj->chpoweruse->str,ch,obj,NULL,TO_CHAR);
	if (obj->victpoweruse != NULL && obj->victpoweruse != '\0'
		&& str_cmp(obj->victpoweruse->str,"(null)") )
		kavitem(obj->victpoweruse->str,ch,obj,NULL,TO_ROOM);
	if ( IS_SET(obj->spectype, SITEM_SPELL))
	{
		int castlevel = obj->level;
		if (castlevel < 1) castlevel = 1;
		else if (castlevel > 60) castlevel = 60;
		obj_cast_spell( obj->specpower, castlevel, ch, victim, NULL );
		if (!IS_IMMORTAL( ch))
			WAIT_STATE(ch,6);
		if ( IS_SET(obj->spectype, SITEM_DELAY1))
		{
			if (!IS_IMMORTAL( ch))
				WAIT_STATE(ch,6);
		}
		if ( IS_SET(obj->spectype, SITEM_DELAY2)) 
		{
			if (!IS_IMMORTAL( ch))
				WAIT_STATE(ch,12);
		}
		return;
	}
	else if ( IS_SET(obj->spectype, SITEM_TRANSPORTER))
	{
		if (obj->chpoweron != NULL && obj->chpoweron != '\0'
			&& str_cmp(obj->chpoweron->str,"(null)") )
			kavitem(obj->chpoweron->str,ch,obj,NULL,TO_CHAR);
		if (obj->victpoweron != NULL && obj->victpoweron != '\0'
			&& str_cmp(obj->victpoweron->str,"(null)") )
			kavitem(obj->victpoweron->str,ch,obj,NULL,TO_ROOM);
		pRoomIndex     = get_room_index(obj->specpower);
		obj->specpower = ch->in_room->vnum;
		if ( pRoomIndex == NULL ) return;
		char_from_room(ch);
		char_to_room(ch,pRoomIndex);
		do_look(ch,"auto");
		if (obj->chpoweroff != NULL && obj->chpoweroff != '\0'
			&& str_cmp(obj->chpoweroff->str,"(null)") )
			kavitem(obj->chpoweroff->str,ch,obj,NULL,TO_CHAR);
		if (obj->victpoweroff != NULL && obj->victpoweroff != '\0'
			&& str_cmp(obj->victpoweroff->str,"(null)") )
			kavitem(obj->victpoweroff->str,ch,obj,NULL,TO_ROOM);
		if (!IS_SET(obj->quest, QUEST_ARTIFACT) &&
			IS_SET(ch->in_room->room_flags, ROOM_NO_TELEPORT) &&
			CAN_WEAR(obj,ITEM_TAKE))
		{
			send_to_char("A powerful force hurls you from the room.\n\r",ch);
			act("$n is hurled from the room by a powerful force.",ch,NULL,NULL,TO_ROOM);
			ch->position = POS_STUNNED;
			char_from_room(ch);
			char_to_room(ch,get_room_index(ROOM_VNUM_LIMBO));
			act("$n appears in the room, and falls to the ground stunned.",ch,NULL,NULL,TO_ROOM);
		}
		if ( (mount = ch->mount) == NULL) return;
		char_from_room( mount );
		char_to_room( mount, ch->in_room );
		do_look( mount, "auto" );
		return;
	}
	else if ( IS_SET(obj->spectype, SITEM_TELEPORTER))
	{
		if (obj->chpoweron != NULL && obj->chpoweron != '\0'
			&& str_cmp(obj->chpoweron->str,"(null)") )
			kavitem(obj->chpoweron->str,ch,obj,NULL,TO_CHAR);
		if (obj->victpoweron != NULL && obj->victpoweron != '\0'
			&& str_cmp(obj->victpoweron->str,"(null)") )
			kavitem(obj->victpoweron->str,ch,obj,NULL,TO_ROOM);
		pRoomIndex     = get_room_index(obj->specpower);
		if ( pRoomIndex == NULL ) return;
		char_from_room(ch);
		char_to_room(ch,pRoomIndex);
		do_look(ch,"auto");
		if (obj->chpoweroff != NULL && obj->chpoweroff != '\0'
			&& str_cmp(obj->chpoweroff->str,"(null)") )
			kavitem(obj->chpoweroff->str,ch,obj,NULL,TO_CHAR);
		if (obj->victpoweroff != NULL && obj->victpoweroff != '\0'
			&& str_cmp(obj->victpoweroff->str,"(null)") )
			kavitem(obj->victpoweroff->str,ch,obj,NULL,TO_ROOM);
		if (!IS_SET(obj->quest, QUEST_ARTIFACT) &&
			IS_SET(ch->in_room->room_flags, ROOM_NO_TELEPORT) &&
			CAN_WEAR(obj,ITEM_TAKE))
		{
			send_to_char("A powerful force hurls you from the room.\n\r",ch);
			act("$n is hurled from the room by a powerful force.",ch,NULL,NULL,TO_ROOM);
			ch->position = POS_STUNNED;
			char_from_room(ch);
			char_to_room(ch,get_room_index(ROOM_VNUM_LIMBO));
			act("$n appears in the room, and falls to the ground stunned.",ch,NULL,NULL,TO_ROOM);
		}
		if ( (mount = ch->mount) == NULL) return;
		char_from_room( mount );
		char_to_room( mount, ch->in_room );
		do_look( mount, "auto" );
		return;
	}
	else if ( IS_SET(obj->spectype, SITEM_OBJECT))
	{
		if ( get_obj_index(obj->specpower) == NULL ) return;
		obj2 = create_object(get_obj_index(obj->specpower), ch->level);
		if ( CAN_WEAR(obj2,ITEM_TAKE) ) obj_to_char(obj2,ch);
		else                           obj_to_room(obj2,ch->in_room);
	}
	else if ( IS_SET(obj->spectype, SITEM_MOBILE))
	{
		if ( get_mob_index(obj->specpower) == NULL ) return;
		mob = create_mobile(get_mob_index(obj->specpower));
		char_to_room(mob,ch->in_room);
	}
	else if ( IS_SET(obj->spectype, SITEM_ACTION))
	{
		interpret(ch,obj->victpoweron->str);
		if (obj->victpoweroff != NULL && str_cmp(obj->victpoweroff->str,"(null)") &&
			obj->victpoweroff != '\0')
		{
			for ( victim = char_list; victim != NULL; victim = victim_next )
			{
				victim_next	= victim->next;
				if ( victim->in_room == NULL ) continue;
				if ( victim == ch ) continue;
				if ( victim->in_room == ch->in_room )
				{
					interpret(victim,obj->victpoweroff->str);
					continue;
				}
			}
		}
	}
	mudsetting->last_proc_logged = 9;
	return;
}

bool is_ok_to_wear( CHAR_DATA *ch, bool wolf_ok, char *argument )
{
	char arg [MAX_INPUT_LENGTH];
	int count;
	argument = one_argument( argument, arg );
	
	if (!str_cmp(arg,"head"))
	{
		if (IS_HEAD(ch,LOST_HEAD)) return FALSE;
	}
	else if (!str_cmp(arg,"face"))
	{
		if (IS_HEAD(ch,LOST_HEAD)) return FALSE;
	}
	else if (!str_cmp(arg,"left_hand"))
	{
		if (!IS_NPC(ch) && IS_CLASS(ch,CLASS_WEREWOLF) && IS_SET(ch->special, SPC_WOLFMAN) && !wolf_ok) return FALSE;
		if (IS_ARM_L(ch,LOST_ARM)) return FALSE;
		else if (IS_ARM_L(ch,BROKEN_ARM)) return FALSE;
		else if (IS_ARM_L(ch,LOST_HAND)) return FALSE;
		else if (IS_ARM_L(ch,BROKEN_THUMB)) return FALSE;
		else if (IS_ARM_L(ch,LOST_THUMB)) return FALSE;
		count = 0;
		if (IS_ARM_L(ch,LOST_FINGER_I)||IS_ARM_L(ch,BROKEN_FINGER_I)) count+= 1;
		if (IS_ARM_L(ch,LOST_FINGER_M)||IS_ARM_L(ch,BROKEN_FINGER_M)) count+= 1;
		if (IS_ARM_L(ch,LOST_FINGER_R)||IS_ARM_L(ch,BROKEN_FINGER_R)) count+= 1;
		if (IS_ARM_L(ch,LOST_FINGER_L)||IS_ARM_L(ch,BROKEN_FINGER_L)) count+= 1;
		if (count > 2) return FALSE;
	}
	else if (!str_cmp(arg,"right_hand"))
	{
		if (!IS_NPC(ch) && IS_CLASS(ch,CLASS_WEREWOLF) && IS_SET(ch->special, SPC_WOLFMAN) && !wolf_ok) return FALSE;
		if (IS_ARM_R(ch,LOST_ARM)) return FALSE;
		else if (IS_ARM_R(ch,BROKEN_ARM)) return FALSE;
		else if (IS_ARM_R(ch,LOST_HAND)) return FALSE;
		else if (IS_ARM_R(ch,BROKEN_THUMB)) return FALSE;
		else if (IS_ARM_R(ch,LOST_THUMB)) return FALSE;
		count = 0;
		if (IS_ARM_R(ch,LOST_FINGER_I)||IS_ARM_R(ch,BROKEN_FINGER_I)) count+= 1;
		if (IS_ARM_R(ch,LOST_FINGER_M)||IS_ARM_R(ch,BROKEN_FINGER_M)) count+= 1;
		if (IS_ARM_R(ch,LOST_FINGER_R)||IS_ARM_R(ch,BROKEN_FINGER_R)) count+= 1;
		if (IS_ARM_R(ch,LOST_FINGER_L)||IS_ARM_R(ch,BROKEN_FINGER_L)) count+= 1;
		if (count > 2) return FALSE;
	}
	else if (!str_cmp(arg,"left_wrist"))
	{
		if (IS_ARM_L(ch,LOST_ARM)) return FALSE;
		else if (IS_ARM_L(ch,LOST_HAND)) return FALSE;
	}
	else if (!str_cmp(arg,"right_wrist"))
	{
		if (IS_ARM_R(ch,LOST_ARM)) return FALSE;
		else if (IS_ARM_R(ch,LOST_HAND)) return FALSE;
	}
	else if (!str_cmp(arg,"left_finger"))
	{
		if (IS_ARM_L(ch,LOST_ARM)) return FALSE;
		else if (IS_ARM_L(ch,LOST_HAND)) return FALSE;
		else if (IS_ARM_L(ch,LOST_FINGER_R)) return FALSE;
	}
	else if (!str_cmp(arg,"right_finger"))
	{
		if (IS_ARM_R(ch,LOST_ARM)) return FALSE;
		else if (IS_ARM_R(ch,LOST_HAND)) return FALSE;
		else if (IS_ARM_R(ch,LOST_FINGER_R)) return FALSE;
	}
	else if (!str_cmp(arg,"arms"))
	{
		if (IS_ARM_L(ch,LOST_ARM) && IS_ARM_R(ch,LOST_ARM)) return FALSE;
	}
	else if (!str_cmp(arg,"hands"))
	{
		if (IS_ARM_L(ch,LOST_ARM) && IS_ARM_R(ch,LOST_ARM)) return FALSE;
		if (IS_ARM_L(ch,LOST_HAND) || IS_ARM_R(ch,LOST_HAND)) return FALSE;
	}
	else if (!str_cmp(arg,"legs"))
	{
		if (IS_LEG_L(ch,LOST_LEG) && IS_LEG_R(ch,LOST_LEG)) return FALSE;
	}
	else if (!str_cmp(arg,"feet"))
	{
		if (IS_LEG_L(ch,LOST_LEG) && IS_LEG_R(ch,LOST_LEG)) return FALSE;
		if (IS_LEG_L(ch,LOST_FOOT) || IS_LEG_R(ch,LOST_FOOT)) return FALSE;
	}
	return TRUE;
}

void do_qmake( CHAR_DATA *ch, char *argument )
{
	OBJ_INDEX_DATA *pObjIndex;
	OBJ_DATA *obj;
	char arg[MAX_INPUT_LENGTH];
	
	argument = one_argument( argument, arg );
	
	if (arg[0] == '\0')
	{
		send_to_char("Do you wish to qmake a MACHINE or a CARD?\n\r",ch);
		return;
	}
	if (!str_cmp(arg,"card"))
	{
		if ( (pObjIndex = get_obj_index( OBJ_VNUM_QUESTCARD )) == NULL)
		{
			send_to_char("Missing object, please inform Spiral\n\r",ch);
			return;
		}
		if (ch->in_room == NULL) return;
		obj = create_object(pObjIndex, 0);
		obj_to_char(obj, ch);
		quest_object(ch,obj);
	}
	else if (!str_cmp(arg,"machine"))
	{
		if ( (pObjIndex = get_obj_index( OBJ_VNUM_QUESTMACHINE )) == NULL)
		{
			send_to_char("Missing object, please inform Spiral\n\r",ch);
			return;
		}
		if (ch->in_room == NULL) return;
		obj = create_object(pObjIndex, 0);
		obj_to_room(obj, ch->in_room);
	}
	else
	{
		send_to_char("You can only qmake a MACHINE or a CARD.\n\r",ch);
		return;
	}
	send_to_char("Ok.\n\r",ch);
	return;
}

void do_recharge( CHAR_DATA *ch, char *argument )
{
	char buf[MAX_INPUT_LENGTH];
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	OBJ_DATA *qobj;
	int count = 0;
	int value = 1;
	
	argument = one_argument( argument, arg1 );
	argument = one_argument( argument, arg2 );
	
	if ( arg1[0] == '\0' || arg2[0] == '\0' )
	{
		send_to_char( "Syntax: recharge <quest card> <quest machine>\n\r", ch );
		return;
	}
	if ( (obj = get_obj_carry(ch,arg1)) == NULL )
	{
		send_to_char( "You are not carrying that object.\n\r", ch );
		return;
	}
	if (obj->item_type != ITEM_QUESTCARD)
	{
		send_to_char( "That is not a quest card.\n\r", ch );
		return;
	}
	if ( (qobj = get_obj_here(ch,arg2)) == NULL )
	{
		send_to_char( "There is nothing for you to recharge it with.\n\r", ch );
		return;
	}
	if (qobj->item_type != ITEM_QUESTMACHINE)
	{
		send_to_char( "That is not a quest machine.\n\r", ch );
		return;
	}
	if (obj->value[0] == -1) count += 1;
	if (obj->value[1] == -1) count += 1;
	if (obj->value[2] == -1) count += 1;
	if (obj->value[3] == -1) count += 1;
	if (count == 4) quest_object( ch, obj );
	else
	{
		send_to_char( "You have not yet completed the current quest.\n\r", ch );
		return;
	}
	act("You place $p into a small slot in $P.",ch,obj,qobj,TO_CHAR);
	act("$n places $p into a small slot in $P.",ch,obj,qobj,TO_ROOM);
	act("$P makes a few clicks and returns $p.",ch,obj,qobj,TO_CHAR);
	act("$P makes a few clicks and returns $p.",ch,obj,qobj,TO_ROOM);
	value = obj->level;
	if (value < 1) value = 1; else if (value > 100) value = 100;
	
	if ( dice(1,18) == 8 ) 
	{
		act("You notice a wierd {Bblue glow{x around the quest machine",ch,NULL,NULL,TO_CHAR);
		act("You notice a wierd {Bblue glow{x glow around the quest machine",ch,NULL,NULL,TO_ROOM);
		value = value + value;
	}

	obj = create_object(get_obj_index( OBJ_VNUM_PROTOPLASM ), 0);
	obj->value[0] = value;
	obj->level = value;
	obj->cost = value*1000;
	obj->item_type = ITEM_QUEST;
	obj_to_char(obj,ch);
	obj->questmaker = g_string_assign(obj->questmaker,ch->name->str);
	obj->name = g_string_assign(obj->name,"quest token");
	sprintf(buf,"a %d point quest token",value);
	obj->short_descr = g_string_assign(obj->short_descr,buf);
	sprintf(buf,"A %d point quest token lies on the floor.",value);
	obj->description = g_string_assign(obj->description,buf);
	act("You take $p from $P.",ch,obj,qobj,TO_CHAR);
	act("$n takes $p from $P.",ch,obj,qobj,TO_ROOM);
	
	do_autosave(ch,"");
	return;
}
// QUEST_TABLE
void quest_object( CHAR_DATA *ch, OBJ_DATA *obj )
{
	int i;
	static const sh_int quest_selection[] = 
	{
		1305,1306,1310,1311,1312,1313,1314,1317,1318,1319,1320,1326,1327,1328,
		1330,1335,1337,1341,1344,1345,1351,1355,1357,1363,1364,1365,1366,1367,
		1368,1369,1370,1371,1372,1376,1377,1378,1379,1380,1382,1383,1385,1386,
		1389,1390,1391,1392,1393,1395,1397,1398,1399,1502,1503,1504,1505,1506,
		1507,1508,1509,1652,1804,1805,1806,1807,1808,1810,2101,2102,2103,2104,
		2105,2107,2109,2110,2111,2112,2200,2201,2203,2211,2220,2222,2223,2242,
		2243,2244,2245,2246,2250,2251,2252,2254,2261,2270,2271,2280,2281,2285,
		2286,2301,2302,2303,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,
		2315,2316,2317,2318,2319,2320,2321,2323,2324,2325,2326,2327,2328,2329,
		2330,2334,2335,2336,2337,2338,2339,2340,2341,2343,2344,2345,2346,2347,
		2349,2360,2362,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,2380,
		2381,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2396,2400,
		2401,2402,2403,2404,2405,2406,2407,2416,2417,2418,2419,2420,2422,2423,
		2425,2427,2428,2429,2430,2431,2432,2448,2450,2454,2455,2456,2457,2458,
		2459,2460,2461,2462,2463,2464,2465,2466,2802,2803,2804,2805,2903,2904,
		2905,2906,2907,2911,2912,2914,3400,3403,3412,3413,3417,3421,3422,3426,
		3427,3429,3600,3601,3602,3605,3611,3612,3613,4500,4501,4502,4503,4504,
		4505,4506,4507,4508,4509,4510,4512,4702,4703,4704,4706,5000,
		5002,5003,5014,5016,5017,5018,5019,5020,5021,5025,5026,5027,5029,5031,
		5032,5100,5104,5108,5109,5111,5208,5210,5211,5215,5216,5217,5218,5219,
		5221,5222,5226,5231,5232,5233,5235,5237,5239,5241,5243,5250,5251,5252,
		5312,5313,5314,5315,5316,5317,5318,5320,5321,5327,5328,5329,5330,5331,
		5700,5701,5702,5703,5704,5800,5801,5802,5803,5810,5811,5812,5813,5814,
		5815,5817,5819,5820,5821,5901,5902,5904,5905,5906,5907,5908,5909,6000,
		6011,6013,6103,6104,6105,6107,6110,6111,6112,6114,6155,6303,6309,6504,
		6505,6508,6509,6510,6511,6518,6600,6621,6644,6645,6646,6647,6800,6801,
		6802,6803,6804,6805,6806,6807,6808,6809,6810,6811,6812,7800,7802,7803,
		7806,7807,8100,8101,8102,8103,8104,8107,8108,8110,8111,8115,8116,8117,
		8118,8121,8301,8302,8303,8307,8902,8904,8905,8910,8911,8913,8914,8915,
		8916,8917,8918,8919,9101,9102,9103,9104,9105,9202,9203,9204,9205,9206,
		9207,9208,9209,9210,9211,9212,9213,9214,9215,9216,9217,9218,9219,9220,
		9221,9222,9223,9224,9226,9227,9228,9229,9230,9231,9301,9304,9305,9306,
		9308,9309,9310,9312,9314,9315,9316,9318,9319,9320,9325,9326,9327,9328,
		10000,10001,10002,10003,10004,10005,10006,10007,10008,10009,10010,10012,
		10013,10014,10015,10016,10018,10019,10021,11010,11809,11810,11811,11812,
		11813,11814,11815,11816,11817,11818,11819,11820,11821,11822,11823,11824,
		11825,11826,11827,11828,11829,11830,11831,11832,11833,11834,11835,11836,
		11837,11838,11839,11840,11841,11842,11843,11844,11845,11846,11847,11848,
		11849,11850,11851,11852,11853,11854,11855,11856,11857,11858,11859,11860,
		11861,11862,11863,11864,11865,11866,11867,11868,11869,11870,11871,11872,
		11873,11874,11875,11876,11877,11878,11879,11880,11881,11882,11883,11884,
		11885,11886,11887,11888,11889,11890,11893,11894,11895,11896,11897,11898,
		12500,13230,13235,13237,13238,13240,13244,13245,13270,18000,18001,18002,
		18003,18005,18007,18008,18009,18010,18011,18012,18013,18014,18015,18016,
		18018,18019,18020,18022,18023,18024,18025,18026,18027,18028,18029,18030,
		18032,18033,18034,18035,18036,18037,18038,18039,18040,18041,18042,18043,
		18044,18045,18046,18047,18048,18049,18050,18052,18053,18054,18055,18056,
		18057,18058,18059,18060,18061,18063,18064,18065,18066,18067,18068,18069,
		18071,18072,18074,18075,18076,18077,18078,18080,18081,18082,18083,18085,
		18086,18099,18904,18906,18907,18908,18909,18910,18911,18912,18913,18914,
		18915,18916,18917,18918,18919,18920,18921,18923,18924,18927,19901,19902,
		19906,19907,19909,19913,19914,19915,19916,20016,20019,20020,20048,25000,
		25001,25002,25003,25004,25005,25006,25008,25009,25010,25011,25012,25013,
		25014,25015,25016,25017,25018,25019,25020,25021,25022,25023,25024,25025,
		25026,25027,25060,25061,25062,25080,25081,25082
	};
	
	
	int object;
	if (obj == NULL || obj->item_type != ITEM_QUESTCARD)
		return;
	for ( i = 0; i <= 3; i ++ )
	{
		object = number_range( 0, 294 );
		if (object < 1 || object > 294) object = 0;
		obj->value[i] = quest_selection[object];
	}
	return;
}

void do_complete( CHAR_DATA *ch, char *argument )
{
	char buf[MAX_STRING_LENGTH];
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	OBJ_DATA *qobj;
	OBJ_DATA *obj;
	OBJ_INDEX_DATA *pObjIndex;
	int count = 0;
	int count2 = 0;
	
	argument = one_argument( argument, arg1 );
	argument = one_argument( argument, arg2 );
	
	if ( arg1[0] == '\0' )
	{
		send_to_char( "Syntax: complete <quest card> <object>\n\r", ch );
		return;
	}
	
	if ( (qobj = get_obj_carry(ch,arg1)) == NULL )
	{
		send_to_char( "You are not carrying that object.\n\r", ch );
		return;
	}
	else if (qobj->item_type != ITEM_QUESTCARD)
	{
		send_to_char( "That is not a quest card.\n\r", ch );
		return;
	}
	if (qobj->value[0] == -1) count += 1;
	if (qobj->value[1] == -1) count += 1;
	if (qobj->value[2] == -1) count += 1;
	if (qobj->value[3] == -1) count += 1;
	
	if ( arg2[0] == '\0' )
	{
		if (count == 4) {send_to_char("{CThis quest card has been completed.{x\n\r",ch);return;}
		send_to_char("{CYou still need to find the following:{x\n\r",ch);
		if (qobj->value[0] != -1)
		{
			pObjIndex = get_obj_index( qobj->value[0] );
			if ( pObjIndex != NULL )
				sprintf(buf,"{c     %s.{x\n\r",pObjIndex->short_descr);
			else
				qobj->value[0] = -1;
			buf[5] = UPPER(buf[5]);send_to_char(buf,ch);
		}
		if (qobj->value[1] != -1)
		{
			pObjIndex = get_obj_index( qobj->value[1] );
			if ( pObjIndex != NULL )
				sprintf(buf,"{c     %s.{x\n\r",pObjIndex->short_descr);
			else
				qobj->value[1] = -1;
			buf[5] = UPPER(buf[5]);send_to_char(buf,ch);
		}
		if (qobj->value[2] != -1)
		{
			pObjIndex = get_obj_index( qobj->value[2] );
			if ( pObjIndex != NULL )
				sprintf(buf,"{c     %s.{x\n\r",pObjIndex->short_descr);
			else
				qobj->value[2] = -1;
			buf[5] = UPPER(buf[5]);send_to_char(buf,ch);
		}
		if (qobj->value[3] != -1)
		{
			pObjIndex = get_obj_index( qobj->value[3] );
			if ( pObjIndex != NULL )
				sprintf(buf,"{c     %s.{x\n\r",pObjIndex->short_descr);
			else
				qobj->value[3] = -1;
			buf[5] = UPPER(buf[5]);send_to_char(buf,ch);
		}
		return;
	}
	
	if (count == 4)
	{
		act( "{CBut $p has already been completed!{x",ch,qobj,NULL,TO_CHAR );
		return;
	}
	
	if ( (obj = get_obj_carry(ch,arg2)) == NULL )
	{
		send_to_char( "You are not carrying that object.\n\r", ch );
		return;
	}
	if (obj->questmaker != NULL && obj->questmaker->len > 1)
	{
		send_to_char( "You cannot use that item.\n\r", ch );
		return;
	}
	if (obj->pIndexData->vnum == 30037 || obj->pIndexData->vnum == 30041)
	{
		send_to_char( "That item has lost its quest value, you must collect a new one.\n\r", ch );
		return;
	}
	if (qobj->value[0] != -1)
	{
		pObjIndex = get_obj_index( qobj->value[0] );
		if ( pObjIndex != NULL &&
			!str_cmp(obj->short_descr->str, pObjIndex->short_descr))
			qobj->value[0] = -1;
	}
	if (qobj->value[1] != -1)
	{
		pObjIndex = get_obj_index( qobj->value[1] );
		if ( pObjIndex != NULL &&
			!str_cmp(obj->short_descr->str, pObjIndex->short_descr))
			qobj->value[1] = -1;
	}
	if (qobj->value[2] != -1)
	{
		pObjIndex = get_obj_index( qobj->value[2] );
		if ( pObjIndex != NULL &&
			!str_cmp(obj->short_descr->str, pObjIndex->short_descr))
			qobj->value[2] = -1;
	}
	if (qobj->value[3] != -1)
	{
		pObjIndex = get_obj_index( qobj->value[3] );
		if ( pObjIndex != NULL &&
			!str_cmp(obj->short_descr->str, pObjIndex->short_descr))
			qobj->value[3] = -1;
	}

	if (qobj->value[0] == -1) count2 += 1;
	if (qobj->value[1] == -1) count2 += 1;
	if (qobj->value[2] == -1) count2 += 1;
	if (qobj->value[3] == -1) count2 += 1;
	if (count == count2)
	{
		send_to_char( "{rThat item is not required.{x\n\r", ch );
		return;
	}
	
	act("{cYou touch {C$p {cto {C$P, {cand it vanishes!{x",ch,obj,qobj,TO_CHAR);
	act("{c$n touches {C$p {cto {C$P, {cand it vanishes!{c",ch,obj,qobj,TO_ROOM);
	obj_from_char(obj);
	extract_obj(obj);
	if (count >= 3) {act("$p has been completed!",ch,qobj,NULL,TO_CHAR);}
	else if (count == 2) {act("{Y$p now requires one more object!{x",ch,qobj,NULL,TO_CHAR);}
	else if (count == 1) {act("{Y$p now requires two more objects!{x",ch,qobj,NULL,TO_CHAR);}
	else if (count == 0) {act("{Y$p now requires three more objects!{x",ch,qobj,NULL,TO_CHAR);}
	if ( count >= 3)
		return;
	send_to_char("{CYou still need to find the following:{x\n\r",ch);
	if (qobj->value[0] != -1)
	{
		pObjIndex = get_obj_index( qobj->value[0] );
		if ( pObjIndex != NULL )
			sprintf(buf,"{c     %s.{x\n\r",pObjIndex->short_descr);
		else
			qobj->value[0] = -1;
		buf[5] = UPPER(buf[5]);send_to_char(buf,ch);
	}
	if (qobj->value[1] != -1)
	{pObjIndex = get_obj_index( qobj->value[1] );
	if ( pObjIndex != NULL )
		sprintf(buf,"{c     %s.{x\n\r",pObjIndex->short_descr);
	else
		qobj->value[1] = -1;
	buf[5] = UPPER(buf[5]);send_to_char(buf,ch);}
	if (qobj->value[2] != -1)
	{pObjIndex = get_obj_index( qobj->value[2] );
	if ( pObjIndex != NULL )
		sprintf(buf,"{c     %s.{x\n\r",pObjIndex->short_descr);
	else
		qobj->value[2] = -1;
	buf[5] = UPPER(buf[5]);send_to_char(buf,ch);}
	if (qobj->value[3] != -1)
	{pObjIndex = get_obj_index( qobj->value[3] );
	if ( pObjIndex != NULL )
		sprintf(buf,"{c     %s.{x\n\r",pObjIndex->short_descr);
	else
		qobj->value[3] = -1;
	buf[5] = UPPER(buf[5]);send_to_char(buf,ch);}
	return;
}

void do_sheath( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	
	one_argument(argument,arg);
	
	if (arg[0] == '\0') send_to_char("Which hand, left or right?\n\r",ch);
	else if (!str_cmp(arg,"all") || !str_cmp(arg,"both"))
	{
		sheath(ch,TRUE );
		sheath(ch,FALSE);
	}
	else if (!str_cmp(arg,"l") || !str_cmp(arg,"left" )) sheath(ch,FALSE);
	else if (!str_cmp(arg,"r") || !str_cmp(arg,"right")) sheath(ch,TRUE );
	else send_to_char("Which hand, left or right?\n\r",ch);
	return;
}

void do_draw( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	
	one_argument(argument,arg);
	
	if (!IS_NPC(ch) && IS_SET(ch->special, SPC_WOLFMAN))
	{
		send_to_char("Not in this form.\n\r",ch);
		return;
	}
	if (arg[0] == '\0') send_to_char("Which hand, left or right?\n\r",ch);
	else if (!str_cmp(arg,"all") || !str_cmp(arg,"both"))
	{
		draw(ch,TRUE );
		draw(ch,FALSE);
	}
	else if (!str_cmp(arg,"l") || !str_cmp(arg,"left" )) draw(ch,FALSE);
	else if (!str_cmp(arg,"r") || !str_cmp(arg,"right")) draw(ch,TRUE );
	else send_to_char("Which hand, left or right?\n\r",ch);
	return;
}

void sheath( CHAR_DATA *ch, bool right )
{
	OBJ_DATA *obj;
	OBJ_DATA *obj2;
	int scabbard;
	
	if (right)
	{
		scabbard = WEAR_SCABBARD_R;
		if ( (obj = get_eq_char(ch,WEAR_WIELD)) == NULL )
		{
			send_to_char("You are not holding anything in your right hand.\n\r",ch);
			return;
		}
		else if ( (obj2 = get_eq_char(ch,scabbard)) != NULL)
		{
			act("You already have $p in your right scabbard.",ch,obj2,NULL,TO_CHAR);
			return;
		}
		act("You slide $p into your right scabbard.",ch,obj,NULL,TO_CHAR);
		act("$n slides $p into $s right scabbard.",ch,obj,NULL,TO_ROOM);
	}
	else
	{
		scabbard = WEAR_SCABBARD_L;
		if ( (obj = get_eq_char(ch,WEAR_HOLD)) == NULL )
		{
			send_to_char("You are not holding anything in your left hand.\n\r",ch);
			return;
		}
		else if ( (obj2 = get_eq_char(ch,scabbard)) != NULL)
		{
			act("You already have $p in your left scabbard.",ch,obj2,NULL,TO_CHAR);
			return;
		}
		act("You slide $p into your left scabbard.",ch,obj,NULL,TO_CHAR);
		act("$n slides $p into $s left scabbard.",ch,obj,NULL,TO_ROOM);
	}
	if (obj->item_type != ITEM_WEAPON)
	{
		act("$p is not a weapon.",ch,obj,NULL,TO_CHAR);
		return;
	}
	unequip_char(ch,obj);
	obj->wear_loc = scabbard;
	return;
}

void draw( CHAR_DATA *ch, bool right )
{
	OBJ_DATA *obj;
	OBJ_DATA *obj2;
	int scabbard;
	int worn;
	if (right)
	{
		scabbard = WEAR_SCABBARD_R;
		worn = WEAR_WIELD;
		if ( (obj = get_eq_char(ch,scabbard)) == NULL )
		{
			send_to_char("Your right scabbard is empty.\n\r",ch);
			return;
		}
		else if ( (obj2 = get_eq_char(ch,WEAR_WIELD)) != NULL)
		{
			act("You already have $p in your right hand.",ch,obj2,NULL,TO_CHAR);
			return;
		}
		act("You draw $p from your right scabbard.",ch,obj,NULL,TO_CHAR);
		act("$n draws $p from $s right scabbard.",ch,obj,NULL,TO_ROOM);
	}
	else
	{
		scabbard = WEAR_SCABBARD_L;
		worn = WEAR_HOLD;
		if ( (obj = get_eq_char(ch,scabbard)) == NULL )
		{
			send_to_char("Your left scabbard is empty.\n\r",ch);
			return;
		}
		else if ( (obj2 = get_eq_char(ch,WEAR_HOLD)) != NULL)
		{
			act("You already have $p in your left hand.",ch,obj2,NULL,TO_CHAR);
			return;
		}
		act("You draw $p from your left scabbard.",ch,obj,NULL,TO_CHAR);
		act("$n draws $p from $s left scabbard.",ch,obj,NULL,TO_ROOM);
	}
	obj->wear_loc = -1;
	equip_char(ch,obj,worn);
	return;
}

void do_special( CHAR_DATA *ch, char *argument )
{
	char bname[MAX_INPUT_LENGTH];
	char bshort[MAX_INPUT_LENGTH];
	char blong[MAX_INPUT_LENGTH];
	char *kav;
	int dice = number_range(1,3);
	OBJ_DATA *obj;
	
	obj = create_object(get_obj_index( OBJ_VNUM_PROTOPLASM ), 0);
	
	kav = special_item_name( obj );
	
	switch ( dice )
	{
		default:
			sprintf(bname,"%s ring", kav);
			sprintf(bshort,"a %s ring", kav);
			sprintf(blong,"A %s ring lies here.", kav);
			obj->wear_flags = ITEM_WEAR_FINGER + ITEM_TAKE;
			break;
		case 1:
			sprintf(bname,"%s ring", kav);
			sprintf(bshort,"a %s ring", kav);
			sprintf(blong,"A %s ring lies here.", kav);
			obj->wear_flags = ITEM_WEAR_FINGER + ITEM_TAKE;
			break;
		case 2:
			sprintf(bname,"%s necklace", kav);
			sprintf(bshort,"a %s necklace", kav);
			sprintf(blong,"A %s necklace lies here.", kav);
			obj->wear_flags = ITEM_WEAR_NECK + ITEM_TAKE;
			break;
		case 3:
			sprintf(bname,"%s plate", kav);
			sprintf(bshort,"a suit of %s platemail", kav);
			sprintf(blong,"A suit of %s platemail lies here.", kav);
			obj->wear_flags = ITEM_WEAR_BODY + ITEM_TAKE;
			break;
	}
	
	if (obj->wear_flags == 513 || obj->wear_flags == 8193 || 
		obj->wear_flags == 16385)
	{
		obj->item_type = ITEM_WEAPON;
		obj->value[1] = 10;
		obj->value[2] = 20;
		obj->value[3] = number_range(1,12);
	}
	else
	{
		obj->item_type = ITEM_ARMOR;
		obj->value[0] = 15;
	}
	
	obj->level = 50;
	obj->cost = 100000;
	
	obj->questmaker = g_string_assign(obj->questmaker,ch->name->str);
	obj->name = g_string_assign(obj->name,bname);
	
	obj->short_descr = g_string_assign(obj->short_descr,bshort);
	obj->description = g_string_assign(obj->description,blong);
	
	obj_to_char(obj,ch);
	return;
}

char *special_item_name( OBJ_DATA *obj )
{
	static char buf[MAX_INPUT_LENGTH];
	int dice = number_range(1,4);
	switch ( dice )
	{
		default:
			str_cpy(buf,"golden");
			break;
		case 1:
			str_cpy(buf,"golden");
			break;
		case 2:
			str_cpy(buf,"silver");
			break;
		case 3:
			str_cpy(buf,"brass");
			break;
		case 4:
			str_cpy(buf,"copper");
			break;
	}
	return buf;
}

void do_filet (CHAR_DATA *ch, char *argument)
{
	OBJ_DATA *obj,*filet,*filet2, *corpse;
	char arg[MAX_INPUT_LENGTH];
	
	one_argument(argument,arg);
	
	if (( obj = get_eq_char( ch, WEAR_WIELD ) ) == NULL )
	{
		send_to_char("You must be wielding a blade weapon to make a filet.\n\r",ch);
		return;
	}
	if ( obj->item_type != ITEM_WEAPON && obj->value[3] != 1 && obj->value[3] != 3 )
	{
		send_to_char("You must be wielding a blade weapon to make a filet.\n\r",ch);
		return;
	}

	if ( ( corpse = get_obj_list( ch, arg, ch->in_room->contents )) == NULL )
	{
		send_to_char("You don't see a animal corpse to carve up.\n\r",ch);
		return;
	}
	if ( corpse->item_type == ITEM_CORPSE_NPC && IS_SET(corpse->extra_flags,ITEM_FILET))
	{
		filet = create_object(get_obj_index(OBJ_VNUM_FILET),0);
		filet2 = create_object(get_obj_index(OBJ_VNUM_FILET),0);
		filet->timer = 12;
		filet2->timer = 12;
		filet->item_type = ITEM_TFILET;
		filet2->item_type = ITEM_TFILET;
		obj_to_room(filet, ch->in_room);
		obj_to_room(filet2, ch->in_room);
	
		act("You carve up two nice juicy filets off of $p to cook later.",ch, corpse, NULL, TO_CHAR);
		act("$n carves up two nice juicy filets off of $p.",ch, corpse, NULL, TO_ROOM);
		extract_obj(corpse);
	}
}

void do_chop( CHAR_DATA *ch, char *argument )
{
	OBJ_DATA *obj,*wood;

	if (( obj = get_eq_char( ch, WEAR_WIELD ) ) == NULL )
	{
		send_to_char("You must be wielding a blade weapon to hack at trees.\n\r",ch);
		return;
	}
	if ( obj->item_type != ITEM_WEAPON && obj->value[3]  != 1 && obj->value[3]  != 3 )
	{
		send_to_char("You must be wielding a blade weapon to hack at trees.\n\r",ch);
		return;
	}
	if ( ch->in_room->sector_type != SECT_FOREST )
	{
		send_to_char("Hate to break this to you, but you don't see any trees.\n\r",ch);
		return;
	}
	act("You get to work chopping lumber from a near by tree.",ch,NULL,NULL,TO_CHAR);
	act("$n starts to make swinging motions at a near by tree.",ch,NULL,NULL,TO_ROOM);
	wood = create_object(get_obj_index(OBJ_VNUM_FIREWOOD),0);
	obj_to_room(wood,ch->in_room);

}

void do_make_fire( CHAR_DATA *ch, char *argument)
{
	OBJ_DATA *obj,*fire;
	int chance;

	if ( ( obj = get_obj_list( ch, "firewood", ch->in_room->contents ) ) == NULL )
        {
              send_to_char( "You are not carrying any firewood.\n\r", ch );
              return;
        }
	
	if ( ch->in_room->sector_type == SECT_CITY || ch->in_room->sector_type == SECT_INSIDE )
	{
		send_to_char("You can't start a fire here.\n\r",ch);
		return;
	}

	chance = number_range(1,4);
        switch (chance)
	{
		case 1:
			send_to_char("You hit two rocks together but produce no effect..\n\r",ch);
			act("$n hits two rocks together but produce no effect..",ch,NULL,NULL,TO_ROOM);
			return;
		case 2:
			send_to_char("You hit two rocks together and produce a spark.\n\r",ch);
			act("You hits two rocks together and produce a spark.",ch,NULL,NULL,TO_ROOM);
			return;
		case 3:
			send_to_char("You struggle trying to start your fire.\n\r",ch);
			return;
		case 4:
			break;
	}	
	send_to_char("Your spark ingnites your firewood into a small fire.\n\r",ch);
	act("$n starts a small fire.",ch,NULL,NULL,TO_ROOM);
	fire = create_object(get_obj_index(OBJ_VNUM_FIRE),0);
	fire->timer = 15;
	fire->item_type = ITEM_FIRE;
	obj_to_room(fire,ch->in_room);
	extract_obj(obj);
}

void do_cook (CHAR_DATA *ch, char *argument)
{
	OBJ_DATA *fire,*filet;
	int chance;
	
	if ( ( fire = get_obj_list( ch, "fire", ch->in_room->contents )) == NULL )
	{
		send_to_char("You seem to be missing a fire, get one started.\n\r",ch);
		return;
	}

	if ( fire->item_type == ITEM_FIRE )
	{
		if ( ( filet = get_obj_carry( ch, "filet" ) ) == NULL )
        	{
              		send_to_char( "You are not carrying any filets.\n\r", ch );
              		return;
        	}
		chance = number_range(1,4);
		if ( chance != 4 )
		{
			send_to_char("You cook your filet, but it doesn't look done.\n\r",ch);
			return;
		}
		filet->item_type = ITEM_FOOD;
		filet->value[0] = 20;
		filet->value[1] = 4;
		filet->timer = 12;
		send_to_char("You slowly cook your filet until it is golden brown.\n\r",ch);
		act("$n slowly cooks their $p until it is golden brown.",ch,filet,NULL,TO_ROOM);
	}
	else
		send_to_char("That's not a fire!\n\r",ch);	
}



void create_zombie(OBJ_DATA *obj)
{
	OBJ_DATA *obj_content,*obj_next;
	CHAR_DATA *victim;
	MOB_INDEX_DATA *pMobIndex;
	char buf[MAX_STRING_LENGTH];

	if ( ( pMobIndex = get_mob_index( obj->value[2] ) ) == NULL )
		return;
	
	victim = create_mobile( pMobIndex );
	char_to_room(victim,obj->in_room);
	sprintf(buf,"zombie %s",victim->name->str);
	sprintf(buf,"The zombie of %s stands here.\n\r",victim->short_descr->str);
	victim->long_descr = g_string_assign(victim->long_descr,buf);
	victim->name = g_string_assign(victim->name,buf);
	sprintf(buf,"the zombie of %s",victim->short_descr->str);
	victim->short_descr = g_string_assign(victim->short_descr,buf);
	act("$n clambers to $s feet.",victim,NULL,NULL,TO_ROOM);
	victim->powertype = g_string_assign(victim->powertype,"zombie");
	for ( obj_content = obj->contains; obj_content != NULL; obj_content = obj_next )
	{
		obj_next = obj_content->next_content;
		obj_from_obj(obj_content);
		obj_to_char(obj_content,victim);
	}
	extract_obj(obj);
	do_wear(victim,"all");
	str_cpy(buf,"Brains!!! I want Brains!");
	do_say(victim,buf);
	return;	
}

//Simple feed pet routine... might make changes
//for diffrent foods.. 
void do_petfeed ( CHAR_DATA *ch, char *argmuent)
{
    char arg[MSL];
    char arg1[MSL];
    char buf[MSL];
    CHAR_DATA *victim;
    OBJ_DATA *obj;

    argmuent = one_argument(argmuent,arg);
    argmuent = one_argument(argmuent,arg1);

    if ((victim = get_char_room(ch,arg)) == NULL)
    {
        send_to_char("There is no one to feed here!\n\r",ch);
        return;
    }

    if (!IS_NPC(victim) || (IS_NPC(victim) && !IS_PET(victim)))
    {
        send_to_char("They are not your PET!\n\r",ch);
        return;
    }
    
    if (victim != ch->pet || victim->pet_master != ch)
    {
        send_to_char("They are not your PET!\n\r",ch);
        return;
    }


    if ((obj = get_obj_carry(ch,arg1)) == NULL)
    {
        send_to_char("You are not carring that!\n\r",ch);
        return;
    }

    if (obj->item_type != ITEM_PET_FOOD)
    {
        send_to_char("Thats not pet food!\n\r",ch);
        return;
    }
    
    if (victim->pet_stats[PET_HUNGER] > 90)
    {
        send_to_char("They don't look hungry.\n\r",ch);
        return;
    }


    if (victim->pet_stats[PET_LAST_FCOUNT] >= 5)
    {
        do_say(victim,"I don't like that type of food anymore!");
        do_say(victim,"Please get me something else!");
        return;
    }

    if (obj->value[1] == victim->pet_stats[PET_LAST_FOOD])
        victim->pet_stats[PET_LAST_FCOUNT]++;

    sprintf(buf,"You feed your pet %s.\n\r",obj->short_descr->str);
    send_to_char(buf,ch);
    act("$n feeds $N something.",ch,NULL,victim,TO_ROOM);
    do_say(victim,"Thanks for the food!");
    victim->pet_stats[PET_LAST_FOOD] = obj->value[1];
    victim->pet_stats[PET_HUNGER] += obj->value[0];
    extract_obj(obj);

}

void do_petdrink(CHAR_DATA *ch, char *argument)
{
    CHAR_DATA *victim;
    char buf[MSL];
    char arg[MSL];
    char arg1[MSL];
    OBJ_DATA *obj;

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


    if ((victim = get_char_room(ch,arg)) == NULL)
    {
        send_to_char("There is no one to feed here!\n\r",ch);
        return;
    }

    if (!IS_NPC(victim) || (IS_NPC(victim) && !IS_PET(victim)))
    {
        send_to_char("They are not your PET!\n\r",ch);
        return;
    }
    
    if (victim != ch->pet || victim->pet_master != ch)
    {
        send_to_char("They are not your PET!\n\r",ch);
        return;
    }

    if ((obj = get_obj_carry(ch,arg1)) == NULL)
    {
        send_to_char("You are not carring that!\n\r",ch);
        return;
    }

    if (obj->item_type != ITEM_DRINK_CON)
    {
        send_to_char("Thats not a drink container!\n\r",ch);
        return;
    }
    if ( obj->value[1] <= 0 )
    {
        send_to_char( "It is already empty.\n\r", ch );
        return;
    }

    if (victim->pet_stats[PET_THIRST] > 90)
    {
        send_to_char("They don't look thirsty.\n\r",ch);
        return;
    }

    obj->value[1] -= 1;
    if ( obj->value[1] <= 0 )
    {
        obj->value[1] = 0;
    }

    victim->pet_stats[PET_THIRST] += 30;

    sprintf(buf,"You bend down and let %s drink from the container.\n\r",victim->short_descr->str);
    send_to_char(buf,ch);
    act("$n lets $N drink from something.",ch,NULL,victim,TO_ROOM);
    return;

}

void  do_slots(CHAR_DATA *ch, char *argument )
{
  OBJ_DATA            *slotMachine;
  char                buf[MAX_STRING_LENGTH];
  char                arg[MAX_INPUT_LENGTH];
  int counter, winArray[11];
  int cost, jackpot, bars, winnings, numberMatched;
  int bar1, bar2, bar3, bar4, bar5;
  bool partial, won, wonJackpot, frozen, foundSlot;

  char *bar_messages[] = {
    "<------------>",
    "{YGold Coin{x",               /* 1 */
    "{RLock Pick{x",
    "{MSembiance{x",               /* 3 */
    "{cCityguard{x",
    "{CElf Sword{x",               /* 5 */
    "{yAn Orange{x",
    "{rFly Spell{x",
    "{GElemental{x",
    "{WDualWield{x",
    "{BMudSchool{x",              /* 10 */
  };

  argument = one_argument(argument, arg);
  
  if(arg[0] == '\0')
    {
      send_to_char("Syntax: slots <which machine>\n\r", ch);
      return;
    }

  foundSlot = FALSE; 

  for (slotMachine = ch->in_room->contents; slotMachine != NULL; slotMachine = slotMachine->next_content)
    {
      if ( (slotMachine->item_type == ITEM_SLOT_MACHINE) && (can_see_obj(ch,slotMachine)))
	{
	  if(is_name(arg, slotMachine->name->str))
	    {
	      foundSlot = TRUE;
	      break;
	    }
	  else
	    {
	      foundSlot = FALSE;
	    }
	}
    }
  
  if (!IS_SET(mudsetting->mud_setting, MS_CASINO))
  {
      send_to_char("Sorry, the casino is closed!.\n\r",ch);
      return;
  }

  if(foundSlot == FALSE)
    {
      send_to_char("That slot machine is not here.\n\r", ch);
      return;
    }

  cost = slotMachine->value[0];
  if(cost <= 0)
    {
      send_to_char("This slot machine seems to be broken.\n\r", ch);
      return;
    }

  if(cost > ch->gold)
    {
      sprintf(buf, "This slot machine costs %d gold to play.\n\r", cost);
      send_to_char(buf, ch);
      return;
    }

  ch->gold -= cost;

  jackpot = slotMachine->value[1];
  bars = slotMachine->value[2];

  if(slotMachine->value[3] == 1)
    partial = TRUE;
  else
    partial = FALSE;

  //Freeze the amoutn paied off for now..-Spiral
  frozen = FALSE;

  bar1 = number_range( 1, 10 );
  bar2 = number_range( 1, 10 );
  bar3 = number_range( 1, 10 );
  if(bars > 3)
    {
      bar4 = number_range( 1, 10 );
      bar5 = number_range( 1, 10 );
    }
  else
    {
      bar4 = 0;
      bar5 = 0;
    }

  if(bars == 3)
    {
      send_to_char("{g////------------{MSlot Machine{g------------\\\\\\\\{x\n\r", ch);
      sprintf(buf, "{g|{C{{}{g|{x  %s  %s  %s  {h|{C{{}{g|{x\n\r", bar_messages[bar1],
	      bar_messages[bar2], bar_messages[bar3]);
      send_to_char(buf, ch);
      send_to_char("{g\\\\\\\\------------------------------------////{x\n\r", ch);
    }
  else
    {
      send_to_char("{g////-----------------------{MSlot Machine{g----------------------\\\\\\\\{x\n\r", ch);
      sprintf(buf, "{g|{C{{}{g|{x  %s  %s  %s  %s  %s  {g|{C{{}{g|{x\n\r", bar_messages[bar1],
	      bar_messages[bar2], bar_messages[bar3], bar_messages[bar4], bar_messages[bar5]);
      send_to_char(buf, ch);
      send_to_char("{g\\\\\\\\---------------------------------------------------------////{x\n\r",
		   ch);
    }

  wonJackpot = FALSE;
  winnings = 0;
  won = FALSE;
  numberMatched = 0;

  if(bars == 3)
    {
      if( (bar1 == bar2) && (bar2 == bar3) )
        {
          winnings = jackpot;  /* they won the jackpot, make it */
          won = TRUE;          /* worth their while!            */
          slotMachine->value[1] = cost*10;   /* put it back to something */
          wonJackpot = TRUE;
        }
      else
        {
          if(!frozen)
            slotMachine->value[1] += cost;
        }
    }
  else if(bars == 5)
    {
      if( (bar1 == bar2) && (bar2 == bar3) && (bar3 == bar4) && (bar4 == bar5) )
        {
          winnings = jackpot;  /* if no partial, better have a  */
          won = TRUE;          /* kick butt jackpot for them    */
          slotMachine->value[1] = cost*25;
          wonJackpot = TRUE;
        }
      else
        {
          if(!frozen)
            slotMachine->value[1] += cost;
        }
    }
  else
    {
      send_to_char("This is a bad slot machine. Contact casino administration.\n\r", ch);
      return;
    }
  if(!frozen)
    if(slotMachine->value[1] >= 32000)
      slotMachine->value[1] = 31000;

  for(counter = 0; counter <= 12; counter++)
    {
      winArray[counter] = 0;
    }


  if(!won && partial)
    {
      if(bars == 3)
        {
          if(bar1 == bar2)
            {
              winnings += cost/2;
              won = TRUE;
              numberMatched++;
            }
          if(bar1 == bar3)
            {
              numberMatched++;
              if(won)
                winnings += cost;
              else
                {
                  winnings += cost/2;
                  won = TRUE;
                }
            }
          if(bar2 == bar3)
            {
              numberMatched++;
              if(won)
                winnings += cost;
              else
                {
                  winnings += cost/2;
                  won = TRUE;
                }
            }
          if(!frozen)
            {
              if(!won)
                slotMachine->value[1] += cost;
              else
                slotMachine->value[1] -= winnings;
            }
        }
      if( bars == 5)
        {
          winArray[bar1]++;
          winArray[bar2]++;
          winArray[bar3]++;
          winArray[bar4]++;
          winArray[bar5]++;

          for(counter = 0; counter <= 12; counter++)
            {
              if(winArray[counter] > 1)
                numberMatched += winArray[counter];
            }

          if(numberMatched == 5)
            {
              if(!frozen)
                slotMachine->value[1] -= (cost*7)/2;
              winnings += cost*7;
            }
          if(numberMatched == 4)
            {
              if(!frozen)
                slotMachine->value[1] -= (cost*5)/2;
              winnings += cost*5;
            }
          if(numberMatched == 3)
            {
              winnings += cost/2;
              if(!frozen)
                slotMachine->value[1] += cost/2;
            }
          if(numberMatched == 2)
            {
              if(!frozen)
                slotMachine->value[1] += cost-1;
              winnings = 1;
            }
          if(numberMatched == 0)
            {
              winnings = 0;
              if(!frozen)
                slotMachine->value[1] += cost;
            }
          if(winnings > 0)
            won = TRUE;
        }
    }

  ch->gold += winnings;

  if(won && wonJackpot)
    {
      sprintf(buf, "You won the jackpot worth %d gold!! The jackpot now stands at %d gold.\n\r",
	      winnings, slotMachine->value[1]);
      send_to_char(buf, ch);
    }
  if(won && !wonJackpot)
    {
      sprintf(buf, "You matched %d bars and won %d gold! The jackpot is now worth %d gold.\n\r",
	      numberMatched, winnings, slotMachine->value[1]);
      send_to_char(buf, ch);
    }
  if(!won)
    {
      sprintf(buf, "Sorry you didn't win anything. The jackpot is now worth %d gold.\n\r",
	      slotMachine->value[1]);
      send_to_char(buf, ch);
    }

  if(slotMachine->value[1] >= 32000)
    slotMachine->value[1] = 31000;

  return;
}

void do_high_dice( CHAR_DATA *ch, char *argument)
{
  char                buf[MAX_STRING_LENGTH];
  char                arg[MAX_INPUT_LENGTH];
  CHAR_DATA           *dealer;
  int die, dealerDice, playerDice;
  int bet;
  
  argument = one_argument(argument, arg);

  if(arg[0] == '\0' || !is_number(arg))
    {
      send_to_char("Syntax is: highdice <bet>\n\r", ch);
      return;
    }

  bet = atoi(arg);

  if(bet < 10)
    {
      send_to_char("Minimum bet is 10 gold coins.\n\r", ch);
      return;
    }

  if(bet > 1000)
    {
      send_to_char("Maximum bet is 1,000 gold coins.\n\r", ch);
      return;
    }

  for ( dealer = ch->in_room->people; dealer; dealer = dealer->next_in_room )
    {
      if ( IS_NPC(dealer) && IS_SET(dealer->mob_con, MOBCON_DEALER) && can_see(ch,dealer))
	break;
    }
  
  if ( dealer == NULL )
    {
      send_to_char( "You do not see any dice dealer here.\n\r", ch );
      return;
    }

  if(bet > ch->gold)
    {
      send_to_char("You can not afford to bet that much!\n\r", ch);
      return;
    }

  dealerDice = 0;
  playerDice = 0;


  die = number_range(1, 6);
  dealerDice += die;
  die = number_range(1, 6);
  dealerDice += die;

  die = number_range(1, 6);
  playerDice += die;
  die = number_range(1, 6);
  playerDice += die;

  sprintf(buf, "{c%s{g rolled two dice with a total of {W%d!{x\n\r", dealer->short_descr->str, 
	  dealerDice);
  send_to_char(buf, ch);
  sprintf(buf, "{gYou rolled two dice with a total of {W%d!{x\n\r", playerDice);
  send_to_char(buf, ch);

  if(dealerDice > playerDice)
    {
      sprintf(buf, "{RYou lost! {c%s{g takes your bet of {y%d gold{g.{x\n\r",
	      dealer->short_descr->str, bet);
      send_to_char(buf, ch);
      ch->gold -= bet;
    }

  if(dealerDice < playerDice)
    {
      sprintf(buf, "{GYou won! {c%s {ggives you your winnings of {y%d gold{g.{x\n\r",
	      dealer->short_descr->str, bet);
      send_to_char(buf, ch);
      ch->gold += bet;
    }

  if(dealerDice == playerDice)
    {
      sprintf(buf, "{RYou lost! {gThe dealer always wins in a tie. You lose {y%d gold{g.{x\n\r",
	      bet);
      send_to_char(buf, ch);
      ch->gold -= bet;
    }

  return;
}