/* ************************************************************************ * 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); void save_etext(struct char_data *ch); 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(); } void save_etext(struct char_data *ch) { /* this will be really cool soon */ } /* 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; } }