Windows 9x ascii player files (Version 5) 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. and with a few more changes, bpl18. (the PLR_FLAGS for 18 have changed to arrays... need to use .pref[0]) 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, Draco and DRaCo) Fixed affect_total setting all stats to 0 Stopped the mud from opening index.h upon every connect (and forcing it to close) 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: ******************************************************** char *strip_caps(char string[32]) { int i; for (i=0;string[i]!='\0';i++) if (string[i]<91 && string[i]>64) string[i]+=32; return string; } int load_char(char *name, struct char_data * ch) { int rec_count = 0, i, idnum; FILE *plr_index; char *temp, *temp2; char line[256]; char arg2[80]; if(!(plr_index = fopen("pfiles/index.h", "r"))) { playerlog("Error opening player index for load_char"); return -1; } while(get_line(plr_index, line)) if(*line != '~') rec_count++; rewind(plr_index); if(rec_count == 0) { fclose(plr_index); return -1; } for(i = 0; i < rec_count; i++) { get_line(plr_index, line); sscanf(line, "%d %s", &idnum, arg2); temp= str_dup(arg2); strip_caps(temp); temp2 = str_dup(name); strip_caps(temp2); if (!strcmp(temp, temp2)) { fclose(plr_index); store_to_char(arg2, ch); return idnum; } } fclose(plr_index); return -1; } **************************************** You may have to define strip_caps at the top of db.c char *strip_caps(char string[32]); 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->aff_abils.str = ch->real_abils.str = t[0]; ch->aff_abils.intel = ch->real_abils.intel = t[1]; ch->aff_abils.wis = ch->real_abils.wis = t[2]; ch->aff_abils.dex = ch->real_abils.dex = t[3]; ch->aff_abils.con = ch->real_abils.con = t[4]; ch->aff_abils.cha = 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(CAP(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 rather get 30 e-mails about the same bug than none at all. ~Draco~ EMH CoReXS@hotmail.com (the old email still works too)