Merge branch 'NetHack-3.6'

This commit is contained in:
Bart House
2019-10-31 20:46:54 -07:00
9 changed files with 507 additions and 230 deletions

View File

@@ -57,7 +57,7 @@ Spackman, Steve VanDevender, and Paul Winner, ported NetHack 3.1 to the PC.
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 development, Barton House added a Think C port.
MPW. Building on their development, Bart House added a Think C port.
Timo Hakulinen ported NetHack 3.1 to OS/2. Eric Smith ported NetHack 3.1
to the Atari. Pat Rankin, with help from Joshua Delahunty, is responsible
@@ -195,7 +195,7 @@ Unix flavors as well as maintaining the X11 interface.
Ken Lorber, Haoyang Wang, Pat Rankin, and Dean Luick maintained the port
of NetHack 3.6.1 for Mac OSX.
Michael Allison, David Cohrs, Barton House, Pasi Kallinen, Alex Kompel,
Michael Allison, David Cohrs, Bart House, Pasi Kallinen, Alex Kompel,
Dion Nicolaas, Derek S. Ray and Yitzhak Sapir maintained the port of
NetHack 3.6 for Microsoft Windows.
@@ -217,6 +217,9 @@ Derek S. Ray, Alex Smith, Mike Stephenson, Janet Walz and Paul Winner.
In early May 2019, another 320 bug fixes along with some enhancements and
the adopted curses window port, were released as 3.6.2.
Bart House, who had contributed to the game as a porting team participant
for decades, joined the NetHack Development Team in late May 2019.
The official NetHack web site is maintained by Ken Lorber at
http://www.nethack.org/.
@@ -241,7 +244,7 @@ of these miscreants in this, the list of Dungeoneers:
Andy Church Jochen Erwied Pat Rankin
Andy Swanson John Kallen Patric Mueller
Ari Huttunen John Rupley Paul Winner
Barton House John S. Bien Pierre Martineau
Bart House John S. Bien Pierre Martineau
Benson I. Margulies Johnny Lee Ralf Brown
Bill Dyer Jon W{tte Ray Chason
Boudewijn Waijers Jonathan Handler Richard Addison

View File

@@ -24,7 +24,7 @@
.ds vr "NetHack 3.7
.ds f0 "\*(vr
.ds f1
.ds f2 "October 27, 2019
.ds f2 "October 31, 2019
.
.\" A note on some special characters:
.\" \(lq = left double quote
@@ -4911,7 +4911,7 @@ and \fBPaul Winner\fP, ported NetHack 3.1 to the PC.
\fBMike Engber\fP, \fBDavid Hairston\fP, \fBMichael Hamel\fP,
\fBJonathan Handler\fP, \fBJohnny Lee\fP, \fBTim Lennan\fP, \fBRob Menke\fP,
and \fBAndy Swanson\fP, developed NetHack 3.1 for the Macintosh,
porting it for MPW. Building on their development, \fBBarton House\fP
porting it for MPW. Building on their development, \fBBart House\fP
added a Think C port.
.pg
\fBTimo Hakulinen\fP ported NetHack 3.1 to OS/2. \fBEric Smith\fP
@@ -5070,7 +5070,7 @@ flavors and maintained the X11 interface.
\fBKen Lorber\fP, \fBHaoyang Wang\fP, \fBPat Rankin\fP, and \fBDean Luick\fP
maintained the port of NetHack 3.6 for Mac OSX.
.pg
\fBMichael Allison\fP, \fBDavid Cohrs\fP, \fBBarton House\fP,
\fBMichael Allison\fP, \fBDavid Cohrs\fP, \fBBart House\fP,
\fBPasi Kallinen\fP, \fBAlex Kompel\fP, \fBDion Nicolaas\fP,
\fBDerek S. Ray\fP and \fBYitzhak Sapir\fP maintained the port of
NetHack 3.6 for Microsoft Windows.
@@ -5095,6 +5095,9 @@ The NetHack Development Team at the time of release of 3.6.1 consisted of
In early May 2019, another 320 bug fixes along with some enhancements and
the adopted curses window port, were released as 3.6.2.
.pg
\fBBart House\fP, who had contributed to the game as a porting team
participant for decades, joined the NetHack Development Team in late May 2019.
.pg
The official NetHack web site is maintained by \fBKen Lorber\fP
at
.UR http://www.nethack.org/ .
@@ -5130,7 +5133,7 @@ Andreas Dorn Jeff Bailey Pasi Kallinen
Andy Church Jochen Erwied Pat Rankin
Andy Swanson John Kallen Patric Mueller
Ari Huttunen John Rupley Paul Winner
Barton House John S. Bien Pierre Martineau
Bart House John S. Bien Pierre Martineau
Benson I. Margulies Johnny Lee Ralf Brown
Bill Dyer Jon W{tte Ray Chason
Boudewijn Waijers Jonathan Handler Richard Addison

View File

@@ -45,7 +45,7 @@
%.au
\author{Original version - Eric S. Raymond\\
(Edited and expanded for 3.6 by Mike Stephenson and others)}
\date{October 22, 2019}
\date{October 31, 2019}
\maketitle
@@ -1130,7 +1130,7 @@ slot to another so that it has a letter which is more meaningful for you
or that it will appear in a particular location when inventory listings
are displayed.
You can move to a currently empty slot, or if the destination is
occupied--and won't merge--the item there will swap slots with the one
occupied---and won't merge---the item there will swap slots with the one
being moved.
``{\tt \#adjust}'' can also be used to split a stack of objects; when
choosing the item to adjust, enter a count prior to its letter.\\
@@ -2044,9 +2044,9 @@ will result in it disappearing from your map, similarly if it is the
one who moved rather than you.
%.pg
However, if you encounter a monster which you can't see or sense--
perhaps it is invisible and has just tapped you on the noggin--
a special ``remembered, unseen monster'' marker will be displayed at
However, if you encounter a monster which you can't see or
sense---perhaps it is invisible and has just tapped you on the
noggin---a special ``remembered, unseen monster'' marker will be displayed at
the location where you think it is.
That will persist until you have
proven that there is no monster there, even if the unseen monster
@@ -2326,7 +2326,7 @@ But first you need to have a weapon in each hand.
(Note that your two weapons are not fully equal; the one in the
hand you normally wield with is considered primary and the other
one is considered secondary. The most noticeable difference is
after you stop--or before you begin, for that matter--wielding
after you stop---or before you begin, for that matter---wielding
two weapons at once. The primary is your wielded weapon and the
secondary is just an item in your inventory that's been designated
as alternate weapon.)
@@ -2558,7 +2558,7 @@ The commands to use rings are `{\tt P}' (put on) and `{\tt R}' (remove).
%.pg
Spellbooks are tomes of mighty magic. When studied with the `{\tt r}' (read)
command, they transfer to the reader the knowledge of a spell (and
therefore eventually become unreadable) --- unless the attempt backfires.
therefore eventually become unreadable)---unless the attempt backfires.
Reading a cursed spellbook or one with mystic runes beyond
your ken can be harmful to your health!
@@ -2701,9 +2701,9 @@ you are carrying (shopkeepers aside).
Normally, if you have seen an object at a particular map location and
move to another location where you can't directly see that object any
more, if will continue to be displayed on your map.
That remains the case even if it is not actually there any more--
perhaps a monster has picked it up or it has rotted away--
until you can see or feel that location again.
That remains the case even if it is not actually there any
more---perhaps a monster has picked it up or it has rotted
away---until you can see or feel that location again.
One notable exception is that if the object gets covered by the
``remembered, unseen monster'' marker.
When that marker is later removed
@@ -3028,11 +3028,13 @@ See the ``Configuring User Sounds'' section.
Define the directory that contains the sound files.
See the ``Configuring User Sounds'' section.
%.lp
\item[\bb{SYMBOLS}
\item[\bb{SYMBOLS}]
Override one or more symbols in the symbol set used for all dungeon
levels except for the special rogue level.
See the ``Modifying {\it NetHack\/} Symbols'' section.
%.pg
%.lp ""
Example:
%.sd
\begin{verbatim}
@@ -4378,158 +4380,158 @@ Below are the special commands you can rebind. Some of them can be bound to
same keys with no problems, others are in the same ``context'', and if bound
to same keys, only one of those commands will be available. Special command
can only be bound to a single key.
\elist
%.pg
\blist{}
\blist{\itemindent 10mm \labelwidth 15mm \rightmargin 20mm}
%.lp
\item{\bb{count}}
\item[{\bb{count}}]
Prefix key to start a count, to repeat a command this many times.
With {\it number\verb+_+pad\/} only. Default is `{\tt n}'.
%.lp
\item{\bb{doinv}}
\item[{\bb{doinv}}]
Show inventory. With {\it number\verb+_+pad\/} only. Default is `{\tt 0}'.
%.lp
\item{\bb{fight}}
\item[{\bb{fight}}]
Prefix key to force fight a direction. Default is `{\tt F}'.
%.lp
\item{\bb{fight.numpad}}
\item[{\bb{fight.numpad}}]
Prefix key to force fight a direction. With {\it number\verb+_+pad\/} only.
Default is `{\tt -}'.
%.lp
\item{\bb{getdir.help}}
\item[{\bb{getdir.help}}]
When asked for a direction, the key to show the help. Default is `{\tt ?}'.
%.lp
\item{\bb{getdir.self}}
\item[{\bb{getdir.self}}]
When asked for a direction, the key to target yourself. Default is `{\tt .}'.
%.lp
\item{\bb{getdir.self2}}
\item[{\bb{getdir.self2}}]
When asked for a direction, the key to target yourself. Default is `{\tt s}'.
%.lp
\item{\bb{getpos.autodescribe}}
\item[{\bb{getpos.autodescribe}}]
When asked for a location, the key to toggle {\it autodescribe\/}.
Default is `{\tt \#}'.
%.lp
\item{\bb{getpos.all.next}}
\item[{\bb{getpos.all.next}}]
When asked for a location, the key to go to next closest interesting thing.
Default is `{\tt a}'.
%.lp
\item{\bb{getpos.all.prev}}
\item[{\bb{getpos.all.prev}}]
When asked for a location, the key to go to previous closest interesting thing.
Default is `{\tt A}'.
%.lp
\item{\bb{getpos.door.next}}
\item[{\bb{getpos.door.next}}]
When asked for a location, the key to go to next closest door or doorway.
Default is `{\tt d}'.
%.lp
\item{\bb{getpos.door.prev}}
\item[{\bb{getpos.door.prev}}]
When asked for a location, the key to go to previous closest door or doorway.
Default is `{\tt D}'.
%.lp
\item{\bb{getpos.help}}
\item[{\bb{getpos.help}}]
When asked for a location, the key to show help. Default is `{\tt ?}'.
%.lp
\item{\bb{getpos.mon.next}}
\item[{\bb{getpos.mon.next}}]
When asked for a location, the key to go to next closest monster.
Default is `{\tt m}'.
%.lp
\item{\bb{getpos.mon.prev}}
\item[{\bb{getpos.mon.prev}}]
When asked for a location, the key to go to previous closest monster.
Default is `{\tt M}'.
%.lp
\item{\bb{getpos.obj.next}}
\item[{\bb{getpos.obj.next}}]
When asked for a location, the key to go to next closest object.
Default is `{\tt o}'.
%.lp
\item{\bb{getpos.obj.prev}}
\item[{\bb{getpos.obj.prev}}]
When asked for a location, the key to go to previous closest object.
Default is `{\tt O}'.
%.lp
\item{\bb{getpos.menu}}
\item[{\bb{getpos.menu}}]
When asked for a location, and using one of the next or previous keys to
cycle through targets, toggle showing a menu instead. Default is `{\tt !}'.
%.lp
\item{\bb{getpos.moveskip}}
\item[{\bb{getpos.moveskip}}]
When asked for a location, and using the shifted movement keys or
meta-digit keys to fast-move around, move by skipping the same glyphs
instead of by 8 units.
Default is `{\tt *}'.
%.lp
\item{\bb{getpos.filter}}
\item[{\bb{getpos.filter}}]
When asked for a location, change the filtering mode when using one of
the next or previous keys to cycle through targets. Toggles between no
filtering, in view only, and in the same area only. Default is `{\tt "}'.
%.lp
\item{\bb{getpos.pick}}
\item[{\bb{getpos.pick}}]
When asked for a location, the key to choose the location, and possibly
ask for more info. Default is `{\tt .}'.
%.lp
\item{\bb{getpos.pick.once}}
\item[{\bb{getpos.pick.once}}]
When asked for a location, the key to choose the location, and skip
asking for more info. Default is `{\tt ,}'.
%.lp
\item{\bb{getpos.pick.quick}}
\item[{\bb{getpos.pick.quick}}]
When asked for a location, the key to choose the location, skip asking
for more info, and exit the location asking loop. Default is `{\tt ;}'.
%.lp
\item{\bb{getpos.pick.verbose}}
\item[{\bb{getpos.pick.verbose}}]
When asked for a location, the key to choose the location, and show more
info without asking. Default is `{\tt :}'.
%.lp
\item{\bb{getpos.self}}
\item[{\bb{getpos.self}}]
When asked for a location, the key to go to your location.
Default is `{\tt @}'.
%.lp
\item{\bb{getpos.unexplored.next}}
\item[{\bb{getpos.unexplored.next}}]
When asked for a location, the key to go to next closest unexplored location.
Default is `{\tt x}'.
%.lp
\item{\bb{getpos.unexplored.prev}}
\item[{\bb{getpos.unexplored.prev}}]
When asked for a location, the key to go to previous closest unexplored
location. Default is `{\tt X}'.
%.lp
\item{\bb{getpos.valid}}
\item[{\bb{getpos.valid}}]
When asked for a location, the key to go to show valid target locations.
Default is `{\tt \$}'.
%.lp
\item{\bb{getpos.valid.next}}
\item[{\bb{getpos.valid.next}}]
When asked for a location, the key to go to next closest valid location.
Default is `{\tt z}'.
%.lp
\item{\bb{getpos.valid.prev}}
\item[{\bb{getpos.valid.prev}}]
When asked for a location, the key to go to previous closest valid location.
Default is `{\tt Z}'.
%.lp
\item{\bb{nopickup}}
\item[{\bb{nopickup}}]
Prefix key to move without picking up items. Default is `{\tt m}'.
%.lp
\item{\bb{redraw}}
\item[{\bb{redraw}}]
Key to redraw the screen. Default is `{\tt \^{}R}'.
%.lp
\item{\bb{redraw.numpad}}
\item[{\bb{redraw.numpad}}]
Key to redraw the screen. With {\it number\verb+_+pad\/} only.
Default is `{\tt \^{}L}'.
%.lp
\item{\bb{repeat}}
\item[{\bb{repeat}}]
Key to repeat previous command. Default is `{\tt \^{}A}'.
%.lp
\item{\bb{reqmenu}}
\item[{\bb{reqmenu}}]
Prefix key to request menu from some commands. Default is `{\tt m}'.
%.lp
\item{\bb{run}}
\item[{\bb{run}}]
Prefix key to run towards a direction. Default is `{\tt G}'.
%.lp
\item{\bb{run.nopickup}}
\item[{\bb{run.nopickup}}]
Prefix key to run towards a direction without picking up items on the way.
Default is `{\tt M}'.
%.lp
\item{\bb{run.numpad}}
\item[{\bb{run.numpad}}]
Prefix key to run towards a direction. With {\it number\verb+_+pad\/} only.
Default is `{\tt 5}'.
%.lp
\item{\bb{rush}}
\item[{\bb{rush}}]
Prefix key to rush towards a direction. Default is `{\tt g}'.
\elist
\elist
%.hn 2
@@ -4733,6 +4735,8 @@ combination with any of the other attributes.
To specify both a color and an attribute, use `\&' to combine them.
To specify multiple attributes, use `+' to combine those.
%.lp ""
For example: {\tt magenta\&inverse+dim}.
Note that the display may substitute or ignore particular attributes
@@ -4785,23 +4789,19 @@ percentage or absolute number threshold, or text to match against.
\blist{}
%.lp "*"
\item{\bb{}}
``{\tt always}'' will set the default attributes for that field.
\item[{\tt always}] will set the default attributes for that field.
%.lp "*"
\item{\bb{}}
``{\tt up}'' and ``{\tt down}'' set the field attributes for when the field
\item[{\tt up} and ``{\tt down}''] set the field attributes for when the field
value changes upwards or downwards. This attribute times out after
{\tt statushilites} turns.
%.lp "*"
\item{\bb{}}
``{\tt changed}'' sets the field attribute for when the field value
\item[{\tt changed}] sets the field attribute for when the field value
changes. This attribute times out after {\tt statushilites} turns.
(If a field has both a ``changed'' rule and an ``up'' or ``down''
rule which matches a change in the field's value,
the ``up'' or ``down'' one takes precedence.)
%.lp "*"
\item{\bb{}}
percentage sets the field attribute when the field value
\item[{\tt percentage}] sets the field attribute when the field value
matches the percentage.
It is specified as a number between 0 and 100, followed by `{\tt \%}'
(percent sign).
@@ -4829,8 +4829,7 @@ exactly 1 experience point short of the next level.
% percentage will remain at 0\% no matter have many additional experience
% points you earn.)
%.lp "*"
\item{\bb{}}
absolute value sets the attribute when the field value
\item[{\tt absolute}] value sets the attribute when the field value
matches that number.
The number must be 0 or higher, except for ``{\it armor-class\/} which
allows negative values, and may optionally be preceded by `{\tt =}'.
@@ -4839,8 +4838,7 @@ it also matches when value is below or above.
If the prefix is `{\tt <}' or `{\tt >}', only match when strictly
above or below.
%.lp "*"
\item{\bb{}}
text match sets the attribute when the field value matches the text.
\item[{\tt text}] match sets the attribute when the field value matches the text.
Text matches can only be used for ``{\it alignment\/}'',
``{\it carrying-capacity\/}'', ``{\it hunger\/}'', ``{\it dungeon-level\/}'',
and ``{\it title\/}''.
@@ -5469,7 +5467,7 @@ with help from {\it Ross Brown}, {\it Mike Engber}, {\it David Hairston},
{\it Michael Hamel}, {\it Jonathan Handler}, {\it Johnny Lee},
{\it Tim Lennan}, {\it Rob Menke}, and {\it Andy Swanson},
developed {\it NetHack\/} 3.1 for the Macintosh, porting it for MPW.
Building on their development, {\it Barton House} added a Think C port.
Building on their development, {\it Bart House} added a Think C port.
%.pg
\medskip
@@ -5682,7 +5680,7 @@ maintained the port of {\it NetHack\/} 3.6 for Mac OSX.
%.pg
\medskip
{\it Michael Allison}, {\it David Cohrs}, {\it Barton House},
{\it Michael Allison}, {\it David Cohrs}, {\it Bart House},
{\it Pasi Kallinen}, {\it Alex Kompel}, {\it Dion Nicolaas},
{\it Derek S. Ray} and {\it Yitzhak Sapir}
maintained the port of {\it NetHack\/} 3.6 for Microsoft Windows.
@@ -5716,6 +5714,11 @@ time of release of 3.6.1 consisted of
In early May 2019, another 320 bug fixes along with some enhancements and
the adopted curses window port, were released as 3.6.2.
%.pg
\medskip
{\it Bart House}, who had contributed to the game as a porting team participant
for decades, joined the {\it NetHack Development Team} in late May 2019.
%.pg
\medskip
\nd The official {\it NetHack\/} web site is maintained by {\it Ken Lorber} at
@@ -5757,7 +5760,7 @@ Andreas Dorn & Jeff Bailey & Pasi Kallinen\\
Andy Church & Jochen Erwied & Pat Rankin\\
Andy Swanson & John Kallen & Patric Mueller\\
Ari Huttunen & John Rupley & Paul Winner\\
Barton House & John S. Bien & Pierre Martineau\\
Bart House & John S. Bien & Pierre Martineau\\
Benson I. Margulies & Johnny Lee & Ralf Brown\\
Bill Dyer & Jon W\{tte & Ray Chason\\
Boudewijn Waijers & Jonathan Handler & Richard Addison\\

View File

@@ -21,15 +21,17 @@ extern LONG GetCurrentPackageFullName(UINT32 *packageFullNameLength,
PWSTR packageFullName);
extern HRESULT SHGetKnownFolderPath(REFKNOWNFOLDERID rfid,
DWORD dwFlags, HANDLE hToken, PWSTR *ppszPath);
#ifndef DEFINE_KNOWN_FOLDER
#ifdef INITGUID
#define DEFINE_KNOWN_FOLDER(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) const GUID DECLSPEC_SELECTANY name = { l, w1, w2,{ b1, b2, b3, b4, b5, b6, b7, b8 } }
#else
#define DEFINE_KNOWN_FOLDER(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) const GUID name
#endif
#endif /* INITGUID */
#endif /* DEFINE_KNOWN_FOLDER */
DEFINE_KNOWN_FOLDER (FOLDERID_ProgramData, 0x62ab5d82, 0xfdc1, 0x4dc3, 0xa9, 0xdd, 0x07, 0x0d, 0x1d, 0x49, 0x5d, 0x97);
DEFINE_KNOWN_FOLDER (FOLDERID_LocalAppData, 0xf1b32785, 0x6fba, 0x4fcf, 0x9d, 0x55, 0x7b, 0x8e, 0x7f, 0x15, 0x70, 0x91);
DEFINE_KNOWN_FOLDER (FOLDERID_Profile, 0x5e6c858f, 0x0e22, 0x4760, 0x9a, 0xfe, 0xea, 0x33, 0x17, 0xb6, 0x71, 0x73);
#endif
#endif /* __MINGW32__ */
#if 0
#include "wintty.h"

View File

@@ -172,12 +172,12 @@ BEGIN
CONTROL "Chaotic",IDC_PLSEL_ALIGN_CHAOTIC,"Button",BS_AUTORADIOBUTTON,168,72,38,10
CONTROL "Male",IDC_PLSEL_GENDER_MALE,"Button",BS_AUTORADIOBUTTON | WS_GROUP,168,108,30,10
CONTROL "Female",IDC_PLSEL_GENDER_FEMALE,"Button",BS_AUTORADIOBUTTON,168,120,38,10
GROUPBOX "Alignment",IDC_STATIC,162,36,48,54
GROUPBOX "Gender",IDC_STATIC,162,96,48,42
GROUPBOX "Role",IDC_STATIC,6,36,72,150
GROUPBOX "Race",IDC_STATIC,84,36,72,72
GROUPBOX "Alignment",IDC_PLSEL_ALIGNMENT_GROUP,162,36,48,54
GROUPBOX "Gender",IDC_PLSEL_GENDER_GROUP,162,96,48,42
GROUPBOX "Role",IDC_PLSEL_ROLE_GROUP,6,36,72,150
GROUPBOX "Race",IDC_PLSEL_RACE_GROUP,84,36,72,72
PUSHBUTTON "Random",IDC_PLSEL_RANDOM,90,192,54,14,WS_GROUP
GROUPBOX "Name",IDC_STATIC,6,0,120,30
GROUPBOX "Name",IDC_PLSEL_NAME_GROUP,6,0,120,30
CONTROL "",IDC_PLSEL_ROLE_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_OWNERDRAWFIXED | LVS_ALIGNLEFT | LVS_NOSCROLL | LVS_NOCOLUMNHEADER | WS_BORDER | WS_GROUP | WS_TABSTOP,12,48,60,130
CONTROL "",IDC_PLSEL_RACE_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_OWNERDRAWFIXED | LVS_ALIGNLEFT | LVS_NOSCROLL | LVS_NOCOLUMNHEADER | WS_BORDER | WS_GROUP | WS_TABSTOP,90,48,60,51
END

View File

@@ -4,6 +4,7 @@
/* various dialog boxes are defined here */
#include "win10.h"
#include "winMS.h"
#include "hack.h"
#include "func_tab.h"
@@ -12,6 +13,7 @@
#include <assert.h>
/*---------------------------------------------------------------*/
/* data for getlin dialog */
struct getlin_data {
@@ -276,22 +278,68 @@ ExtCmdDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
/*---------------------------------------------------------------*/
/* player selector dialog */
/* NOTE: this enumeration is in control tab order */
enum player_selector_control {
psc_name_group,
psc_role_group,
psc_race_group,
psc_alignment_group,
psc_gender_group,
psc_name_box,
psc_role_list,
psc_race_list,
psc_lawful_button,
psc_neutral_button,
psc_chaotic_button,
psc_male_button,
psc_female_button,
psc_play_button,
psc_random_button,
psc_quit_button,
psc_control_count
};
static const s_psc_id[psc_control_count] = {
IDC_PLSEL_NAME_GROUP,
IDC_PLSEL_ROLE_GROUP,
IDC_PLSEL_RACE_GROUP,
IDC_PLSEL_ALIGNMENT_GROUP,
IDC_PLSEL_GENDER_GROUP,
IDC_PLSEL_NAME,
IDC_PLSEL_ROLE_LIST,
IDC_PLSEL_RACE_LIST,
IDC_PLSEL_ALIGN_LAWFUL,
IDC_PLSEL_ALIGN_NEUTRAL,
IDC_PLSEL_ALIGN_CHAOTIC,
IDC_PLSEL_GENDER_MALE,
IDC_PLSEL_GENDER_FEMALE,
IDOK,
IDC_PLSEL_RANDOM,
IDCANCEL
};
typedef struct {
int id;
POINT pos;
SIZE size;
HWND hWnd;
} control_t;
typedef struct plsel_data {
HWND dialog;
HWND focus;
control_t controls[psc_control_count];
SIZE client_size;
int config_race;
int config_role;
int config_gender;
int config_alignment;
HWND control_role;
HWND control_race;
HWND control_genders[ROLE_GENDERS];
HWND control_aligns[ROLE_ALIGNS];
int role_count;
int race_count;
HWND focus;
} plsel_data_t;
INT_PTR CALLBACK PlayerSelectorDlgProc(HWND, UINT, WPARAM, LPARAM);
static void plselInitDialog(HWND hWnd);
static void plselAdjustSelections(HWND hWnd);
static boolean plselRandomize(plsel_data_t * data);
static BOOL plselDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam);
@@ -322,38 +370,314 @@ mswin_player_selection_window()
return ok;
}
int
list_view_height(HWND hWnd, int count)
{
return (ListView_ApproximateViewRect(hWnd, -1, -1, count)) >> 16;
}
/* calculate the size and position of the controls taking into account
the per-monitor DPI expressed as a scaling factor on sizes at 96 DPI */
void
calculate_player_selector_layout(plsel_data_t * data)
{
MonitorInfo monitorInfo;
win10_monitor_info(data->dialog, &monitorInfo);
double scale = monitorInfo.scale;
/* Note these hard coded sizes are in 96DPI pixels and must be
scaled by the per-monitor DPI scaling factor */
int list_width = (int) (120 * scale);
int group_border = (int) (16 * scale);
int client_border = (int) (16 * scale);
int group_spacing = (int) (16 * scale);
int button_width = (int) (80 * scale);
int button_height = (int) (28 * scale);
/* set control sizes */
control_t * name_box = &data->controls[psc_name_box];
name_box->size.cx = (int) (280 * scale);
name_box->size.cy = (int) (24 * scale);
control_t * role_list = &data->controls[psc_role_list];
/* NOTE: we dont' scale the list view reported height as it appears these
values are the actual size the control will be drawn at using the
existing DPI value */
role_list->size.cy = list_view_height(role_list->hWnd, data->role_count);
role_list->size.cx = list_width;
control_t * race_list = &data->controls[psc_race_list];
race_list->size.cy = list_view_height(race_list->hWnd, data->race_count);
race_list->size.cx = list_width;
for(int i = psc_lawful_button; i <= psc_quit_button; i++) {
data->controls[i].size.cx = button_width;
data->controls[i].size.cy = button_height;
}
for(int i = 0; i < 3; i++) {
control_t * group_control = &data->controls[psc_name_group + i];
control_t * inner_control = &data->controls[psc_name_box + i];
group_control->size.cx = inner_control->size.cx + (2 * group_border);
group_control->size.cy = inner_control->size.cy + (2 * group_border);
}
control_t * alignment_group = &data->controls[psc_alignment_group];
alignment_group->size.cx = button_width + (2 * group_border);
alignment_group->size.cy = (3 * button_height) + (2 * group_border);
control_t * gender_group = &data->controls[psc_gender_group];
gender_group->size.cx = button_width + (2 * group_border);
gender_group->size.cy = (2 * button_height) + (2 * group_border);
/* set control positions */
control_t * name_group = &data->controls[psc_name_group];
name_group->pos.x = client_border;
name_group->pos.y = client_border;
control_t * role_group = &data->controls[psc_role_group];
role_group->pos.x = client_border;
role_group->pos.y = name_group->pos.y + name_group->size.cy + group_spacing;
control_t * race_group = &data->controls[psc_race_group];
race_group->pos.x = role_group->pos.x + role_group->size.cx + group_spacing;
race_group->pos.y = role_group->pos.y;
for(int i = 0; i < 3; i++) {
control_t * group_control = &data->controls[psc_name_group + i];
control_t * inner_control = &data->controls[psc_name_box + i];
inner_control->pos.x = group_control->pos.x + group_border;
inner_control->pos.y = group_control->pos.y + group_border;
}
alignment_group->pos.x = race_group->pos.x + race_group->size.cx + group_spacing;
alignment_group->pos.y = race_group->pos.y;
for(int i = psc_lawful_button; i <= psc_chaotic_button; i++) {
data->controls[i].pos.x = alignment_group->pos.x + group_border;
data->controls[i].pos.y = alignment_group->pos.y + group_border +
((i -psc_lawful_button) * button_height);
}
gender_group->pos.x = alignment_group->pos.x;
gender_group->pos.y = alignment_group->pos.y + alignment_group->size.cy + group_spacing;
for(int i = psc_male_button; i <= psc_female_button; i++) {
data->controls[i].pos.x = gender_group->pos.x + group_border;
data->controls[i].pos.y = gender_group->pos.y + group_border +
((i - psc_male_button) * button_height);
}
int group_bottom = role_group->pos.y + role_group->size.cy;
if (group_bottom < race_group->pos.y + race_group->size.cy)
group_bottom = race_group->pos.y + race_group->size.cy;
if (group_bottom < gender_group->pos.y + gender_group->size.cy)
group_bottom = gender_group->pos.y + gender_group->size.cy;
control_t * play_button = &data->controls[psc_play_button];
play_button->pos.y = group_bottom + group_spacing;
play_button->pos.x = role_group->pos.x;
control_t * random_button = &data->controls[psc_random_button];
random_button->pos.y = play_button->pos.y;
random_button->pos.x = race_list->pos.x;
control_t * quit_button = &data->controls[psc_quit_button];
quit_button->pos.y = play_button->pos.y;
quit_button->pos.x = data->controls[psc_female_button].pos.x;
data->client_size.cx = alignment_group->pos.x + alignment_group->size.cx;
data->client_size.cy = quit_button->pos.y + quit_button->size.cy;
data->client_size.cx += client_border;
data->client_size.cy += client_border;
}
void
get_rect_size(RECT * rect, SIZE * size)
{
size->cx = rect->right - rect->left + 1;
size->cy = rect->bottom - rect->top + 1;
}
/* center given dialog in the main window */
void
center_dialog(HWND dialog)
{
RECT main_rect;
SIZE main_size;
RECT dialog_rect;
SIZE dialog_size;
POINT pos;
GetWindowRect(GetNHApp()->hMainWnd, &main_rect);
get_rect_size(&main_rect, &main_size);
GetWindowRect(dialog, &dialog_rect);
get_rect_size(&dialog_rect, &dialog_size);
pos.x = main_rect.left + (main_size.cx - dialog_size.cx) / 2;
pos.y = main_rect.top + (main_size.cy - dialog_size.cy) / 2;
MoveWindow(dialog, pos.x, pos.y, dialog_size.cx, dialog_size.cy,
TRUE);
}
/* size the dialog such that it has the given client rect size */
void
size_dialog(HWND dialog, SIZE new_client_size)
{
RECT dialog_rect;
SIZE dialog_size;
RECT client_rect;
SIZE client_size;
GetWindowRect(dialog, &dialog_rect);
get_rect_size(&dialog_rect, &dialog_size);
GetClientRect(dialog, &client_rect);
get_rect_size(&client_rect, &client_size);
dialog_size.cx += new_client_size.cx - client_size.cx;
dialog_size.cy += new_client_size.cy - client_size.cy;
MoveWindow(dialog, dialog_rect.left, dialog_rect.top,
dialog_size.cx, dialog_size.cy, TRUE);
}
/* helper routine to move all controls according to there position
and size information */
void
move_controls(control_t * controls, int count)
{
control_t * control = controls;
while(count-- > 0) {
MoveWindow(control->hWnd, control->pos.x, control->pos.y,
control->size.cx, control->size.cy, TRUE);
control++;
}
}
/* adjust the size and positions of all controls in the player
selection dialog taking into account the per-monitor DPI. */
void
do_player_selector_layout(plsel_data_t * data)
{
calculate_player_selector_layout(data);
move_controls(data->controls, psc_control_count);
size_dialog(data->dialog, data->client_size);
}
/* initialize player selector dialog */
void
plselInitDialog(struct plsel_data * data)
{
TCHAR wbuf[BUFSZ];
LVCOLUMN lvcol;
SetWindowLongPtr(data->dialog, GWLP_USERDATA, (LONG_PTR) data);
for(int i = 0; i < psc_control_count; i++) {
data->controls[i].id = s_psc_id[i];
data->controls[i].hWnd = GetDlgItem(data->dialog, s_psc_id[i]);
}
control_t * role_list = &data->controls[psc_role_list];
ZeroMemory(&lvcol, sizeof(lvcol));
lvcol.mask = LVCF_WIDTH;
lvcol.cx = 1024;
/* build role list */
ListView_InsertColumn(role_list->hWnd, 0, &lvcol);
data->role_count = 0;
for (int i = 0; roles[i].name.m; i++) {
LVITEM lvitem;
ZeroMemory(&lvitem, sizeof(lvitem));
lvitem.mask = LVIF_STATE | LVIF_TEXT;
lvitem.iItem = i;
lvitem.iSubItem = 0;
lvitem.state = 0;
lvitem.stateMask = LVIS_FOCUSED;
if (flags.female && roles[i].name.f)
lvitem.pszText = NH_A2W(roles[i].name.f, wbuf, BUFSZ);
else
lvitem.pszText = NH_A2W(roles[i].name.m, wbuf, BUFSZ);
if (ListView_InsertItem(role_list->hWnd, &lvitem) == -1) {
panic("cannot insert menu item");
}
data->role_count++;
}
/* build race list */
control_t * race_list = &data->controls[psc_race_list];
ListView_InsertColumn(race_list->hWnd, 0, &lvcol);
data->race_count = 0;
for (int i = 0; races[i].noun; i++) {
LVITEM lvitem;
ZeroMemory(&lvitem, sizeof(lvitem));
lvitem.mask = LVIF_STATE | LVIF_TEXT;
lvitem.iItem = i;
lvitem.iSubItem = 0;
lvitem.state = 0;
lvitem.stateMask = LVIS_FOCUSED;
lvitem.pszText = NH_A2W(races[i].noun, wbuf, BUFSZ);
if (ListView_InsertItem(race_list->hWnd, &lvitem) == -1) {
panic("cannot insert menu item");
}
data->race_count++;
}
/* set gender radio button state */
control_t * gender_buttons = &data->controls[psc_male_button];
for (int i = 0; i < ROLE_GENDERS; i++)
Button_Enable(gender_buttons[i].hWnd, TRUE);
Button_SetCheck(data->controls[psc_male_button].hWnd, BST_CHECKED);
/* set alignment radio button state */
control_t * alignment_buttons = &data->controls[psc_lawful_button];
for (int i = 0; i < ROLE_ALIGNS; i++)
Button_Enable(alignment_buttons[i].hWnd, TRUE);
Button_SetCheck(data->controls[psc_lawful_button].hWnd, BST_CHECKED);
/* set player name */
control_t * name_box = &data->controls[psc_name_box];
SetDlgItemText(data->dialog, name_box->id, NH_A2W(g.plname, wbuf, sizeof(wbuf)));
plselRandomize(data);
/* populate select boxes */
plselAdjustSelections(data->dialog);
/* set tab order */
control_t * control = &data->controls[psc_quit_button];
for(int i = psc_quit_button; i >= psc_name_box; i--, control++)
SetWindowPos(control->hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
do_player_selector_layout(data);
center_dialog(data->dialog);
}
INT_PTR CALLBACK
PlayerSelectorDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
struct plsel_data *data;
RECT main_rt, dlg_rt;
SIZE dlg_sz;
plsel_data_t *data;
switch (message) {
case WM_INITDIALOG:
data = (struct plsel_data *) lParam;
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) data);
/* center dialog in the main window */
GetWindowRect(GetNHApp()->hMainWnd, &main_rt);
GetWindowRect(hWnd, &dlg_rt);
dlg_sz.cx = dlg_rt.right - dlg_rt.left;
dlg_sz.cy = dlg_rt.bottom - dlg_rt.top;
data = (plsel_data_t *) lParam;
data->dialog = hWnd;
dlg_rt.left = (main_rt.left + main_rt.right - dlg_sz.cx) / 2;
dlg_rt.right = dlg_rt.left + dlg_sz.cx;
dlg_rt.top = (main_rt.top + main_rt.bottom - dlg_sz.cy) / 2;
dlg_rt.bottom = dlg_rt.top + dlg_sz.cy;
MoveWindow(hWnd, (main_rt.left + main_rt.right - dlg_sz.cx) / 2,
(main_rt.top + main_rt.bottom - dlg_sz.cy) / 2, dlg_sz.cx,
dlg_sz.cy, TRUE);
/* init dialog */
plselInitDialog(hWnd);
plselInitDialog(data);
/* tell windows to set the focus */
return TRUE;
break;
case WM_DRAWITEM:
if (wParam == IDC_PLSEL_ROLE_LIST || wParam == IDC_PLSEL_RACE_LIST)
@@ -367,20 +691,23 @@ PlayerSelectorDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
data = (struct plsel_data *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
control_t * role_control = &data->controls[psc_role_list];
control_t * race_control = &data->controls[psc_race_list];
switch (nmhdr->code) {
case LVN_KEYDOWN:
{
LPNMLVKEYDOWN lpnmkeydown = (LPNMLVKEYDOWN) lParam;
if (lpnmkeydown->wVKey == ' ') {
if (control == data->control_role) {
int i = ListView_GetNextItem(data->control_role, -1, LVNI_FOCUSED);
assert(i == -1 || ListView_GetNextItem(data->control_role, i, LVNI_FOCUSED) == -1);
if (control == role_control->hWnd) {
int i = ListView_GetNextItem(control, -1, LVNI_FOCUSED);
assert(i == -1 || ListView_GetNextItem(control, i, LVNI_FOCUSED) == -1);
flags.initrole = i;
plselAdjustSelections(hWnd);
} else if (control == data->control_race) {
int i = ListView_GetNextItem(data->control_race, -1, LVNI_FOCUSED);
assert(i == -1 || ListView_GetNextItem(data->control_race, i, LVNI_FOCUSED) == -1);
} else if (control == race_control->hWnd) {
int i = ListView_GetNextItem(control, -1, LVNI_FOCUSED);
assert(i == -1 || ListView_GetNextItem(control, i, LVNI_FOCUSED) == -1);
if (ok_race(flags.initrole, i, ROLE_RANDOM, ROLE_RANDOM)) {
flags.initrace = i;
plselAdjustSelections(hWnd);
@@ -395,10 +722,10 @@ PlayerSelectorDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
int i = lpnmitem->iItem;
if (i == -1)
return FALSE;
if (control == data->control_role) {
if (control == role_control->hWnd) {
flags.initrole = i;
plselAdjustSelections(hWnd);
} else if(control == data->control_race) {
} else if(control == race_control->hWnd) {
if (ok_race(flags.initrole, i, ROLE_RANDOM, ROLE_RANDOM)) {
flags.initrace = i;
plselAdjustSelections(hWnd);
@@ -408,12 +735,12 @@ PlayerSelectorDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
break;
case NM_KILLFOCUS:
{
if (data->focus == data->control_race) {
if (data->focus == race_control->hWnd) {
data->focus = NULL;
ListView_RedrawItems(data->control_race, 0, data->race_count - 1);
} else if (data->focus == data->control_role) {
ListView_RedrawItems(race_control->hWnd, 0, data->race_count - 1);
} else if (data->focus == role_control->hWnd) {
data->focus = NULL;
ListView_RedrawItems(data->control_role, 0, data->role_count - 1);
ListView_RedrawItems(role_control->hWnd, 0, data->role_count - 1);
}
}
break;
@@ -421,11 +748,11 @@ PlayerSelectorDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
data->focus = control;
if (control == data->control_race) {
data->focus = data->control_race;
if (control == race_control->hWnd) {
data->focus = control;
plselAdjustSelections(hWnd);
} else if (control == data->control_role) {
data->focus = data->control_role;
} else if (control == role_control->hWnd) {
data->focus = control;
plselAdjustSelections(hWnd);
}
}
@@ -478,109 +805,29 @@ PlayerSelectorDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
}
break;
case WM_DPICHANGED:
{
data = (struct plsel_data *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
do_player_selector_layout(data);
InvalidateRect(hWnd, NULL, TRUE);
} break;
}
return FALSE;
}
/* initialize player selector dialog */
void
plselInitDialog(HWND hWnd)
{
struct plsel_data * data = (plsel_data_t *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
TCHAR wbuf[BUFSZ];
LVCOLUMN lvcol;
data->control_role = GetDlgItem(hWnd, IDC_PLSEL_ROLE_LIST);
data->control_race = GetDlgItem(hWnd, IDC_PLSEL_RACE_LIST);
ZeroMemory(&lvcol, sizeof(lvcol));
lvcol.mask = LVCF_WIDTH;
lvcol.cx = GetSystemMetrics(SM_CXFULLSCREEN);
/* build role list */
ListView_InsertColumn(data->control_role, 0, &lvcol);
data->role_count = 0;
for (int i = 0; roles[i].name.m; i++) {
LVITEM lvitem;
ZeroMemory(&lvitem, sizeof(lvitem));
lvitem.mask = LVIF_STATE | LVIF_TEXT;
lvitem.iItem = i;
lvitem.iSubItem = 0;
lvitem.state = 0;
lvitem.stateMask = LVIS_FOCUSED;
if (flags.female && roles[i].name.f)
lvitem.pszText = NH_A2W(roles[i].name.f, wbuf, BUFSZ);
else
lvitem.pszText = NH_A2W(roles[i].name.m, wbuf, BUFSZ);
if (ListView_InsertItem(data->control_role, &lvitem) == -1) {
panic("cannot insert menu item");
}
data->role_count++;
}
/* build race list */
ListView_InsertColumn(data->control_race, 0, &lvcol);
data->race_count = 0;
for (int i = 0; races[i].noun; i++) {
LVITEM lvitem;
ZeroMemory(&lvitem, sizeof(lvitem));
lvitem.mask = LVIF_STATE | LVIF_TEXT;
lvitem.iItem = i;
lvitem.iSubItem = 0;
lvitem.state = 0;
lvitem.stateMask = LVIS_FOCUSED;
lvitem.pszText = NH_A2W(races[i].noun, wbuf, BUFSZ);
if (ListView_InsertItem(data->control_race, &lvitem) == -1) {
panic("cannot insert menu item");
}
data->race_count++;
}
for(int i = 0; i < ROLE_GENDERS; i++)
data->control_genders[i] = GetDlgItem(hWnd, IDC_PLSEL_GENDER_MALE + i);
for(int i = 0; i < ROLE_ALIGNS; i++)
data->control_aligns[i] = GetDlgItem(hWnd, IDC_PLSEL_ALIGN_LAWFUL + i);
/* set gender radio button state */
for (int i = 0; i < ROLE_GENDERS; i++)
Button_Enable(data->control_genders[i], TRUE);
Button_SetCheck(data->control_genders[0], BST_CHECKED);
/* set alignment radio button state */
for (int i = 0; i < ROLE_ALIGNS; i++)
Button_Enable(data->control_aligns[i], TRUE);
Button_SetCheck(data->control_aligns[0], BST_CHECKED);
/* set player name */
SetDlgItemText(hWnd, IDC_PLSEL_NAME, NH_A2W(g.plname, wbuf, sizeof(wbuf)));
plselRandomize(data);
/* populate select boxes */
plselAdjustSelections(hWnd);
/* set tab order */
SetWindowPos(GetDlgItem(hWnd, IDCANCEL), NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
SetWindowPos(GetDlgItem(hWnd, IDC_PLSEL_RANDOM), NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
SetWindowPos(GetDlgItem(hWnd, IDOK), NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
for(int i = ROLE_GENDERS - 1; i >= 0; i--)
SetWindowPos(data->control_genders[i], NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
for(int i = ROLE_ALIGNS - 1; i >= 0; i--)
SetWindowPos(data->control_aligns[i], NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
SetWindowPos(data->control_race, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
SetWindowPos(data->control_role, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}
void
plselAdjustSelections(HWND hWnd)
{
struct plsel_data * data = (plsel_data_t *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
control_t * role_control = &data->controls[psc_role_list];
control_t * race_control = &data->controls[psc_race_list];
if (!ok_race(flags.initrole, flags.initrace, ROLE_RANDOM, ROLE_RANDOM))
flags.initrace = pick_race(flags.initrole, ROLE_RANDOM, ROLE_RANDOM, ROLE_RANDOM);
@@ -590,29 +837,31 @@ plselAdjustSelections(HWND hWnd)
if (!ok_align(flags.initrole, flags.initrace, flags.initgend, flags.initalign))
flags.initalign = pick_align(flags.initrole, flags.initrace, flags.initgend , ROLE_RANDOM);
ListView_RedrawItems(data->control_role, 0, data->role_count - 1);
ListView_RedrawItems(data->control_race, 0, data->race_count - 1);
ListView_RedrawItems(role_control->hWnd, 0, data->role_count - 1);
ListView_RedrawItems(race_control->hWnd, 0, data->race_count - 1);
/* set gender radio button state */
for (int i = 0; i < ROLE_GENDERS; i++) {
HWND button = data->controls[psc_male_button+i].hWnd;
BOOL enable = ok_gend(flags.initrole, flags.initrace, i, flags.initalign);
Button_Enable(data->control_genders[i], enable);
LRESULT state = Button_GetCheck(data->control_genders[i]);
Button_Enable(button, enable);
LRESULT state = Button_GetCheck(button);
if (state == BST_CHECKED && flags.initgend != i)
Button_SetCheck(data->control_genders[i], BST_UNCHECKED);
Button_SetCheck(button, BST_UNCHECKED);
if (state == BST_UNCHECKED && flags.initgend == i)
Button_SetCheck(data->control_genders[i], BST_CHECKED);
Button_SetCheck(button, BST_CHECKED);
}
/* set alignment radio button state */
for (int i = 0; i < ROLE_ALIGNS; i++) {
HWND button = data->controls[psc_lawful_button+i].hWnd;
BOOL enable = ok_align(flags.initrole, flags.initrace, flags.initgend, i);
Button_Enable(data->control_aligns[i], enable);
LRESULT state = Button_GetCheck(data->control_aligns[i]);
Button_Enable(button, enable);
LRESULT state = Button_GetCheck(button);
if (state == BST_CHECKED && flags.initalign != i)
Button_SetCheck(data->control_aligns[i], BST_UNCHECKED);
Button_SetCheck(button, BST_UNCHECKED);
if (state == BST_UNCHECKED && flags.initalign == i)
Button_SetCheck(data->control_aligns[i], BST_CHECKED);
Button_SetCheck(button, BST_CHECKED);
}
}

View File

@@ -1,6 +1,6 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by winhack.rc
// Used by NetHackW.rc
//
#define IDC_MYICON 2
#define IDD_WINHACK_DIALOG 102
@@ -114,6 +114,11 @@
#define IDC_PLSEL_ALIGN_CHAOTIC 1336
#define IDC_PLSEL_GENDER_MALE 1337
#define IDC_PLSEL_GENDER_FEMALE 1338
#define IDC_PLSEL_NAME_GROUP 1339
#define IDC_PLSEL_ROLE_GROUP 1340
#define IDC_PLSEL_RACE_GROUP 1341
#define IDC_PLSEL_ALIGNMENT_GROUP 1342
#define IDC_PLSEL_GENDER_GROUP 1343
#define IDM_SAVE 32771
#define IDM_HELP_LONG 32772
#define IDM_HELP_COMMANDS 32773

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" IgnorableNamespaces="uap mp rescap">
<Identity Name="30485NetHackDevTeam.NetHack3.6" Publisher="CN=8BDC628A-FAAA-4EBA-8B5B-EB61BA93BA1F" Version="363.0.19.0" />
<Identity Name="30485NetHackDevTeam.NetHack3.6" Publisher="CN=8BDC628A-FAAA-4EBA-8B5B-EB61BA93BA1F" Version="363.0.20.0" />
<Properties>
<DisplayName>NetHack 3.6</DisplayName>
<PublisherDisplayName>NetHack DevTeam</PublisherDisplayName>

View File

@@ -206,6 +206,18 @@
<ClInclude Include="$(WinWin32Dir)mhstatus.h" />
<ClInclude Include="$(WinWin32Dir)mhtext.h" />
<ClInclude Include="$(WinWin32Dir)winMS.h" />
<ClInclude Include="..\resource.h" />
</ItemGroup>
<ItemGroup>
<Image Include="..\mnsel.bmp" />
<Image Include="..\mnselcnt.bmp" />
<Image Include="..\mnunsel.bmp" />
<Image Include="..\NETHACK.ICO" />
<Image Include="..\petmark.bmp" />
<Image Include="..\pilemark.bmp" />
<Image Include="..\rip.bmp" />
<Image Include="..\splash.bmp" />
<Image Include="..\tiles.bmp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Target Name="AfterBuild">
@@ -217,4 +229,4 @@
<Target Name="AfterRebuild">
<MSBuild Projects="afternethack.proj" Targets="Build" Properties="Configuration=$(Configuration)" />
</Target>
</Project>
</Project>