Many of you may recall the post that I made a while back about the saving
objects in our mud. Well, finally, after much time and effort, I found the
problem. It actually had to do with the fwrite_obj function. It would look
to write the contents of pits, corpses, etc during hotboots and crashes. In
doing so it would look for "ch == NULL" and then write obj->next_content.
Well, since this same function was called if an item was flagged
ITEM_SAVING, it would write the object correctly, and then try to write
obj->next_content..... OOPS!!! That means the next object in the ROOM!
I've posted the finished, working, function for the saving part, the loading
part, and also the revised fwrite_obj, just incase anyone wants to use it.
Let me know if you have any issues. Just note where you got in your code!
Thanks for everyone's input at the time.
- Valnir
[EMAIL PROTECTED]
Legend of the Nobles (Wolfpaw Hosted)
telnet://play.legendofthenobles.com:5400
http://www.legendofthenobles.com
void save_pit ( void )
{
OBJ_DATA *obj, *obj_next;
FILE *fp;
char buf[MSL];
sprintf( buf, "%sobjects.dat", DATA_DIR );
if ( !( fp = fopen( buf, "w+" ) ) )
{
bug( "Save objects: fopen", 0 );
return;
}
for ( obj = object_list; obj != NULL; obj = obj_next )
{
obj_next = obj->next;
if ( obj->pIndexData->delete )
continue;
if ( obj->carried_by != NULL
|| ( obj->in_obj != NULL
&& obj->in_obj->carried_by != NULL ) )
continue;
if ( obj->item_type == ITEM_CORPSE_PC
|| obj->pIndexData->vnum == OBJ_VNUM_PIT
|| IS_OBJ_STAT(obj, ITEM_SAVE) )
fwrite_obj( NULL, obj, fp, 0 );
}
fprintf( fp, "#END\n" );
fclose( fp );
return;
}
/* MUST be done after loading rooms */
void load_pit ( void )
{
FILE *fp;
OBJ_DATA *obj, *obj_next;
char buf[MSL];
int iNest;
sprintf( buf, "%sobjects.dat", DATA_DIR );
if (( fp = fopen(buf, "r")) == NULL )
{
log_string("Error: objects.dat file not found!");
return;
}
for ( iNest = 0; iNest < MAX_NEST; iNest++ )
rgObjNest[iNest] = NULL;
for ( ; ; )
{
char letter;
char *word;
letter = fread_letter( fp );
if ( letter == '*' )
{
fread_to_eol( fp );
continue;
}
if ( letter != '#' )
{
bug( "Load_pit: # not found.", 0 );
break;
}
word = fread_word( fp );
if ( !str_cmp( word, "OBJECT" ) ) fread_obj ( NULL, fp );
else if ( !str_cmp( word, "O" ) ) fread_obj ( NULL, fp );
else if ( !str_cmp( word, "END" ) ) break;
else
{
bug( "Load_pit: bad section.", 0 );
break;
}
}
fclose(fp);
for ( obj = object_list; obj != NULL; obj = obj_next )
{
obj_next = obj->next;
if ( obj->in_room == get_room_index( ROOM_VNUM_LIMBO ) )
{
if ( obj->room && obj->room != 0 )
{
obj_from_room( obj );
obj_to_room( obj, get_room_index( obj->room ) );
obj->room = 0;
}
else
extract_obj( obj );
}
}
return;
}
/*
* Write an object and its contents.
*/
void fwrite_obj( CHAR_DATA *ch, OBJ_DATA *obj, FILE *fp, int iNest )
{
EXTRA_DESCR_DATA *ed;
AFFECT_DATA *paf;
/* save characters inventory */
if ( ch != NULL && obj->next_content != NULL )
fwrite_obj( ch, obj->next_content, fp, iNest );
/*
* Saves objects in containers/corpse/pit/etc through saves
* log off, hotboots. Saves in recursion so they load in the
* right order later. - Revisions 02/28/2005 - Valnir
*/
if ( ch == NULL && obj->in_obj != NULL
&& obj->next_content != NULL )
fwrite_obj( ch, obj->next_content, fp, iNest );
/*
* Castrate storage characters.
*/
if ( ch != NULL )
if ( (!level_restrict(ch,obj->level) && obj->item_type !=
ITEM_CONTAINER) )
return;
/* do not write object if object index is flagged for deletion */
if ( obj->pIndexData && obj->pIndexData->delete )
{
char buf[MSL];
sprintf( buf, "fwrite_obj: Object[%d] flagged for deletion. %s "
"removed from char.", obj->pIndexData->vnum,
capitalize(obj->short_descr) );
log_string( buf );
}
else
{
fprintf( fp, "#O\n" );
fprintf( fp, "Vnum %d\n", obj->pIndexData->vnum );
if (!obj->pIndexData->new_format)
fprintf( fp, "Oldstyle\n");
if (obj->enchanted)
fprintf( fp,"Enchanted\n");
fprintf( fp, "Nest %d\n", iNest );
/* save the room the object was in */
if ( ch == NULL && iNest == 0 && obj->in_room != NULL )
fprintf( fp, "Room %d\n", obj->in_room->vnum );
/* these data are only used if they do not match the defaults */
if ( obj->name != obj->pIndexData->name)
fprintf( fp, "Name %s~\n", obj->name );
if ( obj->short_descr != obj->pIndexData->short_descr)
fprintf( fp, "ShD %s~\n", obj->short_descr );
if ( obj->description != obj->pIndexData->description)
fprintf( fp, "Desc %s~\n", obj->description );
if ( obj->extra_flags != obj->pIndexData->extra_flags)
fprintf( fp, "ExtF %d\n", obj->extra_flags );
if ( obj->wear_flags != obj->pIndexData->wear_flags)
fprintf( fp, "WeaF %d\n", obj->wear_flags );
if ( obj->item_type != obj->pIndexData->item_type)
fprintf( fp, "Ityp %d\n", obj->item_type );
if ( obj->weight != obj->pIndexData->weight)
fprintf( fp, "Wt %d\n", obj->weight );
if ( obj->condition != obj->pIndexData->condition )
fprintf( fp, "Cond %d\n", obj->condition );
if ( obj->material != obj->pIndexData->material )
fprintf( fp, "Material %s~\n",
material_table[obj->material].name );
/* variable data */
fprintf( fp, "Wear %d\n", obj->wear_loc );
if (obj->level != obj->pIndexData->level)
fprintf( fp, "Lev %d\n", obj->level );
if (obj->timer != 0)
fprintf( fp, "Time %d\n", obj->timer );
fprintf( fp, "Cost %d\n", obj->cost );
if (obj->value[0] != obj->pIndexData->value[0]
|| obj->value[1] != obj->pIndexData->value[1]
|| obj->value[2] != obj->pIndexData->value[2]
|| obj->value[3] != obj->pIndexData->value[3]
|| obj->value[4] != obj->pIndexData->value[4])
fprintf( fp, "Val %d %d %d %d %d\n",
obj->value[0], obj->value[1], obj->value[2],
obj->value[3], obj->value[4] );
switch ( obj->item_type )
{
case ITEM_TOKEN:
if ( obj->value[0] > 1 )
fprintf( fp, "Restings %d\n", obj->value[0] );
break;
case ITEM_POTION:
case ITEM_SCROLL:
case ITEM_PILL:
if ( obj->value[1] > 0 )
{
fprintf( fp, "Spell 1 '%s'\n",
skill_table[obj->value[1]].name );
}
if ( obj->value[2] > 0 )
{
fprintf( fp, "Spell 2 '%s'\n",
skill_table[obj->value[2]].name );
}
if ( obj->value[3] > 0 )
{
fprintf( fp, "Spell 3 '%s'\n",
skill_table[obj->value[3]].name );
}
break;
case ITEM_STAFF:
case ITEM_WAND:
if ( obj->value[3] > 0 )
{
fprintf( fp, "Spell 3 '%s'\n",
skill_table[obj->value[3]].name );
}
break;
}
for ( paf = obj->affected; paf != NULL; paf = paf->next )
{
if (paf->type < 0 || paf->type >= MAX_SKILL)
continue;
fprintf( fp, "Affc '%s' %3d %3d %3d %3d %3d %20ld\n",
skill_table[paf->type].name,
paf->where, paf->level,
paf->duration, paf->modifier,
paf->location, paf->bitvector );
}
for ( ed = obj->extra_descr; ed != NULL; ed = ed->next )
{
fprintf( fp, "ExDe %s~ %s~\n", ed->keyword, ed->description );
}
fprintf( fp, "End\n\n" );
}
if ( obj->contains != NULL )
fwrite_obj( ch, obj->contains, fp, iNest + 1 );
return;
}