Experimental #saveoptions command
Add a #saveoptions extended command, to allow saving configuration settings from within the game. This is still highly experimental, and gives plenty of warnings before asking to overwrite the file. Lack of option saving is one of the biggest complaints new players have, so this should help with it. More experienced players with highly customized config file should not use this feature, as it completely rewrites the file, removing all comments and non-config lines.
This commit is contained in:
@@ -1765,6 +1765,7 @@ taming magic acting on an already tame creature might make it become tamer
|
||||
eliminate scimitar skill and have scimitars use saber skill
|
||||
simplified configuration options menu
|
||||
rudimentary key rebinding in game options
|
||||
experimental #saveoptions command to allow saving configuration settings
|
||||
|
||||
|
||||
Platform- and/or Interface-Specific New Features
|
||||
|
||||
@@ -203,6 +203,7 @@ extern boolean parse_status_hl1(char *op, boolean);
|
||||
extern void status_notify_windowport(boolean);
|
||||
extern void clear_status_hilites(void);
|
||||
extern int count_status_hilites(void);
|
||||
extern void all_options_statushilites(strbuf_t *);
|
||||
extern boolean status_hilite_menu(void);
|
||||
#endif /* STATUS_HILITES */
|
||||
|
||||
@@ -878,6 +879,7 @@ extern void nh_compress(const char *);
|
||||
extern void nh_uncompress(const char *);
|
||||
extern boolean lock_file(const char *, int, int);
|
||||
extern void unlock_file(const char *);
|
||||
extern int do_write_config_file(void);
|
||||
extern boolean parse_config_line(char *);
|
||||
#ifdef USER_SOUNDS
|
||||
extern boolean can_read_file(const char *);
|
||||
@@ -1955,11 +1957,12 @@ extern void initoptions(void);
|
||||
extern void initoptions_init(void);
|
||||
extern void initoptions_finish(void);
|
||||
extern boolean parseoptions(char *, boolean, boolean);
|
||||
extern char *get_option_value(const char *);
|
||||
extern char *get_option_value(const char *, boolean);
|
||||
extern int doset_simple(void);
|
||||
extern int doset(void);
|
||||
extern int dotogglepickup(void);
|
||||
extern void option_help(void);
|
||||
extern void all_options_strbuf(strbuf_t *);
|
||||
extern void next_opt(winid, const char *);
|
||||
extern int fruitadd(char *, struct fruit *);
|
||||
extern int choose_classes_menu(const char *, int, boolean, char *, char *);
|
||||
@@ -2663,6 +2666,8 @@ extern int do_symset(boolean);
|
||||
extern int load_symset(const char *, int);
|
||||
extern void free_symsets(void);
|
||||
extern const struct symparse *match_sym(char *);
|
||||
extern void savedsym_free(void);
|
||||
extern void savedsym_strbuf(strbuf_t *);
|
||||
extern boolean parsesymbols(char *, int);
|
||||
#ifdef ENHANCED_SYMBOLS
|
||||
extern struct customization_detail *find_matching_symset_customization(
|
||||
|
||||
21
src/botl.c
21
src/botl.c
@@ -4021,6 +4021,27 @@ status_hilites_viewall(void)
|
||||
destroy_nhwindow(datawin);
|
||||
}
|
||||
|
||||
void
|
||||
all_options_statushilites(strbuf_t *sbuf)
|
||||
{
|
||||
struct _status_hilite_line_str *hlstr;
|
||||
char buf[BUFSZ];
|
||||
|
||||
status_hilite_linestr_done();
|
||||
status_hilite_linestr_gather();
|
||||
|
||||
hlstr = status_hilite_str;
|
||||
|
||||
while (hlstr) {
|
||||
Sprintf(buf, "OPTIONS=hilite_status: %.*s\n",
|
||||
(int) (BUFSZ - sizeof "OPTIONS=hilite_status: " - 1),
|
||||
hlstr->str);
|
||||
strbuf_append(sbuf, buf);
|
||||
hlstr = hlstr->next;
|
||||
}
|
||||
status_hilite_linestr_done();
|
||||
}
|
||||
|
||||
boolean
|
||||
status_hilite_menu(void)
|
||||
{
|
||||
|
||||
@@ -2589,6 +2589,8 @@ struct ext_func_tab extcmdlist[] = {
|
||||
do_rush, PREFIXCMD, NULL },
|
||||
{ 'S', "save", "save the game and exit",
|
||||
dosave, IFBURIED | GENERALCMD | NOFUZZERCMD, NULL },
|
||||
{ '\0', "saveoptions", "save the game configuration",
|
||||
do_write_config_file, IFBURIED | GENERALCMD | NOFUZZERCMD, NULL },
|
||||
{ 's', "search", "search for traps and secret doors",
|
||||
dosearch, IFBURIED | CMD_M_PREFIX, "searching" },
|
||||
{ '*', "seeall", "show all equipment in use",
|
||||
|
||||
42
src/files.c
42
src/files.c
@@ -1984,6 +1984,48 @@ char configfile[BUFSZ];
|
||||
const char *backward_compat_configfile = "nethack.cnf";
|
||||
#endif
|
||||
|
||||
/* #saveoptions - save config options into file */
|
||||
int
|
||||
do_write_config_file(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char tmp[BUFSZ];
|
||||
|
||||
if (!configfile[0]) {
|
||||
pline("Strange, could not figure out config file name.");
|
||||
return ECMD_OK;
|
||||
}
|
||||
if (flags.suppress_alert < FEATURE_NOTICE_VER(3,7,0)) {
|
||||
pline("Warning: saveoptions is highly experimental!");
|
||||
wait_synch();
|
||||
pline("Some settings are not saved!");
|
||||
wait_synch();
|
||||
pline("All manual customization and comments are removed from the file!");
|
||||
wait_synch();
|
||||
}
|
||||
#define overwrite_prompt "Overwrite config file %.*s?"
|
||||
Sprintf(tmp, overwrite_prompt, (int)(BUFSZ - sizeof overwrite_prompt - 2), configfile);
|
||||
#undef overwrite_prompt
|
||||
if (!paranoid_query(TRUE, tmp))
|
||||
return ECMD_OK;
|
||||
|
||||
fp = fopen(configfile, "w");
|
||||
if (fp) {
|
||||
size_t len, wrote;
|
||||
strbuf_t buf;
|
||||
|
||||
strbuf_init(&buf);
|
||||
all_options_strbuf(&buf);
|
||||
len = strlen(buf.str);
|
||||
wrote = fwrite(buf.str, 1, len, fp);
|
||||
fclose(fp);
|
||||
strbuf_empty(&buf);
|
||||
if (wrote != len)
|
||||
pline("An error occurred, wrote only partial data (%lu/%lu).", wrote, len);
|
||||
}
|
||||
return ECMD_OK;
|
||||
}
|
||||
|
||||
/* remember the name of the file we're accessing;
|
||||
if may be used in option reject messages */
|
||||
static void
|
||||
|
||||
@@ -631,7 +631,7 @@ nhl_get_config(lua_State *L)
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
if (argc == 1) {
|
||||
lua_pushstring(L, get_option_value(luaL_checkstring(L, 1)));
|
||||
lua_pushstring(L, get_option_value(luaL_checkstring(L, 1), TRUE));
|
||||
return 1;
|
||||
} else
|
||||
nhl_error(L, "Wrong args");
|
||||
|
||||
428
src/options.c
428
src/options.c
File diff suppressed because it is too large
Load Diff
@@ -1158,6 +1158,7 @@ freedynamicdata(void)
|
||||
free_invbuf(); /* let_to_name (invent.c) */
|
||||
free_youbuf(); /* You_buf,&c (pline.c) */
|
||||
msgtype_free();
|
||||
savedsym_free();
|
||||
tmp_at(DISP_FREEMEM, 0); /* temporary display effects */
|
||||
#ifdef FREE_ALL_MEMORY
|
||||
#define free_current_level() savelev(&tnhfp, -1)
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
#include "hack.h"
|
||||
#include "tcap.h"
|
||||
|
||||
static void savedsym_add(const char *, const char *, int);
|
||||
static struct _savedsym *savedsym_find(const char *, int);
|
||||
|
||||
extern const uchar def_r_oc_syms[MAXOCLASSES]; /* drawing.c */
|
||||
|
||||
#if defined(TERMLIB) || defined(CURSES_GRAPHICS)
|
||||
@@ -661,6 +664,74 @@ free_symsets(void)
|
||||
/* assert( symset_list == NULL ); */
|
||||
}
|
||||
|
||||
struct _savedsym {
|
||||
char *name;
|
||||
char *val;
|
||||
int which_set;
|
||||
struct _savedsym *next;
|
||||
};
|
||||
struct _savedsym *saved_symbols = NULL;
|
||||
|
||||
void
|
||||
savedsym_free(void)
|
||||
{
|
||||
struct _savedsym *tmp = saved_symbols, *tmp2;
|
||||
|
||||
while (tmp) {
|
||||
tmp2 = tmp->next;
|
||||
free(tmp->name);
|
||||
free(tmp->val);
|
||||
free(tmp);
|
||||
tmp = tmp2;
|
||||
}
|
||||
}
|
||||
|
||||
static struct _savedsym *
|
||||
savedsym_find(const char *name, int which_set)
|
||||
{
|
||||
struct _savedsym *tmp = saved_symbols;
|
||||
|
||||
while (tmp) {
|
||||
if (which_set == tmp->which_set && !strcmp(name, tmp->name))
|
||||
return tmp;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
savedsym_add(const char *name, const char *val, int which_set)
|
||||
{
|
||||
struct _savedsym *tmp = NULL;
|
||||
|
||||
if ((tmp = savedsym_find(name, which_set)) != 0) {
|
||||
free(tmp->val);
|
||||
tmp->val = dupstr(val);
|
||||
} else {
|
||||
tmp = (struct _savedsym *)alloc(sizeof(struct _savedsym));
|
||||
tmp->name = dupstr(name);
|
||||
tmp->val = dupstr(val);
|
||||
tmp->which_set = which_set;
|
||||
tmp->next = saved_symbols;
|
||||
saved_symbols = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
savedsym_strbuf(strbuf_t *sbuf)
|
||||
{
|
||||
struct _savedsym *tmp = saved_symbols;
|
||||
char buf[BUFSZ];
|
||||
|
||||
while (tmp) {
|
||||
Sprintf(buf, "%sSYMBOLS=%s:%s\n",
|
||||
(tmp->which_set == ROGUESET) ? "ROGUE" : "",
|
||||
tmp->name, tmp->val);
|
||||
strbuf_append(sbuf, buf);
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the value of a SYMBOLS line from a config file */
|
||||
boolean
|
||||
parsesymbols(register char *opts, int which_set)
|
||||
@@ -720,6 +791,7 @@ parsesymbols(register char *opts, int which_set)
|
||||
}
|
||||
}
|
||||
}
|
||||
savedsym_add(opts, strval, which_set);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user