From: Pasi Kallinen Date: Sun, 19 Feb 2023 13:44:29 +0000 (+0200) Subject: Tips and option to disable them X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5d659cf1f68eec0ee1c83948ef5c57a724e31169;p=nethack Tips and option to disable them Adds a more general way to handle gameplay tips, and adds a boolean option "tips", which can be used to disable all tips. Adds a helpful longer message when the game goes into the "farlook" mode. Also adds a lua binding to easily show multi-line text in a menu window. Breaks save compat. --- diff --git a/dat/nhcore.lua b/dat/nhcore.lua index 5eb94b737..c3887c3e8 100644 --- a/dat/nhcore.lua +++ b/dat/nhcore.lua @@ -65,6 +65,19 @@ function mk_dgl_extrainfo() end end +-- Show a helpful tip when player first uses getpos() +function show_getpos_tip() + nh.text([[ +Tip: Farlooking or selecting a map location + +You are now in a "farlook" mode - the movement keys move the cursor, +not your character. Game time does not advance. This mode is used +to look around the map, or to select a location on it. + +When in this mode, you can press ESC to return to normal game mode, +and pressing ? will show the key help. +]]); +end -- Callback functions nhcore = { @@ -81,5 +94,8 @@ nhcore = { -- game_exit is called when the game exits (quit, saved, ...) -- game_exit = function() end, + + -- getpos_tip is called the first time the code enters getpos() + getpos_tip = show_getpos_tip, }; diff --git a/dat/opthelp b/dat/opthelp index c48dd72f9..109454fa0 100644 --- a/dat/opthelp +++ b/dat/opthelp @@ -66,6 +66,7 @@ sparkle display sparkly effect for resisted magical [True] standout use standout mode for --More-- on messages [False] status_updates update the status lines [True] time display elapsed game time, in moves [False] +tips show some helpful tips during gameplay [True] tombstone print tombstone when you die [True] toptenwin print topten in a window rather than stdout [False] travel enables travelling via mouse click if supported; [True] diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index c4c4be6a0..af05cdc55 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -4529,6 +4529,9 @@ screen. uses a timer-based delay. The default is on if configured into the program.) Persistent. +.lp "tips " +Show some helpful tips during gameplay (default on). +Persistent. .lp tombstone Draw a tombstone graphic upon your death (default on). Persistent. diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 2b03d74ac..6575e93ef 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -4957,6 +4957,9 @@ screen. (Applies to ``tty'' and ``curses'' interfaces only; ``X11'' interface a uses a timer-based delay. The default is on if configured into the program.) Persistent. %.lp +\item[\ib{tips}] +Show some helpful tips during gameplay (default on). Persistent. +%.lp \item[\ib{tombstone}] Draw a tombstone graphic upon your death (default on). Persistent. %.lp diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 691b87eb1..e9e15a001 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1977,6 +1977,8 @@ have 'I u' mention whether there are any unpaid items on the floor (unusual but not impossible); it doesn't itemize them or show shop price add items given a Japanese name when playing as a Samurai to discoveries list make music improvisations more varied and interesting, as well as useful +give a helpful tip when first entering "farlook" mode +add a boolean option tips to disable all of the helpful tips Platform- and/or Interface-Specific New Features diff --git a/doc/lua.adoc b/doc/lua.adoc index 90ec18d2f..c49bba557 100644 --- a/doc/lua.adoc +++ b/doc/lua.adoc @@ -384,6 +384,15 @@ Example: nh.stop_timer_at({x=5,y=6}, "melt-ice"); +=== text + +Show long texts in a menu window. Wordwraps automatically. + +Example: + + nh.text("long long long string\nwith newlines too."); + + === variable Set or get a global variable. These are persistent, saved and restored along with the game. diff --git a/include/context.h b/include/context.h index b11ac5a8f..662165dda 100644 --- a/include/context.h +++ b/include/context.h @@ -11,6 +11,14 @@ #define CONTEXTVERBSZ 30 +enum nh_tips { + TIP_ENHANCE = 0, /* #enhance */ + TIP_SWIM, /* walking into water */ + TIP_GETPOS, /* getpos/farlook */ + + NUM_TIPS +}; + /* * The context structure houses things that the game tracks * or adjusts during the game, to preserve game state or context. @@ -153,8 +161,7 @@ struct context_info { boolean botl; /* partially redo status line */ boolean botlx; /* print an entirely new bottom line */ boolean door_opened; /* set to true if door was opened during test_move */ - boolean enhance_tip; /* player is informed about #enhance */ - boolean swim_tip; /* player was informed about walking into water */ + boolean tips[NUM_TIPS]; struct dig_info digging; struct victual_info victual; struct engrave_info engraving; diff --git a/include/extern.h b/include/extern.h index 5e89e43ef..649fbe9bb 100644 --- a/include/extern.h +++ b/include/extern.h @@ -966,6 +966,7 @@ extern int wiz_debug_cmd_traveldisplay(void); extern boolean u_rooted(void); extern boolean u_maybe_impaired(void); extern const char *u_locomotion(const char *); +extern void handle_tip(int); extern void domove(void); extern void runmode_delay_output(void); extern void overexert_hp(void); diff --git a/include/flag.h b/include/flag.h index 5a99da206..9cf67e4c0 100644 --- a/include/flag.h +++ b/include/flag.h @@ -34,6 +34,7 @@ struct flag { boolean friday13; /* it's Friday the 13th */ boolean goldX; /* for BUCX filtering, whether gold is X or U */ boolean help; /* look in data file for info about stuff */ + boolean tips; /* show helpful hints? */ boolean ignintr; /* ignore interrupts */ boolean implicit_uncursed; /* maybe omit "uncursed" status in inventory */ boolean ins_chkpt; /* checkpoint as appropriate; INSURANCE */ diff --git a/include/hack.h b/include/hack.h index b53f78b4a..a1fc3093b 100644 --- a/include/hack.h +++ b/include/hack.h @@ -519,6 +519,7 @@ enum nhcore_calls { NHCORE_RESTORE_OLD_GAME, NHCORE_MOVELOOP_TURN, NHCORE_GAME_EXIT, + NHCORE_GETPOS_TIP, NUM_NHCORE_CALLS }; diff --git a/include/optlist.h b/include/optlist.h index 4ba345936..ca9a01b64 100644 --- a/include/optlist.h +++ b/include/optlist.h @@ -615,6 +615,8 @@ static int optfn_##a(int, int, boolean, char *, char *); NHOPTB(timed_delay, Map, 0, opt_in, set_in_config, Off, No, No, No, NoAlias, (boolean *) 0, Term_False) #endif + NHOPTB(tips, Advanced, 0, opt_out, set_in_game, + On, Yes, No, No, NoAlias, &flags.tips, Term_False) NHOPTB(tombstone, Advanced, 0, opt_out, set_in_game, On, Yes, No, No, NoAlias, &flags.tombstone, Term_False) NHOPTB(toptenwin, Advanced, 0, opt_in, set_in_game, diff --git a/include/patchlevel.h b/include/patchlevel.h index 8c7ed8ab7..c49335cbd 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -17,7 +17,7 @@ * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. */ -#define EDITLEVEL 73 +#define EDITLEVEL 74 /* * Development status possibilities. diff --git a/src/do_name.c b/src/do_name.c index dca437d44..abd8e2d18 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -806,6 +806,8 @@ getpos(coord *ccp, boolean force, const char *goal) mMoOdDxX[i] = gc.Cmd.spkeys[mMoOdDxX_def[i]]; mMoOdDxX[SIZE(mMoOdDxX_def)] = '\0'; + handle_tip(TIP_GETPOS); + if (!goal) goal = "desired location"; if (Verbose(0, getpos1)) { diff --git a/src/hack.c b/src/hack.c index ea15c795e..eade9a4d9 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1641,6 +1641,32 @@ u_simple_floortyp(coordxy x, coordxy y) return ROOM; } +/* maybe show a helpful gameplay tip? */ +void +handle_tip(int tip) +{ + if (!flags.tips) + return; + + if (tip >= 0 && tip < NUM_TIPS && !gc.context.tips[tip]) { + gc.context.tips[tip] = TRUE; + switch (tip) { + case TIP_ENHANCE: + pline("(Use the #enhance command to advance them.)"); + break; + case TIP_SWIM: + pline("(Use '%s' prefix to step in if you really want to.)", + visctrl(cmd_from_func(do_reqmenu))); + break; + case TIP_GETPOS: + l_nhcore_call(NHCORE_GETPOS_TIP); + break; + default: + impossible("Unknown tip in handle_tip(%i)", tip); + } + } +} + /* Is it dangerous for hero to move to x,y due to water or lava? */ static boolean swim_move_danger(coordxy x, coordxy y) @@ -1665,18 +1691,13 @@ swim_move_danger(coordxy x, coordxy y) || liquid_wall) { if (gc.context.nopick) { /* moving with m-prefix */ - gc.context.swim_tip = TRUE; + gc.context.tips[TIP_SWIM] = TRUE; return FALSE; } else if (ParanoidSwim || liquid_wall) { You("avoid %s into the %s.", ing_suffix(u_locomotion("step")), waterbody_name(x, y)); - if (!gc.context.swim_tip) { - pline( - "(Use '%s' prefix to step in if you really want to.)", - visctrl(cmd_from_func(do_reqmenu))); - gc.context.swim_tip = TRUE; - } + handle_tip(TIP_SWIM); return TRUE; } } diff --git a/src/nhlua.c b/src/nhlua.c index 8f14238b2..1a67b185a 100644 --- a/src/nhlua.c +++ b/src/nhlua.c @@ -49,6 +49,7 @@ static int nhl_pline(lua_State *); static int nhl_verbalize(lua_State *); static int nhl_parse_config(lua_State *); static int nhl_menu(lua_State *); +static int nhl_text(lua_State *); static int nhl_getlin(lua_State *); static int nhl_makeplural(lua_State *); static int nhl_makesingular(lua_State *); @@ -80,6 +81,7 @@ static const char *const nhcore_call_names[NUM_NHCORE_CALLS] = { "restore_old_game", "moveloop_turn", "game_exit", + "getpos_tip", }; static boolean nhcore_call_available[NUM_NHCORE_CALLS]; @@ -769,6 +771,53 @@ nhl_menu(lua_State *L) return 1; } +/* text("foo\nbar\nbaz") */ +static int +nhl_text(lua_State *L) +{ + int argc = lua_gettop(L); + + if (argc > 0) { + menu_item *picks = (menu_item *) 0; + winid tmpwin; + anything any = cg.zeroany; + + tmpwin = create_nhwindow(NHW_MENU); + start_menu(tmpwin, MENU_BEHAVE_STANDARD); + + while (lua_gettop(L) > 0) { + char *ostr = dupstr(luaL_checkstring(L, 1)); + char *ptr, *str = ostr; + char *lstr = str + strlen(str) - 1; + + do { + char *nlp = strchr(str, '\n'); + + if (nlp && (nlp - str) <= 76) { + ptr = nlp; + } else { + ptr = str + 76; + if (ptr > lstr) + ptr = lstr; + } + while ((ptr > str) && !(*ptr == ' ' || *ptr == '\n')) + ptr--; + *ptr = '\0'; + add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0, ATR_NONE, 0, + str, MENU_ITEMFLAGS_NONE); + str = ptr + 1; + } while (*str && str <= lstr); + lua_pop(L, 1); + free(ostr); + } + + end_menu(tmpwin, (char *) 0); + (void) select_menu(tmpwin, PICK_NONE, &picks); + destroy_nhwindow(tmpwin); + } + return 0; +} + /* makeplural("zorkmid") */ static int nhl_makeplural(lua_State *L) @@ -1448,6 +1497,7 @@ static const struct luaL_Reg nhl_functions[] = { {"pline", nhl_pline}, {"verbalize", nhl_verbalize}, {"menu", nhl_menu}, + {"text", nhl_text}, {"getlin", nhl_getlin}, {"makeplural", nhl_makeplural}, diff --git a/src/weapon.c b/src/weapon.c index 7f2308669..d862102c6 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -77,11 +77,7 @@ give_may_advance_msg(int skill) : (skill <= P_LAST_WEAPON) ? "weapon " : (skill <= P_LAST_SPELL) ? "spell casting " : "fighting "); - - if (!gc.context.enhance_tip) { - gc.context.enhance_tip = TRUE; - pline("(Use the #enhance command to advance them.)"); - } + handle_tip(TIP_ENHANCE); } /* weapon's skill category name for use as generalized description of weapon; @@ -1170,7 +1166,7 @@ enhance_weapon_skill(void) int clr = 0; /* player knows about #enhance, don't show tip anymore */ - gc.context.enhance_tip = TRUE; + gc.context.tips[TIP_ENHANCE] = TRUE; if (wizard && y_n("Advance skills without practice?") == 'y') speedy = TRUE;