Merge branch 'NetHack-3.6'
This commit is contained in:
@@ -223,7 +223,7 @@ for decades, joined the NetHack Development Team in late May 2019.
|
||||
NetHack 3.6.3 was released on December 5, 2019 containing over 190 bug
|
||||
fixes to NetHack 3.6.2.
|
||||
|
||||
NetHack 3.6.4 was released on December 17, 2019 containing a security
|
||||
NetHack 3.6.4 was released on December 18, 2019 containing a security
|
||||
fix and a few bug fixes.
|
||||
|
||||
The official NetHack web site is maintained by Ken Lorber at
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
.ds vr "NetHack 3.7
|
||||
.ds f0 "\*(vr
|
||||
.ds f1
|
||||
.ds f2 "December 17, 2019
|
||||
.ds f2 "December 18, 2019
|
||||
.
|
||||
.\" A note on some special characters:
|
||||
.\" \(lq = left double quote
|
||||
@@ -4800,6 +4800,13 @@ to identify unique people for the score file.
|
||||
MAX_STATUENAME_RANK\ =\ Maximum number of score file entries to use for
|
||||
random statue names (default is 10).
|
||||
.lp
|
||||
ACCESSIBILITY\ =\ 0 or 1 to disable or enable, respectively, the ability for players
|
||||
to set S_pet_override and S_hero_override symbols in their configuration file.
|
||||
.lp
|
||||
PORTABLE_DEVICE_PATHS\ =\ 0 or 1 Windows OS only, the game will look
|
||||
for all of its external files, and write to all of its output files in one place
|
||||
rather than at the standard locations.
|
||||
.lp
|
||||
DUMPLOGFILE\ =\ A filename where the end-of-game dumplog is saved.
|
||||
Not defining this will prevent dumplog from being created. Only available
|
||||
if your game is compiled with DUMPLOG. Allows the following placeholders:
|
||||
@@ -5162,7 +5169,7 @@ participant for decades, joined the NetHack Development Team in late May 2019.
|
||||
NetHack 3.6.3 was released on December 5, 2019 containing over 190 bug
|
||||
fixes to NetHack 3.6.2.
|
||||
.pg
|
||||
NetHack 3.6.4 was released on December 17, 2019 containing a security fix
|
||||
NetHack 3.6.4 was released on December 18, 2019 containing a security fix
|
||||
and a few bug fixes.
|
||||
.pg
|
||||
The official NetHack web site is maintained by \fBKen Lorber\fP
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
%.au
|
||||
\author{Original version - Eric S. Raymond\\
|
||||
(Edited and expanded for 3.6 by Mike Stephenson and others)}
|
||||
\date{December 17, 2019}
|
||||
\date{December 18, 2019}
|
||||
|
||||
\maketitle
|
||||
|
||||
@@ -5309,6 +5309,16 @@ Minimum number of points to get an entry in the score file.
|
||||
0 or 1 to use user names or numeric userids, respectively, to identify
|
||||
unique people for the score file
|
||||
%.lp
|
||||
\item[\ib{ACCESSIBILITY}]
|
||||
0 or 1 to disable or enable, respectively, the ability for players
|
||||
to set S\verb+_+pet\verb+_+override and S\verb+_+hero\verb+_+override
|
||||
symbols in their configuration file.
|
||||
%.lp
|
||||
\item[\ib{PORTABLE\verb+_+DEVICE\verb+_+PATHS}]
|
||||
0 or 1 Windows OS only, the game will look for all of its external
|
||||
files, and write to all of its output files in one place
|
||||
rather than at the standard locations.
|
||||
%.lp
|
||||
\item[\ib{DUMPLOGFILE}]
|
||||
A filename where the end-of-game dumplog is saved.
|
||||
Not defining this will prevent dumplog from being created. Only available
|
||||
@@ -5767,7 +5777,7 @@ fixes to NetHack 3.6.2.
|
||||
|
||||
%.pg
|
||||
\medskip
|
||||
NetHack 3.6.4 was released on December 17, 2019 containing a security fix and
|
||||
NetHack 3.6.4 was released on December 18, 2019 containing a security fix and
|
||||
a few bug fixes.
|
||||
|
||||
%.pg
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
Original version - Eric S. Raymond
|
||||
(Edited and expanded for 3.6 by Mike Stephenson and others)
|
||||
|
||||
December 17, 2019
|
||||
December 18, 2019
|
||||
|
||||
|
||||
|
||||
@@ -5634,6 +5634,15 @@
|
||||
MAX_STATUENAME_RANK = Maximum number of score file entries to
|
||||
use for random statue names (default is 10).
|
||||
|
||||
ACCESSIBILITY = 0 or 1 to disable or enable, respectively, the
|
||||
ability for players to set S_pet_override and S_hero_override
|
||||
symbols in their configuration file.
|
||||
|
||||
PORTABLE_DEVICE_PATHS = 0 or 1 Windows OS only, the game will
|
||||
look for all of its external files, and write to all of its
|
||||
output files in one place rather than at the standard loca-
|
||||
tions.
|
||||
|
||||
DUMPLOGFILE = A filename where the end-of-game dumplog is
|
||||
saved. Not defining this will prevent dumplog from being cre-
|
||||
ated. Only available if your game is compiled with DUMPLOG. Al-
|
||||
@@ -5685,6 +5694,15 @@
|
||||
If you just want to see what the current top players/games
|
||||
list is, you can type nethack -s all on most versions.
|
||||
|
||||
|
||||
NetHack is an intricate and difficult game. Novices might
|
||||
"discovery" mode that enables you to keep old save files and
|
||||
cheat death, at the paltry cost of not getting on the high score
|
||||
|
||||
There are two ways of enabling explore mode. One is to
|
||||
start the game with the -X command-line switch or with the play-
|
||||
mode:explore option. The other is to issue the "#exploremode"
|
||||
NetHack 3.6 December 18, 2019
|
||||
11. Explore mode
|
||||
|
||||
NetHack is an intricate and difficult game. Novices might
|
||||
@@ -5751,16 +5769,21 @@
|
||||
|
||||
Andries Brouwer did a major re-write, transforming Hack into
|
||||
a very different game, and published (at least) three versions
|
||||
(1.0.1, 1.0.2, and 1.0.3) for UNIX machines to the Usenet.
|
||||
|
||||
Don G. Kneller ported Hack 1.0.3 to Microsoft C and MS-DOS,
|
||||
producing PC HACK 1.01e, added support for DEC Rainbow graphics
|
||||
in version 1.03g, and went on to produce at least four more ver-
|
||||
sions (3.0, 3.2, 3.51, and 3.6).
|
||||
|
||||
R. Black ported PC HACK 3.51 to Lattice C and the Atari
|
||||
520/1040ST, producing ST Hack 1.03.
|
||||
|
||||
incorporating many of the added features, and produced NetHack
|
||||
NetHack Guidebook 88
|
||||
Don G. Kneller ported Hack 1.0.3 to Microsoft C and MS-DOS,
|
||||
producing PC HACK 1.01e, added support for DEC Rainbow graphics
|
||||
in version 1.03g, and went on to produce at least four more ver-
|
||||
sions (3.0, 3.2, 3.51, and 3.6).
|
||||
R. Black ported PC HACK 3.51 to Lattice C and the Atari
|
||||
520/1040ST, producing ST Hack 1.03.
|
||||
Mike Stephenson merged these various versions back together,
|
||||
incorporating many of the added features, and produced NetHack
|
||||
1.4. He then coordinated a cast of thousands in enhancing and
|
||||
@@ -5815,9 +5838,18 @@
|
||||
Jon W{tte and Hao-yang Wang, with help from Ross Brown, Mike
|
||||
Engber, David Hairston, Michael Hamel, Jonathan Handler, Johnny
|
||||
Lee, Tim Lennan, Rob Menke, and Andy Swanson, developed NetHack
|
||||
3.1 for the Macintosh, porting it for MPW. Building on their de-
|
||||
velopment, Bart House added a Think C port.
|
||||
3.1 for the Macintosh, porting it for MPW. Building on their
|
||||
|
||||
ed NetHack 3.1 to the Atari. Pat Rankin, with help from Joshua
|
||||
Delahunty, was responsible for the VMS version of NetHack 3.1.
|
||||
|
||||
Dean Luick, with help from David Cohrs, developed NetHack
|
||||
3.1 for X11. Warwick Allison wrote a tiled version of NetHack
|
||||
for the Atari; he later contributed the tiles to the NetHack De-
|
||||
velopment Team and tile support was then added to other plat-
|
||||
|
||||
NetHack Guidebook 89
|
||||
development, Bart House added a Think C port.
|
||||
Timo Hakulinen ported NetHack 3.1 to OS/2. Eric Smith port-
|
||||
ed NetHack 3.1 to the Atari. Pat Rankin, with help from Joshua
|
||||
Delahunty, was responsible for the VMS version of NetHack 3.1.
|
||||
@@ -5828,7 +5860,6 @@
|
||||
for the Atari; he later contributed the tiles to the NetHack De-
|
||||
velopment Team and tile support was then added to other plat-
|
||||
forms.
|
||||
|
||||
The 3.2 NetHack Development Team, comprised of Michael Alli-
|
||||
son, Ken Arromdee, David Cohrs, Jessie Collet, Steve Creps, Kevin
|
||||
Darcy, Timo Hakulinen, Steve Linhart, Dean Luick, Pat Rankin, Er-
|
||||
@@ -5882,6 +5913,18 @@
|
||||
lison, Ken Arromdee, David Cohrs, Jessie Collet, Steve Creps,
|
||||
Kevin Darcy, Timo Hakulinen, Kevin Hugo, Steve Linhart, Ken Lor-
|
||||
ber, Dean Luick, Pat Rankin, Eric Smith, Mike Stephenson, Janet
|
||||
|
||||
|
||||
NetHack 3.6 December 18, 2019
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
NetHack Guidebook 90
|
||||
|
||||
|
||||
|
||||
Walz, and Paul Winner, released 3.3.0 in December 1999 and 3.3.1
|
||||
in August of 2000.
|
||||
|
||||
@@ -5949,6 +5992,18 @@
|
||||
|
||||
The release of NetHack 3.4.3 in December 2003 marked the be-
|
||||
ginning of a long release hiatus. 3.4.3 proved to be a remarkably
|
||||
|
||||
|
||||
NetHack 3.6 December 18, 2019
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
NetHack Guidebook 91
|
||||
|
||||
|
||||
|
||||
stable version that provided continued enjoyment by the community
|
||||
for more than a decade. The NetHack Development Team slowly and
|
||||
quietly continued to work on the game behind the scenes during
|
||||
@@ -6014,6 +6069,19 @@
|
||||
Alex Kompel, Dion Nicolaas, Derek S. Ray and Yitzhak Sapir main-
|
||||
tained the port of NetHack 3.6 for Microsoft Windows.
|
||||
|
||||
|
||||
|
||||
|
||||
NetHack 3.6 December 18, 2019
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
NetHack Guidebook 92
|
||||
|
||||
|
||||
|
||||
Pat Rankin attempted to keep the VMS port running for
|
||||
NetHack 3.6, hindered by limited access. Kevin Smolkowski has up-
|
||||
dated and tested it for the most recent version of OpenVMS (V8.4
|
||||
@@ -6042,7 +6110,7 @@
|
||||
NetHack 3.6.3 was released on December 5, 2019 containing
|
||||
over 190 bug fixes to NetHack 3.6.2.
|
||||
|
||||
NetHack 3.6.4 was released on December 17, 2019 containing a
|
||||
NetHack 3.6.4 was released on December 18, 2019 containing a
|
||||
security fix and a few bug fixes.
|
||||
|
||||
The official NetHack web site is maintained by Ken Lorber at
|
||||
@@ -6079,6 +6147,19 @@
|
||||
of Dungeoneers:
|
||||
Adam Aronow J. Ali Harlow Mikko Juola
|
||||
Alex Kompel Janet Walz Nathan Eady
|
||||
|
||||
|
||||
|
||||
NetHack 3.6 December 18, 2019
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
NetHack Guidebook 93
|
||||
|
||||
|
||||
|
||||
Alex Smith Janne Salmijarvi Norm Meluch
|
||||
Andreas Dorn Jean-Christophe Collet Olaf Seibert
|
||||
Andy Church Jeff Bailey Pasi Kallinen
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.4 $ $NHDT-Date: 1576287569 2019/12/14 01:39:29 $
|
||||
$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.12 $ $NHDT-Date: 1576638499 2019/12/18 03:08:19 $
|
||||
|
||||
fixes36.4 contains a terse summary of changes made to 3.6.3 in order to
|
||||
produce 3.6.4.
|
||||
@@ -16,12 +16,19 @@ message "your knapsack can't accomodate any more items" when picking stuff up
|
||||
pending; vary the message rather than add more convoluted pickup code
|
||||
dozen-ish assorted spelling/typo fixes in messages and source comments
|
||||
fix potential buffer overflow when parsing run-time configuration file
|
||||
wizard mode wishing for terrain would leave it unmapped if done while blind
|
||||
wizard mode terrain wish could leave hero in water (severe vision limits) or
|
||||
in lava (trapped, sinking) which wasn't there any more
|
||||
flying hero can go down (via '>') holes or trap doors instead of escaping trap
|
||||
polymorphed hero hiding on the ceiling can now use '>' to unhide instead of
|
||||
being told "you can't go down here"
|
||||
|
||||
|
||||
Platform- and/or Interface-Specific Fixes or Features
|
||||
-----------------------------------------------------
|
||||
fix compilation on platforms that split the ncurses and tinfo libraries
|
||||
allow run-from-removable-device on Windows
|
||||
Windows: allow all game files to be on a portable device via the sysconf
|
||||
option 'portable_device_paths'
|
||||
|
||||
|
||||
General New Features
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 mondata.h $NHDT-Date: 1550524558 2019/02/18 21:15:58 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.37 $ */
|
||||
/* NetHack 3.6 mondata.h $NHDT-Date: 1576626512 2019/12/17 23:48:32 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.39 $ */
|
||||
/* Copyright (c) 1989 Mike Threepoint */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
(is_minion((mon)->data) && mon_aligntyp(mon) == A_LAWFUL)
|
||||
#define is_flyer(ptr) (((ptr)->mflags1 & M1_FLY) != 0L)
|
||||
#define is_floater(ptr) ((ptr)->mlet == S_EYE || (ptr)->mlet == S_LIGHT)
|
||||
/* clinger: piercers, mimics, wumpus -- generally don't fall down holes */
|
||||
#define is_clinger(ptr) (((ptr)->mflags1 & M1_CLING) != 0L)
|
||||
#define is_swimmer(ptr) (((ptr)->mflags1 & M1_SWIM) != 0L)
|
||||
#define breathless(ptr) (((ptr)->mflags1 & M1_BREATHLESS) != 0L)
|
||||
@@ -41,13 +42,23 @@
|
||||
#define noncorporeal(ptr) ((ptr)->mlet == S_GHOST)
|
||||
#define tunnels(ptr) (((ptr)->mflags1 & M1_TUNNEL) != 0L)
|
||||
#define needspick(ptr) (((ptr)->mflags1 & M1_NEEDPICK) != 0L)
|
||||
/* hides_under() requires an object at the location in order to hide */
|
||||
#define hides_under(ptr) (((ptr)->mflags1 & M1_CONCEAL) != 0L)
|
||||
/* is_hider() is True for mimics but when hiding they appear as something
|
||||
else rather than become mon->mundetected, so use is_hider() with care */
|
||||
#define is_hider(ptr) (((ptr)->mflags1 & M1_HIDE) != 0L)
|
||||
/* piercers cling to the ceiling; lurkers above are hiders but they fly
|
||||
so aren't classified as clingers; unfortunately mimics are classified
|
||||
as both hiders and clingers but have nothing to do with ceilings;
|
||||
wumpuses (not wumpi :-) cling but aren't hiders */
|
||||
#define ceiling_hider(ptr) \
|
||||
(is_hider(ptr) && ((is_clinger(ptr) && (ptr)->mlet != S_MIMIC) \
|
||||
|| is_flyer(ptr))) /* lurker above */
|
||||
#define haseyes(ptr) (((ptr)->mflags1 & M1_NOEYES) == 0L)
|
||||
/* used to decide whether plural applies so no need for 'more than 2' */
|
||||
#define eyecount(ptr) \
|
||||
(!haseyes(ptr) ? 0 : ((ptr) == &mons[PM_CYCLOPS] \
|
||||
|| (ptr) == &mons[PM_FLOATING_EYE]) \
|
||||
? 1 \
|
||||
(!haseyes(ptr) ? 0 \
|
||||
: ((ptr) == &mons[PM_CYCLOPS] || (ptr) == &mons[PM_FLOATING_EYE]) ? 1 \
|
||||
: 2)
|
||||
#define nohands(ptr) (((ptr)->mflags1 & M1_NOHANDS) != 0L)
|
||||
#define nolimbs(ptr) (((ptr)->mflags1 & M1_NOLIMBS) == M1_NOLIMBS)
|
||||
|
||||
@@ -44,13 +44,30 @@
|
||||
/****************************************************************************/
|
||||
/* Version 3.6.x */
|
||||
|
||||
/* Patch 4, December 17, 2019
|
||||
/* Patch 4, December 18, 2019
|
||||
*
|
||||
* fix potential buffer overflow when parsing run-time configuration file
|
||||
* GDBPATH and GREPPATH from sysconf or -D... on compilation command line were
|
||||
* being processed even if PANICTRACE was disabled but only being freed
|
||||
* at end of game when that was enabled
|
||||
* fix the article used in the message when your steed encounters a polymorph trap
|
||||
* fix the article used in the message when your steed encounters a polymorph
|
||||
* trap
|
||||
* allow teleporting onto the vibrating square
|
||||
* message "your knapsack can't accomodate any more items" when picking stuff
|
||||
* up or removing such from container was inaccurate if there was some
|
||||
* gold pending; vary the message rather than add more convoluted pickup
|
||||
* code
|
||||
* dozen-ish assorted spelling/typo fixes in messages and source comments
|
||||
* fix potential buffer overflow when parsing run-time configuration file
|
||||
* wizard mode wishing for terrain would leave it unmapped if done while blind
|
||||
* wizard mode terrain wish could leave hero in water (severe vision limits)
|
||||
* or in lava (trapped, sinking) which wasn't there any more
|
||||
* flying hero can go down (via '>') holes or trap doors instead of escaping
|
||||
* trap
|
||||
* polymorphed hero hiding on the ceiling can now use '>' to unhide instead of
|
||||
* being told "you can't go down here"
|
||||
* fix compilation on platforms that split the ncurses and tinfo libraries
|
||||
* Windows: allow all game files to be on a portable device via the sysconf
|
||||
* option 'portable_device_paths'
|
||||
*/
|
||||
|
||||
/* Patch 3, December 5, 2019
|
||||
|
||||
@@ -17,9 +17,6 @@ struct sysopt {
|
||||
char *debugfiles; /* files to show debugplines in. '*' is all. */
|
||||
#ifdef DUMPLOG
|
||||
char *dumplogfile; /* where the dump file is saved */
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
char *portable_device_top; /* nethack configuration for a portable drive */
|
||||
#endif
|
||||
int env_dbgfl; /* 1: debugfiles comes from getenv("DEBUGFILES")
|
||||
* so sysconf's DEBUGFILES shouldn't override it;
|
||||
@@ -51,7 +48,9 @@ struct sysopt {
|
||||
|
||||
/* enable accessibility options */
|
||||
int accessibility;
|
||||
|
||||
#ifdef WIN32
|
||||
int portable_device_paths; /* nethack configuration for a portable device */
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct sysopt sysopt;
|
||||
|
||||
20
src/do.c
20
src/do.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 do.c $NHDT-Date: 1576181796 2019/12/12 20:16:36 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.197 $ */
|
||||
/* NetHack 3.6 do.c $NHDT-Date: 1576638499 2019/12/18 03:08:19 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.198 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Derek S. Ray, 2015. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -994,6 +994,24 @@ dodown()
|
||||
: surface(u.ux, u.uy));
|
||||
return 0; /* didn't move */
|
||||
}
|
||||
|
||||
if (Upolyd && ceiling_hider(&mons[u.umonnum]) && u.uundetected) {
|
||||
u.uundetected = 0;
|
||||
if (Flying) { /* lurker above */
|
||||
You("fly out of hiding.");
|
||||
} else { /* piercer */
|
||||
You("drop to the %s.", surface(u.ux, u.uy));
|
||||
if (is_pool_or_lava(u.ux, u.uy)) {
|
||||
pooleffects(FALSE);
|
||||
} else {
|
||||
(void) pickup(1);
|
||||
if ((trap = t_at(u.ux, u.uy)) != 0)
|
||||
dotrap(trap, TOOKPLUNGE);
|
||||
}
|
||||
}
|
||||
return 1; /* came out of hiding; might need '>' again to go down */
|
||||
}
|
||||
|
||||
if (!stairs_down && !ladder_down) {
|
||||
trap = t_at(u.ux, u.uy);
|
||||
if (trap && (uteetering_at_seen_pit(trap) || uescaped_shaft(trap))) {
|
||||
|
||||
24
src/files.c
24
src/files.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 files.c $NHDT-Date: 1576096997 2019/12/11 20:43:17 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.301 $ */
|
||||
/* NetHack 3.7 files.c $NHDT-Date: 1576626110 2019/12/17 23:41:50 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.276 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Derek S. Ray, 2015. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -2595,12 +2595,6 @@ char *origbuf;
|
||||
if (sysopt.dumplogfile)
|
||||
free((genericptr_t) sysopt.dumplogfile);
|
||||
sysopt.dumplogfile = dupstr(bufp);
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
} else if (src == SET_IN_SYS && match_varname(buf, "portable_device_top", 8)) {
|
||||
if (sysopt.portable_device_top)
|
||||
free((genericptr_t) sysopt.portable_device_top);
|
||||
sysopt.portable_device_top = dupstr(bufp);
|
||||
#endif
|
||||
} else if (src == SET_IN_SYS && match_varname(buf, "GENERICUSERS", 12)) {
|
||||
if (sysopt.genericusers)
|
||||
@@ -2741,6 +2735,16 @@ char *origbuf;
|
||||
return FALSE;
|
||||
}
|
||||
sysopt.accessibility = n;
|
||||
#ifdef WIN32
|
||||
} else if (src == SET_IN_SYS
|
||||
&& match_varname(buf, "portable_device_paths", 8)) {
|
||||
n = atoi(bufp);
|
||||
if (n < 0 || n > 1) {
|
||||
config_error_add("Illegal value in portable_device_paths (not 0,1).");
|
||||
return FALSE;
|
||||
}
|
||||
sysopt.portable_device_paths = n;
|
||||
#endif
|
||||
#endif /* SYSCF */
|
||||
|
||||
} else if (match_varname(buf, "BOULDER", 3)) {
|
||||
@@ -3296,6 +3300,7 @@ boolean FDECL((*proc), (char *));
|
||||
free(buf);
|
||||
}
|
||||
buf = strcat(tmpbuf, ep);
|
||||
if (strlen(buf) >= sizeof inbuf)
|
||||
buf[sizeof inbuf - 1] = '\0';
|
||||
}
|
||||
|
||||
@@ -4338,11 +4343,10 @@ reveal_paths(VOID_ARGS)
|
||||
raw_printf("No end-of-game disclosure file (%s).", nodumpreason);
|
||||
|
||||
#ifdef WIN32
|
||||
if (sysopt.portable_device_top) {
|
||||
if (sysopt.portable_device_paths) {
|
||||
const char *pd = get_portable_device();
|
||||
|
||||
raw_printf("Writable folder for portable device config (sysconf %s):",
|
||||
"portable_device_top");
|
||||
raw_printf("portable_device_paths (set in sysconf):");
|
||||
raw_printf(" \"%s\"", pd);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 hack.c $NHDT-Date: 1568509227 2019/09/15 01:00:27 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.216 $ */
|
||||
/* NetHack 3.6 hack.c $NHDT-Date: 1576638500 2019/12/18 03:08:20 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.220 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Derek S. Ray, 2015. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -2123,6 +2123,10 @@ boolean newspot; /* true if called by spoteffects */
|
||||
}
|
||||
/* not mounted */
|
||||
|
||||
/* if hiding on ceiling then don't automatically enter pool */
|
||||
if (Upolyd && ceiling_hider(&mons[u.umonnum]) && u.uundetected)
|
||||
return FALSE;
|
||||
|
||||
/* drown(),lava_effects() return true if hero changes
|
||||
location while surviving the problem */
|
||||
if (is_lava(u.ux, u.uy)) {
|
||||
|
||||
89
src/objnam.c
89
src/objnam.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.7 objnam.c $NHDT-Date: 1575768412 2019/12/08 01:26:52 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.273 $ */
|
||||
/* NetHack 3.7 objnam.c $NHDT-Date: 1576638500 2019/12/18 03:08:20 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.257 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Robert Patrick Rankin, 2011. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -3675,7 +3675,9 @@ struct obj *no_wish;
|
||||
goto typfnd;
|
||||
}
|
||||
}
|
||||
/* Let wizards wish for traps and furniture.
|
||||
|
||||
/*
|
||||
* Let wizards wish for traps and furniture.
|
||||
* Must come after objects check so wizards can still wish for
|
||||
* trap objects like beartraps.
|
||||
* Disallow such topology tweaks for WIZKIT startup wishes.
|
||||
@@ -3683,6 +3685,7 @@ struct obj *no_wish;
|
||||
wiztrap:
|
||||
if (wizard && !g.program_state.wizkit_wishing) {
|
||||
struct rm *lev;
|
||||
boolean madeterrain = FALSE;
|
||||
int trap, x = u.ux, y = u.uy;
|
||||
|
||||
for (trap = NO_TRAP + 1; trap < TRAPNUM; trap++) {
|
||||
@@ -3705,7 +3708,8 @@ struct obj *no_wish;
|
||||
return (struct obj *) &cg.zeroobj;
|
||||
}
|
||||
|
||||
/* furniture and terrain */
|
||||
/* furniture and terrain (use at your own risk; can clobber stairs
|
||||
or place furniture on existing traps which shouldn't be allowed) */
|
||||
lev = &levl[x][y];
|
||||
p = eos(bp);
|
||||
if (!BSTRCMPI(bp, p - 8, "fountain")) {
|
||||
@@ -3714,43 +3718,36 @@ struct obj *no_wish;
|
||||
if (!strncmpi(bp, "magic ", 6))
|
||||
lev->blessedftn = 1;
|
||||
pline("A %sfountain.", lev->blessedftn ? "magic " : "");
|
||||
newsym(x, y);
|
||||
return (struct obj *) &cg.zeroobj;
|
||||
}
|
||||
if (!BSTRCMPI(bp, p - 6, "throne")) {
|
||||
madeterrain = TRUE;
|
||||
} else if (!BSTRCMPI(bp, p - 6, "throne")) {
|
||||
lev->typ = THRONE;
|
||||
pline("A throne.");
|
||||
newsym(x, y);
|
||||
return (struct obj *) &cg.zeroobj;
|
||||
}
|
||||
if (!BSTRCMPI(bp, p - 4, "sink")) {
|
||||
madeterrain = TRUE;
|
||||
} else if (!BSTRCMPI(bp, p - 4, "sink")) {
|
||||
lev->typ = SINK;
|
||||
g.level.flags.nsinks++;
|
||||
pline("A sink.");
|
||||
newsym(x, y);
|
||||
return (struct obj *) &cg.zeroobj;
|
||||
}
|
||||
madeterrain = TRUE;
|
||||
|
||||
/* ("water" matches "potion of water" rather than terrain) */
|
||||
if (!BSTRCMPI(bp, p - 4, "pool") || !BSTRCMPI(bp, p - 4, "moat")) {
|
||||
} else if (!BSTRCMPI(bp, p - 4, "pool")
|
||||
|| !BSTRCMPI(bp, p - 4, "moat")) {
|
||||
lev->typ = !BSTRCMPI(bp, p - 4, "pool") ? POOL : MOAT;
|
||||
del_engr_at(x, y);
|
||||
pline("A %s.", (lev->typ == POOL) ? "pool" : "moat");
|
||||
/* Must manually make kelp! */
|
||||
water_damage_chain(g.level.objects[x][y], TRUE);
|
||||
newsym(x, y);
|
||||
return (struct obj *) &cg.zeroobj;
|
||||
}
|
||||
if (!BSTRCMPI(bp, p - 4, "lava")) { /* also matches "molten lava" */
|
||||
madeterrain = TRUE;
|
||||
|
||||
/* also matches "molten lava" */
|
||||
} else if (!BSTRCMPI(bp, p - 4, "lava")) {
|
||||
lev->typ = LAVAPOOL;
|
||||
del_engr_at(x, y);
|
||||
pline("A pool of molten lava.");
|
||||
if (!(Levitation || Flying))
|
||||
(void) lava_effects();
|
||||
newsym(x, y);
|
||||
return (struct obj *) &cg.zeroobj;
|
||||
}
|
||||
|
||||
if (!BSTRCMPI(bp, p - 5, "altar")) {
|
||||
pooleffects(FALSE);
|
||||
madeterrain = TRUE;
|
||||
} else if (!BSTRCMPI(bp, p - 5, "altar")) {
|
||||
aligntyp al;
|
||||
|
||||
lev->typ = ALTAR;
|
||||
@@ -3763,37 +3760,43 @@ struct obj *no_wish;
|
||||
else if (!strncmpi(bp, "unaligned ", 10))
|
||||
al = A_NONE;
|
||||
else /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
|
||||
al = (!rn2(6)) ? A_NONE : rn2((int) A_LAWFUL + 2) - 1;
|
||||
al = !rn2(6) ? A_NONE : (rn2((int) A_LAWFUL + 2) - 1);
|
||||
lev->altarmask = Align2amask(al);
|
||||
pline("%s altar.", An(align_str(al)));
|
||||
newsym(x, y);
|
||||
return (struct obj *) &cg.zeroobj;
|
||||
}
|
||||
|
||||
if (!BSTRCMPI(bp, p - 5, "grave")
|
||||
madeterrain = TRUE;
|
||||
} else if (!BSTRCMPI(bp, p - 5, "grave")
|
||||
|| !BSTRCMPI(bp, p - 9, "headstone")) {
|
||||
make_grave(x, y, (char *) 0);
|
||||
pline("%s.", IS_GRAVE(lev->typ) ? "A grave"
|
||||
: "Can't place a grave here");
|
||||
newsym(x, y);
|
||||
return (struct obj *) &cg.zeroobj;
|
||||
}
|
||||
|
||||
if (!BSTRCMPI(bp, p - 4, "tree")) {
|
||||
madeterrain = TRUE;
|
||||
} else if (!BSTRCMPI(bp, p - 4, "tree")) {
|
||||
lev->typ = TREE;
|
||||
pline("A tree.");
|
||||
newsym(x, y);
|
||||
block_point(x, y);
|
||||
return (struct obj *) &cg.zeroobj;
|
||||
}
|
||||
|
||||
if (!BSTRCMPI(bp, p - 4, "bars")) {
|
||||
madeterrain = TRUE;
|
||||
} else if (!BSTRCMPI(bp, p - 4, "bars")) {
|
||||
lev->typ = IRONBARS;
|
||||
pline("Iron bars.");
|
||||
newsym(x, y);
|
||||
madeterrain = TRUE;
|
||||
}
|
||||
|
||||
if (madeterrain) {
|
||||
feel_newsym(x, y); /* map the spot where the wish occurred */
|
||||
/* hero started at <x,y> but might not be there anymore (create
|
||||
lava, decline to die, and get teleported away to safety) */
|
||||
if (u.uinwater && !is_pool(u.ux, u.uy)) {
|
||||
u.uinwater = 0; /* leave the water */
|
||||
docrt();
|
||||
g.vision_full_recalc = 1;
|
||||
} else if (u.utrap && u.utraptype == TT_LAVA
|
||||
&& !is_lava(u.ux, u.uy)) {
|
||||
reset_utrap(FALSE);
|
||||
}
|
||||
/* cast 'const' away; caller won't modify this */
|
||||
return (struct obj *) &cg.zeroobj;
|
||||
}
|
||||
}
|
||||
} /* end of wizard mode traps and terrain */
|
||||
|
||||
if (!oclass && !typ) {
|
||||
if (!strncmpi(bp, "polearm", 7)) {
|
||||
|
||||
12
src/sys.c
12
src/sys.c
@@ -34,9 +34,6 @@ sys_early_init()
|
||||
#endif
|
||||
#ifdef DUMPLOG
|
||||
sysopt.dumplogfile = (char *) 0;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
sysopt.portable_device_top = (char *) 0;
|
||||
#endif
|
||||
sysopt.env_dbgfl = 0; /* haven't checked getenv("DEBUGFILES") yet */
|
||||
sysopt.shellers = (char *) 0;
|
||||
@@ -86,6 +83,9 @@ sys_early_init()
|
||||
/* default to little-endian in 3.7 */
|
||||
sysopt.saveformat[0] = sysopt.bonesformat[0] = lendian;
|
||||
sysopt.accessibility = 0;
|
||||
#ifdef WIN32
|
||||
sysopt.portable_device_paths = 0;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -108,12 +108,6 @@ sysopt_release()
|
||||
#ifdef DUMPLOG
|
||||
if (sysopt.dumplogfile)
|
||||
free((genericptr_t)sysopt.dumplogfile), sysopt.dumplogfile=(char *)0;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
if (sysopt.portable_device_top) {
|
||||
free((genericptr_t) sysopt.portable_device_top);
|
||||
sysopt.portable_device_top = (char *) 0;
|
||||
}
|
||||
#endif
|
||||
if (sysopt.genericusers)
|
||||
free((genericptr_t) sysopt.genericusers),
|
||||
|
||||
12
src/trap.c
12
src/trap.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 trap.c $NHDT-Date: 1576274483 2019/12/13 22:01:23 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.325 $ */
|
||||
/* NetHack 3.6 trap.c $NHDT-Date: 1576638501 2019/12/18 03:08:21 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.329 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Robert Patrick Rankin, 2013. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -486,7 +486,8 @@ unsigned ftflags;
|
||||
; /* KMH -- You can't escape the Sokoban level traps */
|
||||
else if (Levitation || u.ustuck
|
||||
|| (!Can_fall_thru(&u.uz) && !levl[u.ux][u.uy].candig)
|
||||
|| ((Flying || is_clinger(g.youmonst.data))
|
||||
|| ((Flying || is_clinger(g.youmonst.data)
|
||||
|| (ceiling_hider(g.youmonst.data) && u.uundetected))
|
||||
&& !(ftflags & TOOKPLUNGE))
|
||||
|| (Inhell && !u.uevent.invoked && newlevel == bottom)) {
|
||||
dont_fall = "don't fall in.";
|
||||
@@ -3725,6 +3726,7 @@ drown()
|
||||
boolean inpool_ok = FALSE, crawl_ok;
|
||||
int i, x, y;
|
||||
|
||||
feel_newsym(u.ux, u.uy); /* in case Blind, map the water here */
|
||||
/* happily wading in the same contiguous pool */
|
||||
if (u.uinwater && is_pool(u.ux - u.dx, u.uy - u.dy)
|
||||
&& (Swimming || Amphibious)) {
|
||||
@@ -5241,6 +5243,7 @@ lava_effects()
|
||||
int dmg = d(6, 6); /* only applicable for water walking */
|
||||
boolean usurvive, boil_away;
|
||||
|
||||
feel_newsym(u.ux, u.uy); /* in case Blind, map the lava here */
|
||||
burn_away_slime();
|
||||
if (likes_lava(g.youmonst.data))
|
||||
return FALSE;
|
||||
@@ -5365,7 +5368,10 @@ sink_into_lava()
|
||||
static const char sink_deeper[] = "You sink deeper into the lava.";
|
||||
|
||||
if (!u.utrap || u.utraptype != TT_LAVA) {
|
||||
; /* do nothing; this shouldn't happen */
|
||||
; /* do nothing; this usually won't happen but could after
|
||||
* polymorphing from a flier into a ceiling hider and then hiding;
|
||||
* allmain() only checks whether the hero is at a lava location,
|
||||
* not whether he or she is currently sinking */
|
||||
} else if (!is_lava(u.ux, u.uy)) {
|
||||
reset_utrap(FALSE); /* this shouldn't happen either */
|
||||
} else if (!u.uinvulnerable) {
|
||||
|
||||
@@ -167,25 +167,16 @@ folder_file_exists(const char * folder, const char * file_name)
|
||||
boolean
|
||||
test_portable_config(
|
||||
const char *executable_path,
|
||||
char *portable_device_top_path,
|
||||
size_t portable_device_top_path_size)
|
||||
char *portable_device_path,
|
||||
size_t portable_device_path_size)
|
||||
{
|
||||
int lth = 0;
|
||||
const char *sysconf = "sysconf";
|
||||
char tmppath[MAX_PATH];
|
||||
boolean retval = FALSE,
|
||||
save_initoptions_noterminate = iflags.initoptions_noterminate;
|
||||
char tmppath[MAX_PATH], *toppath, *sysconftop;
|
||||
#ifdef UNICODE
|
||||
TCHAR wdrive[_MAX_DRIVE];
|
||||
TCHAR wthisdir[_MAX_DIR];
|
||||
TCHAR wfname[_MAX_FNAME];
|
||||
TCHAR wext[_MAX_EXT];
|
||||
#endif
|
||||
char drive[_MAX_DRIVE];
|
||||
char thisdir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
errno_t err;
|
||||
|
||||
if (portable_device_top_path && folder_file_exists(executable_path, "sysconf")) {
|
||||
if (portable_device_path && folder_file_exists(executable_path, "sysconf")) {
|
||||
/*
|
||||
There is a sysconf file (not just sysconf.template) present in
|
||||
the exe path, which is not the way NetHack is initially distributed,
|
||||
@@ -195,101 +186,38 @@ test_portable_config(
|
||||
delve into that...
|
||||
*/
|
||||
|
||||
*portable_device_top_path = '\0';
|
||||
(void) strncpy(tmppath, executable_path, sizeof tmppath - (1 + sizeof "sysconf"));
|
||||
tmppath[sizeof tmppath - (1 + sizeof "sysconf")] = '\0';
|
||||
(void) strcat(tmppath, "sysconf");
|
||||
/* split the path up */
|
||||
#ifdef UNICODE
|
||||
{
|
||||
int sz, wchars_num = MultiByteToWideChar( CP_ACP, 0, tmppath, -1, NULL, 0);
|
||||
wchar_t *wstr;
|
||||
|
||||
if (wchars_num) {
|
||||
wstr = (wchar_t *) alloc(wchars_num * sizeof(wchar_t));
|
||||
MultiByteToWideChar( CP_ACP, 0, tmppath, -1, wstr, wchars_num);
|
||||
err = _wsplitpath_s(wstr, wdrive, _MAX_DRIVE, wthisdir, _MAX_DIR,
|
||||
wfname, _MAX_FNAME, wext, _MAX_EXT);
|
||||
free(wstr);
|
||||
}
|
||||
sz = WideCharToMultiByte(CP_ACP, 0, wdrive, -1, drive,
|
||||
0, NULL, NULL);
|
||||
if (sz <= sizeof drive)
|
||||
WideCharToMultiByte(CP_ACP, 0, wdrive, -1, drive,
|
||||
sz, NULL, NULL);
|
||||
|
||||
}
|
||||
#else
|
||||
err = _splitpath_s(tmppath, drive, _MAX_DRIVE, thisdir, _MAX_DIR,
|
||||
fname, _MAX_FNAME, ext, _MAX_EXT);
|
||||
#endif
|
||||
if (err != 0)
|
||||
goto done_test;
|
||||
|
||||
toppath = (char *) alloc(portable_device_top_path_size);
|
||||
*toppath = '\0';
|
||||
/* -2 because we need to append the path separator */
|
||||
(void) strncpy(toppath, drive, portable_device_top_path_size - 2);
|
||||
toppath[portable_device_top_path_size - 2] = '\0';
|
||||
(void) strcat(toppath, "\\");
|
||||
*portable_device_path = '\0';
|
||||
lth = sizeof tmppath - strlen(sysconf);
|
||||
(void) strncpy(tmppath, executable_path, lth - 1);
|
||||
tmppath[lth - 1] = '\0';
|
||||
(void) strcat(tmppath, sysconf);
|
||||
|
||||
iflags.initoptions_noterminate = 1;
|
||||
/* assure_syscf_file(); */
|
||||
config_error_init(TRUE, tmppath, FALSE);
|
||||
/* ... and _must_ parse correctly. */
|
||||
if (read_config_file(tmppath, SET_IN_SYS)
|
||||
&& sysopt.portable_device_top
|
||||
&& (strlen(sysopt.portable_device_top) + strlen(toppath)
|
||||
< portable_device_top_path_size - 3)) {
|
||||
sysconftop = sysopt.portable_device_top;
|
||||
if (sysconftop[1] == ':')
|
||||
sysconftop += 2; /* skip the device if specified */
|
||||
if (*sysconftop == '\\')
|
||||
sysconftop += 1; /* skip the root folder if specified */
|
||||
(void) strcat(toppath, sysconftop);
|
||||
append_slash(toppath);
|
||||
&& sysopt.portable_device_paths)
|
||||
retval = TRUE;
|
||||
} else {
|
||||
if (config_error_done())
|
||||
(void) config_error_done();
|
||||
iflags.initoptions_noterminate = save_initoptions_noterminate;
|
||||
sysopt_release(); /* the real sysconf processing comes later */
|
||||
}
|
||||
if (retval) {
|
||||
lth = strlen(executable_path);
|
||||
if (lth <= (int) portable_device_path_size - 1)
|
||||
Strcpy(portable_device_path, executable_path);
|
||||
else
|
||||
retval = FALSE;
|
||||
}
|
||||
iflags.initoptions_noterminate = save_initoptions_noterminate;
|
||||
sysopt_release();
|
||||
if (retval)
|
||||
Strcpy(portable_device_top_path, toppath);
|
||||
free(toppath);
|
||||
}
|
||||
done_test:
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static char portable_device_top_path[MAX_PATH];
|
||||
static char portable_device_path[MAX_PATH];
|
||||
|
||||
const char *get_portable_device()
|
||||
{
|
||||
return (const char *) portable_device_top_path;
|
||||
}
|
||||
|
||||
boolean illegal_dir(const char *d1, const char *d2)
|
||||
{
|
||||
int i;
|
||||
char tmpbuf[MAX_PATH];
|
||||
|
||||
if (!strcmpi(d1, d2)) {
|
||||
(void) strncpy(tmpbuf, &portable_device_top_path[3],
|
||||
sizeof tmpbuf - 1);
|
||||
tmpbuf[sizeof tmpbuf - 1] = '\0';
|
||||
i = (int) strlen(tmpbuf) - 1;
|
||||
if (tmpbuf[i] == '\\')
|
||||
tmpbuf[i] = '\0';
|
||||
raw_printf("Illegal \"portable_device_top = %s\" in your sysconf file",
|
||||
tmpbuf);
|
||||
raw_printf("because the exe is running from that folder.");
|
||||
raw_printf("Point 'portable_device_top' to a different folder.");
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
return (const char *) portable_device_path;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -308,19 +236,17 @@ set_default_prefix_locations(const char *programPath)
|
||||
strcpy(executable_path, get_executable_path());
|
||||
append_slash(executable_path);
|
||||
|
||||
if (test_portable_config(executable_path, portable_device_top_path,
|
||||
sizeof portable_device_top_path)) {
|
||||
if (illegal_dir(portable_device_top_path, executable_path))
|
||||
windows_startup_state = 2;
|
||||
if (test_portable_config(executable_path,
|
||||
portable_device_path, sizeof portable_device_path)) {
|
||||
g.fqn_prefix[SYSCONFPREFIX] = executable_path;
|
||||
g.fqn_prefix[CONFIGPREFIX] = portable_device_top_path;
|
||||
g.fqn_prefix[HACKPREFIX] = portable_device_top_path;
|
||||
g.fqn_prefix[SAVEPREFIX] = portable_device_top_path;
|
||||
g.fqn_prefix[LEVELPREFIX] = portable_device_top_path;
|
||||
g.fqn_prefix[BONESPREFIX] = portable_device_top_path;
|
||||
g.fqn_prefix[SCOREPREFIX] = portable_device_top_path;
|
||||
g.fqn_prefix[LOCKPREFIX] = portable_device_top_path;
|
||||
g.fqn_prefix[TROUBLEPREFIX] = portable_device_top_path;
|
||||
g.fqn_prefix[CONFIGPREFIX] = portable_device_path;
|
||||
g.fqn_prefix[HACKPREFIX] = portable_device_path;
|
||||
g.fqn_prefix[SAVEPREFIX] = portable_device_path;
|
||||
g.fqn_prefix[LEVELPREFIX] = portable_device_path;
|
||||
g.fqn_prefix[BONESPREFIX] = portable_device_path;
|
||||
g.fqn_prefix[SCOREPREFIX] = portable_device_path;
|
||||
g.fqn_prefix[LOCKPREFIX] = portable_device_path;
|
||||
g.fqn_prefix[TROUBLEPREFIX] = portable_device_path;
|
||||
g.fqn_prefix[DATAPREFIX] = executable_path;
|
||||
} else {
|
||||
build_known_folder_path(&FOLDERID_Profile, profile_path,
|
||||
|
||||
Reference in New Issue
Block a user