/****************************************************************************
* [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, Fireblade, Edmond, Conran | *
* ------------------------------------------------------------------------ *
* 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 <sys/stat.h>
#ifndef WIN32
#include <dirent.h>
#endif
#include "mud.h"
/*
* Increment with every major format change.
*/
#define SAVEVERSION 3
/*
* 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;
/*
* Externals
*/
void fwrite_comments( CHAR_DATA *ch, FILE *fp );
void fread_comment( CHAR_DATA *ch, FILE *fp );
void fwrite_variables( CHAR_DATA *ch, FILE *fp );
void fread_variable( 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 ) );
int fread_char args( ( CHAR_DATA *ch, FILE *fp, bool preload) );
void write_corpses args( ( CHAR_DATA *ch, char *name, OBJ_DATA *objrem ) );
#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
#ifdef CORRUPT
#undef CORRUPT
#endif
#define CORRUPT do \
{ \
found = FALSE; \
d->character = NULL; \
bug("Load_char_obj: %s is corrupted!", strsave); \
} while(0)
/*
* 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 )
{
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 );
}
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 )
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||IS_SET(ch->pcdata->flags, PCFLAG_RETIRED))
{
sprintf( strback, "%s%s", GOD_DIR, capitalize( ch->pcdata->filename ) );
if ( ( fp = fopen( strback, "w" ) ) == NULL )
{
perror( strsave );
bug( "Save_god_level: fopen", 0 );
}
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 ( IS_SET( sysdata.save_flags, SV_TMPSAVE ))
fp = fopen( TEMP_FILE, "w");
else
fp = fopen( strsave, "w");
if ( fp == NULL )
{
if ( IS_SET( sysdata.save_flags, SV_TMPSAVE ) )
perror( TEMP_FILE );
else
perror( strsave );
bug( "Save_char_obj: fopen", 0 );
}
else
{
bool ferr;
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 ( sysdata.save_pets && ch->pcdata->pet )
fwrite_mobile( fp, ch->pcdata->pet );
if ( ch->variables )
fwrite_variables( ch, fp );
if ( ch->comments ) /* comments */
fwrite_comments( ch, fp ); /* comments */
fprintf( fp, "#END\n" );
ferr = ferror(fp);
fclose( fp );
if ( IS_SET( sysdata.save_flags, SV_TMPSAVE ) ) {
if (ferr)
{
perror(strsave);
bug("Error writing temp file for %s -- not copying", strsave);
}
else
rename(TEMP_FILE, strsave);
}
}
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;
sh_int pos;
SKILLTYPE *skill = NULL;
HOME_DATA *tmphome;
fprintf( fp, "#PLAYER\n" );
fprintf( fp, "Version %d\n", SAVEVERSION );
fprintf( fp, "Name %s~\n", ch->name );
if ( ch->description[0] != '\0' )
fprintf( fp, "Description %s~\n", ch->description );
fprintf( fp, "Sex %d\n", ch->sex );
fprintf( fp, "Class %d\n", ch->class );
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, "Played %d\n",
ch->played + (int) (current_time - ch->logon) );
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 );
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, "Stance %d\n", ch->stance);
fprintf (fp, "Stances %d %d %d %d %d %d %d %d %d %d %d %d\n",
ch->pcdata->stances[0], ch->pcdata->stances[1],
ch->pcdata->stances[2], ch->pcdata->stances[3],
ch->pcdata->stances[4], ch->pcdata->stances[5],
ch->pcdata->stances[6], ch->pcdata->stances[7],
ch->pcdata->stances[8], ch->pcdata->stances[9],
ch->pcdata->stances[10], ch->pcdata->stances[11]);
fprintf( fp, "Gold %d\n", ch->gold );
fprintf( fp, "Exp %d\n", ch->exp );
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 );
/* Band aid for Edmond's screw up */
fprintf( fp, "SavingThrows %d %d %d %d %d\n",
race_table[ch->race]->saving_poison_death,
race_table[ch->race]->saving_wand,
race_table[ch->race]->saving_para_petri,
race_table[ch->race]->saving_breath,
race_table[ch->race]->saving_spell_staff );
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, "Honour %d\n", ch->pcdata->honour );
fprintf( fp, "Hitroll %d\n", ch->hitroll );
fprintf( fp, "Damroll %d\n", ch->damroll );
fprintf( fp, "Armor %d\n", ch->armor );
if ( ch->wimpy )
fprintf( fp, "Wimpy %d\n", ch->wimpy );
if ( !xIS_EMPTY( ch->deaf ) )
fprintf( fp, "Deaf %s\n", print_bitvector (&ch->deaf) );
if ( ch->pcdata->imc_deaf )
fprintf( fp, "IMC %ld\n", ch->pcdata->imc_deaf );
if ( ch->pcdata->imc_allow )
fprintf( fp, "IMCAllow %ld\n", ch->pcdata->imc_allow );
if ( ch->pcdata->imc_deny )
fprintf( fp, "IMCDeny %ld\n", ch->pcdata->imc_deny );
fprintf(fp, "ICEListen %s~\n", ch->pcdata->ice_listen);
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->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->icq && ch->pcdata->icq[0] != '\0' )
fprintf( fp, "ICQ %s~\n", ch->pcdata->icq );
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 );
/* 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 );
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 );
}
fprintf( fp, "Flags %d\n", ch->pcdata->flags );
if ( ch->pcdata->release_date )
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, "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] );
// Hmm not sure if we really want this. Might suck if you forgot you
// were visible to some peeps.
// Course, it personally sucks more for me when I forget I'm _not_
// visible, but meh.
// fprintf( fp, "SeeMe %s~\n", ch->pcdata->see_me ); // Alty
if ( ch->pcdata->recent_site )
fprintf( fp, "Site %s\n", ch->pcdata->recent_site );
else
fprintf( fp, "Site (Link-Dead)\n" );
/* This MUST come after Room in pfile */
if ( xIS_SET( ch->in_room->room_flags, ROOM_HOUSE ) && !IS_IMMORTAL( ch ) )
{
int i;
for (tmphome = first_home; tmphome; tmphome = tmphome->next)
for (i = 0; i < MAX_HOUSE_ROOMS; i++)
if (tmphome->vnum[i] == ch->in_room->vnum)
fprintf( fp, "Homeowner %s~\n", tmphome->name );
}
else
{
HOMEBUY_DATA *tmphb;
for ( tmphb = first_homebuy; tmphb; tmphb = tmphb->next)
if ( ch->in_room->vnum == tmphb->vnum )
fprintf( fp, "Homeowner %s~\n", tmphb->seller );
}
for (sn = 0; sn < AT_MAXCOLOR; ++sn)
if (ch->pcdata->colorize[sn] != -1)
fprintf( fp, "Color %s %d\n", at_color_table[sn].name,
ch->pcdata->colorize[sn] );
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 );
}
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 )
{
EXTRA_DESCR_DATA *ed;
AFFECT_DATA *paf;
sh_int 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 )
fwrite_obj( ch, obj->prev_content, fp, iNest, os_type );
/*
* Castrate storage characters.
* Catch deleted objects -Thoric
* Do NOT save prototype items! -Thoric
*/
if ( (ch && ch->level < obj->level)
|| ( obj->item_type == ITEM_KEY && !IS_OBJ_STAT(obj, ITEM_CLANOBJECT ))
|| ( (os_type == OS_VAULT) && (obj->item_type == ITEM_CORPSE_PC) )
|| obj_extracted(obj)
|| IS_OBJ_STAT( obj, ITEM_PROTOTYPE ) )
return;
/* Strip out existing gold-midas keys */
if ( obj->item_type == ITEM_TREASURE
&& obj->pIndexData->item_type == ITEM_KEY )
return;
/* Munch magic flagged containers for now - bandaid */
if ( obj->item_type == ITEM_CONTAINER
&& IS_OBJ_STAT( obj, ITEM_MAGIC ) )
xTOGGLE_BIT( obj->extra_flags, ITEM_MAGIC );
/* 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->owner[0] != '\0' )
fprintf( fp, "Owner %s~\n", obj->owner );
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 );
fprintf( fp, "Vnum %d\n", obj->pIndexData->vnum );
if ( ( os_type == OS_CORPSE || os_type == OS_VAULT ) && obj->in_room )
fprintf( fp, "Room %d\n", obj->in_room->vnum );
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 = WEAR_NONE;
for ( wear = 0; wear < MAX_WEAR && wear_loc == WEAR_NONE; 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 );
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;
}
/*
* 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;
extern FILE *fpArea;
extern char strArea[MAX_INPUT_LENGTH];
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;
if ( d->host )
ch->pcdata->recent_site = STRALLOC( d->host );
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);
ch->pcdata->condition[COND_THIRST] = 48;
ch->pcdata->condition[COND_FULL] = 48;
ch->pcdata->condition[COND_BLOODTHIRST] = 10;
ch->pcdata->nuisance = NULL;
ch->pcdata->wizinvis = 0;
ch->pcdata->charmies = 0;
ch->mental_state = -10;
ch->mobinvis = 0;
for(i = 0; i < MAX_SKILL; i++)
ch->pcdata->learned[i] = 0;
for (i = 0; i < MAX_STANCE; i++)
ch->pcdata->stances[i] = 0;
ch->stance = 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;
/* Set up defaults for imc stuff */
ch->pcdata->imc_deaf = 0;
ch->pcdata->imc_deny = 0;
ch->pcdata->imc_allow = 0;
ch->pcdata->ice_listen = NULL;
for (i = 0; i < AT_MAXCOLOR; ++i)
ch->pcdata->colorize[i] = -1;
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;
}
if ( (word=fread_word(fp)) == NULL )
{
CORRUPT;
break;
}
if ( !strcmp( word, "PLAYER" ) )
{
if ( fread_char(ch, fp, preload) == -1 )
{
CORRUPT;
break;
}
if ( preload )
break;
update_aris( ch );
}
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, "VARIABLE") )
fread_variable(ch, fp ); /* Variables (tags) */
else
if ( !strcmp( word, "MOBILE") )
{
CHAR_DATA *mob;
if ( ( mob = fread_mobile( fp ) ) == NULL )
break;
ch->pcdata->pet = mob;
mob->master = ch;
xSET_BIT( ch->act, PLR_BOUGHT_PET ); /* Pet crash fix */
xSET_BIT(mob->affected_by, AFF_CHARM);
if ( xIS_SET( mob->act, ACT_MOUNTED ) )
xREMOVE_BIT( mob->act, ACT_MOUNTED );
}
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 ( ch->pcdata->ice_listen == NULL )
ch->pcdata->ice_listen = str_dup("");
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->deity_name = STRALLOC( "" );
ch->pcdata->deity = NULL;
ch->pcdata->pet = 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->email = str_dup( "" );
ch->pcdata->icq = str_dup( "" );
ch->pcdata->bio = STRALLOC( "" );
ch->pcdata->authed_by = STRALLOC( "" );
ch->pcdata->prompt = STRALLOC( "" );
ch->pcdata->fprompt = STRALLOC( "" );
ch->pcdata->see_me = str_dup( "" );
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
{
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->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.
*/
#if defined(KEY)
#undef KEY
#endif
#define KEY( literal, field, value ) \
if ( !strcmp( word, literal ) ) \
{ \
field = value; \
fMatch = TRUE; \
break; \
}
int 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;
sh_int killcnt;
bool fMatch;
HOME_DATA *tmphome;
bool fHonour = FALSE;
file_ver = 0;
killcnt = 0;
for ( ; ; )
{
word = feof( fp ) ? "End" : fread_word( fp );
if ( !word )
return -1;
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 ) );
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 ( !sname )
return -1;
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 ( !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 ) );
break;
case 'B':
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 ) );
break;
case 'C':
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, "&R\n\rWarning: the organization %s no longer exists, and therefore you no longer\n\rbelong to that organization.\n\r",
ch->pcdata->clan_name );
add_loginmsg( ch->name, 18, buf );
STRFREE( ch->pcdata->clan_name );
ch->pcdata->clan_name = STRALLOC( "" );
}
fMatch = TRUE;
break;
}
KEY( "Class", ch->class, fread_number( fp ) );
if ( !str_cmp( word, "Color" ) )
{
char *cword;
int at;
cword = fread_word(fp);
if ( !cword )
return -1;
for (at = 0; at < AT_MAXCOLOR; ++at)
if (!str_cmp(cword, at_color_table[at].name))
break;
if (at < AT_MAXCOLOR)
ch->pcdata->colorize[at] = fread_number(fp);
else
{
bug("Fread_char: color %s invalid.", cword);
fread_number(fp);
}
fMatch = TRUE;
break;
}
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 ( !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, "&Y\n\rWarning: the council %s no longer exists, and therefore you no longer\n\rbelong to a council.\n\r",
ch->pcdata->council_name );
add_loginmsg( ch->name, 18, buf );
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->deaf, fread_bitvector( 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, "&R\n\rYour deity, %s, has met its demise!\n\r",
ch->pcdata->deity_name );
add_loginmsg( ch->name, 18, buf );
STRFREE( ch->pcdata->deity_name );
ch->pcdata->deity_name = STRALLOC( "" );
/* Temporarily commenting this out for deicide -- Blod, 7/2002
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( "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, "&R\n\rWarning: the organization %s no longer exists, and therefore you no longer\n\rbelong to that organization.\n\r",
ch->pcdata->clan_name );
add_loginmsg( ch->name, 18, buf );
STRFREE( ch->pcdata->clan_name );
ch->pcdata->clan_name = STRALLOC( "" );
}
fMatch = TRUE;
break;
}
break;
case 'H':
KEY( "Height", ch->height, fread_number( fp ) );
if ( !strcmp(word, "Helled") )
{
ch->pcdata->release_date = fread_number(fp);
ch->pcdata->helled_by = fread_string(fp);
fMatch = TRUE;
break;
}
KEY( "Hitroll", ch->hitroll, fread_number( fp ) );
KEY( "Homepage", ch->pcdata->homepage, fread_string_nohash( fp ) );
if ( !strcmp( word, "Honour" ) )
{
ch->pcdata->honour = fread_number( fp );
fHonour = TRUE;
fMatch = TRUE;
break;
}
if ( !strcmp( word, "Homeowner" ) )
{
int i;
fMatch = TRUE;
if ( ch->in_room && xIS_SET( ch->in_room->room_flags, ROOM_HOUSE ) )
{
for (tmphome = first_home; tmphome; tmphome = tmphome->next)
for (i = 0; i < MAX_HOUSE_ROOMS; i++)
if (tmphome->vnum[i] == ch->in_room->vnum)
if ( strcmp( tmphome->name, fread_string( fp ) ) )
ch->in_room = get_room_index( ROOM_VNUM_TEMPLE );
}
else fread_string( fp );
break;
}
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':
KEY( "ICQ", ch->pcdata->icq, fread_string_nohash( fp ) );
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 ( "IMC", ch->pcdata->imc_deaf, fread_number( fp ) );
KEY ( "IMCAllow", ch->pcdata->imc_allow, fread_number( fp ) );
KEY ( "IMCDeny", ch->pcdata->imc_deny, fread_number( fp ) );
KEY ( "ICEListen", ch->pcdata->ice_listen, fread_string_nohash( fp ) );
KEY( "Immune", ch->immune, fread_number( fp ) );
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':
KEY( "Level", ch->level, fread_number( fp ) );
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 ) );
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 ("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 '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( "SeeMe", ch->pcdata->see_me, fread_string( fp ) ); // Alty
KEY( "Sex", ch->sex, fread_number( fp ) );
KEY( "ShortDescr", ch->short_descr, fread_string( fp ) );
KEY ("Stance", ch->stance, fread_number (fp));
if (!str_cmp (word, "Stances"))
{
int tmp;
for (tmp = 0; tmp < MAX_STANCE; tmp++)
{
ch->pcdata->stances[tmp] = fread_number (fp);
}
fMatch = TRUE;
break;
}
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 )
{
ch->pcdata->prev_site = STRALLOC( fread_word( fp ) );
sprintf( buf, "Last connected from: %s\n\r", ch->pcdata->prev_site );
send_to_char( buf, ch );
}
else
fread_to_eol( fp );
fMatch = TRUE;
if ( preload )
word = "End";
else
break;
}
if ( !strcmp( word, "Skill" ) )
{
char *sword;
int sn;
int value;
if ( preload )
word = "End";
else
{
value = fread_number( fp );
if ( (sword=fread_word(fp)) == NULL )
return -1;
if ( file_ver < 3 )
sn = skill_lookup(sword);
else
sn = bsearch_skill_exact(sword, 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 ( skill_table[sn]->skill_level[ch->class] >= LEVEL_IMMORTAL )
{
ch->pcdata->learned[sn] = 0;
ch->practice++;
}
}
}
fMatch = TRUE;
break;
}
}
if ( !strcmp( word, "Spell" ) )
{
char *sword;
int sn;
int value;
if ( preload )
word = "End";
else
{
value = fread_number( fp );
if ( (sword=fread_word(fp)) == NULL )
return -1;
sn = bsearch_skill_exact(sword, 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 ( 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':
KEY( "Email", ch->pcdata->email, fread_string_nohash( fp ) );
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->email)
ch->pcdata->email = str_dup( "" );
if (!ch->pcdata->icq)
ch->pcdata->icq = str_dup( "" );
if (!ch->pcdata->homepage)
ch->pcdata->homepage = str_dup( "" );
if ( !fHonour && ( ch->level >= 50 ) )
ch->pcdata->honour = 10;
if (!ch->pcdata->see_me)
ch->pcdata->see_me = 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( "" );
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;
}
/* 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);
return 0;
}
KEY( "Exp", ch->exp, fread_number( fp ) );
break;
case 'T':
if ( !strcmp( word, "Tongue" ) )
{
char *sword;
int sn;
int value;
if ( preload )
word = "End";
else
{
value = fread_number( fp );
if ( (sword=fread_word(fp)) == NULL )
return -1;
sn = bsearch_skill_exact(sword, 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 ( 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':
if ( !strcmp( word, "Vnum" ) )
{
ch->pIndexData = get_mob_index( fread_number( fp ) );
fMatch = TRUE;
break;
}
KEY( "Version", file_ver, fread_number( fp ) );
break;
case 'W':
KEY( "Weight", ch->weight, fread_number( fp ) );
if ( !strcmp( word, "Weapon" ) )
{
char *sword;
int sn;
int value;
if ( preload )
word = "End";
else
{
value = fread_number( fp );
if ( (sword=fread_word(fp)) == NULL )
return -1;
sn = bsearch_skill_exact(sword, 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 ( 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 );
}
}
return 0;
}
bool check_owner( OBJ_DATA *obj )
{
HOME_DATA *home;
for ( home=first_home;home;home = home->next)
if ( home->vnum[0] == obj->pIndexData->vnum )
if ( !str_cmp( home->name, obj->owner ) )
return TRUE;
return FALSE;
}
void fread_obj( CHAR_DATA *ch, FILE *fp, sh_int 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 ) not sure why these are even here - but for housing purposes, they
// room = ch->in_room; should go away - so they are removed. they serve no other purpose
CREATE( obj, OBJ_DATA, 1 );
obj->count = 1;
obj->wear_loc = -1;
obj->weight = 1;
obj->owner = STRALLOC("");
fNest = TRUE; /* Requiring a Nest 0 is a waste */
/* fVnum = TRUE; We can't assume this - what if Vnum isn't written to the file? Crashy crashy is what */
fVnum = FALSE;
iNest = 0;
for ( ; ; )
{
word = feof( fp ) ? "End" : fread_word( fp );
fMatch = FALSE;
if ( !word )
break;
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
{
char *sword;
int sn;
if ( (sword=fread_word(fp)) != NULL )
{
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':
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_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 ( obj->item_type == ITEM_HOUSEKEY )
{
if ( !check_owner( obj ) )
{
bug ( "Fread_obj: house key found not belonging to correct house", 0 );
if ( obj->name )
STRFREE( obj->name );
if ( obj->description )
STRFREE( obj->description );
if ( obj->short_descr )
STRFREE( obj->short_descr );
DISPOSE( obj );
return;
}
}
if ( !fNest || !fVnum )
{
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
{
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 );
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_VAULT && room)
{
obj = 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 '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 'O':
if ( !strcmp( word, "Owner" ) )
{
STRFREE( obj->owner );
obj->owner = fread_string( fp );
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, "Spell" ) )
{
char *sword;
int iValue;
int sn = -1;
iValue = fread_number( fp );
if ( (sword=fread_word(fp)) != NULL )
sn = skill_lookup(sword);
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 );
/* clean up some garbage */
if ( file_ver < 3 && os_type != OS_VAULT )
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 ( !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->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;
}
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 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_DATA *vch;
char buf [MAX_STRING_LENGTH];
char arg [MAX_INPUT_LENGTH];
char name[MAX_INPUT_LENGTH];
struct stat fst;
one_argument( argument, arg );
if ( arg[0] == '\0' )
{
send_to_char( "Usage: last <playername>\n\r", ch );
return;
}
if ( get_trust( ch ) < LEVEL_ASCENDANT
&& ( !str_cmp( arg, "Thoric" )
|| !str_cmp( arg, "Nivek" )
|| !str_cmp( arg, "Kali" )
|| !str_cmp( arg, "Blodkai" )
|| !str_cmp( arg, "Edmond" ) ) )
{
set_char_color( AT_IMMORT, ch );
send_to_char( "Their godly glow prevents you from getting a good look.\n\r", ch );
return;
}
if ( (vch = load_player( arg )) == NULL )
sprintf( buf, "%s was not found.\n\r", arg );
else
{
strcpy( name, capitalize(arg) );
sprintf( buf, "%s%c/%s", PLAYER_DIR, tolower(arg[0]), name );
if ( stat( buf, &fst ) != -1 )
{
sprintf( buf, "%s last logged from %s on: %s\r", name,
vch->pcdata->prev_site ? vch->pcdata->prev_site : "(Link-Dead)",
ctime( &fst.st_mtime ) );
if ( !vch->desc )
{
if ( sysdata.save_pets && vch->pcdata && vch->pcdata->pet )
extract_char( vch->pcdata->pet, TRUE );
extract_char( vch, TRUE );
}
}
else
sprintf( buf, "%s was not found.\n\r", 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;
extern FILE *fpArea;
extern char strArea[MAX_INPUT_LENGTH];
extern int falling;
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 ( QUICKMATCH( mob->name, mob->pIndexData->player_name) == 0 )
fprintf( fp, "Name %s~\n", mob->name );
if ( QUICKMATCH( mob->short_descr, mob->pIndexData->short_descr) == 0 )
fprintf( fp, "Short %s~\n", mob->short_descr );
if ( QUICKMATCH( mob->long_descr, mob->pIndexData->long_descr) == 0 )
fprintf( fp, "Long %s~\n", mob->long_descr );
if ( QUICKMATCH( mob->description, mob->pIndexData->description) == 0 )
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" );
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;
}
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 )
{
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;
char buf[MAX_STRING_LENGTH];
if ( IS_NPC( ch ) || !ch->pcdata->pet )
return;
fclose( fpReserve );
if ( (fp = fopen( argument, "w")) == NULL )
{
sprintf(buf, "Write_char_mobile: couldn't open %s for writing!\n\r",
argument );
bug(buf, 0 );
fpReserve = fopen( NULL_FILE, "r" );
return;
}
mob = ch->pcdata->pet;
xSET_BIT( mob->affected_by, AFF_CHARM );
fwrite_mobile( fp, mob );
fclose( fp );
fpReserve = fopen( NULL_FILE, "r" );
return;
}
/*
* This will read in the saved mobile for a char --Shaddai
*/
void read_char_mobile( char *argument )
{
FILE *fp;
CHAR_DATA *mob;
char buf[MAX_STRING_LENGTH];
fclose( fpReserve );
if ( (fp = fopen( argument, "r")) == NULL )
{
sprintf(buf, "Read_char_mobile: couldn't open %s for reading!\n\r",
argument );
bug(buf, 0 );
fpReserve = fopen( NULL_FILE, "r" );
return;
}
mob = fread_mobile( fp );
fclose( fp );
fpReserve = fopen( NULL_FILE, "r" );
return;
}