aboutsummaryrefslogtreecommitdiffstats
path: root/src/jake2/client/Menu.java
diff options
context:
space:
mode:
authorHolger Zickner <[email protected]>2004-07-07 19:59:59 +0000
committerHolger Zickner <[email protected]>2004-07-07 19:59:59 +0000
commit6e23fc1074d1f0c2c2812f4c2e663f5a21a43c20 (patch)
tree46ecc6d0255c874ba4cd26dc3d0733f785019896 /src/jake2/client/Menu.java
import of Jake2 version sunrisesunrise
Diffstat (limited to 'src/jake2/client/Menu.java')
-rw-r--r--src/jake2/client/Menu.java4977
1 files changed, 4977 insertions, 0 deletions
diff --git a/src/jake2/client/Menu.java b/src/jake2/client/Menu.java
new file mode 100644
index 0000000..264d38f
--- /dev/null
+++ b/src/jake2/client/Menu.java
@@ -0,0 +1,4977 @@
+/*
+ * Menu.java
+ * Copyright (C) 2004
+ *
+ * $Id: Menu.java,v 1.1 2004-07-07 19:58:51 hzi Exp $
+ */
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+package jake2.client;
+
+import jake2.Globals;
+import jake2.game.Cmd;
+import jake2.game.cvar_t;
+import jake2.qcommon.*;
+import jake2.sys.NET;
+import jake2.sys.Sys;
+import jake2.util.Lib;
+import jake2.util.Math3D;
+
+import java.awt.Dimension;
+import java.io.RandomAccessFile;
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * Menu
+ *
+ *
+ */
+
+abstract class keyfunc_t {
+ abstract String execute(int key);
+}
+
+public final class Menu extends Key {
+
+ static int m_main_cursor;
+ static final int NUM_CURSOR_FRAMES = 15;
+
+ static final String menu_in_sound = "misc/menu1.wav";
+ static final String menu_move_sound = "misc/menu2.wav";
+ static final String menu_out_sound = "misc/menu3.wav";
+
+ static boolean m_entersound; // play after drawing a frame, so caching
+ // won't disrupt the sound
+
+ static xcommand_t m_drawfunc;
+
+ static keyfunc_t m_keyfunc;
+
+ // =============================================================================
+ /* Support Routines */
+
+ public final static int MAX_MENU_DEPTH = 8;
+
+ public static class menulayer_t {
+ xcommand_t draw;
+ keyfunc_t key;
+ }
+
+ static class menuframework_s {
+ int x, y;
+ int cursor;
+
+ int nitems;
+ int nslots;
+ menucommon_s items[] = new menucommon_s[64];
+
+ String statusbar;
+
+ //void (*cursordraw)( struct _tag_menuframework *m );
+ mcallback cursordraw;
+
+ }
+
+ static class mcallback {
+ public void execute(Object self) {
+ }
+ }
+
+ static class menucommon_s {
+ int type;
+ String name;
+ int x, y;
+ menuframework_s parent;
+ int cursor_offset;
+ int localdata[] = { 0, 0, 0, 0 };
+ int flags;
+ int n = -1; //position in an array.
+
+ String statusbar;
+
+ mcallback callback;
+ mcallback statusbarfunc;
+ mcallback ownerdraw;
+ mcallback cursordraw;
+ }
+
+ static class menufield_s extends menucommon_s {
+ //char buffer[80];
+ StringBuffer buffer; //allow deletion.
+
+ int cursor;
+ int length;
+ int visible_length;
+ int visible_offset;
+ }
+
+ static class menuslider_s extends menucommon_s {
+
+ float minvalue;
+ float maxvalue;
+ float curvalue;
+
+ float range;
+ }
+
+ static class menulist_s extends menucommon_s {
+ int curvalue;
+ String itemnames[];
+ }
+
+ static class menuaction_s extends menucommon_s {
+
+ }
+
+ static class menuseparator_s extends menucommon_s {
+
+ }
+
+ public static menulayer_t m_layers[] = new menulayer_t[MAX_MENU_DEPTH];
+ public static int m_menudepth;
+
+ static void Banner(String name) {
+ int w, h;
+
+ Dimension dim = new Dimension();
+ Globals.re.DrawGetPicSize(dim, name);
+
+ Globals.re.DrawPic(viddef.width / 2 - dim.width / 2, viddef.height / 2 - 110, name);
+ }
+
+ static void PushMenu(xcommand_t draw, keyfunc_t key) { //, String(*key) (int k) ) {
+ int i;
+
+ if (Cvar.VariableValue("maxclients") == 1 && Com.ServerState() != 0)
+ Cvar.Set("paused", "1");
+
+ // if this menu is already present, drop back to that level
+ // to avoid stacking menus by hotkeys
+ for (i = 0; i < m_menudepth; i++)
+ if (m_layers[i].draw == draw && m_layers[i].key == key) {
+ m_menudepth = i;
+ }
+
+ if (i == m_menudepth) {
+ if (m_menudepth >= MAX_MENU_DEPTH)
+ Com.Error(ERR_FATAL, "PushMenu: MAX_MENU_DEPTH");
+
+ m_layers[m_menudepth].draw = m_drawfunc;
+ m_layers[m_menudepth].key = m_keyfunc;
+ m_menudepth++;
+ }
+
+ m_drawfunc = draw;
+ m_keyfunc = key;
+
+ m_entersound = true;
+
+ cls.key_dest = key_menu;
+ }
+
+ static void ForceMenuOff() {
+ m_drawfunc = null;
+ m_keyfunc = null;
+ cls.key_dest = key_game;
+ m_menudepth = 0;
+ Key.ClearStates();
+ Cvar.Set("paused", "0");
+ }
+
+ static void PopMenu() {
+ S.StartLocalSound(menu_out_sound);
+ if (m_menudepth < 1)
+ Com.Error(ERR_FATAL, "PopMenu: depth < 1");
+ m_menudepth--;
+
+ m_drawfunc = m_layers[m_menudepth].draw;
+ m_keyfunc = m_layers[m_menudepth].key;
+
+ if (0 == m_menudepth)
+ ForceMenuOff();
+ }
+
+ static String Default_MenuKey(menuframework_s m, int key) {
+ String sound = null;
+ menucommon_s item;
+
+ if (m != null) {
+ if ((item = ((menucommon_s) Menu_ItemAtCursor(m))) != null) {
+ if (item.type == MTYPE_FIELD) {
+ if (Field_Key((menufield_s) item, key))
+ return null;
+ }
+ }
+ }
+
+ switch (key) {
+ case K_ESCAPE :
+ PopMenu();
+ return menu_out_sound;
+ case K_KP_UPARROW :
+ case K_UPARROW :
+ if (m != null) {
+ m.cursor--;
+ Menu_AdjustCursor(m, -1);
+ sound = menu_move_sound;
+ }
+ break;
+ case K_TAB :
+ if (m != null) {
+ m.cursor++;
+ Menu_AdjustCursor(m, 1);
+ sound = menu_move_sound;
+ }
+ break;
+ case K_KP_DOWNARROW :
+ case K_DOWNARROW :
+ if (m != null) {
+ m.cursor++;
+ Menu_AdjustCursor(m, 1);
+ sound = menu_move_sound;
+ }
+ break;
+ case K_KP_LEFTARROW :
+ case K_LEFTARROW :
+ if (m != null) {
+ Menu_SlideItem(m, -1);
+ sound = menu_move_sound;
+ }
+ break;
+ case K_KP_RIGHTARROW :
+ case K_RIGHTARROW :
+ if (m != null) {
+ Menu_SlideItem(m, 1);
+ sound = menu_move_sound;
+ }
+ break;
+
+ case K_MOUSE1 :
+ case K_MOUSE2 :
+ case K_MOUSE3 :
+ case K_JOY1 :
+ case K_JOY2 :
+ case K_JOY3 :
+ case K_JOY4 :
+ /*
+ case K_AUX1 :
+ case K_AUX2 :
+ case K_AUX3 :
+ case K_AUX4 :
+ case K_AUX5 :
+ case K_AUX6 :
+ case K_AUX7 :
+ case K_AUX8 :
+ case K_AUX9 :
+ case K_AUX10 :
+ case K_AUX11 :
+ case K_AUX12 :
+ case K_AUX13 :
+ case K_AUX14 :
+ case K_AUX15 :
+ case K_AUX16 :
+ case K_AUX17 :
+ case K_AUX18 :
+ case K_AUX19 :
+ case K_AUX20 :
+ case K_AUX21 :
+ case K_AUX22 :
+ case K_AUX23 :
+ case K_AUX24 :
+ case K_AUX25 :
+ case K_AUX26 :
+ case K_AUX27 :
+ case K_AUX28 :
+ case K_AUX29 :
+ case K_AUX30 :
+ case K_AUX31 :
+ case K_AUX32 :
+ */
+ case K_KP_ENTER :
+ case K_ENTER :
+ if (m != null)
+ Menu_SelectItem(m);
+ sound = menu_move_sound;
+ break;
+ }
+
+ return sound;
+ }
+
+ /*
+ ================
+ DrawCharacter
+
+ Draws one solid graphics character
+ cx and cy are in 320*240 coordinates, and will be centered on
+ higher res screens.
+ ================
+ */
+ public static void DrawCharacter(int cx, int cy, int num) {
+ re.DrawChar(cx + ((viddef.width - 320) >> 1), cy + ((viddef.height - 240) >> 1), num);
+ }
+
+ public static void Print(int cx, int cy, String str) {
+ //while (*str)
+ for (int n = 0; n < str.length(); n++) {
+ DrawCharacter(cx, cy, str.charAt(n) + 128);
+ //str++;
+ cx += 8;
+ }
+ }
+
+ public static void PrintWhite(int cx, int cy, String str) {
+ for (int n = 0; n < str.length(); n++) {
+ DrawCharacter(cx, cy, str.charAt(n));
+ //str++;
+ cx += 8;
+ }
+ }
+
+ public static void DrawPic(int x, int y, String pic) {
+ re.DrawPic(x + ((viddef.width - 320) >> 1), y + ((viddef.height - 240) >> 1), pic);
+ }
+
+ /*
+ =============
+ DrawCursor
+
+ Draws an animating cursor with the point at
+ x,y. The pic will extend to the left of x,
+ and both above and below y.
+ =============
+ */
+ static boolean cached;
+ static void DrawCursor(int x, int y, int f) {
+ //char cursorname[80];
+ String cursorname;
+
+ assert(f >= 0) : "negative time and cursor bug";
+
+ f = Math.abs(f);
+
+ if (!cached) {
+ int i;
+
+ for (i = 0; i < NUM_CURSOR_FRAMES; i++) {
+ cursorname = "m_cursor" + i;
+
+ re.RegisterPic(cursorname);
+ }
+ cached = true;
+ }
+
+ cursorname = "m_cursor" + f;
+ re.DrawPic(x, y, cursorname);
+ }
+
+ public static void DrawTextBox(int x, int y, int width, int lines) {
+ int cx, cy;
+ int n;
+
+ // draw left side
+ cx = x;
+ cy = y;
+ DrawCharacter(cx, cy, 1);
+
+ for (n = 0; n < lines; n++) {
+ cy += 8;
+ DrawCharacter(cx, cy, 4);
+ }
+ DrawCharacter(cx, cy + 8, 7);
+
+ // draw middle
+ cx += 8;
+ while (width > 0) {
+ cy = y;
+ DrawCharacter(cx, cy, 2);
+
+ for (n = 0; n < lines; n++) {
+ cy += 8;
+ DrawCharacter(cx, cy, 5);
+ }
+ DrawCharacter(cx, cy + 8, 8);
+
+ width -= 1;
+ cx += 8;
+ }
+
+ // draw right side
+ cy = y;
+ DrawCharacter(cx, cy, 3);
+ for (n = 0; n < lines; n++) {
+ cy += 8;
+ DrawCharacter(cx, cy, 6);
+
+ }
+ DrawCharacter(cx, cy + 8, 9);
+
+ }
+
+ /*
+ =======================================================================
+
+ MAIN MENU
+
+ =======================================================================
+ */
+ static final int MAIN_ITEMS = 5;
+
+ static xcommand_t Main_Draw = new xcommand_t() {
+ public void execute() {
+ Main_Draw();
+ }
+ };
+ static void Main_Draw() {
+ int i;
+ int w, h;
+ int ystart;
+ int xoffset;
+ int widest = -1;
+ int totalheight = 0;
+ String litname;
+ String[] names = { "m_main_game", "m_main_multiplayer", "m_main_options", "m_main_video", "m_main_quit" };
+ Dimension dim = new Dimension();
+
+ for (i = 0; i < names.length; i++) {
+ Globals.re.DrawGetPicSize(dim, names[i]);
+ w = dim.width;
+ h = dim.height;
+
+ if (w > widest)
+ widest = w;
+ totalheight += (h + 12);
+ }
+
+ ystart = (Globals.viddef.height / 2 - 110);
+ xoffset = (Globals.viddef.width - widest + 70) / 2;
+
+ for (i = 0; i < names.length; i++) {
+ if (i != m_main_cursor)
+ Globals.re.DrawPic(xoffset, ystart + i * 40 + 13, names[i]);
+ }
+
+ //strcat(litname, "_sel");
+ litname = names[m_main_cursor] + "_sel";
+ Globals.re.DrawPic(xoffset, ystart + m_main_cursor * 40 + 13, litname);
+
+ DrawCursor(xoffset - 25, ystart + m_main_cursor * 40 + 11, (int) ((Globals.cls.realtime / 100)) % NUM_CURSOR_FRAMES);
+
+ Globals.re.DrawGetPicSize(dim, "m_main_plaque");
+ w = dim.width;
+ h = dim.height;
+ Globals.re.DrawPic(xoffset - 30 - w, ystart, "m_main_plaque");
+
+ Globals.re.DrawPic(xoffset - 30 - w, ystart + h + 5, "m_main_logo");
+ }
+
+ static keyfunc_t Main_Key = new keyfunc_t() {
+ public String execute(int key) {
+ return Main_Key(key);
+ }
+ };
+
+ static String Main_Key(int key) {
+ String sound = menu_move_sound;
+
+ switch (key) {
+ case Key.K_ESCAPE :
+ PopMenu();
+ break;
+
+ case Key.K_KP_DOWNARROW :
+ case Key.K_DOWNARROW :
+ if (++m_main_cursor >= MAIN_ITEMS)
+ m_main_cursor = 0;
+ return sound;
+
+ case Key.K_KP_UPARROW :
+ case Key.K_UPARROW :
+ if (--m_main_cursor < 0)
+ m_main_cursor = MAIN_ITEMS - 1;
+ return sound;
+
+ case Key.K_KP_ENTER :
+ case Key.K_ENTER :
+ m_entersound = true;
+
+ switch (m_main_cursor) {
+ case 0 :
+ Menu_Game_f();
+ break;
+
+ case 1 :
+ Menu_Multiplayer_f();
+ break;
+
+ case 2 :
+ Menu_Options_f();
+ break;
+
+ case 3 :
+ Menu_Video_f();
+ break;
+
+ case 4 :
+ Menu_Quit_f();
+ break;
+ }
+ }
+
+ return null;
+ }
+
+ static xcommand_t Menu_Main = new xcommand_t() {
+ public void execute() {
+ Menu_Main_f();
+ }
+ };
+
+ static void Menu_Main_f() {
+ PushMenu(new xcommand_t() {
+ public void execute() {
+ Main_Draw();
+ }
+ }, new keyfunc_t() {
+ public String execute(int key) {
+ return Main_Key(key);
+ }
+ });
+ }
+
+ /*
+ =======================================================================
+
+ MULTIPLAYER MENU
+
+ =======================================================================
+ */
+ static menuframework_s s_multiplayer_menu = new menuframework_s();
+ static menuaction_s s_join_network_server_action = new menuaction_s();
+ static menuaction_s s_start_network_server_action = new menuaction_s();
+ static menuaction_s s_player_setup_action = new menuaction_s();
+
+ static void Multiplayer_MenuDraw() {
+ Banner("m_banner_multiplayer");
+
+ Menu_AdjustCursor(s_multiplayer_menu, 1);
+ Menu_Draw(s_multiplayer_menu);
+ }
+
+ static void PlayerSetupFunc(Object unused) {
+ Menu_PlayerConfig_f();
+ }
+
+ static void JoinNetworkServerFunc(Object unused) {
+ Menu_JoinServer_f();
+ }
+
+ static void StartNetworkServerFunc(Object unused) {
+ Menu_StartServer_f();
+ }
+
+ static void Multiplayer_MenuInit() {
+ s_multiplayer_menu.x = (int) (viddef.width * 0.50f - 64);
+ s_multiplayer_menu.nitems = 0;
+
+ s_join_network_server_action.type = MTYPE_ACTION;
+ s_join_network_server_action.flags = QMF_LEFT_JUSTIFY;
+ s_join_network_server_action.x = 0;
+ s_join_network_server_action.y = 0;
+ s_join_network_server_action.name = " join network server";
+ s_join_network_server_action.callback = new mcallback() {
+ public void execute(Object o) {
+ JoinNetworkServerFunc(o);
+ };
+ };
+
+ s_start_network_server_action.type = MTYPE_ACTION;
+ s_start_network_server_action.flags = QMF_LEFT_JUSTIFY;
+ s_start_network_server_action.x = 0;
+ s_start_network_server_action.y = 10;
+ s_start_network_server_action.name = " start network server";
+ s_start_network_server_action.callback = new mcallback() {
+ public void execute(Object o) {
+ StartNetworkServerFunc(o);
+ }
+ };
+
+ s_player_setup_action.type = MTYPE_ACTION;
+ s_player_setup_action.flags = QMF_LEFT_JUSTIFY;
+ s_player_setup_action.x = 0;
+ s_player_setup_action.y = 20;
+ s_player_setup_action.name = " player setup";
+ s_player_setup_action.callback = new mcallback() {
+ public void execute(Object o) {
+ PlayerSetupFunc(o);
+ }
+ };
+
+ Menu_AddItem(s_multiplayer_menu, s_join_network_server_action);
+ Menu_AddItem(s_multiplayer_menu, s_start_network_server_action);
+ Menu_AddItem(s_multiplayer_menu, s_player_setup_action);
+
+ Menu_SetStatusBar(s_multiplayer_menu, null);
+
+ Menu_Center(s_multiplayer_menu);
+ }
+
+ static String Multiplayer_MenuKey(int key) {
+ return Default_MenuKey(s_multiplayer_menu, key);
+ }
+
+ static xcommand_t Menu_Multiplayer = new xcommand_t() {
+ public void execute() {
+ Menu_Multiplayer_f();
+ }
+ };
+
+ static void Menu_Multiplayer_f() {
+ Multiplayer_MenuInit();
+ PushMenu(new xcommand_t() {
+ public void execute() {
+ Multiplayer_MenuDraw();
+ }
+ }, new keyfunc_t() {
+ public String execute(int key) {
+ return Multiplayer_MenuKey(key);
+ }
+ });
+ }
+
+ /*
+ =======================================================================
+
+ KEYS MENU
+
+ =======================================================================
+ */
+ static String bindnames[][] = { { "+attack", "attack" }, {
+ "weapnext", "next weapon" }, {
+ "+forward", "walk forward" }, {
+ "+back", "backpedal" }, {
+ "+left", "turn left" }, {
+ "+right", "turn right" }, {
+ "+speed", "run" }, {
+ "+moveleft", "step left" }, {
+ "+moveright", "step right" }, {
+ "+strafe", "sidestep" }, {
+ "+lookup", "look up" }, {
+ "+lookdown", "look down" }, {
+ "centerview", "center view" }, {
+ "+mlook", "mouse look" }, {
+ "+klook", "keyboard look" }, {
+ "+moveup", "up / jump" }, {
+ "+movedown", "down / crouch" }, {
+
+ "inven", "inventory" }, {
+ "invuse", "use item" }, {
+ "invdrop", "drop item" }, {
+ "invprev", "prev item" }, {
+ "invnext", "next item" }, {
+
+ "cmd help", "help computer" }, {
+ null, null }
+ };
+
+ int keys_cursor;
+ static boolean bind_grab;
+
+ static menuframework_s s_keys_menu = new menuframework_s();
+ static menuaction_s s_keys_attack_action = new menuaction_s();
+ static menuaction_s s_keys_change_weapon_action = new menuaction_s();
+ static menuaction_s s_keys_walk_forward_action = new menuaction_s();
+ static menuaction_s s_keys_backpedal_action = new menuaction_s();
+ static menuaction_s s_keys_turn_left_action = new menuaction_s();
+ static menuaction_s s_keys_turn_right_action = new menuaction_s();
+ static menuaction_s s_keys_run_action = new menuaction_s();
+ static menuaction_s s_keys_step_left_action = new menuaction_s();
+ static menuaction_s s_keys_step_right_action = new menuaction_s();
+ static menuaction_s s_keys_sidestep_action = new menuaction_s();
+ static menuaction_s s_keys_look_up_action = new menuaction_s();
+ static menuaction_s s_keys_look_down_action = new menuaction_s();
+ static menuaction_s s_keys_center_view_action = new menuaction_s();
+ static menuaction_s s_keys_mouse_look_action = new menuaction_s();
+ static menuaction_s s_keys_keyboard_look_action = new menuaction_s();
+ static menuaction_s s_keys_move_up_action = new menuaction_s();
+ static menuaction_s s_keys_move_down_action = new menuaction_s();
+ static menuaction_s s_keys_inventory_action = new menuaction_s();
+ static menuaction_s s_keys_inv_use_action = new menuaction_s();
+ static menuaction_s s_keys_inv_drop_action = new menuaction_s();
+ static menuaction_s s_keys_inv_prev_action = new menuaction_s();
+ static menuaction_s s_keys_inv_next_action = new menuaction_s();
+
+ static menuaction_s s_keys_help_computer_action = new menuaction_s();
+
+ static void UnbindCommand(String command) {
+ int j;
+ int l;
+ String b;
+
+ for (j = 0; j < 256; j++) {
+ b = keybindings[j];
+ if (b == null)
+ continue;
+ if (b.equals(command))
+ Key.SetBinding(j, "");
+ }
+ }
+
+ static void FindKeysForCommand(String command, int twokeys[]) {
+ int count;
+ int j;
+ int l;
+ String b;
+
+ twokeys[0] = twokeys[1] = -1;
+ count = 0;
+
+ for (j = 0; j < 256; j++) {
+ b = keybindings[j];
+ if (b == null)
+ continue;
+
+ if (b.equals(command)) {
+ twokeys[count] = j;
+ count++;
+ if (count == 2)
+ break;
+ }
+ }
+ }
+
+ static void KeyCursorDrawFunc(menuframework_s menu) {
+ if (bind_grab)
+ re.DrawChar(menu.x, menu.y + menu.cursor * 9, '=');
+ else
+ re.DrawChar(menu.x, menu.y + menu.cursor * 9, 12 + ((int) (Sys.Milliseconds() / 250) & 1));
+ }
+
+ static void DrawKeyBindingFunc(Object self) {
+ int keys[] = { 0, 0 };
+ menuaction_s a = (menuaction_s) self;
+
+ FindKeysForCommand(bindnames[a.localdata[0]][0], keys);
+
+ if (keys[0] == -1) {
+ Menu_DrawString(a.x + a.parent.x + 16, a.y + a.parent.y, "???");
+ }
+ else {
+ int x;
+ String name;
+
+ name = Key.KeynumToString(keys[0]);
+
+ Menu_DrawString(a.x + a.parent.x + 16, a.y + a.parent.y, name);
+
+ x = strlen(name) * 8;
+
+ if (keys[1] != -1) {
+ Menu_DrawString(a.x + a.parent.x + 24 + x, a.y + a.parent.y, "or");
+ Menu_DrawString(a.x + a.parent.x + 48 + x, a.y + a.parent.y, Key.KeynumToString(keys[1]));
+ }
+ }
+ }
+
+ static void KeyBindingFunc(Object self) {
+ menuaction_s a = (menuaction_s) self;
+ int keys[] = { 0, 0 };
+
+ FindKeysForCommand(bindnames[a.localdata[0]][0], keys);
+
+ if (keys[1] != -1)
+ UnbindCommand(bindnames[a.localdata[0]][0]);
+
+ bind_grab = true;
+
+ Menu_SetStatusBar(s_keys_menu, "press a key or button for this action");
+ }
+
+ static void Keys_MenuInit() {
+ int y = 0;
+ int i = 0;
+
+ s_keys_menu.x = (int) (viddef.width * 0.50);
+ s_keys_menu.nitems = 0;
+ s_keys_menu.cursordraw = new mcallback() {
+ public void execute(Object o) {
+ KeyCursorDrawFunc((menuframework_s) o);
+ }
+ };
+
+ s_keys_attack_action.type = MTYPE_ACTION;
+ s_keys_attack_action.flags = QMF_GRAYED;
+ s_keys_attack_action.x = 0;
+ s_keys_attack_action.y = y;
+ s_keys_attack_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+ s_keys_attack_action.localdata[0] = i;
+ s_keys_attack_action.name = bindnames[s_keys_attack_action.localdata[0]][1];
+
+ s_keys_change_weapon_action.type = MTYPE_ACTION;
+ s_keys_change_weapon_action.flags = QMF_GRAYED;
+ s_keys_change_weapon_action.x = 0;
+ s_keys_change_weapon_action.y = y += 9;
+ s_keys_change_weapon_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+
+ s_keys_change_weapon_action.localdata[0] = ++i;
+ s_keys_change_weapon_action.name = bindnames[s_keys_change_weapon_action.localdata[0]][1];
+
+ s_keys_walk_forward_action.type = MTYPE_ACTION;
+ s_keys_walk_forward_action.flags = QMF_GRAYED;
+ s_keys_walk_forward_action.x = 0;
+ s_keys_walk_forward_action.y = y += 9;
+ s_keys_walk_forward_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+ s_keys_walk_forward_action.localdata[0] = ++i;
+ s_keys_walk_forward_action.name = bindnames[s_keys_walk_forward_action.localdata[0]][1];
+
+ s_keys_backpedal_action.type = MTYPE_ACTION;
+ s_keys_backpedal_action.flags = QMF_GRAYED;
+ s_keys_backpedal_action.x = 0;
+ s_keys_backpedal_action.y = y += 9;
+ s_keys_backpedal_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+ s_keys_backpedal_action.localdata[0] = ++i;
+ s_keys_backpedal_action.name = bindnames[s_keys_backpedal_action.localdata[0]][1];
+
+ s_keys_turn_left_action.type = MTYPE_ACTION;
+ s_keys_turn_left_action.flags = QMF_GRAYED;
+ s_keys_turn_left_action.x = 0;
+ s_keys_turn_left_action.y = y += 9;
+ s_keys_turn_left_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+ s_keys_turn_left_action.localdata[0] = ++i;
+ s_keys_turn_left_action.name = bindnames[s_keys_turn_left_action.localdata[0]][1];
+
+ s_keys_turn_right_action.type = MTYPE_ACTION;
+ s_keys_turn_right_action.flags = QMF_GRAYED;
+ s_keys_turn_right_action.x = 0;
+ s_keys_turn_right_action.y = y += 9;
+ s_keys_turn_right_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+ s_keys_turn_right_action.localdata[0] = ++i;
+ s_keys_turn_right_action.name = bindnames[s_keys_turn_right_action.localdata[0]][1];
+
+ s_keys_run_action.type = MTYPE_ACTION;
+ s_keys_run_action.flags = QMF_GRAYED;
+ s_keys_run_action.x = 0;
+ s_keys_run_action.y = y += 9;
+ s_keys_run_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+ s_keys_run_action.localdata[0] = ++i;
+ s_keys_run_action.name = bindnames[s_keys_run_action.localdata[0]][1];
+
+ s_keys_step_left_action.type = MTYPE_ACTION;
+ s_keys_step_left_action.flags = QMF_GRAYED;
+ s_keys_step_left_action.x = 0;
+ s_keys_step_left_action.y = y += 9;
+ s_keys_step_left_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+ s_keys_step_left_action.localdata[0] = ++i;
+ s_keys_step_left_action.name = bindnames[s_keys_step_left_action.localdata[0]][1];
+
+ s_keys_step_right_action.type = MTYPE_ACTION;
+ s_keys_step_right_action.flags = QMF_GRAYED;
+ s_keys_step_right_action.x = 0;
+ s_keys_step_right_action.y = y += 9;
+ s_keys_step_right_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+
+ s_keys_step_right_action.localdata[0] = ++i;
+ s_keys_step_right_action.name = bindnames[s_keys_step_right_action.localdata[0]][1];
+
+ s_keys_sidestep_action.type = MTYPE_ACTION;
+ s_keys_sidestep_action.flags = QMF_GRAYED;
+ s_keys_sidestep_action.x = 0;
+ s_keys_sidestep_action.y = y += 9;
+ s_keys_sidestep_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+
+ s_keys_sidestep_action.localdata[0] = ++i;
+ s_keys_sidestep_action.name = bindnames[s_keys_sidestep_action.localdata[0]][1];
+
+ s_keys_look_up_action.type = MTYPE_ACTION;
+ s_keys_look_up_action.flags = QMF_GRAYED;
+ s_keys_look_up_action.x = 0;
+ s_keys_look_up_action.y = y += 9;
+ s_keys_look_up_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+
+ s_keys_look_up_action.localdata[0] = ++i;
+ s_keys_look_up_action.name = bindnames[s_keys_look_up_action.localdata[0]][1];
+
+ s_keys_look_down_action.type = MTYPE_ACTION;
+ s_keys_look_down_action.flags = QMF_GRAYED;
+ s_keys_look_down_action.x = 0;
+ s_keys_look_down_action.y = y += 9;
+ s_keys_look_down_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+
+ s_keys_look_down_action.localdata[0] = ++i;
+ s_keys_look_down_action.name = bindnames[s_keys_look_down_action.localdata[0]][1];
+
+ s_keys_center_view_action.type = MTYPE_ACTION;
+ s_keys_center_view_action.flags = QMF_GRAYED;
+ s_keys_center_view_action.x = 0;
+ s_keys_center_view_action.y = y += 9;
+ s_keys_center_view_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+
+ s_keys_center_view_action.localdata[0] = ++i;
+ s_keys_center_view_action.name = bindnames[s_keys_center_view_action.localdata[0]][1];
+
+ s_keys_mouse_look_action.type = MTYPE_ACTION;
+ s_keys_mouse_look_action.flags = QMF_GRAYED;
+ s_keys_mouse_look_action.x = 0;
+ s_keys_mouse_look_action.y = y += 9;
+ s_keys_mouse_look_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+
+ s_keys_mouse_look_action.localdata[0] = ++i;
+ s_keys_mouse_look_action.name = bindnames[s_keys_mouse_look_action.localdata[0]][1];
+
+ s_keys_keyboard_look_action.type = MTYPE_ACTION;
+ s_keys_keyboard_look_action.flags = QMF_GRAYED;
+ s_keys_keyboard_look_action.x = 0;
+ s_keys_keyboard_look_action.y = y += 9;
+ s_keys_keyboard_look_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+
+ s_keys_keyboard_look_action.localdata[0] = ++i;
+ s_keys_keyboard_look_action.name = bindnames[s_keys_keyboard_look_action.localdata[0]][1];
+
+ s_keys_move_up_action.type = MTYPE_ACTION;
+ s_keys_move_up_action.flags = QMF_GRAYED;
+ s_keys_move_up_action.x = 0;
+ s_keys_move_up_action.y = y += 9;
+ s_keys_move_up_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+
+ s_keys_move_up_action.localdata[0] = ++i;
+ s_keys_move_up_action.name = bindnames[s_keys_move_up_action.localdata[0]][1];
+
+ s_keys_move_down_action.type = MTYPE_ACTION;
+ s_keys_move_down_action.flags = QMF_GRAYED;
+ s_keys_move_down_action.x = 0;
+ s_keys_move_down_action.y = y += 9;
+ s_keys_move_down_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+
+ s_keys_move_down_action.localdata[0] = ++i;
+ s_keys_move_down_action.name = bindnames[s_keys_move_down_action.localdata[0]][1];
+
+ s_keys_inventory_action.type = MTYPE_ACTION;
+ s_keys_inventory_action.flags = QMF_GRAYED;
+ s_keys_inventory_action.x = 0;
+ s_keys_inventory_action.y = y += 9;
+ s_keys_inventory_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+
+ s_keys_inventory_action.localdata[0] = ++i;
+ s_keys_inventory_action.name = bindnames[s_keys_inventory_action.localdata[0]][1];
+
+ s_keys_inv_use_action.type = MTYPE_ACTION;
+ s_keys_inv_use_action.flags = QMF_GRAYED;
+ s_keys_inv_use_action.x = 0;
+ s_keys_inv_use_action.y = y += 9;
+ s_keys_inv_use_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+
+ s_keys_inv_use_action.localdata[0] = ++i;
+ s_keys_inv_use_action.name = bindnames[s_keys_inv_use_action.localdata[0]][1];
+
+ s_keys_inv_drop_action.type = MTYPE_ACTION;
+ s_keys_inv_drop_action.flags = QMF_GRAYED;
+ s_keys_inv_drop_action.x = 0;
+ s_keys_inv_drop_action.y = y += 9;
+ s_keys_inv_drop_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+
+ s_keys_inv_drop_action.localdata[0] = ++i;
+ s_keys_inv_drop_action.name = bindnames[s_keys_inv_drop_action.localdata[0]][1];
+
+ s_keys_inv_prev_action.type = MTYPE_ACTION;
+ s_keys_inv_prev_action.flags = QMF_GRAYED;
+ s_keys_inv_prev_action.x = 0;
+ s_keys_inv_prev_action.y = y += 9;
+ s_keys_inv_prev_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+
+ s_keys_inv_prev_action.localdata[0] = ++i;
+ s_keys_inv_prev_action.name = bindnames[s_keys_inv_prev_action.localdata[0]][1];
+
+ s_keys_inv_next_action.type = MTYPE_ACTION;
+ s_keys_inv_next_action.flags = QMF_GRAYED;
+ s_keys_inv_next_action.x = 0;
+ s_keys_inv_next_action.y = y += 9;
+ s_keys_inv_next_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+
+ s_keys_inv_next_action.localdata[0] = ++i;
+ s_keys_inv_next_action.name = bindnames[s_keys_inv_next_action.localdata[0]][1];
+
+ s_keys_help_computer_action.type = MTYPE_ACTION;
+ s_keys_help_computer_action.flags = QMF_GRAYED;
+ s_keys_help_computer_action.x = 0;
+ s_keys_help_computer_action.y = y += 9;
+ s_keys_help_computer_action.ownerdraw = new mcallback() {
+ public void execute(Object o) {
+ DrawKeyBindingFunc(o);
+ }
+ };
+
+ s_keys_help_computer_action.localdata[0] = ++i;
+ s_keys_help_computer_action.name = bindnames[s_keys_help_computer_action.localdata[0]][1];
+
+ Menu_AddItem(s_keys_menu, s_keys_attack_action);
+ Menu_AddItem(s_keys_menu, s_keys_change_weapon_action);
+ Menu_AddItem(s_keys_menu, s_keys_walk_forward_action);
+ Menu_AddItem(s_keys_menu, s_keys_backpedal_action);
+ Menu_AddItem(s_keys_menu, s_keys_turn_left_action);
+ Menu_AddItem(s_keys_menu, s_keys_turn_right_action);
+ Menu_AddItem(s_keys_menu, s_keys_run_action);
+ Menu_AddItem(s_keys_menu, s_keys_step_left_action);
+ Menu_AddItem(s_keys_menu, s_keys_step_right_action);
+ Menu_AddItem(s_keys_menu, s_keys_sidestep_action);
+ Menu_AddItem(s_keys_menu, s_keys_look_up_action);
+ Menu_AddItem(s_keys_menu, s_keys_look_down_action);
+ Menu_AddItem(s_keys_menu, s_keys_center_view_action);
+ Menu_AddItem(s_keys_menu, s_keys_mouse_look_action);
+ Menu_AddItem(s_keys_menu, s_keys_keyboard_look_action);
+ Menu_AddItem(s_keys_menu, s_keys_move_up_action);
+ Menu_AddItem(s_keys_menu, s_keys_move_down_action);
+
+ Menu_AddItem(s_keys_menu, s_keys_inventory_action);
+ Menu_AddItem(s_keys_menu, s_keys_inv_use_action);
+ Menu_AddItem(s_keys_menu, s_keys_inv_drop_action);
+ Menu_AddItem(s_keys_menu, s_keys_inv_prev_action);
+ Menu_AddItem(s_keys_menu, s_keys_inv_next_action);
+
+ Menu_AddItem(s_keys_menu, s_keys_help_computer_action);
+
+ Menu_SetStatusBar(s_keys_menu, "enter to change, backspace to clear");
+ Menu_Center(s_keys_menu);
+ }
+
+ static xcommand_t Keys_MenuDraw = new xcommand_t() {
+ public void execute() {
+ Keys_MenuDraw_f();
+ }
+ };
+
+ static void Keys_MenuDraw_f() {
+ Menu_AdjustCursor(s_keys_menu, 1);
+ Menu_Draw(s_keys_menu);
+ }
+
+ static keyfunc_t Keys_MenuKey = new keyfunc_t() {
+ public String execute(int key) {
+ return Keys_MenuKey_f(key);
+ }
+ };
+ static String Keys_MenuKey_f(int key) {
+ menuaction_s item = (menuaction_s) Menu_ItemAtCursor(s_keys_menu);
+
+ if (bind_grab) {
+ if (key != K_ESCAPE && key != '`') {
+ //char cmd[1024];
+ String cmd;
+
+ //Com_sprintf(cmd, sizeof(cmd), "bind \"%s\" \"%s\"\n", Key_KeynumToString(key), bindnames[item.localdata[0]][0]);
+ cmd = "bind \"" + Key.KeynumToString(key) + "\" \"" + bindnames[item.localdata[0]][0] + "\"";
+ Cbuf.InsertText(cmd);
+ }
+
+ Menu_SetStatusBar(s_keys_menu, "enter to change, backspace to clear");
+ bind_grab = false;
+ return menu_out_sound;
+ }
+
+ switch (key) {
+ case K_KP_ENTER :
+ case K_ENTER :
+ KeyBindingFunc(item);
+ return menu_in_sound;
+ case K_BACKSPACE : // delete bindings
+ case K_DEL : // delete bindings
+ case K_KP_DEL :
+ UnbindCommand(bindnames[item.localdata[0]][0]);
+ return menu_out_sound;
+ default :
+ return Default_MenuKey(s_keys_menu, key);
+ }
+ }
+
+ static xcommand_t Menu_Keys = new xcommand_t() {
+ public void execute() {
+ Menu_Keys_f();
+ }
+ };
+ static void Menu_Keys_f() {
+ Keys_MenuInit();
+ PushMenu(new xcommand_t() {
+ public void execute() {
+ Keys_MenuDraw_f();
+ }
+ }, new keyfunc_t() {
+ public String execute(int key) {
+ return Keys_MenuKey_f(key);
+ }
+ });
+ }
+
+ /*
+ =======================================================================
+
+ CONTROLS MENU
+
+ =======================================================================
+ */
+ static cvar_t win_noalttab;
+
+ static menuframework_s s_options_menu = new menuframework_s();
+ static menuaction_s s_options_defaults_action = new menuaction_s();
+ static menuaction_s s_options_customize_options_action = new menuaction_s();
+ static menuslider_s s_options_sensitivity_slider = new menuslider_s();
+ static menulist_s s_options_freelook_box = new menulist_s();
+ static menulist_s s_options_noalttab_box = new menulist_s();
+ static menulist_s s_options_alwaysrun_box = new menulist_s();
+ static menulist_s s_options_invertmouse_box = new menulist_s();
+ static menulist_s s_options_lookspring_box = new menulist_s();
+ static menulist_s s_options_lookstrafe_box = new menulist_s();
+ static menulist_s s_options_crosshair_box = new menulist_s();
+ static menuslider_s s_options_sfxvolume_slider = new menuslider_s();
+ static menulist_s s_options_joystick_box = new menulist_s();
+ static menulist_s s_options_cdvolume_box = new menulist_s();
+ static menulist_s s_options_quality_list = new menulist_s();
+ static menulist_s s_options_compatibility_list = new menulist_s();
+ static menuaction_s s_options_console_action = new menuaction_s();
+
+ static void CrosshairFunc(Object unused) {
+ Cvar.SetValue("crosshair", s_options_crosshair_box.curvalue);
+ }
+
+ static void JoystickFunc(Object unused) {
+ Cvar.SetValue("in_joystick", s_options_joystick_box.curvalue);
+ }
+
+ static void CustomizeControlsFunc(Object unused) {
+ Menu_Keys_f();
+ }
+
+ static void AlwaysRunFunc(Object unused) {
+ Cvar.SetValue("cl_run", s_options_alwaysrun_box.curvalue);
+ }
+
+ static void FreeLookFunc(Object unused) {
+ Cvar.SetValue("freelook", s_options_freelook_box.curvalue);
+ }
+
+ static void MouseSpeedFunc(Object unused) {
+ Cvar.SetValue("sensitivity", s_options_sensitivity_slider.curvalue / 2.0F);
+ }
+
+ static void NoAltTabFunc(Object unused) {
+ Cvar.SetValue("win_noalttab", s_options_noalttab_box.curvalue);
+ }
+
+ static float ClampCvar(float min, float max, float value) {
+ if (value < min)
+ return min;
+ if (value > max)
+ return max;
+ return value;
+ }
+
+ static void ControlsSetMenuItemValues() {
+ s_options_sfxvolume_slider.curvalue = Cvar.VariableValue("s_volume") * 10;
+ s_options_cdvolume_box.curvalue = 1 - ((int) Cvar.VariableValue("cd_nocd"));
+ s_options_quality_list.curvalue = 1 - ((int) Cvar.VariableValue("s_loadas8bit"));
+ s_options_sensitivity_slider.curvalue = (sensitivity.value) * 2;
+
+ Cvar.SetValue("cl_run", ClampCvar(0, 1, cl_run.value));
+ s_options_alwaysrun_box.curvalue = (int) cl_run.value;
+
+ s_options_invertmouse_box.curvalue = m_pitch.value < 0 ? 1 : 0;
+
+ Cvar.SetValue("lookspring", ClampCvar(0, 1, lookspring.value));
+ s_options_lookspring_box.curvalue = (int) lookspring.value;
+
+ Cvar.SetValue("lookstrafe", ClampCvar(0, 1, lookstrafe.value));
+ s_options_lookstrafe_box.curvalue = (int) lookstrafe.value;
+
+ Cvar.SetValue("freelook", ClampCvar(0, 1, freelook.value));
+ s_options_freelook_box.curvalue = (int) freelook.value;
+
+ Cvar.SetValue("crosshair", ClampCvar(0, 3, Globals.crosshair.value));
+ s_options_crosshair_box.curvalue = (int) Globals.crosshair.value;
+
+ Cvar.SetValue("in_joystick", ClampCvar(0, 1, in_joystick.value));
+ s_options_joystick_box.curvalue = (int) in_joystick.value;
+
+ s_options_noalttab_box.curvalue = (int) win_noalttab.value;
+ }
+
+ static void ControlsResetDefaultsFunc(Object unused) {
+ Cbuf.AddText("exec default.cfg\n");
+ Cbuf.Execute();
+
+ ControlsSetMenuItemValues();
+ }
+
+ static void InvertMouseFunc(Object unused) {
+ Cvar.SetValue("m_pitch", -m_pitch.value);
+ }
+
+ static void LookspringFunc(Object unused) {
+ Cvar.SetValue("lookspring", 1 - lookspring.value);
+ }
+
+ static void LookstrafeFunc(Object unused) {
+ Cvar.SetValue("lookstrafe", 1 - lookstrafe.value);
+ }
+
+ static void UpdateVolumeFunc(Object unused) {
+ Cvar.SetValue("s_volume", s_options_sfxvolume_slider.curvalue / 10);
+ }
+
+ static void UpdateCDVolumeFunc(Object unused) {
+ Cvar.SetValue("cd_nocd", 1 - s_options_cdvolume_box.curvalue);
+ }
+
+ static void ConsoleFunc(Object unused) {
+ /*
+ ** the proper way to do this is probably to have ToggleConsole_f accept a parameter
+ */
+
+ if (cl.attractloop) {
+ Cbuf.AddText("killserver\n");
+ return;
+ }
+
+ Key.ClearTyping();
+ Console.ClearNotify();
+
+ ForceMenuOff();
+ cls.key_dest = key_console;
+ }
+
+ static void UpdateSoundQualityFunc(Object unused) {
+ if (s_options_quality_list.curvalue != 0) {
+ Cvar.SetValue("s_khz", 22);
+ Cvar.SetValue("s_loadas8bit", 0);
+ }
+ else {
+ Cvar.SetValue("s_khz", 11);
+ Cvar.SetValue("s_loadas8bit", 1);
+ }
+
+ Cvar.SetValue("s_primary", s_options_compatibility_list.curvalue);
+
+ DrawTextBox(8, 120 - 48, 36, 3);
+ Print(16 + 16, 120 - 48 + 8, "Restarting the sound system. This");
+ Print(16 + 16, 120 - 48 + 16, "could take up to a minute, so");
+ Print(16 + 16, 120 - 48 + 24, "please be patient.");
+
+ // the text box won't show up unless we do a buffer swap
+ re.EndFrame();
+
+ CL.Snd_Restart_f.execute();
+ }
+
+ static String cd_music_items[] = { "disabled", "enabled", null };
+ static String quality_items[] = { "low", "high", null };
+
+ static String compatibility_items[] = { "max compatibility", "max performance", null };
+
+ static String yesno_names[] = { "no", "yes", null };
+
+ static String crosshair_names[] = { "none", "cross", "dot", "angle", null };
+
+ static void Options_MenuInit() {
+
+ win_noalttab = Cvar.Get("win_noalttab", "0", CVAR_ARCHIVE);
+
+ /*
+ ** configure controls menu and menu items
+ */
+ s_options_menu.x = viddef.width / 2;
+ s_options_menu.y = viddef.height / 2 - 58;
+ s_options_menu.nitems = 0;
+
+ s_options_sfxvolume_slider.type = MTYPE_SLIDER;
+ s_options_sfxvolume_slider.x = 0;
+ s_options_sfxvolume_slider.y = 0;
+ s_options_sfxvolume_slider.name = "effects volume";
+ s_options_sfxvolume_slider.callback = new mcallback() {
+ public void execute(Object o) {
+ UpdateVolumeFunc(o);
+ }
+ };
+ s_options_sfxvolume_slider.minvalue = 0;
+ s_options_sfxvolume_slider.maxvalue = 10;
+ s_options_sfxvolume_slider.curvalue = Cvar.VariableValue("s_volume") * 10;
+
+ s_options_cdvolume_box.type = MTYPE_SPINCONTROL;
+ s_options_cdvolume_box.x = 0;
+ s_options_cdvolume_box.y = 10;
+ s_options_cdvolume_box.name = "CD music";
+ s_options_cdvolume_box.callback = new mcallback() {
+ public void execute(Object o) {
+ UpdateCDVolumeFunc(o);
+ }
+ };
+ s_options_cdvolume_box.itemnames = cd_music_items;
+ s_options_cdvolume_box.curvalue = 1 - (int) Cvar.VariableValue("cd_nocd");
+
+ s_options_quality_list.type = MTYPE_SPINCONTROL;
+ s_options_quality_list.x = 0;
+ s_options_quality_list.y = 20;
+ ;
+ s_options_quality_list.name = "sound quality";
+ s_options_quality_list.callback = new mcallback() {
+ public void execute(Object o) {
+ UpdateSoundQualityFunc(o);
+ }
+ };
+ s_options_quality_list.itemnames = quality_items;
+ s_options_quality_list.curvalue = 1 - (int) Cvar.VariableValue("s_loadas8bit");
+
+ s_options_compatibility_list.type = MTYPE_SPINCONTROL;
+ s_options_compatibility_list.x = 0;
+ s_options_compatibility_list.y = 30;
+ s_options_compatibility_list.name = "sound compatibility";
+ s_options_compatibility_list.callback = new mcallback() {
+ public void execute(Object o) {
+ UpdateSoundQualityFunc(o);
+ }
+ };
+ s_options_compatibility_list.itemnames = compatibility_items;
+ s_options_compatibility_list.curvalue = (int) Cvar.VariableValue("s_primary");
+
+ s_options_sensitivity_slider.type = MTYPE_SLIDER;
+ s_options_sensitivity_slider.x = 0;
+ s_options_sensitivity_slider.y = 50;
+ s_options_sensitivity_slider.name = "mouse speed";
+ s_options_sensitivity_slider.callback = new mcallback() {
+ public void execute(Object o) {
+ MouseSpeedFunc(o);
+ }
+ };
+ s_options_sensitivity_slider.minvalue = 2;
+ s_options_sensitivity_slider.maxvalue = 22;
+
+ s_options_alwaysrun_box.type = MTYPE_SPINCONTROL;
+ s_options_alwaysrun_box.x = 0;
+ s_options_alwaysrun_box.y = 60;
+ s_options_alwaysrun_box.name = "always run";
+ s_options_alwaysrun_box.callback = new mcallback() {
+ public void execute(Object o) {
+ AlwaysRunFunc(o);
+ }
+ };
+ s_options_alwaysrun_box.itemnames = yesno_names;
+
+ s_options_invertmouse_box.type = MTYPE_SPINCONTROL;
+ s_options_invertmouse_box.x = 0;
+ s_options_invertmouse_box.y = 70;
+ s_options_invertmouse_box.name = "invert mouse";
+ s_options_invertmouse_box.callback = new mcallback() {
+ public void execute(Object o) {
+ InvertMouseFunc(o);
+ }
+ };
+ s_options_invertmouse_box.itemnames = yesno_names;
+
+ s_options_lookspring_box.type = MTYPE_SPINCONTROL;
+ s_options_lookspring_box.x = 0;
+ s_options_lookspring_box.y = 80;
+ s_options_lookspring_box.name = "lookspring";
+ s_options_lookspring_box.callback = new mcallback() {
+ public void execute(Object o) {
+ LookspringFunc(o);
+ }
+ };
+ s_options_lookspring_box.itemnames = yesno_names;
+
+ s_options_lookstrafe_box.type = MTYPE_SPINCONTROL;
+ s_options_lookstrafe_box.x = 0;
+ s_options_lookstrafe_box.y = 90;
+ s_options_lookstrafe_box.name = "lookstrafe";
+ s_options_lookstrafe_box.callback = new mcallback() {
+ public void execute(Object o) {
+ LookstrafeFunc(o);
+ }
+ };
+ s_options_lookstrafe_box.itemnames = yesno_names;
+
+ s_options_freelook_box.type = MTYPE_SPINCONTROL;
+ s_options_freelook_box.x = 0;
+ s_options_freelook_box.y = 100;
+ s_options_freelook_box.name = "free look";
+ s_options_freelook_box.callback = new mcallback() {
+ public void execute(Object o) {
+ FreeLookFunc(o);
+ }
+ };
+ s_options_freelook_box.itemnames = yesno_names;
+
+ s_options_crosshair_box.type = MTYPE_SPINCONTROL;
+ s_options_crosshair_box.x = 0;
+ s_options_crosshair_box.y = 110;
+ s_options_crosshair_box.name = "crosshair";
+ s_options_crosshair_box.callback = new mcallback() {
+ public void execute(Object o) {
+ CrosshairFunc(o);
+ }
+ };
+ s_options_crosshair_box.itemnames = crosshair_names;
+ /*
+ s_options_noalttab_box.type = MTYPE_SPINCONTROL;
+ s_options_noalttab_box.x = 0;
+ s_options_noalttab_box.y = 110;
+ s_options_noalttab_box.name = "disable alt-tab";
+ s_options_noalttab_box.callback = NoAltTabFunc;
+ s_options_noalttab_box.itemnames = yesno_names;
+ */
+ s_options_joystick_box.type = MTYPE_SPINCONTROL;
+ s_options_joystick_box.x = 0;
+ s_options_joystick_box.y = 120;
+ s_options_joystick_box.name = "use joystick";
+ s_options_joystick_box.callback = new mcallback() {
+ public void execute(Object o) {
+ JoystickFunc(o);
+ }
+ };
+ s_options_joystick_box.itemnames = yesno_names;
+
+ s_options_customize_options_action.type = MTYPE_ACTION;
+ s_options_customize_options_action.x = 0;
+ s_options_customize_options_action.y = 140;
+ s_options_customize_options_action.name = "customize controls";
+ s_options_customize_options_action.callback = new mcallback() {
+ public void execute(Object o) {
+ CustomizeControlsFunc(o);
+ }
+ };
+
+ s_options_defaults_action.type = MTYPE_ACTION;
+ s_options_defaults_action.x = 0;
+ s_options_defaults_action.y = 150;
+ s_options_defaults_action.name = "reset defaults";
+ s_options_defaults_action.callback = new mcallback() {
+ public void execute(Object o) {
+ ControlsResetDefaultsFunc(o);
+ }
+ };
+
+ s_options_console_action.type = MTYPE_ACTION;
+ s_options_console_action.x = 0;
+ s_options_console_action.y = 160;
+ s_options_console_action.name = "go to console";
+ s_options_console_action.callback = new mcallback() {
+ public void execute(Object o) {
+ ConsoleFunc(o);
+ }
+ };
+
+ ControlsSetMenuItemValues();
+
+ Menu_AddItem(s_options_menu, s_options_sfxvolume_slider);
+
+ Menu_AddItem(s_options_menu, s_options_cdvolume_box);
+ Menu_AddItem(s_options_menu, s_options_quality_list);
+ Menu_AddItem(s_options_menu, s_options_compatibility_list);
+ Menu_AddItem(s_options_menu, s_options_sensitivity_slider);
+ Menu_AddItem(s_options_menu, s_options_alwaysrun_box);
+ Menu_AddItem(s_options_menu, s_options_invertmouse_box);
+ Menu_AddItem(s_options_menu, s_options_lookspring_box);
+ Menu_AddItem(s_options_menu, s_options_lookstrafe_box);
+ Menu_AddItem(s_options_menu, s_options_freelook_box);
+ Menu_AddItem(s_options_menu, s_options_crosshair_box);
+// Menu_AddItem(s_options_menu, s_options_joystick_box);
+ Menu_AddItem(s_options_menu, s_options_customize_options_action);
+ Menu_AddItem(s_options_menu, s_options_defaults_action);
+ Menu_AddItem(s_options_menu, s_options_console_action);
+ }
+
+ static void Options_MenuDraw() {
+ Banner("m_banner_options");
+ Menu_AdjustCursor(s_options_menu, 1);
+ Menu_Draw(s_options_menu);
+ }
+
+ static String Options_MenuKey(int key) {
+ return Default_MenuKey(s_options_menu, key);
+ }
+
+ static xcommand_t Menu_Options = new xcommand_t() {
+ public void execute() {
+ Menu_Options_f();
+ }
+ };
+
+ static void Menu_Options_f() {
+ Options_MenuInit();
+ PushMenu(new xcommand_t() {
+ public void execute() {
+ Options_MenuDraw();
+ }
+ }, new keyfunc_t() {
+ public String execute(int key) {
+ return Options_MenuKey(key);
+ }
+ });
+ }
+
+ /*
+ =======================================================================
+
+ VIDEO MENU
+
+ =======================================================================
+ */
+
+ static xcommand_t Menu_Video = new xcommand_t() {
+ public void execute() {
+ Menu_Video_f();
+ }
+ };
+
+ static void Menu_Video_f() {
+ VID.MenuInit();
+ PushMenu(new xcommand_t() {
+ public void execute() {
+ VID.MenuDraw();
+ }
+ }, new keyfunc_t() {
+ public String execute(int key) {
+ return VID.MenuKey(key);
+ }
+ });
+ }
+
+ /*
+ =============================================================================
+
+ END GAME MENU
+
+ =============================================================================
+ */
+ static int credits_start_time;
+
+ static String creditsIndex[] = new String[256];
+ static String creditsBuffer;
+ static String idcredits[] =
+ {
+ "+QUAKE II BY ID SOFTWARE",
+ "",
+ "+PROGRAMMING",
+ "John Carmack",
+ "John Cash",
+ "Brian Hook",
+ "",
+ "+JAVA PORT BY JTEAM",
+ "CWEI",
+ "HOZ",
+ "RST",
+ "",
+ "+ART",
+ "Adrian Carmack",
+ "Kevin Cloud",
+ "Paul Steed",
+ "",
+ "+LEVEL DESIGN",
+ "Tim Willits",
+ "American McGee",
+ "Christian Antkow",
+ "Paul Jaquays",
+ "Brandon James",
+ "",
+ "+BIZ",
+ "Todd Hollenshead",
+ "Barrett (Bear) Alexander",
+ "Donna Jackson",
+ "",
+ "",
+ "+SPECIAL THANKS",
+ "Ben Donges for beta testing",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "+ADDITIONAL SUPPORT",
+ "",
+ "+LINUX PORT AND CTF",
+ "Dave \"Zoid\" Kirsch",
+ "",
+ "+CINEMATIC SEQUENCES",
+ "Ending Cinematic by Blur Studio - ",
+ "Venice, CA",
+ "",
+ "Environment models for Introduction",
+ "Cinematic by Karl Dolgener",
+ "",
+ "Assistance with environment design",
+ "by Cliff Iwai",
+ "",
+ "+SOUND EFFECTS AND MUSIC",
+ "Sound Design by Soundelux Media Labs.",
+ "Music Composed and Produced by",
+ "Soundelux Media Labs. Special thanks",
+ "to Bill Brown, Tom Ozanich, Brian",
+ "Celano, Jeff Eisner, and The Soundelux",
+ "Players.",
+ "",
+ "\"Level Music\" by Sonic Mayhem",
+ "www.sonicmayhem.com",
+ "",
+ "\"Quake II Theme Song\"",
+ "(C) 1997 Rob Zombie. All Rights",
+ "Reserved.",
+ "",
+ "Track 10 (\"Climb\") by Jer Sypult",
+ "",
+ "Voice of computers by",
+ "Carly Staehlin-Taylor",
+ "",
+ "+THANKS TO ACTIVISION",
+ "+IN PARTICULAR:",
+ "",
+ "John Tam",
+ "Steve Rosenthal",
+ "Marty Stratton",
+ "Henk Hartong",
+ "",
+ "Quake II(tm) (C)1997 Id Software, Inc.",
+ "All Rights Reserved. Distributed by",
+ "Activision, Inc. under license.",
+ "Quake II(tm), the Id Software name,",
+ "the \"Q II\"(tm) logo and id(tm)",
+ "logo are trademarks of Id Software,",
+ "Inc. Activision(R) is a registered",
+ "trademark of Activision, Inc. All",
+ "other trademarks and trade names are",
+ "properties of their respective owners.",
+ null };
+ static String credits[] = idcredits;
+ static String xatcredits[] =
+ {
+ "+QUAKE II MISSION PACK: THE RECKONING",
+ "+BY",
+ "+XATRIX ENTERTAINMENT, INC.",
+ "",
+ "+DESIGN AND DIRECTION",
+ "Drew Markham",
+ "",
+ "+PRODUCED BY",
+ "Greg Goodrich",
+ "",
+ "+PROGRAMMING",
+ "Rafael Paiz",
+ "",
+ "+LEVEL DESIGN / ADDITIONAL GAME DESIGN",
+ "Alex Mayberry",
+ "",
+ "+LEVEL DESIGN",
+ "Mal Blackwell",
+ "Dan Koppel",
+ "",
+ "+ART DIRECTION",
+ "Michael \"Maxx\" Kaufman",
+ "",
+ "+COMPUTER GRAPHICS SUPERVISOR AND",
+ "+CHARACTER ANIMATION DIRECTION",
+ "Barry Dempsey",
+ "",
+ "+SENIOR ANIMATOR AND MODELER",
+ "Jason Hoover",
+ "",
+ "+CHARACTER ANIMATION AND",
+ "+MOTION CAPTURE SPECIALIST",
+ "Amit Doron",
+ "",
+ "+ART",
+ "Claire Praderie-Markham",
+ "Viktor Antonov",
+ "Corky Lehmkuhl",
+ "",
+ "+INTRODUCTION ANIMATION",
+ "Dominique Drozdz",
+ "",
+ "+ADDITIONAL LEVEL DESIGN",
+ "Aaron Barber",
+ "Rhett Baldwin",
+ "",
+ "+3D CHARACTER ANIMATION TOOLS",
+ "Gerry Tyra, SA Technology",
+ "",
+ "+ADDITIONAL EDITOR TOOL PROGRAMMING",
+ "Robert Duffy",
+ "",
+ "+ADDITIONAL PROGRAMMING",
+ "Ryan Feltrin",
+ "",
+ "+PRODUCTION COORDINATOR",
+ "Victoria Sylvester",
+ "",
+ "+SOUND DESIGN",
+ "Gary Bradfield",
+ "",
+ "+MUSIC BY",
+ "Sonic Mayhem",
+ "",
+ "",
+ "",
+ "+SPECIAL THANKS",
+ "+TO",
+ "+OUR FRIENDS AT ID SOFTWARE",
+ "",
+ "John Carmack",
+ "John Cash",
+ "Brian Hook",
+ "Adrian Carmack",
+ "Kevin Cloud",
+ "Paul Steed",
+ "Tim Willits",
+ "Christian Antkow",
+ "Paul Jaquays",
+ "Brandon James",
+ "Todd Hollenshead",
+ "Barrett (Bear) Alexander",
+ "Dave \"Zoid\" Kirsch",
+ "Donna Jackson",
+ "",
+ "",
+ "",
+ "+THANKS TO ACTIVISION",
+ "+IN PARTICULAR:",
+ "",
+ "Marty Stratton",
+ "Henk \"The Original Ripper\" Hartong",
+ "Kevin Kraff",
+ "Jamey Gottlieb",
+ "Chris Hepburn",
+ "",
+ "+AND THE GAME TESTERS",
+ "",
+ "Tim Vanlaw",
+ "Doug Jacobs",
+ "Steven Rosenthal",
+ "David Baker",
+ "Chris Campbell",
+ "Aaron Casillas",
+ "Steve Elwell",
+ "Derek Johnstone",
+ "Igor Krinitskiy",
+ "Samantha Lee",
+ "Michael Spann",
+ "Chris Toft",
+ "Juan Valdes",
+ "",
+ "+THANKS TO INTERGRAPH COMPUTER SYTEMS",
+ "+IN PARTICULAR:",
+ "",
+ "Michael T. Nicolaou",
+ "",
+ "",
+ "Quake II Mission Pack: The Reckoning",
+ "(tm) (C)1998 Id Software, Inc. All",
+ "Rights Reserved. Developed by Xatrix",
+ "Entertainment, Inc. for Id Software,",
+ "Inc. Distributed by Activision Inc.",
+ "under license. Quake(R) is a",
+ "registered trademark of Id Software,",
+ "Inc. Quake II Mission Pack: The",
+ "Reckoning(tm), Quake II(tm), the Id",
+ "Software name, the \"Q II\"(tm) logo",
+ "and id(tm) logo are trademarks of Id",
+ "Software, Inc. Activision(R) is a",
+ "registered trademark of Activision,",
+ "Inc. Xatrix(R) is a registered",
+ "trademark of Xatrix Entertainment,",
+ "Inc. All other trademarks and trade",
+ "names are properties of their",
+ "respective owners.",
+ null };
+
+ static String roguecredits[] =
+ {
+ "+QUAKE II MISSION PACK 2: GROUND ZERO",
+ "+BY",
+ "+ROGUE ENTERTAINMENT, INC.",
+ "",
+ "+PRODUCED BY",
+ "Jim Molinets",
+ "",
+ "+PROGRAMMING",
+ "Peter Mack",
+ "Patrick Magruder",
+ "",
+ "+LEVEL DESIGN",
+ "Jim Molinets",
+ "Cameron Lamprecht",
+ "Berenger Fish",
+ "Robert Selitto",
+ "Steve Tietze",
+ "Steve Thoms",
+ "",
+ "+ART DIRECTION",
+ "Rich Fleider",
+ "",
+ "+ART",
+ "Rich Fleider",
+ "Steve Maines",
+ "Won Choi",
+ "",
+ "+ANIMATION SEQUENCES",
+ "Creat Studios",
+ "Steve Maines",
+ "",
+ "+ADDITIONAL LEVEL DESIGN",
+ "Rich Fleider",
+ "Steve Maines",
+ "Peter Mack",
+ "",
+ "+SOUND",
+ "James Grunke",
+ "",
+ "+GROUND ZERO THEME",
+ "+AND",
+ "+MUSIC BY",
+ "Sonic Mayhem",
+ "",
+ "+VWEP MODELS",
+ "Brent \"Hentai\" Dill",
+ "",
+ "",
+ "",
+ "+SPECIAL THANKS",
+ "+TO",
+ "+OUR FRIENDS AT ID SOFTWARE",
+ "",
+ "John Carmack",
+ "John Cash",
+ "Brian Hook",
+ "Adrian Carmack",
+ "Kevin Cloud",
+ "Paul Steed",
+ "Tim Willits",
+ "Christian Antkow",
+ "Paul Jaquays",
+ "Brandon James",
+ "Todd Hollenshead",
+ "Barrett (Bear) Alexander",
+ "Katherine Anna Kang",
+ "Donna Jackson",
+ "Dave \"Zoid\" Kirsch",
+ "",
+ "",
+ "",
+ "+THANKS TO ACTIVISION",
+ "+IN PARTICULAR:",
+ "",
+ "Marty Stratton",
+ "Henk Hartong",
+ "Mitch Lasky",
+ "Steve Rosenthal",
+ "Steve Elwell",
+ "",
+ "+AND THE GAME TESTERS",
+ "",
+ "The Ranger Clan",
+ "Dave \"Zoid\" Kirsch",
+ "Nihilistic Software",
+ "Robert Duffy",
+ "",
+ "And Countless Others",
+ "",
+ "",
+ "",
+ "Quake II Mission Pack 2: Ground Zero",
+ "(tm) (C)1998 Id Software, Inc. All",
+ "Rights Reserved. Developed by Rogue",
+ "Entertainment, Inc. for Id Software,",
+ "Inc. Distributed by Activision Inc.",
+ "under license. Quake(R) is a",
+ "registered trademark of Id Software,",
+ "Inc. Quake II Mission Pack 2: Ground",
+ "Zero(tm), Quake II(tm), the Id",
+ "Software name, the \"Q II\"(tm) logo",
+ "and id(tm) logo are trademarks of Id",
+ "Software, Inc. Activision(R) is a",
+ "registered trademark of Activision,",
+ "Inc. Rogue(R) is a registered",
+ "trademark of Rogue Entertainment,",
+ "Inc. All other trademarks and trade",
+ "names are properties of their",
+ "respective owners.",
+ null };
+
+ public static void Credits_MenuDraw() {
+ int i, y;
+
+ /*
+ ** draw the credits
+ */
+ for (i = 0, y = (int) (viddef.height - ((cls.realtime - credits_start_time) / 40.0F));
+ credits[i] != null && y < viddef.height;
+ y += 10, i++) {
+ int j, stringoffset = 0;
+ boolean bold = false;
+
+ if (y <= -8)
+ continue;
+
+ if (credits[i].length() > 0 && credits[i].charAt(0) == '+') {
+ bold = true;
+ stringoffset = 1;
+ }
+ else {
+ bold = false;
+ stringoffset = 0;
+ }
+
+ for (j = 0; j + stringoffset < credits[i].length(); j++) {
+ int x;
+
+ x = (viddef.width - strlen(credits[i]) * 8 - stringoffset * 8) / 2 + (j + stringoffset) * 8;
+
+ if (bold)
+ re.DrawChar(x, y, credits[i].charAt(j + stringoffset) + 128);
+ else
+ re.DrawChar(x, y, credits[i].charAt(j + stringoffset));
+ }
+ }
+
+ if (y < 0)
+ credits_start_time = cls.realtime;
+ }
+
+ public static String Credits_Key(int key) {
+ switch (key) {
+ case K_ESCAPE :
+ if (creditsBuffer != null)
+ //FS.FreeFile(creditsBuffer);
+ ;
+ PopMenu();
+ break;
+ }
+
+ return menu_out_sound;
+
+ }
+
+ static xcommand_t Menu_Credits = new xcommand_t() {
+ public void execute() {
+ Menu_Credits_f();
+ }
+ };
+ static void Menu_Credits_f() {
+ int n;
+ int count;
+ String p;
+ int isdeveloper = 0;
+
+ byte b[] = FS.LoadFile("credits");
+
+ if (b != null) {
+ creditsBuffer = new String(b);
+ String line[] = Lib.linesplit(creditsBuffer);
+
+ for (n = 0; n < line.length; n++) {
+ creditsIndex[n] = line[n];
+ }
+
+ creditsIndex[n] = null;
+ credits = creditsIndex;
+ }
+ else {
+ isdeveloper = FS.Developer_searchpath(1);
+
+ if (isdeveloper == 1) // xatrix
+ credits = xatcredits;
+ else if (isdeveloper == 2) // ROGUE
+ credits = roguecredits;
+ else {
+ credits = idcredits;
+ }
+
+ }
+
+ credits_start_time = cls.realtime;
+ PushMenu(new xcommand_t() {
+ public void execute() {
+ Credits_MenuDraw();
+ }
+ }, new keyfunc_t() {
+ public String execute(int key) {
+ return Credits_Key(key);
+ }
+ });
+ }
+
+ /*
+ =============================================================================
+
+ GAME MENU
+
+ =============================================================================
+ */
+
+ static int m_game_cursor;
+
+ static menuframework_s s_game_menu = new menuframework_s();
+ static menuaction_s s_easy_game_action = new menuaction_s();
+ static menuaction_s s_medium_game_action = new menuaction_s();
+ static menuaction_s s_hard_game_action = new menuaction_s();
+ static menuaction_s s_load_game_action = new menuaction_s();
+ static menuaction_s s_save_game_action = new menuaction_s();
+ static menuaction_s s_credits_action = new menuaction_s();
+ static menuseparator_s s_blankline = new menuseparator_s();
+
+ static void StartGame() {
+ // disable updates and start the cinematic going
+ cl.servercount = -1;
+ ForceMenuOff();
+ Cvar.SetValue("deathmatch", 0);
+ Cvar.SetValue("coop", 0);
+
+ Cvar.SetValue("gamerules", 0); //PGM
+
+ Cbuf.AddText("loading ; killserver ; wait ; newgame\n");
+ cls.key_dest = key_game;
+ }
+
+ static void EasyGameFunc(Object data) {
+ Cvar.ForceSet("skill", "0");
+ StartGame();
+ }
+
+ static void MediumGameFunc(Object data) {
+ Cvar.ForceSet("skill", "1");
+ StartGame();
+ }
+
+ static void HardGameFunc(Object data) {
+ Cvar.ForceSet("skill", "2");
+ StartGame();
+ }
+
+ static void LoadGameFunc(Object unused) {
+ Menu_LoadGame_f();
+ }
+
+ static void SaveGameFunc(Object unused) {
+ Menu_SaveGame_f();
+ }
+
+ static void CreditsFunc(Object unused) {
+ Menu_Credits_f();
+ }
+
+ static String difficulty_names[] = { "easy", "medium", "fuckin shitty hard", null };
+ static void Game_MenuInit() {
+
+ s_game_menu.x = (int) (viddef.width * 0.50);
+ s_game_menu.nitems = 0;
+
+ s_easy_game_action.type = MTYPE_ACTION;
+ s_easy_game_action.flags = QMF_LEFT_JUSTIFY;
+ s_easy_game_action.x = 0;
+ s_easy_game_action.y = 0;
+ s_easy_game_action.name = "easy";
+ s_easy_game_action.callback = new mcallback() {
+ public void execute(Object o) {
+ EasyGameFunc(o);
+ }
+ };
+
+ s_medium_game_action.type = MTYPE_ACTION;
+ s_medium_game_action.flags = QMF_LEFT_JUSTIFY;
+ s_medium_game_action.x = 0;
+ s_medium_game_action.y = 10;
+ s_medium_game_action.name = "medium";
+ s_medium_game_action.callback = new mcallback() {
+ public void execute(Object o) {
+ MediumGameFunc(o);
+ }
+ };
+
+ s_hard_game_action.type = MTYPE_ACTION;
+ s_hard_game_action.flags = QMF_LEFT_JUSTIFY;
+ s_hard_game_action.x = 0;
+ s_hard_game_action.y = 20;
+ s_hard_game_action.name = "hard";
+ s_hard_game_action.callback = new mcallback() {
+ public void execute(Object o) {
+ HardGameFunc(o);
+ }
+ };
+
+ s_blankline.type = MTYPE_SEPARATOR;
+
+ s_load_game_action.type = MTYPE_ACTION;
+ s_load_game_action.flags = QMF_LEFT_JUSTIFY;
+ s_load_game_action.x = 0;
+ s_load_game_action.y = 40;
+ s_load_game_action.name = "load game";
+ s_load_game_action.callback = new mcallback() {
+ public void execute(Object o) {
+ LoadGameFunc(o);
+ }
+ };
+
+ s_save_game_action.type = MTYPE_ACTION;
+ s_save_game_action.flags = QMF_LEFT_JUSTIFY;
+ s_save_game_action.x = 0;
+ s_save_game_action.y = 50;
+ s_save_game_action.name = "save game";
+ s_save_game_action.callback = new mcallback() {
+ public void execute(Object o) {
+ SaveGameFunc(o);
+ }
+ };
+
+ s_credits_action.type = MTYPE_ACTION;
+ s_credits_action.flags = QMF_LEFT_JUSTIFY;
+ s_credits_action.x = 0;
+ s_credits_action.y = 60;
+ s_credits_action.name = "credits";
+ s_credits_action.callback = new mcallback() {
+ public void execute(Object o) {
+ CreditsFunc(o);
+ }
+ };
+
+ Menu_AddItem(s_game_menu, s_easy_game_action);
+ Menu_AddItem(s_game_menu, s_medium_game_action);
+ Menu_AddItem(s_game_menu, s_hard_game_action);
+ Menu_AddItem(s_game_menu, s_blankline);
+ Menu_AddItem(s_game_menu, s_load_game_action);
+ Menu_AddItem(s_game_menu, s_save_game_action);
+ Menu_AddItem(s_game_menu, s_blankline);
+ Menu_AddItem(s_game_menu, s_credits_action);
+
+ Menu_Center(s_game_menu);
+ }
+
+ static void Game_MenuDraw() {
+ Banner("m_banner_game");
+ Menu_AdjustCursor(s_game_menu, 1);
+ Menu_Draw(s_game_menu);
+ }
+
+ static String Game_MenuKey(int key) {
+ return Default_MenuKey(s_game_menu, key);
+ }
+
+ static xcommand_t Menu_Game = new xcommand_t() {
+ public void execute() {
+ Menu_Game_f();
+ }
+ };
+
+ static void Menu_Game_f() {
+ Game_MenuInit();
+ PushMenu(new xcommand_t() {
+ public void execute() {
+ Game_MenuDraw();
+ }
+ }, new keyfunc_t() {
+ public String execute(int key) {
+ return Game_MenuKey(key);
+ }
+ });
+ m_game_cursor = 1;
+ }
+
+ /*
+ =============================================================================
+
+ LOADGAME MENU
+
+ =============================================================================
+ */
+
+ public final static int MAX_SAVEGAMES = 15;
+
+ static menuframework_s s_savegame_menu = new menuframework_s();
+ static menuframework_s s_loadgame_menu = new menuframework_s();
+
+ static menuaction_s s_loadgame_actions[] = new menuaction_s[MAX_SAVEGAMES];
+
+ static {
+ for (int n = 0; n < MAX_SAVEGAMES; n++)
+ s_loadgame_actions[n] = new menuaction_s();
+ }
+
+ //String m_savestrings[] = new String [MAX_SAVEGAMES][32];
+ static String m_savestrings[] = new String[MAX_SAVEGAMES];
+
+ static {
+ for (int n = 0; n < MAX_SAVEGAMES; n++)
+ m_savestrings[n] = "";
+ }
+
+ static boolean m_savevalid[] = new boolean[MAX_SAVEGAMES];
+
+ static void Create_Savestrings() {
+ int i;
+ RandomAccessFile f;
+ //char name[MAX_OSPATH];
+ String name;
+
+ for (i = 0; i < MAX_SAVEGAMES; i++) {
+ name = FS.Gamedir() + "/save/save" + i + "/server.ssv";
+ f = fopen(name, "r");
+ if (f == null) {
+ m_savestrings[i] = "<EMPTY>";
+ m_savevalid[i] = false;
+ }
+ else {
+ m_savestrings[i] = freadString(f, 32);
+ fclose(f);
+ m_savevalid[i] = true;
+ }
+ }
+ }
+
+ static void LoadGameCallback(Object self) {
+ menuaction_s a = (menuaction_s) self;
+
+ if (m_savevalid[a.localdata[0]])
+ Cbuf.AddText("load save" + a.localdata[0] + "\n");
+ ForceMenuOff();
+ }
+
+ static void LoadGame_MenuInit() {
+ int i;
+
+ s_loadgame_menu.x = viddef.width / 2 - 120;
+ s_loadgame_menu.y = viddef.height / 2 - 58;
+ s_loadgame_menu.nitems = 0;
+
+ Create_Savestrings();
+
+ for (i = 0; i < MAX_SAVEGAMES; i++) {
+ s_loadgame_actions[i].name = m_savestrings[i];
+ s_loadgame_actions[i].flags = QMF_LEFT_JUSTIFY;
+ s_loadgame_actions[i].localdata[0] = i;
+ s_loadgame_actions[i].callback = new mcallback() {
+ public void execute(Object o) {
+ LoadGameCallback(o);
+ }
+ };
+
+ s_loadgame_actions[i].x = 0;
+ s_loadgame_actions[i].y = (i) * 10;
+ if (i > 0) // separate from autosave
+ s_loadgame_actions[i].y += 10;
+
+ s_loadgame_actions[i].type = MTYPE_ACTION;
+
+ Menu_AddItem(s_loadgame_menu, s_loadgame_actions[i]);
+ }
+ }
+
+ static void LoadGame_MenuDraw() {
+ Banner("m_banner_load_game");
+ // Menu_AdjustCursor( &s_loadgame_menu, 1 );
+ Menu_Draw(s_loadgame_menu);
+ }
+
+ static String LoadGame_MenuKey(int key) {
+ if (key == K_ESCAPE || key == K_ENTER) {
+ s_savegame_menu.cursor = s_loadgame_menu.cursor - 1;
+ if (s_savegame_menu.cursor < 0)
+ s_savegame_menu.cursor = 0;
+ }
+ return Default_MenuKey(s_loadgame_menu, key);
+ }
+
+ static xcommand_t Menu_LoadGame = new xcommand_t() {
+ public void execute() {
+ Menu_LoadGame_f();
+ }
+ };
+ static void Menu_LoadGame_f() {
+ LoadGame_MenuInit();
+ PushMenu(new xcommand_t() {
+ public void execute() {
+ LoadGame_MenuDraw();
+ }
+ }, new keyfunc_t() {
+ public String execute(int key) {
+ return LoadGame_MenuKey(key);
+ }
+ });
+ }
+
+ /*
+ =============================================================================
+
+ SAVEGAME MENU
+
+ =============================================================================
+ */
+ //static menuframework_s s_savegame_menu;
+ static menuaction_s s_savegame_actions[] = new menuaction_s[MAX_SAVEGAMES];
+
+ static void SaveGameCallback(Object self) {
+ menuaction_s a = (menuaction_s) self;
+
+ Cbuf.AddText("save save" + a.localdata[0] + "\n");
+ ForceMenuOff();
+ }
+
+ static void SaveGame_MenuDraw() {
+ Banner("m_banner_save_game");
+ Menu_AdjustCursor(s_savegame_menu, 1);
+ Menu_Draw(s_savegame_menu);
+ }
+
+ static void SaveGame_MenuInit() {
+ int i;
+
+ s_savegame_menu.x = viddef.width / 2 - 120;
+ s_savegame_menu.y = viddef.height / 2 - 58;
+ s_savegame_menu.nitems = 0;
+
+ Create_Savestrings();
+
+ // don't include the autosave slot
+ for (i = 0; i < MAX_SAVEGAMES - 1; i++) {
+ s_savegame_actions[i].name = m_savestrings[i + 1];
+ s_savegame_actions[i].localdata[0] = i + 1;
+ s_savegame_actions[i].flags = QMF_LEFT_JUSTIFY;
+ s_savegame_actions[i].callback = new mcallback() {
+ public void execute(Object o) {
+ SaveGameCallback(o);
+ }
+ };
+
+ s_savegame_actions[i].x = 0;
+ s_savegame_actions[i].y = (i) * 10;
+
+ s_savegame_actions[i].type = MTYPE_ACTION;
+
+ Menu_AddItem(s_savegame_menu, s_savegame_actions[i]);
+ }
+ }
+
+ static String SaveGame_MenuKey(int key) {
+ if (key == K_ENTER || key == K_ESCAPE) {
+ s_loadgame_menu.cursor = s_savegame_menu.cursor - 1;
+ if (s_loadgame_menu.cursor < 0)
+ s_loadgame_menu.cursor = 0;
+ }
+ return Default_MenuKey(s_savegame_menu, key);
+ }
+
+ static xcommand_t Menu_SaveGame = new xcommand_t() {
+ public void execute() {
+ Menu_SaveGame_f();
+ }
+ };
+ static void Menu_SaveGame_f() {
+ if (0 == Com.ServerState())
+ return; // not playing a game
+
+ SaveGame_MenuInit();
+ PushMenu(new xcommand_t() {
+ public void execute() {
+ SaveGame_MenuDraw();
+ }
+ }, new keyfunc_t() {
+ public String execute(int key) {
+ return SaveGame_MenuKey(key);
+ }
+ });
+ Create_Savestrings();
+ }
+
+ /*
+ =============================================================================
+
+ JOIN SERVER MENU
+
+ =============================================================================
+ */
+
+ static menuframework_s s_joinserver_menu = new menuframework_s();
+ static menuseparator_s s_joinserver_server_title = new menuseparator_s();
+ static menuaction_s s_joinserver_search_action = new menuaction_s();
+ static menuaction_s s_joinserver_address_book_action = new menuaction_s();
+
+ static netadr_t local_server_netadr[] = new netadr_t[MAX_LOCAL_SERVERS];
+ static String local_server_names[] = new String[MAX_LOCAL_SERVERS]; //[80];
+ static menuaction_s s_joinserver_server_actions[] = new menuaction_s[MAX_LOCAL_SERVERS];
+
+ // user readable information
+ // network address
+ static {
+ for (int n = 0; n < MAX_LOCAL_SERVERS; n++) {
+ local_server_netadr[n] = new netadr_t();
+ local_server_names[n] = "";
+ s_joinserver_server_actions[n] = new menuaction_s();
+ s_joinserver_server_actions[n].n = n;
+ }
+ }
+
+ static int m_num_servers;
+
+ static void AddToServerList(netadr_t adr, String info) {
+ int i;
+
+ if (m_num_servers == MAX_LOCAL_SERVERS)
+ return;
+
+ String x = info.trim();
+
+ // ignore if duplicated
+ for (i = 0; i < m_num_servers; i++)
+ if (0 == strcmp(x, local_server_names[i]))
+ return;
+
+ local_server_netadr[m_num_servers] = adr;
+ local_server_names[m_num_servers] = x;
+ m_num_servers++;
+ }
+
+ static void JoinServerFunc(Object self) {
+ String buffer;
+ int index;
+
+ index = ((menucommon_s) self).n;
+
+ if (Q_stricmp(local_server_names[index], NO_SERVER_STRING) == 0)
+ return;
+
+ if (index >= m_num_servers)
+ return;
+
+ buffer = "connect " + NET.AdrToString(local_server_netadr[index]) + "\n";
+ Cbuf.AddText(buffer);
+ ForceMenuOff();
+ }
+
+ static void AddressBookFunc(Object self) {
+ Menu_AddressBook_f();
+ }
+
+ static void NullCursorDraw(Object self) {
+ }
+
+ static void SearchLocalGames() {
+ int i;
+
+ m_num_servers = 0;
+ for (i = 0; i < MAX_LOCAL_SERVERS; i++)
+ local_server_names[i] = NO_SERVER_STRING;
+
+ DrawTextBox(8, 120 - 48, 36, 3);
+ Print(16 + 16, 120 - 48 + 8, "Searching for local servers, this");
+ Print(16 + 16, 120 - 48 + 16, "could take up to a minute, so");
+ Print(16 + 16, 120 - 48 + 24, "please be patient.");
+
+ // the text box won't show up unless we do a buffer swap
+ re.EndFrame();
+
+ // send out info packets
+ CL.PingServers_f.execute();
+ }
+
+ static void SearchLocalGamesFunc(Object self) {
+ SearchLocalGames();
+ }
+
+ static void JoinServer_MenuInit() {
+ int i;
+
+ s_joinserver_menu.x = (int) (viddef.width * 0.50 - 120);
+ s_joinserver_menu.nitems = 0;
+
+ s_joinserver_address_book_action.type = MTYPE_ACTION;
+ s_joinserver_address_book_action.name = "address book";
+ s_joinserver_address_book_action.flags = QMF_LEFT_JUSTIFY;
+ s_joinserver_address_book_action.x = 0;
+ s_joinserver_address_book_action.y = 0;
+ s_joinserver_address_book_action.callback = new mcallback() {
+ public void execute(Object o) {
+ AddressBookFunc(o);
+ }
+ };
+
+ s_joinserver_search_action.type = MTYPE_ACTION;
+ s_joinserver_search_action.name = "refresh server list";
+ s_joinserver_search_action.flags = QMF_LEFT_JUSTIFY;
+ s_joinserver_search_action.x = 0;
+ s_joinserver_search_action.y = 10;
+ s_joinserver_search_action.callback = new mcallback() {
+ public void execute(Object o) {
+ SearchLocalGamesFunc(o);
+ }
+ };
+ s_joinserver_search_action.statusbar = "search for servers";
+
+ s_joinserver_server_title.type = MTYPE_SEPARATOR;
+ s_joinserver_server_title.name = "connect to...";
+ s_joinserver_server_title.x = 80;
+ s_joinserver_server_title.y = 30;
+
+ for (i = 0; i < MAX_LOCAL_SERVERS; i++) {
+ s_joinserver_server_actions[i].type = MTYPE_ACTION;
+ local_server_names[i] = NO_SERVER_STRING;
+ s_joinserver_server_actions[i].name = local_server_names[i];
+ s_joinserver_server_actions[i].flags = QMF_LEFT_JUSTIFY;
+ s_joinserver_server_actions[i].x = 0;
+ s_joinserver_server_actions[i].y = 40 + i * 10;
+ s_joinserver_server_actions[i].callback = new mcallback() {
+ public void execute(Object o) {
+ JoinServerFunc(o);
+ }
+ };
+ s_joinserver_server_actions[i].statusbar = "press ENTER to connect";
+ }
+
+ Menu_AddItem(s_joinserver_menu, s_joinserver_address_book_action);
+ Menu_AddItem(s_joinserver_menu, s_joinserver_server_title);
+ Menu_AddItem(s_joinserver_menu, s_joinserver_search_action);
+
+ for (i = 0; i < 8; i++)
+ Menu_AddItem(s_joinserver_menu, s_joinserver_server_actions[i]);
+
+ Menu_Center(s_joinserver_menu);
+
+ SearchLocalGames();
+ }
+
+ static void JoinServer_MenuDraw() {
+ Banner("m_banner_join_server");
+ Menu_Draw(s_joinserver_menu);
+ }
+
+ static String JoinServer_MenuKey(int key) {
+ return Default_MenuKey(s_joinserver_menu, key);
+ }
+
+ static xcommand_t Menu_JoinServer = new xcommand_t() {
+ public void execute() {
+ Menu_JoinServer_f();
+ }
+ };
+ static void Menu_JoinServer_f() {
+ JoinServer_MenuInit();
+ PushMenu(new xcommand_t() {
+ public void execute() {
+ JoinServer_MenuDraw();
+ }
+ }, new keyfunc_t() {
+ public String execute(int key) {
+ return JoinServer_MenuKey(key);
+ }
+ });
+ }
+
+ /*
+ =============================================================================
+
+ START SERVER MENU
+
+ =============================================================================
+ */
+ static menuframework_s s_startserver_menu = new menuframework_s();
+ static String mapnames[];
+ static int nummaps;
+
+ static menuaction_s s_startserver_start_action = new menuaction_s();
+ static menuaction_s s_startserver_dmoptions_action = new menuaction_s();
+ static menufield_s s_timelimit_field = new menufield_s();
+ static menufield_s s_fraglimit_field = new menufield_s();
+ static menufield_s s_maxclients_field = new menufield_s();
+ static menufield_s s_hostname_field = new menufield_s();
+ static menulist_s s_startmap_list = new menulist_s();
+ static menulist_s s_rules_box = new menulist_s();
+
+ static void DMOptionsFunc(Object self) {
+ if (s_rules_box.curvalue == 1)
+ return;
+ Menu_DMOptions_f();
+ }
+
+ static void RulesChangeFunc(Object self) {
+ // DM
+ if (s_rules_box.curvalue == 0) {
+ s_maxclients_field.statusbar = null;
+ s_startserver_dmoptions_action.statusbar = null;
+ }
+ else if (s_rules_box.curvalue == 1)
+ // coop // PGM
+ {
+ s_maxclients_field.statusbar = "4 maximum for cooperative";
+ if (atoi(s_maxclients_field.buffer.toString()) > 4)
+ s_maxclients_field.buffer = new StringBuffer("4");
+ s_startserver_dmoptions_action.statusbar = "N/A for cooperative";
+ }
+ // =====
+ // PGM
+ // ROGUE GAMES
+ else if (FS.Developer_searchpath(2) == 2) {
+ if (s_rules_box.curvalue == 2) // tag
+ {
+ s_maxclients_field.statusbar = null;
+ s_startserver_dmoptions_action.statusbar = null;
+ }
+ /*
+ else if(s_rules_box.curvalue == 3) // deathball
+ {
+ s_maxclients_field.statusbar = null;
+ s_startserver_dmoptions_action.statusbar = null;
+ }
+ */
+ }
+ // PGM
+ // =====
+ }
+
+ static void StartServerActionFunc(Object self) {
+ //char startmap[1024];
+ String startmap;
+ int timelimit;
+ int fraglimit;
+ int maxclients;
+ String spot;
+
+ //strcpy(startmap, strchr(mapnames[s_startmap_list.curvalue], '\n') + 1);
+ String x = mapnames[s_startmap_list.curvalue];
+
+ int pos = x.indexOf('\n');
+ if (pos == -1)
+ startmap = x;
+ else
+ startmap = x.substring(pos + 1, x.length());
+
+ maxclients = atoi(s_maxclients_field.buffer.toString());
+ timelimit = atoi(s_timelimit_field.buffer.toString());
+ fraglimit = atoi(s_fraglimit_field.buffer.toString());
+
+ Cvar.SetValue("maxclients", ClampCvar(0, maxclients, maxclients));
+ Cvar.SetValue("timelimit", ClampCvar(0, timelimit, timelimit));
+ Cvar.SetValue("fraglimit", ClampCvar(0, fraglimit, fraglimit));
+ Cvar.Set("hostname", s_hostname_field.buffer.toString());
+ // Cvar.SetValue ("deathmatch", !s_rules_box.curvalue );
+ // Cvar.SetValue ("coop", s_rules_box.curvalue );
+
+ // PGM
+ if ((s_rules_box.curvalue < 2) || (FS.Developer_searchpath(2) != 2)) {
+ Cvar.SetValue("deathmatch", 1 - (int) (s_rules_box.curvalue));
+ Cvar.SetValue("coop", s_rules_box.curvalue);
+ Cvar.SetValue("gamerules", 0);
+ }
+ else {
+ Cvar.SetValue("deathmatch", 1);
+ // deathmatch is always true for rogue games, right?
+ Cvar.SetValue("coop", 0);
+ // FIXME - this might need to depend on which game we're running
+ Cvar.SetValue("gamerules", s_rules_box.curvalue);
+ }
+ // PGM
+
+ spot = null;
+ if (s_rules_box.curvalue == 1) // PGM
+ {
+ if (Q_stricmp(startmap, "bunk1") == 0)
+ spot = "start";
+ else if (Q_stricmp(startmap, "mintro") == 0)
+ spot = "start";
+ else if (Q_stricmp(startmap, "fact1") == 0)
+ spot = "start";
+ else if (Q_stricmp(startmap, "power1") == 0)
+ spot = "pstart";
+ else if (Q_stricmp(startmap, "biggun") == 0)
+ spot = "bstart";
+ else if (Q_stricmp(startmap, "hangar1") == 0)
+ spot = "unitstart";
+ else if (Q_stricmp(startmap, "city1") == 0)
+ spot = "unitstart";
+ else if (Q_stricmp(startmap, "boss1") == 0)
+ spot = "bosstart";
+ }
+
+ if (spot != null) {
+ if (Com.ServerState() != 0)
+ Cbuf.AddText("disconnect\n");
+ Cbuf.AddText("gamemap \"*" + startmap + "$" + spot + "\"\n");
+ }
+ else {
+ Cbuf.AddText("map " + startmap + "\n");
+ }
+
+ ForceMenuOff();
+ }
+
+ static String dm_coop_names[] = { "deathmatch", "cooperative", null };
+ static String dm_coop_names_rogue[] = { "deathmatch", "cooperative", "tag",
+ // "deathball",
+ null };
+
+ static void StartServer_MenuInit() {
+
+ // =======
+ // PGM
+ // =======
+
+ byte[] buffer = null;
+ //char mapsname[1024];
+ String mapsname;
+ String s;
+ int length;
+ int i;
+ RandomAccessFile fp;
+
+ /*
+ ** load the list of map names
+ */
+ mapsname = FS.Gamedir() + "/maps.lst";
+
+ if ((fp = fopen(mapsname, "r")) == null) {
+ buffer = FS.LoadFile("maps.lst");
+ if (buffer == null)
+ //if ((length = FS_LoadFile("maps.lst", (Object *) & buffer)) == -1)
+ Com.Error(ERR_DROP, "couldn't find maps.lst\n");
+ }
+ else {
+ try {
+ int len = (int) fp.length();
+ buffer = new byte[len];
+ fp.readFully(buffer);
+ }
+ catch (Exception e) {
+ Com.Error(ERR_DROP, "couldn't load maps.lst\n");
+ }
+ }
+
+ s = new String(buffer);
+ String lines[] = Lib.linesplit(s);
+
+ nummaps = lines.length;
+
+ if (nummaps == 0)
+ Com.Error(ERR_DROP, "no maps in maps.lst\n");
+
+ mapnames = new String[nummaps + 1];
+
+ for (i = 0; i < nummaps; i++) {
+ String shortname, longname, scratch;
+
+ Com.ParseHelp ph = new Com.ParseHelp(lines[i]);
+
+ shortname = Com.Parse(ph).toUpperCase();
+ longname = Com.Parse(ph);
+ scratch = longname + "\n" + shortname;
+ mapnames[i] = scratch;
+ }
+ mapnames[nummaps] = null;
+
+ if (fp != null) {
+ fclose(fp);
+ fp = null;
+
+ }
+ else {
+ FS.FreeFile(buffer);
+ }
+
+ /*
+ ** initialize the menu stuff
+ */
+ s_startserver_menu.x = (int) (viddef.width * 0.50);
+ s_startserver_menu.nitems = 0;
+
+ s_startmap_list.type = MTYPE_SPINCONTROL;
+ s_startmap_list.x = 0;
+ s_startmap_list.y = 0;
+ s_startmap_list.name = "initial map";
+ s_startmap_list.itemnames = mapnames;
+
+ s_rules_box.type = MTYPE_SPINCONTROL;
+ s_rules_box.x = 0;
+ s_rules_box.y = 20;
+ s_rules_box.name = "rules";
+
+ // PGM - rogue games only available with rogue DLL.
+ if (FS.Developer_searchpath(2) == 2)
+ s_rules_box.itemnames = dm_coop_names_rogue;
+ else
+ s_rules_box.itemnames = dm_coop_names;
+ // PGM
+
+ if (Cvar.VariableValue("coop") != 0)
+ s_rules_box.curvalue = 1;
+ else
+ s_rules_box.curvalue = 0;
+ s_rules_box.callback = new mcallback() {
+ public void execute(Object o) {
+ RulesChangeFunc(o);
+ }
+ };
+
+ s_timelimit_field.type = MTYPE_FIELD;
+ s_timelimit_field.name = "time limit";
+ s_timelimit_field.flags = QMF_NUMBERSONLY;
+ s_timelimit_field.x = 0;
+ s_timelimit_field.y = 36;
+ s_timelimit_field.statusbar = "0 = no limit";
+ s_timelimit_field.length = 3;
+ s_timelimit_field.visible_length = 3;
+ s_timelimit_field.buffer = new StringBuffer(Cvar.VariableString("timelimit"));
+
+ s_fraglimit_field.type = MTYPE_FIELD;
+ s_fraglimit_field.name = "frag limit";
+ s_fraglimit_field.flags = QMF_NUMBERSONLY;
+ s_fraglimit_field.x = 0;
+ s_fraglimit_field.y = 54;
+ s_fraglimit_field.statusbar = "0 = no limit";
+ s_fraglimit_field.length = 3;
+ s_fraglimit_field.visible_length = 3;
+ s_fraglimit_field.buffer = new StringBuffer(Cvar.VariableString("fraglimit"));
+
+ /*
+ ** maxclients determines the maximum number of players that can join
+ ** the game. If maxclients is only "1" then we should default the menu
+ ** option to 8 players, otherwise use whatever its current value is.
+ ** Clamping will be done when the server is actually started.
+ */
+ s_maxclients_field.type = MTYPE_FIELD;
+ s_maxclients_field.name = "max players";
+ s_maxclients_field.flags = QMF_NUMBERSONLY;
+ s_maxclients_field.x = 0;
+ s_maxclients_field.y = 72;
+ s_maxclients_field.statusbar = null;
+ s_maxclients_field.length = 3;
+ s_maxclients_field.visible_length = 3;
+ if (Cvar.VariableValue("maxclients") == 1)
+ s_maxclients_field.buffer = new StringBuffer("8");
+ else
+ s_maxclients_field.buffer = new StringBuffer(Cvar.VariableString("maxclients"));
+
+ s_hostname_field.type = MTYPE_FIELD;
+ s_hostname_field.name = "hostname";
+ s_hostname_field.flags = 0;
+ s_hostname_field.x = 0;
+ s_hostname_field.y = 90;
+ s_hostname_field.statusbar = null;
+ s_hostname_field.length = 12;
+ s_hostname_field.visible_length = 12;
+ s_hostname_field.buffer = new StringBuffer(Cvar.VariableString("hostname"));
+
+ s_startserver_dmoptions_action.type = MTYPE_ACTION;
+ s_startserver_dmoptions_action.name = " deathmatch flags";
+ s_startserver_dmoptions_action.flags = QMF_LEFT_JUSTIFY;
+ s_startserver_dmoptions_action.x = 24;
+ s_startserver_dmoptions_action.y = 108;
+ s_startserver_dmoptions_action.statusbar = null;
+ s_startserver_dmoptions_action.callback = new mcallback() {
+ public void execute(Object o) {
+ DMOptionsFunc(o);
+ }
+ };
+
+ s_startserver_start_action.type = MTYPE_ACTION;
+ s_startserver_start_action.name = " begin";
+ s_startserver_start_action.flags = QMF_LEFT_JUSTIFY;
+ s_startserver_start_action.x = 24;
+ s_startserver_start_action.y = 128;
+ s_startserver_start_action.callback = new mcallback() {
+ public void execute(Object o) {
+ StartServerActionFunc(o);
+ }
+ };
+
+ Menu_AddItem(s_startserver_menu, s_startmap_list);
+ Menu_AddItem(s_startserver_menu, s_rules_box);
+ Menu_AddItem(s_startserver_menu, s_timelimit_field);
+ Menu_AddItem(s_startserver_menu, s_fraglimit_field);
+ Menu_AddItem(s_startserver_menu, s_maxclients_field);
+ Menu_AddItem(s_startserver_menu, s_hostname_field);
+ Menu_AddItem(s_startserver_menu, s_startserver_dmoptions_action);
+ Menu_AddItem(s_startserver_menu, s_startserver_start_action);
+
+ Menu_Center(s_startserver_menu);
+
+ // call this now to set proper inital state
+ RulesChangeFunc(null);
+ }
+
+ static void StartServer_MenuDraw() {
+ Menu_Draw(s_startserver_menu);
+ }
+
+ static String StartServer_MenuKey(int key) {
+ if (key == K_ESCAPE) {
+ if (mapnames != null) {
+ int i;
+
+ for (i = 0; i < nummaps; i++)
+ mapnames[i] = null;
+
+ }
+ mapnames = null;
+ nummaps = 0;
+ }
+
+ return Default_MenuKey(s_startserver_menu, key);
+ }
+
+ static xcommand_t Menu_StartServer = new xcommand_t() {
+ public void execute() {
+ Menu_StartServer_f();
+ }
+ };
+ static void Menu_StartServer_f() {
+ StartServer_MenuInit();
+ PushMenu(new xcommand_t() {
+ public void execute() {
+ StartServer_MenuDraw();
+ }
+ }, new keyfunc_t() {
+ public String execute(int key) {
+ return StartServer_MenuKey(key);
+ }
+ });
+ }
+
+ /*
+ =============================================================================
+
+ DMOPTIONS BOOK MENU
+
+ =============================================================================
+ */
+ static String dmoptions_statusbar; //[128];
+
+ static menuframework_s s_dmoptions_menu = new menuframework_s();
+
+ static menulist_s s_friendlyfire_box = new menulist_s();
+ static menulist_s s_falls_box = new menulist_s();
+ static menulist_s s_weapons_stay_box = new menulist_s();
+ static menulist_s s_instant_powerups_box = new menulist_s();
+ static menulist_s s_powerups_box = new menulist_s();
+ static menulist_s s_health_box = new menulist_s();
+ static menulist_s s_spawn_farthest_box = new menulist_s();
+ static menulist_s s_teamplay_box = new menulist_s();
+ static menulist_s s_samelevel_box = new menulist_s();
+ static menulist_s s_force_respawn_box = new menulist_s();
+ static menulist_s s_armor_box = new menulist_s();
+ static menulist_s s_allow_exit_box = new menulist_s();
+ static menulist_s s_infinite_ammo_box = new menulist_s();
+ static menulist_s s_fixed_fov_box = new menulist_s();
+ static menulist_s s_quad_drop_box = new menulist_s();
+
+ // ROGUE
+ static menulist_s s_no_mines_box = new menulist_s();
+ static menulist_s s_no_nukes_box = new menulist_s();
+ static menulist_s s_stack_double_box = new menulist_s();
+ static menulist_s s_no_spheres_box = new menulist_s();
+ // ROGUE
+
+ static void setvalue(int flags) {
+ Cvar.SetValue("dmflags", flags);
+ dmoptions_statusbar = "dmflags = " + flags;
+ }
+
+ static void DMFlagCallback(Object self) {
+ menulist_s f = (menulist_s) self;
+ int flags;
+ int bit = 0;
+
+ flags = (int) Cvar.VariableValue("dmflags");
+
+ if (f == s_friendlyfire_box) {
+ if (f.curvalue != 0)
+ flags &= ~DF_NO_FRIENDLY_FIRE;
+ else
+ flags |= DF_NO_FRIENDLY_FIRE;
+ setvalue(flags);
+ return;
+ }
+ else if (f == s_falls_box) {
+ if (f.curvalue != 0)
+ flags &= ~DF_NO_FALLING;
+ else
+ flags |= DF_NO_FALLING;
+ setvalue(flags);
+ return;
+ }
+ else if (f == s_weapons_stay_box) {
+ bit = DF_WEAPONS_STAY;
+ }
+ else if (f == s_instant_powerups_box) {
+ bit = DF_INSTANT_ITEMS;
+ }
+ else if (f == s_allow_exit_box) {
+ bit = DF_ALLOW_EXIT;
+ }
+ else if (f == s_powerups_box) {
+ if (f.curvalue != 0)
+ flags &= ~DF_NO_ITEMS;
+ else
+ flags |= DF_NO_ITEMS;
+ setvalue(flags);
+ return;
+ }
+ else if (f == s_health_box) {
+ if (f.curvalue != 0)
+ flags &= ~DF_NO_HEALTH;
+ else
+ flags |= DF_NO_HEALTH;
+ setvalue(flags);
+ return;
+ }
+ else if (f == s_spawn_farthest_box) {
+ bit = DF_SPAWN_FARTHEST;
+ }
+ else if (f == s_teamplay_box) {
+ if (f.curvalue == 1) {
+ flags |= DF_SKINTEAMS;
+ flags &= ~DF_MODELTEAMS;
+ }
+ else if (f.curvalue == 2) {
+ flags |= DF_MODELTEAMS;
+ flags &= ~DF_SKINTEAMS;
+ }
+ else {
+ flags &= ~(DF_MODELTEAMS | DF_SKINTEAMS);
+ }
+
+ setvalue(flags);
+ return;
+ }
+ else if (f == s_samelevel_box) {
+ bit = DF_SAME_LEVEL;
+ }
+ else if (f == s_force_respawn_box) {
+ bit = DF_FORCE_RESPAWN;
+ }
+ else if (f == s_armor_box) {
+ if (f.curvalue != 0)
+ flags &= ~DF_NO_ARMOR;
+ else
+ flags |= DF_NO_ARMOR;
+ setvalue(flags);
+ return;
+ }
+ else if (f == s_infinite_ammo_box) {
+ bit = DF_INFINITE_AMMO;
+ }
+ else if (f == s_fixed_fov_box) {
+ bit = DF_FIXED_FOV;
+ }
+ else if (f == s_quad_drop_box) {
+ bit = DF_QUAD_DROP;
+ }
+
+ // =======
+ // ROGUE
+ else if (FS.Developer_searchpath(2) == 2) {
+ if (f == s_no_mines_box) {
+ bit = DF_NO_MINES;
+ }
+ else if (f == s_no_nukes_box) {
+ bit = DF_NO_NUKES;
+ }
+ else if (f == s_stack_double_box) {
+ bit = DF_NO_STACK_DOUBLE;
+ }
+ else if (f == s_no_spheres_box) {
+ bit = DF_NO_SPHERES;
+ }
+ }
+ // ROGUE
+ // =======
+
+ if (f != null) {
+ if (f.curvalue == 0)
+ flags &= ~bit;
+ else
+ flags |= bit;
+ }
+
+ Cvar.SetValue("dmflags", flags);
+
+ dmoptions_statusbar = "dmflags = " + flags;
+
+ }
+
+ //static String yes_no_names[] = { "no", "yes", 0 };
+ static String teamplay_names[] = { "disabled", "by skin", "by model", null };
+
+ static void DMOptions_MenuInit() {
+
+ int dmflags = (int) Cvar.VariableValue("dmflags");
+ int y = 0;
+
+ s_dmoptions_menu.x = (int) (viddef.width * 0.50);
+ s_dmoptions_menu.nitems = 0;
+
+ s_falls_box.type = MTYPE_SPINCONTROL;
+ s_falls_box.x = 0;
+ s_falls_box.y = y;
+ s_falls_box.name = "falling damage";
+ s_falls_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_falls_box.itemnames = yes_no_names;
+ s_falls_box.curvalue = (dmflags & DF_NO_FALLING) == 0 ? 1 : 0;
+
+ s_weapons_stay_box.type = MTYPE_SPINCONTROL;
+ s_weapons_stay_box.x = 0;
+ s_weapons_stay_box.y = y += 10;
+ s_weapons_stay_box.name = "weapons stay";
+ s_weapons_stay_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_weapons_stay_box.itemnames = yes_no_names;
+ s_weapons_stay_box.curvalue = (dmflags & DF_WEAPONS_STAY) != 0 ? 1 : 0;
+
+ s_instant_powerups_box.type = MTYPE_SPINCONTROL;
+ s_instant_powerups_box.x = 0;
+ s_instant_powerups_box.y = y += 10;
+ s_instant_powerups_box.name = "instant powerups";
+ s_instant_powerups_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_instant_powerups_box.itemnames = yes_no_names;
+ s_instant_powerups_box.curvalue = (dmflags & DF_INSTANT_ITEMS) != 0 ? 1 : 0;
+
+ s_powerups_box.type = MTYPE_SPINCONTROL;
+ s_powerups_box.x = 0;
+ s_powerups_box.y = y += 10;
+ s_powerups_box.name = "allow powerups";
+ s_powerups_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_powerups_box.itemnames = yes_no_names;
+ s_powerups_box.curvalue = (dmflags & DF_NO_ITEMS) == 0 ? 1 : 0;
+
+ s_health_box.type = MTYPE_SPINCONTROL;
+ s_health_box.x = 0;
+ s_health_box.y = y += 10;
+ s_health_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_health_box.name = "allow health";
+ s_health_box.itemnames = yes_no_names;
+ s_health_box.curvalue = (dmflags & DF_NO_HEALTH) == 0 ? 1 : 0;
+
+ s_armor_box.type = MTYPE_SPINCONTROL;
+ s_armor_box.x = 0;
+ s_armor_box.y = y += 10;
+ s_armor_box.name = "allow armor";
+ s_armor_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_armor_box.itemnames = yes_no_names;
+ s_armor_box.curvalue = (dmflags & DF_NO_ARMOR) == 0 ? 1 : 0;
+
+ s_spawn_farthest_box.type = MTYPE_SPINCONTROL;
+ s_spawn_farthest_box.x = 0;
+ s_spawn_farthest_box.y = y += 10;
+ s_spawn_farthest_box.name = "spawn farthest";
+ s_spawn_farthest_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_spawn_farthest_box.itemnames = yes_no_names;
+ s_spawn_farthest_box.curvalue = (dmflags & DF_SPAWN_FARTHEST) != 0 ? 1 : 0;
+
+ s_samelevel_box.type = MTYPE_SPINCONTROL;
+ s_samelevel_box.x = 0;
+ s_samelevel_box.y = y += 10;
+ s_samelevel_box.name = "same map";
+ s_samelevel_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_samelevel_box.itemnames = yes_no_names;
+ s_samelevel_box.curvalue = (dmflags & DF_SAME_LEVEL) != 0 ? 1 : 0;
+
+ s_force_respawn_box.type = MTYPE_SPINCONTROL;
+ s_force_respawn_box.x = 0;
+ s_force_respawn_box.y = y += 10;
+ s_force_respawn_box.name = "force respawn";
+ s_force_respawn_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_force_respawn_box.itemnames = yes_no_names;
+ s_force_respawn_box.curvalue = (dmflags & DF_FORCE_RESPAWN) != 0 ? 1 : 0;
+
+ s_teamplay_box.type = MTYPE_SPINCONTROL;
+ s_teamplay_box.x = 0;
+ s_teamplay_box.y = y += 10;
+ s_teamplay_box.name = "teamplay";
+ s_teamplay_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_teamplay_box.itemnames = teamplay_names;
+
+ s_allow_exit_box.type = MTYPE_SPINCONTROL;
+ s_allow_exit_box.x = 0;
+ s_allow_exit_box.y = y += 10;
+ s_allow_exit_box.name = "allow exit";
+ s_allow_exit_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_allow_exit_box.itemnames = yes_no_names;
+ s_allow_exit_box.curvalue = (dmflags & DF_ALLOW_EXIT) != 0 ? 1 : 0;
+
+ s_infinite_ammo_box.type = MTYPE_SPINCONTROL;
+ s_infinite_ammo_box.x = 0;
+ s_infinite_ammo_box.y = y += 10;
+ s_infinite_ammo_box.name = "infinite ammo";
+ s_infinite_ammo_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_infinite_ammo_box.itemnames = yes_no_names;
+ s_infinite_ammo_box.curvalue = (dmflags & DF_INFINITE_AMMO) != 0 ? 1 : 0;
+
+ s_fixed_fov_box.type = MTYPE_SPINCONTROL;
+ s_fixed_fov_box.x = 0;
+ s_fixed_fov_box.y = y += 10;
+ s_fixed_fov_box.name = "fixed FOV";
+ s_fixed_fov_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_fixed_fov_box.itemnames = yes_no_names;
+ s_fixed_fov_box.curvalue = (dmflags & DF_FIXED_FOV) != 0 ? 1 : 0;
+
+ s_quad_drop_box.type = MTYPE_SPINCONTROL;
+ s_quad_drop_box.x = 0;
+ s_quad_drop_box.y = y += 10;
+ s_quad_drop_box.name = "quad drop";
+ s_quad_drop_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_quad_drop_box.itemnames = yes_no_names;
+ s_quad_drop_box.curvalue = (dmflags & DF_QUAD_DROP) != 0 ? 1 : 0;
+
+ s_friendlyfire_box.type = MTYPE_SPINCONTROL;
+ s_friendlyfire_box.x = 0;
+ s_friendlyfire_box.y = y += 10;
+ s_friendlyfire_box.name = "friendly fire";
+ s_friendlyfire_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_friendlyfire_box.itemnames = yes_no_names;
+ s_friendlyfire_box.curvalue = (dmflags & DF_NO_FRIENDLY_FIRE) == 0 ? 1 : 0;
+
+ // ============
+ // ROGUE
+ if (FS.Developer_searchpath(2) == 2) {
+ s_no_mines_box.type = MTYPE_SPINCONTROL;
+ s_no_mines_box.x = 0;
+ s_no_mines_box.y = y += 10;
+ s_no_mines_box.name = "remove mines";
+ s_no_mines_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_no_mines_box.itemnames = yes_no_names;
+ s_no_mines_box.curvalue = (dmflags & DF_NO_MINES) != 0 ? 1 : 0;
+
+ s_no_nukes_box.type = MTYPE_SPINCONTROL;
+ s_no_nukes_box.x = 0;
+ s_no_nukes_box.y = y += 10;
+ s_no_nukes_box.name = "remove nukes";
+ s_no_nukes_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_no_nukes_box.itemnames = yes_no_names;
+ s_no_nukes_box.curvalue = (dmflags & DF_NO_NUKES) != 0 ? 1 : 0;
+
+ s_stack_double_box.type = MTYPE_SPINCONTROL;
+ s_stack_double_box.x = 0;
+ s_stack_double_box.y = y += 10;
+ s_stack_double_box.name = "2x/4x stacking off";
+ s_stack_double_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_stack_double_box.itemnames = yes_no_names;
+ s_stack_double_box.curvalue = (dmflags & DF_NO_STACK_DOUBLE);
+
+ s_no_spheres_box.type = MTYPE_SPINCONTROL;
+ s_no_spheres_box.x = 0;
+ s_no_spheres_box.y = y += 10;
+ s_no_spheres_box.name = "remove spheres";
+ s_no_spheres_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DMFlagCallback(o);
+ }
+ };
+ s_no_spheres_box.itemnames = yes_no_names;
+ s_no_spheres_box.curvalue = (dmflags & DF_NO_SPHERES) != 0 ? 1 : 0;
+
+ }
+ // ROGUE
+ // ============
+
+ Menu_AddItem(s_dmoptions_menu, s_falls_box);
+ Menu_AddItem(s_dmoptions_menu, s_weapons_stay_box);
+ Menu_AddItem(s_dmoptions_menu, s_instant_powerups_box);
+ Menu_AddItem(s_dmoptions_menu, s_powerups_box);
+ Menu_AddItem(s_dmoptions_menu, s_health_box);
+ Menu_AddItem(s_dmoptions_menu, s_armor_box);
+ Menu_AddItem(s_dmoptions_menu, s_spawn_farthest_box);
+ Menu_AddItem(s_dmoptions_menu, s_samelevel_box);
+ Menu_AddItem(s_dmoptions_menu, s_force_respawn_box);
+ Menu_AddItem(s_dmoptions_menu, s_teamplay_box);
+ Menu_AddItem(s_dmoptions_menu, s_allow_exit_box);
+ Menu_AddItem(s_dmoptions_menu, s_infinite_ammo_box);
+ Menu_AddItem(s_dmoptions_menu, s_fixed_fov_box);
+ Menu_AddItem(s_dmoptions_menu, s_quad_drop_box);
+ Menu_AddItem(s_dmoptions_menu, s_friendlyfire_box);
+
+ // =======
+ // ROGUE
+ if (FS.Developer_searchpath(2) == 2) {
+ Menu_AddItem(s_dmoptions_menu, s_no_mines_box);
+ Menu_AddItem(s_dmoptions_menu, s_no_nukes_box);
+ Menu_AddItem(s_dmoptions_menu, s_stack_double_box);
+ Menu_AddItem(s_dmoptions_menu, s_no_spheres_box);
+ }
+ // ROGUE
+ // =======
+
+ Menu_Center(s_dmoptions_menu);
+
+ // set the original dmflags statusbar
+ DMFlagCallback(null);
+ Menu_SetStatusBar(s_dmoptions_menu, dmoptions_statusbar);
+ }
+
+ static void DMOptions_MenuDraw() {
+ Menu_Draw(s_dmoptions_menu);
+ }
+
+ static String DMOptions_MenuKey(int key) {
+ return Default_MenuKey(s_dmoptions_menu, key);
+ }
+
+ static xcommand_t Menu_DMOptions = new xcommand_t() {
+ public void execute() {
+ Menu_DMOptions_f();
+ }
+ };
+ static void Menu_DMOptions_f() {
+ DMOptions_MenuInit();
+ PushMenu(new xcommand_t() {
+ public void execute() {
+ DMOptions_MenuDraw();
+ }
+ }, new keyfunc_t() {
+ public String execute(int key) {
+ return DMOptions_MenuKey(key);
+ }
+ });
+ }
+
+ /*
+ =============================================================================
+
+ DOWNLOADOPTIONS BOOK MENU
+
+ =============================================================================
+ */
+ static menuframework_s s_downloadoptions_menu = new menuframework_s();
+
+ static menuseparator_s s_download_title = new menuseparator_s();
+ static menulist_s s_allow_download_box = new menulist_s();
+ static menulist_s s_allow_download_maps_box = new menulist_s();
+ static menulist_s s_allow_download_models_box = new menulist_s();
+ static menulist_s s_allow_download_players_box = new menulist_s();
+ static menulist_s s_allow_download_sounds_box = new menulist_s();
+
+ static void DownloadCallback(Object self) {
+ menulist_s f = (menulist_s) self;
+
+ if (f == s_allow_download_box) {
+ Cvar.SetValue("allow_download", f.curvalue);
+ }
+
+ else if (f == s_allow_download_maps_box) {
+ Cvar.SetValue("allow_download_maps", f.curvalue);
+ }
+
+ else if (f == s_allow_download_models_box) {
+ Cvar.SetValue("allow_download_models", f.curvalue);
+ }
+
+ else if (f == s_allow_download_players_box) {
+ Cvar.SetValue("allow_download_players", f.curvalue);
+ }
+
+ else if (f == s_allow_download_sounds_box) {
+ Cvar.SetValue("allow_download_sounds", f.curvalue);
+ }
+ }
+
+ static String yes_no_names[] = { "no", "yes", null };
+ static void DownloadOptions_MenuInit() {
+
+ int y = 0;
+
+ s_downloadoptions_menu.x = (int) (viddef.width * 0.50);
+ s_downloadoptions_menu.nitems = 0;
+
+ s_download_title.type = MTYPE_SEPARATOR;
+ s_download_title.name = "Download Options";
+ s_download_title.x = 48;
+ s_download_title.y = y;
+
+ s_allow_download_box.type = MTYPE_SPINCONTROL;
+ s_allow_download_box.x = 0;
+ s_allow_download_box.y = y += 20;
+ s_allow_download_box.name = "allow downloading";
+ s_allow_download_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DownloadCallback(o);
+ }
+ };
+ s_allow_download_box.itemnames = yes_no_names;
+ s_allow_download_box.curvalue = (Cvar.VariableValue("allow_download") != 0) ? 1 : 0;
+
+ s_allow_download_maps_box.type = MTYPE_SPINCONTROL;
+ s_allow_download_maps_box.x = 0;
+ s_allow_download_maps_box.y = y += 20;
+ s_allow_download_maps_box.name = "maps";
+ s_allow_download_maps_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DownloadCallback(o);
+ }
+ };
+ s_allow_download_maps_box.itemnames = yes_no_names;
+ s_allow_download_maps_box.curvalue = (Cvar.VariableValue("allow_download_maps") != 0) ? 1 : 0;
+
+ s_allow_download_players_box.type = MTYPE_SPINCONTROL;
+ s_allow_download_players_box.x = 0;
+ s_allow_download_players_box.y = y += 10;
+ s_allow_download_players_box.name = "player models/skins";
+ s_allow_download_players_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DownloadCallback(o);
+ }
+ };
+ s_allow_download_players_box.itemnames = yes_no_names;
+ s_allow_download_players_box.curvalue = (Cvar.VariableValue("allow_download_players") != 0) ? 1 : 0;
+
+ s_allow_download_models_box.type = MTYPE_SPINCONTROL;
+ s_allow_download_models_box.x = 0;
+ s_allow_download_models_box.y = y += 10;
+ s_allow_download_models_box.name = "models";
+ s_allow_download_models_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DownloadCallback(o);
+ }
+ };
+ s_allow_download_models_box.itemnames = yes_no_names;
+ s_allow_download_models_box.curvalue = (Cvar.VariableValue("allow_download_models") != 0) ? 1 : 0;
+
+ s_allow_download_sounds_box.type = MTYPE_SPINCONTROL;
+ s_allow_download_sounds_box.x = 0;
+ s_allow_download_sounds_box.y = y += 10;
+ s_allow_download_sounds_box.name = "sounds";
+ s_allow_download_sounds_box.callback = new mcallback() {
+ public void execute(Object o) {
+ DownloadCallback(o);
+ }
+ };
+ s_allow_download_sounds_box.itemnames = yes_no_names;
+ s_allow_download_sounds_box.curvalue = (Cvar.VariableValue("allow_download_sounds") != 0) ? 1 : 0;
+
+ Menu_AddItem(s_downloadoptions_menu, s_download_title);
+ Menu_AddItem(s_downloadoptions_menu, s_allow_download_box);
+ Menu_AddItem(s_downloadoptions_menu, s_allow_download_maps_box);
+ Menu_AddItem(s_downloadoptions_menu, s_allow_download_players_box);
+ Menu_AddItem(s_downloadoptions_menu, s_allow_download_models_box);
+ Menu_AddItem(s_downloadoptions_menu, s_allow_download_sounds_box);
+
+ Menu_Center(s_downloadoptions_menu);
+
+ // skip over title
+ if (s_downloadoptions_menu.cursor == 0)
+ s_downloadoptions_menu.cursor = 1;
+ }
+
+ static void DownloadOptions_MenuDraw() {
+ Menu_Draw(s_downloadoptions_menu);
+ }
+
+ static String DownloadOptions_MenuKey(int key) {
+ return Default_MenuKey(s_downloadoptions_menu, key);
+ }
+
+ static xcommand_t Menu_DownloadOptions = new xcommand_t() {
+ public void execute() {
+ Menu_DownloadOptions_f();
+ }
+ };
+ static void Menu_DownloadOptions_f() {
+ DownloadOptions_MenuInit();
+ PushMenu(new xcommand_t() {
+ public void execute() {
+ DownloadOptions_MenuDraw();
+ }
+ }, new keyfunc_t() {
+ public String execute(int key) {
+ return DownloadOptions_MenuKey(key);
+ }
+ });
+ }
+ /*
+ =============================================================================
+
+ ADDRESS BOOK MENU
+
+ =============================================================================
+ */
+
+ static menuframework_s s_addressbook_menu = new menuframework_s();
+ static menufield_s s_addressbook_fields[] = new menufield_s[NUM_ADDRESSBOOK_ENTRIES];
+ static {
+ for (int n = 0; n < NUM_ADDRESSBOOK_ENTRIES; n++)
+ s_addressbook_fields[n] = new menufield_s();
+ }
+
+ static void AddressBook_MenuInit() {
+ int i;
+
+ s_addressbook_menu.x = viddef.width / 2 - 142;
+ s_addressbook_menu.y = viddef.height / 2 - 58;
+ s_addressbook_menu.nitems = 0;
+
+ for (i = 0; i < NUM_ADDRESSBOOK_ENTRIES; i++) {
+ cvar_t adr;
+ //char buffer[20];
+ String buffer;
+
+ //Com_sprintf(buffer, sizeof(buffer), "adr%d", i);
+ buffer = "adr" + i;
+
+ adr = Cvar.Get(buffer, "", CVAR_ARCHIVE);
+
+ s_addressbook_fields[i].type = MTYPE_FIELD;
+ s_addressbook_fields[i].name = null;
+ s_addressbook_fields[i].callback = null;
+ s_addressbook_fields[i].x = 0;
+ s_addressbook_fields[i].y = i * 18 + 0;
+ s_addressbook_fields[i].localdata[0] = i;
+ s_addressbook_fields[i].cursor = 0;
+ s_addressbook_fields[i].length = 60;
+ s_addressbook_fields[i].visible_length = 30;
+
+ s_addressbook_fields[i].buffer = new StringBuffer(adr.string);
+
+ Menu_AddItem(s_addressbook_menu, s_addressbook_fields[i]);
+ }
+ }
+
+ static keyfunc_t AddressBook_MenuKey = new keyfunc_t() {
+ public String execute(int key) {
+ return AddressBook_MenuKey_f(key);
+ }
+ };
+
+ static String AddressBook_MenuKey_f(int key) {
+ if (key == K_ESCAPE) {
+ int index;
+ //char buffer[20];
+ String buffer;
+
+ for (index = 0; index < NUM_ADDRESSBOOK_ENTRIES; index++) {
+ buffer = "adr" + index;
+ //Com_sprintf(buffer, sizeof(buffer), "adr%d", index);
+ Cvar.Set(buffer, s_addressbook_fields[index].buffer.toString());
+ }
+ }
+ return Default_MenuKey(s_addressbook_menu, key);
+ }
+
+ static xcommand_t AddressBook_MenuDraw = new xcommand_t() {
+ public void execute() {
+ AddressBook_MenuDraw_f();
+ }
+ };
+ static void AddressBook_MenuDraw_f() {
+ Banner("m_banner_addressbook");
+ Menu_Draw(s_addressbook_menu);
+ }
+
+ static xcommand_t Menu_AddressBook = new xcommand_t() {
+ public void execute() {
+ Menu_AddressBook_f();
+ }
+ };
+ static void Menu_AddressBook_f() {
+ AddressBook_MenuInit();
+ PushMenu(new xcommand_t() {
+ public void execute() {
+ AddressBook_MenuDraw_f();
+ }
+ }, new keyfunc_t() {
+ public String execute(int key) {
+ return AddressBook_MenuKey_f(key);
+ }
+ });
+ }
+ /*
+ =============================================================================
+
+ PLAYER CONFIG MENU
+
+ =============================================================================
+ */
+ static menuframework_s s_player_config_menu = new menuframework_s();
+ static menufield_s s_player_name_field = new menufield_s();
+ static menulist_s s_player_model_box = new menulist_s();
+ static menulist_s s_player_skin_box = new menulist_s();
+ static menulist_s s_player_handedness_box = new menulist_s();
+ static menulist_s s_player_rate_box = new menulist_s();
+ static menuseparator_s s_player_skin_title = new menuseparator_s();
+ static menuseparator_s s_player_model_title = new menuseparator_s();
+ static menuseparator_s s_player_hand_title = new menuseparator_s();
+ static menuseparator_s s_player_rate_title = new menuseparator_s();
+ static menuaction_s s_player_download_action = new menuaction_s();
+
+ static class playermodelinfo_s {
+ int nskins;
+ String skindisplaynames[];
+ //char displayname[MAX_DISPLAYNAME];
+ String displayname;
+ //char directory[MAX_QPATH];
+ String directory;
+ };
+
+ static playermodelinfo_s s_pmi[] = new playermodelinfo_s[MAX_PLAYERMODELS];
+ static String s_pmnames[] = new String[MAX_PLAYERMODELS];
+ static int s_numplayermodels;
+
+ static int rate_tbl[] = { 2500, 3200, 5000, 10000, 25000, 0 };
+ static String rate_names[] = { "28.8 Modem", "33.6 Modem", "Single ISDN", "Dual ISDN/Cable", "T1/LAN", "User defined", null };
+
+ static void DownloadOptionsFunc(Object self) {
+ Menu_DownloadOptions_f();
+ }
+
+ static void HandednessCallback(Object unused) {
+ Cvar.SetValue("hand", s_player_handedness_box.curvalue);
+ }
+
+ static void RateCallback(Object unused) {
+ if (s_player_rate_box.curvalue != rate_tbl.length - 1) //sizeof(rate_tbl) / sizeof(* rate_tbl) - 1)
+ Cvar.SetValue("rate", rate_tbl[s_player_rate_box.curvalue]);
+ }
+
+ static void ModelCallback(Object unused) {
+ s_player_skin_box.itemnames = s_pmi[s_player_model_box.curvalue].skindisplaynames;
+ s_player_skin_box.curvalue = 0;
+ }
+
+ static boolean IconOfSkinExists(String skin, String pcxfiles[], int npcxfiles) {
+ int i;
+ //char scratch[1024];
+ String scratch;
+
+ //strcpy(scratch, skin);
+ scratch = skin;
+ int pos = scratch.lastIndexOf('.');
+ if (pos != -1)
+ scratch = scratch.substring(0, pos) + "_i.pcx";
+
+ else
+ scratch += "_i.pcx";
+
+ for (i = 0; i < npcxfiles; i++) {
+ if (strcmp(pcxfiles[i], scratch) == 0)
+ return true;
+ }
+
+ return false;
+ }
+
+ static boolean PlayerConfig_ScanDirectories() {
+ //char findname[1024];
+ String findname;
+ //char scratch[1024];
+ String scratch;
+
+ int ndirs = 0, npms = 0;
+ int a, b, c;
+ String dirnames[];
+
+ String path = null;
+
+ int i;
+
+ //extern String * FS_ListFiles(String , int *, unsigned, unsigned);
+
+ s_numplayermodels = 0;
+
+ /*
+ ** get a list of directories
+ */
+ do {
+ path = FS.NextPath(path);
+ findname = path + "/players/*.*";
+
+ if ((dirnames = FS.ListFiles(findname, 0, SFF_SUBDIR)) != null) {
+ ndirs = dirnames.length;
+ break;
+ }
+ }
+ while (path != null);
+
+ if (dirnames == null)
+ return false;
+
+ /*
+ ** go through the subdirectories
+ */
+ npms = ndirs;
+ if (npms > MAX_PLAYERMODELS)
+ npms = MAX_PLAYERMODELS;
+
+ for (i = 0; i < npms; i++) {
+ int k, s;
+ //String a, b, c;
+ String pcxnames[];
+ String skinnames[];
+ int npcxfiles;
+ int nskins = 0;
+
+ if (dirnames[i] == null)
+ continue;
+
+ // verify the existence of tris.md2
+ scratch = dirnames[i];
+ scratch += "/tris.md2";
+ if (Sys.FindFirst(scratch, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM) == null) {
+ //free(dirnames[i]);
+ dirnames[i] = null;
+ Sys.FindClose();
+ continue;
+ }
+ Sys.FindClose();
+
+ // verify the existence of at least one pcx skin
+ scratch = dirnames[i] + "/*.pcx";
+ pcxnames = FS.ListFiles(scratch, 0, 0);
+ npcxfiles = pcxnames.length;
+
+ if (pcxnames == null) {
+
+ dirnames[i] = null;
+ continue;
+ }
+
+ // count valid skins, which consist of a skin with a matching "_i" icon
+ for (k = 0; k < npcxfiles - 1; k++) {
+ if (!pcxnames[k].endsWith("_i.pcx")) {
+ //if (!strstr(pcxnames[k], "_i.pcx")) {
+ if (IconOfSkinExists(pcxnames[k], pcxnames, npcxfiles - 1)) {
+ nskins++;
+ }
+ }
+ }
+ if (nskins == 0)
+ continue;
+
+ skinnames = new String[nskins + 1]; //malloc(sizeof(String) * (nskins + 1));
+ //memset(skinnames, 0, sizeof(String) * (nskins + 1));
+
+ // copy the valid skins
+ for (s = 0, k = 0; k < npcxfiles - 1; k++) {
+
+ if (!strstr(pcxnames[k], "_i.pcx")) {
+ if (IconOfSkinExists(pcxnames[k], pcxnames, npcxfiles - 1)) {
+ a = pcxnames[k].lastIndexOf('/');
+ b = pcxnames[k].lastIndexOf('\\');
+
+ if (a > b)
+ c = a;
+ else
+ c = b;
+
+ scratch = pcxnames[k].substring(c + 1, pcxnames[k].length());
+ int pos = scratch.lastIndexOf('.');
+ if (pos != -1)
+ scratch = scratch.substring(0, pos);
+
+ skinnames[s] = scratch;
+ s++;
+ }
+ }
+ }
+
+ // at this point we have a valid player model
+ if (s_pmi[s_numplayermodels] == null)
+ s_pmi[s_numplayermodels] = new playermodelinfo_s();
+
+ s_pmi[s_numplayermodels].nskins = nskins;
+ s_pmi[s_numplayermodels].skindisplaynames = skinnames;
+
+ // make short name for the model
+ a = dirnames[i].lastIndexOf('/');
+ b = dirnames[i].lastIndexOf('\\');
+
+ if (a > b)
+ c = a;
+ else
+ c = b;
+
+ s_pmi[s_numplayermodels].displayname = dirnames[i].substring(c + 1);
+ s_pmi[s_numplayermodels].directory = dirnames[i].substring(c + 1);
+
+ s_numplayermodels++;
+ }
+
+ return true;
+
+ }
+
+ static int pmicmpfnc(Object _a, Object _b) {
+ playermodelinfo_s a = (playermodelinfo_s) _a;
+ playermodelinfo_s b = (playermodelinfo_s) _b;
+
+ /*
+ ** sort by male, female, then alphabetical
+ */
+ if (strcmp(a.directory, "male") == 0)
+ return -1;
+ else if (strcmp(b.directory, "male") == 0)
+ return 1;
+
+ if (strcmp(a.directory, "female") == 0)
+ return -1;
+ else if (strcmp(b.directory, "female") == 0)
+ return 1;
+
+ return strcmp(a.directory, b.directory);
+ }
+
+ static String handedness[] = { "right", "left", "center", null };
+
+ static boolean PlayerConfig_MenuInit() {
+ /*
+ extern cvar_t * name;
+ extern cvar_t * team;
+ extern cvar_t * skin;
+ */
+ //har currentdirectory[1024];
+ String currentdirectory;
+ //char currentskin[1024];
+ String currentskin;
+
+ int i = 0;
+
+ int currentdirectoryindex = 0;
+ int currentskinindex = 0;
+
+ cvar_t hand = Cvar.Get("hand", "0", CVAR_USERINFO | CVAR_ARCHIVE);
+
+ PlayerConfig_ScanDirectories();
+
+ if (s_numplayermodels == 0)
+ return false;
+
+ if (hand.value < 0 || hand.value > 2)
+ Cvar.SetValue("hand", 0);
+
+ currentdirectory = skin.string;
+
+ if (currentdirectory.lastIndexOf('/') != -1) {
+ currentskin = rightFrom(currentdirectory, '/');
+ currentdirectory = leftFrom(currentdirectory, '/');
+ }
+ else if (currentdirectory.lastIndexOf('\\') != -1) {
+ currentskin = rightFrom(currentdirectory, '\\');
+ currentdirectory = leftFrom(currentdirectory, '\\');
+ }
+ else {
+ currentdirectory = "male";
+ currentskin = "grunt";
+ }
+
+ //qsort(s_pmi, s_numplayermodels, sizeof(s_pmi[0]), pmicmpfnc);
+ Arrays.sort(s_pmi, 0, s_numplayermodels, new Comparator() {
+ public int compare(Object o1, Object o2) {
+ return pmicmpfnc(o1, o2);
+ }
+ });
+
+ //memset(s_pmnames, 0, sizeof(s_pmnames));
+ s_pmnames = new String[MAX_PLAYERMODELS];
+
+ for (i = 0; i < s_numplayermodels; i++) {
+ s_pmnames[i] = s_pmi[i].displayname;
+ if (Q_stricmp(s_pmi[i].directory, currentdirectory) == 0) {
+ int j;
+
+ currentdirectoryindex = i;
+
+ for (j = 0; j < s_pmi[i].nskins; j++) {
+ if (Q_stricmp(s_pmi[i].skindisplaynames[j], currentskin) == 0) {
+ currentskinindex = j;
+ break;
+ }
+ }
+ }
+ }
+
+ s_player_config_menu.x = viddef.width / 2 - 95;
+ s_player_config_menu.y = viddef.height / 2 - 97;
+ s_player_config_menu.nitems = 0;
+
+ s_player_name_field.type = MTYPE_FIELD;
+ s_player_name_field.name = "name";
+ s_player_name_field.callback = null;
+ s_player_name_field.x = 0;
+ s_player_name_field.y = 0;
+ s_player_name_field.length = 20;
+ s_player_name_field.visible_length = 20;
+ s_player_name_field.buffer = new StringBuffer(name.string);
+ s_player_name_field.cursor = strlen(name.string);
+
+ s_player_model_title.type = MTYPE_SEPARATOR;
+ s_player_model_title.name = "model";
+ s_player_model_title.x = -8;
+ s_player_model_title.y = 60;
+
+ s_player_model_box.type = MTYPE_SPINCONTROL;
+ s_player_model_box.x = -56;
+ s_player_model_box.y = 70;
+ s_player_model_box.callback = new mcallback() {
+ public void execute(Object o) {
+ ModelCallback(o);
+ }
+ };
+ s_player_model_box.cursor_offset = -48;
+ s_player_model_box.curvalue = currentdirectoryindex;
+ s_player_model_box.itemnames = s_pmnames;
+
+ s_player_skin_title.type = MTYPE_SEPARATOR;
+ s_player_skin_title.name = "skin";
+ s_player_skin_title.x = -16;
+ s_player_skin_title.y = 84;
+
+ s_player_skin_box.type = MTYPE_SPINCONTROL;
+ s_player_skin_box.x = -56;
+ s_player_skin_box.y = 94;
+ s_player_skin_box.name = null;
+ s_player_skin_box.callback = null;
+ s_player_skin_box.cursor_offset = -48;
+ s_player_skin_box.curvalue = currentskinindex;
+ s_player_skin_box.itemnames = s_pmi[currentdirectoryindex].skindisplaynames;
+
+ s_player_hand_title.type = MTYPE_SEPARATOR;
+ s_player_hand_title.name = "handedness";
+ s_player_hand_title.x = 32;
+ s_player_hand_title.y = 108;
+
+ s_player_handedness_box.type = MTYPE_SPINCONTROL;
+ s_player_handedness_box.x = -56;
+ s_player_handedness_box.y = 118;
+ s_player_handedness_box.name = null;
+ s_player_handedness_box.cursor_offset = -48;
+ s_player_handedness_box.callback = new mcallback() {
+ public void execute(Object o) {
+ HandednessCallback(o);
+ }
+ };
+ s_player_handedness_box.curvalue = (int) Cvar.VariableValue("hand");
+ s_player_handedness_box.itemnames = handedness;
+
+ for (i = 0; i < rate_tbl.length - 1; i++)
+ if (Cvar.VariableValue("rate") == rate_tbl[i])
+ break;
+
+ s_player_rate_title.type = MTYPE_SEPARATOR;
+ s_player_rate_title.name = "connect speed";
+ s_player_rate_title.x = 56;
+ s_player_rate_title.y = 156;
+
+ s_player_rate_box.type = MTYPE_SPINCONTROL;
+ s_player_rate_box.x = -56;
+ s_player_rate_box.y = 166;
+ s_player_rate_box.name = null;
+ s_player_rate_box.cursor_offset = -48;
+ s_player_rate_box.callback = new mcallback() {
+ public void execute(Object o) {
+ RateCallback(o);
+ }
+ };
+ s_player_rate_box.curvalue = i;
+ s_player_rate_box.itemnames = rate_names;
+
+ s_player_download_action.type = MTYPE_ACTION;
+ s_player_download_action.name = "download options";
+ s_player_download_action.flags = QMF_LEFT_JUSTIFY;
+ s_player_download_action.x = -24;
+ s_player_download_action.y = 186;
+ s_player_download_action.statusbar = null;
+ s_player_download_action.callback = new mcallback() {
+ public void execute(Object o) {
+ DownloadOptionsFunc(o);
+ }
+ };
+
+ Menu_AddItem(s_player_config_menu, s_player_name_field);
+ Menu_AddItem(s_player_config_menu, s_player_model_title);
+ Menu_AddItem(s_player_config_menu, s_player_model_box);
+ if (s_player_skin_box.itemnames != null) {
+ Menu_AddItem(s_player_config_menu, s_player_skin_title);
+ Menu_AddItem(s_player_config_menu, s_player_skin_box);
+ }
+ Menu_AddItem(s_player_config_menu, s_player_hand_title);
+ Menu_AddItem(s_player_config_menu, s_player_handedness_box);
+ Menu_AddItem(s_player_config_menu, s_player_rate_title);
+ Menu_AddItem(s_player_config_menu, s_player_rate_box);
+ Menu_AddItem(s_player_config_menu, s_player_download_action);
+
+ return true;
+ }
+
+ static int yaw;
+
+ static void PlayerConfig_MenuDraw() {
+
+ refdef_t refdef = new refdef_t();
+ //char scratch[MAX_QPATH];
+ String scratch;
+
+ //memset(refdef, 0, sizeof(refdef));
+
+ refdef.x = viddef.width / 2;
+ refdef.y = viddef.height / 2 - 72;
+ refdef.width = 144;
+ refdef.height = 168;
+ refdef.fov_x = 40;
+ refdef.fov_y = Math3D.CalcFov(refdef.fov_x, refdef.width, refdef.height);
+ refdef.time = cls.realtime * 0.001f;
+
+ if (s_pmi[s_player_model_box.curvalue].skindisplaynames != null) {
+
+ int maxframe = 29;
+ entity_t entity = new entity_t();
+
+ //memset(entity, 0, sizeof(entity));
+
+ scratch = "players/" + s_pmi[s_player_model_box.curvalue].directory + "/tris.md2";
+
+ entity.model = re.RegisterModel(scratch);
+
+ scratch =
+ "players/"
+ + s_pmi[s_player_model_box.curvalue].directory
+ + "/"
+ + s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue]
+ + ".pcx";
+
+ entity.skin = re.RegisterSkin(scratch);
+ entity.flags = RF_FULLBRIGHT;
+ entity.origin[0] = 80;
+ entity.origin[1] = 0;
+ entity.origin[2] = 0;
+ VectorCopy(entity.origin, entity.oldorigin);
+ entity.frame = 0;
+ entity.oldframe = 0;
+ entity.backlerp = 0.0f;
+ entity.angles[1] = yaw++;
+ if (++yaw > 360)
+ yaw -= 360;
+
+ refdef.areabits = null;
+ refdef.num_entities = 1;
+ refdef.entities = new entity_t[] { entity };
+ refdef.lightstyles = null;
+ refdef.rdflags = RDF_NOWORLDMODEL;
+
+ Menu_Draw(s_player_config_menu);
+
+ DrawTextBox(
+ (int) ((refdef.x) * (320.0F / viddef.width) - 8),
+ (int) ((viddef.height / 2) * (240.0F / viddef.height) - 77),
+ refdef.width / 8,
+ refdef.height / 8);
+ refdef.height += 4;
+
+ re.RenderFrame(refdef);
+
+ scratch =
+ "/players/"
+ + s_pmi[s_player_model_box.curvalue].directory
+ + "/"
+ + s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue]
+ + "_i.pcx";
+
+ re.DrawPic(s_player_config_menu.x - 40, refdef.y, scratch);
+ }
+ }
+
+ static String PlayerConfig_MenuKey(int key) {
+ int i;
+
+ if (key == K_ESCAPE) {
+ //char scratch[1024];
+ String scratch;
+
+ Cvar.Set("name", s_player_name_field.buffer.toString());
+
+ scratch =
+ s_pmi[s_player_model_box.curvalue].directory
+ + "/"
+ + s_pmi[s_player_model_box.curvalue].skindisplaynames[s_player_skin_box.curvalue];
+
+ Cvar.Set("skin", scratch);
+
+ for (i = 0; i < s_numplayermodels; i++) {
+ int j;
+
+ for (j = 0; j < s_pmi[i].nskins; j++) {
+ if (s_pmi[i].skindisplaynames[j] != null)
+ s_pmi[i].skindisplaynames[j] = null;
+ }
+ s_pmi[i].skindisplaynames = null;
+ s_pmi[i].nskins = 0;
+ }
+ }
+ return Default_MenuKey(s_player_config_menu, key);
+ }
+
+ static xcommand_t Menu_PlayerConfig = new xcommand_t() {
+ public void execute() {
+ Menu_PlayerConfig_f();
+ }
+ };
+ static void Menu_PlayerConfig_f() {
+ if (!PlayerConfig_MenuInit()) {
+ Menu_SetStatusBar(s_multiplayer_menu, "No valid player models found");
+ return;
+ }
+ Menu_SetStatusBar(s_multiplayer_menu, null);
+ PushMenu(new xcommand_t() {
+ public void execute() {
+ PlayerConfig_MenuDraw();
+ }
+ }, new keyfunc_t() {
+ public String execute(int key) {
+ return PlayerConfig_MenuKey(key);
+ }
+ });
+ }
+
+ /*
+ =======================================================================
+
+ QUIT MENU
+
+ =======================================================================
+ */
+
+ static String Quit_Key(int key) {
+ switch (key) {
+ case K_ESCAPE :
+ case 'n' :
+ case 'N' :
+ PopMenu();
+ break;
+
+ case 'Y' :
+ case 'y' :
+ cls.key_dest = key_console;
+ CL.Quit_f.execute();
+ break;
+
+ default :
+ break;
+ }
+
+ return null;
+
+ }
+
+ static void Quit_Draw() {
+ int w, h;
+ Dimension d = new Dimension();
+ re.DrawGetPicSize(d, "quit");
+ w = d.width;
+ h = d.height;
+ re.DrawPic((viddef.width - w) / 2, (viddef.height - h) / 2, "quit");
+ }
+
+ static xcommand_t Menu_Quit = new xcommand_t() {
+ public void execute() {
+ Menu_Quit_f();
+ }
+ };
+
+ static void Menu_Quit_f() {
+ PushMenu(new xcommand_t() {
+ public void execute() {
+ Quit_Draw();
+ }
+ }, new keyfunc_t() {
+ public String execute(int key) {
+ return Quit_Key(key);
+ }
+ });
+ }
+
+ // =============================================================================
+ /* Menu Subsystem */
+
+ /**
+ * Init
+ */
+ public static void Init() {
+ Cmd.AddCommand("menu_main", Menu_Main);
+ Cmd.AddCommand("menu_game", Menu_Game);
+ Cmd.AddCommand("menu_loadgame", Menu_LoadGame);
+ Cmd.AddCommand("menu_savegame", Menu_SaveGame);
+ Cmd.AddCommand("menu_joinserver", Menu_JoinServer);
+ Cmd.AddCommand("menu_addressbook", Menu_AddressBook);
+ Cmd.AddCommand("menu_startserver", Menu_StartServer);
+ Cmd.AddCommand("menu_dmoptions", Menu_DMOptions);
+ Cmd.AddCommand("menu_playerconfig", Menu_PlayerConfig);
+ Cmd.AddCommand("menu_downloadoptions", Menu_DownloadOptions);
+ Cmd.AddCommand("menu_credits", Menu_Credits);
+ Cmd.AddCommand("menu_multiplayer", Menu_Multiplayer);
+ Cmd.AddCommand("menu_video", Menu_Video);
+ Cmd.AddCommand("menu_options", Menu_Options);
+ Cmd.AddCommand("menu_keys", Menu_Keys);
+ Cmd.AddCommand("menu_quit", Menu_Quit);
+
+ for (int i = 0; i < m_layers.length; i++) {
+ m_layers[i] = new menulayer_t();
+ }
+ }
+
+ /*
+ =================
+ Draw
+ =================
+ */
+ static void Draw() {
+ if (cls.key_dest != key_menu)
+ return;
+
+ // repaint everything next frame
+ SCR.DirtyScreen();
+
+ // dim everything behind it down
+ if (cl.cinematictime > 0)
+ re.DrawFill(0, 0, viddef.width, viddef.height, 0);
+ else
+ re.DrawFadeScreen();
+
+ m_drawfunc.execute();
+
+ // delay playing the enter sound until after the
+ // menu has been drawn, to avoid delay while
+ // caching images
+ if (m_entersound) {
+ S.StartLocalSound(menu_in_sound);
+ m_entersound = false;
+ }
+ }
+
+ /*
+ =================
+ Keydown
+ =================
+ */
+ static void Keydown(int key) {
+ String s;
+
+ if (m_keyfunc != null)
+ if ((s = m_keyfunc.execute(key)) != null)
+ S.StartLocalSound(s);
+ }
+
+ public static void Action_DoEnter(menuaction_s a) {
+ if (a.callback != null)
+ a.callback.execute(a);
+ }
+
+ public static void Action_Draw(menuaction_s a) {
+ if ((a.flags & QMF_LEFT_JUSTIFY) != 0) {
+ if ((a.flags & QMF_GRAYED) != 0)
+ Menu_DrawStringDark(a.x + a.parent.x + LCOLUMN_OFFSET, a.y + a.parent.y, a.name);
+ else
+ Menu_DrawString(a.x + a.parent.x + LCOLUMN_OFFSET, a.y + a.parent.y, a.name);
+ }
+ else {
+ if ((a.flags & QMF_GRAYED) != 0)
+ Menu_DrawStringR2LDark(a.x + a.parent.x + LCOLUMN_OFFSET, a.y + a.parent.y, a.name);
+ else
+ Menu_DrawStringR2L(a.x + a.parent.x + LCOLUMN_OFFSET, a.y + a.parent.y, a.name);
+ }
+ if (a.ownerdraw != null)
+ a.ownerdraw.execute(a);
+ }
+
+ public static boolean Field_DoEnter(menufield_s f) {
+ if (f.callback != null) {
+ f.callback.execute(f);
+ return true;
+ }
+ return false;
+ }
+
+ public static void Field_Draw(menufield_s f) {
+ int i;
+ String tempbuffer;
+ //[128] = "";
+
+ if (f.name != null)
+ Menu_DrawStringR2LDark(f.x + f.parent.x + LCOLUMN_OFFSET, f.y + f.parent.y, f.name);
+
+ //strncpy(tempbuffer, f.buffer + f.visible_offset, f.visible_length);
+ String s = f.buffer.toString();
+ tempbuffer = s.substring(f.visible_offset, s.length());
+ re.DrawChar(f.x + f.parent.x + 16, f.y + f.parent.y - 4, 18);
+ re.DrawChar(f.x + f.parent.x + 16, f.y + f.parent.y + 4, 24);
+
+ re.DrawChar(f.x + f.parent.x + 24 + f.visible_length * 8, f.y + f.parent.y - 4, 20);
+ re.DrawChar(f.x + f.parent.x + 24 + f.visible_length * 8, f.y + f.parent.y + 4, 26);
+
+ for (i = 0; i < f.visible_length; i++) {
+ re.DrawChar(f.x + f.parent.x + 24 + i * 8, f.y + f.parent.y - 4, 19);
+ re.DrawChar(f.x + f.parent.x + 24 + i * 8, f.y + f.parent.y + 4, 25);
+ }
+
+ Menu_DrawString(f.x + f.parent.x + 24, f.y + f.parent.y, tempbuffer);
+
+ if (Menu_ItemAtCursor(f.parent) == f) {
+ int offset;
+
+ if (f.visible_offset != 0)
+ offset = f.visible_length;
+ else
+ offset = f.cursor;
+
+ if ((((int) (Sys.Milliseconds() / 250)) & 1) != 0) {
+ re.DrawChar(f.x + f.parent.x + (offset + 2) * 8 + 8, f.y + f.parent.y, 11);
+ }
+ else {
+ re.DrawChar(f.x + f.parent.x + (offset + 2) * 8 + 8, f.y + f.parent.y, ' ');
+ }
+ }
+ }
+
+ public static boolean Field_Key(menufield_s f, int k) {
+ char key = (char) k;
+
+ switch (key) {
+ case K_KP_SLASH :
+ key = '/';
+ break;
+ case K_KP_MINUS :
+ key = '-';
+ break;
+ case K_KP_PLUS :
+ key = '+';
+ break;
+ case K_KP_HOME :
+ key = '7';
+ break;
+ case K_KP_UPARROW :
+ key = '8';
+ break;
+ case K_KP_PGUP :
+ key = '9';
+ break;
+ case K_KP_LEFTARROW :
+ key = '4';
+ break;
+ case K_KP_5 :
+ key = '5';
+ break;
+ case K_KP_RIGHTARROW :
+ key = '6';
+ break;
+ case K_KP_END :
+ key = '1';
+ break;
+ case K_KP_DOWNARROW :
+ key = '2';
+ break;
+ case K_KP_PGDN :
+ key = '3';
+ break;
+ case K_KP_INS :
+ key = '0';
+ break;
+ case K_KP_DEL :
+ key = '.';
+ break;
+ }
+
+ if (key > 127) {
+ switch (key) {
+ case K_DEL :
+ default :
+ return false;
+ }
+ }
+
+ /*
+ ** support pasting from the clipboard
+ */
+ if ((Character.toUpperCase(key) == 'V' && keydown[K_CTRL]) || (((key == K_INS) || (key == K_KP_INS)) && keydown[K_SHIFT])) {
+ String cbd;
+
+ if ((cbd = Sys.GetClipboardData()) != null) {
+ //strtok(cbd, "\n\r\b");
+ String lines[] = Lib.linesplit(cbd);
+ if (lines.length > 0 && lines[0].length() != 0) {
+ //strncpy(f.buffer, cbd, f.length - 1);
+ f.buffer = new StringBuffer(lines[0]);
+ f.cursor = f.buffer.length();
+
+ f.visible_offset = f.cursor - f.visible_length;
+
+ if (f.visible_offset < 0)
+ f.visible_offset = 0;
+ }
+ }
+ return true;
+ }
+
+ switch (key) {
+ case K_KP_LEFTARROW :
+ case K_LEFTARROW :
+ case K_BACKSPACE :
+ if (f.cursor > 0) {
+ f.buffer.deleteCharAt(f.cursor - 1);
+ //memmove(f.buffer[f.cursor - 1], f.buffer[f.cursor], strlen(& f.buffer[f.cursor]) + 1);
+ f.cursor--;
+
+ if (f.visible_offset != 0) {
+ f.visible_offset--;
+ }
+ }
+ break;
+
+ case K_KP_DEL :
+ case K_DEL :
+ //memmove(& f.buffer[f.cursor], & f.buffer[f.cursor + 1], strlen(& f.buffer[f.cursor + 1]) + 1);
+ f.buffer.deleteCharAt(f.cursor);
+ break;
+
+ case K_KP_ENTER :
+ case K_ENTER :
+ case K_ESCAPE :
+ case K_TAB :
+ return false;
+
+ case K_SPACE :
+ default :
+ if (!Character.isDigit(key) && (f.flags & QMF_NUMBERSONLY) != 0)
+ return false;
+
+ if (f.cursor < f.length) {
+ f.buffer.append(key);
+ f.cursor++;
+
+ if (f.cursor > f.visible_length) {
+ f.visible_offset++;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ public static void Menu_AddItem(menuframework_s menu, menucommon_s item) {
+ if (menu.nitems == 0)
+ menu.nslots = 0;
+
+ if (menu.nitems < MAXMENUITEMS) {
+ menu.items[menu.nitems] = item;
+ ((menucommon_s) menu.items[menu.nitems]).parent = menu;
+ menu.nitems++;
+ }
+
+ menu.nslots = Menu_TallySlots(menu);
+ }
+
+ /*
+ ** Menu_AdjustCursor
+ **
+ ** This function takes the given menu, the direction, and attempts
+ ** to adjust the menu's cursor so that it's at the next available
+ ** slot.
+ */
+ public static void Menu_AdjustCursor(menuframework_s m, int dir) {
+ menucommon_s citem;
+
+ /*
+ ** see if it's in a valid spot
+ */
+ if (m.cursor >= 0 && m.cursor < m.nitems) {
+ if ((citem = Menu_ItemAtCursor(m)) != null) {
+ if (citem.type != MTYPE_SEPARATOR)
+ return;
+ }
+ }
+
+ /*
+ ** it's not in a valid spot, so crawl in the direction indicated until we
+ ** find a valid spot
+ */
+ if (dir == 1) {
+ while (true) {
+ citem = Menu_ItemAtCursor(m);
+ if (citem != null)
+ if (citem.type != MTYPE_SEPARATOR)
+ break;
+ m.cursor += dir;
+ if (m.cursor >= m.nitems)
+ m.cursor = 0;
+ }
+ }
+ else {
+ while (true) {
+ citem = Menu_ItemAtCursor(m);
+ if (citem != null)
+ if (citem.type != MTYPE_SEPARATOR)
+ break;
+ m.cursor += dir;
+ if (m.cursor < 0)
+ m.cursor = m.nitems - 1;
+ }
+ }
+ }
+
+ public static void Menu_Center(menuframework_s menu) {
+ int height;
+
+ height = ((menucommon_s) menu.items[menu.nitems - 1]).y;
+ height += 10;
+
+ menu.y = (viddef.height - height) / 2;
+ }
+
+ public static void Menu_Draw(menuframework_s menu) {
+ int i;
+ menucommon_s item;
+
+ /*
+ ** draw contents
+ */
+ for (i = 0; i < menu.nitems; i++) {
+ switch (((menucommon_s) menu.items[i]).type) {
+ case MTYPE_FIELD :
+ Field_Draw((menufield_s) menu.items[i]);
+ break;
+ case MTYPE_SLIDER :
+ Slider_Draw((menuslider_s) menu.items[i]);
+ break;
+ case MTYPE_LIST :
+ MenuList_Draw((menulist_s) menu.items[i]);
+ break;
+ case MTYPE_SPINCONTROL :
+ SpinControl_Draw((menulist_s) menu.items[i]);
+ break;
+ case MTYPE_ACTION :
+ Action_Draw((menuaction_s) menu.items[i]);
+ break;
+ case MTYPE_SEPARATOR :
+ Separator_Draw((menuseparator_s) menu.items[i]);
+ break;
+ }
+ }
+
+ item = Menu_ItemAtCursor(menu);
+
+ if (item != null && item.cursordraw != null) {
+ item.cursordraw.execute(item);
+ }
+ else if (menu.cursordraw != null) {
+ menu.cursordraw.execute(menu);
+ }
+ else if (item != null && item.type != MTYPE_FIELD) {
+ if ((item.flags & QMF_LEFT_JUSTIFY) != 0) {
+ re.DrawChar(menu.x + item.x - 24 + item.cursor_offset, menu.y + item.y, 12 + ((int) (Sys.Milliseconds() / 250) & 1));
+ }
+ else {
+ re.DrawChar(menu.x + item.cursor_offset, menu.y + item.y, 12 + ((int) (Sys.Milliseconds() / 250) & 1));
+ }
+ }
+
+ if (item != null) {
+ if (item.statusbarfunc != null)
+ item.statusbarfunc.execute(item);
+ else if (item.statusbar != null)
+ Menu_DrawStatusBar(item.statusbar);
+ else
+ Menu_DrawStatusBar(menu.statusbar);
+
+ }
+ else {
+ Menu_DrawStatusBar(menu.statusbar);
+ }
+ }
+
+ public static void Menu_DrawStatusBar(String string) {
+ if (string != null) {
+ int l = strlen(string);
+ int maxrow = viddef.height / 8;
+ int maxcol = viddef.width / 8;
+ int col = maxcol / 2 - l / 2;
+
+ re.DrawFill(0, viddef.height - 8, viddef.width, 8, 4);
+ Menu_DrawString(col * 8, viddef.height - 8, string);
+ }
+ else {
+ re.DrawFill(0, viddef.height - 8, viddef.width, 8, 0);
+ }
+ }
+
+ public static void Menu_DrawString(int x, int y, String string) {
+ int i;
+
+ for (i = 0; i < strlen(string); i++) {
+ re.DrawChar((x + i * 8), y, string.charAt(i));
+ }
+ }
+
+ public static void Menu_DrawStringDark(int x, int y, String string) {
+ int i;
+
+ for (i = 0; i < strlen(string); i++) {
+ re.DrawChar((x + i * 8), y, string.charAt(i) + 128);
+ }
+ }
+
+ public static void Menu_DrawStringR2L(int x, int y, String string) {
+ int i;
+
+ for (i = 0; i < strlen(string); i++) {
+ re.DrawChar((x - i * 8), y, string.charAt(strlen(string) - i - 1));
+ }
+ }
+
+ public static void Menu_DrawStringR2LDark(int x, int y, String string) {
+ int i;
+
+ for (i = 0; i < strlen(string); i++) {
+ re.DrawChar((x - i * 8), y, string.charAt(strlen(string) - i - 1) + 128);
+ }
+ }
+
+ public static menucommon_s Menu_ItemAtCursor(menuframework_s m) {
+ if (m.cursor < 0 || m.cursor >= m.nitems)
+ return null;
+
+ return (menucommon_s) m.items[m.cursor];
+ }
+
+ static boolean Menu_SelectItem(menuframework_s s) {
+ menucommon_s item = Menu_ItemAtCursor(s);
+
+ if (item != null) {
+ switch (item.type) {
+ case MTYPE_FIELD :
+ return Field_DoEnter((menufield_s) item);
+ case MTYPE_ACTION :
+ Action_DoEnter((menuaction_s) item);
+ return true;
+ case MTYPE_LIST :
+ // Menulist_DoEnter( ( menulist_s ) item );
+ return false;
+ case MTYPE_SPINCONTROL :
+ // SpinControl_DoEnter( ( menulist_s ) item );
+ return false;
+ }
+ }
+ return false;
+ }
+
+ public static void Menu_SetStatusBar(menuframework_s m, String string) {
+ m.statusbar = string;
+ }
+
+ public static void Menu_SlideItem(menuframework_s s, int dir) {
+ menucommon_s item = (menucommon_s) Menu_ItemAtCursor(s);
+
+ if (item != null) {
+ switch (item.type) {
+ case MTYPE_SLIDER :
+ Slider_DoSlide((menuslider_s) item, dir);
+ break;
+ case MTYPE_SPINCONTROL :
+ SpinControl_DoSlide((menulist_s) item, dir);
+ break;
+ }
+ }
+ }
+
+ public static int Menu_TallySlots(menuframework_s menu) {
+ int i;
+ int total = 0;
+
+ for (i = 0; i < menu.nitems; i++) {
+ if (((menucommon_s) menu.items[i]).type == MTYPE_LIST) {
+ int nitems = 0;
+ String n[] = ((menulist_s) menu.items[i]).itemnames;
+
+ while (n[nitems] != null)
+ nitems++;
+
+ total += nitems;
+ }
+ else {
+ total++;
+ }
+ }
+
+ return total;
+ }
+
+ public static void Menulist_DoEnter(menulist_s l) {
+ int start;
+
+ start = l.y / 10 + 1;
+
+ l.curvalue = l.parent.cursor - start;
+
+ if (l.callback != null)
+ l.callback.execute(l);
+ }
+
+ public static void MenuList_Draw(menulist_s l) {
+ String n[];
+ int y = 0;
+
+ Menu_DrawStringR2LDark(l.x + l.parent.x + LCOLUMN_OFFSET, l.y + l.parent.y, l.name);
+
+ n = l.itemnames;
+
+ re.DrawFill(l.x - 112 + l.parent.x, l.parent.y + l.y + l.curvalue * 10 + 10, 128, 10, 16);
+ int i = 0;
+
+ while (n[i] != null) {
+ Menu_DrawStringR2LDark(l.x + l.parent.x + LCOLUMN_OFFSET, l.y + l.parent.y + y + 10, n[i]);
+
+ i++;
+ y += 10;
+ }
+ }
+
+ public static void Separator_Draw(menuseparator_s s) {
+ if (s.name != null)
+ Menu_DrawStringR2LDark(s.x + s.parent.x, s.y + s.parent.y, s.name);
+ }
+
+ public static void Slider_DoSlide(menuslider_s s, int dir) {
+ s.curvalue += dir;
+
+ if (s.curvalue > s.maxvalue)
+ s.curvalue = s.maxvalue;
+ else if (s.curvalue < s.minvalue)
+ s.curvalue = s.minvalue;
+
+ if (s.callback != null)
+ s.callback.execute(s);
+ }
+
+ public static final int SLIDER_RANGE = 10;
+
+ public static void Slider_Draw(menuslider_s s) {
+ int i;
+
+ Menu_DrawStringR2LDark(s.x + s.parent.x + LCOLUMN_OFFSET, s.y + s.parent.y, s.name);
+
+ s.range = (s.curvalue - s.minvalue) / (float) (s.maxvalue - s.minvalue);
+
+ if (s.range < 0)
+ s.range = 0;
+ if (s.range > 1)
+ s.range = 1;
+ re.DrawChar(s.x + s.parent.x + RCOLUMN_OFFSET, s.y + s.parent.y, 128);
+ for (i = 0; i < SLIDER_RANGE; i++)
+ re.DrawChar(RCOLUMN_OFFSET + s.x + i * 8 + s.parent.x + 8, s.y + s.parent.y, 129);
+ re.DrawChar(RCOLUMN_OFFSET + s.x + i * 8 + s.parent.x + 8, s.y + s.parent.y, 130);
+ re.DrawChar((int) (8 + RCOLUMN_OFFSET + s.parent.x + s.x + (SLIDER_RANGE - 1) * 8 * s.range), s.y + s.parent.y, 131);
+ }
+
+ public static void SpinControl_DoEnter(menulist_s s) {
+ s.curvalue++;
+ if (s.itemnames[s.curvalue] == null)
+ s.curvalue = 0;
+
+ if (s.callback != null)
+ s.callback.execute(s);
+ }
+
+ public static void SpinControl_DoSlide(menulist_s s, int dir) {
+ s.curvalue += dir;
+
+ if (s.curvalue < 0)
+ s.curvalue = 0;
+ else if (s.itemnames[s.curvalue] == null)
+ s.curvalue--;
+
+ if (s.callback != null)
+ s.callback.execute(s);
+ }
+
+ public static void SpinControl_Draw(menulist_s s) {
+ //char buffer[100];
+ String buffer;
+
+ if (s.name != null) {
+ Menu_DrawStringR2LDark(s.x + s.parent.x + LCOLUMN_OFFSET, s.y + s.parent.y, s.name);
+ }
+
+ if (s.itemnames[s.curvalue].indexOf('\n') == -1) {
+ Menu_DrawString(RCOLUMN_OFFSET + s.x + s.parent.x, s.y + s.parent.y, s.itemnames[s.curvalue]);
+ }
+ else {
+ String line1, line2;
+ line1 = Lib.leftFrom(s.itemnames[s.curvalue], '\n');
+ Menu_DrawString(RCOLUMN_OFFSET + s.x + s.parent.x, s.y + s.parent.y, line1);
+
+ line2 = Lib.rightFrom(s.itemnames[s.curvalue], '\n');
+
+ int pos = line2.indexOf('\n');
+ if (pos != -1)
+ line2 = line2.substring(0, pos);
+
+ Menu_DrawString(RCOLUMN_OFFSET + s.x + s.parent.x, s.y + s.parent.y + 10, line2);
+ }
+ }
+}