/***************************************************************************
* 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;
}