forked from kyonshi/grenzland-mud
Adding of the appropropriate structs to the plrtoascii utility. Incoorporation of changes from old circlemud CVS snapshot this also gives more info on SYSERRors. cleanup of zmalloc language (shit->tmp) PRF_ROOMFLAGS has been renamed to PRF_SHOWVNUMS for clarity. "Deaf" has been changed to "No_shout" in preference_bits, for clarity. Addition of hindex (help index) command. who command added argument -g and -l to check who are grouped (and leaders) toggle has been expanded, and the commands nohassle, holylight, color, buildwalk, syslog and roomflags were moved to toggles. renaming of some vars in dg files (xxx -> dg_xxx) for clarity. set <player> password can now be used by other people than the first implementor - id check removed. fix of a couple of minor bugs: - crash bug related to freeing a pointer twice - ascii pfiles bug. - host was not updated correctly after switch to ascii pfiles. Todo: make "who #-#", "who #-" and "who -#" all work as "who -l #-#" did before Remove redundant commands which are now toggles. Make script variables save to pfile instead of its own file.
852 lines
25 KiB
C
852 lines
25 KiB
C
/* ************************************************************************
|
|
* File: players.c Part of CircleMUD *
|
|
* Usage: Player loading/saving and utility routines *
|
|
* *
|
|
* All rights reserved. See license.doc for complete information. *
|
|
* *
|
|
* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
|
|
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. *
|
|
************************************************************************ */
|
|
|
|
#include "conf.h"
|
|
#include "sysdep.h"
|
|
|
|
#include "structs.h"
|
|
#include "utils.h"
|
|
#include "db.h"
|
|
#include "handler.h"
|
|
#include "pfdefaults.h"
|
|
#include "dg_scripts.h"
|
|
#include "comm.h"
|
|
#include "genmob.h"
|
|
|
|
#define LOAD_HIT 0
|
|
#define LOAD_MANA 1
|
|
#define LOAD_MOVE 2
|
|
#define LOAD_STRENGTH 3
|
|
|
|
/* local functions */
|
|
void build_player_index(void);
|
|
int sprintascii(char *out, bitvector_t bits);
|
|
void tag_argument(char *argument, char *tag);
|
|
void load_affects(FILE *fl, struct char_data *ch);
|
|
void load_skills(FILE *fl, struct char_data *ch);
|
|
void load_HMVS(struct char_data *ch, const char *line, int mode);
|
|
|
|
/* external fuctions */
|
|
bitvector_t asciiflag_conv(char *flag);
|
|
void save_char_vars(struct char_data *ch);
|
|
|
|
/* 'global' vars */
|
|
struct player_index_element *player_table = NULL; /* index to plr file */
|
|
int top_of_p_table = 0; /* ref to top of table */
|
|
int top_of_p_file = 0; /* ref of size of p file */
|
|
long top_idnum = 0; /* highest idnum in use */
|
|
|
|
|
|
/* external ASCII Player Files vars */
|
|
extern struct pclean_criteria_data pclean_criteria[];
|
|
|
|
|
|
/* ASCII Player Files - set this TRUE if you want poofin/poofout
|
|
strings saved in the pfiles
|
|
*/
|
|
#define ASCII_SAVE_POOFS FALSE
|
|
|
|
|
|
/*************************************************************************
|
|
* stuff related to the player index *
|
|
*************************************************************************/
|
|
|
|
|
|
/* new version to build player index for ASCII Player Files */
|
|
/* generate index table for the player file */
|
|
void build_player_index(void)
|
|
{
|
|
int rec_count = 0, i;
|
|
FILE *plr_index;
|
|
char index_name[40], line[256], bits[64];
|
|
char arg2[80];
|
|
|
|
sprintf(index_name, "%s%s", LIB_PLRFILES, INDEX_FILE);
|
|
if (!(plr_index = fopen(index_name, "r"))) {
|
|
top_of_p_table = -1;
|
|
log("No player index file! First new char will be IMP!");
|
|
return;
|
|
}
|
|
|
|
while (get_line(plr_index, line))
|
|
if (*line != '~')
|
|
rec_count++;
|
|
rewind(plr_index);
|
|
|
|
if (rec_count == 0) {
|
|
player_table = NULL;
|
|
top_of_p_table = -1;
|
|
return;
|
|
}
|
|
|
|
CREATE(player_table, struct player_index_element, rec_count);
|
|
for (i = 0; i < rec_count; i++) {
|
|
get_line(plr_index, line);
|
|
sscanf(line, "%ld %s %d %s %d", &player_table[i].id, arg2,
|
|
&player_table[i].level, bits, (int *)&player_table[i].last);
|
|
CREATE(player_table[i].name, char, strlen(arg2) + 1);
|
|
strcpy(player_table[i].name, arg2);
|
|
player_table[i].flags = asciiflag_conv(bits);
|
|
top_idnum = MAX(top_idnum, player_table[i].id);
|
|
}
|
|
|
|
fclose(plr_index);
|
|
top_of_p_file = top_of_p_table = i - 1;
|
|
}
|
|
|
|
|
|
/*
|
|
* Create a new entry in the in-memory index table for the player file.
|
|
* If the name already exists, by overwriting a deleted character, then
|
|
* we re-use the old position.
|
|
*/
|
|
int create_entry(char *name)
|
|
{
|
|
int i, pos;
|
|
|
|
if (top_of_p_table == -1) { /* no table */
|
|
CREATE(player_table, struct player_index_element, 1);
|
|
pos = top_of_p_table = 0;
|
|
} else if ((pos = get_ptable_by_name(name)) == -1) { /* new name */
|
|
i = ++top_of_p_table + 1;
|
|
|
|
RECREATE(player_table, struct player_index_element, i);
|
|
pos = top_of_p_table;
|
|
}
|
|
|
|
CREATE(player_table[pos].name, char, strlen(name) + 1);
|
|
|
|
/* copy lowercase equivalent of name to table field */
|
|
for (i = 0; (player_table[pos].name[i] = LOWER(name[i])); i++)
|
|
/* Nothing */;
|
|
|
|
/* clear the bitflag in case we have garbage data */
|
|
player_table[pos].flags = 0;
|
|
|
|
return (pos);
|
|
}
|
|
|
|
|
|
/* This function necessary to save a seperate ASCII player index */
|
|
void save_player_index(void)
|
|
{
|
|
int i;
|
|
char index_name[50], bits[64];
|
|
FILE *index_file;
|
|
|
|
sprintf(index_name, "%s%s", LIB_PLRFILES, INDEX_FILE);
|
|
if (!(index_file = fopen(index_name, "w"))) {
|
|
log("SYSERR: Could not write player index file");
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i <= top_of_p_table; i++)
|
|
if (*player_table[i].name) {
|
|
sprintascii(bits, player_table[i].flags);
|
|
fprintf(index_file, "%ld %s %d %s %ld\n", player_table[i].id,
|
|
player_table[i].name, player_table[i].level, *bits ? bits : "0",
|
|
player_table[i].last);
|
|
}
|
|
fprintf(index_file, "~\n");
|
|
|
|
fclose(index_file);
|
|
}
|
|
|
|
|
|
void free_player_index(void)
|
|
{
|
|
int tp;
|
|
|
|
if (!player_table)
|
|
return;
|
|
|
|
for (tp = 0; tp <= top_of_p_table; tp++)
|
|
if (player_table[tp].name)
|
|
free(player_table[tp].name);
|
|
|
|
free(player_table);
|
|
player_table = NULL;
|
|
top_of_p_table = 0;
|
|
}
|
|
|
|
|
|
long get_ptable_by_name(const char *name)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i <= top_of_p_table; i++)
|
|
if (!str_cmp(player_table[i].name, name))
|
|
return (i);
|
|
|
|
return (-1);
|
|
}
|
|
|
|
|
|
long get_id_by_name(const char *name)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i <= top_of_p_table; i++)
|
|
if (!str_cmp(player_table[i].name, name))
|
|
return (player_table[i].id);
|
|
|
|
return (-1);
|
|
}
|
|
|
|
|
|
char *get_name_by_id(long id)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i <= top_of_p_table; i++)
|
|
if (player_table[i].id == id)
|
|
return (player_table[i].name);
|
|
|
|
return (NULL);
|
|
}
|
|
|
|
|
|
/*************************************************************************
|
|
* stuff related to the save/load player system *
|
|
*************************************************************************/
|
|
|
|
|
|
#define NUM_OF_SAVE_THROWS 5
|
|
|
|
/* new load_char reads ASCII Player Files */
|
|
/* Load a char, TRUE if loaded, FALSE if not */
|
|
int load_char(const char *name, struct char_data *ch)
|
|
{
|
|
int id, i;
|
|
FILE *fl;
|
|
char fname[40];
|
|
char buf[128], buf2[128], line[MAX_INPUT_LENGTH + 1], tag[6];
|
|
|
|
if ((id = get_ptable_by_name(name)) < 0)
|
|
return (-1);
|
|
else {
|
|
if (!get_filename(fname, sizeof(fname), PLR_FILE, player_table[id].name))
|
|
return (-1);
|
|
if (!(fl = fopen(fname, "r"))) {
|
|
mudlog(NRM, LVL_GOD, TRUE, "SYSERR: Couldn't open player file %s", fname);
|
|
return (-1);
|
|
}
|
|
|
|
/* character initializations */
|
|
/* initializations necessary to keep some things straight */
|
|
ch->affected = NULL;
|
|
for (i = 1; i <= MAX_SKILLS; i++)
|
|
GET_SKILL(ch, i) = 0;
|
|
GET_SEX(ch) = PFDEF_SEX;
|
|
GET_CLASS(ch) = PFDEF_CLASS;
|
|
GET_LEVEL(ch) = PFDEF_LEVEL;
|
|
GET_HOME(ch) = PFDEF_HOMETOWN;
|
|
GET_HEIGHT(ch) = PFDEF_HEIGHT;
|
|
GET_WEIGHT(ch) = PFDEF_WEIGHT;
|
|
GET_ALIGNMENT(ch) = PFDEF_ALIGNMENT;
|
|
PLR_FLAGS(ch) = PFDEF_PLRFLAGS;
|
|
AFF_FLAGS(ch) = PFDEF_AFFFLAGS;
|
|
for (i = 0; i < NUM_OF_SAVE_THROWS; i++)
|
|
GET_SAVE(ch, i) = PFDEF_SAVETHROW;
|
|
GET_LOADROOM(ch) = PFDEF_LOADROOM;
|
|
GET_INVIS_LEV(ch) = PFDEF_INVISLEV;
|
|
GET_FREEZE_LEV(ch) = PFDEF_FREEZELEV;
|
|
GET_WIMP_LEV(ch) = PFDEF_WIMPLEV;
|
|
GET_COND(ch, FULL) = PFDEF_HUNGER;
|
|
GET_COND(ch, THIRST) = PFDEF_THIRST;
|
|
GET_COND(ch, DRUNK) = PFDEF_DRUNK;
|
|
GET_BAD_PWS(ch) = PFDEF_BADPWS;
|
|
PRF_FLAGS(ch) = PFDEF_PREFFLAGS;
|
|
GET_PRACTICES(ch) = PFDEF_PRACTICES;
|
|
GET_GOLD(ch) = PFDEF_GOLD;
|
|
GET_BANK_GOLD(ch) = PFDEF_BANK;
|
|
GET_EXP(ch) = PFDEF_EXP;
|
|
GET_HITROLL(ch) = PFDEF_HITROLL;
|
|
GET_DAMROLL(ch) = PFDEF_DAMROLL;
|
|
GET_AC(ch) = PFDEF_AC;
|
|
ch->real_abils.str = PFDEF_STR;
|
|
ch->real_abils.str_add = PFDEF_STRADD;
|
|
ch->real_abils.dex = PFDEF_DEX;
|
|
ch->real_abils.intel = PFDEF_INT;
|
|
ch->real_abils.wis = PFDEF_WIS;
|
|
ch->real_abils.con = PFDEF_CON;
|
|
ch->real_abils.cha = PFDEF_CHA;
|
|
GET_HIT(ch) = PFDEF_HIT;
|
|
GET_MAX_HIT(ch) = PFDEF_MAXHIT;
|
|
GET_MANA(ch) = PFDEF_MANA;
|
|
GET_MAX_MANA(ch) = PFDEF_MAXMANA;
|
|
GET_MOVE(ch) = PFDEF_MOVE;
|
|
GET_MAX_MOVE(ch) = PFDEF_MAXMOVE;
|
|
GET_OLC_ZONE(ch) = PFDEF_OLC;
|
|
GET_HOST(ch) = NULL;
|
|
GET_PAGE_LENGTH(ch) = PFDEF_PAGELENGTH;
|
|
|
|
while (get_line(fl, line)) {
|
|
tag_argument(line, tag);
|
|
|
|
switch (*tag) {
|
|
case 'A':
|
|
if (!strcmp(tag, "Ac ")) GET_AC(ch) = atoi(line);
|
|
else if (!strcmp(tag, "Act ")) PLR_FLAGS(ch) = asciiflag_conv(line);
|
|
else if (!strcmp(tag, "Aff ")) AFF_FLAGS(ch) = asciiflag_conv(line);
|
|
else if (!strcmp(tag, "Affs")) load_affects(fl, ch);
|
|
else if (!strcmp(tag, "Alin")) GET_ALIGNMENT(ch) = atoi(line);
|
|
break;
|
|
|
|
case 'B':
|
|
if (!strcmp(tag, "Badp")) GET_BAD_PWS(ch) = atoi(line);
|
|
else if (!strcmp(tag, "Bank")) GET_BANK_GOLD(ch) = atoi(line);
|
|
else if (!strcmp(tag, "Brth")) ch->player.time.birth = atol(line);
|
|
break;
|
|
|
|
case 'C':
|
|
if (!strcmp(tag, "Cha ")) ch->real_abils.cha = atoi(line);
|
|
else if (!strcmp(tag, "Clas")) GET_CLASS(ch) = atoi(line);
|
|
else if (!strcmp(tag, "Con ")) ch->real_abils.con = atoi(line);
|
|
break;
|
|
|
|
case 'D':
|
|
if (!strcmp(tag, "Desc")) ch->player.description = fread_string(fl, buf2);
|
|
else if (!strcmp(tag, "Dex ")) ch->real_abils.dex = atoi(line);
|
|
else if (!strcmp(tag, "Drnk")) GET_COND(ch, DRUNK) = atoi(line);
|
|
else if (!strcmp(tag, "Drol")) GET_DAMROLL(ch) = atoi(line);
|
|
break;
|
|
|
|
case 'E':
|
|
if (!strcmp(tag, "Exp ")) GET_EXP(ch) = atoi(line);
|
|
break;
|
|
|
|
case 'F':
|
|
if (!strcmp(tag, "Frez")) GET_FREEZE_LEV(ch) = atoi(line);
|
|
break;
|
|
|
|
case 'G':
|
|
if (!strcmp(tag, "Gold")) GET_GOLD(ch) = atoi(line);
|
|
break;
|
|
|
|
case 'H':
|
|
if (!strcmp(tag, "Hit ")) load_HMVS(ch, line, LOAD_HIT);
|
|
else if (!strcmp(tag, "Hite")) GET_HEIGHT(ch) = atoi(line);
|
|
else if (!strcmp(tag, "Home")) GET_HOME(ch) = atoi(line);
|
|
else if (!strcmp(tag, "Host")) GET_HOST(ch) = strdup(line);
|
|
else if (!strcmp(tag, "Hrol")) GET_HITROLL(ch) = atoi(line);
|
|
else if (!strcmp(tag, "Hung")) GET_COND(ch, FULL) = atoi(line);
|
|
break;
|
|
|
|
case 'I':
|
|
if (!strcmp(tag, "Id ")) GET_IDNUM(ch) = atol(line);
|
|
else if (!strcmp(tag, "Int ")) ch->real_abils.intel = atoi(line);
|
|
else if (!strcmp(tag, "Invs")) GET_INVIS_LEV(ch) = atoi(line);
|
|
break;
|
|
|
|
case 'L':
|
|
if (!strcmp(tag, "Last")) ch->player.time.logon = atol(line);
|
|
else if (!strcmp(tag, "Lern")) GET_PRACTICES(ch) = atoi(line);
|
|
else if (!strcmp(tag, "Levl")) GET_LEVEL(ch) = atoi(line);
|
|
break;
|
|
|
|
case 'M':
|
|
if (!strcmp(tag, "Mana")) load_HMVS(ch, line, LOAD_MANA);
|
|
else if (!strcmp(tag, "Move")) load_HMVS(ch, line, LOAD_MOVE);
|
|
break;
|
|
|
|
case 'N':
|
|
if (!strcmp(tag, "Name")) GET_PC_NAME(ch) = strdup(line);
|
|
break;
|
|
|
|
case 'O':
|
|
if (!strcmp(tag, "Olc")) GET_OLC_ZONE(ch) = atoi(line);
|
|
break;
|
|
|
|
case 'P':
|
|
if (!strcmp(tag, "Page")) GET_PAGE_LENGTH(ch) = atoi(line);
|
|
else if (!strcmp(tag, "Pass")) strcpy(GET_PASSWD(ch), line);
|
|
else if (!strcmp(tag, "Plyd")) ch->player.time.played = atoi(line);
|
|
#ifdef ASCII_SAVE_POOFS
|
|
else if (!strcmp(tag, "PfIn")) POOFIN(ch) = strdup(line);
|
|
else if (!strcmp(tag, "PfOt")) POOFOUT(ch) = strdup(line);
|
|
#endif
|
|
else if (!strcmp(tag, "Pref")) PRF_FLAGS(ch) = asciiflag_conv(line);
|
|
break;
|
|
|
|
case 'R':
|
|
if (!strcmp(tag, "Room")) GET_LOADROOM(ch) = atoi(line);
|
|
break;
|
|
|
|
case 'S':
|
|
if (!strcmp(tag, "Sex ")) GET_SEX(ch) = atoi(line);
|
|
else if (!strcmp(tag, "Skil")) load_skills(fl, ch);
|
|
else if (!strcmp(tag, "Str ")) load_HMVS(ch, line, LOAD_STRENGTH);
|
|
break;
|
|
|
|
case 'T':
|
|
if (!strcmp(tag, "Thir")) GET_COND(ch, THIRST) = atoi(line);
|
|
else if (!strcmp(tag, "Thr1")) GET_SAVE(ch, 0) = atoi(line);
|
|
else if (!strcmp(tag, "Thr2")) GET_SAVE(ch, 1) = atoi(line);
|
|
else if (!strcmp(tag, "Thr3")) GET_SAVE(ch, 2) = atoi(line);
|
|
else if (!strcmp(tag, "Thr4")) GET_SAVE(ch, 3) = atoi(line);
|
|
else if (!strcmp(tag, "Thr5")) GET_SAVE(ch, 4) = atoi(line);
|
|
else if (!strcmp(tag, "Titl")) GET_TITLE(ch) = strdup(line);
|
|
break;
|
|
|
|
case 'W':
|
|
if (!strcmp(tag, "Wate")) GET_WEIGHT(ch) = atoi(line);
|
|
else if (!strcmp(tag, "Wimp")) GET_WIMP_LEV(ch) = atoi(line);
|
|
else if (!strcmp(tag, "Wis ")) ch->real_abils.wis = atoi(line);
|
|
break;
|
|
|
|
default:
|
|
sprintf(buf, "SYSERR: Unknown tag %s in pfile %s", tag, name);
|
|
}
|
|
}
|
|
}
|
|
|
|
affect_total(ch);
|
|
|
|
/* initialization for imms */
|
|
if (GET_LEVEL(ch) >= LVL_IMMORT) {
|
|
for (i = 1; i <= MAX_SKILLS; i++)
|
|
GET_SKILL(ch, i) = 100;
|
|
GET_COND(ch, FULL) = -1;
|
|
GET_COND(ch, THIRST) = -1;
|
|
GET_COND(ch, DRUNK) = -1;
|
|
}
|
|
fclose(fl);
|
|
return(id);
|
|
}
|
|
|
|
|
|
/* remove ^M's from file output */
|
|
/* There may be a similar function in Oasis (and I'm sure
|
|
it's part of obuild). Remove this if you get a
|
|
multiple definition error or if it you want to use a
|
|
substitute
|
|
*/
|
|
void kill_ems(char *str)
|
|
{
|
|
char *ptr1, *ptr2, *tmp;
|
|
|
|
tmp = str;
|
|
ptr1 = str;
|
|
ptr2 = str;
|
|
|
|
while (*ptr1) {
|
|
if ((*(ptr2++) = *(ptr1++)) == '\r')
|
|
if (*ptr1 == '\r')
|
|
ptr1++;
|
|
}
|
|
*ptr2 = '\0';
|
|
}
|
|
|
|
|
|
/*
|
|
* write the vital data of a player to the player file
|
|
*
|
|
* And that's it! No more fudging around with the load room.
|
|
*/
|
|
/* This is the ASCII Player Files save routine */
|
|
void save_char(struct char_data * ch)
|
|
{
|
|
FILE *fl;
|
|
char fname[40], bits[127], buf[MAX_STRING_LENGTH];
|
|
int i, id, save_index = FALSE;
|
|
struct affected_type *aff, tmp_aff[MAX_AFFECT];
|
|
struct obj_data *char_eq[NUM_WEARS];
|
|
|
|
if (IS_NPC(ch) || GET_PFILEPOS(ch) < 0)
|
|
return;
|
|
|
|
/*
|
|
* If ch->desc is not null, then we need to update some session data
|
|
* before saving.
|
|
*/
|
|
if (ch->desc) {
|
|
if (ch->desc->host && *ch->desc->host) {
|
|
if (!GET_HOST(ch))
|
|
GET_HOST(ch) = strdup(ch->desc->host);
|
|
else if (GET_HOST(ch) && strcmp(GET_HOST(ch), ch->desc->host)) {
|
|
free(GET_HOST(ch));
|
|
GET_HOST(ch) = strdup(ch->desc->host);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* We only update the time.played and time.logon if the character
|
|
* is playing.
|
|
*/
|
|
if (STATE(ch->desc) == CON_PLAYING) {
|
|
ch->player.time.played += time(0) - ch->player.time.logon;
|
|
ch->player.time.logon = time(0);
|
|
}
|
|
}
|
|
|
|
if (!get_filename(fname, sizeof(fname), PLR_FILE, GET_NAME(ch)))
|
|
return;
|
|
if (!(fl = fopen(fname, "w"))) {
|
|
mudlog(NRM, LVL_GOD, TRUE, "SYSERR: Couldn't open player file %s for write", fname);
|
|
return;
|
|
}
|
|
|
|
/* remove affects from eq and spells (from char_to_store) */
|
|
/* Unaffect everything a character can be affected by */
|
|
|
|
for (i = 0; i < NUM_WEARS; i++) {
|
|
if (GET_EQ(ch, i))
|
|
char_eq[i] = unequip_char(ch, i);
|
|
#ifndef NO_EXTRANEOUS_TRIGGERS
|
|
remove_otrigger(char_eq[i], ch);
|
|
#endif
|
|
else
|
|
char_eq[i] = NULL;
|
|
}
|
|
|
|
for (aff = ch->affected, i = 0; i < MAX_AFFECT; i++) {
|
|
if (aff) {
|
|
tmp_aff[i] = *aff;
|
|
tmp_aff[i].next = 0;
|
|
aff = aff->next;
|
|
} else {
|
|
tmp_aff[i].type = 0; /* Zero signifies not used */
|
|
tmp_aff[i].duration = 0;
|
|
tmp_aff[i].modifier = 0;
|
|
tmp_aff[i].location = 0;
|
|
tmp_aff[i].bitvector = 0;
|
|
tmp_aff[i].next = 0;
|
|
}
|
|
}
|
|
save_char_vars(ch);
|
|
|
|
/*
|
|
* remove the affections so that the raw values are stored; otherwise the
|
|
* effects are doubled when the char logs back in.
|
|
*/
|
|
|
|
while (ch->affected)
|
|
affect_remove(ch, ch->affected);
|
|
|
|
if ((i >= MAX_AFFECT) && aff && aff->next)
|
|
log("SYSERR: WARNING: OUT OF STORE ROOM FOR AFFECTED TYPES!!!");
|
|
|
|
ch->aff_abils = ch->real_abils;
|
|
|
|
/* end char_to_store code */
|
|
|
|
if (GET_NAME(ch)) fprintf(fl, "Name: %s\n", GET_NAME(ch));
|
|
if (GET_PASSWD(ch)) fprintf(fl, "Pass: %s\n", GET_PASSWD(ch));
|
|
if (GET_TITLE(ch)) fprintf(fl, "Titl: %s\n", GET_TITLE(ch));
|
|
if (ch->player.description && *ch->player.description) {
|
|
strcpy(buf, ch->player.description);
|
|
kill_ems(buf);
|
|
fprintf(fl, "Desc:\n%s~\n", buf);
|
|
}
|
|
#ifdef ASCII_SAVE_POOFS
|
|
if (POOFIN(ch)) fprintf(fl, "PfIn: %s\n", POOFIN(ch));
|
|
if (POOFOUT(ch)) fprintf(fl, "PfOt: %s\n", POOFOUT(ch));
|
|
#endif
|
|
if (GET_SEX(ch) != PFDEF_SEX) fprintf(fl, "Sex : %d\n", GET_SEX(ch));
|
|
if (GET_CLASS(ch) != PFDEF_CLASS) fprintf(fl, "Clas: %d\n", GET_CLASS(ch));
|
|
if (GET_LEVEL(ch) != PFDEF_LEVEL) fprintf(fl, "Levl: %d\n", GET_LEVEL(ch));
|
|
if (GET_HOME(ch) != PFDEF_HOMETOWN) fprintf(fl, "Home: %d\n", GET_HOME(ch));
|
|
|
|
fprintf(fl, "Id : %ld\n", GET_IDNUM(ch));
|
|
fprintf(fl, "Brth: %ld\n", ch->player.time.birth);
|
|
fprintf(fl, "Plyd: %d\n", ch->player.time.played);
|
|
fprintf(fl, "Last: %ld\n", ch->player.time.logon);
|
|
|
|
if (GET_HOST(ch)) fprintf(fl, "Host: %s\n", GET_HOST(ch));
|
|
if (GET_HEIGHT(ch) != PFDEF_HEIGHT) fprintf(fl, "Hite: %d\n", GET_HEIGHT(ch));
|
|
if (GET_WEIGHT(ch) != PFDEF_HEIGHT) fprintf(fl, "Wate: %d\n", GET_WEIGHT(ch));
|
|
if (GET_ALIGNMENT(ch) != PFDEF_ALIGNMENT) fprintf(fl, "Alin: %d\n", GET_ALIGNMENT(ch));
|
|
|
|
if (PLR_FLAGS(ch) != PFDEF_PLRFLAGS) {
|
|
sprintascii(bits, PLR_FLAGS(ch)); fprintf(fl, "Act : %s\n", bits);
|
|
}
|
|
if (AFF_FLAGS(ch) != PFDEF_AFFFLAGS) {
|
|
sprintascii(bits, AFF_FLAGS(ch)); fprintf(fl, "Aff : %s\n", bits);
|
|
}
|
|
if (PRF_FLAGS(ch) != PFDEF_PREFFLAGS) {
|
|
sprintascii(bits, PRF_FLAGS(ch)); fprintf(fl, "Pref: %s\n", bits);
|
|
}
|
|
|
|
if (GET_SAVE(ch, 0) != PFDEF_SAVETHROW) fprintf(fl, "Thr1: %d\n", GET_SAVE(ch, 0));
|
|
if (GET_SAVE(ch, 1) != PFDEF_SAVETHROW) fprintf(fl, "Thr2: %d\n", GET_SAVE(ch, 1));
|
|
if (GET_SAVE(ch, 2) != PFDEF_SAVETHROW) fprintf(fl, "Thr3: %d\n", GET_SAVE(ch, 2));
|
|
if (GET_SAVE(ch, 3) != PFDEF_SAVETHROW) fprintf(fl, "Thr4: %d\n", GET_SAVE(ch, 3));
|
|
if (GET_SAVE(ch, 4) != PFDEF_SAVETHROW) fprintf(fl, "Thr5: %d\n", GET_SAVE(ch, 4));
|
|
|
|
if (GET_WIMP_LEV(ch) != PFDEF_WIMPLEV) fprintf(fl, "Wimp: %d\n", GET_WIMP_LEV(ch));
|
|
if (GET_FREEZE_LEV(ch) != PFDEF_FREEZELEV) fprintf(fl, "Frez: %d\n", GET_FREEZE_LEV(ch));
|
|
if (GET_INVIS_LEV(ch) != PFDEF_INVISLEV) fprintf(fl, "Invs: %d\n", GET_INVIS_LEV(ch));
|
|
if (GET_LOADROOM(ch) != PFDEF_LOADROOM) fprintf(fl, "Room: %d\n", GET_LOADROOM(ch));
|
|
|
|
if (GET_BAD_PWS(ch) != PFDEF_BADPWS) fprintf(fl, "Badp: %d\n", GET_BAD_PWS(ch));
|
|
if (GET_PRACTICES(ch) != PFDEF_PRACTICES) fprintf(fl, "Lern: %d\n", GET_PRACTICES(ch));
|
|
|
|
if (GET_COND(ch, FULL) != PFDEF_HUNGER && GET_LEVEL(ch) < LVL_IMMORT) fprintf(fl, "Hung: %d\n", GET_COND(ch, FULL));
|
|
if (GET_COND(ch, THIRST) != PFDEF_THIRST && GET_LEVEL(ch) < LVL_IMMORT) fprintf(fl, "Thir: %d\n", GET_COND(ch, THIRST));
|
|
if (GET_COND(ch, DRUNK) != PFDEF_DRUNK && GET_LEVEL(ch) < LVL_IMMORT) fprintf(fl, "Drnk: %d\n", GET_COND(ch, DRUNK));
|
|
|
|
if (GET_HIT(ch) != PFDEF_HIT || GET_MAX_HIT(ch) != PFDEF_MAXHIT) fprintf(fl, "Hit : %d/%d\n", GET_HIT(ch), GET_MAX_HIT(ch));
|
|
if (GET_MANA(ch) != PFDEF_MANA || GET_MAX_MANA(ch) != PFDEF_MAXMANA) fprintf(fl, "Mana: %d/%d\n", GET_MANA(ch), GET_MAX_MANA(ch));
|
|
if (GET_MOVE(ch) != PFDEF_MOVE || GET_MAX_MOVE(ch) != PFDEF_MAXMOVE) fprintf(fl, "Move: %d/%d\n", GET_MOVE(ch), GET_MAX_MOVE(ch));
|
|
|
|
if (GET_STR(ch) != PFDEF_STR || GET_ADD(ch) != PFDEF_STRADD) fprintf(fl, "Str : %d/%d\n", GET_STR(ch), GET_ADD(ch));
|
|
|
|
|
|
if (GET_INT(ch) != PFDEF_INT) fprintf(fl, "Int : %d\n", GET_INT(ch));
|
|
if (GET_WIS(ch) != PFDEF_WIS) fprintf(fl, "Wis : %d\n", GET_WIS(ch));
|
|
if (GET_DEX(ch) != PFDEF_DEX) fprintf(fl, "Dex : %d\n", GET_DEX(ch));
|
|
if (GET_CON(ch) != PFDEF_CON) fprintf(fl, "Con : %d\n", GET_CON(ch));
|
|
if (GET_CHA(ch) != PFDEF_CHA) fprintf(fl, "Cha : %d\n", GET_CHA(ch));
|
|
|
|
if (GET_AC(ch) != PFDEF_AC) fprintf(fl, "Ac : %d\n", GET_AC(ch));
|
|
if (GET_GOLD(ch) != PFDEF_GOLD) fprintf(fl, "Gold: %d\n", GET_GOLD(ch));
|
|
if (GET_BANK_GOLD(ch) != PFDEF_BANK) fprintf(fl, "Bank: %d\n", GET_BANK_GOLD(ch));
|
|
if (GET_EXP(ch) != PFDEF_EXP) fprintf(fl, "Exp : %d\n", GET_EXP(ch));
|
|
if (GET_HITROLL(ch) != PFDEF_HITROLL) fprintf(fl, "Hrol: %d\n", GET_HITROLL(ch));
|
|
if (GET_DAMROLL(ch) != PFDEF_DAMROLL) fprintf(fl, "Drol: %d\n", GET_DAMROLL(ch));
|
|
if (GET_OLC_ZONE(ch) != PFDEF_OLC) fprintf(fl, "Olc : %d\n", GET_OLC_ZONE(ch));
|
|
if (GET_PAGE_LENGTH(ch) != PFDEF_PAGELENGTH) fprintf(fl, "Page: %d\n", GET_PAGE_LENGTH(ch));
|
|
|
|
/* Save skills */
|
|
if (GET_LEVEL(ch) < LVL_IMMORT) {
|
|
fprintf(fl, "Skil:\n");
|
|
for (i = 1; i <= MAX_SKILLS; i++) {
|
|
if (GET_SKILL(ch, i))
|
|
fprintf(fl, "%d %d\n", i, GET_SKILL(ch, i));
|
|
}
|
|
fprintf(fl, "0 0\n");
|
|
}
|
|
|
|
/* Save affects */
|
|
if (tmp_aff[0].type > 0) {
|
|
fprintf(fl, "Affs:\n");
|
|
for (i = 0; i < MAX_AFFECT; i++) {
|
|
aff = &tmp_aff[i];
|
|
if (aff->type)
|
|
fprintf(fl, "%d %d %d %d %d\n", aff->type, aff->duration,
|
|
aff->modifier, aff->location, (int)aff->bitvector);
|
|
}
|
|
fprintf(fl, "0 0 0 0 0\n");
|
|
}
|
|
|
|
fclose(fl);
|
|
|
|
/* more char_to_store code to restore affects */
|
|
|
|
/* add spell and eq affections back in now */
|
|
for (i = 0; i < MAX_AFFECT; i++) {
|
|
if (tmp_aff[i].type)
|
|
affect_to_char(ch, &tmp_aff[i]);
|
|
}
|
|
|
|
for (i = 0; i < NUM_WEARS; i++) {
|
|
if (char_eq[i])
|
|
#ifndef NO_EXTRANEOUS_TRIGGERS
|
|
if (wear_otrigger(char_eq[i], ch, i))
|
|
#endif
|
|
equip_char(ch, char_eq[i], i);
|
|
#ifndef NO_EXTRANEOUS_TRIGGERS
|
|
else
|
|
obj_to_char(char_eq[i], ch);
|
|
#endif
|
|
}
|
|
|
|
/* end char_to_store code */
|
|
|
|
if ((id = get_ptable_by_name(GET_NAME(ch))) < 0)
|
|
return;
|
|
|
|
/* update the player in the player index */
|
|
if (player_table[id].level != GET_LEVEL(ch)) {
|
|
save_index = TRUE;
|
|
player_table[id].level = GET_LEVEL(ch);
|
|
}
|
|
if (player_table[id].last != ch->player.time.logon) {
|
|
save_index = TRUE;
|
|
player_table[id].last = ch->player.time.logon;
|
|
}
|
|
i = player_table[id].flags;
|
|
if (PLR_FLAGGED(ch, PLR_DELETED))
|
|
SET_BIT(player_table[id].flags, PINDEX_DELETED);
|
|
else
|
|
REMOVE_BIT(player_table[id].flags, PINDEX_DELETED);
|
|
if (PLR_FLAGGED(ch, PLR_NODELETE) || PLR_FLAGGED(ch, PLR_CRYO))
|
|
SET_BIT(player_table[id].flags, PINDEX_NODELETE);
|
|
else
|
|
REMOVE_BIT(player_table[id].flags, PINDEX_NODELETE);
|
|
|
|
if (PLR_FLAGGED(ch, PLR_FROZEN) || PLR_FLAGGED(ch, PLR_NOWIZLIST))
|
|
SET_BIT(player_table[id].flags, PINDEX_NOWIZLIST);
|
|
else
|
|
REMOVE_BIT(player_table[id].flags, PINDEX_NOWIZLIST);
|
|
|
|
if (player_table[id].flags != i || save_index)
|
|
save_player_index();
|
|
}
|
|
|
|
/* Separate a 4-character id tag from the data it precedes */
|
|
void tag_argument(char *argument, char *tag)
|
|
{
|
|
char *tmp = argument, *ttag = tag, *wrt = argument;
|
|
int i;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
*(ttag++) = *(tmp++);
|
|
*ttag = '\0';
|
|
|
|
while (*tmp == ':' || *tmp == ' ')
|
|
tmp++;
|
|
|
|
while (*tmp)
|
|
*(wrt++) = *(tmp++);
|
|
*wrt = '\0';
|
|
}
|
|
|
|
/*************************************************************************
|
|
* stuff related to the player file cleanup system *
|
|
*************************************************************************/
|
|
|
|
/*
|
|
* remove_player() removes all files associated with a player who is
|
|
* self-deleted, deleted by an immortal, or deleted by the auto-wipe
|
|
* system (if enabled).
|
|
*/
|
|
void remove_player(int pfilepos)
|
|
{
|
|
char fname[40];
|
|
int i;
|
|
|
|
if (!*player_table[pfilepos].name)
|
|
return;
|
|
|
|
/* Unlink all player-owned files */
|
|
for (i = 0; i < MAX_FILES; i++) {
|
|
if (get_filename(fname, sizeof(fname), i, player_table[pfilepos].name))
|
|
unlink(fname);
|
|
}
|
|
|
|
log("PCLEAN: %s Lev: %d Last: %s",
|
|
player_table[pfilepos].name, player_table[pfilepos].level,
|
|
asctime(localtime(&player_table[pfilepos].last)));
|
|
player_table[pfilepos].name[0] = '\0';
|
|
save_player_index();
|
|
}
|
|
|
|
|
|
void clean_pfiles(void)
|
|
{
|
|
int i, ci;
|
|
|
|
for (i = 0; i <= top_of_p_table; i++) {
|
|
/*
|
|
* We only want to go further if the player isn't protected
|
|
* from deletion and hasn't already been deleted.
|
|
*/
|
|
if (!IS_SET(player_table[i].flags, PINDEX_NODELETE) &&
|
|
*player_table[i].name) {
|
|
/*
|
|
* If the player is already flagged for deletion, then go
|
|
* ahead and get rid of him.
|
|
*/
|
|
if (IS_SET(player_table[i].flags, PINDEX_DELETED)) {
|
|
remove_player(i);
|
|
} else {
|
|
/*
|
|
* Now we check to see if the player has overstayed his
|
|
* welcome based on level.
|
|
*/
|
|
for (ci = 0; pclean_criteria[ci].level > -1; ci++) {
|
|
if (player_table[i].level <= pclean_criteria[ci].level &&
|
|
((time(0) - player_table[i].last) >
|
|
(pclean_criteria[ci].days * SECS_PER_REAL_DAY))) {
|
|
remove_player(i);
|
|
break;
|
|
}
|
|
}
|
|
/*
|
|
* If we got this far and the players hasn't been kicked out,
|
|
* then he can stay a little while longer.
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
* After everything is done, we should rebuild player_index and
|
|
* remove the entries of the players that were just deleted.
|
|
*/
|
|
}
|
|
|
|
void load_affects(FILE *fl, struct char_data *ch)
|
|
{
|
|
int num = 0, num2 = 0, num3 = 0, num4 = 0, num5 = 0, i;
|
|
char line[MAX_INPUT_LENGTH + 1];
|
|
struct affected_type af;
|
|
|
|
i = 0;
|
|
do {
|
|
get_line(fl, line);
|
|
sscanf(line, "%d %d %d %d %d", &num, &num2, &num3, &num4, &num5);
|
|
if (num > 0) {
|
|
af.type = num;
|
|
af.duration = num2;
|
|
af.modifier = num3;
|
|
af.location = num4;
|
|
af.bitvector = num5;
|
|
affect_to_char(ch, &af);
|
|
i++;
|
|
}
|
|
} while (num != 0);
|
|
}
|
|
|
|
|
|
void load_skills(FILE *fl, struct char_data *ch)
|
|
{
|
|
int num = 0, num2 = 0;
|
|
char line[MAX_INPUT_LENGTH + 1];
|
|
|
|
do {
|
|
get_line(fl, line);
|
|
sscanf(line, "%d %d", &num, &num2);
|
|
if (num != 0)
|
|
GET_SKILL(ch, num) = num2;
|
|
} while (num != 0);
|
|
}
|
|
|
|
|
|
void load_HMVS(struct char_data *ch, const char *line, int mode)
|
|
{
|
|
int num = 0, num2 = 0;
|
|
|
|
sscanf(line, "%d/%d", &num, &num2);
|
|
|
|
switch (mode) {
|
|
case LOAD_HIT:
|
|
GET_HIT(ch) = num;
|
|
GET_MAX_HIT(ch) = num2;
|
|
break;
|
|
|
|
case LOAD_MANA:
|
|
GET_MANA(ch) = num;
|
|
GET_MAX_MANA(ch) = num2;
|
|
break;
|
|
|
|
case LOAD_MOVE:
|
|
GET_MOVE(ch) = num;
|
|
GET_MAX_MOVE(ch) = num2;
|
|
break;
|
|
|
|
case LOAD_STRENGTH:
|
|
ch->real_abils.str = num;
|
|
ch->real_abils.str_add = num2;
|
|
break;
|
|
}
|
|
}
|