/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts 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 3 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, see . */ /*********************************************************************************************** *** Confidential - Westwood Studios *** *********************************************************************************************** * * * Project Name : Commando * * * * $Archive:: /Commando/Code/Combat/input.cpp $* * * * $Author:: Byon_g $* * * * $Modtime:: 3/15/02 3:22p $* * * * $Revision:: 120 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "input.h" #include "slist.h" #include "assets.h" #include "ini.h" #include "directinput.h" #include "debug.h" #include "timemgr.h" #include "registry.h" #include "ffactory.h" #include "win.h" #include "translatedb.h" #include "string_ids.h" #include "vehicle.h" #include "combat.h" #include "ccamera.h" #define DIRECTINPUT_VERSION 0x0800 #include #include //////////////////////////////////////////////////////////////// // Special virtual keys //////////////////////////////////////////////////////////////// #define VK_MOUSEWHEEL_UP 0x100 #define VK_MOUSEWHEEL_DOWN 0x101 /* ** */ float MouseSensitivity = 0.5f; float MouseScale = 1; bool MouseInvert = true; bool Mouse2DInvert = false; const char *DEFAULT_INPUT_FILENAME = "DEFAULT_INPUT.CFG"; #define BUTTON_BIT_HELD DirectInput::DI_BUTTON_HELD #define BUTTON_BIT_HIT DirectInput::DI_BUTTON_HIT #define BUTTON_BIT_RELEASED DirectInput::DI_BUTTON_RELEASED #define BUTTON_BIT_DOUBLE 8 #define SLIDER_DEAD_ZONE 0.01f /* ** Button states */ #define BUTTON_UP 0x0000 #define BUTTON_HIT 0x0001 #define BUTTON_RELEASE 0x0002 #define BUTTON_HELD 0x0003 #define BUTTON_DOUBLE 0x0004 #define BUTTON_SHIFT 0x1000 #define BUTTON_CTRL 0x2000 #define BUTTON_ALT 0x4000 #define BUTTON_DEBUG 0x8000 /* ** Database Strings */ #define ENTRY_ACTIVATE_BUTTON "ActivateButton" #define ENTRY_FUNCTION "Function" #define ENTRY_MIN "Min" #define ENTRY_MAX "Max" #define ENTRY_ACCELERATION "Acceleration" #define SECTION_MISC_SETTINGS "Misc Settings" #define ENTRY_DAMAGE_INDICATORS "DamageIndicatorsEnabled" #define ENTRY_MOUSE_SENSITIVITY "MouseSensitivity" #define ENTRY_MOUSE_SCALE "MouseScale" #define ENTRY_MOUSE_INVERT "MouseInvert" #define ENTRY_MOUSE_2D_INVERT "Mouse2DInvert" #define ENTRY_TARGET_STEERING "TargetSteering" typedef struct { short ID; char *Name; } StringID; StringID ButtonNames[] = { { DIK_F1, "F1_Key" }, { DIK_F2, "F2_Key" }, { DIK_F3, "F3_Key" }, { DIK_F4, "F4_Key" }, { DIK_F5, "F5_Key" }, { DIK_F6, "F6_Key" }, { DIK_F7, "F7_Key" }, { DIK_F8, "F8_Key" }, { DIK_F9, "F9_Key" }, { DIK_F10, "F10_Key" }, { DIK_F11, "F11_Key" }, { DIK_F12, "F12_Key" }, { DIK_0, "0_Key" }, { DIK_1, "1_Key" }, { DIK_2, "2_Key" }, { DIK_3, "3_Key" }, { DIK_4, "4_Key" }, { DIK_5, "5_Key" }, { DIK_6, "6_Key" }, { DIK_7, "7_Key" }, { DIK_8, "8_Key" }, { DIK_9, "9_Key" }, { DIK_A, "A_Key" }, { DIK_B, "B_Key" }, { DIK_C, "C_Key" }, { DIK_D, "D_Key" }, { DIK_E, "E_Key" }, { DIK_F, "F_Key" }, { DIK_G, "G_Key" }, { DIK_H, "H_Key" }, { DIK_I, "I_Key" }, { DIK_J, "J_Key" }, { DIK_K, "K_Key" }, { DIK_L, "L_Key" }, { DIK_M, "M_Key" }, { DIK_N, "N_Key" }, { DIK_O, "O_Key" }, { DIK_P, "P_Key" }, { DIK_Q, "Q_Key" }, { DIK_R, "R_Key" }, { DIK_S, "S_Key" }, { DIK_T, "T_Key" }, { DIK_U, "U_Key" }, { DIK_V, "V_Key" }, { DIK_W, "W_Key" }, { DIK_X, "X_Key" }, { DIK_Y, "Y_Key" }, { DIK_Z, "Z_Key" }, { DIK_MINUS, "Minus_Key" }, { DIK_EQUALS, "Equals_Key" }, { DIK_BACK, "Backspace_Key" }, { DIK_TAB, "Tab_Key" }, { DIK_LBRACKET, "Left_Bracket_Key" }, { DIK_RBRACKET, "Right_Bracket_Key" }, { DIK_RETURN, "Enter_Key" }, { DIK_SEMICOLON, "Semicolon_Key" }, { DIK_APOSTROPHE, "Apostrophe_Key" }, { DIK_GRAVE, "Grave_Key" }, { DIK_BACKSLASH, "Backslash_Key" }, { DIK_COMMA, "Comma_Key" }, { DIK_PERIOD, "Period_Key" }, { DIK_SLASH, "Slash_Key" }, { DIK_SPACE, "Space_Bar_Key" }, { DIK_CAPITAL, "Caps_Lock_Key" }, { DIK_NUMLOCK, "Num_Lock_Key" }, { DIK_SCROLL, "Scroll_Lock_Key" }, { DIK_ESCAPE, "Escape_Key" }, { DIK_NUMPAD0, "Keypad_0_Key" }, { DIK_NUMPAD1, "Keypad_1_Key" }, { DIK_NUMPAD2, "Keypad_2_Key" }, { DIK_NUMPAD3, "Keypad_3_Key" }, { DIK_NUMPAD4, "Keypad_4_Key" }, { DIK_NUMPAD5, "Keypad_5_Key" }, { DIK_NUMPAD6, "Keypad_6_Key" }, { DIK_NUMPAD7, "Keypad_7_Key" }, { DIK_NUMPAD8, "Keypad_8_Key" }, { DIK_NUMPAD9, "Keypad_9_Key" }, { DIK_SUBTRACT, "Keypad_Minus_Key" }, { DIK_MULTIPLY, "Keypad_Star_Key" }, { DIK_ADD, "Keypad_Plus_Key" }, { DIK_DECIMAL, "Keypad_Period_Key" }, { DIK_NUMPADENTER, "Keypad_Enter_Key" }, { DIK_DIVIDE, "Keypad_Slash_Key" }, { DIK_HOME, "Home_Key" }, { DIK_PRIOR, "Page_Up_Key" }, { DIK_END, "End_Key" }, { DIK_NEXT, "Page_Down_Key" }, { DIK_INSERT, "Insert_Key" }, { DIK_DELETE, "Delete_Key" }, { DIK_UP, "Up_Key" }, { DIK_DOWN, "Down_Key" }, { DIK_LEFT, "Left_Key" }, { DIK_RIGHT, "Right_Key" }, { DIK_SYSRQ, "Sys_Req_Key" }, { DIK_CONTROL, "Control_Key" }, { DIK_LCONTROL, "Left_Control_Key" }, { DIK_RCONTROL, "Right_Control_Key" }, { DIK_SHIFT, "Shift_Key" }, { DIK_LSHIFT, "Left_Shift_Key" }, { DIK_RSHIFT, "Right_Shift_Key" }, { DIK_ALT, "Alt_Key" }, { DIK_LALT, "Left_Alt_Key" }, { DIK_RALT, "Right_Alt_Key" }, { DIK_WIN, "Windows_Key" }, { DIK_LWIN, "Left_Windows_Key" }, { DIK_RWIN, "Right_Windows_Key" }, { DIK_APPS, "App_Menu_Key" }, { DirectInput::BUTTON_MOUSE_LEFT, "Left_Mouse_Button" }, { DirectInput::BUTTON_MOUSE_RIGHT, "Right_Mouse_Button" }, { DirectInput::BUTTON_MOUSE_CENTER, "Center_Mouse_Button" }, { DirectInput::BUTTON_JOYSTICK_A, "Joystick_Button_A" }, { DirectInput::BUTTON_JOYSTICK_B, "Joystick_Button_B" }, }; #define NUM_BUTTON_NAMES ( sizeof(ButtonNames) / sizeof(ButtonNames[0]) ) StringID SliderNames[] = { { Input::SLIDER_MOUSE_LEFT, "Mouse_Left" }, { Input::SLIDER_MOUSE_RIGHT, "Mouse_Right" }, { Input::SLIDER_MOUSE_UP, "Mouse_Up" }, { Input::SLIDER_MOUSE_DOWN, "Mouse_Down" }, { Input::SLIDER_MOUSE_WHEEL_FORWARD, "Mouse_Wheel_Forward" }, { Input::SLIDER_MOUSE_WHEEL_BACKWARD, "Mouse_Wheel_Backward" }, { Input::SLIDER_JOYSTICK_LEFT, "Joystick_Left" }, { Input::SLIDER_JOYSTICK_RIGHT, "Joystick_Right" }, { Input::SLIDER_JOYSTICK_UP, "Joystick_Up" }, { Input::SLIDER_JOYSTICK_DOWN, "Joystick_Down" }, }; #define NUM_SLIDER_NAMES ( sizeof( SliderNames ) / sizeof( SliderNames[0] ) ) #define NUM_FUNCTIONS INPUT_FUNCTION_COUNT StringID Functions[ NUM_FUNCTIONS ] = { { INPUT_FUNCTION_MOVE_FORWARD, "MoveForward" }, { INPUT_FUNCTION_MOVE_BACKWARD, "MoveBackward" }, { INPUT_FUNCTION_MOVE_LEFT, "MoveLeft" }, { INPUT_FUNCTION_MOVE_RIGHT, "MoveRight" }, { INPUT_FUNCTION_MOVE_UP, "MoveUp" }, { INPUT_FUNCTION_MOVE_DOWN, "MoveDown" }, { INPUT_FUNCTION_WALK_MODE, "WalkMode" }, { INPUT_FUNCTION_TURN_LEFT, "TurnLeft" }, { INPUT_FUNCTION_TURN_RIGHT, "TurnRight" }, { INPUT_FUNCTION_VEHICLE_TURN_LEFT, "VehicleTurnLeft" }, { INPUT_FUNCTION_VEHICLE_TURN_RIGHT, "VehicleTurnRight" }, { INPUT_FUNCTION_VEHICLE_TOGGLE_GUNNER, "VehicleToggleGunner"}, { INPUT_FUNCTION_WEAPON_UP, "WeaponUp" }, { INPUT_FUNCTION_WEAPON_DOWN, "WeaponDown" }, { INPUT_FUNCTION_WEAPON_LEFT, "WeaponLeft" }, { INPUT_FUNCTION_WEAPON_RIGHT, "WeaponRight" }, { INPUT_FUNCTION_WEAPON_RESET, "WeaponReset" }, { INPUT_FUNCTION_ZOOM_IN, "ZoomIn" }, { INPUT_FUNCTION_ZOOM_OUT, "ZoomOut" }, { INPUT_FUNCTION_ACTION, "Action" }, // Was Ladder { INPUT_FUNCTION_JUMP, "Jump" }, { INPUT_FUNCTION_CROUCH, "Crouch" }, { INPUT_FUNCTION_DIVE_FORWARD, "DiveForward" }, { INPUT_FUNCTION_DIVE_BACKWARD, "DiveBackward" }, { INPUT_FUNCTION_DIVE_LEFT, "DiveLeft" }, { INPUT_FUNCTION_DIVE_RIGHT, "DiveRight" }, { INPUT_FUNCTION_TURN_AROUND, "TurnAround" }, { INPUT_FUNCTION_DROP_FLAG, "DropFlag" }, { INPUT_FUNCTION_NEXT_WEAPON, "NextWeapon" }, { INPUT_FUNCTION_PREV_WEAPON, "PrevWeapon" }, { INPUT_FUNCTION_FIRE_WEAPON_PRIMARY, "FireWeaponPrimary" }, { INPUT_FUNCTION_FIRE_WEAPON_SECONDARY, "FireWeaponSecondary"}, { INPUT_FUNCTION_USE_WEAPON, "UseWeapon" }, { INPUT_FUNCTION_RELOAD_WEAPON, "ReloadWeapon" }, { INPUT_FUNCTION_SELECT_NO_WEAPON, "SelectNoWeapon" }, { INPUT_FUNCTION_SELECT_WEAPON_0, "SelectWeapon0" }, { INPUT_FUNCTION_SELECT_WEAPON_1, "SelectWeapon1" }, { INPUT_FUNCTION_SELECT_WEAPON_2, "SelectWeapon2" }, { INPUT_FUNCTION_SELECT_WEAPON_3, "SelectWeapon3" }, { INPUT_FUNCTION_SELECT_WEAPON_4, "SelectWeapon4" }, { INPUT_FUNCTION_SELECT_WEAPON_5, "SelectWeapon5" }, { INPUT_FUNCTION_SELECT_WEAPON_6, "SelectWeapon6" }, { INPUT_FUNCTION_SELECT_WEAPON_7, "SelectWeapon7" }, { INPUT_FUNCTION_SELECT_WEAPON_8, "SelectWeapon8" }, { INPUT_FUNCTION_SELECT_WEAPON_9, "SelectWeapon9" }, { INPUT_FUNCTION_CYCLE_POG, "CyclePog" }, // { INPUT_FUNCTION_HUD_ZOOM_RADAR_IN, "HudZoomRadarIn" }, // { INPUT_FUNCTION_HUD_ZOOM_RADAR_OUT, "HudZoomRadarOut" }, { INPUT_FUNCTION_PANIC, "Panic" }, { INPUT_FUNCTION_CURSOR_TARGETING, "CursorTargeting" }, { INPUT_FUNCTION_FIRST_PERSON_TOGGLE, "FirstPersonToggle" }, { INPUT_FUNCTION_SUICIDE, "Suicide" }, { INPUT_FUNCTION_VERBOSE_HELP, "VerboseHelp" }, { INPUT_FUNCTION_BEGIN_PUBLIC_MESSAGE, "BeginPublicMessage" }, { INPUT_FUNCTION_BEGIN_TEAM_MESSAGE, "BeginTeamMessage" }, { INPUT_FUNCTION_BEGIN_PRIVATE_MESSAGE, "BeginPrivateMessage"}, { INPUT_FUNCTION_BEGIN_CONSOLE, "BeginConsole" }, { INPUT_FUNCTION_HELP_SCREEN, "HelpScreen" }, { INPUT_FUNCTION_EVA_OBJECTIVES_SCREEN, "ObjectivesScreen" }, { INPUT_FUNCTION_EVA_MAP_SCREEN, "MapScreen" }, // DEBUGGING { INPUT_FUNCTION_CAMERA_HEADING_LEFT, "CameraHeadingLeft" }, { INPUT_FUNCTION_CAMERA_HEADING_RIGHT, "CameraHeadingRight" }, { INPUT_FUNCTION_CAMERA_TRANSTILT_INC, "CameraTransTiltInc" }, { INPUT_FUNCTION_CAMERA_TRANSTILT_DEC, "CameraTransTiltDec" }, { INPUT_FUNCTION_CAMERA_VIEWTILT_INC, "CameraViewTiltInc" }, { INPUT_FUNCTION_CAMERA_VIEWTILT_DEC, "CameraViewTiltDec" }, { INPUT_FUNCTION_CAMERA_DIST_INC, "CameraDistInc" }, { INPUT_FUNCTION_CAMERA_DIST_DEC, "CameraDistDec" }, { INPUT_FUNCTION_CAMERA_FOV_INC, "CameraFOVInc" }, { INPUT_FUNCTION_CAMERA_FOV_DEC, "CameraFOVDec" }, { INPUT_FUNCTION_CAMERA_HEIGHT_INC, "CameraHeightInc" }, { INPUT_FUNCTION_CAMERA_HEIGHT_DEC, "CameraHeightDec" }, { INPUT_FUNCTION_MENU_SERVERQUICKSTART, "ServerQuickStart" }, { INPUT_FUNCTION_MENU_CLIENTQUICKSTART, "ClientQuickStart" }, { INPUT_FUNCTION_MAKE_SCREEN_SHOT, "MakeScreenShot" }, { INPUT_FUNCTION_TOGGLE_MOVIE_CAPTURE, "ToggleMovieCapture" }, //{ INPUT_FUNCTION_INCREMENT_ACTIVE_MESSAGE, "IncrementActiveMessage" }, //{ INPUT_FUNCTION_DECREMENT_ACTIVE_MESSAGE, "DecrementActiveMessage" }, //{ INPUT_FUNCTION_INCREMENT_DEBUG_SWITCH_1, "IncrementDebugSwitch1" }, //{ INPUT_FUNCTION_INCREMENT_DEBUG_SWITCH_2, "IncrementDebugSwitch2" }, { INPUT_FUNCTION_DEBUG_SINGLE_STEP, "DebugSingleStep" }, { INPUT_FUNCTION_DEBUG_SINGLE_STEP_STEP, "DebugSingleStepStep"}, { INPUT_FUNCTION_DEBUG_RAPID_MOVE, "DebugRapidMove" }, { INPUT_FUNCTION_DEBUG_GENERIC0, "GenericDebug0" }, { INPUT_FUNCTION_DEBUG_GENERIC1, "GenericDebug1" }, { INPUT_FUNCTION_DEBUG_FAR_CLIP_IN, "DebugFarClipIn" }, { INPUT_FUNCTION_DEBUG_FAR_CLIP_OUT, "DebugFarClipOut" }, { INPUT_FUNCTION_QUICK_FULL_EXIT, "QuickFullExit" }, { INPUT_FUNCTION_VIS_UPDATE, "VisUpdate" }, // { INPUT_FUNCTION_TOGGLE_PERFORMANCE_SAMPLING, "TogglePerformanceSampling" }, { INPUT_FUNCTION_TOGGLE_SNAP_SHOT_MODE, "ToggleSnapShotMode" }, { INPUT_FUNCTION_SNAP_SHOT_ADVANCE, "SnapShotAdvance" }, //{ INPUT_FUNCTION_DEBUG_OPTIONS_DIALOG, "DebugOptionsDialog" }, { INPUT_FUNCTION_CNC, "CNC" }, { INPUT_FUNCTION_QUICKSAVE, "Quicksave" }, // Menu { INPUT_FUNCTION_MENU_TOGGLE, "MenuToggle" }, // In game EVA { INPUT_FUNCTION_EVA_MISSION_OBJECTIVES_TOGGLE, "EvaMissionObjectives" }, { INPUT_FUNCTION_RADIO_CMD_01, "RadioCommand01"}, { INPUT_FUNCTION_RADIO_CMD_02, "RadioCommand02"}, { INPUT_FUNCTION_RADIO_CMD_03, "RadioCommand03"}, { INPUT_FUNCTION_RADIO_CMD_04, "RadioCommand04"}, { INPUT_FUNCTION_RADIO_CMD_05, "RadioCommand05"}, { INPUT_FUNCTION_RADIO_CMD_06, "RadioCommand06"}, { INPUT_FUNCTION_RADIO_CMD_07, "RadioCommand07"}, { INPUT_FUNCTION_RADIO_CMD_08, "RadioCommand08"}, { INPUT_FUNCTION_RADIO_CMD_09, "RadioCommand09"}, { INPUT_FUNCTION_RADIO_CMD_10, "RadioCommand10"}, { INPUT_FUNCTION_RADIO_CMD_11, "RadioCommand11"}, { INPUT_FUNCTION_RADIO_CMD_12, "RadioCommand12"}, { INPUT_FUNCTION_RADIO_CMD_13, "RadioCommand13"}, { INPUT_FUNCTION_RADIO_CMD_14, "RadioCommand14"}, { INPUT_FUNCTION_RADIO_CMD_15, "RadioCommand15"}, { INPUT_FUNCTION_RADIO_CMD_16, "RadioCommand16"}, { INPUT_FUNCTION_RADIO_CMD_17, "RadioCommand17"}, { INPUT_FUNCTION_RADIO_CMD_18, "RadioCommand18"}, { INPUT_FUNCTION_RADIO_CMD_19, "RadioCommand19"}, { INPUT_FUNCTION_RADIO_CMD_20, "RadioCommand20"}, { INPUT_FUNCTION_RADIO_CMD_21, "RadioCommand21"}, { INPUT_FUNCTION_RADIO_CMD_22, "RadioCommand22"}, { INPUT_FUNCTION_RADIO_CMD_23, "RadioCommand23"}, { INPUT_FUNCTION_RADIO_CMD_24, "RadioCommand24"}, { INPUT_FUNCTION_RADIO_CMD_25, "RadioCommand25"}, { INPUT_FUNCTION_RADIO_CMD_26, "RadioCommand26"}, { INPUT_FUNCTION_RADIO_CMD_27, "RadioCommand27"}, { INPUT_FUNCTION_RADIO_CMD_28, "RadioCommand28"}, { INPUT_FUNCTION_RADIO_CMD_29, "RadioCommand29"}, { INPUT_FUNCTION_RADIO_CMD_30, "RadioCommand30"}, { INPUT_FUNCTION_TEAM_INFO_TOGGLE, "TeamInfoToggle" }, { INPUT_FUNCTION_BATTLE_INFO_TOGGLE, "BattleInfoToggle" }, { INPUT_FUNCTION_SERVER_INFO_TOGGLE, "ServerInfoToggle" }, // Profiler Controls { INPUT_FUNCTION_PROFILE_ENTER_CHILD0, "ProfileEnterChild0" }, { INPUT_FUNCTION_PROFILE_ENTER_CHILD1, "ProfileEnterChild1" }, { INPUT_FUNCTION_PROFILE_ENTER_CHILD2, "ProfileEnterChild2" }, { INPUT_FUNCTION_PROFILE_ENTER_CHILD3, "ProfileEnterChild3" }, { INPUT_FUNCTION_PROFILE_ENTER_CHILD4, "ProfileEnterChild4" }, { INPUT_FUNCTION_PROFILE_ENTER_CHILD5, "ProfileEnterChild5" }, { INPUT_FUNCTION_PROFILE_ENTER_CHILD6, "ProfileEnterChild6" }, { INPUT_FUNCTION_PROFILE_ENTER_CHILD7, "ProfileEnterChild7" }, { INPUT_FUNCTION_PROFILE_ENTER_CHILD8, "ProfileEnterChild8" }, { INPUT_FUNCTION_PROFILE_ENTER_CHILD9, "ProfileEnterChild9" }, { INPUT_FUNCTION_PROFILE_ENTER_PARENT, "ProfileEnterParent" }, { INPUT_FUNCTION_PROFILE_RESET, "ProfileReset" }, }; /* ** FunctionKeyStates */ int FunctionKeyStates[ NUM_FUNCTIONS ] = { BUTTON_HELD, //INPUT_FUNCTION_MOVE_FORWARD, BUTTON_HELD, //INPUT_FUNCTION_MOVE_BACKWARD, BUTTON_HELD, //INPUT_FUNCTION_MOVE_LEFT, BUTTON_HELD, //INPUT_FUNCTION_MOVE_RIGHT, BUTTON_HELD, //INPUT_FUNCTION_MOVE_UP, BUTTON_HELD, //INPUT_FUNCTION_MOVE_DOWN, BUTTON_HELD, //INPUT_FUNCTION_WALK_MODE, BUTTON_HELD, //INPUT_FUNCTION_TURN_LEFT, BUTTON_HELD, //INPUT_FUNCTION_TURN_RIGHT, BUTTON_HELD, //INPUT_FUNCTION_VEHICLE_TURN_LEFT, BUTTON_HELD, //INPUT_FUNCTION_VEHICLE_TURN_RIGHT, BUTTON_HIT, //INPUT_FUNCTION_VEHICLE_TOGGLE_GUNNER, BUTTON_HELD, //INPUT_FUNCTION_WEAPON_UP, BUTTON_HELD, //INPUT_FUNCTION_WEAPON_DOWN, BUTTON_HELD, //INPUT_FUNCTION_WEAPON_LEFT, BUTTON_HELD, //INPUT_FUNCTION_WEAPON_RIGHT, BUTTON_HELD, //INPUT_FUNCTION_WEAPON_RESET, BUTTON_HELD, //INPUT_FUNCTION_ZOOM_IN, BUTTON_HELD, //INPUT_FUNCTION_ZOOM_OUT, BUTTON_HIT, //INPUT_FUNCTION_ACTION, BUTTON_HIT, //INPUT_FUNCTION_JUMP, // BUTTON_HIT, //INPUT_FUNCTION_CROUCH, BUTTON_HELD, //INPUT_FUNCTION_CROUCH, BUTTON_DOUBLE, //INPUT_FUNCTION_DIVE_FORWARD, BUTTON_DOUBLE, //INPUT_FUNCTION_DIVE_BACKWARD, BUTTON_DOUBLE, //INPUT_FUNCTION_DIVE_LEFT, BUTTON_DOUBLE, //INPUT_FUNCTION_DIVE_RIGHT, BUTTON_HIT, //INPUT_FUNCTION_TURN_AROUND, BUTTON_HIT, //INPUT_FUNCTION_DROP_FLAG, BUTTON_HIT, //INPUT_FUNCTION_NEXT_WEAPON, BUTTON_HIT, //INPUT_FUNCTION_PREV_WEAPON, BUTTON_HELD, //INPUT_FUNCTION_FIRE_WEAPON_PRIMARY, BUTTON_HELD, //INPUT_FUNCTION_FIRE_WEAPON_SECONDARY, BUTTON_HIT, //INPUT_FUNCTION_USE_WEAPON, BUTTON_HIT, //INPUT_FUNCTION_RELOAD_WEAPON, BUTTON_HIT, //INPUT_FUNCTION_SELECT_NO_WEAPON, BUTTON_HIT, //INPUT_FUNCTION_SELECT_WEAPON_0, BUTTON_HIT, //INPUT_FUNCTION_SELECT_WEAPON_1, BUTTON_HIT, //INPUT_FUNCTION_SELECT_WEAPON_2, BUTTON_HIT, //INPUT_FUNCTION_SELECT_WEAPON_3, BUTTON_HIT, //INPUT_FUNCTION_SELECT_WEAPON_4, BUTTON_HIT, //INPUT_FUNCTION_SELECT_WEAPON_5, BUTTON_HIT, //INPUT_FUNCTION_SELECT_WEAPON_6, BUTTON_HIT, //INPUT_FUNCTION_SELECT_WEAPON_7, BUTTON_HIT, //INPUT_FUNCTION_SELECT_WEAPON_8, BUTTON_HIT, //INPUT_FUNCTION_SELECT_WEAPON_9, BUTTON_HIT, //INPUT_FUNCTION_CYCLE_POG // BUTTON_HIT, //INPUT_FUNCTION_HUD_ZOOM_RADAR_IN, // BUTTON_HIT, //INPUT_FUNCTION_HUD_ZOOM_RADAR_OUT, BUTTON_HIT, //INPUT_FUNCTION_PANIC, BUTTON_HELD, //INPUT_FUNCTION_CURSOR_TARGETING, BUTTON_HIT, //INPUT_FUNCTION_FIRST_PERSON_TOGGLE, BUTTON_HIT, //INPUT_FUNCTION_SUICIDE, BUTTON_HIT, //INPUT_FUNCTION_VERBOSE_HELP, BUTTON_HIT, //INPUT_FUNCTION_BEGIN_PUBLIC_MESSAGE, BUTTON_HIT, //INPUT_FUNCTION_BEGIN_TEAM_MESSAGE, BUTTON_HIT, //INPUT_FUNCTION_BEGIN_PRIVATE_MESSAGE, BUTTON_HIT, //INPUT_FUNCTION_BEGIN_CONSOLE, BUTTON_HIT, //INPUT_FUNCTION_HELP_SCREEN, BUTTON_HIT, //INPUT_FUNCTION_EVA_OBJECTIVES_SCREEN BUTTON_HIT, //INPUT_FUNCTION_EVA_MAP_SCREEN // DEBUGGING BUTTON_HELD | BUTTON_DEBUG, //INPUT_FUNCTION_CAMERA_HEADING_LEFT, BUTTON_HELD | BUTTON_DEBUG, //INPUT_FUNCTION_CAMERA_HEADING_RIGHT, BUTTON_HELD | BUTTON_DEBUG, //INPUT_FUNCTION_CAMERA_TRANSTILT_INC, BUTTON_HELD | BUTTON_DEBUG, //INPUT_FUNCTION_CAMERA_TRANSTILT_DEC, BUTTON_HELD | BUTTON_DEBUG, //INPUT_FUNCTION_CAMERA_VIEWTILT_INC, BUTTON_HELD | BUTTON_DEBUG, //INPUT_FUNCTION_CAMERA_VIEWTILT_DEC, BUTTON_HELD | BUTTON_DEBUG, //INPUT_FUNCTION_CAMERA_DIST_INC, BUTTON_HELD | BUTTON_DEBUG, //INPUT_FUNCTION_CAMERA_DIST_DEC, BUTTON_HELD | BUTTON_DEBUG, //INPUT_FUNCTION_CAMERA_FOV_INC, BUTTON_HELD | BUTTON_DEBUG, //INPUT_FUNCTION_CAMERA_FOV_DEC, BUTTON_HELD | BUTTON_DEBUG, //INPUT_FUNCTION_CAMERA_HEIGHT_INC, BUTTON_HELD | BUTTON_DEBUG, //INPUT_FUNCTION_CAMERA_HEIGHT_DEC, BUTTON_HIT | BUTTON_DEBUG, //INPUT_FUNCTION_MENU_SERVERQUICKSTART, BUTTON_HIT | BUTTON_DEBUG, //INPUT_FUNCTION_MENU_CLIENTQUICKSTART, BUTTON_HIT, //INPUT_FUNCTION_MAKE_SCREEN_SHOT, BUTTON_HIT | BUTTON_DEBUG, //INPUT_FUNCTION_TOGGLE_MOVIE_CAPTURE, BUTTON_HIT | BUTTON_DEBUG, //INPUT_FUNCTION_DEBUG_SINGLE_STEP, BUTTON_HIT | BUTTON_DEBUG, //INPUT_FUNCTION_DEBUG_SINGLE_STEP_STEP, BUTTON_HELD, //INPUT_FUNCTION_DEBUG_RAPID_MOVE, BUTTON_HIT | BUTTON_DEBUG, //INPUT_FUNCTION_DEBUG_GENERIC0, BUTTON_HIT | BUTTON_DEBUG, //INPUT_FUNCTION_DEBUG_GENERIC1, BUTTON_HELD | BUTTON_DEBUG, //INPUT_FUNCTION_DEBUG_FAR_CLIP_IN, BUTTON_HELD | BUTTON_DEBUG, //INPUT_FUNCTION_DEBUG_FAR_CLIP_OUT, BUTTON_HIT | BUTTON_DEBUG, //INPUT_FUNCTION_QUICK_FULL_EXIT, BUTTON_HIT | BUTTON_DEBUG, //INPUT_FUNCTION_VIS_UPDATE, BUTTON_HIT, //INPUT_FUNCTION_TOGGLE_SNAP_SHOT_MODE, BUTTON_HIT, //INPUT_FUNCTION_SNAP_SHOT_ADVANCE, BUTTON_HIT, //INPUT_FUNCTION_CNC, BUTTON_HIT, //INPUT_FUNCTION_QUICKSAVE, // Menu BUTTON_HIT, //INPUT_FUNCTION_MENU_TOGGLE, // In game EVA BUTTON_HIT, //INPUT_FUNCTION_EVA_MISSION_OBJECTIVES_TOGGLE, BUTTON_HIT | BUTTON_CTRL, // INPUT_FUNCTION_CNC_RADIO_CMD_01 BUTTON_HIT | BUTTON_CTRL, // INPUT_FUNCTION_CNC_RADIO_CMD_02 BUTTON_HIT | BUTTON_CTRL, // INPUT_FUNCTION_CNC_RADIO_CMD_03 BUTTON_HIT | BUTTON_CTRL, // INPUT_FUNCTION_CNC_RADIO_CMD_04 BUTTON_HIT | BUTTON_CTRL, // INPUT_FUNCTION_CNC_RADIO_CMD_05 BUTTON_HIT | BUTTON_CTRL, // INPUT_FUNCTION_CNC_RADIO_CMD_06 BUTTON_HIT | BUTTON_CTRL, // INPUT_FUNCTION_CNC_RADIO_CMD_07 BUTTON_HIT | BUTTON_CTRL, // INPUT_FUNCTION_CNC_RADIO_CMD_08 BUTTON_HIT | BUTTON_CTRL, // INPUT_FUNCTION_CNC_RADIO_CMD_09 BUTTON_HIT | BUTTON_CTRL, // INPUT_FUNCTION_CNC_RADIO_CMD_10 BUTTON_HIT | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_11, BUTTON_HIT | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_12, BUTTON_HIT | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_13, BUTTON_HIT | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_14, BUTTON_HIT | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_15, BUTTON_HIT | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_16, BUTTON_HIT | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_17, BUTTON_HIT | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_18, BUTTON_HIT | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_19, BUTTON_HIT | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_20, BUTTON_HIT | BUTTON_CTRL | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_21, BUTTON_HIT | BUTTON_CTRL | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_22, BUTTON_HIT | BUTTON_CTRL | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_23, BUTTON_HIT | BUTTON_CTRL | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_24, BUTTON_HIT | BUTTON_CTRL | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_25, BUTTON_HIT | BUTTON_CTRL | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_26, BUTTON_HIT | BUTTON_CTRL | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_27, BUTTON_HIT | BUTTON_CTRL | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_28, BUTTON_HIT | BUTTON_CTRL | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_29, BUTTON_HIT | BUTTON_CTRL | BUTTON_ALT, // INPUT_FUNCTION_RADIO_CMD_30, BUTTON_HIT, //INPUT_FUNCTION_TEAM_INFO_TOGGLE, BUTTON_HIT, //INPUT_FUNCTION_BATTLE_INFO_TOGGLE, BUTTON_HIT, //INPUT_FUNCTION_SERVER_INFO_TOGGLE BUTTON_HIT, //INPUT_FUNCTION_PROFILE_ENTER_CHILD0, BUTTON_HIT, //INPUT_FUNCTION_PROFILE_ENTER_CHILD1, BUTTON_HIT, //INPUT_FUNCTION_PROFILE_ENTER_CHILD2, BUTTON_HIT, //INPUT_FUNCTION_PROFILE_ENTER_CHILD3, BUTTON_HIT, //INPUT_FUNCTION_PROFILE_ENTER_CHILD4, BUTTON_HIT, //INPUT_FUNCTION_PROFILE_ENTER_CHILD5, BUTTON_HIT, //INPUT_FUNCTION_PROFILE_ENTER_CHILD6, BUTTON_HIT, //INPUT_FUNCTION_PROFILE_ENTER_CHILD7, BUTTON_HIT, //INPUT_FUNCTION_PROFILE_ENTER_CHILD8, BUTTON_HIT, //INPUT_FUNCTION_PROFILE_ENTER_CHILD9, BUTTON_HIT, //INPUT_FUNCTION_PROFILE_ENTER_PARENT, BUTTON_HIT, //INPUT_FUNCTION_PROFILE_RESET, }; /* ** */ class AcceleratedKeyDef { public: float Value; short Function; float Min; float Max; float Acceleration; }; /* ** */ float Input::Sliders[ NUM_SLIDERS ]; bool Input::ConsoleMode = false; bool Input::MenuMode = false; int Input::Queue[ Input::QUEUE_MAX ]; int Input::QueueHead; int Input::QueueTail; int Input::QueueSize; float Input::FunctionValue[ INPUT_FUNCTION_COUNT ]; float Input::FunctionClamp[ INPUT_FUNCTION_COUNT ]; int Input::FunctionPrimaryKeys[ INPUT_FUNCTION_COUNT ]; int Input::FunctionSecondaryKeys[ INPUT_FUNCTION_COUNT ]; bool Input::DamageIndicatorsEnabled = true; bool Input::UsingDirectInput = true; SimpleDynVecClass AcceleratedKeyList; int _StatsHelpScreen; int _StatsObjectives; int _StatsMap; int _StatsMenu; /* ** */ void Input::Init(bool use_dinput) { ConsoleMode = false; MenuMode = false; if (use_dinput) { DirectInput::Init(); } UsingDirectInput = use_dinput; _StatsHelpScreen = 0; _StatsObjectives = 0; _StatsMap = 0; _StatsMenu = 0; memset( FunctionValue, 0, sizeof( FunctionValue ) ); return ; } void Input::Shutdown( void ) { Free_Mappings(); if (UsingDirectInput) { DirectInput::Shutdown(); } Debug_Say(( "Help Screen Hits: %d\n", _StatsHelpScreen )); Debug_Say(( " Objectives Hits: %d\n", _StatsObjectives )); Debug_Say(( " Map Screen Hits: %d\n", _StatsMap )); Debug_Say(( "Menu Screen Hits: %d\n", _StatsMenu )); return ; } void Input::Free_Mappings( void ) { // // Simply reset the key arrays // ::memset (FunctionPrimaryKeys, 0, sizeof (FunctionPrimaryKeys)); ::memset (FunctionSecondaryKeys, 0, sizeof (FunctionSecondaryKeys)); // // Free the accelerated key list // AcceleratedKeyList.Delete_All (); return; } void Input::Load_Registry( const char * key ) { /*RegistryClass * registry = new RegistryClass( key ); WWASSERT( registry ); if ( registry->Is_Valid() ) { MouseSensitivity = registry->Get_Float( "MouseSensitivity", MouseSensitivity ); MouseScale = registry->Get_Float( "MouseScale", MouseScale ); MouseInvert = registry->Get_Bool( "MouseInvert", MouseInvert ); Mouse2DInvert = registry->Get_Bool( "Mouse2DInvert", Mouse2DInvert ); } delete registry;*/ //Input::Set_Mouse_Sensitivity( MouseSensitivity ); } void Input::Save_Registry( const char * key ) { /*RegistryClass * registry = new RegistryClass( key ); WWASSERT( registry ); if ( registry->Is_Valid() ) { registry->Set_Float( "MouseSensitivity", MouseSensitivity ); registry->Set_Float( "MouseScale", MouseScale ); registry->Set_Bool( "MouseInvert", MouseInvert ); registry->Set_Bool( "Mouse2DInvert", Mouse2DInvert ); } delete registry;*/ } float Input::Get_Mouse_Sensitivity( void ) { return MouseSensitivity; } void Input::Set_Mouse_Sensitivity( float mouse_sensitivity ) { // save this in the registry... MouseSensitivity = WWMath::Clamp( mouse_sensitivity, 0, 1 ); /* When MouseSensitivity == 0, set MouseScale to 0.00025 When MouseSensitivity == 1, set MouseScale to 0.025 When MouseSensitivity == x, set MouseScale to 25 * 10^(2x-5) */ MouseScale = 25.0f * pow( 10.0f, 2*MouseSensitivity - 5 ); } bool Input::Get_Mouse_Invert( void ) { return MouseInvert; } void Input::Set_Mouse_Invert( bool invert ) { // save this in the registry... MouseInvert = invert; } bool Input::Get_Mouse_2D_Invert( void ) { return Mouse2DInvert; } void Input::Set_Mouse_2D_Invert( bool invert ) { // save this in the registry... Mouse2DInvert = invert; } void Input::Flush( void ) { if (UsingDirectInput) { DirectInput::Flush(); } } void Input::Update_Sliders( void ) { if (!UsingDirectInput) { return; } float wheel_scale = -0.05f; // // Update mouse sliders // float mouse_x = MouseScale * (float)(DirectInput::Get_Mouse_Axis( DirectInput::MOUSE_X_AXIS )); float mouse_y = MouseScale * (float)(DirectInput::Get_Mouse_Axis( DirectInput::MOUSE_Y_AXIS )); float mouse_z = wheel_scale * (float)(DirectInput::Get_Mouse_Axis( DirectInput::MOUSE_Z_AXIS )); if (TimeManager::Get_Frame_Real_Seconds() > 0.0f) { mouse_x /= TimeManager::Get_Frame_Real_Seconds(); mouse_y /= TimeManager::Get_Frame_Real_Seconds(); } else { mouse_x = 0.0f; mouse_y = 0.0f; mouse_z = 0.0f; } WWASSERT(WWMath::Is_Valid_Float(mouse_x)); WWASSERT(WWMath::Is_Valid_Float(mouse_y)); // it comes in as inverted if ( !MouseInvert ) { mouse_y = -mouse_y; } // Debug_Say(( "Mouse %f %f\n", mouse_x, mouse_y )); Sliders[ SLIDER_MOUSE_LEFT - FIRST_SLIDER ] = MAX( -mouse_x , 0.0f ); Sliders[ SLIDER_MOUSE_RIGHT - FIRST_SLIDER ] = MAX( mouse_x , 0.0f ); Sliders[ SLIDER_MOUSE_UP - FIRST_SLIDER ] = MAX( -mouse_y , 0.0f ); Sliders[ SLIDER_MOUSE_DOWN - FIRST_SLIDER ] = MAX( mouse_y , 0.0f ); Sliders[ SLIDER_MOUSE_WHEEL_FORWARD - FIRST_SLIDER ] = MAX( -mouse_z , 0.0f ); Sliders[ SLIDER_MOUSE_WHEEL_BACKWARD - FIRST_SLIDER ] = MAX( mouse_z , 0.0f ); // // Update joystick sliders // float joystick_x = (float)DirectInput::Get_Joystick_Axis_State( DirectInput::JOYSTICK_X_AXIS ) / 1000.0f; float joystick_y = (float)DirectInput::Get_Joystick_Axis_State( DirectInput::JOYSTICK_Y_AXIS ) / 1000.0f; const float DEAD_ZONE = 0.15f; if (WWMath::Fabs(joystick_x) < DEAD_ZONE) { joystick_x = 0.0f; } else { joystick_x = WWMath::Sign(joystick_x) * (WWMath::Fabs(joystick_x) - DEAD_ZONE) * 1.5f / (1.0f - DEAD_ZONE); } Sliders[ SLIDER_JOYSTICK_LEFT - FIRST_SLIDER ] = MAX( -joystick_x , 0.0f ); Sliders[ SLIDER_JOYSTICK_RIGHT - FIRST_SLIDER ] = MAX( joystick_x , 0.0f ); Sliders[ SLIDER_JOYSTICK_UP - FIRST_SLIDER ] = MAX( -joystick_y , 0.0f ); Sliders[ SLIDER_JOYSTICK_DOWN - FIRST_SLIDER ] = MAX( joystick_y , 0.0f ); return ; } void Input::Update( void ) { if (!UsingDirectInput) { return; } if (!GameInFocus) { DirectInput::Unacquire(); return; } // Update Direct Input DirectInput::Read(); Update_Sliders (); // // zero all values // memset( FunctionValue, 0, sizeof( FunctionValue ) ); // No ESC, O, M, F1, etc in cinematics! if ( COMBAT_CAMERA && COMBAT_CAMERA->Is_In_Cinematic() && !DebugManager::Allow_Cinematic_Keys() ) { return; } // // Don't process function inputs if we're in the menu // if ( MenuMode == false || ConsoleMode ) { // // Update the value of each function based on what keys are down // for (int index = 0; index < INPUT_FUNCTION_COUNT; index ++) { float value1 = Get_Value (index, FunctionPrimaryKeys[index], 1.0F); float value2 = Get_Value (index, FunctionSecondaryKeys[index], 1.0F); // // Special case the enter key. If the enter key isn't hit, then // check for the num-pad enter key // if (value1 == 0.0F && value2 == 0.0F) { if ( FunctionPrimaryKeys[index] == DIK_RETURN || FunctionSecondaryKeys[index] == DIK_RETURN) { value1 = Get_Value (index, DIK_NUMPADENTER, 1.0F); } } FunctionValue[index] = max (value1, value2); } _StatsHelpScreen += Get_State( INPUT_FUNCTION_HELP_SCREEN ) ? 1 : 0; _StatsObjectives += Get_State( INPUT_FUNCTION_EVA_OBJECTIVES_SCREEN ) ? 1 : 0; _StatsMap += Get_State( INPUT_FUNCTION_EVA_MAP_SCREEN ) ? 1 : 0; _StatsMenu += Get_State( INPUT_FUNCTION_MENU_TOGGLE ) ? 1 : 0; // // Special case sniping mode. In sniping mode we make the primary zoom-in and zoom-out // keys exclusive. // if (COMBAT_CAMERA->Is_Star_Sniping ()) { int key1 = FunctionPrimaryKeys[INPUT_FUNCTION_ZOOM_IN]; int key2 = FunctionPrimaryKeys[INPUT_FUNCTION_ZOOM_OUT]; // // Loop over and zero out any function that uses either of these primary keys // for (index = 0; index < INPUT_FUNCTION_COUNT; index ++) { // // Does this function use one of the keys that is mapped to the zoom functions? // if ( FunctionPrimaryKeys[index] == key1 || FunctionSecondaryKeys[index] == key1 || FunctionPrimaryKeys[index] == key2 || FunctionSecondaryKeys[index] == key2) { // // Zero out this function as necessary // if (index != INPUT_FUNCTION_ZOOM_IN && index != INPUT_FUNCTION_ZOOM_OUT) { FunctionValue[index] = 0; } } } } // // Special case the vehicle turning so it inherits the values // of the strafe command // FunctionValue[INPUT_FUNCTION_VEHICLE_TURN_LEFT] = max (FunctionValue[INPUT_FUNCTION_MOVE_LEFT], FunctionValue[INPUT_FUNCTION_TURN_LEFT]); FunctionValue[INPUT_FUNCTION_VEHICLE_TURN_RIGHT] = max (FunctionValue[INPUT_FUNCTION_MOVE_RIGHT], FunctionValue[INPUT_FUNCTION_TURN_RIGHT]); // // Apply accelerated keys // for (index = 0; index < AcceleratedKeyList.Count (); index ++) { AcceleratedKeyDef &def = AcceleratedKeyList[index]; // // Is this fuction activated? // if ( Get_Value (def.Function, FunctionPrimaryKeys[def.Function], 1.0F) || Get_Value (def.Function, FunctionSecondaryKeys[def.Function], 1.0F)) { // // Apply the accelerated value // def.Value += def.Acceleration * TimeManager::Get_Frame_Real_Seconds (); def.Value = WWMath::Clamp (def.Value, def.Min, def.Max); // // Store the function's value (if necessary) // if (def.Value != 0.0F) { FunctionValue[def.Function] = def.Value; } } else { // // Reset the function's accelerated value // def.Value = 0.0F; } } } else { int index = INPUT_FUNCTION_BEGIN_CONSOLE; float value1 = Get_Value (index, FunctionPrimaryKeys[index], 1.0F); float value2 = Get_Value (index, FunctionSecondaryKeys[index], 1.0F); FunctionValue[index] = max (value1, value2); } return ; } int Input::Console_Get_Key() { if ( QueueSize > 0 ) { int key = Queue[ QueueTail ]; if ( ++QueueTail == QUEUE_MAX ) { QueueTail = 0; } QueueSize--; return key; } return 0; } void Input::Console_Add_Key( int key ) { if ( QueueSize < QUEUE_MAX ) { Queue[ QueueHead ] = key; if ( ++QueueHead == QUEUE_MAX ) { QueueHead = 0; } QueueSize++; } } /* ** */ bool Input::Is_Button_Down (int button_id) { if (!UsingDirectInput) { return(false); } return ((DirectInput::Get_Button_Value(button_id) & BUTTON_BIT_HELD) != 0); } /* ** */ float Input::Get_Value( int function_index, int input, float clamp ) { if (!UsingDirectInput) { return(0.0f); } if ( input >= FIRST_SLIDER ) { // return slider state float slider = Sliders[ input - FIRST_SLIDER ]; // // ignore the dead zone #if 0 if ( slider < SLIDER_DEAD_ZONE ) { slider = 0; } // Ignore the clamp if ( slider > clamp ) { slider = clamp; } #endif // if ( input == SLIDER_MOUSE_LEFT ) Debug_Say(( "Slider %f\n", slider )); return slider; } else { #if(0) // // Bail if this is a debug key and the debug button isn't down // if ((FunctionKeyStates[function_index] & 0xF000) & BUTTON_DEBUG) { if ((DirectInput::Get_Button_Value(DIK_F9) & BUTTON_BIT_HELD) == 0) { return 0.0F; } } else if ((DirectInput::Get_Button_Value(DIK_F9) & BUTTON_BIT_HELD)) { return 0.0F; } #endif int modifier = 0; // Special case ctrl and alt for the 0 - 9 keys // Assumtion: DIK_keys go 1,2,3..9,0 if ( (input&0xFF) >= DIK_1 && (input&0xFF) <= DIK_0 ) { // Shift is a key, used for walk! // modifier |= ((DirectInput::Get_Button_Value(DIK_SHIFT) & BUTTON_BIT_HELD) ? BUTTON_SHIFT : 0); modifier |= ((DirectInput::Get_Button_Value(DIK_CONTROL) & BUTTON_BIT_HELD) ? BUTTON_CTRL : 0); modifier |= ((DirectInput::Get_Button_Value(DIK_ALT) & BUTTON_BIT_HELD) ? BUTTON_ALT : 0); } modifier |= ((DirectInput::Get_Button_Value(DIK_F9) & BUTTON_BIT_HELD) ? BUTTON_DEBUG : 0); int funcModifier = (FunctionKeyStates[function_index] & 0xF000); if (funcModifier != modifier) { return 0.0f; } switch( FunctionKeyStates[ function_index ] & 0x0F ) { case BUTTON_UP: return (DirectInput::Get_Button_Value( input ) & BUTTON_BIT_HELD) ? 0.0 : 1.0; case BUTTON_HIT: return (DirectInput::Get_Button_Value( input ) & BUTTON_BIT_HIT) ? 1.0 : 0.0; case BUTTON_RELEASE: return (DirectInput::Get_Button_Value( input ) & BUTTON_BIT_RELEASED) ? 1.0 : 0.0; case BUTTON_HELD: return (DirectInput::Get_Button_Value( input ) & BUTTON_BIT_HELD) ? 1.0 : 0.0; case BUTTON_DOUBLE: return (DirectInput::Get_Button_Value( input ) & BUTTON_BIT_DOUBLE) ? 1.0 : 0.0; } } return 0.0f; } /* ** */ short Input::Get_Function( const char *name ) { if ( name && name[0] ) { // find function for ( int function = 0; function < NUM_FUNCTIONS; function++ ) { if ( !stricmp( name, Functions[function].Name ) ) { return Functions[function].ID; } } Debug_Say(( "Unknown function name %s\n", name )); } return 0; } /* ** */ const char *Input::Get_Key_Name( short key_id ) { // // Check each button name // for (int index = 0; index < NUM_BUTTON_NAMES; index ++) { if (ButtonNames[index].ID == key_id) { return ButtonNames[index].Name; } } // // Check each slider name // for (index = 0; index < NUM_SLIDER_NAMES; index ++) { if (SliderNames[index].ID == key_id) { return SliderNames[index].Name; } } Debug_Say(( "Could not find a name for key %d\n", key_id )); return NULL; } /* ** */ short Input::Get_Key( const char *name ) { if (name != NULL && name[0] != 0) { // // Check each button name // for (int index = 0; index < NUM_BUTTON_NAMES; index ++) { if (::stricmp (name, ButtonNames[index].Name) == 0) { return ButtonNames[index].ID; } } // // Check each slider name // for (index = 0; index < NUM_SLIDER_NAMES; index ++) { if (::stricmp (name, SliderNames[index].Name) == 0) { return SliderNames[index].ID; } } Debug_Say(( "Could not find key name %s\n", name )); } return 0; } /* ** */ int Input::Get_Primary_Key_For_Function (int function_id) { return FunctionPrimaryKeys[ function_id ]; } /* ** */ int Input::Get_Secondary_Key_For_Function (int function_id) { return FunctionSecondaryKeys[ function_id ]; } /* ** */ void Input::Set_Primary_Key_For_Function (int function_id, int key_id) { FunctionPrimaryKeys[ function_id ] = key_id; // Use weapon key is the same as secondary fire, just hit rather than held if ( function_id == INPUT_FUNCTION_FIRE_WEAPON_SECONDARY ) { Set_Primary_Key_For_Function ( INPUT_FUNCTION_USE_WEAPON, key_id ); } // Copy jump and crouch to move up and down if ( function_id == INPUT_FUNCTION_CROUCH ) { Set_Primary_Key_For_Function ( INPUT_FUNCTION_MOVE_DOWN, key_id ); } if ( function_id == INPUT_FUNCTION_JUMP ) { Set_Primary_Key_For_Function ( INPUT_FUNCTION_MOVE_UP, key_id ); } return ; } /* ** */ void Input::Set_Secondary_Key_For_Function (int function_id, int key_id) { FunctionSecondaryKeys[ function_id ] = key_id; // Use weapon key is the same as secondary fire, just hit rather than held if ( function_id == INPUT_FUNCTION_FIRE_WEAPON_SECONDARY ) { Set_Secondary_Key_For_Function ( INPUT_FUNCTION_USE_WEAPON, key_id ); } // Copy jump and crouch to move up and down if ( function_id == INPUT_FUNCTION_CROUCH ) { Set_Secondary_Key_For_Function ( INPUT_FUNCTION_MOVE_DOWN, key_id ); } if ( function_id == INPUT_FUNCTION_JUMP ) { Set_Secondary_Key_For_Function ( INPUT_FUNCTION_MOVE_UP, key_id ); } return ; } /* ** */ void Input::Save_Configuration (const char *filename) { INIClass input_ini; // // Loop over each function and save its key mappings to the INI file // for (int index = 0; index < NUM_FUNCTIONS; index ++) { StringClass pri_name; StringClass sec_name; pri_name.Format ("%s_Primary", Functions[index].Name); sec_name.Format ("%s_Secondary", Functions[index].Name); StringClass pri_key; StringClass sec_key; // // Get the name of the primary key that's mapped to this function // if (FunctionPrimaryKeys[index] != 0) { pri_key = Get_Key_Name (FunctionPrimaryKeys[index]); } // // Get the name of the secondary key that's mapped to this function // if (FunctionSecondaryKeys[index] != 0) { sec_key = Get_Key_Name (FunctionSecondaryKeys[index]); } // // Read the primary and secondary keys for this function // input_ini.Put_String ("Generic Key Mappings", pri_name, pri_key); input_ini.Put_String ("Generic Key Mappings", sec_name, sec_key); } // // Save the accelerated functions // Save_Accelerated_Keys (&input_ini); Save_Misc_Settings (&input_ini); // // Save the data to a file // StringClass config_filename; config_filename.Format( "config\\%s", filename ); FileClass *ini_file = _TheWritingFileFactory->Get_File (config_filename); if (ini_file != NULL) { ini_file->Open (FileClass::WRITE); input_ini.Save (*ini_file); _TheWritingFileFactory->Return_File (ini_file); } return ; } /* ** */ typedef struct { int text_id; int dik_id; } KEY_NAME_MAPPING; const KEY_NAME_MAPPING DIK_KEY_NAME_ARRAY[] = { { IDS_KEYNAME_DIK_F1, DIK_F1 }, { IDS_KEYNAME_DIK_F2, DIK_F2 }, { IDS_KEYNAME_DIK_F3, DIK_F3 }, { IDS_KEYNAME_DIK_F4, DIK_F4 }, { IDS_KEYNAME_DIK_F5, DIK_F5 }, { IDS_KEYNAME_DIK_F6, DIK_F6 }, { IDS_KEYNAME_DIK_F7, DIK_F7 }, { IDS_KEYNAME_DIK_F8, DIK_F8 }, { IDS_KEYNAME_DIK_F9, DIK_F9 }, { IDS_KEYNAME_DIK_F10, DIK_F10 }, { IDS_KEYNAME_DIK_F11, DIK_F11 }, { IDS_KEYNAME_DIK_F12, DIK_F12 }, { IDS_KEYNAME_DIK_0, DIK_0 }, { IDS_KEYNAME_DIK_1, DIK_1 }, { IDS_KEYNAME_DIK_2, DIK_2 }, { IDS_KEYNAME_DIK_3, DIK_3 }, { IDS_KEYNAME_DIK_4, DIK_4 }, { IDS_KEYNAME_DIK_5, DIK_5 }, { IDS_KEYNAME_DIK_6, DIK_6 }, { IDS_KEYNAME_DIK_7, DIK_7 }, { IDS_KEYNAME_DIK_8, DIK_8 }, { IDS_KEYNAME_DIK_9, DIK_9 }, { IDS_KEYNAME_DIK_A, DIK_A }, { IDS_KEYNAME_DIK_B, DIK_B }, { IDS_KEYNAME_DIK_C, DIK_C }, { IDS_KEYNAME_DIK_D, DIK_D }, { IDS_KEYNAME_DIK_E, DIK_E }, { IDS_KEYNAME_DIK_F, DIK_F }, { IDS_KEYNAME_DIK_G, DIK_G }, { IDS_KEYNAME_DIK_H, DIK_H }, { IDS_KEYNAME_DIK_I, DIK_I }, { IDS_KEYNAME_DIK_J, DIK_J }, { IDS_KEYNAME_DIK_K, DIK_K }, { IDS_KEYNAME_DIK_L, DIK_L }, { IDS_KEYNAME_DIK_M, DIK_M }, { IDS_KEYNAME_DIK_N, DIK_N }, { IDS_KEYNAME_DIK_O, DIK_O }, { IDS_KEYNAME_DIK_P, DIK_P }, { IDS_KEYNAME_DIK_Q, DIK_Q }, { IDS_KEYNAME_DIK_R, DIK_R }, { IDS_KEYNAME_DIK_S, DIK_S }, { IDS_KEYNAME_DIK_T, DIK_T }, { IDS_KEYNAME_DIK_U, DIK_U }, { IDS_KEYNAME_DIK_V, DIK_V }, { IDS_KEYNAME_DIK_W, DIK_W }, { IDS_KEYNAME_DIK_X, DIK_X }, { IDS_KEYNAME_DIK_Y, DIK_Y }, { IDS_KEYNAME_DIK_Z, DIK_Z }, { IDS_KEYNAME_DIK_MINUS, DIK_MINUS }, { IDS_KEYNAME_DIK_EQUALS, DIK_EQUALS }, { IDS_KEYNAME_DIK_BACK, DIK_BACK }, { IDS_KEYNAME_DIK_TAB, DIK_TAB }, { IDS_KEYNAME_DIK_LBRACKET, DIK_LBRACKET }, { IDS_KEYNAME_DIK_RBRACKET, DIK_RBRACKET }, { IDS_KEYNAME_DIK_RETURN, DIK_RETURN }, { IDS_KEYNAME_DIK_SEMICOLON, DIK_SEMICOLON }, { IDS_KEYNAME_DIK_APOSTROPHE,DIK_APOSTROPHE }, { IDS_KEYNAME_DIK_GRAVE, DIK_GRAVE }, { IDS_KEYNAME_DIK_BACKSLASH, DIK_BACKSLASH }, { IDS_KEYNAME_DIK_COMMA, DIK_COMMA }, { IDS_KEYNAME_DIK_PERIOD, DIK_PERIOD }, { IDS_KEYNAME_DIK_SLASH, DIK_SLASH }, { IDS_KEYNAME_DIK_SPACE, DIK_SPACE }, { IDS_KEYNAME_DIK_CAPITAL, DIK_CAPITAL }, { IDS_KEYNAME_DIK_NUMLOCK, DIK_NUMLOCK }, { IDS_KEYNAME_DIK_SCROLL, DIK_SCROLL }, { IDS_KEYNAME_DIK_ESCAPE, DIK_ESCAPE }, { IDS_KEYNAME_DIK_NUMPAD0, DIK_NUMPAD0 }, { IDS_KEYNAME_DIK_NUMPAD1, DIK_NUMPAD1 }, { IDS_KEYNAME_DIK_NUMPAD2, DIK_NUMPAD2 }, { IDS_KEYNAME_DIK_NUMPAD3, DIK_NUMPAD3 }, { IDS_KEYNAME_DIK_NUMPAD4, DIK_NUMPAD4 }, { IDS_KEYNAME_DIK_NUMPAD5, DIK_NUMPAD5 }, { IDS_KEYNAME_DIK_NUMPAD6, DIK_NUMPAD6 }, { IDS_KEYNAME_DIK_NUMPAD7, DIK_NUMPAD7 }, { IDS_KEYNAME_DIK_NUMPAD8, DIK_NUMPAD8 }, { IDS_KEYNAME_DIK_NUMPAD9, DIK_NUMPAD9 }, { IDS_KEYNAME_DIK_SUBTRACT, DIK_SUBTRACT }, { IDS_KEYNAME_DIK_MULTIPLY, DIK_MULTIPLY }, { IDS_KEYNAME_DIK_ADD, DIK_ADD }, { IDS_KEYNAME_DIK_DECIMAL, DIK_DECIMAL }, { IDS_KEYNAME_DIK_NUMPADENTER, DIK_NUMPADENTER }, { IDS_KEYNAME_DIK_DIVIDE, DIK_DIVIDE }, { IDS_KEYNAME_DIK_HOME, DIK_HOME }, { IDS_KEYNAME_DIK_PRIOR, DIK_PRIOR }, { IDS_KEYNAME_DIK_END, DIK_END }, { IDS_KEYNAME_DIK_NEXT, DIK_NEXT }, { IDS_KEYNAME_DIK_INSERT, DIK_INSERT }, { IDS_KEYNAME_DIK_DELETE, DIK_DELETE }, { IDS_KEYNAME_DIK_UP, DIK_UP }, { IDS_KEYNAME_DIK_DOWN, DIK_DOWN }, { IDS_KEYNAME_DIK_LEFT, DIK_LEFT }, { IDS_KEYNAME_DIK_RIGHT, DIK_RIGHT }, { IDS_KEYNAME_DIK_SYSRQ, DIK_SYSRQ }, { IDS_KEYNAME_DIK_CONTROL, DIK_CONTROL }, { IDS_KEYNAME_DIK_LCONTROL, DIK_LCONTROL }, { IDS_KEYNAME_DIK_RCONTROL, DIK_RCONTROL }, { IDS_KEYNAME_DIK_SHIFT, DIK_SHIFT }, { IDS_KEYNAME_DIK_LSHIFT, DIK_LSHIFT }, { IDS_KEYNAME_DIK_RSHIFT, DIK_RSHIFT }, { IDS_KEYNAME_DIK_ALT, DIK_ALT }, { IDS_KEYNAME_DIK_LALT, DIK_LALT }, { IDS_KEYNAME_DIK_RALT, DIK_RALT }, { IDS_KEYNAME_DIK_WIN, DIK_WIN }, { IDS_KEYNAME_DIK_LWIN, DIK_LWIN }, { IDS_KEYNAME_DIK_RWIN, DIK_RWIN }, { IDS_KEYNAME_DIK_APPS, DIK_APPS }, { IDS_INPUT_LBUTTON, DirectInput::BUTTON_MOUSE_LEFT }, { IDS_INPUT_RBUTTON, DirectInput::BUTTON_MOUSE_RIGHT }, { IDS_INPUT_MBUTTON, DirectInput::BUTTON_MOUSE_CENTER }, { IDS_INPUT_MW_UP, Input::SLIDER_MOUSE_WHEEL_FORWARD }, { IDS_INPUT_MW_DN, Input::SLIDER_MOUSE_WHEEL_BACKWARD }, { 0, DirectInput::BUTTON_JOYSTICK_A }, { 0, DirectInput::BUTTON_JOYSTICK_B }, { 0, Input::SLIDER_MOUSE_LEFT }, { 0, Input::SLIDER_MOUSE_RIGHT }, { 0, Input::SLIDER_MOUSE_UP }, { 0, Input::SLIDER_MOUSE_DOWN }, { 0, Input::SLIDER_JOYSTICK_LEFT }, { 0, Input::SLIDER_JOYSTICK_RIGHT }, { 0, Input::SLIDER_JOYSTICK_UP }, { 0, Input::SLIDER_JOYSTICK_DOWN }, }; const int KEYNAME_MAP_COUNT = sizeof (DIK_KEY_NAME_ARRAY) / sizeof (KEY_NAME_MAPPING); /* ** */ void Input::Load_Configuration (const char *filename) { Free_Mappings (); // // Try to load the INI file // INIClass *input_ini = Get_INI (filename); if (input_ini == NULL) { Debug_Say(("Input::Load_Configuration - Unable to load %s\n", filename)); return ; } // // Loop over each function and try to read data about it from the INI // for (int index = 0; index < NUM_FUNCTIONS; index ++) { StringClass pri_name; StringClass sec_name; pri_name.Format ("%s_Primary", Functions[index].Name); sec_name.Format ("%s_Secondary", Functions[index].Name); // // Read the primary and secondary keys for this function // StringClass pri_key(0,true); input_ini->Get_String (pri_key,"Generic Key Mappings", pri_name); StringClass sec_key(0,true); input_ini->Get_String (sec_key,"Generic Key Mappings", sec_name); // // Set the primary key for this function // if (pri_key.Is_Empty () == false) { FunctionPrimaryKeys[index] = Get_Key (pri_key); } // // Set the secondary key for this function // if (pri_key.Is_Empty () == false) { FunctionSecondaryKeys[index] = Get_Key (sec_key); } } // // Load the accelerated keys from the ini // Load_Accelerated_Keys (input_ini); Load_Misc_Settings (input_ini); // // Free the INI // Release_INI (input_ini); // // Reset the mouse sensitivity to ensure its clamped properly // Input::Set_Mouse_Sensitivity (MouseSensitivity); return ; } /* ** */ void Input::Load_Accelerated_Keys (INIClass *input_ini) { int count = input_ini->Entry_Count ("Accelerated Keys"); // // Load information about each accelerated key // for (int index = 0; index < count; index ++) { StringClass entry_name(input_ini->Get_Entry ("Accelerated Keys", index),true); StringClass section_name(0,true); input_ini->Get_String (section_name, "Accelerated Keys", entry_name); Load_Accelerated_Key (input_ini, section_name); } return ; } /* ** */ void Input::Load_Accelerated_Key (INIClass *input_ini, const char *section_name) { StringClass function_name(0,true); input_ini->Get_String (function_name, section_name, ENTRY_FUNCTION); // // Fill in the structure we use to describe the accelerated key from the INI section. // AcceleratedKeyDef def; def.Function = Get_Function (function_name); def.Min = input_ini->Get_Float (section_name, ENTRY_MIN, 0); def.Max = input_ini->Get_Float (section_name, ENTRY_MAX, 0); def.Acceleration = input_ini->Get_Float (section_name, ENTRY_ACCELERATION, 1); // // Add this definition to the list // AcceleratedKeyList.Add (def); return ; } /* ** */ void Input::Save_Accelerated_Keys (INIClass *input_ini) { for (int index = 0; index < AcceleratedKeyList.Count (); index ++) { AcceleratedKeyDef &def = AcceleratedKeyList[index]; // // Add an entry for this key to the section // StringClass entry_name; StringClass section_name; entry_name.Format ("%d", index + 1); section_name.Format ("AcceleratedKey%d", index + 1); input_ini->Put_String ("Accelerated Keys", entry_name, section_name); // // Save this accelerated key's definition to its own section // input_ini->Put_String (section_name, ENTRY_FUNCTION, Functions[def.Function].Name); input_ini->Put_Float (section_name, ENTRY_MIN, def.Min); input_ini->Put_Float (section_name, ENTRY_MAX, def.Max); input_ini->Put_Float (section_name, ENTRY_ACCELERATION, def.Acceleration); } return ; } //////////////////////////////////////////////////////////////// // // Get_Translated_Key_Name // //////////////////////////////////////////////////////////////// void Input::Get_Translated_Key_Name (int dik_id, WideStringClass &name) { for (int index = 0; index < KEYNAME_MAP_COUNT; index ++) { // // Is this the entry we're looking for? // if (DIK_KEY_NAME_ARRAY[index].dik_id == dik_id) { if (DIK_KEY_NAME_ARRAY[index].text_id != 0) { name = TRANSLATE (DIK_KEY_NAME_ARRAY[index].text_id); } break; } } return ; } /* ** */ void Input::Load_Misc_Settings (INIClass *input_ini) { DamageIndicatorsEnabled = input_ini->Get_Bool (SECTION_MISC_SETTINGS, ENTRY_DAMAGE_INDICATORS, true); MouseSensitivity = input_ini->Get_Float (SECTION_MISC_SETTINGS, ENTRY_MOUSE_SENSITIVITY, 0.5F); MouseScale = input_ini->Get_Float (SECTION_MISC_SETTINGS, ENTRY_MOUSE_SCALE, 1.0F); MouseInvert = input_ini->Get_Bool (SECTION_MISC_SETTINGS, ENTRY_MOUSE_INVERT, true); Mouse2DInvert = input_ini->Get_Bool (SECTION_MISC_SETTINGS, ENTRY_MOUSE_2D_INVERT, false); bool is_target_steering = input_ini->Get_Bool (ENTRY_TARGET_STEERING, false); VehicleGameObj::Set_Target_Steering (is_target_steering); // // Apply the settings // Input::Set_Mouse_Sensitivity( MouseSensitivity ); return ; } /* ** */ void Input::Save_Misc_Settings (INIClass *input_ini) { input_ini->Put_Bool (SECTION_MISC_SETTINGS, ENTRY_DAMAGE_INDICATORS, DamageIndicatorsEnabled); input_ini->Put_Float (SECTION_MISC_SETTINGS, ENTRY_MOUSE_SENSITIVITY, MouseSensitivity); input_ini->Put_Float (SECTION_MISC_SETTINGS, ENTRY_MOUSE_SCALE, MouseScale); input_ini->Put_Bool (SECTION_MISC_SETTINGS, ENTRY_MOUSE_INVERT, MouseInvert); input_ini->Put_Bool (SECTION_MISC_SETTINGS, ENTRY_MOUSE_2D_INVERT, Mouse2DInvert); input_ini->Put_Bool (SECTION_MISC_SETTINGS, ENTRY_TARGET_STEERING, VehicleGameObj::Is_Target_Steering ()); return ; } /* ** */ int Input::Find_First_Function_By_Primary_Key (int key_id) { return Find_Next_Function_By_Primary_Key (-1, key_id); } /* ** */ int Input::Find_Next_Function_By_Primary_Key (int function_id, int key_id) { int retval = -1; for (int index = (function_id + 1); index < INPUT_FUNCTION_COUNT; index ++) { if (FunctionPrimaryKeys[index] == key_id) { retval = index; break; } } return retval; } /* ** */ int Input::Find_First_Function_By_Secondary_Key (int key_id) { return Find_Next_Function_By_Secondary_Key (-1, key_id); } /* ** */ int Input::Find_Next_Function_By_Secondary_Key (int function_id, int key_id) { int retval = -1; for (int index = (function_id + 1); index < INPUT_FUNCTION_COUNT; index ++) { if (FunctionSecondaryKeys[index] == key_id) { retval = index; break; } } return retval; }