Windows 9x ascii player files (Version 4) Finally a simple pfile conversion for windows based circlemuds. This was tested on a stock circle30bpl11. With a VERY minimal amount of changes it was sucessfully run on bpl17. If you know what you're doing, you should be able to patch it onto just about any other version. If it's not stock bpl11, i can't guarentee anything, but hey, that's coding. *Changes* Fixed the bug causing player_table[i].name from creating properly Fixed the case-sensitive names (draco and Draco) Fixed affect_total setting all stats to 0 Stopped the mud from opening index.h upon every connect Added spell affections and fixed attributes problem Under the lib directory, make a new directory called "pfiles". Enter the etc dir and delete the file "players" Open db.c and look for this line under create_entry(char *name): for (i = 0; (*(player_table[top_of_p_table].name + i) = LOWER(*(name + i))); i++); and replace it with: for (i = 0; (*(player_table[top_of_p_table].name + i) = *(name + i)); i++); ******************************************************** Then replace the load_char function with this: ******************************************************** int load_char(char *name, struct char_data * ch) { int i, idnum; name = CAP(name); for (i = 0; i < top_of_p_table+1; i++) if (!strcmp(name, player_table[i].name)) { store_to_char(name, ch); return player_table[i].id; } return -1; } **************************************** And replace build_player_index with this: ***************************************** void build_player_index(void) { int rec_count = 0, i, idnum; FILE *plr_index; char line[256]; char arg2[80]; if(!(plr_index = fopen("pfiles/index.h", "r"))) { top_of_p_table = -1; return; } /* count the number of players in the index */ while(get_line(plr_index, line)) if(*line != '~') rec_count++; rewind(plr_index); if(rec_count == 0) { player_table = NULL; top_of_p_file = 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, "%d %s", &idnum, arg2); CREATE(player_table[i].name, char, strlen(arg2) + 1); player_table[i].name = str_dup(CAP(arg2)); player_table[i].id = idnum; } fclose(plr_index); top_of_p_file = (i - 1); top_of_p_table = (i - 1); } ************************************** Add this just below build_player_index: ************************************** void append_player_index(char *name, int idnum) { int i; FILE *plr_index; if(!(plr_index = fopen("pfiles/index.h", "w"))) { return; } for (i = 0; i < top_of_p_table+1; i++) fprintf(plr_index, "%d %s\n", player_table[i].id, player_table[i].name); fprintf(plr_index, "~"); fclose(plr_index); } ********************** Replace save_char with: ********************** void save_char(struct char_data * ch, sh_int load_room) { if (IS_NPC(ch) || !ch->desc || GET_PFILEPOS(ch) < 0) return; char_to_store(ch); } **************************** Replace store_to_char with: **************************** void store_to_char(char *name, struct char_data * ch) { char line[256], chdesc[8192]; struct affected_type af; int num, i, t[10]; FILE *rpfile; char filename[32]; /* to save memory, only PC's -- not MOB's -- have player_specials */ if (ch->player_specials == NULL) CREATE(ch->player_specials, struct player_special_data, 1); sprintf(filename, "pfiles/%s.pfile", name); if (!(rpfile = fopen(filename, "r"))) { init_char(ch); return; } ch->player.name = str_dup(name); set_title(ch, fread_string(rpfile, buf2)); POOFIN(ch) = str_dup(fread_string(rpfile, buf2)); POOFOUT(ch) = str_dup(fread_string(rpfile, buf2)); strncpy(GET_PASSWD(ch), CRYPT(fread_string(rpfile, buf2), GET_NAME(ch)), MAX_PWD_LENGTH); *(GET_PASSWD(ch) + MAX_PWD_LENGTH) = '\0'; strcpy(chdesc, fread_string(rpfile, buf2)); linea: get_line(rpfile,line); if (!(sscanf(line,"%dh %dH %dm %dM %dv %dV %dXP %dG %dBG\n",t,t+1,t+2,t+3,t+4,t+5,t+6,t+7,t+8))) { sprintf(chdesc, "%s\n%s", chdesc, line); goto linea; } ch->player.description = str_dup(chdesc); GET_HIT(ch) = t[0]; GET_MAX_HIT(ch) = t[1]; GET_MANA(ch) = t[2]; GET_MAX_MANA(ch) = t[3]; GET_MOVE(ch) = t[4]; GET_MAX_MOVE(ch) = t[5]; GET_EXP(ch) = t[6]; GET_GOLD(ch) = t[7]; GET_BANK_GOLD(ch) = t[8]; get_line(rpfile,line); sscanf(line,"Str:%d, Int:%d, Wis:%d, Dex:%d, Con:%d, Cha:%d, Hitr:%d, Damr:%d, AC:%d\n",t,t+1,t+2,t+3,t+4,t+5,t+6,t+7,t+8); ch->real_abils.str = t[0]; ch->real_abils.intel = t[1]; ch->real_abils.wis = t[2]; ch->real_abils.dex = t[3]; ch->real_abils.con = t[4]; ch->real_abils.cha = t[5]; GET_HITROLL(ch) = t[6]; GET_DAMROLL(ch) = t[7]; GET_AC(ch) = t[8]; get_line(rpfile,line); sscanf(line,"Height:%d, Weight:%d, Sex:%d, Class:%d, Lvl:%d\n",t,t+1,t+2,t+3,t+4); GET_HEIGHT(ch) = t[0]; GET_WEIGHT(ch) = t[1]; GET_SEX(ch) = t[2]; GET_CLASS(ch) = t[3]; GET_LEVEL(ch) = t[4]; get_line(rpfile,line); sscanf(line,"Birth:%d, Played:%d, Lstlogn:%d, Align:%d\n",t,t+1,t+2,t+3); ch->player.time.birth = t[0]; ch->player.time.played = t[1]; ch->player.time.logon = t[2]; GET_ALIGNMENT(ch) = t[3]; get_line(rpfile,line); sscanf(line,"Pos:%d, ID:%d, Carry_W:%d, Carry_N:%d\n",t,t+1,t+2,t+3); GET_POS(ch) = t[0]; GET_IDNUM(ch) = t[1]; IS_CARRYING_W(ch) = t[2]; IS_CARRYING_N(ch) = t[3]; get_line(rpfile,line); sscanf(line,"PLR:%d, PRF:%d, Wimp:%d, Frzlvl:%d, ilvl:%d, STL:%d\n",t,t+1,t+2,t+3,t+4,t+5); PLR_FLAGS(ch) = t[0]; PRF_FLAGS(ch) = t[1]; GET_WIMP_LEV(ch) = t[2]; GET_FREEZE_LEV(ch) = t[3]; GET_INVIS_LEV(ch) = t[4]; GET_PRACTICES(ch) = t[6]; get_line(rpfile,line); sscanf(line,"Drunk:%d, Full:%d, Thirst:%d\n", t, t+1, t+2); GET_COND(ch, DRUNK) = t[0]; GET_COND(ch, FULL) = t[1]; GET_COND(ch, THIRST) = t[2]; for (i = 0; i < MAX_SKILLS+1; i++) { if (!get_line(rpfile,line)) break; sscanf(line,"%d\n",&num); (ch)->player_specials->saved.skills[i] = num; } for (i = 0; i < MAX_AFFECT; i++) { if (!get_line(rpfile,line)) break; if (!sscanf(line,"Type:%d, Dur:%d, Mod:%d, Loc:%d, Bitv:%d\n",t,t+1,t+2,t+3,t+4)) break; af.type = t[0]; af.duration = t[1]; af.modifier = t[2]; af.location = t[3]; af.bitvector = t[4]; affect_join(ch, &af, FALSE, FALSE, FALSE, FALSE); } fclose(rpfile); } /* store_to_char */ ******************* And char_to_store: ******************* void char_to_store(struct char_data * ch) { int i; struct affected_type *af; FILE *wpfile; char filename[32]; struct obj_data *char_eq[NUM_WEARS]; for (i = 0; i < NUM_WEARS; i++) { if (GET_EQ(ch, i)) char_eq[i] = unequip_char(ch, i); else char_eq[i] = NULL; } sprintf(filename, "pfiles/%s.pfile", GET_NAME(ch)); if (!(wpfile = fopen(filename, "w"))) { sprintf(buf, "Error saving char file %s", GET_NAME(ch)); mudlog(buf, NRM, LVL_GOD, TRUE); return; } fprintf(wpfile, "%s~\n" "%s~\n" "%s~\n" "%s~\n" "%s~\n", GET_TITLE(ch) ? GET_TITLE(ch) : "needs a title", POOFIN(ch) ? POOFIN(ch) : "has appeared", POOFOUT(ch) ? POOFOUT(ch) : "has disappeared", GET_PASSWD(ch), ch->player.description ? ch->player.description : "No description available."); fprintf(wpfile, "%dh %dH %dm %dM %dv %dV %dXP %dG %dBG\n", GET_HIT(ch), GET_MAX_HIT(ch), GET_MANA(ch), GET_MAX_MANA(ch), GET_MOVE(ch), GET_MAX_MOVE(ch), GET_EXP(ch), GET_GOLD(ch), GET_BANK_GOLD(ch)); fprintf(wpfile, "Str:%d, Int:%d, Wis:%d, Dex:%d, Con:%d, Cha:%d, Hitr:%d, Damr:%d, AC:%d\n", ch->real_abils.str, ch->real_abils.intel, ch->real_abils.wis, ch->real_abils.dex, ch->real_abils.con, ch->real_abils.cha, GET_HITROLL(ch), GET_DAMROLL(ch), GET_AC(ch)); fprintf(wpfile, "Height:%d, Weight:%d, Sex:%d, Class:%d, Lvl:%d\n", GET_HEIGHT(ch), GET_WEIGHT(ch), GET_SEX(ch), GET_CLASS(ch), GET_LEVEL(ch)); fprintf(wpfile, "Birth:%d, Played:%d, Lstlogn:%d, Align:%d\n", ch->player.time.birth, ch->player.time.played + (time(0) - ch->player.time.logon), time(0), GET_ALIGNMENT(ch)); fprintf(wpfile, "Pos:%d, ID:%d, Carry_W:%d, Carry_N:%d\n", GET_POS(ch), GET_IDNUM(ch), IS_CARRYING_W(ch), IS_CARRYING_N(ch)); fprintf(wpfile, "PLR:%d, PRF:%d, Wimp:%d, Frzlvl:%d, ilvl:%d, STL:%d\n", PLR_FLAGS(ch), PRF_FLAGS(ch), GET_WIMP_LEV(ch), GET_FREEZE_LEV(ch), GET_INVIS_LEV(ch), GET_PRACTICES(ch)); fprintf(wpfile, "Drunk:%d, Full:%d, Thirst:%d\n", GET_COND(ch, DRUNK), GET_COND(ch, FULL), GET_COND(ch, THIRST)); for (i = 0; i < MAX_SKILLS+1; i++) fprintf(wpfile, "%d\n", (ch)->player_specials->saved.skills[i]); for (af = ch->affected; af; af = af->next) fprintf(wpfile, "Type:%d, Dur:%d, Mod:%d, Loc:%d, Bitv:%d\n", af->type, af->duration, af->modifier, af->location, af->bitvector); fclose(wpfile); for (i = 0; i < NUM_WEARS; i++) { if (char_eq[i]) equip_char(ch, char_eq[i], i); } } /* Char to store */ **************************** You must also change these lines: void char_to_store(struct char_data * ch, struct char_file_u * st); void store_to_char(struct char_file_u * st, struct char_data * ch); to these: void char_to_store(struct char_data * ch); void store_to_char(char *name, struct char_data * ch); and this line (in init_char): player_table[top_of_p_table].id = GET_IDNUM(ch) = ++top_idnum; to this: player_table[top_of_p_table].id = GET_IDNUM(ch) = top_of_p_table + 1; and at the end of init_char add: append_player_index(GET_NAME(ch), GET_IDNUM(ch)); Next, open comm.c and delete the three lines containing player_fl After that, open interpreter.c and change these lines: if ((player_i = load_char(tmp_name, &tmp_store)) > -1) { store_to_char(&tmp_store, d->character); to this: if ((player_i = load_char(tmp_name, d->character)) > -1) { Now move over to act.wizard.c and change: if (load_char(buf2, &tmp_store) > -1) { store_to_char(&tmp_store, victim); to: if (load_char(buf2, victim) > -1) { change: if (load_char(arg, &chdata) < 0) { to: CREATE(vict, struct char_data, 1); clear_char(vict); CREATE(vict->player_specials, struct player_special_data, 1); if (load_char(arg, vict) < 0) { change: if (load_char(value, &vbuf) < 0) { to: CREATE(vict, struct char_data, 1); clear_char(vict); CREATE(vict->player_specials, struct player_special_data, 1); if (load_char(value, vict) < 0) { and finally: if ((player_i = load_char(name, &tmp_store)) > -1) { store_to_char(&tmp_store, cbuf); to: CREATE(cbuf->player_specials, struct player_special_data, 1); if ((player_i = load_char(name, cbuf)) > -1) { You must also change ACMD(do_last) to: ACMD(do_last) { struct char_data *vict = NULL; extern char *class_abbrevs[]; one_argument(argument, arg); if (!*arg) { send_to_char("For whom do you wish to search?\r\n", ch); return; } CREATE(vict, struct char_data, 1); clear_char(vict); CREATE(vict->player_specials, struct player_special_data, 1); if (load_char(arg, vict) < 0) { send_to_char("There is no such player.\r\n", ch); return; } if ((GET_LEVEL(vict) > GET_LEVEL(ch)) && (GET_LEVEL(ch) < LVL_IMPL)) { send_to_char("You are not sufficiently godly for that!\r\n", ch); return; } sprintf(buf, "[%5ld] [%2d %s] %-12s : %-20s\r\n", GET_IDNUM(vict), (int) GET_LEVEL(vict), class_abbrevs[(int) GET_CLASS(vict)], GET_NAME(vict), ctime(&vict->player.time.logon)); send_to_char(buf, ch); } and change case 2: in ACMD(do_show) to: case 2: /* player */ if (!*value) { send_to_char("A name would help.\r\n", ch); return; } CREATE(vict, struct char_data, 1); clear_char(vict); CREATE(vict->player_specials, struct player_special_data, 1); if (load_char(value, vict) < 0) { send_to_char("There is no such player.\r\n", ch); return; } sprintf(buf + strlen(buf), "Player: %-12s (%s) [%2d %s]\r\n", GET_NAME(vict), genders[(int) GET_SEX(vict)], GET_LEVEL(vict), class_abbrevs[(int) GET_CLASS(vict)]); sprintf(buf, "Au: %-8d Bal: %-8d Exp: %-8d Align: %-5d Lessons: %-3d\r\n", GET_GOLD(vict), GET_BANK_GOLD(vict), GET_EXP(vict), GET_ALIGNMENT(vict), GET_PRACTICES(vict)); strcpy(birth, ctime(&vict->player.time.birth)); sprintf(buf, "Started: %-20.16s Last: %-20.16s Played: %3dh %2dm\r\n", birth, ctime(&vict->player.time.logon), (int) (vict->player.time.played / 3600), (int) (vict->player.time.played / 60 % 60)); send_to_char(buf, ch); free_char(vict); break; and also change: char_to_store(vict, &tmp_store); fseek(player_fl, (player_i) * sizeof(struct char_file_u), SEEK_SET); fwrite(&tmp_store, sizeof(struct char_file_u), 1, player_fl); to: GET_PFILEPOS(cbuf) = player_i; save_char(cbuf, GET_LOADROOM(cbuf)); Now you need to change the places these new functions are defined. Go to db.h and interpreter.c and change these lines: int load_char(char *name, struct char_file_u *char_element); to these: int load_char(char *name, struct char_data *ch); Also, in db.h you must change these lines: void char_to_store(struct char_data *ch, struct char_file_u *st); void store_to_char(struct char_file_u *st, struct char_data *ch); to these: void char_to_store(struct char_data *ch); void store_to_char(char *name, struct char_data *ch); Now save, compile, and that's all. If you run across any bugs/glitches/things that shouldn't be, drop me a line and I'll fix it. I'd reather get 30 e-mails about the same bug than none at all. ~Draco~ EMH Night247@hotmail.com