/*___________________________________________________________________________* )()( 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/stat.h> #include <unistd.h> #include <errno.h> #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; }