1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 1997, 2005 - 3D Realms Entertainment
4
5 This file is part of Shadow Warrior version 1.2
6
7 Shadow Warrior is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
16 See the GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22 Original Source: 1997 - Frank Maddin and Jim Norwood
23 Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
24 */
25 //-------------------------------------------------------------------------
26 #include "build.h"
27 #include "osd.h"
28
29 #include "keys.h"
30 #include "names2.h"
31 #include "panel.h"
32 #include "game.h"
33 #include "tags.h"
34 #include "sector.h"
35 #include "sprite.h"
36 #include "weapon.h"
37 #include "player.h"
38 #include "jsector.h"
39 #include "control.h"
40 #include "menus.h"
41 #include "sw_strs.h"
42 #include "pal.h"
43 #include "demo.h"
44
45 #include "function.h"
46 #include "gamedefs.h"
47 #include "config.h"
48 #include "net.h"
49 #include "fx_man.h"
50 #include "music.h"
51 #include "text.h"
52
53 #include "colormap.h"
54
55 //#define PLOCK_VERSION TRUE
56
57
58 short TimeLimitTable[9] = {0,3,5,10,15,20,30,45,60};
59
60 short QuickLoadNum = -1;
61 char QuickLoadDescrDialog[32];
62 BOOL QuickSaveMode = FALSE;
63 BOOL SavePrompt = FALSE;
64 extern BOOL InMenuLevel, LoadGameOutsideMoveLoop, LoadGameFromDemo;
65 extern BYTE RedBookSong[40];
66 extern BOOL ExitLevel, NewGame;
67 extern short Level, Skill;
68 extern BOOL MusicInitialized, FxInitialized;
69 BOOL MNU_CheckUserMap(MenuItem *item);
70 BOOL MNU_SaveGameCheck(MenuItem_p item);
71 BOOL MNU_TeamPlayCheck(MenuItem *item);
72 BOOL MNU_CoopPlayCheck(MenuItem *item);
73 BOOL MNU_StatCheck(MenuItem *item);
74 BOOL MNU_LoadGameCheck(MenuItem *item);
75 static BOOL MNU_TryMusicInit(void);
76 static void MNU_UpLevel(void);
77
78 BOOL MNU_LoadSaveDraw(UserCall call, MenuItem * item);
79 BOOL MNU_LoadSaveMove(UserCall call, MenuItem * item);
80
81 BOOL MenuButtonAutoRun = FALSE;
82 BOOL MenuButtonAutoAim = FALSE;
83 // misc load-save vars
84 short LastSaveNum = 99;
85 char SaveGameDescr[10][80];
86 char BackupSaveGameDescr[80];
87 short screen_tile = -1;
88
89 BOOL MenuInputMode = FALSE;
90 SHORT MenuTextShade = 0;
91 BOOL passwordvalid = FALSE;
92
93 BOOL MNU_HurtTeammateCheck(MenuItem *item);
94 BOOL MNU_TeamPlayChange(void);
95
96 // Font pic table
97 unsigned short xlatfont[] = {
98 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32
99 2274, 2294, 2274, 2277, 2278, 2280, 2295, 2282, 2283, 2281, 2286, 2297, 2285, // 45
100 2299, 2301, 2271, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, // 57
101 2292, 2293, 2296, 2287, 2298, 2300, 2275, 2236, 2237, 2238, 2239, 2240, // 69
102 2241, 2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, // 81
103 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, 2261, 2290, 2289, 2291, // 93
104 2279, 2284, 2295, 2236, 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, // 105
105 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, // 117
106 2257, 2258, 2259, 2260, 2261, 2282, 2288, 2283, 2272 // 126
107 };
108
109 int slidersettings [sldr_max] =
110 {
111 0, SENSE_DEFAULT, FXVOL_DEFAULT, MUSIC_DEFAULT, SCRSIZE_DEFAULT,
112 BRIGHTNESS_DEFAULT, BORDERTILE_DEFAULT, GAMETYPE_DEFAULT, NETLEVEL_DEFAULT,
113 MONSTERS_DEFAULT, KILLLIMIT_DEFAULT, TIMELIMIT_DEFAULT, PLAYERCOLOR_DEFAULT,
114 0,0, // video mode
115 32767>>12, 32767>>12, // advanced mouse scale
116 0, 0, 0, 0, // joystick axis configuration
117 PANELSCALE_DEFAULT
118 };
119
120 short buttonsettings[btn_max];
121
122 // EXTERNS ////////////////////////////
123 #define XDIM 320
124 #define YDIM 200
125 extern char DefaultPalette[];
126 extern BOOL QuitFlag;
127
128 void TerminateGame(void);
129 void ResetKeys(void);
130
131 // GLOBALS ////////////////////////////
132
133 char playertextbuffer[80]; // Used for various input strings
134 char playerbuflen = 0; // Current length of the string in
135 // the buffer
136 char maxtextlen; // max length allowed for current
137
138 static VMODE validresolutions[MAXVALIDMODES];
139 static int numvalidresolutions = 0, validbpps[8], numvalidbpps = 0;
140
UpdateValidModes(int bpp,int fs)141 static void UpdateValidModes(int bpp, int fs)
142 {
143 int i, j;
144
145 numvalidresolutions = numvalidbpps = 0;
146 for (i=0; i<validmodecnt; i++) {
147 if ((validmode[i].fs & 1) != fs) continue;
148
149 for (j=0; j<numvalidbpps; j++)
150 if (validbpps[j] == validmode[i].bpp) break;
151 if (j==numvalidbpps) validbpps[numvalidbpps++] = validmode[i].bpp;
152
153 if (validmode[i].bpp != bpp) continue;
154
155 validresolutions[numvalidresolutions].x = validmode[i].xdim;
156 validresolutions[numvalidresolutions].y = validmode[i].ydim;
157 validresolutions[numvalidresolutions].bpp = validmode[i].bpp;
158 validresolutions[numvalidresolutions].fs = validmode[i].fs;
159 numvalidresolutions++;
160 }
161 }
162
163
164 MenuItem sound_i[] =
165 {
166 {DefButton(btn_music, 0, "Music"), OPT_XS, OPT_LINE(0), 1, m_defshade, 0, MNU_TryMusicInit, MNU_MusicCheck, NULL},
167 {DefSlider(sldr_musicvolume, 0, "Music Volume"), OPT_XS, OPT_LINE(1), 1, m_defshade, 0, MNU_TryMusicInit, MNU_MusicCheck, NULL},
168 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(1), 0, m_defshade, 0, NULL, NULL, NULL},
169
170 {DefButton(btn_sound, 0, "Sounds"), OPT_XS, OPT_LINE(2), 1, m_defshade, 0, NULL, MNU_FxCheck, NULL},
171 {DefSlider(sldr_sndfxvolume, 0, "Sound Volume"), OPT_XS, OPT_LINE(3), 1, m_defshade, 0, NULL, MNU_FxCheck, NULL},
172 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(3), 0, m_defshade, 0, NULL, NULL, NULL},
173
174 //{DefButton(btn_talking, 0, "Talking"), OPT_XS, OPT_LINE(4), 1, m_defshade, 0, NULL, MNU_FxCheck, NULL},
175 {DefButton(btn_ambience, 0, "Ambience"), OPT_XS, OPT_LINE(4), 1, m_defshade, 0, NULL, MNU_FxCheck, NULL},
176 {DefButton(btn_flipstereo, 0, "Flip Stereo"), OPT_XS, OPT_LINE(5), 1, m_defshade, 0, NULL, MNU_FxCheck, NULL},
177 //{DefButton(btn_playcd, 0, "Play CD"), OPT_XS, OPT_LINE(6), 1, m_defshade, 0, NULL, NULL, NULL},
178 {DefNone}
179 };
180
181 MenuGroup soundgroup = {110,5,"^Sound",sound_i,pic_optionstitl,0,m_defshade, NULL,NULL, 0};
182
183 MenuItem parental_i[] =
184 {
185 {DefButton(btn_parental, 0, "Kid Mode"), OPT_XS, OPT_LINE(0), 1, m_defshade, 0, NULL, NULL, NULL},
186 {DefOption(KEYSC_P, "Change Password"), OPT_XS, OPT_LINE(1), 1, m_defshade, 0, MNU_ParentalCustom, NULL, NULL},
187 {DefNone}
188 };
189
190 MenuGroup parentalgroup = {65, 5, "^Kid Mode", parental_i, pic_newgametitl, 0, m_defshade, MNU_DoParentalPassword,NULL,0};
191
192 MenuItem screen_i[] =
193 {
194 {DefSlider(sldr_scrsize, 0, "Screen Size"), OPT_XS, OPT_LINE(0), 1, m_defshade, 0, NULL, NULL, NULL},//, MNU_BorderCheck},
195 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(0), 0, m_defshade, 0, NULL, NULL, NULL},
196
197 {DefSlider(sldr_bordertile, 0, "Border Tile"), OPT_XS, OPT_LINE(1), 1, m_defshade, 0, NULL, NULL, NULL},//, MNU_BorderCheck},
198 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(1), 0, m_defshade, 0, NULL, NULL, NULL},
199
200 {DefSlider(sldr_brightness, KEYSC_B, "Brightness"), OPT_XS, OPT_LINE(2), 1, m_defshade, 0, NULL, NULL, NULL},
201 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(2), 0, m_defshade, 0, NULL, NULL, NULL},
202
203 {DefSlider(sldr_panelscale, 0, "Panel Scale"), OPT_XS, OPT_LINE(3), 1, m_defshade, 0, NULL, NULL, NULL},
204 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(3), 0, m_defshade, 0, NULL, NULL, NULL},
205
206 #if USE_POLYMOST && USE_OPENGL
207 {DefButton(btn_texfilter, 0, "Filtering"), OPT_XS, OPT_LINE(5), 1, m_defshade, 0, NULL, MNU_TexFilterCheck, NULL},
208 #endif
209 {DefButton(btn_videofs, 0, "Fullscreen"), OPT_XS, OPT_LINE(6), 1, m_defshade, 0, NULL, NULL, NULL},
210 {DefSlider(sldr_videobpp, 0, "Colour"), OPT_XS, OPT_LINE(7), 1, m_defshade, 0, NULL, NULL, NULL},
211 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(7), 0, m_defshade, 0, NULL, NULL, NULL},
212 {DefSlider(sldr_videores, 0, "Resolution"), OPT_XS, OPT_LINE(8), 1, m_defshade, 0, NULL, NULL, NULL},
213 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(8), 0, m_defshade, 0, NULL, NULL, NULL},
214 {DefOption(0, "Apply Settings"), OPT_XSIDE, OPT_LINE(10), 1, m_defshade, 0, MNU_ApplyVideoModeSettings, NULL, NULL},
215 {DefNone}
216 };
217
218 MenuGroup screengroup = {65, 5, "^Screen", screen_i, pic_newgametitl, 0, m_defshade, NULL,NULL, 0};
219
220 MenuItem mouse_i[] =
221 {
222 {DefSlider(sldr_mouse, 0, "Mouse Speed"), OPT_XS, OPT_LINE(0), 1, m_defshade, 0, NULL, MNU_MouseCheck, NULL},
223 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(0), 0, m_defshade, 0, NULL, NULL, NULL}, // Blank line for mouse
224
225 {DefButton(btn_mouse_aim, 0, "Mouse Aiming"), OPT_XS, OPT_LINE(1), 1, m_defshade, 0, NULL, MNU_MouseCheck, NULL},
226 {DefButton(btn_mouse_invert, 0, "Invert Mouse"), OPT_XS, OPT_LINE(2), 1, m_defshade, 0, NULL, MNU_MouseCheck, NULL},
227 {DefNone}
228 };
229
230 MenuGroup mousegroup = {65, 5, "^Mouse", mouse_i, pic_newgametitl, 0, m_defshade, NULL,NULL, 0};
231
232 MenuGroup keysetupgroup = {0, 0, NULL, NULL, 0, 0, m_defshade, MNU_KeySetupCustom, NULL, 0};
233
234 static char MouseButtonFunctions[MAXMOUSEBUTTONS][2][MAXFUNCTIONLENGTH];
235 static BOOL MNU_SetMouseButtonFunctions(MenuItem_p item);
236 static BOOL MNU_MouseButtonPostProcess(MenuItem_p item);
237 static BOOL MNU_MouseButtonSetupCustom(UserCall call, MenuItem_p item);
238 MenuGroup mousebuttongroup = {0, 0, NULL, NULL, 0, 0, m_defshade, MNU_MouseButtonSetupCustom, NULL, 0};
239 MenuItem mousesetup_i[] =
240 {
241 {DefLayer(0, "Left", &mousebuttongroup), OPT_XS, OPT_LINE(0), 1, m_defshade, mousebutton_Left, NULL, NULL, MNU_MouseButtonPostProcess},
242 {DefInert(0, MouseButtonFunctions[mousebutton_Left][0]), OPT_XSIDE, OPT_LINE(0), 1, m_defshade, mousebutton_Left, NULL, MNU_SetMouseButtonFunctions, NULL},
243 {DefLayer(0, "Double Left", &mousebuttongroup), OPT_XS, OPT_LINE(1), 1, m_defshade, 128+mousebutton_Left, NULL, NULL, MNU_MouseButtonPostProcess},
244 {DefInert(0, MouseButtonFunctions[mousebutton_Left][1]), OPT_XSIDE, OPT_LINE(1), 1, m_defshade, 128+mousebutton_Left, NULL, MNU_SetMouseButtonFunctions, NULL},
245 {DefLayer(0, "Right", &mousebuttongroup), OPT_XS, OPT_LINE(2), 1, m_defshade, mousebutton_Right, NULL, NULL, MNU_MouseButtonPostProcess},
246 {DefInert(0, MouseButtonFunctions[mousebutton_Right][0]), OPT_XSIDE, OPT_LINE(2), 1, m_defshade, mousebutton_Right, NULL, MNU_SetMouseButtonFunctions, NULL},
247 {DefLayer(0, "Double Right", &mousebuttongroup), OPT_XS, OPT_LINE(3), 1, m_defshade, 128+mousebutton_Right, NULL, NULL, MNU_MouseButtonPostProcess},
248 {DefInert(0, MouseButtonFunctions[mousebutton_Right][1]), OPT_XSIDE, OPT_LINE(3), 1, m_defshade, 128+mousebutton_Right, NULL, MNU_SetMouseButtonFunctions, NULL},
249 {DefLayer(0, "Middle", &mousebuttongroup), OPT_XS, OPT_LINE(4), 1, m_defshade, mousebutton_Middle, NULL, NULL, MNU_MouseButtonPostProcess},
250 {DefInert(0, MouseButtonFunctions[mousebutton_Middle][0]), OPT_XSIDE, OPT_LINE(4), 1, m_defshade, mousebutton_Middle, NULL, MNU_SetMouseButtonFunctions, NULL},
251 {DefLayer(0, "Double Middle", &mousebuttongroup), OPT_XS, OPT_LINE(5), 1, m_defshade, 128+mousebutton_Middle, NULL, NULL, MNU_MouseButtonPostProcess},
252 {DefInert(0, MouseButtonFunctions[mousebutton_Middle][1]), OPT_XSIDE, OPT_LINE(5), 1, m_defshade, 128+mousebutton_Middle, NULL, MNU_SetMouseButtonFunctions, NULL},
253 {DefLayer(0, "Thumb", &mousebuttongroup), OPT_XS, OPT_LINE(6), 1, m_defshade, mousebutton_Thumb, NULL, NULL, MNU_MouseButtonPostProcess},
254 {DefInert(0, MouseButtonFunctions[mousebutton_Thumb][0]), OPT_XSIDE, OPT_LINE(6), 1, m_defshade, mousebutton_Thumb, NULL, MNU_SetMouseButtonFunctions, NULL},
255 {DefLayer(0, "Double Thumb", &mousebuttongroup), OPT_XS, OPT_LINE(7), 1, m_defshade, 128+mousebutton_Thumb, NULL, NULL, MNU_MouseButtonPostProcess},
256 {DefInert(0, MouseButtonFunctions[mousebutton_Thumb][1]), OPT_XSIDE, OPT_LINE(7), 1, m_defshade, 128+mousebutton_Thumb, NULL, MNU_SetMouseButtonFunctions, NULL},
257 {DefLayer(0, "Wheel Up", &mousebuttongroup), OPT_XS, OPT_LINE(8), 1, m_defshade, mousebutton_WheelUp, NULL, NULL, MNU_MouseButtonPostProcess},
258 {DefInert(0, MouseButtonFunctions[mousebutton_WheelUp][0]), OPT_XSIDE, OPT_LINE(8), 1, m_defshade, mousebutton_WheelUp, NULL, MNU_SetMouseButtonFunctions, NULL},
259 {DefLayer(0, "Wheel Down", &mousebuttongroup), OPT_XS, OPT_LINE(9), 1, m_defshade, mousebutton_WheelDown, NULL, NULL, MNU_MouseButtonPostProcess},
260 {DefInert(0, MouseButtonFunctions[mousebutton_WheelDown][0]), OPT_XSIDE, OPT_LINE(9), 1, m_defshade, mousebutton_WheelDown, NULL, MNU_SetMouseButtonFunctions, NULL},
261 {DefNone}
262 };
263 MenuGroup mousesetupgroup = {65, 5, "^Mouse Buttons", mousesetup_i, pic_newgametitl, 0, m_defshade, NULL, NULL, 0};
264
265 #define MAXJOYSTICKBUTTONPAGES 4
266 static char JoystickButtonFunctions[MAXJOYBUTTONS][2][MAXFUNCTIONLENGTH];
267 static int JoystickButtonPage = 0;
268 static BOOL MNU_JoystickButtonsInitialise(MenuItem_p item);
269 static BOOL MNU_SetJoystickButtonFunctions(MenuItem_p item);
270 static BOOL MNU_JoystickButtonPostProcess(MenuItem_p item);
271 static BOOL MNU_JoystickButtonSetupCustom(UserCall call, MenuItem_p item);
272 static BOOL MNU_JoystickButtonNextPage(void);
273 MenuGroup joybuttonsgroup = {0, 0, NULL, NULL, 0, 0, m_defshade, MNU_JoystickButtonSetupCustom, NULL, 0};
274 MenuItem joybuttons_i[MAXJOYSTICKBUTTONPAGES][20] =
275 {
276 {
277 {DefLayer(0, "A", &joybuttonsgroup), OPT_XS, OPT_LINE(0), 1, m_defshade, joybutton_A, NULL, NULL, MNU_JoystickButtonPostProcess},
278 {DefInert(0, JoystickButtonFunctions[joybutton_A][0]), OPT_XSIDE, OPT_LINE(0), 1, m_defshade, joybutton_A, NULL, MNU_SetJoystickButtonFunctions, NULL},
279 {DefLayer(0, "Double A", &joybuttonsgroup), OPT_XS, OPT_LINE(1), 1, m_defshade, 128+joybutton_A, NULL, NULL, MNU_JoystickButtonPostProcess},
280 {DefInert(0, JoystickButtonFunctions[joybutton_A][1]), OPT_XSIDE, OPT_LINE(1), 1, m_defshade, 128+joybutton_A, NULL, MNU_SetJoystickButtonFunctions, NULL},
281 {DefLayer(0, "B", &joybuttonsgroup), OPT_XS, OPT_LINE(2), 1, m_defshade, joybutton_B, NULL, NULL, MNU_JoystickButtonPostProcess},
282 {DefInert(0, JoystickButtonFunctions[joybutton_B][0]), OPT_XSIDE, OPT_LINE(2), 1, m_defshade, joybutton_B, NULL, MNU_SetJoystickButtonFunctions, NULL},
283 {DefLayer(0, "Double B", &joybuttonsgroup), OPT_XS, OPT_LINE(3), 1, m_defshade, 128+joybutton_B, NULL, NULL, MNU_JoystickButtonPostProcess},
284 {DefInert(0, JoystickButtonFunctions[joybutton_B][1]), OPT_XSIDE, OPT_LINE(3), 1, m_defshade, 128+joybutton_B, NULL, MNU_SetJoystickButtonFunctions, NULL},
285 {DefLayer(0, "X", &joybuttonsgroup), OPT_XS, OPT_LINE(4), 1, m_defshade, joybutton_X, NULL, NULL, MNU_JoystickButtonPostProcess},
286 {DefInert(0, JoystickButtonFunctions[joybutton_X][0]), OPT_XSIDE, OPT_LINE(4), 1, m_defshade, joybutton_X, NULL, MNU_SetJoystickButtonFunctions, NULL},
287 {DefLayer(0, "Double X", &joybuttonsgroup), OPT_XS, OPT_LINE(5), 1, m_defshade, 128+joybutton_X, NULL, NULL, MNU_JoystickButtonPostProcess},
288 {DefInert(0, JoystickButtonFunctions[joybutton_X][1]), OPT_XSIDE, OPT_LINE(5), 1, m_defshade, 128+joybutton_X, NULL, MNU_SetJoystickButtonFunctions, NULL},
289 {DefLayer(0, "Y", &joybuttonsgroup), OPT_XS, OPT_LINE(6), 1, m_defshade, joybutton_Y, NULL, NULL, MNU_JoystickButtonPostProcess},
290 {DefInert(0, JoystickButtonFunctions[joybutton_Y][0]), OPT_XSIDE, OPT_LINE(6), 1, m_defshade, joybutton_Y, NULL, MNU_SetJoystickButtonFunctions, NULL},
291 {DefLayer(0, "Double Y", &joybuttonsgroup), OPT_XS, OPT_LINE(7), 1, m_defshade, 128+joybutton_Y, NULL, NULL, MNU_JoystickButtonPostProcess},
292 {DefInert(0, JoystickButtonFunctions[joybutton_Y][1]), OPT_XSIDE, OPT_LINE(7), 1, m_defshade, 128+joybutton_Y, NULL, MNU_SetJoystickButtonFunctions, NULL},
293
294 {DefInert(0, "Page 1 / 4"), OPT_XS, OPT_LINE(10), 1, m_defshade, 0, NULL, NULL, NULL },
295 {DefOption(0, "Next..."), OPT_XSIDE, OPT_LINE(10), 1, m_defshade, 0, MNU_JoystickButtonNextPage, NULL, NULL },
296 {DefNone}
297 },
298
299 {
300 {DefLayer(0, "Left stick", &joybuttonsgroup), OPT_XS, OPT_LINE(0), 1, m_defshade, joybutton_LeftStick, NULL, NULL, MNU_JoystickButtonPostProcess},
301 {DefInert(0, JoystickButtonFunctions[joybutton_LeftStick][0]), OPT_XSIDE, OPT_LINE(0), 1, m_defshade, joybutton_LeftStick, NULL, MNU_SetJoystickButtonFunctions, NULL},
302 {DefLayer(0, "Dbl Left stick", &joybuttonsgroup), OPT_XS, OPT_LINE(1), 1, m_defshade, 128+joybutton_LeftStick, NULL, NULL, MNU_JoystickButtonPostProcess},
303 {DefInert(0, JoystickButtonFunctions[joybutton_LeftStick][1]), OPT_XSIDE, OPT_LINE(1), 1, m_defshade, 128+joybutton_LeftStick, NULL, MNU_SetJoystickButtonFunctions, NULL},
304 {DefLayer(0, "Right stick", &joybuttonsgroup), OPT_XS, OPT_LINE(2), 1, m_defshade, joybutton_RightStick, NULL, NULL, MNU_JoystickButtonPostProcess},
305 {DefInert(0, JoystickButtonFunctions[joybutton_RightStick][0]), OPT_XSIDE, OPT_LINE(2), 1, m_defshade, joybutton_RightStick, NULL, MNU_SetJoystickButtonFunctions, NULL},
306 {DefLayer(0, "Dbl Right stick", &joybuttonsgroup), OPT_XS, OPT_LINE(3), 1, m_defshade, 128+joybutton_RightStick, NULL, NULL, MNU_JoystickButtonPostProcess},
307 {DefInert(0, JoystickButtonFunctions[joybutton_RightStick][1]), OPT_XSIDE, OPT_LINE(3), 1, m_defshade, 128+joybutton_RightStick, NULL, MNU_SetJoystickButtonFunctions, NULL},
308 {DefLayer(0, "Left shoulder", &joybuttonsgroup), OPT_XS, OPT_LINE(4), 1, m_defshade, joybutton_LeftShoulder, NULL, NULL, MNU_JoystickButtonPostProcess},
309 {DefInert(0, JoystickButtonFunctions[joybutton_LeftShoulder][0]), OPT_XSIDE, OPT_LINE(4), 1, m_defshade, joybutton_LeftShoulder, NULL, MNU_SetJoystickButtonFunctions, NULL},
310 {DefLayer(0, "Dbl Lt shoulder", &joybuttonsgroup), OPT_XS, OPT_LINE(5), 1, m_defshade, 128+joybutton_LeftShoulder, NULL, NULL, MNU_JoystickButtonPostProcess},
311 {DefInert(0, JoystickButtonFunctions[joybutton_LeftShoulder][1]), OPT_XSIDE, OPT_LINE(5), 1, m_defshade, 128+joybutton_LeftShoulder, NULL, MNU_SetJoystickButtonFunctions, NULL},
312 {DefLayer(0, "Right shoulder", &joybuttonsgroup), OPT_XS, OPT_LINE(6), 1, m_defshade, joybutton_RightShoulder, NULL, NULL, MNU_JoystickButtonPostProcess},
313 {DefInert(0, JoystickButtonFunctions[joybutton_RightShoulder][0]), OPT_XSIDE, OPT_LINE(6), 1, m_defshade, joybutton_RightShoulder, NULL, MNU_SetJoystickButtonFunctions, NULL},
314 {DefLayer(0, "Dbl Rt shoulder", &joybuttonsgroup), OPT_XS, OPT_LINE(7), 1, m_defshade, 128+joybutton_RightShoulder, NULL, NULL, MNU_JoystickButtonPostProcess},
315 {DefInert(0, JoystickButtonFunctions[joybutton_RightShoulder][1]), OPT_XSIDE, OPT_LINE(7), 1, m_defshade, 128+joybutton_RightShoulder, NULL, MNU_SetJoystickButtonFunctions, NULL},
316
317 {DefInert(0, "Page 2 / 4"), OPT_XS, OPT_LINE(10), 1, m_defshade, 0, NULL, NULL, NULL },
318 {DefOption(0, "Next..."), OPT_XSIDE, OPT_LINE(10), 1, m_defshade, 0, MNU_JoystickButtonNextPage, NULL, NULL },
319 {DefNone}
320 },
321
322 {
323 {DefLayer(0, "Dpad up", &joybuttonsgroup), OPT_XS, OPT_LINE(0), 1, m_defshade, joybutton_DpadUp, NULL, NULL, MNU_JoystickButtonPostProcess},
324 {DefInert(0, JoystickButtonFunctions[joybutton_DpadUp][0]), OPT_XSIDE, OPT_LINE(0), 1, m_defshade, joybutton_DpadUp, NULL, MNU_SetJoystickButtonFunctions, NULL},
325 {DefLayer(0, "Dbl Dpad up", &joybuttonsgroup), OPT_XS, OPT_LINE(1), 1, m_defshade, 128+joybutton_DpadUp, NULL, NULL, MNU_JoystickButtonPostProcess},
326 {DefInert(0, JoystickButtonFunctions[joybutton_DpadUp][1]), OPT_XSIDE, OPT_LINE(1), 1, m_defshade, 128+joybutton_DpadUp, NULL, MNU_SetJoystickButtonFunctions, NULL},
327 {DefLayer(0, "Dpad down", &joybuttonsgroup), OPT_XS, OPT_LINE(2), 1, m_defshade, joybutton_DpadDown, NULL, NULL, MNU_JoystickButtonPostProcess},
328 {DefInert(0, JoystickButtonFunctions[joybutton_DpadDown][0]), OPT_XSIDE, OPT_LINE(2), 1, m_defshade, joybutton_DpadDown, NULL, MNU_SetJoystickButtonFunctions, NULL},
329 {DefLayer(0, "Dbl Dpad down", &joybuttonsgroup), OPT_XS, OPT_LINE(3), 1, m_defshade, 128+joybutton_DpadDown, NULL, NULL, MNU_JoystickButtonPostProcess},
330 {DefInert(0, JoystickButtonFunctions[joybutton_DpadDown][1]), OPT_XSIDE, OPT_LINE(3), 1, m_defshade, 128+joybutton_DpadDown, NULL, MNU_SetJoystickButtonFunctions, NULL},
331 {DefLayer(0, "Dpad left", &joybuttonsgroup), OPT_XS, OPT_LINE(4), 1, m_defshade, joybutton_DpadLeft, NULL, NULL, MNU_JoystickButtonPostProcess},
332 {DefInert(0, JoystickButtonFunctions[joybutton_DpadLeft][0]), OPT_XSIDE, OPT_LINE(4), 1, m_defshade, joybutton_DpadLeft, NULL, MNU_SetJoystickButtonFunctions, NULL},
333 {DefLayer(0, "Dbl Dpad left", &joybuttonsgroup), OPT_XS, OPT_LINE(5), 1, m_defshade, 128+joybutton_DpadLeft, NULL, NULL, MNU_JoystickButtonPostProcess},
334 {DefInert(0, JoystickButtonFunctions[joybutton_DpadLeft][1]), OPT_XSIDE, OPT_LINE(5), 1, m_defshade, 128+joybutton_DpadLeft, NULL, MNU_SetJoystickButtonFunctions, NULL},
335 {DefLayer(0, "Dpad right", &joybuttonsgroup), OPT_XS, OPT_LINE(6), 1, m_defshade, joybutton_DpadRight, NULL, NULL, MNU_JoystickButtonPostProcess},
336 {DefInert(0, JoystickButtonFunctions[joybutton_DpadRight][0]), OPT_XSIDE, OPT_LINE(6), 1, m_defshade, joybutton_DpadRight, NULL, MNU_SetJoystickButtonFunctions, NULL},
337 {DefLayer(0, "Dbl Dpad right", &joybuttonsgroup), OPT_XS, OPT_LINE(7), 1, m_defshade, 128+joybutton_DpadRight, NULL, NULL, MNU_JoystickButtonPostProcess},
338 {DefInert(0, JoystickButtonFunctions[joybutton_DpadRight][1]), OPT_XSIDE, OPT_LINE(7), 1, m_defshade, 128+joybutton_DpadRight, NULL, MNU_SetJoystickButtonFunctions, NULL},
339
340 {DefInert(0, "Page 3 / 4"), OPT_XS, OPT_LINE(10), 1, m_defshade, 0, NULL, NULL, NULL },
341 {DefOption(0, "Next..."), OPT_XSIDE, OPT_LINE(10), 1, m_defshade, 0, MNU_JoystickButtonNextPage, NULL, NULL },
342 {DefNone}
343 },
344
345 {
346 {DefLayer(0, "Back", &joybuttonsgroup), OPT_XS, OPT_LINE(0), 1, m_defshade, joybutton_Back, NULL, NULL, MNU_JoystickButtonPostProcess},
347 {DefInert(0, JoystickButtonFunctions[joybutton_Back][0]), OPT_XSIDE, OPT_LINE(0), 1, m_defshade, joybutton_Back, NULL, MNU_SetJoystickButtonFunctions, NULL},
348 {DefLayer(0, "Dbl Back", &joybuttonsgroup), OPT_XS, OPT_LINE(1), 1, m_defshade, 128+joybutton_Back, NULL, NULL, MNU_JoystickButtonPostProcess},
349 {DefInert(0, JoystickButtonFunctions[joybutton_Back][1]), OPT_XSIDE, OPT_LINE(1), 1, m_defshade, 128+joybutton_Back, NULL, MNU_SetJoystickButtonFunctions, NULL},
350 {DefLayer(0, "Guide", &joybuttonsgroup), OPT_XS, OPT_LINE(2), 1, m_defshade, joybutton_Guide, NULL, NULL, MNU_JoystickButtonPostProcess},
351 {DefInert(0, JoystickButtonFunctions[joybutton_Guide][0]), OPT_XSIDE, OPT_LINE(2), 1, m_defshade, joybutton_Guide, NULL, MNU_SetJoystickButtonFunctions, NULL},
352 {DefLayer(0, "Dbl Guide", &joybuttonsgroup), OPT_XS, OPT_LINE(3), 1, m_defshade, 128+joybutton_Guide, NULL, NULL, MNU_JoystickButtonPostProcess},
353 {DefInert(0, JoystickButtonFunctions[joybutton_Guide][1]), OPT_XSIDE, OPT_LINE(3), 1, m_defshade, 128+joybutton_Guide, NULL, MNU_SetJoystickButtonFunctions, NULL},
354 {DefLayer(0, "Start", &joybuttonsgroup), OPT_XS, OPT_LINE(4), 1, m_defshade, joybutton_Start, NULL, NULL, MNU_JoystickButtonPostProcess},
355 {DefInert(0, JoystickButtonFunctions[joybutton_Start][0]), OPT_XSIDE, OPT_LINE(4), 1, m_defshade, joybutton_Start, NULL, MNU_SetJoystickButtonFunctions, NULL},
356 {DefLayer(0, "Dbl Start", &joybuttonsgroup), OPT_XS, OPT_LINE(5), 1, m_defshade, 128+joybutton_Start, NULL, NULL, MNU_JoystickButtonPostProcess},
357 {DefInert(0, JoystickButtonFunctions[joybutton_Start][1]), OPT_XSIDE, OPT_LINE(5), 1, m_defshade, 128+joybutton_Start, NULL, MNU_SetJoystickButtonFunctions, NULL},
358
359 {DefInert(0, "Page 4 / 4"), OPT_XS, OPT_LINE(10), 1, m_defshade, 0, NULL, NULL, NULL },
360 {DefOption(0, "Next..."), OPT_XSIDE, OPT_LINE(10), 1, m_defshade, 0, MNU_JoystickButtonNextPage, NULL, NULL },
361 {DefNone}
362 },
363 };
364 MenuGroup joybuttonssetupgroup = {65, 5, "^Joystick Setup", joybuttons_i[0], pic_newgametitl, 0, m_defshade, NULL, NULL, 0};
365
366 static char JoystickAxisName[64];
367 static char JoystickAxisPageName[64];
368 static char JoystickAxisFunctions[2][MAXFUNCTIONLENGTH];
369 static int JoystickAxisPage = 0;
370 static BOOL MNU_JoystickAxesInitialise(MenuItem_p item);
371 static BOOL MNU_SetJoystickAxisFunctions(MenuItem_p item);
372 static BOOL MNU_JoystickAxisPostProcess(MenuItem_p item);
373 static BOOL MNU_JoystickAxisSetupCustom(UserCall call, MenuItem_p item);
374 static BOOL MNU_JoystickAxisNextPage(void);
375 MenuGroup joyaxesgroup = {0, 0, NULL, NULL, 0, 0, m_defshade, MNU_JoystickAxisSetupCustom, NULL, 0};
376 MenuItem joyaxes_i[] =
377 {
378 {DefInert(0, JoystickAxisName), OPT_XS, OPT_LINE(0), 1, MENU_SHADE_INACTIVE, 0, NULL, NULL, NULL},
379
380 {DefSlider(sldr_joyaxisscale, 0, "Axis Scale"), OPT_XS, OPT_LINE(2), 1, m_defshade, 0, NULL, NULL, NULL},
381 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(2), 0, m_defshade, 0, NULL, NULL, NULL},
382 {DefButton(btn_joyaxis_invert, 0, "Invert"), OPT_XS, OPT_LINE(3), 1, m_defshade, 0, NULL, NULL, NULL},
383 {DefSlider(sldr_joyaxisanalog, 0, "Analog"), OPT_XS, OPT_LINE(4), 1, m_defshade, 0, NULL, NULL, NULL},
384 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(4), 0, m_defshade, 0, NULL, NULL, NULL},
385 {DefLayer(0, "Digital +ve", &joyaxesgroup), OPT_XS, OPT_LINE(5), 1, m_defshade, 1, NULL, NULL, MNU_JoystickAxisPostProcess},
386 {DefInert(0, JoystickAxisFunctions[1]), OPT_XSIDE, OPT_LINE(5), 1, m_defshade, 1, NULL, MNU_SetJoystickAxisFunctions, NULL},
387 {DefLayer(0, "Digital -ve", &joyaxesgroup), OPT_XS, OPT_LINE(6), 1, m_defshade, 0, NULL, NULL, MNU_JoystickAxisPostProcess},
388 {DefInert(0, JoystickAxisFunctions[0]), OPT_XSIDE, OPT_LINE(6), 1, m_defshade, 0, NULL, MNU_SetJoystickAxisFunctions, NULL},
389
390 {DefSlider(sldr_joyaxisdead, 0, "Dead Zone"), OPT_XS, OPT_LINE(8), 1, m_defshade, 0, NULL, NULL, NULL},
391 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(8), 0, m_defshade, 0, NULL, NULL, NULL},
392 {DefSlider(sldr_joyaxissatur, 0, "Saturate"), OPT_XS, OPT_LINE(9), 1, m_defshade, 0, NULL, NULL, NULL},
393 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(9), 0, m_defshade, 0, NULL, NULL, NULL},
394
395 {DefInert(0, JoystickAxisPageName), OPT_XS, OPT_LINE(11), 1, m_defshade, 0, NULL, NULL, NULL},
396 {DefOption(0, "Next..."), OPT_XSIDE, OPT_LINE(11), 1, m_defshade, 0, MNU_JoystickAxisNextPage, NULL, NULL},
397
398 {DefNone},
399 };
400 MenuGroup joyaxessetupgroup = {65, 5, "^Joystick Axes", joyaxes_i, pic_newgametitl, 0, m_defshade, NULL, NULL, 1};
401
402
403 static char MouseAxisFunctions[MAXMOUSEAXES][2][MAXAXISFUNCTIONLENGTH] = { {"", ""}, {"", ""} };
404 static BOOL MNU_SetMouseAxisFunctions(MenuItem_p item);
405 static BOOL MNU_MouseDigitalPostProcess(MenuItem_p item);
406 static BOOL MNU_MouseDigitalSetupCustom(UserCall call, MenuItem_p item);
407 MenuGroup mouseaxesdigigroup = {0, 0, NULL, NULL, 0, 0, m_defshade, MNU_MouseDigitalSetupCustom, NULL, 0};
408 MenuItem mouseaxes_i[] =
409 {
410 {DefSlider(sldr_mousescalex, 0, "X-Axis Scale"), OPT_XS, OPT_LINE(0), 1, m_defshade, 0, NULL, NULL, NULL},
411 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(0), 0, m_defshade, 0, NULL, NULL, NULL},
412 {DefSlider(sldr_mousescaley, 0, "Y-Axis Scale"), OPT_XS, OPT_LINE(1), 1, m_defshade, 0, NULL, NULL, NULL},
413 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(1), 0, m_defshade, 0, NULL, NULL, NULL},
414 {DefLayer(0, "Digital Left", &mouseaxesdigigroup), OPT_XS, OPT_LINE(3), 1, m_defshade, 0+0, NULL, NULL, MNU_MouseDigitalPostProcess},
415 {DefInert(0, MouseAxisFunctions[0][0]), OPT_XSIDE, OPT_LINE(3), 1, m_defshade, 0+0, NULL, MNU_SetMouseAxisFunctions, NULL},
416 {DefLayer(0, "Digital Right", &mouseaxesdigigroup), OPT_XS, OPT_LINE(4), 1, m_defshade, 0+1, NULL, NULL, MNU_MouseDigitalPostProcess},
417 {DefInert(0, MouseAxisFunctions[0][1]), OPT_XSIDE, OPT_LINE(4), 1, m_defshade, 0+1, NULL, MNU_SetMouseAxisFunctions, NULL},
418 {DefLayer(0, "Digital Up", &mouseaxesdigigroup), OPT_XS, OPT_LINE(5), 1, m_defshade, 2+0, NULL, NULL, MNU_MouseDigitalPostProcess},
419 {DefInert(0, MouseAxisFunctions[1][0]), OPT_XSIDE, OPT_LINE(5), 1, m_defshade, 2+0, NULL, MNU_SetMouseAxisFunctions, NULL},
420 {DefLayer(0, "Digital Down", &mouseaxesdigigroup), OPT_XS, OPT_LINE(6), 1, m_defshade, 2+1, NULL, NULL, MNU_MouseDigitalPostProcess},
421 {DefInert(0, MouseAxisFunctions[1][1]), OPT_XSIDE, OPT_LINE(6), 1, m_defshade, 2+1, NULL, MNU_SetMouseAxisFunctions, NULL},
422 {DefNone}
423 };
424 MenuGroup mouseaxesgroup = {65, 5, "^Mouse Axes", mouseaxes_i, pic_newgametitl, 0, m_defshade, NULL, NULL, 0};
425
426 MenuItem inputsetup_i[] =
427 {
428 {DefLayer(0, "Keys Setup", &keysetupgroup),OPT_XS, OPT_LINE(0),1,m_defshade,0,NULL,NULL,NULL},
429 {DefLayer(0, "Mouse Options", &mousegroup),OPT_XS, OPT_LINE(2), 1, m_defshade,0,NULL, MNU_MouseCheck, NULL},
430 {DefLayer(0, "Mouse Buttons Setup", &mousesetupgroup),OPT_XS, OPT_LINE(3),1,m_defshade,0,NULL,NULL,NULL},
431 {DefLayer(0, "Mouse Axes Setup", &mouseaxesgroup),OPT_XS, OPT_LINE(4),1,m_defshade,0,NULL,NULL,NULL},
432 {DefLayer(0, "Joystick Buttons Setup", &joybuttonssetupgroup),OPT_XS,OPT_LINE(6),1,m_defshade,0,NULL,MNU_JoystickCheck,MNU_JoystickButtonsInitialise},
433 {DefLayer(0, "Joystick Axes Setup", &joyaxessetupgroup), OPT_XS, OPT_LINE(7),1,m_defshade,0,NULL,MNU_JoystickCheck,MNU_JoystickAxesInitialise},
434 {DefOption(0, "Apply Modern Defaults"), OPT_XS, OPT_LINE(9),1,m_defshade,0,MNU_LoadModernDefaults,NULL,NULL},
435 {DefOption(0, "Apply Classic Defaults"), OPT_XS, OPT_LINE(10),1,m_defshade,0,MNU_LoadClassicDefaults,NULL,NULL},
436 {DefNone}
437 };
438 MenuGroup inputsetupgroup = {65, 5, "^Input", inputsetup_i, pic_newgametitl, 0, m_defshade, NULL,NULL, 0};
439
440 MenuItem player_i[] =
441 {
442 {DefOption(0, "Player Name"), OPT_XS, OPT_LINE(0), 1, m_defshade, 0, MNU_PlayerNameCustom, NULL, NULL},
443 {DefInert(0, CommPlayerName), OPT_XSIDE, OPT_LINE(0), 1, m_defshade, 0, NULL, NULL, NULL},
444 {DefSlider(sldr_playercolor, 0, "Player Color"), OPT_XS, OPT_LINE(1), 1, m_defshade, 0, NULL, NULL, NULL},
445 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(1), 0, m_defshade, 0, NULL, NULL, NULL},
446 {DefNone}
447 };
448 MenuGroup playergroup = {50, 5, "^Player", player_i, pic_optionstitl, 0, m_defshade, MNU_DoPlayerName, NULL, 0};
449
450 MenuItem options_i[] =
451 {
452 {DefLayer(0, "Screen Menu", &screengroup),OPT_XS, OPT_LINE(0), 1, m_defshade,0,NULL, NULL, NULL},
453 {DefLayer(0, "Sound Menu", &soundgroup),OPT_XS, OPT_LINE(1), 1, m_defshade,0,MNU_TryMusicInit, MNU_MusicFxCheck, NULL},
454 {DefLayer(0, "Input Menu", &inputsetupgroup),OPT_XS, OPT_LINE(2), 1,m_defshade,0,NULL,NULL,NULL},
455 {DefLayer(0, "Player Menu", &playergroup),OPT_XS, OPT_LINE(3), 1, m_defshade,0,NULL,NULL,NULL},
456 #ifndef PLOCK_VERSION // No need for this in weener version
457 {DefLayer(0, "Kid Mode", &parentalgroup),OPT_XS, OPT_LINE(4), 1, m_defshade,0,NULL, NULL, NULL},
458 #endif
459 {DefButton(btn_messages, 0, "Messages"), OPT_XS, OPT_LINE(5), 1, m_defshade, 0, NULL, NULL, NULL},
460 // {DefButton(btn_bobbing, 0, "View Bobbing"), OPT_XS, OPT_LINE(7), 1, m_defshade, 0, NULL, NULL, NULL},
461 {DefButton(btn_shadows, 0, "Shadows"), OPT_XS, OPT_LINE(6), 1, m_defshade, 0, NULL, NULL, NULL},
462 {DefButton(btn_auto_run, 0, "Auto Run"), OPT_XS, OPT_LINE(7), 1, m_defshade, 0, NULL, NULL, NULL},
463 {DefButton(btn_crosshair, 0, "Crosshair"), OPT_XS, OPT_LINE(8), 1, m_defshade, 0, NULL, NULL, NULL},
464 {DefButton(btn_auto_aim, 0, "Auto-Aiming"), OPT_XS, OPT_LINE(9), 1, m_defshade, 0, NULL, NULL, NULL},
465 {DefButton(btn_voxels, 0, "Voxel Sprites"), OPT_XS, OPT_LINE(10), 1, m_defshade, 0, NULL, NULL, NULL},
466 {DefButton(btn_stats, 0, "Level Stats"), OPT_XS, OPT_LINE(11), 1, m_defshade, 0, NULL, MNU_StatCheck, NULL},
467 {DefNone}
468 };
469
470 MenuGroup optiongroup = {100, 5, "^Options", options_i, pic_optionstitl, 0, m_defshade, NULL,NULL, 0};
471
472 MenuItem skill_i[] =
473 {
474 {DefOption(KEYSC_E, &SkillNames[0][0]), 30, 46, pic_easy, m_defshade, 0, MNU_StartGame, NULL, NULL},
475 {DefOption(KEYSC_N, &SkillNames[1][0]), 30, 62, pic_normal, m_defshade, 0, MNU_StartGame, NULL, NULL},
476 {DefOption(KEYSC_H, &SkillNames[2][0]), 30, 78, pic_hard, m_defshade, 0, MNU_StartGame, NULL, NULL},
477 {DefOption(KEYSC_I, &SkillNames[3][0]), 30, 94, pic_impossible, m_defshade, 0, MNU_StartGame, NULL, NULL},
478 {DefNone}
479 };
480
481 MenuGroup skillgroup = {100, 5, "^Skill", skill_i, pic_newgametitl, 0, m_defshade, NULL, NULL, 2};
482
483 MenuItem episode_i[] =
484 {
485 {DefLayer(KEYSC_S, &EpisodeNames[0][0], &skillgroup), 30, 46, pic_episode1, m_defshade, 0, MNU_EpisodeCustom, NULL, NULL},
486 {DefLayer(KEYSC_F, &EpisodeNames[1][0], &skillgroup), 30, 78, pic_episode2, m_defshade, 0, MNU_EpisodeCustom, MNU_ShareWareCheck, MNU_ShareWareMessage},
487 //{DefLayer(KEYSC_S, NULL, &skillgroup), 60, 30, pic_episode1, m_defshade, 0, MNU_EpisodeCustom},
488 //{DefLayer(KEYSC_F, NULL, &skillgroup), 60, 46, pic_episode2, m_defshade, 0, MNU_EpisodeCustom},
489 //{DefLayer(KEYSC_T, NULL, &skillgroup), 60, 62, pic_episode3, m_defshade, 0, MNU_EpisodeCustom},
490 {DefNone}
491 };
492
493 MenuGroup episodegroup = {100, 5, "^Episode", episode_i, pic_newgametitl, 0, m_defshade, MNU_DoEpisodeSelect, NULL, 0};
494
495 extern char UserMapName[80];
496
497 MenuItem network_extra_i[] =
498 {
499 {DefSlider(sldr_monsters, 0, "Monsters"),OPT_XS, OPT_LINE(0), 1, m_defshade, 0, NULL, NULL, NULL},
500 {DefInert(0, NULL), OPT_XSIDE,OPT_LINE(0), 0, m_defshade, 0, NULL, NULL, NULL},
501
502 {DefButton(btn_teamplay, 0, "Team Play"), OPT_XS, OPT_LINE(1), 1, m_defshade, 0, MNU_TeamPlayChange, MNU_TeamPlayCheck, NULL},
503 {DefButton(btn_friendlyfire, 0, "Hurt Teammate"),OPT_XS, OPT_LINE(2), 1, m_defshade, 0, NULL, MNU_HurtTeammateCheck, NULL},
504 {DefButton(btn_nuke, 0, "Play with Nuke"),OPT_XS, OPT_LINE(3), 1, m_defshade, 0, NULL, NULL, NULL},
505 {DefNone}
506 };
507
508 MenuGroup networkextragroup = {50, 5, "^Net Options", network_extra_i, pic_newgametitl, 0, m_defshade, NULL, NULL, 0};
509
510 MenuItem network_i[] =
511 {
512 {DefSlider(sldr_gametype, 0, "Game Type"), OPT_XS, OPT_LINE(0), 1, m_defshade, 0, NULL, NULL, NULL},
513 {DefInert(0, NULL), OPT_XSIDE-38, OPT_LINE(0), 0, m_defshade, 0, NULL, NULL, NULL},
514
515 {DefSlider(sldr_netlevel, 0, "Level"), OPT_XS, OPT_LINE(1), 1, m_defshade, 0, NULL, MNU_CheckUserMap, NULL},
516 {DefInert(0, NULL), OPT_XSIDE-70, OPT_LINE(1), 0, m_defshade, 0, NULL, MNU_CheckUserMap, NULL},
517 {DefInert(0, " "), OPT_XS, OPT_LINE(2), pic_episode1, m_defshade, 0, NULL, MNU_CheckUserMap, NULL},
518
519 {DefButton(btn_markers, 0, "Markers"), OPT_XS, OPT_LINE(3), 1, m_defshade, 0, NULL, NULL, NULL},
520
521 {DefSlider(sldr_killlimit, 0, "Kill Limit"),OPT_XS, OPT_LINE(4), 1, m_defshade, 0, NULL, MNU_CoopPlayCheck, NULL},
522 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(4), 0, m_defshade, 0, NULL, MNU_CoopPlayCheck, NULL},
523
524 {DefSlider(sldr_timelimit, 0, "Time Limit"),OPT_XS, OPT_LINE(5), 1, m_defshade, 0, NULL, MNU_CoopPlayCheck, NULL},
525 {DefInert(0, NULL), OPT_XSIDE, OPT_LINE(5), 0, m_defshade, 0, NULL, MNU_CoopPlayCheck, NULL},
526
527 {DefLayer(0, "Other Options", &networkextragroup),OPT_XS, OPT_LINE(7), 1, m_defshade,0,NULL, NULL, NULL},
528
529 {DefInert(0, UserMapName), OPT_XSIDE, OPT_LINE(8), pic_episode1, m_defshade, 0, NULL, NULL, NULL},
530 {DefOption(KEYSC_S, "Start Game"), OPT_XS, OPT_LINE(8), pic_episode1, m_defshade, 0, MNU_StartNetGame, NULL, NULL},
531
532 {DefNone}
533
534 };
535
536 MenuGroup networkgroup = {50, 5, "^Network Game", network_i, pic_newgametitl, 0, m_defshade, NULL, NULL, 0};
537
538 MenuItem load_i[] =
539 {
540 #define SD_YSTART 26
541 #define SD_XSTART 5
542 #define SD_YOFF 13
543 #define SD_LINE(line) (SD_YSTART + (line * SD_YOFF))
544 {DefOption(0, NULL), SD_XSTART, SD_LINE(0), 0, m_defshade, 0, MNU_GetLoadCustom, NULL, NULL},
545 {DefOption(0, NULL), SD_XSTART, SD_LINE(1), 0, m_defshade, 0, MNU_GetLoadCustom, NULL, NULL},
546 {DefOption(0, NULL), SD_XSTART, SD_LINE(2), 0, m_defshade, 0, MNU_GetLoadCustom, NULL, NULL},
547 {DefOption(0, NULL), SD_XSTART, SD_LINE(3), 0, m_defshade, 0, MNU_GetLoadCustom, NULL, NULL},
548 {DefOption(0, NULL), SD_XSTART, SD_LINE(4), 0, m_defshade, 0, MNU_GetLoadCustom, NULL, NULL},
549 {DefOption(0, NULL), SD_XSTART, SD_LINE(5), 0, m_defshade, 0, MNU_GetLoadCustom, NULL, NULL},
550 {DefOption(0, NULL), SD_XSTART, SD_LINE(6), 0, m_defshade, 0, MNU_GetLoadCustom, NULL, NULL},
551 {DefOption(0, NULL), SD_XSTART, SD_LINE(7), 0, m_defshade, 0, MNU_GetLoadCustom, NULL, NULL},
552 {DefOption(0, NULL), SD_XSTART, SD_LINE(8), 0, m_defshade, 0, MNU_GetLoadCustom, NULL, NULL},
553 {DefOption(0, NULL), SD_XSTART, SD_LINE(9), 0, m_defshade, 0, MNU_GetLoadCustom, NULL, NULL},
554 {DefNone}
555 };
556
557 MenuItem save_i[] =
558 {
559 {DefOption(0, NULL), SD_XSTART, SD_LINE(0), 0, m_defshade, 0, MNU_GetSaveCustom, NULL, NULL},
560 {DefOption(0, NULL), SD_XSTART, SD_LINE(1), 0, m_defshade, 0, MNU_GetSaveCustom, NULL, NULL},
561 {DefOption(0, NULL), SD_XSTART, SD_LINE(2), 0, m_defshade, 0, MNU_GetSaveCustom, NULL, NULL},
562 {DefOption(0, NULL), SD_XSTART, SD_LINE(3), 0, m_defshade, 0, MNU_GetSaveCustom, NULL, NULL},
563 {DefOption(0, NULL), SD_XSTART, SD_LINE(4), 0, m_defshade, 0, MNU_GetSaveCustom, NULL, NULL},
564 {DefOption(0, NULL), SD_XSTART, SD_LINE(5), 0, m_defshade, 0, MNU_GetSaveCustom, NULL, NULL},
565 {DefOption(0, NULL), SD_XSTART, SD_LINE(6), 0, m_defshade, 0, MNU_GetSaveCustom, NULL, NULL},
566 {DefOption(0, NULL), SD_XSTART, SD_LINE(7), 0, m_defshade, 0, MNU_GetSaveCustom, NULL, NULL},
567 {DefOption(0, NULL), SD_XSTART, SD_LINE(8), 0, m_defshade, 0, MNU_GetSaveCustom, NULL, NULL},
568 {DefOption(0, NULL), SD_XSTART, SD_LINE(9), 0, m_defshade, 0, MNU_GetSaveCustom, NULL, NULL},
569 {DefNone}
570 };
571
572 // No actual submenus for this, just quit text.
573 MenuGroup quitgroup = {0, 0, NULL, NULL, 0, 0, m_defshade, MNU_QuitCustom, NULL, 0};
574 MenuGroup quickloadgroup = {0, 0, NULL, NULL, 0, 0, m_defshade, MNU_QuickLoadCustom, NULL, 0};
575 MenuGroup ordergroup = {0, 0, NULL, NULL, 0, 0, m_defshade, MNU_OrderCustom, NULL, 0};
576
577 // save and load function calls
578 MenuGroup SaveGameGroup = {100, 5, "^Save Game", save_i, pic_savegame, 0, m_defshade, MNU_LoadSaveDraw, MNU_LoadSaveMove, 0};
579 MenuGroup LoadGameGroup = {100, 5, "^Load Game", load_i, pic_loadgame, 0, m_defshade, MNU_LoadSaveDraw, MNU_LoadSaveMove, 0};
580
581 #define MAIN_YSTART 32
582 #define MAIN_YOFF 17
583 #define MAIN_XSTART 55
584 #define MAIN_LINE(line) (MAIN_YSTART + (MAIN_YOFF * line))
585
586 #define MAIN_MENU_COOL_STUFF "^Cool Stuff"
587 #define MAIN_MENU_HOW_TO_ORDER "^How to Order"
588
589 MenuItem main_i[] =
590 {
591 {DefLayer(KEYSC_N, "^New Game", &episodegroup), MAIN_XSTART, MAIN_LINE(0), pic_newgame, m_defshade, 0, NULL, NULL, NULL},
592 {DefLayer(KEYSC_L, "^Load Game", &LoadGameGroup), MAIN_XSTART, MAIN_LINE(1), pic_load, m_defshade, 0, NULL, MNU_LoadGameCheck, NULL},
593 {DefLayer(KEYSC_S, "^Save Game", &SaveGameGroup), MAIN_XSTART, MAIN_LINE(2), pic_save, m_defshade, 0, NULL, MNU_SaveGameCheck, NULL},
594 {DefLayer(KEYSC_O, "^Options", &optiongroup), MAIN_XSTART, MAIN_LINE(3), pic_options, m_defshade, 0, NULL, NULL, NULL},
595 {DefLayer(KEYSC_H, "^Oh Dear", &ordergroup), MAIN_XSTART, MAIN_LINE(4), pic_orderinfo, m_defshade, 0, NULL, NULL, NULL},
596 {DefLayer(KEYSC_Q, "^Quit", &quitgroup), MAIN_XSTART, MAIN_LINE(5), pic_quit, m_defshade, 0, NULL, NULL, NULL},
597 {DefNone}
598 };
599
600 MenuGroup maingroup = {160, 15, NULL, main_i, pic_shadow_warrior, 0, m_defshade, NULL, NULL, 0};
601
602 CTLType ControlPanelType;
603
604 #define MaxLayers 10 // Maximum layers deep a menu can go
605 short menuarrayptr; // Index into menuarray
606 MenuGroup *menuarray[MaxLayers], *currentmenu;
607 BOOL UsingMenus = FALSE;
608 BOOL ForceMenus = FALSE;
609
610 #define MAXDIALOG 2 // Maximum number of dialog strings allowed
611 char *dialog[MAXDIALOG];
612
613 // Global menu setting values ////////////////////////////////////////////////////////////////////
614 // Mouse slider vars
615 #define SENSE_MIN 75
616 #define SENSE_MUL 10
617 int SENSITIVITY = SENSE_MIN + (SENSE_DEFAULT * SENSE_MUL);
618
619 // Sound vars
620 #define FX_MIN 0
621 #define MUSIC_MIN 0
622 #define VOL_MUL 16
623
624 // User input data for all devices
625 UserInput mnu_input, mnu_input_buffered, order_input_buffered;
626
627 // Menu function call back pointer for multiplay menus
628 BOOL(*cust_callback) (UserCall call, MenuItem_p item);
629 UserCall cust_callback_call;
630 MenuItem_p cust_callback_item;
631
632 // Prototypes ///////////////////////////////////////////////////////////////////////////////////
633
634 typedef enum {
635 dialog_NoAnswer = 0,
636 dialog_Yes = 1,
637 dialog_No = 2
638 } DialogResponse;
639
640 static DialogResponse MNU_Dialog(void);
641 VOID LoadSaveMsg(char *msg);
642 static VOID MNU_ItemPreProcess(MenuGroup *group);
643 static void MNU_SelectItem(MenuGroup * group, short index, BOOL draw);
644 static void MNU_PushItem(MenuItem * item, BOOL draw);
645
646 static int MNU_ControlAxisOffset(int num);
647 static int MNU_ControlAxisNum(int offset);
648
649
650 // F U N C T I O N S ////////////////////////////////////////////////////////////////////////////
651
652 // CUSTOM ROUTINES ////////////////////////////////////////////////////////////////////////////////
653
654 BOOL
MNU_DoEpisodeSelect(UserCall call,MenuItem * UNUSED (item))655 MNU_DoEpisodeSelect(UserCall call, MenuItem * UNUSED(item))
656 {
657 short w,h;
658 char TempString[80];
659 char *extra_text;
660
661 if (call != uc_touchup)
662 return(TRUE);
663
664 extra_text = EpisodeSubtitles[0];
665 MNU_MeasureString(extra_text, &w, &h);
666 MNU_DrawString(30, 63, extra_text, 1, 16);
667 extra_text = EpisodeSubtitles[1];
668 MNU_MeasureString(extra_text, &w, &h);
669 MNU_DrawString(30, 96, extra_text, 1, 16);
670
671 return(TRUE);
672 }
673
674 BOOL
MNU_DoParentalPassword(UserCall UNUSED (call),MenuItem_p UNUSED (item))675 MNU_DoParentalPassword(UserCall UNUSED(call), MenuItem_p UNUSED(item))
676 {
677 short w,h;
678 signed char MNU_InputString(char *, short);
679 static BOOL cur_show;
680 char TempString[80];
681 char *extra_text;
682
683
684 extra_text = "This mode should remove most of the";
685 MNU_MeasureString(extra_text, &w, &h);
686 MNU_DrawString(TEXT_XCENTER(w), 60, extra_text, 1, 16);
687 extra_text = "offensive content. We still recommend";
688 MNU_MeasureString(extra_text, &w, &h);
689 MNU_DrawString(TEXT_XCENTER(w), 70, extra_text, 1, 16);
690 extra_text = "you review the game prior to play.";
691 MNU_MeasureString(extra_text, &w, &h);
692 MNU_DrawString(TEXT_XCENTER(w), 80, extra_text, 1, 16);
693
694 // get input
695 if(MenuInputMode)
696 {
697 switch(MNU_InputString(MessageInputString, 80))
698 {
699 case -1: // Cancel Input (pressed ESC) or Err
700 KB_ClearKeysDown();
701 KB_FlushKeyboardQueue();
702 MenuInputMode = FALSE;
703 memset(MessageInputString, '\0', sizeof(MessageInputString));
704 break;
705 case FALSE: // Input finished (RETURN)
706 if (MessageInputString[0] == '\0')
707 {
708 MenuInputMode = FALSE;
709 KB_ClearKeysDown();
710 KB_FlushKeyboardQueue();
711 memset(MessageInputString, '\0', sizeof(MessageInputString));
712 }
713 else
714 {
715 MenuInputMode = FALSE;
716 KB_ClearKeysDown();
717 KB_FlushKeyboardQueue();
718
719 if(gs.Password[0] != '\0' && passwordvalid == FALSE)
720 {
721 if(!Bstrcasecmp(gs.Password,MessageInputString))
722 {
723 passwordvalid = TRUE;
724 if (currentmenu->cursor == 0 && gs.ParentalLock == TRUE)
725 {
726 buttonsettings[btn_parental] = gs.ParentalLock = FALSE;
727 if (!InMenuLevel)
728 JS_ToggleLockouts();
729 }
730
731 if (currentmenu->cursor == 1) // Is it on the password line?
732 {
733 MenuInputMode = TRUE;
734 KB_ClearKeysDown();
735 KB_FlushKeyboardQueue();
736 }
737 //memset(gs.Password, '\0', sizeof(gs.Password));
738 }
739 } else
740 {
741 if (currentmenu->cursor == 1) // Is it on the password line?
742 {
743 strcpy(gs.Password,MessageInputString);
744 passwordvalid = FALSE;
745 }
746 }
747
748 memset(MessageInputString, '\0', sizeof(MessageInputString));
749 }
750 break;
751 case TRUE: // Got input
752 break;
753 }
754
755 //CON_Message("Password = '%s'",gs.Password);
756 //CON_Message("Passwordvalid = %d",passwordvalid);
757
758 if(gs.Password[0] != '\0' && passwordvalid == FALSE && currentmenu->cursor == 1)
759 {
760 sprintf(TempString,"Enter Old Password");
761 MNU_MeasureString(TempString, &w, &h);
762 MNU_DrawString(TEXT_XCENTER(w), MESSAGE_LINE-10, TempString,1,16);
763 }
764 else
765 if (passwordvalid == TRUE && currentmenu->cursor == 1)
766 {
767 sprintf(TempString,"Enter New Password");
768 MNU_MeasureString(TempString, &w, &h);
769 MNU_DrawString(TEXT_XCENTER(w), MESSAGE_LINE-10, TempString,1,16);
770 }
771 else
772 {
773 sprintf(TempString,"Enter Password");
774 MNU_MeasureString(TempString, &w, &h);
775 MNU_DrawString(TEXT_XCENTER(w), MESSAGE_LINE-10, TempString,1,16);
776 }
777
778 MNU_MeasureString(MessageInputString, &w, &h);
779
780 cur_show ^= 1;
781 if (cur_show)
782 {
783 MNU_DrawString(TEXT_XCENTER(w), MESSAGE_LINE, MessageInputString,1,16);
784 rotatesprite((TEXT_XCENTER(w)+w+7)<<16,(MESSAGE_LINE+3)<<16,64<<9,0,COINCURSOR+((totalclock>>3)%7),0,0,MenuDrawFlags,0,0,xdim-1,ydim-1);
785 }
786 else
787 {
788 MNU_DrawString(TEXT_XCENTER(w), MESSAGE_LINE, MessageInputString,1,16);
789 rotatesprite((TEXT_XCENTER(w)+w+7)<<16,(MESSAGE_LINE+3)<<16,64<<9,0,COINCURSOR+((totalclock>>3)%7),0,0,MenuDrawFlags,0,0,xdim-1,ydim-1);
790 }
791
792 }
793
794 return(TRUE);
795 }
796
797 BOOL
MNU_ParentalCustom(void)798 MNU_ParentalCustom(void)
799 {
800
801 if (MenuInputMode)
802 {
803 // toggle edit mode
804 MenuInputMode = FALSE;
805 memset(MessageInputString, '\0', sizeof(MessageInputString));
806 }
807 else
808 {
809 // clear keyboard buffer
810 while (KB_KeyWaiting())
811 {
812 if (KB_Getch() == 0)
813 KB_Getch();
814 }
815
816 // toggle edit mode
817 MenuInputMode = TRUE;
818 }
819
820 return (TRUE);
821 }
822
823 BOOL
MNU_DoPlayerName(UserCall call,MenuItem_p item)824 MNU_DoPlayerName(UserCall call, MenuItem_p item)
825 {
826 short w,h;
827 signed char MNU_InputString(char *, short);
828 static BOOL cur_show;
829 char TempString[80];
830 char *extra_text;
831
832 (void)call;
833 (void)item;
834
835 // get input
836 if(MenuInputMode)
837 {
838 switch(MNU_InputString(MessageInputString, 80))
839 {
840 case -1: // Cancel Input (pressed ESC) or Err
841 KB_ClearKeysDown();
842 KB_FlushKeyboardQueue();
843 MenuInputMode = FALSE;
844 memset(MessageInputString, '\0', sizeof(MessageInputString));
845 break;
846 case FALSE: // Input finished (RETURN)
847 if (MessageInputString[0] != '\0')
848 SendMulitNameChange(MessageInputString, -1);
849
850 MenuInputMode = FALSE;
851 KB_ClearKeysDown();
852 KB_FlushKeyboardQueue();
853 memset(MessageInputString, '\0', sizeof(MessageInputString));
854 break;
855 case TRUE: // Got input
856 break;
857 }
858
859 sprintf(TempString,"Enter a new Player Name");
860 MNU_MeasureString(TempString, &w, &h);
861 MNU_DrawString(TEXT_XCENTER(w), MESSAGE_LINE-10, TempString,1,16);
862
863 MNU_MeasureString(MessageInputString, &w, &h);
864
865 MNU_DrawString(TEXT_XCENTER(w), MESSAGE_LINE, MessageInputString,1,16);
866 rotatesprite((TEXT_XCENTER(w)+w+7)<<16,(MESSAGE_LINE+3)<<16,64<<9,0,COINCURSOR+((totalclock>>3)%7),0,0,MenuDrawFlags,0,0,xdim-1,ydim-1);
867 rotatesprite((TEXT_XCENTER(w)+w+7)<<16,(MESSAGE_LINE+3)<<16,64<<9,0,COINCURSOR+((totalclock>>3)%7),0,0,MenuDrawFlags,0,0,xdim-1,ydim-1);
868 }
869
870 return(TRUE);
871 }
872
873 BOOL
MNU_PlayerNameCustom(void)874 MNU_PlayerNameCustom(void)
875 {
876
877 if (MenuInputMode)
878 {
879 // toggle edit mode
880 MenuInputMode = FALSE;
881 memset(MessageInputString, '\0', sizeof(MessageInputString));
882 }
883 else
884 {
885 // clear keyboard buffer
886 while (KB_KeyWaiting())
887 {
888 if (KB_Getch() == 0)
889 KB_Getch();
890 }
891
892 // toggle edit mode
893 MenuInputMode = TRUE;
894 }
895
896 return (TRUE);
897 }
898
MNU_KeySetupCustom(UserCall call,MenuItem * item)899 BOOL MNU_KeySetupCustom(UserCall call, MenuItem *item)
900 {
901 static int currentkey = 0, currentcol = 0;
902 static int currentmode = 0;
903
904 if (call == uc_touchup)
905 return (TRUE);
906
907 if (cust_callback == NULL) {
908 if (call != uc_setup)
909 return (FALSE);
910 currentkey = 0;
911 currentcol = 0;
912 currentmode = 0;
913 }
914
915 cust_callback = MNU_KeySetupCustom;
916 cust_callback_call = call;
917 cust_callback_item = item;
918
919 {
920 short w, h = 0;
921 char *s = "Keys Setup";
922 rotatesprite(10 << 16, (5-3) << 16, MZ, 0, 2427,
923 m_defshade, 0, MenuDrawFlags|ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1);
924 MNU_MeasureStringLarge(s, &w, &h);
925 MNU_DrawStringLarge(TEXT_XCENTER(w), 5, s);
926 }
927
928 if (currentmode) {
929 // customising a key
930 char *strs[] = { "Press the key to assign to", "\"%s\" %s", "or ESCAPE to cancel." };
931 char *col[2] = { "(primary)", "(secondary)" };
932 short w, h = 8;
933 int i, j, y;
934
935 if (KEY_PRESSED(KEYSC_ESC)) {
936 KB_ClearKeyDown(sc_Escape);
937 currentmode = 0;
938 } else if (KB_GetLastScanCode() > 0) {
939 KB_ClearKeyDown( KB_GetLastScanCode() );
940
941 KeyboardKeys[currentkey][currentcol] = KB_GetLastScanCode();
942 if (currentkey != gamefunc_Show_Console) {
943 CONTROL_MapKey(currentkey,
944 KeyboardKeys[currentkey][0],
945 KeyboardKeys[currentkey][1]);
946 } else {
947 OSD_CaptureKey(KB_GetLastScanCode());
948 }
949
950 currentmode = 0;
951 }
952
953 MNU_MeasureString(strs[0], &w, &h);
954
955 y = (YDIM - (h+3) * SIZ(strs)) / 2;
956
957 for (i=0; i<(int)SIZ(strs); i++) {
958 w = 0;
959 sprintf(ds,strs[i],gamefunctions[currentkey],col[currentcol]);
960 for (j=0; ds[j]; j++) if (ds[j] == '_') ds[j] = ' ';
961 MNU_MeasureString(ds, &w, &h);
962 MNU_DrawString((XDIM - w)/2, y, ds, 0, 16);
963 y += h+3;
964 }
965
966 } else {
967 // key list
968 #define PGSIZ 14
969 int topitem = 0, botitem = NUMGAMEFUNCTIONS;
970 int i,j;
971 char *morestr = "More...";
972 const char *p;
973
974 UserInput inpt = {FALSE,FALSE,dir_None};
975 CONTROL_GetUserInput(&inpt);
976
977 if (KEY_PRESSED(KEYSC_ESC) || inpt.button1) {
978 KEY_PRESSED(KEYSC_ESC) = FALSE;
979 cust_callback = NULL;
980 CONTROL_ClearUserInput(&inpt);
981 return TRUE;
982 }
983 else if (KB_KeyPressed(sc_Delete)) {
984 KB_ClearKeyDown(sc_Delete);
985 if (currentkey != gamefunc_Show_Console) {
986 KeyboardKeys[currentkey][currentcol] = 0xff;
987 CONTROL_MapKey(currentkey,
988 KeyboardKeys[currentkey][0],
989 KeyboardKeys[currentkey][1]);
990 }
991 }
992 else if (KB_KeyPressed(sc_Home)) {
993 currentkey = 0;
994 KB_ClearKeyDown(sc_Home);
995 }
996 else if (KB_KeyPressed(sc_End)) {
997 currentkey = NUMGAMEFUNCTIONS-1;
998 KB_ClearKeyDown(sc_End);
999 }
1000 else if (KB_KeyPressed(sc_PgDn)) {
1001 currentkey += PGSIZ;
1002 if (currentkey >= NUMGAMEFUNCTIONS) currentkey = NUMGAMEFUNCTIONS-1;
1003 KB_ClearKeyDown(sc_PgDn);
1004 }
1005 else if (KB_KeyPressed(sc_PgUp)) {
1006 currentkey -= PGSIZ;
1007 if (currentkey < 0) currentkey = 0;
1008 KB_ClearKeyDown(sc_PgUp);
1009 }
1010 else if (inpt.button0) {
1011 currentmode = 1;
1012 KB_ClearLastScanCode();
1013 KB_ClearKeysDown();
1014 }
1015 else if (inpt.dir == dir_North) currentkey = max(0,currentkey-1);
1016 else if (inpt.dir == dir_South) currentkey = min(NUMGAMEFUNCTIONS-1,currentkey+1);
1017 else if (inpt.dir == dir_East) currentcol = 1;
1018 else if (inpt.dir == dir_West) currentcol = 0;
1019
1020 if (currentkey == gamefunc_Show_Console) currentcol = 0;
1021
1022 CONTROL_ClearUserInput(&inpt);
1023
1024 if (NUMGAMEFUNCTIONS > PGSIZ) {
1025 topitem = currentkey - PGSIZ/2;
1026 botitem = topitem + PGSIZ;
1027
1028 if (topitem < 0) {
1029 botitem += -topitem;
1030 topitem = 0;
1031 } else if (botitem >= NUMGAMEFUNCTIONS) {
1032 botitem = NUMGAMEFUNCTIONS-1;
1033 topitem = botitem - PGSIZ;
1034 }
1035 }
1036
1037 for (i = topitem; i <= botitem; i++) {
1038 for (j = 0; gamefunctions[i][j]; j++) {
1039 if (gamefunctions[i][j] == '_') ds[j] = ' ';
1040 else ds[j] = gamefunctions[i][j];
1041 }
1042 ds[j] = 0;
1043
1044 j = OPT_LINE(0)+(i-topitem)*8;
1045 MNU_DrawSmallString(OPT_XS, j, ds, (i==currentkey)?0:12, 16);
1046
1047 p = getkeyname(KeyboardKeys[i][0]);
1048 if (!p || KeyboardKeys[i][0]==0xff) p = " -";
1049 MNU_DrawSmallString(OPT_XSIDE, j, (char*)p, (i==currentkey)?-5:12,
1050 (i==currentkey && currentcol==0) ? 14:16);
1051
1052 if (i == gamefunc_Show_Console) continue;
1053
1054 p = getkeyname(KeyboardKeys[i][1]);
1055 if (!p || KeyboardKeys[i][1]==0xff) p = " -";
1056 MNU_DrawSmallString(OPT_XSIDE + 4*14, j, (char*)p, (i==currentkey)?-5:12,
1057 (i==currentkey && currentcol==1) ? 14:16);
1058 }
1059
1060 {
1061 short dx,dy;
1062 dx = 0, dy = 8;
1063 MNU_MeasureSmallString(morestr,&dx,&dy);
1064 if (topitem > 0)
1065 MNU_DrawSmallString(XDIM - OPT_XS - dx, OPT_LINE(0), morestr, 8,16);
1066 if (botitem < NUMGAMEFUNCTIONS-1)
1067 MNU_DrawSmallString(XDIM - OPT_XS - dx, OPT_LINE(0)+PGSIZ*8, morestr, 8,16);
1068 }
1069 #undef PGSIZ
1070 }
1071
1072 return (TRUE);
1073 }
1074
MNU_SelectButtonFunction(const char * buttonname,int * currentfunc)1075 static int MNU_SelectButtonFunction(const char *buttonname, int *currentfunc)
1076 {
1077 const int PGSIZ = 9;
1078 const char *strs[] = { "Select the function to assign to", "%s", "or ESCAPE to cancel." };
1079 int topitem = 0, botitem = NUMGAMEFUNCTIONS-1;
1080 int i, j, y;
1081 short w, h=0;
1082 int returnval = 0;
1083
1084 UserInput inpt = {FALSE,FALSE,dir_None};
1085 CONTROL_GetUserInput(&inpt);
1086
1087 if (inpt.button1) {
1088 KB_ClearKeyDown(sc_Escape);
1089 returnval = -1;
1090 }
1091 else if (KB_KeyPressed(sc_Home)) {
1092 *currentfunc = 0;
1093 KB_ClearKeyDown(sc_Home);
1094 }
1095 else if (KB_KeyPressed(sc_End)) {
1096 *currentfunc = NUMGAMEFUNCTIONS-1; // -1 because the last one is the console and the top is 'none'
1097 KB_ClearKeyDown(sc_End);
1098 }
1099 else if (KB_KeyPressed(sc_PgDn)) {
1100 *currentfunc += PGSIZ;
1101 if (*currentfunc >= NUMGAMEFUNCTIONS) *currentfunc = NUMGAMEFUNCTIONS-1;
1102 KB_ClearKeyDown(sc_PgDn);
1103 }
1104 else if (KB_KeyPressed(sc_PgUp)) {
1105 *currentfunc -= PGSIZ;
1106 if (*currentfunc < 0) *currentfunc = 0;
1107 KB_ClearKeyDown(sc_PgUp);
1108 }
1109 else if (inpt.button0) {
1110 returnval = 1;
1111 }
1112 else if (inpt.dir == dir_North) *currentfunc = max(0, *currentfunc-1);
1113 else if (inpt.dir == dir_South) *currentfunc = min(NUMGAMEFUNCTIONS-1, *currentfunc+1);
1114
1115 CONTROL_ClearUserInput(&inpt);
1116
1117 if (NUMGAMEFUNCTIONS-1 > PGSIZ) {
1118 topitem = *currentfunc - PGSIZ/2;
1119 botitem = topitem + PGSIZ;
1120
1121 if (topitem < 0) {
1122 botitem += -topitem;
1123 topitem = 0;
1124 } else if (botitem >= NUMGAMEFUNCTIONS) {
1125 botitem = NUMGAMEFUNCTIONS-1;
1126 topitem = botitem - PGSIZ;
1127 }
1128 }
1129
1130 y = OPT_LINE(0);
1131 for (i=0; i<(int)SIZ(strs); i++) {
1132 w = 0;
1133 sprintf(ds, strs[i], buttonname);
1134 for (j=0; ds[j]; j++) if (ds[j] == '_') ds[j] = ' ';
1135 MNU_MeasureString(ds, &w, &h);
1136 MNU_DrawString((XDIM - w)/2, y, ds, 0, 16);
1137 y += h;
1138 }
1139
1140 for (i = topitem; i <= botitem; i++) {
1141 if (i == 0) {
1142 strcpy(ds, " -none-");
1143 } else {
1144 for (j = 0; gamefunctions[i-1][j]; j++) {
1145 if (gamefunctions[i-1][j] == '_') ds[j] = ' ';
1146 else ds[j] = gamefunctions[i-1][j];
1147 }
1148 ds[j] = 0;
1149 }
1150
1151 j = OPT_LINE(4)+(i-topitem)*8;
1152 MNU_DrawSmallString(130, j, ds, (i == *currentfunc)?0:12, 16);
1153 }
1154
1155 {
1156 short dx = 0, dy = 8;
1157 const char *morestr = "More...";
1158
1159 MNU_MeasureSmallString(morestr,&dx,&dy);
1160 if (topitem > 0)
1161 MNU_DrawSmallString(XDIM - OPT_XS - dx, OPT_LINE(4), morestr, 8,16);
1162 if (botitem < NUMGAMEFUNCTIONS-1)
1163 MNU_DrawSmallString(XDIM - OPT_XS - dx, OPT_LINE(4)+PGSIZ*8, morestr, 8,16);
1164 }
1165
1166 return returnval;
1167 }
1168
1169
1170 static MenuItem_p mouse_button_item = NULL;
1171
MNU_MouseButtonPostProcess(MenuItem_p item)1172 static BOOL MNU_MouseButtonPostProcess(MenuItem_p item)
1173 {
1174 mouse_button_item = item;
1175 return TRUE;
1176 }
1177
MNU_MouseButtonSetupCustom(UserCall call,MenuItem_p item)1178 BOOL MNU_MouseButtonSetupCustom(UserCall call, MenuItem_p item)
1179 {
1180 int button, clicked, selection;
1181 static int currentfunc = 0;
1182
1183 if (call == uc_touchup)
1184 return (TRUE);
1185
1186 clicked = !!(mouse_button_item->tics & 128);
1187 button = (mouse_button_item->tics & 127);
1188
1189 if (cust_callback == NULL)
1190 {
1191 if (call != uc_setup)
1192 return (FALSE);
1193 if (clicked)
1194 currentfunc = MouseButtonsClicked[button];
1195 else
1196 currentfunc = MouseButtons[button];
1197 currentfunc++;
1198
1199 cust_callback = MNU_MouseButtonSetupCustom;
1200 cust_callback_call = call;
1201 cust_callback_item = item;
1202 }
1203
1204 {
1205 short w, h = 0;
1206 const char *s = "Mouse Buttons";
1207
1208 rotatesprite(10 << 16, (5-3) << 16, MZ, 0, 2427,
1209 m_defshade, 0, MenuDrawFlags|ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1);
1210 MNU_MeasureStringLarge(s, &w, &h);
1211 MNU_DrawStringLarge(TEXT_XCENTER(w), 5, s);
1212 }
1213
1214 selection = MNU_SelectButtonFunction(mouse_button_item->text, ¤tfunc);
1215 switch (selection)
1216 {
1217 case -1: //cancel
1218 cust_callback = NULL;
1219 break;
1220 case 1: //acknowledge
1221 currentfunc--;
1222 if (clicked)
1223 MouseButtonsClicked[button] = currentfunc;
1224 else
1225 MouseButtons[button] = currentfunc;
1226 CONTROL_MapButton(currentfunc, button, clicked, controldevice_mouse);
1227 MNU_SetMouseButtonFunctions(mouse_button_item);
1228 cust_callback = NULL;
1229 break;
1230 default: break;
1231 }
1232
1233 return TRUE;
1234 }
1235
MNU_SetMouseButtonFunctions(MenuItem_p item)1236 static BOOL MNU_SetMouseButtonFunctions(MenuItem_p item)
1237 {
1238 int button, clicked, function;
1239 char *p;
1240
1241 clicked = !!(item->tics & 128);
1242 button = (item->tics & 127);
1243 ASSERT(button >= 0 && button < MAXMOUSEBUTTONS);
1244
1245 if (clicked)
1246 function = MouseButtonsClicked[button];
1247 else
1248 function = MouseButtons[button];
1249
1250 if (function < 0)
1251 strcpy(MouseButtonFunctions[button][clicked], " -");
1252 else
1253 {
1254 strcpy(MouseButtonFunctions[button][clicked], CONFIG_FunctionNumToName(function));
1255 for (p = MouseButtonFunctions[button][clicked]; *p; p++)
1256 if (*p == '_')
1257 *p = ' ';
1258 }
1259 return TRUE;
1260 }
1261
1262
1263 static MenuItem_p mouse_digital_item = NULL;
1264
MNU_MouseDigitalPostProcess(MenuItem_p item)1265 static BOOL MNU_MouseDigitalPostProcess(MenuItem_p item)
1266 {
1267 mouse_digital_item = item;
1268 return TRUE;
1269 }
1270
MNU_MouseDigitalSetupCustom(UserCall call,MenuItem_p item)1271 static BOOL MNU_MouseDigitalSetupCustom(UserCall call, MenuItem_p item)
1272 {
1273 int axis, direction;
1274 static int currentfunc = 0;
1275
1276 if (call == uc_touchup)
1277 return (TRUE);
1278
1279 axis = !!(mouse_digital_item->tics & 2);
1280 direction = (mouse_digital_item->tics & 1);
1281
1282 if (cust_callback == NULL) {
1283 if (call != uc_setup)
1284 return (FALSE);
1285 currentfunc = MouseDigitalAxes[axis][direction];
1286 currentfunc++;
1287
1288 cust_callback = MNU_MouseDigitalSetupCustom;
1289 cust_callback_call = call;
1290 cust_callback_item = item;
1291 }
1292
1293 {
1294 short w, h = 0;
1295 const char *s = "Adv'd Mouse";
1296
1297 rotatesprite(10 << 16, (5-3) << 16, MZ, 0, 2427,
1298 m_defshade, 0, MenuDrawFlags|ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1);
1299 MNU_MeasureStringLarge(s, &w, &h);
1300 MNU_DrawStringLarge(TEXT_XCENTER(w), 5, s);
1301 }
1302
1303 int selection = MNU_SelectButtonFunction(mouse_digital_item->text, ¤tfunc);
1304 switch (selection) {
1305 case -1: //cancel
1306 cust_callback = NULL;
1307 break;
1308 case 1: //acknowledge
1309 currentfunc--;
1310 MouseDigitalAxes[axis][direction] = currentfunc;
1311 CONTROL_MapDigitalAxis(axis, currentfunc, direction, controldevice_mouse);
1312 MNU_SetMouseAxisFunctions(mouse_digital_item);
1313 cust_callback = NULL;
1314 break;
1315 default: break;
1316 }
1317
1318 return TRUE;
1319 }
1320
MNU_SetMouseAxisFunctions(MenuItem_p item)1321 static BOOL MNU_SetMouseAxisFunctions(MenuItem_p item)
1322 {
1323 int axis, direction;
1324 char *p;
1325
1326 axis = !!(item->tics & 2);
1327 direction = (item->tics & 1);
1328 ASSERT(axis >= 0 && axis < MAXMOUSEAXES);
1329
1330 if (MouseDigitalAxes[axis][direction] < 0) {
1331 strcpy(MouseAxisFunctions[axis][direction], " -");
1332 } else {
1333 strcpy(MouseAxisFunctions[axis][direction],
1334 CONFIG_FunctionNumToName(MouseDigitalAxes[axis][direction]));
1335 for (p = MouseAxisFunctions[axis][direction]; *p; p++) {
1336 if (*p == '_')
1337 *p = ' ';
1338 }
1339 }
1340 return TRUE;
1341 }
1342
1343
1344 static MenuItem_p joystick_button_item = NULL;
1345
MNU_JoystickButtonsInitialise(MenuItem_p UNUSED (mitem))1346 static BOOL MNU_JoystickButtonsInitialise(MenuItem_p UNUSED(mitem))
1347 {
1348 JoystickButtonPage = 0;
1349 joybuttonssetupgroup.items = &joybuttons_i[JoystickButtonPage][0];
1350 joybuttonssetupgroup.cursor = 0;
1351 return TRUE;
1352 }
1353
MNU_JoystickButtonPostProcess(MenuItem_p item)1354 static BOOL MNU_JoystickButtonPostProcess(MenuItem_p item)
1355 {
1356 joystick_button_item = item;
1357 return TRUE;
1358 }
1359
MNU_JoystickButtonSetupCustom(UserCall call,MenuItem * item)1360 static BOOL MNU_JoystickButtonSetupCustom(UserCall call, MenuItem *item)
1361 {
1362 int button, clicked, selection;
1363 static int currentfunc = 0;
1364
1365 if (call == uc_touchup)
1366 return (TRUE);
1367
1368 clicked = !!(joystick_button_item->tics & 128);
1369 button = joystick_button_item->tics & 127;
1370
1371 if (cust_callback == NULL)
1372 {
1373 if (call != uc_setup)
1374 return (FALSE);
1375
1376 if (clicked) {
1377 currentfunc = JoystickButtonsClicked[button];
1378 } else {
1379 currentfunc = JoystickButtons[button];
1380 }
1381 currentfunc++;
1382
1383 cust_callback = MNU_JoystickButtonSetupCustom;
1384 cust_callback_call = call;
1385 cust_callback_item = item;
1386 }
1387
1388 {
1389 short w, h = 0;
1390 const char *s = "Joystick Setup";
1391
1392 rotatesprite(10 << 16, (5-3) << 16, MZ, 0, 2427,
1393 m_defshade, 0, MenuDrawFlags|ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1);
1394 MNU_MeasureStringLarge(s, &w, &h);
1395 MNU_DrawStringLarge(TEXT_XCENTER(w), 5, s);
1396 }
1397
1398 selection = MNU_SelectButtonFunction(joystick_button_item->text, ¤tfunc);
1399 switch (selection) {
1400 case -1: //cancel
1401 cust_callback = NULL;
1402 break;
1403 case 1: //acknowledge
1404 currentfunc--;
1405 if (clicked)
1406 JoystickButtonsClicked[button] = currentfunc;
1407 else
1408 JoystickButtons[button] = currentfunc;
1409 CONTROL_MapButton(currentfunc, button, clicked, controldevice_joystick);
1410 MNU_SetJoystickButtonFunctions(joystick_button_item);
1411 cust_callback = NULL;
1412 break;
1413 default: break;
1414 }
1415
1416 return TRUE;
1417 }
1418
MNU_JoystickButtonNextPage(void)1419 static BOOL MNU_JoystickButtonNextPage(void)
1420 {
1421 JoystickButtonPage = (JoystickButtonPage + 1) % MAXJOYSTICKBUTTONPAGES;
1422 joybuttonssetupgroup.items = &joybuttons_i[JoystickButtonPage][0];
1423 joybuttonssetupgroup.cursor = 0;
1424 MNU_ItemPreProcess(&joybuttonssetupgroup);
1425 return TRUE;
1426 }
1427
MNU_SetJoystickButtonFunctions(MenuItem_p item)1428 static BOOL MNU_SetJoystickButtonFunctions(MenuItem_p item)
1429 {
1430 int button, clicked, function;
1431 char *p;
1432
1433 clicked = !!(item->tics & 128);
1434 button = item->tics & 127;
1435 ASSERT(button >= 0 && button < MAXJOYBUTTONS);
1436
1437 if (clicked) {
1438 function = JoystickButtonsClicked[button];
1439 } else {
1440 function = JoystickButtons[button];
1441 }
1442 if (function < 0) {
1443 strcpy(JoystickButtonFunctions[button][clicked], " -");
1444 } else {
1445 strcpy(JoystickButtonFunctions[button][clicked], CONFIG_FunctionNumToName(function));
1446 for (p = JoystickButtonFunctions[button][clicked]; *p; p++) {
1447 if (*p == '_')
1448 *p = ' ';
1449 }
1450 }
1451 return TRUE;
1452 }
1453
1454
1455 static MenuItem_p joystick_axis_item = NULL;
1456
MNU_JoystickAxesInitialise(MenuItem_p UNUSED (mitem))1457 static BOOL MNU_JoystickAxesInitialise(MenuItem_p UNUSED(mitem))
1458 {
1459 if (!CONTROL_JoyPresent) {
1460 return TRUE;
1461 }
1462 if (JoystickAxisPage < 0 || JoystickAxisPage >= joynumaxes) {
1463 JoystickAxisPage = 0;
1464 }
1465
1466 strcpy(JoystickAxisName, getjoyname(0, JoystickAxisPage));
1467 sprintf(JoystickAxisPageName, "Page %d / %d", JoystickAxisPage+1, joynumaxes);
1468 slidersettings[sldr_joyaxisanalog] = MNU_ControlAxisOffset(JoystickAnalogAxes[JoystickAxisPage]);
1469 if (JoystickAnalogScale[JoystickAxisPage] < 0)
1470 {
1471 slidersettings[sldr_joyaxisscale] = klabs(JoystickAnalogScale[JoystickAxisPage]) >> 13;
1472 buttonsettings[btn_joyaxis_invert] = 1;
1473 }
1474 else
1475 {
1476 slidersettings[sldr_joyaxisscale] = JoystickAnalogScale[JoystickAxisPage] >> 13;
1477 buttonsettings[btn_joyaxis_invert] = 0;
1478 }
1479 slidersettings[sldr_joyaxisdead] = JoystickAnalogDead[JoystickAxisPage] >> 10;
1480 slidersettings[sldr_joyaxissatur] = JoystickAnalogSaturate[JoystickAxisPage] >> 10;
1481
1482 return TRUE;
1483 }
1484
MNU_JoystickAxisPostProcess(MenuItem_p item)1485 static BOOL MNU_JoystickAxisPostProcess(MenuItem_p item)
1486 {
1487 joystick_axis_item = item;
1488 return TRUE;
1489 }
1490
MNU_JoystickAxisSetupCustom(UserCall call,MenuItem * item)1491 static BOOL MNU_JoystickAxisSetupCustom(UserCall call, MenuItem *item)
1492 {
1493 static int currentfunc = 0;
1494
1495 if (call == uc_touchup)
1496 return (TRUE);
1497
1498 if (cust_callback == NULL) {
1499 if (call != uc_setup)
1500 return (FALSE);
1501
1502 currentfunc = JoystickDigitalAxes[JoystickAxisPage][joystick_axis_item->tics];
1503 currentfunc++;
1504
1505 cust_callback = MNU_JoystickAxisSetupCustom;
1506 cust_callback_call = call;
1507 cust_callback_item = item;
1508 }
1509
1510 {
1511 short w, h = 0;
1512 const char *s = "Joystick Axes";
1513
1514 rotatesprite(10 << 16, (5-3) << 16, MZ, 0, 2427,
1515 m_defshade, 0, MenuDrawFlags|ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1);
1516 MNU_MeasureStringLarge(s, &w, &h);
1517 MNU_DrawStringLarge(TEXT_XCENTER(w), 5, s);
1518 }
1519
1520 int selection = MNU_SelectButtonFunction(joystick_axis_item->text, ¤tfunc);
1521 switch (selection) {
1522 case -1: //cancel
1523 cust_callback = NULL;
1524 break;
1525 case 1: //acknowledge
1526 currentfunc--;
1527 JoystickDigitalAxes[JoystickAxisPage][joystick_axis_item->tics] = currentfunc;
1528 CONTROL_MapDigitalAxis(JoystickAxisPage, currentfunc, joystick_axis_item->tics, controldevice_joystick);
1529 MNU_SetJoystickAxisFunctions(joystick_axis_item);
1530 cust_callback = NULL;
1531 break;
1532 default: break;
1533 }
1534
1535 return TRUE;
1536 }
1537
MNU_JoystickAxisNextPage(void)1538 static BOOL MNU_JoystickAxisNextPage(void)
1539 {
1540 JoystickAxisPage = (JoystickAxisPage + 1) % joynumaxes;
1541 joyaxessetupgroup.cursor = 1;
1542 MNU_ItemPreProcess(&joyaxessetupgroup);
1543 MNU_JoystickAxesInitialise(NULL);
1544 return TRUE;
1545 }
1546
MNU_SetJoystickAxisFunctions(MenuItem_p item)1547 static BOOL MNU_SetJoystickAxisFunctions(MenuItem_p item)
1548 {
1549 int function;
1550 char *p;
1551
1552 function = JoystickDigitalAxes[JoystickAxisPage][item->tics];
1553 if (function < 0) {
1554 strcpy(JoystickAxisFunctions[item->tics], " -");
1555 } else {
1556 strcpy(JoystickAxisFunctions[item->tics], CONFIG_FunctionNumToName(function));
1557 for (p = JoystickAxisFunctions[item->tics]; *p; p++) {
1558 if (*p == '_')
1559 *p = ' ';
1560 }
1561 }
1562 return TRUE;
1563 }
1564
1565
1566 BOOL
MNU_OrderCustom(UserCall call,MenuItem * item)1567 MNU_OrderCustom(UserCall call, MenuItem * item)
1568 {
1569 static signed char on_screen = 0;
1570 UserInput order_input;
1571 static int limitmove=0;
1572 UserInput tst_input;
1573 BOOL select_held = FALSE;
1574 int zero = 0;
1575 static BOOL DidOrderSound = FALSE;
1576 short choose_snd;
1577 static int wanghandle;
1578
1579 static short RegOrderScreen[] =
1580 {
1581 5262,
1582 5261,
1583 4979,
1584 5111,
1585 5118,
1586 5113,
1587 //5111,
1588 //5118,
1589 //4979,
1590 //5261,
1591 //5262
1592
1593 5114 // JBF: for my credits
1594 };
1595 static short SWOrderScreen[] =
1596 {
1597 5262,
1598 5110,
1599 5112,
1600 5113,
1601 5111,
1602 5118,
1603 4979,
1604
1605 5114 // JBF: for my credits
1606 };
1607 short *OrderScreen, OrderScreenSiz;
1608
1609 if (SW_SHAREWARE) {
1610 OrderScreen = SWOrderScreen;
1611 OrderScreenSiz = SIZ(SWOrderScreen);
1612 } else {
1613 OrderScreen = RegOrderScreen;
1614 OrderScreenSiz = SIZ(RegOrderScreen);
1615 }
1616
1617 // Ignore the special touchup calls
1618 if (call == uc_touchup)
1619 return (TRUE);
1620
1621 if (cust_callback == NULL)
1622 {
1623 if (call != uc_setup)
1624 return (FALSE);
1625 cust_callback = MNU_OrderCustom;
1626 cust_callback_call = uc_draw;
1627 cust_callback_item = item;
1628 return (TRUE);
1629 }
1630
1631 if (SW_SHAREWARE && on_screen == 0 && !DidOrderSound)
1632 {
1633 DidOrderSound = TRUE;
1634 choose_snd = STD_RANDOM_RANGE(1000);
1635 if (choose_snd > 500 && !FX_SoundActive(wanghandle))
1636 wanghandle = PlaySound(DIGI_WANGORDER1, &zero, &zero, &zero, v3df_dontpan);
1637 else
1638 if (!FX_SoundActive(wanghandle))
1639 wanghandle = PlaySound(DIGI_WANGORDER2, &zero, &zero, &zero, v3df_dontpan);
1640 }
1641
1642 order_input.button0 = order_input.button1 = FALSE;
1643 order_input.dir = dir_None;
1644
1645 // Zero out the input structure
1646 tst_input.button0 = tst_input.button1 = FALSE;
1647 tst_input.dir = dir_None;
1648
1649 if(!select_held)
1650 {
1651 CONTROL_GetUserInput(&tst_input);
1652 //order_input_buffered.dir = tst_input.dir;
1653 // Support a few other keys too
1654 if (KEY_PRESSED(KEYSC_SPACE)||KEY_PRESSED(KEYSC_ENTER))
1655 {
1656 KEY_PRESSED(KEYSC_SPACE) = FALSE;
1657 KEY_PRESSED(KEYSC_ENTER) = FALSE;
1658 tst_input.dir = dir_South;
1659 }
1660 }
1661
1662 if (order_input_buffered.button0 || order_input_buffered.button1 || order_input_buffered.dir != dir_None)
1663 {
1664 if(tst_input.button0 == order_input_buffered.button0 &&
1665 tst_input.button1 == order_input_buffered.button1 &&
1666 tst_input.dir == order_input_buffered.dir)
1667 {
1668 select_held = TRUE;
1669 }
1670 else
1671 {
1672 if (labs(totalclock - limitmove) > 7)
1673 {
1674 order_input.button0 = order_input_buffered.button0;
1675 order_input.button1 = order_input_buffered.button1;
1676 order_input.dir = order_input_buffered.dir;
1677
1678 order_input_buffered.button0 = tst_input.button0;
1679 order_input_buffered.button1 = tst_input.button1;
1680 order_input_buffered.dir = tst_input.dir;
1681
1682 limitmove = totalclock;
1683 }
1684 }
1685 }
1686 else
1687 {
1688 select_held = FALSE;
1689 order_input_buffered.button0 = tst_input.button0;
1690 order_input_buffered.button1 = tst_input.button1;
1691 order_input_buffered.dir = tst_input.dir;
1692 }
1693
1694 if (order_input_buffered.button1)
1695 {
1696 KEY_PRESSED(KEYSC_ESC) = FALSE;
1697 cust_callback = NULL;
1698 DidOrderSound = FALSE;
1699 on_screen = 0;
1700 ExitMenus();
1701 return(TRUE);
1702 }
1703
1704 if (order_input.dir == dir_North)
1705 {
1706 on_screen--;
1707 }
1708 else
1709 if (order_input.dir == dir_South)
1710 {
1711 on_screen++;
1712 }
1713 else
1714 if (order_input.dir == dir_West)
1715 {
1716 on_screen--;
1717 }
1718 else
1719 if (order_input.dir == dir_East)
1720 {
1721 on_screen++;
1722 }
1723
1724 // CTW MODIFICATION
1725 // I reversed the logic in here to allow the user to loop around.
1726 // Yeah... I changed default behavior just because I wanted to.
1727 // AND YOU CAN'T STOP ME SUCKER!!!
1728 if(on_screen < 0)
1729 on_screen = OrderScreenSiz-1;
1730
1731 if(on_screen > OrderScreenSiz-1)
1732 on_screen = 0;
1733 // CTW MODIFICATION END
1734
1735 flushperms();
1736 rotatesprite(0,0,RS_SCALE,0,OrderScreen[on_screen],0,0,
1737 (ROTATE_SPRITE_CORNER|ROTATE_SPRITE_SCREEN_CLIP|ROTATE_SPRITE_NON_MASK|ROTATE_SPRITE_IGNORE_START_MOST),
1738 0, 0, xdim-1, ydim-1);
1739 SetRedrawScreen(&Player[myconnectindex]);
1740
1741 if (on_screen == OrderScreenSiz-1)
1742 {
1743 // Jonathon's credits page hack :-)
1744
1745 static char *jtitle = "^Port Credits";
1746 static char *jtext[] = {
1747 "*GAME AND ENGINE PORT",
1748 " Jonathon \"JonoF\" Fowler",
1749 "-",
1750 "*\"POLYMOST\" 3D RENDERER",
1751 "*NETWORKING, OTHER CODE",
1752 " Ken \"Awesoken\" Silverman",
1753 "-",
1754 " Visit http://www.jonof.id.au/jfsw for the",
1755 " source code, latest news, and updates of this port."
1756 };
1757 static char *scroller[] = {
1758 "This program is free software; you can redistribute it",
1759 "and/or modify it under the terms of the GNU General",
1760 "Public License as published by the Free Software",
1761 "Foundation; either version 2 of the License, or (at your",
1762 "option) any later version.",
1763 "",
1764 "This program is distributed in the hope that it will be",
1765 "useful but WITHOUT ANY WARRANTY; without even the implied",
1766 "warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR",
1767 "PURPOSE. See the GNU General Public License (GPL.TXT) for",
1768 "more details.",
1769 "",
1770 "",
1771 "",
1772 "",
1773 "Thanks to these people for their input and contributions:",
1774 "",
1775 "Richard \"TerminX\" Gobeille,",
1776 "Par \"Parkar\" Karlsson", // "Pär \"Parkar\" Karlsson",
1777 "Ben \"ProAsm\" Smit",
1778 "",
1779 "and all those who submitted bug reports and ",
1780 "supported the project financially!",
1781 "",
1782 "",
1783 "--x--",
1784 "",
1785 "",
1786 "",
1787 ""
1788 };
1789 const int numscrollerlines = SIZ(scroller);
1790 short dimx, dimy;
1791 int ycur = 54;
1792 unsigned ji;
1793
1794 dimy = 0; MNU_MeasureString(jtitle, &dimx, &dimy);
1795 MNU_DrawString(160-(dimx>>1), ycur, jtitle, 0, 0);
1796 ycur += dimy + 8;
1797
1798 for (ji = 0; ji < SIZ(jtext); ji++)
1799 {
1800 switch (jtext[ji][0])
1801 {
1802 case '-':
1803 ycur += 6;
1804 break;
1805 case '*':
1806 dimx = dimy = 0;
1807 MNU_MeasureString(&jtext[ji][1], &dimx, &dimy);
1808 MNU_DrawString(160-(dimx>>1), ycur, &jtext[ji][1], 0, 16);
1809 ycur += dimy+1;
1810 break;
1811 default:
1812 if (ji>0 && jtext[ji-1][0] == '*') ycur += 3;
1813 dimx = dimy = 0;
1814 MNU_MeasureSmallString(&jtext[ji][1], &dimx, &dimy);
1815 MNU_DrawSmallString(160-(dimx>>1), ycur, &jtext[ji][1], 0, 0);
1816 ycur += dimy+1;
1817 break;
1818 }
1819 }
1820
1821 int m,i;
1822 for (m=0, i=(totalclock/104)%numscrollerlines; m<4; m++,i++)
1823 {
1824 if (i == numscrollerlines)
1825 i=0;
1826 dimx = dimy = 0;
1827 MNU_MeasureSmallString(scroller[i], &dimx, &dimy);
1828 MNU_DrawSmallString(160-(dimx>>1), 154+(m*7), scroller[i], 0, 8);
1829 }
1830 }
1831
1832 //KB_ClearKeysDown();
1833
1834 return (TRUE);
1835 }
1836
MNU_LoadModernDefaults(void)1837 BOOL MNU_LoadModernDefaults(void)
1838 {
1839 CONFIG_SetDefaultKeyDefinitions(CONFIG_DEFAULTS_MODERN);
1840 CONFIG_SetMouseDefaults(CONFIG_DEFAULTS_MODERN);
1841 CONFIG_SetJoystickDefaults(CONFIG_DEFAULTS_MODERN);
1842 return TRUE;
1843 }
1844
MNU_LoadClassicDefaults(void)1845 BOOL MNU_LoadClassicDefaults(void)
1846 {
1847 CONFIG_SetDefaultKeyDefinitions(CONFIG_DEFAULTS_CLASSIC);
1848 CONFIG_SetMouseDefaults(CONFIG_DEFAULTS_CLASSIC);
1849 CONFIG_SetJoystickDefaults(CONFIG_DEFAULTS_CLASSIC);
1850 return TRUE;
1851 }
1852
1853
1854 short EpisodeMenuSelection;
1855
1856 void
ExitMenus(void)1857 ExitMenus(void)
1858 {
1859 ControlPanelType = ct_mainmenu;
1860 UsingMenus = FALSE;
1861
1862 if (LoadGameOutsideMoveLoop)
1863 return;
1864
1865 ResumeGame();
1866 SetRedrawScreen(&Player[myconnectindex]);
1867 }
1868
1869 BOOL
MNU_StartGame(void)1870 MNU_StartGame(void)
1871 {
1872 PLAYERp pp = Player + screenpeek;
1873 int handle = 0;
1874 int zero = 0;
1875
1876 // always assumed that a demo is playing
1877
1878 ready2send = 0;
1879 Skill = currentmenu->cursor;
1880
1881 if (EpisodeMenuSelection >= 1)
1882 Level = 5;
1883 else
1884 Level = 1;
1885
1886 ExitMenus();
1887 DemoPlaying = FALSE;
1888 ExitLevel = TRUE;
1889 NewGame = TRUE;
1890 DemoMode = FALSE;
1891 CameraTestMode = FALSE;
1892
1893 //InitNewGame();
1894
1895 if(Skill == 0)
1896 handle = PlaySound(DIGI_TAUNTAI3,&zero,&zero,&zero,v3df_none);
1897 else
1898 if(Skill == 1)
1899 handle = PlaySound(DIGI_NOFEAR,&zero,&zero,&zero,v3df_none);
1900 else
1901 if(Skill == 2)
1902 handle = PlaySound(DIGI_WHOWANTSWANG,&zero,&zero,&zero,v3df_none);
1903 else
1904 if(Skill == 3)
1905 handle = PlaySound(DIGI_NOPAIN,&zero,&zero,&zero,v3df_none);
1906
1907 if (handle >= FX_Ok)
1908 while(FX_SoundActive(handle))
1909 handleevents();
1910
1911 return (TRUE);
1912 }
1913
ResetMenuInput(VOID)1914 VOID ResetMenuInput(VOID)
1915 {
1916 cust_callback = NULL;
1917 InputMode = FALSE;
1918 }
1919
1920 BOOL
MNU_StartNetGame(void)1921 MNU_StartNetGame(void)
1922 {
1923 extern BOOL ExitLevel, ShortGameMode, DemoInitOnce, FirstTimeIntoGame;
1924 extern short Level, Skill;
1925 int pnum;
1926
1927 // always assumed that a demo is playing
1928
1929 ready2send = 0;
1930 // Skill can go negative here
1931 Skill = gs.NetMonsters-1;
1932 Level = gs.NetLevel + 1;
1933 if (!AutoNet)
1934 ExitMenus();
1935 DemoPlaying = FALSE;
1936 ExitLevel = TRUE;
1937 NewGame = TRUE;
1938 // restart demo for multi-play mode
1939 DemoInitOnce = FALSE;
1940 ResetMenuInput();
1941
1942 // TENSW: return if a joiner
1943 if (/* CTW REMOVED gTenActivated && */!AutoNet && FirstTimeIntoGame)
1944 return TRUE;
1945
1946 // need to set gNet vars for self
1947 // everone else gets a packet to set them
1948 gNet.AutoAim = gs.AutoAim;
1949 gNet.SpawnMarkers = gs.NetSpawnMarkers;
1950 gNet.HurtTeammate = gs.NetHurtTeammate;
1951 gNet.Nuke = gs.NetNuke;
1952 gNet.KillLimit = gs.NetKillLimit*10;
1953 gNet.TimeLimit = TimeLimitTable[gs.NetTimeLimit]*60*120;
1954
1955 if (ShortGameMode)
1956 {
1957 gNet.KillLimit /= 10;
1958 gNet.TimeLimit /= 2;
1959 }
1960
1961 gNet.TimeLimitClock = gNet.TimeLimit;
1962 gNet.TeamPlay = gs.NetTeamPlay;
1963 gNet.MultiGameType = gs.NetGameType+1;
1964
1965 if (gNet.MultiGameType == MULTI_GAME_COMMBAT_NO_RESPAWN)
1966 {
1967 gNet.MultiGameType = MULTI_GAME_COMMBAT;
1968 gNet.NoRespawn = TRUE;
1969 }
1970 else
1971 {
1972 gNet.NoRespawn = FALSE;
1973 }
1974
1975 if (CommEnabled)
1976 {
1977 PACKET_NEW_GAME p;
1978
1979 p.PacketType = PACKET_TYPE_NEW_GAME;
1980 p.Level = Level;
1981 p.Skill = Skill;
1982 p.GameType = gs.NetGameType;
1983 p.AutoAim = gs.AutoAim;
1984 p.HurtTeammate = gs.NetHurtTeammate;
1985 p.TeamPlay = gs.NetTeamPlay;
1986 p.SpawnMarkers = gs.NetSpawnMarkers;
1987 p.KillLimit = gs.NetKillLimit;
1988 p.TimeLimit = gs.NetTimeLimit;
1989 p.Nuke = gs.NetNuke;
1990
1991 netbroadcastpacket((BYTEp)(&p), sizeof(p)); // TENSW
1992 }
1993
1994
1995 return (TRUE);
1996 }
1997
1998
1999 BOOL
MNU_EpisodeCustom(void)2000 MNU_EpisodeCustom(void)
2001 {
2002 EpisodeMenuSelection = currentmenu->cursor;
2003
2004 return (TRUE);
2005 }
2006
2007 BOOL
MNU_QuitCustom(UserCall call,MenuItem_p item)2008 MNU_QuitCustom(UserCall call, MenuItem_p item)
2009 {
2010 int select;
2011 DialogResponse ret;
2012 extern BOOL DrawScreen;
2013
2014 // Ignore the special touchup calls
2015 if (call == uc_touchup)
2016 return (TRUE);
2017
2018 if (cust_callback == NULL)
2019 {
2020 if (call != uc_setup)
2021 return (FALSE);
2022
2023 memset(dialog, 0, sizeof(dialog));
2024
2025 dialog[0] = S_QUITYN;
2026
2027 cust_callback = MNU_QuitCustom;
2028 cust_callback_call = uc_draw;
2029 cust_callback_item = item;
2030
2031 return(TRUE);
2032 }
2033
2034 ret = MNU_Dialog();
2035
2036 if (DrawScreen || ret == dialog_NoAnswer)
2037 return(TRUE);
2038
2039 cust_callback = NULL;
2040 ExitMenus();
2041
2042 if (ret == dialog_Yes)
2043 {
2044 if (CommPlayers >= 2)
2045 MultiPlayQuitFlag = TRUE;
2046 else
2047 QuitFlag = TRUE;
2048 }
2049
2050 KB_ClearKeysDown();
2051
2052 return (TRUE);
2053 }
2054
2055 BOOL
MNU_QuickLoadCustom(UserCall call,MenuItem_p item)2056 MNU_QuickLoadCustom(UserCall call, MenuItem_p item)
2057 {
2058 int select;
2059 extern BOOL ReloadPrompt;
2060 int bak;
2061 PLAYERp pp = Player + myconnectindex;
2062 extern short GlobInfoStringTime;
2063 extern BOOL DrawScreen;
2064 DialogResponse ret;
2065
2066 if (cust_callback == NULL)
2067 {
2068 if (call != uc_setup)
2069 return (FALSE);
2070
2071 memset(dialog, 0, sizeof(dialog));
2072
2073 dialog[0] = "Load saved game";
2074 sprintf(QuickLoadDescrDialog,"\"%s\" (Y/N)?",SaveGameDescr[QuickLoadNum]);
2075 dialog[1] = QuickLoadDescrDialog;
2076
2077 cust_callback = MNU_QuickLoadCustom;
2078 cust_callback_call = uc_draw;
2079 cust_callback_item = item;
2080
2081 return(TRUE);
2082 }
2083
2084 // Ignore the special touchup calls
2085 if (call == uc_touchup)
2086 return (TRUE);
2087
2088 ret = MNU_Dialog();
2089
2090 if (DrawScreen || ret == dialog_NoAnswer)
2091 {
2092 return(TRUE);
2093 }
2094
2095 if (ret == dialog_No)
2096 {
2097 cust_callback = NULL;
2098 if (ReloadPrompt)
2099 {
2100 ReloadPrompt = FALSE;
2101 bak = GlobInfoStringTime;
2102 GlobInfoStringTime = 999;
2103 PutStringInfo(pp, "Press SPACE to restart");
2104 GlobInfoStringTime = bak;
2105 }
2106
2107 KB_ClearKeysDown();
2108 ExitMenus();
2109 }
2110 else
2111 {
2112 // Y pressed
2113 cust_callback = NULL;
2114
2115 KB_ClearKeysDown();
2116 LoadSaveMsg("Loading...");
2117
2118 PauseAction();
2119
2120 ReloadPrompt = FALSE;
2121 if (LoadGame(QuickLoadNum) == -1)
2122 {
2123 ResumeAction();
2124 return (FALSE);
2125 }
2126
2127 ready2send = 1;
2128 LastSaveNum = -1;
2129
2130 // do a load game here
2131 KB_ClearKeysDown();
2132 ExitMenus();
2133 }
2134
2135 KB_ClearKeysDown();
2136
2137 return (TRUE);
2138 }
2139
2140 // MENU FUNCTIONS /////////////////////////////////////////////////////////////////////////////////
2141 ////////////////////////////////////////////////
2142 // Set some global menu related defaults
2143 ////////////////////////////////////////////////
2144 void
MNU_InitMenus(void)2145 MNU_InitMenus(void)
2146 {
2147 pClearTextLine(Player + myconnectindex, TEXT_INFO_LINE(0));
2148
2149 slidersettings[sldr_mouse] = gs.MouseSpeed/(MOUSE_SENS_MAX_VALUE/SLDR_MOUSESENSEMAX);
2150
2151 slidersettings[sldr_sndfxvolume] = gs.SoundVolume / (FX_VOL_MAX_VALUE/SLDR_SNDFXVOLMAX);
2152 slidersettings[sldr_musicvolume] = gs.MusicVolume / (MUSIC_VOL_MAX_VALUE/SLDR_MUSICVOLMAX);
2153 slidersettings[sldr_scrsize] = gs.BorderNum;
2154 slidersettings[sldr_brightness] = gs.Brightness;
2155 slidersettings[sldr_panelscale] = gs.PanelScale - 1;
2156 slidersettings[sldr_bordertile] = gs.BorderTile;
2157
2158 {
2159 int i,newx=xdim,newy=ydim;
2160
2161 #if USE_POLYMOST && USE_OPENGL
2162 buttonsettings[btn_texfilter] = (gltexfiltermode & 1);
2163 #endif
2164 buttonsettings[btn_videofs] = fullscreen;
2165
2166 UpdateValidModes(bpp,fullscreen);
2167 for (i=0; i<numvalidbpps; i++)
2168 if (validbpps[i] == bpp)
2169 slidersettings[sldr_videobpp] = i;
2170
2171 i = checkvideomode(&newx, &newy, bpp, fullscreen, 1);
2172 if (i != 0x7fffffff && i >= 0)
2173 for (i=0; i<numvalidresolutions; i++)
2174 if (validresolutions[i].x == newx && validresolutions[i].y == newy)
2175 slidersettings[sldr_videores] = i;
2176 }
2177
2178 buttonsettings[btn_auto_run] = gs.AutoRun;
2179 buttonsettings[btn_auto_aim] = gs.AutoAim;
2180 buttonsettings[btn_messages] = gs.Messages;
2181 buttonsettings[btn_crosshair] = gs.Crosshair;
2182 // buttonsettings[btn_bobbing] = gs.Bobbing;
2183 buttonsettings[btn_shadows] = gs.Shadows;
2184
2185 buttonsettings[btn_mouse_aim] = gs.MouseAimingType;
2186 buttonsettings[btn_mouse_invert] = gs.MouseInvert;
2187 buttonsettings[btn_sound] = gs.FxOn;
2188 buttonsettings[btn_music] = gs.MusicOn;
2189 buttonsettings[btn_talking] = gs.Talking;
2190
2191 buttonsettings[btn_voxels] = gs.Voxels;
2192 buttonsettings[btn_ambience] = gs.Ambient;
2193 buttonsettings[btn_playcd] = gs.PlayCD;
2194 buttonsettings[btn_flipstereo] = gs.FlipStereo;
2195 buttonsettings[btn_stats] = gs.Stats;
2196
2197 slidersettings[sldr_gametype] = gs.NetGameType;
2198 slidersettings[sldr_netlevel] = gs.NetLevel;
2199 slidersettings[sldr_monsters] = gs.NetMonsters;
2200 slidersettings[sldr_killlimit] = gs.NetKillLimit;
2201 slidersettings[sldr_timelimit] = gs.NetTimeLimit;
2202 slidersettings[sldr_playercolor] = gs.NetColor;
2203
2204 buttonsettings[btn_nuke] = gs.NetNuke;
2205 buttonsettings[btn_markers] = gs.NetSpawnMarkers;
2206 buttonsettings[btn_teamplay] = gs.NetTeamPlay;
2207 buttonsettings[btn_friendlyfire] = gs.NetHurtTeammate;
2208 buttonsettings[btn_parental] = gs.ParentalLock;
2209
2210 slidersettings[sldr_mousescalex] = MouseAnalogScale[0]>>13;
2211 slidersettings[sldr_mousescaley] = MouseAnalogScale[1]>>13;
2212
2213 slidersettings[sldr_joyaxisscale] = 0;
2214 buttonsettings[btn_joyaxis_invert] = 0;
2215 slidersettings[sldr_joyaxisanalog] = 0;
2216 slidersettings[sldr_joyaxisdead] = 0;
2217 slidersettings[sldr_joyaxissatur] = 0;
2218
2219 // Distinguish between Single or Multiplay for new game menu types
2220 if(CommPlayers > 1)
2221 main_i[0].child = &networkgroup;
2222 else
2223 // #ifdef SW_SHAREWARE
2224 main_i[0].child = &episodegroup;
2225 // #else
2226 // main_i[0].child = &skillgroup;
2227 // #endif
2228 main_i[4].text = (SW_SHAREWARE) ? MAIN_MENU_HOW_TO_ORDER : MAIN_MENU_COOL_STUFF;
2229 main_i[4].hotkey = (SW_SHAREWARE) ? KEYSC_H : KEYSC_C;
2230 }
2231
2232 ////////////////////////////////////////////////
2233 // Measure the pixel width of a graphic string
2234 ////////////////////////////////////////////////
2235 static char lg_xlat_num[] = {0,1,2,3,4,5,6,7,8,9};
2236 #define FONT_LARGE_ALPHA 3706
2237 #define FONT_LARGE_DIGIT 3732
2238
2239 void
MNU_MeasureStringLarge(const char * string,short * w,short * h)2240 MNU_MeasureStringLarge(const char *string, short *w, short *h)
2241 {
2242 short ndx, width, height;
2243 char c;
2244 short pic;
2245
2246 width = 0;
2247 height = *h;
2248
2249 for (ndx = 0; (c = string[ndx]) != 0; ndx++)
2250 {
2251 if (isalpha(c))
2252 {
2253 c = toupper(c);
2254 pic = FONT_LARGE_ALPHA + (c - 'A');
2255 }
2256 else
2257 if (isdigit(c))
2258 {
2259 pic = FONT_LARGE_DIGIT + lg_xlat_num[(c - '0')];
2260 }
2261 else
2262 if (c == ' ')
2263 {
2264 width += 10; // Special case for space char
2265 continue;
2266 }
2267 else
2268 {
2269 continue;
2270 }
2271
2272 width += tilesizx[pic]+1;
2273 if (height < tilesizy[pic])
2274 height = tilesizy[pic];
2275 }
2276
2277 *w = width;
2278 *h = height;
2279 }
2280
2281 ////////////////////////////////////////////////
2282 // Draw a string using a graphic font
2283 ////////////////////////////////////////////////
2284 void
MNU_DrawStringLarge(short x,short y,const char * string)2285 MNU_DrawStringLarge(short x, short y, const char *string)
2286 {
2287 int ndx, offset;
2288 char c;
2289 short pic;
2290
2291 offset = x;
2292
2293 for (ndx = 0; (c = string[ndx]) != 0; ndx++)
2294 {
2295 if (isalpha(c))
2296 {
2297 c = toupper(c);
2298 pic = FONT_LARGE_ALPHA + (c - 'A');
2299 }
2300 else
2301 if (isdigit(c))
2302 {
2303 pic = FONT_LARGE_DIGIT + lg_xlat_num[(c - '0')];
2304 }
2305 else
2306 if (c == ' ')
2307 {
2308 offset += 10;
2309 continue;
2310 }
2311 else
2312 {
2313 continue;
2314 }
2315
2316 rotatesprite(offset << 16, y << 16, MZ, 0, pic, MenuTextShade, 0, MenuDrawFlags|ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1);
2317 offset += tilesizx[pic] + 1;
2318 }
2319
2320 }
2321
2322
2323 ////////////////////////////////////////////////
2324 // Measure the pixel width of a graphic string
2325 ////////////////////////////////////////////////
2326 void
MNU_MeasureString(const char * string,short * w,short * h)2327 MNU_MeasureString(const char *string, short *w, short *h)
2328 {
2329 short ndx, width, height;
2330 char c;
2331 short ac;
2332
2333 if (string[0] == '^')
2334 {
2335 MNU_MeasureStringLarge(&string[1], w, h);
2336 return;
2337 }
2338
2339 width = 0;
2340 height = *h;
2341
2342 for (ndx = 0; (c = string[ndx]) != 0; ndx++)
2343 {
2344 ac = c - '!' + STARTALPHANUM;
2345 if( (ac < STARTALPHANUM || ac > ENDALPHANUM) && c != asc_Space )
2346 break;
2347
2348 if (c > asc_Space && c < 127)
2349 {
2350 width += tilesizx[ac];
2351 if (height < tilesizy[ac])
2352 height = tilesizy[ac];
2353 }
2354 else
2355 if (c == asc_Space)
2356 width += 4; // Special case for space char
2357 }
2358
2359 *w = width;
2360 *h = height;
2361 }
2362
2363 ////////////////////////////////////////////////
2364 // Draw a string using a graphic font
2365 //
2366 // MenuTextShade and MenuDrawFlags
2367 ////////////////////////////////////////////////
2368 void
MNU_DrawString(short x,short y,const char * string,short shade,short pal)2369 MNU_DrawString(short x, short y, const char *string, short shade, short pal)
2370 {
2371 int ndx, offset;
2372 char c;
2373 short ac;
2374
2375 if (string[0] == '^')
2376 {
2377 MNU_DrawStringLarge(x,y, &string[1]);
2378 return;
2379 }
2380
2381 offset = x;
2382
2383 for (ndx = 0; (c = string[ndx]) != 0; ndx++)
2384 {
2385 ac = c - '!' + STARTALPHANUM;
2386 if( (ac < STARTALPHANUM || ac > ENDALPHANUM) && c != asc_Space )
2387 break;
2388
2389 if (c > asc_Space && c < 127)
2390 {
2391 rotatesprite(offset<<16,y<<16,MZ,0,ac, shade, pal, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
2392 offset += tilesizx[ac];
2393 } else
2394 if (c == asc_Space)
2395 offset += 4; // Special case for space char
2396 }
2397
2398 }
2399 /* Original code
2400 void
2401 MNU_DrawString(short x, short y, char *string)
2402 {
2403 int ndx, offset;
2404 char c;
2405
2406 if (string[0] == '^')
2407 {
2408 MNU_DrawStringLarge(x,y, &string[1]);
2409 return;
2410 }
2411
2412 offset = x;
2413
2414 for (ndx = 0; (c = string[ndx]) != 0; ndx++)
2415 {
2416 if (c > asc_Space && c < 127)
2417 {
2418 rotatesprite(offset << 16, y << 16, MZ, 0, xlatfont[c], MenuTextShade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
2419 offset += tilesizx[xlatfont[c]];
2420 } else
2421 if (c == asc_Space)
2422 offset += 4; // Special case for space char
2423 }
2424
2425 }
2426 */
2427
2428 ////////////////////////////////////////////////
2429 // Measure the pixel width of a small font string
2430 ////////////////////////////////////////////////
2431 void
MNU_MeasureSmallString(const char * string,short * w,short * h)2432 MNU_MeasureSmallString(const char *string, short *w, short *h)
2433 {
2434 short ndx, width, height;
2435 char c;
2436 short ac;
2437
2438 width = 0;
2439 height = *h;
2440
2441 for (ndx = 0; (c = string[ndx]) != 0; ndx++)
2442 {
2443 ac = (c - '!') + 2930;
2444 if( (ac < 2930 || ac > 3023) && c != asc_Space )
2445 break;
2446
2447 if (c > asc_Space && c < 127)
2448 {
2449 width += tilesizx[ac];
2450 if (height < tilesizy[ac])
2451 height = tilesizy[ac];
2452 }
2453 else
2454 if (c == asc_Space)
2455 width += 4; // Special case for space char
2456 }
2457
2458 *w = width;
2459 *h = height;
2460 }
2461
2462 ////////////////////////////////////////////////
2463 // Draw a string using a small graphic font
2464 ////////////////////////////////////////////////
2465 void
MNU_DrawSmallString(short x,short y,const char * string,short shade,short pal)2466 MNU_DrawSmallString(short x, short y, const char *string, short shade, short pal)
2467 {
2468 int ndx;
2469 char c;
2470 short ac,offset;
2471
2472
2473 offset = x;
2474
2475 for (ndx = 0; (c = string[ndx]) != 0; ndx++)
2476 {
2477 ac = c - '!' + 2930;
2478 if( (ac < 2930 || ac > 3023) && c != asc_Space )
2479 break;
2480
2481 if (c > asc_Space && c < 127)
2482 {
2483 rotatesprite(offset<<16,y<<16,MZ,0,ac, shade, pal, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
2484
2485 offset += tilesizx[ac];
2486
2487 } else
2488 if (c == asc_Space)
2489 {
2490 offset += 4; // Special case for space char
2491 }
2492 }
2493
2494 }
2495
2496 ////////////////////////////////////////////////
2497 // Get an input string from user using small font
2498 ////////////////////////////////////////////////
2499
2500 signed char
MNU_InputSmallString(char * name,short pix_width)2501 MNU_InputSmallString(char *name, short pix_width)
2502 {
2503 char ch;
2504 short w, h;
2505 UserInput con_input;
2506
2507 #define ascii_backspace 8
2508 #define ascii_esc 27
2509 #define ascii_return 13
2510
2511 if (!MoveSkip4 && !MessageInputMode)
2512 {
2513 con_input.dir = dir_None;
2514 CONTROL_GetUserInput(&con_input);
2515
2516 if (con_input.dir == dir_North)
2517 {
2518 CON_CommandHistory(1);
2519 }
2520 else
2521 if (con_input.dir == dir_South)
2522 {
2523 CON_CommandHistory(-1);
2524 }
2525 }
2526
2527 while (KB_KeyWaiting())
2528 {
2529 ch = KB_Getch();
2530
2531 // skip any extended key
2532 if (ch == 0)
2533 {
2534 ch = KB_Getch();
2535 if (ch == 104) // extended enter
2536 ch = ascii_return;
2537 else
2538 continue;
2539 }
2540
2541 if (ch == ascii_backspace)
2542 {
2543 name[strlen(name) - 1] = '\0';
2544 continue;
2545 }
2546 else
2547 if (ch == ascii_esc)
2548 {
2549 return (-1);
2550 }
2551 else
2552 if (ch == ascii_return)
2553 {
2554 return (FALSE);
2555 }
2556 else
2557 if (!isprint(ch))
2558 continue;
2559
2560 MNU_MeasureSmallString(name, &w, &h);
2561 if (w < pix_width)
2562 {
2563 if(strlen(name) < 256) // Dont let it go too far!
2564 sprintf(name, "%s%c", name, ch);
2565 }
2566 }
2567
2568 return (TRUE);
2569
2570 }
2571
2572 ////////////////////////////////////////////////
2573 // Draw dialog text on screen
2574 ////////////////////////////////////////////////
2575 static DialogResponse
MNU_Dialog(void)2576 MNU_Dialog(void)
2577 {
2578 short ndx, linecnt, w[MAXDIALOG], h, x, y;
2579
2580 linecnt = 0;
2581 h = 8;
2582
2583 for (ndx = 0; ndx < MAXDIALOG && dialog[ndx]; ndx++)
2584 {
2585 MNU_MeasureString(dialog[ndx], &w[ndx], &h);
2586 ASSERT(w[ndx] < XDIM);
2587 linecnt++;
2588 }
2589
2590 y = ((YDIM - ((h * linecnt) + (linecnt * 2))) / 2);
2591
2592 for (ndx = 0; ndx < linecnt; ndx++)
2593 {
2594 x = ((XDIM - w[ndx]) / 2);
2595 MNU_DrawString(x, y, dialog[ndx],1,16);
2596 y += (h + 3);
2597 }
2598
2599 CONTROL_GetUserInput(&mnu_input);
2600
2601 if (KB_KeyPressed(sc_Y) || KB_KeyPressed(sc_Enter) || mnu_input.button0)
2602 return dialog_Yes;
2603 else if (KB_KeyPressed(sc_N) || KB_KeyPressed(sc_Escape) || mnu_input.button1)
2604 return dialog_No;
2605 else
2606 return dialog_NoAnswer;
2607 }
2608
2609 ////////////////////////////////////////////////
2610 // Get an input string from user
2611 ////////////////////////////////////////////////
2612
2613 signed char
MNU_InputString(char * name,short pix_width)2614 MNU_InputString(char *name, short pix_width)
2615 {
2616 char ch;
2617 short w, h;
2618
2619 #define ascii_backspace 8
2620 #define ascii_esc 27
2621 #define ascii_return 13
2622
2623 while (KB_KeyWaiting())
2624 {
2625 ch = KB_Getch();
2626
2627 ////DSPRINTF(ds, "%c %d", ch, ch);
2628 //MONO_PRINT(ds);
2629
2630 // skip most extended keys
2631 if (ch == 0)
2632 {
2633 ch = KB_Getch();
2634
2635 ////DSPRINTF(ds, "extended key %c %d", ch, ch);
2636 //MONO_PRINT(ds);
2637
2638 if (ch == 104) // extended enter
2639 ch = ascii_return;
2640 else
2641 continue;
2642 }
2643
2644 if (ch == ascii_backspace)
2645 {
2646 name[strlen(name) - 1] = '\0';
2647 continue;
2648 }
2649 else
2650 if (ch == ascii_esc)
2651 {
2652 return (-1);
2653 }
2654 else
2655 if (ch == ascii_return)
2656 {
2657 return (FALSE);
2658 }
2659 else
2660 if (!isprint(ch))
2661 continue;
2662
2663 MNU_MeasureString(name, &w, &h);
2664 if (w < pix_width)
2665 {
2666 sprintf(name, "%s%c", name, ch);
2667 }
2668 }
2669
2670 return (TRUE);
2671
2672 }
2673
2674 #define SS_XSTART 146L
2675 #define SS_YSTART SD_YSTART
2676 #define SS_BORDER_SIZE 5L
2677
LoadSaveMsg(char * msg)2678 VOID LoadSaveMsg(char *msg)
2679 {
2680 short w,h;
2681
2682 flushperms();
2683 DrawMenuLevelScreen();
2684 strcpy((char*)ds, (char*)msg);
2685 MNU_MeasureString(ds, &w, &h);
2686 MNU_DrawString(TEXT_XCENTER(w), 170, ds, 1, 16);
2687 nextpage();
2688 }
2689
2690
2691 ////////////////////////////////////////////////
2692 // Load Game menu
2693 // This function gets called whenever you
2694 // press enter on one of the load game
2695 // spots.
2696 // I'm figuring it need to do the following:
2697 // . Load the game if there is one by calling: MNU_LoadGameCustom.
2698 ////////////////////////////////////////////////
2699 BOOL
MNU_GetLoadCustom(void)2700 MNU_GetLoadCustom(void)
2701 {
2702 short load_num;
2703
2704 load_num = currentmenu->cursor;
2705
2706 // no saved game exists - don't do anything
2707 if (SaveGameDescr[load_num][0] == '\0')
2708 return (FALSE);
2709
2710 if (InMenuLevel || DemoMode || DemoPlaying)
2711 {
2712 LoadSaveMsg("Loading...");
2713
2714 if (LoadGame(load_num) == -1)
2715 return (FALSE);
2716
2717 QuickLoadNum = load_num;
2718 // the (Quick)Save menu should default to the last loaded game
2719 SaveGameGroup.cursor = load_num;
2720
2721 ExitMenus();
2722 ExitLevel = TRUE;
2723 LoadGameOutsideMoveLoop = TRUE;
2724 if (DemoMode || DemoPlaying)
2725 LoadGameFromDemo = TRUE;
2726
2727 return(TRUE);
2728 }
2729
2730 LoadSaveMsg("Loading...");
2731
2732 PauseAction();
2733
2734 if (LoadGame(load_num) == -1)
2735 {
2736 ResumeAction();
2737 return (FALSE);
2738 }
2739
2740 QuickLoadNum = load_num;
2741 // the (Quick)Save menu should default to the last loaded game
2742 SaveGameGroup.cursor = load_num;
2743
2744 ready2send = 1;
2745 LastSaveNum = -1;
2746 ExitMenus();
2747
2748 if (DemoMode)
2749 {
2750 ExitLevel = TRUE;
2751 DemoPlaying = FALSE;
2752 }
2753
2754 return (TRUE);
2755 }
2756
2757 ////////////////////////////////////////////////
2758 // Save Game menu
2759 // This function gets called whenever you
2760 // press enter on one of the save game
2761 // spots.
2762 // I'm figuring it need to do the following:
2763 // . Call MNU_GetInput to allow string input of description.
2764 // . Save the game if there is one by calling: MNU_SaveGameCustom.
2765 ////////////////////////////////////////////////
2766 BOOL
MNU_GetSaveCustom(void)2767 MNU_GetSaveCustom(void)
2768 {
2769 short save_num;
2770 extern BOOL InMenuLevel, LoadGameOutsideMoveLoop;
2771
2772 save_num = currentmenu->cursor;
2773
2774 if (InMenuLevel)
2775 return(FALSE);
2776
2777 if (MenuInputMode)
2778 {
2779 PauseAction();
2780
2781 LoadSaveMsg("Saving...");
2782
2783 if (SaveGame(save_num) != -1)
2784 {
2785 QuickLoadNum = save_num;
2786
2787 LoadGameGroup.cursor = save_num;
2788 LastSaveNum = -1;
2789 }
2790
2791 ResumeAction();
2792 ExitMenus();
2793
2794 // toggle edit mode
2795 MenuInputMode = FALSE;
2796 }
2797 else
2798 {
2799 strcpy(BackupSaveGameDescr, SaveGameDescr[save_num]);
2800
2801 // clear keyboard buffer
2802 while (KB_KeyWaiting())
2803 {
2804 if (KB_Getch() == 0)
2805 KB_Getch();
2806 }
2807
2808 // toggle edit mode
2809 MenuInputMode = TRUE;
2810 }
2811
2812 return (TRUE);
2813 }
2814
2815 ////////////////////////////////////////////////
2816 // Load/Save Touchup function
2817 // This function gets called each frame by DrawMenus
2818 ////////////////////////////////////////////////
2819
2820 static BOOL
MNU_DrawLoadSave(short game_num)2821 MNU_DrawLoadSave(short game_num)
2822 {
2823 // screen border
2824 rotatesprite(SS_XSTART << 16, SS_YSTART << 16, MZ, 0, pic_loadsavescreen,
2825 0, 0, MenuDrawFlags | ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1);
2826
2827 // description box
2828 rotatesprite((SD_XSTART) << 16, (SD_YSTART) << 16, MZ, 0, pic_savedescr,
2829 0, 0, MenuDrawFlags | ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1);
2830
2831 // cursor for text boxes
2832 rotatesprite((SD_XSTART + 3) << 16, (SD_LINE(game_num) + 1) << 16, MZ, 0, pic_loadsavecursor,
2833 0, 0, MenuDrawFlags | ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1);
2834
2835 return(TRUE);
2836 }
2837
2838 static char SaveGameInfo1[80];
2839 static char SaveGameInfo2[80];
2840
2841 BOOL
MNU_LoadSaveMove(UserCall UNUSED (call),MenuItem_p UNUSED (item))2842 MNU_LoadSaveMove(UserCall UNUSED(call), MenuItem_p UNUSED(item))
2843 {
2844 short i;
2845 short game_num;
2846 short tile;
2847 static short SaveGameEpisode, SaveGameLevel, SaveGameSkill;
2848 BOOL GotInput = FALSE;
2849
2850 if (!UsingMenus)
2851 return(TRUE);
2852
2853 game_num = currentmenu->cursor;
2854
2855 // read all descr first time through - LastSaveNum starts at 99
2856 if (LastSaveNum == 99)
2857 {
2858 memset(SaveGameDescr, '\0', sizeof(SaveGameDescr));
2859
2860 for (i = 0; i < 10; i++)
2861 LoadGameDescr(i, SaveGameDescr[i]);
2862 }
2863
2864 // cursor has moved - read header
2865 if (game_num != LastSaveNum)
2866 {
2867 screen_tile = LoadGameFullHeader(game_num, SaveGameDescr[game_num],
2868 &SaveGameLevel, &SaveGameSkill);
2869
2870 sprintf(SaveGameInfo1, "Level %d, Skill %d", SaveGameLevel, SaveGameSkill+1);
2871 SaveGameInfo2[0] = 0;
2872 }
2873
2874 if (QuickSaveMode)
2875 {
2876 QuickSaveMode = FALSE;
2877 MenuInputMode = TRUE;
2878 strcpy(BackupSaveGameDescr, SaveGameDescr[game_num]);
2879 KB_ClearKeysDown();
2880 KB_FlushKeyboardQueue();
2881 }
2882
2883 LastSaveNum = game_num;
2884
2885 // input mode check
2886 if (MenuInputMode)
2887 {
2888 MenuItem *item = ¤tmenu->items[currentmenu->cursor];
2889
2890 if (SavePrompt)
2891 {
2892 if (KB_KeyPressed(sc_Y) || KB_KeyPressed(sc_Enter))
2893 {
2894 KB_ClearKeyDown(sc_Y);
2895 KB_ClearKeyDown(sc_Enter);
2896 SavePrompt = FALSE;
2897 // use input
2898 item->custom();
2899 }
2900 else
2901 if (KB_KeyPressed(sc_N))
2902 {
2903 KB_ClearKeyDown(sc_N);
2904 strcpy(SaveGameDescr[game_num], BackupSaveGameDescr);
2905 SavePrompt = FALSE;
2906 MenuInputMode = FALSE;
2907 }
2908 }
2909 else
2910 // get input
2911 switch (MNU_InputString(SaveGameDescr[game_num], 114))
2912 {
2913 case -1: // Cancel Input (pressed ESC) or Err
2914 strcpy(SaveGameDescr[game_num], BackupSaveGameDescr);
2915 MenuInputMode = FALSE;
2916 KB_ClearKeysDown();
2917 break;
2918 case FALSE: // Input finished (RETURN)
2919 // no input
2920 if (SaveGameDescr[game_num][0] == '\0')
2921 {
2922 strcpy(SaveGameDescr[game_num], BackupSaveGameDescr);
2923 MenuInputMode = FALSE;
2924 }
2925 else
2926 {
2927 GotInput = TRUE;
2928 }
2929 KB_ClearKeyDown(sc_Enter);
2930 break;
2931 case TRUE: // Got input
2932 break;
2933 }
2934
2935 if (GotInput)
2936 {
2937 if (BackupSaveGameDescr[0])
2938 SavePrompt = TRUE;
2939
2940 if (!SavePrompt)
2941 {
2942 // use input
2943 item->custom();
2944 }
2945 }
2946 }
2947
2948 return (TRUE);
2949 }
2950
2951 BOOL
MNU_LoadSaveDraw(UserCall call,MenuItem_p UNUSED (item))2952 MNU_LoadSaveDraw(UserCall call, MenuItem_p UNUSED(item))
2953 {
2954 short i;
2955 short game_num;
2956 short tile;
2957
2958 if (call != uc_touchup)
2959 return(TRUE);
2960
2961 game_num = currentmenu->cursor;
2962
2963 // misc drawing
2964 MNU_DrawLoadSave(game_num);
2965
2966 // print game descriptions
2967 for (i = 0; i < 10; i++)
2968 {
2969 if (i == game_num && MenuInputMode && !SavePrompt)
2970 {
2971 static BOOL cur_show;
2972 char tmp[sizeof(SaveGameDescr[0])];
2973
2974 //cur_show ^= 1;
2975 cur_show = (totalclock & 32);
2976 if (cur_show)
2977 {
2978 // add a cursor to the end
2979 sprintf(tmp, "%s_", SaveGameDescr[i]);
2980 }
2981 else
2982 strcpy(tmp, SaveGameDescr[i]);
2983
2984 MNU_DrawString(SD_XSTART + 4, SD_YSTART + (i * SD_YOFF) + 2, tmp, 1, 16);
2985 }
2986 else
2987 if (SaveGameDescr[i][0] != '\0')
2988 {
2989 MNU_DrawString(SD_XSTART + 4, SD_YSTART + (i * SD_YOFF) + 2, SaveGameDescr[i], 1, 16);
2990 }
2991 }
2992
2993 if (screen_tile != -1)
2994 {
2995 // draw 160x100 save screen
2996 rotatesprite((SS_XSTART + SS_BORDER_SIZE) << 16, (SS_YSTART + SS_BORDER_SIZE) << 16, (1 << 16), 0 + 512, screen_tile,
2997 0, 0, MenuDrawFlags | ROTATE_SPRITE_CORNER | ROTATE_SPRITE_NON_MASK | ROTATE_SPRITE_YFLIP, 0, 0, xdim - 1, ydim - 1);
2998
2999 // draw info string
3000 MNU_DrawString(SS_XSTART + 13, SS_YSTART + 100 + 10, SaveGameInfo1, 1, 16);
3001 MNU_DrawString(SS_XSTART + 13, SS_YSTART + 100 + 18, SaveGameInfo2, 1, 16);
3002
3003 if (SavePrompt)
3004 {
3005 MNU_DrawString(SS_XSTART + SS_BORDER_SIZE + 5, SS_YSTART + SS_BORDER_SIZE + 47, "Overwrite previous", 1, 16);
3006 MNU_DrawString(SS_XSTART + SS_BORDER_SIZE + 5, SS_YSTART + SS_BORDER_SIZE + 47 + 12, " saved game (Y/N)", 1, 16);
3007 }
3008 }
3009 else
3010 {
3011 // draw 160x100 black pic
3012 rotatesprite((SS_XSTART + SS_BORDER_SIZE) << 16, (SS_YSTART + SS_BORDER_SIZE) << 16, (1 << 16), 0, pic_loadsavescreenbak,
3013 0, 0, MenuDrawFlags | ROTATE_SPRITE_CORNER | ROTATE_SPRITE_NON_MASK, 0, 0, xdim - 1, ydim - 1);
3014
3015 MNU_DrawString(SS_XSTART + SS_BORDER_SIZE + 60, SS_YSTART + SS_BORDER_SIZE + 47, "Empty", 1, 16);
3016 }
3017
3018
3019 return (TRUE);
3020 }
3021
3022 BOOL
MNU_ShareWareCheck(MenuItem * item)3023 MNU_ShareWareCheck(MenuItem *item)
3024 {
3025 if (SW_SHAREWARE) {
3026 SET(item->flags, mf_disabled);
3027 }
3028
3029 return (TRUE);
3030 }
3031
3032 BOOL
MNU_CheckUserMap(MenuItem * item)3033 MNU_CheckUserMap(MenuItem *item)
3034 {
3035 if (UserMapName[0] == '\0')
3036 RESET(item->flags, mf_disabled);
3037 else
3038 SET(item->flags, mf_disabled);
3039 return (TRUE);
3040 }
3041
3042 BOOL
MNU_ShareWareMessage(MenuItem * item)3043 MNU_ShareWareMessage(MenuItem *item)
3044 {
3045 char *extra_text;
3046 short w,h;
3047
3048 if (SW_SHAREWARE) {
3049 extra_text = "Be sure to call 800-3DREALMS today";
3050 MNU_MeasureString(extra_text, &w, &h);
3051 MNU_DrawString(TEXT_XCENTER(w), 110, extra_text, 1, 16);
3052 extra_text = "and order the game.";
3053 MNU_MeasureString(extra_text, &w, &h);
3054 MNU_DrawString(TEXT_XCENTER(w), 120, extra_text, 1, 16);
3055 extra_text = "You are only playing the first ";
3056 MNU_MeasureString(extra_text, &w, &h);
3057 MNU_DrawString(TEXT_XCENTER(w), 130, extra_text, 1, 16);
3058 extra_text = "four levels, and are missing most";
3059 MNU_MeasureString(extra_text, &w, &h);
3060 MNU_DrawString(TEXT_XCENTER(w), 140, extra_text, 1, 16);
3061 extra_text = "of the game, weapons and monsters.";
3062 MNU_MeasureString(extra_text, &w, &h);
3063 MNU_DrawString(TEXT_XCENTER(w), 150, extra_text, 1, 16);
3064 extra_text = "See the ordering information.";
3065 MNU_MeasureString(extra_text, &w, &h);
3066 MNU_DrawString(TEXT_XCENTER(w), 160, extra_text, 1, 16);
3067 SET(item->flags, mf_disabled);
3068 }
3069 return (TRUE);
3070 }
3071
3072 BOOL
MNU_SaveGameCheck(MenuItem * item)3073 MNU_SaveGameCheck(MenuItem *item)
3074 {
3075 extern BOOL InMenuLevel;
3076 extern BOOL DemoMode;
3077
3078 if (CommEnabled || CommPlayers > 1 || DemoMode)
3079 {
3080 SET(item->flags, mf_disabled);
3081 return(TRUE);
3082 }
3083
3084 if (InMenuLevel)
3085 SET(item->flags, mf_disabled);
3086 else
3087 {
3088 if (TEST(Player[myconnectindex].Flags, PF_DEAD))
3089 SET(item->flags, mf_disabled);
3090 else
3091 RESET(item->flags, mf_disabled);
3092 }
3093
3094
3095 return (TRUE);
3096 }
3097
3098 BOOL
MNU_LoadGameCheck(MenuItem * item)3099 MNU_LoadGameCheck(MenuItem *item)
3100 {
3101 if (CommEnabled || CommPlayers > 1)
3102 {
3103 SET(item->flags, mf_disabled);
3104 return(TRUE);
3105 }
3106
3107 return (TRUE);
3108 }
3109
3110 BOOL
MNU_StatCheck(MenuItem * item)3111 MNU_StatCheck(MenuItem *item)
3112 {
3113 if (CommEnabled || CommPlayers > 1)
3114 {
3115 SET(item->flags, mf_disabled);
3116 return(TRUE);
3117 }
3118
3119 return (TRUE);
3120 }
3121
3122 BOOL
MNU_HurtTeammateCheck(MenuItem * item)3123 MNU_HurtTeammateCheck(MenuItem *item)
3124 {
3125 switch (gs.NetGameType+1)
3126 {
3127 // deathmatch and deathmatch no respawn
3128 case MULTI_GAME_COMMBAT:
3129 case MULTI_GAME_COMMBAT_NO_RESPAWN:
3130 if (gs.NetTeamPlay)
3131 RESET(item->flags, mf_disabled);
3132 else
3133 SET(item->flags, mf_disabled);
3134 break;
3135 // co-op
3136 case MULTI_GAME_COOPERATIVE:
3137 RESET(item->flags, mf_disabled);
3138 break;
3139 }
3140
3141 return (TRUE);
3142 }
3143
3144 BOOL
MNU_TeamPlayCheck(MenuItem * item)3145 MNU_TeamPlayCheck(MenuItem *item)
3146 {
3147 switch (gs.NetGameType+1)
3148 {
3149 // co-op
3150 case MULTI_GAME_COOPERATIVE:
3151 SET(item->flags, mf_disabled);
3152 break;
3153 default:
3154 RESET(item->flags, mf_disabled);
3155 break;
3156 }
3157
3158 return (TRUE);
3159 }
3160
3161 BOOL
MNU_CoopPlayCheck(MenuItem * item)3162 MNU_CoopPlayCheck(MenuItem *item)
3163 {
3164 switch (gs.NetGameType+1)
3165 {
3166 // co-op
3167 case MULTI_GAME_COOPERATIVE:
3168 SET(item->flags, mf_disabled);
3169 break;
3170 default:
3171 RESET(item->flags, mf_disabled);
3172 break;
3173 }
3174
3175 return (TRUE);
3176 }
3177
3178 BOOL
MNU_TeamPlayChange(void)3179 MNU_TeamPlayChange(void)
3180 {
3181 // if team play changes then do a pre process again
3182 MNU_ItemPreProcess(currentmenu);
3183 return (TRUE);
3184 }
3185
3186 BOOL
MNU_TexFilterCheck(MenuItem * item)3187 MNU_TexFilterCheck(MenuItem *item)
3188 {
3189 if (bpp == 8)
3190 {
3191 SET(item->flags, mf_disabled);
3192 }
3193 else
3194 {
3195 RESET(item->flags, mf_disabled);
3196 }
3197
3198 return (TRUE);
3199 }
3200
3201 BOOL
MNU_MouseCheck(MenuItem * item)3202 MNU_MouseCheck(MenuItem *item)
3203 {
3204 if (!CONTROL_MousePresent)
3205 {
3206 SET(item->flags, mf_disabled);
3207 }
3208 else
3209 {
3210 RESET(item->flags, mf_disabled);
3211 }
3212
3213 return (TRUE);
3214 }
3215
3216 BOOL
MNU_JoystickCheck(MenuItem * item)3217 MNU_JoystickCheck(MenuItem *item)
3218 {
3219 if (!CONTROL_JoyPresent)
3220 {
3221 SET(item->flags, mf_disabled);
3222 }
3223 else
3224 {
3225 RESET(item->flags, mf_disabled);
3226 }
3227
3228 return (TRUE);
3229 }
3230
3231 // This is only called when Enter is pressed
3232 static BOOL
MNU_TryMusicInit(void)3233 MNU_TryMusicInit(void)
3234 {
3235 if (PlaySong(0, RedBookSong[Level], TRUE, FALSE))
3236 {
3237 if (currentmenu->cursor == 0)
3238 MNU_MusicCheck(¤tmenu->items[currentmenu->cursor+1]);
3239 }
3240
3241 return (TRUE);
3242 }
3243
3244 BOOL
MNU_MusicCheck(MenuItem * item)3245 MNU_MusicCheck(MenuItem *item)
3246 {
3247 if (SW_SHAREWARE) {
3248 if (MusicDevice < 0 || !MusicInitialized)
3249 {
3250 SET(item->flags, mf_disabled);
3251 }
3252 else
3253 {
3254 RESET(item->flags, mf_disabled);
3255 }
3256 } else {
3257 // Redbook audio stuff
3258 //JBF
3259 //if (!cdvalid)
3260 // {
3261 // SET(item->flags, mf_disabled); // Just don't let CD Redbook ever be invalid!
3262 // }
3263 //else
3264 {
3265 RESET(item->flags, mf_disabled);
3266 }
3267 }
3268
3269 return (TRUE);
3270 }
3271
3272 BOOL
MNU_FxCheck(MenuItem * item)3273 MNU_FxCheck(MenuItem *item)
3274 {
3275 if (FXDevice < 0 || !FxInitialized)
3276 {
3277 SET(item->flags, mf_disabled);
3278 }
3279 else
3280 {
3281 RESET(item->flags, mf_disabled);
3282 }
3283
3284 return (TRUE);
3285 }
3286
3287 BOOL
MNU_MusicFxCheck(MenuItem * item)3288 MNU_MusicFxCheck(MenuItem *item)
3289 {
3290 if (FXDevice < 0 && MusicDevice < 0)
3291 {
3292 SET(item->flags, mf_disabled);
3293 }
3294 else
3295 {
3296 RESET(item->flags, mf_disabled);
3297 }
3298
3299 return (TRUE);
3300 }
3301
3302 BOOL
MNU_ApplyVideoModeSettings(void)3303 MNU_ApplyVideoModeSettings(void)
3304 {
3305 int lastx, lasty, lastbpp, lastfs;
3306 int newx, newy, newbpp, newfs;
3307
3308 lastx = xdim; lasty = ydim; lastbpp = bpp; lastfs = fullscreen;
3309 newx = validresolutions[ slidersettings[sldr_videores] ].x;
3310 newy = validresolutions[ slidersettings[sldr_videores] ].y;
3311 newbpp = validbpps[ slidersettings[sldr_videobpp] ];
3312 newfs = buttonsettings[btn_videofs];
3313
3314 if (lastx == newx && lasty == newy && lastbpp == newbpp && lastfs == newfs) return FALSE;
3315
3316 if (setgamemode(newfs, newx, newy, newbpp))
3317 setgamemode(lastfs, lastx, lasty, lastbpp);
3318 else
3319 {
3320 ScreenMode = newfs;
3321 ScreenWidth = newx;
3322 ScreenHeight = newy;
3323 ScreenBPP = newbpp;
3324
3325 SetupAspectRatio();
3326 SetRedrawScreen(Player + myconnectindex);
3327 }
3328 MNU_ItemPreProcess(currentmenu);
3329 return FALSE;
3330 }
3331
3332 ////////////////////////////////////////////////
3333 // Do a toggle button
3334 ////////////////////////////////////////////////
3335 void
MNU_DoButton(MenuItem_p item,BOOL draw)3336 MNU_DoButton(MenuItem_p item, BOOL draw)
3337 {
3338 int x, y;
3339 BOOL state;
3340 int last_value;
3341 short shade = MENU_SHADE_DEFAULT;
3342 extern char LevelSong[];
3343 char *extra_text = NULL;
3344 PLAYERp pp = &Player[myconnectindex];
3345 int button_x,zero=0;
3346 int handle=0;
3347 extern BOOL MusicInitialized,FxInitialized;
3348
3349 button_x = OPT_XSIDE;
3350
3351 x = item->x;
3352 y = item->y;
3353
3354 if (TEST(item->flags, mf_disabled))
3355 {
3356 shade = MENU_SHADE_INACTIVE;
3357 }
3358
3359 if (!draw)
3360 {
3361 switch (item->button)
3362 {
3363 case btn_nuke:
3364 gs.NetNuke = state = buttonsettings[item->button];
3365 break;
3366 case btn_voxels:
3367 gs.Voxels = state = buttonsettings[item->button];
3368 break;
3369 case btn_stats:
3370 gs.Stats = state = buttonsettings[item->button];
3371 break;
3372 case btn_markers:
3373 gs.NetSpawnMarkers = state = buttonsettings[item->button];
3374 break;
3375 case btn_teamplay:
3376 gs.NetTeamPlay = state = buttonsettings[item->button];
3377 break;
3378 case btn_friendlyfire:
3379 gs.NetHurtTeammate = state = buttonsettings[item->button];
3380 break;
3381 case btn_crosshair:
3382 gs.Crosshair = state = buttonsettings[item->button];
3383 break;
3384 case btn_auto_aim:
3385 last_value = gs.AutoAim;
3386 gs.AutoAim = state = buttonsettings[item->button];
3387 if (gs.AutoAim != last_value)
3388 MenuButtonAutoAim = TRUE;
3389 break;
3390 case btn_messages:
3391 gs.Messages = state = buttonsettings[item->button];
3392 break;
3393 case btn_auto_run:
3394 last_value = gs.AutoRun;
3395 gs.AutoRun = state = buttonsettings[item->button];
3396 if (gs.AutoRun != last_value)
3397 MenuButtonAutoRun = TRUE;
3398 break;
3399 case btn_mouse_aim:
3400 last_value = gs.MouseAimingType;
3401 gs.MouseAimingType = state = buttonsettings[item->button];
3402 if (gs.MouseAimingType != last_value)
3403 {
3404 //RESET(pp->Flags, PF_MOUSE_AIMING_ON);
3405 //gs.MouseAimingOn = FALSE;
3406 }
3407 //extra_text = gs.MouseAimingType ? "Momentary" : "Toggle";
3408 break;
3409 case btn_mouse_invert:
3410 gs.MouseInvert = state = buttonsettings[item->button];
3411 break;
3412 // case btn_bobbing:
3413 // gs.Bobbing = state = buttonsettings[item->button];
3414 // break;
3415 case btn_sound:
3416
3417 if (!FxInitialized)
3418 break;
3419
3420 last_value = gs.FxOn;
3421 gs.FxOn = state = buttonsettings[item->button];
3422 if (gs.FxOn != last_value)
3423 {
3424 if (!gs.FxOn)
3425 StopFX();
3426 }
3427 break;
3428 case btn_music:
3429 last_value = gs.MusicOn;
3430 gs.MusicOn = state = buttonsettings[item->button];
3431 if (gs.MusicOn != last_value)
3432 {
3433 BOOL bak;
3434
3435 if (gs.MusicOn)
3436 {
3437 bak = DemoMode;
3438 PlaySong(LevelSong, RedBookSong[Level], TRUE, TRUE);
3439 DemoMode = bak;
3440 }
3441 else
3442 {
3443 bak = DemoMode;
3444 StopSong();
3445 DemoMode = bak;
3446
3447 if (SW_SHAREWARE)
3448 {
3449 handle = PlaySound(DIGI_NOLIKEMUSIC,&zero,&zero,&zero,v3df_none);
3450
3451 if (handle >= FX_Ok)
3452 while(FX_SoundActive(handle))
3453 handleevents();
3454 }
3455 }
3456 }
3457 break;
3458 case btn_talking:
3459 gs.Talking = state = buttonsettings[item->button];
3460 break;
3461 case btn_playcd:
3462 last_value = gs.PlayCD;
3463 gs.PlayCD = state = buttonsettings[item->button];
3464 break;
3465 case btn_ambience:
3466 last_value = gs.Ambient;
3467 gs.Ambient = state = buttonsettings[item->button];
3468 if (gs.Ambient != last_value)
3469 {
3470 if(!InMenuLevel)
3471 {
3472 if (gs.Ambient)
3473 StartAmbientSound();
3474 else
3475 StopAmbientSound();
3476 }
3477 }
3478 break;
3479 case btn_flipstereo:
3480 last_value = gs.FlipStereo;
3481 gs.FlipStereo = state = buttonsettings[item->button];
3482 if (gs.FlipStereo != last_value)
3483 FlipStereo();
3484 break;
3485 case btn_shadows:
3486 gs.Shadows = state = buttonsettings[item->button];
3487 break;
3488
3489 case btn_parental:
3490 if(gs.Password[0] != '\0' && gs.ParentalLock == TRUE)
3491 {
3492 if(passwordvalid)
3493 {
3494 state = buttonsettings[btn_parental] = gs.ParentalLock = FALSE;
3495 if (!InMenuLevel)
3496 JS_ToggleLockouts();
3497 } else
3498 {
3499 state = buttonsettings[btn_parental] = gs.ParentalLock = TRUE;
3500 MenuInputMode = TRUE;
3501 memset(MessageInputString, '\0', sizeof(MessageInputString));
3502 KB_ClearKeysDown();
3503 KB_FlushKeyboardQueue();
3504 }
3505 } else
3506 {
3507 gs.ParentalLock = state = buttonsettings[item->button];
3508 if (!InMenuLevel)
3509 JS_ToggleLockouts();
3510 }
3511 break;
3512
3513 case btn_videofs:
3514 {
3515 int lastx, lasty, lastbpp, newoffset, i;
3516
3517 state = buttonsettings[btn_videofs];
3518
3519 lastx = validresolutions[ slidersettings[sldr_videores] ].x;
3520 lasty = validresolutions[ slidersettings[sldr_videores] ].y;
3521 lastbpp = validbpps[ slidersettings[sldr_videobpp] ];
3522 UpdateValidModes(lastbpp, buttonsettings[btn_videofs]);
3523
3524 // check if the last bpp is still a valid choice
3525 for (i=0; i<numvalidbpps; i++)
3526 if (validbpps[i] == lastbpp) break;
3527 if (i == numvalidbpps)
3528 {
3529 // it wasn't
3530 slidersettings[sldr_videobpp] = 0;
3531 lastbpp = validbpps[0];
3532 UpdateValidModes(lastbpp, buttonsettings[btn_videofs]);
3533 }
3534 else
3535 slidersettings[sldr_videobpp] = i;
3536
3537 // find the nearest resolution to the one last selected
3538 newoffset = 0;
3539 for (i=0; i<numvalidresolutions; i++)
3540 {
3541 if (abs(lastx * lasty - validresolutions[i].x * validresolutions[i].y) <
3542 abs(lastx * lasty - validresolutions[newoffset].x * validresolutions[newoffset].y))
3543 newoffset = i;
3544 }
3545 slidersettings[sldr_videores] = newoffset;
3546 }
3547 break;
3548
3549 case btn_texfilter:
3550 {
3551 state = buttonsettings[item->button];
3552 #if USE_POLYMOST && USE_OPENGL
3553 if (state != (gltexfiltermode & 1))
3554 {
3555 // Preserve the mipmap level, toggling the nearest/linear filter.
3556 gltexfiltermode = (gltexfiltermode & ~1) | state;
3557 gltexapplyprops();
3558 }
3559 #endif
3560 }
3561 break;
3562
3563 case btn_joyaxis_invert:
3564 {
3565 int newscale;
3566
3567 state = buttonsettings[item->button];
3568 newscale = klabs(JoystickAnalogScale[JoystickAxisPage]);
3569 if (state)
3570 newscale = -newscale;
3571 JoystickAnalogScale[JoystickAxisPage] = newscale;
3572 CONTROL_SetAnalogAxisScale(JoystickAxisPage, newscale, controldevice_joystick);
3573 break;
3574 }
3575
3576 default:
3577 state = buttonsettings[item->button];
3578 break;
3579 }
3580 }
3581
3582 if (!draw)
3583 return;
3584
3585 switch (item->button)
3586 {
3587 case btn_mouse_aim:
3588 extra_text = gs.MouseAimingType ? "Momentary" : "Toggle";
3589 break;
3590 default: break;
3591 }
3592
3593
3594 state = buttonsettings[item->button];
3595
3596 // Draw the button
3597 if (item->text)
3598 {
3599 if (state)
3600 {
3601 // set
3602 rotatesprite(button_x << 16, y << 16, MZ, 0, pic_radiobuttn2, shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
3603 }
3604 else
3605 {
3606 // not set
3607 rotatesprite(button_x << 16, y << 16, MZ, 0, pic_radiobuttn1, shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
3608 }
3609
3610 MenuTextShade = shade;
3611 MNU_DrawString(x, y, item->text, MenuTextShade, 16);
3612
3613 if (extra_text)
3614 MNU_DrawString(OPT_XSIDE + tilesizx[pic_radiobuttn1] + 6, y, extra_text, MenuTextShade, 16);
3615 MenuTextShade = MENU_SHADE_DEFAULT;
3616 }
3617 else
3618 {
3619 if (state)
3620 rotatesprite(x << 16, y << 16, MZ, 0, pic_radiobuttn2, 2, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
3621 else
3622 rotatesprite(x << 16, y << 16, MZ, 0, pic_radiobuttn1, 2, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
3623
3624 x += tilesizx[pic_radiobuttn1] + 4;
3625
3626 // Draw the menu item text
3627 rotatesprite(x << 16, y << 16, MZ, 0, item->pic, 2, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
3628 }
3629
3630 }
3631
3632 //char *gametype[] = {"War [Respawn]","Cooperative","War [No Respawn]"};
3633 char *gametype[] = {"WangBang (spawn)","WangBang (no spawn)","Cooperative"};
3634 char *playercolors[] = {"Brown","Gray","Purple","Red","Yellow","Olive","Green","Blue"};
3635 char *monsterskills[] = {"No Monsters","Easy","Normal","Hard","Insane!"};
3636
3637 void
MNU_DoSlider(short dir,MenuItem_p item,BOOL draw)3638 MNU_DoSlider(short dir, MenuItem_p item, BOOL draw)
3639 {
3640 short offset, i, barwidth;
3641 int x, y, knobx;
3642 short shade = MENU_SHADE_DEFAULT;
3643 char *extra_text=NULL;
3644 char tmp_text[256];
3645
3646 memset(tmp_text,0,256);
3647
3648 if (TEST(item->flags, mf_disabled))
3649 {
3650 shade = MENU_SHADE_INACTIVE;
3651 dir = 0;
3652 }
3653
3654 switch (item->slider)
3655 {
3656 case sldr_mouse:
3657 barwidth = SLDR_MOUSESENSEMAX;
3658 offset = slidersettings[sldr_mouse] += dir;
3659
3660 if (TEST(item->flags, mf_disabled))
3661 break;
3662
3663 offset = max(offset, 0);
3664 offset = min(offset, SLDR_MOUSESENSEMAX-1);
3665
3666 slidersettings[sldr_mouse] = offset;
3667
3668 gs.MouseSpeed = offset * (MOUSE_SENS_MAX_VALUE/SLDR_MOUSESENSEMAX);
3669 CONTROL_SetMouseSensitivity(gs.MouseSpeed);
3670 break;
3671
3672 case sldr_sndfxvolume:
3673 barwidth = SLDR_SNDFXVOLMAX;
3674 offset = slidersettings[sldr_sndfxvolume] += dir;
3675
3676 if (TEST(item->flags, mf_disabled))
3677 break;
3678
3679 offset = max(offset, 0);
3680 offset = min(offset, SLDR_SNDFXVOLMAX-1);
3681
3682 slidersettings[sldr_sndfxvolume] = offset;
3683 gs.SoundVolume = FX_MIN + (offset * VOL_MUL);
3684 FX_SetVolume(gs.SoundVolume);
3685 break;
3686
3687 case sldr_musicvolume:
3688 barwidth = SLDR_MUSICVOLMAX;
3689 offset = slidersettings[sldr_musicvolume] += dir;
3690 if (TEST(item->flags, mf_disabled))
3691 break;
3692
3693 offset = max(offset, 0);
3694 offset = min(offset, SLDR_MUSICVOLMAX-1);
3695
3696 slidersettings[sldr_musicvolume] = offset;
3697 gs.MusicVolume = MUSIC_MIN + (offset * VOL_MUL);
3698 SetSongVolume(gs.MusicVolume);
3699 break;
3700
3701 case sldr_scrsize:
3702 {
3703 short bnum;
3704
3705 barwidth = SLDR_SCRSIZEMAX;
3706 slidersettings[sldr_scrsize] = gs.BorderNum;
3707 slidersettings[sldr_scrsize] -= dir;
3708 offset = slidersettings[sldr_scrsize];
3709
3710 if (TEST(item->flags, mf_disabled))
3711 break;
3712
3713 ////DSPRINTF(ds,"BorderNum %d",gs.BorderNum);
3714 //MONO_PRINT(ds);
3715
3716 offset = max(offset, 0);
3717 offset = min(offset, SLDR_SCRSIZEMAX - 1);
3718
3719 bnum = offset;
3720
3721 offset = (SLDR_SCRSIZEMAX-1) - offset;
3722 slidersettings[sldr_scrsize] = offset;
3723
3724 if (!BorderAdjust)
3725 gs.BorderNum = bnum;
3726
3727 SetBorder(&Player[myconnectindex], bnum);
3728
3729 break;
3730 }
3731
3732 case sldr_brightness:
3733 barwidth = SLDR_BRIGHTNESSMAX;
3734 offset = slidersettings[sldr_brightness] += dir;
3735
3736 if (TEST(item->flags, mf_disabled))
3737 break;
3738
3739 offset = max(offset, 0);
3740 offset = min(offset, SLDR_BRIGHTNESSMAX - 1);
3741 slidersettings[sldr_brightness] = offset;
3742
3743 if (gs.Brightness != offset)
3744 {
3745 gs.Brightness = offset;
3746 COVERsetbrightness(gs.Brightness,&palette_data[0][0]);
3747 }
3748 break;
3749
3750 case sldr_bordertile:
3751 barwidth = SLDR_BORDERTILEMAX;
3752 offset = slidersettings[sldr_bordertile] += dir;
3753
3754 if (TEST(item->flags, mf_disabled))
3755 break;
3756
3757 offset = max(offset, 0);
3758 offset = min(offset, SLDR_BORDERTILEMAX - 1);
3759 slidersettings[sldr_bordertile] = offset;
3760
3761 if (gs.BorderTile != offset)
3762 {
3763 gs.BorderTile = offset;
3764
3765 SetRedrawScreen(&Player[myconnectindex]);
3766 }
3767 break;
3768
3769 case sldr_panelscale:
3770 barwidth = SLDR_PANELSCALEMAX;
3771 offset = slidersettings[sldr_panelscale] += dir;
3772
3773 if (TEST(item->flags, mf_disabled))
3774 break;
3775
3776 offset = max(offset, 0);
3777 offset = min(offset, SLDR_PANELSCALEMAX - 1);
3778 slidersettings[sldr_panelscale] = offset;
3779
3780 if (gs.PanelScale != offset+1)
3781 {
3782 gs.PanelScale = offset+1;
3783 PanelScale = gs.PanelScale<<13;
3784 }
3785 break;
3786
3787 case sldr_gametype:
3788 barwidth = SLDR_GAMETYPEMAX;
3789 offset = slidersettings[sldr_gametype] += dir;
3790
3791 if (TEST(item->flags, mf_disabled))
3792 break;
3793
3794 offset = max(offset, 0);
3795 offset = min(offset, SLDR_GAMETYPEMAX - 1);
3796 slidersettings[sldr_gametype] = offset;
3797
3798 extra_text = gametype[offset];
3799 MNU_DrawString(OPT_XSIDE, item->y, extra_text, 1, 16);
3800 gs.NetGameType = offset;
3801 // friendly fire menu
3802 MNU_ItemPreProcess(currentmenu);
3803 break;
3804
3805 case sldr_netlevel:
3806 barwidth = SLDR_NETLEVELMAX;
3807 offset = slidersettings[sldr_netlevel] += dir;
3808
3809 if (TEST(item->flags, mf_disabled))
3810 break;
3811
3812 offset = max(offset, 0);
3813 offset = min(offset, SLDR_NETLEVELMAX - 1);
3814 slidersettings[sldr_netlevel] = offset;
3815
3816 // Show the currently selected level on next line
3817 //extra_text = MNU_LevelName[offset];
3818 //MNU_DrawString(OPT_XS, item->y+10, extra_text, 1, 16);
3819 sprintf(tmp_text, "L%02d: %s", offset+1, LevelInfo[offset+1].Description);
3820 MNU_DrawString(OPT_XS, item->y+10, tmp_text, 1, 16);
3821 gs.NetLevel = offset;
3822 break;
3823
3824 case sldr_monsters:
3825 barwidth = SLDR_MONSTERSMAX;
3826 offset = slidersettings[sldr_monsters] += dir;
3827
3828 if (TEST(item->flags, mf_disabled))
3829 break;
3830
3831 offset = max(offset, 0);
3832 offset = min(offset, SLDR_MONSTERSMAX - 1);
3833 slidersettings[sldr_monsters] = offset;
3834
3835 extra_text = monsterskills[offset];
3836 MNU_DrawString(OPT_XSIDE+54, item->y, extra_text, 1, 16);
3837 gs.NetMonsters = offset;
3838 break;
3839
3840 case sldr_killlimit:
3841 barwidth = SLDR_KILLLIMITMAX;
3842 offset = slidersettings[sldr_killlimit] += dir;
3843
3844 if (TEST(item->flags, mf_disabled))
3845 break;
3846
3847 offset = max(offset, 0);
3848 offset = min(offset, SLDR_KILLLIMITMAX - 1);
3849 slidersettings[sldr_killlimit] = offset;
3850
3851 if(offset == 0)
3852 {
3853 strcpy(tmp_text,"Infinite\n");
3854 }
3855 else
3856 {
3857 sprintf(tmp_text,"%d",offset*10);
3858 //itoa(offset*10,tmp_text,10);
3859 }
3860 MNU_DrawString(OPT_XSIDE+101, item->y, tmp_text, 1, 16);
3861 gs.NetKillLimit = offset;
3862 break;
3863
3864 case sldr_timelimit:
3865 barwidth = SLDR_TIMELIMITMAX;
3866 offset = slidersettings[sldr_timelimit] += dir;
3867
3868 if (TEST(item->flags, mf_disabled))
3869 break;
3870
3871 offset = max(offset, 0);
3872 offset = min(offset, SLDR_TIMELIMITMAX - 1);
3873 slidersettings[sldr_timelimit] = offset;
3874
3875 if(offset == 0)
3876 {
3877 strcpy(tmp_text,"Infinite\n");
3878 }
3879 else
3880 {
3881 sprintf(tmp_text,"%d Minutes\n",TimeLimitTable[offset]);
3882 }
3883
3884 MNU_DrawString(OPT_XSIDE+86, item->y, tmp_text, 1, 16);
3885 gs.NetTimeLimit = offset;
3886 break;
3887
3888 case sldr_playercolor:
3889 barwidth = SLDR_PLAYERCOLORMAX;
3890 offset = slidersettings[sldr_playercolor] += dir;
3891
3892 if (TEST(item->flags, mf_disabled))
3893 break;
3894
3895 offset = max(offset, 0);
3896 offset = min(offset, SLDR_PLAYERCOLORMAX - 1);
3897 slidersettings[sldr_playercolor] = offset;
3898
3899 extra_text = playercolors[offset];
3900 MNU_DrawString(OPT_XSIDE+78, item->y, extra_text, 1, PALETTE_PLAYER0+offset);
3901 SendMulitNameChange(NULL, offset);
3902 break;
3903
3904 case sldr_videores:
3905 {
3906 offset = max(0,min(slidersettings[sldr_videores] + dir, numvalidresolutions-1));
3907 barwidth = numvalidresolutions;
3908
3909 if (TEST(item->flags, mf_disabled))
3910 break;
3911
3912 slidersettings[sldr_videores] = offset;
3913
3914 sprintf(tmp_text, "%dx%d", validresolutions[offset].x, validresolutions[offset].y);
3915 MNU_DrawString(OPT_XSIDE, item->y+OPT_YINC, tmp_text, 1, 16);
3916 } break;
3917
3918 case sldr_videobpp:
3919 {
3920 offset = max(0,min(slidersettings[sldr_videobpp] + dir, numvalidbpps-1));
3921 barwidth = numvalidbpps;
3922
3923 if (TEST(item->flags, mf_disabled))
3924 break;
3925
3926 if (slidersettings[sldr_videobpp] != offset) {
3927 int lastx, lasty, newoffset, i;
3928
3929 slidersettings[sldr_videobpp] = offset;
3930
3931 // find the nearest resolution to the one last selected
3932 lastx = validresolutions[ slidersettings[sldr_videores] ].x;
3933 lasty = validresolutions[ slidersettings[sldr_videores] ].y;
3934 UpdateValidModes(validbpps[offset], buttonsettings[btn_videofs]);
3935 newoffset = 0;
3936 for (i=0; i<numvalidresolutions; i++) {
3937 if (abs(lastx * lasty - validresolutions[i].x * validresolutions[i].y) <
3938 abs(lastx * lasty - validresolutions[newoffset].x * validresolutions[newoffset].y))
3939 newoffset = i;
3940 }
3941 slidersettings[sldr_videores] = newoffset;
3942 }
3943
3944 sprintf(tmp_text, "%d bpp", validbpps[offset]);
3945 MNU_DrawString(OPT_XSIDE+tilesizx[pic_slidelend]+tilesizx[pic_sliderend]+(barwidth+1)*tilesizx[pic_slidebar], item->y, tmp_text, 1, 16);
3946 } break;
3947
3948 case sldr_mousescalex:
3949 case sldr_mousescaley:
3950 barwidth = 8+1+8;
3951 offset = slidersettings[item->slider] + dir;
3952
3953 if (TEST(item->flags, mf_disabled))
3954 break;
3955
3956 offset = max(offset, 0);
3957 offset = min(offset, barwidth-1);
3958
3959 if (slidersettings[item->slider] != offset)
3960 {
3961 slidersettings[item->slider] = offset;
3962 MouseAnalogScale[item->slider - sldr_mousescalex] = offset<<13;
3963 CONTROL_SetAnalogAxisScale(item->slider - sldr_mousescalex, offset<<13, controldevice_mouse);
3964 }
3965
3966 sprintf(tmp_text, "%.2f", (float)(slidersettings[item->slider]<<13) / 65535.f);
3967 MNU_DrawSmallString(OPT_XSIDE+tilesizx[pic_slidelend]+tilesizx[pic_sliderend]+(MAX_SLDR_WIDTH+1)*tilesizx[pic_slidebar], item->y+4, tmp_text, 1, 16);
3968 break;
3969
3970 case sldr_joyaxisscale:
3971 barwidth = 8+1+8;
3972 offset = slidersettings[item->slider] + dir;
3973
3974 if (TEST(item->flags, mf_disabled))
3975 break;
3976
3977 offset = max(offset, 0);
3978 offset = min(offset, barwidth-1);
3979
3980 if (slidersettings[item->slider] != offset)
3981 {
3982 int newscale;
3983
3984 slidersettings[item->slider] = offset;
3985 newscale = offset<<13;
3986 if (buttonsettings[btn_joyaxis_invert])
3987 newscale = -newscale;
3988 JoystickAnalogScale[JoystickAxisPage] = newscale;
3989 CONTROL_SetAnalogAxisScale(JoystickAxisPage, newscale, controldevice_joystick);
3990 }
3991
3992 sprintf(tmp_text, "%.2f", (float)(slidersettings[item->slider]<<13) / 65535.f);
3993 MNU_DrawSmallString(OPT_XSIDE+tilesizx[pic_slidelend]+tilesizx[pic_sliderend]+(MAX_SLDR_WIDTH+1)*tilesizx[pic_slidebar], item->y+4, tmp_text, 1, 16);
3994 break;
3995
3996 case sldr_joyaxisanalog:
3997 {
3998 const char *p;
3999
4000 barwidth = MNU_ControlAxisOffset(analog_maxtype);
4001 offset = slidersettings[item->slider] + dir;
4002
4003 if (TEST(item->flags, mf_disabled))
4004 break;
4005
4006 offset = max(offset, 0);
4007 offset = min(offset, barwidth-1);
4008
4009 if (slidersettings[item->slider] != offset)
4010 {
4011 slidersettings[item->slider] = offset;
4012 JoystickAnalogAxes[JoystickAxisPage] = MNU_ControlAxisNum(offset);
4013 CONTROL_MapAnalogAxis(JoystickAxisPage, MNU_ControlAxisNum(offset), controldevice_joystick);
4014 }
4015
4016 p = CONFIG_AnalogNumToName(MNU_ControlAxisNum(offset));
4017 if (!p)
4018 {
4019 p = "-";
4020 }
4021 else
4022 {
4023 // Skip past the "analog_" prefix.
4024 while (*p != 0 && *p != '_') p++;
4025 if (*p == '_') p++;
4026 }
4027 MNU_DrawSmallString(OPT_XSIDE+tilesizx[pic_slidelend]+tilesizx[pic_sliderend]+(barwidth+1)*tilesizx[pic_slidebar], item->y+4, p, 1, 16);
4028 }
4029 break;
4030
4031 case sldr_joyaxisdead:
4032 case sldr_joyaxissatur:
4033 barwidth = (32768>>10)+1;
4034 offset = slidersettings[item->slider] + dir;
4035
4036 if (TEST(item->flags, mf_disabled))
4037 break;
4038
4039 offset = max(offset, 0);
4040 offset = min(offset, barwidth-1);
4041
4042 if (slidersettings[item->slider] != offset)
4043 {
4044 slidersettings[item->slider] = offset;
4045 if (item->slider == sldr_joyaxisdead)
4046 {
4047 JoystickAnalogDead[JoystickAxisPage] = min((offset<<10), 32767);
4048 CONTROL_SetJoyAxisDead(JoystickAxisPage, JoystickAnalogDead[JoystickAxisPage]);
4049 }
4050 else
4051 {
4052 JoystickAnalogSaturate[JoystickAxisPage] = min((offset<<10), 32767);
4053 CONTROL_SetJoyAxisSaturate(JoystickAxisPage, JoystickAnalogSaturate[JoystickAxisPage]);
4054 }
4055 }
4056
4057 sprintf(tmp_text, "%.2f", (float)(slidersettings[item->slider]<<10) / 32767.f);
4058 MNU_DrawSmallString(OPT_XSIDE+tilesizx[pic_slidelend]+tilesizx[pic_sliderend]+(MAX_SLDR_WIDTH+1)*tilesizx[pic_slidebar], item->y+4, tmp_text, 1, 16);
4059 break;
4060
4061 default:
4062 return;
4063 }
4064
4065 if (!draw)
4066 return;
4067
4068 // Now draw it
4069 item++;
4070 x = item->x;
4071 y = item->y;
4072
4073 // Draw the left end cap of the bar
4074 rotatesprite(x << 16, y << 16, MZ, 0, pic_slidelend, shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
4075
4076 x += tilesizx[pic_slidelend];
4077 knobx = x;
4078
4079 // Draw the in between sections
4080 for (i = 0; i < min(barwidth,MAX_SLDR_WIDTH); i++)
4081 {
4082 rotatesprite(x << 16, y << 16, MZ, 0, pic_slidebar, shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
4083 x += tilesizx[pic_slidebar];
4084 }
4085
4086 // Draw the right end cap
4087 rotatesprite(x << 16, y << 16, MZ, 0, pic_sliderend, shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
4088
4089 // Draw the knob, compressing the X coordinate if the bar is too wide
4090 if (barwidth > MAX_SLDR_WIDTH)
4091 {
4092 knobx += offset * (MAX_SLDR_WIDTH*tilesizx[pic_slidebar]-tilesizx[pic_sliderknob]) / (barwidth-1);
4093 }
4094 else
4095 {
4096 knobx += tilesizx[pic_slidebar] * offset;
4097 }
4098 rotatesprite(knobx << 16, (y + 2) << 16, MZ, 0, pic_sliderknob, shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
4099 }
4100
4101 ////////////////////////////////////////////////
4102 // Start up menu array
4103 ////////////////////////////////////////////////
4104 static void
MNU_SetupMenu(void)4105 MNU_SetupMenu(void)
4106 {
4107 MenuGroup *rootmenu;
4108
4109 static MenuGroup *rootmenulist[] =
4110 {
4111 &maingroup,
4112 &SaveGameGroup,
4113 &LoadGameGroup,
4114 &soundgroup,
4115 &optiongroup,
4116 &quickloadgroup,
4117 &quitgroup,
4118 &ordergroup,
4119 &episodegroup,
4120 };
4121
4122 rootmenu = rootmenulist[ControlPanelType];
4123 ASSERT(ControlPanelType < ct_max);
4124
4125 menuarrayptr = 0;
4126 menuarray[0] = currentmenu = rootmenu;
4127
4128 // Get currently held input state and invalidate it.
4129 CONTROL_GetUserInput(&mnu_input);
4130 CONTROL_ClearUserInput(&mnu_input);
4131
4132 mnu_input_buffered.button0 = mnu_input_buffered.button1 = FALSE;
4133 mnu_input_buffered.dir = dir_None;
4134 order_input_buffered.button0 = order_input_buffered.button1 = FALSE;
4135 order_input_buffered.dir = dir_None;
4136 ResetKeys();
4137
4138 // custom cust_callback starts out as null
4139 cust_callback = NULL;
4140
4141 // for QuitCustom and QuickLoadCustom
4142 if (currentmenu->items == NULL)
4143 {
4144 if (currentmenu->draw_custom)
4145 currentmenu->draw_custom(uc_setup, NULL);
4146 }
4147
4148 if(ControlPanelType == ct_mainmenu)
4149 currentmenu->cursor = 0;
4150
4151 // disable any items necessary
4152 MNU_ItemPreProcess(currentmenu);
4153 }
4154
4155 ////////////////////////////////////////////////
4156 // Draw an item
4157 ////////////////////////////////////////////////
4158 /*
4159 static void
4160 MNU_ClearFlags(MenuGroup * node)
4161 {
4162 MenuItem *i;
4163
4164 if (!node->items)
4165 return;
4166
4167 for (i = node->items; i->type != mt_none; i++)
4168 {
4169 i->flags &= ~MenuSelectFlags;
4170 if (i->child)
4171 MNU_ClearFlags((MenuGroup *) i->child);
4172 }
4173 }
4174 */
4175 ////////////////////////////////////////////////
4176 // Pop a group off the menu stack
4177 ////////////////////////////////////////////////
4178 static void
MNU_PopGroup(void)4179 MNU_PopGroup(void)
4180 {
4181 if (!menuarrayptr)
4182 return;
4183
4184 currentmenu = menuarray[--menuarrayptr];
4185
4186 SetFragBar(Player + myconnectindex);
4187 //PanelRefresh(Player + myconnectindex);
4188 }
4189
4190 ////////////////////////////////////////////////
4191 // Push a group on to the menu stack
4192 ////////////////////////////////////////////////
4193 static void
MNU_PushGroup(MenuGroup * node)4194 MNU_PushGroup(MenuGroup * node)
4195 {
4196 if (menuarrayptr == MaxLayers - 1)
4197 return;
4198
4199 currentmenu = menuarray[++menuarrayptr] = node;
4200
4201 SetFragBar(Player + myconnectindex);
4202 }
4203
4204 ////////////////////////////////////////////////
4205 // Setup a new menu subgroup
4206 ////////////////////////////////////////////////
4207 static void
MNU_SetupGroup(void)4208 MNU_SetupGroup(void)
4209 {
4210 MNU_SelectItem(currentmenu, currentmenu->cursor, FALSE);
4211 MNU_DrawMenu();
4212 }
4213
4214 static VOID
MNU_ItemPreProcess(MenuGroup * group)4215 MNU_ItemPreProcess(MenuGroup * group)
4216 {
4217 MenuItem *item;
4218
4219 if (!group->items)
4220 return;
4221
4222 // process all items when going down a level
4223 // to see if anything is disabled
4224 for (item = group->items; item->type != mt_none; item++)
4225 {
4226 if (item->preprocess)
4227 item->preprocess(item);
4228 }
4229 }
4230
4231 VOID
MNU_ItemPostProcess(MenuGroup * group)4232 MNU_ItemPostProcess(MenuGroup * group)
4233 {
4234 MenuItem *item;
4235 int zero = 0;
4236
4237 if (!group->items)
4238 return;
4239
4240 item = ¤tmenu->items[currentmenu->cursor];
4241
4242 if (item->postprocess)
4243 {
4244 item->postprocess(item);
4245 }
4246 }
4247
4248 ////////////////////////////////////////////////
4249 // Go to next menu subgroup
4250 ////////////////////////////////////////////////
4251 static void
MNU_DownLevel(MenuGroup * group)4252 MNU_DownLevel(MenuGroup * group)
4253 {
4254
4255 if (!group)
4256 {
4257 TerminateGame();
4258 printf("MNU_DownLevel() - NULL card\n");
4259 exit(0);
4260 }
4261
4262 MNU_PushGroup(group);
4263
4264 if (group->items == NULL)
4265 {
4266 if (group->draw_custom && group->draw_custom(uc_setup, NULL))
4267 MNU_PopGroup();
4268 }
4269
4270 MNU_ItemPreProcess(currentmenu);
4271
4272 MNU_SetupGroup();
4273
4274 SetRedrawScreen(&Player[myconnectindex]);
4275 }
4276
4277 ////////////////////////////////////////////////
4278 // Go to previous menu subgroup
4279 ////////////////////////////////////////////////
4280 static void
MNU_UpLevel(void)4281 MNU_UpLevel(void)
4282 {
4283 int zero = 0;
4284 static int handle1=0;
4285 // if run out of menus then EXIT
4286 if (!menuarrayptr)
4287 {
4288 if(!FX_SoundActive(handle1))
4289 handle1 = PlaySound(DIGI_STARCLINK,&zero,&zero,&zero,v3df_dontpan);
4290 ExitMenus();
4291 return;
4292 }
4293
4294 if (currentmenu->items)
4295 currentmenu->items[currentmenu->cursor].flags &= ~mf_selected;
4296 MNU_PopGroup();
4297 MNU_SetupGroup();
4298
4299 SetRedrawScreen(&Player[myconnectindex]);
4300 }
4301
4302 ////////////////////////////////////////////////
4303 // Do a menu item action
4304 ////////////////////////////////////////////////
4305 static void
MNU_DoItem(void)4306 MNU_DoItem(void)
4307 {
4308 MenuItem *item;
4309
4310 item = ¤tmenu->items[currentmenu->cursor];
4311 if (!item) return;
4312
4313 if (TEST(item->flags, mf_disabled))
4314 {
4315 // Try to process again
4316 if (item->preprocess)
4317 item->preprocess(item);
4318
4319 // Check once more
4320 if (TEST(item->flags, mf_disabled))
4321 return;
4322 }
4323
4324 switch (item->type)
4325 {
4326 case mt_option:
4327 if (item->custom != NULL)
4328 item->custom();
4329 break;
4330 case mt_button:
4331 MNU_PushItem(item, FALSE);
4332 if (item->custom != NULL)
4333 item->custom();
4334 break;
4335 case mt_layer:
4336 if (item->custom != NULL)
4337 item->custom();
4338 MNU_DownLevel(item->child);
4339 break;
4340 default: break;
4341 }
4342 }
4343
4344 ////////////////////////////////////////////////
4345 // Draw an item icon or cursor
4346 ////////////////////////////////////////////////
4347 static void
MNU_DrawItemIcon(MenuItem * item)4348 MNU_DrawItemIcon(MenuItem * item)
4349 {
4350 //void BorderRefreshClip(PLAYERp pp, short x, short y, short x2, short y2);
4351 int x = item->x, y = item->y;
4352 int scale = MZ;
4353 short w,h;
4354
4355 if (item->text)
4356 {
4357 scale /= 2;
4358 x -= mulscale17(tilesizx[pic_yinyang],scale) + 2;
4359 y += 4;
4360 }
4361 else
4362 {
4363 scale -= (1<<13);
4364 x -= ((tilesizx[pic_yinyang]) / 2) - 3;
4365 y += 8;
4366 }
4367
4368 rotatesprite(x << 16, y << 16,
4369 scale, 0, pic_yinyang, item->shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
4370
4371 SetRedrawScreen(&Player[myconnectindex]);
4372 //BorderRefreshClip(&Player[myconnectindex], x - 24, y - 24, x + 24, y + 24);
4373 }
4374
4375 ////////////////////////////////////////////////
4376 // Draw an item
4377 ////////////////////////////////////////////////
4378 static void
MNU_DrawItem(MenuItem * item)4379 MNU_DrawItem(MenuItem * item)
4380 {
4381 char *ptr;
4382 short px, py;
4383
4384 MNU_ItemPostProcess(currentmenu); // Put this in so things can be drawn on item select
4385
4386 if (!item->pic)
4387 return;
4388
4389 MNU_DrawItemIcon(item);
4390
4391 // if text string skip this part
4392 if (item->text)
4393 return;
4394
4395 if (TEST(item->flags, mf_selected) && !TEST(item->flags, mf_disabled))
4396 {
4397 // Highlighted
4398 if (item->type != mt_button)
4399 rotatesprite(item->x << 16, item->y << 16, MZ, 0, item->pic,
4400 -30 + STD_RANDOM_RANGE(50), PALETTE_MENU_HIGHLIGHT, MenuDrawFlags,
4401 0, 0, xdim - 1, ydim - 1);
4402 else
4403 rotatesprite((item->x + tilesizx[pic_radiobuttn1] + 4) << 16, item->y << 16,
4404 MZ, 0, item->pic, item->shade, PALETTE_MENU_HIGHLIGHT, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
4405 }
4406 else
4407 {
4408 // Un highlighted
4409 if (item->type != mt_button)
4410 rotatesprite(item->x << 16, item->y << 16, MZ, 0, item->pic,
4411 item->shade, 0, MenuDrawFlags, 0, 319, 199, 0);
4412 else
4413 rotatesprite((item->x + tilesizx[pic_radiobuttn1] + 4) << 16, item->y << 16,
4414 MZ, 0, item->pic, item->shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
4415 }
4416 }
4417
4418 ////////////////////////////////////////////////
4419 // Draw the menu contents
4420 ////////////////////////////////////////////////
4421 static void
MNU_DrawMenuContents(void)4422 MNU_DrawMenuContents(void)
4423 {
4424 MenuItem *item;
4425 short w,h;
4426
4427 ASSERT(currentmenu != NULL);
4428
4429 if (currentmenu->text)
4430 {
4431 // Draw the backdrop bar
4432 rotatesprite(10 << 16, (currentmenu->y-3) << 16, MZ, 0, 2427,
4433 currentmenu->shade, 0, MenuDrawFlags|ROTATE_SPRITE_CORNER, 0, 0, xdim - 1, ydim - 1);
4434 MNU_MeasureStringLarge(currentmenu->text, &w, &h);
4435 MNU_DrawString(TEXT_XCENTER(w), currentmenu->y, currentmenu->text, 1, 16);
4436 }
4437 else
4438 if (currentmenu->titlepic)
4439 {
4440 rotatesprite(currentmenu->x << 16, currentmenu->y << 16, MZ, 0, currentmenu->titlepic,
4441 currentmenu->shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
4442 }
4443
4444 if (!currentmenu->items)
4445 return;
4446
4447 for (item = currentmenu->items; item->type != mt_none; item++)
4448 {
4449 if (item->pic)
4450 {
4451 if (item->type == mt_button)
4452 {
4453 // all drawing done here also
4454 MNU_DoButton(item, TRUE);
4455 }
4456 else
4457 {
4458 if (item->text)
4459 {
4460 if (TEST(item->flags, mf_disabled))
4461 MenuTextShade = MENU_SHADE_INACTIVE;
4462 MNU_DrawString(item->x, item->y, item->text, MenuTextShade, 16);
4463 MenuTextShade = MENU_SHADE_DEFAULT;
4464 }
4465 else
4466 {
4467 rotatesprite(item->x << 16, item->y << 16, MZ, 0, item->pic,
4468 item->shade, 0, MenuDrawFlags, 0, 0, xdim - 1, ydim - 1);
4469 }
4470 }
4471 }
4472
4473 // Is there a slider attached to this item? Draw it.
4474 if (item->type == mt_slider)
4475 MNU_DoSlider(0, item, TRUE);
4476 }
4477
4478 MNU_SelectItem(currentmenu, currentmenu->cursor, TRUE);
4479
4480 if (currentmenu->draw_custom)
4481 currentmenu->draw_custom(uc_touchup, NULL);
4482 }
4483
4484 ////////////////////////////////////////////////
4485 // Draw the menu
4486 ////////////////////////////////////////////////
4487 void
MNU_DrawMenu(void)4488 MNU_DrawMenu(void)
4489 {
4490 if (cust_callback != NULL)
4491 {
4492 cust_callback(cust_callback_call, cust_callback_item);
4493 return;
4494 }
4495
4496 if (currentmenu->items || currentmenu->titlepic)
4497 {
4498 MNU_DrawMenuContents();
4499 }
4500 }
4501
4502 ////////////////////////////////////////////////
4503 // Select a menu item
4504 ////////////////////////////////////////////////
4505 void
MNU_SelectItem(MenuGroup * group,short index,BOOL draw)4506 MNU_SelectItem(MenuGroup * group, short index, BOOL draw)
4507 {
4508 MenuItem *item;
4509
4510 if (index != group->cursor)
4511 {
4512 item = &group->items[group->cursor];
4513 item->flags &= ~mf_selected;
4514 if (draw)
4515 MNU_DrawItem(item);
4516 }
4517
4518 group->cursor = index;
4519 item = &group->items[group->cursor];
4520 item->flags |= mf_selected;
4521 if (draw)
4522 MNU_DrawItem(item);
4523 }
4524
4525 ////////////////////////////////////////////////
4526 // Toggle a menu radio button on/off
4527 ////////////////////////////////////////////////
4528 static void
MNU_PushItem(MenuItem * item,BOOL draw)4529 MNU_PushItem(MenuItem * item, BOOL draw)
4530 {
4531 if (item->type != mt_button)
4532 return;
4533
4534 buttonsettings[item->button] ^= 1;
4535
4536 // if (draw)
4537 MNU_DoButton(item, draw);
4538 }
4539
4540 ////////////////////////////////////////////////
4541 // Go to next item on menu
4542 ////////////////////////////////////////////////
4543 static void
MNU_NextItem(void)4544 MNU_NextItem(void)
4545 {
4546 MenuTag type;
4547 MenuFlags flag;
4548
4549 type = currentmenu->items[currentmenu->cursor + 1].type;
4550 flag = currentmenu->items[currentmenu->cursor + 1].flags;
4551
4552 if (type == mt_none)
4553 MNU_SelectItem(currentmenu, 0, FALSE);
4554 else
4555 MNU_SelectItem(currentmenu, currentmenu->cursor + 1, FALSE);
4556
4557 type = currentmenu->items[currentmenu->cursor].type;
4558 flag = currentmenu->items[currentmenu->cursor].flags;
4559
4560 if (type == mt_inert || flag == mf_disabled)
4561 MNU_NextItem();
4562 }
4563
4564 ////////////////////////////////////////////////
4565 // Go to previous item on menu
4566 ////////////////////////////////////////////////
4567 static void
MNU_PrevItem(void)4568 MNU_PrevItem(void)
4569 {
4570 MenuTag type;
4571 MenuFlags flag;
4572
4573 if (!currentmenu->cursor)
4574 while (currentmenu->items[++currentmenu->cursor].type != mt_none);
4575
4576 MNU_SelectItem(currentmenu, currentmenu->cursor - 1, FALSE);
4577
4578 type = currentmenu->items[currentmenu->cursor].type;
4579 flag = currentmenu->items[currentmenu->cursor].flags;
4580 if (type == mt_inert || flag == mf_disabled)
4581 MNU_PrevItem();
4582 }
4583
4584 ////////////////////////////////////////////////
4585 // Find hotkey press on current menu, if any.
4586 ////////////////////////////////////////////////
4587 static BOOL
MNU_DoHotkey(void)4588 MNU_DoHotkey(void)
4589 {
4590 MenuItem_p item;
4591 short index;
4592
4593 if (!currentmenu->items) return FALSE;
4594
4595 index = 0;
4596 for (item = currentmenu->items; item->type != mt_none; item++)
4597 {
4598 if (KEY_PRESSED(item->hotkey) && item->hotkey != 0)
4599 {
4600 MNU_SelectItem(currentmenu, index, FALSE);
4601 return (TRUE);
4602 }
4603 index++;
4604 }
4605
4606 return (FALSE);
4607 }
4608
4609 ////////////////////////////////////////////////
4610 // Setup Menus
4611 ////////////////////////////////////////////////
4612 void
SetupMenu(void)4613 SetupMenu(void)
4614 {
4615 if (!UsingMenus && !ConPanel) // Doing this check for multiplay
4616 // menus
4617 {
4618 MNU_SetupMenu();
4619
4620 // Clear the previous ESC key press
4621 KEY_PRESSED(KEYSC_ESC) = FALSE;
4622 UsingMenus = TRUE;
4623 }
4624 }
4625
4626 ////////////////////////////////////////////////
4627 // Setup the main menu
4628 // This function will not loop if in modem
4629 // or network game, otherwise it stops the
4630 // game play until user finished in menus.
4631 ////////////////////////////////////////////////
4632 #define MNU_SENSITIVITY 10 // The menu's mouse sensitivity, should be real low
4633
MNU_DoMenu(CTLType UNUSED (type),PLAYERp UNUSED (pp))4634 void MNU_DoMenu( CTLType UNUSED(type), PLAYERp UNUSED(pp) )
4635 {
4636 BOOL resetitem;
4637 UCHAR key;
4638 int zero = 0;
4639 static int handle2 = 0;
4640 static int limitmove=0;
4641
4642 resetitem = TRUE;
4643
4644 if (cust_callback != NULL)
4645 {
4646 cust_callback(cust_callback_call, cust_callback_item);
4647 return;
4648 }
4649
4650 //ControlPanelType = type;
4651 SetupMenu();
4652
4653 // Zero out the input structure
4654 mnu_input.button0 = mnu_input.button1 = FALSE;
4655 mnu_input.dir = dir_None;
4656
4657 // should not get input if you are editing a save game slot
4658 if(totalclock < limitmove) limitmove = totalclock;
4659 if (!MenuInputMode)
4660 {
4661 UserInput tst_input;
4662 BOOL select_held = FALSE;
4663
4664
4665 // Zero out the input structure
4666 tst_input.button0 = tst_input.button1 = FALSE;
4667 tst_input.dir = dir_None;
4668
4669 if(!select_held)
4670 {
4671 CONTROL_GetUserInput(&tst_input);
4672 mnu_input_buffered.dir = tst_input.dir;
4673 }
4674
4675 if(mnu_input_buffered.button0 || mnu_input_buffered.button1)
4676 {
4677 if(tst_input.button0 == mnu_input_buffered.button0 &&
4678 tst_input.button1 == mnu_input_buffered.button1)
4679 {
4680 select_held = TRUE;
4681 }
4682 else
4683 if(totalclock - limitmove > 7)
4684 {
4685 mnu_input.button0 = mnu_input_buffered.button0;
4686 mnu_input.button1 = mnu_input_buffered.button1;
4687
4688 mnu_input_buffered.button0 = tst_input.button0;
4689 mnu_input_buffered.button1 = tst_input.button1;
4690 }
4691 } else
4692 {
4693 select_held = FALSE;
4694 mnu_input_buffered.button0 = tst_input.button0;
4695 mnu_input_buffered.button1 = tst_input.button1;
4696 }
4697
4698 if(totalclock - limitmove > 7 && !select_held)
4699 {
4700 mnu_input.dir = mnu_input_buffered.dir;
4701
4702 if (mnu_input.dir != dir_None)
4703 if(!FX_SoundActive(handle2))
4704 handle2 = PlaySound(DIGI_STAR,&zero,&zero,&zero,v3df_dontpan);
4705
4706 limitmove = totalclock;
4707 mnu_input_buffered.dir = dir_None;
4708 }
4709 }
4710
4711 if (mnu_input.dir == dir_North)
4712 {
4713 MNU_PrevItem();
4714 resetitem = TRUE;
4715 }
4716 else
4717 if (mnu_input.dir == dir_South)
4718 {
4719 MNU_NextItem();
4720 resetitem = TRUE;
4721 }
4722 else
4723 if (mnu_input.button0)
4724 {
4725 static int handle5=0;
4726 if(!FX_SoundActive(handle5))
4727 handle5 = PlaySound(DIGI_SWORDSWOOSH,&zero,&zero,&zero,v3df_dontpan);
4728 KB_ClearKeysDown();
4729 MNU_DoItem();
4730 resetitem = TRUE;
4731 }
4732 else
4733 if (mnu_input.dir == dir_West
4734 && currentmenu->items[currentmenu->cursor].type == mt_slider)
4735 {
4736 MNU_DoSlider(-1, ¤tmenu->items[currentmenu->cursor], FALSE);
4737 resetitem = TRUE;
4738 }
4739 else
4740 if (mnu_input.dir == dir_East
4741 && currentmenu->items[currentmenu->cursor].type == mt_slider)
4742 {
4743 MNU_DoSlider(1, ¤tmenu->items[currentmenu->cursor], FALSE);
4744 resetitem = TRUE;
4745 }
4746 else
4747 if (mnu_input.button1 || BUTTON(gamefunc_Show_Menu))
4748 {
4749 static int handle3=0;
4750 CONTROL_ClearButton(gamefunc_Show_Menu);
4751 if(!FX_SoundActive(handle3))
4752 handle3 = PlaySound(DIGI_SWORDSWOOSH,&zero,&zero,&zero,v3df_dontpan);
4753 MNU_UpLevel();
4754 resetitem = TRUE;
4755 }
4756 else
4757 if (MNU_DoHotkey())
4758 {
4759 static int handle4=0;
4760 if(!FX_SoundActive(handle4))
4761 handle4 = PlaySound(DIGI_STAR,&zero,&zero,&zero,v3df_dontpan);
4762 resetitem = TRUE;
4763 mnu_input_buffered.button0 = mnu_input_buffered.button1 = FALSE;
4764 }
4765 else
4766 resetitem = FALSE;
4767
4768 // !FRANK! I added this because the old custom was only called for drawing
4769 // Needed one for drawing and moving.
4770 if (currentmenu->move_custom)
4771 currentmenu->move_custom(uc_setup, NULL);
4772
4773 if (resetitem)
4774 {
4775 KB_ClearKeysDown();
4776 ResetKeys();
4777 }
4778 }
4779
4780 ////////////////////////////////////////////////
4781 // Checks to see if we should be in menus
4782 ////////////////////////////////////////////////
4783 void
MNU_CheckForMenus(void)4784 MNU_CheckForMenus(void)
4785 {
4786 extern BOOL GamePaused;
4787
4788 if (UsingMenus)
4789 {
4790 //if (MoveSkip2 == 0)
4791 MNU_DoMenu(ct_mainmenu, Player + myconnectindex);
4792 }
4793 else
4794 {
4795 if ((ForceMenus || KEY_PRESSED(KEYSC_ESC) || BUTTON(gamefunc_Show_Menu)) && dimensionmode == 3 && !ConPanel)
4796 {
4797 KEY_PRESSED(KEYSC_ESC) = 0;
4798 CONTROL_ClearButton(gamefunc_Show_Menu);
4799 KB_ClearKeysDown();
4800 // setup sliders/buttons
4801 MNU_InitMenus();
4802 MNU_DoMenu(ct_mainmenu, Player + myconnectindex);
4803 pMenuClearTextLine(Player + myconnectindex);
4804 PauseGame();
4805 }
4806 }
4807
4808 ForceMenus = FALSE;
4809 }
4810
4811 void
MNU_CheckForMenusAnyKey(void)4812 MNU_CheckForMenusAnyKey(void)
4813 {
4814 if (UsingMenus)
4815 {
4816 //if (MoveSkip2 == 0)
4817 MNU_DoMenu(ct_mainmenu, Player + myconnectindex);
4818 }
4819 else
4820 {
4821 if (KeyPressed() || ForceMenus)
4822 {
4823 ResetKeys();
4824 KB_ClearKeysDown();
4825 MNU_InitMenus();
4826 MNU_DoMenu(ct_mainmenu, Player + myconnectindex);
4827 pMenuClearTextLine(Player + myconnectindex);
4828 }
4829 }
4830
4831 ForceMenus = FALSE;
4832 }
4833
MNU_ControlAxisOffset(int num)4834 static int MNU_ControlAxisOffset(int num)
4835 {
4836 switch (num) {
4837 case -1: return 0;
4838 case analog_turning: return 1;
4839 case analog_strafing: return 2;
4840 case analog_moving: return 3;
4841 case analog_lookingupanddown: return 4;
4842 case analog_maxtype: return 5;
4843 default: return 0;
4844 }
4845 }
4846
MNU_ControlAxisNum(int offset)4847 static int MNU_ControlAxisNum(int offset)
4848 {
4849 switch (offset) {
4850 case 0: return -1;
4851 case 1: return analog_turning;
4852 case 2: return analog_strafing;
4853 case 3: return analog_moving;
4854 case 4: return analog_lookingupanddown;
4855 default: return -1;
4856 }
4857 }
4858
4859
4860
4861 ///////////////////////////////////////////////////////////////////////////////////////////////////
4862 // Miscellaneous Routines
4863 ///////////////////////////////////////////////////////////////////////////////////////////////////
4864
4865 typedef struct RGB_color_typ
4866 {
4867 unsigned char red;
4868 unsigned char green;
4869 unsigned char blue;
4870 } RGB_color, *RGB_color_ptr;
4871
4872 #define PALETTE_MASK 0x3c6
4873 #define PALETTE_READ 0x3c7
4874 #define PALETTE_WRITE 0x3c8
4875 #define PALETTE_DATA 0x3c9
4876
4877 unsigned char palette_data[256][3]; // Global palette array
4878
4879 // V E R T I C A L R E T R A C E V A R I A B L E S //////////////////////////////////////////
4880
4881 #define VGA_INPUT_STATUS_1 0x3DA // VGA status register 1, bit 3 is the vsync
4882 // 1 = retrace in progress
4883 // 0 = no retrace
4884 #define VGA_VSYNC_MASK 0x08 // Masks off unwanted bits of status register.
4885
4886
4887 // These routines are not used and should not be used. Would interfere with VESA palette
4888 // cards.
4889 #if 0
4890 /////////////////////////////////////////////////
4891 // WaitForVsync
4892 // Waits for a vertical retrace to occur. If one is in progress, it waits for the next one.
4893 /////////////////////////////////////////////////
4894 void
4895 WaitForVsync(void)
4896 {
4897 while (inp(VGA_INPUT_STATUS_1) & VGA_VSYNC_MASK);
4898 // Retrace in progress, wait.
4899
4900 // Wait for vsync, and exit.
4901 while (!inp(VGA_INPUT_STATUS_1) & VGA_VSYNC_MASK);
4902 }
4903
4904 void
4905 Get_Palette(unsigned char *pal)
4906 {
4907 int i;
4908
4909 outp(PALETTE_READ, 0);
4910 for (i = 0; i < 768; i++)
4911 pal[i] = inp(PALETTE_DATA);
4912 }
4913 void
4914 Set_Palette(unsigned char *buff)
4915 {
4916 int i;
4917
4918 outp(PALETTE_WRITE, 0); // Resets color ram pointer to 1st
4919 // color
4920 for (i = 0; i < 768; i++)
4921 outp(PALETTE_DATA, buff[i]);
4922 }
4923
4924 #endif
4925
4926
4927 /*
4928 =================================================================================================
4929 =
4930 = FadeOut - Fades the palette to color at assigned click rate
4931 =
4932 =================================================================================================
4933 */
4934 // Heres some temp timer junk for this routine. Replace it with game timer stuff later.
4935 //unsigned int *clock = (unsigned int *)0x046C;
4936
4937 void
Fade_Timer(int clicks)4938 Fade_Timer(int clicks)
4939 {
4940 // unsigned int now;
4941 int now;
4942
4943 now = totalclock;
4944
4945 while (abs(totalclock - now) < clicks) handleevents();
4946 }
4947
4948 void
FadeIn(unsigned char startcolor,unsigned int clicks)4949 FadeIn(unsigned char startcolor, unsigned int clicks)
4950 {
4951 int i, palreg, usereg, tmpreg1 = 0, tmpreg2 = 0;
4952 RGB_color color;
4953 unsigned char temp_pal[768], *palette;
4954
4955 #if USE_POLYMOST && USE_OPENGL
4956 if (getrendermode() >= 3) return;
4957 #endif
4958
4959 palette = &palette_data[0][0];
4960
4961 color.red = palette_data[startcolor][0];
4962 color.green = palette_data[startcolor][1];
4963 color.blue = palette_data[startcolor][2];
4964
4965 usereg = 0;
4966 for (i = 0; i < 768; i++)
4967 {
4968 if (usereg == 0)
4969 temp_pal[i] = color.red;
4970 else
4971 if (usereg == 1)
4972 temp_pal[i] = color.green;
4973 else
4974 temp_pal[i] = color.blue;
4975
4976 if (++usereg > 2)
4977 usereg = 0;
4978 }
4979
4980 for (i = 0; i < 32; i++)
4981 {
4982 for (palreg = 0; palreg < 768; palreg++)
4983 {
4984 tmpreg1 = (int) (temp_pal[palreg]) + 2;
4985 tmpreg2 = (int) (temp_pal[palreg]) - 2;
4986 if (tmpreg1 > 255)
4987 tmpreg1 = 255;
4988 if (tmpreg2 < 0)
4989 tmpreg2 = 0;
4990
4991 if (temp_pal[palreg] < palette[palreg])
4992 {
4993 if ((temp_pal[palreg] = tmpreg1) > palette[palreg])
4994 temp_pal[palreg] = palette[palreg];
4995 }
4996 else
4997 if (temp_pal[palreg] > palette[palreg])
4998 if ((temp_pal[palreg] = tmpreg2) < palette[palreg])
4999 temp_pal[palreg] = palette[palreg];
5000
5001 }
5002
5003 set_pal(&temp_pal[0]);
5004
5005 // Delay clicks
5006 Fade_Timer(clicks);
5007 }
5008 }
5009
5010 void
FadeOut(unsigned char targetcolor,unsigned int clicks)5011 FadeOut(unsigned char targetcolor, unsigned int clicks)
5012 {
5013 int i, palreg, usereg = 0, tmpreg1 = 0, tmpreg2 = 0;
5014 RGB_color color;
5015 unsigned char temp_pal[768];
5016
5017 #if USE_POLYMOST && USE_OPENGL
5018 if (getrendermode() >= 3) return;
5019 #endif
5020
5021 color.red = palette_data[targetcolor][0];
5022 color.green = palette_data[targetcolor][1];
5023 color.blue = palette_data[targetcolor][2];
5024
5025 memcpy(&temp_pal[0], &palette_data[0][0], 768);
5026
5027 for (i = 0; i < 32; i++)
5028 {
5029 for (palreg = 0; palreg < 768; palreg++)
5030 {
5031 tmpreg1 = (int) (temp_pal[palreg]) + 2;
5032 tmpreg2 = (int) (temp_pal[palreg]) - 2;
5033 if (tmpreg1 > 255)
5034 tmpreg1 = 255;
5035 if (tmpreg2 < 0)
5036 tmpreg2 = 0;
5037
5038 if (usereg == 0)
5039 {
5040 if (temp_pal[palreg] < color.red)
5041 {
5042 if ((temp_pal[palreg] = tmpreg1) > color.red)
5043 temp_pal[palreg] = color.red;
5044 }
5045 else
5046 if (temp_pal[palreg] > color.red)
5047 if ((temp_pal[palreg] = tmpreg2) < color.red)
5048 temp_pal[palreg] = color.red;
5049 }
5050 else
5051 if (usereg == 1)
5052 {
5053 if (temp_pal[palreg] < color.green)
5054 {
5055 if ((temp_pal[palreg] = tmpreg1) > color.green)
5056 temp_pal[palreg] = color.green;
5057 }
5058 else
5059 if (temp_pal[palreg] > color.green)
5060 if ((temp_pal[palreg] = tmpreg2) < color.green)
5061 temp_pal[palreg] = color.green;
5062 }
5063 else
5064 if (usereg == 2)
5065 {
5066 if (temp_pal[palreg] < color.blue)
5067 {
5068 if ((temp_pal[palreg] = tmpreg1) > color.blue)
5069 temp_pal[palreg] = color.blue;
5070 }
5071 else
5072 if (temp_pal[palreg] > color.blue)
5073 if ((temp_pal[palreg] = tmpreg2) < color.blue)
5074 temp_pal[palreg] = color.blue;
5075 }
5076
5077 if (++usereg > 2)
5078 usereg = 0;
5079 }
5080
5081
5082 set_pal(&temp_pal[0]);
5083
5084 // Delay clicks
5085 Fade_Timer(clicks);
5086 }
5087 }
5088
5089 //////////////////////////////////////////////////////////////////////////////
5090 #define FADE_DAMAGE_FACTOR 3 // 100 health / 32 shade cycles = 3.125
5091
5092 // Fades from 100% to 62.5% somewhat quickly,
5093 // then from 62.5% to 37.5% slowly,
5094 // then from 37.5% to 0% quickly.
5095 // This seems to capture the pain caused by enemy shots, plus the extreme
5096 // fade caused by being blinded or intense pain.
5097 // Perhaps the next step would be to apply a gentle smoothing to the
5098 // intersections of these lines.
5099 static int faderamp[32] = {
5100 64,60,56,52,48,44, // y=64-4x
5101
5102 40,39,38,38,37, // y=44.8-(16/20)x
5103 36,35,34,34,33,
5104 32,31,30,30,29,
5105 28,27,26,26,25,
5106
5107 24,20,16,12,8, 4 // y=128-4x
5108 };
5109
5110 unsigned char ppalette[MAX_SW_PLAYERS_REG][768];
5111
5112 //////////////////////////////////////////
5113 // Set the amount of redness for damage
5114 // the player just took
5115 //////////////////////////////////////////
5116 void
SetFadeAmt(PLAYERp pp,short damage,unsigned char startcolor)5117 SetFadeAmt(PLAYERp pp, short damage, unsigned char startcolor)
5118 {
5119 int palreg, usereg = 0, tmpreg1 = 0, tmpreg2 = 0;
5120 short fadedamage=0;
5121 RGB_color color;
5122
5123 //CON_ConMessage("SetAmt: fadeamt = %d, startcolor = %d, pp = %d",pp->FadeAmt,startcolor,pp->StartColor);
5124
5125 if (abs(pp->FadeAmt) > 0 && startcolor == pp->StartColor)
5126 return;
5127
5128 // Don't ever over ride flash bomb
5129 if (pp->StartColor == 1 && abs(pp->FadeAmt) > 0)
5130 return;
5131
5132 // Reset the palette
5133 if(pp == Player + screenpeek)
5134 {
5135 #if USE_POLYMOST && USE_OPENGL
5136 if (getrendermode() >= 3)
5137 {
5138 setpalettefade(0,0,0,0);
5139 }
5140 else
5141 #endif
5142 {
5143 COVERsetbrightness(gs.Brightness,&palette_data[0][0]);
5144 }
5145 if (pp->FadeAmt <= 0)
5146 GetPaletteFromVESA(&ppalette[screenpeek][0]);
5147 }
5148
5149 if(damage < -150 && damage > -1000) fadedamage = 150;
5150 else
5151 if(damage < -1000) // Underwater
5152 fadedamage = abs(damage+1000);
5153 else
5154 fadedamage = abs(damage);
5155
5156 if(damage >= -5 && damage < 0)
5157 fadedamage += 10;
5158
5159 // Don't let red to TOO red
5160 if(startcolor == COLOR_PAIN && fadedamage > 100) fadedamage = 100;
5161
5162 pp->FadeAmt = fadedamage / FADE_DAMAGE_FACTOR;
5163
5164 if (pp->FadeAmt <= 0)
5165 {
5166 pp->FadeAmt = 0;
5167 return;
5168 }
5169
5170 // It's a health item, just do a preset flash amount
5171 if (damage > 0)
5172 pp->FadeAmt = 3;
5173
5174 pp->StartColor = startcolor;
5175
5176 pp->FadeTics = 0;
5177
5178 // Set player's palette to current game palette
5179 GetPaletteFromVESA(pp->temp_pal);
5180
5181 color.red = palette_data[pp->StartColor][0];
5182 color.green = palette_data[pp->StartColor][1];
5183 color.blue = palette_data[pp->StartColor][2];
5184
5185 for (palreg = 0; palreg < 768; palreg++)
5186 {
5187 tmpreg1 = (int) (pp->temp_pal[palreg]) + ((2 * pp->FadeAmt) + 4);
5188 tmpreg2 = (int) (pp->temp_pal[palreg]) - ((2 * pp->FadeAmt) + 4);
5189 if (tmpreg1 > 255)
5190 tmpreg1 = 255;
5191 if (tmpreg2 < 0)
5192 tmpreg2 = 0;
5193
5194 if (usereg == 0)
5195 {
5196 if (pp->temp_pal[palreg] < color.red)
5197 {
5198 if ((pp->temp_pal[palreg] = tmpreg1) > color.red)
5199 pp->temp_pal[palreg] = color.red;
5200 }
5201 else
5202 if (pp->temp_pal[palreg] > color.red)
5203 if ((pp->temp_pal[palreg] = tmpreg2) < color.red)
5204 pp->temp_pal[palreg] = color.red;
5205 }
5206 else
5207 if (usereg == 1)
5208 {
5209 if (pp->temp_pal[palreg] < color.green)
5210 {
5211 if ((pp->temp_pal[palreg] = tmpreg1) > color.green)
5212 pp->temp_pal[palreg] = color.green;
5213 }
5214 else
5215 if (pp->temp_pal[palreg] > color.green)
5216 if ((pp->temp_pal[palreg] = tmpreg2) < color.green)
5217 pp->temp_pal[palreg] = color.green;
5218 }
5219 else
5220 if (usereg == 2)
5221 {
5222 if (pp->temp_pal[palreg] < color.blue)
5223 {
5224 if ((pp->temp_pal[palreg] = tmpreg1) > color.blue)
5225 pp->temp_pal[palreg] = color.blue;
5226 }
5227 else
5228 if (pp->temp_pal[palreg] > color.blue)
5229 if ((pp->temp_pal[palreg] = tmpreg2) < color.blue)
5230 pp->temp_pal[palreg] = color.blue;
5231 }
5232
5233 if (++usereg > 2)
5234 usereg = 0;
5235 }
5236
5237 // Do initial palette set
5238 if(pp == Player + screenpeek)
5239 {
5240 #if USE_POLYMOST && USE_OPENGL
5241 if (getrendermode() >= 3)
5242 {
5243 setpalettefade(color.red, color.green, color.blue, faderamp[ min(31,max(0,32-abs(pp->FadeAmt))) ] );
5244 }
5245 else
5246 #endif
5247 {
5248 set_pal(pp->temp_pal);
5249 }
5250 if (damage < -1000)
5251 pp->FadeAmt = 1000; // Don't call DoPaletteFlash for underwater stuff
5252 }
5253 }
5254
5255 //////////////////////////////////////////
5256 // Do the screen reddness based on damage
5257 //////////////////////////////////////////
5258 #define MAXFADETICS 5
5259 void
DoPaletteFlash(PLAYERp pp)5260 DoPaletteFlash(PLAYERp pp)
5261 {
5262 int i, palreg, tmpreg1 = 0, tmpreg2 = 0;
5263 unsigned char *pal_ptr = &ppalette[screenpeek][0];
5264
5265
5266 if (pp->FadeAmt <= 1)
5267 {
5268 pp->FadeAmt = 0;
5269 pp->StartColor = 0;
5270 if(pp == Player + screenpeek)
5271 {
5272 #if USE_POLYMOST && USE_OPENGL
5273 if (getrendermode() >= 3)
5274 {
5275 setpalettefade(0,0,0,0);
5276 }
5277 else
5278 #endif
5279 {
5280 COVERsetbrightness(gs.Brightness,&palette_data[0][0]);
5281 }
5282 memcpy(pp->temp_pal, palette_data, sizeof(palette_data));
5283 DoPlayerDivePalette(pp); // Check Dive again
5284 DoPlayerNightVisionPalette(pp); // Check Night Vision again
5285 }
5286
5287 return;
5288 }
5289
5290
5291 pp->FadeTics += synctics; // Add this frame's tic amount to
5292 // counter
5293
5294 if (pp->FadeTics >= MAXFADETICS)
5295 {
5296 while (pp->FadeTics >= MAXFADETICS)
5297 {
5298 pp->FadeTics -= MAXFADETICS;
5299
5300 pp->FadeAmt--; // Decrement FadeAmt till it gets to
5301 // 0 again.
5302 }
5303 }
5304 else
5305 return; // Return if they were not >
5306 // MAXFADETICS
5307
5308 if (pp->FadeAmt > 32)
5309 return;
5310
5311 if (pp->FadeAmt <= 1)
5312 {
5313 pp->FadeAmt = 0;
5314 pp->StartColor = 0;
5315 if(pp == Player + screenpeek)
5316 {
5317 #if USE_POLYMOST && USE_OPENGL
5318 if (getrendermode() >= 3)
5319 {
5320 setpalettefade(0,0,0,0);
5321 }
5322 else
5323 #endif
5324 {
5325 COVERsetbrightness(gs.Brightness,&palette_data[0][0]);
5326 }
5327 memcpy(pp->temp_pal, palette_data, sizeof(palette_data));
5328 DoPlayerDivePalette(pp); // Check Dive again
5329 DoPlayerNightVisionPalette(pp); // Check Night Vision again
5330 }
5331 return;
5332 }
5333 else
5334 {
5335 //CON_Message("gamavalues = %d, %d, %d",pp->temp_pal[pp->StartColor],pp->temp_pal[pp->StartColor+1],pp->temp_pal[pp->StartColor+2]);
5336 for (palreg = 0; palreg < 768; palreg++)
5337 {
5338 tmpreg1 = (int) (pp->temp_pal[palreg]) + 2;
5339 tmpreg2 = (int) (pp->temp_pal[palreg]) - 2;
5340 if (tmpreg1 > 255)
5341 tmpreg1 = 255;
5342 if (tmpreg2 < 0)
5343 tmpreg2 = 0;
5344
5345 if (pp->temp_pal[palreg] < pal_ptr[palreg])
5346 {
5347 if ((pp->temp_pal[palreg] = tmpreg1) > pal_ptr[palreg])
5348 pp->temp_pal[palreg] = pal_ptr[palreg];
5349 }
5350 else
5351 if (pp->temp_pal[palreg] > pal_ptr[palreg])
5352 if ((pp->temp_pal[palreg] = tmpreg2) < pal_ptr[palreg])
5353 pp->temp_pal[palreg] = pal_ptr[palreg];
5354
5355 }
5356
5357 // Only hard set the palette if this is currently the player's view
5358 if(pp == Player + screenpeek)
5359 {
5360 #if USE_POLYMOST && USE_OPENGL
5361 if (getrendermode() >= 3)
5362 {
5363 setpalettefade(
5364 palette_data[pp->StartColor][0],
5365 palette_data[pp->StartColor][1],
5366 palette_data[pp->StartColor][2],
5367 faderamp[ min(31,max(0,32-abs(pp->FadeAmt))) ]
5368 );
5369 }
5370 else
5371 #endif
5372 {
5373 set_pal(pp->temp_pal);
5374 }
5375 }
5376
5377 }
5378
5379 }
5380
ResetPalette(PLAYERp pp)5381 VOID ResetPalette(PLAYERp pp)
5382 {
5383 #if USE_POLYMOST && USE_OPENGL
5384 if (getrendermode() >= 3)
5385 {
5386 setpalettefade(0,0,0,0);
5387 }
5388 else
5389 #endif
5390 {
5391 COVERsetbrightness(gs.Brightness,&palette_data[0][0]);
5392 }
5393 memcpy(pp->temp_pal, palette_data, sizeof(palette_data));
5394 //DoPlayerDivePalette(pp); // Check Dive again
5395 //DoPlayerNightVisionPalette(pp); // Check Night Vision again
5396 pp->FadeAmt = 0;
5397 pp->StartColor = 0;
5398 pp->FadeTics = 0;
5399 }
5400
5401 // vim:ts=4:sw=4:enc=utf-8:
5402
5403
5404