/************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefiting. We hope that you share your changes too. What goes * * around, comes around. * *************************************************************************** * ROM 2.4 is copyright 1993-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * *************************************************************************** * 1stMud ROM Derivative (c) 2001-2004 by Markanth * * http://www.firstmud.com/ <markanth@firstmud.com> * * By using this code you have agreed to follow the term of * * the 1stMud license in ../doc/1stMud/LICENSE * ***************************************************************************/ #include "merc.h" #include "recycle.h" #include "tables.h" #include "interp.h" #include "vnums.h" static ObjData *rgObjNest[MAX_NEST]; Proto(void write_char, (CharData *, FileData *)); Proto(void write_pet, (CharData *, FileData *)); Proto(void read_pet, (CharData *, FileData *)); Proto(void read_descriptor, (Descriptor *, FileData *)); Proto(void write_descriptor, (Descriptor *, FileData *)); #define TAB_SIZE 8 char *format_tabs(int len) { if (len < TAB_SIZE) return "\t\t\t"; else if (len < TAB_SIZE * 2) return "\t\t"; else if (len < TAB_SIZE * 3) return "\t"; else return FORMATF("%*s", Max(1, len - (TAB_SIZE)), " "); } const char *pfile_filename(const char *name) { static int i; static char rbuf[5][MSL]; char buf[MSL], first_name[MSL]; ++i, i %= 5; strcpy(buf, name); one_argument(buf, first_name); sprintf(rbuf[i], "%s.plr", first_name); return (rbuf[i]); } char *pfilename(const char *name, pfile_t type) { static int i; static char rbuf[5][MSL]; char filename[MSL]; ++i, i %= 5; strcpy(filename, pfile_filename(name)); switch (type) { case PFILE_NORMAL: #ifndef INITIAL_ALPHA_PFILEDIRS sprintf(rbuf[i], PLAYER_DIR "%s", filename); #else sprintf(rbuf[i], PLAYER_DIR "%c" DIR_SYM "%s", filename[0], filename); #endif break; case PFILE_BACKUP: #ifndef INITIAL_ALPHA_PFILEDIRS sprintf(rbuf[i], PLAYER_BACKUP "%s", filename); #else sprintf(rbuf[i], PLAYER_BACKUP "%c" DIR_SYM "%s", filename[0], filename); #endif break; case PFILE_DELETED: sprintf(rbuf[i], DELETE_DIR "%s", filename); break; default: sprintf(rbuf[i], "ERROR_PFILENAME_%s_INCORRECT_TYPE_%d", filename, (int) type); bugf("ERROR_PFILENAME_INCORRECT_TYPE %d - %s", (int) type, filename); break; } return (rbuf[i]); } bool save_char_obj_to_filename(CharData * ch, const char *filename) { FileData *fp; if ((fp = f_open(filename, "w")) == NULL) { bugf("Save_char_obj: file open on %s", ch->name); log_error(filename); return false; } else { write_char(ch, fp); if (ch->carrying_first != NULL) write_obj(ch, ch->carrying_last, fp, 0, 0, SAVE_CHAR); if (ch->pet != NULL && ch->pet->in_room == ch->in_room) { write_pet(ch->pet, fp); write_obj(ch->pet, ch->pet->carrying_last, fp, 0, 0, SAVE_PET); } if (ch->desc && (crs_info.status == CRS_COPYOVER || crash_info.crashed)) write_descriptor(ch->desc, fp); f_printf(fp, "#%s" LF, END_MARK); f_close(fp); return true; } } void save_char_obj(CharData * ch) { if (IsNPC(ch)) return; if (ch->desc != NULL && ch->desc->original != NULL) ch = ch->desc->original; if (get_trust(ch) < mud_info.min_save_lvl) return; save_char_obj_to_filename(ch, pfilename(ch->name, PFILE_NORMAL)); return; } void backup_char_obj(CharData * ch) { char buf[MIL]; if (IsNPC(ch)) return; if (ch->desc != NULL && ch->desc->original != NULL) ch = ch->desc->original; if (get_trust(ch) < mud_info.min_save_lvl * 3) return; strcpy(buf, pfilename(ch->name, PFILE_BACKUP)); if (save_char_obj_to_filename(ch, buf)) { ch->pcdata->backup = ch->pcdata->played; #ifdef unix system(FORMATF("gzip -fq %s", buf)); #endif } return; } void write_char(CharData * ch, FileData * fp) { AffectData *paf; NameList *nl; int sn, gn, pos; int i, j; f_printf(fp, "#%s" LF, get_char_save_header(IsNPC(ch) ? SAVE_MOB : SAVE_CHAR)); write_string(fp, "Name", ch->name, NULL); write_int(fp, "Id", "%ld", ch->id, 0); write_time(fp, "LogO", current_time, false); write_int(fp, "Vers", "%d", PFILE_VERSION, 0); write_string(fp, "ShD", ch->short_descr, NULL); write_string(fp, "LnD", ch->long_descr, NULL); write_string(fp, "Desc", ch->description, NULL); write_string(fp, "Prom", ch->prompt, NULL); write_string(fp, "GProm", ch->gprompt, NULL); write_string(fp, "Race", ch->race->name, NULL); if (CharClan(ch) != NULL) { write_string(fp, "Clan", CharClan(ch)->name, NULL); write_int(fp, "Rank", "%d", ch->rank, -1); } write_int(fp, "Sex", "%d", ch->sex, -1); write_array(fp, "Cla", "%d", ch->Class, MAX_MCLASS); write_int(fp, "PrClass", "%d", ch->pcdata->prime_class, 0); if (ch->pcdata->stay_race) f_printf(fp, "StayRace" LF); write_int(fp, "Levl", "%d", ch->level, 0); write_int(fp, "Tru", "%d", ch->trust, 0); write_int(fp, "Sec", "%d", ch->pcdata->security, 0); write_int(fp, "Plyd", "%d", ch->pcdata->played + (int) (current_time - ch->logon), 0); write_int(fp, "Scro", "%d", ch->lines, -1); write_int(fp, "Cols", "%d", ch->columns, -1); write_int(fp, "Room", "%ld", (ch->in_room == get_room_index(ROOM_VNUM_LIMBO) && ch->was_in_room != NULL) ? ch->was_in_room->vnum : ch->in_room == NULL ? 3001 : ch->in_room->vnum, 0); f_writef(fp, "HMV", "%ld %ld %ld %ld %ld %ld" LF, ch->hit, ch->max_hit, ch->mana, ch->max_mana, ch->move, ch->max_move); write_int(fp, "Gold", "%ld", ch->gold, 0); write_int(fp, "Silv", "%ld", ch->silver, 0); write_int(fp, "Exp", "%d", ch->exp, 0); write_bit(fp, "Act", ch->act, 0); write_bit(fp, "AfBy", ch->affected_by, 0); write_bit(fp, "Comm", ch->comm, 0); write_bit(fp, "Wizn", ch->wiznet, 0); write_int(fp, "Invi", "%d", ch->invis_level, 0); write_int(fp, "Inco", "%d", ch->incog_level, 0); write_int(fp, "Pos", "%d", ch->position == POS_FIGHTING ? POS_STANDING : ch->position, -1); write_int(fp, "Prac", "%d", ch->practice, 0); write_int(fp, "Trai", "%d", ch->train, 0); write_int(fp, "Save", "%d", ch->saving_throw, 0); write_int(fp, "Alig", "%d", ch->alignment, 0); write_int(fp, "Hit", "%d", ch->hitroll, 0); write_int(fp, "Dam", "%d", ch->damroll, 0); write_array(fp, "ACs", "%d", ch->armor, MAX_AC); write_array(fp, "Stance", "%d", ch->stance, MAX_STANCE); write_int(fp, "Wimp", "%d", ch->wimpy, 0); write_array(fp, "Attr", "%d", ch->perm_stat, STAT_MAX); write_array(fp, "AMod", "%d", ch->mod_stat, STAT_MAX); if (IsNPC(ch)) { write_int(fp, "Vnum", "%ld", ch->pIndexData->vnum, 0); } else { write_string(fp, "Pass", ch->pcdata->pwd, NULL); write_string(fp, "Bin", ch->pcdata->bamfin, NULL); write_string(fp, "Bout", ch->pcdata->bamfout, NULL); write_string(fp, "Titl", ch->pcdata->title, NULL); write_int(fp, "Pnts", "%d", ch->pcdata->points, 0); write_int(fp, "TSex", "%d", ch->pcdata->true_sex, -1); write_int(fp, "LLev", "%d", ch->pcdata->last_level, 0); f_writef(fp, "HMVP", "%ld %ld %ld" LF, ch->pcdata->perm_hit, ch->pcdata->perm_mana, ch->pcdata->perm_move); write_array(fp, "Cnd", "%d", ch->pcdata->condition, 4); write_int(fp, "QuestPnts", "%d", ch->pcdata->quest.points, 0); write_int(fp, "QuestTime", "%d", ch->pcdata->quest.time, 0); if (ch->pcdata->quest.giver) write_int(fp, "QuestGiver", "%ld", ch->pcdata->quest.giver->pIndexData->vnum, 0); if (ch->pcdata->quest.room) write_int(fp, "QuestLoc", "%ld", ch->pcdata->quest.room->vnum, 0); if (ch->pcdata->quest.obj) write_int(fp, "QuestObj", "%ld", ch->pcdata->quest.obj->pIndexData->vnum, 0); if (ch->pcdata->quest.mob) write_int(fp, "QuestMob", "%ld", ch->pcdata->quest.mob->pIndexData->vnum, 0); write_int(fp, "Trivia", "%d", ch->pcdata->trivia, 0); if (ch->pcdata->str_ed_key != '.' && ch->pcdata->str_ed_key != ' ') f_writef(fp, "StrEdKey", "%c" LF, ch->pcdata->str_ed_key); write_int(fp, "TimeZone", "%d", ch->pcdata->timezone, -1); write_int(fp, "AWins", "%d", ch->pcdata->awins, 0); write_int(fp, "ALosses", "%d", ch->pcdata->alosses, 0); write_int(fp, "BankG", "%ld", ch->pcdata->gold_bank, 0); write_int(fp, "Shares", "%d", ch->pcdata->shares, 0); if (ch->deity != NULL) write_string(fp, "Deity", ch->deity->name, NULL); if (Gquester(ch)) { write_array(fp, "GQmobs", "%ld", ch->gquest->gq_mobs, gquest_info.mob_count); } if (war_info.status != WAR_OFF && ch->war != NULL) { f_writef(fp, "WarInfo", "%ld %ld %ld %s" LF, ch->war->hit, ch->war->mana, ch->war->move, write_flags(ch->war->flags)); } if (HAS_HOME(ch)) { write_array(fp, "Homes", "%ld", ch->pcdata->home, MAX_HOME_VNUMS); } if (ch->color_prefix && ch->color_prefix != COLORCODE) { f_writef(fp, "CPref", "%c", ch->color_prefix); } f_writef(fp, "Colo", "%d", MAX_CUSTOM_COLOR); for (i = 0; i < MAX_CUSTOM_COLOR; i++) for (j = 0; j < CT_MAX; j++) f_printf(fp, " %d", ch->pcdata->colors[i][j]); f_printf(fp, LF); write_string(fp, "CTemplate", ch->pcdata->color_scheme->name, NULL); write_string(fp, "Pretit", ch->pcdata->pretit, NULL); write_string(fp, "WhoD", ch->pcdata->who_descr, NULL); write_array(fp, "GStats", "%ld", ch->pcdata->gamestat, MAX_GAMESTAT); write_bit(fp, "Vt100", ch->pcdata->vt100, 0); for (pos = 0; pos < MAX_ALIAS; pos++) { if (NullStr(ch->pcdata->alias[pos]) || NullStr(ch->pcdata->alias_sub[pos])) break; f_writef(fp, "Alias", "%s %s~" LF, ch->pcdata->alias[pos], ch->pcdata->alias_sub[pos]); } for (pos = 0; pos < MAX_BUDDY; pos++) { if (NullStr(ch->pcdata->buddies[pos])) break; write_string(fp, "Buddy", ch->pcdata->buddies[pos], NULL); } for (pos = 0; pos < MAX_IGNORE; pos++) { if (NullStr(ch->pcdata->ignore[pos])) break; f_writef(fp, "Ignore", "%s~ %s" LF, ch->pcdata->ignore[pos], write_flags(ch->pcdata->ignore_flags[pos])); } for (nl = ch->pcdata->killer_first; nl != NULL; nl = nl->next) write_word(fp, "Kller", nl->name, NULL); f_writef(fp, "Boards", "%d", MAX_BOARD); for (i = 0; i < MAX_BOARD; i++) f_printf(fp, " %s " TIME_T_FMT, boards[i].short_name, ch->pcdata->last_note[i]); f_printf(fp, LF); f_writef(fp, "Subscribe", "%d", MAX_BOARD); for (i = 0; i < MAX_BOARD; i++) f_printf(fp, " %s %d", boards[i].short_name, ch->pcdata->unsubscribed[i]); f_printf(fp, LF); write_array(fp, "Timers", "%ld", ch->pcdata->timers, MAX_TIMER); for (sn = 0; sn < top_skill; sn++) { if (skill_table[sn].name != NULL && ch->pcdata->learned[sn] > 0) { f_writef(fp, "Sk", "%d '%s'" LF, ch->pcdata->learned[sn], skill_table[sn].name); } } for (gn = 0; gn < top_group; gn++) { if (group_table[gn].name != NULL && ch->pcdata->group_known[gn]) { f_writef(fp, "Gr", "'%s'" LF, group_table[gn].name); } } } for (paf = ch->affect_first; paf != NULL; paf = paf->next) { if (paf->type < 0 || paf->type >= top_skill) continue; f_writef(fp, "Affc", "'%s' %3d %3d %3d %3d %3d %s" LF, skill_table[paf->type].name, paf->where, paf->level, paf->duration, paf->modifier, paf->location, write_flags(paf->bitvector)); } write_rle(ch->pcdata->explored, fp); #ifndef DISABLE_I3 i3save_char(ch, fp); #endif f_printf(fp, END_MARK LF); return; } void write_pet(CharData * pet, FileData * fp) { AffectData *paf; f_printf(fp, "#%s" LF, get_char_save_header(SAVE_PET)); write_int(fp, "Vnum", "%ld", pet->pIndexData->vnum, 0); write_string(fp, "Name", pet->name, NULL); write_time(fp, "LogO", current_time, false); write_string(fp, "ShD", pet->short_descr, pet->pIndexData->short_descr); write_string(fp, "LnD", pet->long_descr, pet->pIndexData->long_descr); write_string(fp, "Desc", pet->description, pet->pIndexData->description); if (pet->race != pet->pIndexData->race) write_string(fp, "Race", pet->race->name, NULL); write_int(fp, "Sex", "%d", pet->sex, -1); write_int(fp, "Levl", "%d", pet->level, pet->pIndexData->level); f_writef(fp, "HMV", "%ld %ld %ld %ld %ld %ld" LF, pet->hit, pet->max_hit, pet->mana, pet->max_mana, pet->move, pet->max_move); write_int(fp, "Gold", "%ld", pet->gold, 0); write_int(fp, "Silv", "%ld", pet->silver, 0); write_int(fp, "Exp", "%d", pet->exp, 0); write_bit(fp, "Act", pet->act, pet->pIndexData->act); write_bit(fp, "AfBy", pet->affected_by, pet->pIndexData->affected_by); write_bit(fp, "Comm", pet->comm, 0); write_int(fp, "Pos", "%d", pet->position = POS_FIGHTING ? POS_STANDING : pet->position, -1); write_int(fp, "Save", "%d", pet->saving_throw, 0); write_int(fp, "Alig", "%d", pet->alignment, pet->pIndexData->alignment); write_int(fp, "Hit", "%d", pet->hitroll, pet->pIndexData->hitroll); write_int(fp, "Dam", "%d", pet->damroll, pet->pIndexData->damage[DICE_BONUS]); write_array(fp, "ACs", "%d", pet->armor, MAX_AC); write_array(fp, "Attr", "%d", pet->perm_stat, STAT_MAX); write_array(fp, "AMod", "%d", pet->mod_stat, STAT_MAX); for (paf = pet->affect_first; paf != NULL; paf = paf->next) { if (paf->type < 0 || paf->type >= top_skill) continue; f_writef(fp, "Affc", "'%s' %3d %3d %3d %3d %3d %s" LF, skill_table[paf->type].name, paf->where, paf->level, paf->duration, paf->modifier, paf->location, write_flags(paf->bitvector)); } f_printf(fp, END_MARK LF); return; } char *get_obj_save_header(save_t type) { switch (type) { case SAVE_CHAR: return "OBJECT"; case SAVE_CORPSE: return "CORPSE"; case SAVE_ROOM: return "ROOMOBJ"; case SAVE_PET: return "PETOBJ"; default: bugf("Bad save type (%d)", type); return "OBJECT"; } } char *get_char_save_header(save_t type) { switch (type) { case SAVE_CHAR: return "PLAYER"; case SAVE_MOB: return "MOB"; case SAVE_PET: return "PET"; default: return "CHAR"; } } #define get_desc_save_header "DESC" void write_obj(CharData * ch, ObjData * obj, FileData * fp, int iNest, int iNext, save_t type) { ExDescrData *ed; AffectData *paf; vnum_t where = ROOM_VNUM_MORGUE; if (!obj) return; if (obj->prev_content != NULL) { if (obj->prev_content->in_room == NULL || (type == SAVE_ROOM && iNext < 35)) write_obj(ch, obj->prev_content, fp, iNest, iNext + 1, type); } if (type == SAVE_CORPSE || type == SAVE_ROOM) { if (obj->in_obj != NULL) where = 1; if (obj->in_room != NULL) where = obj->in_room->vnum; } if (ch && !IsObjStat(obj, ITEM_QUEST) && (type == SAVE_CHAR || type == SAVE_PET) && obj->prev_content == NULL) { if ((ch->level < obj->level - lvl_bonus(ch))) return; if ( (obj->item_type == ITEM_KEY && (IsNPC(ch) || obj->pIndexData->vnum != ch->pcdata->home_key)) || (obj->item_type == ITEM_MAP && !obj->value[0])) return; } f_printf(fp, "#%s" LF, get_obj_save_header(type)); write_int(fp, "Vnum", "%ld", obj->pIndexData->vnum, 0); if (type == SAVE_CORPSE || type == SAVE_ROOM) write_int(fp, "Where", "%ld", where, ROOM_VNUM_MORGUE); write_string(fp, "Owner", obj->owner, NULL); if (!obj->pIndexData->new_format) f_printf(fp, "Oldstyle" LF); if (obj->enchanted) f_printf(fp, "Enchanted" LF); write_int(fp, "Nest", "%d", iNest, -1); write_string(fp, "Name", obj->name, obj->pIndexData->name); write_string(fp, "ShD", obj->short_descr, obj->pIndexData->short_descr); write_string(fp, "Desc", obj->description, obj->pIndexData->description); write_bit(fp, "ExtF", obj->extra_flags, obj->pIndexData->extra_flags); write_bit(fp, "WeaF", obj->wear_flags, obj->pIndexData->wear_flags); write_int(fp, "Ityp", "%d", obj->item_type, obj->pIndexData->item_type); write_int(fp, "Wt", "%d", obj->weight, obj->pIndexData->weight); write_int(fp, "Cond", "%d", obj->condition, obj->pIndexData->condition); write_int(fp, "Wear", "%d", obj->wear_loc, WEAR_NONE); write_int(fp, "Lev", "%d", obj->level, obj->pIndexData->level); write_int(fp, "Time", "%d", obj->timer, 0); write_int(fp, "Cost", "%ld", obj->cost, 0); if (obj->enchanted || memcmp(obj->value, obj->pIndexData->value, sizeof(obj->value))) write_array(fp, "Valu", "%ld", obj->value, 5); switch (obj->item_type) { case ITEM_POTION: case ITEM_SCROLL: case ITEM_PILL: if (obj->value[1] > 0) { f_writef(fp, "Spell 1", "'%s'" LF, skill_table[obj->value[1]].name); } if (obj->value[2] > 0) { f_writef(fp, "Spell 2", "'%s'" LF, skill_table[obj->value[2]].name); } if (obj->value[3] > 0) { f_writef(fp, "Spell 3", "'%s'" LF, skill_table[obj->value[3]].name); } break; case ITEM_STAFF: case ITEM_WAND: if (obj->value[3] > 0) { f_writef(fp, "Spell 3", "'%s'" LF, skill_table[obj->value[3]].name); } break; default: break; } for (paf = obj->affect_first; paf != NULL; paf = paf->next) { if (paf->type < 0 || paf->type >= top_skill) continue; f_writef(fp, "Affc", "'%s' %3d %3d %3d %3d %3d %s" LF, skill_table[paf->type].name, paf->where, paf->level, paf->duration, paf->modifier, paf->location, write_flags(paf->bitvector)); } for (ed = obj->ed_first; ed != NULL; ed = ed->next) { f_writef(fp, "ExDe", "%s~ %s~" LF, ed->keyword, ed->description); } f_printf(fp, END_MARK LF); if (obj->content_last != NULL) write_obj(ch, obj->content_last, fp, iNest + 1, iNext, type); return; } void write_descriptor(Descriptor * d, FileData * fp) { f_printf(fp, "#%s" LF, get_desc_save_header); write_string(fp, "Host", d->host, NULL); write_int(fp, "Descr", "%d", d->descriptor, 0); write_int(fp, "Connected", "%d", d->connected, 0); write_int(fp, "IP", "%ld", d->ip, 0); write_int(fp, "Port", "%d", d->port, 0); write_bit(fp, "Flags", d->desc_flags, 0); write_int(fp, "ScrW", "%u", d->scr_width, 80); write_int(fp, "ScrH", "%u", d->scr_height, 24); write_int(fp, "ByteN", "%d", d->bytes_normal, 0); #ifndef DISABLE_MCCP write_int(fp, "ByteC", "%d", d->bytes_compressed, 0); write_int(fp, "CVersion", "%d", d->mccp_version, 0); #endif write_string(fp, "TType", d->ttype, NULL); if (IsMXP(d)) { write_string(fp, "MXPSup", d->mxp.supports, NULL); write_int(fp, "MXPVer", "%.2f", d->mxp.mxp_ver, 0); write_int(fp, "MXPClVer", "%.2f", d->mxp.client_ver, 0); write_int(fp, "MXPStyl", "%.2f", d->mxp.style_ver, 0); write_string(fp, "MXPClien", d->mxp.client, NULL); write_int(fp, "MXPReg", "%d", d->mxp.registered, 0); write_bit(fp, "MXPFlag1", d->mxp.flags, 0); write_bit(fp, "MXPFlag2", d->mxp.flags2, 0); } if (IsPortal(d)) { write_int(fp, "Keycode", "%u", d->portal.keycode, 0); write_string(fp, "PortVer", d->portal.version, NULL); } if (IsFireCl(d)) write_int(fp, "IMPver", "%.2f", d->imp_vers, 0); if (IsPueblo(d)) write_int(fp, "Pueblo", "%.2f", d->pueblo_vers, 0); f_printf(fp, END_MARK LF); return; } void set_player_level(CharData * ch, int Old, int New, int version) { int diff = MAX_LEVEL - LEVEL_IMMORTAL; int imm_level = Old - diff; int mod = New - Old; if (ch->version >= version) return; if (ch->level >= imm_level) ch->level += mod; if (ch->trust >= imm_level) ch->trust += mod; save_char_obj(ch); } void pload_default(CharData * ch) { int stat; ch->race = default_race; ch->act = PLR_NOSUMMON | PLR_AUTOMAP | PLR_AUTOEXIT | PLR_AUTODAMAGE | PLR_AUTOASSIST | PLR_AUTOGOLD | PLR_AUTOLOOT | PLR_AUTOSAC | PLR_AUTOSPLIT | PLR_AUTOPROMPT; ch->comm = COMM_COMBINE | COMM_PROMPT; ch->prompt = str_dup(DEFAULT_PROMPT); for (stat = 0; stat < STAT_MAX; stat++) ch->perm_stat[stat] = 13; ch->pcdata->security = 0; default_color(ch, _NONE); end_quest(ch, 0); #ifndef DISABLE_I3 i3init_char(ch); #endif } void pload_found(CharData * ch) { int i; if (ch->race == NULL) ch->race = default_race; ch->size = ch->race->size; ch->dam_type = 17; for (i = 0; i < MAX_RACE_SKILL; i++) { if (ch->race->skills[i] == NULL) break; group_add(ch, ch->race->skills[i], false); } ch->affected_by = ch->affected_by | ch->race->aff; ch->imm_flags = ch->imm_flags | ch->race->imm; ch->res_flags = ch->res_flags | ch->race->res; ch->vuln_flags = ch->vuln_flags | ch->race->vuln; ch->form = ch->race->form; ch->parts = ch->race->parts; set_player_level(ch, 0, 0, 0); ch->Class[CLASS_COUNT] = 0; while (ch->Class[ch->Class[CLASS_COUNT]] != -1) ch->Class[CLASS_COUNT] += 1; if (ch->version < 11) { ch->pcdata->home[PC_HOME_COUNT] = 0; while (get_room_index(ch->pcdata->home[PC_HOME_COUNT]) != NULL) ch->pcdata->home[PC_HOME_COUNT] += 1; } if (ch->version < 12) default_color(ch, _NONE); } bool load_char_obj(Descriptor * d, const char *name) { CharData *ch; static FileData *fp; static bool found; char buf[MIL]; ch = new_char(); ch->pcdata = new_pcdata(); d->character = ch; ch->desc = d; ch->name = str_dup(capitalize(name)); ch->id = get_pc_id(); pload_default(ch); found = false; sprintf(buf, "%s.gz", pfilename(name, PFILE_NORMAL)); #ifdef GZFILEIO if ((fp = f_open(buf, "rb")) == NULL) #else if ((fp = f_open(buf, "r")) != NULL) { f_close(fp); #ifdef unix system(FORMATF("gzip -dfq %s", buf)); #else bugf("File '%s' is compressed!", buf); AttemptJump = false; return found; #endif } #endif sprintf(buf, pfilename(name, PFILE_NORMAL)); if ((fp = f_open(buf, "r")) != NULL) { int iNest; AttemptJump = true; if (setjmp(jump_env) == 1) { size_t iLine, iChar; char c; iChar = f_tell(fp); f_seek(fp, 0, SEEK_SET); for (iLine = 0; (size_t) f_tell(fp) < iChar; iLine++) { while ((c = f_getc(fp)) != '\n' && c != EOF) ; } f_seek(fp, iChar, SEEK_SET); bugf("[*LCO*] Error in file '%s' line %d", capitalize(name), iLine); f_close(fp); return found; } for (iNest = 0; iNest < MAX_NEST; iNest++) rgObjNest[iNest] = NULL; found = true; for (;;) { char letter; char *word; letter = read_letter(fp); if (letter == '*') { read_to_eol(fp); continue; } if (letter != '#') { bugf("# not found. (%c)", letter); break; } word = read_word(fp); if (!str_cmp(word, get_char_save_header(SAVE_CHAR))) read_char(ch, fp); else if (!str_cmp(word, get_obj_save_header(SAVE_CHAR))) read_obj(ch, fp, SAVE_CHAR); else if (!str_cmp(word, get_char_save_header(SAVE_PET))) read_pet(ch, fp); else if (!str_cmp(word, get_obj_save_header(SAVE_PET))) read_obj(ch, fp, SAVE_PET); else if (!str_cmp(word, get_desc_save_header)) read_descriptor(d, fp); else if (!str_cmp(word, END_MARK)) break; else { bug("Load_char_obj: bad section."); break; } } f_close(fp); } AttemptJump = false; if (found) { pload_found(ch); } return found; } void read_char(CharData * ch, FileData * fp) { char buf[MAX_STRING_LENGTH]; const char *word; bool fMatch; int count = 0; int count2 = 0; int lastlogoff = current_time; int percent; int ignore = 0; logf("Loading %s.", ch->name); for (;;) { word = f_eof(fp) ? END_MARK : read_word(fp); fMatch = false; switch (toupper(word[0])) { case '*': fMatch = true; read_to_eol(fp); break; case 'A': Key("Act", ch->act, read_flag(fp)); Key("AffectedBy", ch->affected_by, read_flag(fp)); Key("AfBy", ch->affected_by, read_flag(fp)); Key("Alignment", ch->alignment, read_number(fp)); Key("Alig", ch->alignment, read_number(fp)); Key("AWins", ch->pcdata->awins, read_number(fp)); Key("ALosses", ch->pcdata->alosses, read_number(fp)); if (!str_cmp(word, "Alia")) { if (count >= MAX_ALIAS) { read_to_eol(fp); fMatch = true; break; } ch->pcdata->alias[count] = str_dup(read_word(fp)); ch->pcdata->alias_sub[count] = str_dup(read_word(fp)); count++; fMatch = true; break; } if (!str_cmp(word, "Alias")) { if (count >= MAX_ALIAS) { read_to_eol(fp); fMatch = true; break; } ch->pcdata->alias[count] = str_dup(read_word(fp)); ch->pcdata->alias_sub[count] = read_string(fp); count++; fMatch = true; break; } Key_Ignore("AC"); Key_Ignore("Armor"); if (!str_cmp(word, "ACs")) { if (ch->version < 9) { int i; for (i = 0; i < 4; i++) ch->armor[i] = read_number(fp); } else read_array(fp, ch->armor, MAX_AC, 100); fMatch = true; break; } if (!str_cmp(word, "AffD")) { AffectData *paf; int sn; paf = new_affect(); sn = skill_lookup(read_word(fp)); if (sn < 0) bug("read_char: unknown skill."); else paf->type = sn; paf->level = read_number(fp); paf->duration = read_number(fp); paf->modifier = read_number(fp); paf->location = read_enum(apply_t, fp); paf->bitvector = read_number(fp); Link(paf, ch->affect, next, prev); fMatch = true; break; } if (!str_cmp(word, "Affc")) { AffectData *paf; int sn; paf = new_affect(); sn = skill_lookup(read_word(fp)); if (sn < 0) bug("read_char: unknown skill."); else paf->type = sn; paf->where = read_enum(where_t, fp); paf->level = read_number(fp); paf->duration = read_number(fp); paf->modifier = read_number(fp); paf->location = read_enum(apply_t, fp); paf->bitvector = read_flag(fp); Link(paf, ch->affect, next, prev); fMatch = true; break; } if (!str_cmp(word, "AttrMod") || !str_cmp(word, "AMod")) { if (ch->version < 9) { int stat; for (stat = 0; stat < STAT_MAX; stat++) ch->mod_stat[stat] = read_number(fp); } else read_array(fp, ch->mod_stat, STAT_MAX, 3); fMatch = true; break; } if (!str_cmp(word, "AttrPerm") || !str_cmp(word, "Attr")) { if (ch->version < 9) { int stat; for (stat = 0; stat < STAT_MAX; stat++) ch->perm_stat[stat] = read_number(fp); } else read_array(fp, ch->perm_stat, STAT_MAX, 3); fMatch = true; break; } break; case 'B': Key_Str("Bamfin", ch->pcdata->bamfin); Key_Str("Bamfout", ch->pcdata->bamfout); Key_Str("Bin", ch->pcdata->bamfin); Key_Str("Bout", ch->pcdata->bamfout); Key("BankG", ch->pcdata->gold_bank, read_number(fp)); if (!str_cmp(word, "Buddy")) { if (count2 >= MAX_BUDDY) { read_to_eol(fp); fMatch = true; break; } ch->pcdata->buddies[count2] = read_string(fp); count2++; fMatch = true; break; } if (!str_cmp(word, "Boards")) { int i, num = read_number(fp); char *boardname; for (; num; num--) { boardname = read_word(fp); i = board_lookup(boardname); if (i == BOARD_NOTFOUND) { sprintf(buf, "read_char: %s had unknown board name: %s. Skipped.", ch->name, boardname); log_string(buf); read_number(fp); } else ch->pcdata->last_note[i] = read_number(fp); } fMatch = true; break; } break; case 'C': if (!str_cmp(word, "Cla") || !str_cmp(word, "Class")) { if (ch->version < 10) { int i, j; for (i = 0; i < MAX_MCLASS; i++) { ch->Class[i] = read_number(fp); if (ch->Class[i] == -1) break; } for (i = j = 0; i < MAX_MCLASS; i++) { if (ch->Class[i] < 0 || ch->Class[i] >= top_class) { ch->Class[i] = -1; j++; continue; } ch->Class[i - j] = ch->Class[i]; ch->Class[i - j + 1] = -1; } } else { read_array(fp, ch->Class, MAX_MCLASS, -1); } fMatch = true; break; } Key_SFun("Clan", ch->pcdata->clan, clan_lookup); if (!str_cmp(word, "Condition") || !str_cmp(word, "Cond")) { ch->pcdata->condition[0] = read_number(fp); ch->pcdata->condition[1] = read_number(fp); ch->pcdata->condition[2] = read_number(fp); fMatch = true; break; } if (!str_cmp(word, "Cnd")) { if (ch->version < 9) { ch->pcdata->condition[0] = read_number(fp); ch->pcdata->condition[1] = read_number(fp); ch->pcdata->condition[2] = read_number(fp); ch->pcdata->condition[3] = read_number(fp); } else read_array(fp, ch->pcdata->condition, 4, 0); fMatch = true; break; } Key("Comm", ch->comm, read_flag(fp)); Key("Cols", ch->columns, read_number(fp)); Key("CPref", ch->color_prefix, read_letter(fp)); if (!str_cmp(word, "Colo")) { if (ch->version >= 8) { int i, j, num = read_number(fp); for (i = 0; i < Min(num, MAX_CUSTOM_COLOR); i++) { if (i >= MAX_CUSTOM_COLOR) break; for (j = 0; j < CT_MAX; j++) ch->pcdata->colors[i][j] = read_enum(color_value_t, fp); } } read_to_eol(fp); fMatch = true; break; } if (!str_cmp(word, "CTemplate")) { const char *str = read_string(fp); ColorTemplate *tmp = find_color_template(str); ch->pcdata->color_scheme = !tmp ? default_color_scheme : tmp; free_string(str); fMatch = true; break; } break; case 'D': Key("Damroll", ch->damroll, read_number(fp)); Key("Dam", ch->damroll, read_number(fp)); Key_Str("Description", ch->description); Key_Str("Desc", ch->description); Key_SFun("Deity", ch->deity, deity_lookup); break; case 'E': if (!str_cmp(word, END_MARK)) { if (ch->in_room == NULL) ch->in_room = get_room_index(ROOM_VNUM_LIMBO); percent = (current_time - lastlogoff) * 25 / (2 * 60 * 60); percent = Min(percent, 100); if (percent > 0 && !IsAffected(ch, AFF_POISON) && !IsAffected(ch, AFF_PLAGUE)) { ch->hit += (ch->max_hit - ch->hit) * percent / 100; ch->mana += (ch->max_mana - ch->mana) * percent / 100; ch->move += (ch->max_move - ch->move) * percent / 100; } return; } Key("Exp", ch->exp, read_number(fp)); break; case 'G': Key("Gold", ch->gold, read_number(fp)); if (!str_cmp(word, "GQmobs")) { if (gquest_info.running != GQUEST_OFF) { ch->gquest = new_gqlist(); alloc_mem(ch->gquest->gq_mobs, vnum_t, gquest_info.mob_count); read_array(fp, ch->gquest->gq_mobs, gquest_info.mob_count, -1); ch->gquest->ch = ch; Link(ch->gquest, gqlist, next, prev); } fMatch = true; break; } if (!str_cmp(word, "Group") || !str_cmp(word, "Gr")) { int gn; char *temp; temp = read_word(fp); gn = group_lookup(temp); if (gn < 0) { bugf("read_char: unknown group (%s). ", temp); } else gn_add(ch, gn); fMatch = true; break; } Key_Array("Gstats", ch->pcdata->gamestat, MAX_GAMESTAT, 0); Key_Str("GProm", ch->gprompt); break; case 'H': Key("Hitroll", ch->hitroll, read_number(fp)); Key("Hit", ch->hitroll, read_number(fp)); Key("HKey", ch->pcdata->home_key, read_number(fp)); Key("HRoom", ch->pcdata->home_room, read_number(fp)); Key_Array("Homes", ch->pcdata->home, MAX_HOME_VNUMS, 0); if (!str_cmp(word, "HpManaMove") || !str_cmp(word, "HMV")) { ch->hit = read_number(fp); ch->max_hit = read_number(fp); ch->mana = read_number(fp); ch->max_mana = read_number(fp); ch->move = read_number(fp); ch->max_move = read_number(fp); fMatch = true; break; } if (!str_cmp(word, "HpManaMovePerm") || !str_cmp(word, "HMVP")) { ch->pcdata->perm_hit = read_number(fp); ch->pcdata->perm_mana = read_number(fp); ch->pcdata->perm_move = read_number(fp); fMatch = true; break; } break; case 'I': Key("Id", ch->id, read_number(fp)); Key("InvisLevel", ch->invis_level, read_number(fp)); Key("Inco", ch->incog_level, read_number(fp)); Key("Invi", ch->invis_level, read_number(fp)); if (!str_cmp(word, "Ignore")) { if (ignore >= MAX_IGNORE) { read_to_eol(fp); fMatch = true; break; } ch->pcdata->ignore[ignore] = read_string(fp); ch->pcdata->ignore_flags[ignore] = read_flag(fp); ignore++; fMatch = true; break; } #ifndef DISABLE_I3 if ((fMatch = i3load_char(ch, fp, word))) break; #endif break; case 'K': if (!str_cmp(word, "Kller")) { NameList *nl = new_namelist(); nl->name = str_dup(read_word(fp)); if (is_player_name(nl->name)) Link(nl, ch->pcdata->killer, next, prev); else free_namelist(nl); fMatch = true; break; } break; case 'L': Key("LastLevel", ch->pcdata->last_level, read_number(fp)); Key("LLev", ch->pcdata->last_level, read_number(fp)); Key("Level", ch->level, read_number(fp)); Key("Lev", ch->level, read_number(fp)); Key("Levl", ch->level, read_number(fp)); Key("LogO", lastlogoff, read_number(fp)); Key_Str("LongDescr", ch->long_descr); Key_Str("LnD", ch->long_descr); break; case 'N': Key_Str("Name", ch->name); Key_Ignore("Not"); break; case 'P': Key_Str("Password", ch->pcdata->pwd); Key_Str("Pass", ch->pcdata->pwd); Key("Played", ch->pcdata->played, read_number(fp)); Key("Plyd", ch->pcdata->played, read_number(fp)); Key("Points", ch->pcdata->points, read_number(fp)); Key("Pnts", ch->pcdata->points, read_number(fp)); Key_Str("Pretit", ch->pcdata->pretit); Key("Position", ch->position, read_enum(position_t, fp)); Key("Pos", ch->position, read_enum(position_t, fp)); Key("Practice", ch->practice, read_number(fp)); Key("Prac", ch->practice, read_number(fp)); Key("PrClass", ch->pcdata->prime_class, read_number(fp)); Key_Str("Prompt", ch->prompt); Key_Str("Prom", ch->prompt); break; case 'Q': Key("QuestPnts", ch->pcdata->quest.points, read_number(fp)); Key("QuestTime", ch->pcdata->quest.time, read_number(fp)); Key("QuestStatus", ch->pcdata->quest.status, read_enum(quest_t, fp)); Key_Do("QuestLoc", (ch->pcdata->quest.room = get_room_index(read_number(fp)))); Key_Do("QuestMob", (ch->pcdata->quest.mob = find_quest_char(ch, read_number(fp)))); Key_Do("QuestObj", (ch->pcdata->quest.obj = create_quest_obj(ch, read_number(fp)))); Key_Do("QuestGiver", (ch->pcdata->quest.giver = find_quest_char(ch, read_number(fp)))); break; case 'R': Key("Rank", ch->rank, read_number(fp)); Key_SFun("Race", ch->race, race_lookup); Key_Do("RoomRLE", read_rle(ch->pcdata->explored, fp)); Key_Do("Room", (ch->in_room = get_room_index(read_number(fp)))); break; case 'S': Key("SavingThrow", ch->saving_throw, read_number(fp)); Key("Save", ch->saving_throw, read_number(fp)); Key("Scro", ch->lines, read_number(fp)); Key("Sex", ch->sex, read_enum(sex_t, fp)); Key_Str("ShortDescr", ch->short_descr); Key_Str("ShD", ch->short_descr); Key("Sec", ch->pcdata->security, read_number(fp)); Key("Silv", ch->silver, read_number(fp)); Key("Shares", ch->pcdata->shares, read_number(fp)); Key("StrEdKey", ch->pcdata->str_ed_key, read_letter(fp)); Key_Do("StayRace", (ch->pcdata->stay_race = true)); Key_Array("Stance", ch->stance, MAX_STANCE, 0); if (!str_cmp(word, "Skill") || !str_cmp(word, "Sk")) { int sn; int value; char *temp; value = read_number(fp); temp = read_word(fp); sn = skill_lookup(temp); if (sn < 0) { bugf("read_char: unknown skill. (%s)", temp); } else ch->pcdata->learned[sn] = value; fMatch = true; break; } if (!str_cmp(word, "Subscribe")) { int i, num = read_number(fp); char *boardname; for (; num; num--) { boardname = read_word(fp); i = board_lookup(boardname); if (i == BOARD_NOTFOUND) { sprintf(buf, "read_char: %s had unknown board name: %s. Skipped.", ch->name, boardname); log_string(buf); read_number(fp); } else ch->pcdata->unsubscribed[i] = read_number(fp); } fMatch = true; break; } break; case 'T': Key("TrueSex", ch->pcdata->true_sex, read_enum(sex_t, fp)); Key("TSex", ch->pcdata->true_sex, read_enum(sex_t, fp)); Key("Trai", ch->train, read_number(fp)); Key("Trust", ch->trust, read_number(fp)); Key("Tru", ch->trust, read_number(fp)); Key("Trivia", ch->pcdata->trivia, read_number(fp)); Key("TimeZone", ch->pcdata->timezone, read_number(fp)); if (!str_cmp(word, "Title") || !str_cmp(word, "Titl")) { ch->pcdata->title = read_string(fp); if (ch->pcdata->title[0] != '.' && ch->pcdata->title[0] != ',' && ch->pcdata->title[0] != '!' && ch->pcdata->title[0] != '?') { sprintf(buf, " %s", ch->pcdata->title); replace_str(&ch->pcdata->title, buf); } fMatch = true; break; } Key_Array("Timers", ch->pcdata->timers, MAX_TIMER, 0); break; case 'V': Key("Version", ch->version, read_number(fp)); Key("Vers", ch->version, read_number(fp)); Key("Vt100", ch->pcdata->vt100, read_flag(fp)); Key_Do("Vnum", (ch->pIndexData = get_char_index(read_number(fp)))); break; case 'W': if (!str_cmp(word, "WarInfo")) { if (war_info.status != WAR_OFF) { ch->war = new_warlist(); ch->war->hit = read_number(fp); ch->war->mana = read_number(fp); ch->war->move = read_number(fp); ch->war->flags = read_flag(fp); ch->war->ch = ch; Link(ch->war, warlist, next, prev); } fMatch = true; break; } Key("Wimpy", ch->wimpy, read_number(fp)); Key("Wimp", ch->wimpy, read_number(fp)); Key("Wizn", ch->wiznet, read_flag(fp)); Key_Str("WhoD", ch->pcdata->who_descr); break; } if (!fMatch) { bugf("read_char: no match for %s->%s.", ch->name, word); read_to_eol(fp); } } } void read_pet(CharData * ch, FileData * fp) { const char *word; CharData *pet; bool fMatch; int lastlogoff = current_time; int percent; word = f_eof(fp) ? END_MARK : read_word(fp); if (!str_cmp(word, "Vnum")) { vnum_t vnum; vnum = read_number(fp); if (get_char_index(vnum) == NULL) { bugf("Fread_pet: bad vnum %ld.", vnum); pet = create_mobile(get_char_index(MOB_VNUM_FIDO)); } else pet = create_mobile(get_char_index(vnum)); } else { bug("Fread_pet: no vnum in file."); pet = create_mobile(get_char_index(MOB_VNUM_FIDO)); } for (;;) { word = f_eof(fp) ? END_MARK : read_word(fp); fMatch = false; switch (toupper(word[0])) { case '*': fMatch = true; read_to_eol(fp); break; case 'A': Key("Act", pet->act, read_flag(fp)); Key("AfBy", pet->affected_by, read_flag(fp)); Key("Alig", pet->alignment, read_number(fp)); if (!str_cmp(word, "ACs")) { if (pet->version < 9) { int i; for (i = 0; i < 4; i++) pet->armor[i] = read_number(fp); } else read_array(fp, pet->armor, MAX_AC, 100); fMatch = true; break; } if (!str_cmp(word, "AffD")) { AffectData *paf; int sn; paf = new_affect(); sn = skill_lookup(read_word(fp)); if (sn < 0) bug("read_char: unknown skill."); else paf->type = sn; paf->level = read_number(fp); paf->duration = read_number(fp); paf->modifier = read_number(fp); paf->location = read_enum(apply_t, fp); paf->bitvector = read_number(fp); Link(paf, pet->affect, next, prev); fMatch = true; break; } if (!str_cmp(word, "Affc")) { AffectData *paf; int sn; paf = new_affect(); sn = skill_lookup(read_word(fp)); if (sn < 0) bug("read_char: unknown skill."); else paf->type = sn; paf->where = read_enum(where_t, fp); paf->level = read_number(fp); paf->duration = read_number(fp); paf->modifier = read_number(fp); paf->location = read_enum(apply_t, fp); paf->bitvector = read_flag(fp); Link(paf, pet->affect, next, prev); fMatch = true; break; } if (!str_cmp(word, "AMod")) { if (pet->version < 9) { int stat; for (stat = 0; stat < STAT_MAX; stat++) pet->mod_stat[stat] = read_number(fp); } else read_array(fp, pet->mod_stat, STAT_MAX, 0); fMatch = true; break; } if (!str_cmp(word, "Attr")) { if (ch->version < 9) { int stat; for (stat = 0; stat < STAT_MAX; stat++) pet->perm_stat[stat] = read_number(fp); } else read_array(fp, pet->perm_stat, STAT_MAX, 3); fMatch = true; break; } break; case 'C': Key("Comm", pet->comm, read_flag(fp)); break; case 'D': Key("Dam", pet->damroll, read_number(fp)); Key_Str("Desc", pet->description); break; case 'E': if (!str_cmp(word, END_MARK)) { pet->leader = ch; pet->master = ch; ch->pet = pet; percent = (current_time - lastlogoff) * 25 / (2 * 60 * 60); if (percent > 0 && !IsAffected(ch, AFF_POISON) && !IsAffected(ch, AFF_PLAGUE)) { percent = Min(percent, 100); pet->hit += (pet->max_hit - pet->hit) * percent / 100; pet->mana += (pet->max_mana - pet->mana) * percent / 100; pet->move += (pet->max_move - pet->move) * percent / 100; } return; } Key("Exp", pet->exp, read_number(fp)); break; case 'G': Key("Gold", pet->gold, read_number(fp)); break; case 'H': Key("Hit", pet->hitroll, read_number(fp)); if (!str_cmp(word, "HMV")) { pet->hit = read_number(fp); pet->max_hit = read_number(fp); pet->mana = read_number(fp); pet->max_mana = read_number(fp); pet->move = read_number(fp); pet->max_move = read_number(fp); fMatch = true; break; } break; case 'L': Key("Levl", pet->level, read_number(fp)); Key_Str("LnD", pet->long_descr); Key("LogO", lastlogoff, read_number(fp)); break; case 'N': Key_Str("Name", pet->name); break; case 'P': Key("Pos", pet->position, read_enum(position_t, fp)); break; case 'R': Key_SFun("Race", pet->race, race_lookup); break; case 'S': Key("Save", pet->saving_throw, read_number(fp)); Key("Sex", pet->sex, read_enum(sex_t, fp)); Key_Str("ShD", pet->short_descr); Key("Silv", pet->silver, read_number(fp)); break; if (!fMatch) { bug("Fread_pet: no match."); read_to_eol(fp); } } } } void read_obj(CharData * ch, FileData * fp, save_t type) { ObjData *obj; const char *word; int iNest; bool fMatch; bool fNest; bool fVnum; bool first; bool new_format; bool make_new; vnum_t where; fVnum = false; obj = NULL; first = true; new_format = false; make_new = false; word = f_eof(fp) ? END_MARK : read_word(fp); if (!str_cmp(word, "Vnum")) { vnum_t vnum; ObjIndex *pObj; first = false; vnum = read_number(fp); if ((pObj = get_obj_index(vnum)) == NULL) { bugf("Fread_obj: bad vnum %ld.", vnum); } else { obj = create_object(pObj, -1); new_format = true; fVnum = true; } } if (obj == NULL) { obj = new_obj(); obj->name = str_dup(""); obj->short_descr = str_dup(""); obj->description = str_dup(""); } fNest = false; fVnum = true; iNest = 0; where = type == SAVE_CORPSE ? ROOM_VNUM_MORGUE : 0; for (;;) { if (first) first = false; else word = f_eof(fp) ? END_MARK : read_word(fp); fMatch = false; switch (toupper(word[0])) { case '*': fMatch = true; read_to_eol(fp); break; case 'A': if (!str_cmp(word, "AffD")) { AffectData *paf; int sn; paf = new_affect(); sn = skill_lookup(read_word(fp)); if (sn < 0) bug("Fread_obj: unknown skill."); else paf->type = sn; paf->level = read_number(fp); paf->duration = read_number(fp); paf->modifier = read_number(fp); paf->location = read_enum(apply_t, fp); paf->bitvector = read_number(fp); Link(paf, obj->affect, next, prev); fMatch = true; break; } if (!str_cmp(word, "Affc")) { AffectData *paf; int sn; paf = new_affect(); sn = skill_lookup(read_word(fp)); if (sn < 0) bug("Fread_obj: unknown skill."); else paf->type = sn; paf->where = read_enum(where_t, fp); paf->level = read_number(fp); paf->duration = read_number(fp); paf->modifier = read_number(fp); paf->location = read_enum(apply_t, fp); paf->bitvector = read_flag(fp); Link(paf, obj->affect, next, prev); fMatch = true; break; } break; case 'C': Key("Cond", obj->condition, read_number(fp)); Key("Cost", obj->cost, read_number(fp)); break; case 'D': Key_Str("Description", obj->description); Key_Str("Desc", obj->description); break; case 'E': Key_Do("Enchanted", (obj->enchanted = true)); Key("ExtraFlags", obj->extra_flags, read_number(fp)); Key("ExtF", obj->extra_flags, read_flag(fp)); if (!str_cmp(word, "ExtraDescr") || !str_cmp(word, "ExDe")) { ExDescrData *ed; ed = new_ed(); ed->keyword = read_string(fp); ed->description = read_string(fp); Link(ed, obj->ed, next, prev); fMatch = true; } if (!str_cmp(word, END_MARK)) { if (!fNest || (fVnum && obj->pIndexData == NULL)) { bug("Fread_obj: incomplete object."); free_obj(obj); return; } else { if (!fVnum) { free_obj(obj); obj = create_object(get_obj_index(OBJ_VNUM_DUMMY), 0); } if (!new_format) { Link(obj, obj, next, prev); obj->pIndexData->count++; } if (!obj->pIndexData->new_format && obj->item_type == ITEM_ARMOR && obj->value[1] == 0) { obj->value[1] = obj->value[0]; obj->value[2] = obj->value[0]; } if (make_new) { wloc_t wear; wear = obj->wear_loc; extract_obj(obj); obj = create_object(obj->pIndexData, 0); obj->wear_loc = wear; } if (iNest == 0 || rgObjNest[iNest] == NULL) { switch (type) { case SAVE_CORPSE: { RoomIndex *Room; CorpseData *c; c = new_corpse(); c->corpse = obj; Link(c, corpse, next, prev); if ((Room = get_room_index(where)) == NULL) Room = get_room_index(ROOM_VNUM_MORGUE); obj_to_room(obj, Room); } break; case SAVE_ROOM: { RoomIndex *Room; if ((Room = get_room_index(where)) == NULL) extract_obj(obj); else obj_to_room(obj, Room); } break; case SAVE_CHAR: obj_to_char(obj, ch); break; case SAVE_PET: obj_to_char(obj, ch->pet ? ch->pet : ch); break; default: bugf("Bad save type (%d)", type); break; } } else obj_to_obj(obj, rgObjNest[iNest - 1]); return; } } break; case 'I': Key("ItemType", obj->item_type, read_enum(item_t, fp)); Key("Ityp", obj->item_type, read_enum(item_t, fp)); break; case 'L': Key("Level", obj->level, read_number(fp)); Key("Lev", obj->level, read_number(fp)); break; case 'N': Key_Str("Name", obj->name); if (!str_cmp(word, "Nest")) { iNest = read_number(fp); if (iNest < 0 || iNest >= MAX_NEST) { bugf("Fread_obj: bad nest %d.", iNest); } else { rgObjNest[iNest] = obj; fNest = true; } fMatch = true; } break; case 'O': if (!str_cmp(word, "Oldstyle")) { if (obj->pIndexData != NULL && obj->pIndexData->new_format) make_new = true; fMatch = true; break; } Key_Str("Owner", obj->owner); break; case 'S': Key_Str("ShortDescr", obj->short_descr); Key_Str("ShD", obj->short_descr); if (!str_cmp(word, "Spell")) { int iValue; int sn; iValue = read_number(fp); sn = skill_lookup(read_word(fp)); if (iValue < 0 || iValue > 3) { bugf("Fread_obj: bad iValue %d.", iValue); } else if (sn < 0) { bug("Fread_obj: unknown skill."); } else { obj->value[iValue] = sn; } fMatch = true; break; } break; case 'T': Key("Timer", obj->timer, read_number(fp)); Key("Time", obj->timer, read_number(fp)); break; case 'V': if (!str_cmp(word, "Values") || !str_cmp(word, "Vals")) { obj->value[0] = read_number(fp); obj->value[1] = read_number(fp); obj->value[2] = read_number(fp); obj->value[3] = read_number(fp); if (obj->item_type == ITEM_WEAPON && obj->value[0] == 0) obj->value[0] = obj->pIndexData->value[0]; fMatch = true; break; } if (!str_cmp(word, "Val")) { obj->value[0] = read_number(fp); obj->value[1] = read_number(fp); obj->value[2] = read_number(fp); obj->value[3] = read_number(fp); obj->value[4] = read_number(fp); fMatch = true; break; } Key_Array("Valu", obj->value, 5, 0); if (!str_cmp(word, "Vnum")) { vnum_t vnum; ObjIndex *pObj; vnum = read_number(fp); if ((pObj = get_obj_index(vnum)) == NULL) bugf("Fread_obj: bad vnum %ld.", vnum); else { obj->pIndexData = pObj; fVnum = true; } fMatch = true; break; } break; case 'W': Key("WearFlags", obj->wear_flags, read_number(fp)); Key("WeaF", obj->wear_flags, read_flag(fp)); Key("WearLoc", obj->wear_loc, read_enum(wloc_t, fp)); Key("Wear", obj->wear_loc, read_enum(wloc_t, fp)); Key("Weight", obj->weight, read_number(fp)); Key("Wt", obj->weight, read_number(fp)); Key("Where", where, read_number(fp)); break; } if (!fMatch) { bug("Fread_obj: no match."); read_to_eol(fp); } } } void read_descriptor(Descriptor * d, FileData * fp) { const char *word; bool fMatch; for (;;) { word = f_eof(fp) ? END_MARK : read_word(fp); fMatch = false; if (crs_info.status != CRS_COPYOVER_RECOVER) { if (!str_cmp(word, END_MARK)) return; else { read_to_eol(fp); continue; } } switch (toupper(word[0])) { case '*': fMatch = true; read_to_eol(fp); break; case 'B': Key("ByteN", d->bytes_normal, read_number(fp)); #ifndef DISABLE_MCCP Key("ByteC", d->bytes_compressed, read_number(fp)); #endif break; case 'C': Key("Connected", d->connected, read_enum(connect_t, fp)); #ifndef DISABLE_MCCP Key("CVersion", d->mccp_version, read_number(fp)); #endif break; case 'D': Key("Descr", d->descriptor, read_number(fp)); break; case 'E': if (!str_cmp(word, END_MARK)) return; break; case 'F': Key("Flags", d->desc_flags, read_flag(fp)); break; case 'H': Key_Str("Host", d->host); break; case 'I': Key_Do("IMPver", d->imp_vers = atof(read_word(fp))); Key("IP", d->ip, read_number(fp)); break; case 'K': Key("Keycode", d->portal.keycode, read_number(fp)); break; case 'M': Key_Str("MXPSup", d->mxp.supports); Key_Do("MXPVer", d->mxp.mxp_ver = atof(read_word(fp))); Key_Do("MXPClVer", d->mxp.client_ver = atof(read_word(fp))); Key_Do("MXPStyl", d->mxp.style_ver = atof(read_word(fp))); Key_Str("MXPClien", d->mxp.client); Key("MXPReg", d->mxp.registered, read_number(fp)); Key("MXPFlag1", d->mxp.flags, read_flag(fp)); Key("MXPFlag2", d->mxp.flags2, read_flag(fp)); break; case 'P': Key_StrCpy("PortVer", d->portal.version); Key_Do("Pueblo", d->pueblo_vers = atof(read_word(fp))); Key("Port", d->port, read_number(fp)); break; case 'S': Key("ScrW", d->scr_width, read_number(fp)); Key("ScrH", d->scr_height, read_number(fp)); break; case 'T': Key_StrCpy("TType", d->ttype); break; } if (!fMatch) { bugf("no match for %s.", word); read_to_eol(fp); } } } void save_corpses(void) { FileData *fp; CorpseData *c; if ((fp = f_open(CORPSE_FILE, "w")) == NULL) { bug("save_corpses: " CORPSE_FILE " not found."); } else { for (c = corpse_first; c != NULL; c = c->next) { if (c->corpse->item_type == ITEM_CORPSE_PC) write_obj(NULL, c->corpse, fp, 0, 0, SAVE_CORPSE); else update_corpses(c->corpse, true); } f_printf(fp, "#" END_MARK LF); f_close(fp); } return; } void load_corpses(void) { FileData *fp; log_string("Loading corpses..."); if ((fp = f_open(CORPSE_FILE, "r")) == NULL) { bug("load_corpses: " CORPSE_FILE " not found"); } else { for (;;) { char letter; char *word; letter = read_letter(fp); if (letter == '*') { read_to_eol(fp); continue; } if (letter != '#') { bugf("# not found. (%c)", letter); break; } word = read_word(fp); if (!str_cmp(word, get_obj_save_header(SAVE_CORPSE))) read_obj(NULL, fp, SAVE_CORPSE); else if (!str_cmp(word, END_MARK)) break; else { bug("load_corpses: bad section."); break; } } f_close(fp); } return; } void update_corpses(ObjData * obj, bool pdelete) { if (obj && obj->item_type == ITEM_CORPSE_PC) { CorpseData *c; for (c = corpse_first; c != NULL; c = c->next) if (c->corpse == obj) break; if (c != NULL) { if (pdelete) { UnLink(c, corpse, next, prev); free_corpse(c); save_corpses(); } } else if (obj->content_first != NULL && obj->in_room != NULL) { c = new_corpse(); c->corpse = obj; Link(c, corpse, next, prev); save_corpses(); } } return; } void checkcorpse(CharData * ch) { CorpseData *c; bool found = false; int count = 0; if (!ch || IsNPC(ch)) return; for (c = corpse_first; c != NULL; c = c->next) { if (c->corpse && is_name(ch->name, c->corpse->owner)) { found = true; count++; } } if (found) { chprintlnf(ch, NEWLINE "{f{RWARNING:{x {WYou have %s in the game.{x", intstr(count, "corpse")); new_wiznet(ch, intstr(count, "corpse"), 0, 0, 0, "$N has $t in the game."); } }