/* * XPilot NG, a multiplayer space war game. * * Copyright (C) 1991-2001 by * * Bjørn Stabell * Ken Ronny Schouten * Bert Gijsbers * Dick Balaska * * Copyright (C) 2003-2004 Kristian Söderblom * * 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 */ #include "xpclient.h" #define MAX_BUTTON_DEFS 10 static BITV_DECL(keyv, NUM_KEYS); static unsigned char keyv_new[NUM_KEYS]; keys_t buttonDefs[MAX_POINTER_BUTTONS][MAX_BUTTON_DEFS+1]; char *pointerButtonBindings[MAX_POINTER_BUTTONS] = { NULL, NULL, NULL, NULL, NULL }; static int Key_get_count(keys_t key); static bool Key_inc_count(keys_t key); static bool Key_dec_count(keys_t key); void Pointer_control_newbie_message(void) { xp_option_t *opt = Find_option("keyExit"); char msg[MSG_LEN]; const char *val; if (!newbie) return; if (!opt) return; val = Option_value_to_string(opt); if (strlen(val) == 0) return; if (clData.pointerControl) snprintf(msg, sizeof(msg), "Mouse steering enabled. " "Key(s) to disable it: %s.", val); else snprintf(msg, sizeof(msg), "Mouse steering disabled. " "Click background with left mouse button to enable it."); Add_newbie_message(msg); } void Pointer_control_set_state(bool on) { if (clData.pointerControl == on) return; Platform_specific_pointer_control_set_state(on); clData.pointerControl = on; if (!clData.restorePointerControl) Pointer_control_newbie_message(); } void Talk_set_state(bool on) { if (clData.talking == on) return; if (on) { /* When enabling talking, disable pointer control if it is enabled. */ if (clData.pointerControl) { clData.restorePointerControl = true; Pointer_control_set_state(false); } } Platform_specific_talk_set_state(on); if (!on) { /* When disabling talking, enable pointer control if it was enabled. */ if (clData.restorePointerControl) { Pointer_control_set_state(true); clData.restorePointerControl = false; } } clData.talking = on; } static inline int pointer_button_index_by_option(xp_option_t *opt) { return atoi(Option_get_name(opt) + strlen("pointerButton")) - 1; } static int numButtonDefs[MAX_POINTER_BUTTONS] = { 0, 0, 0, 0, 0 }; static int Num_buttonDefs(int ind) { assert(ind >= 0); assert(ind < MAX_POINTER_BUTTONS); return numButtonDefs[ind]; } static void Clear_buttonDefs(int ind) { assert(ind >= 0); assert(ind < MAX_POINTER_BUTTONS); numButtonDefs[ind] = 0; } int Key_init(void) { int i; if (sizeof(keyv) != KEYBOARD_SIZE) { warn("%s, %d: keyv size %d, KEYBOARD_SIZE is %d", __FILE__, __LINE__, sizeof(keyv), KEYBOARD_SIZE); exit(1); } memset(keyv, 0, sizeof keyv); for (i = 0; i < NUM_KEYS; i++) keyv_new[i] = 0; BITV_SET(keyv, KEY_SHIELD); return 0; } int Key_update(void) { return Send_keyboard(keyv); } static bool Key_check_talk_macro(keys_t key) { if (key >= KEY_MSG_1 && key < KEY_MSG_1 + TALK_FAST_NR_OF_MSGS) Talk_macro((int)(key - KEY_MSG_1)); return true; } static bool Key_press_id_mode(void) { showUserName = showUserName ? false : true; scoresChanged = true; return false; /* server doesn't need to know */ } static bool Key_press_autoshield_hack(void) { if (auto_shield && BITV_ISSET(keyv, KEY_SHIELD)) BITV_CLR(keyv, KEY_SHIELD); return false; } static bool Key_press_shield(keys_t key) { if (toggle_shield) { shields = !shields; if (shields) BITV_SET(keyv, key); else BITV_CLR(keyv, key); return true; } else if (auto_shield) shields = true; return false; } static bool Key_press_fuel(void) { fuelTime = FUEL_NOTIFY_TIME; return false; } static bool Key_press_swap_settings(void) { double tmp; #define SWAP(a, b) (tmp = (a), (a) = (b), (b) = tmp) SWAP(power, power_s); SWAP(turnspeed, turnspeed_s); SWAP(turnresistance, turnresistance_s); controlTime = CONTROL_TIME; Config_redraw(); return true; } static bool Key_press_swap_scalefactor(void) { double a = clData.altScaleFactor; Set_altScaleFactor(NULL, clData.scaleFactor); Set_scaleFactor(NULL, a); return false; } static bool Key_press_increase_power(void) { power = power * 1.10; power = MIN(power, MAX_PLAYER_POWER); Send_power(power); Config_redraw(); controlTime = CONTROL_TIME; return false; /* server doesn't see these keypresses anymore */ } static bool Key_press_decrease_power(void) { power = power / 1.10; power = MAX(power, MIN_PLAYER_POWER); Send_power(power); Config_redraw(); controlTime = CONTROL_TIME; return false; /* server doesn't see these keypresses anymore */ } static bool Key_press_increase_turnspeed(void) { turnspeed = turnspeed * 1.05; turnspeed = MIN(turnspeed, MAX_PLAYER_TURNSPEED); Send_turnspeed(turnspeed); Config_redraw(); controlTime = CONTROL_TIME; return false; /* server doesn't see these keypresses anymore */ } static bool Key_press_decrease_turnspeed(void) { turnspeed = turnspeed / 1.05; turnspeed = MAX(turnspeed, MIN_PLAYER_TURNSPEED); Send_turnspeed(turnspeed); Config_redraw(); controlTime = CONTROL_TIME; return false; /* server doesn't see these keypresses anymore */ } static bool Key_press_talk(void) { int i; /* * this releases mouse in x11 client, so we clear the mouse buttons * so they don't lock on */ if (clData.pointerControl) for (i = 0; i < MAX_POINTER_BUTTONS; i++) Pointer_button_released(i); Talk_set_state(!clData.talking); return false; /* server doesn't need to know */ } static bool Key_press_show_items(void) { instruments.showItems = !instruments.showItems; return false; /* server doesn't need to know */ } static bool Key_press_show_messages(void) { instruments.showMessages = !instruments.showMessages; return false; /* server doesn't need to know */ } static bool Key_press_pointer_control(void) { Pointer_control_set_state(!clData.pointerControl); return false; /* server doesn't need to know */ } static bool Key_press_toggle_fullscreen(void) { Toggle_fullscreen(); return false; /* server doesn't need to know */ } static bool Key_press_toggle_radar_score(void) { Toggle_radar_and_scorelist(); return false; /* server doesn't need to know */ } static bool Key_press_toggle_record(void) { Record_toggle(); return false; /* server doesn't need to know */ } static bool Key_press_toggle_sound(void) { #ifdef SOUND sound = !sound; #endif return false; /* server doesn't need to know */ } static bool Key_press_msgs_stdout(void) { Print_messages_to_stdout(); return false; /* server doesn't need to know */ } static bool Key_press_select_lose_item(void) { if (lose_item_active == 1) lose_item_active = 2; else lose_item_active = 1; return true; } static bool Key_press_yes(void) { /* Handled in other code */ assert(!clData.quitMode); return false; /* server doesn't need to know */ } static bool Key_press_no(void) { return false; /* server doesn't need to know */ } static bool Key_press_exit(void) { int i; /* exit pointer control if exit key pressed in pointer control mode */ if (clData.pointerControl) { /* * this releases mouse, so we clear the mouse buttons so * they don't lock on */ for (i = 0; i < MAX_POINTER_BUTTONS; i++) Pointer_button_released(i); Pointer_control_set_state(false); return false; /* server doesn't need to know */ } clData.quitMode = true; Add_alert_message("Really Quit (y/n) ?", 0.0); return false; /* server doesn't need to know */ } static int Key_get_count(keys_t key) { if (key >= NUM_KEYS) return -1; return keyv_new[key]; } static bool Key_inc_count(keys_t key) { if (key >= NUM_KEYS) return false; if (keyv_new[key] < 255) { ++keyv_new[key]; return true; } return false; } static bool Key_dec_count(keys_t key) { if (key >= NUM_KEYS) return false; if (keyv_new[key] > 0) { --keyv_new[key]; return true; } return false; } void Key_clear_counts(void) { int i; bool change = false; for (i = 0; i < NUM_KEYS; i++) { if (keyv_new[i] > 0) { /* set to one so that Key_release(i) will trigger */ keyv_new[i] = 1; change |= Key_release((keys_t)i); } } if (change) Net_key_change(); } /* Remember which key we used to exit quit mode. */ static keys_t quit_mode_exit_key = KEY_DUMMY; static bool Quit_mode_key_press(keys_t key) { if (key == KEY_YES) Client_exit(0); if (key == KEY_NO || key == KEY_EXIT) { clData.quitMode = false; Clear_alert_messages(); quit_mode_exit_key = key; } return false; } bool Key_press(keys_t key) { bool countchange; int keycount, i; if (clData.quitMode) return Quit_mode_key_press(key); countchange = Key_inc_count(key); keycount = Key_get_count(key); /* * keycount -1 means this was a client only key, we don't count those */ if (keycount != -1) { /* * if countchange is false it means that Key__count() * failed to change the count due to being at the end of the range * (should be very rare) keycount != 1 means that this key was * already pressed (multiple key mappings) */ if ((!countchange) || (keycount != 1)) return true; } Key_check_talk_macro(key); switch (key) { case KEY_ID_MODE: return Key_press_id_mode(); case KEY_FIRE_SHOT: case KEY_FIRE_LASER: case KEY_FIRE_MISSILE: case KEY_FIRE_TORPEDO: case KEY_FIRE_HEAT: case KEY_DROP_MINE: case KEY_DETACH_MINE: Key_press_autoshield_hack(); break; case KEY_SHIELD: if (Key_press_shield(key)) return true; break; case KEY_REFUEL: case KEY_REPAIR: case KEY_TANK_NEXT: case KEY_TANK_PREV: Key_press_fuel(); break; case KEY_SWAP_SETTINGS: if (!Key_press_swap_settings()) return false; break; case KEY_SWAP_SCALEFACTOR: if (!Key_press_swap_scalefactor()) return false; break; case KEY_INCREASE_POWER: return Key_press_increase_power(); case KEY_DECREASE_POWER: return Key_press_decrease_power(); case KEY_INCREASE_TURNSPEED: return Key_press_increase_turnspeed(); case KEY_DECREASE_TURNSPEED: return Key_press_decrease_turnspeed(); case KEY_TALK: return Key_press_talk(); case KEY_TOGGLE_OWNED_ITEMS: return Key_press_show_items(); case KEY_TOGGLE_MESSAGES: return Key_press_show_messages(); case KEY_POINTER_CONTROL: /* * this releases mouse, so we clear the mouse buttons so they * don't lock on */ if (clData.pointerControl) for (i = 0; i < MAX_POINTER_BUTTONS; i++) Pointer_button_released(i); return Key_press_pointer_control(); case KEY_TOGGLE_RECORD: return Key_press_toggle_record(); case KEY_TOGGLE_SOUND: return Key_press_toggle_sound(); case KEY_TOGGLE_RADAR_SCORE: return Key_press_toggle_radar_score(); case KEY_PRINT_MSGS_STDOUT: return Key_press_msgs_stdout(); case KEY_TOGGLE_FULLSCREEN: return Key_press_toggle_fullscreen(); case KEY_SELECT_ITEM: case KEY_LOSE_ITEM: if (!Key_press_select_lose_item()) return false; case KEY_EXIT: return Key_press_exit(); case KEY_YES: return Key_press_yes(); case KEY_NO: return Key_press_no(); default: break; } if (key < NUM_KEYS) BITV_SET(keyv, key); return true; } bool Key_release(keys_t key) { bool countchange; int keycount; /* * Make sure nothing is done when we release the button we used * to exit quit mode with. */ if (key == quit_mode_exit_key) { assert(key != KEY_DUMMY); quit_mode_exit_key = KEY_DUMMY; return false; } countchange = Key_dec_count(key); keycount = Key_get_count(key); /* -1 means this was a client only key, we don't count those */ if (keycount != -1) { /* * if countchange is false it means that Key__count() * failed to change the count due to being at the end of the range * (happens to most key releases let through from talk mode) * keycount != 0 means that some physical keys remain pressed * that map to this xpilot key */ if ((!countchange) || (keycount != 0)) return true; } switch (key) { case KEY_ID_MODE: case KEY_TALK: case KEY_TOGGLE_OWNED_ITEMS: case KEY_TOGGLE_MESSAGES: return false; /* server doesn't need to know */ /* Don auto-shield hack */ /* restore shields */ case KEY_FIRE_SHOT: case KEY_FIRE_LASER: case KEY_FIRE_MISSILE: case KEY_FIRE_TORPEDO: case KEY_FIRE_HEAT: case KEY_DROP_MINE: case KEY_DETACH_MINE: if (auto_shield && shields && !BITV_ISSET(keyv, KEY_SHIELD)) { /* Here We need to know if any other weapons are still on */ /* before we turn shield back on */ BITV_CLR(keyv, key); if (!BITV_ISSET(keyv, KEY_FIRE_SHOT) && !BITV_ISSET(keyv, KEY_FIRE_LASER) && !BITV_ISSET(keyv, KEY_FIRE_MISSILE) && !BITV_ISSET(keyv, KEY_FIRE_TORPEDO) && !BITV_ISSET(keyv, KEY_FIRE_HEAT) && !BITV_ISSET(keyv, KEY_DROP_MINE) && !BITV_ISSET(keyv, KEY_DETACH_MINE)) BITV_SET(keyv, KEY_SHIELD); } break; case KEY_SHIELD: if (toggle_shield) return false; else if (auto_shield) shields = false; break; case KEY_REFUEL: case KEY_REPAIR: fuelTime = FUEL_NOTIFY_TIME; break; case KEY_SELECT_ITEM: case KEY_LOSE_ITEM: if (lose_item_active == 2) lose_item_active = 1; else lose_item_active = -(int)(clientFPS + 0.5); break; default: break; } if (key < NUM_KEYS) BITV_CLR(keyv, key); return true; } void Reset_shields(void) { if (toggle_shield || auto_shield) { BITV_SET(keyv, KEY_SHIELD); shields = true; if (auto_shield) { if (BITV_ISSET(keyv, KEY_FIRE_SHOT) || BITV_ISSET(keyv, KEY_FIRE_LASER) || BITV_ISSET(keyv, KEY_FIRE_MISSILE) || BITV_ISSET(keyv, KEY_FIRE_TORPEDO) || BITV_ISSET(keyv, KEY_FIRE_HEAT) || BITV_ISSET(keyv, KEY_DROP_MINE) || BITV_ISSET(keyv, KEY_DETACH_MINE)) BITV_CLR(keyv, KEY_SHIELD); } Net_key_change(); } } void Set_auto_shield(bool on) { auto_shield = on; } void Set_toggle_shield(bool on) { toggle_shield = on; if (toggle_shield) { if (auto_shield) shields = true; else shields = (BITV_ISSET(keyv, KEY_SHIELD)) ? true : false; } } /* * Function to call when a button of a pointing device has been pressed. * Argument 'button' should be 1 for the first pointer button, etc. */ void Pointer_button_pressed(int button) { int i, b_index = button - 1; bool key_change = false; if (button < 1 || button > MAX_POINTER_BUTTONS) return; for (i = 0; i < Num_buttonDefs(b_index); i++) key_change |= Key_press(buttonDefs[b_index][i]); if (key_change) Net_key_change(); } void Pointer_button_released(int button) { int i, b_index = button - 1; bool key_change = false; if (button < 1 || button > MAX_POINTER_BUTTONS) return; for (i = 0; i < Num_buttonDefs(b_index); i++) key_change |= Key_release(buttonDefs[b_index][i]); if (key_change) Net_key_change(); } void Keyboard_button_pressed(xp_keysym_t ks) { bool change = false; keys_t key; #if 0 { char foo[80]; sprintf(foo, "keysym = %d (0x%x) []", (int)ks, (int)ks); Add_message(foo); } #endif for (key = Generic_lookup_key(ks, true); key != KEY_DUMMY; key = Generic_lookup_key(ks, false)) change |= Key_press(key); if (change) Net_key_change(); } void Keyboard_button_released(xp_keysym_t ks) { bool change = false; keys_t key; for (key = Generic_lookup_key(ks, true); key != KEY_DUMMY; key = Generic_lookup_key(ks, false)) change |= Key_release(key); if (change) Net_key_change(); } static void Bind_key_to_pointer_button(keys_t key, int ind) { int num_defs; assert(ind >= 0); assert(ind < MAX_POINTER_BUTTONS); assert(key != KEY_DUMMY); num_defs = Num_buttonDefs(ind); if (num_defs == MAX_BUTTON_DEFS) { warn("Can only have %d keys bound to pointerButton%d.", MAX_BUTTON_DEFS, ind + 1); return; } buttonDefs[ind][num_defs] = key; numButtonDefs[ind]++; } static bool setPointerButtonBinding(xp_option_t *opt, const char *value) { int ind = pointer_button_index_by_option(opt); char *ptr, *valcpy; int j; assert(ind >= 0); assert(ind < MAX_POINTER_BUTTONS); assert(value); XFREE(pointerButtonBindings[ind]); Clear_buttonDefs(ind); pointerButtonBindings[ind] = xp_safe_strdup(value); valcpy = xp_safe_strdup(value); for (ptr = strtok(valcpy, " \t\r\n"); ptr != NULL; ptr = strtok(NULL, " \t\r\n")) { if (!strncasecmp(ptr, "key", 3)) ptr += 3; for (j = 0; j < num_options; j++) { xp_option_t *opt_j = Option_by_index(j); const char *opt_j_name; keys_t opt_j_key; assert(opt_j); opt_j_name = Option_get_name(opt_j); opt_j_key = Option_get_key(opt_j); if (opt_j_key != KEY_DUMMY && (!strcasecmp(ptr, opt_j_name + 3))) { Bind_key_to_pointer_button(opt_j_key, ind); break; } } if (j == num_options) warn("Unknown key \"%s\" for %s.", ptr, Option_get_name(opt)); } XFREE(valcpy); return true; } static const char *getPointerButtonBinding(xp_option_t *opt) { int ind = pointer_button_index_by_option(opt); assert(ind >= 0); assert(ind < MAX_POINTER_BUTTONS); return pointerButtonBindings[ind]; } /* * Generic key options. */ /* unused: a s */ xp_option_t key_options[] = { XP_KEY_OPTION( "keyTurnLeft", "", KEY_TURN_LEFT, "Turn left (anti-clockwise).\n"), XP_KEY_OPTION( "keyTurnRight", "", KEY_TURN_RIGHT, "Turn right (clockwise).\n"), XP_KEY_OPTION( "keyThrust", "Shift_R Shift_L", KEY_THRUST, "Thrust.\n"), XP_KEY_OPTION( "keyShield", "space", KEY_SHIELD, "Raise or toggle the shield.\n"), XP_KEY_OPTION( "keyFireShot", "Return Linefeed", KEY_FIRE_SHOT, "Fire shot.\n" "Note that shields must be down to fire.\n"), XP_KEY_OPTION( "keyFireMissile", "backslash", KEY_FIRE_MISSILE, "Fire smart missile.\n"), XP_KEY_OPTION( "keyFireTorpedo", "quoteright", KEY_FIRE_TORPEDO, "Fire unguided torpedo.\n"), XP_KEY_OPTION( "keyFireHeat", "semicolon", KEY_FIRE_HEAT, "Fire heatseeking missile.\n"), XP_KEY_OPTION( "keyFireLaser", "slash", KEY_FIRE_LASER, "Activate laser beam.\n"), XP_KEY_OPTION( "keyDropMine", "Tab", KEY_DROP_MINE, "Drop a stationary mine.\n"), XP_KEY_OPTION( "keyDetachMine", "bracketright", KEY_DETACH_MINE, "Detach a moving mine.\n"), XP_KEY_OPTION( "keyDetonateMines", "equal", KEY_DETONATE_MINES, "Detonate the closest mine you have dropped or thrown.\n"), XP_KEY_OPTION( "keyLockClose", "Up", KEY_LOCK_CLOSE, "Lock on closest player.\n"), XP_KEY_OPTION( "keyLockNextClose", "Down", KEY_LOCK_NEXT_CLOSE, "Lock on next closest player.\n"), XP_KEY_OPTION( "keyLockNext", "Next Right", /* Next is a.k.a. Page Down */ KEY_LOCK_NEXT, "Lock on next player.\n"), XP_KEY_OPTION( "keyLockPrev", "Prior Right", /* Prior is a.k.a. Page Up */ KEY_LOCK_PREV, "Lock on previous player.\n"), XP_KEY_OPTION( "keyRefuel", "f Control_L Control_R", KEY_REFUEL, "Refuel.\n"), XP_KEY_OPTION( "keyRepair", "f", KEY_REPAIR, "Repair target.\n"), XP_KEY_OPTION( "keyCloak", "Delete BackSpace", KEY_CLOAK, "Toggle cloakdevice.\n"), XP_KEY_OPTION( "keyEcm", "bracketleft", KEY_ECM, "Use ECM.\n"), XP_KEY_OPTION( "keySelfDestruct", "End", KEY_SELF_DESTRUCT, "Toggle self destruct.\n"), XP_KEY_OPTION( "keyIdMode", "u", KEY_ID_MODE, "Toggle User mode (show real names).\n"), XP_KEY_OPTION( "keyPause", "Pause", KEY_PAUSE, "Toggle pause mode.\n" "When the ship is stationary on its homebase.\n"), XP_KEY_OPTION( "keySwapSettings", "", KEY_SWAP_SETTINGS, "Swap to alternate control settings.\n" "These are the power, turn speed and turn resistance settings.\n"), XP_KEY_OPTION( "keySwapScaleFactor", "", KEY_SWAP_SCALEFACTOR, "Swap scalefactor settings.\n"), XP_KEY_OPTION( "keyChangeHome", "Home h", KEY_CHANGE_HOME, "Change home base.\n" "When the ship is close to a suitable base.\n"), XP_KEY_OPTION( "keyConnector", "f Control_L Control_R", KEY_CONNECTOR, "Connect to a ball.\n"), XP_KEY_OPTION( "keyDropBall", "d", KEY_DROP_BALL, "Drop a ball.\n"), XP_KEY_OPTION( "keyTankNext", "e", KEY_TANK_NEXT, "Use the next tank.\n"), XP_KEY_OPTION( "keyTankPrev", "w", KEY_TANK_PREV, "Use the the previous tank.\n"), XP_KEY_OPTION( "keyTankDetach", "r", KEY_TANK_DETACH, "Detach the current tank.\n"), XP_KEY_OPTION( "keyIncreasePower", "KP_Multiply", KEY_INCREASE_POWER, "Increase engine power.\n"), XP_KEY_OPTION( "keyDecreasePower", "KP_Divide", KEY_DECREASE_POWER, "Decrease engine power.\n"), XP_KEY_OPTION( "keyIncreaseTurnspeed", "KP_Add", KEY_INCREASE_TURNSPEED, "Increase turnspeed.\n"), XP_KEY_OPTION( "keyDecreaseTurnspeed", "KP_Subtract", KEY_DECREASE_TURNSPEED, "Decrease turnspeed.\n"), XP_KEY_OPTION( "keyTransporter", "t", KEY_TRANSPORTER, "Use transporter to steal an item.\n"), XP_KEY_OPTION( "keyDeflector", "o", KEY_DEFLECTOR, "Toggle deflector.\n"), XP_KEY_OPTION( "keyHyperJump", "q", KEY_HYPERJUMP, "Teleport.\n"), XP_KEY_OPTION( "keyPhasing", "p", KEY_PHASING, "Use phasing device.\n"), XP_KEY_OPTION( "keyTalk", "m", KEY_TALK, "Toggle talk window.\n"), XP_KEY_OPTION( "keyToggleNuclear", "n", KEY_TOGGLE_NUCLEAR, "Toggle nuclear weapon modifier.\n"), XP_KEY_OPTION( "keyToggleCluster", "c", KEY_TOGGLE_CLUSTER, "Toggle cluster weapon modifier.\n"), XP_KEY_OPTION( "keyToggleImplosion", "i", KEY_TOGGLE_IMPLOSION, "Toggle implosion weapon modifier.\n"), XP_KEY_OPTION( "keyToggleVelocity", "v", KEY_TOGGLE_VELOCITY, "Toggle explosion velocity weapon modifier.\n"), XP_KEY_OPTION( "keyToggleMini", "x", KEY_TOGGLE_MINI, "Toggle mini weapon modifier.\n"), XP_KEY_OPTION( "keyToggleSpread", "z", KEY_TOGGLE_SPREAD, "Toggle spread weapon modifier.\n"), XP_KEY_OPTION( "keyTogglePower", "b", KEY_TOGGLE_POWER, "Toggle power weapon modifier.\n"), XP_KEY_OPTION( "keyToggleCompass", "KP_7", KEY_TOGGLE_COMPASS, "Toggle HUD/radar compass lock.\n"), XP_KEY_OPTION( "keyToggleAutoPilot", "h", KEY_TOGGLE_AUTOPILOT, "Toggle automatic pilot mode.\n"), XP_KEY_OPTION( "keyToggleLaser", "l", KEY_TOGGLE_LASER, "Toggle laser modifier.\n"), XP_KEY_OPTION( "keyEmergencyThrust", "j", KEY_EMERGENCY_THRUST, "Pull emergency thrust handle.\n"), XP_KEY_OPTION( "keyEmergencyShield", "Caps_Lock", KEY_EMERGENCY_SHIELD, "Toggle emergency shield power.\n"), XP_KEY_OPTION( "keyTractorBeam", "comma", KEY_TRACTOR_BEAM, "Use tractor beam in attract mode.\n"), XP_KEY_OPTION( "keyPressorBeam", "period", KEY_PRESSOR_BEAM, "Use tractor beam in repulse mode.\n"), XP_KEY_OPTION( "keyClearModifiers", "k", KEY_CLEAR_MODIFIERS, "Clear current weapon modifiers.\n"), XP_KEY_OPTION( "keyLoadModifiers1", "1", KEY_LOAD_MODIFIERS_1, "Load the weapon modifiers from bank 1.\n"), XP_KEY_OPTION( "keyLoadModifiers2", "2", KEY_LOAD_MODIFIERS_2, "Load the weapon modifiers from bank 2.\n"), XP_KEY_OPTION( "keyLoadModifiers3", "3", KEY_LOAD_MODIFIERS_3, "Load the weapon modifiers from bank 3.\n"), XP_KEY_OPTION( "keyLoadModifiers4", "4", KEY_LOAD_MODIFIERS_4, "Load the weapon modifiers from bank 4.\n"), XP_KEY_OPTION( "keyToggleOwnedItems", "KP_8", KEY_TOGGLE_OWNED_ITEMS, "Toggle list of owned items on HUD.\n"), XP_KEY_OPTION( "keyToggleMessages", "KP_9", KEY_TOGGLE_MESSAGES, "Toggle showing of messages.\n"), XP_KEY_OPTION( "keyReprogram", "quoteleft", KEY_REPROGRAM, "Reprogram modifier or lock bank.\n"), XP_KEY_OPTION( "keyLoadLock1", "5", KEY_LOAD_LOCK_1, "Load player lock from bank 1.\n"), XP_KEY_OPTION( "keyLoadLock2", "6", KEY_LOAD_LOCK_2, "Load player lock from bank 2.\n"), XP_KEY_OPTION( "keyLoadLock3", "7", KEY_LOAD_LOCK_3, "Load player lock from bank 3.\n"), XP_KEY_OPTION( "keyLoadLock4", "8", KEY_LOAD_LOCK_4, "Load player lock from bank 4.\n"), XP_KEY_OPTION( "keyToggleRecord", "KP_5", KEY_TOGGLE_RECORD, "Toggle recording of session (see recordFile).\n"), #ifdef SOUND XP_KEY_OPTION( "keyToggleSound", "", KEY_TOGGLE_SOUND, "Toggle sound. Changes value of option 'sound'.\n"), #endif XP_KEY_OPTION( "keyToggleRadarScore", "F11", KEY_TOGGLE_RADAR_SCORE, "Toggles the radar and score windows on and off.\n"), XP_KEY_OPTION( "keyToggleFullScreen", "F11", KEY_TOGGLE_FULLSCREEN, "Toggles between fullscreen mode and window mode.\n"), XP_KEY_OPTION( "keySelectItem", "KP_0 KP_Insert", KEY_SELECT_ITEM, "Select an item to lose.\n"), XP_KEY_OPTION( "keyLoseItem", "KP_Delete KP_Decimal", KEY_LOSE_ITEM, "Lose the selected item.\n"), XP_KEY_OPTION( "keyPrintMessagesStdout", "Print", KEY_PRINT_MSGS_STDOUT, "Print the current messages to stdout.\n"), XP_KEY_OPTION( "keyTalkCursorLeft", "Left", KEY_TALK_CURSOR_LEFT, "Move Cursor to the left in the talk window.\n"), XP_KEY_OPTION( "keyTalkCursorRight", "Right", KEY_TALK_CURSOR_RIGHT, "Move Cursor to the right in the talk window.\n"), XP_KEY_OPTION( "keyTalkCursorUp", "Up", KEY_TALK_CURSOR_UP, "Browsing in the history of the talk window.\n"), XP_KEY_OPTION( "keyTalkCursorDown", "Down", KEY_TALK_CURSOR_DOWN, "Browsing in the history of the talk window.\n"), XP_KEY_OPTION( "keyPointerControl", "KP_Enter", KEY_POINTER_CONTROL, "Toggle pointer control.\n"), XP_KEY_OPTION( "keyExit", "Escape", KEY_EXIT, "Generic exit key.\n" "Used for example to exit mouse mode or quit the client.\n"), XP_KEY_OPTION( "keyYes", "y", KEY_YES, "Positive reply key.\n" "Used to reply 'yes' to client questions.\n"), XP_KEY_OPTION( "keyNo", "n", KEY_NO, "Negative reply key.\n" "Used to reply 'no' to client questions.\n"), XP_KEY_OPTION( "keySendMsg1", "F1", KEY_MSG_1, "Sends the talkmessage stored in msg1.\n"), XP_KEY_OPTION( "keySendMsg2", "F2", KEY_MSG_2, "Sends the talkmessage stored in msg2.\n"), XP_KEY_OPTION( "keySendMsg3", "F3", KEY_MSG_3, "Sends the talkmessage stored in msg3.\n"), XP_KEY_OPTION( "keySendMsg4", "F4", KEY_MSG_4, "Sends the talkmessage stored in msg4.\n"), XP_KEY_OPTION( "keySendMsg5", "F5", KEY_MSG_5, "Sends the talkmessage stored in msg5.\n"), XP_KEY_OPTION( "keySendMsg6", "F6", KEY_MSG_6, "Sends the talkmessage stored in msg6.\n"), XP_KEY_OPTION( "keySendMsg7", "F7", KEY_MSG_7, "Sends the talkmessage stored in msg7.\n"), XP_KEY_OPTION( "keySendMsg8", "F8", KEY_MSG_8, "Sends the talkmessage stored in msg8.\n"), XP_KEY_OPTION( "keySendMsg9", "F9", KEY_MSG_9, "Sends the talkmessage stored in msg9.\n"), XP_KEY_OPTION( "keySendMsg10", "F10", KEY_MSG_10, "Sends the talkmessage stored in msg10.\n"), XP_KEY_OPTION( "keySendMsg11", "", /* F11 is keyToggleFullScreen now */ KEY_MSG_11, "Sends the talkmessage stored in msg11.\n"), XP_KEY_OPTION( "keySendMsg12", "", KEY_MSG_12, "Sends the talkmessage stored in msg12.\n"), XP_KEY_OPTION( "keySendMsg13", "", KEY_MSG_13, "Sends the talkmessage stored in msg13.\n"), XP_KEY_OPTION( "keySendMsg14", "", KEY_MSG_14, "Sends the talkmessage stored in msg14.\n"), XP_KEY_OPTION( "keySendMsg15", "", KEY_MSG_15, "Sends the talkmessage stored in msg15.\n"), XP_KEY_OPTION( "keySendMsg16", "", KEY_MSG_16, "Sends the talkmessage stored in msg16.\n"), XP_KEY_OPTION( "keySendMsg17", "", KEY_MSG_17, "Sends the talkmessage stored in msg17.\n"), XP_KEY_OPTION( "keySendMsg18", "", KEY_MSG_18, "Sends the talkmessage stored in msg18.\n"), XP_KEY_OPTION( "keySendMsg19", "", KEY_MSG_19, "Sends the talkmessage stored in msg19.\n"), XP_KEY_OPTION( "keySendMsg20", "", KEY_MSG_20, "Sends the talkmessage stored in msg20.\n"), /* * These are after the keys so that the key options will be * present when the pointer button options are stored. */ XP_STRING_OPTION( "pointerButton1", "keyFireShot", NULL, 0, setPointerButtonBinding, NULL, getPointerButtonBinding, XP_OPTFLAG_DEFAULT, "The keys to activate when pressing the first mouse button.\n"), XP_STRING_OPTION( "pointerButton2", "keyThrust", NULL, 0, setPointerButtonBinding, NULL, getPointerButtonBinding, XP_OPTFLAG_DEFAULT, "The keys to activate when pressing the second mouse button.\n"), XP_STRING_OPTION( "pointerButton3", "keyThrust", NULL, 0, setPointerButtonBinding, NULL, getPointerButtonBinding, XP_OPTFLAG_DEFAULT, "The keys to activate when pressing the third mouse button.\n"), XP_STRING_OPTION( "pointerButton4", "", NULL, 0, setPointerButtonBinding, NULL, getPointerButtonBinding, XP_OPTFLAG_DEFAULT, "The keys to activate when pressing the fourth mouse button.\n"), XP_STRING_OPTION( "pointerButton5", "", NULL, 0, setPointerButtonBinding, NULL, getPointerButtonBinding, XP_OPTFLAG_DEFAULT, "The keys to activate when pressing the fifth mouse button.\n"), }; void Store_key_options(void) { STORE_OPTIONS(key_options); }