area/
build/testing/
log/
player/
player/backup/
#include <glib.h>
#include <sys/types.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

#include <merc.h>
#include <recycle.h>
#include <tables.h>

extern GMemChunk *obj_mem_chunk;
extern GMemChunk *extra_desc_mem_chunk;
extern bool			fBootDb;
extern char			str_empty	[1];

/*
 * Array of containers read for proper re-nesting of objects.
 */
static	OBJ_DATA *	rgObjNest[MAX_NEST];

extern GSList *obj_free;

OBJ_DATA *obj;

void init_obj(OBJ_DATA *obj)
{
	obj->OOwner		=	g_string_new("");
	obj->page_content	=	g_string_new("");
	obj->questowner		=	g_string_new("");
	obj->questmaker		=	g_string_new("");
	obj->victpoweruse	=	g_string_new("");
	obj->owner		=	g_string_new("");
	obj->victpoweroff	=	g_string_new("");
	obj->victpoweron	=	g_string_new("");
	obj->chpoweruse		=	g_string_new("");
	obj->chpoweroff		=	g_string_new("");
	obj->chpoweron		=	g_string_new("");
	obj->description	=	g_string_new("");
	obj->short_descr	=	g_string_new("");
	obj->name		=	g_string_new("");

}

/*
 * reset the Values after recycle.
 */
void reset_object( OBJ_DATA *obj )
{
	int x;

	obj->plane	=	0;
	obj->last_seen_on	=	0;
	for (x = 0; x < MAX_SPHERE; x++)
		obj->sphere[x]	=	0;
	for (x = 0; x < 4; x++)
		obj->value[x]		=	0;
	obj->timer	=	0;
	obj->level	=	0;
	obj->cost	=	0;
	obj->points	=	0;
	obj->quest	=	0;
	obj->resistance	=	0;
	obj->toughness	=	0;
	obj->condition	=	0;
	obj->specpower	=	0;
	obj->spectype	=	0;
	obj->weight	=	0;
	obj->wear_loc	=	0;
	obj->wear_flags	=	0;
	obj->extra_flags	=	0;
	obj->item_type	=	0;
	obj->mprog_delay	=	0;
	obj->mprog_target	=	NULL;
	obj->in_room	=	NULL;
	obj->pIndexData	=	NULL;
	obj->affected	=	NULL;
	obj->extra_descr	=	NULL;
	obj->chobj	=	NULL;
	obj->carried_by	=	NULL;
	obj->on	=	NULL;
	obj->in_obj	=	NULL;
	obj->contains	=	NULL;
	obj->next_content	=	NULL;

	obj->OOwner		=	g_string_assign(obj->OOwner,"");
	obj->page_content	=	g_string_assign(obj->page_content,"");
	obj->questowner		=	g_string_assign(obj->questowner,"");
	obj->questmaker		=	g_string_assign(obj->questmaker,"");
	obj->victpoweruse	=	g_string_assign(obj->victpoweruse,"");
	obj->owner		=	g_string_assign(obj->owner,"");
	obj->victpoweroff	=	g_string_assign(obj->victpoweroff,"");
	obj->victpoweron	=	g_string_assign(obj->victpoweron,"");
	obj->chpoweruse		=	g_string_assign(obj->chpoweruse,"");
	obj->chpoweroff		=	g_string_assign(obj->chpoweroff,"");
	obj->chpoweron		=	g_string_assign(obj->chpoweron,"");
	obj->description	=	g_string_assign(obj->description,"");
	obj->short_descr	=	g_string_assign(obj->short_descr,"");
	obj->name		=	g_string_assign(obj->name,"");


}

void set_rObjNest_null(){
	int iNest;
	
	for ( iNest = 0; iNest < MAX_NEST; iNest++ )
		rgObjNest[iNest] = NULL;
		
}

OBJ_DATA *new_obj(void)
{
	//static OBJ_DATA obj_zero;
	OBJ_DATA *obj;
	
	if (g_slist_length(obj_free) == 0)
	{
		obj = g_chunk_new (OBJ_DATA, obj_mem_chunk);
		init_obj(obj);
	}
	else
	{
		obj = (OBJ_DATA *)obj_free->data;
		obj_free = g_slist_remove(obj_free,obj);	
		mudsetting->objects_recycled++;
		mudsetting->Objects_Recycled_HEAP--;
	}
	
	//*obj = obj_zero;

	reset_object(obj);
	
	VALIDATE(obj);
	
	return obj;
}

void free_obj(OBJ_DATA *obj)
{
	if (!IS_VALID(obj))
		return;

	INVALIDATE(obj);
	obj_free = g_slist_append(obj_free,obj);
	mudsetting->Objects_Recycled_HEAP++;
	// Subject from objects created, and add to recycled
	mudsetting->objects_created--;
}

extern GSList *extra_descr_free;

EXTRA_DESCR_DATA *new_extra_descr(void)
{
	EXTRA_DESCR_DATA *ed;
	
	if (g_slist_length(extra_descr_free) == 0)
	{
		ed = g_chunk_new (EXTRA_DESCR_DATA, extra_desc_mem_chunk);
	}
	else
	{
		ed = (EXTRA_DESCR_DATA *)extra_descr_free->data;
		extra_descr_free = g_slist_remove(extra_descr_free,ed);	
	}
	
	ed->keyword = &str_empty[0];
	ed->description = &str_empty[0];
	VALIDATE(ed);
	return ed;
}

void free_extra_descr(EXTRA_DESCR_DATA *ed)
{
	if (!IS_VALID(ed))
		return;
	
	INVALIDATE(ed);
	
	extra_descr_free = g_slist_append(extra_descr_free,ed);
}

bool deadbeat(CHAR_DATA *ch, OBJ_DATA *obj)
{
	char buf[MAX_STRING_LENGTH];
	int min_out ,hour_out,i,objexpcost,objquestcost;
	bool found = FALSE;

	
	if (IS_IMMORTAL(ch))
		return FALSE;

	if ( !IS_SET(obj->quest, QUEST_ARTIFACT) ) 
		return FALSE;

	if ( copyover_start == TRUE )
		return FALSE;

	if (obj->last_seen_on == 0)
		return FALSE;

	sprintf(buf, "You logged out: %s",ctime(&obj->last_seen_on));
	write_to_buffer(ch->desc,buf,0);

        sprintf(buf, "The current time: %s",ctime(&current_time));
	send_to_char(buf,ch);

//	min_out = ( (int)time(0) - obj->last_seen_on ) / ( PULSE_PER_SECOND * 12 ); 
//	hour_out = (((int)time(0) - obj->last_seen_on ) / ( (PULSE_PER_SECOND * 12) * 60 )); 

	min_out =  ( (long)current_time - obj->last_seen_on ) / 60; 
	hour_out = (( (long)current_time - obj->last_seen_on ) / ( 60 * 60 )); 

	if ( hour_out > 0 )
		sprintf(buf,"Your artifact, %s  was logged out %d minutes ( %d hours)\n\r", obj->short_descr->str, min_out, hour_out);
	else
		sprintf(buf,"Your artifact, %s  was logged out %d minute(s)\n\r", obj->short_descr->str, min_out);
			
	send_to_char(buf,ch);

	/* find the artifact in the table to get cost */

	for(i = 0; i < 20; i++)
	{
		if (obj->pIndexData->vnum == rent_table[i].obj_vnum)
		{
			found = TRUE;
			break;
		}
	}

	if (!found)
	{
		bug("Artifact not found in the rent table!",0);
		return FALSE;
	}
	
	/* calculate cost, get hour rate */
	objexpcost = (rent_table[i].exp_cost / 24) * hour_out; 
	objquestcost = (rent_table[i].qp_cost / 24) * hour_out; 

	ch->exp = ch->exp - objexpcost;
	ch->pcdata->quest = ch->pcdata->quest - objquestcost;
	ch->pcdata->spent[SPENT_QP] += objquestcost;
	sprintf(buf,"You paid %d exp, %d Quest points to keep %s.\n\r",objexpcost,objquestcost,obj->short_descr->str);
	send_to_char(buf,ch);

	if ( ch->exp <= 0 )
	{
		send_to_char("You are a deadbeat for not having enough exp to pay for your artifact!\n\r",ch);
		return TRUE;
	}

	if ( ch->pcdata->quest <= 0 )
	{
		send_to_char("You are a deadbeat for not having enough quest points to pay for your artifact!\n\r",ch);
		return TRUE;
	}

	return FALSE;
}

/*
 * Write an object and its contents.
 */
void fwrite_obj( CHAR_DATA *ch, OBJ_DATA *obj, FILE *fp, int iNest )
{
	EXTRA_DESCR_DATA *ed;
	AFFECT_DATA *paf;
	int sn;
/*
    int vnum = obj->pIndexData->vnum;

     *
     * Slick recursion to write lists backwards,
     *   so loading them will load in forwards order.
     */
	if ( obj->next_content != NULL )
		fwrite_obj( ch, obj->next_content, fp, iNest );
	
    /*
     * Castrate storage characters.
     */
	
	if ( (obj->chobj != NULL && (!IS_NPC(obj->chobj) &&
		obj->chobj->pcdata->obj_vnum != 0)))
		return;
	
	fprintf( fp, "#OBJECT\n" );
	fprintf( fp, "Nest         %d\n",	iNest			     );
	fprintf( fp, "Name         %s~\n",	obj->name->str		     );
	fprintf( fp, "ShortDescr   %s~\n",	obj->short_descr->str	     );
	fprintf( fp, "Description  %s~\n",	obj->description->str	     );
	if (obj->chpoweron != NULL && strlen(obj->chpoweron->str) > 1 && str_cmp(obj->chpoweron->str,"(null)") )
		fprintf( fp, "Poweronch    %s~\n",	obj->chpoweron->str	     );
	if (obj->chpoweroff != NULL && strlen(obj->chpoweroff->str) > 1 && str_cmp(obj->chpoweroff->str,"(null)"))
		fprintf( fp, "Poweroffch   %s~\n",	obj->chpoweroff->str      );
	if (obj->chpoweruse != NULL && strlen(obj->chpoweruse->str) > 1 && str_cmp(obj->chpoweruse->str,"(null)"))
		fprintf( fp, "Powerusech   %s~\n",	obj->chpoweruse->str     );
	if (obj->victpoweron != NULL && strlen(obj->victpoweron->str) > 1 && str_cmp(obj->victpoweron->str,"(null)"))
		fprintf( fp, "Poweronvict  %s~\n",	obj->victpoweron->str     );
	if (obj->victpoweroff != NULL && strlen(obj->victpoweroff->str) > 1 && str_cmp(obj->victpoweroff->str,"(null)"))
		fprintf( fp, "Poweroffvict %s~\n",	obj->victpoweroff->str    );
	if (obj->victpoweruse != NULL && strlen(obj->victpoweruse->str) > 1 && str_cmp(obj->victpoweruse->str,"(null)"))
		fprintf( fp, "Powerusevict %s~\n",	obj->victpoweruse->str    );
	if (obj->page_content != NULL && obj->page_content->len > 1 && str_cmp(obj->page_content->str,"(null)"))
		fprintf( fp, "Page %s~\n",	obj->page_content->str   );
	if (obj->questmaker != NULL && strlen(obj->questmaker->str) > 1)
		fprintf( fp, "Questmaker   %s~\n",	obj->questmaker->str      );
	if (obj->questowner != NULL && strlen(obj->questowner->str) > 1)
		fprintf( fp, "Questowner   %s~\n",	obj->questowner->str      );
	if (obj->OOwner != NULL && strlen(obj->OOwner->str) > 1)
		fprintf( fp, "OOwner       %s~\n",	obj->OOwner->str 		     );


/*
    if ( vnum < 17 || ( vnum >= 30003 && vnum <= 30037 ) )
	fprintf( fp, "Vnum         %d\n",	obj->pIndexData->vnum     );
    else
	fprintf( fp, "Vnum         30041\n"			     );
*/
	fprintf( fp, "Vnum         %d\n",	obj->pIndexData->vnum	     );
	
	fprintf( fp, "ExtraFlags   %d\n",	obj->extra_flags	     );
	fprintf( fp, "WearFlags    %d\n",	obj->wear_flags		     );
	fprintf( fp, "WearLoc      %d\n",	obj->wear_loc		     );
	fprintf( fp, "ItemType     %d\n",	obj->item_type		     );
	
	if (IS_SET(obj->quest, QUEST_ARTIFACT) ) 
		//fprintf( fp, "Last_seen     %d\n",	(int)time(0))  );
		fprintf( fp, "Last_seen     %ld\n", (long)current_time  );

	fprintf( fp, "Weight       %d\n",	obj->weight		     );
	if (obj->spectype != 0)
		fprintf( fp, "Spectype     %d\n",	obj->spectype	     );
	if (obj->specpower != 0)
		fprintf( fp, "Specpower    %d\n",	obj->specpower	     );
	fprintf( fp, "Condition    %d\n",	obj->condition		     );
	fprintf( fp, "Toughness    %d\n",	obj->toughness		     );
	fprintf( fp, "Resistance   %d\n",	obj->resistance		     );
	if (obj->quest != 0)
		fprintf( fp, "Quest        %d\n",	obj->quest	     );
	if (obj->points != 0)
		fprintf( fp, "Points       %d\n",	obj->points
			);
	
	fprintf( fp, "NSphere  ");
	for ( sn = 0 ; sn < MAX_SPHERE ; sn++ )
	{
		fprintf( fp, " %d", obj->sphere[sn]);
	}
	fprintf( fp, "\n");
	
	fprintf( fp, "Plane        %d\n",	obj->plane		     );
	fprintf( fp, "Level        %d\n",	obj->level		     );
	fprintf( fp, "Timer        %d\n",	obj->timer		     );
	fprintf( fp, "Cost         %d\n",	obj->cost		     );
	fprintf( fp, "Values       %d %d %d %d\n",
		obj->value[0], obj->value[1], obj->value[2], obj->value[3]	     );
	
	switch ( obj->item_type )
	{
		case ITEM_POTION:
			if ( obj->value[1] > 0 )
			{
				fprintf( fp, "Spell 1      '%s'\n", 
					skill_table[obj->value[1]].name );
			}
			
			if ( obj->value[2] > 0 )
			{
				fprintf( fp, "Spell 2      '%s'\n", 
					skill_table[obj->value[2]].name );
			}
			
			if ( obj->value[3] > 0 )
			{
				fprintf( fp, "Spell 3      '%s'\n", 
					skill_table[obj->value[3]].name );
			}
			
			break;
			
		case ITEM_SCROLL:
			if ( obj->value[1] > 0 )
			{
				fprintf( fp, "Spell 1      '%s'\n", 
					skill_table[obj->value[1]].name );
			}
			
			if ( obj->value[2] > 0 )
			{
				fprintf( fp, "Spell 2      '%s'\n", 
					skill_table[obj->value[2]].name );
			}
			
			if ( obj->value[3] > 0 )
			{
				fprintf( fp, "Spell 3      '%s'\n", 
					skill_table[obj->value[3]].name );
			}
			
			break;
			
		case ITEM_PILL:
		case ITEM_STAFF:
		case ITEM_WAND:
			if ( obj->value[3] > 0 )
			{
				fprintf( fp, "Spell 3      '%s'\n", 
					skill_table[obj->value[3]].name );
			}
			
			break;
	}
	
	for ( paf = obj->affected; paf != NULL; paf = paf->next )
	{
/*
	if ( paf->type < 0 || paf->type >= MAX_SKILL ) continue;
*/
		fprintf( fp, "AffectData   %d %d %d\n",
			paf->duration, paf->modifier, paf->location );
	}
/*
    if ( vnum >= 17 && ( vnum < 30003 || vnum > 30037 ) )
    {
	for ( paf = obj->pIndexData->affected; paf != NULL; paf = paf->next )
	{
**
	    if ( paf->type < 0 || paf->type >= MAX_SKILL ) continue;
**
	    fprintf( fp, "AffectData   %d %d %d\n",
		paf->duration, paf->modifier, paf->location );
	}
    }
*/
	for ( ed = obj->extra_descr; ed != NULL; ed = ed->next )
	{
		fprintf( fp, "ExtraDescr   %s~ %s~\n",
			ed->keyword, ed->description );
	}
/*
    if ( vnum >= 17 && ( vnum < 30003 || vnum > 30037 ) )
    {
	for ( ed = obj->pIndexData->extra_descr; ed != NULL; ed = ed->next )
	{
	    fprintf( fp, "ExtraDescr   %s~ %s~\n",
		ed->keyword, ed->description );
	}
    }
*/
	fprintf( fp, "End\n\n" );
	
	if ( obj->contains != NULL )
		fwrite_obj( ch, obj->contains, fp, iNest + 1 );
	
	return;
}

void fread_obj( CHAR_DATA *ch, FILE *fp )
{
	//static OBJ_DATA obj_zero;
	OBJ_DATA *obj;
	char log[MAX_STRING_LENGTH];
	char *word;
	int dummy;
	int iNest;
	bool fMatch;
	bool fNest;
	bool fVnum;
	
	obj			= new_obj();
	obj->spectype		= 0;
	obj->last_seen_on 	= 0;
	obj->specpower		= 0;
	obj->condition		= 100;
	obj->toughness		= 0;
	obj->resistance	= 100;
	obj->quest		= 0;
	obj->points		= 0;
	obj->plane 		= 1;
	
        /*
	obj->sphere[0]          = 0;
	obj->sphere[1]          = 0;
	obj->sphere[2]          = 0;
	obj->sphere[3]          = 0;
	obj->sphere[4]          = 0;
	obj->sphere[5]          = 0;
	obj->sphere[6]          = 0;
	obj->sphere[7]          = 0;
	obj->sphere[8]          = 0;
        */
	
	fNest		= FALSE;
	fVnum		= TRUE;
	iNest		= 0;
	
	for ( ; ; )
	{
		word   = feof( fp ) ? (char *)"End" : fread_word( fp );
		fMatch = FALSE;
		
		switch ( UPPER(word[0]) )
		{
			case '*':
				fMatch = TRUE;
				fread_to_eol( fp );
				break;
				
			case 'A':
				if ( !str_cmp( word, "Affect" ) || !str_cmp( word, "AffectData" ) )
				{
					AFFECT_DATA *paf;
					
					paf = new_affect();	
					paf->type	= 0;
					paf->duration	= fread_number( fp );
					paf->modifier	= fread_number( fp );
					paf->location	= fread_number( fp );
					paf->bitvector	= 0;
					paf->next	= obj->affected;
					obj->affected	= paf;
					fMatch		= TRUE;
					break;
				}
				break;
				
			case 'C':
				KEY( "Condition",	obj->condition,		fread_number( fp ) );
				KEY( "Cost",	obj->cost,		fread_number( fp ) );
				break;
				
			case 'D':
				h_KEY( "Description",	obj->description,	nonfread_string(obj->description, fp ) );
				break;
				
			case 'E':
				KEY( "ExtraFlags",	obj->extra_flags,	fread_number( fp ) );
				
				if ( !str_cmp( word, "ExtraDescr" ) )
				{
					EXTRA_DESCR_DATA *ed;
					
					/*
					if ( extra_descr_free == NULL )
					{
						ed			= alloc_perm( sizeof(*ed) );
					}
					else
					{
						ed			= extra_descr_free;
						extra_descr_free	= extra_descr_free->next;
					}
					*/
					ed = new_extra_descr();
					
					ed->keyword		= fread_string( fp );
					ed->description		= fread_string( fp );
					ed->next		= obj->extra_descr;
					obj->extra_descr	= ed;
					fMatch = TRUE;
				}
				
				if ( !str_cmp( word, "End" ) )
				{
					if ( !fNest || !fVnum )
					{
						bug( "Fread_obj: incomplete object.", 0 );
						free_obj(obj);
						return;
					}
					else
					{
						g_slist_append(object_list,obj);
						
						obj->pIndexData->count++;

						/*** RENT PROC HERE **/
						if (!IS_IMMORTAL(ch))
						{
							if (deadbeat(ch,obj))
							{
								obj_to_char( obj, ch );
								unequip_char( ch, obj );
                                extract_obj(obj);
								strip_note(ch,obj);
								return;
							}
						}
						if ( iNest == 0 || rgObjNest[iNest] == NULL )
							obj_to_char( obj, ch );
						else
							obj_to_obj( obj, rgObjNest[iNest-1] );
						
						//Add to the values
						mudsetting->total_objects_created++ ;
						mudsetting->objects_created++;

						return;
					}
				}
				break;
				
			case 'I':
				KEY( "ItemType",	obj->item_type,		fread_number( fp ) );
				break;
				
			case 'L':
				KEY( "Level",	obj->level,		fread_number( fp ) );
				KEY( "Last_seen",obj->last_seen_on,		fread_number( fp ) );
				break;
				
			case 'N':
				h_KEY( "Name",	obj->name,		nonfread_string(obj->name, fp ) );
				
				if ( !str_cmp( word, "Nest" ) )
				{
					iNest = fread_number( fp );
					if ( iNest < 0 || iNest >= MAX_NEST )
					{
						bug( "Fread_obj: bad nest %d.", iNest );
					}
					else
					{
						rgObjNest[iNest] = obj;
						fNest = TRUE;
					}
					fMatch = TRUE;
				}
				if ( !str_cmp( word, "NSphere" ) )
				{
					for ( dummy = 0 ; dummy < MAX_SPHERE; dummy++ )
					{
						obj->sphere[dummy] = fread_number( fp );
					}
					fMatch = TRUE;
					break;
				}
				
				break;
			
			case 'O':
				h_KEY( "OOwner",	obj->OOwner,	nonfread_string(obj->OOwner, fp ) );
				break;
				
			case 'P':
				KEY( "Points",		obj->points,		fread_number( fp ) );
				KEY( "Plane",		obj->plane,		fread_number( fp ) );
				h_KEY( "Poweronch",	obj->chpoweron,	nonfread_string(obj->chpoweron, fp ) );
				h_KEY( "Poweroffch",	obj->chpoweroff,	nonfread_string(obj->chpoweroff, fp ) );
				h_KEY( "Powerusech",	obj->chpoweruse,	nonfread_string(obj->chpoweruse, fp ) );
				h_KEY( "Poweronvict",	obj->victpoweron,	nonfread_string(obj->victpoweron, fp ) );
				h_KEY( "Poweroffvict",	obj->victpoweroff,	nonfread_string(obj->victpoweroff, fp ) );
				h_KEY( "Powerusevict",	obj->victpoweruse,	nonfread_string(obj->victpoweruse, fp ) );
				h_KEY( "Page",	obj->page_content,	nonfread_string(obj->page_content, fp ) );
				break;
				
			case 'Q':
				KEY( "Quest",	obj->quest,		fread_number( fp ) );
				KEY( "Qtimer",        ch->countdown,	fread_number( fp ) );
				h_KEY( "Questmaker",	obj->questmaker,	nonfread_string(obj->questmaker, fp ) );
				h_KEY( "Questowner",	obj->questowner,	nonfread_string(obj->questowner, fp ) );
				break;
				
			case 'R':
				KEY( "Resistance",	obj->resistance,	fread_number( fp ) );
				break;
				
			case 'S':
				h_KEY( "ShortDescr",	obj->short_descr,	nonfread_string(obj->short_descr, fp ) );
				KEY( "Spectype",	obj->spectype,		fread_number( fp ) );
				KEY( "Specpower",	obj->specpower,		fread_number( fp ) );
				
				if ( !str_cmp( word, "Spell" ) )
				{
					int iValue;
					int sn;
					
					iValue = fread_number( fp );
					sn     = skill_lookup( fread_word( fp ) );
					if ( iValue < 0 || iValue > 3 )
					{
						bug( "Fread_obj: bad iValue %d.", iValue );
					}
					else if ( sn < 0 )
					{
						bug( "Fread_obj: unknown skill.", 0 );
					}
					else
					{
						obj->value[iValue] = sn;
					}
					fMatch = TRUE;
					break;
				}
				
				if ( !str_cmp( word, "Sphere" ) )
				{
					for ( dummy = 0 ; dummy < (MAX_SPHERE -1 ); dummy++ )
					{
						obj->sphere[dummy] = fread_number( fp );
					}
					fMatch = TRUE;
					break;
				}

				break;
				
			case 'T':
				KEY( "Timer",	obj->timer,		fread_number( fp ) );
				KEY( "Toughness",	obj->toughness,		fread_number( fp ) );
				break;
				
			case 'V':
				if ( !str_cmp( word, "Values" ) )
				{
					obj->value[0]	= fread_number( fp );
					obj->value[1]	= fread_number( fp );
					obj->value[2]	= fread_number( fp );
					obj->value[3]	= fread_number( fp );
					fMatch		= TRUE;
					break;
				}
				
				if ( !str_cmp( word, "Vnum" ) )
				{
					int vnum;
					
					vnum = fread_number( fp );
					if ( ( obj->pIndexData = get_obj_index( vnum ) ) == NULL )
					{
						vnum = 30041;
						if ( ( obj->pIndexData = get_obj_index( vnum ) ) == NULL )
							bug( "Fread_obj: bad vnum %d.", vnum );
						else
							fVnum = TRUE;
					}
					else
						fVnum = TRUE;
					fMatch = TRUE;
					break;
				}
				break;
				
			case 'W':
				KEY( "WearFlags",	obj->wear_flags,	fread_number( fp ) );
				KEY( "WearLoc",	obj->wear_loc,		fread_number( fp ) );
				KEY( "Weight",	obj->weight,		fread_number( fp ) );
				break;
				
		}
		if (Player_Error == TRUE)
		{
			write_to_buffer(ch->desc,"Your pfilE has a problem, please note Spiral or Dominion with another char",0);
			sprintf(log,"Pfile error in player %s",ch->name->str);	
			log_string2(log);
			logchan(log_buf, NULL, NULL,WIZ_LINK,0, LEVEL_QUESTMAKER);
			close_socket(ch->desc);
		    Player_Load = FALSE;
			return;
		}
		
		if ( !fMatch )
		{
			bug( "Fread_obj: no match.", 0 );
			fread_to_eol( fp );
		}
	}
	//Init object
	if (obj->OOwner->str[0] == '\0' && obj->questowner->str[0] != '\0')
		obj->OOwner = obj->questowner;
}
/*
 * Create an instance of an object.
 */
OBJ_DATA *create_object( OBJ_INDEX_DATA *pObjIndex, int level )
{
	//static OBJ_DATA obj_zero;
	OBJ_DATA *obj;
	
	if ( pObjIndex == NULL )
	{
		bug( "Create_object: NULL pObjIndex.", 0 );
		exit( 1 );  
	}

	obj             = new_obj();
	obj->pIndexData	= pObjIndex;
	obj->in_room	= NULL;
	obj->level		= level;
	obj->wear_loc	= -1;
	
	obj->contains	= NULL;
	obj->affected	= NULL;
	obj->name		= g_string_assign(obj->name,pObjIndex->name);
	obj->short_descr	= g_string_assign(obj->short_descr,pObjIndex->short_descr);
	obj->description	= g_string_assign(obj->description,pObjIndex->description);
	
	if (pObjIndex->chpoweron != NULL)
	{
		obj->chpoweron    = g_string_assign(obj->chpoweron,pObjIndex->chpoweron);
		obj->chpoweroff   = g_string_assign(obj->chpoweroff,pObjIndex->chpoweroff);
		obj->chpoweruse   = g_string_assign(obj->chpoweruse,pObjIndex->chpoweruse);
		obj->victpoweron  = g_string_assign(obj->victpoweron,pObjIndex->victpoweron);
		obj->victpoweroff = g_string_assign(obj->victpoweroff,pObjIndex->victpoweroff);
		obj->victpoweruse = g_string_assign(obj->victpoweruse,pObjIndex->victpoweruse);
		obj->spectype     = pObjIndex->spectype;
		obj->specpower    = pObjIndex->specpower;
	}
	else
	{
		obj->chpoweron    = g_string_assign(obj->chpoweron, "(null)" );
		obj->chpoweroff   = g_string_assign(obj->chpoweroff, "(null)" );
		obj->chpoweruse   = g_string_assign(obj->chpoweruse, "(null)" );
		obj->victpoweron  = g_string_assign(obj->victpoweron, "(null)" );
		obj->victpoweroff = g_string_assign(obj->victpoweroff, "(null)" );
		obj->victpoweruse = g_string_assign(obj->victpoweruse, "(null)" );
		obj->spectype     = 0;
		obj->specpower    = 0;
	}
	obj->questmaker     = g_string_assign(obj->questmaker, "" );
	obj->questowner     = g_string_assign(obj->questowner, "" );
	obj->page_content     = g_string_assign(obj->page_content, "" );
	obj->OOwner     = g_string_assign(obj->OOwner,"");
	obj->owner		= g_string_assign(obj->owner,"");
	obj->chobj		= NULL;
	
	obj->quest		= 0;
	obj->points		= 0;
	
	obj->item_type	= pObjIndex->item_type;
	obj->extra_flags	= pObjIndex->extra_flags;
	obj->wear_flags	= pObjIndex->wear_flags;
	obj->value[0]	= pObjIndex->value[0];
	obj->value[1]	= pObjIndex->value[1];
	obj->value[2]	= pObjIndex->value[2];
	obj->value[3]	= pObjIndex->value[3];
	obj->weight		= pObjIndex->weight;
	obj->plane 		= 1;
	obj->cost		= number_fuzzy( 10 )
		* number_fuzzy( level ) * number_fuzzy( level );
	
	if (obj->pIndexData->vnum >= 29500 && obj->pIndexData->vnum <= 29599)
	{
		SET_BIT(obj->quest, QUEST_ARTIFACT);
		obj->condition	= 100;
		obj->toughness	= 100;
		obj->resistance	= 1;
		obj->level	= 60;
		obj->cost	= 1000000;
	}
	else if (obj->pIndexData->vnum >= 29600 && obj->pIndexData->vnum <= 29699)
	{
		SET_BIT(obj->quest, QUEST_RELIC);
		obj->condition	= 100;
		obj->toughness	= 100;
		obj->resistance	= 1;
	}
	else if (obj->pIndexData->vnum == 30042)
	{
		SET_BIT(obj->quest, QUEST_MASTERY);
		obj->condition	= 100;
		obj->toughness	= 100;
		obj->resistance	= 1;
	}
	else
	{
		obj->condition	= 100;
		obj->toughness	= 5;
		obj->resistance	= 25;
	}
	
    /*
     * Mess with object properties.
     */
	switch ( obj->item_type )
	{
		default:
			bug( "Read_object: vnum %d bad type.", pObjIndex->vnum );
			break;
			
		case ITEM_LIGHT:
		case ITEM_TREASURE:
		case ITEM_FURNITURE:
		case ITEM_TRASH:
		case ITEM_CONTAINER:
		case ITEM_DRINK_CON:
		case ITEM_KEY:
		case ITEM_FOOD:
		case ITEM_BOAT:
		case ITEM_CORPSE_NPC:
		case ITEM_CORPSE_PC:
		case ITEM_FOUNTAIN:
		case ITEM_PORTAL:
		case ITEM_EGG:
		case ITEM_VOODOO:
		case ITEM_STAKE:
		case ITEM_MISSILE:
		case ITEM_AMMO:
		case ITEM_QUEST:
		case ITEM_QUESTCARD:
		case ITEM_QUESTMACHINE:
		case ITEM_SYMBOL:
		case ITEM_BOOK:
		case ITEM_PAGE:
		case ITEM_TOOL:
		case ITEM_FOCI:
		case ITEM_COOKIE:
		case ITEM_TFILET:
		case ITEM_FIRE:
		case ITEM_WALL:
		case ITEM_SUNSHIELD:
		case ITEM_PET_FOOD:
		case ITEM_WWF_CONT:
		
			break;
			
		case ITEM_SCROLL:
			obj->value[0]	= number_fuzzy( obj->value[0] );
			break;
			
		case ITEM_WAND:
        case ITEM_STAFF:
			obj->value[0]	= number_fuzzy( obj->value[0] );
			obj->value[1]	= number_fuzzy( obj->value[1] );
			obj->value[2]	= obj->value[1];
			break;
			
		case ITEM_WEAPON:
			if (!IS_SET(obj->quest, QUEST_ARTIFACT)
				&& !IS_SET(obj->quest, QUEST_RELIC))
			{
				obj->value[1]	= number_range( 1, 10 );
				obj->value[2]	= number_range((obj->value[1]+1),(obj->value[1]*2));
			}
			break;
		
        case ITEM_SLOT_MACHINE:
            if (obj->value[2] > 5)
               obj->value[2] = 5;
            else if(obj->value[2] < 3)
             obj->value[2] = 3;
            break;

		case ITEM_ARMOR:
			if (!IS_SET(obj->quest, QUEST_ARTIFACT)
				&& !IS_SET(obj->quest, QUEST_RELIC))
				obj->value[0]	= number_range( 5, 15 );
			break;
			
		case ITEM_POTION:
		case ITEM_PILL:
			obj->value[0]	= number_fuzzy( number_fuzzy( obj->value[0] ) );
			break;
			
		case ITEM_MONEY:
			obj->value[0]	= obj->cost;
			break;
	}
	
	object_list = g_slist_append(object_list,obj);
	pObjIndex->count++;
	
	//Add the total objects -- Spiral
	mudsetting->total_objects_created++;
	mudsetting->objects_created++;

	return obj;
}
/*
 * Translates mob virtual number to its obj index struct.
 * Hash table lookup.
 */
OBJ_INDEX_DATA *get_obj_index( int vnum )
{
	OBJ_INDEX_DATA *pObjIndex;
	
	for ( pObjIndex  = obj_index_hash[vnum % MAX_KEY_HASH];
		pObjIndex != NULL;
		pObjIndex  = pObjIndex->next )
	{
		if ( pObjIndex->vnum == vnum )
			return pObjIndex;
	}
	
	if ( fBootDb )
	{
		bug( "Get_obj_index: bad vnum %d.", vnum );
		exit( 1 );
	}
	
	return NULL;
}

/*
 * Move an object into an object.
 */
void obj_to_obj( OBJ_DATA *obj, OBJ_DATA *obj_to )
{
	if (obj == NULL) return;
	obj->next_content		= obj_to->contains;
	obj_to->contains		= obj;
	obj->in_obj			= obj_to;
	obj->in_room		= NULL;
	obj->carried_by		= NULL;
	
	for ( ; obj_to != NULL; obj_to = obj_to->in_obj )
	{
		if ( obj_to->carried_by != NULL && !IS_SET(obj_to->spectype,SITEM_MORPH))
			obj_to->carried_by->carry_weight += get_obj_weight( obj );
	}
	
	return;
}