/****************************************************************************
* ResortMUD Version 5.0 was mainly programmed by Ntanel, Garinan, Josh, *
* Badastaz, Digifuzz, Senir, Kratas, Scion, Shogar and Tagith. *
* ------------------------------------------------------------------------ *
* Copyright (C) 1996 - 2001 Haslage Net Electronics: MudWorld of Lorain, *
* Ohio. ALL RIGHTS RESERVED See /doc/RMLicense.txt for more details. *
****************************************************************************/
/****************************************************************************
* [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// *
* -----------------------------------------------------------| (0...0) *
* SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by Derek Snider | ).:.( *
* -----------------------------------------------------------| {o o} *
* SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ *
* Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek, |~'~.VxvxV.~'~*
* Tricops and Fireblade | *
* ------------------------------------------------------------------------ *
* 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 <string.h>
#include <ctype.h>
#include <time.h>
#include <sys/stat.h>
#ifndef WIN32
#include <dirent.h>
#endif
#include "mud.h"
#include "gboards.h"
void removename( char **list, const char *name );
MUD_CHANNEL *find_channel( char *name );
short find_old_age( CHAR_DATA * ch );
short calculate_age( CHAR_DATA * ch );
/*
* Increment with every major format change.
*/
#define SAVEVERSION 5
/*
* Array to keep track of equipment temporarily. -Thoric
*/
OBJ_DATA *save_equipment[MAX_WEAR][MAX_LAYERS];
CHAR_DATA *quitting_char, *loading_char, *saving_char;
int file_ver;
extern FILE *fpArea;
extern char strArea[MAX_INPUT_LENGTH];
extern int falling;
/*
* 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, OBJ_DATA * objrem ) );
void fwrite_alias( ALIAS_DATA * first_alias, FILE * fp );
void fread_alias( CHAR_DATA * ch, FILE * fp );
int get_obj_room_vnum_recursive( OBJ_DATA * obj );
#ifdef WIN32 /* NJG */
UINT timer_code = 0; /* needed to kill the timer */
/* Note: need to include: WINMM.LIB to link to timer functions */
void caught_alarm( );
void CALLBACK alarm_handler( UINT IDEvent, /* identifies timer event */
UINT uReserved, /* not used */
DWORD dwUser, /* application-defined instance data */
DWORD dwReserved1, /* not used */
DWORD dwReserved2 ) /* not used */
{
caught_alarm( );
}
void kill_timer( )
{
if( timer_code )
timeKillEvent( timer_code );
timer_code = 0;
}
#endif
/*
* 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;
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 )
{
if( ( get_trust( ch ) >= obj->level ) || ( obj->level < LEVEL_IMMORTAL ) )
{
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 obj->level = %d",
ch->name, obj->name,
ch->level, obj->level );
bug( buf, 0 ); -- Removed level restrictions -- Scion
}*/
unequip_char( ch, obj );
}
}
/*
* Re-equip character -Thoric
*/
void re_equip_char( CHAR_DATA * ch )
{
int x, y;
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[MAX_INPUT_LENGTH];
char strback[MAX_INPUT_LENGTH];
FILE *fp;
if( !ch )
{
bug( "Save_char_obj: null ch!", 0 );
return;
}
if( IS_NPC( ch ) || ( ch->level < 2 && ch->level2 == -1 && ch->level3 == -1 ) )
return;
saving_char = ch;
if( ch->desc && ch->desc->original )
ch = ch->desc->original;
de_equip_char( ch );
ch->save_time = current_time;
sprintf( strsave, "%s%c/%s", PLAYER_DIR, tolower( ch->pcdata->filename[0] ), capitalize( ch->pcdata->filename ) );
/*
* Auto-backup pfile (can cause lag with high disk access situtations).
*/
/*
* Backup of each pfile on save as above can cause lag in high disk
* access situations on big muds like Realms. Quitbackup saves most
* of that and keeps an adequate backup -- Blodkai, 10/97
*/
if( IS_SET( sysdata.save_flags, SV_BACKUP ) || ( IS_SET( sysdata.save_flags, SV_QUITBACKUP ) && quitting_char == ch ) )
{
sprintf( strback, "%s%c/%s", BACKUP_DIR, tolower( ch->pcdata->filename[0] ), capitalize( ch->pcdata->filename ) );
rename( strsave, strback );
}
/*
* 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 )
{
sprintf( strback, "%s%s", GOD_DIR, capitalize( ch->pcdata->filename ) );
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 );
fclose( fp );
}
}
if( ch->level > 103 && ch->level != 110 )
{
sprintf( strback, "%s%s.immlist", GOD_DIR, capitalize( ch->pcdata->filename ) );
if( ( fp = fopen( strback, "w" ) ) == NULL )
{
bug( "save_char_obj: IMMLIST: Unable to open!" );
perror( strback );
}
else
{
fprintf( fp, "Name %s~\n", ch->name );
fprintf( fp, "Level %d\n", ch->level );
if( ch->pcdata->lastname && ch->pcdata->lastname[0] != '\0' )
fprintf( fp, "Lastname %s~\n", ch->pcdata->lastname );
if( ch->pcdata->email && ch->pcdata->email[0] != '\0' )
fprintf( fp, "Email %s~\n", ch->pcdata->email );
fprintf( fp, "End\n" );
fclose( fp );
}
}
if( ( fp = fopen( strsave, "w" ) ) == NULL )
{
bug( "Save_char_obj: fopen", 0 );
perror( strsave );
}
else
{
fwrite_char( ch, fp );
if( ch->morph )
fwrite_morph_data( ch, fp );
if( ch->first_carrying )
fwrite_obj( ch, ch->last_carrying, fp, 0, OS_CARRY );
if( !IS_NPC( ch ) && ch->pcdata->first_alias )
fwrite_alias( ch->pcdata->first_alias, fp );
if( sysdata.save_pets && ch->pcdata->pet )
fwrite_mobile( fp, ch->pcdata->pet );
if( ch->comments ) /* comments */
fwrite_comments( ch, fp ); /* comments */
fprintf( fp, "#END\n" );
fclose( fp );
}
re_equip_char( ch );
quitting_char = NULL;
saving_char = NULL;
return;
}
/*
* Write the char.
*/
void fwrite_char( CHAR_DATA * ch, FILE * fp )
{
AFFECT_DATA *paf;
int sn, track, i;
short pos;
SKILLTYPE *skill = NULL;
fprintf( fp, "#PLAYER\n" );
fprintf( fp, "Version %d\n", SAVEVERSION );
fprintf( fp, "Name %s~\n", ch->name );
if( ch->description )
fprintf( fp, "Description %s~\n", ch->description );
fprintf( fp, "Sex %d\n", ch->sex );
fprintf( fp, "HairColor %s~\n", ch->pcdata->hair_color );
fprintf( fp, "HairLength %s~\n", ch->pcdata->hair_length );
fprintf( fp, "EyeColor %s~\n", ch->pcdata->eye_color );
fprintf( fp, "SkinTone %s~\n", ch->pcdata->skin_tone );
fprintf( fp, "CHBuild %s~\n", ch->pcdata->ch_build );
fprintf( fp, "CHHeight %s~\n", ch->pcdata->ch_height );
fprintf( fp, "Class %d\n", ch->class );
fprintf( fp, "Class2 %d\n", ch->class2 );
fprintf( fp, "Class3 %d\n", ch->class3 );
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 );
fprintf( fp, "Level3 %d\n", ch->level3 );
fprintf( fp, "Played %d\n", ch->played + ( int )( current_time - ch->logon ) );
fprintf( fp, "Bday %d\n", ch->day );
fprintf( fp, "Bmonth %d\n", ch->month );
fprintf( fp, "Byear %d\n", ch->year );
fprintf( fp, "Agemod %d\n", ch->age_bonus );
fprintf( fp, "Room %d\n",
( ch->in_room == get_room_index( ROOM_VNUM_LIMBO )
&& ch->was_in_room ) ? ch->was_in_room->vnum : ch->in_room->vnum );
if( ch->nextquest != 0 )
fprintf( fp, "QuestNext %d\n", ch->nextquest );
else if( ch->countdown != 0 )
fprintf( fp, "QuestNext %d\n", 30 );
fprintf( fp, "Memorized %d %d %d %d %d %d %d %d\n",
ch->pcdata->memorize[0],
ch->pcdata->memorize[1],
ch->pcdata->memorize[2],
ch->pcdata->memorize[3],
ch->pcdata->memorize[4], ch->pcdata->memorize[5], ch->pcdata->memorize[6], ch->pcdata->memorize[7] );
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, "Gold %d\n", ch->gold );
fprintf( fp, "Silver %d\n", ch->silver );
fprintf( fp, "Copper %d\n", ch->copper );
fprintf( fp, "Exp %d\n", ch->exp );
fprintf( fp, "Exp2 %d\n", ch->exp2 );
fprintf( fp, "Smites %d\n", ch->pcdata->smites );
fprintf( fp, "Smited %d\n", ch->pcdata->smited );
fprintf( fp, "Height %d\n", ch->height );
fprintf( fp, "Weight %d\n", ch->weight );
if( !xIS_EMPTY( ch->act ) )
fprintf( fp, "Act %s\n", print_bitvector( &ch->act ) );
if( !xIS_EMPTY( ch->affected_by ) )
fprintf( fp, "AffectedBy %s\n", print_bitvector( &ch->affected_by ) );
if( !xIS_EMPTY( ch->no_affected_by ) )
fprintf( fp, "NoAffectedBy %s\n", print_bitvector( &ch->no_affected_by ) );
/*
* Strip off fighting positions & store as
* new style (pos>=100 flags new style in character loading)
*/
pos = ch->position;
if( pos == POS_BERSERK || pos == POS_AGGRESSIVE || pos == POS_FIGHTING || pos == POS_DEFENSIVE || pos == POS_EVASIVE )
pos = POS_STANDING;
pos += 100;
fprintf( fp, "Position %d\n", pos );
fprintf( fp, "Style %d\n", ch->style );
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, "Balance %d\n", ch->pcdata->balance );
fprintf( fp, "GBalance %d\n", ch->pcdata->gbalance );
fprintf( fp, "SBalance %d\n", ch->pcdata->sbalance );
fprintf( fp, "Glory %d\n", ch->pcdata->quest_curr );
fprintf( fp, "MGlory %d\n", ch->pcdata->quest_accum );
fprintf( fp, "Hitroll %d\n", ch->hitroll );
fprintf( fp, "Damroll %d\n", ch->damroll );
fprintf( fp, "Armor %d\n", ch->armor );
fprintf( fp, "Bounty %d\n", ch->bounty );
fprintf( fp, "Bowed %d\n", ch->bowed );
fprintf( fp, "Belig %d\n", ch->belig );
fprintf( fp, "Bkills %d\n", ch->bkills );
if( ch->pcdata->wedto )
fprintf( fp, "WedTo %s~\n", ch->pcdata->wedto );
if( ch->wimpy )
fprintf( fp, "Wimpy %d\n", ch->wimpy );
if( ch->deaf )
fprintf( fp, "Deaf %d\n", ch->deaf );
if( ch->resistant )
fprintf( fp, "Resistant %d\n", ch->resistant );
if( ch->no_resistant )
fprintf( fp, "NoResistant %d\n", ch->no_resistant );
if( ch->immune )
fprintf( fp, "Immune %d\n", ch->immune );
if( ch->no_immune )
fprintf( fp, "NoImmune %d\n", ch->no_immune );
if( ch->susceptible )
fprintf( fp, "Susceptible %d\n", ch->susceptible );
if( ch->no_susceptible )
fprintf( fp, "NoSusceptible %d\n", ch->no_susceptible );
if( ch->pcdata && ch->pcdata->outcast_time )
fprintf( fp, "Outcast_time %ld\n", ch->pcdata->outcast_time );
if( ch->pcdata && ch->pcdata->nuisance )
fprintf( fp, "NuisanceNew %ld %ld %d %d\n", ch->pcdata->nuisance->time,
ch->pcdata->nuisance->max_time, ch->pcdata->nuisance->flags, ch->pcdata->nuisance->power );
if( ch->mental_state != -10 )
fprintf( fp, "Mentalstate %d\n", ch->mental_state );
fprintf( fp, "Password %s~\n", ch->pcdata->pwd );
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->extraname && ch->pcdata->extraname[0] != '\0' )
fprintf( fp, "Extraname %s~\n", ch->pcdata->extraname );
if( ch->pcdata->lastname && ch->pcdata->lastname[0] != '\0' )
fprintf( fp, "Lastname %s~\n", ch->pcdata->lastname );
if( ch->pcdata->homepage && ch->pcdata->homepage[0] != '\0' )
fprintf( fp, "Homepage %s~\n", ch->pcdata->homepage );
if( ch->pcdata->email && ch->pcdata->email[0] != '\0' )
fprintf( fp, "Email %s~\n", ch->pcdata->email );
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->fprompt && *ch->pcdata->fprompt )
fprintf( fp, "FPrompt %s~\n", ch->pcdata->fprompt );
if( ch->pcdata->pagerlen != 24 )
fprintf( fp, "Pagerlen %d\n", ch->pcdata->pagerlen );
/*
* Save note board status
*/
/*
* Save number of boards in case that number changes
*/
fprintf( fp, "Boards %d ", MAX_BOARD );
for( i = 0; i < MAX_BOARD; i++ )
fprintf( fp, "%s %ld ", boards[i].short_name, ch->pcdata->last_note[i] );
fprintf( fp, "\n" );
for( pos = 0; pos < MAX_ALIAS; pos++ ) /* alias - shogar */
{
if( !ch->pcdata->alias[pos] || !ch->pcdata->alias_sub[pos] )
break;
fprintf( fp, "Alias %s %s~\n", ch->pcdata->alias[pos], ch->pcdata->alias_sub[pos] );
}
/*
* If ch is ignoring players then store those players
*/
{
IGNORE_DATA *temp;
for( temp = ch->pcdata->first_ignored; temp; temp = temp->next )
{
fprintf( fp, "Ignored %s~\n", temp->name );
}
}
if( IS_IMMORTAL( ch ) )
{
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->trust )
fprintf( fp, "Trust %d\n", ch->trust );
if( ch->pcdata && ch->pcdata->restore_time )
fprintf( fp, "Restore_time %ld\n", ch->pcdata->restore_time );
fprintf( fp, "WizInvis %d\n", ch->pcdata->wizinvis );
fprintf( fp, "GhostLevel %d\n", ch->ghost_level );
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->council2 )
fprintf( fp, "Council2 %s~\n", ch->pcdata->council2_name );
if( ch->pcdata->deity_name && ch->pcdata->deity_name[0] != '\0' )
if( ch->pcdata->hometown && ( ch->pcdata->htown_vnum > -1 ) )
fprintf( fp, "Hometown %d\n", ch->pcdata->htown_vnum );
if( ch->pcdata->nation && ( ch->pcdata->nation_vnum > -1 ) )
fprintf( fp, "Nation %d\n", ch->pcdata->nation_vnum );
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 );
fprintf( fp, "Flags %d\n", ch->pcdata->flags );
if( ch->pcdata->release_date > current_time )
fprintf( fp, "Helled %d %s~\n", ( int )ch->pcdata->release_date, ch->pcdata->helled_by );
fprintf( fp, "PKills %d\n", ch->pcdata->pkills );
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 );
fprintf( fp, "ArenaWins %d\n", ch->pcdata->arena_wins );
fprintf( fp, "ArenaKills %d\n", ch->pcdata->arena_kills );
fprintf( fp, "ArenaDeaths %d\n", ch->pcdata->arena_deaths );
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 %d\n",
ch->pcdata->condition[0],
ch->pcdata->condition[1], ch->pcdata->condition[2], ch->pcdata->condition[3], ch->pcdata->condition[4] );
if( ch->desc && ch->desc->host )
fprintf( fp, "Site %s\n", ch->desc->host );
else
fprintf( fp, "Site (Link-Dead)\n" );
for( sn = 1; sn < top_sn; sn++ )
{
if( skill_table[sn]->name && ch->pcdata->learned[sn] > 0 )
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 %s\n",
skill->name, paf->duration, paf->modifier, paf->location, print_bitvector( &paf->bitvector ) );
else
fprintf( fp, "Affect %3d %3d %3d %3d %s\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 );
}
if( ch->pcdata->first_qbit )
{
BIT_DATA *bit;
for( bit = ch->pcdata->first_qbit; bit; bit = bit->next )
fprintf( fp, "Qbit %d %s~\n", bit->number, bit->desc );
}
if( ch->pcdata->chan_listen )
fprintf( fp, "Channels %s~\n", ch->pcdata->chan_listen );
#ifdef I3
i3save_char( ch, fp );
#endif
#ifdef IMC
imc_savechar( ch, fp );
#endif
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, short os_type )
{
EXTRA_DESCR_DATA *ed;
AFFECT_DATA *paf;
short wear, wear_loc, x;
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 ) )
{
if( os_type == OS_CARRY )
fwrite_obj( ch, obj->prev_content, fp, iNest, OS_CARRY );
else
fwrite_obj( ch, obj->prev_content, fp, iNest, OS_GROUND );
}
/*
* Castrate storage characters.
* Catch deleted objects -Thoric
* Do NOT save prototype items! -Thoric
*/
if( ( ch && ( get_trust( ch ) < obj->level ) && ( obj->level >= LEVEL_IMMORTAL ) )
|| ( obj->item_type == ITEM_KEY && !IS_OBJ_STAT( obj, ITEM_CLANOBJECT ) )
|| obj_extracted( obj ) || IS_OBJ_STAT( obj, ITEM_PROTOTYPE ) )
return;
/*
* Corpse saving. -- Altrag
*/
fprintf( fp, ( os_type == OS_CORPSE ? "#CORPSE\n" : "#OBJECT\n" ) );
if( iNest )
fprintf( fp, "Nest %d\n", iNest );
if( obj->count > 1 )
fprintf( fp, "Count %d\n", obj->count );
if( obj->name && obj->pIndexData->name && str_cmp( obj->name, obj->pIndexData->name ) )
fprintf( fp, "Name %s~\n", obj->name );
if( obj->short_descr && obj->pIndexData->short_descr && str_cmp( obj->short_descr, obj->pIndexData->short_descr ) )
fprintf( fp, "ShortDescr %s~\n", obj->short_descr );
if( obj->description && obj->pIndexData->description && str_cmp( obj->description, obj->pIndexData->description ) )
fprintf( fp, "Description %s~\n", obj->description );
if( obj->action_desc && obj->pIndexData->action_desc && str_cmp( obj->action_desc, obj->pIndexData->action_desc ) )
fprintf( fp, "ActionDesc %s~\n", obj->action_desc );
fprintf( fp, "Vnum %d\n", obj->pIndexData->vnum );
if( ( ( os_type == OS_GROUND ) || ( os_type == OS_CORPSE || os_type == OS_LOCKER ) ) && obj->in_room )
fprintf( fp, "Room %d\n", obj->in_room->vnum );
else if( IS_OBJ_STAT( obj, ITEM_ARTIFACT ) && !obj->in_room )
fprintf( fp, "Room %d\n", get_obj_room_vnum_recursive( obj ) );
if( !xSAME_BITS( obj->extra_flags, obj->pIndexData->extra_flags ) )
fprintf( fp, "ExtraFlags %s\n", print_bitvector( &obj->extra_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->gold_cost != obj->pIndexData->gold_cost )
fprintf( fp, "Gold_cost %d\n", obj->gold_cost );
if( obj->silver_cost != obj->pIndexData->silver_cost )
fprintf( fp, "Silver_cost %d\n", obj->silver_cost );
if( obj->copper_cost != obj->pIndexData->copper_cost )
fprintf( fp, "Copper_cost %d\n", obj->copper_cost );
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
|| paf->location == APPLY_RECURRINGSPELL )
&& 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
|| paf->location == APPLY_RECURRINGSPELL )
&& 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 )
fwrite_obj( ch, obj->last_content, fp, iNest + 1, OS_CARRY );
return;
}
void fwrite_alias( ALIAS_DATA * first_alias, FILE * fp )
{
ALIAS_DATA *alias;
for( alias = first_alias; alias; alias = alias->next )
{
fprintf( fp, "#ALIAS\n" );
fprintf( fp, "Name %s~\n", alias->name );
fprintf( fp, "Commands %s~\n", alias->alias );
fprintf( fp, "End\n\n" );
}
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;
FILE *fp;
bool found;
struct stat fst;
int i, x;
char buf[MAX_INPUT_LENGTH];
CREATE( ch, CHAR_DATA, 1 );
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->pcdata->filename = STRALLOC( name );
ch->name = NULL;
ch->act = multimeb( PLR_BLANK, PLR_COMBINE, PLR_PROMPT, -1 );
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->no_resistant = 0;
ch->no_susceptible = 0;
ch->no_immune = 0;
ch->was_in_room = NULL;
xCLEAR_BITS( ch->no_affected_by );
if( sysdata.neverempty ) /* Altrag */
{
ch->pcdata->condition[COND_THIRST] = 40;
ch->pcdata->condition[COND_FULL] = 40;
}
else
{
ch->pcdata->condition[COND_THIRST] = 48;
ch->pcdata->condition[COND_FULL] = 48;
}
ch->pcdata->condition[COND_BLOODTHIRST] = 10;
ch->pcdata->condition[COND_BLEEDING] = 0;
ch->pcdata->nuisance = NULL;
ch->pcdata->wizinvis = 0;
ch->pcdata->balance = 0;
ch->pcdata->gbalance = 0;
ch->pcdata->sbalance = 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->style = STYLE_FIGHTING;
ch->comments = NULL; /* comments */
ch->pcdata->pagerlen = 24;
ch->pcdata->first_ignored = NULL; /* Ignore list */
ch->pcdata->last_ignored = NULL;
ch->pcdata->tell_history = NULL; /* imm only lasttell cmnd */
ch->pcdata->lt_index = 0; /* last tell index */
ch->morph = NULL;
ch->pcdata->hometown = NULL;
ch->pcdata->nation = NULL;
ch->pcdata->htown_vnum = -1;
ch->pcdata->nation_vnum = -1;
ch->pcdata->smites = 0;
ch->pcdata->smited = 0;
ch->pcdata->wedto = NULL;
ch->pcdata->afkmsg = NULL;
ch->pcdata->arena = NULL;
#ifdef I3
i3init_char( ch );
#endif
#ifdef IMC
imc_initchar( ch );
#endif
for( i = 0; i < 10; i++ )
{
ch->pcdata->say_history[0] = NULL;
ch->pcdata->tell_histories[0] = NULL;
}
found = FALSE;
sprintf( strsave, "%s%c/%s", PLAYER_DIR, tolower( name[0] ), capitalize( name ) );
if( stat( strsave, &fst ) != -1 )
{
if( fst.st_size == 0 )
{
sprintf( strsave, "%s%c/%s", BACKUP_DIR, tolower( name[0] ), capitalize( name ) );
send_to_char( "Restoring your backup player file...", ch );
}
else
{
sprintf( buf, "%s player data for: %s (%dK)",
preload ? "Preloading" : "Loading", ch->pcdata->filename, ( int )fst.st_size / 1024 );
log_string_plus( buf, LOG_COMM, LEVEL_GREATER );
}
}
/*
* else no player file
*/
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;
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( !strcmp( word, "PLAYER" ) )
{
fread_char( ch, fp, preload );
if( preload )
break;
}
else if( !strcmp( word, "ALIAS" ) ) /* Aliases */
fread_alias( ch, fp );
else if( !strcmp( word, "OBJECT" ) ) /* Objects */
fread_obj( ch, fp, OS_CARRY );
else if( !strcmp( word, "MorphData" ) ) /* Morphs */
fread_morph_data( ch, fp );
else if( !strcmp( word, "COMMENT" ) )
fread_comment( ch, fp ); /* Comments */
else if( !strcmp( word, "MOBILE" ) )
{
CHAR_DATA *mob;
if( ( mob = fread_mobile( fp ) ) )
{
ch->pcdata->pet = mob;
mob->master = ch;
xSET_BIT( mob->affected_by, AFF_CHARM );
}
else
bug( "%s: Deleted mob saved on %s - skipping", __FUNCTION__, ch->name );
}
else if( !strcmp( word, "END" ) ) /* Done */
break;
else
{
bug( "Load_char_obj: bad section.", 0 );
bug( name, 0 );
break;
}
}
fclose( fp );
fpArea = NULL;
strcpy( strArea, "$" );
}
if( !found )
{
ch->name = STRALLOC( name );
ch->short_descr = STRALLOC( "" );
ch->long_descr = STRALLOC( "" );
ch->description = STRALLOC( "" );
ch->editor = NULL;
ch->pcdata->clan_name = STRALLOC( "" );
ch->pcdata->clan = NULL;
ch->pcdata->council_name = STRALLOC( "" );
ch->pcdata->council = NULL;
ch->pcdata->council2_name = STRALLOC( "" );
ch->pcdata->council2 = NULL;
ch->pcdata->deity_name = STRALLOC( "" );
ch->pcdata->deity = NULL;
ch->pcdata->pet = NULL;
ch->pcdata->pwd = str_dup( "" );
/*
* every characters starts at default board from login.. this board
* should be read_level == 0 !
*/
ch->pcdata->board = &boards[DEFAULT_BOARD];
ch->pcdata->bamfin = str_dup( "" );
ch->pcdata->bamfout = str_dup( "" );
ch->pcdata->rank = str_dup( "" );
ch->pcdata->bestowments = str_dup( "" );
ch->pcdata->title = STRALLOC( "" );
/*
* Set to NULL instead because they might be stralloc'd and then fread_string
* called upon them without checking. It's handled down in the end section
* of fread_char anyway.
* This is *NOT* handled in fread_char. This stuff is only done when there is no
* char to fread. -- Alty
*/
ch->pcdata->extraname = STRALLOC( "" );
ch->pcdata->lastname = STRALLOC( "" );
ch->pcdata->homepage = str_dup( "" );
ch->pcdata->email = str_dup( "" );
ch->pcdata->bio = STRALLOC( "" );
ch->pcdata->authed_by = STRALLOC( "" );
ch->pcdata->prompt = STRALLOC( "" );
ch->pcdata->fprompt = 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;
ch->pcdata->hometown = NULL;
ch->pcdata->nation = NULL;
ch->pcdata->nation_vnum = -1;
ch->pcdata->htown_vnum = -1;
ch->pcdata->hair_color = STRALLOC( "" );
ch->pcdata->eye_color = STRALLOC( "" );
ch->pcdata->skin_tone = STRALLOC( "" );
ch->pcdata->ch_build = STRALLOC( "" );
ch->pcdata->hair_length = STRALLOC( "" );
ch->pcdata->ch_height = STRALLOC( "" );
}
else
{
if( !ch->name )
ch->name = STRALLOC( name );
if( !ch->pcdata->clan_name )
{
ch->pcdata->clan_name = STRALLOC( "" );
ch->pcdata->clan = NULL;
}
if( !ch->pcdata->council_name )
{
ch->pcdata->council_name = STRALLOC( "" );
ch->pcdata->council = NULL;
}
if( !ch->pcdata->council2_name )
{
ch->pcdata->council2_name = STRALLOC( "" );
ch->pcdata->council2 = 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( xIS_SET( ch->act, PLR_FLEE ) )
xREMOVE_BIT( ch->act, PLR_FLEE );
if( IS_IMMORTAL( ch ) )
{
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);
* }
* }
*/
}
/*
* Rebuild affected_by and RIS to catch errors - FB
*/
update_aris( ch );
loading_char = NULL;
return found;
}
/*
* Read in a char.
*/
void fread_char( CHAR_DATA * ch, FILE * fp, bool preload )
{
char buf[MAX_STRING_LENGTH];
char *line;
char *word;
int x1, x2, x3, x4, x5, x6, x7;
short killcnt;
bool fMatch;
int count = 0;
file_ver = 0;
killcnt = 0;
ch->silver = 0;
ch->copper = 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':
KEY( "Act", ch->act, fread_bitvector( fp ) );
KEY( "AffectedBy", ch->affected_by, fread_bitvector( fp ) );
KEY( "Alignment", ch->alignment, fread_number( fp ) );
KEY( "Armor", ch->armor, fread_number( fp ) );
KEY( "ArenaWins", ch->pcdata->arena_wins, fread_number( fp ) );
KEY( "ArenaKills", ch->pcdata->arena_kills, fread_number( fp ) );
KEY( "ArenaDeaths", ch->pcdata->arena_deaths, fread_number( fp ) );
if( !strcmp( word, "Affect" ) || !strcmp( word, "AffectData" ) )
{
AFFECT_DATA *paf;
if( preload )
{
fMatch = TRUE;
fread_to_eol( fp );
break;
}
CREATE( paf, AFFECT_DATA, 1 );
if( !strcmp( 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 );
if( paf->location == APPLY_WEAPONSPELL
|| paf->location == APPLY_WEARSPELL
|| paf->location == APPLY_REMOVESPELL
|| paf->location == APPLY_STRIPSN || paf->location == APPLY_RECURRINGSPELL )
paf->modifier = slot_lookup( paf->modifier );
paf->bitvector = fread_bitvector( fp );
LINK( paf, ch->first_affect, ch->last_affect, next, prev );
fMatch = TRUE;
break;
}
if( !strcmp( 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, "Alias" ) )
{
if( count >= MAX_ALIAS )
{
fread_to_eol( fp );
fMatch = TRUE;
break;
}
ch->pcdata->alias[count] = str_dup( fread_word( fp ) );
ch->pcdata->alias_sub[count] = fread_string_nohash( fp );
count++;
fMatch = TRUE;
break;
}
if( !strcmp( 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 ) );
KEY( "Agemod", ch->age_bonus, fread_number( fp ) );
break;
case 'B':
if( file_ver < 4 )
{
KEY( "BL", ch->pcdata->ch_height, fread_string( fp ) );
KEY( "BU", ch->pcdata->ch_build, fread_string( fp ) );
}
KEY( "Balance", ch->pcdata->balance, fread_number( fp ) );
KEY( "Bday", ch->day, fread_number( fp ) );
KEY( "Bmonth", ch->month, fread_number( fp ) );
KEY( "Byear", ch->year, fread_number( fp ) );
KEY( "Bamfin", ch->pcdata->bamfin, fread_string_nohash( fp ) );
KEY( "Bamfout", ch->pcdata->bamfout, fread_string_nohash( fp ) );
KEY( "Belig", ch->belig, fread_number( fp ) );
KEY( "Bkills", ch->bkills, fread_number( fp ) );
KEY( "Bounty", ch->bounty, fread_number( fp ) );
KEY( "Bowed", ch->bowed, fread_number( fp ) );
/*
* Read in board status
*/
if( !str_cmp( word, "Boards" ) )
{
int i, num = fread_number( fp ); /* number of boards saved */
char *boardname;
for( ; num; num-- ) /* for each of the board saved */
{
boardname = fread_word( fp );
i = board_lookup( boardname ); /* find board number */
if( i == BOARD_NOTFOUND ) /* Does board still exist ? */
{
sprintf( buf, "fread_char: %s had unknown board name: %s. Skipped.", ch->name, boardname );
log_string( buf );
fread_number( fp ); /* read last_note and skip info */
}
else /* Save it */
ch->pcdata->last_note[i] = fread_number( fp );
} /* for */
fMatch = TRUE;
} /* Boards */
KEY( "Bestowments", ch->pcdata->bestowments, fread_string_nohash( fp ) );
KEY( "Bio", ch->pcdata->bio, fread_string( fp ) );
break;
case 'C':
KEY( "Channels", ch->pcdata->chan_listen, fread_string( fp ) );
if( file_ver > 3 )
{
KEY( "CHBuild", ch->pcdata->ch_build, fread_string( fp ) );
KEY( "CHHeight", ch->pcdata->ch_height, fread_string( fp ) );
}
if( !strcmp( 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\r\nbelong to that organization.\r\n",
ch->pcdata->clan_name );
send_to_char( buf, ch );
STRFREE( ch->pcdata->clan_name );
ch->pcdata->clan_name = STRALLOC( "" );
}
fMatch = TRUE;
break;
}
KEY( "Class", ch->class, fread_number( fp ) );
if( !str_cmp( word, "Class2" ) )
{
fMatch = TRUE;
ch->class2 = fread_number( fp );
if( ch->class2 < 0 )
ch->class2 = 0;
}
if( !str_cmp( word, "Class3" ) )
{
fMatch = TRUE;
ch->class3 = fread_number( fp );
if( ch->class3 < 0 )
ch->class3 = 0;
}
if( !str_cmp( word, "Condition" ) )
{
line = fread_line( fp );
sscanf( line, "%d %d %d %d %d", &x1, &x2, &x3, &x4, &x5 );
ch->pcdata->condition[0] = x1;
ch->pcdata->condition[1] = x2;
ch->pcdata->condition[2] = x3;
ch->pcdata->condition[3] = x4;
ch->pcdata->condition[4] = x5;
fMatch = TRUE;
}
KEY( "Copper", ch->copper, fread_number( fp ) );
if( !strcmp( 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\r\nbelong to a council.\r\n",
ch->pcdata->council_name );
send_to_char( buf, ch );
STRFREE( ch->pcdata->council_name );
ch->pcdata->council_name = STRALLOC( "" );
}
fMatch = TRUE;
break;
}
if( !strcmp( word, "Council2" ) )
{
ch->pcdata->council2_name = fread_string( fp );
if( !preload
&& ch->pcdata->council2_name[0] != '\0'
&& ( ch->pcdata->council2 = get_council( ch->pcdata->council2_name ) ) == NULL )
{
sprintf( buf,
"Warning: the council %s no longer exists, and herefore you no longer\r\nbelong to a council.\r\n",
ch->pcdata->council2_name );
send_to_char( buf, ch );
STRFREE( ch->pcdata->council2_name );
ch->pcdata->council2_name = STRALLOC( "" );
}
fMatch = TRUE;
break;
}
break;
case 'D':
KEY( "Damroll", ch->damroll, fread_number( fp ) );
KEY( "Deaf", ch->deaf, fread_number( fp ) );
if( !strcmp( 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.\r\n", 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 ) );
if( !strcmp( word, "Filename" ) )
{
/*
* File Name already set externally.
*/
fread_to_eol( fp );
fMatch = TRUE;
break;
}
KEY( "Flags", ch->pcdata->flags, fread_number( fp ) );
KEY( "FPrompt", ch->pcdata->fprompt, fread_string( fp ) );
break;
case 'G':
KEY( "GBalance", ch->pcdata->gbalance, fread_number( fp ) );
KEY( "GhostLevel", ch->ghost_level, fread_number( fp ) );
KEY( "Glory", ch->pcdata->quest_curr, fread_number( fp ) );
KEY( "Gold", ch->gold, fread_number( fp ) );
/*
* temporary measure
*/
if( !strcmp( word, "Guild" ) )
{
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\r\nbelong to that organization.\r\n",
ch->pcdata->clan_name );
send_to_char( buf, ch );
STRFREE( ch->pcdata->clan_name );
ch->pcdata->clan_name = STRALLOC( "" );
}
fMatch = TRUE;
break;
}
break;
case 'H':
KEY( "Height", ch->height, fread_number( fp ) );
if( file_ver > 3 )
{
KEY( "HairColor", ch->pcdata->hair_color, fread_string( fp ) );
KEY( "HairLength", ch->pcdata->hair_length, fread_string( fp ) );
}
else
{
KEY( "HC", ch->pcdata->hair_color, fread_string( fp ) );
KEY( "HL", ch->pcdata->hair_length, fread_string( fp ) );
}
if( !strcmp( 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( "Hometown", ch->pcdata->htown_vnum, fread_number( fp ) );
KEY( "Homepage", ch->pcdata->homepage, fread_string_nohash( fp ) );
if( !strcmp( 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':
if( !strcmp( word, "Ignored" ) )
{
char *temp;
char fname[1024];
struct stat fst;
int ign;
IGNORE_DATA *inode;
/*
* Get the name
*/
temp = fread_string( fp );
sprintf( fname, "%s%c/%s", PLAYER_DIR, tolower( temp[0] ), capitalize( temp ) );
/*
* If there isn't a pfile for the name
*/
/*
* then don't add it to the list
*/
if( stat( fname, &fst ) == -1 )
{
fMatch = TRUE;
break;
}
/*
* Count the number of names already ignored
*/
for( ign = 0, inode = ch->pcdata->first_ignored; inode; inode = inode->next )
{
ign++;
}
/*
* Add the name unless the limit has been reached
*/
if( ign >= MAX_IGN )
{
bug( "fread_char: too many ignored names" );
}
else
{
/*
* Add the name to the list
*/
CREATE( inode, IGNORE_DATA, 1 );
inode->name = STRALLOC( temp );
inode->next = NULL;
inode->prev = NULL;
LINK( inode, ch->pcdata->first_ignored, ch->pcdata->last_ignored, next, prev );
}
fMatch = TRUE;
break;
}
KEY( "IllegalPK", ch->pcdata->illegal_pk, fread_number( fp ) );
KEY( "Immune", ch->immune, fread_number( fp ) );
#ifdef IMC
if( ( fMatch = imc_loadchar( ch, fp, word ) ) )
break;
#endif
#ifdef I3
if( ( fMatch = i3load_char( ch, fp, word ) ) )
break;
#endif
break;
case 'K':
if( !strcmp( 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':
if( !strcmp( word, "Lastname" ) )
{
ch->pcdata->lastname = fread_string( fp );
if( isalpha( ch->pcdata->lastname[0] ) || isdigit( ch->pcdata->lastname[0] ) )
{
sprintf( buf, " %s", ch->pcdata->lastname );
if( ch->pcdata->lastname )
STRFREE( ch->pcdata->lastname );
ch->pcdata->lastname = STRALLOC( buf );
}
fMatch = TRUE;
break;
}
KEY( "Level", ch->level, fread_number( fp ) );
if( !str_cmp( word, "Level2" ) )
{
x1 = fread_number( fp );
if( file_ver < 5 )
ch->level2 = -1;
else
ch->level2 = x1;
fMatch = TRUE;
}
if( !str_cmp( word, "Level3" ) )
{
x1 = fread_number( fp );
if( file_ver < 5 )
ch->level3 = -1;
else
ch->level3 = x1;
fMatch = TRUE;
}
KEY( "LongDescr", ch->long_descr, fread_string( fp ) );
if( !strcmp( word, "Languages" ) )
{
ch->speaks = fread_number( fp );
ch->speaking = fread_number( fp );
fMatch = TRUE;
}
break;
case 'M':
KEY( "MDeaths", ch->pcdata->mdeaths, fread_number( fp ) );
if( !strcmp( word, "Memorized" ) )
{
ch->pcdata->memorize[0] = fread_number( fp );
ch->pcdata->memorize[1] = fread_number( fp );
ch->pcdata->memorize[2] = fread_number( fp );
ch->pcdata->memorize[3] = fread_number( fp );
ch->pcdata->memorize[4] = fread_number( fp );
ch->pcdata->memorize[5] = fread_number( fp );
ch->pcdata->memorize[6] = fread_number( fp );
ch->pcdata->memorize[7] = fread_number( fp );
fMatch = TRUE;
}
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 ) );
if( !strcmp( word, "MobRange" ) )
{
ch->pcdata->m_range_lo = fread_number( fp );
ch->pcdata->m_range_hi = fread_number( fp );
fMatch = TRUE;
}
break;
case 'N':
KEY( "Name", ch->name, fread_string( fp ) );
KEY( "Nation", ch->pcdata->nation_vnum, fread_number( fp ) );
KEY( "NoAffectedBy", ch->no_affected_by, fread_bitvector( fp ) );
KEY( "NoImmune", ch->no_immune, fread_number( fp ) );
KEY( "NoResistant", ch->no_resistant, fread_number( fp ) );
KEY( "NoSusceptible", ch->no_susceptible, fread_number( fp ) );
if( !strcmp( "Nuisance", word ) )
{
fMatch = TRUE;
CREATE( ch->pcdata->nuisance, NUISANCE_DATA, 1 );
ch->pcdata->nuisance->time = fread_number( fp );
ch->pcdata->nuisance->max_time = fread_number( fp );
ch->pcdata->nuisance->flags = fread_number( fp );
ch->pcdata->nuisance->power = 1;
}
if( !strcmp( "NuisanceNew", word ) )
{
fMatch = TRUE;
CREATE( ch->pcdata->nuisance, NUISANCE_DATA, 1 );
ch->pcdata->nuisance->time = fread_number( fp );
ch->pcdata->nuisance->max_time = fread_number( fp );
ch->pcdata->nuisance->flags = fread_number( fp );
ch->pcdata->nuisance->power = fread_number( fp );
}
break;
case 'O':
KEY( "Outcast_time", ch->pcdata->outcast_time, fread_number( fp ) );
if( !strcmp( word, "ObjRange" ) )
{
ch->pcdata->o_range_lo = fread_number( fp );
ch->pcdata->o_range_hi = fread_number( fp );
fMatch = TRUE;
}
break;
case 'P':
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->played, fread_number( fp ) );
/*
* KEY( "Position", ch->position, fread_number( fp ) );
*/
/*
* new positions are stored in the file from 100 up
* old positions are from 0 up
* if reading an old position, some translation is necessary
*/
if( !strcmp( word, "Position" ) )
{
ch->position = fread_number( fp );
if( ch->position < 100 )
{
switch ( ch->position )
{
default:;
case 0:;
case 1:;
case 2:;
case 3:;
case 4:
break;
case 5:
ch->position = 6;
break;
case 6:
ch->position = 8;
break;
case 7:
ch->position = 9;
break;
case 8:
ch->position = 12;
break;
case 9:
ch->position = 13;
break;
case 10:
ch->position = 14;
break;
case 11:
ch->position = 15;
break;
}
fMatch = TRUE;
}
else
{
ch->position -= 100;
fMatch = TRUE;
}
}
KEY( "Practice", ch->practice, fread_number( fp ) );
KEY( "Prompt", ch->pcdata->prompt, fread_string( fp ) );
if( !strcmp( word, "PTimer" ) )
{
add_timer( ch, TIMER_PKILLED, fread_number( fp ), NULL, 0 );
fMatch = TRUE;
break;
}
break;
case 'Q':
KEY( "QuestNext", ch->nextquest, fread_number( fp ) );
break;
if( !strcmp( word, "Qbit" ) )
{
BIT_DATA *bit;
BIT_DATA *desc;
CREATE( bit, BIT_DATA, 1 );
bit->number = fread_number( fp );
if( ( desc = find_qbit( bit->number ) ) == NULL )
strcpy( bit->desc, fread_string( fp ) );
else
{
strcpy( bit->desc, desc->desc );
fread_string( fp );
}
LINK( bit, ch->pcdata->first_qbit, ch->pcdata->last_qbit, next, prev );
fMatch = TRUE;
}
break;
case 'R':
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 ) );
if( !strcmp( word, "Room" ) )
{
ch->in_room = get_room_index( fread_number( fp ) );
if( !ch->in_room )
ch->in_room = get_room_index( ROOM_VNUM_LIMBO );
fMatch = TRUE;
break;
}
if( !strcmp( word, "RoomRange" ) )
{
ch->pcdata->r_range_lo = fread_number( fp );
ch->pcdata->r_range_hi = fread_number( fp );
fMatch = TRUE;
}
break;
case 'S':
KEY( "SBalance", ch->pcdata->sbalance, fread_number( fp ) );
if( file_ver > 3 )
{
KEY( "SkinTone", ch->pcdata->skin_tone, fread_string( fp ) );
}
else
{
KEY( "ST", ch->pcdata->skin_tone, fread_string( fp ) );
}
KEY( "Sex", ch->sex, fread_number( fp ) );
KEY( "ShortDescr", ch->short_descr, fread_string( fp ) );
KEY( "Silver", ch->silver, fread_number( fp ) );
KEY( "Smites", ch->pcdata->smites, fread_number( fp ) );
KEY( "Smited", ch->pcdata->smited, fread_number( fp ) );
KEY( "Style", ch->style, fread_number( fp ) );
KEY( "Susceptible", ch->susceptible, fread_number( fp ) );
if( !strcmp( 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( !strcmp( 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( !strcmp( word, "Site" ) )
{
if( !preload )
{
sprintf( buf, "Last connected from: %s\r\n", fread_word( fp ) );
send_to_char( buf, ch );
}
else
fread_to_eol( fp );
fMatch = TRUE;
if( preload )
word = "End";
else
break;
}
if( !strcmp( word, "Skill" ) )
{
int sn;
int value;
if( preload )
word = "End";
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 );
else
{
ch->pcdata->learned[sn] = value;
/*
* Take care of people who have stuff they shouldn't *
* * Assumes class and level were loaded before. -- Altrag *
* * Assumes practices are loaded first too now. -- Altrag
*/
if( ch->level < LEVEL_IMMORTAL )
{
if( ch->level3 != -1 )
{
if( ( skill_table[sn]->skill_level[ch->class]
&& skill_table[sn]->skill_level[ch->class2]
&& skill_table[sn]->skill_level[ch->class3] ) >= LEVEL_IMMORTAL )
{
ch->pcdata->learned[sn] = 0;
ch->practice++;
}
}
else if( ch->level2 != -1 )
{
if( ( skill_table[sn]->skill_level[ch->class]
&& skill_table[sn]->skill_level[ch->class2] ) >= LEVEL_IMMORTAL )
{
ch->pcdata->learned[sn] = 0;
ch->practice++;
}
}
else if( skill_table[sn]->skill_level[ch->class] >= LEVEL_IMMORTAL )
{
ch->pcdata->learned[sn] = 0;
ch->practice++;
}
}
}
fMatch = TRUE;
break;
}
}
if( !strcmp( word, "Spell" ) )
{
int sn;
int value;
if( preload )
word = "End";
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 );
else
{
ch->pcdata->learned[sn] = value;
if( ch->level < LEVEL_IMMORTAL )
{
if( ch->level3 != -1 )
{
if( ( skill_table[sn]->skill_level[ch->class]
&& skill_table[sn]->skill_level[ch->class2]
&& skill_table[sn]->skill_level[ch->class3] ) >= LEVEL_IMMORTAL )
{
ch->pcdata->learned[sn] = 0;
ch->practice++;
}
}
else if( ch->level2 != -1 )
{
if( ( skill_table[sn]->skill_level[ch->class]
&& skill_table[sn]->skill_level[ch->class2] ) >= LEVEL_IMMORTAL )
{
ch->pcdata->learned[sn] = 0;
ch->practice++;
}
}
else if( skill_table[sn]->skill_level[ch->class] >= LEVEL_IMMORTAL )
{
ch->pcdata->learned[sn] = 0;
ch->practice++;
}
}
}
fMatch = TRUE;
break;
}
}
if( strcmp( word, "End" ) )
break;
case 'E':
if( file_ver > 3 )
{
KEY( "Email", ch->pcdata->email, fread_string_nohash( fp ) );
KEY( "EyeColor", ch->pcdata->eye_color, fread_string( fp ) );
}
else
{
KEY( "EC", ch->pcdata->eye_color, fread_string( fp ) );
}
if( !strcmp( word, "Extraname" ) )
{
ch->pcdata->extraname = fread_string( fp );
if( isalpha( ch->pcdata->extraname[0] ) || isdigit( ch->pcdata->extraname[0] ) )
{
sprintf( buf, " %s", ch->pcdata->extraname );
if( ch->pcdata->extraname )
STRFREE( ch->pcdata->extraname );
ch->pcdata->extraname = STRALLOC( buf );
}
fMatch = TRUE;
break;
}
if( !strcmp( 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->extraname )
ch->pcdata->extraname = STRALLOC( "" );
if( !ch->pcdata->lastname )
ch->pcdata->lastname = STRALLOC( "" );
if( !ch->pcdata->homepage )
ch->pcdata->homepage = str_dup( "" );
if( !ch->pcdata->email )
ch->pcdata->email = str_dup( "" );
if( !ch->pcdata->authed_by )
ch->pcdata->authed_by = STRALLOC( "" );
if( !ch->pcdata->prompt )
ch->pcdata->prompt = STRALLOC( "" );
if( !ch->pcdata->fprompt )
ch->pcdata->fprompt = STRALLOC( "" );
if( !ch->pcdata->hair_color )
ch->pcdata->hair_color = STRALLOC( "" );
if( !ch->pcdata->eye_color )
ch->pcdata->eye_color = STRALLOC( "" );
if( !ch->pcdata->skin_tone )
ch->pcdata->skin_tone = STRALLOC( "" );
if( !ch->pcdata->ch_build )
ch->pcdata->ch_build = STRALLOC( "" );
if( !ch->pcdata->hair_length )
ch->pcdata->hair_length = STRALLOC( "" );
if( !ch->pcdata->ch_height )
ch->pcdata->ch_height = STRALLOC( "" );
ch->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 ) )
{
int i;
ch->speaks = ~0;
if( ch->speaking == 0 )
ch->speaking = ~0;
CREATE( ch->pcdata->tell_history, char *, 26 );
for( i = 0; i < 26; i++ )
ch->pcdata->tell_history[i] = NULL;
}
if( ch->pcdata->chan_listen != NULL )
{
MUD_CHANNEL *channel = NULL;
char *channels = ch->pcdata->chan_listen;
char arg[MAX_INPUT_LENGTH];
while( channels[0] != '\0' )
{
channels = one_argument( channels, arg );
if( !( channel = find_channel( arg ) ) )
removename( &ch->pcdata->chan_listen, arg );
}
}
/*
* Provide at least the one channel
*/
else
ch->pcdata->chan_listen =
STRALLOC( "chat auction quest music newbiechat guildtalk clantalk ordertalk ooc icc" );
if( !ch->pcdata->prompt )
ch->pcdata->prompt = STRALLOC( "" );
/*
* this disallows chars from being 6', 180lbs, but easier than a flag
*/
if( ch->height == 72 )
ch->height = number_range( race_table[ch->race]->height * .9, race_table[ch->race]->height * 1.1 );
if( ch->weight == 180 )
ch->weight = number_range( race_table[ch->race]->weight * .9, race_table[ch->race]->weight * 1.1 );
if( ch->year == 0 )
ch->age = find_old_age( ch );
else
ch->age = calculate_age( ch );
if( ch->month > 11 )
ch->month = 11; /* Catches the bad month values */
if( ch->day > 25 )
ch->day = 25; /* Cathes the bad day values */
return;
}
KEY( "Exp", ch->exp, fread_number( fp ) );
KEY( "Exp2", ch->exp2, fread_number( fp ) );
break;
case 'T':
if( !strcmp( word, "Tongue" ) )
{
int sn;
int value;
if( preload )
word = "End";
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 );
else
{
ch->pcdata->learned[sn] = value;
if( ch->level < LEVEL_IMMORTAL )
{
if( ch->level3 != -1 )
{
if( ( skill_table[sn]->skill_level[ch->class]
&& skill_table[sn]->skill_level[ch->class2]
&& skill_table[sn]->skill_level[ch->class3] ) >= LEVEL_IMMORTAL )
{
ch->pcdata->learned[sn] = 0;
ch->practice++;
}
}
else if( ch->level2 != -1 )
{
if( ( skill_table[sn]->skill_level[ch->class]
&& skill_table[sn]->skill_level[ch->class2] ) >= LEVEL_IMMORTAL )
{
ch->pcdata->learned[sn] = 0;
ch->practice++;
}
}
else if( skill_table[sn]->skill_level[ch->class] >= LEVEL_IMMORTAL )
{
ch->pcdata->learned[sn] = 0;
ch->practice++;
}
}
}
fMatch = TRUE;
}
break;
}
KEY( "Trust", ch->trust, fread_number( fp ) );
/*
* Let no character be trusted higher than one below maxlevel -- Narn
*/
ch->trust = UMIN( ch->trust, MAX_LEVEL - 1 );
if( !strcmp( 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':
KEY( "Version", file_ver, fread_number( fp ) );
break;
case 'W':
KEY( "WedTo", ch->pcdata->wedto, fread_string( fp ) );
KEY( "Weight", ch->weight, fread_number( fp ) );
if( !strcmp( word, "Weapon" ) )
{
int sn;
int value;
if( preload )
word = "End";
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 );
else
{
ch->pcdata->learned[sn] = value;
if( ch->level < LEVEL_IMMORTAL )
{
if( ch->level3 != -1 )
{
if( ( skill_table[sn]->skill_level[ch->class]
&& skill_table[sn]->skill_level[ch->class2]
&& skill_table[sn]->skill_level[ch->class3] ) >= LEVEL_IMMORTAL )
{
ch->pcdata->learned[sn] = 0;
ch->practice++;
}
}
else if( ch->level2 != -1 )
{
if( ( skill_table[sn]->skill_level[ch->class]
&& skill_table[sn]->skill_level[ch->class2] ) >= LEVEL_IMMORTAL )
{
ch->pcdata->learned[sn] = 0;
ch->practice++;
}
}
else if( skill_table[sn]->skill_level[ch->class] >= LEVEL_IMMORTAL )
{
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, short os_type )
{
OBJ_DATA *obj;
char *word;
char buf[MAX_STRING_LENGTH];
int iNest;
bool fMatch;
bool fNest;
bool fVnum;
ROOM_INDEX_DATA *room = NULL;
if( ch )
room = ch->in_room;
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':
KEY( "ActionDesc", obj->action_desc, fread_string( fp ) );
if( !strcmp( word, "Affect" ) || !strcmp( word, "AffectData" ) )
{
AFFECT_DATA *paf;
int pafmod;
CREATE( paf, AFFECT_DATA, 1 );
if( !strcmp( 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_STRIPSN
|| paf->location == APPLY_REMOVESPELL || paf->location == APPLY_RECURRINGSPELL )
paf->modifier = slot_lookup( pafmod );
else
paf->modifier = pafmod;
LINK( paf, obj->first_affect, obj->last_affect, next, prev );
fMatch = TRUE;
break;
}
break;
case 'C':
if( ( !strcmp( word, "Copper_cost" ) ) || ( !strcmp( word, "Copper_Cost" ) ) )
{
obj->copper_cost = fread_number( fp );
fMatch = TRUE;
}
KEY( "Cost", obj->gold_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_bitvector( fp ) );
if( !strcmp( word, "ExtraDescr" ) )
{
EXTRA_DESCR_DATA *ed;
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( !strcmp( word, "End" ) )
{
if( !fNest || !fVnum || !obj->pIndexData )
{
if( obj->name )
sprintf( buf, "Fread_obj: %s incomplete object.", obj->name );
else
sprintf( buf, "Fread_obj: incomplete object." );
bug( buf, 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
{
short 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 );
LINK( obj, first_object, last_object, 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
*/
if( os_type == OS_CORPSE )
{
if( !room )
{
bug( "Fread_obj: Corpse without room", 0 );
room = get_room_index( ROOM_VNUM_LIMBO );
}
/*
* Give the corpse a timer if there isn't one
*/
if( obj->timer < 1 )
obj->timer = 40;
if( room->vnum == ROOM_VNUM_HALLOFFALLEN && obj->first_content )
obj->timer = -1;
obj = obj_to_room( obj, room );
}
else if( os_type == OS_LOCKER )
{
obj = obj_to_room( obj, ch->pcdata->locker_room );
}
else if( os_type == OS_GROUND )
{
if( !room )
{
bug( "Fread_obj: OS_GROUND vnum %d without room, skipped!", obj->pIndexData->vnum );
}
else
obj_to_room( obj, room );
}
else if( iNest == 0 || rgObjNest[iNest] == NULL )
{
int slot = -1;
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 );
}
obj = obj_to_char( obj, ch );
if( reslot && slot != -1 )
save_equipment[wear_loc][slot] = obj;
}
else
{
if( rgObjNest[iNest - 1] )
{
separate_obj( rgObjNest[iNest - 1] );
obj = obj_to_obj( obj, rgObjNest[iNest - 1] );
}
else
bug( "Fread_obj: nest layer missing %d", iNest - 1 );
}
if( fNest )
rgObjNest[iNest] = obj;
return;
}
}
break;
case 'G':
if( ( !strcmp( word, "Gold_cost" ) ) || ( !strcmp( word, "Gold_Cost" ) ) )
{
obj->gold_cost = fread_number( fp );
fMatch = TRUE;
}
break;
case 'I':
KEY( "ItemType", obj->item_type, fread_number( fp ) );
break;
case 'L':
KEY( "Level", obj->level, fread_number( fp ) );
break;
case 'N':
KEY( "Name", obj->name, fread_string( fp ) );
if( !strcmp( 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 ) ) );
case 'S':
KEY( "ShortDescr", obj->short_descr, fread_string( fp ) );
if( ( !strcmp( word, "Silver_cost" ) ) || ( !strcmp( word, "Silver_Cost" ) ) )
{
obj->silver_cost = fread_number( fp );
fMatch = TRUE;
}
if( !strcmp( 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( !strcmp( 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 );
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( !strcmp( word, "Vnum" ) )
{
int vnum;
vnum = fread_number( fp );
/*
* bug( "Fread_obj: bad vnum %d.", vnum );
*/
if( ( obj->pIndexData = get_obj_index( vnum ) ) == NULL )
fVnum = FALSE;
else
{
fVnum = TRUE;
obj->gold_cost = obj->pIndexData->gold_cost;
obj->silver_cost = obj->pIndexData->silver_cost;
obj->copper_cost = obj->pIndexData->copper_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;
}
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;
}
}
}
void fread_alias( CHAR_DATA * ch, FILE * fp )
{
ALIAS_DATA *alias;
char *word;
bool fMatch;
CREATE( alias, ALIAS_DATA, 1 );
for( ;; )
{
word = feof( fp ) ? "End" : fread_word( fp );
fMatch = FALSE;
switch ( UPPER( word[0] ) )
{
case '*':
fMatch = TRUE;
fread_to_eol( fp );
break;
case 'C':
KEY( "Commands", alias->alias, fread_string( fp ) );
break;
case 'E':
if( !strcmp( word, "End" ) )
{
if( !alias->name || !alias->alias )
{
bug( "fread_alias: %s%s%s", alias->name ? "" : "NULL alias->name",
( !alias->name && !alias->alias ) ? " and " : "NULL alias->alias" );
DISPOSE( alias );
return;
}
else
{
/*
* bug( "Debug: fread_alias: %s %s", alias->name, alias->alias );
*/
LINK( alias, ch->pcdata->first_alias, ch->pcdata->last_alias, next, prev );
return;
}
}
break;
case 'N':
KEY( "Name", alias->name, fread_string( fp ) );
break;
}
if( !fMatch )
{
bug( "Fread_obj: no match." );
bug( word );
fread_to_eol( fp );
DISPOSE( alias );
return;
}
}
}
void set_alarm( long seconds )
{
#ifdef WIN32
kill_timer( ); /* kill old timer */
timer_code = timeSetEvent( seconds * 1000L, 1000, alarm_handler, 0, TIME_PERIODIC );
#else
alarm( seconds );
#endif
}
/*
* 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;
argument = one_argument( argument, arg );
if( arg[0] == '\0' )
{
send_to_char( "Usage: last <playername>\r\n", ch );
send_to_char( "Usage: last <# of entries OR \'-1\' for all entries OR \'today\' for all of today's entries>\r\n", ch );
send_to_char( "Usage: last <playername> <count>\r\n", ch );
return;
}
if( get_trust( ch ) < LEVEL_ASCENDANT )
{
set_char_color( AT_IMMORT, ch );
send_to_char( "Their godly glow prevents you from getting a good look.\r\n", ch );
return;
}
if( isdigit( arg[0] ) || atoi( arg ) == -1 || !str_cmp( arg, "today" ) ) //View list instead of players
{
send_to_char
( "&w&RName Time Host/Ip\r\n&c&w---------------------------------------------------------------------------\r\n",
ch );
if( !str_cmp( arg, "today" ) )
read_last_file( ch, -2, NULL );
else
read_last_file( ch, atoi( arg ), NULL );
return;
}
strcpy( name, capitalize( arg ) );
if( argument[0] != '\0' )
{
send_to_char
( "&w&RName Time Host/Ip\r\n&c&w---------------------------------------------------------------------------\r\n",
ch );
read_last_file( ch, atoi( argument ), name );
return;
}
sprintf( buf, "%s%c/%s", 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.\r\n", name );
send_to_char( buf, ch );
}
/*
* Added support for removeing so we could take out the write_corpses
* so we could take it out of the save_char_obj function. --Shaddai
*/
void write_corpses( CHAR_DATA * ch, char *name, OBJ_DATA * objrem )
{
OBJ_DATA *corpse;
FILE *fp = NULL;
/*
* 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( corpse = first_object; corpse; corpse = corpse->next )
if( corpse->pIndexData->vnum == OBJ_VNUM_CORPSE_PC &&
corpse->in_room != NULL && !str_cmp( corpse->short_descr + 14, name ) && objrem != corpse )
{
if( !fp )
{
char buf[127];
sprintf( buf, "%s%s", CORPSE_DIR, capitalize( name ) );
if( !( fp = fopen( buf, "w" ) ) )
{
bug( "Write_corpses: Cannot open file.", 0 );
perror( buf );
return;
}
}
fwrite_obj( ch, corpse, fp, 0, OS_CORPSE );
}
if( fp )
{
fprintf( fp, "#END\n\n" );
fclose( fp );
}
else
{
char buf[127];
sprintf( buf, "%s%s", CORPSE_DIR, capitalize( name ) );
remove( buf );
}
return;
}
void load_corpses( void )
{
DIR *dp;
struct dirent *de;
if( !( dp = opendir( CORPSE_DIR ) ) )
{
bug( "Load_corpses: can't open CORPSE_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", CORPSE_DIR, de->d_name );
fprintf( stderr, "Corpse -> %s\n", strArea );
if( !( fpArea = fopen( strArea, "r" ) ) )
{
perror( strArea );
continue;
}
for( ;; )
{
char letter;
char *word;
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( !strcmp( word, "CORPSE" ) )
fread_obj( NULL, fpArea, OS_CORPSE );
else if( !strcmp( word, "OBJECT" ) )
fread_obj( NULL, fpArea, OS_CARRY );
else if( !strcmp( word, "END" ) )
break;
else
{
bug( "Load_corpses: bad section.", 0 );
break;
}
}
fclose( fpArea );
}
}
fpArea = NULL;
strcpy( strArea, "$" );
closedir( dp );
falling = 0;
return;
}
/*
* This will write one mobile structure pointed to be fp --Shaddai
*/
void fwrite_mobile( FILE * fp, CHAR_DATA * mob )
{
if( !IS_NPC( mob ) || !fp )
return;
fprintf( fp, "#MOBILE\n" );
fprintf( fp, "Vnum %d\n", mob->pIndexData->vnum );
if( mob->in_room )
fprintf( fp, "Room %d\n",
( mob->in_room == get_room_index( ROOM_VNUM_LIMBO )
&& mob->was_in_room ) ? mob->was_in_room->vnum : mob->in_room->vnum );
if( mob->name && mob->pIndexData->player_name && str_cmp( mob->name, mob->pIndexData->player_name ) )
fprintf( fp, "Name %s~\n", mob->name );
if( mob->short_descr && mob->pIndexData->short_descr && str_cmp( mob->short_descr, mob->pIndexData->short_descr ) )
fprintf( fp, "Short %s~\n", mob->short_descr );
if( mob->long_descr && mob->pIndexData->long_descr && str_cmp( mob->long_descr, mob->pIndexData->long_descr ) )
fprintf( fp, "Long %s~\n", mob->long_descr );
if( mob->description && mob->pIndexData->description && str_cmp( mob->description, mob->pIndexData->description ) )
fprintf( fp, "Description %s~\n", mob->description );
fprintf( fp, "Position %d\n", mob->position );
fprintf( fp, "Flags %s\n", print_bitvector( &mob->act ) );
/* Might need these later --Shaddai
de_equip_char( mob );
re_equip_char( mob );
*/
if( mob->first_carrying )
fwrite_obj( mob, mob->last_carrying, fp, 0, OS_CARRY );
fprintf( fp, "EndMobile\n\n" );
return;
}
/*
* This will read one mobile structure pointer to by fp --Shaddai
*/
CHAR_DATA *fread_mobile( FILE * fp )
{
CHAR_DATA *mob = NULL;
char *word;
bool fMatch;
int inroom = 0;
ROOM_INDEX_DATA *pRoomIndex = NULL;
word = feof( fp ) ? "EndMobile" : fread_word( fp );
if( !strcmp( word, "Vnum" ) )
{
int vnum;
vnum = fread_number( fp );
mob = create_mobile( get_mob_index( vnum ) );
if( !mob )
{
for( ;; )
{
word = feof( fp ) ? "EndMobile" : fread_word( fp );
/*
* So we don't get so many bug messages when something messes up
* * --Shaddai
*/
if( !strcmp( word, "EndMobile" ) )
break;
}
bug( "Fread_mobile: No index data for vnum %d", vnum );
return NULL;
}
}
else
{
for( ;; )
{
word = feof( fp ) ? "EndMobile" : fread_word( fp );
/*
* So we don't get so many bug messages when something messes up
* * --Shaddai
*/
if( !strcmp( word, "EndMobile" ) )
break;
}
extract_char( mob, TRUE );
bug( "Fread_mobile: Vnum not found", 0 );
return NULL;
}
for( ;; )
{
word = feof( fp ) ? "EndMobile" : fread_word( fp );
fMatch = FALSE;
switch ( UPPER( word[0] ) )
{
case '*':
fMatch = TRUE;
fread_to_eol( fp );
break;
case '#':
if( !strcmp( word, "#OBJECT" ) )
fread_obj( mob, fp, OS_CARRY );
case 'D':
KEY( "Description", mob->description, fread_string( fp ) );
break;
case 'E':
if( !strcmp( word, "EndMobile" ) )
{
if( inroom == 0 )
inroom = ROOM_VNUM_TEMPLE;
pRoomIndex = get_room_index( inroom );
if( !pRoomIndex )
pRoomIndex = get_room_index( ROOM_VNUM_TEMPLE );
char_to_room( mob, pRoomIndex );
return mob;
}
if( !strcmp( word, "End" ) ) /* End of object, need to ignore this.
* sometimes they creep in there somehow -- Scion */
fMatch = TRUE; /* Trick the system into thinking it matched something */
break;
case 'F':
KEY( "Flags", mob->act, fread_bitvector( fp ) );
case 'L':
KEY( "Long", mob->long_descr, fread_string( fp ) );
break;
case 'N':
KEY( "Name", mob->name, fread_string( fp ) );
break;
case 'P':
KEY( "Position", mob->position, fread_number( fp ) );
break;
case 'R':
KEY( "Room", inroom, fread_number( fp ) );
break;
case 'S':
KEY( "Short", mob->short_descr, fread_string( fp ) );
break;
}
if( !fMatch && strcmp( word, "End" ) )
{
bug( "Fread_mobile: no match.", 0 );
bug( word, 0 );
}
}
return NULL;
}
/*
* This will write in the saved mobile for a char --Shaddai
*/
void write_char_mobile( CHAR_DATA * ch, char *argument )
{
FILE *fp;
CHAR_DATA *mob;
if( IS_NPC( ch ) || !ch->pcdata->pet )
return;
if( ( fp = fopen( argument, "w" ) ) == NULL )
{
bug( "Write_char_mobile: couldn't open %s for writing!\r\n", argument );
return;
}
mob = ch->pcdata->pet;
xSET_BIT( mob->affected_by, AFF_CHARM );
fwrite_mobile( fp, mob );
fclose( fp );
fp = NULL;
return;
}
/*
* This will read in the saved mobile for a char --Shaddai
*/
void read_char_mobile( char *argument )
{
FILE *fp;
CHAR_DATA *mob;
if( ( fp = fopen( argument, "r" ) ) == NULL )
{
bug( "Read_char_mobile: couldn't open %s for reading!\r\n", argument );
return;
}
mob = fread_mobile( fp );
fclose( fp );
fp = NULL;
return;
}
/* Return the vnum the obj is in, regardless of being carried or inside containers. -- Scion */
int get_obj_room_vnum_recursive( OBJ_DATA * obj )
{
if( !obj )
return ROOM_VNUM_LIMBO;
if( obj->in_obj )
{
// bug("Debug 0",0);
return get_obj_room_vnum_recursive( obj->in_obj );
}
else if( obj->carried_by )
{
CHAR_DATA *ch = obj->carried_by;
if( ch->in_room )
{
// bug("Debug 1",0);
return ch->in_room->vnum;
}
else
{
bug( "get_obj_room_vnum_recursive: Char \"%s\" not in room?!", ch->name );
return ROOM_VNUM_LIMBO;
}
}
else if( obj->in_room )
{
// bug("Debug 2",0);
return obj->in_room->vnum;
}
else
{
bug( "get_obj_room_vnum_recursive: obj isn't carried, inside containers, or inside a room!", 0 );
return ROOM_VNUM_LIMBO;
}
}
/*
* Save the world's objects and mobs in their current positions -- Scion
*/
void save_world( void )
{
FILE *mobfp;
FILE *objfp;
int mobfile = 0;
int objfile = 0;
char filename[256];
CHAR_DATA *rch;
OBJ_DATA *obj;
sprintf( filename, "%s%s", SYSTEM_DIR, MOB_FILE );
if( ( mobfp = fopen( filename, "w" ) ) == NULL )
{
bug( "save_world: fopen mob file", 0 );
perror( filename );
}
else
mobfile++;
sprintf( filename, "%s%s", SYSTEM_DIR, OBJ_FILE );
if( ( objfp = fopen( filename, "w" ) ) == NULL )
{
bug( "save_world: fopen obj file", 0 );
perror( filename );
}
else
objfile++;
if( objfile )
{
for( obj = first_object; obj; obj = obj->next )
{
/*
* Objects that are in inventories get written in fwrite_mob, or to a player's pfile
*/
if( IS_OBJ_STAT( obj, ITEM_PROTOTYPE )
|| ( !IS_OBJ_STAT( obj, ITEM_PLRBLD ) && !IS_OBJ_STAT( obj, ITEM_ARTIFACT ) )
|| ( obj->in_room &&
( IS_SET( obj->in_room->room_flags, ROOM_DONATION )
|| IS_SET( obj->in_room->room_flags, ROOM_CLANSTOREROOM ) ) ) )
continue;
else
{
if( IS_OBJ_STAT( obj, ITEM_ARTIFACT ) )
obj->count = 1;
fwrite_obj( NULL, obj, objfp, 0, OS_GROUND );
}
}
fprintf( objfp, "#END" );
fclose( objfp );
}
if( mobfile )
{
for( rch = first_char; rch; rch = rch->next )
{
if( !IS_NPC( rch ) || rch == supermob || xIS_SET( rch->act, ACT_PROTOTYPE ) || xIS_SET( rch->act, ACT_PET ) )
continue;
else
fwrite_mobile( mobfp, rch );
}
fprintf( mobfp, "#END" );
fclose( mobfp );
}
}
void load_world( void )
{
FILE *mobfp;
FILE *objfp;
char filename[256];
char *word;
int done = 0;
int mobfile = 0;
int objfile = 0;
sprintf( filename, "%s%s", SYSTEM_DIR, MOB_FILE );
if( ( mobfp = fopen( filename, "r" ) ) == NULL )
{
bug( "load_world: fopen mob file", 0 );
perror( filename );
return;
}
else
mobfile++;
sprintf( filename, "%s%s", SYSTEM_DIR, OBJ_FILE );
if( ( objfp = fopen( filename, "r" ) ) == NULL )
{
bug( "load_world: fopen obj file", 0 );
perror( filename );
return;
}
else
objfile++;
if( mobfile )
{
while( done == 0 )
{
if( feof( mobfp ) )
done++;
else
{
word = fread_word( mobfp );
if( str_cmp( word, "#END" ) )
fread_mobile( mobfp );
else
done++;
}
}
fclose( mobfp );
}
done = 0;
if( objfile )
{
while( done == 0 )
{
if( feof( objfp ) )
done++;
else
{
word = fread_word( objfp );
if( str_cmp( word, "#END" ) )
fread_obj( NULL, objfp, OS_GROUND );
else
done++;
}
}
fclose( objfp );
}
}