/**************************************************************************
* 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-2003 by Ryan Jennings *
* http://1stmud.dlmud.com/ <r-jenn@shaw.ca> *
***************************************************************************/
#include "merc.h"
#include "recycle.h"
#include "tables.h"
#include "lookup.h"
#include "interp.h"
#include "save.h"
#include "signals.h"
static OBJ_DATA *rgObjNest[MAX_NEST];
PROTOTYPE(void new_warlist, (CHAR_DATA *));
PROTOTYPE(void free_warlist, (WAR_DATA *));
PROTOTYPE(void new_gqlist, (CHAR_DATA *));
PROTOTYPE(void free_gqlist, (GQ_DATA *));
/*
* Local functions.
*/
PROTOTYPE(void fwrite_char, (CHAR_DATA *, FILE *));
PROTOTYPE(void fwrite_pet, (CHAR_DATA *, FILE *));
PROTOTYPE(void read_pet, (CHAR_DATA *, READ_DATA *));
PROTOTYPE(void read_descriptor, (DESCRIPTOR_DATA *, READ_DATA *));
PROTOTYPE(void fwrite_descriptor, (DESCRIPTOR_DATA *, FILE *));
#define TAB_SIZE 8
char *format_tabs(int len)
{
if (len <= 0)
return "";
else if (len < TAB_SIZE)
return "\t\t";
else if (len < (TAB_SIZE * 2))
return "\t";
else
return " ";
}
/* print *str if not the same as *not, formating *name */
void fwrite_string(FILE * fp, const char *name, const char *str,
const char *def)
{
if (IS_NULLSTR(name))
fprintf(fp, "%s~\n", fix_string(str));
else if (!IS_NULLSTR(str) && (IS_NULLSTR(def) || str_cmp(str, def)))
fprintf(fp, "%s%s%s~\n", name, format_tabs(strlen(name)),
fix_string(str));
}
/* wrap *str in quotes ('') if not the same as *not, formating *name */
void fwrite_word(FILE * fp, const char *name, const char *str, const char *def)
{
if (IS_NULLSTR(name))
fprintf(fp, "'%s'\n", fix_string(str));
else if (!IS_NULLSTR(str) && (IS_NULLSTR(def) || str_cmp(str, def)))
fprintf(fp, "%s%s'%s'\n", name, format_tabs(strlen(name)),
fix_string(str));
}
/* print bit if not the same as not, formating *name */
void fwrite_bit(FILE * fp, const char *name, flag_t bit, flag_t def)
{
if (IS_NULLSTR(name))
fprintf(fp, "%s\n", fwrite_flags(bit));
else if (bit != def)
fprintf(fp, "%s%s%s\n", name, format_tabs(strlen(name)),
fwrite_flags(bit));
}
/* print *format, formating *name */
void fwritef(FILE * fp, const char *name, const char *format, ...)
{
va_list args;
va_start(args, format);
if (IS_NULLSTR(name))
vfprintf(fp, format, args);
else
{
fprintf(fp, "%s%s", name, format_tabs(strlen(name)));
vfprintf(fp, format, args);
}
va_end(args);
fprintf(fp, "\n");
}
/*
* Save a character and inventory.
* Would be cool to save NPC's too for quest purposes,
* some of the infrastructure is provided.
*/
void save_char_obj(CHAR_DATA * ch)
{
char strsave[MAX_INPUT_LENGTH];
WRITE_DATA *fp;
if (IS_NPC(ch))
return;
if (ch->desc != NULL && ch->desc->original != NULL)
ch = ch->desc->original;
sprintf(strsave, "%s%s", PLAYER_DIR, capitalize(ch->name));
if ((fp = open_write(strsave)) == NULL)
{
bug("Save_char_obj: file open");
log_error(strsave);
}
else
{
fwrite_char(ch, fp->stream);
if (ch->first_carrying != NULL)
fwrite_obj(ch, ch->first_carrying, fp->stream, 0, "O");
/* save the pets */
if (ch->pet != NULL && ch->pet->in_room == ch->in_room)
fwrite_pet(ch->pet, fp->stream);
if (ch->desc && (crs_info.status == CRS_COPYOVER || crash_info.crashed))
fwrite_descriptor(ch->desc, fp->stream);
fprintf(fp->stream, "#END\n");
close_write(fp);
}
return;
}
/*
* Write the char.
*/
void fwrite_char(CHAR_DATA * ch, FILE * fp)
{
AFFECT_DATA *paf;
int sn, gn, pos;
int i, j;
fprintf(fp, "#%s\n", IS_NPC(ch) ? "MOB" : "PLAYER");
fwrite_string(fp, "Name", ch->name, NULL);
fwrite_int(fp, "Id", "%ld", ch->id, 0);
fwrite_int(fp, "LogO", "%ld", current_time, 0);
fwrite_int(fp, "Vers", "%d", 9, 0);
fwrite_string(fp, "ShD", ch->short_descr, NULL);
fwrite_string(fp, "LnD", ch->long_descr, NULL);
fwrite_string(fp, "Desc", ch->description, NULL);
fwrite_string(fp, "Prom", ch->prompt, NULL);
fwrite_string(fp, "Race", ch->race->name, NULL);
if (ch->clan != NULL)
{
fwrite_string(fp, "Clan", ch->clan->name, NULL);
fwrite_int(fp, "Rank", "%d", ch->rank, -1);
}
fwrite_int(fp, "Sex", "%d", ch->sex, -1);
fwritef(fp, "Cla", "%s", class_numbers(ch, TRUE));
if (ch->pcdata->stay_race)
fprintf(fp, "StayRace\n");
fwrite_int(fp, "Levl", "%d", ch->level, 0);
fwrite_int(fp, "Tru", "%d", ch->trust, 0);
fwrite_int(fp, "Sec", "%d", ch->pcdata->security, 0); /* OLC */
fwrite_int(fp, "Plyd", "%d", ch->played + (int) (current_time - ch->logon),
0);
fwrite_int(fp, "Scro", "%d", ch->lines, -1);
fwrite_int(fp, "Cols", "%d", ch->columns, -1);
fwrite_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);
fwritef(fp, "HMV", "%ld %ld %ld %ld %ld %ld", ch->hit,
ch->max_hit, ch->mana, ch->max_mana, ch->move, ch->max_move);
fwrite_int(fp, "Gold", "%ld", ch->gold, 0);
fwrite_int(fp, "Silv", "%ld", ch->silver, 0);
fwrite_int(fp, "Exp", "%d", ch->exp, 0);
fwrite_bit(fp, "Act", ch->act, 0);
fwrite_bit(fp, "AfBy", ch->affected_by, 0);
fwrite_bit(fp, "Comm", ch->comm, 0);
fwrite_bit(fp, "Wizn", ch->wiznet, 0);
fwrite_int(fp, "Invi", "%d", ch->invis_level, 0);
fwrite_int(fp, "Inco", "%d", ch->incog_level, 0);
fwrite_int(fp, "Pos", "%d",
ch->position == POS_FIGHTING ? POS_STANDING : ch->position, -1);
fwrite_int(fp, "Prac", "%d", ch->practice, 0);
fwrite_int(fp, "Trai", "%d", ch->train, 0);
fwrite_int(fp, "Save", "%d", ch->saving_throw, 0);
fwrite_int(fp, "Alig", "%d", ch->alignment, 0);
fwrite_int(fp, "Hit", "%d", ch->hitroll, 0);
fwrite_int(fp, "Dam", "%d", ch->damroll, 0);
fwrite_array("ACs", "%d", ch->armor, 4);
fwrite_array("Stance", "%d", ch->stance, MAX_STANCE);
fwrite_int(fp, "Wimp", "%d", ch->wimpy, 0);
fwrite_array("Attr", "%d", ch->perm_stat, MAX_STATS);
fwrite_array("AMod", "%d", ch->mod_stat, MAX_STATS);
if (IS_NPC(ch))
{
fwrite_int(fp, "Vnum", "%ld", ch->pIndexData->vnum, 0);
}
else
{
fwrite_string(fp, "Pass", ch->pcdata->pwd, NULL);
fwrite_string(fp, "Bin", ch->pcdata->bamfin, NULL);
fwrite_string(fp, "Bout", ch->pcdata->bamfout, NULL);
fwrite_string(fp, "Titl", ch->pcdata->title, NULL);
fwrite_int(fp, "Pnts", "%d", ch->pcdata->points, 0);
fwrite_int(fp, "TSex", "%d", ch->pcdata->true_sex, -1);
fwrite_int(fp, "LLev", "%d", ch->pcdata->last_level, 0);
fwritef(fp, "HMVP", "%ld %ld %ld", ch->pcdata->perm_hit,
ch->pcdata->perm_mana, ch->pcdata->perm_move);
fwrite_array("Cnd", "%d", ch->pcdata->condition, 4);
fwrite_int(fp, "QuestPnts", "%d", ch->pcdata->questpoints, 0);
fwrite_int(fp, "QuestNext", "%d", ch->pcdata->nextquest, 0);
fwrite_int(fp, "QuestCount", "%d", ch->pcdata->countdown, 0);
fwrite_int(fp, "QuestGiver", "%ld", ch->pcdata->questgiver, 0);
fwrite_int(fp, "QuestLoc", "%ld", ch->pcdata->questloc, 0);
fwrite_int(fp, "QuestObj", "%ld", ch->pcdata->questobj, 0);
fwrite_int(fp, "QuestMob", "%ld", ch->pcdata->questmob, 0);
fwrite_int(fp, "Trivia", "%d", ch->pcdata->trivia, 0);
if (ch->pcdata->str_ed_key != '.' && ch->pcdata->str_ed_key != ' ')
fwritef(fp, "StrEdKey", "%c", ch->pcdata->str_ed_key);
fwrite_int(fp, "TimeZone", "%d", ch->pcdata->timezone, -1);
fwrite_int(fp, "AWins", "%d", ch->pcdata->awins, 0);
fwrite_int(fp, "ALosses", "%d", ch->pcdata->alosses, 0);
fwrite_int(fp, "BankS", "%ld", ch->pcdata->silver_bank, 0);
fwrite_int(fp, "BankG", "%ld", ch->pcdata->gold_bank, 0);
fwrite_int(fp, "Shares", "%d", ch->pcdata->shares, 0);
if (ch->deity != NULL)
fwrite_string(fp, "Deity", ch->deity->name, NULL);
if (ON_GQUEST(ch))
{
fwrite_array("GQmobs", "%ld", ch->gquest->gq_mobs,
gquest_info.mob_count);
}
if (war_info.status != WAR_OFF && ch->war != NULL)
{
fwritef(fp, "WarInfo", "%ld %ld %ld %s", ch->war->hit,
ch->war->mana, ch->war->move, fwrite_flags(ch->war->flags));
}
if (count_home(ch) > 0)
{
fwrite_array("Homes", "%ld", ch->pcdata->home, MAX_HOUSE_ROOMS);
fwrite_int(fp, "HKey", "%ld", ch->pcdata->home_key, 0);
}
fprintf(fp, "Colo\t\t%d", MAX_CUSTOM_COLOUR);
for (i = 0; i < MAX_CUSTOM_COLOUR; i++)
for (j = 0; j < CT_MAX; j++)
fprintf(fp, " %d", ch->pcdata->colour[i][j]);
fprintf(fp, "\n");
fwrite_string(fp, "WhoD", ch->pcdata->who_descr, NULL);
fwrite_array("GStats", "%ld", ch->pcdata->gamestat, MAX_GAMESTAT);
/* write alias */
for (pos = 0; pos < MAX_ALIAS; pos++)
{
if (ch->pcdata->alias[pos] == NULL ||
ch->pcdata->alias_sub[pos] == NULL)
break;
fwritef(fp, "Alias", "%s %s~", ch->pcdata->alias[pos],
ch->pcdata->alias_sub[pos]);
}
for (pos = 0; pos < MAX_BUDDY; pos++)
{
if (ch->pcdata->buddies[pos] == NULL)
break;
fwrite_string(fp, "Buddy", ch->pcdata->buddies[pos], NULL);
}
for (pos = 0; pos < MAX_IGNORE; pos++)
{
if (IS_NULLSTR(ch->pcdata->ignore[pos]))
break;
fwritef(fp, "Ignore", "%s~ %s", ch->pcdata->ignore[pos],
fwrite_flags(ch->pcdata->ignore_flags[pos]));
}
/* Save note board status */
/* Save number of boards in case that number changes */
fprintf(fp, "Boards\t\t %d", MAX_BOARD);
for (i = 0; i < MAX_BOARD; i++)
fprintf(fp, " %s %ld", boards[i].short_name,
ch->pcdata->last_note[i]);
fprintf(fp, "\n");
for (sn = 0; sn < maxSkill; sn++)
{
if (skill_table[sn].name != NULL && ch->pcdata->learned[sn] > 0)
{
fwritef(fp, "Sk", "%d '%s'",
ch->pcdata->learned[sn], skill_table[sn].name);
}
}
for (gn = 0; gn < maxGroup; gn++)
{
if (group_table[gn].name != NULL && ch->pcdata->group_known[gn])
{
fwritef(fp, "Gr", "'%s'", group_table[gn].name);
}
}
}
for (paf = ch->first_affect; paf != NULL; paf = paf->next)
{
if (paf->type < 0 || paf->type >= maxSkill)
continue;
fwritef(fp, "Affc", "'%s' %3d %3d %3d %3d %3d %s",
skill_table[paf->type].name, paf->where, paf->level,
paf->duration, paf->modifier, paf->location,
fwrite_flags(paf->bitvector));
}
fwrite_rle(ch->pcdata->explored, fp);
fprintf(fp, "End\n\n");
return;
}
/* write a pet */
void fwrite_pet(CHAR_DATA * pet, FILE * fp)
{
AFFECT_DATA *paf;
fprintf(fp, "#PET\n");
fwrite_int(fp, "Vnum", "%ld", pet->pIndexData->vnum, 0);
fwrite_string(fp, "Name", pet->name, NULL);
fwrite_int(fp, "LogO", "%ld", current_time, 0);
fwrite_string(fp, "ShD", pet->short_descr, pet->pIndexData->short_descr);
fwrite_string(fp, "LnD", pet->long_descr, pet->pIndexData->long_descr);
fwrite_string(fp, "Desc", pet->description, pet->pIndexData->description);
if (pet->race != pet->pIndexData->race)
fwrite_string(fp, "Race", pet->race->name, NULL);
if (pet->clan != NULL)
fwrite_string(fp, "Clan", pet->clan->name, NULL);
fwrite_int(fp, "Sex", "%d", pet->sex, -1);
fwrite_int(fp, "Levl", "%d", pet->level, pet->pIndexData->level);
fwritef(fp, "HMV", "%ld %ld %ld %ld %ld %ld", pet->hit, pet->max_hit,
pet->mana, pet->max_mana, pet->move, pet->max_move);
fwrite_int(fp, "Gold", "%ld", pet->gold, 0);
fwrite_int(fp, "Silv", "%ld", pet->silver, 0);
fwrite_int(fp, "Exp", "%d", pet->exp, 0);
fwrite_bit(fp, "Act", pet->act, pet->pIndexData->act);
fwrite_bit(fp, "AfBy", pet->affected_by, pet->pIndexData->affected_by);
fwrite_bit(fp, "Comm", pet->comm, 0);
fwrite_int(fp, "Pos", "%d", pet->position =
POS_FIGHTING ? POS_STANDING : pet->position, -1);
fwrite_int(fp, "Save", "%d", pet->saving_throw, 0);
fwrite_int(fp, "Alig", "%d", pet->alignment, pet->pIndexData->alignment);
fwrite_int(fp, "Hit", "%d", pet->hitroll, pet->pIndexData->hitroll);
fwrite_int(fp, "Dam", "%d", pet->damroll,
pet->pIndexData->damage[DICE_BONUS]);
fwrite_array("ACs", "%d", pet->armor, 4);
fwrite_array("Attr", "%d", pet->perm_stat, MAX_STATS);
fwrite_array("AMod", "%d", pet->mod_stat, MAX_STATS);
for (paf = pet->first_affect; paf != NULL; paf = paf->next)
{
if (paf->type < 0 || paf->type >= maxSkill)
continue;
fwritef(fp, "Affc", "'%s' %3d %3d %3d %3d %3d %s",
skill_table[paf->type].name, paf->where, paf->level,
paf->duration, paf->modifier, paf->location,
fwrite_flags(paf->bitvector));
}
fprintf(fp, "End\n");
return;
}
/*
* Write an object and its contents.
*/
void fwrite_obj(CHAR_DATA * ch, OBJ_DATA * obj, FILE * fp, int iNest,
char *marker)
{
EXTRA_DESCR_DATA *ed;
AFFECT_DATA *paf;
vnum_t where = ROOM_VNUM_MORGUE;
/*
* Slick recursion to write lists backwards,
* so loading them will load in forwards order.
*/
if (obj->next_content != NULL)
fwrite_obj(ch, obj->next_content, fp, iNest, marker);
if (!ch)
{
if (obj->in_obj != NULL)
where = 1;
if (obj->in_room != NULL)
where = obj->in_room->vnum;
}
/*
* Castrate storage characters.
*/
if (ch
&& ((ch->level < obj->level - 2 && obj->item_type != ITEM_CONTAINER)
|| obj->item_type == ITEM_KEY || (obj->item_type == ITEM_MAP
&& !obj->value[0])))
return;
fwrite_word(fp, "#", marker, NULL);
fwrite_int(fp, "Vnum", "%ld", obj->pIndexData->vnum, 0);
if (!ch)
fwrite_int(fp, "Where", "%ld", where, ROOM_VNUM_MORGUE);
fwrite_string(fp, "Owner", obj->owner, NULL);
if (!obj->pIndexData->new_format)
fprintf(fp, "Oldstyle\n");
if (obj->enchanted)
fprintf(fp, "Enchanted\n");
fwrite_int(fp, "Nest", "%d", iNest, -1);
/* these data are only used if they do not match the defaults */
/* new saving functions handle defaults - Markanth 07/07/2003 */
fwrite_string(fp, "Name", obj->name, obj->pIndexData->name);
fwrite_string(fp, "ShD", obj->short_descr, obj->pIndexData->short_descr);
fwrite_string(fp, "Desc", obj->description, obj->pIndexData->description);
fwrite_bit(fp, "ExtF", obj->extra_flags, obj->pIndexData->extra_flags);
fwrite_bit(fp, "WeaF", obj->wear_flags, obj->pIndexData->wear_flags);
fwrite_int(fp, "Ityp", "%d", obj->item_type, obj->pIndexData->item_type);
fwrite_int(fp, "Wt", "%d", obj->weight, obj->pIndexData->weight);
fwrite_int(fp, "Cond", "%d", obj->condition, obj->pIndexData->condition);
/* variable data */
fwrite_int(fp, "Wear", "%d", obj->wear_loc, WEAR_NONE);
fwrite_int(fp, "Lev", "%d", obj->level, obj->pIndexData->level);
fwrite_int(fp, "Time", "%d", obj->timer, 0);
fwrite_int(fp, "Cost", "%d", obj->cost, 0);
if (memcmp(obj->value, obj->pIndexData->value, sizeof(obj->value)))
fwrite_array("Valu", "%ld", obj->value, 5);
switch (obj->item_type)
{
case ITEM_POTION:
case ITEM_SCROLL:
case ITEM_PILL:
if (obj->value[1] > 0)
{
fwritef(fp, "Spell 1", "'%s'", skill_table[obj->value[1]].name);
}
if (obj->value[2] > 0)
{
fwritef(fp, "Spell 2", "'%s'", skill_table[obj->value[2]].name);
}
if (obj->value[3] > 0)
{
fwritef(fp, "Spell 3", "'%s'", skill_table[obj->value[3]].name);
}
break;
case ITEM_STAFF:
case ITEM_WAND:
if (obj->value[3] > 0)
{
fwritef(fp, "Spell 3", "'%s'", skill_table[obj->value[3]].name);
}
break;
}
for (paf = obj->first_affect; paf != NULL; paf = paf->next)
{
if (paf->type < 0 || paf->type >= maxSkill)
continue;
fwritef(fp, "Affc", "'%s' %3d %3d %3d %3d %3d %s",
skill_table[paf->type].name, paf->where, paf->level,
paf->duration, paf->modifier, paf->location,
fwrite_flags(paf->bitvector));
}
for (ed = obj->first_extra_descr; ed != NULL; ed = ed->next)
{
fwritef(fp, "ExDe", "%s~ %s~", ed->keyword, ed->description);
}
fprintf(fp, "End\n\n");
if (obj->first_content != NULL)
fwrite_obj(ch, obj->first_content, fp, iNest + 1, marker);
return;
}
void fwrite_descriptor(DESCRIPTOR_DATA * d, FILE * fp)
{
fprintf(fp, "#DESC\n");
fwrite_string(fp, "Host", d->host, NULL);
fwrite_int(fp, "Descr", "%d", d->descriptor, 0);
fwrite_int(fp, "Connected", "%d", d->connected, 0);
fwrite_bit(fp, "Flags", d->d_flags, 0);
fwrite_int(fp, "ScrW", "%u", d->scr_width, 80);
fwrite_int(fp, "ScrH", "%u", d->scr_height, 24);
fwrite_int(fp, "ByteN", "%ld", d->bytes_normal, 0);
#if !defined(NO_MCCP)
fwrite_int(fp, "ByteC", "%ld", d->bytes_compressed, 0);
fwrite_int(fp, "CVersion", "%d", d->mccp_version, 0);
#endif
fwrite_string(fp, "TType", d->ttype, NULL);
if (IS_MXP(d))
{
fwrite_string(fp, "MXPSup", d->mxp.supports, NULL);
fwrite_int(fp, "MXPVer", "%.2f", d->mxp.mxp_ver, 0);
fwrite_int(fp, "MXPClVer", "%.2f", d->mxp.client_ver, 0);
fwrite_int(fp, "MXPStyl", "%.2f", d->mxp.style_ver, 0);
fwrite_string(fp, "MXPClien", d->mxp.client, NULL);
fwrite_int(fp, "MXPReg", "%d", d->mxp.registered, 0);
fwrite_bit(fp, "MXPFlag1", d->mxp.flags, 0);
fwrite_bit(fp, "MXPFlag2", d->mxp.flags2, 0);
}
if (IS_PORTAL(d))
{
fwrite_int(fp, "Keycode", "%u", d->portal.keycode, 0);
fwrite_string(fp, "PortVer", d->portal.version, NULL);
}
if (IS_FIRECL(d))
fwrite_int(fp, "IMPver", "%.2f", d->imp_vers, 0);
if (IS_PUEBLO(d))
fwrite_int(fp, "Pueblo", "%.2f", d->pueblo_vers, 0);
fprintf(fp, "End\n\n");
return;
}
void set_player_level(CHAR_DATA * 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(CHAR_DATA * ch)
{
int stat, i, iClass;
ch->race = default_race;
ch->act = PLR_NOSUMMON | PLR_AUTOMAP;
ch->comm = COMM_COMBINE | COMM_PROMPT;
for (iClass = 0; iClass < MAX_MCLASS; iClass++)
ch->Class[iClass] = -1;
ch->prompt = str_dup("<%hhp %mm %vmv> ");
ch->pcdata->confirm_delete = FALSE;
ch->pcdata->board = &boards[DEFAULT_BOARD];
ch->info_settings = INFO_QUIET; /* this actually turns quiet off */
ch->pcdata->pwd = str_dup("");
ch->pcdata->webpass = str_dup("");
ch->pcdata->bamfin = str_dup("");
ch->pcdata->bamfout = str_dup("");
ch->pcdata->title = str_dup("");
ch->pcdata->who_descr = str_dup("");
ch->pcdata->afk_msg = str_dup("");
for (stat = 0; stat < MAX_STATS; stat++)
ch->perm_stat[stat] = 13;
ch->pcdata->condition[COND_THIRST] = 48;
ch->pcdata->condition[COND_FULL] = 48;
ch->pcdata->condition[COND_HUNGER] = 48;
ch->pcdata->security = 0; /* OLC */
default_colour(ch, -1);
for (i = 0; i < MAX_GAMESTAT; i++)
ch->pcdata->gamestat[i] = 0;
ch->pcdata->trivia = 0;
end_quest(ch, 0);
ch->pcdata->timezone = -1;
}
/*
* Load a char and inventory into a new ch structure.
*/
bool load_char_obj(DESCRIPTOR_DATA * d, const char *name)
{
char strsave[MAX_INPUT_LENGTH];
char buf[100];
CHAR_DATA *ch;
READ_DATA *fp;
bool found;
int i;
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;
/* decompress if .gz file exists */
sprintf(strsave, "%s%s%s", PLAYER_DIR, capitalize(name), ".gz");
if ((fp = open_read(strsave)) != NULL)
{
close_read(fp);
sprintf(buf, "gzip -dfq %s", strsave);
system(buf);
}
sprintf(strsave, "%s%s", PLAYER_DIR, capitalize(name));
if ((fp = open_read(strsave)) != NULL)
{
int iNest;
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 != '#')
{
bug("Load_char_obj: # not found.");
break;
}
word = read_word(fp);
if (!str_cmp(word, "PLAYER"))
read_char(ch, fp);
else if (!str_cmp(word, "OBJECT"))
read_obj(ch, fp, FALSE);
else if (!str_cmp(word, "O"))
read_obj(ch, fp, FALSE);
else if (!str_cmp(word, "PET"))
read_pet(ch, fp);
else if (!str_cmp(word, "DESC"))
read_descriptor(d, fp);
else if (!str_cmp(word, "END"))
break;
else
{
bug("Load_char_obj: bad section.");
break;
}
}
close_read(fp);
}
/* initialize race */
if (found)
{
if (ch->race == NULL)
ch->race = default_race;
ch->size = ch->race->size;
ch->dam_type = 17; /*punch */
for (i = 0; i < 5; 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;
if (ch->war && war_info.status == WAR_OFF)
free_warlist(ch->war);
if (ch->gquest && gquest_info.running == GQUEST_OFF)
free_gqlist(ch->gquest);
/* Change this to set player levels when changing max level
The first number is the OLD max level, the second is the
NEW max level, and the third is the new version that should be
in the pfile after the change. */
set_player_level(ch, 0, 0, 0);
}
return found;
}
/*
* Read in a char.
*/
void read_char(CHAR_DATA * ch, READ_DATA * 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;
sprintf(buf, "Loading %s.", ch->name);
log_string(buf);
for (;;)
{
word = steof(fp) ? "End" : read_word(fp);
fMatch = FALSE;
switch (UPPER(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(ch->armor, 4, 100);
fMatch = TRUE;
break;
}
if (!str_cmp(word, "AffD"))
{
AFFECT_DATA *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->first_affect, ch->last_affect, next, prev);
fMatch = TRUE;
break;
}
if (!str_cmp(word, "Affc"))
{
AFFECT_DATA *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->first_affect, ch->last_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 < MAX_STATS; stat++)
ch->mod_stat[stat] = read_number(fp);
}
else
read_array(ch->mod_stat, MAX_STATS, 3);
fMatch = TRUE;
break;
}
if (!str_cmp(word, "AttrPerm") || !str_cmp(word, "Attr"))
{
if (ch->version < 9)
{
int stat;
for (stat = 0; stat < MAX_STATS; stat++)
ch->perm_stat[stat] = read_number(fp);
}
else
read_array(ch->perm_stat, MAX_STATS, 3);
fMatch = TRUE;
break;
}
break;
case 'B':
KEYS("Bamfin", ch->pcdata->bamfin);
KEYS("Bamfout", ch->pcdata->bamfout);
KEYS("Bin", ch->pcdata->bamfin);
KEYS("Bout", ch->pcdata->bamfout);
KEY("BankS", ch->pcdata->silver_bank, read_number(fp));
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;
}
/* Read in board status */
if (!str_cmp(word, "Boards"))
{
int i, num = read_number(fp); /* number of boards saved */
char *boardname;
for (; num; num--) /* for each of the board saved */
{
boardname = read_word(fp);
i = board_lookup(boardname); /* find board number */
if (i == BOARD_NOTFOUND) /* Does board still exist ? */
{
sprintf(buf,
"read_char: %s had unknown board name: %s. Skipped.",
ch->name, boardname);
log_string(buf);
read_number(fp); /* read last_note and skip info */
}
else /* Save it */
ch->pcdata->last_note[i] = read_number(fp);
} /* for */
fMatch = TRUE;
break;
} /* Boards */
break;
case 'C':
if (!str_cmp(word, "Cla") || !str_cmp(word, "Class"))
{
int iClass = 0;
bool invalid = FALSE;
fMatch = TRUE;
for (iClass = 0; iClass < MAX_MCLASS; iClass++)
ch->Class[iClass] = -1;
for (iClass = 0; iClass < MAX_MCLASS; iClass++)
{
ch->Class[iClass] = read_number(fp);
if (ch->Class[iClass] == -1)
break;
}
for (iClass = 0; iClass < MAX_MCLASS; iClass++)
{
if (invalid)
{
ch->Class[iClass - 1] = ch->Class[iClass];
ch->Class[iClass] = -1;
continue;
}
if (ch->Class[iClass] < 0 || ch->Class[iClass] >= maxClass)
{
ch->Class[iClass] = -1;
invalid = TRUE;
}
}
break;
}
KEY_SFUN("Clan", ch->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(ch->pcdata->condition, 4, 0);
fMatch = TRUE;
break;
}
KEY("Comm", ch->comm, read_flag(fp));
KEY("Cols", ch->columns, read_number(fp));
if (!str_cmp(word, "Colo"))
{
if (ch->version >= 8)
{
int i, j, num = read_number(fp);
for (i = 0; i < UMIN(num, MAX_CUSTOM_COLOUR); i++)
{
if (i >= MAX_CUSTOM_COLOUR)
break;
for (j = 0; j < CT_MAX; j++)
ch->pcdata->colour[i][j] = read_number(fp);
}
}
read_to_eol(fp);
fMatch = TRUE;
break;
}
break;
case 'D':
KEY("Damroll", ch->damroll, read_number(fp));
KEY("Dam", ch->damroll, read_number(fp));
KEYS("Description", ch->description);
KEYS("Desc", ch->description);
KEY_SFUN("Deity", ch->deity, deity_lookup);
break;
case 'E':
if (!str_cmp(word, "End"))
{
if (ch->in_room == NULL)
ch->in_room = get_room_index(ROOM_VNUM_LIMBO);
/* adjust hp mana move up -- here for speed's sake */
percent = (current_time - lastlogoff) * 25 / (2 * 60 * 60);
percent = UMIN(percent, 100);
if (percent > 0 && !IS_AFFECTED(ch, AFF_POISON)
&& !IS_AFFECTED(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"))
{
new_gqlist(ch);
read_array(ch->gquest->gq_mobs, gquest_info.mob_count, -1);
fMatch = TRUE;
break;
}
if (!str_cmp(word, "Group") || !str_cmp(word, "Gr"))
{
int gn;
char *temp;
temp = read_word(fp);
gn = group_lookup(temp);
/* gn = group_lookup( read_word( fp ) ); */
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);
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_ARRAY("Homes", ch->pcdata->home, MAX_HOUSE_ROOMS, 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;
}
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));
KEYS("LongDescr", ch->long_descr);
KEYS("LnD", ch->long_descr);
break;
case 'N':
KEYS("Name", ch->name);
KEY_IGNORE("Not");
break;
case 'P':
KEYS("Password", ch->pcdata->pwd);
KEYS("Pass", ch->pcdata->pwd);
KEY("Played", ch->played, read_number(fp));
KEY("Plyd", ch->played, read_number(fp));
KEY("Points", ch->pcdata->points, read_number(fp));
KEY("Pnts", ch->pcdata->points, read_number(fp));
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));
KEYS("Prompt", ch->prompt);
KEYS("Prom", ch->prompt);
break;
case 'Q':
KEY("QuestPnts", ch->pcdata->questpoints, read_number(fp));
KEY("QuestNext", ch->pcdata->nextquest, read_number(fp));
KEY("QuestCount", ch->pcdata->countdown, read_number(fp));
KEY("QuestLoc", ch->pcdata->questloc, read_number(fp));
KEY("QuestObj", ch->pcdata->questobj, read_number(fp));
KEY("QuestGiver", ch->pcdata->questgiver, read_number(fp));
KEY("QuestMob", ch->pcdata->questmob, 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_number(fp));
KEYS("ShortDescr", ch->short_descr);
KEYS("ShD", ch->short_descr);
KEY("Sec", ch->pcdata->security, read_number(fp)); /* OLC */
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);
/* sn = skill_lookup( read_word( fp ) ); */
if (sn < 0)
{
bugf("read_char: unknown skill. (%s)", temp);
}
else
ch->pcdata->learned[sn] = value;
fMatch = TRUE;
break;
}
break;
case 'T':
KEY("TrueSex", ch->pcdata->true_sex, read_number(fp));
KEY("TSex", ch->pcdata->true_sex, read_number(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_string(ch->pcdata->title, buf);
}
fMatch = TRUE;
break;
}
break;
case 'V':
KEY("Version", ch->version, read_number(fp));
KEY("Vers", ch->version, read_number(fp));
KEY_DO("Vnum", (ch->pIndexData = get_mob_index(read_number(fp))));
break;
case 'W':
if (!str_cmp(word, "WarInfo"))
{
new_warlist(ch);
ch->war->hit = read_number(fp);
ch->war->mana = read_number(fp);
ch->war->move = read_number(fp);
ch->war->flags = read_flag(fp);
fMatch = TRUE;
break;
}
KEY("Wimpy", ch->wimpy, read_number(fp));
KEY("Wimp", ch->wimpy, read_number(fp));
KEY("Wizn", ch->wiznet, read_flag(fp));
KEYS("WhoD", ch->pcdata->who_descr);
break;
}
if (!fMatch)
{
bugf("read_char: no match for %s->%s.", ch->name, word);
read_to_eol(fp);
}
}
}
/* load a pet from the forgotten reaches */
void read_pet(CHAR_DATA * ch, READ_DATA * fp)
{
const char *word;
CHAR_DATA *pet;
bool fMatch;
int lastlogoff = current_time;
int percent;
/* first entry had BETTER be the vnum or we barf */
word = steof(fp) ? "END" : read_word(fp);
if (!str_cmp(word, "Vnum"))
{
vnum_t vnum;
vnum = read_number(fp);
if (get_mob_index(vnum) == NULL)
{
bugf("Fread_pet: bad vnum %ld.", vnum);
pet = create_mobile(get_mob_index(MOB_VNUM_FIDO));
}
else
pet = create_mobile(get_mob_index(vnum));
}
else
{
bug("Fread_pet: no vnum in file.");
pet = create_mobile(get_mob_index(MOB_VNUM_FIDO));
}
for (;;)
{
word = steof(fp) ? "END" : read_word(fp);
fMatch = FALSE;
switch (UPPER(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(pet->armor, 4, 100);
fMatch = TRUE;
break;
}
if (!str_cmp(word, "AffD"))
{
AFFECT_DATA *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->first_affect, pet->last_affect, next, prev);
fMatch = TRUE;
break;
}
if (!str_cmp(word, "Affc"))
{
AFFECT_DATA *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->first_affect, pet->last_affect, next, prev);
fMatch = TRUE;
break;
}
if (!str_cmp(word, "AMod"))
{
if (pet->version < 9)
{
int stat;
for (stat = 0; stat < MAX_STATS; stat++)
pet->mod_stat[stat] = read_number(fp);
}
else
read_array(pet->mod_stat, MAX_STATS, 0);
fMatch = TRUE;
break;
}
if (!str_cmp(word, "Attr"))
{
if (ch->version < 9)
{
int stat;
for (stat = 0; stat < MAX_STATS; stat++)
pet->perm_stat[stat] = read_number(fp);
}
else
read_array(pet->perm_stat, MAX_STATS, 3);
fMatch = TRUE;
break;
}
break;
case 'C':
KEY_SFUN("Clan", pet->clan, clan_lookup);
KEY("Comm", pet->comm, read_flag(fp));
break;
case 'D':
KEY("Dam", pet->damroll, read_number(fp));
KEYS("Desc", pet->description);
break;
case 'E':
if (!str_cmp(word, "End"))
{
pet->leader = ch;
pet->master = ch;
ch->pet = pet;
/* adjust hp mana move up -- here for speed's sake */
percent = (current_time - lastlogoff) * 25 / (2 * 60 * 60);
if (percent > 0 && !IS_AFFECTED(ch, AFF_POISON)
&& !IS_AFFECTED(ch, AFF_PLAGUE))
{
percent = UMIN(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));
KEYS("LnD", pet->long_descr);
KEY("LogO", lastlogoff, read_number(fp));
break;
case 'N':
KEYS("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_number(fp));
KEYS("ShD", pet->short_descr);
KEY("Silv", pet->silver, read_number(fp));
break;
if (!fMatch)
{
bug("Fread_pet: no match.");
read_to_eol(fp);
}
}
}
}
EXTERN OBJ_DATA *obj_free;
void read_obj(CHAR_DATA * ch, READ_DATA * fp, bool pit)
{
OBJ_DATA *obj;
const char *word;
int iNest;
bool fMatch;
bool fNest;
bool fVnum;
bool first;
bool new_format; /* to prevent errors */
bool make_new; /* update object */
vnum_t where;
fVnum = FALSE;
obj = NULL;
first = TRUE; /* used to counter fp offset */
new_format = FALSE;
make_new = FALSE;
word = steof(fp) ? "End" : read_word(fp);
if (!str_cmp(word, "Vnum"))
{
vnum_t vnum;
first = FALSE; /* fp will be in right place */
vnum = read_number(fp);
if (get_obj_index(vnum) == NULL)
{
bugf("Fread_obj: bad vnum %ld.", vnum);
}
else
{
obj = create_object(get_obj_index(vnum), -1);
new_format = TRUE;
fVnum = TRUE;
}
}
if (obj == NULL) /* either not found or old style */
{
obj = new_obj();
obj->name = str_dup("");
obj->short_descr = str_dup("");
obj->description = str_dup("");
}
fNest = FALSE;
fVnum = TRUE;
iNest = 0;
where = 0;
for (;;)
{
if (first)
first = FALSE;
else
word = steof(fp) ? "End" : read_word(fp);
fMatch = FALSE;
switch (UPPER(word[0]))
{
case '*':
fMatch = TRUE;
read_to_eol(fp);
break;
case 'A':
if (!str_cmp(word, "AffD"))
{
AFFECT_DATA *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->first_affect, obj->last_affect, next, prev);
fMatch = TRUE;
break;
}
if (!str_cmp(word, "Affc"))
{
AFFECT_DATA *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->first_affect, obj->last_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':
KEYS("Description", obj->description);
KEYS("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"))
{
EXTRA_DESCR_DATA *ed;
ed = new_extra_descr();
ed->keyword = read_string(fp);
ed->description = read_string(fp);
LINK(ed, obj->first_extra_descr, obj->last_extra_descr, next,
prev);
fMatch = TRUE;
}
if (!str_cmp(word, "End"))
{
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, object_first, object_last, 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)
{
if (!ch)
{
if (!pit)
{
ROOM_INDEX_DATA *Room;
CORPSE_DATA *c;
c = new_corpse();
c->corpse = obj;
LINK(c, corpse_first, corpse_last, next, prev);
if ((Room = get_room_index(where)) == NULL)
Room = get_room_index(ROOM_VNUM_MORGUE);
obj_to_room(obj, Room);
}
else
{
OBJ_DATA *pit;
if (!(pit = get_donation_pit()))
free_obj(obj);
else
obj_to_obj(obj, pit);
}
}
else
obj_to_char(obj, ch);
}
else
obj_to_obj(obj, rgObjNest[iNest - 1]);
return;
}
}
break;
case 'I':
KEY("ItemType", obj->item_type, read_number(fp));
KEY("Ityp", obj->item_type, read_number(fp));
break;
case 'L':
KEY("Level", obj->level, read_number(fp));
KEY("Lev", obj->level, read_number(fp));
break;
case 'N':
KEYS("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;
}
KEYS("Owner", obj->owner);
break;
case 'S':
KEYS("ShortDescr", obj->short_descr);
KEYS("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;
vnum = read_number(fp);
if ((obj->pIndexData = get_obj_index(vnum)) == NULL)
bugf("Fread_obj: bad vnum %ld.", vnum);
else
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_DATA * d, READ_DATA * fp)
{
const char *word;
bool fMatch;
for (;;)
{
word = steof(fp) ? "END" : read_word(fp);
fMatch = FALSE;
if (crs_info.status != CRS_COPYOVER_RECOVER)
{
if (!str_cmp(word, "End"))
return;
else
{
read_to_eol(fp);
continue;
}
}
switch (UPPER(word[0]))
{
case '*':
fMatch = TRUE;
read_to_eol(fp);
break;
case 'B':
KEY("ByteN", d->bytes_normal, read_number(fp));
#if !defined(NO_MCCP)
KEY("ByteC", d->bytes_compressed, read_number(fp));
#endif
break;
case 'C':
KEY("Connected", d->connected, read_enum(connect_t, fp));
#if !defined(NO_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"))
return;
break;
case 'F':
KEY("Flags", d->d_flags, read_flag(fp));
break;
case 'H':
KEYS("Host", d->host);
break;
case 'I':
KEY_DO("IMPver", d->imp_vers = atof(read_word(fp)));
break;
case 'K':
KEY("Keycode", d->portal.keycode, read_number(fp));
break;
case 'M':
KEYS("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)));
KEYS("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':
KEYS_CPY("PortVer", d->portal.version);
KEY_DO("Pueblo", d->pueblo_vers = atof(read_word(fp)));
break;
case 'S':
KEY("ScrW", d->scr_width, read_number(fp));
KEY("ScrH", d->scr_height, read_number(fp));
break;
case 'T':
KEYS_CPY("TType", d->ttype);
break;
}
if (!fMatch)
{
bugf("no match for %s.", word);
read_to_eol(fp);
}
}
}
void save_corpses(void)
{
WRITE_DATA *fp;
CORPSE_DATA *c;
if ((fp = open_write(CORPSE_FILE)) == 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)
fwrite_obj(NULL, c->corpse, fp->stream, 0, "C");
else
update_corpses(c->corpse, TRUE);
}
fprintf(fp->stream, "#END\n");
fflush(fp->stream);
close_write(fp);
}
return;
}
void load_corpses(void)
{
READ_DATA *fp;
if ((fp = open_read(CORPSE_FILE)) == 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 != '#')
{
bug("load_corpses: # not found.");
break;
}
word = read_word(fp);
if ((!str_cmp(word, "CORPSE")) || (!str_cmp(word, "C")))
read_obj(NULL, fp, FALSE);
else if (!str_cmp(word, "END"))
break;
else
{
bug("load_corpses: bad section.");
break;
}
}
close_read(fp);
}
return;
}
void update_corpses(OBJ_DATA * obj, bool pdelete)
{
if (obj && obj->item_type == ITEM_CORPSE_PC)
{
CORPSE_DATA *c;
for (c = corpse_first; c != NULL; c = c->next)
if (c->corpse == obj)
break;
if (c != NULL)
{
if (pdelete)
{
UNLINK(c, corpse_first, corpse_last, next, prev);
free_corpse(c);
}
save_corpses();
}
else if (obj->first_content != NULL && obj->in_room != NULL)
{
c = new_corpse();
c->corpse = obj;
LINK(c, corpse_first, corpse_last, next, prev);
save_corpses();
}
}
return;
}
void checkcorpse(CHAR_DATA * ch)
{
CORPSE_DATA *c;
bool found = FALSE;
int count = 0;
if (!ch || IS_NPC(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, "\n\r{f{RWARNING:{x {WYou have %d corpse%s in the game.{x",
count, count > 1 ? "s" : "");
sprintf(log_buf, "%s has %d corpse%s in the game.", ch->name, count,
count > 1 ? "s" : "");
log_string(log_buf);
wiznet(log_buf, NULL, NULL, 0, 0, 0);
}
}