Custom hotkey remapping for unit/building production keys in Options#2589
Custom hotkey remapping for unit/building production keys in Options#2589wahidkurdo wants to merge 4 commits intoTheSuperHackers:mainfrom
Conversation
…n keys - Add per-faction (USA/China/GLA) hotkey categories to KeyboardOptionsMenu - Override-Map in HotKeyManager for persistent key rebinding - Manual overlay layout management (no Shell push/pop conflicts) - ComboBox category selector, ListBox command list, TextEntry key input - Assign/ResetAll buttons with full MetaMap + CommandButton support - Includes .wnd UI layout files under Patch/Window/Menus/
|
| Filename | Overview |
|---|---|
| GeneralsMD/Code/GameEngine/Include/GameClient/HotKey.h | Adds setOverride, removeOverride, getOverride, clearAllOverrides, loadOverrides, saveOverrides, and OverrideMap typedef to HotKeyManager; backing storage m_hotKeyOverrides added correctly. |
| GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/HotKey.cpp | Implements override methods; loadOverrides() is missing an strncmp prefix guard, allowing any key longer than 7 chars in the INI to be silently misinterpreted as a command-button override. |
| GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/KeyboardOptionsMenu.cpp | Major rework: adds faction-based CommandButton hotkey UI, manual overlay open/close helpers, and conflict warning; previous null-check and missing-method issues are resolved; NULL should be nullptr in the fallback MessageBoxA call. |
| GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp | Routes Keyboard Options button to OpenKeyboardOptionsMenu(); also adds unrelated #if defined(ENABLE_VOICE_CHAT) dead-code blocks that appear out of scope for this PR. |
| GeneralsMD/Code/GameEngine/Include/GameClient/GUICallbacks.h | Adds extern declarations for OpenKeyboardOptionsMenu and CloseKeyboardOptionsMenu; straightforward and correct. |
| GeneralsMD/Code/GameEngine/Source/Common/System/FunctionLexicon.cpp | Registers KeyboardOptionsMenuUpdate in the layout update table so the new .wnd file can resolve its callback; correct and minimal change. |
Sequence Diagram
sequenceDiagram
participant OM as OptionsMenu
participant KOM as KeyboardOptionsMenu
participant HKM as HotKeyManager
participant INI as HotKeyOverrides.ini
Note over HKM: init() on startup
HKM->>INI: loadOverrides()
INI-->>HKM: HotKey_* entries to m_hotKeyOverrides
OM->>KOM: OpenKeyboardOptionsMenu()
KOM->>KOM: winCreateLayout(KeyboardOptionsMenu.wnd)
KOM->>OM: hide OptionsMenu overlay
KOM->>HKM: getOverride(cmdButtonName)
HKM-->>KOM: current override key (or empty)
Note over KOM: User selects entry, types new key, clicks Assign
KOM->>HKM: setOverride(cmdButtonName, newKey)
KOM->>HKM: saveOverrides()
HKM->>INI: write HotKey_* entries
KOM->>OM: CloseKeyboardOptionsMenu()
KOM->>KOM: destroyWindows() + deleteInstance()
KOM->>OM: show OptionsMenu overlay
Prompt To Fix All With AI
This is a comment left during a code review.
Path: GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/HotKey.cpp
Line: 280-283
Comment:
**Missing prefix validation corrupts override map**
`key.getLength() > (Int)prefixLen` only checks that the key is longer than 7 characters; it does not verify the key actually starts with `"HotKey_"`. Any entry in `HotKeyOverrides.ini` whose key is longer than 7 chars but does *not* start with `HotKey_` (e.g. from a manual edit or future migration) will have its first 7 bytes stripped and inserted into `m_hotKeyOverrides` with a garbage command-button name. `saveOverrides()` already uses `strncmp` to guard against this — `loadOverrides()` should do the same.
```suggestion
if (key.getLength() > (Int)prefixLen
&& strncmp(key.str(), HOTKEY_OVERRIDE_PREFIX, prefixLen) == 0)
```
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/KeyboardOptionsMenu.cpp
Line: 667
Comment:
**`NULL` → `nullptr` for pointer argument**
`MessageBoxA` takes an `HWND` (pointer) as its first argument; per the project's style rules, pointer literals should use `nullptr` rather than `NULL`.
```suggestion
MessageBoxA( nullptr,
```
**Rule Used:** Use nullptr instead of NULL for null pointer liter... ([source](https://app.greptile.com/review/custom-context?memory=c69cf1a9-c69a-4330-a013-69bb5d6701da))
**Learnt From**
[TheSuperHackers/GeneralsGameCode#2067](https://github.com/TheSuperHackers/GeneralsGameCode/pull/2067#discussion_r2703746722)
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp
Line: 74-77
Comment:
**Unrelated dead-code block**
This `#if defined(ENABLE_VOICE_CHAT)` block — and the similar comments added in `OptionsMenuInit`, `OptionsMenuShutdown`, and `OptionsMenuSystem` — appear unrelated to the hotkey remapping feature. Since `ENABLE_VOICE_CHAT` is never defined these blocks compile away entirely, but they add confusing noise. Were these voice-chat removals intended to be part of this PR?
How can I resolve this? If you propose a fix, please make it concise.Reviews (4): Last reviewed commit: "fix: address code review feedback" | Re-trigger Greptile
GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/KeyboardOptionsMenu.cpp
Show resolved
Hide resolved
GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/KeyboardOptionsMenu.cpp
Show resolved
Hide resolved
375b7c7 to
66fca53
Compare
- Show conflict warning in description text when duplicate hotkey detected - Replace NULL with nullptr in runInit call - Include HotKey.h and HotKey.cpp with override methods
GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/KeyboardOptionsMenu.cpp
Show resolved
Hide resolved
- Show conflict warning in description text when duplicate hotkey detected - Replace NULL with nullptr in runInit call - Include HotKey.h and HotKey.cpp with override methods
There was a problem hiding this comment.
We do not add game data files to this repository. You will need to document the data changes that are required to use the new code.
There was a problem hiding this comment.
The Hotkey option was already in the game but hidden during EA never finished. The code consists of AI prompts; no one is going to write hundreds of lines of code without help from Claude.
i already pushed the README.md for how to use it. The Only Problem is that you need the Window-Menus files in game Folder
There was a problem hiding this comment.
The code consists of AI prompts; no one is going to write hundreds of lines of code without help from Claude.
Do you think that EA had AI when they wrote hunderds of thousands of line of code for the generals and zero hour games?
There was a problem hiding this comment.
The code consists of AI prompts; no one is going to write hundreds of lines of code without help from Claude.
Do you think that EA had AI when they wrote hunderds of thousands of line of code for the generals and zero hour games?
They got paid for it and we dont
| } | ||
| else if (controlID == buttonAccept ) | ||
| { | ||
| // VoiceOptionsUI::Save() removed — /voice slash commands persist directly. |
There was a problem hiding this comment.
This comment doesn't make sense
i sent a pull request before for generalsOnline voice chat this was for it
| GameWindow *control = (GameWindow *)mData1; | ||
| Int controlID = control->winGetWindowId(); | ||
|
|
||
| // VoiceOptionsUI event routing removed — /voice-only configuration. |
| //------------------------------------------------------------------------------------------------- | ||
| void OptionsMenuShutdown( WindowLayout *layout, void *userData ) | ||
| { | ||
| // VoiceOptionsUI::Teardown() removed with /voice-only configuration. |
| } | ||
|
|
||
|
|
||
| // Voice-chat options panel disabled — use /voice slash commands instead. |
| #include "GameNetwork/GameSpy/PeerDefs.h" | ||
| #include "GameLogic/GameLogic.h" | ||
| #include "GameLogic/ScriptEngine.h" | ||
| #if defined(ENABLE_VOICE_CHAT) |
There was a problem hiding this comment.
Unused code and out of scope for this PR.
| UnicodeString str; | ||
| GadgetComboBoxReset(comboBoxCategoryList); | ||
|
|
||
| // Built-in MetaMap categories (global hotkeys) |
There was a problem hiding this comment.
The code consists of AI prompts; no one is going to write hundreds of lines of code without help from Claude.
Do you think that EA had AI when they wrote hunderds of thousands of line of code for the generals and zero hour games?
You can now set Custom Hotkeys in game Options
Test Done its working without crashes