/*___________________________________________________________________________*
)()( DalekenMUD 1.12 (C) 2000 )()(
`][' by Martin Thomson, Lee Brooks, `]['
|| Ken Herbert and David Jacques ||
|| ----------------------------------------------------------------- ||
|| Envy Diku Mud improvements copyright (C) 1994 by Michael Quan, ||
|| David Love, Guilherme 'Willie' Arnold, and Mitchell Tse. ||
|| Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael ||
|| Chastain, Michael Quan, and Mitchell Tse. ||
|| Original Diku Mud copyright (C) 1990, 1991 ||
|| by Sebastian Hammer, Michael Seifert, Hans Henrik St{rfeldt, ||
|| Tom Madsen, and Katja Nyboe. ||
|| ----------------------------------------------------------------- ||
|| Any use of this software must follow the licenses of the ||
|| creators. 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. ||
|| ----------------------------------------------------------------- ||
|| save.c ||
|| Player saving and loading. ||
*_/<>\_________________________________________________________________/<>\_*/
#include "mud.h"
#include "event.h"
#include "db.h"
#if !defined( WIN32 )
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#endif
#if defined( __sun )
# include <memory.h>
#endif
#if defined( __sun )
int system args( ( const char *string ) );
#endif
/*
* Local functions.
*/
void fwrite_char args( ( CHAR_DATA *ch, FILE *fp ) );
int fread_char args( ( CHAR_DATA *ch, FILE *fp, int *version ) );
DECLARE_READ_FUN( read_char_affect );
DECLARE_READ_FUN( read_obj_affect );
DECLARE_READ_FUN( read_alias );
DECLARE_READ_FUN( read_board );
DECLARE_READ_FUN( read_clan );
DECLARE_READ_FUN( read_event );
DECLARE_READ_FUN( read_event_o );
DECLARE_READ_FUN( read_exdesc_o );
DECLARE_READ_FUN( read_magic );
DECLARE_READ_FUN( read_mana );
DECLARE_READ_FUN( read_max_mana );
DECLARE_READ_FUN( read_multiclass );
DECLARE_READ_FUN( read_perm_o );
DECLARE_READ_FUN( read_race_o );
DECLARE_READ_FUN( read_religion );
DECLARE_READ_FUN( read_required_o );
DECLARE_READ_FUN( read_skill );
DECLARE_READ_FUN( read_spell_o );
DECLARE_READ_FUN( read_values_o );
/*
* External stuff.
*/
extern char *daPrompt;
bool special_read args( ( FILE *fp, struct file_read_type *read_table,
void *vo ) );
/* Courtesy of Yaz of 4th Realm */
char *initial( const char *str )
{
static char strint[2];
strint[1] = '\0';
strint[0] = LOWER( str[0] );
return strint;
}
/*
* Save a character and inventory.
* Would be cool to save NPC's too for quest purposes,
* some of the infrastructure is provided.
* Need means of loading vnum, that is ALL.
*/
void save_char_obj( CHAR_DATA *ch )
{
FILE *fp;
char strsave[MAX_INPUT_LENGTH];
ch->save_time = current_time;
if( IS_NPC( ch ) || ch->level < SysInfo->saveat
|| xIS_SET( ch->act, PLR_NOSAVE ) )
return;
if( ch->desc && ch->desc->original )
ch = ch->desc->original;
/* player files parsed directories by Yaz 4th Realm */
sprintf( strsave, "%s%c%s%s", PLAYER_DIR, LOWER( ch->name[0] ),
DIR_SEPARATOR, capitalize( ch->name ) );
if( ( fp = open_file( strsave, "w", TRUE ) ) )
{
/* if( ch->desc )
fprintf( fp, "## Host \"%s\";\n", ch->desc->host ); */
write_next_item( fp, "Char", ch );
fprintf( fp, "\neof\n\n" );
close_file( fp );
}
else
{
/* Can't use bug here, it causes crashes since we have fpReserve
* closed.
bug( "Save_char_obj: open_file %s: ", ch->name );
*/
perror( strsave );
}
return;
}
int get_orig_sex( CHAR_DATA *ch )
{
int sex = ch->sex;
AFFECT_DATA *af;
if( !IS_AFFECTED( ch, AFF_POLYMORPH ) )
return ch->sex;
for( af = ch->affected; af; af = af->next )
{
if( xIS_SET( af->bitvector, AFF_POLYMORPH )
&& af->location == APPLY_SEX )
sex -= af->modifier;
}
return sex;
}
int get_orig_race( CHAR_DATA *ch )
{
int race = ch->race;
AFFECT_DATA *af;
if( !IS_AFFECTED( ch, AFF_POLYMORPH ) )
return race;
for( af = ch->affected; af; af = af->next )
{
if( xIS_SET( af->bitvector, AFF_POLYMORPH )
&& af->location == APPLY_RACE )
race -= af->modifier;
}
return race;
}
/*
* Load a char and inventory into a new ch structure.
*/
bool load_char_obj( DESCRIPTOR_DATA *d, const char *name )
{
CHAR_DATA *ch;
int i, status;
bool found;
char sorry_player[] =
"********************************************************\n\r"
"** One or more of the critical fields in your player **\n\r"
"** file were corrupted since you last played. Please **\n\r"
"** contact an administrator or programmer to **\n\r"
"** investigate the recovery of your characters. **\n\r"
"********************************************************\n\r";
/* parsed player file directories by Yaz of 4th Realm */
/* decompress if .gz file exists - Thx Alander */
#if defined( HAVE_GZIP ) && !defined( WIN32 )
{
struct stat tmp;
sprintf( strArea, "%s%c%s%s.gz", PLAYER_DIR, LOWER( name[0] ),
DIR_SEPARATOR, capitalize( name ) );
if( stat( strArea, &tmp ) == 0 )
{
char buf[MAX_STRING_LENGTH];
sprintf( buf, "gzip -dfq %s", strArea );
system( buf );
}
}
#endif
sprintf( strArea, "%s%c%s%s", PLAYER_DIR, LOWER( name[0] ),
DIR_SEPARATOR, capitalize( name ) );
if( ( fpArea = open_file( strArea, "r", TRUE ) ) )
{
found = TRUE;
ch = read_next_item( fpArea, &status );
if( !ch || status < 0 )
{
bug( "Load_char_obj: %s section PLAYER corrupt.\n\r",
name );
write_to_buffer( d, sorry_player );
/*
* In case you are curious, it is ok to leave ch alone for
* close_socket to free.
* We want to now kick the bad character out as what we are missing
* are MANDATORY fields. -Kahn
*/
ch = new_character( TRUE );
xSET_BIT( ch->act, PLR_DENY );
}
close_file( fpArea );
fpArea = NULL;
}
else
{
found = FALSE;
ch = new_character( TRUE );
ch->pcdata->prompt = str_dup( daPrompt );
for( i = 0; i < MAX_BOARD; i++ )
ch->pcdata->last_note[i] = 0;
vzero( ch->act );
xSET_BIT( ch->act, PLR_AUTOEXIT );
xSET_BIT( ch->act, PLR_AUTOGOLD );
xSET_BIT( ch->act, PLR_AUTOSPLIT );
xSET_BIT( ch->act, PLR_BLANK );
xSET_BIT( ch->act, PLR_COLOUR );
xSET_BIT( ch->act, PLR_COMBINE );
xSET_BIT( ch->act, PLR_PROMPT );
ch->pcdata->pwd = str_dup( "" );
ch->pcdata->immname = str_dup( "" );
ch->pcdata->bamfin = str_dup( "" );
ch->pcdata->bamfout = str_dup( "" );
ch->pcdata->immskll = str_dup( "" );
ch->pcdata->title = str_dup( "" );
ch->pcdata->setmin = str_dup( "enters from the" );
ch->pcdata->setmout = str_dup( "leaves" );
ch->pcdata->perm_str = 15;
ch->pcdata->perm_int = 15;
ch->pcdata->perm_wis = 15;
ch->pcdata->perm_dex = 15;
ch->pcdata->perm_con = 15;
ch->pcdata->condition[COND_THIRST] = 1000;
ch->pcdata->condition[COND_FULL] = 1000;
ch->pcdata->pagelen = 20;
ch->pcdata->aliases = NULL;
ch->pcdata->security = 0;
ch->pcdata->pc_bits = 0;
ch->pcdata->familiar = 0;
ch->pcdata->blink = 0;
ch->pcdata->killed = ch->pcdata->died = 0;
ch->pcdata->religion = NULL;
ch->pcdata->clan = NULL;
ch->pcdata->clan_rank = RANK_NONE;
ch->pcdata->quest = new_quest();
ch->pcdata->language = LANG_COMMON;
ch->practice = 300;
ch->body_parts = BODY_PARTS_HUMAN;
for( i = 0; i < MAGIC_MAX; i++ )
{
ch->pcdata->perm_magic[i] = 2;
ch->max_mana[i] = 10;
}
for( i = 0; i < NUM_MULTI_CLASS; i++ )
ch->pcdata->multi_class[i] = CLASS_UNKNOWN;
}
d->character = ch;
ch->desc = d;
ch->name = str_dup( name );
ch->pcdata->board = &board_table[0];
ch->pcdata->switched = FALSE;
return found;
}
void do_delet( CHAR_DATA *ch, const char *argument )
{
send_to_char( "&RAre you INSANE?!?&n\n\r", ch );
return;
}
void do_delete( CHAR_DATA *ch, const char *argument )
{
char strsave[MAX_INPUT_LENGTH];
DESCRIPTOR_DATA *d;
HIGHEST_DATA *high;
if( IS_NPC( ch ) )
return;
if( strcmp( crypt( argument, ch->pcdata->pwd ), ch->pcdata->pwd ) )
{
send_to_char( "That password is incorrect.\n\r", ch );
return;
}
if( ch->position == POS_FIGHTING )
{
send_to_char( "No way! You are fighting.\n\r", ch );
return;
}
if( ch->position < POS_STUNNED )
{
send_to_char( "You're not DEAD yet.\n\r", ch );
return;
}
if( ch->desc && ch->desc->pString )
string_add( ch, "@" );
send_to_char( "PISS OFF!!!\n\r", ch );
send_to_char( " [We will miss you badly.]\n\r\n\r", ch );
act( "$n has finally succumbed to sanity and has deleted.",
ch, NULL, NULL, TO_ROOM );
sprintf( log_buf,
"%s has finally succumbed to sanity and has deleted.", ch->name );
log_string( log_buf );
wiznet( ch, WIZ_LOGINS, get_trust( ch ), log_buf );
if( !IS_IMMORTAL( ch ) )
talk_channel( NULL, log_buf, CHANNEL_INFO, "INFO" );
sprintf( strsave, "%s%c%s%s", PLAYER_DIR, LOWER( ch->name[0] ),
DIR_SEPARATOR, capitalize( ch->name ) );
{
#if !defined( WIN32 )
struct stat tmp;
if( stat( strsave, &tmp ) == 0 )
{
#else
FILE *fp;
if( ( fp = open_file( strsave, "r", FALSE ) ) )
{
close_file( fp );
#endif
sprintf( log_buf, "rm -f %s", strsave );
system( log_buf );
}
else
{
send_to_char( "No need to concern yourself, you don't really exist.\n\r", ch );
}
}
/*
* Remove char from highest.
*/
for( high = highest_first; high; high = high->next )
{
int i;
if( str_cmp( high->type, "TopTen" )
&& str_cmp( high->type, class_table[ch->class].name )
&& str_cmp( high->type, race_table[ch->race].name ) )
continue;
for( i = 0; i < 10; ++i )
if( high->entries[i] && high->entries[i]->level > 0
&& !str_cmp( ch->name, high->entries[i]->name ) )
break;
if( i < 10 )
free_highent( high->entries[i] );
for( ; i < 9; ++i )
high->entries[i] = high->entries[i+1];
high->entries[9] = NULL;
}
/*
* After extract_char the ch is no longer valid!
*/
d = ch->desc;
extract_char( ch, TRUE );
if( d )
close_socket( d );
return;
}