/***************************************************************************
 *  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 <sys/types.h>
#include <stdio.h>
#include <string.h>
#include "merc.h"
extern	int	_filbuf		args( (FILE *) );



/*
 * Local functions.
 */
void	save_char_internal	args( ( CHAR_DATA *ch, FILE *fp ) );
void	save_obj_internal	args( ( CHAR_DATA *ch, FILE *fp ) );
void	load_char_internal	args( ( CHAR_DATA *ch, FILE *fp ) );
void	load_obj_internal	args( ( CHAR_DATA *ch, FILE *fp ) );



/*
 * Save a character and inventory.
 * Would be cool to save NPC's too for quest purposes.
 */
void save_char_obj( CHAR_DATA *ch )
{
    char strsave[MAX_INPUT_LENGTH];
    FILE *fp;

    if ( IS_NPC(ch) || ch->level < 2 )
	return;

    if ( ch->desc != NULL && ch->desc->original != NULL )
	ch = ch->desc->original;

    ch->save_time = current_time;
    fclose( fpReserve );
    sprintf( strsave, "%s%s", PLAYER_DIR, capitalize( ch->name ) );
    if ( ( fp = fopen( strsave, "w" ) ) == NULL )
    {
	bug( "Save_char_obj: fopen", 0 );
	perror( strsave );
    }
    else
    {
	save_char_internal( ch, fp );
	save_obj_internal(  ch, fp );
    }

    fclose( fp );
    fpReserve = fopen( NULL_FILE, "r" );
    return;
}



/*
 * Save the character.
 */
void save_char_internal( CHAR_DATA *ch, FILE *fp )
{
    AFFECT_DATA *paf;
    int sn;
    bool fsn;

    fprintf( fp, "#PLAYER\n" );
    fprintf( fp, "Name         %s~\n",	ch->name		);
    fprintf( fp, "Password     %s~\n",	ch->pwd			);
    fprintf( fp, "ShortDescr   %s~\n",	ch->short_descr		);
    fprintf( fp, "LongDescr    %s~\n",	ch->long_descr		);
    fprintf( fp, "Description\n%s~\n",	ch->description		);
    fprintf( fp, "Title        %s~\n",	ch->title		);
    fprintf( fp, "Poofin       %s~\n",	ch->poofin		);
    fprintf( fp, "Poofout      %s~\n",	ch->poofout		);
    fprintf( fp, "Sex          %d\n",	ch->sex			);
    fprintf( fp, "Class        %s\n",
	IS_NPC(ch) ? "Mob" : class_table[ch->class].who_name		     );
    fprintf( fp, "Level        %d\n",	ch->level		);
    fprintf( fp, "Played       %d\n",
	ch->played + current_time - ch->logon			);
    fprintf( fp, "Rnum         %d\n",	ch->rnum		);
    fprintf( fp, "Room         %d\n",
	room_index[ch->in_room<2 ? ch->was_in_room : ch->in_room].vnum	     );

    if ( !IS_NPC(ch) )
    {
	fprintf( fp, "PermAttr     %d %d %d %d %d\n",
	    ch->pcdata->perm_str,
	    ch->pcdata->perm_int,
	    ch->pcdata->perm_wis,
	    ch->pcdata->perm_dex,
	    ch->pcdata->perm_con );
	fprintf( fp, "ModAttr      %d %d %d %d %d\n",
	    ch->pcdata->mod_str, 
	    ch->pcdata->mod_int, 
	    ch->pcdata->mod_wis,
	    ch->pcdata->mod_dex, 
	    ch->pcdata->mod_con );
    }

    fprintf( fp, "Hp           %d %d\n", ch->hit,  ch->max_hit	);
    fprintf( fp, "Mana         %d %d\n", ch->mana, ch->max_mana	);
    fprintf( fp, "Move         %d %d\n", ch->move, ch->max_move	);
    fprintf( fp, "Gold         %d\n",	ch->gold		);
    fprintf( fp, "Exp          %d\n",	ch->exp			);
    fprintf( fp, "Act          %d\n",   ch->act			);
    fprintf( fp, "AffectedBy   %d\n",	ch->affected_by		);
    fprintf( fp, "Position     %d\n",	ch->position		);
    fprintf( fp, "Practice     %d\n",	ch->practice		);
    fprintf( fp, "CarryWeight  %d\n",	ch->carry_weight	);
    fprintf( fp, "CarryNumber  %d\n",	ch->carry_number	);
    fprintf( fp, "SavingThrow  %d\n",	ch->saving_throw	);
    fprintf( fp, "Alignment    %d\n",	ch->alignment		);
    fprintf( fp, "Hitroll      %d\n",	ch->hitroll		);
    fprintf( fp, "Damroll      %d\n",	ch->damroll		);
    fprintf( fp, "Armor        %d\n",	ch->armor		);
    fprintf( fp, "Wimpy        %d\n",	ch->wimpy		);

    if ( !IS_NPC(ch) )
    {
	fprintf( fp, "Condition    %d %d %d\n",
	    ch->pcdata->condition[0],
	    ch->pcdata->condition[1],
	    ch->pcdata->condition[2] );
    }

    fprintf( fp, "\n" );

    if ( !IS_NPC(ch) )
    {
	fsn = FALSE;
	for ( sn = 0; sn < MAX_SKILL; sn++ )
	{
	    if ( skill_table[sn].name != NULL && ch->pcdata->learned[sn] > 0 )
	    {
		fsn = TRUE;
		fprintf( fp, "Skill        %d '%s'\n",
		    ch->pcdata->learned[sn], skill_table[sn].name );
	    }
	}
	if ( fsn )
	    fprintf( fp, "\n" );
    }

    if ( ch->affected != NULL )
    {
	for ( paf = ch->affected; paf != NULL; paf = paf->next )
	{
	    fprintf( fp, "Affect %3d %3d %3d %3d %10d\n",
		paf->type,
		paf->duration,
		paf->modifier,
		paf->location,
		paf->bitvector
		);
	}
	fprintf( fp, "\n" );
    }

    return;
}



/*
 * Save the objects.
 * Contents of containers are NOT saved, this hoses weight too.
 * We don't care much as we don't want player-carryable containers anyways.
 */
void save_obj_internal( CHAR_DATA *ch, FILE *fp )
{
    EXTRA_DESCR_DATA *ed;
    AFFECT_DATA *paf;
    OBJ_DATA *obj;

    for ( obj = ch->carrying; obj != NULL; obj = obj->next_content )
    {
	/*
	 * Castrate storage characters.
	 */
	if ( ch->level < obj->level
	||   obj->item_type == ITEM_KEY
	||   obj->item_type == ITEM_POTION )
	    continue;

	fprintf( fp, "#OBJECT\n" );
	fprintf( fp, "Name         %s~\n",	obj->name		     );
	fprintf( fp, "ShortDescr   %s~\n",	obj->short_descr	     );
	fprintf( fp, "Description  %s~\n",	obj->description	     );
	fprintf( fp, "Vnum         %d\n",	obj_index[obj->rnum].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		     );
	fprintf( fp, "Weight       %d\n",	obj->weight		     );
	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:
	case ITEM_SCROLL:
	    if ( obj->value[1] > 0 )
	    {
		fprintf( fp, "Spell        '%s'\n", 
		    skill_table[obj->value[1]].name );
	    }

	    if ( obj->value[2] > 0 )
	    {
		fprintf( fp, "Spell        '%s'\n", 
		    skill_table[obj->value[2]].name );
	    }

	    if ( obj->value[3] > 0 )
	    {
		fprintf( fp, "Spell        '%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        '%s'\n", 
		    skill_table[obj->value[3]].name );
	    }

	    break;
	}

	for ( paf = obj->affected; paf != NULL; paf = paf->next )
	{
	    fprintf( fp, "Affect       %d %d %d %d %d\n",
		paf->type,
		paf->duration,
		paf->modifier,
		paf->location,
		paf->bitvector
		);
	}

	for ( ed = obj->ex_description; ed != NULL; ed = ed->next )
	{
	    fprintf( fp, "ExtraDescr   %s %s~\n",
		ed->keyword, ed->description );
	}

	fprintf( fp, "\n" );
    }

    return;
}



/*
 * Load a char and inventory into a new ch structure.
 */
bool load_char_obj( DESCRIPTOR_DATA *d, char *name )
{
    static PC_DATA pcdata_zero;
    char strsave[MAX_INPUT_LENGTH];
    CHAR_DATA *ch;
    FILE *fp;
    bool found;

    if ( char_free == NULL )
    {
	ch				= alloc_mem( sizeof(*ch) );
    }
    else
    {
	ch				= char_free;
	char_free			= char_free->next;
    }

    clear_char( ch );
    d->character			= ch;
    ch->desc				= d;
    ch->name				= str_dup( name );
    ch->pcdata				= alloc_mem( sizeof(*ch->pcdata) );
    *ch->pcdata				= pcdata_zero;
    ch->pcdata->perm_str		= 13;
    ch->pcdata->perm_int		= 13; 
    ch->pcdata->perm_wis		= 13;
    ch->pcdata->perm_dex		= 13;
    ch->pcdata->perm_con		= 13;
    ch->pcdata->condition[COND_THIRST]	= 24;
    ch->pcdata->condition[COND_FULL]	= 24;

    found = FALSE;
    fclose( fpReserve );
    sprintf( strsave, "%s%s", PLAYER_DIR, capitalize( name ) );
    if ( ( fp = fopen( strsave, "r" ) ) != NULL )
    {
#if 0
	found = TRUE;
#endif
	load_char_internal( ch, fp );
	load_obj_internal(  ch, fp );
	fclose( fp );
    }

    fpReserve = fopen( NULL_FILE, "r" );
    return found;
}



void load_char_internal( CHAR_DATA *ch, FILE *fp )
{
    return;
}



void load_obj_internal( CHAR_DATA *ch, FILE *fp )
{
    return;
}