/************************************************************************** * File: players.c Part of tbaMUD * * Usage: Player loading/saving and utility routines. * * * * All rights reserved. See license 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" #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); void write_aliases_ascii(FILE *file, struct char_data *ch); void read_aliases_ascii(FILE *file, struct char_data *ch, int count); void save_char_vars_ascii(FILE *file, struct char_data *ch); void read_saved_vars_ascii(FILE *file, struct char_data *ch, int count); void strip_cr(char *buffer); /* '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[]; /* 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 %ld", &player_table[i].id, arg2, &player_table[i].level, bits, &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]; char f1[128], f2[128], f3[128], f4[128]; 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. 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_HEIGHT(ch) = PFDEF_HEIGHT; GET_WEIGHT(ch) = PFDEF_WEIGHT; GET_ALIGNMENT(ch) = PFDEF_ALIGNMENT; 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, HUNGER) = PFDEF_HUNGER; GET_COND(ch, THIRST) = PFDEF_THIRST; GET_COND(ch, DRUNK) = PFDEF_DRUNK; GET_BAD_PWS(ch) = PFDEF_BADPWS; 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; GET_ALIASES(ch) = NULL; SITTING(ch) = NULL; NEXT_SITTING(ch) = NULL; GET_QUESTPOINTS(ch) = PFDEF_QUESTPOINTS; for (i = 0; i < AF_ARRAY_MAX; i++) AFF_FLAGS(ch)[i] = PFDEF_AFFFLAGS; for (i = 0; i < PM_ARRAY_MAX; i++) PLR_FLAGS(ch)[i] = PFDEF_PLRFLAGS; for (i = 0; i < PR_ARRAY_MAX; i++) PRF_FLAGS(ch)[i] = PFDEF_PREFFLAGS; 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 ")) { sscanf(line, "%s %s %s %s", f1, f2, f3, f4); PLR_FLAGS(ch)[0] = asciiflag_conv(f1); PLR_FLAGS(ch)[1] = asciiflag_conv(f2); PLR_FLAGS(ch)[2] = asciiflag_conv(f3); PLR_FLAGS(ch)[3] = asciiflag_conv(f4); } else if (!strcmp(tag, "Aff ")) { sscanf(line, "%s %s %s %s", f1, f2, f3, f4); AFF_FLAGS(ch)[0] = asciiflag_conv(f1); AFF_FLAGS(ch)[1] = asciiflag_conv(f2); AFF_FLAGS(ch)[2] = asciiflag_conv(f3); AFF_FLAGS(ch)[3] = asciiflag_conv(f4); } else if (!strcmp(tag, "Affs")) load_affects(fl, ch); else if (!strcmp(tag, "Alin")) GET_ALIGNMENT(ch) = atoi(line); else if (!strcmp(tag, "Alis")) read_aliases_ascii(fl, 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, "Host")) GET_HOST(ch) = strdup(line); else if (!strcmp(tag, "Hrol")) GET_HITROLL(ch) = atoi(line); else if (!strcmp(tag, "Hung")) GET_COND(ch, HUNGER) = 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); else if (!strcmp(tag, "PfIn")) POOFIN(ch) = strdup(line); else if (!strcmp(tag, "PfOt")) POOFOUT(ch) = strdup(line); else if (!strcmp(tag, "Pref")) sscanf(line, "%s %s %s %s", f1, f2, f3, f4); PRF_FLAGS(ch)[0] = asciiflag_conv(f1); PRF_FLAGS(ch)[1] = asciiflag_conv(f2); PRF_FLAGS(ch)[2] = asciiflag_conv(f3); PRF_FLAGS(ch)[3] = asciiflag_conv(f4); break; case 'Q': if (!strcmp(tag, "Qstp")) GET_QUESTPOINTS(ch) = atoi(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 'V': if (!strcmp(tag, "Vars")) read_saved_vars_ascii(fl, ch, atoi(line)); 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, HUNGER) = -1; GET_COND(ch, THIRST) = -1; GET_COND(ch, DRUNK) = -1; } fclose(fl); return(id); } /* Write the vital data of a player to the player file. */ /* This is the ASCII Player Files save routine. */ void save_char(struct char_data * ch) { FILE *fl; char fname[40], 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 update 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); } } /* 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; } /* 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; } } /* 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); strip_cr(buf); fprintf(fl, "Desc:\n%s~\n", buf); } if (POOFIN(ch)) fprintf(fl, "PfIn: %s\n", POOFIN(ch)); if (POOFOUT(ch)) fprintf(fl, "PfOt: %s\n", POOFOUT(ch)); 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)); 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) fprintf(fl, "Act : %u %u %u %u\n", PLR_FLAGS(ch)[0], PLR_FLAGS(ch)[1], PLR_FLAGS(ch)[2], PLR_FLAGS(ch)[3]); if(AFF_FLAGS(ch) != PFDEF_AFFFLAGS) fprintf(fl, "Aff : %u %u %u %u\n", AFF_FLAGS(ch)[0], AFF_FLAGS(ch)[1], AFF_FLAGS(ch)[2], AFF_FLAGS(ch)[3]); if(PRF_FLAGS(ch) != PFDEF_PREFFLAGS) fprintf(fl, "Pref: %d %d %d %d\n", PRF_FLAGS(ch)[0], PRF_FLAGS(ch)[1], PRF_FLAGS(ch)[2], PRF_FLAGS(ch)[3]); 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, HUNGER) != PFDEF_HUNGER && GET_LEVEL(ch) < LVL_IMMORT) fprintf(fl, "Hung: %d\n", GET_COND(ch, HUNGER)); 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)); if (GET_QUESTPOINTS(ch) != PFDEF_QUESTPOINTS) fprintf(fl, "Qstp: %d\n", GET_QUESTPOINTS(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"); } write_aliases_ascii(fl, ch); save_char_vars_ascii(fl, ch); fclose(fl); /* More char_to_store code to add spell and eq affections back in. */ 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 { /* 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; } }