/**************************************************************************** * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// * * -----------------------------------------------------------| (0...0) * * SMAUG 1.0 (C) 1994, 1995, 1996 by Derek Snider | ).:.( * * -----------------------------------------------------------| {o o} * * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ * * Scryn, Rennard, Swordbearer, Gorog, Grishnakh and Tricops |~'~.VxvxV.~'~* * ------------------------------------------------------------------------ * * Merc 2.1 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. * * ------------------------------------------------------------------------ * * Character saving and loading module * ****************************************************************************/ #include <sys/types.h> #include <ctype.h> #include <stdio.h> #include <string.h> #include <time.h> #include <unistd.h> #include <sys/stat.h> #include <sys/dir.h> #include "mud.h" /* * Increment with every major format change. */ #define SAVEVERSION 6 /* * Corpse Loader stuff --GW */ #define LCORPSE_DIR "../loadedcorpses/" int cloaded; bool CR; ROOM_INDEX_DATA *croom; char * get_class2 args( ( CHAR_DATA *ch ) ); char * get_advclass args( ( CHAR_DATA *ch ) ); char * get_advclass2 args( ( CHAR_DATA *ch ) ); void load_char_cmap( CHAR_DATA *ch, char *argument ); void save_char_cmaps( FILE *fp, CHAR_DATA *ch ); /* * Array to keep track of equipment temporarily. -Thoric */ OBJ_DATA *save_equipment[MAX_WEAR][8]; CHAR_DATA *quitting_char, *loading_char, *saving_char; int file_ver; CHAR_DATA *corpse_ch; /* * Externals */ void fwrite_comments( CHAR_DATA *ch, FILE *fp ); void fread_comment( CHAR_DATA *ch, FILE *fp ); /* * Array of containers read for proper re-nesting of objects. */ static OBJ_DATA * rgObjNest [MAX_NEST]; /* * Local functions. */ void fwrite_char args( ( CHAR_DATA *ch, FILE *fp ) ); void fread_char args( ( CHAR_DATA *ch, FILE *fp, bool preload) ); void write_corpses args( ( CHAR_DATA *ch, char *name, bool write_2 ) ); void write_locker args( ( CHAR_DATA *ch, char *name ) ); void read_finger( CHAR_DATA *ch, char *argument ) { FILE *fp; char buf [ MAX_STRING_LENGTH ]; char fingload [ MAX_INPUT_LENGTH ]; struct stat fst; WIZENT *wiz; extern WIZENT *first_wiz; buf[0] = '\0'; record_call("<read_finger>"); while( isspace(*argument) ) argument++; /* This names the player finger file Joe.F in the player's directory. * If you want a different extension for your finger files, * then just change the "F" to whatever extension you want. * BE SURE if you change the extension here, to change it in the * save_finger function */ sprintf( fingload, "%s%c/%s.F", FINGER_DIR, tolower(argument[0]), capitalize( argument ) ); if ( stat( fingload, &fst ) == -1 ) { ch_printf(ch, "No Finger Data Found for: '%s'.\n\r", argument ); return; } // new_fclose(fpReserve); if ( !( fp = fopen ( fingload, "r" ) ) ) { sprintf( buf, "Load_finger_Info: fopen %s ", argument ); bug( buf, 0 ); perror( fingload ); ch_printf(ch, "No Finger Data Found for: '%s'.\n\r", argument ); return; } else { for( wiz = first_wiz; wiz; wiz = wiz->next ) { if ( !str_cmp( wiz->name, argument ) && wiz->level > get_trust(ch) ) { ch_printf( ch, "Information on %s is beyond your grasp!\n\r", capitalize(wiz->name) ); new_fclose( fp ); return; } } fread_finger ( ch, fp ); } new_fclose( fp ); // fpReserve = fopen( NULL_FILE, "r" ); return; } void fread_finger ( CHAR_DATA *ch, FILE *fp ) { char *finger; char buf[MAX_STRING_LENGTH]; buf[0] = '\0'; record_call("<fread_finger>"); send_to_char(" Finger Info\n\r",ch); send_to_char(" -----------\n\r\n\r",ch); finger = fread_string( fp ); ch_printf(ch, "%s\n\r", finger); return; } void fwrite_finger( CHAR_DATA *ch, FILE *fp ) { char * buf1; char * buf2; char * buf3; char * buf4; buf1 = STRALLOC(get_class(ch)); buf2 = STRALLOC(get_class2(ch)); buf3 = STRALLOC(get_advclass(ch)); buf4 = STRALLOC(get_advclass2(ch)); buf1 = STRALLOC(capitalize(buf1)); buf2 = STRALLOC(capitalize(buf2)); buf3 = STRALLOC(capitalize(buf3)); buf4 = STRALLOC(capitalize(buf4)); record_call("<fwrite_finger>"); fprintf( fp, "&CName: &W%s\n", ch->name ); fprintf( fp, "&CMud Age: &W%-13d\n\r", get_age( ch ) ); fprintf( fp, "&CLevels: &W[&R%d&W/&R%d&W/&R%d&W/&R%d&W] [1/2/3/4]\n",ch->level,ch->level2,ch->advlevel, ch->advlevel2 ); fprintf( fp, "&CSex: &W%s\n", ch->sex == SEX_MALE ? "Male" : ch->sex == SEX_FEMALE ? "Female" : "Neutral" ); fprintf( fp, "&CClasses: &W[&R%s&W/&R%s&W/&R%s&W/&R%s&W]\n", QUICKLINK(buf1),QUICKLINK(buf2), QUICKLINK(buf3), QUICKLINK(buf4)); fprintf( fp, "&CRace: &W%s\n", capitalize(get_race(ch)) ); fprintf( fp, "&CTitle: &W%s\n", ch->pcdata->title); fprintf( fp, "&CLast On: &W%s~\n", (char * ) ctime(&ch->pcdata->logon) ); return; } void save_finger( CHAR_DATA *ch ) { FILE *fp=NULL; char buf [MAX_STRING_LENGTH]; char fng [MAX_INPUT_LENGTH]; record_call("<save_finger>"); if( IS_NPC(ch) || ch->level < 2 ) return; if ( ch->desc && ch->desc->original ) ch = ch->desc->original; /* This names the player finger file Joe.F in the player's directory. * If you want a different extension for your finger files, * then just change the "F" to whatever extension you want. * BE SURE if you change the extension here, to change it in the * read_finger function */ sprintf( fng, "%s%c/%s.F", FINGER_DIR, tolower(ch->name[0]), capitalize( ch->name ) ); // new_fclose(fpReserve); if((fp = fopen(fng, "w"))==NULL ) { sprintf( buf, "Save_finger: fopen %s ", ch->name); bug( buf, 0 ); perror(fng); return; } else { fwrite_finger( ch, fp ); new_fclose(fp); } // fpReserve = fopen( NULL_FILE, "r" ); return; } /* * Un-equip character before saving to ensure proper -Thoric * stats are saved in case of changes to or removal of EQ */ void de_equip_char( CHAR_DATA *ch ) { char buf[MAX_STRING_LENGTH]; OBJ_DATA *obj; int x,y; record_call("<de_equip_char>"); if ( !ch ) { bug("DE_EQUIP_CHAR: NULL CH!",0); return; } for ( x = 0; x < MAX_WEAR; x++ ) for ( y = 0; y < MAX_LAYERS; y++ ) save_equipment[x][y] = NULL; for ( obj = ch->first_carrying; obj; obj = obj->next_content ) if ( obj->wear_loc > -1 && obj->wear_loc < MAX_WEAR ) { for ( x = 0; x < MAX_LAYERS; x++ ) if ( !save_equipment[obj->wear_loc][x] ) { save_equipment[obj->wear_loc][x] = obj; break; if ( x == MAX_LAYERS ) { sprintf( buf, "%s had on more than %d layers of clothing in one location (%d): %s", ch->name, MAX_LAYERS, obj->wear_loc, obj->name ); bug( buf, 0 ); } } /* else { sprintf( buf, "%s had on %s: ch->level = %d ", ch->name, obj->name, ch->level); bug( buf, 0 ); }-- Spam.. --GW*/ unequip_char(ch, obj); } } /* * Re-equip character -Thoric */ void re_equip_char( CHAR_DATA *ch ) { int x,y; record_call("<re_equip_char>"); for ( x = 0; x < MAX_WEAR; x++ ) for ( y = 0; y < MAX_LAYERS; y++ ) if ( save_equipment[x][y] != NULL ) { if ( quitting_char != ch ) equip_char(ch, save_equipment[x][y], x); save_equipment[x][y] = NULL; } else break; } /* * Save a character and inventory. * Would be cool to save NPC's too for quest purposes, * some of the infrastructure is provided. */ void save_char_obj( CHAR_DATA *ch ) { char strsave[MSL]; char strback[MSL]; char buf[MSL]; FILE *fp=NULL; int no_limit=FALSE; record_call("<save_char_obj>"); if ( !ch ) { bug( "Save_char_obj: null ch!", 0 ); return; } if ( IS_NPC(ch) || ch->level < 2 ) return; saving_char = ch; /* save pc's clan's data while we're at it to keep the data in sync */ if ( !IS_NPC(ch) && ch->pcdata->clan ) save_clan( ch->pcdata->clan ); /* save deity's data to keep it in sync -ren */ /* if ( !IS_NPC(ch) && ch->pcdata->deity ) save_deity( ch->pcdata->deity ); */ /* if ( ch->desc && ch->desc->original ) ch = ch->desc->original;*/ /* Save Offline Data --GW */ // save_offline_data(ch); /* Topten Stuff */ topten_check(ch); de_equip_char( ch ); /* Keep the Chars NATURAL Stats .. --GW */ ch->pcdata->nat_hp = ch->max_hit; ch->pcdata->nat_mana = ch->max_mana; ch->pcdata->save_time = current_time; sprintf( strsave, "%s%c/%s", PLAYER_DIR, tolower(ch->name[0]), capitalize( ch->name ) ); /* * Auto-backup pfile (can cause lag with high disk access situtations */ if ( IS_SET( sysdata.save_flags, SV_BACKUP ) ) { sprintf( strback, "%s%c/%s", BACKUP_DIR, tolower(ch->name[0]), capitalize( ch->name ) ); rename( strsave, strback ); sprintf( buf,"gzip -f %s%c/%s",BACKUP_DIR, tolower(ch->name[0]), capitalize( ch->name )); system( buf ); } /* * Save immortal stats, level & vnums for wizlist -Thoric * and do_vnums command * * Also save the player flags so we the wizlist builder can see * who is a guest and who is retired. */ if ( ch->level >= LEVEL_IMMORTAL ) { fp=NULL; sprintf( strback, "%s%s", "../gods/", capitalize( ch->name ) ); if ( ( fp = fopen( strback, "w" ) ) == NULL ) { bug( "Save_god_level: fopen", 0 ); perror( strsave ); } else { fprintf( fp, "Level %d\n", ch->level ); fprintf( fp, "Pcflags %d\n", ch->pcdata->flags ); if ( ch->pcdata->r_range_lo && ch->pcdata->r_range_hi ) fprintf( fp, "RoomRange %d %d\n", ch->pcdata->r_range_lo, ch->pcdata->r_range_hi ); if ( ch->pcdata->o_range_lo && ch->pcdata->o_range_hi ) fprintf( fp, "ObjRange %d %d\n", ch->pcdata->o_range_lo, ch->pcdata->o_range_hi ); if ( ch->pcdata->m_range_lo && ch->pcdata->m_range_hi ) fprintf( fp, "MobRange %d %d\n", ch->pcdata->m_range_lo, ch->pcdata->m_range_hi ); new_fclose( fp ); } } fp=NULL; if ( ( fp = fopen( strsave, "w" ) ) == NULL ) { bug( "Save_char_obj: fopen", 0 ); perror( strsave ); } else { fwrite_char( ch, fp ); if ( ch->pcdata->comments ) /* comments */ fwrite_comments( ch, fp ); /* comments */ /* Write Personal Socials --GW */ save_char_socials(fp,ch); fprintf( fp, "#END\n" ); new_fclose( fp ); /* Imp/Comm/Council Morts ie: loaded eq */ if ( IS_SET(ch->pcdata->flagstwo,MOREPC_NO_LIMIT_CNT) ) no_limit=TRUE; /* Immortals dont affect limits */ if ( IS_IMMORTAL(ch) ) no_limit=2; /* New Obj Loader/Saver --GW */ sprintf(buf,"%s%c/%s",PLAYER_OBJ_DIR,tolower(ch->name[0]), capitalize(ch->name)); fp=NULL; if ( ( fp=fopen( buf, "w" ) )!=NULL ) { if ( ch->first_carrying ) fwrite_obj( ch, ch->last_carrying, fp, 0, OS_CARRY, no_limit ); fprintf( fp,"#END\n"); new_fclose(fp); } } re_equip_char( ch ); write_corpses(ch, NULL, FALSE); quitting_char = NULL; saving_char = NULL; return; } /* * Write the char. */ void fwrite_char( CHAR_DATA *ch, FILE *fp ) { AFFECT_DATA *paf; int sn, track; int pos; SKILLTYPE *skill=NULL; record_call("<fwrite_char>"); fprintf( fp, "#%s\n", IS_NPC(ch) ? "MOB" : "PLAYER" ); fprintf( fp, "Name %s~\n", ch->name ); fprintf( fp, "Name2 %s~\n", ch->pcdata->name ); fprintf( fp, "Version %d\n", SAVEVERSION ); if ( ch->short_descr && ch->short_descr[0] != '\0' ) fprintf( fp, "ShortDescr %s~\n", ch->short_descr ); if ( ch->long_descr && ch->long_descr[0] != '\0' ) fprintf( fp, "LongDescr %s~\n", ch->long_descr ); if ( ch->description && ch->description[0] != '\0' ) fprintf( fp, "Description %s~\n", ch->description ); fprintf( fp, "Sex %d\n", ch->sex ); fprintf( fp, "Bank %ld\n", ch->pcdata->bank ); fprintf( fp, "SilverBank %ld\n", ch->pcdata->silver_bank ); fprintf( fp, "GoldBank %ld\n", ch->pcdata->gold_bank ); fprintf( fp, "Bounty %d\n", ch->pcdata->bounty ); fprintf( fp, "Class %d\n", ch->class ); fprintf( fp, "Class2 %d\n", ch->class2 ); fprintf( fp, "Advlevel %d\n", ch->advlevel ); fprintf( fp, "Advlevel2 %d\n", ch->advlevel2 ); fprintf( fp, "Advclass %d\n", ch->advclass ); fprintf( fp, "Advclass2 %d\n", ch->advclass2 ); fprintf( fp, "Clevel %d\n", ch->pcdata->clevel ); fprintf( fp, "cperm %d\n", ch->pcdata->cperm ); fprintf( fp, "ChallChar %s~\n", ch->pcdata->challenge_char_name ); fprintf( fp, "imc %d\n", ch->pcdata->imc ); fprintf( fp, "Race %d\n", ch->race ); fprintf( fp, "Languages %d %d\n", ch->speaks, ch->speaking ); fprintf( fp, "Level %d\n", ch->level ); fprintf( fp, "Level2 %d\n", ch->level2 ); if ( ch->pcdata->trust ) fprintf( fp, "Trust %d\n", ch->pcdata->trust ); fprintf( fp, "Played %d\n", ch->pcdata->played + (int) (current_time - ch->pcdata->logon) ); if ( ch->in_room ) { fprintf( fp, "Room %d\n", ch->in_room->vnum ); } fprintf( fp, "StartRoom %d\n", ch->pcdata->start_room ); fprintf( fp, "InvisStart %d\n", ch->pcdata->invis_start ); fprintf( fp, "HpManaMove %d %d %d %d %d %d\n", ch->hit, ch->max_hit, ch->mana, ch->max_mana, ch->move, ch->max_move ); fprintf( fp, "Nat_HP %d\n", ch->pcdata->nat_hp ); fprintf( fp, "Nat_MANA %d\n", ch->pcdata->nat_mana ); fprintf( fp, "Old_Hp %d\n", ch->pcdata->old_hp ); fprintf( fp, "Old_Mana %d\n", ch->pcdata->old_mana ); fprintf( fp, "Old_Move %d\n", ch->pcdata->old_move ); fprintf( fp, "Old_Exp %d\n", ch->pcdata->old_exp ); fprintf( fp, "Clssdropped %d\n", ch->pcdata->clssdropped ); fprintf( fp, "Copper %ld\n", ch->gold ); fprintf( fp, "Silver %ld\n", ch->silver ); fprintf( fp, "RGold %ld\n", ch->real_gold ); fprintf( fp, "Exp %ld\n", ch->exp ); if ( ch->act ) fprintf( fp, "Act %d\n", ch->act ); if ( !xIS_EMPTY(ch->affected_by) ) fprintf( fp, "AffectedBy %s\n", print_bitvector(&ch->affected_by)); fprintf( fp, "Position %d\n", ch->position == POS_FIGHTING ? POS_STANDING : ch->position ); fprintf( fp, "Practice %d\n", ch->practice ); fprintf( fp, "SavingThrows %d %d %d %d %d\n", ch->saving_poison_death, ch->saving_wand, ch->saving_para_petri, ch->saving_breath, ch->saving_spell_staff ); fprintf( fp, "Alignment %d\n", ch->alignment ); fprintf( fp, "Favor %d\n", ch->pcdata->favor ); fprintf( fp, "Glory %d\n", ch->pcdata->quest_curr ); fprintf( fp, "MGlory %d\n", ch->pcdata->quest_accum ); fprintf( fp, "MinorAff %d\n", ch->pcdata->minoraffects ); fprintf( fp, "MajorAff %d\n", ch->pcdata->majoraffects ); fprintf( fp, "MinorRes %d\n", ch->pcdata->minorresist ); fprintf( fp, "MajorRes %d\n", ch->pcdata->majorresist ); fprintf( fp, "Skill100s %d\n", ch->pcdata->skill100s ); fprintf( fp, "GloryStatus %d\n", ch->pcdata->glory_status ); fprintf( fp, "Stock1 %d\n", ch->pcdata->shares[1] ); fprintf( fp, "Stock2 %d\n", ch->pcdata->shares[2] ); fprintf( fp, "Stock3 %d\n", ch->pcdata->shares[3] ); fprintf( fp, "Guildlevel %d\n", ch->pcdata->guildlevel ); if (ch->pcdata->nextquest != 0) fprintf( fp, "QuestNext %d\n", ch->pcdata->nextquest ); else if (ch->pcdata->countdown != 0) fprintf( fp, "QuestNext %d\n", 10 ); fprintf( fp, "QuestPoints %d\n", ch->pcdata->questpoints ); fprintf( fp, "Countdown %d\n", ch->pcdata->countdown ); fprintf( fp, "QuestObj %d\n", ch->pcdata->questobj ); fprintf( fp, "QuestMob %d\n", ch->pcdata->questmob ); fprintf( fp, "QuestInRoom %d\n", ch->pcdata->questinroom ); fprintf( fp, "Hitroll %d\n", ch->hitroll ); fprintf( fp, "Damroll %d\n", ch->damroll ); fprintf( fp, "Ego %d\n", ch->pcdata->ego ); fprintf( fp, "Armor %d\n", ch->armor ); fprintf( fp, "MARating %d\n", ch->pcdata->martial_arts_rating ); fprintf( fp, "MArmor %d\n", ch->magical_armor ); fprintf( fp, "awins %d\n", ch->pcdata->awins ); fprintf( fp, "alosses %d\n", ch->pcdata->alosses ); fprintf( fp, "plr_wager %d\n", ch->pcdata->plr_wager ); fprintf( fp, "Rroom %d\n", ch->pcdata->rentroom ); fprintf( fp, "incog %d\n", ch->pcdata->incog_level ); fprintf( fp, "NumKombats %d\n", ch->pcdata->num_kombats ); fprintf( fp, "NumKombatants %d\n", ch->pcdata->num_kombatants ); fprintf( fp, "NumKombatsWon %d\n", ch->pcdata->num_kombats_won ); fprintf( fp, "PkChamps %d\n", ch->pcdata->pkchamps ); /* Mail forwarding fix --GW */ if ( ch->pcdata->mail_forward == NULL || str_cmp(ch->pcdata->mail_forward, "(null)" ) ) fprintf( fp, "MForward %s~\n", ch->pcdata->mail_forward); if ( ch->wimpy ) fprintf( fp, "Wimpy %d\n", ch->wimpy ); if ( ch->pcdata->deaf ) fprintf( fp, "Deaf %d\n", ch->pcdata->deaf ); if ( ch->resistant ) fprintf( fp, "Resistant %d\n", ch->resistant ); if ( ch->immune ) fprintf( fp, "Immune %d\n", ch->immune ); if ( ch->susceptible ) fprintf( fp, "Susceptible %d\n", ch->susceptible ); if ( ch->pcdata && ch->pcdata->outcast_time ) fprintf( fp, "Outcast_time %ld\n",ch->pcdata->outcast_time ); if ( ch->pcdata && ch->pcdata->restore_time ) fprintf( fp, "Restore_time %ld\n",ch->pcdata->restore_time ); if ( ch->mental_state != -10 ) fprintf( fp, "Mentalstate %d\n", ch->mental_state ); if ( IS_NPC(ch) ) { fprintf( fp, "Vnum %d\n", ch->pIndexData->vnum ); fprintf( fp, "Mobinvis %d\n", ch->mobinvis ); } else { fprintf( fp, "Email %s~\n", ch->pcdata->email ); fprintf( fp, "Password %s~\n", ch->pcdata->pwd ); if ( ch->pcdata->bamfin && ch->pcdata->bamfin[0] != '\0' ) fprintf( fp, "Bamfin %s~\n", ch->pcdata->bamfin ); if ( ch->pcdata->bamfout && ch->pcdata->bamfout[0] != '\0' ) fprintf( fp, "Bamfout %s~\n", ch->pcdata->bamfout ); if ( ch->pcdata->rank && ch->pcdata->rank[0] != '\0' ) fprintf( fp, "Rank %s~\n", ch->pcdata->rank ); if ( ch->pcdata->bestowments && ch->pcdata->bestowments[0] != '\0' ) fprintf( fp, "Bestowments %s~\n", ch->pcdata->bestowments ); fprintf( fp, "Title %s~\n", ch->pcdata->title ); if ( ch->pcdata->homepage && ch->pcdata->homepage[0] != '\0' ) fprintf( fp, "Homepage %s~\n", ch->pcdata->homepage ); if ( ch->pcdata->bio && ch->pcdata->bio[0] != '\0' ) fprintf( fp, "Bio %s~\n", ch->pcdata->bio ); if ( ch->pcdata->authed_by && ch->pcdata->authed_by[0] != '\0' ) fprintf( fp, "AuthedBy %s~\n", ch->pcdata->authed_by ); if ( ch->pcdata->min_snoop ) fprintf( fp, "Minsnoop %d\n", ch->pcdata->min_snoop ); if ( ch->pcdata->prompt && *ch->pcdata->prompt ) fprintf( fp, "Prompt %s~\n", ch->pcdata->prompt ); if ( ch->pcdata->pagerlen != 24 ) fprintf( fp, "Pagerlen %d\n", ch->pcdata->pagerlen ); if ( IS_IMMORTAL( ch ) ) { fprintf( fp, "WizInvis %d\n", ch->pcdata->wizinvis ); if ( ch->pcdata->r_range_lo && ch->pcdata->r_range_hi ) fprintf( fp, "RoomRange %d %d\n", ch->pcdata->r_range_lo, ch->pcdata->r_range_hi ); if ( ch->pcdata->o_range_lo && ch->pcdata->o_range_hi ) fprintf( fp, "ObjRange %d %d\n", ch->pcdata->o_range_lo, ch->pcdata->o_range_hi ); if ( ch->pcdata->m_range_lo && ch->pcdata->m_range_hi ) fprintf( fp, "MobRange %d %d\n", ch->pcdata->m_range_lo, ch->pcdata->m_range_hi ); } if ( ch->pcdata->council) fprintf( fp, "Council %s~\n", ch->pcdata->council_name ); if ( ch->pcdata->deity_name && ch->pcdata->deity_name[0] != '\0' ) fprintf( fp, "Deity %s~\n", ch->pcdata->deity_name ); if ( ch->pcdata->clan_name && ch->pcdata->clan_name[0] != '\0' ) fprintf( fp, "Clan %s~\n", ch->pcdata->clan_name ); if ( ch->pcdata->guild_name && ch->pcdata->guild_name[0] != '\0' ) fprintf( fp, "Guild %s~\n", ch->pcdata->guild_name ); fprintf( fp, "Flags %d\n", ch->pcdata->flags ); fprintf( fp, "Flags2 %d\n", ch->pcdata->flagstwo); if ( ch->pcdata->release_date > current_time ) fprintf( fp, "Helled %d %s~\n", (int)ch->pcdata->release_date, ch->pcdata->helled_by ); if ( ch->pcdata->pkills ) fprintf( fp, "PKills %d\n", ch->pcdata->pkills ); if ( ch->pcdata->pdeaths ) fprintf( fp, "PDeaths %d\n", ch->pcdata->pdeaths ); if ( get_timer( ch , TIMER_PKILLED) && ( get_timer( ch , TIMER_PKILLED) > 0 ) ) fprintf( fp, "PTimer %d\n", get_timer(ch, TIMER_PKILLED)); fprintf( fp, "MKills %d\n", ch->pcdata->mkills ); fprintf( fp, "MDeaths %d\n", ch->pcdata->mdeaths ); if ( ch->pcdata->illegal_pk ) fprintf( fp, "IllegalPK %d\n", ch->pcdata->illegal_pk ); fprintf( fp, "AttrPerm %d %d %d %d %d %d %d\n", ch->perm_str, ch->perm_int, ch->perm_wis, ch->perm_dex, ch->perm_con, ch->perm_cha, ch->perm_lck ); fprintf( fp, "AttrMod %d %d %d %d %d %d %d\n", ch->mod_str, ch->mod_int, ch->mod_wis, ch->mod_dex, ch->mod_con, ch->mod_cha, ch->mod_lck ); fprintf( fp, "Condition %d %d %d %d\n", ch->pcdata->condition[0], ch->pcdata->condition[1], ch->pcdata->condition[2], ch->pcdata->condition[3] ); if ( ch->desc && ch->desc->host ) fprintf( fp, "Site %s\n", ch->desc->host ); else fprintf( fp, "Site (Link-Dead)\n" ); fprintf(fp,"CSettings %d\n",ch->pcdata->colormap_settings); /* Write Cmaps --GW */ save_char_cmaps(fp,ch); /* Write Site locks */ save_hosts(ch,fp); /* write alias */ for (pos = 0; pos < MAX_ALIAS; pos++) { if (ch->pcdata->alias[pos] == NULL || ch->pcdata->alias_sub[pos] == NULL) break; fprintf(fp,"Alias %s %s~\n",ch->pcdata->alias[pos], ch->pcdata->alias_sub[pos]); } /* write ignores */ for (pos = 0; pos < MAX_IGNORE; pos++) { if (ch->pcdata->ignore[pos] == NULL ) break; fprintf(fp,"Ignore %s~\n",ch->pcdata->ignore[pos]); } for ( sn = 1; sn < top_sn; sn++ ) { if ( skill_table[sn]->name && ch->pcdata->learned[sn] > 0 && ( CAN_USE_SK( ch, skill_table[sn] ) || CAN_USE_RACE_SK( ch, skill_table[sn] ) ) ) { /* Fix for Mysterious 185% skill bug --GW */ if ( ch->pcdata->learned[sn] > 100 ) ch->pcdata->learned[sn] = 80; switch( skill_table[sn]->type ) { default: fprintf( fp, "Skill %d '%s'\n", ch->pcdata->learned[sn], skill_table[sn]->name ); break; case SKILL_SPELL: fprintf( fp, "Spell %d '%s'\n", ch->pcdata->learned[sn], skill_table[sn]->name ); break; case SKILL_WEAPON: fprintf( fp, "Weapon %d '%s'\n", ch->pcdata->learned[sn], skill_table[sn]->name ); break; case SKILL_TONGUE: fprintf( fp, "Tongue %d '%s'\n", ch->pcdata->learned[sn], skill_table[sn]->name ); break; } } } } for ( paf = ch->first_affect; paf; paf = paf->next ) { if ( paf->type >= 0 && (skill=get_skilltype(paf->type)) == NULL ) continue; if ( paf->type >= 0 && paf->type < TYPE_PERSONAL ) fprintf( fp, "AffectData '%s' %3d %3d %3d %10s\n", skill->name, paf->duration, paf->modifier, paf->location, print_bitvector(&paf->bitvector) ); else fprintf( fp, "Affect %3d %3d %3d %3d %10s\n", paf->type, paf->duration, paf->modifier, paf->location, print_bitvector(&paf->bitvector) ); } track = URANGE( 2, ((ch->level+3) * MAX_KILLTRACK)/LEVEL_AVATAR, MAX_KILLTRACK ); for ( sn = 0; sn < track; sn++ ) { if ( ch->pcdata->killed[sn].vnum == 0 ) break; fprintf( fp, "Killed %d %d\n", ch->pcdata->killed[sn].vnum, ch->pcdata->killed[sn].count ); } fprintf( fp, "End\n\n" ); return; } /* * Write an object and its contents. */ void fwrite_obj( CHAR_DATA *ch, OBJ_DATA *obj, FILE *fp, int iNest, sh_int os_type, sh_int no_limit ) { EXTRA_DESCR_DATA *ed; AFFECT_DATA *paf; sh_int wear, wear_loc, x; bool NO_SAVE=FALSE; bool SAVEROOM=FALSE; record_call("<fwrite_obj>"); if ( iNest >= MAX_NEST ) { bug( "fwrite_obj: iNest hit MAX_NEST %d", iNest ); return; } /* * Slick recursion to write lists backwards, * so loading them will load in forwards order. */ if ( obj->prev_content && os_type != OS_CORPSE && os_type != OS_LOCKER && os_type != OS_SAVEROOM ) fwrite_obj( ch, obj->prev_content, fp, iNest, OS_CARRY, no_limit ); if ( obj->prev_content && os_type == OS_SAVEROOM ) fwrite_obj( ch, obj->prev_content, fp, iNest, OS_SAVEROOM, FALSE ); /* * Catch deleted objects -Thoric */ if ( obj_extracted(obj) ) return; /* * Do NOT save prototype items! -Thoric */ if ( IS_OBJ_STAT( obj, ITEM_PROTOTYPE ) ) return; /* * No Saving of LIFE_PROTECTION objects --GW */ if ( obj->item_type == ITEM_LIFE_PROTECTION ) return; /* * Nope - no keys save.. --GW */ if ( obj->item_type == ITEM_KEY ) return; /* * Save Rooms Dont Save Certain Things! --GW */ if ( os_type == OS_SAVEROOM ) { SAVEROOM=TRUE; switch( obj->item_type ) { case ITEM_KEY: NO_SAVE = TRUE; break; case ITEM_TRASH: NO_SAVE = TRUE; break; case ITEM_FOOD: NO_SAVE = TRUE; break; case ITEM_TREASURE: NO_SAVE = TRUE; break; case ITEM_CORPSE_NPC: NO_SAVE = TRUE; break; case ITEM_CORPSE_PC: NO_SAVE = TRUE; break; case ITEM_SCRAPS: NO_SAVE = TRUE; break; case ITEM_INSIG: NO_SAVE = TRUE; break; default: break; } if ( IS_SET( obj->second_flags, ITEM2_NOSAVE ) ) NO_SAVE = TRUE; if ( NO_SAVE ) return; } /* Redone to support Lockers, GW */ /* SaveRoom Support added --GW */ if ( os_type == OS_CORPSE ) fprintf( fp, "#CORPSE\n" ); else if ( os_type == OS_LOCKER ) fprintf( fp, "#LOCKER\n" ); else fprintf( fp, "#OBJECT\n" ); if ( os_type == OS_SAVEROOM ) os_type = OS_CARRY; /* Imp/Comm/Council Morts ie: loaded eq */ if ( no_limit == TRUE ) fprintf( fp, "ImpChar YES!~\n"); if ( no_limit == 2 ) fprintf( fp, "Immortal YES!~\n"); if ( iNest ) fprintf( fp, "Nest %d\n", iNest ); if ( obj->count > 1 ) fprintf( fp, "Count %d\n", obj->count ); if ( QUICKMATCH( obj->name, obj->pIndexData->name ) == 0 ) fprintf( fp, "Name %s~\n", obj->name ); if ( QUICKMATCH( obj->short_descr, obj->pIndexData->short_descr ) == 0 ) fprintf( fp, "ShortDescr %s~\n", obj->short_descr ); if ( QUICKMATCH( obj->description, obj->pIndexData->description ) == 0 ) fprintf( fp, "Description %s~\n", obj->description ); if ( QUICKMATCH( obj->action_desc, obj->pIndexData->action_desc ) == 0 ) fprintf( fp, "ActionDesc %s~\n", obj->action_desc ); if ( obj->spare_desc ) fprintf( fp, "SpareDesc %s~\n", obj->spare_desc ); if ( obj->loaded_by && str_cmp( obj->loaded_by, "(null)")) fprintf( fp, "LoadedBy %s~\n", obj->loaded_by ); if ( obj->modified_by && str_cmp( obj->modified_by, "(null)")) fprintf( fp, "ModifiedBy %s~\n", obj->modified_by ); if ( obj->modified_date && str_cmp( obj->modified_date, "(null)")) fprintf( fp, "ModifiedDate %s~\n", obj->modified_date ); fprintf( fp, "Vnum %d\n", obj->pIndexData->vnum ); if ( ( os_type == OS_CORPSE || os_type == OS_LOCKER ) && obj->in_room ) fprintf( fp, "Room %d\n", obj->in_room->vnum ); if ( obj->extra_flags != obj->pIndexData->extra_flags ) fprintf( fp, "ExtraFlags %d\n", obj->extra_flags ); if ( obj->second_flags != obj->pIndexData->second_flags) fprintf( fp, "ExtraFlags2 %d\n", obj->second_flags ); if ( obj->magic_flags != obj->pIndexData->magic_flags) fprintf( fp, "MagicFlags %d\n", obj->magic_flags ); if ( obj->wear_flags != obj->pIndexData->wear_flags ) fprintf( fp, "WearFlags %d\n", obj->wear_flags ); wear_loc = -1; for ( wear = 0; wear < MAX_WEAR; wear++ ) for ( x = 0; x < MAX_LAYERS; x++ ) if ( obj == save_equipment[wear][x] ) { wear_loc = wear; break; } else if ( !save_equipment[wear][x] ) break; if ( wear_loc != -1 ) fprintf( fp, "WearLoc %d\n", wear_loc ); if ( obj->item_type != obj->pIndexData->item_type ) fprintf( fp, "ItemType %d\n", obj->item_type ); if ( obj->weight != obj->pIndexData->weight ) fprintf( fp, "Weight %d\n", obj->weight ); if ( obj->level ) fprintf( fp, "Level %d\n", obj->level ); if ( obj->timer ) fprintf( fp, "Timer %d\n", obj->timer ); if ( obj->cost != obj->pIndexData->cost ) fprintf( fp, "Cost %d\n", obj->cost ); /* Upstatted EQ */ if ( obj->dam_bonus > 0 ) fprintf( fp, "BonusDam %d\n", obj->dam_bonus ); if ( obj->hit_bonus > 0 ) fprintf( fp, "BonusHit %d\n", obj->hit_bonus ); if ( obj->ac_bonus > 0 ) fprintf( fp, "BonusAC %d\n", obj->ac_bonus ); if ( obj->mac_bonus > 0 ) fprintf( fp, "BonusMAC %d\n", obj->mac_bonus ); if ( obj->value[0] || obj->value[1] || obj->value[2] || obj->value[3] || obj->value[4] || obj->value[5] ) fprintf( fp, "Values %d %d %d %d %d %d\n", obj->value[0], obj->value[1], obj->value[2], obj->value[3], obj->value[4], obj->value[5] ); switch ( obj->item_type ) { case ITEM_PILL: /* was down there with staff and wand, wrongly - Scryn */ case ITEM_POTION: case ITEM_SCROLL: if ( IS_VALID_SN(obj->value[1]) ) fprintf( fp, "Spell 1 '%s'\n", skill_table[obj->value[1]]->name ); if ( IS_VALID_SN(obj->value[2]) ) fprintf( fp, "Spell 2 '%s'\n", skill_table[obj->value[2]]->name ); if ( IS_VALID_SN(obj->value[3]) ) fprintf( fp, "Spell 3 '%s'\n", skill_table[obj->value[3]]->name ); break; case ITEM_STAFF: case ITEM_WAND: if ( IS_VALID_SN(obj->value[3]) ) fprintf( fp, "Spell 3 '%s'\n", skill_table[obj->value[3]]->name ); break; case ITEM_SALVE: if ( IS_VALID_SN(obj->value[4]) ) fprintf( fp, "Spell 4 '%s'\n", skill_table[obj->value[4]]->name ); if ( IS_VALID_SN(obj->value[5]) ) fprintf( fp, "Spell 5 '%s'\n", skill_table[obj->value[5]]->name ); break; } for ( paf = obj->first_affect; paf; paf = paf->next ) { /* * Save extra object affects -Thoric */ if ( paf->type < 0 || paf->type >= top_sn ) { fprintf( fp, "Affect %d %d %d %d %s\n", paf->type, paf->duration, ((paf->location == APPLY_WEAPONSPELL || paf->location == APPLY_WEARSPELL || paf->location == APPLY_REMOVESPELL || paf->location == APPLY_STRIPSN) && IS_VALID_SN(paf->modifier)) ? skill_table[paf->modifier]->slot : paf->modifier, paf->location, print_bitvector(&paf->bitvector) ); } else fprintf( fp, "AffectData '%s' %d %d %d %s\n", skill_table[paf->type]->name, paf->duration, ((paf->location == APPLY_WEAPONSPELL || paf->location == APPLY_WEARSPELL || paf->location == APPLY_REMOVESPELL || paf->location == APPLY_STRIPSN) && IS_VALID_SN(paf->modifier)) ? skill_table[paf->modifier]->slot : paf->modifier, paf->location, print_bitvector(&paf->bitvector) ); } for ( ed = obj->first_extradesc; ed; ed = ed->next ) fprintf( fp, "ExtraDescr %s~ %s~\n", ed->keyword, ed->description ); fprintf( fp, "End\n\n" ); if ( obj->first_content && !SAVEROOM ) fwrite_obj( ch, obj->last_content, fp, iNest + 1, OS_CARRY, no_limit ); else if ( obj->first_content && SAVEROOM ) fwrite_obj( ch, obj->last_content, fp, iNest + 1, OS_SAVEROOM, FALSE ); return; } /* * Load a char and inventory into a new ch structure. */ bool load_char_obj( DESCRIPTOR_DATA *d, char *name, bool preload ) { char strsave[MAX_INPUT_LENGTH]; CHAR_DATA *ch=NULL; FILE *fp; bool found; bool compressed; struct stat fst; int i, x; extern FILE *fpArea; extern char strArea[MAX_INPUT_LENGTH]; char buf[MAX_INPUT_LENGTH]; CREATE( ch, CHAR_DATA, 1 ); record_call("<load_char_obj>"); for ( x = 0; x < MAX_WEAR; x++ ) for ( i = 0; i < MAX_LAYERS; i++ ) save_equipment[x][i] = NULL; clear_char( ch ); loading_char = ch; CREATE( ch->pcdata, PC_DATA, 1 ); d->character = ch; ch->desc = d; ch->name = STRALLOC( name ); ch->act = PLR_BLANK | PLR_COMBINE | PLR_PROMPT; ch->perm_str = 13; ch->perm_int = 13; ch->perm_wis = 13; ch->perm_dex = 13; ch->perm_con = 13; ch->perm_cha = 13; ch->perm_lck = 13; ch->pcdata->condition[COND_THIRST] = 48; ch->pcdata->condition[COND_FULL] = 48; ch->pcdata->condition[COND_BLOODTHIRST] = 10; ch->pcdata->played = 0; ch->pcdata->logon = current_time; ch->pcdata->wizinvis = 0; ch->mental_state = -10; ch->mobinvis = 0; for(i = 0; i < MAX_SKILL; i++) ch->pcdata->learned[i] = 0; ch->pcdata->release_date = 0; ch->pcdata->helled_by = NULL; ch->saving_poison_death = 0; ch->saving_wand = 0; ch->saving_para_petri = 0; ch->saving_breath = 0; ch->saving_spell_staff = 0; ch->pcdata->comments = NULL; /* comments */ ch->pcdata->pagerlen = 24; found = FALSE; compressed = FALSE; strsave[0] = '\0'; sprintf( strsave, "%s%c/%s", PLAYER_DIR, tolower(name[0]), capitalize( name ) ); if ( stat( strsave, &fst ) == -1 ) { strsave[0] = '\0'; compressed = TRUE; sprintf( strsave, "%s%c/%s.gz", PLAYER_DIR, tolower(name[0]), capitalize( name ) ); } if ( stat( strsave, &fst ) != -1 ) { if ( compressed ) { sprintf( buf, "Uncompressing Player Data for: %s (%dK)",ch->name ,(int) fst.st_size/1024 ); log_string_plus( buf, LOG_COMM, 59 ); buf[0] = '\0'; /* decompress if .gz file exists - Thx Alander */ fp=NULL; if ( ( fp = fopen( strsave, "r" ) ) ) { new_fclose( fp ); sprintf( buf, "gunzip -f %s", strsave ); system( buf ); strsave[0] = '\0'; sprintf( strsave, "%s%c/%s", PLAYER_DIR, tolower(name[0]), capitalize( name ) ); } } if ( fst.st_size == 0 ) { sprintf( buf, "Uncompressing BACKUP Player Data for: %s (%dK)",ch->name ,(int) fst.st_size/1024 ); log_string_plus( buf, LOG_COMM, LEVEL_GOD ); buf[0] = '\0'; sprintf( strsave, "%s%c/%s", BACKUP_DIR, tolower(name[0]), capitalize( name ) ); if ( stat( strsave, &fst ) == -1 ) { sprintf( strsave, "%s%c/%s.gz", BACKUP_DIR, tolower(name[0]), capitalize( name ) ); } send_to_char( "Restoring your backup player file...", ch ); /* decompress if .gz file exists - Thx Alander */ fp=NULL; if ( ( fp = fopen( strsave, "r" ) ) ) { new_fclose( fp ); sprintf( buf, "gunzip -f %s", strsave ); system( buf ); sprintf( strsave, "%s%c/%s", BACKUP_DIR, tolower(name[0]), capitalize( name ) ); } } else { sprintf( buf, "%s player data for: %s (%dK)", preload ? "Preloading" : "Loading", ch->name, (int) fst.st_size/1024 ); log_string_plus( buf, LOG_COMM, 59 ); } } /* else no player file */ fp=NULL; if ( ( fp = fopen( strsave, "r" ) ) != NULL ) { int iNest; for ( iNest = 0; iNest < MAX_NEST; iNest++ ) rgObjNest[iNest] = NULL; found = TRUE; /* Cheat so that bug will show line #'s -- Altrag */ fpArea = fp; strcpy(strArea, strsave); for ( ; ; ) { char letter; char *word=NULL; letter = fread_letter( fp ); if ( letter == '*' ) { fread_to_eol( fp ); continue; } if ( letter != '#' ) { bug( "Load_char_obj: # not found. (%c)", letter ); bug( name, 0 ); break; } word = fread_word( fp ); if ( !str_cmp( word, "PLAYER" ) ) { fread_char ( ch, fp, preload ); if ( preload ) break; } /* Changing this Around to Suit the new Object Loader --GW*/ else if ( file_ver < 5 ) { if ( !str_cmp( word, "OBJECT" ) ) /* Objects */ { load_limited_toggle(FALSE); fread_obj ( ch, fp, OS_CARRY ); load_limited_toggle(TRUE); } } else if ( !str_cmp( word, "COMMENT") ) fread_comment(ch, fp ); /* Comments */ else if ( !str_cmp( word, "PSOCIAL" ) ) /* Psocials */ load_char_social(fp,ch); else if ( !str_cmp( word, "END" ) ) /* Done */ break; else { bug( "Load_char_obj: bad section.", 0 ); bug( name, 0 ); break; } } new_fclose( fp ); fpArea = NULL; strcpy(strArea, "$"); /* New Object Loader --GW */ if ( file_ver > 4 && !preload ) { sprintf(buf,"%s%c/%s", PLAYER_OBJ_DIR, tolower(ch->name[0]), capitalize(ch->name)); if ( stat( buf, &fst ) != -1 ) { fp=NULL; if ( ( fp=fopen( buf, "r" ) )!=NULL) { strcpy(strArea, buf); sprintf( buf,"Loading Objects for: %s (%dK) (V%d)",capitalize(ch->name), (int) fst.st_size/1024, file_ver ); log_string_plus( buf,LOG_COMM, 59 ); fpArea = fp; for ( ; ; ) { char letter; char *word=NULL; letter = fread_letter( fp ); if ( letter == '*' ) { fread_to_eol( fp ); continue; } if ( letter != '#' ) { bug( "Load_char_obj: # not found.", 0 ); bug( name, 0 ); break; } word = fread_word( fp ); if ( !str_cmp( word, "OBJECT" ) ) { load_limited_toggle(FALSE); fread_obj ( ch, fp, OS_CARRY ); load_limited_toggle(TRUE); } else if ( !str_cmp( word, "END" ) ) break; else { bug("Fread_Player: Bad Obj File. (%s)", word); bug( name, 0); break; } } new_fclose(fp); fpArea = NULL; strcpy(strArea, "$" ); } } } } if ( !found ) { ch->short_descr = STRALLOC( "" ); ch->long_descr = STRALLOC( "" ); ch->description = STRALLOC( "" ); ch->pcdata->editor = NULL; ch->pcdata->clan_name = STRALLOC( "" ); ch->pcdata->clan = NULL; ch->pcdata->guild_name = STRALLOC( "" ); ch->pcdata->guild = NULL; ch->pcdata->council_name = STRALLOC( "" ); ch->pcdata->council = NULL; ch->pcdata->deity_name = STRALLOC( "" ); ch->pcdata->deity = NULL; ch->pcdata->pwd = str_dup( "" ); ch->pcdata->bamfin = str_dup( "" ); ch->pcdata->bamfout = str_dup( "" ); ch->pcdata->rank = str_dup( "" ); ch->pcdata->bestowments = str_dup( "" ); ch->pcdata->title = STRALLOC( "" ); ch->pcdata->homepage = str_dup( "" ); ch->pcdata->bio = STRALLOC( "" ); ch->pcdata->authed_by = STRALLOC( "" ); ch->pcdata->prompt = STRALLOC( "" ); ch->pcdata->r_range_lo = 0; ch->pcdata->r_range_hi = 0; ch->pcdata->m_range_lo = 0; ch->pcdata->m_range_hi = 0; ch->pcdata->o_range_lo = 0; ch->pcdata->o_range_hi = 0; ch->pcdata->wizinvis = 0; } else { load_char_offline_data(ch); if ( !ch->pcdata->clan_name ) { ch->pcdata->clan_name = STRALLOC( "" ); ch->pcdata->clan = NULL; } if ( !ch->pcdata->clan_name ) { ch->pcdata->guild_name = STRALLOC( "" ); ch->pcdata->guild = NULL; } if ( !ch->pcdata->council_name ) { ch->pcdata->council_name = STRALLOC( "" ); ch->pcdata->council = NULL; } if ( !ch->pcdata->deity_name ) { ch->pcdata->deity_name = STRALLOC( "" ); ch->pcdata->deity = NULL; } if ( !ch->pcdata->bio ) ch->pcdata->bio = STRALLOC( "" ); if ( !ch->pcdata->authed_by ) ch->pcdata->authed_by = STRALLOC( "" ); if ( !IS_NPC( ch ) && IS_IMMORTAL( ch ) && !preload ) { if ( ch->pcdata->wizinvis < 2 ) ch->pcdata->wizinvis = ch->level; assign_area( ch ); } if ( file_ver > 1 ) { for ( i = 0; i < MAX_WEAR; i++ ) { for ( x = 0; x < MAX_LAYERS; x++ ) { if ( save_equipment[i][x] ) { equip_char( ch, save_equipment[i][x], i ); save_equipment[i][x] = NULL; } else { break; } }}} /* Must be done *AFTER* eq is worn because of wis/int modifiers */ /* if ( !IS_IMMORTAL(ch) ) REMOVE_BIT(ch->speaks, LANG_COMMON | race_table[ch->race].language); if ( countlangs(ch->speaks) < (ch->level / 10) && !IS_IMMORTAL(ch) ) { int prct = 5 + (get_curr_int(ch) / 6) + (get_curr_wis(ch) / 7); do { int iLang; int lang = 1; int need = (ch->level / 10) - countlangs(ch->speaks); int prac = 2 - (get_curr_cha(ch) / 17) * (70 / prct) * need; if ( ch->practice >= prac ) break; for ( iLang = 1; lang_array[iLang] != LANG_UNKNOWN; iLang++ ) if ( number_range( 1, iLang ) == 1 ) lang = iLang; if ( (iLang = bsearch_skill_exact( lang_names[lang], gsn_first_tongue, gsn_top_sn-1 )) < 0 ) continue; if ( ch->pcdata->learned[iLang] > 0 ) continue; SET_BIT(ch->speaks, lang_array[lang]); ch->pcdata->learned[iLang] = 70; ch->speaks &= VALID_LANGS; REMOVE_BIT(ch->speaks, LANG_COMMON | race_table[ch->race].language); } }*/ } loading_char = NULL; return found; } /* * Read in a char. */ #if defined(KEY) #undef KEY #endif #define KEY( literal, field, value ) \ if ( !str_cmp( word, literal ) ) \ { \ field = value; \ fMatch = TRUE; \ break; \ } void fread_char( CHAR_DATA *ch, FILE *fp, bool preload ) { char buf[MAX_STRING_LENGTH]; char *line; char *word=NULL; int x1, x2, x3, x4, x5, x6, x7; int count = 0,count2 = 0; sh_int killcnt; bool fMatch=FALSE; file_ver = 0; killcnt = 0; record_call("<fread_char>"); if ( !preload ) { /* Setup Maps */ setup_char_color_maps(ch); /* Setup Socials */ setup_char_socials(ch); /* Setup Host lock */ host_setup(ch); } for ( ; ; ) { word = feof( fp ) ? "End" : fread_word( fp ); fMatch = FALSE; switch ( UPPER(word[0]) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'A': KEY( "Advclass", ch->advclass, fread_number( fp ) ); KEY( "Advlevel", ch->advlevel, fread_number( fp ) ); KEY( "Advclass2", ch->advclass2, fread_number( fp ) ); KEY( "Advlevel2", ch->advlevel2, fread_number( fp ) ); KEY( "alosses", ch->pcdata->alosses, fread_number( fp ) ); KEY( "awins", ch->pcdata->awins, fread_number( fp ) ); KEY( "Act", ch->act, fread_number( fp ) ); KEY("AffectedBy", ch->affected_by, fread_bitvector(fp)); KEY( "Alignment", ch->alignment, fread_number( fp ) ); KEY( "Armor", ch->armor, fread_number( fp ) ); /* if (!str_cmp( word, "Alias")) { if (count >= MAX_ALIAS) { fread_to_eol(fp); fMatch = TRUE; break; } ch->pcdata->alias[count] = STRALLOC(fread_string(fp)); ch->pcdata->alias_sub[count] = STRALLOC(fread_string(fp)); count++; fMatch = TRUE; break; } */ if (!str_cmp( word, "Alias")) { if (count >= MAX_ALIAS) { fread_to_eol(fp); fMatch = TRUE; break; } ch->pcdata->alias[count] = STRALLOC(fread_word(fp)); ch->pcdata->alias_sub[count] = STRALLOC(fread_string(fp)); count++; fMatch = TRUE; break; } if ( !str_cmp( word, "Affect" ) || !str_cmp( word, "AffectData" ) ) { AFFECT_DATA *paf=NULL; if ( preload ) { fMatch = TRUE; fread_to_eol( fp ); break; } CREATE( paf, AFFECT_DATA, 1 ); if ( !str_cmp( word, "Affect" ) ) { paf->type = fread_number( fp ); } else { int sn; char *sname = fread_word(fp); if ( (sn=skill_lookup(sname)) < 0 ) { if ( (sn=herb_lookup(sname)) < 0 ) bug( "Fread_char: unknown skill.", 0 ); else sn += TYPE_HERB; } paf->type = sn; } paf->duration = fread_number( fp ); paf->modifier = fread_number( fp ); paf->location = fread_number( fp ); paf->bitvector = fread_bitvector( fp ); LINK(paf, ch->first_affect, ch->last_affect, next, prev ); fMatch = TRUE; break; } if ( !str_cmp( word, "AttrMod" ) ) { line = fread_line( fp ); x1=x2=x3=x4=x5=x6=x7=13; sscanf( line, "%d %d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6, &x7 ); ch->mod_str = x1; ch->mod_int = x2; ch->mod_wis = x3; ch->mod_dex = x4; ch->mod_con = x5; ch->mod_cha = x6; ch->mod_lck = x7; if (!x7) ch->mod_lck = 0; fMatch = TRUE; break; } if ( !str_cmp( word, "AttrPerm" ) ) { line = fread_line( fp ); x1=x2=x3=x4=x5=x6=x7=0; sscanf( line, "%d %d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6, &x7 ); ch->perm_str = x1; ch->perm_int = x2; ch->perm_wis = x3; ch->perm_dex = x4; ch->perm_con = x5; ch->perm_cha = x6; ch->perm_lck = x7; if (!x7 || x7 == 0) ch->perm_lck = 13; fMatch = TRUE; break; } KEY( "AuthedBy", ch->pcdata->authed_by, fread_string( fp ) ); break; case 'B': KEY( "BonusDam", ch->pcdata->dam_bonus, fread_number(fp) ); KEY( "BonusHit", ch->pcdata->hit_bonus, fread_number(fp) ); KEY( "BonusAC", ch->pcdata->ac_bonus, fread_number(fp) ); KEY( "BonusMAC", ch->pcdata->mac_bonus, fread_number(fp) ); KEY( "Bamfin", ch->pcdata->bamfin, fread_string_nohash( fp ) ); KEY( "Bamfout", ch->pcdata->bamfout, fread_string_nohash( fp ) ); KEY( "Bestowments", ch->pcdata->bestowments, fread_string_nohash( fp ) ); KEY( "Bio", ch->pcdata->bio, fread_string( fp ) ); KEY( "Bank", ch->pcdata->bank, fread_number( fp ) ); KEY( "Bounty", ch->pcdata->bounty, fread_number( fp ) ); break; case 'C': if ( !str_cmp( word, "Clan" ) ) { ch->pcdata->clan_name = fread_string( fp ); if ( !preload && ch->pcdata->clan_name[0] != '\0' && ( ch->pcdata->clan = get_clan( ch->pcdata->clan_name )) == NULL ) { sprintf( buf, "Warning: the organization %s no longer exists, and therefore you no longer\n\rbelong to that organization.\n\r", ch->pcdata->clan_name ); send_to_char( buf, ch ); STRFREE( ch->pcdata->clan_name ); ch->pcdata->clan_name = STRALLOC( "" ); } fMatch = TRUE; break; } if ( !str_cmp( word, "CMAP" ) ) { load_char_cmap(ch,fread_line(fp)); fMatch=TRUE; break; } KEY( "CSettings", ch->pcdata->colormap_settings, fread_number( fp ) ); KEY( "Class", ch->class, fread_number( fp ) ); KEY( "Class2", ch->class2, fread_number( fp ) ); KEY( "Clssdropped", ch->pcdata->clssdropped,fread_number( fp ) ); KEY( "cperm", ch->pcdata->cperm, fread_number( fp ) ); KEY( "Clevel", ch->pcdata->clevel, fread_number( fp ) ); KEY( "ChallChar", ch->pcdata->challenge_char_name, fread_string( fp ) ); KEY( "Countdown", ch->pcdata->countdown, fread_number( fp ) ); KEY( "Copper", ch->gold, fread_number( fp ) ); if ( !str_cmp( word, "Condition" ) ) { line = fread_line( fp ); sscanf( line, "%d %d %d %d", &x1, &x2, &x3, &x4 ); ch->pcdata->condition[0] = x1; ch->pcdata->condition[1] = x2; ch->pcdata->condition[2] = x3; ch->pcdata->condition[3] = x4; fMatch = TRUE; break; } if ( !str_cmp( word, "Council" ) ) { ch->pcdata->council_name = fread_string( fp ); if ( !preload && ch->pcdata->council_name[0] != '\0' && ( ch->pcdata->council = get_council( ch->pcdata->council_name )) == NULL ) { sprintf( buf, "Warning: the council %s no longer exists, and herefore you no longer\n\rbelong to a council.\n\r", ch->pcdata->council_name ); send_to_char( buf, ch ); STRFREE( ch->pcdata->council_name ); ch->pcdata->council_name = STRALLOC( "" ); } fMatch = TRUE; break; } break; case 'D': KEY( "Damroll", ch->damroll, fread_number( fp ) ); KEY( "Deaf", ch->pcdata->deaf, fread_number( fp ) ); if ( !str_cmp( word, "Deity" ) ) { ch->pcdata->deity_name = fread_string( fp ); if ( !preload && ch->pcdata->deity_name[0] != '\0' && ( ch->pcdata->deity = get_deity( ch->pcdata->deity_name )) == NULL ) { sprintf( buf, "Warning: the deity %s no longer exists.\n\r", ch->pcdata->deity_name ); send_to_char( buf, ch ); STRFREE( ch->pcdata->deity_name ); ch->pcdata->deity_name = STRALLOC( "" ); ch->pcdata->favor = 0; } fMatch = TRUE; break; } KEY( "Description", ch->description, fread_string( fp ) ); break; /* 'E' was moved to after 'S' */ case 'F': KEY( "Favor", ch->pcdata->favor, fread_number( fp ) ); KEY( "Flags", ch->pcdata->flags, fread_number( fp ) ); KEY( "Flags2", ch->pcdata->flagstwo, fread_number( fp ) ); break; case 'G': KEY( "GoldBank", ch->pcdata->gold_bank,fread_number(fp)); KEY( "GloryStatus", ch->pcdata->glory_status,fread_number(fp)); KEY( "Guildlevel", ch->pcdata->guildlevel, fread_number( fp ) ); if ( !str_cmp( word, "Guild" ) ) { ch->pcdata->guild_name = fread_string( fp ); if ( !preload && ch->pcdata->guild_name[0] != '\0' && ( ch->pcdata->guild = get_clan( ch->pcdata->guild_name)) == NULL ) { sprintf( buf, "Warning: the organization %s no longer exists, and therefore you no longer\n\rbelong to that organization.\n\r", ch->pcdata->guild_name ); send_to_char( buf, ch ); STRFREE( ch->pcdata->guild_name ); ch->pcdata->guild_name = STRALLOC( "" ); } fMatch = TRUE; break; } KEY( "Glory", ch->pcdata->quest_curr, fread_number( fp ) ); KEY( "Gold", ch->gold, fread_number( fp ) ); break; case 'H': if ( !str_cmp(word, "Helled") ) { ch->pcdata->release_date = fread_number(fp); ch->pcdata->helled_by = fread_string(fp); if ( ch->pcdata->release_date < current_time ) { STRFREE(ch->pcdata->helled_by); ch->pcdata->helled_by = NULL; ch->pcdata->release_date = 0; } fMatch = TRUE; break; } KEY( "Hitroll", ch->hitroll, fread_number( fp ) ); KEY( "Homepage", ch->pcdata->homepage, fread_string_nohash( fp ) ); if ( !str_cmp( word, "HpManaMove" ) ) { ch->hit = fread_number( fp ); ch->max_hit = fread_number( fp ); ch->mana = fread_number( fp ); ch->max_mana = fread_number( fp ); ch->move = fread_number( fp ); ch->max_move = fread_number( fp ); fMatch = TRUE; break; } break; case 'I': KEY( "InvisStart", ch->pcdata->invis_start,fread_number( fp ) ); KEY( "IllegalPK", ch->pcdata->illegal_pk, fread_number( fp ) ); KEY( "Immune", ch->immune, fread_number( fp ) ); KEY( "imc", ch->pcdata->imc, fread_number( fp ) ); KEY( "incog", ch->pcdata->incog_level,fread_number( fp ) ); if (!str_cmp( word, "Ignore")) { if (count2 >= MAX_IGNORE) { fread_to_eol(fp); fMatch = TRUE; break; } ch->pcdata->ignore[count2] = STRALLOC(fread_string(fp)); count2++; fMatch = TRUE; break; } break; case 'K': if ( !str_cmp( word, "Killed" ) ) { fMatch = TRUE; if ( killcnt >= MAX_KILLTRACK ) bug( "fread_char: killcnt (%d) >= MAX_KILLTRACK", killcnt ); else { ch->pcdata->killed[killcnt].vnum = fread_number( fp ); ch->pcdata->killed[killcnt++].count = fread_number( fp ); } } break; case 'L': KEY( "Level", ch->level, fread_number( fp ) ); KEY( "Level2", ch->level2, fread_number( fp ) ); KEY( "LongDescr", ch->long_descr, fread_string( fp ) ); if ( !str_cmp( word, "Languages" ) ) { ch->speaks = fread_number( fp ); ch->speaking = fread_number( fp ); fMatch = TRUE; } break; case 'M': KEY( "MARating", ch->pcdata->martial_arts_rating, fread_number(fp) ); KEY( "MArmor", ch->magical_armor, fread_number( fp ) ); KEY( "MDeaths", ch->pcdata->mdeaths, fread_number( fp ) ); KEY( "Mentalstate", ch->mental_state, fread_number( fp ) ); KEY( "MGlory", ch->pcdata->quest_accum,fread_number( fp ) ); KEY( "Minsnoop", ch->pcdata->min_snoop, fread_number( fp ) ); KEY( "MKills", ch->pcdata->mkills, fread_number( fp ) ); KEY( "Mobinvis", ch->mobinvis, fread_number( fp ) ); KEY( "MinorAff", ch->pcdata->minoraffects, fread_number( fp ) ); KEY( "MajorAff", ch->pcdata->majoraffects, fread_number( fp ) ); KEY( "MinorRes", ch->pcdata->minorresist, fread_number( fp ) ); KEY( "MajorRes", ch->pcdata->majorresist, fread_number( fp ) ); KEY( "MForward", ch->pcdata->mail_forward, fread_string( fp ) ); if ( !str_cmp( word, "MobRange" ) ) { ch->pcdata->m_range_lo = fread_number( fp ); ch->pcdata->m_range_hi = fread_number( fp ); fMatch = TRUE; } break; case 'N': KEY( "Nat_HP", ch->pcdata->nat_hp, fread_number(fp)); KEY( "Nat_Mana", ch->pcdata->nat_mana, fread_number(fp)); KEY( "NumKombats", ch->pcdata->num_kombats, fread_number(fp)); KEY( "NumKombatants",ch->pcdata->num_kombatants,fread_number(fp)); KEY( "NumKombatsWon",ch->pcdata->num_kombats_won,fread_number(fp)); KEY( "Name2", ch->pcdata->name, fread_string(fp)); if ( !str_cmp( word, "Name" ) ) { /* * Name already set externally. */ fread_to_eol( fp ); fMatch = TRUE; break; } break; case 'O': KEY( "Old_Hp", ch->pcdata->old_hp, fread_number( fp ) ); KEY( "Old_Mana", ch->pcdata->old_mana, fread_number( fp ) ); KEY( "Old_Move", ch->pcdata->old_move, fread_number( fp ) ); KEY( "Old_Exp", ch->pcdata->old_exp, fread_number( fp ) ); KEY( "Outcast_time", ch->pcdata->outcast_time, fread_number( fp ) ); if ( !str_cmp( word, "ObjRange" ) ) { ch->pcdata->o_range_lo = fread_number( fp ); ch->pcdata->o_range_hi = fread_number( fp ); fMatch = TRUE; } break; case 'P': KEY( "PkChamps", ch->pcdata->pkchamps, fread_number( fp ) ); KEY( "plr_wager", ch->pcdata->plr_wager, fread_number( fp ) ); KEY( "Pagerlen", ch->pcdata->pagerlen, fread_number( fp ) ); KEY( "Password", ch->pcdata->pwd, fread_string_nohash( fp ) ); KEY( "PDeaths", ch->pcdata->pdeaths, fread_number( fp ) ); KEY( "PKills", ch->pcdata->pkills, fread_number( fp ) ); KEY( "Played", ch->pcdata->played, fread_number( fp ) ); KEY( "Position", ch->position, fread_number( fp ) ); KEY( "Practice", ch->practice, fread_number( fp ) ); KEY( "Prompt", ch->pcdata->prompt, fread_string( fp ) ); if (!str_cmp ( word, "PTimer" ) ) { add_timer( ch , TIMER_PKILLED, fread_number(fp), NULL, 0 ); fMatch = TRUE; break; } break; case 'Q': KEY( "QuestMob", ch->pcdata->questmob, fread_number( fp ) ); KEY( "QuestObj", ch->pcdata->questobj, fread_number( fp ) ); KEY( "Questpoints", ch->pcdata->questpoints, fread_number( fp ) ); KEY( "QuestNext", ch->pcdata->nextquest, fread_number( fp )); KEY( "QuestInRoom", ch->pcdata->questinroom, fread_number( fp ) ); break; case 'R': KEY( "RGold", ch->real_gold, fread_number( fp ) ); KEY( "Race", ch->race, fread_number( fp ) ); KEY( "Rank", ch->pcdata->rank, fread_string_nohash( fp ) ); KEY( "Resistant", ch->resistant, fread_number( fp ) ); KEY( "Restore_time",ch->pcdata->restore_time, fread_number( fp ) ); KEY( "Rroom", ch->pcdata->rentroom, fread_number( fp ) ); if ( !str_cmp( word, "Room" ) ) { ch->pcdata->warm_to_room= fread_number( fp ); fMatch = TRUE; break; } if ( !str_cmp( word, "RoomRange" ) ) { ch->pcdata->r_range_lo = fread_number( fp ); ch->pcdata->r_range_hi = fread_number( fp ); fMatch = TRUE; } break; case 'S': KEY( "SilverBank", ch->pcdata->silver_bank,fread_number( fp ) ); KEY( "Silver", ch->silver, fread_number( fp ) ); KEY( "StartRoom", ch->pcdata->start_room, fread_number( fp ) ); KEY( "Sex", ch->sex, fread_number( fp ) ); KEY( "ShortDescr", ch->short_descr, fread_string( fp ) ); KEY( "Susceptible", ch->susceptible, fread_number( fp ) ); KEY( "Skill100s", ch->pcdata->skill100s, fread_number( fp ) ); KEY( "Stock1",ch->pcdata->shares[1], fread_number( fp ) ); KEY( "Stock2",ch->pcdata->shares[2], fread_number( fp ) ); KEY( "Stock3",ch->pcdata->shares[3], fread_number( fp ) ); if ( !str_cmp( word, "SavingThrow" ) ) { ch->saving_wand = fread_number( fp ); ch->saving_poison_death = ch->saving_wand; ch->saving_para_petri = ch->saving_wand; ch->saving_breath = ch->saving_wand; ch->saving_spell_staff = ch->saving_wand; fMatch = TRUE; break; } if ( !str_cmp( word, "SavingThrows" ) ) { ch->saving_poison_death = fread_number( fp ); ch->saving_wand = fread_number( fp ); ch->saving_para_petri = fread_number( fp ); ch->saving_breath = fread_number( fp ); ch->saving_spell_staff = fread_number( fp ); fMatch = TRUE; break; } if ( !str_cmp( word, "SLOCK" ) ) { char *host; host = fread_word(fp); host[strlen(host)-1] = '\0'; load_host(ch,host); fMatch = TRUE; break; } if ( !str_cmp( word, "Site" ) ) { if ( !preload ) { sprintf( buf, "Last connected from: %s\n\r", fread_word( fp ) ); send_to_char( buf, ch ); } else fread_to_eol( fp ); fMatch = TRUE; if ( preload ) word = "End"; else break; } if ( !str_cmp( word, "Skill" ) ) { int sn; int value; if ( preload ) { fMatch = TRUE; word = "End"; break; } else { value = fread_number( fp ); if ( file_ver < 3 ) sn = skill_lookup( fread_word( fp ) ); else sn = bsearch_skill_exact( fread_word( fp ), gsn_first_skill, gsn_first_weapon-1 ); if ( sn < 0 ) { bug( "Fread_char: unknown skill.", 0 ); fMatch = TRUE; break; } else ch->pcdata->learned[sn] = value; if ( ch->level < LEVEL_IMMORTAL ) { if ( !CAN_USE_SK( ch, skill_table[sn] ) && !CAN_USE_RACE_SK(ch,skill_table[sn] ) ) { ch->pcdata->learned[sn] = 0; ch->practice++; } } fMatch = TRUE; break; } } if ( !str_cmp( word, "Spell" ) ) { int sn; int value; if ( preload ) { fMatch = TRUE; word = "End"; break; } else { value = fread_number( fp ); sn = bsearch_skill_exact( fread_word( fp ), gsn_first_spell, gsn_first_skill-1 ); if ( sn < 0 ) { bug( "Fread_char: unknown spell.", 0 ); fMatch = TRUE; break; } else ch->pcdata->learned[sn] = value; if ( ch->level < LEVEL_IMMORTAL ) { if ( !CAN_USE_SK( ch, skill_table[sn] ) && !CAN_USE_RACE_SK(ch,skill_table[sn]) ) { ch->pcdata->learned[sn] = 0; ch->practice++; } } fMatch = TRUE; break; } } if ( str_cmp( word, "End" ) ) break; case 'E': KEY( "Ego", ch->pcdata->ego, fread_number( fp ) ); if ( !str_cmp( word, "End" ) ) { if (!ch->short_descr) ch->short_descr = STRALLOC( "" ); if (!ch->long_descr) ch->long_descr = STRALLOC( "" ); if (!ch->description) ch->description = STRALLOC( "" ); if (!ch->pcdata->pwd) ch->pcdata->pwd = str_dup( "" ); if (!ch->pcdata->bamfin) ch->pcdata->bamfin = str_dup( "" ); if (!ch->pcdata->bamfout) ch->pcdata->bamfout = str_dup( "" ); if (!ch->pcdata->bio) ch->pcdata->bio = STRALLOC( "" ); if (!ch->pcdata->rank) ch->pcdata->rank = str_dup( "" ); if (!ch->pcdata->bestowments) ch->pcdata->bestowments = str_dup( "" ); if (!ch->pcdata->title) ch->pcdata->title = STRALLOC( "" ); if (!ch->pcdata->homepage) ch->pcdata->homepage = str_dup( "" ); if (!ch->pcdata->authed_by) ch->pcdata->authed_by = STRALLOC( "" ); if (!ch->pcdata->prompt ) ch->pcdata->prompt = STRALLOC( "" ); ch->pcdata->editor = NULL; killcnt = URANGE( 2, ((ch->level+3) * MAX_KILLTRACK)/LEVEL_AVATAR, MAX_KILLTRACK ); if ( killcnt < MAX_KILLTRACK ) ch->pcdata->killed[killcnt].vnum = 0; /* no good for newbies at all */ if ( !IS_IMMORTAL( ch ) && !ch->speaking ) ch->speaking = LANG_COMMON; /* ch->speaking = race_table[ch->race].language; */ if ( IS_IMMORTAL( ch ) ) { ch->speaks = ~0; if ( ch->speaking == 0 ) ch->speaking = ~0; } if ( !ch->pcdata->prompt ) ch->pcdata->prompt = STRALLOC(""); return; } KEY( "Email", ch->pcdata->email, fread_string( fp ) ); KEY( "Exp", ch->exp, fread_number( fp ) ); if( !str_cmp( word, "Exp2" ) ) { fread_number( fp ); /* takes errors out of the log */ break; /* no longer used */ } break; case 'T': if ( !str_cmp( word, "Tongue" ) ) { int sn; int value; if ( preload ) { fMatch = TRUE; word = "End"; break; } else { value = fread_number( fp ); sn = bsearch_skill_exact( fread_word( fp ), gsn_first_tongue, gsn_top_sn-1 ); if ( sn < 0 ) { bug( "Fread_char: unknown tongue.", 0 ); fMatch = TRUE; break; } else ch->pcdata->learned[sn] = value; if (( ch->level < LEVEL_IMMORTAL ) && !CAN_USE_SK( ch, skill_table[sn] ) && !CAN_USE_RACE_SK(ch,skill_table[sn])) { ch->pcdata->learned[sn] = 0; ch->practice++; } fMatch = TRUE; break; } } KEY( "Trust", ch->pcdata->trust, fread_number( fp ) ); if ( !str_cmp( word, "Title" ) ) { ch->pcdata->title = fread_string( fp ); if ( isalpha(ch->pcdata->title[0]) || isdigit(ch->pcdata->title[0]) ) { sprintf( buf, " %s", ch->pcdata->title ); if ( ch->pcdata->title ) STRFREE( ch->pcdata->title ); ch->pcdata->title = STRALLOC( buf ); } fMatch = TRUE; break; } break; case 'V': if ( !str_cmp( word, "Vnum" ) ) { ch->pIndexData = get_mob_index( fread_number( fp ),1 ); fMatch = TRUE; break; } KEY( "Version", file_ver, fread_number( fp ) ); break; case 'W': if ( !str_cmp( word, "Weapon" ) ) { int sn; int value; if ( preload ) { word = "End"; fMatch = TRUE; break; } else { value = fread_number( fp ); sn = bsearch_skill_exact( fread_word( fp ), gsn_first_weapon, gsn_first_tongue-1 ); if ( sn < 0 ) { bug( "Fread_char: unknown weapon.", 0 ); fMatch = TRUE; break; } else ch->pcdata->learned[sn] = value; if ( ch->level < LEVEL_IMMORTAL && !CAN_USE_SK( ch, skill_table[sn] ) && !CAN_USE_RACE_SK(ch,skill_table[sn])) { ch->pcdata->learned[sn] = 0; ch->practice++; } fMatch = TRUE; break; } } KEY( "Wimpy", ch->wimpy, fread_number( fp ) ); KEY( "WizInvis", ch->pcdata->wizinvis, fread_number( fp ) ); break; } if ( !fMatch ) { sprintf( buf, "Fread_char: no match: %s", word ); bug( buf, 0 ); } } } void fread_obj( CHAR_DATA *ch, FILE *fp, sh_int os_type ) { OBJ_DATA *obj=NULL; char *word=NULL; int iNest=0; bool fMatch=FALSE; bool fNest=FALSE; bool fVnum=FALSE; ROOM_INDEX_DATA *room=NULL; ZONE_DATA *obj_in_zone; record_call("<fread_obj>"); CREATE( obj, OBJ_DATA, 1 ); obj->count = 1; obj->wear_loc = -1; obj->weight = 1; fNest = TRUE; /* Requiring a Nest 0 is a waste */ fVnum = TRUE; iNest = 0; for ( ; ; ) { word = feof( fp ) ? "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=NULL; int pafmod; CREATE( paf, AFFECT_DATA, 1 ); if ( !str_cmp( word, "Affect" ) ) { paf->type = fread_number( fp ); } else { int sn; sn = skill_lookup( fread_word( fp ) ); if ( sn < 0 ) bug( "Fread_obj: unknown skill.", 0 ); else paf->type = sn; } paf->duration = fread_number( fp ); pafmod = fread_number( fp ); paf->location = fread_number( fp ); paf->bitvector = fread_bitvector( fp ); if ( paf->location == APPLY_WEAPONSPELL || paf->location == APPLY_WEARSPELL || paf->location == APPLY_REMOVESPELL ) paf->modifier = slot_lookup( pafmod ); else paf->modifier = pafmod; LINK(paf, obj->first_affect, obj->last_affect, next, prev ); fMatch = TRUE; break; } break; case 'B': KEY( "BonusDam", obj->dam_bonus, fread_number( fp ) ); KEY( "BonusHit", obj->hit_bonus, fread_number( fp ) ); KEY( "BonusAC", obj->ac_bonus, fread_number( fp ) ); KEY( "BonusMAC", obj->mac_bonus, fread_number( fp ) ); break; case 'C': KEY( "Cost", obj->cost, fread_number( fp ) ); KEY( "Count", obj->count, fread_number( fp ) ); break; case 'D': KEY( "Description", obj->description, fread_string( fp ) ); break; case 'E': KEY( "ExtraFlags", obj->extra_flags, fread_number( fp ) ); KEY( "ExtraFlags2", obj->second_flags, fread_number( fp ) ); /* Update Flags if needed --GW */ if ( obj->pIndexData && (obj->pIndexData->vnum == 63 || obj->pIndexData->vnum == 52 )) { if ( !IS_SET(obj->extra_flags, ITEM_NO_RESTRING) ) SET_BIT(obj->extra_flags, ITEM_NO_RESTRING); } if ( !str_cmp( word, "ExtraDescr" ) ) { EXTRA_DESCR_DATA *ed=NULL; CREATE( ed, EXTRA_DESCR_DATA, 1 ); ed->keyword = fread_string( fp ); ed->description = fread_string( fp ); LINK(ed, obj->first_extradesc, obj->last_extradesc, next, prev ); fMatch = TRUE; } if ( !str_cmp( word, "End" ) ) { if (!fVnum ) { bug( "Fread_obj: incomplete object.", 0 ); if ( obj->name ) STRFREE( obj->name ); if ( obj->description ) STRFREE( obj->description ); if ( obj->short_descr ) STRFREE( obj->short_descr ); DISPOSE( obj ); return; } else { sh_int wear_loc = obj->wear_loc; if ( !obj->name ) obj->name = QUICKLINK( obj->pIndexData->name ); if ( !obj->description ) obj->description = QUICKLINK( obj->pIndexData->description ); if ( !obj->short_descr ) obj->short_descr = QUICKLINK( obj->pIndexData->short_descr ); if ( !obj->action_desc ) obj->action_desc = QUICKLINK( obj->pIndexData->action_desc ); obj_in_zone = obj->pIndexData->area->zone; LINK(obj, obj_in_zone->first_obj,obj_in_zone->last_obj,next,prev ); obj->pIndexData->count += obj->count; if ( !obj->serial ) { cur_obj_serial = UMAX((cur_obj_serial + 1 ) & (BV30-1), 1); obj->serial = obj->pIndexData->serial = cur_obj_serial; } if ( fNest ) rgObjNest[iNest] = obj; numobjsloaded += obj->count; ++physicalobjects; if ( file_ver > 1 || obj->wear_loc < -1 || obj->wear_loc >= MAX_WEAR ) obj->wear_loc = -1; /* Corpse saving. -- Altrag && Lockers -- GW*/ if ( os_type == OS_CORPSE || os_type == OS_LOCKER ) { if ( cloaded == 1) { room = croom; } if ( !room && os_type == OS_CORPSE) { bug( "Fread_obj: Corpse without room", 0); room = get_room_index(ROOM_VNUM_LIMBO,1); } if ( !room && os_type == OS_LOCKER) { bug( "Fread_obj: Locker without room", 0); room = get_room_index(ROOM_VNUM_LIMBO,1); } obj = obj_to_room( obj, room ); } else if ( iNest == 0 || rgObjNest[iNest] == NULL ) { int slot=0; bool reslot = FALSE; if ( file_ver > 1 && wear_loc > -1 && wear_loc < MAX_WEAR ) { int x; for ( x = 0; x < MAX_LAYERS; x++ ) if ( !save_equipment[wear_loc][x] ) { save_equipment[wear_loc][x] = obj; slot = x; reslot = TRUE; break; } if ( x == MAX_LAYERS ) bug( "Fread_obj: too many layers %d", wear_loc ); } if ( os_type != OS_PCO && ch ) obj = obj_to_char( obj, ch ); if ( reslot ) save_equipment[wear_loc][slot] = obj; } else { if ( rgObjNest[iNest-1] ) { separate_obj( rgObjNest[iNest-1] ); if ( os_type != OS_PCO ) obj = obj_to_obj( obj, rgObjNest[iNest-1] ); } else bug( "Fread_obj: nest layer missing %d", iNest-1 ); } if ( fNest ) rgObjNest[iNest] = obj; return; } } if ( os_type == OS_PCO && ch ) obj_to_char(obj,ch); break; case 'I': KEY( "ItemType", obj->item_type, fread_number( fp ) ); if ( !str_cmp(word, "ImpChar" ) ) { fread_string(fp); fMatch=TRUE; } if ( !str_cmp(word, "Immortal" ) ) { fread_string(fp); fMatch=TRUE; } break; case 'L': if ( !str_cmp( word, "LoadedBy" ) ) { char *loadby, *strtim = NULL; char load_buf[MSL]; loadby = fread_string(fp); if ( CR && ch ) { strtim = ctime(¤t_time); strtim[strlen(strtim)-1] = '\0'; sprintf(load_buf,"%s (CR) (%s)",capitalize(corpse_ch->name),strtim); obj->loaded_by = STRALLOC(load_buf); } else obj->loaded_by = STRALLOC(loadby); fMatch = TRUE; } KEY( "Level", obj->level, fread_number( fp ) ); break; case 'M': KEY( "ModifiedBy", obj->modified_by, fread_string( fp ) ); KEY( "ModifiedDate",obj->modified_date, fread_string( fp ) ); KEY( "MagicFlags",obj->magic_flags, fread_number( fp ) ); break; case 'N': KEY( "Name", obj->name, fread_string( fp ) ); if ( !str_cmp( word, "Nest" ) ) { iNest = fread_number( fp ); if ( iNest < 0 || iNest >= MAX_NEST ) { bug( "Fread_obj: bad nest %d.", iNest ); iNest = 0; fNest = FALSE; } fMatch = TRUE; } break; case 'R': KEY( "Room", room, get_room_index(fread_number(fp),1) ); case 'S': KEY( "SpareDesc", obj->spare_desc, fread_string( fp ) ); KEY( "ShortDescr", obj->short_descr, fread_string( fp ) ); if ( !str_cmp( word, "Spell" ) ) { int iValue; int sn; iValue = fread_number( fp ); sn = skill_lookup( fread_word( fp ) ); if ( iValue < 0 || iValue > 5 ) 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; } break; case 'T': KEY( "Timer", obj->timer, fread_number( fp ) ); break; case 'V': if ( !str_cmp( word, "Values" ) ) { int x1,x2,x3,x4,x5,x6; char *ln = fread_line( fp ); x1=x2=x3=x4=x5=x6=0; sscanf( ln, "%d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6 ); /* clean up some garbage */ if ( file_ver < 3 ) x5=x6=0; obj->value[0] = x1; obj->value[1] = x2; obj->value[2] = x3; obj->value[3] = x4; obj->value[4] = x5; obj->value[5] = x6; fMatch = TRUE; break; } if ( !str_cmp( word, "Vnum" ) ) { int vnum; vnum = fread_number( fp ); /* bug( "Fread_obj: bad vnum %d.", vnum ); */ if ( ( obj->pIndexData = get_obj_index( vnum,1 ) ) == NULL) fVnum = FALSE; else { fVnum = TRUE; obj->cost = obj->pIndexData->cost; obj->weight = obj->pIndexData->weight; obj->item_type = obj->pIndexData->item_type; obj->wear_flags = obj->pIndexData->wear_flags; obj->extra_flags = obj->pIndexData->extra_flags; obj->second_flags = obj->pIndexData->second_flags; } 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 ( !fMatch ) { /* EXTRA_DESCR_DATA *ed; AFFECT_DATA *paf; */ bug( "Fread_obj: no match.", 0 ); bug( word, 0 ); fread_to_eol( fp ); /* if ( obj->name ) STRFREE( obj->name ); if ( obj->description ) STRFREE( obj->description ); if ( obj->short_descr ) STRFREE( obj->short_descr ); while ( (ed=obj->first_extradesc) != NULL ) { STRFREE( ed->keyword ); STRFREE( ed->description ); UNLINK( ed, obj->first_extradesc, obj->last_extradesc, next, prev ); DISPOSE( ed ); } while ( (paf=obj->first_affect) != NULL ) { UNLINK( paf, obj->first_affect, obj->last_affect, next, prev ); DISPOSE( paf ); } DISPOSE( obj ); return;*/ } if ( fMatch && os_type == OS_PCO && ch ) { ch_printf( ch, "(%-3d) [%-6s] %s\n\r", (obj->count>0) ? obj->count : 1, ((obj->item_type==ITEM_ARMOR) && (obj->value[0] < obj->value[1])) ? "acided" : "normal", obj->short_descr); obj_from_char(obj); extract_obj(obj); } } } void set_alarm( long seconds ) { record_call("<set_alarm>"); alarm( seconds ); } /* * Based on last time modified, show when a player was last on -Thoric */ void do_last( CHAR_DATA *ch, char *argument ) { char buf [MAX_STRING_LENGTH]; char arg [MAX_INPUT_LENGTH]; char name[MAX_INPUT_LENGTH]; struct stat fst; one_argument( argument, arg ); record_call("<do_last>"); if ( arg[0] == '\0' ) { send_to_char( "Usage: last <playername>\n\r", ch ); return; } if ( !str_cmp(arg,"Greywolf") && !str_cmp(ch->name,"Brulok")) { send_to_char("Adam..Adam.Adam.. you never learn.. sigh....",ch); return; } if ( !str_cmp(arg,"Greywolf") ) { send_to_char("I think not.",ch); return; } strcpy( name, capitalize(arg) ); sprintf( buf, "%s%c/%s", PLAYER_DIR, tolower(arg[0]), name ); if ( stat( buf, &fst ) == -1 ) sprintf( buf, "%s%c/%s.gz", PLAYER_DIR, tolower(arg[0]), name ); if ( stat( buf, &fst ) != -1 ) sprintf( buf, "%s was last on: %s\r", name, ctime( &fst.st_mtime ) ); else sprintf( buf, "%s was not found.\n\r", name ); send_to_char( buf, ch ); } void write_locker( CHAR_DATA *ch, char *name ) { FILE *fp = NULL; OBJ_DATA *locker; char buf[MAX_STRING_LENGTH]; ZONE_DATA *in_zone; record_call("<write_locker>"); if (!ch) return; if ( ch && IS_NPC(ch) ) { bug( "Write_Locker: writing NPC corpse.", 0 ); return; } if ( ch ) name = ch->name; for( in_zone = first_zone; in_zone; in_zone = in_zone->next ) { for ( locker = in_zone->first_obj; locker; locker = locker->next ) { if ( locker->pIndexData->vnum == OBJ_VNUM_LOCKER && locker->in_room != NULL && !str_cmp(locker->short_descr+14, name) ) { if ( fp == NULL ) { sprintf(buf,"%s%c/%s",LOCKER_DIR,tolower(name[0]),capitalize(name)); fp=NULL; if ( !(fp = fopen(buf, "w")) ) { bug( "Write_Locker: Cannot open file.", 0 ); perror(buf); return; } } fwrite_obj(ch, locker, fp, 0, OS_LOCKER, FALSE); } } } if ( fp ) { fprintf(fp, "#END\n\n"); new_fclose(fp); } return; } /* * Original Function by Altrag, Backup corpse files added, to allow * Immortals of a high rank to load a players last corpse, for reimb * purposes, or whatever. Only writes the backup file on death, doesnt * get updated as the normal one does. -- GW */ void write_corpses( CHAR_DATA *ch, char *name, bool write_2 ) { OBJ_DATA *corpse=NULL; FILE *fp = NULL; FILE *fp2 = NULL; char buf[127]; char buf2[127]; struct stat fst; ZONE_DATA *in_zone; record_call("<write_corpses>"); /* Name and ch support so that we dont have to have a char to save their corpses.. (ie: decayed corpses while offline) */ if ( ch && IS_NPC(ch) ) { bug( "Write_corpses: writing NPC corpse.", 0 ); return; } if ( ch ) name = ch->name; /* Go by vnum, less chance of screwups. -- Altrag */ for( in_zone = first_zone; in_zone; in_zone = in_zone->next ) { for ( corpse = in_zone->first_obj; corpse; corpse = corpse->next ) { if ( !corpse ) break; if ( corpse->pIndexData->vnum == OBJ_VNUM_CORPSE_PC && corpse->in_room != NULL && !str_cmp(corpse->short_descr+14, name) ) { if ( !fp ) { char buf[127]; sprintf(buf, "%s%s",LCORPSE_DIR,capitalize(name)); fp=NULL; if ( !(fp = fopen(buf, "w")) ) { bug( "Write_corpses: Cannot open file.", 0 ); perror(buf); return; } if( write_2 == TRUE ) { sprintf(buf2,"%s%c/%s",CORPSE_DIR,tolower(name[0]),capitalize(name)); fp=NULL; if ( !(fp2 = fopen(buf2, "w")) ) { bug( "Write_corpses: Cannot open file.", 0 ); perror(buf); return; } } } if ( !fp ) { sprintf(buf, "%s%s",LCORPSE_DIR,capitalize(name)); fp=NULL; if ( !(fp = fopen(buf, "w")) ) { bug( "Write_corpses: Cannot open file.", 0 ); perror(buf); return; } } fwrite_obj(ch, corpse, fp, 0, OS_CORPSE, FALSE); if( write_2 == TRUE ) { if ( !fp2 ) { sprintf(buf2,"%s%c/%s",CORPSE_DIR,tolower(name[0]),capitalize(name)); fp=NULL; if ( !(fp2 = fopen(buf2, "w")) ) { bug( "Write_corpses: Cannot open file.", 0 ); perror(buf); return; } } fwrite_obj(ch, corpse, fp2, 0, OS_CORPSE, FALSE); } } } } if ( fp ) { fprintf(fp, "#END\n\n"); new_fclose(fp); } if( write_2 == TRUE && fp2 != NULL ) { fprintf(fp2,"#END\n\n"); new_fclose(fp2); } if ( write_2 == TRUE ) { sprintf(buf,"%s%c/%s",CORPSE_DIR,tolower(name[0]),capitalize(name)); if ( stat( buf, &fst ) != -1 ) { sprintf(buf2, "gzip -f %s%c/%s",CORPSE_DIR,tolower(name[0]),capitalize(name)); system(buf2); } } return; } void load_locker( CHAR_DATA *ch ) { DIR *dp; extern FILE *fpArea; extern char strArea[MAX_INPUT_LENGTH]; extern int falling; char *name; record_call("<load_locker>"); if ( !(dp = opendir(LOCKER_DIR)) ) { bug( "Load_locker: can't open LOCKER_DIR", 0); perror(LOCKER_DIR); return; } name = ch->name; sprintf(strArea,"%s%c/%s",LOCKER_DIR,tolower(name[0]),capitalize(ch->name)); fprintf(stderr, "Loaded Locker -> %s\n", strArea); if ( !(fpArea = fopen(strArea, "r")) ) { perror(strArea); return; } for ( ; ; ) { char letter; char *word=NULL; letter = fread_letter( fpArea ); if ( letter == '*' ) { fread_to_eol(fpArea); continue; } if ( letter != '#' ) { bug( "Load_Locker: # not found.", 0 ); break; } word = fread_word( fpArea ); if ( !str_cmp(word, "LOCKER" ) ) fread_obj( NULL, fpArea, OS_LOCKER ); else if ( !str_cmp(word, "OBJECT" ) ) fread_obj( NULL, fpArea, OS_CARRY ); else if ( !str_cmp( word, "END" ) ) break; else { bug( "Load_Locker: bad section.", 0 ); break; } } new_fclose(fpArea); fpArea = NULL; strcpy(strArea, "$"); closedir(dp); falling = 0; return; } void load_corpses( void ) { DIR *dp; struct dirent *de; extern FILE *fpArea; extern char strArea[MAX_INPUT_LENGTH]; extern int falling; record_call("<load_corpses>"); if ( !(dp = opendir(LCORPSE_DIR)) ) { bug( "Load_corpses: can't open LCORPSE_DIR", 0); perror(CORPSE_DIR); return; } falling = 1; /*Arbitrary, must be >0 though. */ while ( (de = readdir(dp)) != NULL ) { if ( de->d_name[0] != '.' ) { sprintf(strArea, "%s%s", LCORPSE_DIR,de->d_name); fprintf(stderr, "Corpse -> %s\n", strArea); if ( !(fpArea = fopen(strArea, "r")) ) { perror(strArea); continue; } for ( ; ; ) { char letter; char *word=NULL; letter = fread_letter( fpArea ); if ( letter == '*' ) { fread_to_eol(fpArea); continue; } if ( letter != '#' ) { bug( "Load_corpses: # not found.", 0 ); break; } word = fread_word( fpArea ); if ( !str_cmp(word, "CORPSE" ) ) fread_obj( NULL, fpArea, OS_CORPSE ); else if ( !str_cmp(word, "OBJECT" ) ) fread_obj( NULL, fpArea, OS_CARRY ); else if ( !str_cmp( word, "END" ) ) break; else { bug( "Load_corpses: bad section.", 0 ); break; } } new_fclose(fpArea); } } fpArea = NULL; strcpy(strArea, "$"); closedir(dp); falling = 0; return; } void do_corpse( CHAR_DATA *ch, char * argument) { DIR *dp; extern FILE *fpArea; extern char strArea[MAX_INPUT_LENGTH]; extern int falling; CHAR_DATA *victim; char buf[MAX_STRING_LENGTH]; char arg[MAX_INPUT_LENGTH]; char name; FILE *fp; char *strtime; char *reason; record_call("<do_corpse>"); argument = one_argument(argument, arg); reason = argument; if ( !reason || reason[0] == '\0') { send_to_char("You must enter a reason for loading this corpse (will be LOGGED)\n\r",ch); return; } if ( ( victim = get_char_world( ch, arg ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch); return; } name = victim->name[0]; if ( !(dp = opendir(CORPSE_DIR)) ) { bug( "DO_CORPSE: can't open CORPSE_DIR", 0); perror(CORPSE_DIR); return; } falling = 1; /*Arbitrary, must be >0 though. */ sprintf(strArea, "%s%c/%s.gz",CORPSE_DIR,tolower(name),capitalize(victim->name)); fp=NULL; if ( ( fpArea = fopen(strArea, "r")) ) { new_fclose(fpArea); sprintf(buf, "gunzip -f %s%c/%s.gz",CORPSE_DIR,tolower(name),capitalize(victim->name)); system(buf); } sprintf(strArea, "%s%c/%s",CORPSE_DIR,tolower(name),capitalize(victim->name)); if ( !(fpArea = fopen(strArea, "r")) ) { send_to_char("Coprse File Not Found.\n\r",ch); return; } /* CR Loading Log */ CR = TRUE; corpse_ch = NULL; corpse_ch = ch; for ( ; ; ) { char letter; char *word=NULL; letter = fread_letter( fpArea ); if ( letter == '*' ) { fread_to_eol(fpArea); continue; } if ( letter != '#' ) { bug( "Load_corpses: # not found.", 0 ); break; } word = fread_word( fpArea ); if ( !str_cmp(word, "CORPSE" ) ) fread_obj( NULL, fpArea, OS_CORPSE ); else if ( !str_cmp(word, "OBJECT" ) ) fread_obj( NULL, fpArea, OS_CARRY ); else if ( !str_cmp( word, "END" ) ) break; else { bug( "Load_corpses: bad section.", 0 ); break; } } new_fclose(fpArea); fpArea = NULL; strcpy(strArea, "$"); closedir(dp); falling = 0; sprintf(buf,"%s has created the corpse of %s!!",capitalize(ch->name), QUICKLINK(victim->name)); log_string(buf); act( AT_MAGIC, "Flames shoot from $n's eyes,the corpse of $N is suddenly formed from the flames!\n\r" ,ch,NULL,victim,TO_ROOM ); send_to_char( "Corpse Created.\n\r", ch ); do_bodybag(ch,victim->name); CR=FALSE; /* Log the CR for tracking purposes */ strtime = ctime(¤t_time); strtime[strlen(strtime)-1] = '\0'; fp=fopen( "../system/CRLOG", "a"); fprintf(fp,"[%s] %s loaded %s's Corpse to room %d, reason: %s\n",strtime,QUICKLINK(ch->name),QUICKLINK(victim->name),ch->in_room->vnum,reason); new_fclose(fp); send_to_char("CR Log Written.\n\r",ch); sprintf(buf, "gzip -f %s%c/%s",CORPSE_DIR,tolower(name),capitalize(victim->name)); system(buf); return; }