SAVE.C
上传用户:kesirui
上传日期:2007-01-07
资源大小:263k
文件大小:23k
源码类别:

Internet/网络编程

开发平台:

WINDOWS

  1. /***************************************************************************
  2.  *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
  3.  *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
  4.  *                                                                         *
  5.  *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
  6.  *  Chastain, Michael Quan, and Mitchell Tse.                              *
  7.  *                                                                         *
  8.  *  In order to use any part of this Merc Diku Mud, you must comply with   *
  9.  *  both the original Diku license in 'license.doc' as well the Merc       *
  10.  *  license in 'license.txt'.  In particular, you may not remove either of *
  11.  *  these copyright notices.                                               *
  12.  *                                                                         *
  13.  *  Much time and thought has gone into this software and you are          *
  14.  *  benefitting.  We hope that you share your changes too.  What goes      *
  15.  *  around, comes around.                                                  *
  16.  ***************************************************************************/
  17. #if defined(macintosh)
  18. #include <types.h>
  19. #else
  20. #include <sys/types.h>
  21. #endif
  22. #include <ctype.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <time.h>
  26. #include "merc.h"
  27. #if !defined(macintosh)
  28. extern int _filbuf args( (FILE *) );
  29. #endif
  30. #if !defined(macintosh) && !defined(MSDOS)
  31. void    system          args( ( char *string ) );
  32. #endif
  33. /*
  34.  * Array of containers read for proper re-nesting of objects.
  35.  */
  36. #define MAX_NEST 100
  37. static OBJ_DATA * rgObjNest [MAX_NEST];
  38. /*
  39.  * Local functions.
  40.  */
  41. void fwrite_char args( ( CHAR_DATA *ch,  FILE *fp ) );
  42. void fwrite_obj args( ( CHAR_DATA *ch,  OBJ_DATA  *obj,
  43.     FILE *fp, int iNest ) );
  44. void fread_char args( ( CHAR_DATA *ch,  FILE *fp ) );
  45. void fread_obj args( ( CHAR_DATA *ch,  FILE *fp ) );
  46. /* Courtesy of Yaz of 4th Realm */
  47. char *initial( const char *str )
  48. {
  49.     static char strint[ MAX_STRING_LENGTH ];
  50.     strint[0] = LOWER( str[ 0 ] );
  51.     return strint;
  52. }
  53. /*
  54.  * Save a character and inventory.
  55.  * Would be cool to save NPC's too for quest purposes,
  56.  *   some of the infrastructure is provided.
  57.  */
  58. void save_char_obj( CHAR_DATA *ch )
  59. {
  60.     char strsave[MAX_INPUT_LENGTH];
  61.     FILE *fp;
  62.     // @@@ ECS Allow 1st level to save
  63.     if ( IS_NPC(ch) /*|| ch->level < 2*/ )
  64. return;
  65.     if ( ch->desc != NULL && ch->desc->original != NULL )
  66. ch = ch->desc->original;
  67.     ch->save_time = current_time;
  68.     fclose( fpReserve );
  69.     /* player files parsed directories by Yaz 4th Realm */
  70. #if !defined(machintosh) && !defined(MSDOS) && !defined(WIN32)
  71.     sprintf( strsave, "%s%s%s%s", PLAYER_DIR, initial( ch->name ),
  72.     "/", capitalize( ch->name ) );
  73. #else
  74.     sprintf( strsave, "%s%s", PLAYER_DIR, capitalize( ch->name ) );
  75. #endif
  76.     if ( ( fp = fopen( strsave, "w" ) ) == NULL )
  77.     {
  78. bug( "Save_char_obj: fopen", 0 );
  79. perror( strsave );
  80.     }
  81.     else
  82.     {
  83. fwrite_char( ch, fp );
  84. if ( ch->carrying != NULL )
  85.     fwrite_obj( ch, ch->carrying, fp, 0 );
  86. if (fprintf( fp, "#ENDn" ) == EOF)
  87. //      log_error("I/O error writing player file");
  88.       bug("I/O error writing player file", 0);
  89.     }
  90.     fclose( fp );
  91.     fpReserve = fopen( NULL_FILE, "r" );
  92.     return;
  93. }
  94. /*
  95.  * Write the char.
  96.  */
  97. void fwrite_char( CHAR_DATA *ch, FILE *fp )
  98. {
  99.     AFFECT_DATA *paf;
  100.     int sn;
  101.     fprintf( fp, "#%sn", IS_NPC(ch) ? "MOB" : "PLAYER" );
  102.     fprintf( fp, "Name         %s~n", ch->name );
  103.     fprintf( fp, "ShortDescr   %s~n", ch->short_descr );
  104.     fprintf( fp, "LongDescr    %s~n", ch->long_descr );
  105.     fprintf( fp, "Description  %s~n", ch->description );
  106.     fprintf( fp, "Prompt       %s~n", ch->prompt );
  107.     fprintf( fp, "Sex          %dn", ch->sex );
  108.     fprintf( fp, "Class        %dn", ch->class );
  109.     fprintf( fp, "Race         %dn", ch->race );
  110.     fprintf( fp, "Level        %dn", ch->level );
  111.     fprintf( fp, "Trust        %dn", ch->trust );
  112.     fprintf( fp, "Wizbit       %dn", ch->wizbit );
  113.     fprintf( fp, "Played       %dn",
  114. ch->played + (int) (current_time - ch->logon) );
  115.     fprintf( fp, "Note         %ldn",   ch->last_note           );
  116. //    fprintf( fp, "Note         %dn",   ch->last_note           );
  117.     fprintf( fp, "Room         %dn",
  118. (  ch->in_room == get_room_index( ROOM_VNUM_LIMBO )
  119. && ch->was_in_room != NULL )
  120.     ? ch->was_in_room->vnum
  121.     : ch->in_room->vnum );
  122.     fprintf( fp, "HpManaMove   %d %d %d %d %d %dn",
  123. ch->hit, ch->max_hit, ch->mana, ch->max_mana, ch->move, ch->max_move );
  124.     fprintf( fp, "Gold         %dn", ch->gold );
  125.     fprintf( fp, "Exp          %dn", ch->exp );
  126.     fprintf( fp, "Act          %dn",   ch->act );
  127.     fprintf( fp, "AffectedBy   %dn", ch->affected_by );
  128.     /* Bug fix from Alander */
  129.     fprintf( fp, "Position     %dn",
  130.         ch->position == POS_FIGHTING ? POS_STANDING : ch->position );
  131.     fprintf( fp, "Practice     %dn", ch->practice );
  132.     fprintf( fp, "SavingThrow  %dn", ch->saving_throw );
  133.     fprintf( fp, "Alignment    %dn", ch->alignment );
  134.     fprintf( fp, "Hitroll      %dn", ch->hitroll );
  135.     fprintf( fp, "Damroll      %dn", ch->damroll );
  136.     fprintf( fp, "Armor        %dn", ch->armor );
  137.     fprintf( fp, "Wimpy        %dn", ch->wimpy );
  138.     fprintf( fp, "Deaf         %dn", ch->deaf );
  139.     if ( IS_NPC(ch) )
  140.     {
  141. fprintf( fp, "Vnum         %dn", ch->pIndexData->vnum );
  142.     }
  143.     else
  144.     {
  145. fprintf( fp, "Password     %s~n", ch->pcdata->pwd );
  146. fprintf( fp, "Bamfin       %s~n", ch->pcdata->bamfin );
  147. fprintf( fp, "Bamfout      %s~n", ch->pcdata->bamfout );
  148. fprintf( fp, "Title        %s~n", ch->pcdata->title );
  149. fprintf( fp, "AttrPerm     %d %d %d %d %dn",
  150.     ch->pcdata->perm_str,
  151.     ch->pcdata->perm_int,
  152.     ch->pcdata->perm_wis,
  153.     ch->pcdata->perm_dex,
  154.     ch->pcdata->perm_con );
  155. fprintf( fp, "AttrMod      %d %d %d %d %dn",
  156.     ch->pcdata->mod_str, 
  157.     ch->pcdata->mod_int, 
  158.     ch->pcdata->mod_wis,
  159.     ch->pcdata->mod_dex, 
  160.     ch->pcdata->mod_con );
  161. fprintf( fp, "Condition    %d %d %dn",
  162.     ch->pcdata->condition[0],
  163.     ch->pcdata->condition[1],
  164.     ch->pcdata->condition[2] );
  165. fprintf( fp, "Pagelen      %dn",   ch->pcdata->pagelen     );
  166. for ( sn = 0; sn < MAX_SKILL; sn++ )
  167. {
  168.     if ( skill_table[sn].name != NULL && ch->pcdata->learned[sn] > 0 )
  169.     {
  170. fprintf( fp, "Skill        %d '%s'n",
  171.     ch->pcdata->learned[sn], skill_table[sn].name );
  172.     }
  173. }
  174.     }
  175.     for ( paf = ch->affected; paf != NULL; paf = paf->next )
  176.     {
  177. fprintf( fp, "Affect %3d %3d %3d %3d %10dn",
  178.     paf->type,
  179.     paf->duration,
  180.     paf->modifier,
  181.     paf->location,
  182.     paf->bitvector
  183.     );
  184.     }
  185.     fprintf( fp, "Endnn" );
  186.     return;
  187. }
  188. /*
  189.  * Write an object and its contents.
  190.  */
  191. void fwrite_obj( CHAR_DATA *ch, OBJ_DATA *obj, FILE *fp, int iNest )
  192. {
  193.     EXTRA_DESCR_DATA *ed;
  194.     AFFECT_DATA *paf;
  195.     /*
  196.      * Slick recursion to write lists backwards,
  197.      *   so loading them will load in forwards order.
  198.      */
  199.     if ( obj->next_content != NULL )
  200. fwrite_obj( ch, obj->next_content, fp, iNest );
  201.     /*
  202.      * Castrate storage characters.
  203.      */
  204.     if ( ch->level < obj->level
  205.     ||   obj->item_type == ITEM_KEY
  206.     ||   obj->item_type == ITEM_POTION )
  207. return;
  208.     fprintf( fp, "#OBJECTn" );
  209.     fprintf( fp, "Nest         %dn", iNest      );
  210.     fprintf( fp, "Name         %s~n", obj->name      );
  211.     fprintf( fp, "ShortDescr   %s~n", obj->short_descr      );
  212.     fprintf( fp, "Description  %s~n", obj->description      );
  213.     fprintf( fp, "Vnum         %dn", obj->pIndexData->vnum      );
  214.     fprintf( fp, "ExtraFlags   %dn", obj->extra_flags      );
  215.     fprintf( fp, "WearFlags    %dn", obj->wear_flags      );
  216.     fprintf( fp, "WearLoc      %dn", obj->wear_loc      );
  217.     fprintf( fp, "ItemType     %dn", obj->item_type      );
  218.     fprintf( fp, "Weight       %dn", obj->weight      );
  219.     fprintf( fp, "Level        %dn", obj->level      );
  220.     fprintf( fp, "Timer        %dn", obj->timer      );
  221.     fprintf( fp, "Cost         %dn", obj->cost      );
  222.     fprintf( fp, "Values       %d %d %d %dn",
  223. obj->value[0], obj->value[1], obj->value[2], obj->value[3]      );
  224.     switch ( obj->item_type )
  225.     {
  226.     case ITEM_POTION:
  227.     case ITEM_SCROLL:
  228. if ( obj->value[1] > 0 )
  229. {
  230.     fprintf( fp, "Spell 1      '%s'n",
  231. skill_table[obj->value[1]].name );
  232. }
  233. if ( obj->value[2] > 0 )
  234. {
  235.     fprintf( fp, "Spell 2      '%s'n", 
  236. skill_table[obj->value[2]].name );
  237. }
  238. if ( obj->value[3] > 0 )
  239. {
  240.     fprintf( fp, "Spell 3      '%s'n", 
  241. skill_table[obj->value[3]].name );
  242. }
  243. break;
  244.     case ITEM_PILL:
  245.     case ITEM_STAFF:
  246.     case ITEM_WAND:
  247. if ( obj->value[3] > 0 )
  248. {
  249.     fprintf( fp, "Spell 3      '%s'n", 
  250. skill_table[obj->value[3]].name );
  251. }
  252. break;
  253.     }
  254.     for ( paf = obj->affected; paf != NULL; paf = paf->next )
  255.     {
  256. fprintf( fp, "Affect       %d %d %d %d %dn",
  257.     paf->type,
  258.     paf->duration,
  259.     paf->modifier,
  260.     paf->location,
  261.     paf->bitvector
  262.     );
  263.     }
  264.     for ( ed = obj->extra_descr; ed != NULL; ed = ed->next )
  265.     {
  266. fprintf( fp, "ExtraDescr   %s~ %s~n",
  267.     ed->keyword, ed->description );
  268.     }
  269.     fprintf( fp, "Endnn" );
  270.     if ( obj->contains != NULL )
  271. fwrite_obj( ch, obj->contains, fp, iNest + 1 );
  272.     return;
  273. }
  274. /*
  275.  * Load a char and inventory into a new ch structure.
  276.  */
  277. bool load_char_obj( DESCRIPTOR_DATA *d, char *name )
  278. {
  279.     static PC_DATA pcdata_zero;
  280.     char strsave[MAX_INPUT_LENGTH];
  281.     char buf [MAX_STRING_LENGTH];
  282.     CHAR_DATA *ch;
  283.     FILE *fp;
  284.     bool found;
  285.     if ( char_free == NULL )
  286.     {
  287. ch = alloc_perm( sizeof(*ch) );
  288.     }
  289.     else
  290.     {
  291. ch = char_free;
  292. char_free = char_free->next;
  293.     }
  294.     clear_char( ch );
  295.     if ( pcdata_free == NULL )
  296.     {
  297. ch->pcdata = alloc_perm( sizeof(*ch->pcdata) );
  298.     }
  299.     else
  300.     {
  301. ch->pcdata = pcdata_free;
  302. pcdata_free = pcdata_free->next;
  303.     }
  304.     *ch->pcdata = pcdata_zero;
  305.     d->character = ch;
  306.     ch->desc = d;
  307.     ch->name = str_dup( name );
  308.     ch->prompt                          = str_dup( "<%hhp %mm %vmv> " );
  309.     ch->last_note                       = 0;
  310.     ch->act = PLR_BLANK
  311. | PLR_COMBINE
  312. | PLR_PROMPT;
  313.     ch->pcdata->pwd = str_dup( "" );
  314.     ch->pcdata->bamfin = str_dup( "" );
  315.     ch->pcdata->bamfout = str_dup( "" );
  316.     ch->pcdata->title = str_dup( "" );
  317.     ch->pcdata->perm_str = 13;
  318.     ch->pcdata->perm_int = 13; 
  319.     ch->pcdata->perm_wis = 13;
  320.     ch->pcdata->perm_dex = 13;
  321.     ch->pcdata->perm_con = 13;
  322.     ch->pcdata->condition[COND_THIRST] = 48;
  323.     ch->pcdata->pagelen                 = 20;
  324.     ch->pcdata->condition[COND_FULL] = 48;
  325.     found = FALSE;
  326.     fclose( fpReserve );
  327.     /* parsed player file directories by Yaz of 4th Realm */
  328.     /* decompress if .gz file exists - Thx Alander */
  329. #if !defined(macintosh) && !defined(MSDOS) && !defined(WIN32)
  330.     sprintf( strsave, "%s%s%s%s%s", PLAYER_DIR, initial( ch->name ),
  331.     "/", capitalize( name ), ".gz" );
  332.     if ( ( fp = fopen( strsave, "r" ) ) != NULL )
  333.     {
  334. fclose( fp );
  335. sprintf( buf, "gzip -dfq %s", strsave );
  336. system( buf );
  337.     }
  338. #endif
  339. #if !defined(machintosh) && !defined(MSDOS) && !defined(WIN32)
  340.     sprintf( strsave, "%s%s%s%s", PLAYER_DIR, initial( ch->name ),
  341.     "/", capitalize( name ) );
  342. #else
  343.     sprintf( strsave, "%s%s", PLAYER_DIR, capitalize( name ) );
  344. #endif
  345.     if ( ( fp = fopen( strsave, "r" ) ) != NULL )
  346.     {
  347. int iNest;
  348. for ( iNest = 0; iNest < MAX_NEST; iNest++ )
  349.     rgObjNest[iNest] = NULL;
  350. found = TRUE;
  351. for ( ; ; )
  352. {
  353.     char letter;
  354.     char *word;
  355.     letter = fread_letter( fp );
  356.     if ( letter == '*' )
  357.     {
  358. fread_to_eol( fp );
  359. continue;
  360.     }
  361.     if ( letter != '#' )
  362.     {
  363. bug( "Load_char_obj: # not found.", 0 );
  364. break;
  365.     }
  366.     word = fread_word( fp );
  367.     if      ( !str_cmp( word, "PLAYER" ) ) fread_char ( ch, fp );
  368.     else if ( !str_cmp( word, "OBJECT" ) ) fread_obj  ( ch, fp );
  369.     else if ( !str_cmp( word, "END"    ) ) break;
  370.     else
  371.     {
  372. bug( "Load_char_obj: bad section.", 0 );
  373. break;
  374.     }
  375. }
  376. fclose( fp );
  377.     }
  378.     fpReserve = fopen( NULL_FILE, "r" );
  379.     return found;
  380. }
  381. /*
  382.  * Read in a char.
  383.  */
  384. #if defined(KEY)
  385. #undef KEY
  386. #endif
  387. #define KEY( literal, field, value )
  388. if ( !str_cmp( word, literal ) )
  389. {
  390.     field  = value;
  391.     fMatch = TRUE;
  392.     break;
  393. }
  394. void fread_char( CHAR_DATA *ch, FILE *fp )
  395. {
  396.     char buf[MAX_STRING_LENGTH];
  397.     char *word;
  398.     bool fMatch;
  399.     for ( ; ; )
  400.     {
  401. word   = feof( fp ) ? "End" : fread_word( fp );
  402. fMatch = FALSE;
  403. switch ( UPPER(word[0]) )
  404. {
  405. case '*':
  406.     fMatch = TRUE;
  407.     fread_to_eol( fp );
  408.     break;
  409. case 'A':
  410.     KEY( "Act", ch->act, fread_number( fp ) );
  411.     KEY( "AffectedBy", ch->affected_by, fread_number( fp ) );
  412.     KEY( "Alignment", ch->alignment, fread_number( fp ) );
  413.     KEY( "Armor", ch->armor, fread_number( fp ) );
  414.     if ( !str_cmp( word, "Affect" ) )
  415.     {
  416. AFFECT_DATA *paf;
  417. if ( affect_free == NULL )
  418. {
  419.     paf = alloc_perm( sizeof(*paf) );
  420. }
  421. else
  422. {
  423.     paf = affect_free;
  424.     affect_free = affect_free->next;
  425. }
  426. paf->type = fread_number( fp );
  427. paf->duration = fread_number( fp );
  428. paf->modifier = fread_number( fp );
  429. paf->location = fread_number( fp );
  430. paf->bitvector = fread_number( fp );
  431. paf->next = ch->affected;
  432. ch->affected = paf;
  433. fMatch = TRUE;
  434. break;
  435.     }
  436.     if ( !str_cmp( word, "AttrMod"  ) )
  437.     {
  438. ch->pcdata->mod_str  = fread_number( fp );
  439. ch->pcdata->mod_int  = fread_number( fp );
  440. ch->pcdata->mod_wis  = fread_number( fp );
  441. ch->pcdata->mod_dex  = fread_number( fp );
  442. ch->pcdata->mod_con  = fread_number( fp );
  443. fMatch = TRUE;
  444. break;
  445.     }
  446.     if ( !str_cmp( word, "AttrPerm" ) )
  447.     {
  448. ch->pcdata->perm_str = fread_number( fp );
  449. ch->pcdata->perm_int = fread_number( fp );
  450. ch->pcdata->perm_wis = fread_number( fp );
  451. ch->pcdata->perm_dex = fread_number( fp );
  452. ch->pcdata->perm_con = fread_number( fp );
  453. fMatch = TRUE;
  454. break;
  455.     }
  456.     break;
  457. case 'B':
  458.     KEY( "Bamfin", ch->pcdata->bamfin, fread_string( fp ) );
  459.     KEY( "Bamfout", ch->pcdata->bamfout, fread_string( fp ) );
  460.     break;
  461. case 'C':
  462.     KEY( "Class", ch->class, fread_number( fp ) );
  463.     if ( !str_cmp( word, "Condition" ) )
  464.     {
  465. ch->pcdata->condition[0] = fread_number( fp );
  466. ch->pcdata->condition[1] = fread_number( fp );
  467. ch->pcdata->condition[2] = fread_number( fp );
  468. fMatch = TRUE;
  469. break;
  470.     }
  471.     break;
  472. case 'D':
  473.     KEY( "Damroll", ch->damroll, fread_number( fp ) );
  474.     KEY( "Deaf", ch->deaf, fread_number( fp ) );
  475.     KEY( "Description", ch->description, fread_string( fp ) );
  476.     break;
  477. case 'E':
  478.     if ( !str_cmp( word, "End" ) )
  479.         {
  480.         /* If a bug caused the affected_by to drop off, restore it--Slash */
  481.         ch->affected_by |= race_table[ch->race].bitvector;
  482.   return;
  483.         }
  484.     KEY( "Exp", ch->exp, fread_number( fp ) );
  485.     break;
  486. case 'G':
  487.     KEY( "Gold", ch->gold, fread_number( fp ) );
  488.     break;
  489. case 'H':
  490.     KEY( "Hitroll", ch->hitroll, fread_number( fp ) );
  491.     if ( !str_cmp( word, "HpManaMove" ) )
  492.     {
  493. ch->hit = fread_number( fp );
  494. ch->max_hit = fread_number( fp );
  495. ch->mana = fread_number( fp );
  496. ch->max_mana = fread_number( fp );
  497. ch->move = fread_number( fp );
  498. ch->max_move = fread_number( fp );
  499. fMatch = TRUE;
  500. break;
  501.     }
  502.     break;
  503. case 'L':
  504.     KEY( "Level", ch->level, fread_number( fp ) );
  505.     KEY( "LongDescr", ch->long_descr, fread_string( fp ) );
  506.     break;
  507. case 'N':
  508.     if ( !str_cmp( word, "Name" ) )
  509.     {
  510. /*
  511.  * Name already set externally.
  512.  */
  513. fread_to_eol( fp );
  514. fMatch = TRUE;
  515. break;
  516.     }
  517.     KEY( "Note",        ch->last_note,          fread_number( fp ) );
  518.     break;
  519. case 'P':
  520.     KEY( "Pagelen",     ch->pcdata->pagelen,    fread_number( fp ) );
  521.     KEY( "Password", ch->pcdata->pwd, fread_string( fp ) );
  522.     KEY( "Played", ch->played, fread_number( fp ) );
  523.     KEY( "Position", ch->position, fread_number( fp ) );
  524.     KEY( "Practice", ch->practice, fread_number( fp ) );
  525.     KEY( "Prompt", ch->prompt, fread_string( fp ) );
  526.     break;
  527. case 'R':
  528.     KEY( "Race",        ch->race, fread_number( fp ) );
  529.     if ( !str_cmp( word, "Room" ) )
  530.     {
  531. ch->in_room = get_room_index( fread_number( fp ) );
  532. if ( ch->in_room == NULL )
  533.     ch->in_room = get_room_index( ROOM_VNUM_LIMBO );
  534. fMatch = TRUE;
  535. break;
  536.     }
  537.     break;
  538. case 'S':
  539.     KEY( "SavingThrow", ch->saving_throw, fread_number( fp ) );
  540.     KEY( "Sex", ch->sex, fread_number( fp ) );
  541.     KEY( "ShortDescr", ch->short_descr, fread_string( fp ) );
  542.     if ( !str_cmp( word, "Skill" ) )
  543.     {
  544. int sn;
  545. int value;
  546. value = fread_number( fp );
  547. sn    = skill_lookup( fread_word( fp ) );
  548. if ( sn < 0 )
  549.     bug( "Fread_char: unknown skill.", 0 );
  550. else
  551.     ch->pcdata->learned[sn] = value;
  552. fMatch = TRUE;
  553.     }
  554.     break;
  555. case 'T':
  556.     KEY( "Trust", ch->trust, fread_number( fp ) );
  557.     if ( !str_cmp( word, "Title" ) )
  558.     {
  559. ch->pcdata->title = fread_string( fp );
  560. if ( isalpha(ch->pcdata->title[0])
  561. ||   isdigit(ch->pcdata->title[0]) )
  562. {
  563.     sprintf( buf, " %s", ch->pcdata->title );
  564.     free_string( ch->pcdata->title );
  565.     ch->pcdata->title = str_dup( buf );
  566. }
  567. fMatch = TRUE;
  568. break;
  569.     }
  570.     break;
  571. case 'V':
  572.     if ( !str_cmp( word, "Vnum" ) )
  573.     {
  574. ch->pIndexData = get_mob_index( fread_number( fp ) );
  575. fMatch = TRUE;
  576. break;
  577.     }
  578.     break;
  579. case 'W':
  580.     KEY( "Wimpy", ch->wimpy, fread_number( fp ) );
  581.     KEY( "Wizbit", ch->wizbit, fread_number( fp ) );
  582.     break;
  583. }
  584. /* Make sure old chars have this field - Kahn */
  585. if ( !ch->pcdata->pagelen )
  586.     ch->pcdata->pagelen = 20;
  587. if ( !ch->prompt || ch->prompt == '' )
  588.     ch->prompt = "<%h %m %mv> ";
  589. if ( !fMatch )
  590. {
  591.     bug( "Fread_char: no match.", 0 );
  592.     fread_to_eol( fp );
  593. }
  594.     }
  595. }
  596. void fread_obj( CHAR_DATA *ch, FILE *fp )
  597. {
  598.     static OBJ_DATA obj_zero;
  599.     OBJ_DATA *obj;
  600.     char *word;
  601.     int iNest;
  602.     bool fMatch;
  603.     bool fNest;
  604.     bool fVnum;
  605.     if ( obj_free == NULL )
  606.     {
  607. obj = alloc_perm( sizeof(*obj) );
  608.     }
  609.     else
  610.     {
  611. obj = obj_free;
  612. obj_free = obj_free->next;
  613.     }
  614.     *obj = obj_zero;
  615.     obj->name = str_dup( "" );
  616.     obj->short_descr = str_dup( "" );
  617.     obj->description = str_dup( "" );
  618.     fNest = FALSE;
  619.     fVnum = TRUE;
  620.     iNest = 0;
  621.     for ( ; ; )
  622.     {
  623. word   = feof( fp ) ? "End" : fread_word( fp );
  624. fMatch = FALSE;
  625. switch ( UPPER(word[0]) )
  626. {
  627. case '*':
  628.     fMatch = TRUE;
  629.     fread_to_eol( fp );
  630.     break;
  631. case 'A':
  632.     if ( !str_cmp( word, "Affect" ) )
  633.     {
  634. AFFECT_DATA *paf;
  635. if ( affect_free == NULL )
  636. {
  637.     paf = alloc_perm( sizeof(*paf) );
  638. }
  639. else
  640. {
  641.     paf = affect_free;
  642.     affect_free = affect_free->next;
  643. }
  644. paf->type = fread_number( fp );
  645. paf->duration = fread_number( fp );
  646. paf->modifier = fread_number( fp );
  647. paf->location = fread_number( fp );
  648. paf->bitvector = fread_number( fp );
  649. paf->next = obj->affected;
  650. obj->affected = paf;
  651. fMatch = TRUE;
  652. break;
  653.     }
  654.     break;
  655. case 'C':
  656.     KEY( "Cost", obj->cost, fread_number( fp ) );
  657.     break;
  658. case 'D':
  659.     KEY( "Description", obj->description, fread_string( fp ) );
  660.     break;
  661. case 'E':
  662.     KEY( "ExtraFlags", obj->extra_flags, fread_number( fp ) );
  663.     if ( !str_cmp( word, "ExtraDescr" ) )
  664.     {
  665. EXTRA_DESCR_DATA *ed;
  666. if ( extra_descr_free == NULL )
  667. {
  668.     ed = alloc_perm( sizeof(*ed) );
  669. }
  670. else
  671. {
  672.     ed = extra_descr_free;
  673.     extra_descr_free = extra_descr_free->next;
  674. }
  675. ed->keyword = fread_string( fp );
  676. ed->description = fread_string( fp );
  677. ed->next = obj->extra_descr;
  678. obj->extra_descr = ed;
  679. fMatch = TRUE;
  680.     }
  681.     if ( !str_cmp( word, "End" ) )
  682.     {
  683. if ( !fNest || !fVnum )
  684. {
  685.     bug( "Fread_obj: incomplete object.", 0 );
  686.     free_string( obj->name        );
  687.     free_string( obj->description );
  688.     free_string( obj->short_descr );
  689.     obj->next = obj_free;
  690.     obj_free  = obj;
  691.     return;
  692. }
  693. else
  694. {
  695.     obj->next = object_list;
  696.     object_list = obj;
  697.     obj->pIndexData->count++;
  698.     if ( iNest == 0 || rgObjNest[iNest] == NULL )
  699. obj_to_char( obj, ch );
  700.     else
  701. obj_to_obj( obj, rgObjNest[iNest-1] );
  702.     return;
  703. }
  704.     }
  705.     break;
  706. case 'I':
  707.     KEY( "ItemType", obj->item_type, fread_number( fp ) );
  708.     break;
  709. case 'L':
  710.     KEY( "Level", obj->level, fread_number( fp ) );
  711.     break;
  712. case 'N':
  713.     KEY( "Name", obj->name, fread_string( fp ) );
  714.     if ( !str_cmp( word, "Nest" ) )
  715.     {
  716. iNest = fread_number( fp );
  717. if ( iNest < 0 || iNest >= MAX_NEST )
  718. {
  719.     bug( "Fread_obj: bad nest %d.", iNest );
  720. }
  721. else
  722. {
  723.     rgObjNest[iNest] = obj;
  724.     fNest = TRUE;
  725. }
  726. fMatch = TRUE;
  727.     }
  728.     break;
  729. case 'S':
  730.     KEY( "ShortDescr", obj->short_descr, fread_string( fp ) );
  731.     if ( !str_cmp( word, "Spell" ) )
  732.     {
  733. int iValue;
  734. int sn;
  735. iValue = fread_number( fp );
  736. sn     = skill_lookup( fread_word( fp ) );
  737. if ( iValue < 0 || iValue > 3 )
  738. {
  739.     bug( "Fread_obj: bad iValue %d.", iValue );
  740. }
  741. else if ( sn < 0 )
  742. {
  743.     bug( "Fread_obj: unknown skill.", 0 );
  744. }
  745. else
  746. {
  747.     obj->value[iValue] = sn;
  748. }
  749. fMatch = TRUE;
  750. break;
  751.     }
  752.     break;
  753. case 'T':
  754.     KEY( "Timer", obj->timer, fread_number( fp ) );
  755.     break;
  756. case 'V':
  757.     if ( !str_cmp( word, "Values" ) )
  758.     {
  759. obj->value[0] = fread_number( fp );
  760. obj->value[1] = fread_number( fp );
  761. obj->value[2] = fread_number( fp );
  762. obj->value[3] = fread_number( fp );
  763. fMatch = TRUE;
  764. break;
  765.     }
  766.     if ( !str_cmp( word, "Vnum" ) )
  767.     {
  768. int vnum;
  769. vnum = fread_number( fp );
  770. if ( ( obj->pIndexData = get_obj_index( vnum ) ) == NULL )
  771.           {
  772. //     bug( "Fread_obj: bad vnum %d.", vnum );
  773.           log_string("Fread_object: player file contained invalid vnum");
  774.           obj->pIndexData = get_obj_index(OBJ_VNUM_ERROR);
  775.           }
  776. else
  777.     fVnum = TRUE;
  778. fMatch = TRUE;
  779. break;
  780.     }
  781.     break;
  782. case 'W':
  783.     KEY( "WearFlags", obj->wear_flags, fread_number( fp ) );
  784.     KEY( "WearLoc", obj->wear_loc, fread_number( fp ) );
  785.     KEY( "Weight", obj->weight, fread_number( fp ) );
  786.     break;
  787. }
  788. if ( !fMatch )
  789. {
  790.     bug( "Fread_obj: no match.", 0 );
  791.     fread_to_eol( fp );
  792. }
  793.     }
  794. }