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.
This commit is contained in:
Pasi Kallinen
2023-02-19 15:44:29 +02:00
parent 80842979aa
commit 5d659cf1f6
16 changed files with 131 additions and 16 deletions

View File

@@ -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,
};

View File

@@ -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]

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 */

View File

@@ -519,6 +519,7 @@ enum nhcore_calls {
NHCORE_RESTORE_OLD_GAME,
NHCORE_MOVELOOP_TURN,
NHCORE_GAME_EXIT,
NHCORE_GETPOS_TIP,
NUM_NHCORE_CALLS
};

View File

@@ -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,

View File

@@ -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.

View File

@@ -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)) {

View File

@@ -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;
}
}

View File

@@ -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},

View File

@@ -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;