Here's a command (for version 3.1) that prints out to a file a quick snapshot of some key database files. In case you've ever wanted to peruse the data base from outside the game, but in a format more readable then the database files themselves (.obj, .mob, .zon, etc.) I didn't bother with the .wld files, since there are way too many rooms for this to be practical. Remember to add the command to the command table in interpreter.c! -Ed Glamkowski ACMD(do_output) { char buf[MAX_INPUT_LENGTH], buf2[MAX_STRING_LENGTH]; char output[PATH_MAX]; FILE *fpOut; int i, nr, cnt; int hp = 0, max_hp = 0, min_hp = 0, dam = 0, max_dam = 0, min_dam = 0; one_argument(argument, buf); if (!*buf) { send_to_char(ch, "USAGE: output \r\n"); return; } else if (is_abbrev(buf, "mob")) { snprintf(output, sizeof(output), "%smob.db", MOB_PREFIX); fpOut = fopen(output, "wt"); if (!fpOut) { send_to_char(ch, "Couldn't open %smob.db for writing!\r\n", MOB_PREFIX); return; } for (cnt = 0; cnt <= LVL_IMPL; cnt++) { for (nr = 0; nr <= top_of_mobt; nr++) { if (mob_proto[nr].player.level == cnt) { hp = (int)((((double)GET_MANA(mob_proto + nr) + 1.0) / 2.0) * (double)GET_HIT(mob_proto + nr)); hp += GET_MOVE(mob_proto + nr); max_hp = (GET_HIT(mob_proto + nr) * GET_MANA(mob_proto + nr)); max_hp += GET_MOVE(mob_proto + nr); min_hp = (GET_HIT(mob_proto + nr) * 1) + GET_MOVE(mob_proto + nr); dam = (int)((((double)(mob_proto[nr].mob_specials.damsizedice) + 1.0) / 2.0) * (double)(mob_proto[nr].mob_specials.damnodice)); dam += GET_DAMROLL(mob_proto + nr); max_dam = (mob_proto[nr].mob_specials.damnodice * mob_proto[nr].mob_specials.damsizedice); max_dam += GET_DAMROLL(mob_proto + nr); min_dam = (mob_proto[nr].mob_specials.damnodice * 1) + GET_DAMROLL(mob_proto + nr); fprintf(fpOut, "[%5d] [Level %2d] %33s, HP: %5d/%5d/%5d, Dam: %3d/%3d/%3d\r\n", mob_index[nr].vnum, mob_proto[nr].player.level, mob_proto[nr].player.short_descr, min_hp, hp, max_hp, min_dam, dam, max_dam); } } } } else if (is_abbrev(buf, "obj")) { snprintf(output, sizeof(output), "%sobj.db", OBJ_PREFIX); fpOut = fopen(output, "wt"); if (!fpOut) { send_to_char(ch, "Couldn't open %sobj.db for writing!\r\n", OBJ_PREFIX); return; } for (cnt = 1; cnt < NUM_ITEMS; cnt++) { for (nr = 0; nr <= top_of_objt; nr++) { if (obj_proto[nr].obj_flags.type_flag != cnt) continue; fprintf(fpOut, "[%5d] [Type: %13s] %33s", obj_index[nr].vnum, item_types[obj_proto[nr].obj_flags.type_flag], obj_proto[nr].short_description); if (obj_proto[nr].obj_flags.type_flag == ITEM_WEAPON) { dam = (obj_proto[nr].obj_flags.value[2] + 1.0) / 2.0; dam *= (obj_proto[nr].obj_flags.value[1]); for (i = 0; i < MAX_OBJ_AFFECT; i++) { if (obj_proto[nr].affected[i].location == APPLY_DAMROLL || obj_proto[nr].affected[i].location == APPLY_HIT_N_DAM) dam += obj_proto[nr].affected[i].modifier; } fprintf(fpOut, ", Avg Dam: %2d, Type: %s", dam, attack_hit_text[obj_proto[nr].obj_flags.value[3]].singular); } /* If it is a weapon */ else if (obj_proto[nr].obj_flags.type_flag == ITEM_ARMOR) { fprintf(fpOut, ", AC: %2d", obj_proto[nr].obj_flags.value[0]); for (dam = 0, i = 0; i < MAX_OBJ_AFFECT; i++) { if (obj_proto[nr].affected[i].location == APPLY_AC) dam += obj_proto[nr].affected[i].modifier; } if (dam) fprintf(fpOut, ", APPLY_AC: %d", dam); } else if (obj_proto[nr].obj_flags.type_flag == ITEM_LIGHT) { fprintf(fpOut, ", Duration: %2d", obj_proto[nr].obj_flags.value[2]); } else if (obj_proto[nr].obj_flags.type_flag == ITEM_SCROLL || obj_proto[nr].obj_flags.type_flag == ITEM_POTION) { fprintf(fpOut, ", Spells: (Level %2d) %s, %s, %s", obj_proto[nr].obj_flags.value[0], skill_name(obj_proto[nr].obj_flags.value[1]), skill_name(obj_proto[nr].obj_flags.value[2]), skill_name(obj_proto[nr].obj_flags.value[3])); } else if (obj_proto[nr].obj_flags.type_flag == ITEM_WAND || obj_proto[nr].obj_flags.type_flag == ITEM_STAFF) { fprintf(fpOut, ", Level: %2d, Charges: %2d, Spell: %s", obj_proto[nr].obj_flags.value[0], obj_proto[nr].obj_flags.value[1], skill_name(obj_proto[nr].obj_flags.value[3])); } else if (obj_proto[nr].obj_flags.type_flag == ITEM_CONTAINER) { fprintf(fpOut, ", Capacity: %d", obj_proto[nr].obj_flags.value[0]); } else if (obj_proto[nr].obj_flags.type_flag == ITEM_TREASURE) { fprintf(fpOut, ", Cost: %d", obj_proto[nr].obj_flags.cost); } else if (obj_proto[nr].obj_flags.type_flag == ITEM_DRINKCON || obj_proto[nr].obj_flags.type_flag == ITEM_FOUNTAIN) { sprinttype(obj_proto[nr].obj_flags.value[2], drinks, buf2, sizeof(buf2)); fprintf(fpOut, ", Capacity: %5d, Poisoned: %3s, Liquid: %s", obj_proto[nr].obj_flags.value[0], YESNO(obj_proto[nr].obj_flags.value[3]), buf2); } else if (obj_proto[nr].obj_flags.type_flag == ITEM_FOOD) { fprintf(fpOut, ", Makes Full: %2d, Posioned: %3s", obj_proto[nr].obj_flags.value[0], YESNO(obj_proto[nr].obj_flags.value[3])); } else if (obj_proto[nr].obj_flags.type_flag == ITEM_MONEY) { fprintf(fpOut, ", Coins: %d", obj_proto[nr].obj_flags.value[0]); } fprintf(fpOut, "\r\n"); } } } else if (is_abbrev(buf, "zone")) { snprintf(output, sizeof(output), "%szon.db", ZON_PREFIX); fpOut = fopen(output, "wt"); if (!fpOut) { send_to_char(ch, "Couldn't open %szon.db for writing!\r\n", ZON_PREFIX); return; } for (i = 0; i <= top_of_zone_table; i++) { fprintf(fpOut, "[%5d] %s\r\n", zone_table[i].number, zone_table[i].name); } } else { send_to_char(ch, "USAGE: output \r\n"); return; } if (fpOut) fclose(fpOut); send_to_char(ch, "%s", OK); }