diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 61f00da9b..bb0b879c9 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1550,6 +1550,7 @@ you cannot sacrifice objects/corpses while stunned or confused required /a and /c instead; add '/' and '?' as group accelerators so that they work; /y and /n for them now only work when lootabc is off writing on an unidentified scroll of blank paper identifies blank paper +dumplogs include spells and skills Fixes to 3.7.0-x General Problems Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index 59e7188af..8a5056d91 100644 --- a/include/extern.h +++ b/include/extern.h @@ -3041,6 +3041,7 @@ extern int spelleffects(int, boolean, boolean); extern int tport_spell(int); extern void losespells(void); extern int dovspell(void); +extern void show_spells(void); extern void initialspell(struct obj *) NONNULLARG1; extern int known_spell(short); extern int spell_idx(short); @@ -3673,6 +3674,7 @@ extern void dry_a_towel(struct obj *, int, boolean) NONNULLARG1; extern char *skill_level_name(int, char *) NONNULLARG2; extern const char *skill_name(int); extern boolean can_advance(int, boolean); +extern void show_skills(void); extern int enhance_weapon_skill(void); extern void unrestrict_weapon_skill(int); extern void use_skill(int, int); diff --git a/src/end.c b/src/end.c index 30ba0e91d..f7f61020e 100644 --- a/src/end.c +++ b/src/end.c @@ -599,14 +599,16 @@ dump_everything( /* overview of the game up to this point */ show_gamelog((how >= PANICKED) ? ENL_GAMEOVERALIVE : ENL_GAMEOVERDEAD); putstr(0, 0, ""); - list_vanquished('d', FALSE); /* 'd' => 'y' */ - putstr(0, 0, ""); - list_genocided('d', FALSE); /* 'd' => 'y' */ - putstr(0, 0, ""); + show_spells(); /* ends with a blank line */ + show_skills(); /* ends with a blank line */ show_conduct((how >= PANICKED) ? 1 : 2); putstr(0, 0, ""); show_overview((how >= PANICKED) ? 1 : 2, how); putstr(0, 0, ""); + list_vanquished('d', FALSE); /* 'd' => 'y' */ + putstr(0, 0, ""); + list_genocided('d', FALSE); /* 'd' => 'y' */ + putstr(0, 0, ""); dump_redirect(FALSE); #else nhUse(how); diff --git a/src/spell.c b/src/spell.c index 847f53335..2e64b2c17 100644 --- a/src/spell.c +++ b/src/spell.c @@ -5,6 +5,7 @@ #include "hack.h" /* spellmenu arguments; 0..n-1 used as svs.spl_book[] index when swapping */ +#define SPELLMENU_DUMP (-3) #define SPELLMENU_CAST (-2) #define SPELLMENU_VIEW (-1) #define SPELLMENU_SORT (MAXSPELL) /* special menu entry */ @@ -2043,13 +2044,27 @@ dovspell(void) DISABLE_WARNING_FORMAT_NONLITERAL +/* lists spells for endgame dumplog purposes */ +void +show_spells(void) +{ + int unused = SPELLMENU_DUMP; + if (spellid(0) == NO_SPELL) { + pline("You didn't know any spells."); + pline("%s", ""); + } else { + pline("Spells:"); + nhUse(dospellmenu("", SPELLMENU_DUMP, &unused)); + } +} + /* shows menu of known spells, with options to sort them. return FALSE on cancel, TRUE otherwise. spell_no is set to the internal spl_book index, if any selected */ staticfn boolean dospellmenu( const char *prompt, - int splaction, /* SPELLMENU_CAST, SPELLMENU_VIEW, or + int splaction, /* SPELLMENU_CAST, SPELLMENU_VIEW, SPELLMENU_DUMP or * svs.spl_book[] index */ int *spell_no) { @@ -2071,10 +2086,14 @@ dospellmenu( * (1) that the font is monospaced, and * (2) that selection letters are pre-pended to the * given string and are of the form "a - ". + * For SPELLMENU_DUMP, (2) is untrue, so four spaces + * need to be subtracted. */ if (!iflags.menu_tab_sep) { - Sprintf(buf, "%-20s Level %-12s Fail Retention", - " Name", "Category"); + Sprintf(buf, "%s%-20s Level %-12s Fail Retention", + splaction == SPELLMENU_DUMP ? "" : " ", + "Name", + "Category"); fmt = "%-20s %2d %-12s %3d%% %9s"; sep = ' '; } else { @@ -2102,6 +2121,7 @@ dospellmenu( ? MENU_ITEMFLAGS_SELECTED : MENU_ITEMFLAGS_NONE); } how = PICK_ONE; + how = PICK_NONE; if (splaction == SPELLMENU_VIEW) { if (spellid(1) == NO_SPELL) { /* only one spell => nothing to swap with */ diff --git a/src/weapon.c b/src/weapon.c index 59fa7c30d..317fd7c08 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -16,6 +16,7 @@ staticfn boolean could_advance(int); staticfn boolean peaked_skill(int); staticfn int slots_required(int); staticfn void skill_advance(int); +staticfn void add_skills_to_menu(winid, boolean, boolean); /* Categories whose names don't come from OBJ_NAME(objects[type]) */ @@ -1215,6 +1216,102 @@ static const struct skill_range { { P_FIRST_SPELL, P_LAST_SPELL, "Spellcasting Skills" }, }; +/* write a list of skills onto the given menu + + if selectable is set, give selection letters for skills that can be + advanced and leave room for them on skills that can't be advanced */ +void +add_skills_to_menu(winid win, boolean selectable, boolean speedy) +{ + int pass, i, len, longest; + anything any; + char buf[BUFSZ], sklnambuf[BUFSZ]; + const char *prefix; + int clr = NO_COLOR; + + /* Find the longest skill name. */ + for (longest = 0, i = 0; i < P_NUM_SKILLS; i++) { + if (P_RESTRICTED(i)) + continue; + if ((len = Strlen(P_NAME(i))) > longest) + longest = len; + } + + /* List the skills, making ones that could be advanced selectable if + selectable is set. List the miscellaneous skills first. Possible + future enhancement: list spell skills before weapon skills for + spellcaster roles. */ + for (pass = 0; pass < SIZE(skill_ranges); pass++) + for (i = skill_ranges[pass].first; i <= skill_ranges[pass].last; + i++) { + /* Print headings for skill types */ + any = cg.zeroany; + if (i == skill_ranges[pass].first) + add_menu_heading(win, skill_ranges[pass].name); + + if (P_RESTRICTED(i)) + continue; + /* + * Sigh, this assumes a monospaced font unless + * iflags.menu_tab_sep is set in which case it puts + * tabs between columns. + * The 12 is the longest skill level name. + * The " " is room for a selection letter and dash, "a - ". + */ + if (!selectable) + prefix = ""; + else if (can_advance(i, speedy)) + prefix = ""; /* will be preceded by menu choice */ + else if (could_advance(i)) + prefix = " * "; + else if (peaked_skill(i)) + prefix = " # "; + else + prefix = " "; + (void) skill_level_name(i, sklnambuf); + if (wizard) { + if (!iflags.menu_tab_sep) + Snprintf(buf, sizeof buf, + " %s%-*s %-12s %5d(%4d)", prefix, + longest, P_NAME(i), sklnambuf, P_ADVANCE(i), + practice_needed_to_advance(P_SKILL(i))); + else + Snprintf(buf, sizeof buf, + " %s%s\t%s\t%5d(%4d)", prefix, P_NAME(i), + sklnambuf, P_ADVANCE(i), + practice_needed_to_advance(P_SKILL(i))); + } else { + if (!iflags.menu_tab_sep) + Snprintf(buf, sizeof buf, + " %s %-*s [%s]", prefix, longest, + P_NAME(i), sklnambuf); + else + Snprintf(buf, sizeof buf, + " %s%s\t[%s]", prefix, P_NAME(i), + sklnambuf); + } + any.a_int = selectable && can_advance(i, speedy) ? i + 1 : 0; + add_menu(win, &nul_glyphinfo, &any, 0, 0, + ATR_NONE, clr, buf, MENU_ITEMFLAGS_NONE); + } +} + +/* Displays a skill list for dumplog purposes. */ +void +show_skills(void) +{ + winid win; + menu_item *selected; + + pline("Skills:"); + win = create_nhwindow(NHW_MENU); + start_menu(win, MENU_BEHAVE_STANDARD); + add_skills_to_menu(win, FALSE, FALSE); + end_menu(win, ""); + nhUse(select_menu(win, PICK_NONE, &selected)); + destroy_nhwindow(win); +} + /* * The `#enhance' extended command. What we _really_ would like is * to keep being able to pick things to advance until we couldn't any @@ -1226,14 +1323,11 @@ static const struct skill_range { int enhance_weapon_skill(void) { - int pass, i, n, len, longest, to_advance, eventually_advance, maxxed_cnt; - char buf[BUFSZ], sklnambuf[BUFSZ]; - const char *prefix; + int i, n, to_advance, eventually_advance, maxxed_cnt; + char buf[BUFSZ]; menu_item *selected; - anything any; winid win; boolean speedy = FALSE; - int clr = NO_COLOR; /* player knows about #enhance, don't show tip anymore */ svc.context.tips[TIP_ENHANCE] = TRUE; @@ -1242,13 +1336,11 @@ enhance_weapon_skill(void) speedy = TRUE; do { - /* find longest available skill name, count those that can advance */ + /* count advanceable skills */ to_advance = eventually_advance = maxxed_cnt = 0; - for (longest = 0, i = 0; i < P_NUM_SKILLS; i++) { + for (i = 0; i < P_NUM_SKILLS; i++) { if (P_RESTRICTED(i)) continue; - if ((len = Strlen(P_NAME(i))) > longest) - longest = len; if (can_advance(i, speedy)) to_advance++; else if (could_advance(i)) @@ -1280,64 +1372,8 @@ enhance_weapon_skill(void) add_menu_str(win, ""); } - /* List the skills, making ones that could be advanced - selectable. List the miscellaneous skills first. - Possible future enhancement: list spell skills before - weapon skills for spellcaster roles. */ - for (pass = 0; pass < SIZE(skill_ranges); pass++) - for (i = skill_ranges[pass].first; i <= skill_ranges[pass].last; - i++) { - /* Print headings for skill types */ - any = cg.zeroany; - if (i == skill_ranges[pass].first) - add_menu_heading(win, skill_ranges[pass].name); - - if (P_RESTRICTED(i)) - continue; - /* - * Sigh, this assumes a monospaced font unless - * iflags.menu_tab_sep is set in which case it puts - * tabs between columns. - * The 12 is the longest skill level name. - * The " " is room for a selection letter and dash, "a - ". - */ - if (can_advance(i, speedy)) - prefix = ""; /* will be preceded by menu choice */ - else if (could_advance(i)) - prefix = " * "; - else if (peaked_skill(i)) - prefix = " # "; - else - prefix = - (to_advance + eventually_advance + maxxed_cnt > 0) - ? " " - : ""; - (void) skill_level_name(i, sklnambuf); - if (wizard) { - if (!iflags.menu_tab_sep) - Snprintf(buf, sizeof buf, - " %s%-*s %-12s %5d(%4d)", prefix, - longest, P_NAME(i), sklnambuf, P_ADVANCE(i), - practice_needed_to_advance(P_SKILL(i))); - else - Snprintf(buf, sizeof buf, - " %s%s\t%s\t%5d(%4d)", prefix, P_NAME(i), - sklnambuf, P_ADVANCE(i), - practice_needed_to_advance(P_SKILL(i))); - } else { - if (!iflags.menu_tab_sep) - Snprintf(buf, sizeof buf, - " %s %-*s [%s]", prefix, longest, - P_NAME(i), sklnambuf); - else - Snprintf(buf, sizeof buf, - " %s%s\t[%s]", prefix, P_NAME(i), - sklnambuf); - } - any.a_int = can_advance(i, speedy) ? i + 1 : 0; - add_menu(win, &nul_glyphinfo, &any, 0, 0, - ATR_NONE, clr, buf, MENU_ITEMFLAGS_NONE); - } + add_skills_to_menu( + win, to_advance + eventually_advance + maxxed_cnt > 0, speedy); Strcpy(buf, (to_advance > 0) ? "Pick a skill to advance:" : "Current skills:");