#include "copyright.h" #include <sys/types.h> #include <ctype.h> #include <stdio.h> #if defined (sun) || defined (linux) #include <stdlib.h> #endif #include <string.h> #include <time.h> #include "merc.h" extern int _filbuf(FILE *); /* * Array of containers read for proper re-nesting of objects. */ #define MAX_NEST 100 static OBJ_DATA *rgObjNest[MAX_NEST]; /* * Local functions. */ void fwrite_char(CHAR_DATA *ch, FILE * fp); void fwrite_obj(CHAR_DATA *ch, OBJ_DATA *obj, FILE * fp, int iNest); void fread_char(CHAR_DATA *ch, FILE * fp); void fread_obj(CHAR_DATA *ch, FILE * fp); /* Courtesy of Yaz of 4th Realm */ char * initial(const char *str) { static char strint[MAX_STRING_LENGTH]; strint[0] = tolower(str[0]); return strint; } void do_delet(CHAR_DATA *ch, char *argument) { send_to_char("If you want to DELETE, you have to spell it out.\n\r", ch); send_to_char("Warning... This character WILL be gone. No reimbursements.\n\r", ch); return; } void do_delete(CHAR_DATA *ch, char *argument) { char buf[MAX_INPUT_LENGTH]; char arg[MAX_INPUT_LENGTH]; one_argument(argument, arg); if (str_cmp(arg, ch->name)) { send_to_char("Are you SURE you want to delete this character?\n\r", ch); send_to_char("Type: delete <your name> to delete.\n\r", ch); return; } send_to_char("This character has been deleted.\n\r", ch ); do_quit(ch, ""); sprintf(buf, "rm %s%s/%s",PLAYER_DIR, initial(ch->name), capitalize(ch->name)); system(buf); return; } /* * 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) { FILE *fp; char strsave[MAX_INPUT_LENGTH]; char backup[MAX_INPUT_LENGTH]; if (IS_NPC(ch) || ch->level < 2) return; if (ch->desc && ch->desc->original) ch = ch->desc->original; ch->save_time = current_time; fclose(fpReserve); /* player files parsed directories by Yaz 4th Realm */ sprintf(strsave, "%s%s/%s", PLAYER_DIR, initial(ch->name), capitalize(ch->name)); /* old auto-backup system * sprintf(backup, "cp %s ../pFileBacks/%s", strsave, ch->name); * system( backup ); * sprintf(backup, "gzip -f --fast ../pFileBacks/%s &", ch->name); * system( backup ); */ if (!(fp = fopen(strsave, "w"))) { bug("fopen %s: ", ch->name); perror(strsave); } else { fwrite_char(ch, fp); if (ch->carrying) fwrite_obj(ch, ch->carrying, fp, 0); fprintf(fp, "#END\n"); fclose(fp); } fpReserve = fopen(NULL_FILE, "r"); return; } /* * Write the char. */ void fwrite_char(CHAR_DATA *ch, FILE * fp) { AFFECT_DATA *paf; int sn; int ibeamob; if (!ch || !fp) return; ibeamob= IS_NPC(ch); fprintf(fp, "#%s\n", ibeamob ? "MOB" : "PLAYER"); fprintf(fp, "Nm %s~\n", ch->name); smash_tilde(ch->hostname); fprintf(fp, "Host %s~\n", ch->hostname); fprintf(fp, "ShtDsc %s~\n", ch->short_descr); fprintf(fp, "LngDsc %s~\n", ch->long_descr); fprintf(fp, "Dscr %s~\n", ch->description); fprintf(fp, "Prmpt %s~\n", ch->prompt); fprintf(fp, "Clanname %s~\n", ch->clanname); fprintf(fp, "Sx %d\n", ch->sex); fprintf(fp, "Eviscerated %d\n", ch->eviscerated); fprintf(fp, "Cla %d\n", ch->class); fprintf(fp, "Dual %d\n", ch->dual); fprintf(fp, "Rce %d\n", ch->race); fprintf(fp, "Clan %d\n", ch->clan); fprintf(fp, "Clanrank %d\n", ch->clanrank); fprintf(fp, "Sect %d\n", ch->sect); fprintf(fp, "Lvl %d\n", ch->level); fprintf(fp, "Trst %d\n", ch->trust); if (!ibeamob) fprintf(fp, "Security %d\n", ch->pcdata->security); /* OLC */ fprintf(fp, "Quest %d\n", ch->quest); fprintf(fp, "Qstact %d\n", ch->questact); fprintf(fp, "Wizbt %d\n", ch->wizbit); fprintf(fp, "Playd %d\n", ch->played + (int)(current_time - ch->logon)); fprintf(fp, "Note %ld\n", ch->last_note); fprintf(fp, "Pet %d\n", ch->mypet); fprintf(fp, "Petsname %s~\n", ch->pets_name); 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, "Home %d\n", ch->home_room); fprintf(fp, "HpMnMv %d %d %d %d %d %d\n", ch->hit, ch->max_hit, ch->mana, ch->max_mana, ch->move, ch->max_move); fprintf(fp, "Gold %d\n", ch->gold); fprintf(fp, "Bank %d\n", ch->bank); fprintf(fp, "Exp %d\n", ch->exp); fprintf(fp, "Tneed %d\n", ch->total_need); fprintf(fp, "Recalls %d\n", ch->needed); fprintf(fp, "Act %d\n", ch->act); fprintf(fp, "AffdBy %d\n", ch->affected_by); /* Bug fix from Alander */ fprintf(fp, "Pos %d\n", ch->position == POS_FIGHTING ? POS_STANDING : ch->position); fprintf(fp, "Prac %d\n", ch->practice); fprintf(fp, "SavThr %d\n", ch->saving_throw); fprintf(fp, "SavThrEvil %d\n", ch->saving_throw_evil); fprintf(fp, "SavThrBrea %d\n", ch->saving_throw_breath); fprintf(fp, "SavThrElem %d\n", ch->saving_throw_elemental); fprintf(fp, "SavThrFire %d\n", ch->saving_throw_fire); fprintf(fp, "Align %d\n", ch->alignment); fprintf(fp, "Hit %d\n", ch->hitroll); fprintf(fp, "Dam %d\n", ch->damroll); fprintf(fp, "Armr %d\n", ch->armor); fprintf(fp, "Wimp %d\n", ch->wimpy); fprintf(fp, "Deaf %d\n", ch->deaf); if (IS_NPC(ch)) { fprintf(fp, "Vnum %d\n", ch->pIndexData->vnum); } else { fprintf(fp, "Paswd %s~\n", ch->pcdata->pwd); fprintf(fp, "Bmfin %s~\n", ch->pcdata->bamfin); fprintf(fp, "Bmfout %s~\n", ch->pcdata->bamfout); fprintf(fp, "Ttle %s~\n", ch->pcdata->title); fprintf(fp, "PreTtle %s~\n", ch->pcdata->pretitle); fprintf(fp, "AtrPrm %d %d %d %d %d\n", ch->pcdata->perm_str, ch->pcdata->perm_int, ch->pcdata->perm_wis, ch->pcdata->perm_dex, ch->pcdata->perm_con); fprintf(fp, "AtrMd %d %d %d %d %d\n", ch->pcdata->mod_str, ch->pcdata->mod_int, ch->pcdata->mod_wis, ch->pcdata->mod_dex, ch->pcdata->mod_con); fprintf(fp, "AtrMult %d %d %d %d %d\n", get_curr_force(ch), get_curr_intui(ch), get_curr_luck(ch), get_curr_speed(ch), get_curr_resil(ch)); fprintf(fp, "Cond %d %d %d\n", ch->pcdata->condition[0], ch->pcdata->condition[1], ch->pcdata->condition[2]); fprintf(fp, "Pglen %d\n", ch->pcdata->pagelen); for (sn = 0; sn < MAX_SKILL; sn++) { if (skill_table[sn].name && ch->pcdata->learned[sn] > 0) { fprintf(fp, "Skll %d '%s'\n", ch->pcdata->learned[sn], skill_table[sn].name); } } } for (paf = ch->affected; paf; paf = paf->next) { if (paf->deleted) continue; fprintf(fp, "Aff %3d %3d %3d %3d %10d\n", paf->type, paf->duration, paf->modifier, paf->location, paf->bitvector); } 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) { AFFECT_DATA *paf; EXTRA_DESCR_DATA *ed; /* * Slick recursion to write lists backwards, * so loading them will load in forwards order. */ if (obj->next_content) fwrite_obj(ch, obj->next_content, fp, iNest); /* * Castrate storage characters. */ if (ch->level + 12 < obj->level || obj->item_type == ITEM_KEY || obj->item_type == ITEM_FOOD || IS_SET(obj->extra_flags, ITEM_NOSAVE) || obj->deleted) return; fprintf(fp, "#NEWOBJECT\n"); fprintf(fp, "Nest %d\n", iNest); fprintf(fp, "Name %s~\n", obj->name); fprintf(fp, "ShortDescr %s~\n", obj->short_descr); fprintf(fp, "Description %s~\n", obj->description); fprintf(fp, "Vnum %d\n", obj->pIndexData->vnum); fprintf(fp, "ExtraFlags %d\n", obj->extra_flags); fprintf(fp, "WearFlags %d\n", obj->wear_flags); fprintf(fp, "WearLoc %d\n", obj->wear_loc); fprintf(fp, "ItemType %d\n", obj->item_type); fprintf(fp, "Weight %d\n", obj->weight); fprintf(fp, "Level %d\n", obj->level); fprintf(fp, "Timer %d\n", obj->timer); fprintf(fp, "Cost %d\n", obj->cost); fprintf(fp, "Values %d %d %d %d\n", obj->value[0], obj->value[1], obj->value[2], obj->value[3]); switch (obj->item_type) { case ITEM_POTION: case ITEM_SCROLL: 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_PILL: 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; paf = paf->next) { fprintf(fp, "Affect %d %d %d %d %d\n", paf->type, paf->duration, paf->modifier, paf->location, paf->bitvector); } for (ed = obj->extra_descr; ed; ed = ed->next) { fprintf(fp, "ExtraDescr %s~ %s~\n", ed->keyword, ed->description); } fprintf(fp, "End\n\n"); if (obj->contains) fwrite_obj(ch, obj->contains, fp, iNest + 1); tail_chain(); return; } /* * Load a char and inventory into a new ch structure. */ UBYTE load_char_obj(DESCRIPTOR_DATA *d, char *name) { FILE *fp; static PC_DATA pcdata_zero; CHAR_DATA *ch; char buf[MAX_STRING_LENGTH]; char strsave[MAX_INPUT_LENGTH]; UBYTE found; if (!char_free) { ch = alloc_perm(sizeof(*ch)); } else { ch = char_free; char_free = char_free->next; } clear_char(ch); if (!pcdata_free) { ch->pcdata = alloc_perm(sizeof(*ch->pcdata)); } else { ch->pcdata = pcdata_free; pcdata_free = pcdata_free->next; } *ch->pcdata = pcdata_zero; d->character = ch; ch->desc = d; ch->name = str_dup(name); ch->prompt = str_dup("<%hhp %mm %vmv> "); ch->last_note = 0; ch->eviscerated = 0; ch->gold = 0; ch->bank = 0; ch->mypet = 0; ch->act = PLR_BLANK | PLR_COMBINE | PLR_PROMPT; ch->pcdata->pwd = str_dup(""); ch->pcdata->bamfin = str_dup(""); ch->pcdata->bamfout = str_dup(""); ch->pcdata->title = str_dup(""); ch->pcdata->pretitle = str_dup(""); ch->pcdata->perm_str = 13; ch->pcdata->perm_int = 13; ch->pcdata->perm_wis = 13; ch->pcdata->perm_dex = 13; ch->pcdata->perm_con = 13; ch->pcdata->condition[COND_THIRST] = 48; ch->pcdata->condition[COND_FULL] = 48; ch->pcdata->pagelen = 20; ch->pcdata->switched = FALSE; found = FALSE; fclose(fpReserve); /* parsed player file directories by Yaz of 4th Realm */ /* decompress if .gz file exists - Thx Alander */ sprintf(strsave, "%s%s/%s.gz", PLAYER_DIR, initial(ch->name), capitalize(name)); if ((fp = fopen(strsave, "r"))) { fclose(fp); sprintf(buf, "gzip -dfq %s", strsave); system(buf); } sprintf(strsave, "%s%s/%s", PLAYER_DIR, initial(ch->name), capitalize(name)); if ((fp = fopen(strsave, "r"))) { int iNest; for (iNest = 0; iNest < MAX_NEST; iNest++) rgObjNest[iNest] = NULL; found = TRUE; for (;;) { char letter; char *word; letter = fread_letter(fp); if (letter == '*') { fread_to_eol(fp); continue; } if (letter != '#') { bug("# not found."); break; } word = fread_word(fp); if (!str_cmp(word, "PLAYER")) fread_char(ch, fp); else if (!str_cmp(word, "NEWOBJECT")) fread_obj(ch, fp); else if (!str_cmp(word, "END")) break; else { bug("bad section."); break; } } fclose(fp); } fpReserve = fopen(NULL_FILE, "r"); return found; } /* * Read in a char. */ #if defined( KEY ) #undef KEY #endif #define KEY( literal, field, value ) \ if ( !str_cmp( word, literal ) ) \ { \ field = value; \ fMatch = TRUE; \ break; \ } void fread_char(CHAR_DATA *ch, FILE * fp) { char *word; char buf[MAX_STRING_LENGTH]; UBYTE fMatch; for (;;) { word = feof(fp) ? "End" : fread_word(fp); fMatch = FALSE; switch (toupper(word[0])) { case '*': fMatch = TRUE; fread_to_eol(fp); break; case 'A': KEY("Act", ch->act, fread_number(fp)); KEY("AffdBy", ch->affected_by, fread_number(fp)); KEY("Align", ch->alignment, fread_number(fp)); KEY("Armr", ch->armor, fread_number(fp)); if (!str_cmp(word, "Aff")) { AFFECT_DATA *paf; if (!affect_free) { paf = alloc_perm(sizeof(*paf)); } else { paf = affect_free; affect_free = affect_free->next; } paf->type = fread_number(fp); paf->duration = fread_number(fp); paf->modifier = fread_number(fp); paf->location = fread_number(fp); paf->bitvector = fread_number(fp); paf->deleted = FALSE; paf->next = ch->affected; ch->affected = paf; fMatch = TRUE; break; } if (!str_cmp(word, "AtrMd")) { ch->pcdata->mod_str = fread_number(fp); ch->pcdata->mod_int = fread_number(fp); ch->pcdata->mod_wis = fread_number(fp); ch->pcdata->mod_dex = fread_number(fp); ch->pcdata->mod_con = fread_number(fp); fMatch = TRUE; break; } if (!str_cmp(word, "AtrPrm")) { ch->pcdata->perm_str = fread_number(fp); ch->pcdata->perm_int = fread_number(fp); ch->pcdata->perm_wis = fread_number(fp); ch->pcdata->perm_dex = fread_number(fp); ch->pcdata->perm_con = fread_number(fp); fMatch = TRUE; break; } if (!str_cmp(word, "AtrMult")) { ch->pcdata->mult_str = fread_number(fp); ch->pcdata->mult_int = fread_number(fp); ch->pcdata->mult_wis = fread_number(fp); ch->pcdata->mult_dex = fread_number(fp); ch->pcdata->mult_con = fread_number(fp); fMatch = TRUE; break; } break; case 'B': KEY("Bmfin", ch->pcdata->bamfin, fread_string(fp)); KEY("Bmfout", ch->pcdata->bamfout, fread_string(fp)); KEY("Bank", ch->bank, fread_number(fp)); break; case 'C': KEY("Clan", ch->clan, fread_number(fp)); KEY("Clanrank", ch->clanrank, fread_number(fp)); KEY("Clanname", ch->clanname, fread_string(fp)); KEY("Cla", ch->class, fread_number(fp)); if (!str_cmp(word, "Cond")) { ch->pcdata->condition[0] = fread_number(fp); ch->pcdata->condition[1] = fread_number(fp); ch->pcdata->condition[2] = fread_number(fp); fMatch = TRUE; break; } break; case 'D': KEY("Dam", ch->damroll, fread_number(fp)); KEY("Deaf", ch->deaf, fread_number(fp)); KEY("Dscr", ch->description, fread_string(fp)); KEY("Dual", ch->dual, fread_number(fp)); break; case 'E': if (!str_cmp(word, "End")) return; KEY("Exp", ch->exp, fread_number(fp)); KEY("Eviscerated", ch->eviscerated, fread_number(fp)); break; case 'G': KEY("Gold", ch->gold, fread_number(fp)); break; case 'H': KEY("Hit", ch->hitroll, fread_number(fp)); KEY("Home", ch->home_room, fread_number(fp)); if (!str_cmp(word, "Host")) { fread_to_eol(fp); fMatch = TRUE; break; } if (!str_cmp(word, "HpMnMv")) { 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("Invited", ch->invited, fread_number(fp)); break; case 'L': KEY("Lvl", ch->level, fread_number(fp)); KEY("LngDsc", ch->long_descr, fread_string(fp)); break; case 'N': if (!str_cmp(word, "Nm")) { /* * Name already set externally. */ fread_to_eol(fp); fMatch = TRUE; break; } KEY("Need", ch->needed, fread_number(fp)); KEY("Note", ch->last_note, fread_number(fp)); break; case 'P': KEY("Pglen", ch->pcdata->pagelen, fread_number(fp)); KEY("Paswd", ch->pcdata->pwd, fread_string(fp)); KEY("Playd", ch->played, fread_number(fp)); KEY("Pos", ch->position, fread_number(fp)); KEY("Prac", ch->practice, fread_number(fp)); KEY("Prmpt", ch->prompt, fread_string(fp)); KEY("PreTtle", ch->pcdata->pretitle, fread_string(fp)); KEY("Pet", ch->mypet, fread_number(fp)); KEY("Petsname", ch->pets_name, fread_string(fp)); break; case 'Q': KEY("Quest", ch->quest, fread_number(fp)); KEY("Qstact", ch->questact, fread_number(fp)); break; case 'R': KEY("Rce", ch->race, fread_number(fp)); KEY("Recalls", ch->needed, fread_number(fp)); if (!str_cmp(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; } break; case 'S': KEY("SavThr", ch->saving_throw, fread_number(fp)); KEY("SavThrEvil", ch->saving_throw_evil, fread_number(fp)); KEY("SavThrBrea", ch->saving_throw_breath, fread_number(fp)); KEY("SavThrElem", ch->saving_throw_elemental, fread_number(fp)); KEY("SavThrFire", ch->saving_throw_fire, fread_number(fp)); KEY("Sect", ch->sect, fread_number(fp)); KEY("Sx", ch->sex, fread_number(fp)); KEY("ShtDsc", ch->short_descr, fread_string(fp)); KEY("Security", ch->pcdata->security, fread_number(fp)); /* OLC */ if (!str_cmp(word, "Skll")) { int sn; int value; value = fread_number(fp); sn = skill_lookup(fread_word(fp)); if(sn < 0) { bug("unknown skill."); fMatch = FALSE; } else { ch->pcdata->learned[sn] = value; fMatch = TRUE; } } break; case 'T': KEY("Tneed", ch->total_need, fread_number(fp)); KEY("Trst", ch->trust, fread_number(fp)); if (!str_cmp(word, "Ttle")) { ch->pcdata->title = fread_string(fp); if (isalpha(ch->pcdata->title[0]) || isdigit(ch->pcdata->title[0])) { sprintf(buf, " %s", ch->pcdata->title); free_string(ch->pcdata->title); ch->pcdata->title = str_dup(buf); } fMatch = TRUE; break; } break; case 'V': if (!str_cmp(word, "Vnum")) { ch->pIndexData = get_mob_index(fread_number(fp)); fMatch = TRUE; break; } break; case 'W': KEY("Wimp", ch->wimpy, fread_number(fp)); KEY("Wizbt", ch->wizbit, fread_number(fp)); break; } /* Make sure old chars have this field - Kahn */ if (!ch->pcdata->pagelen) ch->pcdata->pagelen = 20; if (!ch->prompt || ch->prompt == '\0') ch->prompt = str_dup("<%hhp %mm %vmv> "); /* Make sure old chars do not have pagelen > 60 - Kahn */ if (ch->pcdata->pagelen > 60) ch->pcdata->pagelen = 60; if (!fMatch) { sprintf(buf, "no match on: %s\n\r", word); bug(buf); fread_to_eol(fp); } } } void fread_obj(CHAR_DATA *ch, FILE * fp) { static OBJ_DATA obj_zero; OBJ_DATA *obj; char *word; int iNest; UBYTE fMatch; UBYTE fNest; UBYTE fVnum; if (!obj_free) { obj = alloc_perm(sizeof(*obj)); } else { obj = obj_free; obj_free = obj_free->next; } *obj = obj_zero; obj->name = str_dup(""); obj->short_descr = str_dup(""); obj->description = str_dup(""); obj->deleted = FALSE; fNest = FALSE; fVnum = TRUE; iNest = 0; for (;;) { word = feof(fp) ? "End" : fread_word(fp); fMatch = FALSE; switch (toupper(word[0])) { case '*': fMatch = TRUE; fread_to_eol(fp); break; case 'A': if (!str_cmp(word, "Affect")) { AFFECT_DATA *paf; if (!affect_free) { paf = alloc_perm(sizeof(*paf)); } else { paf = affect_free; affect_free = affect_free->next; } paf->type = fread_number(fp); paf->duration = fread_number(fp); paf->modifier = fread_number(fp); paf->location = fread_number(fp); paf->bitvector = fread_number(fp); paf->next = obj->affected; obj->affected = paf; fMatch = TRUE; break; } break; case 'C': KEY("Cost", obj->cost, fread_number(fp)); break; case 'D': KEY("Description", obj->description, fread_string(fp)); break; case 'E': KEY("ExtraFlags", obj->extra_flags, fread_number(fp)); if (!str_cmp(word, "ExtraDescr")) { EXTRA_DESCR_DATA *ed; if (!extra_descr_free) { ed = alloc_perm(sizeof(*ed)); } else { ed = extra_descr_free; extra_descr_free = extra_descr_free->next; } ed->keyword = fread_string(fp); ed->description = fread_string(fp); ed->next = obj->extra_descr; obj->extra_descr = ed; fMatch = TRUE; } if (!str_cmp(word, "End")) { if (!fNest || !fVnum) { bug("incomplete object."); free_string(obj->name); free_string(obj->description); free_string(obj->short_descr); obj->next = obj_free; obj_free = obj; return; } else { obj->next = object_list; object_list = obj; obj->pIndexData->count++; if (iNest == 0 || !rgObjNest[iNest]) obj_to_char(obj, ch); else obj_to_obj(obj, rgObjNest[iNest - 1]); 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 (!str_cmp(word, "Nest")) { iNest = fread_number(fp); if (iNest < 0 || iNest >= MAX_NEST) { bug("bad nest %d.", iNest); } else { rgObjNest[iNest] = obj; fNest = TRUE; } fMatch = TRUE; } break; case 'S': KEY("ShortDescr", obj->short_descr, fread_string(fp)); if (!str_cmp(word, "Spell")) { int iValue; int sn; iValue = fread_number(fp); sn = skill_lookup(fread_word(fp)); if (iValue < 0 || iValue > 3) { bug("bad iValue %d.", iValue); } else if (sn < 0) { bug("unknown skill."); } else { obj->value[iValue] = sn; } fMatch = TRUE; break; } break; case 'T': KEY("Timer", obj->timer, fread_number(fp)); break; case 'V': if (!str_cmp(word, "Values")) { obj->value[0] = fread_number(fp); obj->value[1] = fread_number(fp); obj->value[2] = fread_number(fp); obj->value[3] = fread_number(fp); fMatch = TRUE; break; } if (!str_cmp(word, "Vnum")) { int vnum; vnum = fread_number(fp); if (!(obj->pIndexData = get_obj_index(vnum))) { bug("bad vnum %d.", vnum); fVnum = FALSE; fMatch = FALSE; } else { fVnum = TRUE; fMatch = TRUE; obj->spec_fun = obj->pIndexData->spec_fun; } 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) { bug("no match."); fread_to_eol(fp); } } }